@plandesk/api 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/events.d.ts +17 -1
  2. package/dist/events.d.ts.map +1 -1
  3. package/dist/events.js.map +1 -1
  4. package/dist/index.d.ts +5 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +4 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/projection.d.ts +51 -0
  9. package/dist/projection.d.ts.map +1 -0
  10. package/dist/projection.js +75 -0
  11. package/dist/projection.js.map +1 -0
  12. package/dist/routes/comments.d.ts +4 -0
  13. package/dist/routes/comments.d.ts.map +1 -0
  14. package/dist/routes/comments.js +74 -0
  15. package/dist/routes/comments.js.map +1 -0
  16. package/dist/serialize.d.ts +10 -1
  17. package/dist/serialize.d.ts.map +1 -1
  18. package/dist/serialize.js +10 -0
  19. package/dist/serialize.js.map +1 -1
  20. package/dist/server.d.ts.map +1 -1
  21. package/dist/server.js +3 -1
  22. package/dist/server.js.map +1 -1
  23. package/dist/services/comments.d.ts +31 -0
  24. package/dist/services/comments.d.ts.map +1 -0
  25. package/dist/services/comments.js +97 -0
  26. package/dist/services/comments.js.map +1 -0
  27. package/dist/services/documents.d.ts.map +1 -1
  28. package/dist/services/documents.js +2 -1
  29. package/dist/services/documents.js.map +1 -1
  30. package/dist/services/index.d.ts +6 -0
  31. package/dist/services/index.d.ts.map +1 -1
  32. package/dist/services/index.js +9 -0
  33. package/dist/services/index.js.map +1 -1
  34. package/dist/services/projects.d.ts +49 -2
  35. package/dist/services/projects.d.ts.map +1 -1
  36. package/dist/services/projects.js +122 -2
  37. package/dist/services/projects.js.map +1 -1
  38. package/dist/services/share.d.ts +41 -0
  39. package/dist/services/share.d.ts.map +1 -0
  40. package/dist/services/share.js +65 -0
  41. package/dist/services/share.js.map +1 -0
  42. package/dist/services/sync.d.ts +74 -0
  43. package/dist/services/sync.d.ts.map +1 -0
  44. package/dist/services/sync.js +297 -0
  45. package/dist/services/sync.js.map +1 -0
  46. package/dist/services/tasks.d.ts +13 -1
  47. package/dist/services/tasks.d.ts.map +1 -1
  48. package/dist/services/tasks.js +82 -1
  49. package/dist/services/tasks.js.map +1 -1
  50. package/package.json +4 -3
  51. package/web/_redirects +1 -0
  52. package/web/assets/index-DK5m0p5b.js +171 -0
  53. package/web/index.html +1 -1
  54. package/web/assets/index-DP1jpar6.js +0 -171
@@ -0,0 +1,297 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { getPullCursor, getShare, getSubmission as dbGetSubmission, getSyncRemote, listSubmissions, parseSharePermissions, setPullCursor, setSubmissionStatus, setSyncRemote, upsertSubmission, } from '@plandesk/db';
3
+ export class SyncUnavailableError extends Error {
4
+ constructor(message = 'sync server unavailable') {
5
+ super(message);
6
+ this.name = 'SyncUnavailableError';
7
+ }
8
+ }
9
+ export class SyncUnauthorizedError extends Error {
10
+ constructor(message = 'sync token unauthorized') {
11
+ super(message);
12
+ this.name = 'SyncUnauthorizedError';
13
+ }
14
+ }
15
+ export class InvalidTriageError extends Error {
16
+ constructor(message = 'submission not found') {
17
+ super(message);
18
+ this.name = 'InvalidTriageError';
19
+ }
20
+ }
21
+ export function serializeSubmission(row) {
22
+ return {
23
+ id: row.id,
24
+ project_id: row.projectId,
25
+ hosted_share_id: row.hostedShareId,
26
+ participant_name: row.participantName,
27
+ title: row.title,
28
+ body: row.body,
29
+ severity: row.severity,
30
+ task_ref: row.taskRef,
31
+ status: row.status,
32
+ linked_task_id: row.linkedTaskId,
33
+ created_at: row.createdAt.toISOString(),
34
+ pulled_at: row.pulledAt.toISOString(),
35
+ };
36
+ }
37
+ function parseInvitedEmails(raw) {
38
+ if (raw === null || raw === '') {
39
+ return [];
40
+ }
41
+ const parsed = JSON.parse(raw);
42
+ if (!Array.isArray(parsed)) {
43
+ return [];
44
+ }
45
+ return parsed.filter((value) => typeof value === 'string');
46
+ }
47
+ function buildDesc(submission) {
48
+ const footer = `Reported by ${submission.participantName} (client) via Plan Desk`;
49
+ if (submission.body === null || submission.body === '') {
50
+ return footer;
51
+ }
52
+ return `${submission.body}\n\n${footer}`;
53
+ }
54
+ async function ackSubmission(remote, submissionId, status) {
55
+ const base = remote.serverUrl.replace(/\/$/, '');
56
+ const url = `${base}/api/sync/v1/projects/${encodeURIComponent(remote.globalProjectId)}/submissions/${encodeURIComponent(submissionId)}/ack`;
57
+ let response;
58
+ try {
59
+ response = await fetch(url, {
60
+ method: 'POST',
61
+ headers: {
62
+ Authorization: `Bearer ${remote.syncToken}`,
63
+ 'Content-Type': 'application/json',
64
+ },
65
+ body: JSON.stringify({ status }),
66
+ });
67
+ }
68
+ catch {
69
+ throw new SyncUnavailableError();
70
+ }
71
+ if (!response.ok) {
72
+ throw new SyncUnavailableError(`sync server returned ${String(response.status)}`);
73
+ }
74
+ }
75
+ async function pushProjection(remote, share, view) {
76
+ const base = remote.serverUrl.replace(/\/$/, '');
77
+ const url = `${base}/api/sync/v1/projects/${encodeURIComponent(remote.globalProjectId)}/projection`;
78
+ let response;
79
+ try {
80
+ response = await fetch(url, {
81
+ method: 'PUT',
82
+ headers: {
83
+ Authorization: `Bearer ${remote.syncToken}`,
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ body: JSON.stringify({
87
+ share: {
88
+ token_hash: share.tokenHash,
89
+ audience_name: share.audienceName,
90
+ permissions: parseSharePermissions(share),
91
+ mode: share.mode,
92
+ invited_emails: parseInvitedEmails(share.invitedEmails),
93
+ expires_at: share.expiresAt?.toISOString() ?? null,
94
+ },
95
+ version: Date.now(),
96
+ view,
97
+ }),
98
+ });
99
+ }
100
+ catch {
101
+ throw new SyncUnavailableError();
102
+ }
103
+ if (response.status === 401) {
104
+ throw new SyncUnauthorizedError();
105
+ }
106
+ if (!response.ok) {
107
+ throw new SyncUnavailableError(`sync server returned ${String(response.status)}`);
108
+ }
109
+ }
110
+ function createWatchPush(push, projectId, remote, opts) {
111
+ const debounceMs = opts?.debounceMs ?? 1500;
112
+ const onPushError = opts?.onPushError ??
113
+ ((err) => {
114
+ const message = err instanceof Error ? err.message : String(err);
115
+ console.error(`sync watch push failed: ${message}`);
116
+ });
117
+ let timer;
118
+ let disposed = false;
119
+ const runPush = () => {
120
+ timer = undefined;
121
+ void push(projectId, remote).catch(onPushError);
122
+ };
123
+ return {
124
+ onChange() {
125
+ if (disposed) {
126
+ return;
127
+ }
128
+ if (timer !== undefined) {
129
+ clearTimeout(timer);
130
+ }
131
+ timer = setTimeout(runPush, debounceMs);
132
+ },
133
+ dispose() {
134
+ disposed = true;
135
+ if (timer !== undefined) {
136
+ clearTimeout(timer);
137
+ timer = undefined;
138
+ }
139
+ },
140
+ };
141
+ }
142
+ export function createSyncService(deps) {
143
+ const { db, eventBus, taskService, shareService } = deps;
144
+ return {
145
+ async push(projectId, remote) {
146
+ const shares = shareService.listShares(projectId);
147
+ if (shares === undefined) {
148
+ throw new SyncUnavailableError('project not found');
149
+ }
150
+ const active = shares.filter((share) => share.revoked_at === null);
151
+ let pushed = 0;
152
+ for (const serialized of active) {
153
+ const shareRow = getShare(db, serialized.id);
154
+ if (shareRow === undefined) {
155
+ continue;
156
+ }
157
+ const view = shareService.buildClientView(projectId, serialized.id);
158
+ if (view === undefined) {
159
+ continue;
160
+ }
161
+ await pushProjection(remote, shareRow, view);
162
+ pushed += 1;
163
+ }
164
+ return { pushed };
165
+ },
166
+ async publishProject(projectId, input) {
167
+ const globalProjectId = randomUUID();
168
+ const { pushed } = await this.push(projectId, {
169
+ serverUrl: input.serverUrl,
170
+ globalProjectId,
171
+ syncToken: input.syncToken,
172
+ });
173
+ return { globalProjectId, pushed };
174
+ },
175
+ async pull(projectId, remote) {
176
+ const cursor = getPullCursor(db, projectId);
177
+ const base = remote.serverUrl.replace(/\/$/, '');
178
+ const url = new URL(`${base}/api/sync/v1/projects/${encodeURIComponent(remote.globalProjectId)}/submissions`);
179
+ if (cursor !== undefined) {
180
+ url.searchParams.set('since', cursor);
181
+ }
182
+ let response;
183
+ try {
184
+ response = await fetch(url, {
185
+ headers: { Authorization: `Bearer ${remote.syncToken}` },
186
+ });
187
+ }
188
+ catch {
189
+ throw new SyncUnavailableError();
190
+ }
191
+ if (response.status === 401) {
192
+ throw new SyncUnauthorizedError();
193
+ }
194
+ if (!response.ok) {
195
+ throw new SyncUnavailableError(`sync server returned ${String(response.status)}`);
196
+ }
197
+ const remoteSubmissions = (await response.json());
198
+ const now = new Date();
199
+ let pulled = 0;
200
+ let maxCreatedAt = cursor;
201
+ for (const submission of remoteSubmissions) {
202
+ const inserted = upsertSubmission(db, {
203
+ id: submission.id,
204
+ projectId,
205
+ hostedShareId: submission.share_id,
206
+ participantName: submission.participant.name,
207
+ title: submission.title,
208
+ body: submission.body,
209
+ severity: submission.severity,
210
+ taskRef: submission.task_ref,
211
+ status: 'pending',
212
+ createdAt: new Date(submission.created_at),
213
+ pulledAt: now,
214
+ });
215
+ if (inserted) {
216
+ pulled += 1;
217
+ }
218
+ if (maxCreatedAt === undefined || submission.created_at > maxCreatedAt) {
219
+ maxCreatedAt = submission.created_at;
220
+ }
221
+ }
222
+ if (maxCreatedAt !== undefined && maxCreatedAt !== cursor) {
223
+ setPullCursor(db, projectId, maxCreatedAt);
224
+ }
225
+ if (pulled > 0) {
226
+ eventBus.emit({ type: 'submissions_pulled', projectId });
227
+ }
228
+ return { pulled };
229
+ },
230
+ listTriage(projectId, status) {
231
+ return listSubmissions(db, projectId, status).map(serializeSubmission);
232
+ },
233
+ getSubmission(submissionId) {
234
+ const submission = dbGetSubmission(db, submissionId);
235
+ return submission === undefined ? undefined : serializeSubmission(submission);
236
+ },
237
+ setRemote(projectId, remote) {
238
+ setSyncRemote(db, projectId, {
239
+ serverUrl: remote.serverUrl,
240
+ globalProjectId: remote.globalProjectId,
241
+ syncToken: remote.syncToken,
242
+ });
243
+ },
244
+ getRemote(projectId) {
245
+ const row = getSyncRemote(db, projectId);
246
+ if (row === undefined) {
247
+ return undefined;
248
+ }
249
+ return {
250
+ serverUrl: row.serverUrl,
251
+ globalProjectId: row.globalProjectId,
252
+ syncToken: row.syncToken,
253
+ };
254
+ },
255
+ async triage(submissionId, action, remote, asTask) {
256
+ const submission = dbGetSubmission(db, submissionId);
257
+ if (submission === undefined) {
258
+ throw new InvalidTriageError();
259
+ }
260
+ if (submission.status !== 'pending') {
261
+ return serializeSubmission(submission);
262
+ }
263
+ const projectId = submission.projectId;
264
+ if (action === 'accept') {
265
+ const task = taskService.create(projectId, {
266
+ label: asTask?.label ?? submission.title,
267
+ status: asTask?.status ?? 'todo',
268
+ description: asTask?.description ?? buildDesc(submission),
269
+ });
270
+ if (task === undefined) {
271
+ throw new InvalidTriageError('project not found');
272
+ }
273
+ const updated = setSubmissionStatus(db, submissionId, {
274
+ status: 'accepted',
275
+ linkedTaskId: task.id,
276
+ });
277
+ if (updated === undefined) {
278
+ throw new InvalidTriageError();
279
+ }
280
+ eventBus.emit({ type: 'submissions_pulled', projectId });
281
+ await ackSubmission(remote, submissionId, 'accepted');
282
+ return serializeSubmission(updated);
283
+ }
284
+ const updated = setSubmissionStatus(db, submissionId, { status: 'rejected' });
285
+ if (updated === undefined) {
286
+ throw new InvalidTriageError();
287
+ }
288
+ eventBus.emit({ type: 'submissions_pulled', projectId });
289
+ await ackSubmission(remote, submissionId, 'rejected');
290
+ return serializeSubmission(updated);
291
+ },
292
+ watchPush(projectId, remote, opts) {
293
+ return createWatchPush((id, rem) => this.push(id, rem), projectId, remote, opts);
294
+ },
295
+ };
296
+ }
297
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/services/sync.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,16 @@
1
1
  import { type Db, type TaskStatus } from '@plandesk/db';
2
2
  import type { EventBus } from '../events.js';
3
- import { type PaginationParams } from '../serialize.js';
3
+ import { serializeTask, type PaginationParams } from '../serialize.js';
4
+ type SerializedTask = ReturnType<typeof serializeTask>;
5
+ export type NextActionableReason = 'ok' | 'no_tasks' | 'no_todo_tasks' | 'all_blocked';
6
+ export type NextActionableResult = {
7
+ next_task: SerializedTask | null;
8
+ reason: NextActionableReason;
9
+ blocked: Array<{
10
+ task: SerializedTask;
11
+ waiting_on: SerializedTask[];
12
+ }>;
13
+ };
4
14
  export type TaskServiceDeps = {
5
15
  db: Db;
6
16
  eventBus: EventBus;
@@ -65,6 +75,8 @@ export declare function createTaskService(deps: TaskServiceDeps): {
65
75
  updated_at: string;
66
76
  } | undefined;
67
77
  delete(id: string): boolean;
78
+ nextActionable(projectId: string): NextActionableResult | undefined;
68
79
  };
69
80
  export type TaskService = ReturnType<typeof createTaskService>;
81
+ export {};
70
82
  //# sourceMappingURL=tasks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,EAAE,EACP,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,EAAE,CAAC;IACP,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe;6BAKtC,MAAM,WACT,eAAe,eACX,gBAAgB;;;;;;;;;;;;;sBAmBZ,MAAM,SAAS,eAAe;;;;;;;;;;;;;eA8BrC,MAAM,SAAS,eAAe;;;;;;;;;;;;;eAwB9B,MAAM;EAkBpB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,KAAK,EAAE,EAGP,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AAEvD,MAAM,MAAM,oBAAoB,GAAG,IAAI,GAAG,UAAU,GAAG,eAAe,GAAG,aAAa,CAAC;AAEvF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,cAAc,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,UAAU,EAAE,cAAc,EAAE,CAAA;KAAE,CAAC,CAAC;CACxE,CAAC;AAeF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,EAAE,CAAC;IACP,QAAQ,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe;6BAKtC,MAAM,WACT,eAAe,eACX,gBAAgB;;;;;;;;;;;;;sBAmBZ,MAAM,SAAS,eAAe;;;;;;;;;;;;;eA8BrC,MAAM,SAAS,eAAe;;;;;;;;;;;;;eAwB9B,MAAM;8BAkBS,MAAM,GAAG,oBAAoB,GAAG,SAAS;EAmFtE;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -1,5 +1,15 @@
1
- import { createTask, deleteEdgesByTaskId, deleteTask as dbDeleteTask, getProject, getTask, InvalidTaskStatusError, isTaskStatus, listTasks, nullDocumentsLinkedTask, updateTask, } from '@plandesk/db';
1
+ import { createTask, deleteEdgesByTaskId, deleteTask as dbDeleteTask, getProject, getTask, InvalidTaskStatusError, isTaskStatus, listEdges, listTasks, nullDocumentsLinkedTask, updateTask, } from '@plandesk/db';
2
2
  import { serializeTask } from '../serialize.js';
3
+ // depends_on: prerequisite = to, dependent = from. All other labels: prerequisite = from, dependent = to.
4
+ function prerequisiteAndDependent(edge) {
5
+ if (edge.fromTaskId === edge.toTaskId) {
6
+ return undefined;
7
+ }
8
+ if (edge.label === 'depends_on') {
9
+ return { prerequisite: edge.toTaskId, dependent: edge.fromTaskId };
10
+ }
11
+ return { prerequisite: edge.fromTaskId, dependent: edge.toTaskId };
12
+ }
3
13
  export function createTaskService(deps) {
4
14
  const { db, eventBus } = deps;
5
15
  return {
@@ -75,6 +85,77 @@ export function createTaskService(deps) {
75
85
  eventBus.emit({ type: 'canvas_updated', projectId });
76
86
  return true;
77
87
  },
88
+ nextActionable(projectId) {
89
+ const project = getProject(db, projectId);
90
+ if (!project) {
91
+ return undefined;
92
+ }
93
+ const tasks = listTasks(db, projectId).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
94
+ const edges = listEdges(db, projectId);
95
+ const taskById = new Map(tasks.map((task) => [task.id, task]));
96
+ const prerequisites = new Map();
97
+ for (const edge of edges) {
98
+ const pair = prerequisiteAndDependent(edge);
99
+ if (!pair) {
100
+ continue;
101
+ }
102
+ let set = prerequisites.get(pair.dependent);
103
+ if (!set) {
104
+ set = new Set();
105
+ prerequisites.set(pair.dependent, set);
106
+ }
107
+ set.add(pair.prerequisite);
108
+ }
109
+ if (tasks.length === 0) {
110
+ return { next_task: null, reason: 'no_tasks', blocked: [] };
111
+ }
112
+ const todoTasks = tasks.filter((task) => task.status === 'todo');
113
+ if (todoTasks.length === 0) {
114
+ return { next_task: null, reason: 'no_todo_tasks', blocked: [] };
115
+ }
116
+ const isActionable = (taskId) => {
117
+ const prereqs = prerequisites.get(taskId);
118
+ if (!prereqs || prereqs.size === 0) {
119
+ return true;
120
+ }
121
+ for (const prereqId of prereqs) {
122
+ const prereq = taskById.get(prereqId);
123
+ if (!prereq || prereq.status !== 'done') {
124
+ return false;
125
+ }
126
+ }
127
+ return true;
128
+ };
129
+ const unfinishedPrereqs = (taskId) => {
130
+ const prereqs = prerequisites.get(taskId);
131
+ if (!prereqs) {
132
+ return [];
133
+ }
134
+ return [...prereqs]
135
+ .map((id) => taskById.get(id))
136
+ .filter((task) => task !== undefined && task.status !== 'done')
137
+ .map(serializeTask);
138
+ };
139
+ const blocked = [];
140
+ let nextTask = null;
141
+ for (const task of todoTasks) {
142
+ if (isActionable(task.id)) {
143
+ if (nextTask === null) {
144
+ nextTask = serializeTask(task);
145
+ }
146
+ }
147
+ else {
148
+ blocked.push({
149
+ task: serializeTask(task),
150
+ waiting_on: unfinishedPrereqs(task.id),
151
+ });
152
+ }
153
+ }
154
+ if (nextTask === null) {
155
+ return { next_task: null, reason: 'all_blocked', blocked };
156
+ }
157
+ return { next_task: nextTask, reason: 'ok', blocked };
158
+ },
78
159
  };
79
160
  }
80
161
  //# sourceMappingURL=tasks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plandesk/api",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -19,7 +19,8 @@
19
19
  "devDependencies": {
20
20
  "typescript": "^6.0.3",
21
21
  "vitest": "^3.2.6",
22
- "@plandesk/db": "0.2.0"
22
+ "@plandesk/db": "0.4.0",
23
+ "@plandesk/sync-server": "0.4.0"
23
24
  },
24
25
  "dependencies": {
25
26
  "@hono/node-server": "^2.0.4",
@@ -28,7 +29,7 @@
28
29
  "description": "Plan Desk REST + SSE API and service layer (local-first planning workspace).",
29
30
  "license": "MIT",
30
31
  "author": "asyncdotengineering",
31
- "homepage": "https://plandesk-docs.pages.dev",
32
+ "homepage": "https://plandesk.asyncdot.com",
32
33
  "repository": {
33
34
  "type": "git",
34
35
  "url": "git+https://github.com/asyncdotengineering/plandesk.git",
package/web/_redirects ADDED
@@ -0,0 +1 @@
1
+ /* /index.html 200