@doist/todoist-sdk 14.1.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 (172) hide show
  1. package/README.md +46 -1
  2. package/dist/esm/index.js +1 -1
  3. package/dist/esm/transport/http-dispatcher.js +25 -0
  4. package/dist/esm/utils/index.js +1 -1
  5. package/dist/esm/utils/multipart-upload.js +171 -57
  6. package/dist/esm/utils/url-helpers.js +151 -23
  7. package/dist/types/index.d.ts +2 -1
  8. package/dist/types/transport/http-dispatcher.d.ts +26 -1
  9. package/dist/types/utils/index.d.ts +2 -1
  10. package/dist/types/utils/url-helpers.d.ts +88 -0
  11. package/package.json +6 -12
  12. package/dist/cjs/authentication.js +0 -317
  13. package/dist/cjs/clients/activity-client.js +0 -63
  14. package/dist/cjs/clients/app-client.js +0 -345
  15. package/dist/cjs/clients/backup-client.js +0 -47
  16. package/dist/cjs/clients/base-client.js +0 -31
  17. package/dist/cjs/clients/billing-client.js +0 -152
  18. package/dist/cjs/clients/comment-client.js +0 -91
  19. package/dist/cjs/clients/email-client.js +0 -43
  20. package/dist/cjs/clients/folder-client.js +0 -79
  21. package/dist/cjs/clients/id-mapping-client.js +0 -39
  22. package/dist/cjs/clients/insights-client.js +0 -87
  23. package/dist/cjs/clients/label-client.js +0 -126
  24. package/dist/cjs/clients/productivity-client.js +0 -27
  25. package/dist/cjs/clients/project-client.js +0 -235
  26. package/dist/cjs/clients/reminder-client.js +0 -198
  27. package/dist/cjs/clients/section-client.js +0 -117
  28. package/dist/cjs/clients/task-client.js +0 -254
  29. package/dist/cjs/clients/template-client.js +0 -88
  30. package/dist/cjs/clients/ui-extension-client.js +0 -107
  31. package/dist/cjs/clients/upload-client.js +0 -155
  32. package/dist/cjs/clients/view-options-client.js +0 -25
  33. package/dist/cjs/clients/workspace-client.js +0 -366
  34. package/dist/cjs/consts/endpoints.js +0 -224
  35. package/dist/cjs/index.js +0 -23
  36. package/dist/cjs/package.json +0 -1
  37. package/dist/cjs/test-utils/asserts.js +0 -11
  38. package/dist/cjs/test-utils/msw-setup.js +0 -97
  39. package/dist/cjs/test-utils/obsidian-fetch-adapter.js +0 -54
  40. package/dist/cjs/test-utils/test-defaults.js +0 -371
  41. package/dist/cjs/test-utils/transport-seam.js +0 -17
  42. package/dist/cjs/test-utils/webhook-fixtures.js +0 -32
  43. package/dist/cjs/todoist-api.js +0 -1711
  44. package/dist/cjs/transport/fetch-with-retry.js +0 -219
  45. package/dist/cjs/transport/http-client.js +0 -134
  46. package/dist/cjs/transport/http-dispatcher.js +0 -173
  47. package/dist/cjs/transport/sync-request.js +0 -83
  48. package/dist/cjs/types/activity/index.js +0 -18
  49. package/dist/cjs/types/activity/requests.js +0 -2
  50. package/dist/cjs/types/activity/types.js +0 -28
  51. package/dist/cjs/types/apps/index.js +0 -18
  52. package/dist/cjs/types/apps/requests.js +0 -2
  53. package/dist/cjs/types/apps/types.js +0 -254
  54. package/dist/cjs/types/backups/index.js +0 -18
  55. package/dist/cjs/types/backups/requests.js +0 -2
  56. package/dist/cjs/types/backups/types.js +0 -8
  57. package/dist/cjs/types/billing/index.js +0 -18
  58. package/dist/cjs/types/billing/requests.js +0 -2
  59. package/dist/cjs/types/billing/types.js +0 -92
  60. package/dist/cjs/types/comments/index.js +0 -18
  61. package/dist/cjs/types/comments/requests.js +0 -2
  62. package/dist/cjs/types/comments/types.js +0 -60
  63. package/dist/cjs/types/common.js +0 -10
  64. package/dist/cjs/types/emails/index.js +0 -17
  65. package/dist/cjs/types/emails/requests.js +0 -5
  66. package/dist/cjs/types/errors.js +0 -29
  67. package/dist/cjs/types/folders/index.js +0 -17
  68. package/dist/cjs/types/folders/requests.js +0 -2
  69. package/dist/cjs/types/http.js +0 -24
  70. package/dist/cjs/types/id-mappings/index.js +0 -18
  71. package/dist/cjs/types/id-mappings/requests.js +0 -20
  72. package/dist/cjs/types/id-mappings/types.js +0 -12
  73. package/dist/cjs/types/index.js +0 -40
  74. package/dist/cjs/types/insights/index.js +0 -18
  75. package/dist/cjs/types/insights/requests.js +0 -2
  76. package/dist/cjs/types/insights/types.js +0 -80
  77. package/dist/cjs/types/labels/index.js +0 -18
  78. package/dist/cjs/types/labels/requests.js +0 -2
  79. package/dist/cjs/types/labels/types.js +0 -11
  80. package/dist/cjs/types/productivity/index.js +0 -17
  81. package/dist/cjs/types/productivity/types.js +0 -68
  82. package/dist/cjs/types/projects/index.js +0 -18
  83. package/dist/cjs/types/projects/requests.js +0 -2
  84. package/dist/cjs/types/projects/types.js +0 -66
  85. package/dist/cjs/types/reminders/index.js +0 -17
  86. package/dist/cjs/types/reminders/requests.js +0 -95
  87. package/dist/cjs/types/sections/index.js +0 -18
  88. package/dist/cjs/types/sections/requests.js +0 -2
  89. package/dist/cjs/types/sections/types.js +0 -25
  90. package/dist/cjs/types/sync/commands/calendars.js +0 -2
  91. package/dist/cjs/types/sync/commands/filters.js +0 -2
  92. package/dist/cjs/types/sync/commands/folders.js +0 -2
  93. package/dist/cjs/types/sync/commands/index.js +0 -34
  94. package/dist/cjs/types/sync/commands/labels.js +0 -5
  95. package/dist/cjs/types/sync/commands/notes.js +0 -2
  96. package/dist/cjs/types/sync/commands/notifications.js +0 -2
  97. package/dist/cjs/types/sync/commands/others.js +0 -2
  98. package/dist/cjs/types/sync/commands/project-view-options.js +0 -2
  99. package/dist/cjs/types/sync/commands/projects.js +0 -2
  100. package/dist/cjs/types/sync/commands/reminders.js +0 -2
  101. package/dist/cjs/types/sync/commands/sections.js +0 -2
  102. package/dist/cjs/types/sync/commands/shared.js +0 -20
  103. package/dist/cjs/types/sync/commands/sharing.js +0 -2
  104. package/dist/cjs/types/sync/commands/tasks.js +0 -2
  105. package/dist/cjs/types/sync/commands/view-options.js +0 -2
  106. package/dist/cjs/types/sync/commands/workspace-filters.js +0 -2
  107. package/dist/cjs/types/sync/commands/workspaces.js +0 -2
  108. package/dist/cjs/types/sync/index.js +0 -22
  109. package/dist/cjs/types/sync/request.js +0 -2
  110. package/dist/cjs/types/sync/resource-types.js +0 -39
  111. package/dist/cjs/types/sync/resources/calendars.js +0 -27
  112. package/dist/cjs/types/sync/resources/collaborators.js +0 -21
  113. package/dist/cjs/types/sync/resources/completed-info.js +0 -24
  114. package/dist/cjs/types/sync/resources/filters.js +0 -14
  115. package/dist/cjs/types/sync/resources/folders.js +0 -12
  116. package/dist/cjs/types/sync/resources/index.js +0 -32
  117. package/dist/cjs/types/sync/resources/live-notifications.js +0 -38
  118. package/dist/cjs/types/sync/resources/notes.js +0 -21
  119. package/dist/cjs/types/sync/resources/reminders.js +0 -50
  120. package/dist/cjs/types/sync/resources/suggestions.js +0 -36
  121. package/dist/cjs/types/sync/resources/tooltips.js +0 -8
  122. package/dist/cjs/types/sync/resources/user-plan-limits.js +0 -20
  123. package/dist/cjs/types/sync/resources/user-settings.js +0 -40
  124. package/dist/cjs/types/sync/resources/user.js +0 -110
  125. package/dist/cjs/types/sync/resources/view-options.js +0 -86
  126. package/dist/cjs/types/sync/resources/workspace-filters.js +0 -19
  127. package/dist/cjs/types/sync/resources/workspaces.js +0 -72
  128. package/dist/cjs/types/sync/response.js +0 -54
  129. package/dist/cjs/types/sync/user-preferences.js +0 -71
  130. package/dist/cjs/types/tasks/index.js +0 -18
  131. package/dist/cjs/types/tasks/requests.js +0 -2
  132. package/dist/cjs/types/tasks/types.js +0 -59
  133. package/dist/cjs/types/templates/index.js +0 -17
  134. package/dist/cjs/types/templates/requests.js +0 -2
  135. package/dist/cjs/types/ui-extensions/index.js +0 -18
  136. package/dist/cjs/types/ui-extensions/requests.js +0 -2
  137. package/dist/cjs/types/ui-extensions/types.js +0 -77
  138. package/dist/cjs/types/uploads/index.js +0 -17
  139. package/dist/cjs/types/uploads/requests.js +0 -2
  140. package/dist/cjs/types/users/index.js +0 -17
  141. package/dist/cjs/types/users/types.js +0 -51
  142. package/dist/cjs/types/webhooks/comments.js +0 -96
  143. package/dist/cjs/types/webhooks/envelope.js +0 -26
  144. package/dist/cjs/types/webhooks/filters.js +0 -30
  145. package/dist/cjs/types/webhooks/index.js +0 -25
  146. package/dist/cjs/types/webhooks/labels.js +0 -54
  147. package/dist/cjs/types/webhooks/projects.js +0 -36
  148. package/dist/cjs/types/webhooks/reminders.js +0 -35
  149. package/dist/cjs/types/webhooks/sections.js +0 -53
  150. package/dist/cjs/types/webhooks/tasks.js +0 -68
  151. package/dist/cjs/types/webhooks/types.js +0 -55
  152. package/dist/cjs/types/workspaces/index.js +0 -18
  153. package/dist/cjs/types/workspaces/requests.js +0 -2
  154. package/dist/cjs/types/workspaces/types.js +0 -154
  155. package/dist/cjs/utils/activity-helpers.js +0 -58
  156. package/dist/cjs/utils/case-conversion.js +0 -69
  157. package/dist/cjs/utils/colors.js +0 -143
  158. package/dist/cjs/utils/file-response.js +0 -32
  159. package/dist/cjs/utils/headers.js +0 -16
  160. package/dist/cjs/utils/index.js +0 -31
  161. package/dist/cjs/utils/multipart-upload.js +0 -179
  162. package/dist/cjs/utils/processing-helpers.js +0 -18
  163. package/dist/cjs/utils/project-helpers.js +0 -20
  164. package/dist/cjs/utils/request-helpers.js +0 -21
  165. package/dist/cjs/utils/sanitization.js +0 -116
  166. package/dist/cjs/utils/sync-helpers.js +0 -22
  167. package/dist/cjs/utils/task-sorting.js +0 -281
  168. package/dist/cjs/utils/uncompletable-helpers.js +0 -60
  169. package/dist/cjs/utils/url-helpers.js +0 -74
  170. package/dist/cjs/utils/validators.js +0 -108
  171. package/dist/cjs/utils/view-options.js +0 -19
  172. package/dist/cjs/utils/webhook-parser.js +0 -60
@@ -1,219 +0,0 @@
1
- "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.fetchWithRetry = fetchWithRetry;
15
- const http_1 = require("../types/http");
16
- const http_dispatcher_1 = require("./http-dispatcher");
17
- /**
18
- * Default retry configuration matching the original axios-retry behavior
19
- */
20
- const DEFAULT_RETRY_CONFIG = {
21
- retries: 3,
22
- retryCondition: http_1.isNetworkError,
23
- retryDelay: (retryNumber) => {
24
- // First retry: immediate (0ms delay)
25
- // Subsequent retries: 500ms delay
26
- return retryNumber === 1 ? 0 : 500;
27
- },
28
- };
29
- const TIMEOUT_ERROR_NAME = 'TimeoutError';
30
- function createTimeoutError(timeoutMs) {
31
- const error = new Error(`Request timeout after ${timeoutMs}ms`);
32
- error.name = TIMEOUT_ERROR_NAME;
33
- return error;
34
- }
35
- /**
36
- * Converts Headers object to a plain object
37
- */
38
- function headersToObject(headers) {
39
- const result = {};
40
- headers.forEach((value, key) => {
41
- result[key] = value;
42
- });
43
- return result;
44
- }
45
- /**
46
- * Creates an AbortSignal that aborts after timeoutMs. Returns the signal and a
47
- * clear function to cancel the timeout early.
48
- */
49
- function createTimeoutSignal(timeoutMs, existingSignal) {
50
- const controller = new AbortController();
51
- // Timeout logic
52
- const timeoutId = setTimeout(() => {
53
- controller.abort(createTimeoutError(timeoutMs));
54
- }, timeoutMs);
55
- let abortHandler;
56
- function clear() {
57
- clearTimeout(timeoutId);
58
- if (existingSignal && abortHandler) {
59
- existingSignal.removeEventListener('abort', abortHandler);
60
- }
61
- }
62
- // If there's an existing signal, forward its abort
63
- if (existingSignal) {
64
- if (existingSignal.aborted) {
65
- clearTimeout(timeoutId);
66
- controller.abort(existingSignal.reason);
67
- }
68
- else {
69
- abortHandler = () => {
70
- clearTimeout(timeoutId);
71
- controller.abort(existingSignal.reason);
72
- };
73
- existingSignal.addEventListener('abort', abortHandler, { once: true });
74
- }
75
- }
76
- // Clean up timeout when request completes
77
- controller.signal.addEventListener('abort', () => {
78
- clearTimeout(timeoutId);
79
- });
80
- return { signal: controller.signal, clear };
81
- }
82
- /**
83
- * Converts native fetch Response to CustomFetchResponse for consistency
84
- */
85
- function convertResponseToCustomFetch(response) {
86
- // Clone the response so we can read it multiple times (if clone method exists)
87
- const clonedResponse = response.clone ? response.clone() : response;
88
- return {
89
- ok: response.ok,
90
- status: response.status,
91
- statusText: response.statusText,
92
- headers: headersToObject(response.headers),
93
- text: () => clonedResponse.text(),
94
- json: () => response.json(),
95
- arrayBuffer: () => response.arrayBuffer(),
96
- };
97
- }
98
- /**
99
- * Performs a fetch request with retry logic and timeout support
100
- */
101
- async function fetchWithRetry(args) {
102
- var _a;
103
- const { url, options = {}, retryConfig = {}, customFetch } = args;
104
- const config = Object.assign(Object.assign({}, DEFAULT_RETRY_CONFIG), retryConfig);
105
- const { timeout, signal: userSignal } = options, fetchOptions = __rest(options, ["timeout", "signal"]);
106
- let lastError;
107
- for (let attempt = 0; attempt <= config.retries; attempt++) {
108
- // Timeout clear function for this attempt (hoisted for catch scope)
109
- let clearTimeoutFn;
110
- try {
111
- // Set up timeout and signal handling
112
- let requestSignal = userSignal || undefined;
113
- if (timeout && timeout > 0) {
114
- const timeoutResult = createTimeoutSignal(timeout, requestSignal);
115
- requestSignal = timeoutResult.signal;
116
- clearTimeoutFn = timeoutResult.clear;
117
- }
118
- // Use custom fetch or native fetch
119
- let fetchResponse;
120
- if (customFetch) {
121
- fetchResponse = await customFetch(url, Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal, timeout }));
122
- }
123
- else {
124
- // Read the dispatcher and its paired `fetch` as one value so
125
- // they can never be mismatched. On Node, `fetch` is undici's
126
- // own — paired with the dispatcher — so the request client and
127
- // dispatcher stay on one undici version; otherwise the
128
- // `decompress` interceptor terminates gzip responses when the
129
- // global `fetch`'s bundled undici differs. Browser/edge (and
130
- // Bun) have no paired `fetch` and fall back to the global one.
131
- const transport = await (0, http_dispatcher_1.getDefaultTransport)();
132
- const nativeFetchOptions = Object.assign(Object.assign({}, fetchOptions), { signal: requestSignal });
133
- if ((transport === null || transport === void 0 ? void 0 : transport.dispatcher) !== undefined) {
134
- // @ts-expect-error - dispatcher is a valid option for Node.js fetch but not in the TS types
135
- nativeFetchOptions.dispatcher = transport.dispatcher;
136
- }
137
- // undici's `fetch` and the global `fetch` are the same function
138
- // at runtime but carry different (undici vs DOM) types. Call
139
- // through the global signature, which matches the options above.
140
- const fetchImpl = ((_a = transport === null || transport === void 0 ? void 0 : transport.fetch) !== null && _a !== void 0 ? _a : fetch);
141
- const nativeResponse = await fetchImpl(url, nativeFetchOptions);
142
- fetchResponse = convertResponseToCustomFetch(nativeResponse);
143
- }
144
- // Check if the response is successful
145
- if (!fetchResponse.ok) {
146
- const errorMessage = `HTTP ${fetchResponse.status}: ${fetchResponse.statusText}`;
147
- const error = new Error(errorMessage);
148
- error.status = fetchResponse.status;
149
- error.statusText = fetchResponse.statusText;
150
- error.response = {
151
- data: undefined, // Will be set below if we can parse the response
152
- status: fetchResponse.status,
153
- statusText: fetchResponse.statusText,
154
- headers: fetchResponse.headers,
155
- };
156
- // Try to get response body for error details
157
- try {
158
- const responseText = await fetchResponse.text();
159
- let responseData;
160
- try {
161
- responseData = responseText ? JSON.parse(responseText) : undefined;
162
- }
163
- catch (_b) {
164
- responseData = responseText;
165
- }
166
- error.data = responseData;
167
- error.response.data = responseData;
168
- }
169
- catch (_c) {
170
- // If we can't read the response body, that's OK
171
- }
172
- throw error;
173
- }
174
- // Parse response
175
- const responseText = await fetchResponse.text();
176
- let data;
177
- try {
178
- data = responseText ? JSON.parse(responseText) : undefined;
179
- }
180
- catch (_d) {
181
- // If JSON parsing fails, return the raw text
182
- data = responseText;
183
- }
184
- // Success – clear pending timeout (if any) so Node can exit promptly
185
- if (clearTimeoutFn) {
186
- clearTimeoutFn();
187
- }
188
- return {
189
- data,
190
- status: fetchResponse.status,
191
- statusText: fetchResponse.statusText,
192
- headers: fetchResponse.headers,
193
- };
194
- }
195
- catch (error) {
196
- if (clearTimeoutFn) {
197
- clearTimeoutFn();
198
- }
199
- lastError = error;
200
- // Check if this error should trigger a retry
201
- const shouldRetry = attempt < config.retries && config.retryCondition(lastError);
202
- if (!shouldRetry) {
203
- // Add network error flag for network errors
204
- if ((0, http_1.isNetworkError)(lastError)) {
205
- const networkError = lastError;
206
- networkError.isNetworkError = true;
207
- }
208
- throw lastError;
209
- }
210
- // Wait before retrying
211
- const delay = config.retryDelay(attempt + 1);
212
- if (delay > 0) {
213
- await new Promise((resolve) => setTimeout(resolve, delay));
214
- }
215
- }
216
- }
217
- // This should never be reached, but just in case
218
- throw lastError || new Error('Request failed after retries');
219
- }
@@ -1,134 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.paramsSerializer = paramsSerializer;
4
- exports.isSuccess = isSuccess;
5
- exports.request = request;
6
- const uuid_1 = require("uuid");
7
- const endpoints_1 = require("../consts/endpoints");
8
- const errors_1 = require("../types/errors");
9
- const http_1 = require("../types/http");
10
- const case_conversion_1 = require("../utils/case-conversion");
11
- const fetch_with_retry_1 = require("./fetch-with-retry");
12
- function paramsSerializer(params) {
13
- const qs = new URLSearchParams();
14
- Object.keys(params).forEach((key) => {
15
- const value = params[key];
16
- if (value !== null && value !== undefined) {
17
- if (Array.isArray(value)) {
18
- qs.append(key, JSON.stringify(value));
19
- }
20
- else if (typeof value === 'string' ||
21
- typeof value === 'number' ||
22
- typeof value === 'boolean') {
23
- qs.append(key, String(value));
24
- }
25
- else {
26
- qs.append(key, JSON.stringify(value));
27
- }
28
- }
29
- });
30
- return qs.toString();
31
- }
32
- const defaultHeaders = {
33
- 'Content-Type': 'application/json',
34
- };
35
- function getAuthHeader(apiKey) {
36
- return `Bearer ${apiKey}`;
37
- }
38
- function getRetryDelay(retryCount) {
39
- return retryCount === 1 ? 0 : 500;
40
- }
41
- function getTodoistRequestError(args) {
42
- const { error, originalStack } = args;
43
- const requestError = new errors_1.TodoistRequestError(error.message);
44
- requestError.stack = originalStack ? originalStack.stack : error.stack;
45
- if ((0, http_1.isHttpError)(error)) {
46
- requestError.httpStatusCode = error.status;
47
- requestError.responseData = error.data;
48
- }
49
- return requestError;
50
- }
51
- function getRequestConfiguration(args) {
52
- const { baseURL, apiToken, requestId, customHeaders } = args;
53
- const authHeader = apiToken ? { Authorization: getAuthHeader(apiToken) } : undefined;
54
- const requestIdHeader = requestId ? { 'X-Request-Id': requestId } : undefined;
55
- const headers = Object.assign(Object.assign(Object.assign(Object.assign({}, defaultHeaders), authHeader), requestIdHeader), customHeaders);
56
- return { baseURL, headers };
57
- }
58
- function getHttpClientConfig(args) {
59
- const { baseURL, apiToken, requestId, customHeaders } = args;
60
- const configuration = getRequestConfiguration({ baseURL, apiToken, requestId, customHeaders });
61
- return Object.assign(Object.assign({}, configuration), { timeout: 30000, retry: {
62
- retries: 3,
63
- retryCondition: http_1.isNetworkError,
64
- retryDelay: getRetryDelay,
65
- } });
66
- }
67
- function isSuccess(response) {
68
- return response.status >= 200 && response.status < 300;
69
- }
70
- async function request(args) {
71
- const { httpMethod, baseUri, relativePath, apiToken, payload, requestId: initialRequestId, hasSyncCommands, customHeaders, customFetch, } = args;
72
- // Capture original stack for better error reporting
73
- const originalStack = new Error();
74
- try {
75
- let requestId = initialRequestId;
76
- // Sync api don't allow a request id in the CORS
77
- if (httpMethod === 'POST' && !requestId && !baseUri.includes(endpoints_1.API_BASE_URI)) {
78
- requestId = (0, uuid_1.v4)();
79
- }
80
- const config = getHttpClientConfig({ baseURL: baseUri, apiToken, requestId, customHeaders });
81
- const url = `${baseUri}${relativePath}`;
82
- const fetchOptions = {
83
- method: httpMethod,
84
- headers: config.headers,
85
- timeout: config.timeout,
86
- };
87
- let finalUrl = url;
88
- switch (httpMethod) {
89
- case 'GET':
90
- // For GET requests, add query parameters to URL
91
- if (payload) {
92
- // Convert payload from camelCase to snake_case
93
- const convertedPayload = (0, case_conversion_1.snakeCaseKeys)(payload);
94
- const queryString = paramsSerializer(convertedPayload);
95
- if (queryString) {
96
- const separator = url.includes('?') ? '&' : '?';
97
- finalUrl = `${url}${separator}${queryString}`;
98
- }
99
- }
100
- break;
101
- case 'POST':
102
- case 'PUT':
103
- case 'PATCH':
104
- case 'DELETE': {
105
- // Convert payload from camelCase to snake_case
106
- // Note: While DELETE with body is uncommon, the Todoist API uses it for some endpoints
107
- if (payload) {
108
- const convertedPayload = (0, case_conversion_1.snakeCaseKeys)(payload);
109
- const body = hasSyncCommands
110
- ? JSON.stringify(convertedPayload)
111
- : JSON.stringify(convertedPayload);
112
- fetchOptions.body = body;
113
- }
114
- break;
115
- }
116
- }
117
- // Make the request
118
- const response = await (0, fetch_with_retry_1.fetchWithRetry)({
119
- url: finalUrl,
120
- options: fetchOptions,
121
- retryConfig: config.retry,
122
- customFetch,
123
- });
124
- // Convert snake_case response to camelCase
125
- const convertedData = (0, case_conversion_1.camelCaseKeys)(response.data);
126
- return Object.assign(Object.assign({}, response), { data: convertedData });
127
- }
128
- catch (error) {
129
- if (!(error instanceof Error)) {
130
- throw new Error('An unknown error occurred during the request');
131
- }
132
- throw getTodoistRequestError({ error, originalStack });
133
- }
134
- }
@@ -1,173 +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
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.getDefaultTransport = getDefaultTransport;
37
- exports.getDefaultDispatcher = getDefaultDispatcher;
38
- exports.getDefaultFetch = getDefaultFetch;
39
- exports.resetDefaultDispatcherForTests = resetDefaultDispatcherForTests;
40
- exports.suppressExperimentalWarningsSync = suppressExperimentalWarningsSync;
41
- // Use effectively-disabled keep-alive so short-lived CLI processes do not stay
42
- // open waiting on idle sockets. Undici requires positive values, so we use 1ms.
43
- const KEEP_ALIVE_OPTIONS = {
44
- keepAliveTimeout: 1,
45
- keepAliveMaxTimeout: 1,
46
- };
47
- let defaultTransport;
48
- let defaultTransportPromise;
49
- /**
50
- * The default dispatcher and its paired `fetch`, as a single value so the two
51
- * are always read consistently. Resolves to `undefined` outside Node (browser/
52
- * edge), where callers use the global `fetch` with no dispatcher.
53
- */
54
- function getDefaultTransport() {
55
- if (!isNodeEnvironment()) {
56
- return Promise.resolve(undefined);
57
- }
58
- if (!defaultTransportPromise) {
59
- defaultTransportPromise = createDefaultTransport()
60
- .then((transport) => {
61
- defaultTransport = transport;
62
- return transport;
63
- })
64
- .catch((error) => {
65
- defaultTransport = undefined;
66
- defaultTransportPromise = undefined;
67
- throw error;
68
- });
69
- }
70
- return defaultTransportPromise;
71
- }
72
- async function getDefaultDispatcher() {
73
- var _a;
74
- return (_a = (await getDefaultTransport())) === null || _a === void 0 ? void 0 : _a.dispatcher;
75
- }
76
- /**
77
- * The `fetch` implementation that must be used with the default dispatcher.
78
- * Returns undici's own `fetch` on the full-undici Node path, or `undefined`
79
- * (meaning: use the global `fetch`) in the browser/edge/Bun paths.
80
- *
81
- * Node's global `fetch` is backed by whatever undici version ships inside that
82
- * Node release (6.x on Node 22 … 8.x on Node 26). Our dispatcher — and its
83
- * `decompress` interceptor — comes from the npm `undici` package, which is a
84
- * different version. Handing an npm-undici dispatcher to a mismatched built-in
85
- * client makes gzip responses fail mid-stream with `terminated`. Sourcing
86
- * `fetch` from the same npm `undici` keeps the whole request path on one
87
- * version and removes the split.
88
- *
89
- * Only meaningful after {@link getDefaultTransport} has resolved, which is the
90
- * one place that populates it.
91
- */
92
- function getDefaultFetch() {
93
- return defaultTransport === null || defaultTransport === void 0 ? void 0 : defaultTransport.fetch;
94
- }
95
- async function resetDefaultDispatcherForTests() {
96
- if (!defaultTransportPromise) {
97
- return;
98
- }
99
- const transportPromise = defaultTransportPromise;
100
- defaultTransport = undefined;
101
- defaultTransportPromise = undefined;
102
- await transportPromise.then((transport) => transport.dispatcher.close(), () => undefined);
103
- }
104
- async function createDefaultTransport() {
105
- // Dynamic import so non-Node consumers (browser, edge runtimes) don't pull
106
- // undici into their bundle. `getDefaultTransport` already short-circuits
107
- // outside Node, so this branch only runs when undici is safe to load.
108
- const { EnvHttpProxyAgent, interceptors, fetch: undiciFetch } = await Promise.resolve().then(() => __importStar(require('undici')));
109
- const agent = new EnvHttpProxyAgent(KEEP_ALIVE_OPTIONS);
110
- // Some runtimes report `process.versions.node` (so `isNodeEnvironment()`
111
- // passes) but ship only a partial undici: `interceptors.decompress` is
112
- // absent and dispatchers have no `.compose`. Bun is the common case. There
113
- // the proxy agent alone is enough — Bun's `fetch` decompresses
114
- // gzip/deflate/br/zstd natively — so skip the interceptor instead of
115
- // crashing on the missing API.
116
- if (typeof interceptors.decompress !== 'function') {
117
- // Bun: pair the agent with the global `fetch` (undefined), which
118
- // decompresses natively.
119
- return { dispatcher: agent, fetch: undefined };
120
- }
121
- // Compose the response-decompression interceptor so gzip/deflate/br/zstd
122
- // bodies are decoded before consumers parse them. Required on Node 24+:
123
- // attaching any custom dispatcher to the global `fetch` strips the
124
- // `content-encoding` header but does not actually decompress the body,
125
- // so callers receive raw gzipped bytes and `JSON.parse` fails.
126
- // See https://github.com/Doist/todoist-cli/issues/318.
127
- const decompress = suppressExperimentalWarningsSync(() => interceptors.decompress());
128
- // Pair undici's own `fetch` with this dispatcher so the request client and
129
- // the dispatcher stay on one undici version (see `getDefaultFetch`). The
130
- // global `fetch` is backed by a different, Node-bundled undici; mixing the
131
- // two makes the decompress interceptor terminate gzip responses on some
132
- // Node versions.
133
- return { dispatcher: agent.compose(decompress), fetch: undiciFetch };
134
- }
135
- // undici emits an `ExperimentalWarning` the first time `interceptors.decompress()`
136
- // runs. The interceptor is stable for our gzipped-JSON-over-HTTPS use case;
137
- // silence the warning during dispatcher init only so it does not leak to every
138
- // consumer's stderr on the first request.
139
- //
140
- // `fn` must be synchronous so the override covers a single critical section
141
- // (microseconds) — no unrelated `ExperimentalWarning` from elsewhere can
142
- // interleave and be lost. We suppress every `ExperimentalWarning` rather than
143
- // pattern-matching the message text: the message wording is an undici
144
- // implementation detail (not a stable API), and the suppression window is
145
- // narrow enough that a coarse type filter is safe.
146
- //
147
- // Exported for direct unit testing — the integration path through
148
- // `getDefaultDispatcher()` cannot reliably exercise the helper because both
149
- // the dispatcher singleton and undici's internal `warningEmitted` flag are
150
- // once-per-process.
151
- function suppressExperimentalWarningsSync(fn) {
152
- const originalEmit = process.emitWarning;
153
- process.emitWarning = ((warning, typeOrOptions, ...rest) => {
154
- const type = typeof typeOrOptions === 'string'
155
- ? typeOrOptions
156
- : typeof typeOrOptions === 'object' && typeOrOptions !== null
157
- ? typeOrOptions.type
158
- : undefined;
159
- if (type === 'ExperimentalWarning')
160
- return;
161
- originalEmit.call(process, warning, typeOrOptions, ...rest);
162
- });
163
- try {
164
- return fn();
165
- }
166
- finally {
167
- process.emitWarning = originalEmit;
168
- }
169
- }
170
- function isNodeEnvironment() {
171
- var _a;
172
- return typeof process !== 'undefined' && Boolean((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
173
- }
@@ -1,83 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.performSyncRequest = performSyncRequest;
4
- const endpoints_1 = require("../consts/endpoints");
5
- const types_1 = require("../types");
6
- const sync_1 = require("../types/sync");
7
- const request_helpers_1 = require("../utils/request-helpers");
8
- const validators_1 = require("../utils/validators");
9
- const http_client_1 = require("./http-client");
10
- function serializeUserUpdateArgs(args) {
11
- return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, args), (0, request_helpers_1.spreadIfDefined)(args.dateFormat, (v) => ({
12
- dateFormat: sync_1.DATE_FORMAT_TO_API[v],
13
- }))), (0, request_helpers_1.spreadIfDefined)(args.timeFormat, (v) => ({
14
- timeFormat: sync_1.TIME_FORMAT_TO_API[v],
15
- }))), (0, request_helpers_1.spreadIfDefined)(args.startDay, (v) => ({
16
- startDay: sync_1.DAY_OF_WEEK_TO_API[v],
17
- }))), (0, request_helpers_1.spreadIfDefined)(args.nextWeek, (v) => ({
18
- nextWeek: sync_1.DAY_OF_WEEK_TO_API[v],
19
- })));
20
- }
21
- function serializeTaskUpdateDateCompleteArgs(args) {
22
- return Object.assign(Object.assign(Object.assign({}, args), { isForward: args.isForward ? 1 : 0 }), (0, request_helpers_1.spreadIfDefined)(args.resetSubtasks, (v) => ({
23
- resetSubtasks: v ? 1 : 0,
24
- })));
25
- }
26
- function serializeUpdateGoalsArgs(args) {
27
- return Object.assign(Object.assign(Object.assign(Object.assign({}, args), (0, request_helpers_1.spreadIfDefined)(args.vacationMode, (v) => ({ vacationMode: v ? 1 : 0 }))), (0, request_helpers_1.spreadIfDefined)(args.karmaDisabled, (v) => ({
28
- karmaDisabled: v ? 1 : 0,
29
- }))), (0, request_helpers_1.spreadIfDefined)(args.ignoreDays, (v) => ({
30
- ignoreDays: v.map((day) => {
31
- const apiValue = sync_1.DAY_OF_WEEK_TO_API[day];
32
- if (apiValue === undefined) {
33
- throw new types_1.TodoistArgumentError(`Invalid ignoreDays entry "${String(day)}". Expected a DayOfWeek (e.g. "Monday").`);
34
- }
35
- return apiValue;
36
- }),
37
- })));
38
- }
39
- function preprocessSyncCommands(commands) {
40
- return commands.map((cmd) => {
41
- if (cmd.type === 'user_update')
42
- return Object.assign(Object.assign({}, cmd), { args: serializeUserUpdateArgs(cmd.args) });
43
- if (cmd.type === 'item_update_date_complete')
44
- return Object.assign(Object.assign({}, cmd), { args: serializeTaskUpdateDateCompleteArgs(cmd.args) });
45
- if (cmd.type === 'update_goals')
46
- return Object.assign(Object.assign({}, cmd), { args: serializeUpdateGoalsArgs(cmd.args) });
47
- return cmd;
48
- });
49
- }
50
- /**
51
- * Makes a request to the Sync API and handles error checking.
52
- *
53
- * @param ctx - HTTP identity (auth token, sync API base URI, optional custom fetch).
54
- * @param syncRequest - The sync request payload.
55
- * @param options - Optional request identifier and commands flag.
56
- * @returns The sync response data.
57
- * @throws TodoistRequestError if sync status contains errors.
58
- */
59
- async function performSyncRequest(ctx, syncRequest, options = {}) {
60
- var _a;
61
- const { requestId, hasSyncCommands = false } = options;
62
- const processedRequest = ((_a = syncRequest.commands) === null || _a === void 0 ? void 0 : _a.length)
63
- ? Object.assign(Object.assign({}, syncRequest), { commands: preprocessSyncCommands(syncRequest.commands) }) : syncRequest;
64
- const response = await (0, http_client_1.request)({
65
- httpMethod: 'POST',
66
- baseUri: ctx.syncApiBase,
67
- relativePath: endpoints_1.ENDPOINT_SYNC,
68
- apiToken: ctx.authToken,
69
- customFetch: ctx.customFetch,
70
- payload: processedRequest,
71
- requestId: requestId,
72
- hasSyncCommands: hasSyncCommands,
73
- });
74
- // Check for sync errors and throw if any are found
75
- if (response.data.syncStatus) {
76
- Object.entries(response.data.syncStatus).forEach(([_, value]) => {
77
- if (value === 'ok')
78
- return;
79
- throw new types_1.TodoistRequestError(value.error, value.httpCode, value.errorExtra);
80
- });
81
- }
82
- return (0, validators_1.parseSyncResponse)(response.data);
83
- }
@@ -1,18 +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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./types"), exports);
18
- __exportStar(require("./requests"), exports);
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,28 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ActivityEventSchema = exports.ActivityEventExtraDataSchema = void 0;
4
- const zod_1 = require("zod");
5
- /**
6
- * Flexible object containing event-specific data.
7
- * Uses z.record to accept any properties for forward compatibility.
8
- */
9
- exports.ActivityEventExtraDataSchema = zod_1.z.record(zod_1.z.string(), zod_1.z.any()).nullable();
10
- /**
11
- * Activity log event schema. Accepts unknown fields for forward compatibility.
12
- */
13
- exports.ActivityEventSchema = zod_1.z
14
- .object({
15
- objectType: zod_1.z.string(),
16
- objectId: zod_1.z.string(),
17
- eventType: zod_1.z.string(),
18
- eventDate: zod_1.z.coerce.date(),
19
- id: zod_1.z
20
- .union([zod_1.z.string(), zod_1.z.number()])
21
- .transform((val) => { var _a; return (_a = val === null || val === void 0 ? void 0 : val.toString()) !== null && _a !== void 0 ? _a : null; })
22
- .nullable(),
23
- parentProjectId: zod_1.z.string().nullable(),
24
- parentItemId: zod_1.z.string().nullable(),
25
- initiatorId: zod_1.z.string().nullable(),
26
- extraData: exports.ActivityEventExtraDataSchema,
27
- })
28
- .catchall(zod_1.z.any());
@@ -1,18 +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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./types"), exports);
18
- __exportStar(require("./requests"), exports);