@doist/todoist-sdk 10.2.0-next.2 → 10.2.0-next.4
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/clients/app-client.js +1 -2
- package/dist/cjs/clients/backup-client.js +3 -21
- package/dist/cjs/clients/goals-client.js +9 -10
- package/dist/cjs/clients/template-client.js +2 -3
- package/dist/cjs/clients/ui-extension-client.js +1 -2
- package/dist/cjs/clients/upload-client.js +3 -22
- package/dist/cjs/test-utils/obsidian-fetch-adapter.js +1 -0
- package/dist/cjs/todoist-api.js +68 -0
- package/dist/cjs/transport/fetch-with-retry.js +1 -0
- package/dist/cjs/utils/file-response.js +32 -0
- package/dist/cjs/utils/multipart-upload.js +2 -1
- package/dist/esm/clients/app-client.js +1 -2
- package/dist/esm/clients/backup-client.js +3 -21
- package/dist/esm/clients/goals-client.js +10 -11
- package/dist/esm/clients/template-client.js +2 -3
- package/dist/esm/clients/ui-extension-client.js +1 -2
- package/dist/esm/clients/upload-client.js +3 -22
- package/dist/esm/test-utils/obsidian-fetch-adapter.js +1 -0
- package/dist/esm/todoist-api.js +68 -0
- package/dist/esm/transport/fetch-with-retry.js +1 -0
- package/dist/esm/utils/file-response.js +29 -0
- package/dist/esm/utils/multipart-upload.js +2 -1
- package/dist/types/todoist-api.d.ts +68 -0
- package/dist/types/types/http.d.ts +7 -1
- package/dist/types/utils/file-response.d.ts +15 -0
- package/dist/types/utils/multipart-upload.d.ts +1 -1
- package/package.json +6 -2
|
@@ -16,7 +16,6 @@ const zod_1 = require("zod");
|
|
|
16
16
|
const endpoints_1 = require("../consts/endpoints");
|
|
17
17
|
const http_client_1 = require("../transport/http-client");
|
|
18
18
|
const apps_1 = require("../types/apps");
|
|
19
|
-
const case_conversion_1 = require("../utils/case-conversion");
|
|
20
19
|
const multipart_upload_1 = require("../utils/multipart-upload");
|
|
21
20
|
const validators_1 = require("../utils/validators");
|
|
22
21
|
const base_client_1 = require("./base-client");
|
|
@@ -145,7 +144,7 @@ class AppClient extends base_client_1.BaseClient {
|
|
|
145
144
|
requestId: requestId,
|
|
146
145
|
customFetch: this.customFetch,
|
|
147
146
|
});
|
|
148
|
-
return (0, validators_1.validateAppWithUserCount)(
|
|
147
|
+
return (0, validators_1.validateAppWithUserCount)(data);
|
|
149
148
|
}
|
|
150
149
|
async getAppTestToken(appId, requestId) {
|
|
151
150
|
validators_1.IdSchema.parse(appId);
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BackupClient = void 0;
|
|
4
4
|
const endpoints_1 = require("../consts/endpoints");
|
|
5
5
|
const http_client_1 = require("../transport/http-client");
|
|
6
|
-
const
|
|
6
|
+
const file_response_1 = require("../utils/file-response");
|
|
7
7
|
const validators_1 = require("../utils/validators");
|
|
8
8
|
const base_client_1 = require("./base-client");
|
|
9
9
|
/**
|
|
@@ -35,31 +35,13 @@ class BackupClient extends base_client_1.BaseClient {
|
|
|
35
35
|
if (!response.ok) {
|
|
36
36
|
throw new Error(`Failed to download backup: ${response.status} ${response.statusText}`);
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
const buffer = new TextEncoder().encode(text).buffer;
|
|
40
|
-
return {
|
|
41
|
-
ok: response.ok,
|
|
42
|
-
status: response.status,
|
|
43
|
-
statusText: response.statusText,
|
|
44
|
-
headers: response.headers,
|
|
45
|
-
text: () => Promise.resolve(text),
|
|
46
|
-
json: () => response.json(),
|
|
47
|
-
arrayBuffer: () => Promise.resolve(buffer),
|
|
48
|
-
};
|
|
38
|
+
return (0, file_response_1.wrapAsFileResponse)(response, 'downloadBackup');
|
|
49
39
|
}
|
|
50
40
|
const response = await fetch(url, fetchOptions);
|
|
51
41
|
if (!response.ok) {
|
|
52
42
|
throw new Error(`Failed to download backup: ${response.status} ${response.statusText}`);
|
|
53
43
|
}
|
|
54
|
-
return
|
|
55
|
-
ok: response.ok,
|
|
56
|
-
status: response.status,
|
|
57
|
-
statusText: response.statusText,
|
|
58
|
-
headers: (0, headers_1.headersToRecord)(response.headers),
|
|
59
|
-
text: () => response.text(),
|
|
60
|
-
json: () => response.json(),
|
|
61
|
-
arrayBuffer: () => response.arrayBuffer(),
|
|
62
|
-
};
|
|
44
|
+
return (0, file_response_1.wrapAsFileResponse)(response, 'downloadBackup');
|
|
63
45
|
}
|
|
64
46
|
}
|
|
65
47
|
exports.BackupClient = BackupClient;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GoalsClient = void 0;
|
|
4
|
-
const zod_1 = require("zod");
|
|
5
4
|
const endpoints_1 = require("../consts/endpoints");
|
|
6
5
|
const http_client_1 = require("../transport/http-client");
|
|
7
6
|
const request_helpers_1 = require("../utils/request-helpers");
|
|
@@ -43,7 +42,7 @@ class GoalsClient extends base_client_1.BaseClient {
|
|
|
43
42
|
};
|
|
44
43
|
}
|
|
45
44
|
async getGoal(id) {
|
|
46
|
-
|
|
45
|
+
validators_1.IdSchema.parse(id);
|
|
47
46
|
const response = await (0, http_client_1.request)({
|
|
48
47
|
httpMethod: 'GET',
|
|
49
48
|
baseUri: this.syncApiBase,
|
|
@@ -66,7 +65,7 @@ class GoalsClient extends base_client_1.BaseClient {
|
|
|
66
65
|
return (0, validators_1.validateGoal)(response.data);
|
|
67
66
|
}
|
|
68
67
|
async updateGoal(id, args, requestId) {
|
|
69
|
-
|
|
68
|
+
validators_1.IdSchema.parse(id);
|
|
70
69
|
const response = await (0, http_client_1.request)({
|
|
71
70
|
httpMethod: 'POST',
|
|
72
71
|
baseUri: this.syncApiBase,
|
|
@@ -79,7 +78,7 @@ class GoalsClient extends base_client_1.BaseClient {
|
|
|
79
78
|
return (0, validators_1.validateGoal)(response.data);
|
|
80
79
|
}
|
|
81
80
|
async deleteGoal(id, requestId) {
|
|
82
|
-
|
|
81
|
+
validators_1.IdSchema.parse(id);
|
|
83
82
|
const response = await (0, http_client_1.request)({
|
|
84
83
|
httpMethod: 'DELETE',
|
|
85
84
|
baseUri: this.syncApiBase,
|
|
@@ -91,7 +90,7 @@ class GoalsClient extends base_client_1.BaseClient {
|
|
|
91
90
|
return (0, http_client_1.isSuccess)(response);
|
|
92
91
|
}
|
|
93
92
|
async completeGoal(id, requestId) {
|
|
94
|
-
|
|
93
|
+
validators_1.IdSchema.parse(id);
|
|
95
94
|
const response = await (0, http_client_1.request)({
|
|
96
95
|
httpMethod: 'POST',
|
|
97
96
|
baseUri: this.syncApiBase,
|
|
@@ -103,7 +102,7 @@ class GoalsClient extends base_client_1.BaseClient {
|
|
|
103
102
|
return (0, validators_1.validateGoal)(response.data);
|
|
104
103
|
}
|
|
105
104
|
async uncompleteGoal(id, requestId) {
|
|
106
|
-
|
|
105
|
+
validators_1.IdSchema.parse(id);
|
|
107
106
|
const response = await (0, http_client_1.request)({
|
|
108
107
|
httpMethod: 'POST',
|
|
109
108
|
baseUri: this.syncApiBase,
|
|
@@ -115,8 +114,8 @@ class GoalsClient extends base_client_1.BaseClient {
|
|
|
115
114
|
return (0, validators_1.validateGoal)(response.data);
|
|
116
115
|
}
|
|
117
116
|
async linkTaskToGoal({ goalId, taskId }, requestId) {
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
validators_1.IdSchema.parse(goalId);
|
|
118
|
+
validators_1.IdSchema.parse(taskId);
|
|
120
119
|
const response = await (0, http_client_1.request)({
|
|
121
120
|
httpMethod: 'POST',
|
|
122
121
|
baseUri: this.syncApiBase,
|
|
@@ -129,8 +128,8 @@ class GoalsClient extends base_client_1.BaseClient {
|
|
|
129
128
|
return (0, validators_1.validateGoal)(response.data);
|
|
130
129
|
}
|
|
131
130
|
async unlinkTaskFromGoal({ goalId, taskId }, requestId) {
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
validators_1.IdSchema.parse(goalId);
|
|
132
|
+
validators_1.IdSchema.parse(taskId);
|
|
134
133
|
const response = await (0, http_client_1.request)({
|
|
135
134
|
httpMethod: 'DELETE',
|
|
136
135
|
baseUri: this.syncApiBase,
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TemplateClient = void 0;
|
|
4
4
|
const endpoints_1 = require("../consts/endpoints");
|
|
5
5
|
const http_client_1 = require("../transport/http-client");
|
|
6
|
-
const case_conversion_1 = require("../utils/case-conversion");
|
|
7
6
|
const multipart_upload_1 = require("../utils/multipart-upload");
|
|
8
7
|
const validators_1 = require("../utils/validators");
|
|
9
8
|
const base_client_1 = require("./base-client");
|
|
@@ -53,7 +52,7 @@ class TemplateClient extends base_client_1.BaseClient {
|
|
|
53
52
|
customFetch: this.customFetch,
|
|
54
53
|
requestId,
|
|
55
54
|
});
|
|
56
|
-
return this.validateTemplateResponse(
|
|
55
|
+
return this.validateTemplateResponse(data);
|
|
57
56
|
}
|
|
58
57
|
async importTemplateIntoProject(args, requestId) {
|
|
59
58
|
const { file, fileName, projectId } = args;
|
|
@@ -67,7 +66,7 @@ class TemplateClient extends base_client_1.BaseClient {
|
|
|
67
66
|
customFetch: this.customFetch,
|
|
68
67
|
requestId,
|
|
69
68
|
});
|
|
70
|
-
return this.validateTemplateResponse(
|
|
69
|
+
return this.validateTemplateResponse(data);
|
|
71
70
|
}
|
|
72
71
|
async importTemplateFromId(args, requestId) {
|
|
73
72
|
const { data } = await (0, http_client_1.request)({
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.UiExtensionClient = void 0;
|
|
4
4
|
const endpoints_1 = require("../consts/endpoints");
|
|
5
5
|
const http_client_1 = require("../transport/http-client");
|
|
6
|
-
const case_conversion_1 = require("../utils/case-conversion");
|
|
7
6
|
const multipart_upload_1 = require("../utils/multipart-upload");
|
|
8
7
|
const validators_1 = require("../utils/validators");
|
|
9
8
|
const base_client_1 = require("./base-client");
|
|
@@ -102,7 +101,7 @@ class UiExtensionClient extends base_client_1.BaseClient {
|
|
|
102
101
|
requestId: requestId,
|
|
103
102
|
customFetch: this.customFetch,
|
|
104
103
|
});
|
|
105
|
-
return (0, validators_1.validateUiExtension)(
|
|
104
|
+
return (0, validators_1.validateUiExtension)(data);
|
|
106
105
|
}
|
|
107
106
|
}
|
|
108
107
|
exports.UiExtensionClient = UiExtensionClient;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.UploadClient = void 0;
|
|
4
4
|
const endpoints_1 = require("../consts/endpoints");
|
|
5
5
|
const http_client_1 = require("../transport/http-client");
|
|
6
|
-
const
|
|
6
|
+
const file_response_1 = require("../utils/file-response");
|
|
7
7
|
const multipart_upload_1 = require("../utils/multipart-upload");
|
|
8
8
|
const validators_1 = require("../utils/validators");
|
|
9
9
|
const base_client_1 = require("./base-client");
|
|
@@ -71,32 +71,13 @@ class UploadClient extends base_client_1.BaseClient {
|
|
|
71
71
|
if (!response.ok) {
|
|
72
72
|
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
const text = await response.text();
|
|
76
|
-
const buffer = new TextEncoder().encode(text).buffer;
|
|
77
|
-
return {
|
|
78
|
-
ok: response.ok,
|
|
79
|
-
status: response.status,
|
|
80
|
-
statusText: response.statusText,
|
|
81
|
-
headers: response.headers,
|
|
82
|
-
text: () => Promise.resolve(text),
|
|
83
|
-
json: () => response.json(),
|
|
84
|
-
arrayBuffer: () => Promise.resolve(buffer),
|
|
85
|
-
};
|
|
74
|
+
return (0, file_response_1.wrapAsFileResponse)(response, 'viewAttachment');
|
|
86
75
|
}
|
|
87
76
|
const response = await fetch(fileUrl, fetchOptions);
|
|
88
77
|
if (!response.ok) {
|
|
89
78
|
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
90
79
|
}
|
|
91
|
-
return
|
|
92
|
-
ok: response.ok,
|
|
93
|
-
status: response.status,
|
|
94
|
-
statusText: response.statusText,
|
|
95
|
-
headers: (0, headers_1.headersToRecord)(response.headers),
|
|
96
|
-
text: () => response.text(),
|
|
97
|
-
json: () => response.json(),
|
|
98
|
-
arrayBuffer: () => response.arrayBuffer(),
|
|
99
|
-
};
|
|
80
|
+
return (0, file_response_1.wrapAsFileResponse)(response, 'viewAttachment');
|
|
100
81
|
}
|
|
101
82
|
}
|
|
102
83
|
exports.UploadClient = UploadClient;
|
|
@@ -48,6 +48,7 @@ function createObsidianFetchAdapter(requestUrl) {
|
|
|
48
48
|
// Wrap Obsidian's direct properties as methods returning promises
|
|
49
49
|
text: () => Promise.resolve(response.text),
|
|
50
50
|
json: () => Promise.resolve(response.json),
|
|
51
|
+
arrayBuffer: () => Promise.resolve(response.arrayBuffer),
|
|
51
52
|
};
|
|
52
53
|
};
|
|
53
54
|
}
|
package/dist/cjs/todoist-api.js
CHANGED
|
@@ -945,33 +945,101 @@ class TodoistApi {
|
|
|
945
945
|
return this.folderClient.deleteFolder(id, requestId);
|
|
946
946
|
}
|
|
947
947
|
// ── Goals ──
|
|
948
|
+
/**
|
|
949
|
+
* Retrieves a paginated list of goals.
|
|
950
|
+
*
|
|
951
|
+
* @param args - Optional filters including owner type, workspace ID, cursor, and limit.
|
|
952
|
+
* @returns A promise that resolves to a paginated list of goals.
|
|
953
|
+
*/
|
|
948
954
|
async getGoals(args) {
|
|
949
955
|
return this.goalsClient.getGoals(args);
|
|
950
956
|
}
|
|
957
|
+
/**
|
|
958
|
+
* Searches for goals matching a query.
|
|
959
|
+
*
|
|
960
|
+
* @param args - Search parameters including query string and optional owner type.
|
|
961
|
+
* @returns A promise that resolves to a paginated list of matching goals.
|
|
962
|
+
*/
|
|
951
963
|
async searchGoals(args) {
|
|
952
964
|
return this.goalsClient.searchGoals(args);
|
|
953
965
|
}
|
|
966
|
+
/**
|
|
967
|
+
* Retrieves a single goal by its ID.
|
|
968
|
+
*
|
|
969
|
+
* @param id - The unique identifier of the goal.
|
|
970
|
+
* @returns A promise that resolves to the goal.
|
|
971
|
+
*/
|
|
954
972
|
async getGoal(id) {
|
|
955
973
|
return this.goalsClient.getGoal(id);
|
|
956
974
|
}
|
|
975
|
+
/**
|
|
976
|
+
* Creates a new goal.
|
|
977
|
+
*
|
|
978
|
+
* @param args - Goal attributes including name and optional workspace, description, deadline, and responsible user.
|
|
979
|
+
* @param requestId - Optional custom identifier for the request.
|
|
980
|
+
* @returns A promise that resolves to the created goal.
|
|
981
|
+
*/
|
|
957
982
|
async addGoal(args, requestId) {
|
|
958
983
|
return this.goalsClient.addGoal(args, requestId);
|
|
959
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
* Updates an existing goal.
|
|
987
|
+
*
|
|
988
|
+
* @param id - The unique identifier of the goal to update.
|
|
989
|
+
* @param args - Attributes to update on the goal.
|
|
990
|
+
* @param requestId - Optional custom identifier for the request.
|
|
991
|
+
* @returns A promise that resolves to the updated goal.
|
|
992
|
+
*/
|
|
960
993
|
async updateGoal(id, args, requestId) {
|
|
961
994
|
return this.goalsClient.updateGoal(id, args, requestId);
|
|
962
995
|
}
|
|
996
|
+
/**
|
|
997
|
+
* Deletes a goal by its ID.
|
|
998
|
+
*
|
|
999
|
+
* @param id - The unique identifier of the goal to delete.
|
|
1000
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1001
|
+
* @returns A promise that resolves to `true` if successful.
|
|
1002
|
+
*/
|
|
963
1003
|
async deleteGoal(id, requestId) {
|
|
964
1004
|
return this.goalsClient.deleteGoal(id, requestId);
|
|
965
1005
|
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Marks a goal as complete.
|
|
1008
|
+
*
|
|
1009
|
+
* @param id - The unique identifier of the goal to complete.
|
|
1010
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1011
|
+
* @returns A promise that resolves to the updated goal.
|
|
1012
|
+
*/
|
|
966
1013
|
async completeGoal(id, requestId) {
|
|
967
1014
|
return this.goalsClient.completeGoal(id, requestId);
|
|
968
1015
|
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Marks a previously completed goal as incomplete.
|
|
1018
|
+
*
|
|
1019
|
+
* @param id - The unique identifier of the goal to uncomplete.
|
|
1020
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1021
|
+
* @returns A promise that resolves to the updated goal.
|
|
1022
|
+
*/
|
|
969
1023
|
async uncompleteGoal(id, requestId) {
|
|
970
1024
|
return this.goalsClient.uncompleteGoal(id, requestId);
|
|
971
1025
|
}
|
|
1026
|
+
/**
|
|
1027
|
+
* Links a task to a goal so it contributes to goal progress.
|
|
1028
|
+
*
|
|
1029
|
+
* @param args - The goal ID and task ID to link.
|
|
1030
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1031
|
+
* @returns A promise that resolves to the updated goal.
|
|
1032
|
+
*/
|
|
972
1033
|
async linkTaskToGoal(args, requestId) {
|
|
973
1034
|
return this.goalsClient.linkTaskToGoal(args, requestId);
|
|
974
1035
|
}
|
|
1036
|
+
/**
|
|
1037
|
+
* Unlinks a previously linked task from a goal.
|
|
1038
|
+
*
|
|
1039
|
+
* @param args - The goal ID and task ID to unlink.
|
|
1040
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1041
|
+
* @returns A promise that resolves to `true` if successful.
|
|
1042
|
+
*/
|
|
975
1043
|
async unlinkTaskFromGoal(args, requestId) {
|
|
976
1044
|
return this.goalsClient.unlinkTaskFromGoal(args, requestId);
|
|
977
1045
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.wrapAsFileResponse = wrapAsFileResponse;
|
|
4
|
+
const headers_1 = require("./headers");
|
|
5
|
+
/**
|
|
6
|
+
* Wraps either a native `Response` or a `CustomFetchResponse` into the SDK's
|
|
7
|
+
* `FileResponse` shape (binary endpoints: `viewAttachment`, `downloadBackup`).
|
|
8
|
+
*
|
|
9
|
+
* `arrayBuffer()` is resolved lazily. A customFetch implementation that omits
|
|
10
|
+
* `arrayBuffer()` is still valid for callers that only read `text()`/`json()`;
|
|
11
|
+
* the descriptive error is thrown only if the caller actually requests binary
|
|
12
|
+
* bytes. This avoids the lossy `text()` → `TextEncoder` round-trip that
|
|
13
|
+
* corrupts non-UTF-8 bytes (every `0x80`-`0xFF` byte not part of a valid UTF-8
|
|
14
|
+
* sequence is replaced with `U+FFFD`).
|
|
15
|
+
*/
|
|
16
|
+
function wrapAsFileResponse(response, context) {
|
|
17
|
+
const headers = response.headers instanceof Headers ? (0, headers_1.headersToRecord)(response.headers) : response.headers;
|
|
18
|
+
return {
|
|
19
|
+
ok: response.ok,
|
|
20
|
+
status: response.status,
|
|
21
|
+
statusText: response.statusText,
|
|
22
|
+
headers,
|
|
23
|
+
text: () => response.text(),
|
|
24
|
+
json: () => response.json(),
|
|
25
|
+
arrayBuffer: () => {
|
|
26
|
+
if (typeof response.arrayBuffer !== 'function') {
|
|
27
|
+
throw new Error(`customFetch response must implement arrayBuffer() for ${context} (binary endpoint); reading the body via text() corrupts non-UTF-8 bytes`);
|
|
28
|
+
}
|
|
29
|
+
return response.arrayBuffer();
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.uploadMultipartFile = uploadMultipartFile;
|
|
37
37
|
const fetch_with_retry_1 = require("../transport/fetch-with-retry");
|
|
38
|
+
const case_conversion_1 = require("./case-conversion");
|
|
38
39
|
/**
|
|
39
40
|
* Helper function to determine content-type from filename extension.
|
|
40
41
|
* @param fileName - The filename to analyze
|
|
@@ -174,5 +175,5 @@ async function uploadMultipartFile(args) {
|
|
|
174
175
|
},
|
|
175
176
|
customFetch,
|
|
176
177
|
});
|
|
177
|
-
return response.data;
|
|
178
|
+
return (0, case_conversion_1.camelCaseKeys)(response.data);
|
|
178
179
|
}
|
|
@@ -13,7 +13,6 @@ import { z } from 'zod';
|
|
|
13
13
|
import { ENDPOINT_REST_APPS, ENDPOINT_REST_APPS_INSTALLATIONS, ENDPOINT_REST_USER_AUTHORIZATIONS, ENDPOINT_REST_USER_AUTHORIZATIONS_DELETE, getAppByDistributionTokenEndpoint, getAppClientSecretEndpoint, getAppDistributionTokenEndpoint, getAppEndpoint, getAppIconEndpoint, getAppInstallationEndpoint, getAppSecretsEndpoint, getAppTestTokenEndpoint, getAppTokensEndpoint, getAppVerificationTokenEndpoint, getAppWebhookEndpoint, } from '../consts/endpoints.js';
|
|
14
14
|
import { isSuccess, request } from '../transport/http-client.js';
|
|
15
15
|
import { webhookEventToWireName } from '../types/apps/index.js';
|
|
16
|
-
import { camelCaseKeys } from '../utils/case-conversion.js';
|
|
17
16
|
import { uploadMultipartFile } from '../utils/multipart-upload.js';
|
|
18
17
|
import { IdSchema, validateApp, validateAppArray, validateAppByDistributionToken, validateAppDistributionToken, validateAppInstallation, validateAppInstallationArray, validateAppSecrets, validateAppTestToken, validateAppVerificationToken, validateAppWebhook, validateAppWithUserCount, validateUserAuthorizationArray, } from '../utils/validators.js';
|
|
19
18
|
import { BaseClient } from './base-client.js';
|
|
@@ -142,7 +141,7 @@ export class AppClient extends BaseClient {
|
|
|
142
141
|
requestId: requestId,
|
|
143
142
|
customFetch: this.customFetch,
|
|
144
143
|
});
|
|
145
|
-
return validateAppWithUserCount(
|
|
144
|
+
return validateAppWithUserCount(data);
|
|
146
145
|
}
|
|
147
146
|
async getAppTestToken(appId, requestId) {
|
|
148
147
|
IdSchema.parse(appId);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ENDPOINT_REST_BACKUPS, ENDPOINT_REST_BACKUPS_DOWNLOAD } from '../consts/endpoints.js';
|
|
2
2
|
import { request } from '../transport/http-client.js';
|
|
3
|
-
import {
|
|
3
|
+
import { wrapAsFileResponse } from '../utils/file-response.js';
|
|
4
4
|
import { validateBackupArray } from '../utils/validators.js';
|
|
5
5
|
import { BaseClient } from './base-client.js';
|
|
6
6
|
/**
|
|
@@ -32,30 +32,12 @@ export class BackupClient extends BaseClient {
|
|
|
32
32
|
if (!response.ok) {
|
|
33
33
|
throw new Error(`Failed to download backup: ${response.status} ${response.statusText}`);
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
const buffer = new TextEncoder().encode(text).buffer;
|
|
37
|
-
return {
|
|
38
|
-
ok: response.ok,
|
|
39
|
-
status: response.status,
|
|
40
|
-
statusText: response.statusText,
|
|
41
|
-
headers: response.headers,
|
|
42
|
-
text: () => Promise.resolve(text),
|
|
43
|
-
json: () => response.json(),
|
|
44
|
-
arrayBuffer: () => Promise.resolve(buffer),
|
|
45
|
-
};
|
|
35
|
+
return wrapAsFileResponse(response, 'downloadBackup');
|
|
46
36
|
}
|
|
47
37
|
const response = await fetch(url, fetchOptions);
|
|
48
38
|
if (!response.ok) {
|
|
49
39
|
throw new Error(`Failed to download backup: ${response.status} ${response.statusText}`);
|
|
50
40
|
}
|
|
51
|
-
return
|
|
52
|
-
ok: response.ok,
|
|
53
|
-
status: response.status,
|
|
54
|
-
statusText: response.statusText,
|
|
55
|
-
headers: headersToRecord(response.headers),
|
|
56
|
-
text: () => response.text(),
|
|
57
|
-
json: () => response.json(),
|
|
58
|
-
arrayBuffer: () => response.arrayBuffer(),
|
|
59
|
-
};
|
|
41
|
+
return wrapAsFileResponse(response, 'downloadBackup');
|
|
60
42
|
}
|
|
61
43
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
1
|
import { ENDPOINT_REST_GOALS, ENDPOINT_REST_GOALS_SEARCH, GOAL_COMPLETE, GOAL_TASKS, GOAL_UNCOMPLETE, } from '../consts/endpoints.js';
|
|
3
2
|
import { isSuccess, request } from '../transport/http-client.js';
|
|
4
3
|
import { generatePath } from '../utils/request-helpers.js';
|
|
5
|
-
import { validateGoal, validateGoalArray } from '../utils/validators.js';
|
|
4
|
+
import { IdSchema, validateGoal, validateGoalArray } from '../utils/validators.js';
|
|
6
5
|
import { BaseClient } from './base-client.js';
|
|
7
6
|
/**
|
|
8
7
|
* Internal sub-client handling all goal-domain endpoints.
|
|
@@ -40,7 +39,7 @@ export class GoalsClient extends BaseClient {
|
|
|
40
39
|
};
|
|
41
40
|
}
|
|
42
41
|
async getGoal(id) {
|
|
43
|
-
|
|
42
|
+
IdSchema.parse(id);
|
|
44
43
|
const response = await request({
|
|
45
44
|
httpMethod: 'GET',
|
|
46
45
|
baseUri: this.syncApiBase,
|
|
@@ -63,7 +62,7 @@ export class GoalsClient extends BaseClient {
|
|
|
63
62
|
return validateGoal(response.data);
|
|
64
63
|
}
|
|
65
64
|
async updateGoal(id, args, requestId) {
|
|
66
|
-
|
|
65
|
+
IdSchema.parse(id);
|
|
67
66
|
const response = await request({
|
|
68
67
|
httpMethod: 'POST',
|
|
69
68
|
baseUri: this.syncApiBase,
|
|
@@ -76,7 +75,7 @@ export class GoalsClient extends BaseClient {
|
|
|
76
75
|
return validateGoal(response.data);
|
|
77
76
|
}
|
|
78
77
|
async deleteGoal(id, requestId) {
|
|
79
|
-
|
|
78
|
+
IdSchema.parse(id);
|
|
80
79
|
const response = await request({
|
|
81
80
|
httpMethod: 'DELETE',
|
|
82
81
|
baseUri: this.syncApiBase,
|
|
@@ -88,7 +87,7 @@ export class GoalsClient extends BaseClient {
|
|
|
88
87
|
return isSuccess(response);
|
|
89
88
|
}
|
|
90
89
|
async completeGoal(id, requestId) {
|
|
91
|
-
|
|
90
|
+
IdSchema.parse(id);
|
|
92
91
|
const response = await request({
|
|
93
92
|
httpMethod: 'POST',
|
|
94
93
|
baseUri: this.syncApiBase,
|
|
@@ -100,7 +99,7 @@ export class GoalsClient extends BaseClient {
|
|
|
100
99
|
return validateGoal(response.data);
|
|
101
100
|
}
|
|
102
101
|
async uncompleteGoal(id, requestId) {
|
|
103
|
-
|
|
102
|
+
IdSchema.parse(id);
|
|
104
103
|
const response = await request({
|
|
105
104
|
httpMethod: 'POST',
|
|
106
105
|
baseUri: this.syncApiBase,
|
|
@@ -112,8 +111,8 @@ export class GoalsClient extends BaseClient {
|
|
|
112
111
|
return validateGoal(response.data);
|
|
113
112
|
}
|
|
114
113
|
async linkTaskToGoal({ goalId, taskId }, requestId) {
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
IdSchema.parse(goalId);
|
|
115
|
+
IdSchema.parse(taskId);
|
|
117
116
|
const response = await request({
|
|
118
117
|
httpMethod: 'POST',
|
|
119
118
|
baseUri: this.syncApiBase,
|
|
@@ -126,8 +125,8 @@ export class GoalsClient extends BaseClient {
|
|
|
126
125
|
return validateGoal(response.data);
|
|
127
126
|
}
|
|
128
127
|
async unlinkTaskFromGoal({ goalId, taskId }, requestId) {
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
IdSchema.parse(goalId);
|
|
129
|
+
IdSchema.parse(taskId);
|
|
131
130
|
const response = await request({
|
|
132
131
|
httpMethod: 'DELETE',
|
|
133
132
|
baseUri: this.syncApiBase,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ENDPOINT_REST_TEMPLATES_CREATE_FROM_FILE, ENDPOINT_REST_TEMPLATES_FILE, ENDPOINT_REST_TEMPLATES_IMPORT_FROM_FILE, ENDPOINT_REST_TEMPLATES_IMPORT_FROM_ID, ENDPOINT_REST_TEMPLATES_URL, } from '../consts/endpoints.js';
|
|
2
2
|
import { request } from '../transport/http-client.js';
|
|
3
|
-
import { camelCaseKeys } from '../utils/case-conversion.js';
|
|
4
3
|
import { uploadMultipartFile } from '../utils/multipart-upload.js';
|
|
5
4
|
import { validateCommentArray, validateProjectArray, validateSectionArray, validateTaskArray, } from '../utils/validators.js';
|
|
6
5
|
import { BaseClient } from './base-client.js';
|
|
@@ -50,7 +49,7 @@ export class TemplateClient extends BaseClient {
|
|
|
50
49
|
customFetch: this.customFetch,
|
|
51
50
|
requestId,
|
|
52
51
|
});
|
|
53
|
-
return this.validateTemplateResponse(
|
|
52
|
+
return this.validateTemplateResponse(data);
|
|
54
53
|
}
|
|
55
54
|
async importTemplateIntoProject(args, requestId) {
|
|
56
55
|
const { file, fileName, projectId } = args;
|
|
@@ -64,7 +63,7 @@ export class TemplateClient extends BaseClient {
|
|
|
64
63
|
customFetch: this.customFetch,
|
|
65
64
|
requestId,
|
|
66
65
|
});
|
|
67
|
-
return this.validateTemplateResponse(
|
|
66
|
+
return this.validateTemplateResponse(data);
|
|
68
67
|
}
|
|
69
68
|
async importTemplateFromId(args, requestId) {
|
|
70
69
|
const { data } = await request({
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ENDPOINT_REST_APPS_UI_EXTENSIONS, ENDPOINT_REST_APPS_UI_EXTENSIONS_INSTALLED, getUiExtensionEndpoint, getUiExtensionIconEndpoint, getUiExtensionsByIntegrationEndpoint, } from '../consts/endpoints.js';
|
|
2
2
|
import { isSuccess, request } from '../transport/http-client.js';
|
|
3
|
-
import { camelCaseKeys } from '../utils/case-conversion.js';
|
|
4
3
|
import { uploadMultipartFile } from '../utils/multipart-upload.js';
|
|
5
4
|
import { IdSchema, validateUiExtension, validateUiExtensionArray } from '../utils/validators.js';
|
|
6
5
|
import { BaseClient } from './base-client.js';
|
|
@@ -99,6 +98,6 @@ export class UiExtensionClient extends BaseClient {
|
|
|
99
98
|
requestId: requestId,
|
|
100
99
|
customFetch: this.customFetch,
|
|
101
100
|
});
|
|
102
|
-
return validateUiExtension(
|
|
101
|
+
return validateUiExtension(data);
|
|
103
102
|
}
|
|
104
103
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ENDPOINT_REST_UPLOADS } from '../consts/endpoints.js';
|
|
2
2
|
import { isSuccess, request } from '../transport/http-client.js';
|
|
3
|
-
import {
|
|
3
|
+
import { wrapAsFileResponse } from '../utils/file-response.js';
|
|
4
4
|
import { uploadMultipartFile } from '../utils/multipart-upload.js';
|
|
5
5
|
import { validateAttachment } from '../utils/validators.js';
|
|
6
6
|
import { BaseClient } from './base-client.js';
|
|
@@ -68,31 +68,12 @@ export class UploadClient extends BaseClient {
|
|
|
68
68
|
if (!response.ok) {
|
|
69
69
|
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
const text = await response.text();
|
|
73
|
-
const buffer = new TextEncoder().encode(text).buffer;
|
|
74
|
-
return {
|
|
75
|
-
ok: response.ok,
|
|
76
|
-
status: response.status,
|
|
77
|
-
statusText: response.statusText,
|
|
78
|
-
headers: response.headers,
|
|
79
|
-
text: () => Promise.resolve(text),
|
|
80
|
-
json: () => response.json(),
|
|
81
|
-
arrayBuffer: () => Promise.resolve(buffer),
|
|
82
|
-
};
|
|
71
|
+
return wrapAsFileResponse(response, 'viewAttachment');
|
|
83
72
|
}
|
|
84
73
|
const response = await fetch(fileUrl, fetchOptions);
|
|
85
74
|
if (!response.ok) {
|
|
86
75
|
throw new Error(`Failed to fetch attachment: ${response.status} ${response.statusText}`);
|
|
87
76
|
}
|
|
88
|
-
return
|
|
89
|
-
ok: response.ok,
|
|
90
|
-
status: response.status,
|
|
91
|
-
statusText: response.statusText,
|
|
92
|
-
headers: headersToRecord(response.headers),
|
|
93
|
-
text: () => response.text(),
|
|
94
|
-
json: () => response.json(),
|
|
95
|
-
arrayBuffer: () => response.arrayBuffer(),
|
|
96
|
-
};
|
|
77
|
+
return wrapAsFileResponse(response, 'viewAttachment');
|
|
97
78
|
}
|
|
98
79
|
}
|
|
@@ -45,6 +45,7 @@ export function createObsidianFetchAdapter(requestUrl) {
|
|
|
45
45
|
// Wrap Obsidian's direct properties as methods returning promises
|
|
46
46
|
text: () => Promise.resolve(response.text),
|
|
47
47
|
json: () => Promise.resolve(response.json),
|
|
48
|
+
arrayBuffer: () => Promise.resolve(response.arrayBuffer),
|
|
48
49
|
};
|
|
49
50
|
};
|
|
50
51
|
}
|
package/dist/esm/todoist-api.js
CHANGED
|
@@ -942,33 +942,101 @@ export class TodoistApi {
|
|
|
942
942
|
return this.folderClient.deleteFolder(id, requestId);
|
|
943
943
|
}
|
|
944
944
|
// ── Goals ──
|
|
945
|
+
/**
|
|
946
|
+
* Retrieves a paginated list of goals.
|
|
947
|
+
*
|
|
948
|
+
* @param args - Optional filters including owner type, workspace ID, cursor, and limit.
|
|
949
|
+
* @returns A promise that resolves to a paginated list of goals.
|
|
950
|
+
*/
|
|
945
951
|
async getGoals(args) {
|
|
946
952
|
return this.goalsClient.getGoals(args);
|
|
947
953
|
}
|
|
954
|
+
/**
|
|
955
|
+
* Searches for goals matching a query.
|
|
956
|
+
*
|
|
957
|
+
* @param args - Search parameters including query string and optional owner type.
|
|
958
|
+
* @returns A promise that resolves to a paginated list of matching goals.
|
|
959
|
+
*/
|
|
948
960
|
async searchGoals(args) {
|
|
949
961
|
return this.goalsClient.searchGoals(args);
|
|
950
962
|
}
|
|
963
|
+
/**
|
|
964
|
+
* Retrieves a single goal by its ID.
|
|
965
|
+
*
|
|
966
|
+
* @param id - The unique identifier of the goal.
|
|
967
|
+
* @returns A promise that resolves to the goal.
|
|
968
|
+
*/
|
|
951
969
|
async getGoal(id) {
|
|
952
970
|
return this.goalsClient.getGoal(id);
|
|
953
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* Creates a new goal.
|
|
974
|
+
*
|
|
975
|
+
* @param args - Goal attributes including name and optional workspace, description, deadline, and responsible user.
|
|
976
|
+
* @param requestId - Optional custom identifier for the request.
|
|
977
|
+
* @returns A promise that resolves to the created goal.
|
|
978
|
+
*/
|
|
954
979
|
async addGoal(args, requestId) {
|
|
955
980
|
return this.goalsClient.addGoal(args, requestId);
|
|
956
981
|
}
|
|
982
|
+
/**
|
|
983
|
+
* Updates an existing goal.
|
|
984
|
+
*
|
|
985
|
+
* @param id - The unique identifier of the goal to update.
|
|
986
|
+
* @param args - Attributes to update on the goal.
|
|
987
|
+
* @param requestId - Optional custom identifier for the request.
|
|
988
|
+
* @returns A promise that resolves to the updated goal.
|
|
989
|
+
*/
|
|
957
990
|
async updateGoal(id, args, requestId) {
|
|
958
991
|
return this.goalsClient.updateGoal(id, args, requestId);
|
|
959
992
|
}
|
|
993
|
+
/**
|
|
994
|
+
* Deletes a goal by its ID.
|
|
995
|
+
*
|
|
996
|
+
* @param id - The unique identifier of the goal to delete.
|
|
997
|
+
* @param requestId - Optional custom identifier for the request.
|
|
998
|
+
* @returns A promise that resolves to `true` if successful.
|
|
999
|
+
*/
|
|
960
1000
|
async deleteGoal(id, requestId) {
|
|
961
1001
|
return this.goalsClient.deleteGoal(id, requestId);
|
|
962
1002
|
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Marks a goal as complete.
|
|
1005
|
+
*
|
|
1006
|
+
* @param id - The unique identifier of the goal to complete.
|
|
1007
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1008
|
+
* @returns A promise that resolves to the updated goal.
|
|
1009
|
+
*/
|
|
963
1010
|
async completeGoal(id, requestId) {
|
|
964
1011
|
return this.goalsClient.completeGoal(id, requestId);
|
|
965
1012
|
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Marks a previously completed goal as incomplete.
|
|
1015
|
+
*
|
|
1016
|
+
* @param id - The unique identifier of the goal to uncomplete.
|
|
1017
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1018
|
+
* @returns A promise that resolves to the updated goal.
|
|
1019
|
+
*/
|
|
966
1020
|
async uncompleteGoal(id, requestId) {
|
|
967
1021
|
return this.goalsClient.uncompleteGoal(id, requestId);
|
|
968
1022
|
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Links a task to a goal so it contributes to goal progress.
|
|
1025
|
+
*
|
|
1026
|
+
* @param args - The goal ID and task ID to link.
|
|
1027
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1028
|
+
* @returns A promise that resolves to the updated goal.
|
|
1029
|
+
*/
|
|
969
1030
|
async linkTaskToGoal(args, requestId) {
|
|
970
1031
|
return this.goalsClient.linkTaskToGoal(args, requestId);
|
|
971
1032
|
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Unlinks a previously linked task from a goal.
|
|
1035
|
+
*
|
|
1036
|
+
* @param args - The goal ID and task ID to unlink.
|
|
1037
|
+
* @param requestId - Optional custom identifier for the request.
|
|
1038
|
+
* @returns A promise that resolves to `true` if successful.
|
|
1039
|
+
*/
|
|
972
1040
|
async unlinkTaskFromGoal(args, requestId) {
|
|
973
1041
|
return this.goalsClient.unlinkTaskFromGoal(args, requestId);
|
|
974
1042
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { headersToRecord } from './headers.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wraps either a native `Response` or a `CustomFetchResponse` into the SDK's
|
|
4
|
+
* `FileResponse` shape (binary endpoints: `viewAttachment`, `downloadBackup`).
|
|
5
|
+
*
|
|
6
|
+
* `arrayBuffer()` is resolved lazily. A customFetch implementation that omits
|
|
7
|
+
* `arrayBuffer()` is still valid for callers that only read `text()`/`json()`;
|
|
8
|
+
* the descriptive error is thrown only if the caller actually requests binary
|
|
9
|
+
* bytes. This avoids the lossy `text()` → `TextEncoder` round-trip that
|
|
10
|
+
* corrupts non-UTF-8 bytes (every `0x80`-`0xFF` byte not part of a valid UTF-8
|
|
11
|
+
* sequence is replaced with `U+FFFD`).
|
|
12
|
+
*/
|
|
13
|
+
export function wrapAsFileResponse(response, context) {
|
|
14
|
+
const headers = response.headers instanceof Headers ? headersToRecord(response.headers) : response.headers;
|
|
15
|
+
return {
|
|
16
|
+
ok: response.ok,
|
|
17
|
+
status: response.status,
|
|
18
|
+
statusText: response.statusText,
|
|
19
|
+
headers,
|
|
20
|
+
text: () => response.text(),
|
|
21
|
+
json: () => response.json(),
|
|
22
|
+
arrayBuffer: () => {
|
|
23
|
+
if (typeof response.arrayBuffer !== 'function') {
|
|
24
|
+
throw new Error(`customFetch response must implement arrayBuffer() for ${context} (binary endpoint); reading the body via text() corrupts non-UTF-8 bytes`);
|
|
25
|
+
}
|
|
26
|
+
return response.arrayBuffer();
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fetchWithRetry } from '../transport/fetch-with-retry.js';
|
|
2
|
+
import { camelCaseKeys } from './case-conversion.js';
|
|
2
3
|
/**
|
|
3
4
|
* Helper function to determine content-type from filename extension.
|
|
4
5
|
* @param fileName - The filename to analyze
|
|
@@ -138,5 +139,5 @@ export async function uploadMultipartFile(args) {
|
|
|
138
139
|
},
|
|
139
140
|
customFetch,
|
|
140
141
|
});
|
|
141
|
-
return response.data;
|
|
142
|
+
return camelCaseKeys(response.data);
|
|
142
143
|
}
|
|
@@ -789,15 +789,83 @@ export declare class TodoistApi {
|
|
|
789
789
|
* @returns A promise that resolves to `true` if successful.
|
|
790
790
|
*/
|
|
791
791
|
deleteFolder(id: string, requestId?: string): Promise<boolean>;
|
|
792
|
+
/**
|
|
793
|
+
* Retrieves a paginated list of goals.
|
|
794
|
+
*
|
|
795
|
+
* @param args - Optional filters including owner type, workspace ID, cursor, and limit.
|
|
796
|
+
* @returns A promise that resolves to a paginated list of goals.
|
|
797
|
+
*/
|
|
792
798
|
getGoals(args?: GetGoalsArgs): Promise<GetGoalsResponse>;
|
|
799
|
+
/**
|
|
800
|
+
* Searches for goals matching a query.
|
|
801
|
+
*
|
|
802
|
+
* @param args - Search parameters including query string and optional owner type.
|
|
803
|
+
* @returns A promise that resolves to a paginated list of matching goals.
|
|
804
|
+
*/
|
|
793
805
|
searchGoals(args: SearchGoalsArgs): Promise<GetGoalsResponse>;
|
|
806
|
+
/**
|
|
807
|
+
* Retrieves a single goal by its ID.
|
|
808
|
+
*
|
|
809
|
+
* @param id - The unique identifier of the goal.
|
|
810
|
+
* @returns A promise that resolves to the goal.
|
|
811
|
+
*/
|
|
794
812
|
getGoal(id: string): Promise<Goal>;
|
|
813
|
+
/**
|
|
814
|
+
* Creates a new goal.
|
|
815
|
+
*
|
|
816
|
+
* @param args - Goal attributes including name and optional workspace, description, deadline, and responsible user.
|
|
817
|
+
* @param requestId - Optional custom identifier for the request.
|
|
818
|
+
* @returns A promise that resolves to the created goal.
|
|
819
|
+
*/
|
|
795
820
|
addGoal(args: AddGoalArgs, requestId?: string): Promise<Goal>;
|
|
821
|
+
/**
|
|
822
|
+
* Updates an existing goal.
|
|
823
|
+
*
|
|
824
|
+
* @param id - The unique identifier of the goal to update.
|
|
825
|
+
* @param args - Attributes to update on the goal.
|
|
826
|
+
* @param requestId - Optional custom identifier for the request.
|
|
827
|
+
* @returns A promise that resolves to the updated goal.
|
|
828
|
+
*/
|
|
796
829
|
updateGoal(id: string, args: UpdateGoalArgs, requestId?: string): Promise<Goal>;
|
|
830
|
+
/**
|
|
831
|
+
* Deletes a goal by its ID.
|
|
832
|
+
*
|
|
833
|
+
* @param id - The unique identifier of the goal to delete.
|
|
834
|
+
* @param requestId - Optional custom identifier for the request.
|
|
835
|
+
* @returns A promise that resolves to `true` if successful.
|
|
836
|
+
*/
|
|
797
837
|
deleteGoal(id: string, requestId?: string): Promise<boolean>;
|
|
838
|
+
/**
|
|
839
|
+
* Marks a goal as complete.
|
|
840
|
+
*
|
|
841
|
+
* @param id - The unique identifier of the goal to complete.
|
|
842
|
+
* @param requestId - Optional custom identifier for the request.
|
|
843
|
+
* @returns A promise that resolves to the updated goal.
|
|
844
|
+
*/
|
|
798
845
|
completeGoal(id: string, requestId?: string): Promise<Goal>;
|
|
846
|
+
/**
|
|
847
|
+
* Marks a previously completed goal as incomplete.
|
|
848
|
+
*
|
|
849
|
+
* @param id - The unique identifier of the goal to uncomplete.
|
|
850
|
+
* @param requestId - Optional custom identifier for the request.
|
|
851
|
+
* @returns A promise that resolves to the updated goal.
|
|
852
|
+
*/
|
|
799
853
|
uncompleteGoal(id: string, requestId?: string): Promise<Goal>;
|
|
854
|
+
/**
|
|
855
|
+
* Links a task to a goal so it contributes to goal progress.
|
|
856
|
+
*
|
|
857
|
+
* @param args - The goal ID and task ID to link.
|
|
858
|
+
* @param requestId - Optional custom identifier for the request.
|
|
859
|
+
* @returns A promise that resolves to the updated goal.
|
|
860
|
+
*/
|
|
800
861
|
linkTaskToGoal(args: TaskLinkingArgs, requestId?: string): Promise<Goal>;
|
|
862
|
+
/**
|
|
863
|
+
* Unlinks a previously linked task from a goal.
|
|
864
|
+
*
|
|
865
|
+
* @param args - The goal ID and task ID to unlink.
|
|
866
|
+
* @param requestId - Optional custom identifier for the request.
|
|
867
|
+
* @returns A promise that resolves to `true` if successful.
|
|
868
|
+
*/
|
|
801
869
|
unlinkTaskFromGoal(args: TaskLinkingArgs, requestId?: string): Promise<boolean>;
|
|
802
870
|
/**
|
|
803
871
|
* Retrieves a list of available backups.
|
|
@@ -67,7 +67,12 @@ export declare function isNetworkError(error: Error): error is NetworkError;
|
|
|
67
67
|
*/
|
|
68
68
|
export declare function isHttpError(error: Error): error is HttpError;
|
|
69
69
|
/**
|
|
70
|
-
* Custom fetch response interface that custom HTTP clients must implement
|
|
70
|
+
* Custom fetch response interface that custom HTTP clients must implement.
|
|
71
|
+
*
|
|
72
|
+
* `arrayBuffer()` is optional for back-compat with existing implementations,
|
|
73
|
+
* but must be provided when the fetch is used with binary endpoints
|
|
74
|
+
* (`viewAttachment`, `downloadBackup`) — those endpoints throw at runtime if
|
|
75
|
+
* it is missing rather than fall back to a lossy `text()` round-trip.
|
|
71
76
|
*/
|
|
72
77
|
export type CustomFetchResponse = {
|
|
73
78
|
ok: boolean;
|
|
@@ -76,6 +81,7 @@ export type CustomFetchResponse = {
|
|
|
76
81
|
headers: Record<string, string>;
|
|
77
82
|
text(): Promise<string>;
|
|
78
83
|
json(): Promise<unknown>;
|
|
84
|
+
arrayBuffer?: () => Promise<ArrayBuffer>;
|
|
79
85
|
};
|
|
80
86
|
/**
|
|
81
87
|
* Custom fetch function type for alternative HTTP clients
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CustomFetchResponse, FileResponse } from '../types/http.js';
|
|
2
|
+
type AnyResponse = CustomFetchResponse | Response;
|
|
3
|
+
/**
|
|
4
|
+
* Wraps either a native `Response` or a `CustomFetchResponse` into the SDK's
|
|
5
|
+
* `FileResponse` shape (binary endpoints: `viewAttachment`, `downloadBackup`).
|
|
6
|
+
*
|
|
7
|
+
* `arrayBuffer()` is resolved lazily. A customFetch implementation that omits
|
|
8
|
+
* `arrayBuffer()` is still valid for callers that only read `text()`/`json()`;
|
|
9
|
+
* the descriptive error is thrown only if the caller actually requests binary
|
|
10
|
+
* bytes. This avoids the lossy `text()` → `TextEncoder` round-trip that
|
|
11
|
+
* corrupts non-UTF-8 bytes (every `0x80`-`0xFF` byte not part of a valid UTF-8
|
|
12
|
+
* sequence is replaced with `U+FFFD`).
|
|
13
|
+
*/
|
|
14
|
+
export declare function wrapAsFileResponse(response: AnyResponse, context: 'viewAttachment' | 'downloadBackup'): FileResponse;
|
|
15
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doist/todoist-sdk",
|
|
3
|
-
"version": "10.2.0-next.
|
|
3
|
+
"version": "10.2.0-next.4",
|
|
4
4
|
"description": "The official TypeScript SDK for the Todoist REST API.",
|
|
5
5
|
"author": "Doist developers",
|
|
6
6
|
"repository": "https://github.com/Doist/todoist-sdk-typescript",
|
|
@@ -41,11 +41,14 @@
|
|
|
41
41
|
"build:fix-dts": "node scripts/fix-dts-imports.cjs",
|
|
42
42
|
"build:post": "echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
43
43
|
"build": "npm-run-all clean build:cjs build:esm build:fix-esm build:fix-dts build:post",
|
|
44
|
-
"attw": "
|
|
44
|
+
"attw": "attw --pack --ignore-rules fallback-condition false-esm",
|
|
45
45
|
"integrity-checks": "npm-run-all clean check test build attw",
|
|
46
46
|
"prepublishOnly": "npm run integrity-checks",
|
|
47
47
|
"prepare": "npm run build"
|
|
48
48
|
},
|
|
49
|
+
"overrides": {
|
|
50
|
+
"fflate": "0.8.2"
|
|
51
|
+
},
|
|
49
52
|
"dependencies": {
|
|
50
53
|
"camelcase": "6.3.0",
|
|
51
54
|
"emoji-regex": "10.6.0",
|
|
@@ -56,6 +59,7 @@
|
|
|
56
59
|
"zod": "4.3.6"
|
|
57
60
|
},
|
|
58
61
|
"devDependencies": {
|
|
62
|
+
"@arethetypeswrong/cli": "0.18.2",
|
|
59
63
|
"@semantic-release/changelog": "6.0.3",
|
|
60
64
|
"@semantic-release/git": "10.0.1",
|
|
61
65
|
"conventional-changelog-conventionalcommits": "9.3.1",
|