@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
@@ -10,6 +10,7 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { isNetworkError } from '../types/http.js';
13
+ import { getDefaultDispatcher } from './http-dispatcher.js';
13
14
  /**
14
15
  * Default retry configuration matching the original axios-retry behavior
15
16
  */
@@ -22,32 +23,11 @@ const DEFAULT_RETRY_CONFIG = {
22
23
  return retryNumber === 1 ? 0 : 500;
23
24
  },
24
25
  };
25
- /**
26
- * Cached HTTP agent to prevent creating multiple agents
27
- * null = not initialized, undefined = browser env, UndiciAgent = Node.js env
28
- */
29
- let httpAgent = null;
30
- /**
31
- * Gets the HTTP agent for Node.js environments or undefined for browser environments.
32
- * Uses dynamic import to avoid loading undici in browser environments.
33
- */
34
- async function getHttpAgent() {
35
- var _a;
36
- if (httpAgent === null) {
37
- if (typeof process !== 'undefined' && ((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node)) {
38
- // We're in Node.js - dynamically import undici
39
- const { Agent } = await import('undici');
40
- httpAgent = new Agent({
41
- keepAliveTimeout: 1, // Close connections after 1ms of idle time
42
- keepAliveMaxTimeout: 1, // Maximum time to keep connections alive
43
- });
44
- }
45
- else {
46
- // We're in browser - no agent needed
47
- httpAgent = undefined;
48
- }
49
- }
50
- return httpAgent;
26
+ const TIMEOUT_ERROR_NAME = 'TimeoutError';
27
+ function createTimeoutError(timeoutMs) {
28
+ const error = new Error(`Request timeout after ${timeoutMs}ms`);
29
+ error.name = TIMEOUT_ERROR_NAME;
30
+ return error;
51
31
  }
52
32
  /**
53
33
  * Converts Headers object to a plain object
@@ -67,10 +47,14 @@ function createTimeoutSignal(timeoutMs, existingSignal) {
67
47
  const controller = new AbortController();
68
48
  // Timeout logic
69
49
  const timeoutId = setTimeout(() => {
70
- controller.abort(new Error(`Request timeout after ${timeoutMs}ms`));
50
+ controller.abort(createTimeoutError(timeoutMs));
71
51
  }, timeoutMs);
52
+ let abortHandler;
72
53
  function clear() {
73
54
  clearTimeout(timeoutId);
55
+ if (existingSignal && abortHandler) {
56
+ existingSignal.removeEventListener('abort', abortHandler);
57
+ }
74
58
  }
75
59
  // If there's an existing signal, forward its abort
76
60
  if (existingSignal) {
@@ -79,10 +63,11 @@ function createTimeoutSignal(timeoutMs, existingSignal) {
79
63
  controller.abort(existingSignal.reason);
80
64
  }
81
65
  else {
82
- existingSignal.addEventListener('abort', () => {
66
+ abortHandler = () => {
83
67
  clearTimeout(timeoutId);
84
68
  controller.abort(existingSignal.reason);
85
- }, { once: true });
69
+ };
70
+ existingSignal.addEventListener('abort', abortHandler, { once: true });
86
71
  }
87
72
  }
88
73
  // Clean up timeout when request completes
@@ -131,9 +116,13 @@ export async function fetchWithRetry(args) {
131
116
  fetchResponse = await customFetch(url, Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal, timeout }));
132
117
  }
133
118
  else {
134
- const nativeResponse = await fetch(url, Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal,
119
+ const dispatcher = await getDefaultDispatcher();
120
+ const nativeFetchOptions = Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal });
121
+ if (dispatcher !== undefined) {
135
122
  // @ts-expect-error - dispatcher is a valid option for Node.js fetch but not in the TS types
136
- dispatcher: await getHttpAgent() }));
123
+ nativeFetchOptions.dispatcher = dispatcher;
124
+ }
125
+ const nativeResponse = await fetch(url, nativeFetchOptions);
137
126
  fetchResponse = convertResponseToCustomFetch(nativeResponse);
138
127
  }
139
128
  // Check if the response is successful
@@ -188,6 +177,9 @@ export async function fetchWithRetry(args) {
188
177
  };
189
178
  }
190
179
  catch (error) {
180
+ if (clearTimeoutFn) {
181
+ clearTimeoutFn();
182
+ }
191
183
  lastError = error;
192
184
  // Check if this error should trigger a retry
193
185
  const shouldRetry = attempt < config.retries && config.retryCondition(lastError);
@@ -197,9 +189,6 @@ export async function fetchWithRetry(args) {
197
189
  const networkError = lastError;
198
190
  networkError.isNetworkError = true;
199
191
  }
200
- if (clearTimeoutFn) {
201
- clearTimeoutFn();
202
- }
203
192
  throw lastError;
204
193
  }
205
194
  // Wait before retrying
@@ -207,10 +196,6 @@ export async function fetchWithRetry(args) {
207
196
  if (delay > 0) {
208
197
  await new Promise((resolve) => setTimeout(resolve, delay));
209
198
  }
210
- // Retry path – ensure this attempt's timeout is cleared before looping
211
- if (clearTimeoutFn) {
212
- clearTimeoutFn();
213
- }
214
199
  }
215
200
  }
216
201
  // This should never be reached, but just in case
@@ -1,9 +1,9 @@
1
- import { TodoistRequestError } from './types/errors.js';
2
- import { isNetworkError, isHttpError } from './types/http.js';
3
1
  import { v4 as uuidv4 } from 'uuid';
4
- import { API_BASE_URI } from './consts/endpoints.js';
5
- import { camelCaseKeys, snakeCaseKeys } from './utils/case-conversion.js';
6
- import { fetchWithRetry } from './utils/fetch-with-retry.js';
2
+ import { API_BASE_URI } from '../consts/endpoints.js';
3
+ import { TodoistRequestError } from '../types/errors.js';
4
+ import { isHttpError, isNetworkError } from '../types/http.js';
5
+ import { camelCaseKeys, snakeCaseKeys } from '../utils/case-conversion.js';
6
+ import { fetchWithRetry } from './fetch-with-retry.js';
7
7
  export function paramsSerializer(params) {
8
8
  const qs = new URLSearchParams();
9
9
  Object.keys(params).forEach((key) => {
@@ -0,0 +1,35 @@
1
+ // Use effectively-disabled keep-alive so short-lived CLI processes do not stay
2
+ // open waiting on idle sockets. Undici requires positive values, so we use 1ms.
3
+ const KEEP_ALIVE_OPTIONS = {
4
+ keepAliveTimeout: 1,
5
+ keepAliveMaxTimeout: 1,
6
+ };
7
+ let defaultDispatcherPromise;
8
+ export function getDefaultDispatcher() {
9
+ if (!isNodeEnvironment()) {
10
+ return Promise.resolve(undefined);
11
+ }
12
+ if (!defaultDispatcherPromise) {
13
+ defaultDispatcherPromise = createDefaultDispatcher().catch((error) => {
14
+ defaultDispatcherPromise = undefined;
15
+ throw error;
16
+ });
17
+ }
18
+ return defaultDispatcherPromise;
19
+ }
20
+ export async function resetDefaultDispatcherForTests() {
21
+ if (!defaultDispatcherPromise) {
22
+ return;
23
+ }
24
+ const dispatcherPromise = defaultDispatcherPromise;
25
+ defaultDispatcherPromise = undefined;
26
+ await dispatcherPromise.then((dispatcher) => dispatcher.close(), () => undefined);
27
+ }
28
+ async function createDefaultDispatcher() {
29
+ const { EnvHttpProxyAgent } = await import('undici');
30
+ return new EnvHttpProxyAgent(KEEP_ALIVE_OPTIONS);
31
+ }
32
+ function isNodeEnvironment() {
33
+ var _a;
34
+ return typeof process !== 'undefined' && Boolean((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
35
+ }
@@ -319,6 +319,14 @@ export const ActivityEventSchema = z
319
319
  extraData: ActivityEventExtraDataSchema,
320
320
  })
321
321
  .catchall(z.any());
322
+ /** Available project collaborator roles. */
323
+ export const COLLABORATOR_ROLES = [
324
+ 'CREATOR',
325
+ 'ADMIN',
326
+ 'READ_WRITE',
327
+ 'EDIT_ONLY',
328
+ 'COMPLETE_ONLY',
329
+ ];
322
330
  /**
323
331
  * Available workspace roles.
324
332
  */
@@ -424,3 +432,117 @@ export const WorkspaceSchema = z.object({
424
432
  creatorId: z.string(),
425
433
  properties: WorkspacePropertiesSchema,
426
434
  });
435
+ export const MemberActivityInfoSchema = z.object({
436
+ userId: z.string(),
437
+ tasksAssigned: z.number().int(),
438
+ tasksOverdue: z.number().int(),
439
+ });
440
+ export const WorkspaceUserTaskSchema = z.object({
441
+ id: z.string(),
442
+ content: z.string(),
443
+ responsibleUid: z.string().nullable(),
444
+ due: DueDateSchema.nullable(),
445
+ deadline: DeadlineSchema.nullable(),
446
+ labels: z.array(z.string()),
447
+ notesCount: z.number().int(),
448
+ projectId: z.string(),
449
+ projectName: z.string(),
450
+ priority: z.number().int(),
451
+ description: z.string(),
452
+ isOverdue: z.boolean(),
453
+ });
454
+ // Insights entities
455
+ export const DayActivitySchema = z.object({
456
+ date: z.string(),
457
+ totalCount: z.number().int(),
458
+ });
459
+ export const WeekRollupSchema = z.object({
460
+ fromDate: z.string(),
461
+ toDate: z.string(),
462
+ totalCount: z.number().int(),
463
+ });
464
+ export const ProjectActivityStatsSchema = z.object({
465
+ dayItems: z.array(DayActivitySchema),
466
+ weekItems: z.array(WeekRollupSchema).nullable(),
467
+ });
468
+ /** Available project health statuses. */
469
+ export const HEALTH_STATUSES = [
470
+ 'UNKNOWN',
471
+ 'ON_TRACK',
472
+ 'AT_RISK',
473
+ 'CRITICAL',
474
+ 'EXCELLENT',
475
+ 'ERROR',
476
+ ];
477
+ export const TaskRecommendationSchema = z.object({
478
+ taskId: z.string(),
479
+ recommendation: z.string(),
480
+ });
481
+ export const ProjectHealthSchema = z.object({
482
+ status: z.enum(HEALTH_STATUSES),
483
+ description: z.string().nullable().optional(),
484
+ descriptionSummary: z.string().nullable().optional(),
485
+ taskRecommendations: z.array(TaskRecommendationSchema).nullable().optional(),
486
+ projectId: z.string().nullable().optional(),
487
+ updatedAt: z.string().nullable().optional(),
488
+ isStale: z.boolean().default(false),
489
+ updateInProgress: z.boolean().default(false),
490
+ });
491
+ export const ProjectMetricsSchema = z.object({
492
+ totalTasks: z.number().int(),
493
+ completedTasks: z.number().int(),
494
+ overdueTasks: z.number().int(),
495
+ tasksCreatedThisWeek: z.number().int(),
496
+ tasksCompletedThisWeek: z.number().int(),
497
+ averageCompletionTime: z.number().nullable(),
498
+ });
499
+ export const TaskContextSchema = z.object({
500
+ id: z.string(),
501
+ content: z.string(),
502
+ due: z.string().nullable().optional(),
503
+ deadline: z.string().nullable().optional(),
504
+ priority: z.string(),
505
+ isCompleted: z.boolean(),
506
+ createdAt: z.string(),
507
+ updatedAt: z.string(),
508
+ completedAt: z.string().nullable(),
509
+ completedByUid: z.string().nullable(),
510
+ labels: z.array(z.string()),
511
+ });
512
+ export const ProjectHealthContextSchema = z.object({
513
+ projectId: z.string(),
514
+ projectName: z.string(),
515
+ projectDescription: z.string().nullable(),
516
+ projectMetrics: ProjectMetricsSchema,
517
+ tasks: z.array(TaskContextSchema),
518
+ language: z.string().nullable().optional(),
519
+ });
520
+ export const ProjectProgressSchema = z.object({
521
+ projectId: z.string(),
522
+ completedCount: z.number().int(),
523
+ activeCount: z.number().int(),
524
+ progressPercent: z.number().int(),
525
+ });
526
+ export const ProjectInsightSchema = z.object({
527
+ projectId: z.string(),
528
+ health: ProjectHealthSchema.nullable(),
529
+ progress: ProjectProgressSchema.nullable(),
530
+ });
531
+ export const WorkspaceInsightsSchema = z.object({
532
+ folderId: z.string().nullable(),
533
+ projectInsights: z.array(ProjectInsightSchema),
534
+ });
535
+ // Backups
536
+ export const BackupSchema = z.object({
537
+ version: z.string(),
538
+ url: z.string(),
539
+ });
540
+ // ID Mappings
541
+ export const IdMappingSchema = z.object({
542
+ oldId: z.string().nullable(),
543
+ newId: z.string().nullable(),
544
+ });
545
+ export const MovedIdSchema = z.object({
546
+ oldId: z.string(),
547
+ newId: z.string(),
548
+ });
@@ -15,3 +15,10 @@ export class TodoistRequestError extends CustomError {
15
15
  Object.defineProperty(this, 'name', { value: 'TodoistRequestError' });
16
16
  }
17
17
  }
18
+ export class TodoistArgumentError extends CustomError {
19
+ constructor(message) {
20
+ super(message);
21
+ this.message = message;
22
+ Object.defineProperty(this, 'name', { value: 'TodoistArgumentError' });
23
+ }
24
+ }
@@ -2,12 +2,14 @@
2
2
  * Type guard to check if an error is a network error
3
3
  */
4
4
  export function isNetworkError(error) {
5
- // Network errors in fetch are typically TypeError with specific messages
5
+ // Network errors in fetch are typically TypeError with specific messages.
6
+ // Timeout errors are created by fetch-with-retry with the TimeoutError name.
6
7
  return ((error instanceof TypeError &&
7
8
  (error.message.includes('fetch') ||
8
9
  error.message.includes('network') ||
9
10
  error.message.includes('Failed to fetch') ||
10
11
  error.message.includes('NetworkError'))) ||
12
+ error.name === 'TimeoutError' ||
11
13
  error.isNetworkError === true);
12
14
  }
13
15
  /**
@@ -1 +1,23 @@
1
- export {};
1
+ /** Available reminder delivery services. */
2
+ export const REMINDER_DELIVERY_SERVICES = ['email', 'push'];
3
+ // Email forwarding types
4
+ /** Object types that support email forwarding. */
5
+ export const EMAIL_OBJECT_TYPES = ['project', 'project_comments', 'task'];
6
+ // ID mapping types
7
+ /** Object types that support ID mappings. */
8
+ export const ID_MAPPING_OBJECT_TYPES = [
9
+ 'sections',
10
+ 'tasks',
11
+ 'comments',
12
+ 'reminders',
13
+ 'location_reminders',
14
+ 'projects',
15
+ ];
16
+ /** Object types that support moved ID lookups. */
17
+ export const MOVED_ID_OBJECT_TYPES = [
18
+ 'sections',
19
+ 'tasks',
20
+ 'comments',
21
+ 'reminders',
22
+ 'location_reminders',
23
+ ];
@@ -9,14 +9,7 @@ export const PROJECT_STATUSES = [
9
9
  'COMPLETED',
10
10
  'CANCELED',
11
11
  ];
12
- /** Available default collaborator roles. */
13
- export const COLLABORATOR_ROLES = [
14
- 'CREATOR',
15
- 'ADMIN',
16
- 'READ_WRITE',
17
- 'EDIT_ONLY',
18
- 'COMPLETE_ONLY',
19
- ];
12
+ export { COLLABORATOR_ROLES } from '../../entities.js';
20
13
  /** Available reminder notification services. */
21
14
  export const REMINDER_SERVICES = ['default', 'email', 'mobile', 'push', 'no_default'];
22
15
  /** Available workspace project sort orders. */
@@ -20,11 +20,13 @@ export const LocationReminderSchema = ReminderBaseSchema.extend({
20
20
  export const AbsoluteReminderSchema = ReminderBaseSchema.extend({
21
21
  type: z.literal('absolute'),
22
22
  due: DueDateSchema,
23
+ isUrgent: z.boolean().optional(),
23
24
  }).passthrough();
24
25
  export const RelativeReminderSchema = ReminderBaseSchema.extend({
25
26
  type: z.literal('relative'),
26
27
  minuteOffset: z.number().int(),
27
28
  due: DueDateSchema.optional(),
29
+ isUrgent: z.boolean().optional(),
28
30
  }).passthrough();
29
31
  export const ReminderSchema = z.discriminatedUnion('type', [
30
32
  LocationReminderSchema,
@@ -1,4 +1,4 @@
1
- import { fetchWithRetry } from './fetch-with-retry.js';
1
+ import { fetchWithRetry } from '../transport/fetch-with-retry.js';
2
2
  /**
3
3
  * Helper function to determine content-type from filename extension.
4
4
  * @param fileName - The filename to analyze
@@ -1,5 +1,5 @@
1
- import { AttachmentSchema, SectionSchema, LabelSchema, CommentSchema, UserSchema, CurrentUserSchema, TaskSchema, PersonalProjectSchema, WorkspaceProjectSchema, ProductivityStatsSchema, ActivityEventSchema, WorkspaceUserSchema, WorkspaceInvitationSchema, WorkspacePlanDetailsSchema, JoinWorkspaceResultSchema, WorkspaceSchema, } from '../types/entities.js';
2
- import { FilterSchema, CollaboratorSchema, CollaboratorStateSchema, FolderSchema, NoteSchema, TooltipsSchema, WorkspaceFilterSchema, WorkspaceGoalSchema, CalendarSchema, CalendarAccountSchema, ReminderSchema, CompletedInfoSchema, ViewOptionsSchema, ProjectViewOptionsDefaultsSchema, UserPlanLimitsSchema, LiveNotificationSchema, SyncWorkspaceSchema, SyncUserSchema, UserSettingsSchema, SuggestionSchema, } from '../types/sync/resources/index.js';
1
+ import { AttachmentSchema, SectionSchema, LabelSchema, CommentSchema, UserSchema, CurrentUserSchema, TaskSchema, PersonalProjectSchema, WorkspaceProjectSchema, ProductivityStatsSchema, ActivityEventSchema, WorkspaceUserSchema, WorkspaceInvitationSchema, WorkspacePlanDetailsSchema, JoinWorkspaceResultSchema, WorkspaceSchema, MemberActivityInfoSchema, WorkspaceUserTaskSchema, ProjectActivityStatsSchema, ProjectHealthSchema, ProjectHealthContextSchema, ProjectProgressSchema, WorkspaceInsightsSchema, BackupSchema, IdMappingSchema, MovedIdSchema, } from '../types/entities.js';
2
+ import { FilterSchema, CollaboratorSchema, CollaboratorStateSchema, FolderSchema, NoteSchema, TooltipsSchema, WorkspaceFilterSchema, WorkspaceGoalSchema, CalendarSchema, CalendarAccountSchema, ReminderSchema, LocationReminderSchema, CompletedInfoSchema, ViewOptionsSchema, ProjectViewOptionsDefaultsSchema, UserPlanLimitsSchema, LiveNotificationSchema, SyncWorkspaceSchema, SyncUserSchema, UserSettingsSchema, SuggestionSchema, } from '../types/sync/resources/index.js';
3
3
  function createValidator(schema) {
4
4
  return (input) => schema.parse(input);
5
5
  }
@@ -65,6 +65,21 @@ export const validateWorkspacePlanDetails = createValidator(WorkspacePlanDetails
65
65
  export const validateJoinWorkspaceResult = createValidator(JoinWorkspaceResultSchema);
66
66
  export const validateWorkspace = createValidator(WorkspaceSchema);
67
67
  export const validateWorkspaceArray = createArrayValidator(validateWorkspace);
68
+ export const validateMemberActivityInfo = createValidator(MemberActivityInfoSchema);
69
+ export const validateMemberActivityInfoArray = createArrayValidator(validateMemberActivityInfo);
70
+ export const validateWorkspaceUserTask = createValidator(WorkspaceUserTaskSchema);
71
+ export const validateWorkspaceUserTaskArray = createArrayValidator(validateWorkspaceUserTask);
72
+ export const validateProjectActivityStats = createValidator(ProjectActivityStatsSchema);
73
+ export const validateProjectHealth = createValidator(ProjectHealthSchema);
74
+ export const validateProjectHealthContext = createValidator(ProjectHealthContextSchema);
75
+ export const validateProjectProgress = createValidator(ProjectProgressSchema);
76
+ export const validateWorkspaceInsights = createValidator(WorkspaceInsightsSchema);
77
+ export const validateBackup = createValidator(BackupSchema);
78
+ export const validateBackupArray = createArrayValidator(validateBackup);
79
+ export const validateIdMapping = createValidator(IdMappingSchema);
80
+ export const validateIdMappingArray = createArrayValidator(validateIdMapping);
81
+ export const validateMovedId = createValidator(MovedIdSchema);
82
+ export const validateMovedIdArray = createArrayValidator(validateMovedId);
68
83
  // Sync resource validators
69
84
  export const validateFilter = createValidator(FilterSchema);
70
85
  export const validateFilterArray = createArrayValidator(validateFilter);
@@ -87,6 +102,8 @@ export const validateCalendarAccount = createValidator(CalendarAccountSchema);
87
102
  export const validateCalendarAccountArray = createArrayValidator(validateCalendarAccount);
88
103
  export const validateReminder = createValidator(ReminderSchema);
89
104
  export const validateReminderArray = createArrayValidator(validateReminder);
105
+ export const validateLocationReminder = createValidator(LocationReminderSchema);
106
+ export const validateLocationReminderArray = createArrayValidator(validateLocationReminder);
90
107
  export const validateCompletedInfo = createValidator(CompletedInfoSchema);
91
108
  export const validateCompletedInfoArray = createArrayValidator(validateCompletedInfo);
92
109
  export const validateViewOptions = createValidator(ViewOptionsSchema);
@@ -10,12 +10,12 @@ export type AuthOptions = {
10
10
  export declare const PERMISSIONS: readonly ["task:add", "data:read", "data:read_write", "data:delete", "project:delete", "backups:read"];
11
11
  /**
12
12
  * Permission scope that can be requested during OAuth2 authorization.
13
- * @see {@link https://todoist.com/api/v1/docs#tag/Authorization}
13
+ * @see {@link https://developer.todoist.com/api/v1/#tag/Authorization}
14
14
  */
15
15
  export type Permission = (typeof PERMISSIONS)[number];
16
16
  /**
17
17
  * Parameters required to exchange an authorization code for an access token.
18
- * @see https://todoist.com/api/v1/docs#tag/Authorization/OAuth
18
+ * @see https://developer.todoist.com/api/v1/#tag/Authorization/OAuth
19
19
  */
20
20
  export type AuthTokenRequestArgs = {
21
21
  clientId: string;
@@ -24,7 +24,7 @@ export type AuthTokenRequestArgs = {
24
24
  };
25
25
  /**
26
26
  * Response from a successful OAuth2 token exchange.
27
- * @see https://todoist.com/api/v1/docs#tag/Authorization/OAuth
27
+ * @see https://developer.todoist.com/api/v1/#tag/Authorization/OAuth
28
28
  */
29
29
  export type AuthTokenResponse = {
30
30
  accessToken: string;
@@ -32,13 +32,37 @@ export type AuthTokenResponse = {
32
32
  };
33
33
  /**
34
34
  * Parameters required to revoke a token using RFC 7009 compliant endpoint.
35
- * @see https://todoist.com/api/v1/docs#tag/Authorization
35
+ * @see https://developer.todoist.com/api/v1/#tag/Authorization
36
36
  */
37
37
  export type RevokeTokenRequestArgs = {
38
38
  clientId: string;
39
39
  clientSecret: string;
40
40
  token: string;
41
41
  };
42
+ /**
43
+ * Parameters required to migrate a personal API token to an OAuth token.
44
+ */
45
+ export type MigratePersonalTokenArgs = {
46
+ /** The unique Client ID of the registered Todoist application. */
47
+ clientId: string;
48
+ /** The unique Client Secret of the registered Todoist application. */
49
+ clientSecret: string;
50
+ /** The personal API token obtained from email/password authentication. */
51
+ personalToken: string;
52
+ /** Scopes for the new OAuth token. */
53
+ scope: readonly Permission[];
54
+ };
55
+ /**
56
+ * Response from a successful personal token migration.
57
+ */
58
+ export type MigratePersonalTokenResponse = {
59
+ /** The new OAuth access token, or null if migration failed. */
60
+ accessToken: string | null;
61
+ /** The token type (always 'Bearer'). */
62
+ tokenType: string;
63
+ /** Token expiration time in seconds. */
64
+ expiresIn: number;
65
+ };
42
66
  /**
43
67
  * Generates a random state parameter for OAuth2 authorization.
44
68
  * The state parameter helps prevent CSRF attacks.
@@ -67,7 +91,7 @@ export declare function getAuthStateParameter(): string;
67
91
  * ```
68
92
  *
69
93
  * @returns The full authorization URL to redirect users to
70
- * @see https://todoist.com/api/v1/docs#tag/Authorization/OAuth
94
+ * @see https://developer.todoist.com/api/v1/#tag/Authorization/OAuth
71
95
  */
72
96
  export declare function getAuthorizationUrl({ clientId, permissions, state, baseUrl, }: {
73
97
  clientId: string;
@@ -108,6 +132,27 @@ export declare function getAuthToken(args: AuthTokenRequestArgs, options?: AuthO
108
132
  *
109
133
  * @returns True if revocation was successful
110
134
  * @see https://datatracker.ietf.org/doc/html/rfc7009
111
- * @see https://todoist.com/api/v1/docs#tag/Authorization
135
+ * @see https://developer.todoist.com/api/v1/#tag/Authorization
112
136
  */
113
137
  export declare function revokeToken(args: RevokeTokenRequestArgs, options?: AuthOptions): Promise<boolean>;
138
+ /**
139
+ * Migrates a personal API token to an OAuth access token.
140
+ *
141
+ * This allows applications to transition users from personal API tokens
142
+ * to proper OAuth tokens without requiring the user to go through the
143
+ * full OAuth authorization flow.
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const { accessToken } = await migratePersonalToken({
148
+ * clientId: 'your-client-id',
149
+ * clientSecret: 'your-client-secret',
150
+ * personalToken: 'user-personal-token',
151
+ * scope: 'data:read_write,data:delete'
152
+ * })
153
+ * ```
154
+ *
155
+ * @returns The new OAuth token response
156
+ * @throws {@link TodoistRequestError} If the migration fails
157
+ */
158
+ export declare function migratePersonalToken(args: MigratePersonalTokenArgs, options?: AuthOptions): Promise<MigratePersonalTokenResponse>;
@@ -16,6 +16,8 @@ export declare const ENDPOINT_REST_LABELS_SHARED: string;
16
16
  export declare const ENDPOINT_REST_LABELS_SHARED_RENAME: string;
17
17
  export declare const ENDPOINT_REST_LABELS_SHARED_REMOVE: string;
18
18
  export declare const ENDPOINT_REST_COMMENTS = "comments";
19
+ export declare const ENDPOINT_REST_REMINDERS = "reminders";
20
+ export declare const ENDPOINT_REST_LOCATION_REMINDERS = "location_reminders";
19
21
  export declare const ENDPOINT_REST_TASK_CLOSE = "close";
20
22
  export declare const ENDPOINT_REST_TASK_REOPEN = "reopen";
21
23
  export declare const ENDPOINT_REST_TASK_MOVE = "move";
@@ -29,13 +31,32 @@ export declare const ENDPOINT_REST_ACTIVITIES = "activities";
29
31
  export declare const ENDPOINT_REST_UPLOADS = "uploads";
30
32
  export declare const PROJECT_ARCHIVE = "archive";
31
33
  export declare const PROJECT_UNARCHIVE = "unarchive";
34
+ export declare const ENDPOINT_REST_PROJECTS_ARCHIVED_COUNT: string;
35
+ export declare const ENDPOINT_REST_PROJECTS_PERMISSIONS: string;
36
+ export declare const ENDPOINT_REST_PROJECT_FULL = "full";
37
+ export declare const ENDPOINT_REST_PROJECT_JOIN = "join";
38
+ export declare const SECTION_ARCHIVE = "archive";
39
+ export declare const SECTION_UNARCHIVE = "unarchive";
32
40
  export declare const ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE: string;
33
41
  export declare const ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL: string;
42
+ export declare const ENDPOINT_REST_TASKS_COMPLETED: string;
43
+ export declare const ENDPOINT_REST_TEMPLATES_FILE = "templates/file";
44
+ export declare const ENDPOINT_REST_TEMPLATES_URL = "templates/url";
45
+ export declare const ENDPOINT_REST_TEMPLATES_CREATE_FROM_FILE = "templates/create_project_from_file";
46
+ export declare const ENDPOINT_REST_TEMPLATES_IMPORT_FROM_FILE = "templates/import_into_project_from_file";
47
+ export declare const ENDPOINT_REST_TEMPLATES_IMPORT_FROM_ID = "templates/import_into_project_from_template_id";
48
+ export declare const ENDPOINT_REST_ACCESS_TOKENS_MIGRATE = "access_tokens/migrate_personal_token";
49
+ export declare const ENDPOINT_REST_BACKUPS = "backups";
50
+ export declare const ENDPOINT_REST_BACKUPS_DOWNLOAD = "backups/download";
51
+ export declare const ENDPOINT_REST_EMAILS = "emails";
52
+ export declare const ENDPOINT_REST_ID_MAPPINGS = "id_mappings";
53
+ export declare const ENDPOINT_REST_MOVED_IDS = "moved_ids";
34
54
  export declare const ENDPOINT_SYNC_QUICK_ADD: string;
35
55
  export declare const ENDPOINT_SYNC = "sync";
36
56
  export declare const ENDPOINT_AUTHORIZATION = "authorize";
37
57
  export declare const ENDPOINT_GET_TOKEN = "access_token";
38
58
  export declare const ENDPOINT_REVOKE = "revoke";
59
+ export declare const ENDPOINT_REST_WORKSPACES = "workspaces";
39
60
  export declare const ENDPOINT_WORKSPACE_INVITATIONS = "workspaces/invitations";
40
61
  export declare const ENDPOINT_WORKSPACE_INVITATIONS_ALL = "workspaces/invitations/all";
41
62
  export declare const ENDPOINT_WORKSPACE_INVITATIONS_DELETE = "workspaces/invitations/delete";
@@ -45,5 +66,15 @@ export declare const ENDPOINT_WORKSPACE_PLAN_DETAILS = "workspaces/plan_details"
45
66
  export declare const ENDPOINT_WORKSPACE_USERS = "workspaces/users";
46
67
  export declare function getWorkspaceInvitationAcceptEndpoint(inviteCode: string): string;
47
68
  export declare function getWorkspaceInvitationRejectEndpoint(inviteCode: string): string;
69
+ export declare function getProjectInsightsActivityStatsEndpoint(projectId: string): string;
70
+ export declare function getProjectInsightsHealthEndpoint(projectId: string): string;
71
+ export declare function getProjectInsightsHealthContextEndpoint(projectId: string): string;
72
+ export declare function getProjectInsightsProgressEndpoint(projectId: string): string;
73
+ export declare function getProjectInsightsHealthAnalyzeEndpoint(projectId: string): string;
74
+ export declare function getWorkspaceInsightsEndpoint(workspaceId: string): string;
75
+ export declare const ENDPOINT_WORKSPACE_MEMBERS = "workspaces/members";
76
+ export declare function getWorkspaceUserTasksEndpoint(workspaceId: string, userId: string): string;
77
+ export declare function getWorkspaceInviteUsersEndpoint(workspaceId: string): string;
78
+ export declare function getWorkspaceUserEndpoint(workspaceId: string, userId: string): string;
48
79
  export declare function getWorkspaceActiveProjectsEndpoint(workspaceId: number): string;
49
80
  export declare function getWorkspaceArchivedProjectsEndpoint(workspaceId: number): string;
@@ -1,4 +1,4 @@
1
- import { Label, Section, Task, User, Attachment, Duration, Deadline, RawComment, PersonalProject } from '../types/index.js';
1
+ import { Label, Section, Task, User, Attachment, Duration, Deadline, RawComment, PersonalProject, Reminder } from '../types/index.js';
2
2
  export declare const DEFAULT_TASK_ID = "1234";
3
3
  export declare const DEFAULT_TASK_CONTENT = "This is a task";
4
4
  export declare const DEFAULT_TASK_DESCRIPTION = "A description";
@@ -148,6 +148,10 @@ export declare const DEFAULT_COMMENT: {
148
148
  isDeleted: boolean;
149
149
  projectId?: string | undefined;
150
150
  };
151
+ export declare const DEFAULT_REMINDER_ID = "6XGgmFQrx44wfGHr";
152
+ export declare const DEFAULT_RELATIVE_REMINDER: Reminder;
153
+ export declare const DEFAULT_ABSOLUTE_REMINDER: Reminder;
154
+ export declare const DEFAULT_LOCATION_REMINDER: Reminder;
151
155
  export declare const INVALID_COMMENT: {
152
156
  isDeleted: string;
153
157
  id: string;