@doist/todoist-api-typescript 6.4.1 → 6.5.1
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/consts/endpoints.js +3 -1
- package/dist/cjs/todoist-api.js +38 -0
- package/dist/cjs/types/entities.js +3 -1
- package/dist/cjs/utils/multipart-upload.js +93 -42
- package/dist/esm/consts/endpoints.js +2 -0
- package/dist/esm/todoist-api.js +39 -1
- package/dist/esm/types/entities.js +2 -0
- package/dist/esm/utils/multipart-upload.js +60 -39
- package/dist/types/consts/endpoints.d.ts +2 -0
- package/dist/types/todoist-api.d.ts +17 -1
- package/dist/types/types/entities.d.ts +19 -0
- package/dist/types/types/requests.d.ts +26 -4
- package/dist/types/utils/multipart-upload.d.ts +5 -3
- package/package.json +8 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ENDPOINT_WORKSPACE_USERS = exports.ENDPOINT_WORKSPACE_PLAN_DETAILS = exports.ENDPOINT_WORKSPACE_LOGO = exports.ENDPOINT_WORKSPACE_JOIN = exports.ENDPOINT_WORKSPACE_INVITATIONS_DELETE = exports.ENDPOINT_WORKSPACE_INVITATIONS_ALL = exports.ENDPOINT_WORKSPACE_INVITATIONS = exports.ENDPOINT_REVOKE = exports.ENDPOINT_REVOKE_TOKEN = exports.ENDPOINT_GET_TOKEN = exports.ENDPOINT_AUTHORIZATION = exports.ENDPOINT_SYNC = exports.ENDPOINT_SYNC_QUICK_ADD = exports.PROJECT_UNARCHIVE = exports.PROJECT_ARCHIVE = exports.ENDPOINT_REST_UPLOADS = exports.ENDPOINT_REST_ACTIVITIES = exports.ENDPOINT_REST_PRODUCTIVITY = exports.ENDPOINT_REST_USER = exports.ENDPOINT_REST_PROJECT_COLLABORATORS = exports.ENDPOINT_REST_PROJECTS_ARCHIVED = exports.ENDPOINT_REST_PROJECTS_SEARCH = exports.ENDPOINT_REST_PROJECTS = exports.ENDPOINT_REST_TASK_MOVE = exports.ENDPOINT_REST_TASK_REOPEN = exports.ENDPOINT_REST_TASK_CLOSE = exports.ENDPOINT_REST_COMMENTS = exports.ENDPOINT_REST_LABELS_SHARED_REMOVE = exports.ENDPOINT_REST_LABELS_SHARED_RENAME = exports.ENDPOINT_REST_LABELS_SHARED = exports.ENDPOINT_REST_LABELS_SEARCH = exports.ENDPOINT_REST_LABELS = exports.ENDPOINT_REST_SECTIONS_SEARCH = exports.ENDPOINT_REST_SECTIONS = exports.ENDPOINT_REST_TASKS_COMPLETED_SEARCH = exports.ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE = exports.ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE = exports.ENDPOINT_REST_TASKS_FILTER = exports.ENDPOINT_REST_TASKS = exports.API_BASE_URI = exports.API_VERSION = exports.TODOIST_WEB_URI = void 0;
|
|
3
|
+
exports.ENDPOINT_WORKSPACE_USERS = exports.ENDPOINT_WORKSPACE_PLAN_DETAILS = exports.ENDPOINT_WORKSPACE_LOGO = exports.ENDPOINT_WORKSPACE_JOIN = exports.ENDPOINT_WORKSPACE_INVITATIONS_DELETE = exports.ENDPOINT_WORKSPACE_INVITATIONS_ALL = exports.ENDPOINT_WORKSPACE_INVITATIONS = exports.ENDPOINT_REVOKE = exports.ENDPOINT_REVOKE_TOKEN = exports.ENDPOINT_GET_TOKEN = exports.ENDPOINT_AUTHORIZATION = exports.ENDPOINT_SYNC = exports.ENDPOINT_SYNC_QUICK_ADD = exports.ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL = exports.ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE = exports.PROJECT_UNARCHIVE = exports.PROJECT_ARCHIVE = exports.ENDPOINT_REST_UPLOADS = exports.ENDPOINT_REST_ACTIVITIES = exports.ENDPOINT_REST_PRODUCTIVITY = exports.ENDPOINT_REST_USER = exports.ENDPOINT_REST_PROJECT_COLLABORATORS = exports.ENDPOINT_REST_PROJECTS_ARCHIVED = exports.ENDPOINT_REST_PROJECTS_SEARCH = exports.ENDPOINT_REST_PROJECTS = exports.ENDPOINT_REST_TASK_MOVE = exports.ENDPOINT_REST_TASK_REOPEN = exports.ENDPOINT_REST_TASK_CLOSE = exports.ENDPOINT_REST_COMMENTS = exports.ENDPOINT_REST_LABELS_SHARED_REMOVE = exports.ENDPOINT_REST_LABELS_SHARED_RENAME = exports.ENDPOINT_REST_LABELS_SHARED = exports.ENDPOINT_REST_LABELS_SEARCH = exports.ENDPOINT_REST_LABELS = exports.ENDPOINT_REST_SECTIONS_SEARCH = exports.ENDPOINT_REST_SECTIONS = exports.ENDPOINT_REST_TASKS_COMPLETED_SEARCH = exports.ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE = exports.ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE = exports.ENDPOINT_REST_TASKS_FILTER = exports.ENDPOINT_REST_TASKS = exports.API_BASE_URI = exports.API_VERSION = exports.TODOIST_WEB_URI = void 0;
|
|
4
4
|
exports.getSyncBaseUri = getSyncBaseUri;
|
|
5
5
|
exports.getAuthBaseUri = getAuthBaseUri;
|
|
6
6
|
exports.getWorkspaceInvitationAcceptEndpoint = getWorkspaceInvitationAcceptEndpoint;
|
|
@@ -47,6 +47,8 @@ exports.ENDPOINT_REST_ACTIVITIES = 'activities';
|
|
|
47
47
|
exports.ENDPOINT_REST_UPLOADS = 'uploads';
|
|
48
48
|
exports.PROJECT_ARCHIVE = 'archive';
|
|
49
49
|
exports.PROJECT_UNARCHIVE = 'unarchive';
|
|
50
|
+
exports.ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE = exports.ENDPOINT_REST_PROJECTS + '/move_to_workspace';
|
|
51
|
+
exports.ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL = exports.ENDPOINT_REST_PROJECTS + '/move_to_personal';
|
|
50
52
|
exports.ENDPOINT_SYNC_QUICK_ADD = exports.ENDPOINT_REST_TASKS + '/quick';
|
|
51
53
|
exports.ENDPOINT_SYNC = 'sync';
|
|
52
54
|
exports.ENDPOINT_AUTHORIZATION = 'authorize';
|
package/dist/cjs/todoist-api.js
CHANGED
|
@@ -557,6 +557,44 @@ class TodoistApi {
|
|
|
557
557
|
});
|
|
558
558
|
return (0, validators_1.validateProject)(response.data);
|
|
559
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* Moves a project to a workspace.
|
|
562
|
+
*
|
|
563
|
+
* @param args - The arguments for moving the project.
|
|
564
|
+
* @param requestId - Optional custom identifier for the request.
|
|
565
|
+
* @returns A promise that resolves to the moved project.
|
|
566
|
+
*/
|
|
567
|
+
async moveProjectToWorkspace(args, requestId) {
|
|
568
|
+
const response = await (0, rest_client_1.request)({
|
|
569
|
+
httpMethod: 'POST',
|
|
570
|
+
baseUri: this.syncApiBase,
|
|
571
|
+
relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE,
|
|
572
|
+
apiToken: this.authToken,
|
|
573
|
+
customFetch: this.customFetch,
|
|
574
|
+
payload: args,
|
|
575
|
+
requestId: requestId,
|
|
576
|
+
});
|
|
577
|
+
return (0, validators_1.validateProject)(response.data.project);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Moves a project to personal.
|
|
581
|
+
*
|
|
582
|
+
* @param args - The arguments for moving the project.
|
|
583
|
+
* @param requestId - Optional custom identifier for the request.
|
|
584
|
+
* @returns A promise that resolves to the moved project.
|
|
585
|
+
*/
|
|
586
|
+
async moveProjectToPersonal(args, requestId) {
|
|
587
|
+
const response = await (0, rest_client_1.request)({
|
|
588
|
+
httpMethod: 'POST',
|
|
589
|
+
baseUri: this.syncApiBase,
|
|
590
|
+
relativePath: endpoints_1.ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL,
|
|
591
|
+
apiToken: this.authToken,
|
|
592
|
+
customFetch: this.customFetch,
|
|
593
|
+
payload: args,
|
|
594
|
+
requestId: requestId,
|
|
595
|
+
});
|
|
596
|
+
return (0, validators_1.validateProject)(response.data.project);
|
|
597
|
+
}
|
|
560
598
|
/**
|
|
561
599
|
* Retrieves a list of collaborators for a specific project.
|
|
562
600
|
*
|
|
@@ -11,7 +11,7 @@ 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.FormattedPriceListingSchema = exports.PlanPriceSchema = exports.WorkspaceInvitationSchema = exports.WorkspaceUserSchema = exports.WorkspaceRoleSchema = exports.WORKSPACE_ROLES = exports.ActivityEventSchema = exports.ActivityEventExtraDataSchema = exports.ColorSchema = exports.ProductivityStatsSchema = exports.CurrentUserSchema = exports.TimezoneInfoSchema = exports.UserSchema = exports.CommentSchema = exports.RawCommentSchema = exports.AttachmentSchema = exports.LabelSchema = exports.SectionSchema = exports.WorkspaceProjectSchema = exports.PersonalProjectSchema = exports.BaseProjectSchema = exports.TaskSchema = exports.DeadlineSchema = exports.DurationSchema = exports.DueDateSchema = void 0;
|
|
14
|
+
exports.WorkspaceSchema = exports.WorkspacePropertiesSchema = exports.WorkspaceLimitsSchema = exports.WorkspacePlanSchema = exports.WORKSPACE_PLANS = exports.JoinWorkspaceResultSchema = exports.WorkspacePlanDetailsSchema = exports.FormattedPriceListingSchema = exports.PlanPriceSchema = exports.WorkspaceInvitationSchema = exports.WorkspaceUserSchema = exports.WorkspaceRoleSchema = exports.WORKSPACE_ROLES = exports.ActivityEventSchema = exports.ActivityEventExtraDataSchema = exports.ColorSchema = exports.ProductivityStatsSchema = exports.CurrentUserSchema = exports.TimezoneInfoSchema = exports.UserSchema = exports.CommentSchema = exports.RawCommentSchema = exports.AttachmentSchema = exports.LabelSchema = exports.SectionSchema = exports.WorkspaceProjectSchema = exports.ProjectVisibilitySchema = exports.PersonalProjectSchema = exports.BaseProjectSchema = exports.TaskSchema = exports.DeadlineSchema = exports.DurationSchema = exports.DueDateSchema = void 0;
|
|
15
15
|
const zod_1 = require("zod");
|
|
16
16
|
const url_helpers_1 = require("../utils/url-helpers");
|
|
17
17
|
const uncompletable_helpers_1 = require("../utils/uncompletable-helpers");
|
|
@@ -101,10 +101,12 @@ exports.PersonalProjectSchema = exports.BaseProjectSchema.extend({
|
|
|
101
101
|
}).transform((data) => {
|
|
102
102
|
return Object.assign(Object.assign({}, data), { url: (0, url_helpers_1.getProjectUrl)(data.id, data.name) });
|
|
103
103
|
});
|
|
104
|
+
exports.ProjectVisibilitySchema = zod_1.z.enum(['restricted', 'team', 'public']);
|
|
104
105
|
/**
|
|
105
106
|
* Schema for workspace projects in Todoist.
|
|
106
107
|
*/
|
|
107
108
|
exports.WorkspaceProjectSchema = exports.BaseProjectSchema.extend({
|
|
109
|
+
access: zod_1.z.object({ visibility: exports.ProjectVisibilitySchema }).optional(),
|
|
108
110
|
collaboratorRoleDefault: zod_1.z.string(),
|
|
109
111
|
folderId: zod_1.z.string().nullable(),
|
|
110
112
|
isInviteOnly: zod_1.z.boolean().nullable(),
|
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
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
|
+
})();
|
|
5
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
36
|
exports.uploadMultipartFile = uploadMultipartFile;
|
|
7
|
-
const form_data_1 = __importDefault(require("form-data"));
|
|
8
|
-
const fs_1 = require("fs");
|
|
9
|
-
const path_1 = require("path");
|
|
10
37
|
const fetch_with_retry_1 = require("./fetch-with-retry");
|
|
11
38
|
/**
|
|
12
39
|
* Helper function to determine content-type from filename extension.
|
|
@@ -37,11 +64,13 @@ function getContentTypeFromFileName(fileName) {
|
|
|
37
64
|
* This is a shared utility for uploading files to Todoist endpoints that require
|
|
38
65
|
* multipart/form-data content type (e.g., file uploads, workspace logo uploads).
|
|
39
66
|
*
|
|
67
|
+
* Supports both browser (Blob/File) and Node.js (Buffer/ReadableStream/path) environments.
|
|
68
|
+
*
|
|
40
69
|
* @param baseUrl - The base API URL (e.g., https://api.todoist.com/api/v1/)
|
|
41
70
|
* @param authToken - The authentication token
|
|
42
71
|
* @param endpoint - The relative endpoint path (e.g., 'uploads', 'workspaces/logo')
|
|
43
|
-
* @param file - The file content (
|
|
44
|
-
* @param fileName - Optional file name (required for Buffer/Stream, optional for paths)
|
|
72
|
+
* @param file - The file content (Blob/File for browser, or Buffer/ReadableStream/path for Node)
|
|
73
|
+
* @param fileName - Optional file name (required for Buffer/Stream, optional for paths and File objects)
|
|
45
74
|
* @param additionalFields - Additional form fields to include (e.g., project_id, workspace_id)
|
|
46
75
|
* @param requestId - Optional request ID for idempotency
|
|
47
76
|
* @returns The response data from the server
|
|
@@ -72,52 +101,74 @@ function getContentTypeFromFileName(fileName) {
|
|
|
72
101
|
*/
|
|
73
102
|
async function uploadMultipartFile(args) {
|
|
74
103
|
const { baseUrl, authToken, endpoint, file, fileName, additionalFields, requestId, customFetch, } = args;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
104
|
+
// Build the full URL
|
|
105
|
+
const url = `${baseUrl}${endpoint}`;
|
|
106
|
+
let body;
|
|
107
|
+
const headers = {
|
|
108
|
+
Authorization: `Bearer ${authToken}`,
|
|
109
|
+
};
|
|
110
|
+
if (requestId) {
|
|
111
|
+
headers['X-Request-Id'] = requestId;
|
|
82
112
|
}
|
|
83
|
-
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
if (file instanceof Blob) {
|
|
114
|
+
// Browser path: use native FormData
|
|
115
|
+
const form = new globalThis.FormData();
|
|
116
|
+
const resolvedFileName = fileName || (file instanceof File ? file.name : undefined) || 'upload';
|
|
117
|
+
form.append('file', file, resolvedFileName);
|
|
118
|
+
for (const [key, value] of Object.entries(additionalFields)) {
|
|
119
|
+
if (value !== undefined && value !== null) {
|
|
120
|
+
form.append(key, value.toString());
|
|
121
|
+
}
|
|
87
122
|
}
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
form.append('file', file, {
|
|
91
|
-
filename: fileName,
|
|
92
|
-
contentType: contentType,
|
|
93
|
-
});
|
|
123
|
+
// Don't set Content-Type — let fetch set it with the correct multipart boundary
|
|
124
|
+
body = form;
|
|
94
125
|
}
|
|
95
126
|
else {
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
127
|
+
// Node path: dynamically import Node-only modules
|
|
128
|
+
const [FormDataModule, fsModule, pathModule] = await Promise.all([
|
|
129
|
+
Promise.resolve().then(() => __importStar(require('form-data'))),
|
|
130
|
+
Promise.resolve().then(() => __importStar(require('fs'))),
|
|
131
|
+
Promise.resolve().then(() => __importStar(require('path'))),
|
|
132
|
+
]);
|
|
133
|
+
const FormData = FormDataModule.default;
|
|
134
|
+
const form = new FormData();
|
|
135
|
+
if (typeof file === 'string') {
|
|
136
|
+
// File path - create read stream
|
|
137
|
+
const resolvedFileName = fileName || pathModule.basename(file);
|
|
138
|
+
form.append('file', fsModule.createReadStream(file), resolvedFileName);
|
|
99
139
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
140
|
+
else if (Buffer.isBuffer(file)) {
|
|
141
|
+
// Buffer - require fileName
|
|
142
|
+
if (!fileName) {
|
|
143
|
+
throw new Error('fileName is required when uploading from a Buffer');
|
|
144
|
+
}
|
|
145
|
+
const contentType = getContentTypeFromFileName(fileName);
|
|
146
|
+
form.append('file', file, {
|
|
147
|
+
filename: fileName,
|
|
148
|
+
contentType: contentType,
|
|
149
|
+
});
|
|
106
150
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
151
|
+
else {
|
|
152
|
+
// Stream - require fileName
|
|
153
|
+
if (!fileName) {
|
|
154
|
+
throw new Error('fileName is required when uploading from a stream');
|
|
155
|
+
}
|
|
156
|
+
form.append('file', file, fileName);
|
|
157
|
+
}
|
|
158
|
+
for (const [key, value] of Object.entries(additionalFields)) {
|
|
159
|
+
if (value !== undefined && value !== null) {
|
|
160
|
+
form.append(key, value.toString());
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
Object.assign(headers, form.getHeaders());
|
|
164
|
+
body = form;
|
|
114
165
|
}
|
|
115
166
|
// Make the request using fetch
|
|
116
167
|
const response = await (0, fetch_with_retry_1.fetchWithRetry)({
|
|
117
168
|
url,
|
|
118
169
|
options: {
|
|
119
170
|
method: 'POST',
|
|
120
|
-
body
|
|
171
|
+
body,
|
|
121
172
|
headers,
|
|
122
173
|
timeout: 30000, // 30 second timeout for file uploads
|
|
123
174
|
},
|
|
@@ -38,6 +38,8 @@ export const ENDPOINT_REST_ACTIVITIES = 'activities';
|
|
|
38
38
|
export const ENDPOINT_REST_UPLOADS = 'uploads';
|
|
39
39
|
export const PROJECT_ARCHIVE = 'archive';
|
|
40
40
|
export const PROJECT_UNARCHIVE = 'unarchive';
|
|
41
|
+
export const ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE = ENDPOINT_REST_PROJECTS + '/move_to_workspace';
|
|
42
|
+
export const ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL = ENDPOINT_REST_PROJECTS + '/move_to_personal';
|
|
41
43
|
export const ENDPOINT_SYNC_QUICK_ADD = ENDPOINT_REST_TASKS + '/quick';
|
|
42
44
|
export const ENDPOINT_SYNC = 'sync';
|
|
43
45
|
export const ENDPOINT_AUTHORIZATION = 'authorize';
|
package/dist/esm/todoist-api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { request, isSuccess } from './rest-client.js';
|
|
2
|
-
import { getSyncBaseUri, ENDPOINT_REST_TASKS, ENDPOINT_REST_TASKS_FILTER, ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE, ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE, ENDPOINT_REST_TASKS_COMPLETED_SEARCH, ENDPOINT_REST_PROJECTS, ENDPOINT_REST_PROJECTS_SEARCH, ENDPOINT_SYNC_QUICK_ADD, ENDPOINT_REST_TASK_CLOSE, ENDPOINT_REST_TASK_REOPEN, ENDPOINT_REST_TASK_MOVE, ENDPOINT_REST_LABELS, ENDPOINT_REST_LABELS_SEARCH, ENDPOINT_REST_PROJECT_COLLABORATORS, ENDPOINT_REST_SECTIONS, ENDPOINT_REST_SECTIONS_SEARCH, ENDPOINT_REST_COMMENTS, ENDPOINT_REST_LABELS_SHARED, ENDPOINT_REST_LABELS_SHARED_RENAME, ENDPOINT_REST_LABELS_SHARED_REMOVE, ENDPOINT_SYNC, PROJECT_ARCHIVE, PROJECT_UNARCHIVE, ENDPOINT_REST_PROJECTS_ARCHIVED, ENDPOINT_REST_USER, ENDPOINT_REST_PRODUCTIVITY, ENDPOINT_REST_ACTIVITIES, ENDPOINT_REST_UPLOADS, ENDPOINT_WORKSPACE_INVITATIONS, ENDPOINT_WORKSPACE_INVITATIONS_ALL, ENDPOINT_WORKSPACE_INVITATIONS_DELETE, getWorkspaceInvitationAcceptEndpoint, getWorkspaceInvitationRejectEndpoint, ENDPOINT_WORKSPACE_JOIN, ENDPOINT_WORKSPACE_LOGO, ENDPOINT_WORKSPACE_PLAN_DETAILS, ENDPOINT_WORKSPACE_USERS, getWorkspaceActiveProjectsEndpoint, getWorkspaceArchivedProjectsEndpoint, } from './consts/endpoints.js';
|
|
2
|
+
import { getSyncBaseUri, ENDPOINT_REST_TASKS, ENDPOINT_REST_TASKS_FILTER, ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE, ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE, ENDPOINT_REST_TASKS_COMPLETED_SEARCH, ENDPOINT_REST_PROJECTS, ENDPOINT_REST_PROJECTS_SEARCH, ENDPOINT_SYNC_QUICK_ADD, ENDPOINT_REST_TASK_CLOSE, ENDPOINT_REST_TASK_REOPEN, ENDPOINT_REST_TASK_MOVE, ENDPOINT_REST_LABELS, ENDPOINT_REST_LABELS_SEARCH, ENDPOINT_REST_PROJECT_COLLABORATORS, ENDPOINT_REST_SECTIONS, ENDPOINT_REST_SECTIONS_SEARCH, ENDPOINT_REST_COMMENTS, ENDPOINT_REST_LABELS_SHARED, ENDPOINT_REST_LABELS_SHARED_RENAME, ENDPOINT_REST_LABELS_SHARED_REMOVE, ENDPOINT_SYNC, PROJECT_ARCHIVE, PROJECT_UNARCHIVE, ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE, ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL, ENDPOINT_REST_PROJECTS_ARCHIVED, ENDPOINT_REST_USER, ENDPOINT_REST_PRODUCTIVITY, ENDPOINT_REST_ACTIVITIES, ENDPOINT_REST_UPLOADS, ENDPOINT_WORKSPACE_INVITATIONS, ENDPOINT_WORKSPACE_INVITATIONS_ALL, ENDPOINT_WORKSPACE_INVITATIONS_DELETE, getWorkspaceInvitationAcceptEndpoint, getWorkspaceInvitationRejectEndpoint, ENDPOINT_WORKSPACE_JOIN, ENDPOINT_WORKSPACE_LOGO, ENDPOINT_WORKSPACE_PLAN_DETAILS, ENDPOINT_WORKSPACE_USERS, getWorkspaceActiveProjectsEndpoint, getWorkspaceArchivedProjectsEndpoint, } from './consts/endpoints.js';
|
|
3
3
|
import { validateAttachment, validateComment, validateCommentArray, validateCurrentUser, validateLabel, validateLabelArray, validateProject, validateProjectArray, validateSection, validateSectionArray, validateTask, validateTaskArray, validateUserArray, validateProductivityStats, validateActivityEventArray, validateWorkspaceUserArray, validateWorkspaceInvitation, validateWorkspaceInvitationArray, validateWorkspacePlanDetails, validateJoinWorkspaceResult, validateWorkspaceArray, } from './utils/validators.js';
|
|
4
4
|
import { formatDateToYYYYMMDD } from './utils/url-helpers.js';
|
|
5
5
|
import { uploadMultipartFile } from './utils/multipart-upload.js';
|
|
@@ -554,6 +554,44 @@ export class TodoistApi {
|
|
|
554
554
|
});
|
|
555
555
|
return validateProject(response.data);
|
|
556
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Moves a project to a workspace.
|
|
559
|
+
*
|
|
560
|
+
* @param args - The arguments for moving the project.
|
|
561
|
+
* @param requestId - Optional custom identifier for the request.
|
|
562
|
+
* @returns A promise that resolves to the moved project.
|
|
563
|
+
*/
|
|
564
|
+
async moveProjectToWorkspace(args, requestId) {
|
|
565
|
+
const response = await request({
|
|
566
|
+
httpMethod: 'POST',
|
|
567
|
+
baseUri: this.syncApiBase,
|
|
568
|
+
relativePath: ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE,
|
|
569
|
+
apiToken: this.authToken,
|
|
570
|
+
customFetch: this.customFetch,
|
|
571
|
+
payload: args,
|
|
572
|
+
requestId: requestId,
|
|
573
|
+
});
|
|
574
|
+
return validateProject(response.data.project);
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Moves a project to personal.
|
|
578
|
+
*
|
|
579
|
+
* @param args - The arguments for moving the project.
|
|
580
|
+
* @param requestId - Optional custom identifier for the request.
|
|
581
|
+
* @returns A promise that resolves to the moved project.
|
|
582
|
+
*/
|
|
583
|
+
async moveProjectToPersonal(args, requestId) {
|
|
584
|
+
const response = await request({
|
|
585
|
+
httpMethod: 'POST',
|
|
586
|
+
baseUri: this.syncApiBase,
|
|
587
|
+
relativePath: ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL,
|
|
588
|
+
apiToken: this.authToken,
|
|
589
|
+
customFetch: this.customFetch,
|
|
590
|
+
payload: args,
|
|
591
|
+
requestId: requestId,
|
|
592
|
+
});
|
|
593
|
+
return validateProject(response.data.project);
|
|
594
|
+
}
|
|
557
595
|
/**
|
|
558
596
|
* Retrieves a list of collaborators for a specific project.
|
|
559
597
|
*
|
|
@@ -98,10 +98,12 @@ export const PersonalProjectSchema = BaseProjectSchema.extend({
|
|
|
98
98
|
}).transform((data) => {
|
|
99
99
|
return Object.assign(Object.assign({}, data), { url: getProjectUrl(data.id, data.name) });
|
|
100
100
|
});
|
|
101
|
+
export const ProjectVisibilitySchema = z.enum(['restricted', 'team', 'public']);
|
|
101
102
|
/**
|
|
102
103
|
* Schema for workspace projects in Todoist.
|
|
103
104
|
*/
|
|
104
105
|
export const WorkspaceProjectSchema = BaseProjectSchema.extend({
|
|
106
|
+
access: z.object({ visibility: ProjectVisibilitySchema }).optional(),
|
|
105
107
|
collaboratorRoleDefault: z.string(),
|
|
106
108
|
folderId: z.string().nullable(),
|
|
107
109
|
isInviteOnly: z.boolean().nullable(),
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import FormData from 'form-data';
|
|
2
|
-
import { createReadStream } from 'fs';
|
|
3
|
-
import { basename } from 'path';
|
|
4
1
|
import { fetchWithRetry } from './fetch-with-retry.js';
|
|
5
2
|
/**
|
|
6
3
|
* Helper function to determine content-type from filename extension.
|
|
@@ -31,11 +28,13 @@ function getContentTypeFromFileName(fileName) {
|
|
|
31
28
|
* This is a shared utility for uploading files to Todoist endpoints that require
|
|
32
29
|
* multipart/form-data content type (e.g., file uploads, workspace logo uploads).
|
|
33
30
|
*
|
|
31
|
+
* Supports both browser (Blob/File) and Node.js (Buffer/ReadableStream/path) environments.
|
|
32
|
+
*
|
|
34
33
|
* @param baseUrl - The base API URL (e.g., https://api.todoist.com/api/v1/)
|
|
35
34
|
* @param authToken - The authentication token
|
|
36
35
|
* @param endpoint - The relative endpoint path (e.g., 'uploads', 'workspaces/logo')
|
|
37
|
-
* @param file - The file content (
|
|
38
|
-
* @param fileName - Optional file name (required for Buffer/Stream, optional for paths)
|
|
36
|
+
* @param file - The file content (Blob/File for browser, or Buffer/ReadableStream/path for Node)
|
|
37
|
+
* @param fileName - Optional file name (required for Buffer/Stream, optional for paths and File objects)
|
|
39
38
|
* @param additionalFields - Additional form fields to include (e.g., project_id, workspace_id)
|
|
40
39
|
* @param requestId - Optional request ID for idempotency
|
|
41
40
|
* @returns The response data from the server
|
|
@@ -66,52 +65,74 @@ function getContentTypeFromFileName(fileName) {
|
|
|
66
65
|
*/
|
|
67
66
|
export async function uploadMultipartFile(args) {
|
|
68
67
|
const { baseUrl, authToken, endpoint, file, fileName, additionalFields, requestId, customFetch, } = args;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
// Build the full URL
|
|
69
|
+
const url = `${baseUrl}${endpoint}`;
|
|
70
|
+
let body;
|
|
71
|
+
const headers = {
|
|
72
|
+
Authorization: `Bearer ${authToken}`,
|
|
73
|
+
};
|
|
74
|
+
if (requestId) {
|
|
75
|
+
headers['X-Request-Id'] = requestId;
|
|
76
76
|
}
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
if (file instanceof Blob) {
|
|
78
|
+
// Browser path: use native FormData
|
|
79
|
+
const form = new globalThis.FormData();
|
|
80
|
+
const resolvedFileName = fileName || (file instanceof File ? file.name : undefined) || 'upload';
|
|
81
|
+
form.append('file', file, resolvedFileName);
|
|
82
|
+
for (const [key, value] of Object.entries(additionalFields)) {
|
|
83
|
+
if (value !== undefined && value !== null) {
|
|
84
|
+
form.append(key, value.toString());
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
form.append('file', file, {
|
|
85
|
-
filename: fileName,
|
|
86
|
-
contentType: contentType,
|
|
87
|
-
});
|
|
87
|
+
// Don't set Content-Type — let fetch set it with the correct multipart boundary
|
|
88
|
+
body = form;
|
|
88
89
|
}
|
|
89
90
|
else {
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
// Node path: dynamically import Node-only modules
|
|
92
|
+
const [FormDataModule, fsModule, pathModule] = await Promise.all([
|
|
93
|
+
import('form-data'),
|
|
94
|
+
import('fs'),
|
|
95
|
+
import('path'),
|
|
96
|
+
]);
|
|
97
|
+
const FormData = FormDataModule.default;
|
|
98
|
+
const form = new FormData();
|
|
99
|
+
if (typeof file === 'string') {
|
|
100
|
+
// File path - create read stream
|
|
101
|
+
const resolvedFileName = fileName || pathModule.basename(file);
|
|
102
|
+
form.append('file', fsModule.createReadStream(file), resolvedFileName);
|
|
93
103
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
else if (Buffer.isBuffer(file)) {
|
|
105
|
+
// Buffer - require fileName
|
|
106
|
+
if (!fileName) {
|
|
107
|
+
throw new Error('fileName is required when uploading from a Buffer');
|
|
108
|
+
}
|
|
109
|
+
const contentType = getContentTypeFromFileName(fileName);
|
|
110
|
+
form.append('file', file, {
|
|
111
|
+
filename: fileName,
|
|
112
|
+
contentType: contentType,
|
|
113
|
+
});
|
|
100
114
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
115
|
+
else {
|
|
116
|
+
// Stream - require fileName
|
|
117
|
+
if (!fileName) {
|
|
118
|
+
throw new Error('fileName is required when uploading from a stream');
|
|
119
|
+
}
|
|
120
|
+
form.append('file', file, fileName);
|
|
121
|
+
}
|
|
122
|
+
for (const [key, value] of Object.entries(additionalFields)) {
|
|
123
|
+
if (value !== undefined && value !== null) {
|
|
124
|
+
form.append(key, value.toString());
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
Object.assign(headers, form.getHeaders());
|
|
128
|
+
body = form;
|
|
108
129
|
}
|
|
109
130
|
// Make the request using fetch
|
|
110
131
|
const response = await fetchWithRetry({
|
|
111
132
|
url,
|
|
112
133
|
options: {
|
|
113
134
|
method: 'POST',
|
|
114
|
-
body
|
|
135
|
+
body,
|
|
115
136
|
headers,
|
|
116
137
|
timeout: 30000, // 30 second timeout for file uploads
|
|
117
138
|
},
|
|
@@ -29,6 +29,8 @@ export declare const ENDPOINT_REST_ACTIVITIES = "activities";
|
|
|
29
29
|
export declare const ENDPOINT_REST_UPLOADS = "uploads";
|
|
30
30
|
export declare const PROJECT_ARCHIVE = "archive";
|
|
31
31
|
export declare const PROJECT_UNARCHIVE = "unarchive";
|
|
32
|
+
export declare const ENDPOINT_REST_PROJECTS_MOVE_TO_WORKSPACE: string;
|
|
33
|
+
export declare const ENDPOINT_REST_PROJECTS_MOVE_TO_PERSONAL: string;
|
|
32
34
|
export declare const ENDPOINT_SYNC_QUICK_ADD: string;
|
|
33
35
|
export declare const ENDPOINT_SYNC = "sync";
|
|
34
36
|
export declare const ENDPOINT_AUTHORIZATION = "authorize";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Attachment, PersonalProject, WorkspaceProject, Label, Section, Comment, Task, CurrentUser, ProductivityStats, WorkspaceInvitation, WorkspacePlanDetails, JoinWorkspaceResult, Workspace } from './types/entities.js';
|
|
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 } from './types/requests.js';
|
|
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
3
|
import { CustomFetch } from './types/http.js';
|
|
4
4
|
/**
|
|
5
5
|
* A client for interacting with the Todoist API v1.
|
|
@@ -239,6 +239,22 @@ export declare class TodoistApi {
|
|
|
239
239
|
* @returns A promise that resolves to the updated project.
|
|
240
240
|
*/
|
|
241
241
|
unarchiveProject(id: string, requestId?: string): Promise<PersonalProject | WorkspaceProject>;
|
|
242
|
+
/**
|
|
243
|
+
* Moves a project to a workspace.
|
|
244
|
+
*
|
|
245
|
+
* @param args - The arguments for moving the project.
|
|
246
|
+
* @param requestId - Optional custom identifier for the request.
|
|
247
|
+
* @returns A promise that resolves to the moved project.
|
|
248
|
+
*/
|
|
249
|
+
moveProjectToWorkspace(args: MoveProjectToWorkspaceArgs, requestId?: string): Promise<PersonalProject | WorkspaceProject>;
|
|
250
|
+
/**
|
|
251
|
+
* Moves a project to personal.
|
|
252
|
+
*
|
|
253
|
+
* @param args - The arguments for moving the project.
|
|
254
|
+
* @param requestId - Optional custom identifier for the request.
|
|
255
|
+
* @returns A promise that resolves to the moved project.
|
|
256
|
+
*/
|
|
257
|
+
moveProjectToPersonal(args: MoveProjectToPersonalArgs, requestId?: string): Promise<PersonalProject | WorkspaceProject>;
|
|
242
258
|
/**
|
|
243
259
|
* Retrieves a list of collaborators for a specific project.
|
|
244
260
|
*
|
|
@@ -243,6 +243,12 @@ export declare const PersonalProjectSchema: z.ZodPipe<z.ZodObject<{
|
|
|
243
243
|
parentId: string | null;
|
|
244
244
|
inboxProject: boolean;
|
|
245
245
|
}>>;
|
|
246
|
+
export declare const ProjectVisibilitySchema: z.ZodEnum<{
|
|
247
|
+
restricted: "restricted";
|
|
248
|
+
team: "team";
|
|
249
|
+
public: "public";
|
|
250
|
+
}>;
|
|
251
|
+
export type ProjectVisibility = z.infer<typeof ProjectVisibilitySchema>;
|
|
246
252
|
/**
|
|
247
253
|
* Schema for workspace projects in Todoist.
|
|
248
254
|
*/
|
|
@@ -263,6 +269,13 @@ export declare const WorkspaceProjectSchema: z.ZodPipe<z.ZodObject<{
|
|
|
263
269
|
description: z.ZodString;
|
|
264
270
|
isCollapsed: z.ZodBoolean;
|
|
265
271
|
isShared: z.ZodBoolean;
|
|
272
|
+
access: z.ZodOptional<z.ZodObject<{
|
|
273
|
+
visibility: z.ZodEnum<{
|
|
274
|
+
restricted: "restricted";
|
|
275
|
+
team: "team";
|
|
276
|
+
public: "public";
|
|
277
|
+
}>;
|
|
278
|
+
}, z.core.$strip>>;
|
|
266
279
|
collaboratorRoleDefault: z.ZodString;
|
|
267
280
|
folderId: z.ZodNullable<z.ZodString>;
|
|
268
281
|
isInviteOnly: z.ZodNullable<z.ZodBoolean>;
|
|
@@ -295,6 +308,9 @@ export declare const WorkspaceProjectSchema: z.ZodPipe<z.ZodObject<{
|
|
|
295
308
|
role: string | null;
|
|
296
309
|
status: string;
|
|
297
310
|
workspaceId: string;
|
|
311
|
+
access?: {
|
|
312
|
+
visibility: "restricted" | "team" | "public";
|
|
313
|
+
} | undefined;
|
|
298
314
|
}, {
|
|
299
315
|
id: string;
|
|
300
316
|
canAssignTasks: boolean;
|
|
@@ -319,6 +335,9 @@ export declare const WorkspaceProjectSchema: z.ZodPipe<z.ZodObject<{
|
|
|
319
335
|
role: string | null;
|
|
320
336
|
status: string;
|
|
321
337
|
workspaceId: string;
|
|
338
|
+
access?: {
|
|
339
|
+
visibility: "restricted" | "team" | "public";
|
|
340
|
+
} | undefined;
|
|
322
341
|
}>>;
|
|
323
342
|
/**
|
|
324
343
|
* Represents a personal project in Todoist.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RequireAllOrNone, RequireOneOrNone, RequireExactlyOne } from 'type-fest';
|
|
2
|
-
import type { ActivityEvent, ActivityEventType, ActivityObjectType, Comment, Duration, Label, PersonalProject, ProjectViewStyle, Section, Task, User, WorkspaceProject } from './entities.js';
|
|
2
|
+
import type { ActivityEvent, ActivityEventType, ActivityObjectType, Comment, Duration, Label, PersonalProject, ProjectViewStyle, ProjectVisibility, Section, Task, User, WorkspaceProject } from './entities.js';
|
|
3
3
|
/**
|
|
4
4
|
* Arguments for creating a new task.
|
|
5
5
|
* @see https://todoist.com/api/v1/docs#tag/Tasks/operation/create_task_api_v1_tasks_post
|
|
@@ -511,10 +511,10 @@ export type UploadFileArgs = {
|
|
|
511
511
|
* - ReadableStream: File content as a stream (requires fileName)
|
|
512
512
|
* - string: Path to a file on the filesystem (fileName is optional, will be inferred from path)
|
|
513
513
|
*/
|
|
514
|
-
file: Buffer | NodeJS.ReadableStream | string;
|
|
514
|
+
file: Buffer | NodeJS.ReadableStream | string | Blob;
|
|
515
515
|
/**
|
|
516
516
|
* The name of the file. Required for Buffer and Stream inputs.
|
|
517
|
-
* Optional for file path strings (will be inferred
|
|
517
|
+
* Optional for file path strings and File objects (will be inferred if not provided).
|
|
518
518
|
*/
|
|
519
519
|
fileName?: string;
|
|
520
520
|
/**
|
|
@@ -532,6 +532,28 @@ export type DeleteUploadArgs = {
|
|
|
532
532
|
*/
|
|
533
533
|
fileUrl: string;
|
|
534
534
|
};
|
|
535
|
+
/**
|
|
536
|
+
* Arguments for moving a project to a workspace.
|
|
537
|
+
*/
|
|
538
|
+
export type MoveProjectToWorkspaceArgs = {
|
|
539
|
+
/** The ID of the project to move. */
|
|
540
|
+
projectId: string;
|
|
541
|
+
/** The target workspace ID. */
|
|
542
|
+
workspaceId: string;
|
|
543
|
+
/** Optional target folder ID within the workspace. */
|
|
544
|
+
folderId?: string | null;
|
|
545
|
+
/** Optional access settings for the project in the workspace. */
|
|
546
|
+
access?: {
|
|
547
|
+
visibility: ProjectVisibility;
|
|
548
|
+
};
|
|
549
|
+
};
|
|
550
|
+
/**
|
|
551
|
+
* Arguments for moving a project to personal.
|
|
552
|
+
*/
|
|
553
|
+
export type MoveProjectToPersonalArgs = {
|
|
554
|
+
/** The ID of the project to move. */
|
|
555
|
+
projectId: string;
|
|
556
|
+
};
|
|
535
557
|
/**
|
|
536
558
|
* Arguments for getting workspace invitations.
|
|
537
559
|
*/
|
|
@@ -587,7 +609,7 @@ export type WorkspaceLogoArgs = {
|
|
|
587
609
|
/**
|
|
588
610
|
* The image file to upload (Buffer, Stream, or file path).
|
|
589
611
|
*/
|
|
590
|
-
file?: Buffer | NodeJS.ReadableStream | string;
|
|
612
|
+
file?: Buffer | NodeJS.ReadableStream | string | Blob;
|
|
591
613
|
/**
|
|
592
614
|
* The file name (required for Buffer/Stream uploads).
|
|
593
615
|
*/
|
|
@@ -3,7 +3,7 @@ type UploadMultipartFileArgs = {
|
|
|
3
3
|
baseUrl: string;
|
|
4
4
|
authToken: string;
|
|
5
5
|
endpoint: string;
|
|
6
|
-
file: Buffer | NodeJS.ReadableStream | string;
|
|
6
|
+
file: Buffer | NodeJS.ReadableStream | string | Blob;
|
|
7
7
|
fileName?: string;
|
|
8
8
|
additionalFields: Record<string, string | number | boolean>;
|
|
9
9
|
requestId?: string;
|
|
@@ -15,11 +15,13 @@ type UploadMultipartFileArgs = {
|
|
|
15
15
|
* This is a shared utility for uploading files to Todoist endpoints that require
|
|
16
16
|
* multipart/form-data content type (e.g., file uploads, workspace logo uploads).
|
|
17
17
|
*
|
|
18
|
+
* Supports both browser (Blob/File) and Node.js (Buffer/ReadableStream/path) environments.
|
|
19
|
+
*
|
|
18
20
|
* @param baseUrl - The base API URL (e.g., https://api.todoist.com/api/v1/)
|
|
19
21
|
* @param authToken - The authentication token
|
|
20
22
|
* @param endpoint - The relative endpoint path (e.g., 'uploads', 'workspaces/logo')
|
|
21
|
-
* @param file - The file content (
|
|
22
|
-
* @param fileName - Optional file name (required for Buffer/Stream, optional for paths)
|
|
23
|
+
* @param file - The file content (Blob/File for browser, or Buffer/ReadableStream/path for Node)
|
|
24
|
+
* @param fileName - Optional file name (required for Buffer/Stream, optional for paths and File objects)
|
|
23
25
|
* @param additionalFields - Additional form fields to include (e.g., project_id, workspace_id)
|
|
24
26
|
* @param requestId - Optional request ID for idempotency
|
|
25
27
|
* @returns The response data from the server
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doist/todoist-api-typescript",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.1",
|
|
4
4
|
"description": "A typescript wrapper for the Todoist REST API.",
|
|
5
5
|
"author": "Doist developers",
|
|
6
6
|
"repository": "https://github.com/Doist/todoist-api-typescript",
|
|
@@ -44,11 +44,11 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"camelcase": "6.3.0",
|
|
46
46
|
"emoji-regex": "10.6.0",
|
|
47
|
-
"form-data": "4.0.
|
|
47
|
+
"form-data": "4.0.5",
|
|
48
48
|
"ts-custom-error": "^3.2.0",
|
|
49
49
|
"undici": "^7.16.0",
|
|
50
50
|
"uuid": "11.1.0",
|
|
51
|
-
"zod": "4.
|
|
51
|
+
"zod": "4.3.6"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@doist/eslint-config": "12.0.0",
|
|
@@ -63,15 +63,15 @@
|
|
|
63
63
|
"eslint-plugin-prettier": "5.1.3",
|
|
64
64
|
"husky": "9.1.7",
|
|
65
65
|
"jest": "30.1.3",
|
|
66
|
-
"lint-staged": "16.
|
|
67
|
-
"msw": "2.
|
|
66
|
+
"lint-staged": "16.2.7",
|
|
67
|
+
"msw": "2.12.10",
|
|
68
68
|
"npm-run-all2": "8.0.4",
|
|
69
69
|
"obsidian": "^1.10.2-1",
|
|
70
70
|
"prettier": "3.3.2",
|
|
71
|
-
"rimraf": "6.
|
|
72
|
-
"ts-jest": "29.4.
|
|
71
|
+
"rimraf": "6.1.2",
|
|
72
|
+
"ts-jest": "29.4.6",
|
|
73
73
|
"ts-node": "10.9.2",
|
|
74
|
-
"type-fest": "^
|
|
74
|
+
"type-fest": "^5.0.0",
|
|
75
75
|
"typescript": "5.9.3"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|