@timelynode/sdk
v1.1.0
Published
TypeScript SDK for the TimleyNodes Optimization API
Maintainers
Readme
@timelynode/sdk
TypeScript SDK for the TimleyNodes Optimization API — a belief-propagation solver for timetabling, scheduling, and resource allocation problems.
Installation
npm install @timelynode/sdk
# or
yarn add @timelynode/sdk
# or
pnpm add @timelynode/sdkQuick start
import { TimelyNodeClient } from '@timelynode/sdk';
const client = new TimelyNodeClient({ apiKey: 'your-api-key' });
const result = await client.optimizeAndWait({
jobName: 'semester-1',
graphDefinition: {
version: '1.0',
nodes: [
{ id: 'lec-math', type: 'VARIABLE', metadata: { demand: 1 } },
{ id: 'lec-cs', type: 'VARIABLE', metadata: { demand: 1 } },
{ id: 'clash-A', type: 'CONSTRAINT' },
{ id: 'room-101', type: 'RESOURCE', metadata: { capacity: 2 } },
],
edges: [
{ from: 'lec-math', to: 'clash-A' },
{ from: 'lec-cs', to: 'clash-A' },
{ from: 'clash-A', to: 'room-101' },
],
constraintStrategies: {
'clash-A': {
strategyName: 'resource_capacity',
parameters: { penalty: 100 },
},
},
},
solverConfig: { vectorDimension: 10 },
});
console.log(result.assignment); // { 'lec-math': 3, 'lec-cs': 7 }
console.log(result.totalCost); // 0Two-step usage (submit then poll)
const { jobId } = await client.optimize(request);
// check status
const status = await client.getJob(jobId);
console.log(status.status); // 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED'
// fetch result once complete
const result = await client.waitForResult(jobId, {
pollIntervalMs: 500, // default 1000
timeoutMs: 60_000, // default 300000 (5 min)
});Constraint strategies
| Strategy | Purpose | Key parameter |
|---|---|---|
| clash | Prevent two events sharing a slot | penalty ≥ 1000 for hard |
| resource_capacity | Limit room/resource usage per slot | penalty, variable demand, resource capacity |
| preference | Soft preferred time windows | penalty, variable preferredSlots |
| spreading | Discourage same-day clustering | penalty, requires slotsPerDay in solverConfig |
| room | Teaching-timetable room assignment | penalty (clash cost), alpha (oversize coefficient) |
Room assignment (room strategy)
One room constraint per event. Connect it to the event variable and all candidate rooms.
const result = await client.optimizeAndWait({
jobName: 'timetable-with-rooms',
graphDefinition: {
version: '1.0',
nodes: [
{ id: 'lec-math', type: 'VARIABLE', metadata: { size: 40, duration: 1 } },
{ id: 'room-math', type: 'CONSTRAINT' },
{ id: 'R101', type: 'RESOURCE', metadata: { capacity: 40, layouts: ['lecture'] } },
{ id: 'R202', type: 'RESOURCE', metadata: { capacity: 100, layouts: ['lecture'] } },
],
edges: [
{ from: 'lec-math', to: 'room-math' },
{ from: 'room-math', to: 'R101' },
{ from: 'room-math', to: 'R202' },
],
constraintStrategies: {
'room-math': { strategyName: 'room', parameters: { penalty: 100, alpha: 1.0 } },
},
},
solverConfig: { vectorDimension: 10 },
});
// Room assignments appear in structuredAssignment
console.log(result.structuredAssignment);
// { 'lec-math': { timeslot: 2, room: 'R101', roomSuitability: 0 } }Event metadata: size (attendees), duration (slots, default 1), requiredLayout, requiredEquipment (array).
Room metadata: capacity, layouts (array), equipment (array).
Suitability: exact fit → 0 cost; oversized → alpha × spareRatio; undersized or missing layout/equipment → excluded.ROOM_CLASH in costBreakdown means two events were resolved to the same room at overlapping times — increase penalty or add more candidate rooms.
Error handling
import {
TimelyNodeApiError,
TimelyNodeJobFailedError,
TimelyNodeTimeoutError,
} from '@timelynode/sdk';
try {
const result = await client.optimizeAndWait(request);
} catch (err) {
if (err instanceof TimelyNodeApiError) {
console.error(err.status, err.code, err.message); // 403, LICENSE_INVALID, ...
} else if (err instanceof TimelyNodeJobFailedError) {
console.error('Solver failed for job', err.jobId);
} else if (err instanceof TimelyNodeTimeoutError) {
console.error('Timed out after', err.timeoutMs, 'ms');
}
}API reference
Full OpenAPI spec: https://api.timelynode.com/q/openapi
Interactive docs: https://api.timelynode.com/q/swagger-ui
