@panoptic-it-solutions/zoho-projects-client 0.2.4 → 0.2.6
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/README.md +75 -7
- package/dist/__tests__/fixtures/attachments.d.ts +59 -39
- package/dist/__tests__/fixtures/attachments.d.ts.map +1 -1
- package/dist/__tests__/fixtures/attachments.js +2 -4
- package/dist/__tests__/fixtures/attachments.js.map +1 -1
- package/dist/__tests__/fixtures/comments.d.ts +25 -13
- package/dist/__tests__/fixtures/comments.d.ts.map +1 -1
- package/dist/__tests__/fixtures/events.d.ts +27 -15
- package/dist/__tests__/fixtures/events.d.ts.map +1 -1
- package/dist/__tests__/fixtures/forums.d.ts +25 -13
- package/dist/__tests__/fixtures/forums.d.ts.map +1 -1
- package/dist/__tests__/fixtures/issues.d.ts +50 -26
- package/dist/__tests__/fixtures/issues.d.ts.map +1 -1
- package/dist/__tests__/fixtures/phases.d.ts +325 -41
- package/dist/__tests__/fixtures/phases.d.ts.map +1 -1
- package/dist/__tests__/fixtures/projects.d.ts +176 -8
- package/dist/__tests__/fixtures/projects.d.ts.map +1 -1
- package/dist/__tests__/fixtures/tasklists.d.ts +71 -25
- package/dist/__tests__/fixtures/tasklists.d.ts.map +1 -1
- package/dist/__tests__/fixtures/tasklists.js +1 -3
- package/dist/__tests__/fixtures/tasklists.js.map +1 -1
- package/dist/__tests__/fixtures/tasks.d.ts +257 -62
- package/dist/__tests__/fixtures/tasks.d.ts.map +1 -1
- package/dist/__tests__/fixtures/timelogs.d.ts +2 -2
- package/dist/__tests__/integration/api-v3.test.d.ts +2 -0
- package/dist/__tests__/integration/api-v3.test.d.ts.map +1 -0
- package/dist/__tests__/integration/api-v3.test.js +180 -0
- package/dist/__tests__/integration/api-v3.test.js.map +1 -0
- package/dist/__tests__/integration/setup.d.ts +0 -3
- package/dist/__tests__/integration/setup.d.ts.map +1 -1
- package/dist/__tests__/integration/setup.js +7 -1
- package/dist/__tests__/integration/setup.js.map +1 -1
- package/dist/__tests__/unit/client/attachments.test.js +31 -10
- package/dist/__tests__/unit/client/attachments.test.js.map +1 -1
- package/dist/__tests__/unit/client/blueprints.test.js +11 -11
- package/dist/__tests__/unit/client/blueprints.test.js.map +1 -1
- package/dist/__tests__/unit/client/clients.test.js +6 -6
- package/dist/__tests__/unit/client/clients.test.js.map +1 -1
- package/dist/__tests__/unit/client/comments.test.js +7 -7
- package/dist/__tests__/unit/client/comments.test.js.map +1 -1
- package/dist/__tests__/unit/client/contacts.test.js +6 -6
- package/dist/__tests__/unit/client/contacts.test.js.map +1 -1
- package/dist/__tests__/unit/client/customviews.test.js +8 -8
- package/dist/__tests__/unit/client/customviews.test.js.map +1 -1
- package/dist/__tests__/unit/client/dashboards.test.js +6 -6
- package/dist/__tests__/unit/client/dashboards.test.js.map +1 -1
- package/dist/__tests__/unit/client/events.test.js +6 -6
- package/dist/__tests__/unit/client/events.test.js.map +1 -1
- package/dist/__tests__/unit/client/followers.test.js +8 -8
- package/dist/__tests__/unit/client/followers.test.js.map +1 -1
- package/dist/__tests__/unit/client/forums.test.js +6 -6
- package/dist/__tests__/unit/client/forums.test.js.map +1 -1
- package/dist/__tests__/unit/client/groups.test.js +6 -6
- package/dist/__tests__/unit/client/groups.test.js.map +1 -1
- package/dist/__tests__/unit/client/issues.test.js +6 -6
- package/dist/__tests__/unit/client/issues.test.js.map +1 -1
- package/dist/__tests__/unit/client/leaves.test.js +6 -6
- package/dist/__tests__/unit/client/leaves.test.js.map +1 -1
- package/dist/__tests__/unit/client/modules.test.js +7 -7
- package/dist/__tests__/unit/client/modules.test.js.map +1 -1
- package/dist/__tests__/unit/client/phases.test.js +6 -6
- package/dist/__tests__/unit/client/phases.test.js.map +1 -1
- package/dist/__tests__/unit/client/portals.test.js +3 -3
- package/dist/__tests__/unit/client/portals.test.js.map +1 -1
- package/dist/__tests__/unit/client/profiles.test.js +6 -6
- package/dist/__tests__/unit/client/profiles.test.js.map +1 -1
- package/dist/__tests__/unit/client/projects.test.js +18 -18
- package/dist/__tests__/unit/client/projects.test.js.map +1 -1
- package/dist/__tests__/unit/client/reports.test.js +9 -9
- package/dist/__tests__/unit/client/reports.test.js.map +1 -1
- package/dist/__tests__/unit/client/roles.test.js +6 -6
- package/dist/__tests__/unit/client/roles.test.js.map +1 -1
- package/dist/__tests__/unit/client/search.test.js +7 -7
- package/dist/__tests__/unit/client/search.test.js.map +1 -1
- package/dist/__tests__/unit/client/tags.test.js +9 -9
- package/dist/__tests__/unit/client/tags.test.js.map +1 -1
- package/dist/__tests__/unit/client/tasklists.test.js +12 -12
- package/dist/__tests__/unit/client/tasklists.test.js.map +1 -1
- package/dist/__tests__/unit/client/tasks.test.js +17 -17
- package/dist/__tests__/unit/client/tasks.test.js.map +1 -1
- package/dist/__tests__/unit/client/teams.test.js +8 -8
- package/dist/__tests__/unit/client/teams.test.js.map +1 -1
- package/dist/__tests__/unit/client/timelogs.test.js +7 -7
- package/dist/__tests__/unit/client/timelogs.test.js.map +1 -1
- package/dist/__tests__/unit/client/timers.test.js +11 -11
- package/dist/__tests__/unit/client/timers.test.js.map +1 -1
- package/dist/__tests__/unit/client/trash.test.js +8 -8
- package/dist/__tests__/unit/client/trash.test.js.map +1 -1
- package/dist/__tests__/unit/client/users.test.js +8 -8
- package/dist/__tests__/unit/client/users.test.js.map +1 -1
- package/dist/__tests__/unit/client/widgets.test.js +6 -6
- package/dist/__tests__/unit/client/widgets.test.js.map +1 -1
- package/dist/client.d.ts +63 -11
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +470 -274
- package/dist/client.js.map +1 -1
- package/dist/types/attachments.d.ts +1525 -512
- package/dist/types/attachments.d.ts.map +1 -1
- package/dist/types/attachments.js +51 -10
- package/dist/types/attachments.js.map +1 -1
- package/dist/types/clients.js +2 -2
- package/dist/types/clients.js.map +1 -1
- package/dist/types/comments.d.ts +325 -169
- package/dist/types/comments.d.ts.map +1 -1
- package/dist/types/common.d.ts +33 -15
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types/common.js +12 -7
- package/dist/types/common.js.map +1 -1
- package/dist/types/contacts.d.ts +6 -6
- package/dist/types/dashboards.d.ts +979 -511
- package/dist/types/dashboards.d.ts.map +1 -1
- package/dist/types/dashboards.js +1 -1
- package/dist/types/dashboards.js.map +1 -1
- package/dist/types/documents.d.ts +1300 -676
- package/dist/types/documents.d.ts.map +1 -1
- package/dist/types/events.d.ts +351 -195
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/forums.d.ts +325 -169
- package/dist/types/forums.d.ts.map +1 -1
- package/dist/types/forums.js +2 -2
- package/dist/types/forums.js.map +1 -1
- package/dist/types/groups.js +1 -1
- package/dist/types/groups.js.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/issues.d.ts +650 -338
- package/dist/types/issues.d.ts.map +1 -1
- package/dist/types/issues.js +3 -3
- package/dist/types/issues.js.map +1 -1
- package/dist/types/phases.d.ts +4358 -561
- package/dist/types/phases.d.ts.map +1 -1
- package/dist/types/phases.js +103 -25
- package/dist/types/phases.js.map +1 -1
- package/dist/types/portals.js +5 -5
- package/dist/types/portals.js.map +1 -1
- package/dist/types/profiles.js +1 -1
- package/dist/types/profiles.js.map +1 -1
- package/dist/types/projects.d.ts +6324 -1368
- package/dist/types/projects.d.ts.map +1 -1
- package/dist/types/projects.js +123 -39
- package/dist/types/projects.js.map +1 -1
- package/dist/types/reports.d.ts +650 -338
- package/dist/types/reports.d.ts.map +1 -1
- package/dist/types/reports.js +1 -1
- package/dist/types/reports.js.map +1 -1
- package/dist/types/search.js +1 -1
- package/dist/types/search.js.map +1 -1
- package/dist/types/tags.js +1 -1
- package/dist/types/tags.js.map +1 -1
- package/dist/types/tasklists.d.ts +938 -326
- package/dist/types/tasklists.d.ts.map +1 -1
- package/dist/types/tasklists.js +43 -16
- package/dist/types/tasklists.js.map +1 -1
- package/dist/types/tasks.d.ts +3516 -876
- package/dist/types/tasks.d.ts.map +1 -1
- package/dist/types/tasks.js +70 -23
- package/dist/types/tasks.js.map +1 -1
- package/dist/types/teams.js +2 -2
- package/dist/types/teams.js.map +1 -1
- package/dist/types/timelogs.d.ts +232 -230
- package/dist/types/timelogs.d.ts.map +1 -1
- package/dist/types/timelogs.js.map +1 -1
- package/dist/types/timers.d.ts +750 -390
- package/dist/types/timers.d.ts.map +1 -1
- package/dist/types/trash.d.ts +650 -338
- package/dist/types/trash.d.ts.map +1 -1
- package/dist/types/workdrive.d.ts +1002 -0
- package/dist/types/workdrive.d.ts.map +1 -0
- package/dist/types/workdrive.js +70 -0
- package/dist/types/workdrive.js.map +1 -0
- package/dist/utils/pagination.d.ts +9 -9
- package/dist/utils/pagination.d.ts.map +1 -1
- package/dist/utils/pagination.js +11 -11
- package/dist/utils/pagination.js.map +1 -1
- package/package.json +3 -1
- package/templates/CLAUDE.md +185 -2
package/dist/client.js
CHANGED
|
@@ -96,8 +96,8 @@ export function createZohoProjectsClient(config) {
|
|
|
96
96
|
}
|
|
97
97
|
return result.data;
|
|
98
98
|
}
|
|
99
|
-
// Base path for portal-specific endpoints
|
|
100
|
-
const basePath = `/
|
|
99
|
+
// Base path for portal-specific endpoints (V3 API)
|
|
100
|
+
const basePath = `/api/v3/portal/${portalId}`;
|
|
101
101
|
return {
|
|
102
102
|
/**
|
|
103
103
|
* Projects API
|
|
@@ -107,17 +107,20 @@ export function createZohoProjectsClient(config) {
|
|
|
107
107
|
* List projects with pagination
|
|
108
108
|
*/
|
|
109
109
|
async list(params) {
|
|
110
|
-
const response = await requestWithValidation(`${basePath}/projects
|
|
110
|
+
const response = await requestWithValidation(`${basePath}/projects`, ProjectListResponseSchema, {
|
|
111
111
|
params: {
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
page: params?.page ?? params?.index ?? 1,
|
|
113
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
114
114
|
sort_column: params?.sort_column,
|
|
115
115
|
sort_order: params?.sort_order,
|
|
116
116
|
},
|
|
117
117
|
});
|
|
118
|
+
// V3 API returns array directly, legacy API wraps in { projects: [...] }
|
|
119
|
+
const projects = Array.isArray(response) ? response : response.projects;
|
|
120
|
+
const pageInfo = Array.isArray(response) ? undefined : response.page_info;
|
|
118
121
|
return {
|
|
119
|
-
data:
|
|
120
|
-
pageInfo
|
|
122
|
+
data: projects,
|
|
123
|
+
pageInfo,
|
|
121
124
|
};
|
|
122
125
|
},
|
|
123
126
|
/**
|
|
@@ -130,37 +133,65 @@ export function createZohoProjectsClient(config) {
|
|
|
130
133
|
* Iterate over all projects with auto-pagination
|
|
131
134
|
*/
|
|
132
135
|
iterate(options) {
|
|
133
|
-
return autoPaginate((
|
|
136
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
134
137
|
},
|
|
135
138
|
/**
|
|
136
139
|
* Get a single project by ID
|
|
137
140
|
*/
|
|
138
141
|
async get(projectId) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
// V3 API returns project directly, legacy wraps in {projects: [...]}
|
|
143
|
+
const schema = z.union([
|
|
144
|
+
ProjectSchema, // V3: returns project directly
|
|
145
|
+
z.object({ projects: z.array(ProjectSchema) }), // Legacy
|
|
146
|
+
]);
|
|
147
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}`, schema);
|
|
148
|
+
// Handle both formats
|
|
149
|
+
if (response && typeof response === "object" && "projects" in response) {
|
|
150
|
+
const legacyResponse = response;
|
|
151
|
+
if (legacyResponse.projects.length === 0) {
|
|
152
|
+
throw new ZohoProjectsError(`Project not found: ${projectId}`, 404);
|
|
153
|
+
}
|
|
154
|
+
return legacyResponse.projects[0];
|
|
142
155
|
}
|
|
143
|
-
return response
|
|
156
|
+
return response;
|
|
144
157
|
},
|
|
145
158
|
/**
|
|
146
159
|
* Create a new project
|
|
147
160
|
*/
|
|
148
161
|
async create(data) {
|
|
149
|
-
|
|
150
|
-
|
|
162
|
+
// V3 API returns project directly, legacy wraps in {projects: [...]}
|
|
163
|
+
const schema = z.union([
|
|
164
|
+
ProjectSchema, // V3: returns project directly
|
|
165
|
+
z.object({ projects: z.array(ProjectSchema) }), // Legacy
|
|
166
|
+
]);
|
|
167
|
+
const response = await requestWithValidation(`${basePath}/projects`, schema, { method: "POST", data });
|
|
168
|
+
// Handle both formats
|
|
169
|
+
if (response && typeof response === "object" && "projects" in response) {
|
|
170
|
+
return response.projects[0];
|
|
171
|
+
}
|
|
172
|
+
return response;
|
|
151
173
|
},
|
|
152
174
|
/**
|
|
153
175
|
* Update an existing project
|
|
154
176
|
*/
|
|
155
177
|
async update(projectId, data) {
|
|
156
|
-
|
|
157
|
-
|
|
178
|
+
// V3 API returns project directly, legacy wraps in {projects: [...]}
|
|
179
|
+
const schema = z.union([
|
|
180
|
+
ProjectSchema, // V3: returns project directly
|
|
181
|
+
z.object({ projects: z.array(ProjectSchema) }), // Legacy
|
|
182
|
+
]);
|
|
183
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}`, schema, { method: "PUT", data });
|
|
184
|
+
// Handle both formats
|
|
185
|
+
if (response && typeof response === "object" && "projects" in response) {
|
|
186
|
+
return response.projects[0];
|
|
187
|
+
}
|
|
188
|
+
return response;
|
|
158
189
|
},
|
|
159
190
|
/**
|
|
160
191
|
* Delete a project (moves to trash)
|
|
161
192
|
*/
|
|
162
193
|
async delete(projectId) {
|
|
163
|
-
await request(`${basePath}/projects/${projectId}
|
|
194
|
+
await request(`${basePath}/projects/${projectId}`, {
|
|
164
195
|
method: "DELETE",
|
|
165
196
|
});
|
|
166
197
|
},
|
|
@@ -173,10 +204,10 @@ export function createZohoProjectsClient(config) {
|
|
|
173
204
|
* List tasks for a project with pagination
|
|
174
205
|
*/
|
|
175
206
|
async list(projectId, params) {
|
|
176
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasks
|
|
207
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasks`, TaskListResponseSchema, {
|
|
177
208
|
params: {
|
|
178
|
-
|
|
179
|
-
|
|
209
|
+
page: params?.page ?? params?.index ?? 1,
|
|
210
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
180
211
|
sort_column: params?.sort_column,
|
|
181
212
|
sort_order: params?.sort_order,
|
|
182
213
|
},
|
|
@@ -196,17 +227,27 @@ export function createZohoProjectsClient(config) {
|
|
|
196
227
|
* Iterate over all tasks for a project with auto-pagination
|
|
197
228
|
*/
|
|
198
229
|
iterate(projectId, options) {
|
|
199
|
-
return autoPaginate((
|
|
230
|
+
return autoPaginate((page, per_page) => this.list(projectId, { page, per_page }), options);
|
|
200
231
|
},
|
|
201
232
|
/**
|
|
202
233
|
* Get a single task by ID
|
|
203
234
|
*/
|
|
204
235
|
async get(projectId, taskId) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
236
|
+
// V3 API returns task directly, legacy wraps in {tasks: [...]}
|
|
237
|
+
const schema = z.union([
|
|
238
|
+
TaskSchema, // V3: returns task directly
|
|
239
|
+
z.object({ tasks: z.array(TaskSchema) }), // Legacy
|
|
240
|
+
]);
|
|
241
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasks/${taskId}`, schema);
|
|
242
|
+
// Handle both formats
|
|
243
|
+
if (response && typeof response === "object" && "tasks" in response) {
|
|
244
|
+
const legacyResponse = response;
|
|
245
|
+
if (legacyResponse.tasks.length === 0) {
|
|
246
|
+
throw new ZohoProjectsError(`Task not found: ${taskId}`, 404);
|
|
247
|
+
}
|
|
248
|
+
return legacyResponse.tasks[0];
|
|
208
249
|
}
|
|
209
|
-
return response
|
|
250
|
+
return response;
|
|
210
251
|
},
|
|
211
252
|
/**
|
|
212
253
|
* List all tasks across all projects
|
|
@@ -216,30 +257,51 @@ export function createZohoProjectsClient(config) {
|
|
|
216
257
|
const projects = await this._getProjectsRef().listAll();
|
|
217
258
|
const allTasks = [];
|
|
218
259
|
for (const project of projects) {
|
|
219
|
-
|
|
260
|
+
// V3 API uses 'id' as string directly, legacy uses 'id_string'
|
|
261
|
+
const tasks = await this.listAll(String(project.id), options);
|
|
220
262
|
allTasks.push(...tasks);
|
|
221
263
|
}
|
|
222
264
|
return allTasks;
|
|
223
265
|
},
|
|
224
266
|
/**
|
|
225
267
|
* Create a new task in a project
|
|
268
|
+
* Note: V3 API requires a tasklist to be specified
|
|
226
269
|
*/
|
|
227
270
|
async create(projectId, data) {
|
|
228
|
-
|
|
229
|
-
|
|
271
|
+
// V3 API returns task directly, legacy wraps in {tasks: [...]}
|
|
272
|
+
const schema = z.union([
|
|
273
|
+
TaskSchema, // V3: returns task directly
|
|
274
|
+
z.object({ tasks: z.array(TaskSchema) }), // Legacy
|
|
275
|
+
]);
|
|
276
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasks`, schema, { method: "POST", data });
|
|
277
|
+
// Handle both formats
|
|
278
|
+
if (response && typeof response === "object" && "tasks" in response) {
|
|
279
|
+
return response.tasks[0];
|
|
280
|
+
}
|
|
281
|
+
return response;
|
|
230
282
|
},
|
|
231
283
|
/**
|
|
232
284
|
* Update an existing task
|
|
285
|
+
* Note: V3 API uses PATCH method for updates
|
|
233
286
|
*/
|
|
234
287
|
async update(projectId, taskId, data) {
|
|
235
|
-
|
|
236
|
-
|
|
288
|
+
// V3 API returns task directly, legacy wraps in {tasks: [...]}
|
|
289
|
+
const schema = z.union([
|
|
290
|
+
TaskSchema, // V3: returns task directly
|
|
291
|
+
z.object({ tasks: z.array(TaskSchema) }), // Legacy
|
|
292
|
+
]);
|
|
293
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasks/${taskId}`, schema, { method: "PATCH", data });
|
|
294
|
+
// Handle both formats
|
|
295
|
+
if (response && typeof response === "object" && "tasks" in response) {
|
|
296
|
+
return response.tasks[0];
|
|
297
|
+
}
|
|
298
|
+
return response;
|
|
237
299
|
},
|
|
238
300
|
/**
|
|
239
301
|
* Delete a task (moves to trash)
|
|
240
302
|
*/
|
|
241
303
|
async delete(projectId, taskId) {
|
|
242
|
-
await request(`${basePath}/projects/${projectId}/tasks/${taskId}
|
|
304
|
+
await request(`${basePath}/projects/${projectId}/tasks/${taskId}`, {
|
|
243
305
|
method: "DELETE",
|
|
244
306
|
});
|
|
245
307
|
},
|
|
@@ -255,10 +317,10 @@ export function createZohoProjectsClient(config) {
|
|
|
255
317
|
*/
|
|
256
318
|
async list(projectId, params) {
|
|
257
319
|
// Make the request - may return 204 No Content if no logs
|
|
258
|
-
const rawResponse = await request(`${basePath}/projects/${projectId}/logs
|
|
320
|
+
const rawResponse = await request(`${basePath}/projects/${projectId}/logs`, {
|
|
259
321
|
params: {
|
|
260
|
-
|
|
261
|
-
|
|
322
|
+
page: params.page ?? 1,
|
|
323
|
+
per_page: params.per_page ?? DEFAULT_PAGE_SIZE,
|
|
262
324
|
users_list: params.users_list,
|
|
263
325
|
view_type: params.view_type,
|
|
264
326
|
date: params.date,
|
|
@@ -310,7 +372,7 @@ export function createZohoProjectsClient(config) {
|
|
|
310
372
|
* Iterate over all time logs for a project with auto-pagination
|
|
311
373
|
*/
|
|
312
374
|
iterate(projectId, params, options) {
|
|
313
|
-
return autoPaginate((
|
|
375
|
+
return autoPaginate((page, per_page) => this.list(projectId, { ...params, page, per_page }), options);
|
|
314
376
|
},
|
|
315
377
|
/**
|
|
316
378
|
* List all time logs across all projects
|
|
@@ -319,7 +381,8 @@ export function createZohoProjectsClient(config) {
|
|
|
319
381
|
const projects = await this._getProjectsRef().listAll();
|
|
320
382
|
const allLogs = [];
|
|
321
383
|
for (const project of projects) {
|
|
322
|
-
|
|
384
|
+
// V3 API uses 'id' as string directly, legacy uses 'id_string'
|
|
385
|
+
const logs = await this.listAll(String(project.id), params, options);
|
|
323
386
|
allLogs.push(...logs);
|
|
324
387
|
}
|
|
325
388
|
return allLogs;
|
|
@@ -328,28 +391,28 @@ export function createZohoProjectsClient(config) {
|
|
|
328
391
|
* Create a time log for a task
|
|
329
392
|
*/
|
|
330
393
|
async createForTask(projectId, data) {
|
|
331
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs
|
|
394
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs`, z.object({ timelogs: z.object({ tasklogs: z.array(TimeLogSchema) }) }), { method: "POST", data });
|
|
332
395
|
return response.timelogs.tasklogs[0];
|
|
333
396
|
},
|
|
334
397
|
/**
|
|
335
398
|
* Create a time log for a bug
|
|
336
399
|
*/
|
|
337
400
|
async createForBug(projectId, data) {
|
|
338
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs
|
|
401
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs`, z.object({ timelogs: z.object({ buglogs: z.array(TimeLogSchema) }) }), { method: "POST", data });
|
|
339
402
|
return response.timelogs.buglogs[0];
|
|
340
403
|
},
|
|
341
404
|
/**
|
|
342
405
|
* Create a general time log (not tied to task or bug)
|
|
343
406
|
*/
|
|
344
407
|
async createGeneral(projectId, data) {
|
|
345
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs
|
|
408
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs`, z.object({ timelogs: z.object({ generallogs: z.array(TimeLogSchema) }) }), { method: "POST", data });
|
|
346
409
|
return response.timelogs.generallogs[0];
|
|
347
410
|
},
|
|
348
411
|
/**
|
|
349
412
|
* Update a time log
|
|
350
413
|
*/
|
|
351
414
|
async update(projectId, logId, data) {
|
|
352
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs/${logId}
|
|
415
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/logs/${logId}`, z.object({ timelogs: z.object({ tasklogs: z.array(TimeLogSchema).optional(), buglogs: z.array(TimeLogSchema).optional(), generallogs: z.array(TimeLogSchema).optional() }) }), { method: "PUT", data });
|
|
353
416
|
// Return whichever type was updated
|
|
354
417
|
const logs = response.timelogs.tasklogs || response.timelogs.buglogs || response.timelogs.generallogs || [];
|
|
355
418
|
return logs[0];
|
|
@@ -358,7 +421,7 @@ export function createZohoProjectsClient(config) {
|
|
|
358
421
|
* Delete a time log
|
|
359
422
|
*/
|
|
360
423
|
async delete(projectId, logId) {
|
|
361
|
-
await request(`${basePath}/projects/${projectId}/logs/${logId}
|
|
424
|
+
await request(`${basePath}/projects/${projectId}/logs/${logId}`, {
|
|
362
425
|
method: "DELETE",
|
|
363
426
|
});
|
|
364
427
|
},
|
|
@@ -373,10 +436,10 @@ export function createZohoProjectsClient(config) {
|
|
|
373
436
|
* List all users in the portal
|
|
374
437
|
*/
|
|
375
438
|
async list(params) {
|
|
376
|
-
const response = await requestWithValidation(`${basePath}/users
|
|
439
|
+
const response = await requestWithValidation(`${basePath}/users`, UserListResponseSchema, {
|
|
377
440
|
params: {
|
|
378
|
-
|
|
379
|
-
|
|
441
|
+
page: params?.page ?? params?.index ?? 1,
|
|
442
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
380
443
|
},
|
|
381
444
|
});
|
|
382
445
|
return {
|
|
@@ -394,13 +457,13 @@ export function createZohoProjectsClient(config) {
|
|
|
394
457
|
* Iterate over all users with auto-pagination
|
|
395
458
|
*/
|
|
396
459
|
iterate(options) {
|
|
397
|
-
return autoPaginate((
|
|
460
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
398
461
|
},
|
|
399
462
|
/**
|
|
400
463
|
* Get a single user by ID
|
|
401
464
|
*/
|
|
402
465
|
async get(userId) {
|
|
403
|
-
const response = await requestWithValidation(`${basePath}/users/${userId}
|
|
466
|
+
const response = await requestWithValidation(`${basePath}/users/${userId}`, z.object({ users: z.array(UserSchema) }));
|
|
404
467
|
if (response.users.length === 0) {
|
|
405
468
|
throw new ZohoProjectsError(`User not found: ${userId}`, 404);
|
|
406
469
|
}
|
|
@@ -410,10 +473,10 @@ export function createZohoProjectsClient(config) {
|
|
|
410
473
|
* List users for a specific project
|
|
411
474
|
*/
|
|
412
475
|
async listForProject(projectId, params) {
|
|
413
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/users
|
|
476
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/users`, UserListResponseSchema, {
|
|
414
477
|
params: {
|
|
415
|
-
|
|
416
|
-
|
|
478
|
+
page: params?.page ?? params?.index ?? 1,
|
|
479
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
417
480
|
},
|
|
418
481
|
});
|
|
419
482
|
return {
|
|
@@ -425,28 +488,28 @@ export function createZohoProjectsClient(config) {
|
|
|
425
488
|
* Invite a new user to the portal
|
|
426
489
|
*/
|
|
427
490
|
async invite(data) {
|
|
428
|
-
const response = await requestWithValidation(`${basePath}/users
|
|
491
|
+
const response = await requestWithValidation(`${basePath}/users`, z.object({ users: z.array(UserSchema) }), { method: "POST", data });
|
|
429
492
|
return response.users[0];
|
|
430
493
|
},
|
|
431
494
|
/**
|
|
432
495
|
* Add a user to a project
|
|
433
496
|
*/
|
|
434
497
|
async addToProject(projectId, data) {
|
|
435
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/users
|
|
498
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/users`, z.object({ users: z.array(UserSchema) }), { method: "POST", data });
|
|
436
499
|
return response.users[0];
|
|
437
500
|
},
|
|
438
501
|
/**
|
|
439
502
|
* Update a user's details
|
|
440
503
|
*/
|
|
441
504
|
async update(userId, data) {
|
|
442
|
-
const response = await requestWithValidation(`${basePath}/users/${userId}
|
|
505
|
+
const response = await requestWithValidation(`${basePath}/users/${userId}`, z.object({ users: z.array(UserSchema) }), { method: "PUT", data });
|
|
443
506
|
return response.users[0];
|
|
444
507
|
},
|
|
445
508
|
/**
|
|
446
509
|
* Remove a user from the portal
|
|
447
510
|
*/
|
|
448
511
|
async delete(userId) {
|
|
449
|
-
await request(`${basePath}/users/${userId}
|
|
512
|
+
await request(`${basePath}/users/${userId}`, {
|
|
450
513
|
method: "DELETE",
|
|
451
514
|
});
|
|
452
515
|
},
|
|
@@ -454,7 +517,7 @@ export function createZohoProjectsClient(config) {
|
|
|
454
517
|
* Remove a user from a project
|
|
455
518
|
*/
|
|
456
519
|
async removeFromProject(projectId, userId) {
|
|
457
|
-
await request(`${basePath}/projects/${projectId}/users/${userId}
|
|
520
|
+
await request(`${basePath}/projects/${projectId}/users/${userId}`, {
|
|
458
521
|
method: "DELETE",
|
|
459
522
|
});
|
|
460
523
|
},
|
|
@@ -464,10 +527,10 @@ export function createZohoProjectsClient(config) {
|
|
|
464
527
|
*/
|
|
465
528
|
tags: {
|
|
466
529
|
async list(params) {
|
|
467
|
-
const response = await requestWithValidation(`${basePath}/tags
|
|
530
|
+
const response = await requestWithValidation(`${basePath}/tags`, TagListResponseSchema, {
|
|
468
531
|
params: {
|
|
469
|
-
|
|
470
|
-
|
|
532
|
+
page: params?.page ?? params?.index ?? 1,
|
|
533
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
471
534
|
},
|
|
472
535
|
});
|
|
473
536
|
return { data: response.tags, pageInfo: response.page_info };
|
|
@@ -476,25 +539,25 @@ export function createZohoProjectsClient(config) {
|
|
|
476
539
|
return collectAll(this.iterate(options));
|
|
477
540
|
},
|
|
478
541
|
iterate(options) {
|
|
479
|
-
return autoPaginate((
|
|
542
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
480
543
|
},
|
|
481
544
|
async get(tagId) {
|
|
482
|
-
const response = await requestWithValidation(`${basePath}/tags/${tagId}
|
|
545
|
+
const response = await requestWithValidation(`${basePath}/tags/${tagId}`, z.object({ tags: z.array(TagSchema) }));
|
|
483
546
|
if (response.tags.length === 0) {
|
|
484
547
|
throw new ZohoProjectsError(`Tag not found: ${tagId}`, 404);
|
|
485
548
|
}
|
|
486
549
|
return response.tags[0];
|
|
487
550
|
},
|
|
488
551
|
async create(data) {
|
|
489
|
-
const response = await requestWithValidation(`${basePath}/tags
|
|
552
|
+
const response = await requestWithValidation(`${basePath}/tags`, z.object({ tags: z.array(TagSchema) }), { method: "POST", data });
|
|
490
553
|
return response.tags[0];
|
|
491
554
|
},
|
|
492
555
|
async update(tagId, data) {
|
|
493
|
-
const response = await requestWithValidation(`${basePath}/tags/${tagId}
|
|
556
|
+
const response = await requestWithValidation(`${basePath}/tags/${tagId}`, z.object({ tags: z.array(TagSchema) }), { method: "PUT", data });
|
|
494
557
|
return response.tags[0];
|
|
495
558
|
},
|
|
496
559
|
async delete(tagId) {
|
|
497
|
-
await request(`${basePath}/tags/${tagId}
|
|
560
|
+
await request(`${basePath}/tags/${tagId}`, { method: "DELETE" });
|
|
498
561
|
},
|
|
499
562
|
},
|
|
500
563
|
/**
|
|
@@ -502,10 +565,10 @@ export function createZohoProjectsClient(config) {
|
|
|
502
565
|
*/
|
|
503
566
|
roles: {
|
|
504
567
|
async list(params) {
|
|
505
|
-
const response = await requestWithValidation(`${basePath}/roles
|
|
568
|
+
const response = await requestWithValidation(`${basePath}/roles`, RoleListResponseSchema, {
|
|
506
569
|
params: {
|
|
507
|
-
|
|
508
|
-
|
|
570
|
+
page: params?.page ?? params?.index ?? 1,
|
|
571
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
509
572
|
},
|
|
510
573
|
});
|
|
511
574
|
return { data: response.roles, pageInfo: response.page_info };
|
|
@@ -514,25 +577,25 @@ export function createZohoProjectsClient(config) {
|
|
|
514
577
|
return collectAll(this.iterate(options));
|
|
515
578
|
},
|
|
516
579
|
iterate(options) {
|
|
517
|
-
return autoPaginate((
|
|
580
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
518
581
|
},
|
|
519
582
|
async get(roleId) {
|
|
520
|
-
const response = await requestWithValidation(`${basePath}/roles/${roleId}
|
|
583
|
+
const response = await requestWithValidation(`${basePath}/roles/${roleId}`, z.object({ roles: z.array(RoleSchema) }));
|
|
521
584
|
if (response.roles.length === 0) {
|
|
522
585
|
throw new ZohoProjectsError(`Role not found: ${roleId}`, 404);
|
|
523
586
|
}
|
|
524
587
|
return response.roles[0];
|
|
525
588
|
},
|
|
526
589
|
async create(data) {
|
|
527
|
-
const response = await requestWithValidation(`${basePath}/roles
|
|
590
|
+
const response = await requestWithValidation(`${basePath}/roles`, z.object({ roles: z.array(RoleSchema) }), { method: "POST", data });
|
|
528
591
|
return response.roles[0];
|
|
529
592
|
},
|
|
530
593
|
async update(roleId, data) {
|
|
531
|
-
const response = await requestWithValidation(`${basePath}/roles/${roleId}
|
|
594
|
+
const response = await requestWithValidation(`${basePath}/roles/${roleId}`, z.object({ roles: z.array(RoleSchema) }), { method: "PUT", data });
|
|
532
595
|
return response.roles[0];
|
|
533
596
|
},
|
|
534
597
|
async delete(roleId) {
|
|
535
|
-
await request(`${basePath}/roles/${roleId}
|
|
598
|
+
await request(`${basePath}/roles/${roleId}`, { method: "DELETE" });
|
|
536
599
|
},
|
|
537
600
|
},
|
|
538
601
|
/**
|
|
@@ -540,10 +603,10 @@ export function createZohoProjectsClient(config) {
|
|
|
540
603
|
*/
|
|
541
604
|
profiles: {
|
|
542
605
|
async list(params) {
|
|
543
|
-
const response = await requestWithValidation(`${basePath}/profiles
|
|
606
|
+
const response = await requestWithValidation(`${basePath}/profiles`, ProfileListResponseSchema, {
|
|
544
607
|
params: {
|
|
545
|
-
|
|
546
|
-
|
|
608
|
+
page: params?.page ?? params?.index ?? 1,
|
|
609
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
547
610
|
},
|
|
548
611
|
});
|
|
549
612
|
return { data: response.profiles, pageInfo: response.page_info };
|
|
@@ -552,25 +615,25 @@ export function createZohoProjectsClient(config) {
|
|
|
552
615
|
return collectAll(this.iterate(options));
|
|
553
616
|
},
|
|
554
617
|
iterate(options) {
|
|
555
|
-
return autoPaginate((
|
|
618
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
556
619
|
},
|
|
557
620
|
async get(profileId) {
|
|
558
|
-
const response = await requestWithValidation(`${basePath}/profiles/${profileId}
|
|
621
|
+
const response = await requestWithValidation(`${basePath}/profiles/${profileId}`, z.object({ profiles: z.array(ProfileSchema) }));
|
|
559
622
|
if (response.profiles.length === 0) {
|
|
560
623
|
throw new ZohoProjectsError(`Profile not found: ${profileId}`, 404);
|
|
561
624
|
}
|
|
562
625
|
return response.profiles[0];
|
|
563
626
|
},
|
|
564
627
|
async create(data) {
|
|
565
|
-
const response = await requestWithValidation(`${basePath}/profiles
|
|
628
|
+
const response = await requestWithValidation(`${basePath}/profiles`, z.object({ profiles: z.array(ProfileSchema) }), { method: "POST", data });
|
|
566
629
|
return response.profiles[0];
|
|
567
630
|
},
|
|
568
631
|
async update(profileId, data) {
|
|
569
|
-
const response = await requestWithValidation(`${basePath}/profiles/${profileId}
|
|
632
|
+
const response = await requestWithValidation(`${basePath}/profiles/${profileId}`, z.object({ profiles: z.array(ProfileSchema) }), { method: "PUT", data });
|
|
570
633
|
return response.profiles[0];
|
|
571
634
|
},
|
|
572
635
|
async delete(profileId) {
|
|
573
|
-
await request(`${basePath}/profiles/${profileId}
|
|
636
|
+
await request(`${basePath}/profiles/${profileId}`, { method: "DELETE" });
|
|
574
637
|
},
|
|
575
638
|
},
|
|
576
639
|
/**
|
|
@@ -578,10 +641,10 @@ export function createZohoProjectsClient(config) {
|
|
|
578
641
|
*/
|
|
579
642
|
clients: {
|
|
580
643
|
async list(params) {
|
|
581
|
-
const response = await requestWithValidation(`${basePath}/clients
|
|
644
|
+
const response = await requestWithValidation(`${basePath}/clients`, ClientListResponseSchema, {
|
|
582
645
|
params: {
|
|
583
|
-
|
|
584
|
-
|
|
646
|
+
page: params?.page ?? params?.index ?? 1,
|
|
647
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
585
648
|
},
|
|
586
649
|
});
|
|
587
650
|
return { data: response.clients, pageInfo: response.page_info };
|
|
@@ -590,25 +653,25 @@ export function createZohoProjectsClient(config) {
|
|
|
590
653
|
return collectAll(this.iterate(options));
|
|
591
654
|
},
|
|
592
655
|
iterate(options) {
|
|
593
|
-
return autoPaginate((
|
|
656
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
594
657
|
},
|
|
595
658
|
async get(clientId) {
|
|
596
|
-
const response = await requestWithValidation(`${basePath}/clients/${clientId}
|
|
659
|
+
const response = await requestWithValidation(`${basePath}/clients/${clientId}`, z.object({ clients: z.array(ClientSchema) }));
|
|
597
660
|
if (response.clients.length === 0) {
|
|
598
661
|
throw new ZohoProjectsError(`Client not found: ${clientId}`, 404);
|
|
599
662
|
}
|
|
600
663
|
return response.clients[0];
|
|
601
664
|
},
|
|
602
665
|
async create(data) {
|
|
603
|
-
const response = await requestWithValidation(`${basePath}/clients
|
|
666
|
+
const response = await requestWithValidation(`${basePath}/clients`, z.object({ clients: z.array(ClientSchema) }), { method: "POST", data });
|
|
604
667
|
return response.clients[0];
|
|
605
668
|
},
|
|
606
669
|
async update(clientId, data) {
|
|
607
|
-
const response = await requestWithValidation(`${basePath}/clients/${clientId}
|
|
670
|
+
const response = await requestWithValidation(`${basePath}/clients/${clientId}`, z.object({ clients: z.array(ClientSchema) }), { method: "PUT", data });
|
|
608
671
|
return response.clients[0];
|
|
609
672
|
},
|
|
610
673
|
async delete(clientId) {
|
|
611
|
-
await request(`${basePath}/clients/${clientId}
|
|
674
|
+
await request(`${basePath}/clients/${clientId}`, { method: "DELETE" });
|
|
612
675
|
},
|
|
613
676
|
},
|
|
614
677
|
/**
|
|
@@ -616,10 +679,10 @@ export function createZohoProjectsClient(config) {
|
|
|
616
679
|
*/
|
|
617
680
|
contacts: {
|
|
618
681
|
async list(params) {
|
|
619
|
-
const response = await requestWithValidation(`${basePath}/contacts
|
|
682
|
+
const response = await requestWithValidation(`${basePath}/contacts`, ContactListResponseSchema, {
|
|
620
683
|
params: {
|
|
621
|
-
|
|
622
|
-
|
|
684
|
+
page: params?.page ?? params?.index ?? 1,
|
|
685
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
623
686
|
},
|
|
624
687
|
});
|
|
625
688
|
return { data: response.contacts, pageInfo: response.page_info };
|
|
@@ -628,25 +691,25 @@ export function createZohoProjectsClient(config) {
|
|
|
628
691
|
return collectAll(this.iterate(options));
|
|
629
692
|
},
|
|
630
693
|
iterate(options) {
|
|
631
|
-
return autoPaginate((
|
|
694
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
632
695
|
},
|
|
633
696
|
async get(contactId) {
|
|
634
|
-
const response = await requestWithValidation(`${basePath}/contacts/${contactId}
|
|
697
|
+
const response = await requestWithValidation(`${basePath}/contacts/${contactId}`, z.object({ contacts: z.array(ContactSchema) }));
|
|
635
698
|
if (response.contacts.length === 0) {
|
|
636
699
|
throw new ZohoProjectsError(`Contact not found: ${contactId}`, 404);
|
|
637
700
|
}
|
|
638
701
|
return response.contacts[0];
|
|
639
702
|
},
|
|
640
703
|
async create(data) {
|
|
641
|
-
const response = await requestWithValidation(`${basePath}/contacts
|
|
704
|
+
const response = await requestWithValidation(`${basePath}/contacts`, z.object({ contacts: z.array(ContactSchema) }), { method: "POST", data });
|
|
642
705
|
return response.contacts[0];
|
|
643
706
|
},
|
|
644
707
|
async update(contactId, data) {
|
|
645
|
-
const response = await requestWithValidation(`${basePath}/contacts/${contactId}
|
|
708
|
+
const response = await requestWithValidation(`${basePath}/contacts/${contactId}`, z.object({ contacts: z.array(ContactSchema) }), { method: "PUT", data });
|
|
646
709
|
return response.contacts[0];
|
|
647
710
|
},
|
|
648
711
|
async delete(contactId) {
|
|
649
|
-
await request(`${basePath}/contacts/${contactId}
|
|
712
|
+
await request(`${basePath}/contacts/${contactId}`, { method: "DELETE" });
|
|
650
713
|
},
|
|
651
714
|
},
|
|
652
715
|
/**
|
|
@@ -654,10 +717,10 @@ export function createZohoProjectsClient(config) {
|
|
|
654
717
|
*/
|
|
655
718
|
groups: {
|
|
656
719
|
async list(params) {
|
|
657
|
-
const response = await requestWithValidation(`${basePath}/groups
|
|
720
|
+
const response = await requestWithValidation(`${basePath}/groups`, ProjectGroupListResponseSchema, {
|
|
658
721
|
params: {
|
|
659
|
-
|
|
660
|
-
|
|
722
|
+
page: params?.page ?? params?.index ?? 1,
|
|
723
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
661
724
|
},
|
|
662
725
|
});
|
|
663
726
|
return { data: response.groups, pageInfo: response.page_info };
|
|
@@ -666,25 +729,25 @@ export function createZohoProjectsClient(config) {
|
|
|
666
729
|
return collectAll(this.iterate(options));
|
|
667
730
|
},
|
|
668
731
|
iterate(options) {
|
|
669
|
-
return autoPaginate((
|
|
732
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
670
733
|
},
|
|
671
734
|
async get(groupId) {
|
|
672
|
-
const response = await requestWithValidation(`${basePath}/groups/${groupId}
|
|
735
|
+
const response = await requestWithValidation(`${basePath}/groups/${groupId}`, z.object({ groups: z.array(ProjectGroupSchema) }));
|
|
673
736
|
if (response.groups.length === 0) {
|
|
674
737
|
throw new ZohoProjectsError(`Project group not found: ${groupId}`, 404);
|
|
675
738
|
}
|
|
676
739
|
return response.groups[0];
|
|
677
740
|
},
|
|
678
741
|
async create(data) {
|
|
679
|
-
const response = await requestWithValidation(`${basePath}/groups
|
|
742
|
+
const response = await requestWithValidation(`${basePath}/groups`, z.object({ groups: z.array(ProjectGroupSchema) }), { method: "POST", data });
|
|
680
743
|
return response.groups[0];
|
|
681
744
|
},
|
|
682
745
|
async update(groupId, data) {
|
|
683
|
-
const response = await requestWithValidation(`${basePath}/groups/${groupId}
|
|
746
|
+
const response = await requestWithValidation(`${basePath}/groups/${groupId}`, z.object({ groups: z.array(ProjectGroupSchema) }), { method: "PUT", data });
|
|
684
747
|
return response.groups[0];
|
|
685
748
|
},
|
|
686
749
|
async delete(groupId) {
|
|
687
|
-
await request(`${basePath}/groups/${groupId}
|
|
750
|
+
await request(`${basePath}/groups/${groupId}`, { method: "DELETE" });
|
|
688
751
|
},
|
|
689
752
|
},
|
|
690
753
|
/**
|
|
@@ -692,10 +755,10 @@ export function createZohoProjectsClient(config) {
|
|
|
692
755
|
*/
|
|
693
756
|
leaves: {
|
|
694
757
|
async list(params) {
|
|
695
|
-
const response = await requestWithValidation(`${basePath}/leaves
|
|
758
|
+
const response = await requestWithValidation(`${basePath}/leaves`, LeaveListResponseSchema, {
|
|
696
759
|
params: {
|
|
697
|
-
|
|
698
|
-
|
|
760
|
+
page: params?.page ?? params?.index ?? 1,
|
|
761
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
699
762
|
},
|
|
700
763
|
});
|
|
701
764
|
return { data: response.leaves, pageInfo: response.page_info };
|
|
@@ -704,25 +767,25 @@ export function createZohoProjectsClient(config) {
|
|
|
704
767
|
return collectAll(this.iterate(options));
|
|
705
768
|
},
|
|
706
769
|
iterate(options) {
|
|
707
|
-
return autoPaginate((
|
|
770
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
708
771
|
},
|
|
709
772
|
async get(leaveId) {
|
|
710
|
-
const response = await requestWithValidation(`${basePath}/leaves/${leaveId}
|
|
773
|
+
const response = await requestWithValidation(`${basePath}/leaves/${leaveId}`, z.object({ leaves: z.array(LeaveSchema) }));
|
|
711
774
|
if (response.leaves.length === 0) {
|
|
712
775
|
throw new ZohoProjectsError(`Leave not found: ${leaveId}`, 404);
|
|
713
776
|
}
|
|
714
777
|
return response.leaves[0];
|
|
715
778
|
},
|
|
716
779
|
async create(data) {
|
|
717
|
-
const response = await requestWithValidation(`${basePath}/leaves
|
|
780
|
+
const response = await requestWithValidation(`${basePath}/leaves`, z.object({ leaves: z.array(LeaveSchema) }), { method: "POST", data });
|
|
718
781
|
return response.leaves[0];
|
|
719
782
|
},
|
|
720
783
|
async update(leaveId, data) {
|
|
721
|
-
const response = await requestWithValidation(`${basePath}/leaves/${leaveId}
|
|
784
|
+
const response = await requestWithValidation(`${basePath}/leaves/${leaveId}`, z.object({ leaves: z.array(LeaveSchema) }), { method: "PUT", data });
|
|
722
785
|
return response.leaves[0];
|
|
723
786
|
},
|
|
724
787
|
async delete(leaveId) {
|
|
725
|
-
await request(`${basePath}/leaves/${leaveId}
|
|
788
|
+
await request(`${basePath}/leaves/${leaveId}`, { method: "DELETE" });
|
|
726
789
|
},
|
|
727
790
|
},
|
|
728
791
|
/**
|
|
@@ -730,10 +793,10 @@ export function createZohoProjectsClient(config) {
|
|
|
730
793
|
*/
|
|
731
794
|
teams: {
|
|
732
795
|
async list(params) {
|
|
733
|
-
const response = await requestWithValidation(`${basePath}/teams
|
|
796
|
+
const response = await requestWithValidation(`${basePath}/teams`, TeamListResponseSchema, {
|
|
734
797
|
params: {
|
|
735
|
-
|
|
736
|
-
|
|
798
|
+
page: params?.page ?? params?.index ?? 1,
|
|
799
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
737
800
|
},
|
|
738
801
|
});
|
|
739
802
|
return { data: response.teams, pageInfo: response.page_info };
|
|
@@ -742,32 +805,32 @@ export function createZohoProjectsClient(config) {
|
|
|
742
805
|
return collectAll(this.iterate(options));
|
|
743
806
|
},
|
|
744
807
|
iterate(options) {
|
|
745
|
-
return autoPaginate((
|
|
808
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
746
809
|
},
|
|
747
810
|
async get(teamId) {
|
|
748
|
-
const response = await requestWithValidation(`${basePath}/teams/${teamId}
|
|
811
|
+
const response = await requestWithValidation(`${basePath}/teams/${teamId}`, z.object({ teams: z.array(TeamSchema) }));
|
|
749
812
|
if (response.teams.length === 0) {
|
|
750
813
|
throw new ZohoProjectsError(`Team not found: ${teamId}`, 404);
|
|
751
814
|
}
|
|
752
815
|
return response.teams[0];
|
|
753
816
|
},
|
|
754
817
|
async create(data) {
|
|
755
|
-
const response = await requestWithValidation(`${basePath}/teams
|
|
818
|
+
const response = await requestWithValidation(`${basePath}/teams`, z.object({ teams: z.array(TeamSchema) }), { method: "POST", data });
|
|
756
819
|
return response.teams[0];
|
|
757
820
|
},
|
|
758
821
|
async update(teamId, data) {
|
|
759
|
-
const response = await requestWithValidation(`${basePath}/teams/${teamId}
|
|
822
|
+
const response = await requestWithValidation(`${basePath}/teams/${teamId}`, z.object({ teams: z.array(TeamSchema) }), { method: "PUT", data });
|
|
760
823
|
return response.teams[0];
|
|
761
824
|
},
|
|
762
825
|
async delete(teamId) {
|
|
763
|
-
await request(`${basePath}/teams/${teamId}
|
|
826
|
+
await request(`${basePath}/teams/${teamId}`, { method: "DELETE" });
|
|
764
827
|
},
|
|
765
828
|
async addMembers(teamId, data) {
|
|
766
829
|
const response = await requestWithValidation(`${basePath}/teams/${teamId}/members/`, z.object({ teams: z.array(TeamSchema) }), { method: "POST", data });
|
|
767
830
|
return response.teams[0];
|
|
768
831
|
},
|
|
769
832
|
async removeMember(teamId, userId) {
|
|
770
|
-
await request(`${basePath}/teams/${teamId}/members/${userId}
|
|
833
|
+
await request(`${basePath}/teams/${teamId}/members/${userId}`, {
|
|
771
834
|
method: "DELETE",
|
|
772
835
|
});
|
|
773
836
|
},
|
|
@@ -777,10 +840,10 @@ export function createZohoProjectsClient(config) {
|
|
|
777
840
|
*/
|
|
778
841
|
tasklists: {
|
|
779
842
|
async list(projectId, params) {
|
|
780
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasklists
|
|
843
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasklists`, TaskListListResponseSchema, {
|
|
781
844
|
params: {
|
|
782
|
-
|
|
783
|
-
|
|
845
|
+
page: params?.page ?? params?.index ?? 1,
|
|
846
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
784
847
|
},
|
|
785
848
|
});
|
|
786
849
|
return { data: response.tasklists, pageInfo: response.page_info };
|
|
@@ -789,25 +852,28 @@ export function createZohoProjectsClient(config) {
|
|
|
789
852
|
return collectAll(this.iterate(projectId, options));
|
|
790
853
|
},
|
|
791
854
|
iterate(projectId, options) {
|
|
792
|
-
return autoPaginate((
|
|
855
|
+
return autoPaginate((page, per_page) => this.list(projectId, { page, per_page }), options);
|
|
793
856
|
},
|
|
794
857
|
async get(projectId, tasklistId) {
|
|
795
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasklists/${tasklistId}
|
|
858
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasklists/${tasklistId}`, z.object({ tasklists: z.array(TaskListSchema) }));
|
|
796
859
|
if (response.tasklists.length === 0) {
|
|
797
860
|
throw new ZohoProjectsError(`Task list not found: ${tasklistId}`, 404);
|
|
798
861
|
}
|
|
799
862
|
return response.tasklists[0];
|
|
800
863
|
},
|
|
801
864
|
async create(projectId, data) {
|
|
802
|
-
|
|
803
|
-
|
|
865
|
+
// V3 API returns the tasklist directly, not wrapped in array
|
|
866
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasklists`, TaskListSchema, { method: "POST", data });
|
|
867
|
+
return response;
|
|
804
868
|
},
|
|
805
869
|
async update(projectId, tasklistId, data) {
|
|
806
|
-
|
|
807
|
-
|
|
870
|
+
// V3 API returns the tasklist directly, not wrapped in array
|
|
871
|
+
// V3 API uses PATCH method for updates
|
|
872
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/tasklists/${tasklistId}`, TaskListSchema, { method: "PATCH", data });
|
|
873
|
+
return response;
|
|
808
874
|
},
|
|
809
875
|
async delete(projectId, tasklistId) {
|
|
810
|
-
await request(`${basePath}/projects/${projectId}/tasklists/${tasklistId}
|
|
876
|
+
await request(`${basePath}/projects/${projectId}/tasklists/${tasklistId}`, { method: "DELETE" });
|
|
811
877
|
},
|
|
812
878
|
},
|
|
813
879
|
/**
|
|
@@ -816,37 +882,73 @@ export function createZohoProjectsClient(config) {
|
|
|
816
882
|
*/
|
|
817
883
|
phases: {
|
|
818
884
|
async list(projectId, params) {
|
|
819
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/milestones
|
|
885
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/milestones`, PhaseListResponseSchema, {
|
|
820
886
|
params: {
|
|
821
|
-
|
|
822
|
-
|
|
887
|
+
page: params?.page ?? params?.index ?? 1,
|
|
888
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
823
889
|
},
|
|
824
890
|
});
|
|
825
|
-
|
|
891
|
+
// V3 API returns page_info as array, normalize to object
|
|
892
|
+
let pageInfo;
|
|
893
|
+
if (response.page_info) {
|
|
894
|
+
if (Array.isArray(response.page_info)) {
|
|
895
|
+
const info = response.page_info[0];
|
|
896
|
+
if (info) {
|
|
897
|
+
pageInfo = {
|
|
898
|
+
page: info.page,
|
|
899
|
+
per_page: info.per_page,
|
|
900
|
+
has_more_page: info.has_next_page,
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
else {
|
|
905
|
+
pageInfo = response.page_info;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
return { data: response.milestones, pageInfo };
|
|
826
909
|
},
|
|
827
910
|
async listAll(projectId, options) {
|
|
828
911
|
return collectAll(this.iterate(projectId, options));
|
|
829
912
|
},
|
|
830
913
|
iterate(projectId, options) {
|
|
831
|
-
return autoPaginate((
|
|
914
|
+
return autoPaginate((page, per_page) => this.list(projectId, { page, per_page }), options);
|
|
832
915
|
},
|
|
833
916
|
async get(projectId, phaseId) {
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
917
|
+
// V3 API returns milestone directly, legacy wraps in {milestones: [...]}
|
|
918
|
+
const schema = z.union([
|
|
919
|
+
PhaseSchema, // V3: returns milestone directly
|
|
920
|
+
z.object({ milestones: z.array(PhaseSchema) }), // Legacy
|
|
921
|
+
]);
|
|
922
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/milestones/${phaseId}`, schema);
|
|
923
|
+
// Handle both formats
|
|
924
|
+
if (response && typeof response === "object" && "milestones" in response) {
|
|
925
|
+
const legacyResponse = response;
|
|
926
|
+
if (legacyResponse.milestones.length === 0) {
|
|
927
|
+
throw new ZohoProjectsError(`Phase not found: ${phaseId}`, 404);
|
|
928
|
+
}
|
|
929
|
+
return legacyResponse.milestones[0];
|
|
837
930
|
}
|
|
838
|
-
return response
|
|
931
|
+
return response;
|
|
839
932
|
},
|
|
840
933
|
async create(projectId, data) {
|
|
841
|
-
|
|
842
|
-
|
|
934
|
+
// V3 API returns milestone directly, legacy wraps in {milestones: [...]}
|
|
935
|
+
const schema = z.union([
|
|
936
|
+
PhaseSchema, // V3: returns milestone directly
|
|
937
|
+
z.object({ milestones: z.array(PhaseSchema) }), // Legacy
|
|
938
|
+
]);
|
|
939
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/milestones`, schema, { method: "POST", data });
|
|
940
|
+
// Handle both formats
|
|
941
|
+
if (response && typeof response === "object" && "milestones" in response) {
|
|
942
|
+
return response.milestones[0];
|
|
943
|
+
}
|
|
944
|
+
return response;
|
|
843
945
|
},
|
|
844
946
|
async update(projectId, phaseId, data) {
|
|
845
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/milestones/${phaseId}
|
|
947
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/milestones/${phaseId}`, z.object({ milestones: z.array(PhaseSchema) }), { method: "PUT", data });
|
|
846
948
|
return response.milestones[0];
|
|
847
949
|
},
|
|
848
950
|
async delete(projectId, phaseId) {
|
|
849
|
-
await request(`${basePath}/projects/${projectId}/milestones/${phaseId}
|
|
951
|
+
await request(`${basePath}/projects/${projectId}/milestones/${phaseId}`, { method: "DELETE" });
|
|
850
952
|
},
|
|
851
953
|
},
|
|
852
954
|
/**
|
|
@@ -855,10 +957,10 @@ export function createZohoProjectsClient(config) {
|
|
|
855
957
|
*/
|
|
856
958
|
issues: {
|
|
857
959
|
async list(projectId, params) {
|
|
858
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs
|
|
960
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs`, IssueListResponseSchema, {
|
|
859
961
|
params: {
|
|
860
|
-
|
|
861
|
-
|
|
962
|
+
page: params?.page ?? params?.index ?? 1,
|
|
963
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
862
964
|
},
|
|
863
965
|
});
|
|
864
966
|
return { data: response.bugs, pageInfo: response.page_info };
|
|
@@ -867,25 +969,25 @@ export function createZohoProjectsClient(config) {
|
|
|
867
969
|
return collectAll(this.iterate(projectId, options));
|
|
868
970
|
},
|
|
869
971
|
iterate(projectId, options) {
|
|
870
|
-
return autoPaginate((
|
|
972
|
+
return autoPaginate((page, per_page) => this.list(projectId, { page, per_page }), options);
|
|
871
973
|
},
|
|
872
974
|
async get(projectId, issueId) {
|
|
873
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs/${issueId}
|
|
975
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs/${issueId}`, z.object({ bugs: z.array(IssueSchema) }));
|
|
874
976
|
if (response.bugs.length === 0) {
|
|
875
977
|
throw new ZohoProjectsError(`Issue not found: ${issueId}`, 404);
|
|
876
978
|
}
|
|
877
979
|
return response.bugs[0];
|
|
878
980
|
},
|
|
879
981
|
async create(projectId, data) {
|
|
880
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs
|
|
982
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs`, z.object({ bugs: z.array(IssueSchema) }), { method: "POST", data });
|
|
881
983
|
return response.bugs[0];
|
|
882
984
|
},
|
|
883
985
|
async update(projectId, issueId, data) {
|
|
884
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs/${issueId}
|
|
986
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/bugs/${issueId}`, z.object({ bugs: z.array(IssueSchema) }), { method: "PUT", data });
|
|
885
987
|
return response.bugs[0];
|
|
886
988
|
},
|
|
887
989
|
async delete(projectId, issueId) {
|
|
888
|
-
await request(`${basePath}/projects/${projectId}/bugs/${issueId}
|
|
990
|
+
await request(`${basePath}/projects/${projectId}/bugs/${issueId}`, {
|
|
889
991
|
method: "DELETE",
|
|
890
992
|
});
|
|
891
993
|
},
|
|
@@ -895,10 +997,10 @@ export function createZohoProjectsClient(config) {
|
|
|
895
997
|
*/
|
|
896
998
|
forums: {
|
|
897
999
|
async list(projectId, params) {
|
|
898
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums
|
|
1000
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums`, ForumListResponseSchema, {
|
|
899
1001
|
params: {
|
|
900
|
-
|
|
901
|
-
|
|
1002
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1003
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
902
1004
|
},
|
|
903
1005
|
});
|
|
904
1006
|
return { data: response.forums, pageInfo: response.page_info };
|
|
@@ -907,25 +1009,25 @@ export function createZohoProjectsClient(config) {
|
|
|
907
1009
|
return collectAll(this.iterate(projectId, options));
|
|
908
1010
|
},
|
|
909
1011
|
iterate(projectId, options) {
|
|
910
|
-
return autoPaginate((
|
|
1012
|
+
return autoPaginate((page, per_page) => this.list(projectId, { page, per_page }), options);
|
|
911
1013
|
},
|
|
912
1014
|
async get(projectId, forumId) {
|
|
913
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums/${forumId}
|
|
1015
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums/${forumId}`, z.object({ forums: z.array(ForumSchema) }));
|
|
914
1016
|
if (response.forums.length === 0) {
|
|
915
1017
|
throw new ZohoProjectsError(`Forum not found: ${forumId}`, 404);
|
|
916
1018
|
}
|
|
917
1019
|
return response.forums[0];
|
|
918
1020
|
},
|
|
919
1021
|
async create(projectId, data) {
|
|
920
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums
|
|
1022
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums`, z.object({ forums: z.array(ForumSchema) }), { method: "POST", data });
|
|
921
1023
|
return response.forums[0];
|
|
922
1024
|
},
|
|
923
1025
|
async update(projectId, forumId, data) {
|
|
924
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums/${forumId}
|
|
1026
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/forums/${forumId}`, z.object({ forums: z.array(ForumSchema) }), { method: "PUT", data });
|
|
925
1027
|
return response.forums[0];
|
|
926
1028
|
},
|
|
927
1029
|
async delete(projectId, forumId) {
|
|
928
|
-
await request(`${basePath}/projects/${projectId}/forums/${forumId}
|
|
1030
|
+
await request(`${basePath}/projects/${projectId}/forums/${forumId}`, {
|
|
929
1031
|
method: "DELETE",
|
|
930
1032
|
});
|
|
931
1033
|
},
|
|
@@ -935,10 +1037,10 @@ export function createZohoProjectsClient(config) {
|
|
|
935
1037
|
*/
|
|
936
1038
|
events: {
|
|
937
1039
|
async list(projectId, params) {
|
|
938
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events
|
|
1040
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events`, EventListResponseSchema, {
|
|
939
1041
|
params: {
|
|
940
|
-
|
|
941
|
-
|
|
1042
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1043
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
942
1044
|
},
|
|
943
1045
|
});
|
|
944
1046
|
return { data: response.events, pageInfo: response.page_info };
|
|
@@ -947,84 +1049,178 @@ export function createZohoProjectsClient(config) {
|
|
|
947
1049
|
return collectAll(this.iterate(projectId, options));
|
|
948
1050
|
},
|
|
949
1051
|
iterate(projectId, options) {
|
|
950
|
-
return autoPaginate((
|
|
1052
|
+
return autoPaginate((page, per_page) => this.list(projectId, { page, per_page }), options);
|
|
951
1053
|
},
|
|
952
1054
|
async get(projectId, eventId) {
|
|
953
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events/${eventId}
|
|
1055
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events/${eventId}`, z.object({ events: z.array(EventSchema) }));
|
|
954
1056
|
if (response.events.length === 0) {
|
|
955
1057
|
throw new ZohoProjectsError(`Event not found: ${eventId}`, 404);
|
|
956
1058
|
}
|
|
957
1059
|
return response.events[0];
|
|
958
1060
|
},
|
|
959
1061
|
async create(projectId, data) {
|
|
960
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events
|
|
1062
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events`, z.object({ events: z.array(EventSchema) }), { method: "POST", data });
|
|
961
1063
|
return response.events[0];
|
|
962
1064
|
},
|
|
963
1065
|
async update(projectId, eventId, data) {
|
|
964
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events/${eventId}
|
|
1066
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/events/${eventId}`, z.object({ events: z.array(EventSchema) }), { method: "PUT", data });
|
|
965
1067
|
return response.events[0];
|
|
966
1068
|
},
|
|
967
1069
|
async delete(projectId, eventId) {
|
|
968
|
-
await request(`${basePath}/projects/${projectId}/events/${eventId}
|
|
1070
|
+
await request(`${basePath}/projects/${projectId}/events/${eventId}`, {
|
|
969
1071
|
method: "DELETE",
|
|
970
1072
|
});
|
|
971
1073
|
},
|
|
972
1074
|
},
|
|
973
1075
|
/**
|
|
974
1076
|
* Attachments API (project-scoped)
|
|
975
|
-
* Note:
|
|
1077
|
+
* Note: V3 API requires entity_type and entity_id for listing
|
|
1078
|
+
* Note: V3 Upload requires WorkDrive integration - use workdrive.upload() then associate()
|
|
976
1079
|
*/
|
|
977
1080
|
attachments: {
|
|
978
|
-
|
|
979
|
-
|
|
1081
|
+
/**
|
|
1082
|
+
* List attachments for an entity (V3 API)
|
|
1083
|
+
* Note: V3 requires entity_type and entity_id parameters
|
|
1084
|
+
* @param projectId - Project ID
|
|
1085
|
+
* @param params - List parameters including required entity_type and entity_id
|
|
1086
|
+
*/
|
|
1087
|
+
async listForEntity(projectId, params) {
|
|
1088
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/attachments`, AttachmentListResponseSchema, {
|
|
980
1089
|
params: {
|
|
981
|
-
|
|
982
|
-
|
|
1090
|
+
entity_type: params.entity_type,
|
|
1091
|
+
entity_id: params.entity_id,
|
|
1092
|
+
page: params.page ?? 1,
|
|
1093
|
+
per_page: params.per_page ?? DEFAULT_PAGE_SIZE,
|
|
983
1094
|
},
|
|
984
1095
|
});
|
|
985
|
-
|
|
1096
|
+
// Handle both V3 (attachment) and legacy (attachments) response formats
|
|
1097
|
+
const attachments = "attachment" in response ? response.attachment : response.attachments;
|
|
1098
|
+
return { data: attachments, pageInfo: response.page_info };
|
|
986
1099
|
},
|
|
987
|
-
|
|
988
|
-
|
|
1100
|
+
/**
|
|
1101
|
+
* List all attachments for an entity with auto-pagination
|
|
1102
|
+
*/
|
|
1103
|
+
async listAllForEntity(projectId, params, options) {
|
|
1104
|
+
return collectAll(this.iterateForEntity(projectId, params, options));
|
|
989
1105
|
},
|
|
990
|
-
|
|
991
|
-
|
|
1106
|
+
/**
|
|
1107
|
+
* Iterate over all attachments for an entity with auto-pagination
|
|
1108
|
+
*/
|
|
1109
|
+
iterateForEntity(projectId, params, options) {
|
|
1110
|
+
return autoPaginate((page, per_page) => this.listForEntity(projectId, { ...params, page, per_page }), options);
|
|
1111
|
+
},
|
|
1112
|
+
/**
|
|
1113
|
+
* Convenience method: List attachments for a task
|
|
1114
|
+
*/
|
|
1115
|
+
async listForTask(projectId, taskId, params) {
|
|
1116
|
+
return this.listForEntity(projectId, {
|
|
1117
|
+
entity_type: "task",
|
|
1118
|
+
entity_id: taskId,
|
|
1119
|
+
...params,
|
|
1120
|
+
});
|
|
1121
|
+
},
|
|
1122
|
+
/**
|
|
1123
|
+
* Convenience method: List attachments for a bug/issue
|
|
1124
|
+
*/
|
|
1125
|
+
async listForIssue(projectId, issueId, params) {
|
|
1126
|
+
return this.listForEntity(projectId, {
|
|
1127
|
+
entity_type: "bug",
|
|
1128
|
+
entity_id: issueId,
|
|
1129
|
+
...params,
|
|
1130
|
+
});
|
|
992
1131
|
},
|
|
993
1132
|
async get(projectId, attachmentId) {
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1133
|
+
// V3 API may return attachment directly or wrapped
|
|
1134
|
+
const schema = z.union([
|
|
1135
|
+
AttachmentSchema,
|
|
1136
|
+
z.object({ attachments: z.array(AttachmentSchema) }),
|
|
1137
|
+
]);
|
|
1138
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/attachments/${attachmentId}`, schema);
|
|
1139
|
+
if (response && typeof response === "object" && "attachments" in response) {
|
|
1140
|
+
const wrapped = response;
|
|
1141
|
+
if (wrapped.attachments.length === 0) {
|
|
1142
|
+
throw new ZohoProjectsError(`Attachment not found: ${attachmentId}`, 404);
|
|
1143
|
+
}
|
|
1144
|
+
return wrapped.attachments[0];
|
|
997
1145
|
}
|
|
998
|
-
return response
|
|
1146
|
+
return response;
|
|
999
1147
|
},
|
|
1000
1148
|
/**
|
|
1001
|
-
*
|
|
1149
|
+
* Associate an existing attachment with an entity (V3 API)
|
|
1150
|
+
* Use this after uploading a file to WorkDrive
|
|
1002
1151
|
* @param projectId - Project ID
|
|
1003
|
-
* @param
|
|
1004
|
-
* @param
|
|
1005
|
-
* @param options - Additional options
|
|
1152
|
+
* @param attachmentId - Attachment ID (from WorkDrive upload)
|
|
1153
|
+
* @param data - Entity association details
|
|
1006
1154
|
*/
|
|
1007
|
-
async
|
|
1155
|
+
async associate(projectId, attachmentId, data) {
|
|
1008
1156
|
const FormData = (await import("form-data")).default;
|
|
1009
1157
|
const formData = new FormData();
|
|
1010
|
-
formData.append("
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
formData
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1158
|
+
formData.append("entity_type", data.entity_type);
|
|
1159
|
+
formData.append("entity_id", data.entity_id);
|
|
1160
|
+
await request(`${basePath}/projects/${projectId}/attachments/${attachmentId}`, {
|
|
1161
|
+
method: "POST",
|
|
1162
|
+
data: formData,
|
|
1163
|
+
headers: formData.getHeaders(),
|
|
1164
|
+
});
|
|
1165
|
+
},
|
|
1166
|
+
/**
|
|
1167
|
+
* Add attachments to an entity using attachment IDs (V3 API)
|
|
1168
|
+
* @param projectId - Project ID
|
|
1169
|
+
* @param entityType - Entity type (task, bug, forum)
|
|
1170
|
+
* @param entityId - Entity ID
|
|
1171
|
+
* @param data - Attachment IDs to add
|
|
1172
|
+
*/
|
|
1173
|
+
async addToEntity(projectId, entityType, entityId, data) {
|
|
1174
|
+
const FormData = (await import("form-data")).default;
|
|
1175
|
+
const formData = new FormData();
|
|
1176
|
+
formData.append("attachment_ids", JSON.stringify(data.attachment_ids));
|
|
1177
|
+
await request(`${basePath}/module/${entityType}/entity/${entityId}/attachments`, {
|
|
1020
1178
|
method: "POST",
|
|
1021
1179
|
data: formData,
|
|
1022
1180
|
headers: formData.getHeaders(),
|
|
1023
1181
|
});
|
|
1024
|
-
return response.attachments[0];
|
|
1025
1182
|
},
|
|
1026
1183
|
async delete(projectId, attachmentId) {
|
|
1027
|
-
await request(`${basePath}/projects/${projectId}/attachments/${attachmentId}
|
|
1184
|
+
await request(`${basePath}/projects/${projectId}/attachments/${attachmentId}`, { method: "DELETE" });
|
|
1185
|
+
},
|
|
1186
|
+
},
|
|
1187
|
+
/**
|
|
1188
|
+
* WorkDrive API for file uploads
|
|
1189
|
+
* V3 attachments require uploading to WorkDrive first, then associating with entities
|
|
1190
|
+
*/
|
|
1191
|
+
workdrive: {
|
|
1192
|
+
/**
|
|
1193
|
+
* Upload a file to WorkDrive
|
|
1194
|
+
* After uploading, use attachments.associate() to link to a task/issue
|
|
1195
|
+
* @param file - File buffer or stream
|
|
1196
|
+
* @param filename - Original filename
|
|
1197
|
+
* @param options - Upload options including parent_id (folder ID)
|
|
1198
|
+
* @returns WorkDrive file object with ID to use for association
|
|
1199
|
+
*/
|
|
1200
|
+
async upload(file, filename, options) {
|
|
1201
|
+
const FormData = (await import("form-data")).default;
|
|
1202
|
+
const formData = new FormData();
|
|
1203
|
+
formData.append("content", file, {
|
|
1204
|
+
filename: options.filename ?? filename,
|
|
1205
|
+
contentType: "application/octet-stream",
|
|
1206
|
+
});
|
|
1207
|
+
formData.append("parent_id", options.parent_id);
|
|
1208
|
+
if (options.override_name_exist !== undefined) {
|
|
1209
|
+
formData.append("override-name-exist", options.override_name_exist.toString());
|
|
1210
|
+
}
|
|
1211
|
+
// WorkDrive has its own API base URL
|
|
1212
|
+
const workdriveUrl = apiUrl.replace("projectsapi", "workdrive");
|
|
1213
|
+
const token = await tokenManager.getValidToken();
|
|
1214
|
+
const response = await httpClient.post(`${workdriveUrl}/api/v1/upload`, formData, {
|
|
1215
|
+
headers: {
|
|
1216
|
+
...formData.getHeaders(),
|
|
1217
|
+
Authorization: `Zoho-oauthtoken ${token}`,
|
|
1218
|
+
},
|
|
1219
|
+
});
|
|
1220
|
+
if (!response.data.data || response.data.data.length === 0) {
|
|
1221
|
+
throw new ZohoProjectsError("WorkDrive upload returned no data");
|
|
1222
|
+
}
|
|
1223
|
+
return response.data.data[0];
|
|
1028
1224
|
},
|
|
1029
1225
|
},
|
|
1030
1226
|
/**
|
|
@@ -1032,10 +1228,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1032
1228
|
*/
|
|
1033
1229
|
documents: {
|
|
1034
1230
|
async list(projectId, params) {
|
|
1035
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents
|
|
1231
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents`, DocumentListResponseSchema, {
|
|
1036
1232
|
params: {
|
|
1037
|
-
|
|
1038
|
-
|
|
1233
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1234
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1039
1235
|
folder_id: params?.folder_id,
|
|
1040
1236
|
},
|
|
1041
1237
|
});
|
|
@@ -1045,10 +1241,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1045
1241
|
return collectAll(this.iterate(projectId, options));
|
|
1046
1242
|
},
|
|
1047
1243
|
iterate(projectId, options) {
|
|
1048
|
-
return autoPaginate((
|
|
1244
|
+
return autoPaginate((page, per_page) => this.list(projectId, { page, per_page }), options);
|
|
1049
1245
|
},
|
|
1050
1246
|
async get(projectId, documentId) {
|
|
1051
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents/${documentId}
|
|
1247
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents/${documentId}`, z.object({ documents: z.array(DocumentSchema) }));
|
|
1052
1248
|
if (response.documents.length === 0) {
|
|
1053
1249
|
throw new ZohoProjectsError(`Document not found: ${documentId}`, 404);
|
|
1054
1250
|
}
|
|
@@ -1067,7 +1263,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1067
1263
|
formData.append("description", options.description);
|
|
1068
1264
|
if (options?.folder_id)
|
|
1069
1265
|
formData.append("folder_id", options.folder_id);
|
|
1070
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents
|
|
1266
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents`, z.object({ documents: z.array(DocumentSchema) }), {
|
|
1071
1267
|
method: "POST",
|
|
1072
1268
|
data: formData,
|
|
1073
1269
|
headers: formData.getHeaders(),
|
|
@@ -1075,25 +1271,25 @@ export function createZohoProjectsClient(config) {
|
|
|
1075
1271
|
return response.documents[0];
|
|
1076
1272
|
},
|
|
1077
1273
|
async update(projectId, documentId, data) {
|
|
1078
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents/${documentId}
|
|
1274
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/documents/${documentId}`, z.object({ documents: z.array(DocumentSchema) }), { method: "PUT", data });
|
|
1079
1275
|
return response.documents[0];
|
|
1080
1276
|
},
|
|
1081
1277
|
async delete(projectId, documentId) {
|
|
1082
|
-
await request(`${basePath}/projects/${projectId}/documents/${documentId}
|
|
1278
|
+
await request(`${basePath}/projects/${projectId}/documents/${documentId}`, { method: "DELETE" });
|
|
1083
1279
|
},
|
|
1084
1280
|
// Folder operations
|
|
1085
1281
|
folders: {
|
|
1086
1282
|
async list(projectId, params) {
|
|
1087
1283
|
const response = await requestWithValidation(`${basePath}/projects/${projectId}/folders/`, DocumentFolderListResponseSchema, {
|
|
1088
1284
|
params: {
|
|
1089
|
-
|
|
1090
|
-
|
|
1285
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1286
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1091
1287
|
},
|
|
1092
1288
|
});
|
|
1093
1289
|
return { data: response.folders, pageInfo: response.page_info };
|
|
1094
1290
|
},
|
|
1095
1291
|
async get(projectId, folderId) {
|
|
1096
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/folders/${folderId}
|
|
1292
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/folders/${folderId}`, z.object({ folders: z.array(DocumentFolderSchema) }));
|
|
1097
1293
|
if (response.folders.length === 0) {
|
|
1098
1294
|
throw new ZohoProjectsError(`Folder not found: ${folderId}`, 404);
|
|
1099
1295
|
}
|
|
@@ -1104,11 +1300,11 @@ export function createZohoProjectsClient(config) {
|
|
|
1104
1300
|
return response.folders[0];
|
|
1105
1301
|
},
|
|
1106
1302
|
async update(projectId, folderId, data) {
|
|
1107
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/folders/${folderId}
|
|
1303
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/folders/${folderId}`, z.object({ folders: z.array(DocumentFolderSchema) }), { method: "PUT", data });
|
|
1108
1304
|
return response.folders[0];
|
|
1109
1305
|
},
|
|
1110
1306
|
async delete(projectId, folderId) {
|
|
1111
|
-
await request(`${basePath}/projects/${projectId}/folders/${folderId}
|
|
1307
|
+
await request(`${basePath}/projects/${projectId}/folders/${folderId}`, { method: "DELETE" });
|
|
1112
1308
|
},
|
|
1113
1309
|
},
|
|
1114
1310
|
},
|
|
@@ -1154,10 +1350,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1154
1350
|
const commentsPath = `${basePath}/projects/${projectId}/${entityType}/${entityId}/comments`;
|
|
1155
1351
|
return {
|
|
1156
1352
|
async list(params) {
|
|
1157
|
-
const response = await requestWithValidation(`${commentsPath}
|
|
1353
|
+
const response = await requestWithValidation(`${commentsPath}`, CommentListResponseSchema, {
|
|
1158
1354
|
params: {
|
|
1159
|
-
|
|
1160
|
-
|
|
1355
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1356
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1161
1357
|
},
|
|
1162
1358
|
});
|
|
1163
1359
|
return { data: response.comments, pageInfo: response.page_info };
|
|
@@ -1166,25 +1362,25 @@ export function createZohoProjectsClient(config) {
|
|
|
1166
1362
|
return collectAll(this.iterate(options));
|
|
1167
1363
|
},
|
|
1168
1364
|
iterate(options) {
|
|
1169
|
-
return autoPaginate((
|
|
1365
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
1170
1366
|
},
|
|
1171
1367
|
async get(commentId) {
|
|
1172
|
-
const response = await requestWithValidation(`${commentsPath}/${commentId}
|
|
1368
|
+
const response = await requestWithValidation(`${commentsPath}/${commentId}`, z.object({ comments: z.array(CommentSchema) }));
|
|
1173
1369
|
if (response.comments.length === 0) {
|
|
1174
1370
|
throw new ZohoProjectsError(`Comment not found: ${commentId}`, 404);
|
|
1175
1371
|
}
|
|
1176
1372
|
return response.comments[0];
|
|
1177
1373
|
},
|
|
1178
1374
|
async create(data) {
|
|
1179
|
-
const response = await requestWithValidation(`${commentsPath}
|
|
1375
|
+
const response = await requestWithValidation(`${commentsPath}`, z.object({ comments: z.array(CommentSchema) }), { method: "POST", data });
|
|
1180
1376
|
return response.comments[0];
|
|
1181
1377
|
},
|
|
1182
1378
|
async update(commentId, data) {
|
|
1183
|
-
const response = await requestWithValidation(`${commentsPath}/${commentId}
|
|
1379
|
+
const response = await requestWithValidation(`${commentsPath}/${commentId}`, z.object({ comments: z.array(CommentSchema) }), { method: "PUT", data });
|
|
1184
1380
|
return response.comments[0];
|
|
1185
1381
|
},
|
|
1186
1382
|
async delete(commentId) {
|
|
1187
|
-
await request(`${commentsPath}/${commentId}
|
|
1383
|
+
await request(`${commentsPath}/${commentId}`, {
|
|
1188
1384
|
method: "DELETE",
|
|
1189
1385
|
});
|
|
1190
1386
|
},
|
|
@@ -1233,10 +1429,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1233
1429
|
const followersPath = `${basePath}/projects/${projectId}/${entityType}/${entityId}/followers`;
|
|
1234
1430
|
return {
|
|
1235
1431
|
async list(params) {
|
|
1236
|
-
const response = await requestWithValidation(`${followersPath}
|
|
1432
|
+
const response = await requestWithValidation(`${followersPath}`, FollowerListResponseSchema, {
|
|
1237
1433
|
params: {
|
|
1238
|
-
|
|
1239
|
-
|
|
1434
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1435
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1240
1436
|
},
|
|
1241
1437
|
});
|
|
1242
1438
|
return { data: response.followers, pageInfo: response.page_info };
|
|
@@ -1245,14 +1441,14 @@ export function createZohoProjectsClient(config) {
|
|
|
1245
1441
|
return collectAll(this.iterate(options));
|
|
1246
1442
|
},
|
|
1247
1443
|
iterate(options) {
|
|
1248
|
-
return autoPaginate((
|
|
1444
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
1249
1445
|
},
|
|
1250
1446
|
async add(data) {
|
|
1251
|
-
const response = await requestWithValidation(`${followersPath}
|
|
1447
|
+
const response = await requestWithValidation(`${followersPath}`, z.object({ followers: z.array(FollowerSchema) }), { method: "POST", data });
|
|
1252
1448
|
return response.followers;
|
|
1253
1449
|
},
|
|
1254
1450
|
async remove(userId) {
|
|
1255
|
-
await request(`${followersPath}/${userId}
|
|
1451
|
+
await request(`${followersPath}/${userId}`, {
|
|
1256
1452
|
method: "DELETE",
|
|
1257
1453
|
});
|
|
1258
1454
|
},
|
|
@@ -1280,10 +1476,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1280
1476
|
*/
|
|
1281
1477
|
dashboards: {
|
|
1282
1478
|
async list(params) {
|
|
1283
|
-
const response = await requestWithValidation(`${basePath}/dashboards
|
|
1479
|
+
const response = await requestWithValidation(`${basePath}/dashboards`, DashboardListResponseSchema, {
|
|
1284
1480
|
params: {
|
|
1285
|
-
|
|
1286
|
-
|
|
1481
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1482
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1287
1483
|
},
|
|
1288
1484
|
});
|
|
1289
1485
|
return { data: response.dashboards, pageInfo: response.page_info };
|
|
@@ -1292,25 +1488,25 @@ export function createZohoProjectsClient(config) {
|
|
|
1292
1488
|
return collectAll(this.iterate(options));
|
|
1293
1489
|
},
|
|
1294
1490
|
iterate(options) {
|
|
1295
|
-
return autoPaginate((
|
|
1491
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
1296
1492
|
},
|
|
1297
1493
|
async get(dashboardId) {
|
|
1298
|
-
const response = await requestWithValidation(`${basePath}/dashboards/${dashboardId}
|
|
1494
|
+
const response = await requestWithValidation(`${basePath}/dashboards/${dashboardId}`, z.object({ dashboards: z.array(DashboardSchema) }));
|
|
1299
1495
|
if (response.dashboards.length === 0) {
|
|
1300
1496
|
throw new ZohoProjectsError(`Dashboard not found: ${dashboardId}`, 404);
|
|
1301
1497
|
}
|
|
1302
1498
|
return response.dashboards[0];
|
|
1303
1499
|
},
|
|
1304
1500
|
async create(data) {
|
|
1305
|
-
const response = await requestWithValidation(`${basePath}/dashboards
|
|
1501
|
+
const response = await requestWithValidation(`${basePath}/dashboards`, z.object({ dashboards: z.array(DashboardSchema) }), { method: "POST", data });
|
|
1306
1502
|
return response.dashboards[0];
|
|
1307
1503
|
},
|
|
1308
1504
|
async update(dashboardId, data) {
|
|
1309
|
-
const response = await requestWithValidation(`${basePath}/dashboards/${dashboardId}
|
|
1505
|
+
const response = await requestWithValidation(`${basePath}/dashboards/${dashboardId}`, z.object({ dashboards: z.array(DashboardSchema) }), { method: "PUT", data });
|
|
1310
1506
|
return response.dashboards[0];
|
|
1311
1507
|
},
|
|
1312
1508
|
async delete(dashboardId) {
|
|
1313
|
-
await request(`${basePath}/dashboards/${dashboardId}
|
|
1509
|
+
await request(`${basePath}/dashboards/${dashboardId}`, {
|
|
1314
1510
|
method: "DELETE",
|
|
1315
1511
|
});
|
|
1316
1512
|
},
|
|
@@ -1321,10 +1517,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1321
1517
|
const widgetsPath = `${basePath}/dashboards/${dashboardId}/widgets`;
|
|
1322
1518
|
return {
|
|
1323
1519
|
async list(params) {
|
|
1324
|
-
const response = await requestWithValidation(`${widgetsPath}
|
|
1520
|
+
const response = await requestWithValidation(`${widgetsPath}`, WidgetListResponseSchema, {
|
|
1325
1521
|
params: {
|
|
1326
|
-
|
|
1327
|
-
|
|
1522
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1523
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1328
1524
|
},
|
|
1329
1525
|
});
|
|
1330
1526
|
return { data: response.widgets, pageInfo: response.page_info };
|
|
@@ -1333,25 +1529,25 @@ export function createZohoProjectsClient(config) {
|
|
|
1333
1529
|
return collectAll(this.iterate(options));
|
|
1334
1530
|
},
|
|
1335
1531
|
iterate(options) {
|
|
1336
|
-
return autoPaginate((
|
|
1532
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
1337
1533
|
},
|
|
1338
1534
|
async get(widgetId) {
|
|
1339
|
-
const response = await requestWithValidation(`${widgetsPath}/${widgetId}
|
|
1535
|
+
const response = await requestWithValidation(`${widgetsPath}/${widgetId}`, z.object({ widgets: z.array(WidgetSchema) }));
|
|
1340
1536
|
if (response.widgets.length === 0) {
|
|
1341
1537
|
throw new ZohoProjectsError(`Widget not found: ${widgetId}`, 404);
|
|
1342
1538
|
}
|
|
1343
1539
|
return response.widgets[0];
|
|
1344
1540
|
},
|
|
1345
1541
|
async create(data) {
|
|
1346
|
-
const response = await requestWithValidation(`${widgetsPath}
|
|
1542
|
+
const response = await requestWithValidation(`${widgetsPath}`, z.object({ widgets: z.array(WidgetSchema) }), { method: "POST", data });
|
|
1347
1543
|
return response.widgets[0];
|
|
1348
1544
|
},
|
|
1349
1545
|
async update(widgetId, data) {
|
|
1350
|
-
const response = await requestWithValidation(`${widgetsPath}/${widgetId}
|
|
1546
|
+
const response = await requestWithValidation(`${widgetsPath}/${widgetId}`, z.object({ widgets: z.array(WidgetSchema) }), { method: "PUT", data });
|
|
1351
1547
|
return response.widgets[0];
|
|
1352
1548
|
},
|
|
1353
1549
|
async delete(widgetId) {
|
|
1354
|
-
await request(`${widgetsPath}/${widgetId}
|
|
1550
|
+
await request(`${widgetsPath}/${widgetId}`, {
|
|
1355
1551
|
method: "DELETE",
|
|
1356
1552
|
});
|
|
1357
1553
|
},
|
|
@@ -1364,10 +1560,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1364
1560
|
*/
|
|
1365
1561
|
reports: {
|
|
1366
1562
|
async list(params) {
|
|
1367
|
-
const response = await requestWithValidation(`${basePath}/reports
|
|
1563
|
+
const response = await requestWithValidation(`${basePath}/reports`, ReportListResponseSchema, {
|
|
1368
1564
|
params: {
|
|
1369
|
-
|
|
1370
|
-
|
|
1565
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1566
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1371
1567
|
},
|
|
1372
1568
|
});
|
|
1373
1569
|
return { data: response.reports, pageInfo: response.page_info };
|
|
@@ -1376,10 +1572,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1376
1572
|
return collectAll(this.iterate(options));
|
|
1377
1573
|
},
|
|
1378
1574
|
iterate(options) {
|
|
1379
|
-
return autoPaginate((
|
|
1575
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
1380
1576
|
},
|
|
1381
1577
|
async get(reportId) {
|
|
1382
|
-
const response = await requestWithValidation(`${basePath}/reports/${reportId}
|
|
1578
|
+
const response = await requestWithValidation(`${basePath}/reports/${reportId}`, z.object({ reports: z.array(ReportSchema) }));
|
|
1383
1579
|
if (response.reports.length === 0) {
|
|
1384
1580
|
throw new ZohoProjectsError(`Report not found: ${reportId}`, 404);
|
|
1385
1581
|
}
|
|
@@ -1406,10 +1602,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1406
1602
|
* List reports for a specific project
|
|
1407
1603
|
*/
|
|
1408
1604
|
async listForProject(projectId, params) {
|
|
1409
|
-
const response = await requestWithValidation(`${basePath}/projects/${projectId}/reports
|
|
1605
|
+
const response = await requestWithValidation(`${basePath}/projects/${projectId}/reports`, ReportListResponseSchema, {
|
|
1410
1606
|
params: {
|
|
1411
|
-
|
|
1412
|
-
|
|
1607
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1608
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1413
1609
|
},
|
|
1414
1610
|
});
|
|
1415
1611
|
return { data: response.reports, pageInfo: response.page_info };
|
|
@@ -1424,7 +1620,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1424
1620
|
* Search across all entities
|
|
1425
1621
|
*/
|
|
1426
1622
|
async query(query) {
|
|
1427
|
-
const response = await requestWithValidation(`${basePath}/search
|
|
1623
|
+
const response = await requestWithValidation(`${basePath}/search`, SearchResponseSchema, {
|
|
1428
1624
|
params: {
|
|
1429
1625
|
search_term: query.search_term,
|
|
1430
1626
|
entity_type: query.entity_type,
|
|
@@ -1486,13 +1682,13 @@ export function createZohoProjectsClient(config) {
|
|
|
1486
1682
|
* List items in trash
|
|
1487
1683
|
*/
|
|
1488
1684
|
async list(params) {
|
|
1489
|
-
const response = await requestWithValidation(`${basePath}/trash
|
|
1685
|
+
const response = await requestWithValidation(`${basePath}/trash`, TrashListResponseSchema, {
|
|
1490
1686
|
params: {
|
|
1491
1687
|
entity_type: params?.entity_type,
|
|
1492
1688
|
project_id: params?.project_id,
|
|
1493
1689
|
deleted_by: params?.deleted_by,
|
|
1494
|
-
|
|
1495
|
-
|
|
1690
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1691
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1496
1692
|
},
|
|
1497
1693
|
});
|
|
1498
1694
|
const items = response.trash || response.deleted_items || [];
|
|
@@ -1508,7 +1704,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1508
1704
|
* Iterate over all trash items with auto-pagination
|
|
1509
1705
|
*/
|
|
1510
1706
|
iterate(params, options) {
|
|
1511
|
-
return autoPaginate((
|
|
1707
|
+
return autoPaginate((page, per_page) => this.list({ ...params, page, per_page }), options);
|
|
1512
1708
|
},
|
|
1513
1709
|
/**
|
|
1514
1710
|
* Restore an item from trash
|
|
@@ -1521,7 +1717,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1521
1717
|
* Permanently delete an item from trash
|
|
1522
1718
|
*/
|
|
1523
1719
|
async permanentDelete(entityType, itemId) {
|
|
1524
|
-
await request(`${basePath}/trash/${entityType}/${itemId}
|
|
1720
|
+
await request(`${basePath}/trash/${entityType}/${itemId}`, {
|
|
1525
1721
|
method: "DELETE",
|
|
1526
1722
|
});
|
|
1527
1723
|
},
|
|
@@ -1530,8 +1726,8 @@ export function createZohoProjectsClient(config) {
|
|
|
1530
1726
|
*/
|
|
1531
1727
|
async empty(entityType) {
|
|
1532
1728
|
const path = entityType
|
|
1533
|
-
? `${basePath}/trash/${entityType}
|
|
1534
|
-
: `${basePath}/trash
|
|
1729
|
+
? `${basePath}/trash/${entityType}`
|
|
1730
|
+
: `${basePath}/trash`;
|
|
1535
1731
|
await request(path, { method: "DELETE" });
|
|
1536
1732
|
},
|
|
1537
1733
|
/**
|
|
@@ -1557,7 +1753,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1557
1753
|
* Get a specific portal by ID
|
|
1558
1754
|
*/
|
|
1559
1755
|
async get(portalId) {
|
|
1560
|
-
const response = await requestWithValidation(`/restapi/portals/${portalId}
|
|
1756
|
+
const response = await requestWithValidation(`/restapi/portals/${portalId}`, z.object({ portals: z.array(PortalSchema) }));
|
|
1561
1757
|
if (response.portals.length === 0) {
|
|
1562
1758
|
throw new ZohoProjectsError(`Portal not found: ${portalId}`, 404);
|
|
1563
1759
|
}
|
|
@@ -1579,7 +1775,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1579
1775
|
* List all modules in the portal
|
|
1580
1776
|
*/
|
|
1581
1777
|
async list(params) {
|
|
1582
|
-
const response = await requestWithValidation(`${basePath}/settings/modules
|
|
1778
|
+
const response = await requestWithValidation(`${basePath}/settings/modules`, ModuleListResponseSchema, {
|
|
1583
1779
|
params: {
|
|
1584
1780
|
is_customized: params?.is_customized,
|
|
1585
1781
|
is_default: params?.is_default,
|
|
@@ -1592,7 +1788,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1592
1788
|
* Get a specific module by ID
|
|
1593
1789
|
*/
|
|
1594
1790
|
async get(moduleId) {
|
|
1595
|
-
const response = await requestWithValidation(`${basePath}/settings/modules/${moduleId}
|
|
1791
|
+
const response = await requestWithValidation(`${basePath}/settings/modules/${moduleId}`, z.object({ modules: z.array(ModuleSchema) }));
|
|
1596
1792
|
if (response.modules.length === 0) {
|
|
1597
1793
|
throw new ZohoProjectsError(`Module not found: ${moduleId}`, 404);
|
|
1598
1794
|
}
|
|
@@ -1609,7 +1805,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1609
1805
|
* Get a specific field definition
|
|
1610
1806
|
*/
|
|
1611
1807
|
async getField(moduleId, fieldId) {
|
|
1612
|
-
const response = await requestWithValidation(`${basePath}/settings/modules/${moduleId}/fields/${fieldId}
|
|
1808
|
+
const response = await requestWithValidation(`${basePath}/settings/modules/${moduleId}/fields/${fieldId}`, z.object({ fields: z.array(ModuleFieldSchema) }));
|
|
1613
1809
|
if (response.fields.length === 0) {
|
|
1614
1810
|
throw new ZohoProjectsError(`Field not found: ${fieldId}`, 404);
|
|
1615
1811
|
}
|
|
@@ -1766,10 +1962,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1766
1962
|
* List custom views for a specific entity type
|
|
1767
1963
|
*/
|
|
1768
1964
|
async list(entityType, params) {
|
|
1769
|
-
const response = await requestWithValidation(`${basePath}/${entityType}/customviews
|
|
1965
|
+
const response = await requestWithValidation(`${basePath}/${entityType}/customviews`, CustomViewListResponseSchema, {
|
|
1770
1966
|
params: {
|
|
1771
|
-
|
|
1772
|
-
|
|
1967
|
+
page: params?.page ?? params?.index ?? 1,
|
|
1968
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1773
1969
|
},
|
|
1774
1970
|
});
|
|
1775
1971
|
return { data: response.customviews, pageInfo: response.page_info };
|
|
@@ -1784,13 +1980,13 @@ export function createZohoProjectsClient(config) {
|
|
|
1784
1980
|
* Iterate over all custom views with auto-pagination
|
|
1785
1981
|
*/
|
|
1786
1982
|
iterate(entityType, options) {
|
|
1787
|
-
return autoPaginate((
|
|
1983
|
+
return autoPaginate((page, per_page) => this.list(entityType, { page, per_page }), options);
|
|
1788
1984
|
},
|
|
1789
1985
|
/**
|
|
1790
1986
|
* Get a specific custom view
|
|
1791
1987
|
*/
|
|
1792
1988
|
async get(entityType, viewId) {
|
|
1793
|
-
const response = await requestWithValidation(`${basePath}/${entityType}/customviews/${viewId}
|
|
1989
|
+
const response = await requestWithValidation(`${basePath}/${entityType}/customviews/${viewId}`, z.object({ customviews: z.array(CustomViewSchema) }));
|
|
1794
1990
|
if (response.customviews.length === 0) {
|
|
1795
1991
|
throw new ZohoProjectsError(`Custom view not found: ${viewId}`, 404);
|
|
1796
1992
|
}
|
|
@@ -1800,21 +1996,21 @@ export function createZohoProjectsClient(config) {
|
|
|
1800
1996
|
* Create a custom view
|
|
1801
1997
|
*/
|
|
1802
1998
|
async create(entityType, data) {
|
|
1803
|
-
const response = await requestWithValidation(`${basePath}/${entityType}/customviews
|
|
1999
|
+
const response = await requestWithValidation(`${basePath}/${entityType}/customviews`, z.object({ customviews: z.array(CustomViewSchema) }), { method: "POST", data });
|
|
1804
2000
|
return response.customviews[0];
|
|
1805
2001
|
},
|
|
1806
2002
|
/**
|
|
1807
2003
|
* Update a custom view
|
|
1808
2004
|
*/
|
|
1809
2005
|
async update(entityType, viewId, data) {
|
|
1810
|
-
const response = await requestWithValidation(`${basePath}/${entityType}/customviews/${viewId}
|
|
2006
|
+
const response = await requestWithValidation(`${basePath}/${entityType}/customviews/${viewId}`, z.object({ customviews: z.array(CustomViewSchema) }), { method: "PUT", data });
|
|
1811
2007
|
return response.customviews[0];
|
|
1812
2008
|
},
|
|
1813
2009
|
/**
|
|
1814
2010
|
* Delete a custom view
|
|
1815
2011
|
*/
|
|
1816
2012
|
async delete(entityType, viewId) {
|
|
1817
|
-
await request(`${basePath}/${entityType}/customviews/${viewId}
|
|
2013
|
+
await request(`${basePath}/${entityType}/customviews/${viewId}`, {
|
|
1818
2014
|
method: "DELETE",
|
|
1819
2015
|
});
|
|
1820
2016
|
},
|
|
@@ -1870,10 +2066,10 @@ export function createZohoProjectsClient(config) {
|
|
|
1870
2066
|
* List all blueprints
|
|
1871
2067
|
*/
|
|
1872
2068
|
async list(params) {
|
|
1873
|
-
const response = await requestWithValidation(`${basePath}/settings/blueprints
|
|
2069
|
+
const response = await requestWithValidation(`${basePath}/settings/blueprints`, BlueprintListResponseSchema, {
|
|
1874
2070
|
params: {
|
|
1875
|
-
|
|
1876
|
-
|
|
2071
|
+
page: params?.page ?? params?.index ?? 1,
|
|
2072
|
+
per_page: params?.per_page ?? params?.range ?? DEFAULT_PAGE_SIZE,
|
|
1877
2073
|
},
|
|
1878
2074
|
});
|
|
1879
2075
|
return { data: response.blueprints, pageInfo: response.page_info };
|
|
@@ -1888,13 +2084,13 @@ export function createZohoProjectsClient(config) {
|
|
|
1888
2084
|
* Iterate over all blueprints with auto-pagination
|
|
1889
2085
|
*/
|
|
1890
2086
|
iterate(options) {
|
|
1891
|
-
return autoPaginate((
|
|
2087
|
+
return autoPaginate((page, per_page) => this.list({ page, per_page }), options);
|
|
1892
2088
|
},
|
|
1893
2089
|
/**
|
|
1894
2090
|
* Get a specific blueprint
|
|
1895
2091
|
*/
|
|
1896
2092
|
async get(blueprintId) {
|
|
1897
|
-
const response = await requestWithValidation(`${basePath}/settings/blueprints/${blueprintId}
|
|
2093
|
+
const response = await requestWithValidation(`${basePath}/settings/blueprints/${blueprintId}`, z.object({ blueprints: z.array(BlueprintSchema) }));
|
|
1898
2094
|
if (response.blueprints.length === 0) {
|
|
1899
2095
|
throw new ZohoProjectsError(`Blueprint not found: ${blueprintId}`, 404);
|
|
1900
2096
|
}
|
|
@@ -1921,7 +2117,7 @@ export function createZohoProjectsClient(config) {
|
|
|
1921
2117
|
*/
|
|
1922
2118
|
async executeTransition(projectId, moduleType, transitionId, data) {
|
|
1923
2119
|
const modulePath = moduleType === "Task" ? "tasks" : "bugs";
|
|
1924
|
-
await request(`${basePath}/projects/${projectId}/${modulePath}/${data.entity_id}/transitions/${transitionId}
|
|
2120
|
+
await request(`${basePath}/projects/${projectId}/${modulePath}/${data.entity_id}/transitions/${transitionId}`, {
|
|
1925
2121
|
method: "POST",
|
|
1926
2122
|
data: {
|
|
1927
2123
|
skip_bug_validation: data.skip_bug_validation,
|