API Reference - Project API

Working with Projects using Collections

Interactive Examples

Try these examples with your saved connection. If you haven't connected yet, visit the Try It Out page first.

Get First 5 Projects

Fetch the first 5 projects using Collections.

const projects = api.collections.project;
await projects.fetch({ limit: 5 });
console.log('Projects:', projects.models);
console.log('Has more:', projects.hasMore);

Get Project by ID

Fetch and lookup a specific project by its ID using Collections.

const projects = api.collections.project;
await projects.fetch({ id: 1 });
const project = projects.get(1);
if (project) {
  console.log('Project:', project.name);
  console.log('Timezone:', project.timezone);
}

Fast ID Lookup

Fetch multiple projects and use O(1) indexed lookup by ID.

const projects = api.collections.project;
await projects.fetch({ limit: 100 });
const project = projects.get(1); // O(1) lookup
if (project) {
  console.log('Found:', project.name);
}

Get All Projects (Use with Caution)

Fetch ALL projects across all pages. Warning: This may take time if you have many projects.

const projects = api.collections.project;
await projects.fetchAll();
console.log(`Total projects: ${projects.length}`);

ProjectCollection

The ProjectCollection class provides a Backbone.js-inspired interface for managing project data with built-in indexing, pagination, and array operations.

Accessing the ProjectCollection

import { initializeSGERP } from 'sgerp-frontend-lib';

const api = initializeSGERP({
  activeConnection: 'admin@staging',
  connections: {
    'admin@staging': {
      id: 'admin@staging',
      environment: 'staging',
      user: 'admin',
      password: 'your-password',
      baseUrl: 'https://sgerp-stage.d.gcdev.swatrider.com',
    },
  },
});

// Access the ProjectCollection
const projects = api.collections.project;

Methods

fetch()

Fetch the first page of projects.

await projects.fetch(params?: {
  limit?: number;
  offset?: number;
  id?: number;
}, config?: RequestConfig): Promise<void>

Parameters:

  • params (object, optional) - Query parameters
    • limit (number) - Number of results to return (default: 20)
    • offset (number) - Offset for pagination
    • id (number) - Filter by exact project ID
  • config (RequestConfig, optional) - Request configuration

Example:

const projects = api.collections.project;

// Fetch first 20 projects
await projects.fetch({ limit: 20 });
console.log(`Loaded ${projects.length} projects`);

// Access models
projects.forEach(project => {
  console.log(`${project.name} (ID: ${project.id})`);
  console.log(`  Location: ${project.lat}, ${project.lon}`);
  console.log(`  Timezone: ${project.timezone}`);
});

fetchNext()

Fetch the next page and append to the collection.

await projects.fetchNext(config?: RequestConfig): Promise<void>

Example:

const projects = api.collections.project;

// Fetch first page
await projects.fetch({ limit: 20 });

// Check if more pages exist
if (projects.hasMore) {
  // Fetch and append next page
  await projects.fetchNext();
  console.log(`Now have ${projects.length} projects`);
}

fetchAll()

Fetch all pages automatically.

Warning: This will fetch ALL projects which might take time.

await projects.fetchAll(config?: RequestConfig): Promise<void>

Example:

const projects = api.collections.project;

// Fetch all projects across all pages
await projects.fetchAll();
console.log(`Total projects: ${projects.length}`);

projects.forEach(project => {
  console.log(project.name);
});

Types

Project

interface Project {
  id: number;
  created_at: string;
  modified_at: string;
  name: string;
  external_id: string | null;
  lat: number | null;
  lon: number | null;
  timezone: string;
  data: Record<string, any>;
  is_invalidated: boolean;
}

Pagination

The Project API uses offset-based pagination. Use meta.next_offset for the next page:

Manual Pagination

import { initializeSGERP } from 'sgerp-frontend-lib';

const api = initializeSGERP({ /* config */ });

let offset = 0;
const limit = 20;

do {
  const response = await api.getProjects({ limit, offset });

  console.log(`Projects ${offset + 1} to ${offset + response.objects.length}:`);
  response.objects.forEach(project => {
    console.log(`  - ${project.name}`);
  });

  if (!response.meta.has_more) {
    break;
  }

  offset += limit;
} while (true);

Automatic Pagination

Use the all: true parameter to automatically fetch all pages:

import { initializeSGERP } from 'sgerp-frontend-lib';

const api = initializeSGERP({ /* config */ });

// Automatically fetches all projects across all pages
const response = await api.getProjects({ all: true });
console.log(`Total projects: ${response.objects.length}`);

response.objects.forEach(project => {
  console.log(`  - ${project.name}`);
});

Complete Example

import {
  initializeSGERP,
  type Project,
} from 'sgerp-frontend-lib';

// Initialize the library
const api = initializeSGERP({
  activeConnection: 'admin@staging',
  connections: {
    'admin@staging': {
      id: 'admin@staging',
      environment: 'staging',
      user: 'admin',
      password: 'your-password',
      baseUrl: 'https://sgerp-stage.d.gcdev.swatrider.com',
    },
  },
});

// Check authentication
const loggedIn = await api.isLoggedIn();
if (!loggedIn) {
  console.error('Not authenticated');
  process.exit(1);
}

// List first 20 projects
console.log('Fetching projects...');
const response = await api.getProjects({ limit: 20 });

console.log(`\nFound ${response.objects.length} projects:`);
response.objects.forEach((project, index) => {
  console.log(`\n${index + 1}. ${project.name}`);
  console.log(`   ID: ${project.id}`);
  console.log(`   Timezone: ${project.timezone}`);
  if (project.lat && project.lon) {
    console.log(`   Location: ${project.lat}, ${project.lon}`);
  }
  console.log(`   Created: ${new Date(project.created_at).toLocaleDateString()}`);
});

if (response.meta.has_more) {
  console.log('\n(More projects available...)');
}

// Get ALL projects
console.log('\n--- All Projects ---');
const allProjectsResponse = await api.getProjects({ all: true });
console.log(`Total projects: ${allProjectsResponse.objects.length}`);

// Get a specific project
console.log('\n--- Specific Project ---');
const project = await api.getProjectById(1);
if (project) {
  console.log('Project:', project.name);
  console.log('Details:', project);
}

Error Handling

import { initializeSGERP, APIError } from 'sgerp-frontend-lib';

const api = initializeSGERP({ /* config */ });

try {
  const response = await api.getProjects({ limit: 20 });
  console.log('Projects:', response.objects);
} catch (error) {
  if (error instanceof APIError) {
    if (error.status === 401) {
      console.error('Authentication failed');
    } else if (error.status === 403) {
      console.error('Access denied - insufficient permissions');
    } else {
      console.error('API error:', error.message);
    }
  } else {
    console.error('Unknown error:', error);
  }
}

Working with Project Data

Projects contain additional data in the data field:

import { initializeSGERP } from 'sgerp-frontend-lib';

const api = initializeSGERP({ /* config */ });

const response = await api.getProjects({ limit: 10 });

response.objects.forEach(project => {
  console.log(`\nProject: ${project.name}`);

  // Check if project has custom data
  if (Object.keys(project.data).length > 0) {
    console.log('Custom data:', project.data);
  }

  // Check if project is active
  if (!project.is_invalidated) {
    console.log('Status: Active');
  } else {
    console.log('Status: Invalidated');
  }

  // Work with coordinates
  if (project.lat && project.lon) {
    console.log(`Coordinates: ${project.lat}, ${project.lon}`);
    // Use coordinates for mapping, distance calculations, etc.
  }
});