@doist/todoist-api-typescript 7.3.0 → 7.5.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 (59) hide show
  1. package/README.md +2 -0
  2. package/dist/cjs/authentication.js +14 -4
  3. package/dist/cjs/consts/endpoints.js +11 -1
  4. package/dist/cjs/test-utils/asserts.js +1 -1
  5. package/dist/cjs/test-utils/test-defaults.js +33 -1
  6. package/dist/cjs/todoist-api.js +532 -88
  7. package/dist/cjs/{utils → transport}/fetch-with-retry.js +23 -71
  8. package/dist/cjs/{rest-client.js → transport/http-client.js} +6 -6
  9. package/dist/cjs/transport/http-dispatcher.js +72 -0
  10. package/dist/cjs/types/entities.js +11 -1
  11. package/dist/cjs/types/errors.js +9 -2
  12. package/dist/cjs/types/http.js +3 -1
  13. package/dist/cjs/types/requests.js +3 -0
  14. package/dist/cjs/types/sync/commands/labels.js +3 -0
  15. package/dist/cjs/types/sync/commands/shared.js +15 -0
  16. package/dist/cjs/types/sync/resources/reminders.js +2 -0
  17. package/dist/cjs/types/sync/user-preferences.js +27 -7
  18. package/dist/cjs/utils/multipart-upload.js +1 -1
  19. package/dist/cjs/utils/sanitization.js +7 -7
  20. package/dist/esm/authentication.js +10 -1
  21. package/dist/esm/consts/endpoints.js +9 -0
  22. package/dist/esm/test-utils/asserts.js +1 -1
  23. package/dist/esm/test-utils/test-defaults.js +32 -0
  24. package/dist/esm/todoist-api.js +467 -23
  25. package/dist/esm/{utils → transport}/fetch-with-retry.js +23 -38
  26. package/dist/esm/{rest-client.js → transport/http-client.js} +6 -6
  27. package/dist/esm/transport/http-dispatcher.js +35 -0
  28. package/dist/esm/types/entities.js +10 -0
  29. package/dist/esm/types/errors.js +7 -1
  30. package/dist/esm/types/http.js +3 -1
  31. package/dist/esm/types/requests.js +2 -1
  32. package/dist/esm/types/sync/commands/labels.js +2 -1
  33. package/dist/esm/types/sync/commands/shared.js +13 -1
  34. package/dist/esm/types/sync/resources/reminders.js +2 -0
  35. package/dist/esm/types/sync/user-preferences.js +23 -3
  36. package/dist/esm/utils/multipart-upload.js +1 -1
  37. package/dist/esm/utils/sanitization.js +7 -7
  38. package/dist/types/authentication.d.ts +5 -3
  39. package/dist/types/consts/endpoints.d.ts +9 -0
  40. package/dist/types/test-utils/test-defaults.d.ts +5 -1
  41. package/dist/types/todoist-api.d.ts +144 -3
  42. package/dist/types/{utils → transport}/fetch-with-retry.d.ts +1 -1
  43. package/dist/types/{rest-client.d.ts → transport/http-client.d.ts} +1 -1
  44. package/dist/types/transport/http-dispatcher.d.ts +3 -0
  45. package/dist/types/types/entities.d.ts +8 -1
  46. package/dist/types/types/errors.d.ts +4 -0
  47. package/dist/types/types/requests.d.ts +163 -1
  48. package/dist/types/types/sync/commands/labels.d.ts +5 -1
  49. package/dist/types/types/sync/commands/projects.d.ts +2 -2
  50. package/dist/types/types/sync/commands/reminders.d.ts +3 -2
  51. package/dist/types/types/sync/commands/shared.d.ts +10 -5
  52. package/dist/types/types/sync/resources/reminders.d.ts +4 -0
  53. package/dist/types/types/sync/resources/user.d.ts +2 -2
  54. package/dist/types/types/sync/user-preferences.d.ts +30 -4
  55. package/dist/types/utils/validators.d.ts +4 -0
  56. package/package.json +10 -17
  57. package/dist/cjs/test-utils/mocks.js +0 -3
  58. package/dist/esm/test-utils/mocks.js +0 -3
  59. package/dist/types/test-utils/mocks.d.ts +0 -0
@@ -9,9 +9,12 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { request, isSuccess } from './rest-client.js';
13
- import { getSyncBaseUri, ENDPOINT_REST_TASKS, ENDPOINT_REST_TASKS_FILTER, ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE, ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE, ENDPOINT_REST_TASKS_COMPLETED_SEARCH, ENDPOINT_REST_PROJECTS, ENDPOINT_REST_PROJECTS_SEARCH, ENDPOINT_SYNC_QUICK_ADD, ENDPOINT_REST_TASK_CLOSE, ENDPOINT_REST_TASK_REOPEN, ENDPOINT_REST_TASK_MOVE, ENDPOINT_REST_LABELS, ENDPOINT_REST_LABELS_SEARCH, ENDPOINT_REST_PROJECT_COLLABORATORS, ENDPOINT_REST_SECTIONS, ENDPOINT_REST_SECTIONS_SEARCH, ENDPOINT_REST_COMMENTS, ENDPOINT_REST_LABELS_SHARED, ENDPOINT_REST_LABELS_SHARED_RENAME, ENDPOINT_REST_LABELS_SHARED_REMOVE, ENDPOINT_SYNC, PROJECT_ARCHIVE, PROJECT_UNARCHIVE, ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE, ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL, ENDPOINT_REST_PROJECTS_ARCHIVED, ENDPOINT_REST_USER, ENDPOINT_REST_PRODUCTIVITY, ENDPOINT_REST_ACTIVITIES, ENDPOINT_REST_UPLOADS, ENDPOINT_WORKSPACE_INVITATIONS, ENDPOINT_WORKSPACE_INVITATIONS_ALL, ENDPOINT_WORKSPACE_INVITATIONS_DELETE, getWorkspaceInvitationAcceptEndpoint, getWorkspaceInvitationRejectEndpoint, ENDPOINT_WORKSPACE_JOIN, ENDPOINT_WORKSPACE_LOGO, ENDPOINT_WORKSPACE_PLAN_DETAILS, ENDPOINT_WORKSPACE_USERS, getWorkspaceActiveProjectsEndpoint, getWorkspaceArchivedProjectsEndpoint, } from './consts/endpoints.js';
14
- import { validateAttachment, validateComment, validateCommentArray, validateCurrentUser, validateLabel, validateLabelArray, validateProject, validateProjectArray, validateSection, validateSectionArray, validateTask, validateTaskArray, validateUserArray, validateProductivityStats, validateActivityEventArray, validateWorkspaceUserArray, validateWorkspaceInvitation, validateWorkspaceInvitationArray, validateWorkspacePlanDetails, validateJoinWorkspaceResult, validateWorkspaceArray, } from './utils/validators.js';
12
+ import { DueDateSchema, } from './types/entities.js';
13
+ import { LOCATION_TRIGGERS } from './types/sync/resources/reminders.js';
14
+ import { REMINDER_DELIVERY_SERVICES, } from './types/requests.js';
15
+ import { request, isSuccess } from './transport/http-client.js';
16
+ import { getSyncBaseUri, ENDPOINT_REST_TASKS, ENDPOINT_REST_TASKS_FILTER, ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE, ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE, ENDPOINT_REST_TASKS_COMPLETED_SEARCH, ENDPOINT_REST_PROJECTS, ENDPOINT_REST_PROJECTS_SEARCH, ENDPOINT_SYNC_QUICK_ADD, ENDPOINT_REST_TASK_CLOSE, ENDPOINT_REST_TASK_REOPEN, ENDPOINT_REST_TASK_MOVE, ENDPOINT_REST_LABELS, ENDPOINT_REST_LABELS_SEARCH, ENDPOINT_REST_PROJECT_COLLABORATORS, ENDPOINT_REST_SECTIONS, ENDPOINT_REST_SECTIONS_SEARCH, ENDPOINT_REST_COMMENTS, ENDPOINT_REST_LOCATION_REMINDERS, ENDPOINT_REST_REMINDERS, ENDPOINT_REST_LABELS_SHARED, ENDPOINT_REST_LABELS_SHARED_RENAME, ENDPOINT_REST_LABELS_SHARED_REMOVE, ENDPOINT_SYNC, PROJECT_ARCHIVE, PROJECT_UNARCHIVE, ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE, ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL, ENDPOINT_REST_PROJECTS_ARCHIVED, ENDPOINT_REST_PROJECTS_ARCHIVED_COUNT, ENDPOINT_REST_PROJECTS_PERMISSIONS, ENDPOINT_REST_PROJECT_FULL, ENDPOINT_REST_PROJECT_JOIN, SECTION_ARCHIVE, SECTION_UNARCHIVE, ENDPOINT_REST_USER, ENDPOINT_REST_PRODUCTIVITY, ENDPOINT_REST_ACTIVITIES, ENDPOINT_REST_UPLOADS, ENDPOINT_REST_WORKSPACES, ENDPOINT_WORKSPACE_INVITATIONS, ENDPOINT_WORKSPACE_INVITATIONS_ALL, ENDPOINT_WORKSPACE_INVITATIONS_DELETE, getWorkspaceInvitationAcceptEndpoint, getWorkspaceInvitationRejectEndpoint, ENDPOINT_WORKSPACE_JOIN, ENDPOINT_WORKSPACE_LOGO, ENDPOINT_WORKSPACE_PLAN_DETAILS, ENDPOINT_WORKSPACE_USERS, getWorkspaceActiveProjectsEndpoint, getWorkspaceArchivedProjectsEndpoint, } from './consts/endpoints.js';
17
+ import { validateAttachment, validateComment, validateCommentArray, validateCurrentUser, validateLabel, validateLabelArray, validateProject, validateProjectArray, validateSection, validateSectionArray, validateTask, validateTaskArray, validateUserArray, validateProductivityStats, validateReminder, validateActivityEventArray, validateWorkspaceUserArray, validateWorkspaceInvitation, validateWorkspaceInvitationArray, validateWorkspacePlanDetails, validateJoinWorkspaceResult, validateWorkspace, validateWorkspaceArray, } from './utils/validators.js';
15
18
  import { formatDateToYYYYMMDD } from './utils/url-helpers.js';
16
19
  import { uploadMultipartFile } from './utils/multipart-upload.js';
17
20
  import { normalizeObjectEventTypeForApi, denormalizeObjectTypeFromApi, } from './utils/activity-helpers.js';
@@ -19,7 +22,7 @@ import { processTaskContent } from './utils/uncompletable-helpers.js';
19
22
  import { z } from 'zod';
20
23
  import { v4 as uuidv4 } from 'uuid';
21
24
  import { DATE_FORMAT_TO_API, TIME_FORMAT_TO_API, DAY_OF_WEEK_TO_API, } from './types/sync/index.js';
22
- import { TodoistRequestError } from './types/index.js';
25
+ import { TodoistArgumentError, TodoistRequestError } from './types/index.js';
23
26
  const MAX_COMMAND_COUNT = 100;
24
27
  /**
25
28
  * Joins path segments using `/` separator.
@@ -80,6 +83,56 @@ function headersToRecord(headers) {
80
83
  });
81
84
  return result;
82
85
  }
86
+ const ReminderDeliveryServiceSchema = z.enum(REMINDER_DELIVERY_SERVICES);
87
+ const ReminderIdSchema = z.string();
88
+ const ReminderDueDateSchema = DueDateSchema.pick({
89
+ date: true,
90
+ string: true,
91
+ timezone: true,
92
+ lang: true,
93
+ isRecurring: true,
94
+ })
95
+ .partial()
96
+ .strict();
97
+ const UpdateRelativeReminderArgsSchema = z
98
+ .object({
99
+ reminderType: z.literal('relative'),
100
+ minuteOffset: z.number().int().optional(),
101
+ notifyUid: z.string().optional(),
102
+ service: ReminderDeliveryServiceSchema.optional(),
103
+ isUrgent: z.boolean().optional(),
104
+ })
105
+ .strict();
106
+ const UpdateAbsoluteReminderArgsSchema = z
107
+ .object({
108
+ reminderType: z.literal('absolute'),
109
+ due: ReminderDueDateSchema.optional(),
110
+ notifyUid: z.string().optional(),
111
+ service: ReminderDeliveryServiceSchema.optional(),
112
+ isUrgent: z.boolean().optional(),
113
+ })
114
+ .strict();
115
+ const UpdateLocationReminderArgsSchema = z
116
+ .object({
117
+ notifyUid: z.string().optional(),
118
+ name: z.string().optional(),
119
+ locLat: z.string().optional(),
120
+ locLong: z.string().optional(),
121
+ locTrigger: z.enum(LOCATION_TRIGGERS).optional(),
122
+ radius: z.number().int().optional(),
123
+ })
124
+ .strict()
125
+ .refine((args) => Object.values(args).some((value) => value !== undefined), {
126
+ message: 'At least one reminder field must be provided to updateLocationReminder',
127
+ });
128
+ const UpdateReminderArgsSchema = z
129
+ .discriminatedUnion('reminderType', [
130
+ UpdateRelativeReminderArgsSchema,
131
+ UpdateAbsoluteReminderArgsSchema,
132
+ ])
133
+ .refine((args) => Object.entries(args).some(([key, value]) => key !== 'reminderType' && value !== undefined), {
134
+ message: 'At least one reminder field must be provided to updateReminder',
135
+ });
83
136
  export class TodoistApi {
84
137
  constructor(
85
138
  /**
@@ -683,6 +736,83 @@ export class TodoistApi {
683
736
  });
684
737
  return validateProject(response.data.project);
685
738
  }
739
+ /**
740
+ * Counts the number of archived projects.
741
+ *
742
+ * @param args - Optional parameters to filter the count.
743
+ * @returns A promise that resolves to the count of archived projects.
744
+ */
745
+ async getArchivedProjectsCount(args = {}) {
746
+ const { data } = await request({
747
+ httpMethod: 'GET',
748
+ baseUri: this.syncApiBase,
749
+ relativePath: ENDPOINT_REST_PROJECTS_ARCHIVED_COUNT,
750
+ apiToken: this.authToken,
751
+ customFetch: this.customFetch,
752
+ payload: args,
753
+ });
754
+ return data;
755
+ }
756
+ /**
757
+ * Retrieves the role-to-action permission mappings for projects.
758
+ *
759
+ * @returns A promise that resolves to the permission mappings.
760
+ */
761
+ async getProjectPermissions() {
762
+ const { data } = await request({
763
+ httpMethod: 'GET',
764
+ baseUri: this.syncApiBase,
765
+ relativePath: ENDPOINT_REST_PROJECTS_PERMISSIONS,
766
+ apiToken: this.authToken,
767
+ customFetch: this.customFetch,
768
+ });
769
+ return data;
770
+ }
771
+ /**
772
+ * Retrieves full project data including tasks, sections, collaborators, and notes.
773
+ *
774
+ * @param id - The unique identifier of the project.
775
+ * @param args - Optional parameters.
776
+ * @returns A promise that resolves to the full project data.
777
+ */
778
+ async getFullProject(id, args = {}) {
779
+ z.string().parse(id);
780
+ const { data } = await request({
781
+ httpMethod: 'GET',
782
+ baseUri: this.syncApiBase,
783
+ relativePath: generatePath(ENDPOINT_REST_PROJECTS, id, ENDPOINT_REST_PROJECT_FULL),
784
+ apiToken: this.authToken,
785
+ customFetch: this.customFetch,
786
+ payload: args,
787
+ });
788
+ return {
789
+ project: data.project ? validateProject(data.project) : null,
790
+ commentsCount: data.commentsCount,
791
+ tasks: validateTaskArray(data.tasks),
792
+ sections: validateSectionArray(data.sections),
793
+ collaborators: validateUserArray(data.collaborators),
794
+ notes: validateCommentArray(data.notes),
795
+ };
796
+ }
797
+ /**
798
+ * Joins a shared project by its ID.
799
+ *
800
+ * @param id - The unique identifier of the project to join.
801
+ * @param requestId - Optional custom identifier for the request.
802
+ * @returns A promise that resolves to the joined project.
803
+ */
804
+ async joinProject(id, requestId) {
805
+ z.string().parse(id);
806
+ const response = await request({
807
+ httpMethod: 'POST',
808
+ baseUri: this.syncApiBase,
809
+ relativePath: generatePath(ENDPOINT_REST_PROJECTS, id, ENDPOINT_REST_PROJECT_JOIN),
810
+ apiToken: this.authToken,
811
+ customFetch: this.customFetch,
812
+ requestId: requestId,
813
+ });
814
+ return validateProject(response.data);
815
+ }
686
816
  /**
687
817
  * Retrieves a list of collaborators for a specific project.
688
818
  *
@@ -822,6 +952,44 @@ export class TodoistApi {
822
952
  });
823
953
  return isSuccess(response);
824
954
  }
955
+ /**
956
+ * Archives a section by its ID.
957
+ *
958
+ * @param id - The unique identifier of the section to archive.
959
+ * @param requestId - Optional custom identifier for the request.
960
+ * @returns A promise that resolves to the updated section.
961
+ */
962
+ async archiveSection(id, requestId) {
963
+ z.string().parse(id);
964
+ const response = await request({
965
+ httpMethod: 'POST',
966
+ baseUri: this.syncApiBase,
967
+ relativePath: generatePath(ENDPOINT_REST_SECTIONS, id, SECTION_ARCHIVE),
968
+ apiToken: this.authToken,
969
+ customFetch: this.customFetch,
970
+ requestId: requestId,
971
+ });
972
+ return validateSection(response.data);
973
+ }
974
+ /**
975
+ * Unarchives a section by its ID.
976
+ *
977
+ * @param id - The unique identifier of the section to unarchive.
978
+ * @param requestId - Optional custom identifier for the request.
979
+ * @returns A promise that resolves to the updated section.
980
+ */
981
+ async unarchiveSection(id, requestId) {
982
+ z.string().parse(id);
983
+ const response = await request({
984
+ httpMethod: 'POST',
985
+ baseUri: this.syncApiBase,
986
+ relativePath: generatePath(ENDPOINT_REST_SECTIONS, id, SECTION_UNARCHIVE),
987
+ apiToken: this.authToken,
988
+ customFetch: this.customFetch,
989
+ requestId: requestId,
990
+ });
991
+ return validateSection(response.data);
992
+ }
825
993
  /**
826
994
  * Retrieves a label by its ID.
827
995
  *
@@ -846,7 +1014,7 @@ export class TodoistApi {
846
1014
  * @returns A promise that resolves to an array of labels.
847
1015
  */
848
1016
  async getLabels(args = {}) {
849
- const { data: { results, nextCursor: nextCursor }, } = await request({
1017
+ const { data: { results, nextCursor }, } = await request({
850
1018
  httpMethod: 'GET',
851
1019
  baseUri: this.syncApiBase,
852
1020
  relativePath: ENDPOINT_REST_LABELS,
@@ -945,7 +1113,7 @@ export class TodoistApi {
945
1113
  * @returns A promise that resolves to an array of shared labels.
946
1114
  */
947
1115
  async getSharedLabels(args) {
948
- const { data: { results, nextCursor: nextCursor }, } = await request({
1116
+ const { data: { results, nextCursor }, } = await request({
949
1117
  httpMethod: 'GET',
950
1118
  baseUri: this.syncApiBase,
951
1119
  relativePath: ENDPOINT_REST_LABELS_SHARED,
@@ -1085,6 +1253,208 @@ export class TodoistApi {
1085
1253
  });
1086
1254
  return isSuccess(response);
1087
1255
  }
1256
+ /**
1257
+ * Retrieves a time-based reminder by its ID.
1258
+ *
1259
+ * @param id - The unique identifier of the reminder to retrieve.
1260
+ * @returns A promise that resolves to the requested reminder.
1261
+ */
1262
+ async getReminder(id) {
1263
+ ReminderIdSchema.parse(id);
1264
+ try {
1265
+ const response = await request({
1266
+ httpMethod: 'GET',
1267
+ baseUri: this.syncApiBase,
1268
+ relativePath: generatePath(ENDPOINT_REST_REMINDERS, id),
1269
+ apiToken: this.authToken,
1270
+ customFetch: this.customFetch,
1271
+ });
1272
+ return validateReminder(response.data);
1273
+ }
1274
+ catch (error) {
1275
+ if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
1276
+ throw error;
1277
+ }
1278
+ throw new TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use getLocationReminder instead.`);
1279
+ }
1280
+ }
1281
+ /**
1282
+ * Retrieves a location reminder by its ID.
1283
+ *
1284
+ * @param id - The unique identifier of the location reminder to retrieve.
1285
+ * @returns A promise that resolves to the requested reminder.
1286
+ */
1287
+ async getLocationReminder(id) {
1288
+ ReminderIdSchema.parse(id);
1289
+ try {
1290
+ const response = await request({
1291
+ httpMethod: 'GET',
1292
+ baseUri: this.syncApiBase,
1293
+ relativePath: generatePath(ENDPOINT_REST_LOCATION_REMINDERS, id),
1294
+ apiToken: this.authToken,
1295
+ customFetch: this.customFetch,
1296
+ });
1297
+ return validateReminder(response.data);
1298
+ }
1299
+ catch (error) {
1300
+ if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
1301
+ throw error;
1302
+ }
1303
+ throw new TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use getReminder instead.`);
1304
+ }
1305
+ }
1306
+ /**
1307
+ * Creates a time-based reminder for a task.
1308
+ *
1309
+ * @param args - Reminder creation parameters for relative or absolute reminders.
1310
+ * @param requestId - Optional custom identifier for the request.
1311
+ * @returns A promise that resolves to the created reminder.
1312
+ */
1313
+ async addReminder(args, requestId) {
1314
+ const response = await request({
1315
+ httpMethod: 'POST',
1316
+ baseUri: this.syncApiBase,
1317
+ relativePath: ENDPOINT_REST_REMINDERS,
1318
+ apiToken: this.authToken,
1319
+ customFetch: this.customFetch,
1320
+ payload: args,
1321
+ requestId: requestId,
1322
+ });
1323
+ return validateReminder(response.data);
1324
+ }
1325
+ /**
1326
+ * Creates a location reminder for a task.
1327
+ *
1328
+ * @param args - Location reminder creation parameters.
1329
+ * @param requestId - Optional custom identifier for the request.
1330
+ * @returns A promise that resolves to the created reminder.
1331
+ */
1332
+ async addLocationReminder(args, requestId) {
1333
+ const response = await request({
1334
+ httpMethod: 'POST',
1335
+ baseUri: this.syncApiBase,
1336
+ relativePath: ENDPOINT_REST_LOCATION_REMINDERS,
1337
+ apiToken: this.authToken,
1338
+ customFetch: this.customFetch,
1339
+ payload: Object.assign(Object.assign({}, args), { reminderType: 'location' }),
1340
+ requestId: requestId,
1341
+ });
1342
+ return validateReminder(response.data);
1343
+ }
1344
+ /**
1345
+ * Updates an existing time-based reminder.
1346
+ *
1347
+ * @param id - The unique identifier of the reminder to update.
1348
+ * @param args - Reminder update parameters.
1349
+ * @param requestId - Optional custom identifier for the request.
1350
+ * @returns A promise that resolves to the updated reminder.
1351
+ */
1352
+ async updateReminder(id, args, requestId) {
1353
+ ReminderIdSchema.parse(id);
1354
+ const payload = UpdateReminderArgsSchema.parse(args);
1355
+ try {
1356
+ const response = await request({
1357
+ httpMethod: 'POST',
1358
+ baseUri: this.syncApiBase,
1359
+ relativePath: generatePath(ENDPOINT_REST_REMINDERS, id),
1360
+ apiToken: this.authToken,
1361
+ customFetch: this.customFetch,
1362
+ payload,
1363
+ requestId: requestId,
1364
+ });
1365
+ return validateReminder(response.data);
1366
+ }
1367
+ catch (error) {
1368
+ if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
1369
+ throw error;
1370
+ }
1371
+ throw new TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use updateLocationReminder instead.`);
1372
+ }
1373
+ }
1374
+ /**
1375
+ * Updates an existing location reminder.
1376
+ *
1377
+ * @param id - The unique identifier of the location reminder to update.
1378
+ * @param args - Location reminder update parameters.
1379
+ * @param requestId - Optional custom identifier for the request.
1380
+ * @returns A promise that resolves to the updated reminder.
1381
+ */
1382
+ async updateLocationReminder(id, args, requestId) {
1383
+ ReminderIdSchema.parse(id);
1384
+ const payload = UpdateLocationReminderArgsSchema.parse(args);
1385
+ try {
1386
+ const response = await request({
1387
+ httpMethod: 'POST',
1388
+ baseUri: this.syncApiBase,
1389
+ relativePath: generatePath(ENDPOINT_REST_LOCATION_REMINDERS, id),
1390
+ apiToken: this.authToken,
1391
+ customFetch: this.customFetch,
1392
+ payload,
1393
+ requestId: requestId,
1394
+ });
1395
+ return validateReminder(response.data);
1396
+ }
1397
+ catch (error) {
1398
+ if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
1399
+ throw error;
1400
+ }
1401
+ throw new TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use updateReminder instead.`);
1402
+ }
1403
+ }
1404
+ /**
1405
+ * Deletes a time-based reminder by its ID.
1406
+ *
1407
+ * @param id - The unique identifier of the reminder to delete.
1408
+ * @param requestId - Optional custom identifier for the request.
1409
+ * @returns A promise that resolves to `true` if successful.
1410
+ */
1411
+ async deleteReminder(id, requestId) {
1412
+ ReminderIdSchema.parse(id);
1413
+ try {
1414
+ const response = await request({
1415
+ httpMethod: 'DELETE',
1416
+ baseUri: this.syncApiBase,
1417
+ relativePath: generatePath(ENDPOINT_REST_REMINDERS, id),
1418
+ apiToken: this.authToken,
1419
+ customFetch: this.customFetch,
1420
+ requestId: requestId,
1421
+ });
1422
+ return isSuccess(response);
1423
+ }
1424
+ catch (error) {
1425
+ if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
1426
+ throw error;
1427
+ }
1428
+ throw new TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use deleteLocationReminder instead.`);
1429
+ }
1430
+ }
1431
+ /**
1432
+ * Deletes a location reminder by its ID.
1433
+ *
1434
+ * @param id - The unique identifier of the location reminder to delete.
1435
+ * @param requestId - Optional custom identifier for the request.
1436
+ * @returns A promise that resolves to `true` if successful.
1437
+ */
1438
+ async deleteLocationReminder(id, requestId) {
1439
+ ReminderIdSchema.parse(id);
1440
+ try {
1441
+ const response = await request({
1442
+ httpMethod: 'DELETE',
1443
+ baseUri: this.syncApiBase,
1444
+ relativePath: generatePath(ENDPOINT_REST_LOCATION_REMINDERS, id),
1445
+ apiToken: this.authToken,
1446
+ customFetch: this.customFetch,
1447
+ requestId: requestId,
1448
+ });
1449
+ return isSuccess(response);
1450
+ }
1451
+ catch (error) {
1452
+ if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
1453
+ throw error;
1454
+ }
1455
+ throw new TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use deleteReminder instead.`);
1456
+ }
1457
+ }
1088
1458
  /**
1089
1459
  * Retrieves productivity stats for the authenticated user.
1090
1460
  *
@@ -1520,8 +1890,6 @@ export class TodoistApi {
1520
1890
  /**
1521
1891
  * Retrieves all workspaces for the authenticated user.
1522
1892
  *
1523
- * Uses the Sync API internally to fetch workspace data.
1524
- *
1525
1893
  * @param requestId - Optional custom identifier for the request.
1526
1894
  * @returns A promise that resolves to an array of workspaces.
1527
1895
  *
@@ -1534,17 +1902,93 @@ export class TodoistApi {
1534
1902
  * ```
1535
1903
  */
1536
1904
  async getWorkspaces(requestId) {
1537
- const syncRequest = {
1538
- syncToken: '*',
1539
- resourceTypes: ['workspaces'],
1540
- };
1541
- const syncResponse = await this.requestSync(syncRequest, requestId, false);
1542
- const workspacesData = syncResponse.workspaces;
1543
- if (!workspacesData || typeof workspacesData !== 'object') {
1544
- return [];
1545
- }
1546
- const workspacesArray = Object.values(workspacesData);
1547
- return validateWorkspaceArray(workspacesArray);
1905
+ const response = await request({
1906
+ httpMethod: 'GET',
1907
+ baseUri: this.syncApiBase,
1908
+ relativePath: ENDPOINT_REST_WORKSPACES,
1909
+ apiToken: this.authToken,
1910
+ customFetch: this.customFetch,
1911
+ requestId: requestId,
1912
+ });
1913
+ return validateWorkspaceArray(response.data);
1914
+ }
1915
+ /**
1916
+ * Retrieves a workspace by its ID.
1917
+ *
1918
+ * @param id - The unique identifier of the workspace.
1919
+ * @param requestId - Optional custom identifier for the request.
1920
+ * @returns A promise that resolves to the requested workspace.
1921
+ */
1922
+ async getWorkspace(id, requestId) {
1923
+ z.string().parse(id);
1924
+ const response = await request({
1925
+ httpMethod: 'GET',
1926
+ baseUri: this.syncApiBase,
1927
+ relativePath: generatePath(ENDPOINT_REST_WORKSPACES, id),
1928
+ apiToken: this.authToken,
1929
+ customFetch: this.customFetch,
1930
+ requestId: requestId,
1931
+ });
1932
+ return validateWorkspace(response.data);
1933
+ }
1934
+ /**
1935
+ * Creates a new workspace.
1936
+ *
1937
+ * @param args - The arguments for creating the workspace.
1938
+ * @param requestId - Optional custom identifier for the request.
1939
+ * @returns A promise that resolves to the created workspace.
1940
+ */
1941
+ async addWorkspace(args, requestId) {
1942
+ const response = await request({
1943
+ httpMethod: 'POST',
1944
+ baseUri: this.syncApiBase,
1945
+ relativePath: ENDPOINT_REST_WORKSPACES,
1946
+ apiToken: this.authToken,
1947
+ customFetch: this.customFetch,
1948
+ payload: args,
1949
+ requestId: requestId,
1950
+ });
1951
+ return validateWorkspace(response.data);
1952
+ }
1953
+ /**
1954
+ * Updates an existing workspace.
1955
+ *
1956
+ * @param id - The unique identifier of the workspace to update.
1957
+ * @param args - The arguments for updating the workspace.
1958
+ * @param requestId - Optional custom identifier for the request.
1959
+ * @returns A promise that resolves to the updated workspace.
1960
+ */
1961
+ async updateWorkspace(id, args, requestId) {
1962
+ z.string().parse(id);
1963
+ const response = await request({
1964
+ httpMethod: 'POST',
1965
+ baseUri: this.syncApiBase,
1966
+ relativePath: generatePath(ENDPOINT_REST_WORKSPACES, id),
1967
+ apiToken: this.authToken,
1968
+ customFetch: this.customFetch,
1969
+ payload: args,
1970
+ requestId: requestId,
1971
+ });
1972
+ return validateWorkspace(response.data);
1973
+ }
1974
+ /**
1975
+ * Deletes a workspace by its ID.
1976
+ *
1977
+ * @param id - The unique identifier of the workspace to delete.
1978
+ * @param requestId - Optional custom identifier for the request.
1979
+ * @returns A promise that resolves to `true` if successful.
1980
+ */
1981
+ async deleteWorkspace(id, requestId) {
1982
+ z.string().parse(id);
1983
+ const response = await request({
1984
+ httpMethod: 'DELETE',
1985
+ baseUri: this.syncApiBase,
1986
+ relativePath: generatePath(ENDPOINT_REST_WORKSPACES, id),
1987
+ apiToken: this.authToken,
1988
+ customFetch: this.customFetch,
1989
+ requestId: requestId,
1990
+ });
1991
+ return isSuccess(response);
1548
1992
  }
1549
1993
  /**
1550
1994
  * Gets active projects in a workspace with pagination.
@@ -1571,10 +2015,10 @@ export class TodoistApi {
1571
2015
  payload: queryParams,
1572
2016
  requestId: requestId,
1573
2017
  });
1574
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
2018
+ // oxlint-disable-next-line no-unsafe-assignment, no-unsafe-call, no-unsafe-member-access
1575
2019
  const validatedProjects = (_a = response.data.results) === null || _a === void 0 ? void 0 : _a.map((project) => validateProject(project));
1576
2020
  return Object.assign(Object.assign({}, response.data), {
1577
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2021
+ // oxlint-disable-next-line no-unsafe-assignment
1578
2022
  results: validatedProjects || [] });
1579
2023
  }
1580
2024
  /**
@@ -1602,10 +2046,10 @@ export class TodoistApi {
1602
2046
  payload: queryParams,
1603
2047
  requestId: requestId,
1604
2048
  });
1605
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
2049
+ // oxlint-disable-next-line no-unsafe-assignment, no-unsafe-call, no-unsafe-member-access
1606
2050
  const validatedProjects = (_a = response.data.results) === null || _a === void 0 ? void 0 : _a.map((project) => validateProject(project));
1607
2051
  return Object.assign(Object.assign({}, response.data), {
1608
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2052
+ // oxlint-disable-next-line no-unsafe-assignment
1609
2053
  results: validatedProjects || [] });
1610
2054
  }
1611
2055
  }