@critical-path/client 0.14.8 → 0.15.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.
- package/CHANGELOG.md +41 -0
- package/README.md +9 -15
- package/dist/bin/cli.d.ts.map +1 -1
- package/dist/bin/cli.js +8 -43
- package/dist/bin/cli.js.map +1 -1
- package/dist/contract.test.d.ts +2 -0
- package/dist/contract.test.d.ts.map +1 -0
- package/dist/contract.test.js +54 -0
- package/dist/contract.test.js.map +1 -0
- package/dist/index.d.ts +33 -56
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -9
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +6 -6
- package/dist/index.test.js.map +1 -1
- package/package.json +4 -3
- package/src/bin/cli.ts +9 -45
- package/src/contract.test.ts +65 -0
- package/src/index.test.ts +6 -6
- package/src/index.ts +96 -51
- package/tsconfig.tsbuildinfo +1 -1
package/src/index.ts
CHANGED
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
CreateWorkflowBody,
|
|
3
|
+
UpdateWorkflowBody,
|
|
4
|
+
CreateProjectBody,
|
|
5
|
+
UpdateProjectBody,
|
|
6
|
+
CreateTaskBody,
|
|
7
|
+
UpdateTaskBody,
|
|
8
|
+
CreateDependencyBody,
|
|
9
|
+
CreateTeamBody,
|
|
10
|
+
UpdateTeamBody,
|
|
11
|
+
CreateContainerBody,
|
|
12
|
+
UpdateContainerBody,
|
|
13
|
+
CreateDeliverableBody,
|
|
14
|
+
UpdateDeliverableBody,
|
|
15
|
+
CreateIterationBody,
|
|
16
|
+
UpdateIterationBody,
|
|
17
|
+
CreateCommentBody,
|
|
18
|
+
UpdateCommentBody,
|
|
19
|
+
CommentReactionBody,
|
|
20
|
+
CreateAttachmentBody,
|
|
21
|
+
UploadAttachmentBody,
|
|
22
|
+
PresignAttachmentBody,
|
|
23
|
+
LogTimeBody
|
|
24
|
+
} from '@critical-path/core/schemas';
|
|
25
|
+
import type {
|
|
26
|
+
TaskDependency,
|
|
2
27
|
Project,
|
|
3
28
|
Task,
|
|
4
29
|
TaskTodoItem,
|
|
@@ -98,6 +123,15 @@ export interface ClientOptions {
|
|
|
98
123
|
fetch?: typeof fetch;
|
|
99
124
|
}
|
|
100
125
|
|
|
126
|
+
function toBase64(data: Uint8Array | ArrayBuffer): string {
|
|
127
|
+
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
128
|
+
let binary = '';
|
|
129
|
+
for (let i = 0; i < bytes.length; i += 0x8000) {
|
|
130
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
|
|
131
|
+
}
|
|
132
|
+
return btoa(binary);
|
|
133
|
+
}
|
|
134
|
+
|
|
101
135
|
class NotFoundResponseError extends Error {
|
|
102
136
|
constructor(message: string) {
|
|
103
137
|
super(message);
|
|
@@ -166,7 +200,7 @@ export class CriticalPathClient {
|
|
|
166
200
|
return res.workflow;
|
|
167
201
|
}
|
|
168
202
|
|
|
169
|
-
async createWorkflow(data:
|
|
203
|
+
async createWorkflow(data: CreateWorkflowBody): Promise<Workflow> {
|
|
170
204
|
const res = await this.request<{ workflow: Workflow }>('/workflows', {
|
|
171
205
|
method: 'POST',
|
|
172
206
|
body: JSON.stringify(data)
|
|
@@ -174,7 +208,7 @@ export class CriticalPathClient {
|
|
|
174
208
|
return res.workflow;
|
|
175
209
|
}
|
|
176
210
|
|
|
177
|
-
async updateWorkflow(id: string, updates:
|
|
211
|
+
async updateWorkflow(id: string, updates: UpdateWorkflowBody): Promise<Workflow> {
|
|
178
212
|
const res = await this.request<{ workflow: Workflow }>(`/workflows/${id}`, {
|
|
179
213
|
method: 'PATCH',
|
|
180
214
|
body: JSON.stringify(updates)
|
|
@@ -197,7 +231,7 @@ export class CriticalPathClient {
|
|
|
197
231
|
return res.project;
|
|
198
232
|
}
|
|
199
233
|
|
|
200
|
-
async createProject(data:
|
|
234
|
+
async createProject(data: CreateProjectBody): Promise<Project> {
|
|
201
235
|
const res = await this.request<{ project: Project }>('/projects', {
|
|
202
236
|
method: 'POST',
|
|
203
237
|
body: JSON.stringify(data)
|
|
@@ -205,6 +239,19 @@ export class CriticalPathClient {
|
|
|
205
239
|
return res.project;
|
|
206
240
|
}
|
|
207
241
|
|
|
242
|
+
async updateProject(id: string, updates: UpdateProjectBody): Promise<Project> {
|
|
243
|
+
const res = await this.request<{ project: Project }>(`/projects/${encodeURIComponent(id)}`, {
|
|
244
|
+
method: 'PATCH',
|
|
245
|
+
body: JSON.stringify(updates)
|
|
246
|
+
});
|
|
247
|
+
return res.project;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Deletes a project and its tasks. Resolves to `false` if it does not exist. */
|
|
251
|
+
async deleteProject(id: string): Promise<boolean> {
|
|
252
|
+
return this.deleteRequest(`/projects/${encodeURIComponent(id)}`);
|
|
253
|
+
}
|
|
254
|
+
|
|
208
255
|
async calculateCriticalPath(projectId: string): Promise<CriticalPathAnalysis> {
|
|
209
256
|
const res = await this.request<{ analysis: CriticalPathAnalysis }>(
|
|
210
257
|
`/projects/${encodeURIComponent(projectId)}/critical-path`
|
|
@@ -285,7 +332,7 @@ export class CriticalPathClient {
|
|
|
285
332
|
return res.progressHistory;
|
|
286
333
|
}
|
|
287
334
|
|
|
288
|
-
async createTask(data:
|
|
335
|
+
async createTask(data: CreateTaskBody): Promise<Task> {
|
|
289
336
|
const res = await this.request<{ task: Task }>('/tasks', {
|
|
290
337
|
method: 'POST',
|
|
291
338
|
body: JSON.stringify(data)
|
|
@@ -293,15 +340,7 @@ export class CriticalPathClient {
|
|
|
293
340
|
return res.task;
|
|
294
341
|
}
|
|
295
342
|
|
|
296
|
-
async updateTask(
|
|
297
|
-
id: string,
|
|
298
|
-
updates: Partial<Task> & {
|
|
299
|
-
actorId?: string;
|
|
300
|
-
actorName?: string;
|
|
301
|
-
actorType?: string;
|
|
302
|
-
actor?: { userId: string; username?: string; actorType?: string };
|
|
303
|
-
}
|
|
304
|
-
): Promise<Task> {
|
|
343
|
+
async updateTask(id: string, updates: UpdateTaskBody): Promise<Task> {
|
|
305
344
|
const res = await this.request<{ task: Task }>(`/tasks/${id}`, {
|
|
306
345
|
method: 'PATCH',
|
|
307
346
|
body: JSON.stringify(updates)
|
|
@@ -340,8 +379,7 @@ export class CriticalPathClient {
|
|
|
340
379
|
|
|
341
380
|
async addTodo(
|
|
342
381
|
taskId: string,
|
|
343
|
-
title: string
|
|
344
|
-
options?: { actorId?: string; actorName?: string; actorType?: string }
|
|
382
|
+
title: string
|
|
345
383
|
): Promise<TaskTodoItem> {
|
|
346
384
|
const task = await this.getTask(taskId);
|
|
347
385
|
const item: TaskTodoItem = {
|
|
@@ -351,15 +389,14 @@ export class CriticalPathClient {
|
|
|
351
389
|
createdAt: new Date().toISOString()
|
|
352
390
|
};
|
|
353
391
|
const todos = [...(task.todos || []), item];
|
|
354
|
-
await this.updateTask(taskId, { todos
|
|
392
|
+
await this.updateTask(taskId, { todos });
|
|
355
393
|
return item;
|
|
356
394
|
}
|
|
357
395
|
|
|
358
396
|
async toggleTodo(
|
|
359
397
|
taskId: string,
|
|
360
398
|
todoIdOrTitle: string,
|
|
361
|
-
completed?: boolean
|
|
362
|
-
options?: { actorId?: string; actorName?: string; actorType?: string }
|
|
399
|
+
completed?: boolean
|
|
363
400
|
): Promise<Task> {
|
|
364
401
|
const task = await this.getTask(taskId);
|
|
365
402
|
if (!task.todos || task.todos.length === 0) {
|
|
@@ -373,7 +410,16 @@ export class CriticalPathClient {
|
|
|
373
410
|
}
|
|
374
411
|
item.completed = completed !== undefined ? completed : !item.completed;
|
|
375
412
|
item.completedAt = item.completed ? new Date().toISOString() : undefined;
|
|
376
|
-
return this.updateTask(taskId, { todos: task.todos
|
|
413
|
+
return this.updateTask(taskId, { todos: task.todos });
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/** Declares that `taskId` depends on another task. Rejects with a 409 error on cycles. */
|
|
417
|
+
async addDependency(taskId: string, data: CreateDependencyBody): Promise<TaskDependency> {
|
|
418
|
+
const res = await this.request<{ dependency: TaskDependency }>(`/tasks/${encodeURIComponent(taskId)}/dependencies`, {
|
|
419
|
+
method: 'POST',
|
|
420
|
+
body: JSON.stringify(data)
|
|
421
|
+
});
|
|
422
|
+
return res.dependency;
|
|
377
423
|
}
|
|
378
424
|
|
|
379
425
|
async deleteTask(id: string): Promise<boolean> {
|
|
@@ -411,7 +457,7 @@ export class CriticalPathClient {
|
|
|
411
457
|
return res.team;
|
|
412
458
|
}
|
|
413
459
|
|
|
414
|
-
async createTeam(data:
|
|
460
|
+
async createTeam(data: CreateTeamBody): Promise<Team> {
|
|
415
461
|
const res = await this.request<{ team: Team }>('/teams', {
|
|
416
462
|
method: 'POST',
|
|
417
463
|
body: JSON.stringify(data)
|
|
@@ -419,7 +465,7 @@ export class CriticalPathClient {
|
|
|
419
465
|
return res.team;
|
|
420
466
|
}
|
|
421
467
|
|
|
422
|
-
async updateTeam(id: string, updates:
|
|
468
|
+
async updateTeam(id: string, updates: UpdateTeamBody): Promise<Team> {
|
|
423
469
|
const res = await this.request<{ team: Team }>(`/teams/${id}`, {
|
|
424
470
|
method: 'PATCH',
|
|
425
471
|
body: JSON.stringify(updates)
|
|
@@ -437,7 +483,7 @@ export class CriticalPathClient {
|
|
|
437
483
|
return res.containers;
|
|
438
484
|
}
|
|
439
485
|
|
|
440
|
-
async createContainer(data:
|
|
486
|
+
async createContainer(data: CreateContainerBody): Promise<TaskContainer> {
|
|
441
487
|
const res = await this.request<{ container: TaskContainer }>('/containers', {
|
|
442
488
|
method: 'POST',
|
|
443
489
|
body: JSON.stringify(data)
|
|
@@ -445,7 +491,7 @@ export class CriticalPathClient {
|
|
|
445
491
|
return res.container;
|
|
446
492
|
}
|
|
447
493
|
|
|
448
|
-
async updateContainer(id: string, updates:
|
|
494
|
+
async updateContainer(id: string, updates: UpdateContainerBody): Promise<TaskContainer> {
|
|
449
495
|
const res = await this.request<{ container: TaskContainer }>(`/containers/${id}`, {
|
|
450
496
|
method: 'PATCH',
|
|
451
497
|
body: JSON.stringify(updates)
|
|
@@ -473,7 +519,7 @@ export class CriticalPathClient {
|
|
|
473
519
|
return res.summary;
|
|
474
520
|
}
|
|
475
521
|
|
|
476
|
-
async createDeliverable(data:
|
|
522
|
+
async createDeliverable(data: CreateDeliverableBody): Promise<Deliverable> {
|
|
477
523
|
const res = await this.request<{ deliverable: Deliverable }>('/deliverables', {
|
|
478
524
|
method: 'POST',
|
|
479
525
|
body: JSON.stringify(data)
|
|
@@ -481,7 +527,7 @@ export class CriticalPathClient {
|
|
|
481
527
|
return res.deliverable;
|
|
482
528
|
}
|
|
483
529
|
|
|
484
|
-
async updateDeliverable(id: string, updates:
|
|
530
|
+
async updateDeliverable(id: string, updates: UpdateDeliverableBody): Promise<Deliverable> {
|
|
485
531
|
const res = await this.request<{ deliverable: Deliverable }>(`/deliverables/${id}`, {
|
|
486
532
|
method: 'PATCH',
|
|
487
533
|
body: JSON.stringify(updates)
|
|
@@ -499,7 +545,7 @@ export class CriticalPathClient {
|
|
|
499
545
|
return res.iterations;
|
|
500
546
|
}
|
|
501
547
|
|
|
502
|
-
async createIteration(data:
|
|
548
|
+
async createIteration(data: CreateIterationBody): Promise<Iteration> {
|
|
503
549
|
const res = await this.request<{ iteration: Iteration }>('/iterations', {
|
|
504
550
|
method: 'POST',
|
|
505
551
|
body: JSON.stringify(data)
|
|
@@ -507,7 +553,7 @@ export class CriticalPathClient {
|
|
|
507
553
|
return res.iteration;
|
|
508
554
|
}
|
|
509
555
|
|
|
510
|
-
async updateIteration(id: string, updates:
|
|
556
|
+
async updateIteration(id: string, updates: UpdateIterationBody): Promise<Iteration> {
|
|
511
557
|
const res = await this.request<{ iteration: Iteration }>(`/iterations/${id}`, {
|
|
512
558
|
method: 'PATCH',
|
|
513
559
|
body: JSON.stringify(updates)
|
|
@@ -540,7 +586,7 @@ export class CriticalPathClient {
|
|
|
540
586
|
return res.comment;
|
|
541
587
|
}
|
|
542
588
|
|
|
543
|
-
async addComment(data:
|
|
589
|
+
async addComment(data: CreateCommentBody): Promise<Comment> {
|
|
544
590
|
const res = await this.request<{ comment: Comment }>('/comments', {
|
|
545
591
|
method: 'POST',
|
|
546
592
|
body: JSON.stringify(data)
|
|
@@ -548,7 +594,7 @@ export class CriticalPathClient {
|
|
|
548
594
|
return res.comment;
|
|
549
595
|
}
|
|
550
596
|
|
|
551
|
-
async updateComment(id: string, updates:
|
|
597
|
+
async updateComment(id: string, updates: UpdateCommentBody): Promise<Comment> {
|
|
552
598
|
const res = await this.request<{ comment: Comment }>(`/comments/${encodeURIComponent(id)}`, {
|
|
553
599
|
method: 'PATCH',
|
|
554
600
|
body: JSON.stringify(updates)
|
|
@@ -560,7 +606,7 @@ export class CriticalPathClient {
|
|
|
560
606
|
return this.deleteRequest(`/comments/${encodeURIComponent(id)}`);
|
|
561
607
|
}
|
|
562
608
|
|
|
563
|
-
async addCommentReaction(commentId: string, reaction:
|
|
609
|
+
async addCommentReaction(commentId: string, reaction: CommentReactionBody): Promise<Comment> {
|
|
564
610
|
const res = await this.request<{ comment: Comment }>(`/comments/${encodeURIComponent(commentId)}/reactions`, {
|
|
565
611
|
method: 'POST',
|
|
566
612
|
body: JSON.stringify(reaction)
|
|
@@ -568,11 +614,12 @@ export class CriticalPathClient {
|
|
|
568
614
|
return res.comment;
|
|
569
615
|
}
|
|
570
616
|
|
|
571
|
-
async removeCommentReaction(commentId: string, reaction:
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
617
|
+
async removeCommentReaction(commentId: string, reaction: CommentReactionBody): Promise<Comment> {
|
|
618
|
+
const query = new URLSearchParams({ emoji: reaction.emoji });
|
|
619
|
+
const res = await this.request<{ comment: Comment }>(
|
|
620
|
+
`/comments/${encodeURIComponent(commentId)}/reactions?${query}`,
|
|
621
|
+
{ method: 'DELETE' }
|
|
622
|
+
);
|
|
576
623
|
return res.comment;
|
|
577
624
|
}
|
|
578
625
|
|
|
@@ -592,7 +639,7 @@ export class CriticalPathClient {
|
|
|
592
639
|
return res.attachment;
|
|
593
640
|
}
|
|
594
641
|
|
|
595
|
-
async createAttachment(data:
|
|
642
|
+
async createAttachment(data: CreateAttachmentBody): Promise<Attachment> {
|
|
596
643
|
const res = await this.request<{ attachment: Attachment }>('/attachments', {
|
|
597
644
|
method: 'POST',
|
|
598
645
|
body: JSON.stringify(data)
|
|
@@ -600,21 +647,19 @@ export class CriticalPathClient {
|
|
|
600
647
|
return res.attachment;
|
|
601
648
|
}
|
|
602
649
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
metadata?: Record<string, unknown>;
|
|
614
|
-
}): Promise<Attachment> {
|
|
650
|
+
/**
|
|
651
|
+
* Uploads a file through the server's FileStorageAdapter. Binary data is sent base64-encoded.
|
|
652
|
+
*/
|
|
653
|
+
async uploadAttachmentFile(
|
|
654
|
+
data: Omit<UploadAttachmentBody, 'data'> & { data: string | Uint8Array | ArrayBuffer }
|
|
655
|
+
): Promise<Attachment> {
|
|
656
|
+
const body: UploadAttachmentBody =
|
|
657
|
+
typeof data.data === 'string'
|
|
658
|
+
? { ...data, data: data.data }
|
|
659
|
+
: { ...data, data: toBase64(data.data), encoding: 'base64' };
|
|
615
660
|
const res = await this.request<{ attachment: Attachment }>('/attachments/upload', {
|
|
616
661
|
method: 'POST',
|
|
617
|
-
body: JSON.stringify(
|
|
662
|
+
body: JSON.stringify(body)
|
|
618
663
|
});
|
|
619
664
|
return res.attachment;
|
|
620
665
|
}
|
|
@@ -623,7 +668,7 @@ export class CriticalPathClient {
|
|
|
623
668
|
return this.deleteRequest(`/attachments/${encodeURIComponent(id)}`);
|
|
624
669
|
}
|
|
625
670
|
|
|
626
|
-
async getPresignedAttachmentUploadUrl(options:
|
|
671
|
+
async getPresignedAttachmentUploadUrl(options: PresignAttachmentBody): Promise<PresignedUploadResult> {
|
|
627
672
|
const res = await this.request<{ presigned: PresignedUploadResult }>('/attachments/presign', {
|
|
628
673
|
method: 'POST',
|
|
629
674
|
body: JSON.stringify(options)
|
|
@@ -637,7 +682,7 @@ export class CriticalPathClient {
|
|
|
637
682
|
return res.timeEntries;
|
|
638
683
|
}
|
|
639
684
|
|
|
640
|
-
async logTime(data:
|
|
685
|
+
async logTime(data: LogTimeBody): Promise<TimeEntry> {
|
|
641
686
|
const res = await this.request<{ timeEntry: TimeEntry }>('/time-entries', {
|
|
642
687
|
method: 'POST',
|
|
643
688
|
body: JSON.stringify(data)
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/cli.test.ts","./src/index.test.ts","./src/index.ts","./src/bin/cli.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["./src/cli.test.ts","./src/contract.test.ts","./src/index.test.ts","./src/index.ts","./src/bin/cli.ts"],"version":"5.9.3"}
|