@doist/todoist-api-typescript 6.0.0 → 6.1.4
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/README.md +105 -5
- package/dist/cjs/authentication.js +59 -63
- package/dist/cjs/rest-client.js +15 -11
- package/dist/cjs/test-utils/mocks.js +2 -45
- package/dist/cjs/test-utils/msw-setup.js +74 -5
- package/dist/cjs/test-utils/obsidian-fetch-adapter.js +53 -0
- package/dist/cjs/todoist-api.js +80 -30
- package/dist/cjs/types/entities.js +4 -4
- package/dist/cjs/types/index.js +1 -0
- package/dist/cjs/utils/fetch-with-retry.js +37 -14
- package/dist/cjs/utils/multipart-upload.js +2 -1
- package/dist/esm/authentication.js +59 -63
- package/dist/esm/rest-client.js +15 -11
- package/dist/esm/test-utils/mocks.js +3 -10
- package/dist/esm/test-utils/msw-setup.js +67 -2
- package/dist/esm/test-utils/obsidian-fetch-adapter.js +50 -0
- package/dist/esm/todoist-api.js +80 -30
- package/dist/esm/types/entities.js +4 -4
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/utils/fetch-with-retry.js +37 -14
- package/dist/esm/utils/multipart-upload.js +2 -1
- package/dist/types/authentication.d.ts +20 -0
- package/dist/types/rest-client.d.ts +2 -1
- package/dist/types/test-utils/mocks.d.ts +0 -1
- package/dist/types/test-utils/msw-setup.d.ts +31 -1
- package/dist/types/test-utils/obsidian-fetch-adapter.d.ts +29 -0
- package/dist/types/todoist-api.d.ts +18 -7
- package/dist/types/types/entities.d.ts +4 -4
- package/dist/types/types/http.d.ts +17 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/sync.d.ts +5 -5
- package/dist/types/utils/fetch-with-retry.d.ts +2 -1
- package/dist/types/utils/multipart-upload.d.ts +2 -0
- package/package.json +4 -3
package/dist/esm/todoist-api.js
CHANGED
|
@@ -16,27 +16,6 @@ const MAX_COMMAND_COUNT = 100;
|
|
|
16
16
|
function generatePath(...segments) {
|
|
17
17
|
return segments.join('/');
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
20
|
-
* A client for interacting with the Todoist API v1.
|
|
21
|
-
* This class provides methods to manage tasks, projects, sections, labels, and comments in Todoist.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```typescript
|
|
25
|
-
* const api = new TodoistApi('your-api-token');
|
|
26
|
-
*
|
|
27
|
-
* // Get all tasks
|
|
28
|
-
* const tasks = await api.getTasks();
|
|
29
|
-
*
|
|
30
|
-
* // Create a new task
|
|
31
|
-
* const newTask = await api.addTask({
|
|
32
|
-
* content: 'My new task',
|
|
33
|
-
* projectId: '12345'
|
|
34
|
-
* });
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* For more information about the Todoist API v1, see the [official documentation](https://todoist.com/api/v1).
|
|
38
|
-
* If you're migrating from v9, please refer to the [migration guide](https://todoist.com/api/v1/docs#tag/Migrating-from-v9).
|
|
39
|
-
*/
|
|
40
19
|
export class TodoistApi {
|
|
41
20
|
constructor(
|
|
42
21
|
/**
|
|
@@ -44,11 +23,24 @@ export class TodoistApi {
|
|
|
44
23
|
*/
|
|
45
24
|
authToken,
|
|
46
25
|
/**
|
|
47
|
-
* Optional custom API base URL
|
|
26
|
+
* Optional custom API base URL or options object
|
|
48
27
|
*/
|
|
49
|
-
|
|
28
|
+
baseUrlOrOptions) {
|
|
50
29
|
this.authToken = authToken;
|
|
51
|
-
|
|
30
|
+
// Handle backward compatibility
|
|
31
|
+
if (typeof baseUrlOrOptions === 'string') {
|
|
32
|
+
// Legacy constructor: (authToken, baseUrl)
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
34
|
+
console.warn('TodoistApi constructor with baseUrl as second parameter is deprecated. Use options object instead: new TodoistApi(token, { baseUrl, customFetch })');
|
|
35
|
+
this.syncApiBase = getSyncBaseUri(baseUrlOrOptions);
|
|
36
|
+
this.customFetch = undefined;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// New constructor: (authToken, options)
|
|
40
|
+
const options = baseUrlOrOptions || {};
|
|
41
|
+
this.syncApiBase = getSyncBaseUri(options.baseUrl);
|
|
42
|
+
this.customFetch = options.customFetch;
|
|
43
|
+
}
|
|
52
44
|
}
|
|
53
45
|
/**
|
|
54
46
|
* Retrieves information about the authenticated user.
|
|
@@ -61,6 +53,7 @@ export class TodoistApi {
|
|
|
61
53
|
baseUri: this.syncApiBase,
|
|
62
54
|
relativePath: ENDPOINT_REST_USER,
|
|
63
55
|
apiToken: this.authToken,
|
|
56
|
+
customFetch: this.customFetch,
|
|
64
57
|
});
|
|
65
58
|
return validateCurrentUser(response.data);
|
|
66
59
|
}
|
|
@@ -77,6 +70,7 @@ export class TodoistApi {
|
|
|
77
70
|
baseUri: this.syncApiBase,
|
|
78
71
|
relativePath: generatePath(ENDPOINT_REST_TASKS, id),
|
|
79
72
|
apiToken: this.authToken,
|
|
73
|
+
customFetch: this.customFetch,
|
|
80
74
|
});
|
|
81
75
|
return validateTask(response.data);
|
|
82
76
|
}
|
|
@@ -92,6 +86,7 @@ export class TodoistApi {
|
|
|
92
86
|
baseUri: this.syncApiBase,
|
|
93
87
|
relativePath: ENDPOINT_REST_TASKS,
|
|
94
88
|
apiToken: this.authToken,
|
|
89
|
+
customFetch: this.customFetch,
|
|
95
90
|
payload: args,
|
|
96
91
|
});
|
|
97
92
|
return {
|
|
@@ -111,6 +106,7 @@ export class TodoistApi {
|
|
|
111
106
|
baseUri: this.syncApiBase,
|
|
112
107
|
relativePath: ENDPOINT_REST_TASKS_FILTER,
|
|
113
108
|
apiToken: this.authToken,
|
|
109
|
+
customFetch: this.customFetch,
|
|
114
110
|
payload: args,
|
|
115
111
|
});
|
|
116
112
|
return {
|
|
@@ -130,6 +126,7 @@ export class TodoistApi {
|
|
|
130
126
|
baseUri: this.syncApiBase,
|
|
131
127
|
relativePath: ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE,
|
|
132
128
|
apiToken: this.authToken,
|
|
129
|
+
customFetch: this.customFetch,
|
|
133
130
|
payload: args,
|
|
134
131
|
});
|
|
135
132
|
return {
|
|
@@ -149,6 +146,7 @@ export class TodoistApi {
|
|
|
149
146
|
baseUri: this.syncApiBase,
|
|
150
147
|
relativePath: ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE,
|
|
151
148
|
apiToken: this.authToken,
|
|
149
|
+
customFetch: this.customFetch,
|
|
152
150
|
payload: args,
|
|
153
151
|
});
|
|
154
152
|
return {
|
|
@@ -168,6 +166,7 @@ export class TodoistApi {
|
|
|
168
166
|
baseUri: this.syncApiBase,
|
|
169
167
|
relativePath: ENDPOINT_REST_TASKS_COMPLETED_SEARCH,
|
|
170
168
|
apiToken: this.authToken,
|
|
169
|
+
customFetch: this.customFetch,
|
|
171
170
|
payload: args,
|
|
172
171
|
});
|
|
173
172
|
return {
|
|
@@ -188,6 +187,7 @@ export class TodoistApi {
|
|
|
188
187
|
baseUri: this.syncApiBase,
|
|
189
188
|
relativePath: ENDPOINT_REST_TASKS,
|
|
190
189
|
apiToken: this.authToken,
|
|
190
|
+
customFetch: this.customFetch,
|
|
191
191
|
payload: args,
|
|
192
192
|
requestId: requestId,
|
|
193
193
|
});
|
|
@@ -205,6 +205,7 @@ export class TodoistApi {
|
|
|
205
205
|
baseUri: this.syncApiBase,
|
|
206
206
|
relativePath: ENDPOINT_SYNC_QUICK_ADD,
|
|
207
207
|
apiToken: this.authToken,
|
|
208
|
+
customFetch: this.customFetch,
|
|
208
209
|
payload: args,
|
|
209
210
|
});
|
|
210
211
|
return validateTask(response.data);
|
|
@@ -224,6 +225,7 @@ export class TodoistApi {
|
|
|
224
225
|
baseUri: this.syncApiBase,
|
|
225
226
|
relativePath: generatePath(ENDPOINT_REST_TASKS, id),
|
|
226
227
|
apiToken: this.authToken,
|
|
228
|
+
customFetch: this.customFetch,
|
|
227
229
|
payload: args,
|
|
228
230
|
requestId: requestId,
|
|
229
231
|
});
|
|
@@ -257,15 +259,16 @@ export class TodoistApi {
|
|
|
257
259
|
baseUri: this.syncApiBase,
|
|
258
260
|
relativePath: ENDPOINT_SYNC,
|
|
259
261
|
apiToken: this.authToken,
|
|
262
|
+
customFetch: this.customFetch,
|
|
260
263
|
payload: syncRequest,
|
|
261
264
|
requestId: requestId,
|
|
262
265
|
hasSyncCommands: true,
|
|
263
266
|
});
|
|
264
|
-
if (response.data.
|
|
265
|
-
Object.entries(response.data.
|
|
267
|
+
if (response.data.syncStatus) {
|
|
268
|
+
Object.entries(response.data.syncStatus).forEach(([_, value]) => {
|
|
266
269
|
if (value === 'ok')
|
|
267
270
|
return;
|
|
268
|
-
throw new TodoistRequestError(value.error, value.
|
|
271
|
+
throw new TodoistRequestError(value.error, value.httpCode, value.errorExtra);
|
|
269
272
|
});
|
|
270
273
|
}
|
|
271
274
|
if (!((_a = response.data.items) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
@@ -292,6 +295,7 @@ export class TodoistApi {
|
|
|
292
295
|
baseUri: this.syncApiBase,
|
|
293
296
|
relativePath: generatePath(ENDPOINT_REST_TASKS, id, ENDPOINT_REST_TASK_MOVE),
|
|
294
297
|
apiToken: this.authToken,
|
|
298
|
+
customFetch: this.customFetch,
|
|
295
299
|
payload: Object.assign(Object.assign(Object.assign({}, (args.projectId && { project_id: args.projectId })), (args.sectionId && { section_id: args.sectionId })), (args.parentId && { parent_id: args.parentId })),
|
|
296
300
|
requestId: requestId,
|
|
297
301
|
});
|
|
@@ -311,6 +315,7 @@ export class TodoistApi {
|
|
|
311
315
|
baseUri: this.syncApiBase,
|
|
312
316
|
relativePath: generatePath(ENDPOINT_REST_TASKS, id, ENDPOINT_REST_TASK_CLOSE),
|
|
313
317
|
apiToken: this.authToken,
|
|
318
|
+
customFetch: this.customFetch,
|
|
314
319
|
requestId: requestId,
|
|
315
320
|
});
|
|
316
321
|
return isSuccess(response);
|
|
@@ -329,6 +334,7 @@ export class TodoistApi {
|
|
|
329
334
|
baseUri: this.syncApiBase,
|
|
330
335
|
relativePath: generatePath(ENDPOINT_REST_TASKS, id, ENDPOINT_REST_TASK_REOPEN),
|
|
331
336
|
apiToken: this.authToken,
|
|
337
|
+
customFetch: this.customFetch,
|
|
332
338
|
requestId: requestId,
|
|
333
339
|
});
|
|
334
340
|
return isSuccess(response);
|
|
@@ -347,6 +353,7 @@ export class TodoistApi {
|
|
|
347
353
|
baseUri: this.syncApiBase,
|
|
348
354
|
relativePath: generatePath(ENDPOINT_REST_TASKS, id),
|
|
349
355
|
apiToken: this.authToken,
|
|
356
|
+
customFetch: this.customFetch,
|
|
350
357
|
requestId: requestId,
|
|
351
358
|
});
|
|
352
359
|
return isSuccess(response);
|
|
@@ -364,6 +371,7 @@ export class TodoistApi {
|
|
|
364
371
|
baseUri: this.syncApiBase,
|
|
365
372
|
relativePath: generatePath(ENDPOINT_REST_PROJECTS, id),
|
|
366
373
|
apiToken: this.authToken,
|
|
374
|
+
customFetch: this.customFetch,
|
|
367
375
|
});
|
|
368
376
|
return validateProject(response.data);
|
|
369
377
|
}
|
|
@@ -379,6 +387,7 @@ export class TodoistApi {
|
|
|
379
387
|
baseUri: this.syncApiBase,
|
|
380
388
|
relativePath: ENDPOINT_REST_PROJECTS,
|
|
381
389
|
apiToken: this.authToken,
|
|
390
|
+
customFetch: this.customFetch,
|
|
382
391
|
payload: args,
|
|
383
392
|
});
|
|
384
393
|
return {
|
|
@@ -398,6 +407,7 @@ export class TodoistApi {
|
|
|
398
407
|
baseUri: this.syncApiBase,
|
|
399
408
|
relativePath: ENDPOINT_REST_PROJECTS_ARCHIVED,
|
|
400
409
|
apiToken: this.authToken,
|
|
410
|
+
customFetch: this.customFetch,
|
|
401
411
|
payload: args,
|
|
402
412
|
});
|
|
403
413
|
return {
|
|
@@ -418,6 +428,7 @@ export class TodoistApi {
|
|
|
418
428
|
baseUri: this.syncApiBase,
|
|
419
429
|
relativePath: ENDPOINT_REST_PROJECTS,
|
|
420
430
|
apiToken: this.authToken,
|
|
431
|
+
customFetch: this.customFetch,
|
|
421
432
|
payload: args,
|
|
422
433
|
requestId: requestId,
|
|
423
434
|
});
|
|
@@ -438,6 +449,7 @@ export class TodoistApi {
|
|
|
438
449
|
baseUri: this.syncApiBase,
|
|
439
450
|
relativePath: generatePath(ENDPOINT_REST_PROJECTS, id),
|
|
440
451
|
apiToken: this.authToken,
|
|
452
|
+
customFetch: this.customFetch,
|
|
441
453
|
payload: args,
|
|
442
454
|
requestId: requestId,
|
|
443
455
|
});
|
|
@@ -457,6 +469,7 @@ export class TodoistApi {
|
|
|
457
469
|
baseUri: this.syncApiBase,
|
|
458
470
|
relativePath: generatePath(ENDPOINT_REST_PROJECTS, id),
|
|
459
471
|
apiToken: this.authToken,
|
|
472
|
+
customFetch: this.customFetch,
|
|
460
473
|
requestId: requestId,
|
|
461
474
|
});
|
|
462
475
|
return isSuccess(response);
|
|
@@ -475,6 +488,7 @@ export class TodoistApi {
|
|
|
475
488
|
baseUri: this.syncApiBase,
|
|
476
489
|
relativePath: generatePath(ENDPOINT_REST_PROJECTS, id, PROJECT_ARCHIVE),
|
|
477
490
|
apiToken: this.authToken,
|
|
491
|
+
customFetch: this.customFetch,
|
|
478
492
|
requestId: requestId,
|
|
479
493
|
});
|
|
480
494
|
return validateProject(response.data);
|
|
@@ -493,6 +507,7 @@ export class TodoistApi {
|
|
|
493
507
|
baseUri: this.syncApiBase,
|
|
494
508
|
relativePath: generatePath(ENDPOINT_REST_PROJECTS, id, PROJECT_UNARCHIVE),
|
|
495
509
|
apiToken: this.authToken,
|
|
510
|
+
customFetch: this.customFetch,
|
|
496
511
|
requestId: requestId,
|
|
497
512
|
});
|
|
498
513
|
return validateProject(response.data);
|
|
@@ -511,6 +526,7 @@ export class TodoistApi {
|
|
|
511
526
|
baseUri: this.syncApiBase,
|
|
512
527
|
relativePath: generatePath(ENDPOINT_REST_PROJECTS, projectId, ENDPOINT_REST_PROJECT_COLLABORATORS),
|
|
513
528
|
apiToken: this.authToken,
|
|
529
|
+
customFetch: this.customFetch,
|
|
514
530
|
payload: args,
|
|
515
531
|
});
|
|
516
532
|
return {
|
|
@@ -530,6 +546,7 @@ export class TodoistApi {
|
|
|
530
546
|
baseUri: this.syncApiBase,
|
|
531
547
|
relativePath: ENDPOINT_REST_SECTIONS,
|
|
532
548
|
apiToken: this.authToken,
|
|
549
|
+
customFetch: this.customFetch,
|
|
533
550
|
payload: args,
|
|
534
551
|
});
|
|
535
552
|
return {
|
|
@@ -550,6 +567,7 @@ export class TodoistApi {
|
|
|
550
567
|
baseUri: this.syncApiBase,
|
|
551
568
|
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id),
|
|
552
569
|
apiToken: this.authToken,
|
|
570
|
+
customFetch: this.customFetch,
|
|
553
571
|
});
|
|
554
572
|
return validateSection(response.data);
|
|
555
573
|
}
|
|
@@ -566,6 +584,7 @@ export class TodoistApi {
|
|
|
566
584
|
baseUri: this.syncApiBase,
|
|
567
585
|
relativePath: ENDPOINT_REST_SECTIONS,
|
|
568
586
|
apiToken: this.authToken,
|
|
587
|
+
customFetch: this.customFetch,
|
|
569
588
|
payload: args,
|
|
570
589
|
requestId: requestId,
|
|
571
590
|
});
|
|
@@ -586,6 +605,7 @@ export class TodoistApi {
|
|
|
586
605
|
baseUri: this.syncApiBase,
|
|
587
606
|
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id),
|
|
588
607
|
apiToken: this.authToken,
|
|
608
|
+
customFetch: this.customFetch,
|
|
589
609
|
payload: args,
|
|
590
610
|
requestId: requestId,
|
|
591
611
|
});
|
|
@@ -605,6 +625,7 @@ export class TodoistApi {
|
|
|
605
625
|
baseUri: this.syncApiBase,
|
|
606
626
|
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id),
|
|
607
627
|
apiToken: this.authToken,
|
|
628
|
+
customFetch: this.customFetch,
|
|
608
629
|
requestId: requestId,
|
|
609
630
|
});
|
|
610
631
|
return isSuccess(response);
|
|
@@ -622,6 +643,7 @@ export class TodoistApi {
|
|
|
622
643
|
baseUri: this.syncApiBase,
|
|
623
644
|
relativePath: generatePath(ENDPOINT_REST_LABELS, id),
|
|
624
645
|
apiToken: this.authToken,
|
|
646
|
+
customFetch: this.customFetch,
|
|
625
647
|
});
|
|
626
648
|
return validateLabel(response.data);
|
|
627
649
|
}
|
|
@@ -637,6 +659,7 @@ export class TodoistApi {
|
|
|
637
659
|
baseUri: this.syncApiBase,
|
|
638
660
|
relativePath: ENDPOINT_REST_LABELS,
|
|
639
661
|
apiToken: this.authToken,
|
|
662
|
+
customFetch: this.customFetch,
|
|
640
663
|
payload: args,
|
|
641
664
|
});
|
|
642
665
|
return {
|
|
@@ -657,6 +680,7 @@ export class TodoistApi {
|
|
|
657
680
|
baseUri: this.syncApiBase,
|
|
658
681
|
relativePath: ENDPOINT_REST_LABELS,
|
|
659
682
|
apiToken: this.authToken,
|
|
683
|
+
customFetch: this.customFetch,
|
|
660
684
|
payload: args,
|
|
661
685
|
requestId: requestId,
|
|
662
686
|
});
|
|
@@ -677,6 +701,7 @@ export class TodoistApi {
|
|
|
677
701
|
baseUri: this.syncApiBase,
|
|
678
702
|
relativePath: generatePath(ENDPOINT_REST_LABELS, id),
|
|
679
703
|
apiToken: this.authToken,
|
|
704
|
+
customFetch: this.customFetch,
|
|
680
705
|
payload: args,
|
|
681
706
|
requestId: requestId,
|
|
682
707
|
});
|
|
@@ -696,6 +721,7 @@ export class TodoistApi {
|
|
|
696
721
|
baseUri: this.syncApiBase,
|
|
697
722
|
relativePath: generatePath(ENDPOINT_REST_LABELS, id),
|
|
698
723
|
apiToken: this.authToken,
|
|
724
|
+
customFetch: this.customFetch,
|
|
699
725
|
requestId: requestId,
|
|
700
726
|
});
|
|
701
727
|
return isSuccess(response);
|
|
@@ -712,6 +738,7 @@ export class TodoistApi {
|
|
|
712
738
|
baseUri: this.syncApiBase,
|
|
713
739
|
relativePath: ENDPOINT_REST_LABELS_SHARED,
|
|
714
740
|
apiToken: this.authToken,
|
|
741
|
+
customFetch: this.customFetch,
|
|
715
742
|
payload: args,
|
|
716
743
|
});
|
|
717
744
|
return { results, nextCursor };
|
|
@@ -728,6 +755,7 @@ export class TodoistApi {
|
|
|
728
755
|
baseUri: this.syncApiBase,
|
|
729
756
|
relativePath: ENDPOINT_REST_LABELS_SHARED_RENAME,
|
|
730
757
|
apiToken: this.authToken,
|
|
758
|
+
customFetch: this.customFetch,
|
|
731
759
|
payload: args,
|
|
732
760
|
});
|
|
733
761
|
return isSuccess(response);
|
|
@@ -744,6 +772,7 @@ export class TodoistApi {
|
|
|
744
772
|
baseUri: this.syncApiBase,
|
|
745
773
|
relativePath: ENDPOINT_REST_LABELS_SHARED_REMOVE,
|
|
746
774
|
apiToken: this.authToken,
|
|
775
|
+
customFetch: this.customFetch,
|
|
747
776
|
payload: args,
|
|
748
777
|
});
|
|
749
778
|
return isSuccess(response);
|
|
@@ -760,6 +789,7 @@ export class TodoistApi {
|
|
|
760
789
|
baseUri: this.syncApiBase,
|
|
761
790
|
relativePath: ENDPOINT_REST_COMMENTS,
|
|
762
791
|
apiToken: this.authToken,
|
|
792
|
+
customFetch: this.customFetch,
|
|
763
793
|
payload: args,
|
|
764
794
|
});
|
|
765
795
|
return {
|
|
@@ -780,6 +810,7 @@ export class TodoistApi {
|
|
|
780
810
|
baseUri: this.syncApiBase,
|
|
781
811
|
relativePath: generatePath(ENDPOINT_REST_COMMENTS, id),
|
|
782
812
|
apiToken: this.authToken,
|
|
813
|
+
customFetch: this.customFetch,
|
|
783
814
|
});
|
|
784
815
|
return validateComment(response.data);
|
|
785
816
|
}
|
|
@@ -796,6 +827,7 @@ export class TodoistApi {
|
|
|
796
827
|
baseUri: this.syncApiBase,
|
|
797
828
|
relativePath: ENDPOINT_REST_COMMENTS,
|
|
798
829
|
apiToken: this.authToken,
|
|
830
|
+
customFetch: this.customFetch,
|
|
799
831
|
payload: args,
|
|
800
832
|
requestId: requestId,
|
|
801
833
|
});
|
|
@@ -816,6 +848,7 @@ export class TodoistApi {
|
|
|
816
848
|
baseUri: this.syncApiBase,
|
|
817
849
|
relativePath: generatePath(ENDPOINT_REST_COMMENTS, id),
|
|
818
850
|
apiToken: this.authToken,
|
|
851
|
+
customFetch: this.customFetch,
|
|
819
852
|
payload: args,
|
|
820
853
|
requestId: requestId,
|
|
821
854
|
});
|
|
@@ -835,6 +868,7 @@ export class TodoistApi {
|
|
|
835
868
|
baseUri: this.syncApiBase,
|
|
836
869
|
relativePath: generatePath(ENDPOINT_REST_COMMENTS, id),
|
|
837
870
|
apiToken: this.authToken,
|
|
871
|
+
customFetch: this.customFetch,
|
|
838
872
|
requestId: requestId,
|
|
839
873
|
});
|
|
840
874
|
return isSuccess(response);
|
|
@@ -850,6 +884,7 @@ export class TodoistApi {
|
|
|
850
884
|
baseUri: this.syncApiBase,
|
|
851
885
|
relativePath: ENDPOINT_REST_PRODUCTIVITY,
|
|
852
886
|
apiToken: this.authToken,
|
|
887
|
+
customFetch: this.customFetch,
|
|
853
888
|
});
|
|
854
889
|
return validateProductivityStats(response.data);
|
|
855
890
|
}
|
|
@@ -867,6 +902,7 @@ export class TodoistApi {
|
|
|
867
902
|
baseUri: this.syncApiBase,
|
|
868
903
|
relativePath: ENDPOINT_REST_ACTIVITIES,
|
|
869
904
|
apiToken: this.authToken,
|
|
905
|
+
customFetch: this.customFetch,
|
|
870
906
|
payload: processedArgs,
|
|
871
907
|
});
|
|
872
908
|
// Convert legacy API object types back to modern SDK types
|
|
@@ -929,6 +965,7 @@ export class TodoistApi {
|
|
|
929
965
|
fileName: args.fileName,
|
|
930
966
|
additionalFields: additionalFields,
|
|
931
967
|
requestId: requestId,
|
|
968
|
+
customFetch: this.customFetch,
|
|
932
969
|
});
|
|
933
970
|
return validateAttachment(data);
|
|
934
971
|
}
|
|
@@ -952,6 +989,7 @@ export class TodoistApi {
|
|
|
952
989
|
baseUri: this.syncApiBase,
|
|
953
990
|
relativePath: ENDPOINT_REST_UPLOADS,
|
|
954
991
|
apiToken: this.authToken,
|
|
992
|
+
customFetch: this.customFetch,
|
|
955
993
|
payload: args,
|
|
956
994
|
requestId: requestId,
|
|
957
995
|
});
|
|
@@ -971,6 +1009,7 @@ export class TodoistApi {
|
|
|
971
1009
|
baseUri: this.syncApiBase,
|
|
972
1010
|
relativePath: ENDPOINT_WORKSPACE_INVITATIONS,
|
|
973
1011
|
apiToken: this.authToken,
|
|
1012
|
+
customFetch: this.customFetch,
|
|
974
1013
|
payload: { workspace_id: args.workspaceId },
|
|
975
1014
|
requestId: requestId,
|
|
976
1015
|
});
|
|
@@ -992,6 +1031,7 @@ export class TodoistApi {
|
|
|
992
1031
|
baseUri: this.syncApiBase,
|
|
993
1032
|
relativePath: ENDPOINT_WORKSPACE_INVITATIONS_ALL,
|
|
994
1033
|
apiToken: this.authToken,
|
|
1034
|
+
customFetch: this.customFetch,
|
|
995
1035
|
payload: queryParams,
|
|
996
1036
|
requestId: requestId,
|
|
997
1037
|
});
|
|
@@ -1010,6 +1050,7 @@ export class TodoistApi {
|
|
|
1010
1050
|
baseUri: this.syncApiBase,
|
|
1011
1051
|
relativePath: ENDPOINT_WORKSPACE_INVITATIONS_DELETE,
|
|
1012
1052
|
apiToken: this.authToken,
|
|
1053
|
+
customFetch: this.customFetch,
|
|
1013
1054
|
payload: {
|
|
1014
1055
|
workspace_id: args.workspaceId,
|
|
1015
1056
|
user_email: args.userEmail,
|
|
@@ -1031,6 +1072,7 @@ export class TodoistApi {
|
|
|
1031
1072
|
baseUri: this.syncApiBase,
|
|
1032
1073
|
relativePath: getWorkspaceInvitationAcceptEndpoint(args.inviteCode),
|
|
1033
1074
|
apiToken: this.authToken,
|
|
1075
|
+
customFetch: this.customFetch,
|
|
1034
1076
|
requestId: requestId,
|
|
1035
1077
|
});
|
|
1036
1078
|
return validateWorkspaceInvitation(response.data);
|
|
@@ -1048,6 +1090,7 @@ export class TodoistApi {
|
|
|
1048
1090
|
baseUri: this.syncApiBase,
|
|
1049
1091
|
relativePath: getWorkspaceInvitationRejectEndpoint(args.inviteCode),
|
|
1050
1092
|
apiToken: this.authToken,
|
|
1093
|
+
customFetch: this.customFetch,
|
|
1051
1094
|
requestId: requestId,
|
|
1052
1095
|
});
|
|
1053
1096
|
return validateWorkspaceInvitation(response.data);
|
|
@@ -1065,6 +1108,7 @@ export class TodoistApi {
|
|
|
1065
1108
|
baseUri: this.syncApiBase,
|
|
1066
1109
|
relativePath: ENDPOINT_WORKSPACE_JOIN,
|
|
1067
1110
|
apiToken: this.authToken,
|
|
1111
|
+
customFetch: this.customFetch,
|
|
1068
1112
|
payload: {
|
|
1069
1113
|
invite_code: args.inviteCode,
|
|
1070
1114
|
workspace_id: args.workspaceId,
|
|
@@ -1094,6 +1138,7 @@ export class TodoistApi {
|
|
|
1094
1138
|
delete: true,
|
|
1095
1139
|
},
|
|
1096
1140
|
requestId: requestId,
|
|
1141
|
+
customFetch: this.customFetch,
|
|
1097
1142
|
});
|
|
1098
1143
|
return data;
|
|
1099
1144
|
}
|
|
@@ -1115,6 +1160,7 @@ export class TodoistApi {
|
|
|
1115
1160
|
fileName: args.fileName,
|
|
1116
1161
|
additionalFields: additionalFields,
|
|
1117
1162
|
requestId: requestId,
|
|
1163
|
+
customFetch: this.customFetch,
|
|
1118
1164
|
});
|
|
1119
1165
|
return data;
|
|
1120
1166
|
}
|
|
@@ -1131,6 +1177,7 @@ export class TodoistApi {
|
|
|
1131
1177
|
baseUri: this.syncApiBase,
|
|
1132
1178
|
relativePath: ENDPOINT_WORKSPACE_PLAN_DETAILS,
|
|
1133
1179
|
apiToken: this.authToken,
|
|
1180
|
+
customFetch: this.customFetch,
|
|
1134
1181
|
payload: { workspace_id: args.workspaceId },
|
|
1135
1182
|
requestId: requestId,
|
|
1136
1183
|
});
|
|
@@ -1159,13 +1206,14 @@ export class TodoistApi {
|
|
|
1159
1206
|
baseUri: this.syncApiBase,
|
|
1160
1207
|
relativePath: ENDPOINT_WORKSPACE_USERS,
|
|
1161
1208
|
apiToken: this.authToken,
|
|
1209
|
+
customFetch: this.customFetch,
|
|
1162
1210
|
payload: queryParams,
|
|
1163
1211
|
requestId: requestId,
|
|
1164
1212
|
});
|
|
1165
1213
|
return {
|
|
1166
|
-
hasMore: response.data.
|
|
1167
|
-
nextCursor: response.data.
|
|
1168
|
-
workspaceUsers: validateWorkspaceUserArray(response.data.
|
|
1214
|
+
hasMore: response.data.hasMore || false,
|
|
1215
|
+
nextCursor: response.data.nextCursor,
|
|
1216
|
+
workspaceUsers: validateWorkspaceUserArray(response.data.workspaceUsers || []),
|
|
1169
1217
|
};
|
|
1170
1218
|
}
|
|
1171
1219
|
/**
|
|
@@ -1189,6 +1237,7 @@ export class TodoistApi {
|
|
|
1189
1237
|
baseUri: this.syncApiBase,
|
|
1190
1238
|
relativePath: getWorkspaceActiveProjectsEndpoint(args.workspaceId),
|
|
1191
1239
|
apiToken: this.authToken,
|
|
1240
|
+
customFetch: this.customFetch,
|
|
1192
1241
|
payload: queryParams,
|
|
1193
1242
|
requestId: requestId,
|
|
1194
1243
|
});
|
|
@@ -1219,6 +1268,7 @@ export class TodoistApi {
|
|
|
1219
1268
|
baseUri: this.syncApiBase,
|
|
1220
1269
|
relativePath: getWorkspaceArchivedProjectsEndpoint(args.workspaceId),
|
|
1221
1270
|
apiToken: this.authToken,
|
|
1271
|
+
customFetch: this.customFetch,
|
|
1222
1272
|
payload: queryParams,
|
|
1223
1273
|
requestId: requestId,
|
|
1224
1274
|
});
|
|
@@ -358,9 +358,9 @@ export const WorkspacePlanDetailsSchema = z.object({
|
|
|
358
358
|
hasBillingPortalSwitchToAnnual: z.boolean(),
|
|
359
359
|
});
|
|
360
360
|
export const JoinWorkspaceResultSchema = z.object({
|
|
361
|
-
|
|
362
|
-
|
|
361
|
+
customSortingApplied: z.boolean(),
|
|
362
|
+
projectSortPreference: z.string(),
|
|
363
363
|
role: WorkspaceRoleSchema,
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
userId: z.string(),
|
|
365
|
+
workspaceId: z.string(),
|
|
366
366
|
});
|
package/dist/esm/types/index.js
CHANGED
|
@@ -60,11 +60,26 @@ function createTimeoutSignal(timeoutMs, existingSignal) {
|
|
|
60
60
|
});
|
|
61
61
|
return controller.signal;
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Converts native fetch Response to CustomFetchResponse for consistency
|
|
65
|
+
*/
|
|
66
|
+
function convertResponseToCustomFetch(response) {
|
|
67
|
+
// Clone the response so we can read it multiple times (if clone method exists)
|
|
68
|
+
const clonedResponse = response.clone ? response.clone() : response;
|
|
69
|
+
return {
|
|
70
|
+
ok: response.ok,
|
|
71
|
+
status: response.status,
|
|
72
|
+
statusText: response.statusText,
|
|
73
|
+
headers: headersToObject(response.headers),
|
|
74
|
+
text: () => clonedResponse.text(),
|
|
75
|
+
json: () => response.json(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
63
78
|
/**
|
|
64
79
|
* Performs a fetch request with retry logic and timeout support
|
|
65
80
|
*/
|
|
66
81
|
export async function fetchWithRetry(args) {
|
|
67
|
-
const { url, options = {}, retryConfig = {} } = args;
|
|
82
|
+
const { url, options = {}, retryConfig = {}, customFetch } = args;
|
|
68
83
|
const config = Object.assign(Object.assign({}, DEFAULT_RETRY_CONFIG), retryConfig);
|
|
69
84
|
const { timeout, signal: userSignal } = options, fetchOptions = __rest(options, ["timeout", "signal"]);
|
|
70
85
|
let lastError;
|
|
@@ -75,22 +90,30 @@ export async function fetchWithRetry(args) {
|
|
|
75
90
|
if (timeout && timeout > 0) {
|
|
76
91
|
requestSignal = createTimeoutSignal(timeout, requestSignal);
|
|
77
92
|
}
|
|
78
|
-
|
|
93
|
+
// Use custom fetch or native fetch
|
|
94
|
+
let fetchResponse;
|
|
95
|
+
if (customFetch) {
|
|
96
|
+
fetchResponse = await customFetch(url, Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal, timeout }));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const nativeResponse = await fetch(url, Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal }));
|
|
100
|
+
fetchResponse = convertResponseToCustomFetch(nativeResponse);
|
|
101
|
+
}
|
|
79
102
|
// Check if the response is successful
|
|
80
|
-
if (!
|
|
81
|
-
const errorMessage = `HTTP ${
|
|
103
|
+
if (!fetchResponse.ok) {
|
|
104
|
+
const errorMessage = `HTTP ${fetchResponse.status}: ${fetchResponse.statusText}`;
|
|
82
105
|
const error = new Error(errorMessage);
|
|
83
|
-
error.status =
|
|
84
|
-
error.statusText =
|
|
106
|
+
error.status = fetchResponse.status;
|
|
107
|
+
error.statusText = fetchResponse.statusText;
|
|
85
108
|
error.response = {
|
|
86
109
|
data: undefined, // Will be set below if we can parse the response
|
|
87
|
-
status:
|
|
88
|
-
statusText:
|
|
89
|
-
headers:
|
|
110
|
+
status: fetchResponse.status,
|
|
111
|
+
statusText: fetchResponse.statusText,
|
|
112
|
+
headers: fetchResponse.headers,
|
|
90
113
|
};
|
|
91
114
|
// Try to get response body for error details
|
|
92
115
|
try {
|
|
93
|
-
const responseText = await
|
|
116
|
+
const responseText = await fetchResponse.text();
|
|
94
117
|
let responseData;
|
|
95
118
|
try {
|
|
96
119
|
responseData = responseText ? JSON.parse(responseText) : undefined;
|
|
@@ -107,7 +130,7 @@ export async function fetchWithRetry(args) {
|
|
|
107
130
|
throw error;
|
|
108
131
|
}
|
|
109
132
|
// Parse response
|
|
110
|
-
const responseText = await
|
|
133
|
+
const responseText = await fetchResponse.text();
|
|
111
134
|
let data;
|
|
112
135
|
try {
|
|
113
136
|
data = responseText ? JSON.parse(responseText) : undefined;
|
|
@@ -118,9 +141,9 @@ export async function fetchWithRetry(args) {
|
|
|
118
141
|
}
|
|
119
142
|
return {
|
|
120
143
|
data,
|
|
121
|
-
status:
|
|
122
|
-
statusText:
|
|
123
|
-
headers:
|
|
144
|
+
status: fetchResponse.status,
|
|
145
|
+
statusText: fetchResponse.statusText,
|
|
146
|
+
headers: fetchResponse.headers,
|
|
124
147
|
};
|
|
125
148
|
}
|
|
126
149
|
catch (error) {
|
|
@@ -65,7 +65,7 @@ function getContentTypeFromFileName(fileName) {
|
|
|
65
65
|
* ```
|
|
66
66
|
*/
|
|
67
67
|
export async function uploadMultipartFile(args) {
|
|
68
|
-
const { baseUrl, authToken, endpoint, file, fileName, additionalFields, requestId } = args;
|
|
68
|
+
const { baseUrl, authToken, endpoint, file, fileName, additionalFields, requestId, customFetch, } = args;
|
|
69
69
|
const form = new FormData();
|
|
70
70
|
// Determine file type and add to form data
|
|
71
71
|
if (typeof file === 'string') {
|
|
@@ -115,6 +115,7 @@ export async function uploadMultipartFile(args) {
|
|
|
115
115
|
headers,
|
|
116
116
|
timeout: 30000, // 30 second timeout for file uploads
|
|
117
117
|
},
|
|
118
|
+
customFetch,
|
|
118
119
|
});
|
|
119
120
|
return response.data;
|
|
120
121
|
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import { CustomFetch } from './types/http';
|
|
2
|
+
/**
|
|
3
|
+
* Options for authentication functions
|
|
4
|
+
*/
|
|
5
|
+
export type AuthOptions = {
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
customFetch?: CustomFetch;
|
|
8
|
+
};
|
|
1
9
|
/**
|
|
2
10
|
* Permission scopes that can be requested during OAuth2 authorization.
|
|
3
11
|
* @see {@link https://todoist.com/api/v1/docs#tag/Authorization}
|
|
@@ -89,7 +97,11 @@ export declare function getAuthorizationUrl({ clientId, permissions, state, base
|
|
|
89
97
|
* @returns The access token response
|
|
90
98
|
* @throws {@link TodoistRequestError} If the token exchange fails
|
|
91
99
|
*/
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated Use options object instead: getAuthToken(args, { baseUrl, customFetch })
|
|
102
|
+
*/
|
|
92
103
|
export declare function getAuthToken(args: AuthTokenRequestArgs, baseUrl?: string): Promise<AuthTokenResponse>;
|
|
104
|
+
export declare function getAuthToken(args: AuthTokenRequestArgs, options?: AuthOptions): Promise<AuthTokenResponse>;
|
|
93
105
|
/**
|
|
94
106
|
* Revokes an access token, making it invalid for future use.
|
|
95
107
|
*
|
|
@@ -106,7 +118,11 @@ export declare function getAuthToken(args: AuthTokenRequestArgs, baseUrl?: strin
|
|
|
106
118
|
* @returns True if revocation was successful
|
|
107
119
|
* @see https://todoist.com/api/v1/docs#tag/Authorization/operation/revoke_access_token_api_api_v1_access_tokens_delete
|
|
108
120
|
*/
|
|
121
|
+
/**
|
|
122
|
+
* @deprecated Use options object instead: revokeAuthToken(args, { baseUrl, customFetch })
|
|
123
|
+
*/
|
|
109
124
|
export declare function revokeAuthToken(args: RevokeAuthTokenRequestArgs, baseUrl?: string): Promise<boolean>;
|
|
125
|
+
export declare function revokeAuthToken(args: RevokeAuthTokenRequestArgs, options?: AuthOptions): Promise<boolean>;
|
|
110
126
|
/**
|
|
111
127
|
* Revokes a token using the RFC 7009 OAuth 2.0 Token Revocation standard.
|
|
112
128
|
*
|
|
@@ -126,4 +142,8 @@ export declare function revokeAuthToken(args: RevokeAuthTokenRequestArgs, baseUr
|
|
|
126
142
|
* @see https://datatracker.ietf.org/doc/html/rfc7009
|
|
127
143
|
* @see https://todoist.com/api/v1/docs#tag/Authorization
|
|
128
144
|
*/
|
|
145
|
+
/**
|
|
146
|
+
* @deprecated Use options object instead: revokeToken(args, { baseUrl, customFetch })
|
|
147
|
+
*/
|
|
129
148
|
export declare function revokeToken(args: RevokeTokenRequestArgs, baseUrl?: string): Promise<boolean>;
|
|
149
|
+
export declare function revokeToken(args: RevokeTokenRequestArgs, options?: AuthOptions): Promise<boolean>;
|