@doist/todoist-api-typescript 7.4.0 → 7.6.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 (49) hide show
  1. package/README.md +2 -0
  2. package/dist/cjs/authentication.js +50 -6
  3. package/dist/cjs/consts/endpoints.js +63 -1
  4. package/dist/cjs/test-utils/test-defaults.js +33 -1
  5. package/dist/cjs/todoist-api.js +1130 -168
  6. package/dist/cjs/{utils → transport}/fetch-with-retry.js +23 -71
  7. package/dist/cjs/{rest-client.js → transport/http-client.js} +5 -5
  8. package/dist/cjs/transport/http-dispatcher.js +72 -0
  9. package/dist/cjs/types/entities.js +124 -1
  10. package/dist/cjs/types/errors.js +9 -1
  11. package/dist/cjs/types/http.js +3 -1
  12. package/dist/cjs/types/requests.js +24 -0
  13. package/dist/cjs/types/sync/commands/shared.js +2 -8
  14. package/dist/cjs/types/sync/resources/reminders.js +2 -0
  15. package/dist/cjs/utils/multipart-upload.js +1 -1
  16. package/dist/cjs/utils/validators.js +19 -2
  17. package/dist/esm/authentication.js +47 -4
  18. package/dist/esm/consts/endpoints.js +52 -0
  19. package/dist/esm/test-utils/test-defaults.js +32 -0
  20. package/dist/esm/todoist-api.js +1061 -99
  21. package/dist/esm/{utils → transport}/fetch-with-retry.js +23 -38
  22. package/dist/esm/{rest-client.js → transport/http-client.js} +5 -5
  23. package/dist/esm/transport/http-dispatcher.js +35 -0
  24. package/dist/esm/types/entities.js +122 -0
  25. package/dist/esm/types/errors.js +7 -0
  26. package/dist/esm/types/http.js +3 -1
  27. package/dist/esm/types/requests.js +23 -1
  28. package/dist/esm/types/sync/commands/shared.js +1 -8
  29. package/dist/esm/types/sync/resources/reminders.js +2 -0
  30. package/dist/esm/utils/multipart-upload.js +1 -1
  31. package/dist/esm/utils/validators.js +19 -2
  32. package/dist/types/authentication.d.ts +51 -6
  33. package/dist/types/consts/endpoints.d.ts +31 -0
  34. package/dist/types/test-utils/test-defaults.d.ts +5 -1
  35. package/dist/types/todoist-api.d.ts +338 -6
  36. package/dist/types/{utils → transport}/fetch-with-retry.d.ts +1 -1
  37. package/dist/types/{rest-client.d.ts → transport/http-client.d.ts} +1 -1
  38. package/dist/types/transport/http-dispatcher.d.ts +3 -0
  39. package/dist/types/types/entities.d.ts +258 -14
  40. package/dist/types/types/errors.d.ts +4 -0
  41. package/dist/types/types/requests.d.ts +537 -43
  42. package/dist/types/types/sync/commands/projects.d.ts +2 -2
  43. package/dist/types/types/sync/commands/shared.d.ts +1 -4
  44. package/dist/types/types/sync/resources/reminders.d.ts +4 -0
  45. package/dist/types/types/sync/resources/user.d.ts +2 -2
  46. package/dist/types/types/sync/resources/view-options.d.ts +5 -5
  47. package/dist/types/types/sync/user-preferences.d.ts +1 -1
  48. package/dist/types/utils/validators.d.ts +202 -6
  49. package/package.json +4 -4
@@ -12,11 +12,15 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.TodoistApi = void 0;
15
- const rest_client_1 = require("./rest-client");
15
+ const entities_1 = require("./types/entities");
16
+ const reminders_1 = require("./types/sync/resources/reminders");
17
+ const requests_1 = require("./types/requests");
18
+ const http_client_1 = require("./transport/http-client");
16
19
  const endpoints_1 = require("./consts/endpoints");
17
20
  const validators_1 = require("./utils/validators");
18
21
  const url_helpers_1 = require("./utils/url-helpers");
19
22
  const multipart_upload_1 = require("./utils/multipart-upload");
23
+ const case_conversion_1 = require("./utils/case-conversion");
20
24
  const activity_helpers_1 = require("./utils/activity-helpers");
21
25
  const uncompletable_helpers_1 = require("./utils/uncompletable-helpers");
22
26
  const zod_1 = require("zod");
@@ -83,6 +87,56 @@ function headersToRecord(headers) {
83
87
  });
84
88
  return result;
85
89
  }
90
+ const ReminderDeliveryServiceSchema = zod_1.z.enum(requests_1.REMINDER_DELIVERY_SERVICES);
91
+ const ReminderIdSchema = zod_1.z.string();
92
+ const ReminderDueDateSchema = entities_1.DueDateSchema.pick({
93
+ date: true,
94
+ string: true,
95
+ timezone: true,
96
+ lang: true,
97
+ isRecurring: true,
98
+ })
99
+ .partial()
100
+ .strict();
101
+ const UpdateRelativeReminderArgsSchema = zod_1.z
102
+ .object({
103
+ reminderType: zod_1.z.literal('relative'),
104
+ minuteOffset: zod_1.z.number().int().optional(),
105
+ notifyUid: zod_1.z.string().optional(),
106
+ service: ReminderDeliveryServiceSchema.optional(),
107
+ isUrgent: zod_1.z.boolean().optional(),
108
+ })
109
+ .strict();
110
+ const UpdateAbsoluteReminderArgsSchema = zod_1.z
111
+ .object({
112
+ reminderType: zod_1.z.literal('absolute'),
113
+ due: ReminderDueDateSchema.optional(),
114
+ notifyUid: zod_1.z.string().optional(),
115
+ service: ReminderDeliveryServiceSchema.optional(),
116
+ isUrgent: zod_1.z.boolean().optional(),
117
+ })
118
+ .strict();
119
+ const UpdateLocationReminderArgsSchema = zod_1.z
120
+ .object({
121
+ notifyUid: zod_1.z.string().optional(),
122
+ name: zod_1.z.string().optional(),
123
+ locLat: zod_1.z.string().optional(),
124
+ locLong: zod_1.z.string().optional(),
125
+ locTrigger: zod_1.z.enum(reminders_1.LOCATION_TRIGGERS).optional(),
126
+ radius: zod_1.z.number().int().optional(),
127
+ })
128
+ .strict()
129
+ .refine((args) => Object.values(args).some((value) => value !== undefined), {
130
+ message: 'At least one reminder field must be provided to updateLocationReminder',
131
+ });
132
+ const UpdateReminderArgsSchema = zod_1.z
133
+ .discriminatedUnion('reminderType', [
134
+ UpdateRelativeReminderArgsSchema,
135
+ UpdateAbsoluteReminderArgsSchema,
136
+ ])
137
+ .refine((args) => Object.entries(args).some(([key, value]) => key !== 'reminderType' && value !== undefined), {
138
+ message: 'At least one reminder field must be provided to updateReminder',
139
+ });
86
140
  class TodoistApi {
87
141
  constructor(
88
142
  /**
@@ -114,7 +168,7 @@ class TodoistApi {
114
168
  var _a;
115
169
  const processedRequest = ((_a = syncRequest.commands) === null || _a === void 0 ? void 0 : _a.length)
116
170
  ? Object.assign(Object.assign({}, syncRequest), { commands: preprocessSyncCommands(syncRequest.commands) }) : syncRequest;
117
- const response = await (0, rest_client_1.request)({
171
+ const response = await (0, http_client_1.request)({
118
172
  httpMethod: 'POST',
119
173
  baseUri: this.syncApiBase,
120
174
  relativePath: endpoints_1.ENDPOINT_SYNC,
@@ -168,7 +222,7 @@ class TodoistApi {
168
222
  * @returns A promise that resolves to the current user's information.
169
223
  */
170
224
  async getUser() {
171
- const response = await (0, rest_client_1.request)({
225
+ const response = await (0, http_client_1.request)({
172
226
  httpMethod: 'GET',
173
227
  baseUri: this.syncApiBase,
174
228
  relativePath: endpoints_1.ENDPOINT_REST_USER,
@@ -185,7 +239,7 @@ class TodoistApi {
185
239
  */
186
240
  async getTask(id) {
187
241
  zod_1.z.string().parse(id);
188
- const response = await (0, rest_client_1.request)({
242
+ const response = await (0, http_client_1.request)({
189
243
  httpMethod: 'GET',
190
244
  baseUri: this.syncApiBase,
191
245
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_TASKS, id),
@@ -201,7 +255,7 @@ class TodoistApi {
201
255
  * @returns A promise that resolves to an array of tasks.
202
256
  */
203
257
  async getTasks(args = {}) {
204
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
258
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
205
259
  httpMethod: 'GET',
206
260
  baseUri: this.syncApiBase,
207
261
  relativePath: endpoints_1.ENDPOINT_REST_TASKS,
@@ -221,7 +275,7 @@ class TodoistApi {
221
275
  * @returns A promise that resolves to a paginated response of tasks.
222
276
  */
223
277
  async getTasksByFilter(args) {
224
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
278
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
225
279
  httpMethod: 'GET',
226
280
  baseUri: this.syncApiBase,
227
281
  relativePath: endpoints_1.ENDPOINT_REST_TASKS_FILTER,
@@ -241,7 +295,7 @@ class TodoistApi {
241
295
  * @returns A promise that resolves to a paginated response of completed tasks.
242
296
  */
243
297
  async getCompletedTasksByCompletionDate(args) {
244
- const { data: { items, nextCursor }, } = await (0, rest_client_1.request)({
298
+ const { data: { items, nextCursor }, } = await (0, http_client_1.request)({
245
299
  httpMethod: 'GET',
246
300
  baseUri: this.syncApiBase,
247
301
  relativePath: endpoints_1.ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE,
@@ -261,7 +315,7 @@ class TodoistApi {
261
315
  * @returns A promise that resolves to a paginated response of completed tasks.
262
316
  */
263
317
  async getCompletedTasksByDueDate(args) {
264
- const { data: { items, nextCursor }, } = await (0, rest_client_1.request)({
318
+ const { data: { items, nextCursor }, } = await (0, http_client_1.request)({
265
319
  httpMethod: 'GET',
266
320
  baseUri: this.syncApiBase,
267
321
  relativePath: endpoints_1.ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE,
@@ -281,7 +335,7 @@ class TodoistApi {
281
335
  * @returns A promise that resolves to a paginated response of completed tasks.
282
336
  */
283
337
  async searchCompletedTasks(args) {
284
- const { data: { items, nextCursor }, } = await (0, rest_client_1.request)({
338
+ const { data: { items, nextCursor }, } = await (0, http_client_1.request)({
285
339
  httpMethod: 'GET',
286
340
  baseUri: this.syncApiBase,
287
341
  relativePath: endpoints_1.ENDPOINT_REST_TASKS_COMPLETED_SEARCH,
@@ -294,6 +348,30 @@ class TodoistApi {
294
348
  nextCursor,
295
349
  };
296
350
  }
351
+ /**
352
+ * Retrieves all completed tasks with optional filters.
353
+ *
354
+ * Uses offset-based pagination rather than cursor-based.
355
+ *
356
+ * @param args - Optional parameters including project ID, label, date range, and pagination.
357
+ * @returns A promise that resolves to completed tasks with associated project and section data.
358
+ */
359
+ async getAllCompletedTasks(args = {}) {
360
+ const { since, until } = args, rest = __rest(args, ["since", "until"]);
361
+ const { data } = await (0, http_client_1.request)({
362
+ httpMethod: 'GET',
363
+ baseUri: this.syncApiBase,
364
+ relativePath: endpoints_1.ENDPOINT_REST_TASKS_COMPLETED,
365
+ apiToken: this.authToken,
366
+ customFetch: this.customFetch,
367
+ payload: Object.assign(Object.assign(Object.assign({}, rest), (since ? { since: since.toISOString() } : {})), (until ? { until: until.toISOString() } : {})),
368
+ });
369
+ return {
370
+ projects: data.projects,
371
+ sections: data.sections,
372
+ items: (0, validators_1.validateTaskArray)(data.items),
373
+ };
374
+ }
297
375
  /**
298
376
  * Creates a new task with the provided parameters.
299
377
  *
@@ -304,7 +382,7 @@ class TodoistApi {
304
382
  async addTask(args, requestId) {
305
383
  // Process content based on isUncompletable flag
306
384
  const processedArgs = Object.assign(Object.assign({}, args), { content: (0, uncompletable_helpers_1.processTaskContent)(args.content, args.isUncompletable) });
307
- const response = await (0, rest_client_1.request)({
385
+ const response = await (0, http_client_1.request)({
308
386
  httpMethod: 'POST',
309
387
  baseUri: this.syncApiBase,
310
388
  relativePath: endpoints_1.ENDPOINT_REST_TASKS,
@@ -324,7 +402,7 @@ class TodoistApi {
324
402
  async quickAddTask(args) {
325
403
  // Process text based on isUncompletable flag
326
404
  const processedArgs = Object.assign(Object.assign({}, args), { text: (0, uncompletable_helpers_1.processTaskContent)(args.text, args.isUncompletable) });
327
- const response = await (0, rest_client_1.request)({
405
+ const response = await (0, http_client_1.request)({
328
406
  httpMethod: 'POST',
329
407
  baseUri: this.syncApiBase,
330
408
  relativePath: endpoints_1.ENDPOINT_SYNC_QUICK_ADD,
@@ -353,7 +431,7 @@ class TodoistApi {
353
431
  // Remap `order` → `childOrder` so snakeCaseKeys() produces `child_order`
354
432
  const { order } = processedArgs, argsWithoutOrder = __rest(processedArgs, ["order"]);
355
433
  const remappedArgs = order !== undefined ? Object.assign(Object.assign({}, argsWithoutOrder), { childOrder: order }) : argsWithoutOrder;
356
- const response = await (0, rest_client_1.request)({
434
+ const response = await (0, http_client_1.request)({
357
435
  httpMethod: 'POST',
358
436
  baseUri: this.syncApiBase,
359
437
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_TASKS, id),
@@ -406,7 +484,7 @@ class TodoistApi {
406
484
  */
407
485
  async moveTask(id, args, requestId) {
408
486
  zod_1.z.string().parse(id);
409
- const response = await (0, rest_client_1.request)({
487
+ const response = await (0, http_client_1.request)({
410
488
  httpMethod: 'POST',
411
489
  baseUri: this.syncApiBase,
412
490
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_TASKS, id, endpoints_1.ENDPOINT_REST_TASK_MOVE),
@@ -426,7 +504,7 @@ class TodoistApi {
426
504
  */
427
505
  async closeTask(id, requestId) {
428
506
  zod_1.z.string().parse(id);
429
- const response = await (0, rest_client_1.request)({
507
+ const response = await (0, http_client_1.request)({
430
508
  httpMethod: 'POST',
431
509
  baseUri: this.syncApiBase,
432
510
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_TASKS, id, endpoints_1.ENDPOINT_REST_TASK_CLOSE),
@@ -434,7 +512,7 @@ class TodoistApi {
434
512
  customFetch: this.customFetch,
435
513
  requestId: requestId,
436
514
  });
437
- return (0, rest_client_1.isSuccess)(response);
515
+ return (0, http_client_1.isSuccess)(response);
438
516
  }
439
517
  /**
440
518
  * Reopens a previously closed (completed) task by its ID.
@@ -445,7 +523,7 @@ class TodoistApi {
445
523
  */
446
524
  async reopenTask(id, requestId) {
447
525
  zod_1.z.string().parse(id);
448
- const response = await (0, rest_client_1.request)({
526
+ const response = await (0, http_client_1.request)({
449
527
  httpMethod: 'POST',
450
528
  baseUri: this.syncApiBase,
451
529
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_TASKS, id, endpoints_1.ENDPOINT_REST_TASK_REOPEN),
@@ -453,7 +531,7 @@ class TodoistApi {
453
531
  customFetch: this.customFetch,
454
532
  requestId: requestId,
455
533
  });
456
- return (0, rest_client_1.isSuccess)(response);
534
+ return (0, http_client_1.isSuccess)(response);
457
535
  }
458
536
  /**
459
537
  * Deletes a task by its ID.
@@ -464,7 +542,7 @@ class TodoistApi {
464
542
  */
465
543
  async deleteTask(id, requestId) {
466
544
  zod_1.z.string().parse(id);
467
- const response = await (0, rest_client_1.request)({
545
+ const response = await (0, http_client_1.request)({
468
546
  httpMethod: 'DELETE',
469
547
  baseUri: this.syncApiBase,
470
548
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_TASKS, id),
@@ -472,7 +550,7 @@ class TodoistApi {
472
550
  customFetch: this.customFetch,
473
551
  requestId: requestId,
474
552
  });
475
- return (0, rest_client_1.isSuccess)(response);
553
+ return (0, http_client_1.isSuccess)(response);
476
554
  }
477
555
  /**
478
556
  * Retrieves a project by its ID.
@@ -482,7 +560,7 @@ class TodoistApi {
482
560
  */
483
561
  async getProject(id) {
484
562
  zod_1.z.string().parse(id);
485
- const response = await (0, rest_client_1.request)({
563
+ const response = await (0, http_client_1.request)({
486
564
  httpMethod: 'GET',
487
565
  baseUri: this.syncApiBase,
488
566
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, id),
@@ -498,7 +576,7 @@ class TodoistApi {
498
576
  * @returns A promise that resolves to an array of projects.
499
577
  */
500
578
  async getProjects(args = {}) {
501
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
579
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
502
580
  httpMethod: 'GET',
503
581
  baseUri: this.syncApiBase,
504
582
  relativePath: endpoints_1.ENDPOINT_REST_PROJECTS,
@@ -518,7 +596,7 @@ class TodoistApi {
518
596
  * @returns A promise that resolves to a paginated response of projects.
519
597
  */
520
598
  async searchProjects(args) {
521
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
599
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
522
600
  httpMethod: 'GET',
523
601
  baseUri: this.syncApiBase,
524
602
  relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_SEARCH,
@@ -538,7 +616,7 @@ class TodoistApi {
538
616
  * @returns A promise that resolves to an array of archived projects.
539
617
  */
540
618
  async getArchivedProjects(args = {}) {
541
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
619
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
542
620
  httpMethod: 'GET',
543
621
  baseUri: this.syncApiBase,
544
622
  relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_ARCHIVED,
@@ -559,7 +637,7 @@ class TodoistApi {
559
637
  * @returns A promise that resolves to the created project.
560
638
  */
561
639
  async addProject(args, requestId) {
562
- const response = await (0, rest_client_1.request)({
640
+ const response = await (0, http_client_1.request)({
563
641
  httpMethod: 'POST',
564
642
  baseUri: this.syncApiBase,
565
643
  relativePath: endpoints_1.ENDPOINT_REST_PROJECTS,
@@ -580,7 +658,7 @@ class TodoistApi {
580
658
  */
581
659
  async updateProject(id, args, requestId) {
582
660
  zod_1.z.string().parse(id);
583
- const response = await (0, rest_client_1.request)({
661
+ const response = await (0, http_client_1.request)({
584
662
  httpMethod: 'POST',
585
663
  baseUri: this.syncApiBase,
586
664
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, id),
@@ -600,7 +678,7 @@ class TodoistApi {
600
678
  */
601
679
  async deleteProject(id, requestId) {
602
680
  zod_1.z.string().parse(id);
603
- const response = await (0, rest_client_1.request)({
681
+ const response = await (0, http_client_1.request)({
604
682
  httpMethod: 'DELETE',
605
683
  baseUri: this.syncApiBase,
606
684
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, id),
@@ -608,7 +686,7 @@ class TodoistApi {
608
686
  customFetch: this.customFetch,
609
687
  requestId: requestId,
610
688
  });
611
- return (0, rest_client_1.isSuccess)(response);
689
+ return (0, http_client_1.isSuccess)(response);
612
690
  }
613
691
  /**
614
692
  * Archives a project by its ID.
@@ -619,7 +697,7 @@ class TodoistApi {
619
697
  */
620
698
  async archiveProject(id, requestId) {
621
699
  zod_1.z.string().parse(id);
622
- const response = await (0, rest_client_1.request)({
700
+ const response = await (0, http_client_1.request)({
623
701
  httpMethod: 'POST',
624
702
  baseUri: this.syncApiBase,
625
703
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, id, endpoints_1.PROJECT_ARCHIVE),
@@ -638,7 +716,7 @@ class TodoistApi {
638
716
  */
639
717
  async unarchiveProject(id, requestId) {
640
718
  zod_1.z.string().parse(id);
641
- const response = await (0, rest_client_1.request)({
719
+ const response = await (0, http_client_1.request)({
642
720
  httpMethod: 'POST',
643
721
  baseUri: this.syncApiBase,
644
722
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, id, endpoints_1.PROJECT_UNARCHIVE),
@@ -656,7 +734,7 @@ class TodoistApi {
656
734
  * @returns A promise that resolves to the moved project.
657
735
  */
658
736
  async moveProjectToWorkspace(args, requestId) {
659
- const response = await (0, rest_client_1.request)({
737
+ const response = await (0, http_client_1.request)({
660
738
  httpMethod: 'POST',
661
739
  baseUri: this.syncApiBase,
662
740
  relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE,
@@ -675,7 +753,7 @@ class TodoistApi {
675
753
  * @returns A promise that resolves to the moved project.
676
754
  */
677
755
  async moveProjectToPersonal(args, requestId) {
678
- const response = await (0, rest_client_1.request)({
756
+ const response = await (0, http_client_1.request)({
679
757
  httpMethod: 'POST',
680
758
  baseUri: this.syncApiBase,
681
759
  relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL,
@@ -686,6 +764,83 @@ class TodoistApi {
686
764
  });
687
765
  return (0, validators_1.validateProject)(response.data.project);
688
766
  }
767
+ /**
768
+ * Counts the number of archived projects.
769
+ *
770
+ * @param args - Optional parameters to filter the count.
771
+ * @returns A promise that resolves to the count of archived projects.
772
+ */
773
+ async getArchivedProjectsCount(args = {}) {
774
+ const { data } = await (0, http_client_1.request)({
775
+ httpMethod: 'GET',
776
+ baseUri: this.syncApiBase,
777
+ relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_ARCHIVED_COUNT,
778
+ apiToken: this.authToken,
779
+ customFetch: this.customFetch,
780
+ payload: args,
781
+ });
782
+ return data;
783
+ }
784
+ /**
785
+ * Retrieves the role-to-action permission mappings for projects.
786
+ *
787
+ * @returns A promise that resolves to the permission mappings.
788
+ */
789
+ async getProjectPermissions() {
790
+ const { data } = await (0, http_client_1.request)({
791
+ httpMethod: 'GET',
792
+ baseUri: this.syncApiBase,
793
+ relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_PERMISSIONS,
794
+ apiToken: this.authToken,
795
+ customFetch: this.customFetch,
796
+ });
797
+ return data;
798
+ }
799
+ /**
800
+ * Retrieves full project data including tasks, sections, collaborators, and notes.
801
+ *
802
+ * @param id - The unique identifier of the project.
803
+ * @param args - Optional parameters.
804
+ * @returns A promise that resolves to the full project data.
805
+ */
806
+ async getFullProject(id, args = {}) {
807
+ zod_1.z.string().parse(id);
808
+ const { data } = await (0, http_client_1.request)({
809
+ httpMethod: 'GET',
810
+ baseUri: this.syncApiBase,
811
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, id, endpoints_1.ENDPOINT_REST_PROJECT_FULL),
812
+ apiToken: this.authToken,
813
+ customFetch: this.customFetch,
814
+ payload: args,
815
+ });
816
+ return {
817
+ project: data.project ? (0, validators_1.validateProject)(data.project) : null,
818
+ commentsCount: data.commentsCount,
819
+ tasks: (0, validators_1.validateTaskArray)(data.tasks),
820
+ sections: (0, validators_1.validateSectionArray)(data.sections),
821
+ collaborators: (0, validators_1.validateUserArray)(data.collaborators),
822
+ notes: (0, validators_1.validateCommentArray)(data.notes),
823
+ };
824
+ }
825
+ /**
826
+ * Joins a shared project by its ID.
827
+ *
828
+ * @param id - The unique identifier of the project to join.
829
+ * @param requestId - Optional custom identifier for the request.
830
+ * @returns A promise that resolves to the joined project.
831
+ */
832
+ async joinProject(id, requestId) {
833
+ zod_1.z.string().parse(id);
834
+ const response = await (0, http_client_1.request)({
835
+ httpMethod: 'POST',
836
+ baseUri: this.syncApiBase,
837
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, id, endpoints_1.ENDPOINT_REST_PROJECT_JOIN),
838
+ apiToken: this.authToken,
839
+ customFetch: this.customFetch,
840
+ requestId: requestId,
841
+ });
842
+ return (0, validators_1.validateProject)(response.data);
843
+ }
689
844
  /**
690
845
  * Retrieves a list of collaborators for a specific project.
691
846
  *
@@ -695,7 +850,7 @@ class TodoistApi {
695
850
  */
696
851
  async getProjectCollaborators(projectId, args = {}) {
697
852
  zod_1.z.string().parse(projectId);
698
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
853
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
699
854
  httpMethod: 'GET',
700
855
  baseUri: this.syncApiBase,
701
856
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_PROJECTS, projectId, endpoints_1.ENDPOINT_REST_PROJECT_COLLABORATORS),
@@ -708,6 +863,116 @@ class TodoistApi {
708
863
  nextCursor,
709
864
  };
710
865
  }
866
+ // ── Insights ──
867
+ /**
868
+ * Retrieves activity statistics for a project.
869
+ *
870
+ * @param projectId - The unique identifier of the project.
871
+ * @param args - Optional parameters including weeks and weekly counts flag.
872
+ * @returns A promise that resolves to the project activity stats.
873
+ */
874
+ async getProjectActivityStats(projectId, args = {}) {
875
+ zod_1.z.string().parse(projectId);
876
+ const response = await (0, http_client_1.request)({
877
+ httpMethod: 'GET',
878
+ baseUri: this.syncApiBase,
879
+ relativePath: (0, endpoints_1.getProjectInsightsActivityStatsEndpoint)(projectId),
880
+ apiToken: this.authToken,
881
+ customFetch: this.customFetch,
882
+ payload: Object.assign({ objectType: 'ITEM', eventType: 'COMPLETED' }, args),
883
+ });
884
+ return (0, validators_1.validateProjectActivityStats)(response.data);
885
+ }
886
+ /**
887
+ * Retrieves the health status of a project.
888
+ *
889
+ * @param projectId - The unique identifier of the project.
890
+ * @returns A promise that resolves to the project health data.
891
+ */
892
+ async getProjectHealth(projectId) {
893
+ zod_1.z.string().parse(projectId);
894
+ const response = await (0, http_client_1.request)({
895
+ httpMethod: 'GET',
896
+ baseUri: this.syncApiBase,
897
+ relativePath: (0, endpoints_1.getProjectInsightsHealthEndpoint)(projectId),
898
+ apiToken: this.authToken,
899
+ customFetch: this.customFetch,
900
+ });
901
+ return (0, validators_1.validateProjectHealth)(response.data);
902
+ }
903
+ /**
904
+ * Retrieves the health context for a project, including metrics and task details.
905
+ *
906
+ * @param projectId - The unique identifier of the project.
907
+ * @returns A promise that resolves to the project health context.
908
+ */
909
+ async getProjectHealthContext(projectId) {
910
+ zod_1.z.string().parse(projectId);
911
+ const response = await (0, http_client_1.request)({
912
+ httpMethod: 'GET',
913
+ baseUri: this.syncApiBase,
914
+ relativePath: (0, endpoints_1.getProjectInsightsHealthContextEndpoint)(projectId),
915
+ apiToken: this.authToken,
916
+ customFetch: this.customFetch,
917
+ });
918
+ return (0, validators_1.validateProjectHealthContext)(response.data);
919
+ }
920
+ /**
921
+ * Retrieves progress information for a project.
922
+ *
923
+ * @param projectId - The unique identifier of the project.
924
+ * @returns A promise that resolves to the project progress data.
925
+ */
926
+ async getProjectProgress(projectId) {
927
+ zod_1.z.string().parse(projectId);
928
+ const response = await (0, http_client_1.request)({
929
+ httpMethod: 'GET',
930
+ baseUri: this.syncApiBase,
931
+ relativePath: (0, endpoints_1.getProjectInsightsProgressEndpoint)(projectId),
932
+ apiToken: this.authToken,
933
+ customFetch: this.customFetch,
934
+ });
935
+ return (0, validators_1.validateProjectProgress)(response.data);
936
+ }
937
+ /**
938
+ * Retrieves insights for all projects in a workspace.
939
+ *
940
+ * @param workspaceId - The unique identifier of the workspace.
941
+ * @param args - Optional parameters including project IDs filter.
942
+ * @returns A promise that resolves to workspace insights data.
943
+ */
944
+ async getWorkspaceInsights(workspaceId, args = {}) {
945
+ zod_1.z.string().parse(workspaceId);
946
+ const response = await (0, http_client_1.request)({
947
+ httpMethod: 'GET',
948
+ baseUri: this.syncApiBase,
949
+ relativePath: (0, endpoints_1.getWorkspaceInsightsEndpoint)(workspaceId),
950
+ apiToken: this.authToken,
951
+ customFetch: this.customFetch,
952
+ payload: Object.assign(Object.assign({}, args), (args.projectIds ? { projectIds: args.projectIds.join(',') } : {})),
953
+ });
954
+ return (0, validators_1.validateWorkspaceInsights)(response.data);
955
+ }
956
+ /**
957
+ * Triggers a health analysis for a project.
958
+ *
959
+ * @param projectId - The unique identifier of the project.
960
+ * @param requestId - Optional custom identifier for the request.
961
+ * @returns A promise that resolves to the updated project health data.
962
+ */
963
+ async analyzeProjectHealth(projectId, requestId) {
964
+ zod_1.z.string().parse(projectId);
965
+ const response = await (0, http_client_1.request)({
966
+ httpMethod: 'POST',
967
+ baseUri: this.syncApiBase,
968
+ relativePath: (0, endpoints_1.getProjectInsightsHealthAnalyzeEndpoint)(projectId),
969
+ apiToken: this.authToken,
970
+ customFetch: this.customFetch,
971
+ requestId: requestId,
972
+ });
973
+ return (0, validators_1.validateProjectHealth)(response.data);
974
+ }
975
+ // ── Sections ──
711
976
  /**
712
977
  * Retrieves all sections within a specific project or matching criteria.
713
978
  *
@@ -716,7 +981,7 @@ class TodoistApi {
716
981
  * @returns A promise that resolves to an array of sections.
717
982
  */
718
983
  async getSections(args) {
719
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
984
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
720
985
  httpMethod: 'GET',
721
986
  baseUri: this.syncApiBase,
722
987
  relativePath: endpoints_1.ENDPOINT_REST_SECTIONS,
@@ -736,7 +1001,7 @@ class TodoistApi {
736
1001
  * @returns A promise that resolves to a paginated response of sections.
737
1002
  */
738
1003
  async searchSections(args) {
739
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
1004
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
740
1005
  httpMethod: 'GET',
741
1006
  baseUri: this.syncApiBase,
742
1007
  relativePath: endpoints_1.ENDPOINT_REST_SECTIONS_SEARCH,
@@ -757,7 +1022,7 @@ class TodoistApi {
757
1022
  */
758
1023
  async getSection(id) {
759
1024
  zod_1.z.string().parse(id);
760
- const response = await (0, rest_client_1.request)({
1025
+ const response = await (0, http_client_1.request)({
761
1026
  httpMethod: 'GET',
762
1027
  baseUri: this.syncApiBase,
763
1028
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_SECTIONS, id),
@@ -774,7 +1039,7 @@ class TodoistApi {
774
1039
  * @returns A promise that resolves to the created section.
775
1040
  */
776
1041
  async addSection(args, requestId) {
777
- const response = await (0, rest_client_1.request)({
1042
+ const response = await (0, http_client_1.request)({
778
1043
  httpMethod: 'POST',
779
1044
  baseUri: this.syncApiBase,
780
1045
  relativePath: endpoints_1.ENDPOINT_REST_SECTIONS,
@@ -795,7 +1060,7 @@ class TodoistApi {
795
1060
  */
796
1061
  async updateSection(id, args, requestId) {
797
1062
  zod_1.z.string().parse(id);
798
- const response = await (0, rest_client_1.request)({
1063
+ const response = await (0, http_client_1.request)({
799
1064
  httpMethod: 'POST',
800
1065
  baseUri: this.syncApiBase,
801
1066
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_SECTIONS, id),
@@ -815,7 +1080,7 @@ class TodoistApi {
815
1080
  */
816
1081
  async deleteSection(id, requestId) {
817
1082
  zod_1.z.string().parse(id);
818
- const response = await (0, rest_client_1.request)({
1083
+ const response = await (0, http_client_1.request)({
819
1084
  httpMethod: 'DELETE',
820
1085
  baseUri: this.syncApiBase,
821
1086
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_SECTIONS, id),
@@ -823,7 +1088,45 @@ class TodoistApi {
823
1088
  customFetch: this.customFetch,
824
1089
  requestId: requestId,
825
1090
  });
826
- return (0, rest_client_1.isSuccess)(response);
1091
+ return (0, http_client_1.isSuccess)(response);
1092
+ }
1093
+ /**
1094
+ * Archives a section by its ID.
1095
+ *
1096
+ * @param id - The unique identifier of the section to archive.
1097
+ * @param requestId - Optional custom identifier for the request.
1098
+ * @returns A promise that resolves to the updated section.
1099
+ */
1100
+ async archiveSection(id, requestId) {
1101
+ zod_1.z.string().parse(id);
1102
+ const response = await (0, http_client_1.request)({
1103
+ httpMethod: 'POST',
1104
+ baseUri: this.syncApiBase,
1105
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_SECTIONS, id, endpoints_1.SECTION_ARCHIVE),
1106
+ apiToken: this.authToken,
1107
+ customFetch: this.customFetch,
1108
+ requestId: requestId,
1109
+ });
1110
+ return (0, validators_1.validateSection)(response.data);
1111
+ }
1112
+ /**
1113
+ * Unarchives a section by its ID.
1114
+ *
1115
+ * @param id - The unique identifier of the section to unarchive.
1116
+ * @param requestId - Optional custom identifier for the request.
1117
+ * @returns A promise that resolves to the updated section.
1118
+ */
1119
+ async unarchiveSection(id, requestId) {
1120
+ zod_1.z.string().parse(id);
1121
+ const response = await (0, http_client_1.request)({
1122
+ httpMethod: 'POST',
1123
+ baseUri: this.syncApiBase,
1124
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_SECTIONS, id, endpoints_1.SECTION_UNARCHIVE),
1125
+ apiToken: this.authToken,
1126
+ customFetch: this.customFetch,
1127
+ requestId: requestId,
1128
+ });
1129
+ return (0, validators_1.validateSection)(response.data);
827
1130
  }
828
1131
  /**
829
1132
  * Retrieves a label by its ID.
@@ -833,7 +1136,7 @@ class TodoistApi {
833
1136
  */
834
1137
  async getLabel(id) {
835
1138
  zod_1.z.string().parse(id);
836
- const response = await (0, rest_client_1.request)({
1139
+ const response = await (0, http_client_1.request)({
837
1140
  httpMethod: 'GET',
838
1141
  baseUri: this.syncApiBase,
839
1142
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_LABELS, id),
@@ -849,7 +1152,7 @@ class TodoistApi {
849
1152
  * @returns A promise that resolves to an array of labels.
850
1153
  */
851
1154
  async getLabels(args = {}) {
852
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
1155
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
853
1156
  httpMethod: 'GET',
854
1157
  baseUri: this.syncApiBase,
855
1158
  relativePath: endpoints_1.ENDPOINT_REST_LABELS,
@@ -869,7 +1172,7 @@ class TodoistApi {
869
1172
  * @returns A promise that resolves to a paginated response of labels.
870
1173
  */
871
1174
  async searchLabels(args) {
872
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
1175
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
873
1176
  httpMethod: 'GET',
874
1177
  baseUri: this.syncApiBase,
875
1178
  relativePath: endpoints_1.ENDPOINT_REST_LABELS_SEARCH,
@@ -890,7 +1193,7 @@ class TodoistApi {
890
1193
  * @returns A promise that resolves to the created label.
891
1194
  */
892
1195
  async addLabel(args, requestId) {
893
- const response = await (0, rest_client_1.request)({
1196
+ const response = await (0, http_client_1.request)({
894
1197
  httpMethod: 'POST',
895
1198
  baseUri: this.syncApiBase,
896
1199
  relativePath: endpoints_1.ENDPOINT_REST_LABELS,
@@ -911,7 +1214,7 @@ class TodoistApi {
911
1214
  */
912
1215
  async updateLabel(id, args, requestId) {
913
1216
  zod_1.z.string().parse(id);
914
- const response = await (0, rest_client_1.request)({
1217
+ const response = await (0, http_client_1.request)({
915
1218
  httpMethod: 'POST',
916
1219
  baseUri: this.syncApiBase,
917
1220
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_LABELS, id),
@@ -931,7 +1234,7 @@ class TodoistApi {
931
1234
  */
932
1235
  async deleteLabel(id, requestId) {
933
1236
  zod_1.z.string().parse(id);
934
- const response = await (0, rest_client_1.request)({
1237
+ const response = await (0, http_client_1.request)({
935
1238
  httpMethod: 'DELETE',
936
1239
  baseUri: this.syncApiBase,
937
1240
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_LABELS, id),
@@ -939,7 +1242,7 @@ class TodoistApi {
939
1242
  customFetch: this.customFetch,
940
1243
  requestId: requestId,
941
1244
  });
942
- return (0, rest_client_1.isSuccess)(response);
1245
+ return (0, http_client_1.isSuccess)(response);
943
1246
  }
944
1247
  /**
945
1248
  * Retrieves a list of shared labels.
@@ -948,7 +1251,7 @@ class TodoistApi {
948
1251
  * @returns A promise that resolves to an array of shared labels.
949
1252
  */
950
1253
  async getSharedLabels(args) {
951
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
1254
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
952
1255
  httpMethod: 'GET',
953
1256
  baseUri: this.syncApiBase,
954
1257
  relativePath: endpoints_1.ENDPOINT_REST_LABELS_SHARED,
@@ -965,7 +1268,7 @@ class TodoistApi {
965
1268
  * @returns A promise that resolves to `true` if successful.
966
1269
  */
967
1270
  async renameSharedLabel(args) {
968
- const response = await (0, rest_client_1.request)({
1271
+ const response = await (0, http_client_1.request)({
969
1272
  httpMethod: 'POST',
970
1273
  baseUri: this.syncApiBase,
971
1274
  relativePath: endpoints_1.ENDPOINT_REST_LABELS_SHARED_RENAME,
@@ -973,7 +1276,7 @@ class TodoistApi {
973
1276
  customFetch: this.customFetch,
974
1277
  payload: args,
975
1278
  });
976
- return (0, rest_client_1.isSuccess)(response);
1279
+ return (0, http_client_1.isSuccess)(response);
977
1280
  }
978
1281
  /**
979
1282
  * Removes a shared label.
@@ -982,7 +1285,7 @@ class TodoistApi {
982
1285
  * @returns A promise that resolves to `true` if successful.
983
1286
  */
984
1287
  async removeSharedLabel(args) {
985
- const response = await (0, rest_client_1.request)({
1288
+ const response = await (0, http_client_1.request)({
986
1289
  httpMethod: 'POST',
987
1290
  baseUri: this.syncApiBase,
988
1291
  relativePath: endpoints_1.ENDPOINT_REST_LABELS_SHARED_REMOVE,
@@ -990,7 +1293,7 @@ class TodoistApi {
990
1293
  customFetch: this.customFetch,
991
1294
  payload: args,
992
1295
  });
993
- return (0, rest_client_1.isSuccess)(response);
1296
+ return (0, http_client_1.isSuccess)(response);
994
1297
  }
995
1298
  /**
996
1299
  * Retrieves all comments associated with a task or project.
@@ -999,7 +1302,7 @@ class TodoistApi {
999
1302
  * @returns A promise that resolves to an array of comments.
1000
1303
  */
1001
1304
  async getComments(args) {
1002
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
1305
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
1003
1306
  httpMethod: 'GET',
1004
1307
  baseUri: this.syncApiBase,
1005
1308
  relativePath: endpoints_1.ENDPOINT_REST_COMMENTS,
@@ -1020,7 +1323,7 @@ class TodoistApi {
1020
1323
  */
1021
1324
  async getComment(id) {
1022
1325
  zod_1.z.string().parse(id);
1023
- const response = await (0, rest_client_1.request)({
1326
+ const response = await (0, http_client_1.request)({
1024
1327
  httpMethod: 'GET',
1025
1328
  baseUri: this.syncApiBase,
1026
1329
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_COMMENTS, id),
@@ -1037,7 +1340,7 @@ class TodoistApi {
1037
1340
  * @returns A promise that resolves to the created comment.
1038
1341
  */
1039
1342
  async addComment(args, requestId) {
1040
- const response = await (0, rest_client_1.request)({
1343
+ const response = await (0, http_client_1.request)({
1041
1344
  httpMethod: 'POST',
1042
1345
  baseUri: this.syncApiBase,
1043
1346
  relativePath: endpoints_1.ENDPOINT_REST_COMMENTS,
@@ -1058,7 +1361,7 @@ class TodoistApi {
1058
1361
  */
1059
1362
  async updateComment(id, args, requestId) {
1060
1363
  zod_1.z.string().parse(id);
1061
- const response = await (0, rest_client_1.request)({
1364
+ const response = await (0, http_client_1.request)({
1062
1365
  httpMethod: 'POST',
1063
1366
  baseUri: this.syncApiBase,
1064
1367
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_COMMENTS, id),
@@ -1078,7 +1381,7 @@ class TodoistApi {
1078
1381
  */
1079
1382
  async deleteComment(id, requestId) {
1080
1383
  zod_1.z.string().parse(id);
1081
- const response = await (0, rest_client_1.request)({
1384
+ const response = await (0, http_client_1.request)({
1082
1385
  httpMethod: 'DELETE',
1083
1386
  baseUri: this.syncApiBase,
1084
1387
  relativePath: generatePath(endpoints_1.ENDPOINT_REST_COMMENTS, id),
@@ -1086,132 +1389,374 @@ class TodoistApi {
1086
1389
  customFetch: this.customFetch,
1087
1390
  requestId: requestId,
1088
1391
  });
1089
- return (0, rest_client_1.isSuccess)(response);
1392
+ return (0, http_client_1.isSuccess)(response);
1090
1393
  }
1091
1394
  /**
1092
- * Retrieves productivity stats for the authenticated user.
1395
+ * Retrieves a paginated list of time-based reminders.
1093
1396
  *
1094
- * @returns A promise that resolves to the productivity stats.
1397
+ * @param args - Optional parameters including task ID filter and pagination.
1398
+ * @returns A promise that resolves to a paginated list of reminders.
1095
1399
  */
1096
- async getProductivityStats() {
1097
- const response = await (0, rest_client_1.request)({
1400
+ async getReminders(args = {}) {
1401
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
1098
1402
  httpMethod: 'GET',
1099
1403
  baseUri: this.syncApiBase,
1100
- relativePath: endpoints_1.ENDPOINT_REST_PRODUCTIVITY,
1404
+ relativePath: endpoints_1.ENDPOINT_REST_REMINDERS,
1101
1405
  apiToken: this.authToken,
1102
1406
  customFetch: this.customFetch,
1407
+ payload: args,
1103
1408
  });
1104
- return (0, validators_1.validateProductivityStats)(response.data);
1409
+ return {
1410
+ results: (0, validators_1.validateReminderArray)(results),
1411
+ nextCursor,
1412
+ };
1105
1413
  }
1106
1414
  /**
1107
- * Retrieves activity logs with optional filters.
1415
+ * Retrieves a paginated list of location-based reminders.
1108
1416
  *
1109
- * @param args - Optional filter parameters for activity logs.
1110
- * @returns A promise that resolves to a paginated response of activity events.
1417
+ * @param args - Optional parameters including task ID filter and pagination.
1418
+ * @returns A promise that resolves to a paginated list of location reminders.
1111
1419
  */
1112
- async getActivityLogs(args = {}) {
1113
- // Convert Date objects to YYYY-MM-DD strings
1114
- const dateFrom = args.dateFrom instanceof Date ? (0, url_helpers_1.formatDateToYYYYMMDD)(args.dateFrom) : args.dateFrom;
1115
- const dateTo = args.dateTo instanceof Date ? (0, url_helpers_1.formatDateToYYYYMMDD)(args.dateTo) : args.dateTo;
1116
- // Destructure out raw date, filter-type, and removed legacy fields so they don't leak into payload
1117
- const _a = args, { dateFrom: _dateFrom, dateTo: _dateTo, objectEventTypes, objectType: _objectType, eventType: _eventType, since: _since, until: _until } = _a, rest = __rest(_a, ["dateFrom", "dateTo", "objectEventTypes", "objectType", "eventType", "since", "until"]);
1118
- // Build normalized objectEventTypes for the API
1119
- let normalizedObjectEventTypes;
1120
- if (objectEventTypes !== undefined) {
1121
- const arr = Array.isArray(objectEventTypes) ? objectEventTypes : [objectEventTypes];
1122
- normalizedObjectEventTypes = arr.map(activity_helpers_1.normalizeObjectEventTypeForApi);
1123
- }
1124
- const processedArgs = Object.assign(Object.assign(Object.assign(Object.assign({}, rest), (dateFrom !== undefined ? { dateFrom } : {})), (dateTo !== undefined ? { dateTo } : {})), (normalizedObjectEventTypes !== undefined
1125
- ? { objectEventTypes: normalizedObjectEventTypes }
1126
- : {}));
1127
- const { data: { results, nextCursor }, } = await (0, rest_client_1.request)({
1420
+ async getLocationReminders(args = {}) {
1421
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
1128
1422
  httpMethod: 'GET',
1129
1423
  baseUri: this.syncApiBase,
1130
- relativePath: endpoints_1.ENDPOINT_REST_ACTIVITIES,
1424
+ relativePath: endpoints_1.ENDPOINT_REST_LOCATION_REMINDERS,
1131
1425
  apiToken: this.authToken,
1132
1426
  customFetch: this.customFetch,
1133
- payload: processedArgs,
1134
- });
1135
- // Convert legacy API object types back to modern SDK types
1136
- const normalizedResults = results.map((event) => {
1137
- const normalizedType = (0, activity_helpers_1.denormalizeObjectTypeFromApi)(event.objectType);
1138
- return Object.assign(Object.assign({}, event), { objectType: normalizedType || event.objectType });
1427
+ payload: args,
1139
1428
  });
1140
1429
  return {
1141
- results: (0, validators_1.validateActivityEventArray)(normalizedResults),
1430
+ results: (0, validators_1.validateLocationReminderArray)(results),
1142
1431
  nextCursor,
1143
1432
  };
1144
1433
  }
1145
1434
  /**
1146
- * Uploads a file and returns attachment metadata.
1147
- * This creates an upload record that can be referenced in tasks or comments.
1435
+ * Retrieves a time-based reminder by its ID.
1148
1436
  *
1149
- * @param args - Upload parameters including file content, filename, and optional project ID.
1150
- * @param requestId - Optional custom identifier for the request.
1151
- * @returns A promise that resolves to the uploaded file's attachment metadata.
1152
- *
1153
- * @example
1154
- * ```typescript
1155
- * // Upload from a file path
1156
- * const upload = await api.uploadFile({
1157
- * file: '/path/to/document.pdf',
1158
- * projectId: '12345'
1159
- * })
1160
- *
1161
- * // Upload from a Buffer
1162
- * const buffer = fs.readFileSync('/path/to/document.pdf')
1163
- * const upload = await api.uploadFile({
1164
- * file: buffer,
1165
- * fileName: 'document.pdf', // Required for Buffer/Stream
1166
- * projectId: '12345'
1167
- * })
1437
+ * @param id - The unique identifier of the reminder to retrieve.
1438
+ * @returns A promise that resolves to the requested reminder.
1439
+ */
1440
+ async getReminder(id) {
1441
+ ReminderIdSchema.parse(id);
1442
+ try {
1443
+ const response = await (0, http_client_1.request)({
1444
+ httpMethod: 'GET',
1445
+ baseUri: this.syncApiBase,
1446
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_REMINDERS, id),
1447
+ apiToken: this.authToken,
1448
+ customFetch: this.customFetch,
1449
+ });
1450
+ return (0, validators_1.validateReminder)(response.data);
1451
+ }
1452
+ catch (error) {
1453
+ if (!(error instanceof types_1.TodoistRequestError) || error.httpStatusCode !== 404) {
1454
+ throw error;
1455
+ }
1456
+ throw new types_1.TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use getLocationReminder instead.`);
1457
+ }
1458
+ }
1459
+ /**
1460
+ * Retrieves a location reminder by its ID.
1168
1461
  *
1169
- * // Use the returned fileUrl in a comment
1170
- * await api.addComment({
1171
- * content: 'See attached document',
1172
- * taskId: '67890',
1173
- * attachment: {
1174
- * fileUrl: upload.fileUrl,
1175
- * fileName: upload.fileName,
1176
- * fileType: upload.fileType,
1177
- * resourceType: upload.resourceType
1178
- * }
1179
- * })
1180
- * ```
1462
+ * @param id - The unique identifier of the location reminder to retrieve.
1463
+ * @returns A promise that resolves to the requested reminder.
1181
1464
  */
1182
- async uploadFile(args, requestId) {
1183
- const additionalFields = {};
1184
- if (args.projectId) {
1185
- additionalFields.project_id = args.projectId;
1465
+ async getLocationReminder(id) {
1466
+ ReminderIdSchema.parse(id);
1467
+ try {
1468
+ const response = await (0, http_client_1.request)({
1469
+ httpMethod: 'GET',
1470
+ baseUri: this.syncApiBase,
1471
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_LOCATION_REMINDERS, id),
1472
+ apiToken: this.authToken,
1473
+ customFetch: this.customFetch,
1474
+ });
1475
+ return (0, validators_1.validateReminder)(response.data);
1476
+ }
1477
+ catch (error) {
1478
+ if (!(error instanceof types_1.TodoistRequestError) || error.httpStatusCode !== 404) {
1479
+ throw error;
1480
+ }
1481
+ throw new types_1.TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use getReminder instead.`);
1186
1482
  }
1187
- const data = await (0, multipart_upload_1.uploadMultipartFile)({
1188
- baseUrl: this.syncApiBase,
1189
- authToken: this.authToken,
1190
- endpoint: endpoints_1.ENDPOINT_REST_UPLOADS,
1191
- file: args.file,
1192
- fileName: args.fileName,
1193
- additionalFields: additionalFields,
1194
- requestId: requestId,
1195
- customFetch: this.customFetch,
1196
- });
1197
- return (0, validators_1.validateAttachment)(data);
1198
1483
  }
1199
1484
  /**
1200
- * Deletes an uploaded file by its URL.
1485
+ * Creates a time-based reminder for a task.
1201
1486
  *
1202
- * @param args - The file URL to delete.
1487
+ * @param args - Reminder creation parameters for relative or absolute reminders.
1203
1488
  * @param requestId - Optional custom identifier for the request.
1204
- * @returns A promise that resolves to `true` if deletion was successful.
1205
- *
1206
- * @example
1207
- * ```typescript
1489
+ * @returns A promise that resolves to the created reminder.
1490
+ */
1491
+ async addReminder(args, requestId) {
1492
+ const response = await (0, http_client_1.request)({
1493
+ httpMethod: 'POST',
1494
+ baseUri: this.syncApiBase,
1495
+ relativePath: endpoints_1.ENDPOINT_REST_REMINDERS,
1496
+ apiToken: this.authToken,
1497
+ customFetch: this.customFetch,
1498
+ payload: args,
1499
+ requestId: requestId,
1500
+ });
1501
+ return (0, validators_1.validateReminder)(response.data);
1502
+ }
1503
+ /**
1504
+ * Creates a location reminder for a task.
1505
+ *
1506
+ * @param args - Location reminder creation parameters.
1507
+ * @param requestId - Optional custom identifier for the request.
1508
+ * @returns A promise that resolves to the created reminder.
1509
+ */
1510
+ async addLocationReminder(args, requestId) {
1511
+ const response = await (0, http_client_1.request)({
1512
+ httpMethod: 'POST',
1513
+ baseUri: this.syncApiBase,
1514
+ relativePath: endpoints_1.ENDPOINT_REST_LOCATION_REMINDERS,
1515
+ apiToken: this.authToken,
1516
+ customFetch: this.customFetch,
1517
+ payload: Object.assign(Object.assign({}, args), { reminderType: 'location' }),
1518
+ requestId: requestId,
1519
+ });
1520
+ return (0, validators_1.validateReminder)(response.data);
1521
+ }
1522
+ /**
1523
+ * Updates an existing time-based reminder.
1524
+ *
1525
+ * @param id - The unique identifier of the reminder to update.
1526
+ * @param args - Reminder update parameters.
1527
+ * @param requestId - Optional custom identifier for the request.
1528
+ * @returns A promise that resolves to the updated reminder.
1529
+ */
1530
+ async updateReminder(id, args, requestId) {
1531
+ ReminderIdSchema.parse(id);
1532
+ const payload = UpdateReminderArgsSchema.parse(args);
1533
+ try {
1534
+ const response = await (0, http_client_1.request)({
1535
+ httpMethod: 'POST',
1536
+ baseUri: this.syncApiBase,
1537
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_REMINDERS, id),
1538
+ apiToken: this.authToken,
1539
+ customFetch: this.customFetch,
1540
+ payload,
1541
+ requestId: requestId,
1542
+ });
1543
+ return (0, validators_1.validateReminder)(response.data);
1544
+ }
1545
+ catch (error) {
1546
+ if (!(error instanceof types_1.TodoistRequestError) || error.httpStatusCode !== 404) {
1547
+ throw error;
1548
+ }
1549
+ throw new types_1.TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use updateLocationReminder instead.`);
1550
+ }
1551
+ }
1552
+ /**
1553
+ * Updates an existing location reminder.
1554
+ *
1555
+ * @param id - The unique identifier of the location reminder to update.
1556
+ * @param args - Location reminder update parameters.
1557
+ * @param requestId - Optional custom identifier for the request.
1558
+ * @returns A promise that resolves to the updated reminder.
1559
+ */
1560
+ async updateLocationReminder(id, args, requestId) {
1561
+ ReminderIdSchema.parse(id);
1562
+ const payload = UpdateLocationReminderArgsSchema.parse(args);
1563
+ try {
1564
+ const response = await (0, http_client_1.request)({
1565
+ httpMethod: 'POST',
1566
+ baseUri: this.syncApiBase,
1567
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_LOCATION_REMINDERS, id),
1568
+ apiToken: this.authToken,
1569
+ customFetch: this.customFetch,
1570
+ payload,
1571
+ requestId: requestId,
1572
+ });
1573
+ return (0, validators_1.validateReminder)(response.data);
1574
+ }
1575
+ catch (error) {
1576
+ if (!(error instanceof types_1.TodoistRequestError) || error.httpStatusCode !== 404) {
1577
+ throw error;
1578
+ }
1579
+ throw new types_1.TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use updateReminder instead.`);
1580
+ }
1581
+ }
1582
+ /**
1583
+ * Deletes a time-based reminder by its ID.
1584
+ *
1585
+ * @param id - The unique identifier of the reminder to delete.
1586
+ * @param requestId - Optional custom identifier for the request.
1587
+ * @returns A promise that resolves to `true` if successful.
1588
+ */
1589
+ async deleteReminder(id, requestId) {
1590
+ ReminderIdSchema.parse(id);
1591
+ try {
1592
+ const response = await (0, http_client_1.request)({
1593
+ httpMethod: 'DELETE',
1594
+ baseUri: this.syncApiBase,
1595
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_REMINDERS, id),
1596
+ apiToken: this.authToken,
1597
+ customFetch: this.customFetch,
1598
+ requestId: requestId,
1599
+ });
1600
+ return (0, http_client_1.isSuccess)(response);
1601
+ }
1602
+ catch (error) {
1603
+ if (!(error instanceof types_1.TodoistRequestError) || error.httpStatusCode !== 404) {
1604
+ throw error;
1605
+ }
1606
+ throw new types_1.TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use deleteLocationReminder instead.`);
1607
+ }
1608
+ }
1609
+ /**
1610
+ * Deletes a location reminder by its ID.
1611
+ *
1612
+ * @param id - The unique identifier of the location reminder to delete.
1613
+ * @param requestId - Optional custom identifier for the request.
1614
+ * @returns A promise that resolves to `true` if successful.
1615
+ */
1616
+ async deleteLocationReminder(id, requestId) {
1617
+ ReminderIdSchema.parse(id);
1618
+ try {
1619
+ const response = await (0, http_client_1.request)({
1620
+ httpMethod: 'DELETE',
1621
+ baseUri: this.syncApiBase,
1622
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_LOCATION_REMINDERS, id),
1623
+ apiToken: this.authToken,
1624
+ customFetch: this.customFetch,
1625
+ requestId: requestId,
1626
+ });
1627
+ return (0, http_client_1.isSuccess)(response);
1628
+ }
1629
+ catch (error) {
1630
+ if (!(error instanceof types_1.TodoistRequestError) || error.httpStatusCode !== 404) {
1631
+ throw error;
1632
+ }
1633
+ throw new types_1.TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use deleteReminder instead.`);
1634
+ }
1635
+ }
1636
+ /**
1637
+ * Retrieves productivity stats for the authenticated user.
1638
+ *
1639
+ * @returns A promise that resolves to the productivity stats.
1640
+ */
1641
+ async getProductivityStats() {
1642
+ const response = await (0, http_client_1.request)({
1643
+ httpMethod: 'GET',
1644
+ baseUri: this.syncApiBase,
1645
+ relativePath: endpoints_1.ENDPOINT_REST_PRODUCTIVITY,
1646
+ apiToken: this.authToken,
1647
+ customFetch: this.customFetch,
1648
+ });
1649
+ return (0, validators_1.validateProductivityStats)(response.data);
1650
+ }
1651
+ /**
1652
+ * Retrieves activity logs with optional filters.
1653
+ *
1654
+ * @param args - Optional filter parameters for activity logs.
1655
+ * @returns A promise that resolves to a paginated response of activity events.
1656
+ */
1657
+ async getActivityLogs(args = {}) {
1658
+ // Convert Date objects to YYYY-MM-DD strings
1659
+ const dateFrom = args.dateFrom instanceof Date ? (0, url_helpers_1.formatDateToYYYYMMDD)(args.dateFrom) : args.dateFrom;
1660
+ const dateTo = args.dateTo instanceof Date ? (0, url_helpers_1.formatDateToYYYYMMDD)(args.dateTo) : args.dateTo;
1661
+ // Destructure out raw date, filter-type, and removed legacy fields so they don't leak into payload
1662
+ const _a = args, { dateFrom: _dateFrom, dateTo: _dateTo, objectEventTypes, objectType: _objectType, eventType: _eventType, since: _since, until: _until } = _a, rest = __rest(_a, ["dateFrom", "dateTo", "objectEventTypes", "objectType", "eventType", "since", "until"]);
1663
+ // Build normalized objectEventTypes for the API
1664
+ let normalizedObjectEventTypes;
1665
+ if (objectEventTypes !== undefined) {
1666
+ const arr = Array.isArray(objectEventTypes) ? objectEventTypes : [objectEventTypes];
1667
+ normalizedObjectEventTypes = arr.map(activity_helpers_1.normalizeObjectEventTypeForApi);
1668
+ }
1669
+ const processedArgs = Object.assign(Object.assign(Object.assign(Object.assign({}, rest), (dateFrom !== undefined ? { dateFrom } : {})), (dateTo !== undefined ? { dateTo } : {})), (normalizedObjectEventTypes !== undefined
1670
+ ? { objectEventTypes: normalizedObjectEventTypes }
1671
+ : {}));
1672
+ const { data: { results, nextCursor }, } = await (0, http_client_1.request)({
1673
+ httpMethod: 'GET',
1674
+ baseUri: this.syncApiBase,
1675
+ relativePath: endpoints_1.ENDPOINT_REST_ACTIVITIES,
1676
+ apiToken: this.authToken,
1677
+ customFetch: this.customFetch,
1678
+ payload: processedArgs,
1679
+ });
1680
+ // Convert legacy API object types back to modern SDK types
1681
+ const normalizedResults = results.map((event) => {
1682
+ const normalizedType = (0, activity_helpers_1.denormalizeObjectTypeFromApi)(event.objectType);
1683
+ return Object.assign(Object.assign({}, event), { objectType: normalizedType || event.objectType });
1684
+ });
1685
+ return {
1686
+ results: (0, validators_1.validateActivityEventArray)(normalizedResults),
1687
+ nextCursor,
1688
+ };
1689
+ }
1690
+ /**
1691
+ * Uploads a file and returns attachment metadata.
1692
+ * This creates an upload record that can be referenced in tasks or comments.
1693
+ *
1694
+ * @param args - Upload parameters including file content, filename, and optional project ID.
1695
+ * @param requestId - Optional custom identifier for the request.
1696
+ * @returns A promise that resolves to the uploaded file's attachment metadata.
1697
+ *
1698
+ * @example
1699
+ * ```typescript
1700
+ * // Upload from a file path
1701
+ * const upload = await api.uploadFile({
1702
+ * file: '/path/to/document.pdf',
1703
+ * projectId: '12345'
1704
+ * })
1705
+ *
1706
+ * // Upload from a Buffer
1707
+ * const buffer = fs.readFileSync('/path/to/document.pdf')
1708
+ * const upload = await api.uploadFile({
1709
+ * file: buffer,
1710
+ * fileName: 'document.pdf', // Required for Buffer/Stream
1711
+ * projectId: '12345'
1712
+ * })
1713
+ *
1714
+ * // Use the returned fileUrl in a comment
1715
+ * await api.addComment({
1716
+ * content: 'See attached document',
1717
+ * taskId: '67890',
1718
+ * attachment: {
1719
+ * fileUrl: upload.fileUrl,
1720
+ * fileName: upload.fileName,
1721
+ * fileType: upload.fileType,
1722
+ * resourceType: upload.resourceType
1723
+ * }
1724
+ * })
1725
+ * ```
1726
+ */
1727
+ async uploadFile(args, requestId) {
1728
+ const additionalFields = {};
1729
+ if (args.projectId) {
1730
+ additionalFields.project_id = args.projectId;
1731
+ }
1732
+ const data = await (0, multipart_upload_1.uploadMultipartFile)({
1733
+ baseUrl: this.syncApiBase,
1734
+ authToken: this.authToken,
1735
+ endpoint: endpoints_1.ENDPOINT_REST_UPLOADS,
1736
+ file: args.file,
1737
+ fileName: args.fileName,
1738
+ additionalFields: additionalFields,
1739
+ requestId: requestId,
1740
+ customFetch: this.customFetch,
1741
+ });
1742
+ return (0, validators_1.validateAttachment)(data);
1743
+ }
1744
+ /**
1745
+ * Deletes an uploaded file by its URL.
1746
+ *
1747
+ * @param args - The file URL to delete.
1748
+ * @param requestId - Optional custom identifier for the request.
1749
+ * @returns A promise that resolves to `true` if deletion was successful.
1750
+ *
1751
+ * @example
1752
+ * ```typescript
1208
1753
  * await api.deleteUpload({
1209
1754
  * fileUrl: 'https://cdn.todoist.com/...'
1210
1755
  * })
1211
1756
  * ```
1212
1757
  */
1213
1758
  async deleteUpload(args, requestId) {
1214
- const response = await (0, rest_client_1.request)({
1759
+ const response = await (0, http_client_1.request)({
1215
1760
  httpMethod: 'DELETE',
1216
1761
  baseUri: this.syncApiBase,
1217
1762
  relativePath: endpoints_1.ENDPOINT_REST_UPLOADS,
@@ -1220,7 +1765,7 @@ class TodoistApi {
1220
1765
  payload: args,
1221
1766
  requestId: requestId,
1222
1767
  });
1223
- return (0, rest_client_1.isSuccess)(response);
1768
+ return (0, http_client_1.isSuccess)(response);
1224
1769
  }
1225
1770
  /**
1226
1771
  * Fetches the content of a file attachment from a Todoist comment.
@@ -1299,6 +1844,246 @@ class TodoistApi {
1299
1844
  arrayBuffer: () => response.arrayBuffer(),
1300
1845
  };
1301
1846
  }
1847
+ // ── Backups ──
1848
+ /**
1849
+ * Retrieves a list of available backups.
1850
+ *
1851
+ * @param args - Optional parameters including MFA token.
1852
+ * @returns A promise that resolves to an array of backups.
1853
+ */
1854
+ async getBackups(args = {}) {
1855
+ const response = await (0, http_client_1.request)({
1856
+ httpMethod: 'GET',
1857
+ baseUri: this.syncApiBase,
1858
+ relativePath: endpoints_1.ENDPOINT_REST_BACKUPS,
1859
+ apiToken: this.authToken,
1860
+ customFetch: this.customFetch,
1861
+ payload: args,
1862
+ });
1863
+ return (0, validators_1.validateBackupArray)(response.data);
1864
+ }
1865
+ /**
1866
+ * Downloads a backup file as binary data.
1867
+ *
1868
+ * @param args - Arguments including the backup file URL (from getBackups).
1869
+ * @returns A promise that resolves to a response with binary data accessible via arrayBuffer().
1870
+ */
1871
+ async downloadBackup(args) {
1872
+ const url = `${this.syncApiBase}${endpoints_1.ENDPOINT_REST_BACKUPS_DOWNLOAD}?file=${encodeURIComponent(args.file)}`;
1873
+ const fetchOptions = {
1874
+ headers: { Authorization: `Bearer ${this.authToken}` },
1875
+ };
1876
+ if (this.customFetch) {
1877
+ const response = await this.customFetch(url, fetchOptions);
1878
+ if (!response.ok) {
1879
+ throw new Error(`Failed to download backup: ${response.status} ${response.statusText}`);
1880
+ }
1881
+ const text = await response.text();
1882
+ const buffer = new TextEncoder().encode(text).buffer;
1883
+ return {
1884
+ ok: response.ok,
1885
+ status: response.status,
1886
+ statusText: response.statusText,
1887
+ headers: response.headers,
1888
+ text: () => Promise.resolve(text),
1889
+ json: () => response.json(),
1890
+ arrayBuffer: () => Promise.resolve(buffer),
1891
+ };
1892
+ }
1893
+ const response = await fetch(url, fetchOptions);
1894
+ if (!response.ok) {
1895
+ throw new Error(`Failed to download backup: ${response.status} ${response.statusText}`);
1896
+ }
1897
+ return {
1898
+ ok: response.ok,
1899
+ status: response.status,
1900
+ statusText: response.statusText,
1901
+ headers: headersToRecord(response.headers),
1902
+ text: () => response.text(),
1903
+ json: () => response.json(),
1904
+ arrayBuffer: () => response.arrayBuffer(),
1905
+ };
1906
+ }
1907
+ // ── Emails ──
1908
+ /**
1909
+ * Gets or creates an email forwarding address for an object.
1910
+ *
1911
+ * @param args - Arguments including object type and ID.
1912
+ * @param requestId - Optional custom identifier for the request.
1913
+ * @returns A promise that resolves to the email address.
1914
+ */
1915
+ async getOrCreateEmailForwarding(args, requestId) {
1916
+ const { data } = await (0, http_client_1.request)({
1917
+ httpMethod: 'PUT',
1918
+ baseUri: this.syncApiBase,
1919
+ relativePath: endpoints_1.ENDPOINT_REST_EMAILS,
1920
+ apiToken: this.authToken,
1921
+ customFetch: this.customFetch,
1922
+ payload: args,
1923
+ requestId: requestId,
1924
+ });
1925
+ return data;
1926
+ }
1927
+ /**
1928
+ * Disables email forwarding for an object.
1929
+ *
1930
+ * @param args - Arguments including object type and ID.
1931
+ * @param requestId - Optional custom identifier for the request.
1932
+ * @returns A promise that resolves to `true` if successful.
1933
+ */
1934
+ async disableEmailForwarding(args, requestId) {
1935
+ const queryParams = new URLSearchParams({
1936
+ obj_type: args.objType,
1937
+ obj_id: args.objId,
1938
+ });
1939
+ const response = await (0, http_client_1.request)({
1940
+ httpMethod: 'DELETE',
1941
+ baseUri: this.syncApiBase,
1942
+ relativePath: `${endpoints_1.ENDPOINT_REST_EMAILS}?${queryParams.toString()}`,
1943
+ apiToken: this.authToken,
1944
+ customFetch: this.customFetch,
1945
+ requestId: requestId,
1946
+ });
1947
+ return (0, http_client_1.isSuccess)(response);
1948
+ }
1949
+ // ── ID Mappings ──
1950
+ /**
1951
+ * Retrieves ID mappings between old and new IDs.
1952
+ *
1953
+ * @param args - Arguments including object type and IDs to look up.
1954
+ * @returns A promise that resolves to an array of ID mappings.
1955
+ */
1956
+ async getIdMappings(args) {
1957
+ const response = await (0, http_client_1.request)({
1958
+ httpMethod: 'GET',
1959
+ baseUri: this.syncApiBase,
1960
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_ID_MAPPINGS, args.objName, args.objIds.join(',')),
1961
+ apiToken: this.authToken,
1962
+ customFetch: this.customFetch,
1963
+ });
1964
+ return (0, validators_1.validateIdMappingArray)(response.data);
1965
+ }
1966
+ /**
1967
+ * Retrieves moved IDs for objects that have been migrated.
1968
+ *
1969
+ * @param args - Arguments including object type and optional old IDs to look up.
1970
+ * @returns A promise that resolves to an array of moved ID pairs.
1971
+ */
1972
+ async getMovedIds(args) {
1973
+ const response = await (0, http_client_1.request)({
1974
+ httpMethod: 'GET',
1975
+ baseUri: this.syncApiBase,
1976
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_MOVED_IDS, args.objName),
1977
+ apiToken: this.authToken,
1978
+ customFetch: this.customFetch,
1979
+ payload: args.oldIds ? { oldIds: args.oldIds.join(',') } : undefined,
1980
+ });
1981
+ return (0, validators_1.validateMovedIdArray)(response.data);
1982
+ }
1983
+ // ── Templates ──
1984
+ /**
1985
+ * Exports a project as a template file (CSV format).
1986
+ *
1987
+ * @param args - Arguments including project ID and optional date format preference.
1988
+ * @returns A promise that resolves to the template file content as a string.
1989
+ */
1990
+ async exportTemplateAsFile(args) {
1991
+ const response = await (0, http_client_1.request)({
1992
+ httpMethod: 'GET',
1993
+ baseUri: this.syncApiBase,
1994
+ relativePath: endpoints_1.ENDPOINT_REST_TEMPLATES_FILE,
1995
+ apiToken: this.authToken,
1996
+ customFetch: this.customFetch,
1997
+ payload: args,
1998
+ });
1999
+ return response.data;
2000
+ }
2001
+ /**
2002
+ * Exports a project as a template URL.
2003
+ *
2004
+ * @param args - Arguments including project ID and optional date format preference.
2005
+ * @returns A promise that resolves to the file name and URL.
2006
+ */
2007
+ async exportTemplateAsUrl(args) {
2008
+ const { data } = await (0, http_client_1.request)({
2009
+ httpMethod: 'GET',
2010
+ baseUri: this.syncApiBase,
2011
+ relativePath: endpoints_1.ENDPOINT_REST_TEMPLATES_URL,
2012
+ apiToken: this.authToken,
2013
+ customFetch: this.customFetch,
2014
+ payload: args,
2015
+ });
2016
+ return data;
2017
+ }
2018
+ /**
2019
+ * Creates a new project from a template file.
2020
+ *
2021
+ * @param args - Arguments including project name, template file, and optional workspace ID.
2022
+ * @param requestId - Optional custom identifier for the request.
2023
+ * @returns A promise that resolves to the created project data.
2024
+ */
2025
+ async createProjectFromTemplate(args, requestId) {
2026
+ const { file, fileName, name, workspaceId } = args;
2027
+ const additionalFields = { name };
2028
+ if (workspaceId !== undefined && workspaceId !== null) {
2029
+ additionalFields.workspace_id = workspaceId;
2030
+ }
2031
+ const data = await (0, multipart_upload_1.uploadMultipartFile)({
2032
+ baseUrl: this.syncApiBase,
2033
+ authToken: this.authToken,
2034
+ endpoint: endpoints_1.ENDPOINT_REST_TEMPLATES_CREATE_FROM_FILE,
2035
+ file,
2036
+ fileName,
2037
+ additionalFields,
2038
+ customFetch: this.customFetch,
2039
+ requestId,
2040
+ });
2041
+ return this.validateTemplateResponse((0, case_conversion_1.camelCaseKeys)(data));
2042
+ }
2043
+ /**
2044
+ * Imports a template file into an existing project.
2045
+ *
2046
+ * @param args - Arguments including project ID and template file.
2047
+ * @param requestId - Optional custom identifier for the request.
2048
+ * @returns A promise that resolves to the import result.
2049
+ */
2050
+ async importTemplateIntoProject(args, requestId) {
2051
+ const { file, fileName, projectId } = args;
2052
+ const data = await (0, multipart_upload_1.uploadMultipartFile)({
2053
+ baseUrl: this.syncApiBase,
2054
+ authToken: this.authToken,
2055
+ endpoint: endpoints_1.ENDPOINT_REST_TEMPLATES_IMPORT_FROM_FILE,
2056
+ file,
2057
+ fileName,
2058
+ additionalFields: { project_id: projectId },
2059
+ customFetch: this.customFetch,
2060
+ requestId,
2061
+ });
2062
+ return this.validateTemplateResponse((0, case_conversion_1.camelCaseKeys)(data));
2063
+ }
2064
+ /**
2065
+ * Imports a template by ID into an existing project.
2066
+ *
2067
+ * @param args - Arguments including project ID, template ID, and optional locale.
2068
+ * @param requestId - Optional custom identifier for the request.
2069
+ * @returns A promise that resolves to the import result.
2070
+ */
2071
+ async importTemplateFromId(args, requestId) {
2072
+ const { data } = await (0, http_client_1.request)({
2073
+ httpMethod: 'POST',
2074
+ baseUri: this.syncApiBase,
2075
+ relativePath: endpoints_1.ENDPOINT_REST_TEMPLATES_IMPORT_FROM_ID,
2076
+ apiToken: this.authToken,
2077
+ customFetch: this.customFetch,
2078
+ payload: args,
2079
+ requestId: requestId,
2080
+ });
2081
+ return this.validateTemplateResponse(data);
2082
+ }
2083
+ validateTemplateResponse(data) {
2084
+ var _a, _b, _c, _d;
2085
+ return Object.assign(Object.assign({}, data), { projects: (0, validators_1.validateProjectArray)((_a = data.projects) !== null && _a !== void 0 ? _a : []), sections: (0, validators_1.validateSectionArray)((_b = data.sections) !== null && _b !== void 0 ? _b : []), tasks: (0, validators_1.validateTaskArray)((_c = data.tasks) !== null && _c !== void 0 ? _c : []), comments: (0, validators_1.validateCommentArray)((_d = data.comments) !== null && _d !== void 0 ? _d : []) });
2086
+ }
1302
2087
  /* Workspace methods */
1303
2088
  /**
1304
2089
  * Gets pending invitations for a workspace.
@@ -1308,7 +2093,7 @@ class TodoistApi {
1308
2093
  * @returns Array of email addresses with pending invitations.
1309
2094
  */
1310
2095
  async getWorkspaceInvitations(args, requestId) {
1311
- const response = await (0, rest_client_1.request)({
2096
+ const response = await (0, http_client_1.request)({
1312
2097
  httpMethod: 'GET',
1313
2098
  baseUri: this.syncApiBase,
1314
2099
  relativePath: endpoints_1.ENDPOINT_WORKSPACE_INVITATIONS,
@@ -1330,7 +2115,7 @@ class TodoistApi {
1330
2115
  if (args.workspaceId) {
1331
2116
  queryParams.workspace_id = args.workspaceId;
1332
2117
  }
1333
- const response = await (0, rest_client_1.request)({
2118
+ const response = await (0, http_client_1.request)({
1334
2119
  httpMethod: 'GET',
1335
2120
  baseUri: this.syncApiBase,
1336
2121
  relativePath: endpoints_1.ENDPOINT_WORKSPACE_INVITATIONS_ALL,
@@ -1349,7 +2134,7 @@ class TodoistApi {
1349
2134
  * @returns The deleted invitation.
1350
2135
  */
1351
2136
  async deleteWorkspaceInvitation(args, requestId) {
1352
- const response = await (0, rest_client_1.request)({
2137
+ const response = await (0, http_client_1.request)({
1353
2138
  httpMethod: 'POST',
1354
2139
  baseUri: this.syncApiBase,
1355
2140
  relativePath: endpoints_1.ENDPOINT_WORKSPACE_INVITATIONS_DELETE,
@@ -1371,7 +2156,7 @@ class TodoistApi {
1371
2156
  * @returns The accepted invitation.
1372
2157
  */
1373
2158
  async acceptWorkspaceInvitation(args, requestId) {
1374
- const response = await (0, rest_client_1.request)({
2159
+ const response = await (0, http_client_1.request)({
1375
2160
  httpMethod: 'PUT',
1376
2161
  baseUri: this.syncApiBase,
1377
2162
  relativePath: (0, endpoints_1.getWorkspaceInvitationAcceptEndpoint)(args.inviteCode),
@@ -1389,7 +2174,7 @@ class TodoistApi {
1389
2174
  * @returns The rejected invitation.
1390
2175
  */
1391
2176
  async rejectWorkspaceInvitation(args, requestId) {
1392
- const response = await (0, rest_client_1.request)({
2177
+ const response = await (0, http_client_1.request)({
1393
2178
  httpMethod: 'PUT',
1394
2179
  baseUri: this.syncApiBase,
1395
2180
  relativePath: (0, endpoints_1.getWorkspaceInvitationRejectEndpoint)(args.inviteCode),
@@ -1407,7 +2192,7 @@ class TodoistApi {
1407
2192
  * @returns Workspace user information.
1408
2193
  */
1409
2194
  async joinWorkspace(args, requestId) {
1410
- const response = await (0, rest_client_1.request)({
2195
+ const response = await (0, http_client_1.request)({
1411
2196
  httpMethod: 'POST',
1412
2197
  baseUri: this.syncApiBase,
1413
2198
  relativePath: endpoints_1.ENDPOINT_WORKSPACE_JOIN,
@@ -1476,7 +2261,7 @@ class TodoistApi {
1476
2261
  * @returns Workspace plan details.
1477
2262
  */
1478
2263
  async getWorkspacePlanDetails(args, requestId) {
1479
- const response = await (0, rest_client_1.request)({
2264
+ const response = await (0, http_client_1.request)({
1480
2265
  httpMethod: 'GET',
1481
2266
  baseUri: this.syncApiBase,
1482
2267
  relativePath: endpoints_1.ENDPOINT_WORKSPACE_PLAN_DETAILS,
@@ -1505,7 +2290,7 @@ class TodoistApi {
1505
2290
  if (args.limit) {
1506
2291
  queryParams.limit = args.limit;
1507
2292
  }
1508
- const response = await (0, rest_client_1.request)({
2293
+ const response = await (0, http_client_1.request)({
1509
2294
  httpMethod: 'GET',
1510
2295
  baseUri: this.syncApiBase,
1511
2296
  relativePath: endpoints_1.ENDPOINT_WORKSPACE_USERS,
@@ -1523,8 +2308,6 @@ class TodoistApi {
1523
2308
  /**
1524
2309
  * Retrieves all workspaces for the authenticated user.
1525
2310
  *
1526
- * Uses the Sync API internally to fetch workspace data.
1527
- *
1528
2311
  * @param requestId - Optional custom identifier for the request.
1529
2312
  * @returns A promise that resolves to an array of workspaces.
1530
2313
  *
@@ -1537,17 +2320,196 @@ class TodoistApi {
1537
2320
  * ```
1538
2321
  */
1539
2322
  async getWorkspaces(requestId) {
1540
- const syncRequest = {
1541
- syncToken: '*',
1542
- resourceTypes: ['workspaces'],
2323
+ const response = await (0, http_client_1.request)({
2324
+ httpMethod: 'GET',
2325
+ baseUri: this.syncApiBase,
2326
+ relativePath: endpoints_1.ENDPOINT_REST_WORKSPACES,
2327
+ apiToken: this.authToken,
2328
+ customFetch: this.customFetch,
2329
+ requestId: requestId,
2330
+ });
2331
+ return (0, validators_1.validateWorkspaceArray)(response.data);
2332
+ }
2333
+ /**
2334
+ * Retrieves a workspace by its ID.
2335
+ *
2336
+ * @param id - The unique identifier of the workspace.
2337
+ * @param requestId - Optional custom identifier for the request.
2338
+ * @returns A promise that resolves to the requested workspace.
2339
+ */
2340
+ async getWorkspace(id, requestId) {
2341
+ zod_1.z.string().parse(id);
2342
+ const response = await (0, http_client_1.request)({
2343
+ httpMethod: 'GET',
2344
+ baseUri: this.syncApiBase,
2345
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_WORKSPACES, id),
2346
+ apiToken: this.authToken,
2347
+ customFetch: this.customFetch,
2348
+ requestId: requestId,
2349
+ });
2350
+ return (0, validators_1.validateWorkspace)(response.data);
2351
+ }
2352
+ /**
2353
+ * Creates a new workspace.
2354
+ *
2355
+ * @param args - The arguments for creating the workspace.
2356
+ * @param requestId - Optional custom identifier for the request.
2357
+ * @returns A promise that resolves to the created workspace.
2358
+ */
2359
+ async addWorkspace(args, requestId) {
2360
+ const response = await (0, http_client_1.request)({
2361
+ httpMethod: 'POST',
2362
+ baseUri: this.syncApiBase,
2363
+ relativePath: endpoints_1.ENDPOINT_REST_WORKSPACES,
2364
+ apiToken: this.authToken,
2365
+ customFetch: this.customFetch,
2366
+ payload: args,
2367
+ requestId: requestId,
2368
+ });
2369
+ return (0, validators_1.validateWorkspace)(response.data);
2370
+ }
2371
+ /**
2372
+ * Updates an existing workspace.
2373
+ *
2374
+ * @param id - The unique identifier of the workspace to update.
2375
+ * @param args - The arguments for updating the workspace.
2376
+ * @param requestId - Optional custom identifier for the request.
2377
+ * @returns A promise that resolves to the updated workspace.
2378
+ */
2379
+ async updateWorkspace(id, args, requestId) {
2380
+ zod_1.z.string().parse(id);
2381
+ const response = await (0, http_client_1.request)({
2382
+ httpMethod: 'POST',
2383
+ baseUri: this.syncApiBase,
2384
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_WORKSPACES, id),
2385
+ apiToken: this.authToken,
2386
+ customFetch: this.customFetch,
2387
+ payload: args,
2388
+ requestId: requestId,
2389
+ });
2390
+ return (0, validators_1.validateWorkspace)(response.data);
2391
+ }
2392
+ /**
2393
+ * Deletes a workspace by its ID.
2394
+ *
2395
+ * @param id - The unique identifier of the workspace to delete.
2396
+ * @param requestId - Optional custom identifier for the request.
2397
+ * @returns A promise that resolves to `true` if successful.
2398
+ */
2399
+ async deleteWorkspace(id, requestId) {
2400
+ zod_1.z.string().parse(id);
2401
+ const response = await (0, http_client_1.request)({
2402
+ httpMethod: 'DELETE',
2403
+ baseUri: this.syncApiBase,
2404
+ relativePath: generatePath(endpoints_1.ENDPOINT_REST_WORKSPACES, id),
2405
+ apiToken: this.authToken,
2406
+ customFetch: this.customFetch,
2407
+ requestId: requestId,
2408
+ });
2409
+ return (0, http_client_1.isSuccess)(response);
2410
+ }
2411
+ /**
2412
+ * Retrieves activity information for workspace members.
2413
+ *
2414
+ * @param args - Arguments including workspace ID and optional user/project filters.
2415
+ * @param requestId - Optional custom identifier for the request.
2416
+ * @returns A promise that resolves to workspace members activity data.
2417
+ */
2418
+ async getWorkspaceMembersActivity(args, requestId) {
2419
+ const { workspaceId } = args, queryParams = __rest(args, ["workspaceId"]);
2420
+ const { data } = await (0, http_client_1.request)({
2421
+ httpMethod: 'GET',
2422
+ baseUri: this.syncApiBase,
2423
+ relativePath: endpoints_1.ENDPOINT_WORKSPACE_MEMBERS,
2424
+ apiToken: this.authToken,
2425
+ customFetch: this.customFetch,
2426
+ payload: Object.assign({ workspaceId }, queryParams),
2427
+ requestId: requestId,
2428
+ });
2429
+ return {
2430
+ members: (0, validators_1.validateMemberActivityInfoArray)(data.members),
1543
2431
  };
1544
- const syncResponse = await this.requestSync(syncRequest, requestId, false);
1545
- const workspacesData = syncResponse.workspaces;
1546
- if (!workspacesData || typeof workspacesData !== 'object') {
1547
- return [];
1548
- }
1549
- const workspacesArray = Object.values(workspacesData);
1550
- return (0, validators_1.validateWorkspaceArray)(workspacesArray);
2432
+ }
2433
+ /**
2434
+ * Retrieves tasks assigned to a specific user in a workspace.
2435
+ *
2436
+ * @param args - Arguments including workspace ID, user ID, and optional project filter.
2437
+ * @param requestId - Optional custom identifier for the request.
2438
+ * @returns A promise that resolves to workspace user tasks.
2439
+ */
2440
+ async getWorkspaceUserTasks(args, requestId) {
2441
+ const { workspaceId, userId } = args, queryParams = __rest(args, ["workspaceId", "userId"]);
2442
+ const { data } = await (0, http_client_1.request)({
2443
+ httpMethod: 'GET',
2444
+ baseUri: this.syncApiBase,
2445
+ relativePath: (0, endpoints_1.getWorkspaceUserTasksEndpoint)(workspaceId, userId),
2446
+ apiToken: this.authToken,
2447
+ customFetch: this.customFetch,
2448
+ payload: queryParams,
2449
+ requestId: requestId,
2450
+ });
2451
+ return {
2452
+ tasks: (0, validators_1.validateWorkspaceUserTaskArray)(data.tasks),
2453
+ };
2454
+ }
2455
+ /**
2456
+ * Invites users to a workspace by email.
2457
+ *
2458
+ * @param args - Arguments including workspace ID, email list, and optional role.
2459
+ * @param requestId - Optional custom identifier for the request.
2460
+ * @returns A promise that resolves to the list of invited emails.
2461
+ */
2462
+ async inviteWorkspaceUsers(args, requestId) {
2463
+ const { workspaceId } = args, payload = __rest(args, ["workspaceId"]);
2464
+ const { data } = await (0, http_client_1.request)({
2465
+ httpMethod: 'POST',
2466
+ baseUri: this.syncApiBase,
2467
+ relativePath: (0, endpoints_1.getWorkspaceInviteUsersEndpoint)(workspaceId),
2468
+ apiToken: this.authToken,
2469
+ customFetch: this.customFetch,
2470
+ payload: payload,
2471
+ requestId: requestId,
2472
+ });
2473
+ return data;
2474
+ }
2475
+ /**
2476
+ * Updates a workspace user's role.
2477
+ *
2478
+ * @param args - Arguments including workspace ID, user ID, and new role.
2479
+ * @param requestId - Optional custom identifier for the request.
2480
+ * @returns A promise that resolves to the updated workspace user view.
2481
+ */
2482
+ async updateWorkspaceUser(args, requestId) {
2483
+ const { workspaceId, userId } = args, payload = __rest(args, ["workspaceId", "userId"]);
2484
+ const response = await (0, http_client_1.request)({
2485
+ httpMethod: 'POST',
2486
+ baseUri: this.syncApiBase,
2487
+ relativePath: (0, endpoints_1.getWorkspaceUserEndpoint)(workspaceId, userId),
2488
+ apiToken: this.authToken,
2489
+ customFetch: this.customFetch,
2490
+ payload: payload,
2491
+ requestId: requestId,
2492
+ });
2493
+ return (0, validators_1.validateJoinWorkspaceResult)(response.data);
2494
+ }
2495
+ /**
2496
+ * Removes a user from a workspace.
2497
+ *
2498
+ * @param args - Arguments including workspace ID and user ID.
2499
+ * @param requestId - Optional custom identifier for the request.
2500
+ * @returns A promise that resolves to `true` if successful.
2501
+ */
2502
+ async removeWorkspaceUser(args, requestId) {
2503
+ const { workspaceId, userId } = args;
2504
+ const response = await (0, http_client_1.request)({
2505
+ httpMethod: 'DELETE',
2506
+ baseUri: this.syncApiBase,
2507
+ relativePath: (0, endpoints_1.getWorkspaceUserEndpoint)(workspaceId, userId),
2508
+ apiToken: this.authToken,
2509
+ customFetch: this.customFetch,
2510
+ requestId: requestId,
2511
+ });
2512
+ return (0, http_client_1.isSuccess)(response);
1551
2513
  }
1552
2514
  /**
1553
2515
  * Gets active projects in a workspace with pagination.
@@ -1565,7 +2527,7 @@ class TodoistApi {
1565
2527
  if (args.limit) {
1566
2528
  queryParams.limit = args.limit;
1567
2529
  }
1568
- const response = await (0, rest_client_1.request)({
2530
+ const response = await (0, http_client_1.request)({
1569
2531
  httpMethod: 'GET',
1570
2532
  baseUri: this.syncApiBase,
1571
2533
  relativePath: (0, endpoints_1.getWorkspaceActiveProjectsEndpoint)(args.workspaceId),
@@ -1596,7 +2558,7 @@ class TodoistApi {
1596
2558
  if (args.limit) {
1597
2559
  queryParams.limit = args.limit;
1598
2560
  }
1599
- const response = await (0, rest_client_1.request)({
2561
+ const response = await (0, http_client_1.request)({
1600
2562
  httpMethod: 'GET',
1601
2563
  baseUri: this.syncApiBase,
1602
2564
  relativePath: (0, endpoints_1.getWorkspaceArchivedProjectsEndpoint)(args.workspaceId),