@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.
- package/README.md +2 -0
- package/dist/cjs/authentication.js +50 -6
- package/dist/cjs/consts/endpoints.js +63 -1
- package/dist/cjs/test-utils/test-defaults.js +33 -1
- package/dist/cjs/todoist-api.js +1130 -168
- package/dist/cjs/{utils → transport}/fetch-with-retry.js +23 -71
- package/dist/cjs/{rest-client.js → transport/http-client.js} +5 -5
- package/dist/cjs/transport/http-dispatcher.js +72 -0
- package/dist/cjs/types/entities.js +124 -1
- package/dist/cjs/types/errors.js +9 -1
- package/dist/cjs/types/http.js +3 -1
- package/dist/cjs/types/requests.js +24 -0
- package/dist/cjs/types/sync/commands/shared.js +2 -8
- package/dist/cjs/types/sync/resources/reminders.js +2 -0
- package/dist/cjs/utils/multipart-upload.js +1 -1
- package/dist/cjs/utils/validators.js +19 -2
- package/dist/esm/authentication.js +47 -4
- package/dist/esm/consts/endpoints.js +52 -0
- package/dist/esm/test-utils/test-defaults.js +32 -0
- package/dist/esm/todoist-api.js +1061 -99
- package/dist/esm/{utils → transport}/fetch-with-retry.js +23 -38
- package/dist/esm/{rest-client.js → transport/http-client.js} +5 -5
- package/dist/esm/transport/http-dispatcher.js +35 -0
- package/dist/esm/types/entities.js +122 -0
- package/dist/esm/types/errors.js +7 -0
- package/dist/esm/types/http.js +3 -1
- package/dist/esm/types/requests.js +23 -1
- package/dist/esm/types/sync/commands/shared.js +1 -8
- package/dist/esm/types/sync/resources/reminders.js +2 -0
- package/dist/esm/utils/multipart-upload.js +1 -1
- package/dist/esm/utils/validators.js +19 -2
- package/dist/types/authentication.d.ts +51 -6
- package/dist/types/consts/endpoints.d.ts +31 -0
- package/dist/types/test-utils/test-defaults.d.ts +5 -1
- package/dist/types/todoist-api.d.ts +338 -6
- package/dist/types/{utils → transport}/fetch-with-retry.d.ts +1 -1
- package/dist/types/{rest-client.d.ts → transport/http-client.d.ts} +1 -1
- package/dist/types/transport/http-dispatcher.d.ts +3 -0
- package/dist/types/types/entities.d.ts +258 -14
- package/dist/types/types/errors.d.ts +4 -0
- package/dist/types/types/requests.d.ts +537 -43
- package/dist/types/types/sync/commands/projects.d.ts +2 -2
- package/dist/types/types/sync/commands/shared.d.ts +1 -4
- package/dist/types/types/sync/resources/reminders.d.ts +4 -0
- package/dist/types/types/sync/resources/user.d.ts +2 -2
- package/dist/types/types/sync/resources/view-options.d.ts +5 -5
- package/dist/types/types/sync/user-preferences.d.ts +1 -1
- package/dist/types/utils/validators.d.ts +202 -6
- 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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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(
|
|
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
|
-
|
|
66
|
+
abortHandler = () => {
|
|
83
67
|
clearTimeout(timeoutId);
|
|
84
68
|
controller.abort(existingSignal.reason);
|
|
85
|
-
}
|
|
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
|
|
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
|
|
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 '
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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
|
+
});
|
package/dist/esm/types/errors.js
CHANGED
|
@@ -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
|
+
}
|
package/dist/esm/types/http.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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,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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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;
|