@doist/todoist-sdk 9.0.0 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/authentication.js +1 -0
- package/dist/cjs/clients/activity-client.js +63 -0
- package/dist/cjs/clients/app-client.js +347 -0
- package/dist/cjs/clients/backup-client.js +65 -0
- package/dist/cjs/clients/base-client.js +30 -0
- package/dist/cjs/clients/comment-client.js +92 -0
- package/dist/cjs/clients/email-client.js +43 -0
- package/dist/cjs/clients/folder-client.js +80 -0
- package/dist/cjs/clients/id-mapping-client.js +39 -0
- package/dist/cjs/clients/insights-client.js +88 -0
- package/dist/cjs/clients/label-client.js +127 -0
- package/dist/cjs/clients/productivity-client.js +27 -0
- package/dist/cjs/clients/project-client.js +232 -0
- package/dist/cjs/clients/reminder-client.js +198 -0
- package/dist/cjs/clients/section-client.js +118 -0
- package/dist/cjs/clients/task-client.js +255 -0
- package/dist/cjs/clients/template-client.js +89 -0
- package/dist/cjs/clients/ui-extension-client.js +109 -0
- package/dist/cjs/clients/upload-client.js +102 -0
- package/dist/cjs/clients/workspace-client.js +367 -0
- package/dist/cjs/consts/endpoints.js +66 -1
- package/dist/cjs/test-utils/test-defaults.js +77 -1
- package/dist/cjs/todoist-api.js +422 -1537
- package/dist/cjs/transport/http-client.js +1 -0
- package/dist/cjs/transport/sync-request.js +75 -0
- package/dist/cjs/types/apps/index.js +18 -0
- package/dist/cjs/types/apps/requests.js +2 -0
- package/dist/cjs/types/apps/types.js +253 -0
- package/dist/cjs/types/index.js +2 -0
- package/dist/cjs/types/ui-extensions/index.js +18 -0
- package/dist/cjs/types/ui-extensions/requests.js +2 -0
- package/dist/cjs/types/ui-extensions/types.js +77 -0
- package/dist/cjs/utils/headers.js +16 -0
- package/dist/cjs/utils/request-helpers.js +21 -0
- package/dist/cjs/utils/validators.js +52 -38
- package/dist/esm/authentication.js +1 -0
- package/dist/esm/clients/activity-client.js +59 -0
- package/dist/esm/clients/app-client.js +343 -0
- package/dist/esm/clients/backup-client.js +61 -0
- package/dist/esm/clients/base-client.js +26 -0
- package/dist/esm/clients/comment-client.js +88 -0
- package/dist/esm/clients/email-client.js +39 -0
- package/dist/esm/clients/folder-client.js +76 -0
- package/dist/esm/clients/id-mapping-client.js +35 -0
- package/dist/esm/clients/insights-client.js +84 -0
- package/dist/esm/clients/label-client.js +123 -0
- package/dist/esm/clients/productivity-client.js +23 -0
- package/dist/esm/clients/project-client.js +228 -0
- package/dist/esm/clients/reminder-client.js +194 -0
- package/dist/esm/clients/section-client.js +114 -0
- package/dist/esm/clients/task-client.js +251 -0
- package/dist/esm/clients/template-client.js +85 -0
- package/dist/esm/clients/ui-extension-client.js +105 -0
- package/dist/esm/clients/upload-client.js +98 -0
- package/dist/esm/clients/workspace-client.js +363 -0
- package/dist/esm/consts/endpoints.js +51 -0
- package/dist/esm/test-utils/test-defaults.js +75 -0
- package/dist/esm/todoist-api.js +425 -1540
- package/dist/esm/transport/http-client.js +1 -0
- package/dist/esm/transport/sync-request.js +72 -0
- package/dist/esm/types/apps/index.js +2 -0
- package/dist/esm/types/apps/requests.js +1 -0
- package/dist/esm/types/apps/types.js +248 -0
- package/dist/esm/types/index.js +2 -0
- package/dist/esm/types/ui-extensions/index.js +2 -0
- package/dist/esm/types/ui-extensions/requests.js +1 -0
- package/dist/esm/types/ui-extensions/types.js +74 -0
- package/dist/esm/utils/headers.js +13 -0
- package/dist/esm/utils/request-helpers.js +17 -0
- package/dist/esm/utils/validators.js +14 -0
- package/dist/types/authentication.d.ts +1 -1
- package/dist/types/clients/activity-client.d.ts +12 -0
- package/dist/types/clients/app-client.d.ts +37 -0
- package/dist/types/clients/backup-client.d.ts +14 -0
- package/dist/types/clients/base-client.d.ts +21 -0
- package/dist/types/clients/comment-client.d.ts +15 -0
- package/dist/types/clients/email-client.d.ts +13 -0
- package/dist/types/clients/folder-client.d.ts +16 -0
- package/dist/types/clients/id-mapping-client.d.ts +13 -0
- package/dist/types/clients/insights-client.d.ts +18 -0
- package/dist/types/clients/label-client.d.ts +19 -0
- package/dist/types/clients/productivity-client.d.ts +12 -0
- package/dist/types/clients/project-client.d.ts +26 -0
- package/dist/types/clients/reminder-client.d.ts +25 -0
- package/dist/types/clients/section-client.d.ts +18 -0
- package/dist/types/clients/task-client.d.ts +25 -0
- package/dist/types/clients/template-client.d.ts +17 -0
- package/dist/types/clients/ui-extension-client.d.ts +18 -0
- package/dist/types/clients/upload-client.d.ts +17 -0
- package/dist/types/clients/workspace-client.d.ts +43 -0
- package/dist/types/consts/endpoints.d.ts +24 -0
- package/dist/types/test-utils/test-defaults.d.ts +16 -1
- package/dist/types/todoist-api.d.ts +238 -17
- package/dist/types/transport/sync-request.d.ts +27 -0
- package/dist/types/types/apps/index.d.ts +2 -0
- package/dist/types/types/apps/requests.d.ts +89 -0
- package/dist/types/types/apps/types.d.ts +414 -0
- package/dist/types/types/http.d.ts +8 -1
- package/dist/types/types/index.d.ts +2 -0
- package/dist/types/types/sync/resources/user.d.ts +2 -2
- package/dist/types/types/sync/response.d.ts +2 -2
- package/dist/types/types/sync/user-preferences.d.ts +1 -1
- package/dist/types/types/ui-extensions/index.d.ts +2 -0
- package/dist/types/types/ui-extensions/requests.d.ts +108 -0
- package/dist/types/types/ui-extensions/types.d.ts +185 -0
- package/dist/types/utils/headers.d.ts +7 -0
- package/dist/types/utils/request-helpers.d.ts +13 -0
- package/dist/types/utils/validators.d.ts +223 -0
- package/package.json +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { ENDPOINT_REST_LOCATION_REMINDERS, ENDPOINT_REST_REMINDERS } from '../consts/endpoints.js';
|
|
2
|
+
import { isSuccess, request } from '../transport/http-client.js';
|
|
3
|
+
import { TodoistArgumentError, TodoistRequestError } from '../types/index.js';
|
|
4
|
+
import { ReminderIdSchema, UpdateLocationReminderArgsSchema, UpdateReminderArgsSchema, } from '../types/reminders/index.js';
|
|
5
|
+
import { ReminderTypeEnum } from '../types/sync/resources/reminders.js';
|
|
6
|
+
import { generatePath } from '../utils/request-helpers.js';
|
|
7
|
+
import { validateLocationReminderArray, validateReminder, validateReminderArray, } from '../utils/validators.js';
|
|
8
|
+
import { BaseClient } from './base-client.js';
|
|
9
|
+
/**
|
|
10
|
+
* Internal sub-client handling all reminder-domain endpoints
|
|
11
|
+
* (both time-based and location-based reminders).
|
|
12
|
+
*
|
|
13
|
+
* Instantiated by `TodoistApi`; every public reminder method on
|
|
14
|
+
* `TodoistApi` delegates here. See `todoist-api.ts` for user-facing
|
|
15
|
+
* JSDoc. The time-vs-location 404 translation is preserved here so a
|
|
16
|
+
* caller who used the wrong endpoint gets a TodoistArgumentError
|
|
17
|
+
* pointing at the correct method, rather than a bare 404.
|
|
18
|
+
*/
|
|
19
|
+
export class ReminderClient extends BaseClient {
|
|
20
|
+
async getReminders(args = {}) {
|
|
21
|
+
const { data: { results, nextCursor }, } = await request({
|
|
22
|
+
httpMethod: 'GET',
|
|
23
|
+
baseUri: this.syncApiBase,
|
|
24
|
+
relativePath: ENDPOINT_REST_REMINDERS,
|
|
25
|
+
apiToken: this.authToken,
|
|
26
|
+
customFetch: this.customFetch,
|
|
27
|
+
payload: args,
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
results: validateReminderArray(results),
|
|
31
|
+
nextCursor,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async getLocationReminders(args = {}) {
|
|
35
|
+
const { data: { results, nextCursor }, } = await request({
|
|
36
|
+
httpMethod: 'GET',
|
|
37
|
+
baseUri: this.syncApiBase,
|
|
38
|
+
relativePath: ENDPOINT_REST_LOCATION_REMINDERS,
|
|
39
|
+
apiToken: this.authToken,
|
|
40
|
+
customFetch: this.customFetch,
|
|
41
|
+
payload: args,
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
results: validateLocationReminderArray(results),
|
|
45
|
+
nextCursor,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async getReminder(id) {
|
|
49
|
+
ReminderIdSchema.parse(id);
|
|
50
|
+
try {
|
|
51
|
+
const response = await request({
|
|
52
|
+
httpMethod: 'GET',
|
|
53
|
+
baseUri: this.syncApiBase,
|
|
54
|
+
relativePath: generatePath(ENDPOINT_REST_REMINDERS, id),
|
|
55
|
+
apiToken: this.authToken,
|
|
56
|
+
customFetch: this.customFetch,
|
|
57
|
+
});
|
|
58
|
+
return validateReminder(response.data);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
throw new TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use getLocationReminder instead.`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async getLocationReminder(id) {
|
|
68
|
+
ReminderIdSchema.parse(id);
|
|
69
|
+
try {
|
|
70
|
+
const response = await request({
|
|
71
|
+
httpMethod: 'GET',
|
|
72
|
+
baseUri: this.syncApiBase,
|
|
73
|
+
relativePath: generatePath(ENDPOINT_REST_LOCATION_REMINDERS, id),
|
|
74
|
+
apiToken: this.authToken,
|
|
75
|
+
customFetch: this.customFetch,
|
|
76
|
+
});
|
|
77
|
+
return validateReminder(response.data);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
throw new TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use getReminder instead.`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async addReminder(args, requestId) {
|
|
87
|
+
const response = await request({
|
|
88
|
+
httpMethod: 'POST',
|
|
89
|
+
baseUri: this.syncApiBase,
|
|
90
|
+
relativePath: ENDPOINT_REST_REMINDERS,
|
|
91
|
+
apiToken: this.authToken,
|
|
92
|
+
customFetch: this.customFetch,
|
|
93
|
+
payload: args,
|
|
94
|
+
requestId: requestId,
|
|
95
|
+
});
|
|
96
|
+
return validateReminder(response.data);
|
|
97
|
+
}
|
|
98
|
+
async addLocationReminder(args, requestId) {
|
|
99
|
+
const response = await request({
|
|
100
|
+
httpMethod: 'POST',
|
|
101
|
+
baseUri: this.syncApiBase,
|
|
102
|
+
relativePath: ENDPOINT_REST_LOCATION_REMINDERS,
|
|
103
|
+
apiToken: this.authToken,
|
|
104
|
+
customFetch: this.customFetch,
|
|
105
|
+
payload: Object.assign(Object.assign({}, args), { reminderType: ReminderTypeEnum.Location }),
|
|
106
|
+
requestId: requestId,
|
|
107
|
+
});
|
|
108
|
+
return validateReminder(response.data);
|
|
109
|
+
}
|
|
110
|
+
async updateReminder(id, args, requestId) {
|
|
111
|
+
ReminderIdSchema.parse(id);
|
|
112
|
+
const payload = UpdateReminderArgsSchema.parse(args);
|
|
113
|
+
try {
|
|
114
|
+
const response = await request({
|
|
115
|
+
httpMethod: 'POST',
|
|
116
|
+
baseUri: this.syncApiBase,
|
|
117
|
+
relativePath: generatePath(ENDPOINT_REST_REMINDERS, id),
|
|
118
|
+
apiToken: this.authToken,
|
|
119
|
+
customFetch: this.customFetch,
|
|
120
|
+
payload,
|
|
121
|
+
requestId: requestId,
|
|
122
|
+
});
|
|
123
|
+
return validateReminder(response.data);
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
throw new TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use updateLocationReminder instead.`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async updateLocationReminder(id, args, requestId) {
|
|
133
|
+
ReminderIdSchema.parse(id);
|
|
134
|
+
const payload = UpdateLocationReminderArgsSchema.parse(args);
|
|
135
|
+
try {
|
|
136
|
+
const response = await request({
|
|
137
|
+
httpMethod: 'POST',
|
|
138
|
+
baseUri: this.syncApiBase,
|
|
139
|
+
relativePath: generatePath(ENDPOINT_REST_LOCATION_REMINDERS, id),
|
|
140
|
+
apiToken: this.authToken,
|
|
141
|
+
customFetch: this.customFetch,
|
|
142
|
+
payload,
|
|
143
|
+
requestId: requestId,
|
|
144
|
+
});
|
|
145
|
+
return validateReminder(response.data);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
throw new TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use updateReminder instead.`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async deleteReminder(id, requestId) {
|
|
155
|
+
ReminderIdSchema.parse(id);
|
|
156
|
+
try {
|
|
157
|
+
const response = await request({
|
|
158
|
+
httpMethod: 'DELETE',
|
|
159
|
+
baseUri: this.syncApiBase,
|
|
160
|
+
relativePath: generatePath(ENDPOINT_REST_REMINDERS, id),
|
|
161
|
+
apiToken: this.authToken,
|
|
162
|
+
customFetch: this.customFetch,
|
|
163
|
+
requestId: requestId,
|
|
164
|
+
});
|
|
165
|
+
return isSuccess(response);
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
throw new TodoistArgumentError(`Reminder ${id} was not found on the time-based reminder endpoint. If this is a location reminder, use deleteLocationReminder instead.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async deleteLocationReminder(id, requestId) {
|
|
175
|
+
ReminderIdSchema.parse(id);
|
|
176
|
+
try {
|
|
177
|
+
const response = await request({
|
|
178
|
+
httpMethod: 'DELETE',
|
|
179
|
+
baseUri: this.syncApiBase,
|
|
180
|
+
relativePath: generatePath(ENDPOINT_REST_LOCATION_REMINDERS, id),
|
|
181
|
+
apiToken: this.authToken,
|
|
182
|
+
customFetch: this.customFetch,
|
|
183
|
+
requestId: requestId,
|
|
184
|
+
});
|
|
185
|
+
return isSuccess(response);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
if (!(error instanceof TodoistRequestError) || error.httpStatusCode !== 404) {
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
throw new TodoistArgumentError(`Location reminder ${id} was not found on the location reminder endpoint. If this is a time-based reminder, use deleteReminder instead.`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ENDPOINT_REST_SECTIONS, ENDPOINT_REST_SECTIONS_SEARCH, SECTION_ARCHIVE, SECTION_UNARCHIVE, } from '../consts/endpoints.js';
|
|
3
|
+
import { isSuccess, request } from '../transport/http-client.js';
|
|
4
|
+
import { generatePath } from '../utils/request-helpers.js';
|
|
5
|
+
import { validateSection, validateSectionArray } from '../utils/validators.js';
|
|
6
|
+
import { BaseClient } from './base-client.js';
|
|
7
|
+
/**
|
|
8
|
+
* Internal sub-client handling all section-domain endpoints.
|
|
9
|
+
*
|
|
10
|
+
* Instantiated by `TodoistApi`; every public section method on `TodoistApi`
|
|
11
|
+
* delegates here. See `todoist-api.ts` for the user-facing JSDoc.
|
|
12
|
+
*/
|
|
13
|
+
export class SectionClient extends BaseClient {
|
|
14
|
+
async getSections(args) {
|
|
15
|
+
const { data: { results, nextCursor }, } = await request({
|
|
16
|
+
httpMethod: 'GET',
|
|
17
|
+
baseUri: this.syncApiBase,
|
|
18
|
+
relativePath: ENDPOINT_REST_SECTIONS,
|
|
19
|
+
apiToken: this.authToken,
|
|
20
|
+
customFetch: this.customFetch,
|
|
21
|
+
payload: args,
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
results: validateSectionArray(results),
|
|
25
|
+
nextCursor,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async searchSections(args) {
|
|
29
|
+
const { data: { results, nextCursor }, } = await request({
|
|
30
|
+
httpMethod: 'GET',
|
|
31
|
+
baseUri: this.syncApiBase,
|
|
32
|
+
relativePath: ENDPOINT_REST_SECTIONS_SEARCH,
|
|
33
|
+
apiToken: this.authToken,
|
|
34
|
+
customFetch: this.customFetch,
|
|
35
|
+
payload: args,
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
results: validateSectionArray(results),
|
|
39
|
+
nextCursor,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async getSection(id) {
|
|
43
|
+
z.string().parse(id);
|
|
44
|
+
const response = await request({
|
|
45
|
+
httpMethod: 'GET',
|
|
46
|
+
baseUri: this.syncApiBase,
|
|
47
|
+
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id),
|
|
48
|
+
apiToken: this.authToken,
|
|
49
|
+
customFetch: this.customFetch,
|
|
50
|
+
});
|
|
51
|
+
return validateSection(response.data);
|
|
52
|
+
}
|
|
53
|
+
async addSection(args, requestId) {
|
|
54
|
+
const response = await request({
|
|
55
|
+
httpMethod: 'POST',
|
|
56
|
+
baseUri: this.syncApiBase,
|
|
57
|
+
relativePath: ENDPOINT_REST_SECTIONS,
|
|
58
|
+
apiToken: this.authToken,
|
|
59
|
+
customFetch: this.customFetch,
|
|
60
|
+
payload: args,
|
|
61
|
+
requestId: requestId,
|
|
62
|
+
});
|
|
63
|
+
return validateSection(response.data);
|
|
64
|
+
}
|
|
65
|
+
async updateSection(id, args, requestId) {
|
|
66
|
+
z.string().parse(id);
|
|
67
|
+
const response = await request({
|
|
68
|
+
httpMethod: 'POST',
|
|
69
|
+
baseUri: this.syncApiBase,
|
|
70
|
+
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id),
|
|
71
|
+
apiToken: this.authToken,
|
|
72
|
+
customFetch: this.customFetch,
|
|
73
|
+
payload: args,
|
|
74
|
+
requestId: requestId,
|
|
75
|
+
});
|
|
76
|
+
return validateSection(response.data);
|
|
77
|
+
}
|
|
78
|
+
async deleteSection(id, requestId) {
|
|
79
|
+
z.string().parse(id);
|
|
80
|
+
const response = await request({
|
|
81
|
+
httpMethod: 'DELETE',
|
|
82
|
+
baseUri: this.syncApiBase,
|
|
83
|
+
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id),
|
|
84
|
+
apiToken: this.authToken,
|
|
85
|
+
customFetch: this.customFetch,
|
|
86
|
+
requestId: requestId,
|
|
87
|
+
});
|
|
88
|
+
return isSuccess(response);
|
|
89
|
+
}
|
|
90
|
+
async archiveSection(id, requestId) {
|
|
91
|
+
z.string().parse(id);
|
|
92
|
+
const response = await request({
|
|
93
|
+
httpMethod: 'POST',
|
|
94
|
+
baseUri: this.syncApiBase,
|
|
95
|
+
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id, SECTION_ARCHIVE),
|
|
96
|
+
apiToken: this.authToken,
|
|
97
|
+
customFetch: this.customFetch,
|
|
98
|
+
requestId: requestId,
|
|
99
|
+
});
|
|
100
|
+
return validateSection(response.data);
|
|
101
|
+
}
|
|
102
|
+
async unarchiveSection(id, requestId) {
|
|
103
|
+
z.string().parse(id);
|
|
104
|
+
const response = await request({
|
|
105
|
+
httpMethod: 'POST',
|
|
106
|
+
baseUri: this.syncApiBase,
|
|
107
|
+
relativePath: generatePath(ENDPOINT_REST_SECTIONS, id, SECTION_UNARCHIVE),
|
|
108
|
+
apiToken: this.authToken,
|
|
109
|
+
customFetch: this.customFetch,
|
|
110
|
+
requestId: requestId,
|
|
111
|
+
});
|
|
112
|
+
return validateSection(response.data);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { ENDPOINT_REST_TASKS, ENDPOINT_REST_TASKS_COMPLETED, ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE, ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE, ENDPOINT_REST_TASKS_COMPLETED_SEARCH, ENDPOINT_REST_TASKS_FILTER, ENDPOINT_REST_TASK_CLOSE, ENDPOINT_REST_TASK_MOVE, ENDPOINT_REST_TASK_REOPEN, ENDPOINT_SYNC_QUICK_ADD, } from '../consts/endpoints.js';
|
|
15
|
+
import { isSuccess, request } from '../transport/http-client.js';
|
|
16
|
+
import { performSyncRequest } from '../transport/sync-request.js';
|
|
17
|
+
import { TodoistRequestError } from '../types/index.js';
|
|
18
|
+
import { generatePath, spreadIfDefined } from '../utils/request-helpers.js';
|
|
19
|
+
import { processTaskContent } from '../utils/uncompletable-helpers.js';
|
|
20
|
+
import { validateTask, validateTaskArray } from '../utils/validators.js';
|
|
21
|
+
import { BaseClient } from './base-client.js';
|
|
22
|
+
const MAX_COMMAND_COUNT = 100;
|
|
23
|
+
/**
|
|
24
|
+
* Internal sub-client handling all task-domain endpoints.
|
|
25
|
+
*
|
|
26
|
+
* Instantiated by `TodoistApi`; every public task method on `TodoistApi`
|
|
27
|
+
* delegates here. See `todoist-api.ts` for the user-facing JSDoc.
|
|
28
|
+
*/
|
|
29
|
+
export class TaskClient extends BaseClient {
|
|
30
|
+
async getTask(id) {
|
|
31
|
+
z.string().parse(id);
|
|
32
|
+
const response = await request({
|
|
33
|
+
httpMethod: 'GET',
|
|
34
|
+
baseUri: this.syncApiBase,
|
|
35
|
+
relativePath: generatePath(ENDPOINT_REST_TASKS, id),
|
|
36
|
+
apiToken: this.authToken,
|
|
37
|
+
customFetch: this.customFetch,
|
|
38
|
+
});
|
|
39
|
+
return validateTask(response.data);
|
|
40
|
+
}
|
|
41
|
+
async getTasks(args = {}) {
|
|
42
|
+
const { data: { results, nextCursor }, } = await request({
|
|
43
|
+
httpMethod: 'GET',
|
|
44
|
+
baseUri: this.syncApiBase,
|
|
45
|
+
relativePath: ENDPOINT_REST_TASKS,
|
|
46
|
+
apiToken: this.authToken,
|
|
47
|
+
customFetch: this.customFetch,
|
|
48
|
+
payload: args,
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
results: validateTaskArray(results),
|
|
52
|
+
nextCursor,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async getTasksByFilter(args) {
|
|
56
|
+
const { data: { results, nextCursor }, } = await request({
|
|
57
|
+
httpMethod: 'GET',
|
|
58
|
+
baseUri: this.syncApiBase,
|
|
59
|
+
relativePath: ENDPOINT_REST_TASKS_FILTER,
|
|
60
|
+
apiToken: this.authToken,
|
|
61
|
+
customFetch: this.customFetch,
|
|
62
|
+
payload: args,
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
results: validateTaskArray(results),
|
|
66
|
+
nextCursor,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async getCompletedTasksByCompletionDate(args) {
|
|
70
|
+
const { data: { items, nextCursor }, } = await request({
|
|
71
|
+
httpMethod: 'GET',
|
|
72
|
+
baseUri: this.syncApiBase,
|
|
73
|
+
relativePath: ENDPOINT_REST_TASKS_COMPLETED_BY_COMPLETION_DATE,
|
|
74
|
+
apiToken: this.authToken,
|
|
75
|
+
customFetch: this.customFetch,
|
|
76
|
+
payload: args,
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
items: validateTaskArray(items),
|
|
80
|
+
nextCursor,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async getCompletedTasksByDueDate(args) {
|
|
84
|
+
const { data: { items, nextCursor }, } = await request({
|
|
85
|
+
httpMethod: 'GET',
|
|
86
|
+
baseUri: this.syncApiBase,
|
|
87
|
+
relativePath: ENDPOINT_REST_TASKS_COMPLETED_BY_DUE_DATE,
|
|
88
|
+
apiToken: this.authToken,
|
|
89
|
+
customFetch: this.customFetch,
|
|
90
|
+
payload: args,
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
items: validateTaskArray(items),
|
|
94
|
+
nextCursor,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async searchCompletedTasks(args) {
|
|
98
|
+
const { data: { items, nextCursor }, } = await request({
|
|
99
|
+
httpMethod: 'GET',
|
|
100
|
+
baseUri: this.syncApiBase,
|
|
101
|
+
relativePath: ENDPOINT_REST_TASKS_COMPLETED_SEARCH,
|
|
102
|
+
apiToken: this.authToken,
|
|
103
|
+
customFetch: this.customFetch,
|
|
104
|
+
payload: args,
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
items: validateTaskArray(items),
|
|
108
|
+
nextCursor,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
async getAllCompletedTasks(args = {}) {
|
|
112
|
+
const { since, until } = args, rest = __rest(args, ["since", "until"]);
|
|
113
|
+
const { data } = await request({
|
|
114
|
+
httpMethod: 'GET',
|
|
115
|
+
baseUri: this.syncApiBase,
|
|
116
|
+
relativePath: ENDPOINT_REST_TASKS_COMPLETED,
|
|
117
|
+
apiToken: this.authToken,
|
|
118
|
+
customFetch: this.customFetch,
|
|
119
|
+
payload: Object.assign(Object.assign(Object.assign({}, rest), (since ? { since: since.toISOString() } : {})), (until ? { until: until.toISOString() } : {})),
|
|
120
|
+
});
|
|
121
|
+
return {
|
|
122
|
+
projects: data.projects,
|
|
123
|
+
sections: data.sections,
|
|
124
|
+
items: validateTaskArray(data.items),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async addTask(args, requestId) {
|
|
128
|
+
// Process content based on isUncompletable flag
|
|
129
|
+
const processedArgs = Object.assign(Object.assign({}, args), { content: processTaskContent(args.content, args.isUncompletable) });
|
|
130
|
+
const response = await request({
|
|
131
|
+
httpMethod: 'POST',
|
|
132
|
+
baseUri: this.syncApiBase,
|
|
133
|
+
relativePath: ENDPOINT_REST_TASKS,
|
|
134
|
+
apiToken: this.authToken,
|
|
135
|
+
customFetch: this.customFetch,
|
|
136
|
+
payload: processedArgs,
|
|
137
|
+
requestId: requestId,
|
|
138
|
+
});
|
|
139
|
+
return validateTask(response.data);
|
|
140
|
+
}
|
|
141
|
+
async quickAddTask(args) {
|
|
142
|
+
// Process text based on isUncompletable flag
|
|
143
|
+
const processedArgs = Object.assign(Object.assign({}, args), { text: processTaskContent(args.text, args.isUncompletable) });
|
|
144
|
+
const response = await request({
|
|
145
|
+
httpMethod: 'POST',
|
|
146
|
+
baseUri: this.syncApiBase,
|
|
147
|
+
relativePath: ENDPOINT_SYNC_QUICK_ADD,
|
|
148
|
+
apiToken: this.authToken,
|
|
149
|
+
customFetch: this.customFetch,
|
|
150
|
+
payload: processedArgs,
|
|
151
|
+
});
|
|
152
|
+
return validateTask(response.data);
|
|
153
|
+
}
|
|
154
|
+
async updateTask(id, args, requestId) {
|
|
155
|
+
z.string().parse(id);
|
|
156
|
+
// Translate SDK alias for due-date clearing to Todoist's accepted payload value.
|
|
157
|
+
const normalizedArgs = args.dueString === null ? Object.assign(Object.assign({}, args), { dueString: 'no date' }) : args;
|
|
158
|
+
// Process content if both content and isUncompletable are provided
|
|
159
|
+
const processedArgs = normalizedArgs.content && normalizedArgs.isUncompletable !== undefined
|
|
160
|
+
? Object.assign(Object.assign({}, normalizedArgs), { content: processTaskContent(normalizedArgs.content, normalizedArgs.isUncompletable) }) : normalizedArgs;
|
|
161
|
+
// Remap `order` → `childOrder` so snakeCaseKeys() produces `child_order`
|
|
162
|
+
const { order } = processedArgs, argsWithoutOrder = __rest(processedArgs, ["order"]);
|
|
163
|
+
const remappedArgs = order !== undefined ? Object.assign(Object.assign({}, argsWithoutOrder), { childOrder: order }) : argsWithoutOrder;
|
|
164
|
+
const response = await request({
|
|
165
|
+
httpMethod: 'POST',
|
|
166
|
+
baseUri: this.syncApiBase,
|
|
167
|
+
relativePath: generatePath(ENDPOINT_REST_TASKS, id),
|
|
168
|
+
apiToken: this.authToken,
|
|
169
|
+
customFetch: this.customFetch,
|
|
170
|
+
payload: remappedArgs,
|
|
171
|
+
requestId: requestId,
|
|
172
|
+
});
|
|
173
|
+
return validateTask(response.data);
|
|
174
|
+
}
|
|
175
|
+
async moveTasks(ids, args, requestId) {
|
|
176
|
+
var _a;
|
|
177
|
+
if (ids.length > MAX_COMMAND_COUNT) {
|
|
178
|
+
throw new TodoistRequestError(`Maximum number of items is ${MAX_COMMAND_COUNT}`, 400);
|
|
179
|
+
}
|
|
180
|
+
const commands = ids.map((id) => ({
|
|
181
|
+
type: 'item_move',
|
|
182
|
+
uuid: uuidv4(),
|
|
183
|
+
args: Object.assign(Object.assign(Object.assign({ id }, spreadIfDefined(args.projectId, (v) => ({ projectId: v }))), spreadIfDefined(args.sectionId, (v) => ({ sectionId: v }))), spreadIfDefined(args.parentId, (v) => ({ parentId: v }))),
|
|
184
|
+
}));
|
|
185
|
+
const syncRequest = {
|
|
186
|
+
commands,
|
|
187
|
+
resourceTypes: ['items'],
|
|
188
|
+
};
|
|
189
|
+
const syncResponse = await performSyncRequest(this.syncContext, syncRequest, {
|
|
190
|
+
requestId,
|
|
191
|
+
hasSyncCommands: true,
|
|
192
|
+
});
|
|
193
|
+
if (!((_a = syncResponse.items) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
194
|
+
throw new TodoistRequestError('Tasks not found', 404);
|
|
195
|
+
}
|
|
196
|
+
const syncTasks = syncResponse.items.filter((task) => ids.includes(task.id));
|
|
197
|
+
if (!syncTasks.length) {
|
|
198
|
+
throw new TodoistRequestError('Tasks not found', 404);
|
|
199
|
+
}
|
|
200
|
+
return validateTaskArray(syncTasks);
|
|
201
|
+
}
|
|
202
|
+
async moveTask(id, args, requestId) {
|
|
203
|
+
z.string().parse(id);
|
|
204
|
+
const response = await request({
|
|
205
|
+
httpMethod: 'POST',
|
|
206
|
+
baseUri: this.syncApiBase,
|
|
207
|
+
relativePath: generatePath(ENDPOINT_REST_TASKS, id, ENDPOINT_REST_TASK_MOVE),
|
|
208
|
+
apiToken: this.authToken,
|
|
209
|
+
customFetch: this.customFetch,
|
|
210
|
+
payload: Object.assign(Object.assign(Object.assign({}, spreadIfDefined(args.projectId, (v) => ({ project_id: v }))), spreadIfDefined(args.sectionId, (v) => ({ section_id: v }))), spreadIfDefined(args.parentId, (v) => ({ parent_id: v }))),
|
|
211
|
+
requestId: requestId,
|
|
212
|
+
});
|
|
213
|
+
return validateTask(response.data);
|
|
214
|
+
}
|
|
215
|
+
async closeTask(id, requestId) {
|
|
216
|
+
z.string().parse(id);
|
|
217
|
+
const response = await request({
|
|
218
|
+
httpMethod: 'POST',
|
|
219
|
+
baseUri: this.syncApiBase,
|
|
220
|
+
relativePath: generatePath(ENDPOINT_REST_TASKS, id, ENDPOINT_REST_TASK_CLOSE),
|
|
221
|
+
apiToken: this.authToken,
|
|
222
|
+
customFetch: this.customFetch,
|
|
223
|
+
requestId: requestId,
|
|
224
|
+
});
|
|
225
|
+
return isSuccess(response);
|
|
226
|
+
}
|
|
227
|
+
async reopenTask(id, requestId) {
|
|
228
|
+
z.string().parse(id);
|
|
229
|
+
const response = await request({
|
|
230
|
+
httpMethod: 'POST',
|
|
231
|
+
baseUri: this.syncApiBase,
|
|
232
|
+
relativePath: generatePath(ENDPOINT_REST_TASKS, id, ENDPOINT_REST_TASK_REOPEN),
|
|
233
|
+
apiToken: this.authToken,
|
|
234
|
+
customFetch: this.customFetch,
|
|
235
|
+
requestId: requestId,
|
|
236
|
+
});
|
|
237
|
+
return isSuccess(response);
|
|
238
|
+
}
|
|
239
|
+
async deleteTask(id, requestId) {
|
|
240
|
+
z.string().parse(id);
|
|
241
|
+
const response = await request({
|
|
242
|
+
httpMethod: 'DELETE',
|
|
243
|
+
baseUri: this.syncApiBase,
|
|
244
|
+
relativePath: generatePath(ENDPOINT_REST_TASKS, id),
|
|
245
|
+
apiToken: this.authToken,
|
|
246
|
+
customFetch: this.customFetch,
|
|
247
|
+
requestId: requestId,
|
|
248
|
+
});
|
|
249
|
+
return isSuccess(response);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
import { request } from '../transport/http-client.js';
|
|
3
|
+
import { camelCaseKeys } from '../utils/case-conversion.js';
|
|
4
|
+
import { uploadMultipartFile } from '../utils/multipart-upload.js';
|
|
5
|
+
import { validateCommentArray, validateProjectArray, validateSectionArray, validateTaskArray, } from '../utils/validators.js';
|
|
6
|
+
import { BaseClient } from './base-client.js';
|
|
7
|
+
/**
|
|
8
|
+
* Internal sub-client handling all template-domain endpoints.
|
|
9
|
+
*
|
|
10
|
+
* Instantiated by `TodoistApi`; every public template method on
|
|
11
|
+
* `TodoistApi` delegates here. See `todoist-api.ts` for user-facing
|
|
12
|
+
* JSDoc.
|
|
13
|
+
*/
|
|
14
|
+
export class TemplateClient extends BaseClient {
|
|
15
|
+
async exportTemplateAsFile(args) {
|
|
16
|
+
const response = await request({
|
|
17
|
+
httpMethod: 'GET',
|
|
18
|
+
baseUri: this.syncApiBase,
|
|
19
|
+
relativePath: ENDPOINT_REST_TEMPLATES_FILE,
|
|
20
|
+
apiToken: this.authToken,
|
|
21
|
+
customFetch: this.customFetch,
|
|
22
|
+
payload: args,
|
|
23
|
+
});
|
|
24
|
+
return response.data;
|
|
25
|
+
}
|
|
26
|
+
async exportTemplateAsUrl(args) {
|
|
27
|
+
const { data } = await request({
|
|
28
|
+
httpMethod: 'GET',
|
|
29
|
+
baseUri: this.syncApiBase,
|
|
30
|
+
relativePath: ENDPOINT_REST_TEMPLATES_URL,
|
|
31
|
+
apiToken: this.authToken,
|
|
32
|
+
customFetch: this.customFetch,
|
|
33
|
+
payload: args,
|
|
34
|
+
});
|
|
35
|
+
return data;
|
|
36
|
+
}
|
|
37
|
+
async createProjectFromTemplate(args, requestId) {
|
|
38
|
+
const { file, fileName, name, workspaceId } = args;
|
|
39
|
+
const additionalFields = { name };
|
|
40
|
+
if (workspaceId !== undefined && workspaceId !== null) {
|
|
41
|
+
additionalFields.workspace_id = workspaceId;
|
|
42
|
+
}
|
|
43
|
+
const data = await uploadMultipartFile({
|
|
44
|
+
baseUrl: this.syncApiBase,
|
|
45
|
+
authToken: this.authToken,
|
|
46
|
+
endpoint: ENDPOINT_REST_TEMPLATES_CREATE_FROM_FILE,
|
|
47
|
+
file,
|
|
48
|
+
fileName,
|
|
49
|
+
additionalFields,
|
|
50
|
+
customFetch: this.customFetch,
|
|
51
|
+
requestId,
|
|
52
|
+
});
|
|
53
|
+
return this.validateTemplateResponse(camelCaseKeys(data));
|
|
54
|
+
}
|
|
55
|
+
async importTemplateIntoProject(args, requestId) {
|
|
56
|
+
const { file, fileName, projectId } = args;
|
|
57
|
+
const data = await uploadMultipartFile({
|
|
58
|
+
baseUrl: this.syncApiBase,
|
|
59
|
+
authToken: this.authToken,
|
|
60
|
+
endpoint: ENDPOINT_REST_TEMPLATES_IMPORT_FROM_FILE,
|
|
61
|
+
file,
|
|
62
|
+
fileName,
|
|
63
|
+
additionalFields: { project_id: projectId },
|
|
64
|
+
customFetch: this.customFetch,
|
|
65
|
+
requestId,
|
|
66
|
+
});
|
|
67
|
+
return this.validateTemplateResponse(camelCaseKeys(data));
|
|
68
|
+
}
|
|
69
|
+
async importTemplateFromId(args, requestId) {
|
|
70
|
+
const { data } = await request({
|
|
71
|
+
httpMethod: 'POST',
|
|
72
|
+
baseUri: this.syncApiBase,
|
|
73
|
+
relativePath: ENDPOINT_REST_TEMPLATES_IMPORT_FROM_ID,
|
|
74
|
+
apiToken: this.authToken,
|
|
75
|
+
customFetch: this.customFetch,
|
|
76
|
+
payload: args,
|
|
77
|
+
requestId: requestId,
|
|
78
|
+
});
|
|
79
|
+
return this.validateTemplateResponse(data);
|
|
80
|
+
}
|
|
81
|
+
validateTemplateResponse(data) {
|
|
82
|
+
var _a, _b, _c, _d;
|
|
83
|
+
return Object.assign(Object.assign({}, data), { projects: validateProjectArray((_a = data.projects) !== null && _a !== void 0 ? _a : []), sections: validateSectionArray((_b = data.sections) !== null && _b !== void 0 ? _b : []), tasks: validateTaskArray((_c = data.tasks) !== null && _c !== void 0 ? _c : []), comments: validateCommentArray((_d = data.comments) !== null && _d !== void 0 ? _d : []) });
|
|
84
|
+
}
|
|
85
|
+
}
|