@doist/todoist-api-typescript 7.1.1 → 7.2.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/dist/cjs/todoist-api.js +105 -0
- package/dist/esm/todoist-api.js +105 -0
- package/dist/types/todoist-api.d.ts +31 -20
- package/package.json +1 -1
package/dist/cjs/todoist-api.js
CHANGED
|
@@ -55,6 +55,34 @@ function preprocessSyncCommands(commands) {
|
|
|
55
55
|
return cmd;
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* A client for interacting with the Todoist API v1.
|
|
60
|
+
* This class provides methods to manage tasks, projects, sections, labels, and comments in Todoist.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const api = new TodoistApi('your-api-token');
|
|
65
|
+
*
|
|
66
|
+
* // Get all tasks
|
|
67
|
+
* const tasks = await api.getTasks();
|
|
68
|
+
*
|
|
69
|
+
* // Create a new task
|
|
70
|
+
* const newTask = await api.addTask({
|
|
71
|
+
* content: 'My new task',
|
|
72
|
+
* projectId: '12345'
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* For more information about the Todoist API v1, see the [official documentation](https://todoist.com/api/v1).
|
|
77
|
+
* If you're migrating from v9, please refer to the [migration guide](https://todoist.com/api/v1/docs#tag/Migrating-from-v9).
|
|
78
|
+
*/
|
|
79
|
+
function headersToRecord(headers) {
|
|
80
|
+
const result = {};
|
|
81
|
+
headers.forEach((value, key) => {
|
|
82
|
+
result[key] = value;
|
|
83
|
+
});
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
58
86
|
class TodoistApi {
|
|
59
87
|
constructor(
|
|
60
88
|
/**
|
|
@@ -1194,6 +1222,83 @@ class TodoistApi {
|
|
|
1194
1222
|
});
|
|
1195
1223
|
return (0, rest_client_1.isSuccess)(response);
|
|
1196
1224
|
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Fetches the content of a file attachment from a Todoist comment.
|
|
1227
|
+
*
|
|
1228
|
+
* Accepts either a Comment object (extracts the file URL from its attachment)
|
|
1229
|
+
* or a direct file URL string. Returns the raw Response object so the caller
|
|
1230
|
+
* can read the body in the appropriate format (.arrayBuffer(), .text(), etc.).
|
|
1231
|
+
*
|
|
1232
|
+
* @param commentOrUrl - A Comment object with a file attachment, or a file URL string.
|
|
1233
|
+
* @returns The raw fetch Response for the file content.
|
|
1234
|
+
* @throws Error if a Comment is provided without a file attachment or file URL.
|
|
1235
|
+
*
|
|
1236
|
+
* @example
|
|
1237
|
+
* ```typescript
|
|
1238
|
+
* // From a comment object
|
|
1239
|
+
* const comments = await api.getComments({ taskId: '12345' })
|
|
1240
|
+
* const comment = comments.results[0]
|
|
1241
|
+
* const response = await api.viewAttachment(comment)
|
|
1242
|
+
* const imageData = await response.arrayBuffer()
|
|
1243
|
+
*
|
|
1244
|
+
* // From a URL string
|
|
1245
|
+
* const response = await api.viewAttachment('https://files.todoist.com/...')
|
|
1246
|
+
* const text = await response.text()
|
|
1247
|
+
* ```
|
|
1248
|
+
*/
|
|
1249
|
+
async viewAttachment(commentOrUrl) {
|
|
1250
|
+
var _a;
|
|
1251
|
+
let fileUrl;
|
|
1252
|
+
if (typeof commentOrUrl === 'string') {
|
|
1253
|
+
fileUrl = commentOrUrl;
|
|
1254
|
+
}
|
|
1255
|
+
else {
|
|
1256
|
+
if (!((_a = commentOrUrl.fileAttachment) === null || _a === void 0 ? void 0 : _a.fileUrl)) {
|
|
1257
|
+
throw new Error('Comment does not have a file attachment');
|
|
1258
|
+
}
|
|
1259
|
+
fileUrl = commentOrUrl.fileAttachment.fileUrl;
|
|
1260
|
+
}
|
|
1261
|
+
// Validate the URL belongs to Todoist to prevent leaking the auth token
|
|
1262
|
+
const urlHostname = new URL(fileUrl).hostname;
|
|
1263
|
+
if (!urlHostname.endsWith('.todoist.com')) {
|
|
1264
|
+
throw new Error('Attachment URLs must be on a todoist.com domain');
|
|
1265
|
+
}
|
|
1266
|
+
const fetchOptions = {
|
|
1267
|
+
method: 'GET',
|
|
1268
|
+
headers: { Authorization: `Bearer ${this.authToken}` },
|
|
1269
|
+
};
|
|
1270
|
+
if (this.customFetch) {
|
|
1271
|
+
const response = await this.customFetch(fileUrl, fetchOptions);
|
|
1272
|
+
if (!response.ok) {
|
|
1273
|
+
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
1274
|
+
}
|
|
1275
|
+
// Convert text to ArrayBuffer for custom fetch implementations that lack arrayBuffer()
|
|
1276
|
+
const text = await response.text();
|
|
1277
|
+
const buffer = new TextEncoder().encode(text).buffer;
|
|
1278
|
+
return {
|
|
1279
|
+
ok: response.ok,
|
|
1280
|
+
status: response.status,
|
|
1281
|
+
statusText: response.statusText,
|
|
1282
|
+
headers: response.headers,
|
|
1283
|
+
text: () => Promise.resolve(text),
|
|
1284
|
+
json: () => response.json(),
|
|
1285
|
+
arrayBuffer: () => Promise.resolve(buffer),
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
const response = await fetch(fileUrl, fetchOptions);
|
|
1289
|
+
if (!response.ok) {
|
|
1290
|
+
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
1291
|
+
}
|
|
1292
|
+
return {
|
|
1293
|
+
ok: response.ok,
|
|
1294
|
+
status: response.status,
|
|
1295
|
+
statusText: response.statusText,
|
|
1296
|
+
headers: headersToRecord(response.headers),
|
|
1297
|
+
text: () => response.text(),
|
|
1298
|
+
json: () => response.json(),
|
|
1299
|
+
arrayBuffer: () => response.arrayBuffer(),
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1197
1302
|
/* Workspace methods */
|
|
1198
1303
|
/**
|
|
1199
1304
|
* Gets pending invitations for a workspace.
|
package/dist/esm/todoist-api.js
CHANGED
|
@@ -52,6 +52,34 @@ function preprocessSyncCommands(commands) {
|
|
|
52
52
|
return cmd;
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* A client for interacting with the Todoist API v1.
|
|
57
|
+
* This class provides methods to manage tasks, projects, sections, labels, and comments in Todoist.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const api = new TodoistApi('your-api-token');
|
|
62
|
+
*
|
|
63
|
+
* // Get all tasks
|
|
64
|
+
* const tasks = await api.getTasks();
|
|
65
|
+
*
|
|
66
|
+
* // Create a new task
|
|
67
|
+
* const newTask = await api.addTask({
|
|
68
|
+
* content: 'My new task',
|
|
69
|
+
* projectId: '12345'
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* For more information about the Todoist API v1, see the [official documentation](https://todoist.com/api/v1).
|
|
74
|
+
* If you're migrating from v9, please refer to the [migration guide](https://todoist.com/api/v1/docs#tag/Migrating-from-v9).
|
|
75
|
+
*/
|
|
76
|
+
function headersToRecord(headers) {
|
|
77
|
+
const result = {};
|
|
78
|
+
headers.forEach((value, key) => {
|
|
79
|
+
result[key] = value;
|
|
80
|
+
});
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
55
83
|
export class TodoistApi {
|
|
56
84
|
constructor(
|
|
57
85
|
/**
|
|
@@ -1191,6 +1219,83 @@ export class TodoistApi {
|
|
|
1191
1219
|
});
|
|
1192
1220
|
return isSuccess(response);
|
|
1193
1221
|
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Fetches the content of a file attachment from a Todoist comment.
|
|
1224
|
+
*
|
|
1225
|
+
* Accepts either a Comment object (extracts the file URL from its attachment)
|
|
1226
|
+
* or a direct file URL string. Returns the raw Response object so the caller
|
|
1227
|
+
* can read the body in the appropriate format (.arrayBuffer(), .text(), etc.).
|
|
1228
|
+
*
|
|
1229
|
+
* @param commentOrUrl - A Comment object with a file attachment, or a file URL string.
|
|
1230
|
+
* @returns The raw fetch Response for the file content.
|
|
1231
|
+
* @throws Error if a Comment is provided without a file attachment or file URL.
|
|
1232
|
+
*
|
|
1233
|
+
* @example
|
|
1234
|
+
* ```typescript
|
|
1235
|
+
* // From a comment object
|
|
1236
|
+
* const comments = await api.getComments({ taskId: '12345' })
|
|
1237
|
+
* const comment = comments.results[0]
|
|
1238
|
+
* const response = await api.viewAttachment(comment)
|
|
1239
|
+
* const imageData = await response.arrayBuffer()
|
|
1240
|
+
*
|
|
1241
|
+
* // From a URL string
|
|
1242
|
+
* const response = await api.viewAttachment('https://files.todoist.com/...')
|
|
1243
|
+
* const text = await response.text()
|
|
1244
|
+
* ```
|
|
1245
|
+
*/
|
|
1246
|
+
async viewAttachment(commentOrUrl) {
|
|
1247
|
+
var _a;
|
|
1248
|
+
let fileUrl;
|
|
1249
|
+
if (typeof commentOrUrl === 'string') {
|
|
1250
|
+
fileUrl = commentOrUrl;
|
|
1251
|
+
}
|
|
1252
|
+
else {
|
|
1253
|
+
if (!((_a = commentOrUrl.fileAttachment) === null || _a === void 0 ? void 0 : _a.fileUrl)) {
|
|
1254
|
+
throw new Error('Comment does not have a file attachment');
|
|
1255
|
+
}
|
|
1256
|
+
fileUrl = commentOrUrl.fileAttachment.fileUrl;
|
|
1257
|
+
}
|
|
1258
|
+
// Validate the URL belongs to Todoist to prevent leaking the auth token
|
|
1259
|
+
const urlHostname = new URL(fileUrl).hostname;
|
|
1260
|
+
if (!urlHostname.endsWith('.todoist.com')) {
|
|
1261
|
+
throw new Error('Attachment URLs must be on a todoist.com domain');
|
|
1262
|
+
}
|
|
1263
|
+
const fetchOptions = {
|
|
1264
|
+
method: 'GET',
|
|
1265
|
+
headers: { Authorization: `Bearer ${this.authToken}` },
|
|
1266
|
+
};
|
|
1267
|
+
if (this.customFetch) {
|
|
1268
|
+
const response = await this.customFetch(fileUrl, fetchOptions);
|
|
1269
|
+
if (!response.ok) {
|
|
1270
|
+
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
1271
|
+
}
|
|
1272
|
+
// Convert text to ArrayBuffer for custom fetch implementations that lack arrayBuffer()
|
|
1273
|
+
const text = await response.text();
|
|
1274
|
+
const buffer = new TextEncoder().encode(text).buffer;
|
|
1275
|
+
return {
|
|
1276
|
+
ok: response.ok,
|
|
1277
|
+
status: response.status,
|
|
1278
|
+
statusText: response.statusText,
|
|
1279
|
+
headers: response.headers,
|
|
1280
|
+
text: () => Promise.resolve(text),
|
|
1281
|
+
json: () => response.json(),
|
|
1282
|
+
arrayBuffer: () => Promise.resolve(buffer),
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
const response = await fetch(fileUrl, fetchOptions);
|
|
1286
|
+
if (!response.ok) {
|
|
1287
|
+
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
1288
|
+
}
|
|
1289
|
+
return {
|
|
1290
|
+
ok: response.ok,
|
|
1291
|
+
status: response.status,
|
|
1292
|
+
statusText: response.statusText,
|
|
1293
|
+
headers: headersToRecord(response.headers),
|
|
1294
|
+
text: () => response.text(),
|
|
1295
|
+
json: () => response.json(),
|
|
1296
|
+
arrayBuffer: () => response.arrayBuffer(),
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1194
1299
|
/* Workspace methods */
|
|
1195
1300
|
/**
|
|
1196
1301
|
* Gets pending invitations for a workspace.
|
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
import { Attachment, PersonalProject, WorkspaceProject, Label, Section, Comment, Task, CurrentUser, ProductivityStats, WorkspaceInvitation, WorkspacePlanDetails, JoinWorkspaceResult, Workspace } from './types/entities.js';
|
|
2
2
|
import { AddCommentArgs, AddLabelArgs, AddProjectArgs, AddSectionArgs, AddTaskArgs, GetProjectCommentsArgs, GetTaskCommentsArgs, GetTasksArgs, GetTasksByFilterArgs, UpdateCommentArgs, UpdateLabelArgs, UpdateProjectArgs, UpdateSectionArgs, UpdateTaskArgs, QuickAddTaskArgs, GetSharedLabelsArgs, RenameSharedLabelArgs, RemoveSharedLabelArgs, GetProjectsArgs, SearchProjectsArgs, GetProjectCollaboratorsArgs, GetLabelsArgs, SearchLabelsArgs, GetLabelsResponse, GetTasksResponse, GetProjectsResponse, GetProjectCollaboratorsResponse, GetSectionsArgs, SearchSectionsArgs, GetSectionsResponse, GetSharedLabelsResponse, GetCommentsResponse, type MoveTaskArgs, GetCompletedTasksByCompletionDateArgs, GetCompletedTasksByDueDateArgs, GetCompletedTasksResponse, GetArchivedProjectsArgs, GetArchivedProjectsResponse, SearchCompletedTasksArgs, GetActivityLogsArgs, GetActivityLogsResponse, UploadFileArgs, DeleteUploadArgs, GetWorkspaceInvitationsArgs, DeleteWorkspaceInvitationArgs, WorkspaceInvitationActionArgs, JoinWorkspaceArgs, WorkspaceLogoArgs, GetWorkspacePlanDetailsArgs, GetWorkspaceUsersArgs, GetWorkspaceUsersResponse, GetWorkspaceProjectsArgs, WorkspaceInvitationsResponse, AllWorkspaceInvitationsResponse, WorkspaceLogoResponse, MoveProjectToWorkspaceArgs, MoveProjectToPersonalArgs } from './types/requests.js';
|
|
3
|
-
import { CustomFetch } from './types/http.js';
|
|
3
|
+
import { CustomFetch, CustomFetchResponse } from './types/http.js';
|
|
4
4
|
import { type SyncResponse, type SyncRequest } from './types/sync/index.js';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```typescript
|
|
11
|
-
* const api = new TodoistApi('your-api-token');
|
|
12
|
-
*
|
|
13
|
-
* // Get all tasks
|
|
14
|
-
* const tasks = await api.getTasks();
|
|
15
|
-
*
|
|
16
|
-
* // Create a new task
|
|
17
|
-
* const newTask = await api.addTask({
|
|
18
|
-
* content: 'My new task',
|
|
19
|
-
* projectId: '12345'
|
|
20
|
-
* });
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* For more information about the Todoist API v1, see the [official documentation](https://todoist.com/api/v1).
|
|
24
|
-
* If you're migrating from v9, please refer to the [migration guide](https://todoist.com/api/v1/docs#tag/Migrating-from-v9).
|
|
6
|
+
* Response from viewAttachment, extending CustomFetchResponse with
|
|
7
|
+
* arrayBuffer() support for binary file content.
|
|
25
8
|
*/
|
|
9
|
+
export type ViewAttachmentResponse = CustomFetchResponse & {
|
|
10
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
11
|
+
};
|
|
26
12
|
/**
|
|
27
13
|
* Configuration options for the TodoistApi constructor
|
|
28
14
|
*/
|
|
@@ -511,6 +497,31 @@ export declare class TodoistApi {
|
|
|
511
497
|
* ```
|
|
512
498
|
*/
|
|
513
499
|
deleteUpload(args: DeleteUploadArgs, requestId?: string): Promise<boolean>;
|
|
500
|
+
/**
|
|
501
|
+
* Fetches the content of a file attachment from a Todoist comment.
|
|
502
|
+
*
|
|
503
|
+
* Accepts either a Comment object (extracts the file URL from its attachment)
|
|
504
|
+
* or a direct file URL string. Returns the raw Response object so the caller
|
|
505
|
+
* can read the body in the appropriate format (.arrayBuffer(), .text(), etc.).
|
|
506
|
+
*
|
|
507
|
+
* @param commentOrUrl - A Comment object with a file attachment, or a file URL string.
|
|
508
|
+
* @returns The raw fetch Response for the file content.
|
|
509
|
+
* @throws Error if a Comment is provided without a file attachment or file URL.
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* ```typescript
|
|
513
|
+
* // From a comment object
|
|
514
|
+
* const comments = await api.getComments({ taskId: '12345' })
|
|
515
|
+
* const comment = comments.results[0]
|
|
516
|
+
* const response = await api.viewAttachment(comment)
|
|
517
|
+
* const imageData = await response.arrayBuffer()
|
|
518
|
+
*
|
|
519
|
+
* // From a URL string
|
|
520
|
+
* const response = await api.viewAttachment('https://files.todoist.com/...')
|
|
521
|
+
* const text = await response.text()
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
viewAttachment(commentOrUrl: Comment | string): Promise<ViewAttachmentResponse>;
|
|
514
525
|
/**
|
|
515
526
|
* Gets pending invitations for a workspace.
|
|
516
527
|
*
|
package/package.json
CHANGED