@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
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __rest = (this && this.__rest) || function (s, e) {
36
3
  var t = {};
37
4
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -46,6 +13,7 @@ var __rest = (this && this.__rest) || function (s, e) {
46
13
  Object.defineProperty(exports, "__esModule", { value: true });
47
14
  exports.fetchWithRetry = fetchWithRetry;
48
15
  const http_1 = require("../types/http");
16
+ const http_dispatcher_1 = require("./http-dispatcher");
49
17
  /**
50
18
  * Default retry configuration matching the original axios-retry behavior
51
19
  */
@@ -58,32 +26,11 @@ const DEFAULT_RETRY_CONFIG = {
58
26
  return retryNumber === 1 ? 0 : 500;
59
27
  },
60
28
  };
61
- /**
62
- * Cached HTTP agent to prevent creating multiple agents
63
- * null = not initialized, undefined = browser env, UndiciAgent = Node.js env
64
- */
65
- let httpAgent = null;
66
- /**
67
- * Gets the HTTP agent for Node.js environments or undefined for browser environments.
68
- * Uses dynamic import to avoid loading undici in browser environments.
69
- */
70
- async function getHttpAgent() {
71
- var _a;
72
- if (httpAgent === null) {
73
- if (typeof process !== 'undefined' && ((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node)) {
74
- // We're in Node.js - dynamically import undici
75
- const { Agent } = await Promise.resolve().then(() => __importStar(require('undici')));
76
- httpAgent = new Agent({
77
- keepAliveTimeout: 1, // Close connections after 1ms of idle time
78
- keepAliveMaxTimeout: 1, // Maximum time to keep connections alive
79
- });
80
- }
81
- else {
82
- // We're in browser - no agent needed
83
- httpAgent = undefined;
84
- }
85
- }
86
- return httpAgent;
29
+ const TIMEOUT_ERROR_NAME = 'TimeoutError';
30
+ function createTimeoutError(timeoutMs) {
31
+ const error = new Error(`Request timeout after ${timeoutMs}ms`);
32
+ error.name = TIMEOUT_ERROR_NAME;
33
+ return error;
87
34
  }
88
35
  /**
89
36
  * Converts Headers object to a plain object
@@ -103,10 +50,14 @@ function createTimeoutSignal(timeoutMs, existingSignal) {
103
50
  const controller = new AbortController();
104
51
  // Timeout logic
105
52
  const timeoutId = setTimeout(() => {
106
- controller.abort(new Error(`Request timeout after ${timeoutMs}ms`));
53
+ controller.abort(createTimeoutError(timeoutMs));
107
54
  }, timeoutMs);
55
+ let abortHandler;
108
56
  function clear() {
109
57
  clearTimeout(timeoutId);
58
+ if (existingSignal && abortHandler) {
59
+ existingSignal.removeEventListener('abort', abortHandler);
60
+ }
110
61
  }
111
62
  // If there's an existing signal, forward its abort
112
63
  if (existingSignal) {
@@ -115,10 +66,11 @@ function createTimeoutSignal(timeoutMs, existingSignal) {
115
66
  controller.abort(existingSignal.reason);
116
67
  }
117
68
  else {
118
- existingSignal.addEventListener('abort', () => {
69
+ abortHandler = () => {
119
70
  clearTimeout(timeoutId);
120
71
  controller.abort(existingSignal.reason);
121
- }, { once: true });
72
+ };
73
+ existingSignal.addEventListener('abort', abortHandler, { once: true });
122
74
  }
123
75
  }
124
76
  // Clean up timeout when request completes
@@ -167,9 +119,13 @@ async function fetchWithRetry(args) {
167
119
  fetchResponse = await customFetch(url, Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal, timeout }));
168
120
  }
169
121
  else {
170
- const nativeResponse = await fetch(url, Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal,
122
+ const dispatcher = await (0, http_dispatcher_1.getDefaultDispatcher)();
123
+ const nativeFetchOptions = Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal });
124
+ if (dispatcher !== undefined) {
171
125
  // @ts-expect-error - dispatcher is a valid option for Node.js fetch but not in the TS types
172
- dispatcher: await getHttpAgent() }));
126
+ nativeFetchOptions.dispatcher = dispatcher;
127
+ }
128
+ const nativeResponse = await fetch(url, nativeFetchOptions);
173
129
  fetchResponse = convertResponseToCustomFetch(nativeResponse);
174
130
  }
175
131
  // Check if the response is successful
@@ -224,6 +180,9 @@ async function fetchWithRetry(args) {
224
180
  };
225
181
  }
226
182
  catch (error) {
183
+ if (clearTimeoutFn) {
184
+ clearTimeoutFn();
185
+ }
227
186
  lastError = error;
228
187
  // Check if this error should trigger a retry
229
188
  const shouldRetry = attempt < config.retries && config.retryCondition(lastError);
@@ -233,9 +192,6 @@ async function fetchWithRetry(args) {
233
192
  const networkError = lastError;
234
193
  networkError.isNetworkError = true;
235
194
  }
236
- if (clearTimeoutFn) {
237
- clearTimeoutFn();
238
- }
239
195
  throw lastError;
240
196
  }
241
197
  // Wait before retrying
@@ -243,10 +199,6 @@ async function fetchWithRetry(args) {
243
199
  if (delay > 0) {
244
200
  await new Promise((resolve) => setTimeout(resolve, delay));
245
201
  }
246
- // Retry path – ensure this attempt's timeout is cleared before looping
247
- if (clearTimeoutFn) {
248
- clearTimeoutFn();
249
- }
250
202
  }
251
203
  }
252
204
  // This should never be reached, but just in case
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.paramsSerializer = paramsSerializer;
4
4
  exports.isSuccess = isSuccess;
5
5
  exports.request = request;
6
- const errors_1 = require("./types/errors");
7
- const http_1 = require("./types/http");
8
6
  const uuid_1 = require("uuid");
9
- const endpoints_1 = require("./consts/endpoints");
10
- const case_conversion_1 = require("./utils/case-conversion");
11
- const fetch_with_retry_1 = require("./utils/fetch-with-retry");
7
+ const endpoints_1 = require("../consts/endpoints");
8
+ const errors_1 = require("../types/errors");
9
+ const http_1 = require("../types/http");
10
+ const case_conversion_1 = require("../utils/case-conversion");
11
+ const fetch_with_retry_1 = require("./fetch-with-retry");
12
12
  function paramsSerializer(params) {
13
13
  const qs = new URLSearchParams();
14
14
  Object.keys(params).forEach((key) => {
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getDefaultDispatcher = getDefaultDispatcher;
37
+ exports.resetDefaultDispatcherForTests = resetDefaultDispatcherForTests;
38
+ // Use effectively-disabled keep-alive so short-lived CLI processes do not stay
39
+ // open waiting on idle sockets. Undici requires positive values, so we use 1ms.
40
+ const KEEP_ALIVE_OPTIONS = {
41
+ keepAliveTimeout: 1,
42
+ keepAliveMaxTimeout: 1,
43
+ };
44
+ let defaultDispatcherPromise;
45
+ function getDefaultDispatcher() {
46
+ if (!isNodeEnvironment()) {
47
+ return Promise.resolve(undefined);
48
+ }
49
+ if (!defaultDispatcherPromise) {
50
+ defaultDispatcherPromise = createDefaultDispatcher().catch((error) => {
51
+ defaultDispatcherPromise = undefined;
52
+ throw error;
53
+ });
54
+ }
55
+ return defaultDispatcherPromise;
56
+ }
57
+ async function resetDefaultDispatcherForTests() {
58
+ if (!defaultDispatcherPromise) {
59
+ return;
60
+ }
61
+ const dispatcherPromise = defaultDispatcherPromise;
62
+ defaultDispatcherPromise = undefined;
63
+ await dispatcherPromise.then((dispatcher) => dispatcher.close(), () => undefined);
64
+ }
65
+ async function createDefaultDispatcher() {
66
+ const { EnvHttpProxyAgent } = await Promise.resolve().then(() => __importStar(require('undici')));
67
+ return new EnvHttpProxyAgent(KEEP_ALIVE_OPTIONS);
68
+ }
69
+ function isNodeEnvironment() {
70
+ var _a;
71
+ return typeof process !== 'undefined' && Boolean((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
72
+ }
@@ -11,7 +11,8 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  return t;
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.WorkspaceSchema = exports.WorkspacePropertiesSchema = exports.WorkspaceLimitsSchema = exports.WorkspacePlanSchema = exports.WORKSPACE_PLANS = exports.JoinWorkspaceResultSchema = exports.WorkspacePlanDetailsSchema = exports.WORKSPACE_PLAN_STATUSES = exports.WORKSPACE_CURRENT_PLANS = exports.FormattedPriceListingSchema = exports.PlanPriceSchema = exports.WorkspaceInvitationSchema = exports.WorkspaceUserSchema = exports.WorkspaceRoleSchema = exports.WORKSPACE_ROLES = exports.ActivityEventSchema = exports.ActivityEventExtraDataSchema = exports.ColorSchema = exports.ProductivityStatsSchema = exports.KarmaUpdateSchema = exports.ItemsWithDateSchema = exports.CompletedItemSchema = exports.StreakSchema = exports.CurrentUserSchema = exports.PREMIUM_STATUSES = exports.TimezoneInfoSchema = exports.UserSchema = exports.CommentSchema = exports.RawCommentSchema = exports.AttachmentSchema = exports.UPLOAD_STATES = exports.LabelSchema = exports.SectionSchema = exports.PROJECT_VIEW_STYLES = exports.WorkspaceProjectSchema = exports.ProjectVisibilitySchema = exports.PROJECT_VISIBILITIES = exports.PersonalProjectSchema = exports.BaseProjectSchema = exports.TaskSchema = exports.DeadlineSchema = exports.DurationSchema = exports.DURATION_UNITS = exports.DueDateSchema = void 0;
14
+ exports.ProjectActivityStatsSchema = exports.WeekRollupSchema = exports.DayActivitySchema = exports.WorkspaceUserTaskSchema = exports.MemberActivityInfoSchema = exports.WorkspaceSchema = exports.WorkspacePropertiesSchema = exports.WorkspaceLimitsSchema = exports.WorkspacePlanSchema = exports.WORKSPACE_PLANS = exports.JoinWorkspaceResultSchema = exports.WorkspacePlanDetailsSchema = exports.WORKSPACE_PLAN_STATUSES = exports.WORKSPACE_CURRENT_PLANS = exports.FormattedPriceListingSchema = exports.PlanPriceSchema = exports.WorkspaceInvitationSchema = exports.WorkspaceUserSchema = exports.WorkspaceRoleSchema = exports.WORKSPACE_ROLES = exports.COLLABORATOR_ROLES = exports.ActivityEventSchema = exports.ActivityEventExtraDataSchema = exports.ColorSchema = exports.ProductivityStatsSchema = exports.KarmaUpdateSchema = exports.ItemsWithDateSchema = exports.CompletedItemSchema = exports.StreakSchema = exports.CurrentUserSchema = exports.PREMIUM_STATUSES = exports.TimezoneInfoSchema = exports.UserSchema = exports.CommentSchema = exports.RawCommentSchema = exports.AttachmentSchema = exports.UPLOAD_STATES = exports.LabelSchema = exports.SectionSchema = exports.PROJECT_VIEW_STYLES = exports.WorkspaceProjectSchema = exports.ProjectVisibilitySchema = exports.PROJECT_VISIBILITIES = exports.PersonalProjectSchema = exports.BaseProjectSchema = exports.TaskSchema = exports.DeadlineSchema = exports.DurationSchema = exports.DURATION_UNITS = exports.DueDateSchema = void 0;
15
+ exports.MovedIdSchema = exports.IdMappingSchema = exports.BackupSchema = exports.WorkspaceInsightsSchema = exports.ProjectInsightSchema = exports.ProjectProgressSchema = exports.ProjectHealthContextSchema = exports.TaskContextSchema = exports.ProjectMetricsSchema = exports.ProjectHealthSchema = exports.TaskRecommendationSchema = exports.HEALTH_STATUSES = void 0;
15
16
  const zod_1 = require("zod");
16
17
  const url_helpers_1 = require("../utils/url-helpers");
17
18
  const uncompletable_helpers_1 = require("../utils/uncompletable-helpers");
@@ -322,6 +323,14 @@ exports.ActivityEventSchema = zod_1.z
322
323
  extraData: exports.ActivityEventExtraDataSchema,
323
324
  })
324
325
  .catchall(zod_1.z.any());
326
+ /** Available project collaborator roles. */
327
+ exports.COLLABORATOR_ROLES = [
328
+ 'CREATOR',
329
+ 'ADMIN',
330
+ 'READ_WRITE',
331
+ 'EDIT_ONLY',
332
+ 'COMPLETE_ONLY',
333
+ ];
325
334
  /**
326
335
  * Available workspace roles.
327
336
  */
@@ -427,3 +436,117 @@ exports.WorkspaceSchema = zod_1.z.object({
427
436
  creatorId: zod_1.z.string(),
428
437
  properties: exports.WorkspacePropertiesSchema,
429
438
  });
439
+ exports.MemberActivityInfoSchema = zod_1.z.object({
440
+ userId: zod_1.z.string(),
441
+ tasksAssigned: zod_1.z.number().int(),
442
+ tasksOverdue: zod_1.z.number().int(),
443
+ });
444
+ exports.WorkspaceUserTaskSchema = zod_1.z.object({
445
+ id: zod_1.z.string(),
446
+ content: zod_1.z.string(),
447
+ responsibleUid: zod_1.z.string().nullable(),
448
+ due: exports.DueDateSchema.nullable(),
449
+ deadline: exports.DeadlineSchema.nullable(),
450
+ labels: zod_1.z.array(zod_1.z.string()),
451
+ notesCount: zod_1.z.number().int(),
452
+ projectId: zod_1.z.string(),
453
+ projectName: zod_1.z.string(),
454
+ priority: zod_1.z.number().int(),
455
+ description: zod_1.z.string(),
456
+ isOverdue: zod_1.z.boolean(),
457
+ });
458
+ // Insights entities
459
+ exports.DayActivitySchema = zod_1.z.object({
460
+ date: zod_1.z.string(),
461
+ totalCount: zod_1.z.number().int(),
462
+ });
463
+ exports.WeekRollupSchema = zod_1.z.object({
464
+ fromDate: zod_1.z.string(),
465
+ toDate: zod_1.z.string(),
466
+ totalCount: zod_1.z.number().int(),
467
+ });
468
+ exports.ProjectActivityStatsSchema = zod_1.z.object({
469
+ dayItems: zod_1.z.array(exports.DayActivitySchema),
470
+ weekItems: zod_1.z.array(exports.WeekRollupSchema).nullable(),
471
+ });
472
+ /** Available project health statuses. */
473
+ exports.HEALTH_STATUSES = [
474
+ 'UNKNOWN',
475
+ 'ON_TRACK',
476
+ 'AT_RISK',
477
+ 'CRITICAL',
478
+ 'EXCELLENT',
479
+ 'ERROR',
480
+ ];
481
+ exports.TaskRecommendationSchema = zod_1.z.object({
482
+ taskId: zod_1.z.string(),
483
+ recommendation: zod_1.z.string(),
484
+ });
485
+ exports.ProjectHealthSchema = zod_1.z.object({
486
+ status: zod_1.z.enum(exports.HEALTH_STATUSES),
487
+ description: zod_1.z.string().nullable().optional(),
488
+ descriptionSummary: zod_1.z.string().nullable().optional(),
489
+ taskRecommendations: zod_1.z.array(exports.TaskRecommendationSchema).nullable().optional(),
490
+ projectId: zod_1.z.string().nullable().optional(),
491
+ updatedAt: zod_1.z.string().nullable().optional(),
492
+ isStale: zod_1.z.boolean().default(false),
493
+ updateInProgress: zod_1.z.boolean().default(false),
494
+ });
495
+ exports.ProjectMetricsSchema = zod_1.z.object({
496
+ totalTasks: zod_1.z.number().int(),
497
+ completedTasks: zod_1.z.number().int(),
498
+ overdueTasks: zod_1.z.number().int(),
499
+ tasksCreatedThisWeek: zod_1.z.number().int(),
500
+ tasksCompletedThisWeek: zod_1.z.number().int(),
501
+ averageCompletionTime: zod_1.z.number().nullable(),
502
+ });
503
+ exports.TaskContextSchema = zod_1.z.object({
504
+ id: zod_1.z.string(),
505
+ content: zod_1.z.string(),
506
+ due: zod_1.z.string().nullable().optional(),
507
+ deadline: zod_1.z.string().nullable().optional(),
508
+ priority: zod_1.z.string(),
509
+ isCompleted: zod_1.z.boolean(),
510
+ createdAt: zod_1.z.string(),
511
+ updatedAt: zod_1.z.string(),
512
+ completedAt: zod_1.z.string().nullable(),
513
+ completedByUid: zod_1.z.string().nullable(),
514
+ labels: zod_1.z.array(zod_1.z.string()),
515
+ });
516
+ exports.ProjectHealthContextSchema = zod_1.z.object({
517
+ projectId: zod_1.z.string(),
518
+ projectName: zod_1.z.string(),
519
+ projectDescription: zod_1.z.string().nullable(),
520
+ projectMetrics: exports.ProjectMetricsSchema,
521
+ tasks: zod_1.z.array(exports.TaskContextSchema),
522
+ language: zod_1.z.string().nullable().optional(),
523
+ });
524
+ exports.ProjectProgressSchema = zod_1.z.object({
525
+ projectId: zod_1.z.string(),
526
+ completedCount: zod_1.z.number().int(),
527
+ activeCount: zod_1.z.number().int(),
528
+ progressPercent: zod_1.z.number().int(),
529
+ });
530
+ exports.ProjectInsightSchema = zod_1.z.object({
531
+ projectId: zod_1.z.string(),
532
+ health: exports.ProjectHealthSchema.nullable(),
533
+ progress: exports.ProjectProgressSchema.nullable(),
534
+ });
535
+ exports.WorkspaceInsightsSchema = zod_1.z.object({
536
+ folderId: zod_1.z.string().nullable(),
537
+ projectInsights: zod_1.z.array(exports.ProjectInsightSchema),
538
+ });
539
+ // Backups
540
+ exports.BackupSchema = zod_1.z.object({
541
+ version: zod_1.z.string(),
542
+ url: zod_1.z.string(),
543
+ });
544
+ // ID Mappings
545
+ exports.IdMappingSchema = zod_1.z.object({
546
+ oldId: zod_1.z.string().nullable(),
547
+ newId: zod_1.z.string().nullable(),
548
+ });
549
+ exports.MovedIdSchema = zod_1.z.object({
550
+ oldId: zod_1.z.string(),
551
+ newId: zod_1.z.string(),
552
+ });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TodoistRequestError = void 0;
3
+ exports.TodoistArgumentError = exports.TodoistRequestError = void 0;
4
4
  const ts_custom_error_1 = require("ts-custom-error");
5
5
  const authenticationErrorCodes = [401, 403];
6
6
  class TodoistRequestError extends ts_custom_error_1.CustomError {
@@ -19,3 +19,11 @@ class TodoistRequestError extends ts_custom_error_1.CustomError {
19
19
  }
20
20
  }
21
21
  exports.TodoistRequestError = TodoistRequestError;
22
+ class TodoistArgumentError extends ts_custom_error_1.CustomError {
23
+ constructor(message) {
24
+ super(message);
25
+ this.message = message;
26
+ Object.defineProperty(this, 'name', { value: 'TodoistArgumentError' });
27
+ }
28
+ }
29
+ exports.TodoistArgumentError = TodoistArgumentError;
@@ -6,12 +6,14 @@ exports.isHttpError = isHttpError;
6
6
  * Type guard to check if an error is a network error
7
7
  */
8
8
  function isNetworkError(error) {
9
- // Network errors in fetch are typically TypeError with specific messages
9
+ // Network errors in fetch are typically TypeError with specific messages.
10
+ // Timeout errors are created by fetch-with-retry with the TimeoutError name.
10
11
  return ((error instanceof TypeError &&
11
12
  (error.message.includes('fetch') ||
12
13
  error.message.includes('network') ||
13
14
  error.message.includes('Failed to fetch') ||
14
15
  error.message.includes('NetworkError'))) ||
16
+ error.name === 'TimeoutError' ||
15
17
  error.isNetworkError === true);
16
18
  }
17
19
  /**
@@ -1,2 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MOVED_ID_OBJECT_TYPES = exports.ID_MAPPING_OBJECT_TYPES = exports.EMAIL_OBJECT_TYPES = exports.REMINDER_DELIVERY_SERVICES = void 0;
4
+ /** Available reminder delivery services. */
5
+ exports.REMINDER_DELIVERY_SERVICES = ['email', 'push'];
6
+ // Email forwarding types
7
+ /** Object types that support email forwarding. */
8
+ exports.EMAIL_OBJECT_TYPES = ['project', 'project_comments', 'task'];
9
+ // ID mapping types
10
+ /** Object types that support ID mappings. */
11
+ exports.ID_MAPPING_OBJECT_TYPES = [
12
+ 'sections',
13
+ 'tasks',
14
+ 'comments',
15
+ 'reminders',
16
+ 'location_reminders',
17
+ 'projects',
18
+ ];
19
+ /** Object types that support moved ID lookups. */
20
+ exports.MOVED_ID_OBJECT_TYPES = [
21
+ 'sections',
22
+ 'tasks',
23
+ 'comments',
24
+ 'reminders',
25
+ 'location_reminders',
26
+ ];
@@ -12,14 +12,8 @@ exports.PROJECT_STATUSES = [
12
12
  'COMPLETED',
13
13
  'CANCELED',
14
14
  ];
15
- /** Available default collaborator roles. */
16
- exports.COLLABORATOR_ROLES = [
17
- 'CREATOR',
18
- 'ADMIN',
19
- 'READ_WRITE',
20
- 'EDIT_ONLY',
21
- 'COMPLETE_ONLY',
22
- ];
15
+ var entities_1 = require("../../entities");
16
+ Object.defineProperty(exports, "COLLABORATOR_ROLES", { enumerable: true, get: function () { return entities_1.COLLABORATOR_ROLES; } });
23
17
  /** Available reminder notification services. */
24
18
  exports.REMINDER_SERVICES = ['default', 'email', 'mobile', 'push', 'no_default'];
25
19
  /** Available workspace project sort orders. */
@@ -23,11 +23,13 @@ exports.LocationReminderSchema = exports.ReminderBaseSchema.extend({
23
23
  exports.AbsoluteReminderSchema = exports.ReminderBaseSchema.extend({
24
24
  type: zod_1.z.literal('absolute'),
25
25
  due: entities_1.DueDateSchema,
26
+ isUrgent: zod_1.z.boolean().optional(),
26
27
  }).passthrough();
27
28
  exports.RelativeReminderSchema = exports.ReminderBaseSchema.extend({
28
29
  type: zod_1.z.literal('relative'),
29
30
  minuteOffset: zod_1.z.number().int(),
30
31
  due: entities_1.DueDateSchema.optional(),
32
+ isUrgent: zod_1.z.boolean().optional(),
31
33
  }).passthrough();
32
34
  exports.ReminderSchema = zod_1.z.discriminatedUnion('type', [
33
35
  exports.LocationReminderSchema,
@@ -34,7 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.uploadMultipartFile = uploadMultipartFile;
37
- const fetch_with_retry_1 = require("./fetch-with-retry");
37
+ const fetch_with_retry_1 = require("../transport/fetch-with-retry");
38
38
  /**
39
39
  * Helper function to determine content-type from filename extension.
40
40
  * @param fileName - The filename to analyze
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateUserPlanLimits = exports.validateProjectViewOptionsDefaultsArray = exports.validateProjectViewOptionsDefaults = exports.validateViewOptionsArray = exports.validateViewOptions = exports.validateCompletedInfoArray = exports.validateCompletedInfo = exports.validateReminderArray = exports.validateReminder = exports.validateCalendarAccountArray = exports.validateCalendarAccount = exports.validateCalendarArray = exports.validateCalendar = exports.validateWorkspaceGoalArray = exports.validateWorkspaceGoal = exports.validateWorkspaceFilterArray = exports.validateWorkspaceFilter = exports.validateTooltips = exports.validateNoteArray = exports.validateNote = exports.validateFolderArray = exports.validateFolder = exports.validateCollaboratorStateArray = exports.validateCollaboratorState = exports.validateCollaboratorArray = exports.validateCollaborator = exports.validateFilterArray = exports.validateFilter = exports.validateWorkspaceArray = exports.validateWorkspace = exports.validateJoinWorkspaceResult = exports.validateWorkspacePlanDetails = exports.validateWorkspaceInvitationArray = exports.validateWorkspaceInvitation = exports.validateWorkspaceUser = exports.validateAttachment = exports.validateActivityEventArray = exports.validateActivityEvent = exports.validateCurrentUser = exports.validateProductivityStats = exports.validateUserArray = exports.validateUser = exports.validateCommentArray = exports.validateComment = exports.validateLabelArray = exports.validateLabel = exports.validateSectionArray = exports.validateSection = exports.validateTaskArray = exports.validateTask = void 0;
4
- exports.validateSuggestionArray = exports.validateSuggestion = exports.validateUserSettings = exports.validateSyncUser = exports.validateSyncWorkspaceArray = exports.validateSyncWorkspace = exports.validateLiveNotificationArray = exports.validateLiveNotification = void 0;
3
+ exports.validateWorkspaceFilterArray = exports.validateWorkspaceFilter = exports.validateTooltips = exports.validateNoteArray = exports.validateNote = exports.validateFolderArray = exports.validateFolder = exports.validateCollaboratorStateArray = exports.validateCollaboratorState = exports.validateCollaboratorArray = exports.validateCollaborator = exports.validateFilterArray = exports.validateFilter = exports.validateMovedIdArray = exports.validateMovedId = exports.validateIdMappingArray = exports.validateIdMapping = exports.validateBackupArray = exports.validateBackup = exports.validateWorkspaceInsights = exports.validateProjectProgress = exports.validateProjectHealthContext = exports.validateProjectHealth = exports.validateProjectActivityStats = exports.validateWorkspaceUserTaskArray = exports.validateWorkspaceUserTask = exports.validateMemberActivityInfoArray = exports.validateMemberActivityInfo = exports.validateWorkspaceArray = exports.validateWorkspace = exports.validateJoinWorkspaceResult = exports.validateWorkspacePlanDetails = exports.validateWorkspaceInvitationArray = exports.validateWorkspaceInvitation = exports.validateWorkspaceUser = exports.validateAttachment = exports.validateActivityEventArray = exports.validateActivityEvent = exports.validateCurrentUser = exports.validateProductivityStats = exports.validateUserArray = exports.validateUser = exports.validateCommentArray = exports.validateComment = exports.validateLabelArray = exports.validateLabel = exports.validateSectionArray = exports.validateSection = exports.validateTaskArray = exports.validateTask = void 0;
4
+ exports.validateSuggestionArray = exports.validateSuggestion = exports.validateUserSettings = exports.validateSyncUser = exports.validateSyncWorkspaceArray = exports.validateSyncWorkspace = exports.validateLiveNotificationArray = exports.validateLiveNotification = exports.validateUserPlanLimits = exports.validateProjectViewOptionsDefaultsArray = exports.validateProjectViewOptionsDefaults = exports.validateViewOptionsArray = exports.validateViewOptions = exports.validateCompletedInfoArray = exports.validateCompletedInfo = exports.validateLocationReminderArray = exports.validateLocationReminder = exports.validateReminderArray = exports.validateReminder = exports.validateCalendarAccountArray = exports.validateCalendarAccount = exports.validateCalendarArray = exports.validateCalendar = exports.validateWorkspaceGoalArray = exports.validateWorkspaceGoal = void 0;
5
5
  exports.isWorkspaceProject = isWorkspaceProject;
6
6
  exports.isPersonalProject = isPersonalProject;
7
7
  exports.validateProject = validateProject;
@@ -74,6 +74,21 @@ exports.validateWorkspacePlanDetails = createValidator(entities_1.WorkspacePlanD
74
74
  exports.validateJoinWorkspaceResult = createValidator(entities_1.JoinWorkspaceResultSchema);
75
75
  exports.validateWorkspace = createValidator(entities_1.WorkspaceSchema);
76
76
  exports.validateWorkspaceArray = createArrayValidator(exports.validateWorkspace);
77
+ exports.validateMemberActivityInfo = createValidator(entities_1.MemberActivityInfoSchema);
78
+ exports.validateMemberActivityInfoArray = createArrayValidator(exports.validateMemberActivityInfo);
79
+ exports.validateWorkspaceUserTask = createValidator(entities_1.WorkspaceUserTaskSchema);
80
+ exports.validateWorkspaceUserTaskArray = createArrayValidator(exports.validateWorkspaceUserTask);
81
+ exports.validateProjectActivityStats = createValidator(entities_1.ProjectActivityStatsSchema);
82
+ exports.validateProjectHealth = createValidator(entities_1.ProjectHealthSchema);
83
+ exports.validateProjectHealthContext = createValidator(entities_1.ProjectHealthContextSchema);
84
+ exports.validateProjectProgress = createValidator(entities_1.ProjectProgressSchema);
85
+ exports.validateWorkspaceInsights = createValidator(entities_1.WorkspaceInsightsSchema);
86
+ exports.validateBackup = createValidator(entities_1.BackupSchema);
87
+ exports.validateBackupArray = createArrayValidator(exports.validateBackup);
88
+ exports.validateIdMapping = createValidator(entities_1.IdMappingSchema);
89
+ exports.validateIdMappingArray = createArrayValidator(exports.validateIdMapping);
90
+ exports.validateMovedId = createValidator(entities_1.MovedIdSchema);
91
+ exports.validateMovedIdArray = createArrayValidator(exports.validateMovedId);
77
92
  // Sync resource validators
78
93
  exports.validateFilter = createValidator(resources_1.FilterSchema);
79
94
  exports.validateFilterArray = createArrayValidator(exports.validateFilter);
@@ -96,6 +111,8 @@ exports.validateCalendarAccount = createValidator(resources_1.CalendarAccountSch
96
111
  exports.validateCalendarAccountArray = createArrayValidator(exports.validateCalendarAccount);
97
112
  exports.validateReminder = createValidator(resources_1.ReminderSchema);
98
113
  exports.validateReminderArray = createArrayValidator(exports.validateReminder);
114
+ exports.validateLocationReminder = createValidator(resources_1.LocationReminderSchema);
115
+ exports.validateLocationReminderArray = createArrayValidator(exports.validateLocationReminder);
99
116
  exports.validateCompletedInfo = createValidator(resources_1.CompletedInfoSchema);
100
117
  exports.validateCompletedInfoArray = createArrayValidator(exports.validateCompletedInfo);
101
118
  exports.validateViewOptions = createValidator(resources_1.ViewOptionsSchema);
@@ -1,7 +1,7 @@
1
- import { request, isSuccess } from './rest-client.js';
1
+ import { request, isSuccess } from './transport/http-client.js';
2
2
  import { v4 as uuid } from 'uuid';
3
3
  import { TodoistRequestError } from './types/index.js';
4
- import { getAuthBaseUri, getSyncBaseUri, ENDPOINT_AUTHORIZATION, ENDPOINT_GET_TOKEN, ENDPOINT_REVOKE, } from './consts/endpoints.js';
4
+ import { getAuthBaseUri, getSyncBaseUri, ENDPOINT_AUTHORIZATION, ENDPOINT_GET_TOKEN, ENDPOINT_REVOKE, ENDPOINT_REST_ACCESS_TOKENS_MIGRATE, } from './consts/endpoints.js';
5
5
  /** Available OAuth2 permission scopes. */
6
6
  export const PERMISSIONS = [
7
7
  'task:add',
@@ -51,7 +51,7 @@ export function getAuthStateParameter() {
51
51
  * ```
52
52
  *
53
53
  * @returns The full authorization URL to redirect users to
54
- * @see https://todoist.com/api/v1/docs#tag/Authorization/OAuth
54
+ * @see https://developer.todoist.com/api/v1/#tag/Authorization/OAuth
55
55
  */
56
56
  export function getAuthorizationUrl({ clientId, permissions, state, baseUrl, }) {
57
57
  if (!(permissions === null || permissions === void 0 ? void 0 : permissions.length)) {
@@ -119,7 +119,7 @@ export async function getAuthToken(args, options) {
119
119
  *
120
120
  * @returns True if revocation was successful
121
121
  * @see https://datatracker.ietf.org/doc/html/rfc7009
122
- * @see https://todoist.com/api/v1/docs#tag/Authorization
122
+ * @see https://developer.todoist.com/api/v1/#tag/Authorization
123
123
  */
124
124
  export async function revokeToken(args, options) {
125
125
  if (typeof options === 'string') {
@@ -151,3 +151,46 @@ export async function revokeToken(args, options) {
151
151
  });
152
152
  return isSuccess(response);
153
153
  }
154
+ /**
155
+ * Migrates a personal API token to an OAuth access token.
156
+ *
157
+ * This allows applications to transition users from personal API tokens
158
+ * to proper OAuth tokens without requiring the user to go through the
159
+ * full OAuth authorization flow.
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const { accessToken } = await migratePersonalToken({
164
+ * clientId: 'your-client-id',
165
+ * clientSecret: 'your-client-secret',
166
+ * personalToken: 'user-personal-token',
167
+ * scope: 'data:read_write,data:delete'
168
+ * })
169
+ * ```
170
+ *
171
+ * @returns The new OAuth token response
172
+ * @throws {@link TodoistRequestError} If the migration fails
173
+ */
174
+ export async function migratePersonalToken(args, options) {
175
+ var _a;
176
+ const baseUrl = options === null || options === void 0 ? void 0 : options.baseUrl;
177
+ const customFetch = options === null || options === void 0 ? void 0 : options.customFetch;
178
+ try {
179
+ const response = await request({
180
+ httpMethod: 'POST',
181
+ baseUri: getSyncBaseUri(baseUrl),
182
+ relativePath: ENDPOINT_REST_ACCESS_TOKENS_MIGRATE,
183
+ apiToken: undefined,
184
+ payload: Object.assign(Object.assign({}, args), { scope: args.scope.join(',') }),
185
+ customFetch,
186
+ });
187
+ if (response.status !== 200 || !((_a = response.data) === null || _a === void 0 ? void 0 : _a.accessToken)) {
188
+ throw new TodoistRequestError('Personal token migration failed.', response.status, response.data);
189
+ }
190
+ return response.data;
191
+ }
192
+ catch (error) {
193
+ const err = error;
194
+ throw new TodoistRequestError('Personal token migration failed.', err.httpStatusCode, err.responseData);
195
+ }
196
+ }