@doist/todoist-sdk 14.2.0 → 15.0.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 (166) hide show
  1. package/dist/esm/utils/index.js +1 -1
  2. package/dist/esm/utils/url-helpers.js +151 -23
  3. package/dist/types/utils/index.d.ts +2 -1
  4. package/dist/types/utils/url-helpers.d.ts +88 -0
  5. package/package.json +5 -10
  6. package/dist/cjs/authentication.js +0 -317
  7. package/dist/cjs/clients/activity-client.js +0 -63
  8. package/dist/cjs/clients/app-client.js +0 -345
  9. package/dist/cjs/clients/backup-client.js +0 -47
  10. package/dist/cjs/clients/base-client.js +0 -31
  11. package/dist/cjs/clients/billing-client.js +0 -152
  12. package/dist/cjs/clients/comment-client.js +0 -91
  13. package/dist/cjs/clients/email-client.js +0 -43
  14. package/dist/cjs/clients/folder-client.js +0 -79
  15. package/dist/cjs/clients/id-mapping-client.js +0 -39
  16. package/dist/cjs/clients/insights-client.js +0 -87
  17. package/dist/cjs/clients/label-client.js +0 -126
  18. package/dist/cjs/clients/productivity-client.js +0 -27
  19. package/dist/cjs/clients/project-client.js +0 -235
  20. package/dist/cjs/clients/reminder-client.js +0 -198
  21. package/dist/cjs/clients/section-client.js +0 -117
  22. package/dist/cjs/clients/task-client.js +0 -254
  23. package/dist/cjs/clients/template-client.js +0 -88
  24. package/dist/cjs/clients/ui-extension-client.js +0 -107
  25. package/dist/cjs/clients/upload-client.js +0 -155
  26. package/dist/cjs/clients/view-options-client.js +0 -25
  27. package/dist/cjs/clients/workspace-client.js +0 -366
  28. package/dist/cjs/consts/endpoints.js +0 -224
  29. package/dist/cjs/index.js +0 -24
  30. package/dist/cjs/package.json +0 -1
  31. package/dist/cjs/test-utils/asserts.js +0 -11
  32. package/dist/cjs/test-utils/msw-setup.js +0 -97
  33. package/dist/cjs/test-utils/obsidian-fetch-adapter.js +0 -54
  34. package/dist/cjs/test-utils/test-defaults.js +0 -371
  35. package/dist/cjs/test-utils/transport-seam.js +0 -17
  36. package/dist/cjs/test-utils/webhook-fixtures.js +0 -32
  37. package/dist/cjs/todoist-api.js +0 -1711
  38. package/dist/cjs/transport/fetch-with-retry.js +0 -219
  39. package/dist/cjs/transport/http-client.js +0 -134
  40. package/dist/cjs/transport/http-dispatcher.js +0 -198
  41. package/dist/cjs/transport/sync-request.js +0 -83
  42. package/dist/cjs/types/activity/index.js +0 -18
  43. package/dist/cjs/types/activity/requests.js +0 -2
  44. package/dist/cjs/types/activity/types.js +0 -28
  45. package/dist/cjs/types/apps/index.js +0 -18
  46. package/dist/cjs/types/apps/requests.js +0 -2
  47. package/dist/cjs/types/apps/types.js +0 -254
  48. package/dist/cjs/types/backups/index.js +0 -18
  49. package/dist/cjs/types/backups/requests.js +0 -2
  50. package/dist/cjs/types/backups/types.js +0 -8
  51. package/dist/cjs/types/billing/index.js +0 -18
  52. package/dist/cjs/types/billing/requests.js +0 -2
  53. package/dist/cjs/types/billing/types.js +0 -92
  54. package/dist/cjs/types/comments/index.js +0 -18
  55. package/dist/cjs/types/comments/requests.js +0 -2
  56. package/dist/cjs/types/comments/types.js +0 -60
  57. package/dist/cjs/types/common.js +0 -10
  58. package/dist/cjs/types/emails/index.js +0 -17
  59. package/dist/cjs/types/emails/requests.js +0 -5
  60. package/dist/cjs/types/errors.js +0 -29
  61. package/dist/cjs/types/folders/index.js +0 -17
  62. package/dist/cjs/types/folders/requests.js +0 -2
  63. package/dist/cjs/types/http.js +0 -24
  64. package/dist/cjs/types/id-mappings/index.js +0 -18
  65. package/dist/cjs/types/id-mappings/requests.js +0 -20
  66. package/dist/cjs/types/id-mappings/types.js +0 -12
  67. package/dist/cjs/types/index.js +0 -40
  68. package/dist/cjs/types/insights/index.js +0 -18
  69. package/dist/cjs/types/insights/requests.js +0 -2
  70. package/dist/cjs/types/insights/types.js +0 -80
  71. package/dist/cjs/types/labels/index.js +0 -18
  72. package/dist/cjs/types/labels/requests.js +0 -2
  73. package/dist/cjs/types/labels/types.js +0 -11
  74. package/dist/cjs/types/productivity/index.js +0 -17
  75. package/dist/cjs/types/productivity/types.js +0 -68
  76. package/dist/cjs/types/projects/index.js +0 -18
  77. package/dist/cjs/types/projects/requests.js +0 -2
  78. package/dist/cjs/types/projects/types.js +0 -66
  79. package/dist/cjs/types/reminders/index.js +0 -17
  80. package/dist/cjs/types/reminders/requests.js +0 -95
  81. package/dist/cjs/types/sections/index.js +0 -18
  82. package/dist/cjs/types/sections/requests.js +0 -2
  83. package/dist/cjs/types/sections/types.js +0 -25
  84. package/dist/cjs/types/sync/commands/calendars.js +0 -2
  85. package/dist/cjs/types/sync/commands/filters.js +0 -2
  86. package/dist/cjs/types/sync/commands/folders.js +0 -2
  87. package/dist/cjs/types/sync/commands/index.js +0 -34
  88. package/dist/cjs/types/sync/commands/labels.js +0 -5
  89. package/dist/cjs/types/sync/commands/notes.js +0 -2
  90. package/dist/cjs/types/sync/commands/notifications.js +0 -2
  91. package/dist/cjs/types/sync/commands/others.js +0 -2
  92. package/dist/cjs/types/sync/commands/project-view-options.js +0 -2
  93. package/dist/cjs/types/sync/commands/projects.js +0 -2
  94. package/dist/cjs/types/sync/commands/reminders.js +0 -2
  95. package/dist/cjs/types/sync/commands/sections.js +0 -2
  96. package/dist/cjs/types/sync/commands/shared.js +0 -20
  97. package/dist/cjs/types/sync/commands/sharing.js +0 -2
  98. package/dist/cjs/types/sync/commands/tasks.js +0 -2
  99. package/dist/cjs/types/sync/commands/view-options.js +0 -2
  100. package/dist/cjs/types/sync/commands/workspace-filters.js +0 -2
  101. package/dist/cjs/types/sync/commands/workspaces.js +0 -2
  102. package/dist/cjs/types/sync/index.js +0 -22
  103. package/dist/cjs/types/sync/request.js +0 -2
  104. package/dist/cjs/types/sync/resource-types.js +0 -39
  105. package/dist/cjs/types/sync/resources/calendars.js +0 -27
  106. package/dist/cjs/types/sync/resources/collaborators.js +0 -21
  107. package/dist/cjs/types/sync/resources/completed-info.js +0 -24
  108. package/dist/cjs/types/sync/resources/filters.js +0 -14
  109. package/dist/cjs/types/sync/resources/folders.js +0 -12
  110. package/dist/cjs/types/sync/resources/index.js +0 -32
  111. package/dist/cjs/types/sync/resources/live-notifications.js +0 -38
  112. package/dist/cjs/types/sync/resources/notes.js +0 -21
  113. package/dist/cjs/types/sync/resources/reminders.js +0 -50
  114. package/dist/cjs/types/sync/resources/suggestions.js +0 -36
  115. package/dist/cjs/types/sync/resources/tooltips.js +0 -8
  116. package/dist/cjs/types/sync/resources/user-plan-limits.js +0 -20
  117. package/dist/cjs/types/sync/resources/user-settings.js +0 -40
  118. package/dist/cjs/types/sync/resources/user.js +0 -110
  119. package/dist/cjs/types/sync/resources/view-options.js +0 -86
  120. package/dist/cjs/types/sync/resources/workspace-filters.js +0 -19
  121. package/dist/cjs/types/sync/resources/workspaces.js +0 -72
  122. package/dist/cjs/types/sync/response.js +0 -54
  123. package/dist/cjs/types/sync/user-preferences.js +0 -71
  124. package/dist/cjs/types/tasks/index.js +0 -18
  125. package/dist/cjs/types/tasks/requests.js +0 -2
  126. package/dist/cjs/types/tasks/types.js +0 -59
  127. package/dist/cjs/types/templates/index.js +0 -17
  128. package/dist/cjs/types/templates/requests.js +0 -2
  129. package/dist/cjs/types/ui-extensions/index.js +0 -18
  130. package/dist/cjs/types/ui-extensions/requests.js +0 -2
  131. package/dist/cjs/types/ui-extensions/types.js +0 -77
  132. package/dist/cjs/types/uploads/index.js +0 -17
  133. package/dist/cjs/types/uploads/requests.js +0 -2
  134. package/dist/cjs/types/users/index.js +0 -17
  135. package/dist/cjs/types/users/types.js +0 -51
  136. package/dist/cjs/types/webhooks/comments.js +0 -96
  137. package/dist/cjs/types/webhooks/envelope.js +0 -26
  138. package/dist/cjs/types/webhooks/filters.js +0 -30
  139. package/dist/cjs/types/webhooks/index.js +0 -25
  140. package/dist/cjs/types/webhooks/labels.js +0 -54
  141. package/dist/cjs/types/webhooks/projects.js +0 -36
  142. package/dist/cjs/types/webhooks/reminders.js +0 -35
  143. package/dist/cjs/types/webhooks/sections.js +0 -53
  144. package/dist/cjs/types/webhooks/tasks.js +0 -68
  145. package/dist/cjs/types/webhooks/types.js +0 -55
  146. package/dist/cjs/types/workspaces/index.js +0 -18
  147. package/dist/cjs/types/workspaces/requests.js +0 -2
  148. package/dist/cjs/types/workspaces/types.js +0 -154
  149. package/dist/cjs/utils/activity-helpers.js +0 -58
  150. package/dist/cjs/utils/case-conversion.js +0 -69
  151. package/dist/cjs/utils/colors.js +0 -143
  152. package/dist/cjs/utils/file-response.js +0 -32
  153. package/dist/cjs/utils/headers.js +0 -16
  154. package/dist/cjs/utils/index.js +0 -31
  155. package/dist/cjs/utils/multipart-upload.js +0 -293
  156. package/dist/cjs/utils/processing-helpers.js +0 -18
  157. package/dist/cjs/utils/project-helpers.js +0 -20
  158. package/dist/cjs/utils/request-helpers.js +0 -21
  159. package/dist/cjs/utils/sanitization.js +0 -116
  160. package/dist/cjs/utils/sync-helpers.js +0 -22
  161. package/dist/cjs/utils/task-sorting.js +0 -281
  162. package/dist/cjs/utils/uncompletable-helpers.js +0 -60
  163. package/dist/cjs/utils/url-helpers.js +0 -74
  164. package/dist/cjs/utils/validators.js +0 -108
  165. package/dist/cjs/utils/view-options.js +0 -19
  166. package/dist/cjs/utils/webhook-parser.js +0 -60
@@ -1,293 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
36
- var __asyncValues = (this && this.__asyncValues) || function (o) {
37
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
38
- var m = o[Symbol.asyncIterator], i;
39
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
40
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
41
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
42
- };
43
- var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
44
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
45
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
46
- return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
47
- function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
48
- function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
49
- function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
50
- function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
51
- function fulfill(value) { resume("next", value); }
52
- function reject(value) { resume("throw", value); }
53
- function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
54
- };
55
- Object.defineProperty(exports, "__esModule", { value: true });
56
- exports.uploadMultipartFile = uploadMultipartFile;
57
- const uuid_1 = require("uuid");
58
- const fetch_with_retry_1 = require("../transport/fetch-with-retry");
59
- const case_conversion_1 = require("./case-conversion");
60
- /**
61
- * Helper function to determine content-type from filename extension.
62
- * @param fileName - The filename to analyze
63
- * @returns The appropriate MIME type
64
- */
65
- function getContentTypeFromFileName(fileName) {
66
- const extension = fileName.toLowerCase().split('.').pop();
67
- switch (extension) {
68
- case 'png':
69
- return 'image/png';
70
- case 'jpg':
71
- case 'jpeg':
72
- return 'image/jpeg';
73
- case 'gif':
74
- return 'image/gif';
75
- case 'webp':
76
- return 'image/webp';
77
- case 'svg':
78
- return 'image/svg+xml';
79
- default:
80
- return 'application/octet-stream';
81
- }
82
- }
83
- /**
84
- * Escapes a value for use inside a quoted `Content-Disposition` parameter,
85
- * where a raw quote would end the value early and a raw CR or LF would end the
86
- * header. Note that a lone CR needs escaping too, not just CRLF pairs.
87
- *
88
- * This is the same escaping the platform's own `FormData` encoder applies, so
89
- * servers see exactly what they would from any browser or from undici.
90
- */
91
- function escapeDispositionValue(value) {
92
- return value.replace(/"/g, '%22').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
93
- }
94
- /**
95
- * Lays out a `multipart/form-data` payload around a single file part, as the
96
- * text that goes before and after the file content. Keeping the file content
97
- * out of it lets the same layout serve both a `Blob` body and a streamed one.
98
- */
99
- function layOutMultipart(args) {
100
- const { fileName, fileContentType, additionalFields } = args;
101
- const boundary = `----todoist-sdk-${(0, uuid_1.v4)()}`;
102
- const head = `--${boundary}\r\n` +
103
- `Content-Disposition: form-data; name="file"; filename="${escapeDispositionValue(fileName)}"\r\n` +
104
- `Content-Type: ${fileContentType}\r\n\r\n`;
105
- let tail = '\r\n';
106
- for (const [key, value] of Object.entries(additionalFields)) {
107
- if (value !== undefined && value !== null) {
108
- tail +=
109
- `--${boundary}\r\n` +
110
- `Content-Disposition: form-data; name="${escapeDispositionValue(key)}"\r\n\r\n` +
111
- `${value.toString()}\r\n`;
112
- }
113
- }
114
- tail += `--${boundary}--\r\n`;
115
- return { boundary, head, tail };
116
- }
117
- /**
118
- * Wraps a Node readable stream as a `multipart/form-data` request body.
119
- *
120
- * The result is a web `ReadableStream`, which both the runtime's `fetch` and
121
- * undici's own accept — unlike a Node stream or a `FormData`, either of which
122
- * only works with one particular client. The file is never buffered, so the
123
- * request is sent with `Transfer-Encoding: chunked`.
124
- */
125
- function streamMultipartBody(file, parts) {
126
- const encoder = new TextEncoder();
127
- function chunks() {
128
- return __asyncGenerator(this, arguments, function* chunks_1() {
129
- var _a, e_1, _b, _c;
130
- yield yield __await(encoder.encode(parts.head));
131
- try {
132
- for (var _d = true, file_1 = __asyncValues(file), file_1_1; file_1_1 = yield __await(file_1.next()), _a = file_1_1.done, !_a; _d = true) {
133
- _c = file_1_1.value;
134
- _d = false;
135
- const chunk = _c;
136
- yield yield __await(typeof chunk === 'string' ? encoder.encode(chunk) : new Uint8Array(chunk));
137
- }
138
- }
139
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
140
- finally {
141
- try {
142
- if (!_d && !_a && (_b = file_1.return)) yield __await(_b.call(file_1));
143
- }
144
- finally { if (e_1) throw e_1.error; }
145
- }
146
- yield yield __await(encoder.encode(parts.tail));
147
- });
148
- }
149
- const iterator = chunks();
150
- // Driven by hand rather than with `ReadableStream.from`, which is absent
151
- // from this project's DOM lib types and is still missing in some browsers,
152
- // or `Readable.toWeb`, which would drag a Node-only import into a module
153
- // that browsers also load.
154
- return new ReadableStream({
155
- async pull(controller) {
156
- const { value, done } = await iterator.next();
157
- if (done) {
158
- controller.close();
159
- return;
160
- }
161
- controller.enqueue(value);
162
- },
163
- async cancel(reason) {
164
- var _a;
165
- await ((_a = iterator.return) === null || _a === void 0 ? void 0 : _a.call(iterator, reason));
166
- },
167
- });
168
- }
169
- /**
170
- * Builds the request body for a multipart upload.
171
- *
172
- * Deliberately avoids `FormData`. A `FormData` body is only encoded by the
173
- * `fetch` that owns that `FormData` class — undici brands its own — so a body
174
- * built from the global `FormData` and sent through undici's `fetch`, or the
175
- * reverse, is stringified to the literal `"[object FormData]"` and the upload
176
- * silently carries no file. The `form-data` package fares worse: neither
177
- * `fetch` accepts it as a body at all. `Blob` and `ReadableStream` carry no
178
- * such brand and work with whichever `fetch` dispatches the request,
179
- * including a caller-supplied `customFetch`.
180
- */
181
- function buildMultipartBody(args) {
182
- const { file, fileName, fileContentType, additionalFields } = args;
183
- const parts = layOutMultipart({ fileName, fileContentType, additionalFields });
184
- const contentType = `multipart/form-data; boundary=${parts.boundary}`;
185
- if (file instanceof Blob) {
186
- // A Blob keeps its length, so the request gets a Content-Length and
187
- // stays replayable if it has to be retried. File-backed Blobs (from
188
- // `fs.openAsBlob`) stay lazy here, so nothing is read into memory.
189
- return { body: new Blob([parts.head, file, parts.tail]), contentType, isStreamed: false };
190
- }
191
- return { body: streamMultipartBody(file, parts), contentType, isStreamed: true };
192
- }
193
- /**
194
- * Uploads a file using multipart/form-data.
195
- *
196
- * This is a shared utility for uploading files to Todoist endpoints that require
197
- * multipart/form-data content type (e.g., file uploads, workspace logo uploads).
198
- *
199
- * Supports both browser (Blob/File) and Node.js (Buffer/ReadableStream/path) environments.
200
- *
201
- * @param baseUrl - The base API URL (e.g., https://api.todoist.com/api/v1/)
202
- * @param authToken - The authentication token
203
- * @param endpoint - The relative endpoint path (e.g., 'uploads', 'workspaces/logo')
204
- * @param file - The file content (Blob/File for browser, or Buffer/ReadableStream/path for Node)
205
- * @param fileName - Optional file name (required for Buffer/Stream, optional for paths and File objects)
206
- * @param additionalFields - Additional form fields to include (e.g., project_id, workspace_id)
207
- * @param requestId - Optional request ID for idempotency
208
- * @returns The response data from the server
209
- *
210
- * @example
211
- * ```typescript
212
- * // Upload from a file path
213
- * const result = await uploadMultipartFile(
214
- * 'https://api.todoist.com/api/v1/',
215
- * 'my-token',
216
- * 'uploads',
217
- * '/path/to/file.pdf',
218
- * undefined,
219
- * { project_id: '12345' }
220
- * )
221
- *
222
- * // Upload from a Buffer
223
- * const buffer = Buffer.from('file content')
224
- * const result = await uploadMultipartFile(
225
- * 'https://api.todoist.com/api/v1/',
226
- * 'my-token',
227
- * 'uploads',
228
- * buffer,
229
- * 'document.pdf',
230
- * { project_id: '12345' }
231
- * )
232
- * ```
233
- */
234
- async function uploadMultipartFile(args) {
235
- const { baseUrl, authToken, endpoint, file, fileName, additionalFields, requestId, customFetch, } = args;
236
- // Build the full URL
237
- const url = `${baseUrl}${endpoint}`;
238
- let body;
239
- const headers = {
240
- Authorization: `Bearer ${authToken}`,
241
- };
242
- if (requestId) {
243
- headers['X-Request-Id'] = requestId;
244
- }
245
- // Resolve the file to something every `fetch` accepts as a body part: a
246
- // Blob where the size is known up front, or a Node stream that gets piped
247
- // through untouched.
248
- let filePart;
249
- let resolvedFileName;
250
- if (file instanceof Blob) {
251
- filePart = file;
252
- resolvedFileName = fileName || (file instanceof File ? file.name : undefined) || 'upload';
253
- }
254
- else if (typeof file === 'string') {
255
- // File path: Node-only, so import lazily to keep browser bundles clean.
256
- const [fsModule, pathModule] = await Promise.all([Promise.resolve().then(() => __importStar(require('fs'))), Promise.resolve().then(() => __importStar(require('path')))]);
257
- resolvedFileName = fileName || pathModule.basename(file);
258
- // `openAsBlob` reads the file lazily, so a large upload is not pulled
259
- // into memory, and the resulting body still has a known length.
260
- filePart = await fsModule.openAsBlob(file);
261
- }
262
- else if (Buffer.isBuffer(file)) {
263
- if (!fileName) {
264
- throw new Error('fileName is required when uploading from a Buffer');
265
- }
266
- resolvedFileName = fileName;
267
- filePart = new Blob([
268
- new Uint8Array(file.buffer, file.byteOffset, file.byteLength),
269
- ]);
270
- }
271
- else {
272
- if (!fileName) {
273
- throw new Error('fileName is required when uploading from a stream');
274
- }
275
- resolvedFileName = fileName;
276
- filePart = file;
277
- }
278
- const multipart = buildMultipartBody({
279
- file: filePart,
280
- fileName: resolvedFileName,
281
- fileContentType: (filePart instanceof Blob ? filePart.type : undefined) ||
282
- getContentTypeFromFileName(resolvedFileName),
283
- additionalFields,
284
- });
285
- // The boundary is ours, so Content-Type has to be set explicitly — `fetch`
286
- // only fills it in for a `FormData` body.
287
- headers['Content-Type'] = multipart.contentType;
288
- body = multipart.body;
289
- // Make the request using fetch
290
- const response = await (0, fetch_with_retry_1.fetchWithRetry)(Object.assign(Object.assign({ url, options: Object.assign({ method: 'POST', body,
291
- headers, timeout: 30000 }, (multipart.isStreamed ? { duplex: 'half' } : {})) }, (multipart.isStreamed ? { retryConfig: { retries: 0 } } : {})), { customFetch }));
292
- return (0, case_conversion_1.camelCaseKeys)(response.data);
293
- }
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.customCamelCase = customCamelCase;
7
- const camelcase_1 = __importDefault(require("camelcase"));
8
- const emoji_regex_1 = __importDefault(require("emoji-regex"));
9
- function isEmojiKey(key) {
10
- const regex = (0, emoji_regex_1.default)();
11
- return regex.test(key);
12
- }
13
- function customCamelCase(input) {
14
- // If the value is a solitary emoji string, return the key as-is
15
- if (isEmojiKey(input))
16
- return input;
17
- return (0, camelcase_1.default)(input);
18
- }
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isWorkspaceProject = isWorkspaceProject;
4
- exports.isPersonalProject = isPersonalProject;
5
- /**
6
- * Type guard to check if a project is a workspace project.
7
- * @param project The project to check
8
- * @returns True if the project is a workspace project
9
- */
10
- function isWorkspaceProject(project) {
11
- return 'workspaceId' in project;
12
- }
13
- /**
14
- * Type guard to check if a project is a personal project.
15
- * @param project The project to check
16
- * @returns True if the project is a personal project
17
- */
18
- function isPersonalProject(project) {
19
- return !isWorkspaceProject(project);
20
- }
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generatePath = generatePath;
4
- exports.spreadIfDefined = spreadIfDefined;
5
- /**
6
- * Joins path segments using `/` separator.
7
- * @param segments A list of **valid** path segments.
8
- * @returns A joined path.
9
- */
10
- function generatePath(...segments) {
11
- return segments.join('/');
12
- }
13
- /**
14
- * Returns `fn(value)` spread into an object if `value` is defined, otherwise an empty object.
15
- *
16
- * Used to conditionally include a property on a payload object without
17
- * resorting to mutation or ternary-built object literals.
18
- */
19
- function spreadIfDefined(value, fn) {
20
- return value !== undefined ? fn(value) : {};
21
- }
@@ -1,116 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSanitizedContent = getSanitizedContent;
4
- exports.getSanitizedTasks = getSanitizedTasks;
5
- const BOLD_FORMAT = /(^|[\s!?,;>:]+)(?:\*\*|__|!!)(.+?)(\*\*|__|!!)(?=$|[\s!?,;><:]+)/gi;
6
- const ITALIC_FORMAT = /(^|[\s!?,;>:]+)(?:\*|_|!)(.+?)(\*|_|!)(?=$|[\s!?,;><:]+)/gi;
7
- const BOLD_ITALIC_FORMAT = /(^|[\s!?,;>:]+)(?:\*\*\*|___|!!!)(.+?)(\*\*\*|___|!!!)(?=$|[\s!?,;><:]+)/gi;
8
- const CODE_BLOCK_FORMAT = /```([\s\S]*?)```/gi;
9
- const CODE_INLINE_FORMAT = /`([^`]+)`/gi;
10
- const TODOIST_LINK = /((?:(?:onenote:)?[\w-]+):\/\/[^\s]+)\s+[[(]([^)]+)[\])]/gi;
11
- const MARKDOWN_LINK = /\[(.+?)\]\((.+?)\)/gi;
12
- const GMAIL_LINK = /\[\[gmail=(.+?),\s*(.+?)\]\]/gi;
13
- const OUTLOOK_LINK = /\[\[outlook=(.+?),\s*(.+?)\]\]/gi;
14
- const THUNDERBIRD_LINK = /\[\[thunderbird\n(.+)\n(.+)\n\s*\]\]/gi;
15
- const FAKE_SECTION_PREFIX = '* ';
16
- const FAKE_SECTION_SUFFIX = ':';
17
- function removeStyleFormatting(input) {
18
- if (!input.includes('!') && !input.includes('*') && !input.includes('_')) {
19
- return input;
20
- }
21
- function removeMarkdown(_match, prefix, text) {
22
- return `${prefix}${text}`;
23
- }
24
- input = input.replace(BOLD_ITALIC_FORMAT, removeMarkdown);
25
- input = input.replace(BOLD_FORMAT, removeMarkdown);
26
- input = input.replace(ITALIC_FORMAT, removeMarkdown);
27
- return input;
28
- }
29
- function removeCodeFormatting(input) {
30
- function removeMarkdown(_match, text) {
31
- return text;
32
- }
33
- input = input.replace(CODE_BLOCK_FORMAT, removeMarkdown);
34
- input = input.replace(CODE_INLINE_FORMAT, removeMarkdown);
35
- return input;
36
- }
37
- function removeFakeSectionFormatting(input) {
38
- if (input.startsWith(FAKE_SECTION_PREFIX)) {
39
- input = input.slice(FAKE_SECTION_PREFIX.length);
40
- }
41
- if (input.endsWith(FAKE_SECTION_SUFFIX)) {
42
- input = input.slice(0, input.length - FAKE_SECTION_SUFFIX.length);
43
- }
44
- return input;
45
- }
46
- function removeMarkdownLinks(input) {
47
- if (!input.includes('[') || !input.includes(']')) {
48
- return input;
49
- }
50
- function removeMarkdown(_match, text) {
51
- return text;
52
- }
53
- return input.replace(MARKDOWN_LINK, removeMarkdown);
54
- }
55
- function removeTodoistLinks(input) {
56
- if (!input.includes('(') || !input.includes(')')) {
57
- return input;
58
- }
59
- function removeMarkdown(_match, _url, text) {
60
- return text;
61
- }
62
- return input.replace(TODOIST_LINK, removeMarkdown);
63
- }
64
- function removeAppLinks(input) {
65
- if (input.includes('gmail')) {
66
- input = input.replace(GMAIL_LINK, (_match, _id, text) => text);
67
- }
68
- if (input.includes('outlook')) {
69
- input = input.replace(OUTLOOK_LINK, (_match, _id, text) => text);
70
- }
71
- if (input.includes('thunderbird')) {
72
- input = input.replace(THUNDERBIRD_LINK, (_match, text) => text);
73
- }
74
- return input;
75
- }
76
- /**
77
- * Sanitizes a string by removing Todoist's formatting syntax (e.g. bold, italic, code blocks, links).
78
- *
79
- * @example
80
- * // Removes bold/italic formatting
81
- * getSanitizedContent('Some **bold** and *italic*') // 'Some bold and italic'
82
- *
83
- * // Removes markdown links
84
- * getSanitizedContent('A [markdown](http://url.com) link') // 'A markdown link'
85
- *
86
- * // Removes app-specific links
87
- * getSanitizedContent('A [[gmail=id, link from gmail]]') // 'A link from gmail'
88
- *
89
- * @param input - The string to sanitize
90
- * @returns The sanitized string with all formatting removed
91
- */
92
- function getSanitizedContent(input) {
93
- input = removeStyleFormatting(input);
94
- input = removeCodeFormatting(input);
95
- input = removeFakeSectionFormatting(input);
96
- input = removeMarkdownLinks(input);
97
- input = removeTodoistLinks(input);
98
- input = removeAppLinks(input);
99
- return input;
100
- }
101
- /**
102
- * Takes an array of tasks and returns a new array with sanitized content
103
- * added as 'sanitizedContent' property to each task.
104
- *
105
- * @see {@link getSanitizedContent}
106
- *
107
- * @example
108
- * const tasks = [{ content: '**Bold** task', ... }]
109
- * getSanitizedTasks(tasks) // [{ content: '**Bold** task', sanitizedContent: 'Bold task', ... }]
110
- *
111
- * @param tasks - Array of Task objects to sanitize
112
- * @returns Array of tasks with added sanitizedContent property
113
- */
114
- function getSanitizedTasks(tasks) {
115
- return tasks.map((task) => (Object.assign(Object.assign({}, task), { sanitizedContent: getSanitizedContent(task.content) })));
116
- }
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createCommand = createCommand;
4
- const uuid_1 = require("uuid");
5
- /**
6
- * Creates a strongly-typed Sync API command with an auto-generated UUID.
7
- *
8
- * @param type - The command type (e.g. `'item_add'`, `'project_update'`).
9
- * @param args - The command arguments, constrained by the command type.
10
- * @param tempId - Optional temporary ID for referencing the created resource in subsequent commands.
11
- * @returns A fully formed `SyncCommand` ready to include in a sync request.
12
- *
13
- * @example
14
- * ```typescript
15
- * const cmd = createCommand('item_add', { content: 'Buy milk', priority: 2 })
16
- * // cmd.type === 'item_add'
17
- * // cmd.args is typed as TaskAddArgs
18
- * ```
19
- */
20
- function createCommand(type, args, tempId) {
21
- return Object.assign({ type, uuid: (0, uuid_1.v4)(), args: args }, (tempId !== undefined ? { tempId } : {}));
22
- }