@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workdrive.d.ts","sourceRoot":"","sources":["../../src/types/workdrive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAmBhB,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;GAEG;AACH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAE1B,CAAC;AAEjB,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAQtB,CAAC;AAEjB,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAMhB,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAMhE;;GAEG;AACH,eAAO,MAAM,0BAA0B;IACrC,oCAAoC;;IAEpC,wDAAwD;;IAExD,sEAAsE;;;;;;;;;;EAEtE,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
// WORKDRIVE SCHEMAS
|
|
4
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
/**
|
|
6
|
+
* WorkDrive file upload response
|
|
7
|
+
*/
|
|
8
|
+
export const WorkDriveFileSchema = z.object({
|
|
9
|
+
id: z.string(),
|
|
10
|
+
type: z.string().optional(),
|
|
11
|
+
attributes: z.object({
|
|
12
|
+
name: z.string(),
|
|
13
|
+
type: z.string().optional(),
|
|
14
|
+
extn: z.string().optional(),
|
|
15
|
+
resource_id: z.string().optional(),
|
|
16
|
+
parent_id: z.string().optional(),
|
|
17
|
+
storage_info: z.object({
|
|
18
|
+
size: z.string().optional(),
|
|
19
|
+
files_count: z.string().optional(),
|
|
20
|
+
folders_count: z.string().optional(),
|
|
21
|
+
}).optional(),
|
|
22
|
+
download_url: z.string().optional(),
|
|
23
|
+
permalink: z.string().optional(),
|
|
24
|
+
created_time: z.string().optional(),
|
|
25
|
+
modified_time: z.string().optional(),
|
|
26
|
+
}).passthrough(),
|
|
27
|
+
}).passthrough();
|
|
28
|
+
/**
|
|
29
|
+
* WorkDrive upload response schema
|
|
30
|
+
*/
|
|
31
|
+
export const WorkDriveUploadResponseSchema = z.object({
|
|
32
|
+
data: z.array(WorkDriveFileSchema),
|
|
33
|
+
}).passthrough();
|
|
34
|
+
/**
|
|
35
|
+
* WorkDrive team folder schema
|
|
36
|
+
*/
|
|
37
|
+
export const WorkDriveTeamFolderSchema = z.object({
|
|
38
|
+
id: z.string(),
|
|
39
|
+
type: z.string().optional(),
|
|
40
|
+
attributes: z.object({
|
|
41
|
+
name: z.string(),
|
|
42
|
+
is_default: z.boolean().optional(),
|
|
43
|
+
parent_id: z.string().optional(),
|
|
44
|
+
}).passthrough(),
|
|
45
|
+
}).passthrough();
|
|
46
|
+
/**
|
|
47
|
+
* WorkDrive team schema
|
|
48
|
+
*/
|
|
49
|
+
export const WorkDriveTeamSchema = z.object({
|
|
50
|
+
id: z.string(),
|
|
51
|
+
type: z.string().optional(),
|
|
52
|
+
attributes: z.object({
|
|
53
|
+
name: z.string(),
|
|
54
|
+
}).passthrough(),
|
|
55
|
+
}).passthrough();
|
|
56
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
57
|
+
// INPUT SCHEMAS
|
|
58
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
59
|
+
/**
|
|
60
|
+
* Input for uploading a file to WorkDrive
|
|
61
|
+
*/
|
|
62
|
+
export const WorkDriveUploadInputSchema = z.object({
|
|
63
|
+
/** Parent folder ID in WorkDrive */
|
|
64
|
+
parent_id: z.string(),
|
|
65
|
+
/** Optional custom filename (URL-encoded with UTF-8) */
|
|
66
|
+
filename: z.string().optional(),
|
|
67
|
+
/** If true, overwrites existing file with same name as new version */
|
|
68
|
+
override_name_exist: z.boolean().optional(),
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=workdrive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workdrive.js","sourceRoot":"","sources":["../../src/types/workdrive.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,19 +27,19 @@ export interface AutoPaginateOptions {
|
|
|
27
27
|
/**
|
|
28
28
|
* Create an async generator that automatically handles pagination
|
|
29
29
|
*
|
|
30
|
-
* Usage:
|
|
30
|
+
* Usage (V3 API - page-based):
|
|
31
31
|
* ```ts
|
|
32
|
-
* for await (const project of autoPaginate((
|
|
33
|
-
* client.projects.list({
|
|
32
|
+
* for await (const project of autoPaginate((page, per_page) =>
|
|
33
|
+
* client.projects.list({ page, per_page })
|
|
34
34
|
* )) {
|
|
35
35
|
* console.log(project);
|
|
36
36
|
* }
|
|
37
37
|
* ```
|
|
38
38
|
*
|
|
39
|
-
* @param fetchPage Function that fetches a page given
|
|
39
|
+
* @param fetchPage Function that fetches a page given page number (1-based) and page size
|
|
40
40
|
* @param options Pagination options
|
|
41
41
|
*/
|
|
42
|
-
export declare function autoPaginate<T>(fetchPage: (
|
|
42
|
+
export declare function autoPaginate<T>(fetchPage: (page: number, per_page: number) => Promise<PaginatedResponse<T>>, options?: AutoPaginateOptions): AsyncGenerator<T, void, unknown>;
|
|
43
43
|
/**
|
|
44
44
|
* Collect all items from an async generator into an array
|
|
45
45
|
*
|
|
@@ -50,10 +50,10 @@ export declare function autoPaginate<T>(fetchPage: (index: number, range: number
|
|
|
50
50
|
*/
|
|
51
51
|
export declare function collectAll<T>(generator: AsyncGenerator<T, void, unknown>): Promise<T[]>;
|
|
52
52
|
/**
|
|
53
|
-
* Helper to create pagination params for Zoho API
|
|
53
|
+
* Helper to create pagination params for Zoho V3 API
|
|
54
54
|
*/
|
|
55
|
-
export declare function createPaginationParams(
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
export declare function createPaginationParams(page?: number, per_page?: number): {
|
|
56
|
+
page: number;
|
|
57
|
+
per_page: number;
|
|
58
58
|
};
|
|
59
59
|
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAuB,YAAY,CAAC,CAAC,EACnC,SAAS,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAuB,YAAY,CAAC,CAAC,EACnC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAC5E,OAAO,GAAE,mBAAwB,GAChC,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAqClC;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,SAAS,EAAE,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,GAC1C,OAAO,CAAC,CAAC,EAAE,CAAC,CAMd;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,GAAE,MAAU,EAChB,QAAQ,GAAE,MAA0B,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKpC"}
|
package/dist/utils/pagination.js
CHANGED
|
@@ -10,26 +10,26 @@ export const MAX_PAGE_SIZE = 200;
|
|
|
10
10
|
/**
|
|
11
11
|
* Create an async generator that automatically handles pagination
|
|
12
12
|
*
|
|
13
|
-
* Usage:
|
|
13
|
+
* Usage (V3 API - page-based):
|
|
14
14
|
* ```ts
|
|
15
|
-
* for await (const project of autoPaginate((
|
|
16
|
-
* client.projects.list({
|
|
15
|
+
* for await (const project of autoPaginate((page, per_page) =>
|
|
16
|
+
* client.projects.list({ page, per_page })
|
|
17
17
|
* )) {
|
|
18
18
|
* console.log(project);
|
|
19
19
|
* }
|
|
20
20
|
* ```
|
|
21
21
|
*
|
|
22
|
-
* @param fetchPage Function that fetches a page given
|
|
22
|
+
* @param fetchPage Function that fetches a page given page number (1-based) and page size
|
|
23
23
|
* @param options Pagination options
|
|
24
24
|
*/
|
|
25
25
|
export async function* autoPaginate(fetchPage, options = {}) {
|
|
26
26
|
const pageSize = Math.min(options.pageSize ?? DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
|
|
27
27
|
const maxItems = options.maxItems ?? Infinity;
|
|
28
|
-
let
|
|
28
|
+
let page = 1; // V3 API uses 1-based pages
|
|
29
29
|
let itemsYielded = 0;
|
|
30
30
|
let hasMore = true;
|
|
31
31
|
while (hasMore && itemsYielded < maxItems) {
|
|
32
|
-
const response = await fetchPage(
|
|
32
|
+
const response = await fetchPage(page, pageSize);
|
|
33
33
|
const items = response.data;
|
|
34
34
|
if (items.length === 0) {
|
|
35
35
|
// No more items
|
|
@@ -53,7 +53,7 @@ export async function* autoPaginate(fetchPage, options = {}) {
|
|
|
53
53
|
}
|
|
54
54
|
else {
|
|
55
55
|
// Move to next page
|
|
56
|
-
|
|
56
|
+
page++;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -73,12 +73,12 @@ export async function collectAll(generator) {
|
|
|
73
73
|
return items;
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
* Helper to create pagination params for Zoho API
|
|
76
|
+
* Helper to create pagination params for Zoho V3 API
|
|
77
77
|
*/
|
|
78
|
-
export function createPaginationParams(
|
|
78
|
+
export function createPaginationParams(page = 1, per_page = DEFAULT_PAGE_SIZE) {
|
|
79
79
|
return {
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
page,
|
|
81
|
+
per_page: Math.min(per_page, MAX_PAGE_SIZE),
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
//# sourceMappingURL=pagination.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAoBjC;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,YAAY,CACjC,
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/utils/pagination.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAoBjC;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,YAAY,CACjC,SAA4E,EAC5E,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAChF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAE9C,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,4BAA4B;IAC1C,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,OAAO,GAAG,IAAI,CAAC;IAEnB,OAAO,OAAO,IAAI,YAAY,GAAG,QAAQ,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC;QAE5B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,gBAAgB;YAChB,OAAO,GAAG,KAAK,CAAC;YAChB,MAAM;QACR,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,YAAY,IAAI,QAAQ,EAAE,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD,MAAM,IAAI,CAAC;YACX,YAAY,EAAE,CAAC;QACjB,CAAC;QAED,oCAAoC;QACpC,IAAI,QAAQ,CAAC,QAAQ,EAAE,aAAa,KAAK,KAAK,EAAE,CAAC;YAC/C,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;YACnC,wDAAwD;YACxD,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,oBAAoB;YACpB,IAAI,EAAE,CAAC;QACT,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,SAA2C;IAE3C,MAAM,KAAK,GAAQ,EAAE,CAAC;IACtB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAe,CAAC,EAChB,WAAmB,iBAAiB;IAEpC,OAAO;QACL,IAAI;QACJ,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC;KAC5C,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@panoptic-it-solutions/zoho-projects-client",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "TypeScript client for Zoho Projects V3 API with OAuth 2.0 and rate limiting",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"test:watch": "vitest",
|
|
26
26
|
"test:coverage": "vitest run --coverage",
|
|
27
27
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
28
|
+
"oauth": "npx tsx scripts/get-refresh-token.ts",
|
|
28
29
|
"prepublishOnly": "npm run clean && npm run build"
|
|
29
30
|
},
|
|
30
31
|
"keywords": [
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
"@faker-js/faker": "^9.3.0",
|
|
56
57
|
"@types/node": "^22.0.0",
|
|
57
58
|
"@vitest/coverage-v8": "^2.1.0",
|
|
59
|
+
"dotenv": "^17.2.3",
|
|
58
60
|
"msw": "^2.7.0",
|
|
59
61
|
"typescript": "^5.6.0",
|
|
60
62
|
"vitest": "^2.1.0"
|
package/templates/CLAUDE.md
CHANGED
|
@@ -19,6 +19,9 @@ const client = createZohoProjectsClient({
|
|
|
19
19
|
clientSecret: process.env.ZOHO_CLIENT_SECRET!,
|
|
20
20
|
refreshToken: process.env.ZOHO_REFRESH_TOKEN!,
|
|
21
21
|
portalId: process.env.ZOHO_PORTAL_ID!,
|
|
22
|
+
// For EU region:
|
|
23
|
+
apiUrl: 'https://projectsapi.zoho.eu',
|
|
24
|
+
accountsUrl: 'https://accounts.zoho.eu',
|
|
22
25
|
});
|
|
23
26
|
```
|
|
24
27
|
|
|
@@ -29,8 +32,173 @@ ZOHO_CLIENT_ID= # OAuth client ID from Zoho API Console
|
|
|
29
32
|
ZOHO_CLIENT_SECRET= # OAuth client secret
|
|
30
33
|
ZOHO_REFRESH_TOKEN= # Refresh token from OAuth flow
|
|
31
34
|
ZOHO_PORTAL_ID= # Your Zoho Projects portal ID
|
|
35
|
+
|
|
36
|
+
# Optional - Region URLs (defaults to US)
|
|
37
|
+
ZOHO_API_URL=https://projectsapi.zoho.eu
|
|
38
|
+
ZOHO_ACCOUNTS_URL=https://accounts.zoho.eu
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Required OAuth Scopes
|
|
42
|
+
|
|
43
|
+
For full V3 API functionality:
|
|
44
|
+
```
|
|
45
|
+
ZohoProjects.projects.ALL,ZohoProjects.tasks.ALL,ZohoProjects.tasklists.ALL,ZohoProjects.portals.READ,ZohoProjects.users.ALL,ZohoProjects.timesheets.ALL,ZohoProjects.bugs.ALL,ZohoProjects.milestones.ALL,ZohoProjects.events.ALL,ZohoProjects.forums.ALL,ZohoProjects.documents.ALL,ZohoProjects.tags.ALL,ZohoProjects.status.READ,ZohoProjects.search.READ
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**For file attachments (requires WorkDrive integration):**
|
|
49
|
+
```
|
|
50
|
+
ZohoPC.files.ALL,WorkDrive.team.ALL,WorkDrive.workspace.ALL,WorkDrive.files.ALL,WorkDrive.teamfolders.ALL
|
|
32
51
|
```
|
|
33
52
|
|
|
53
|
+
Use `scripts/get-refresh-token.ts` to generate a token with all scopes. This script will open a browser window for OAuth authorization and automatically request all required scopes.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## File Attachment Workflow (AI Agent Instructions)
|
|
58
|
+
|
|
59
|
+
Zoho Projects uses **WorkDrive** for file storage. There are two methods to attach files to tasks:
|
|
60
|
+
|
|
61
|
+
### Method 1: Simple Direct Upload (Recommended)
|
|
62
|
+
|
|
63
|
+
Use the legacy `/restapi/` endpoint with `uploaddoc` form field. This is the **simplest and most reliable** method - it handles WorkDrive upload and task association in a single request.
|
|
64
|
+
|
|
65
|
+
#### Required OAuth Scopes
|
|
66
|
+
|
|
67
|
+
| Scope | Purpose |
|
|
68
|
+
|-------|---------|
|
|
69
|
+
| `ZohoProjects.tasks.ALL` | Task operations |
|
|
70
|
+
| `ZohoProjects.documents.ALL` | Document access |
|
|
71
|
+
| `ZohoPC.files.ALL` | Attachments API |
|
|
72
|
+
|
|
73
|
+
#### Upload File to Task
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import FormData from 'form-data';
|
|
77
|
+
import axios from 'axios';
|
|
78
|
+
|
|
79
|
+
const formData = new FormData();
|
|
80
|
+
formData.append('uploaddoc', fileBuffer, {
|
|
81
|
+
filename: 'test.txt',
|
|
82
|
+
contentType: 'text/plain'
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const response = await axios.post(
|
|
86
|
+
`https://projectsapi.zoho.eu/restapi/portal/${portalId}/projects/${projectId}/tasks/${taskId}/attachments/`,
|
|
87
|
+
formData,
|
|
88
|
+
{
|
|
89
|
+
headers: {
|
|
90
|
+
Authorization: `Zoho-oauthtoken ${accessToken}`,
|
|
91
|
+
...formData.getHeaders()
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Response contains the attachment with WorkDrive file ID
|
|
97
|
+
const attachment = response.data.thirdparty_attachments[0];
|
|
98
|
+
console.log('Attachment ID:', attachment.attachment_id);
|
|
99
|
+
console.log('WorkDrive File ID:', attachment.third_party_file_id);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### List Task Attachments
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// Via V3 API (preferred)
|
|
106
|
+
const listRes = await axios.get(
|
|
107
|
+
`https://projectsapi.zoho.eu/api/v3/portal/${portalId}/projects/${projectId}/attachments`,
|
|
108
|
+
{
|
|
109
|
+
params: { entity_type: 'task', entity_id: taskId },
|
|
110
|
+
headers: { Authorization: `Zoho-oauthtoken ${accessToken}` }
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
// V3 returns { attachment: [...] } (singular key)
|
|
114
|
+
const attachments = listRes.data.attachment || [];
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Method 2: Manual WorkDrive Upload (Advanced)
|
|
118
|
+
|
|
119
|
+
For more control over the upload process, you can upload to WorkDrive first, then register with Zoho Projects.
|
|
120
|
+
|
|
121
|
+
#### Additional OAuth Scopes Required
|
|
122
|
+
|
|
123
|
+
| Scope | Purpose |
|
|
124
|
+
|-------|---------|
|
|
125
|
+
| `WorkDrive.team.ALL` | Access WorkDrive teams |
|
|
126
|
+
| `WorkDrive.workspace.ALL` | Access workspaces |
|
|
127
|
+
| `WorkDrive.files.ALL` | Upload/manage files |
|
|
128
|
+
| `WorkDrive.teamfolders.ALL` | Access team folders |
|
|
129
|
+
|
|
130
|
+
#### Step 1: Get WorkDrive User Info
|
|
131
|
+
```typescript
|
|
132
|
+
const userRes = await axios.get('https://workdrive.zoho.eu/api/v1/users/me', {
|
|
133
|
+
headers: {
|
|
134
|
+
Authorization: `Zoho-oauthtoken ${accessToken}`,
|
|
135
|
+
Accept: 'application/vnd.api+json'
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
const preferredTeamId = userRes.data.data.attributes.preferred_team_id;
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### Step 2: Find the "Zoho Projects" Team Folder
|
|
142
|
+
```typescript
|
|
143
|
+
const foldersRes = await axios.get(
|
|
144
|
+
`https://workdrive.zoho.eu/api/v1/teams/${preferredTeamId}/teamfolders`,
|
|
145
|
+
{ headers: workdriveHeaders }
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const projectsFolder = foldersRes.data.data.find(
|
|
149
|
+
f => f.attributes.name === 'Zoho Projects'
|
|
150
|
+
);
|
|
151
|
+
const projectsFolderId = projectsFolder.id;
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### Step 3: Find the Project-Specific Subfolder
|
|
155
|
+
```typescript
|
|
156
|
+
const subFoldersRes = await axios.get(
|
|
157
|
+
`https://workdrive.zoho.eu/api/v1/teamfolders/${projectsFolderId}/folders`,
|
|
158
|
+
{ headers: workdriveHeaders }
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
// Find folder named like "PA-{num}-{projectName}-Attachments"
|
|
162
|
+
const projectFolder = subFoldersRes.data.data.find(
|
|
163
|
+
f => f.attributes.name.includes(projectName) && f.attributes.name.includes('-Attachments')
|
|
164
|
+
);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Step 4: Upload File to WorkDrive
|
|
168
|
+
```typescript
|
|
169
|
+
const formData = new FormData();
|
|
170
|
+
formData.append('content', fileBuffer, {
|
|
171
|
+
filename: 'test.txt',
|
|
172
|
+
contentType: 'text/plain'
|
|
173
|
+
});
|
|
174
|
+
formData.append('parent_id', projectFolderId);
|
|
175
|
+
|
|
176
|
+
const uploadRes = await axios.post(
|
|
177
|
+
'https://workdrive.zoho.eu/api/v1/upload',
|
|
178
|
+
formData,
|
|
179
|
+
{ headers: { ...workdriveHeaders, ...formData.getHeaders() } }
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const workdriveFileId = uploadRes.data.data[0].attributes.resource_id;
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Regional API URLs
|
|
186
|
+
|
|
187
|
+
| Region | WorkDrive API | Projects API | Accounts URL |
|
|
188
|
+
|--------|--------------|--------------|--------------|
|
|
189
|
+
| US | workdrive.zoho.com | projectsapi.zoho.com | accounts.zoho.com |
|
|
190
|
+
| EU | workdrive.zoho.eu | projectsapi.zoho.eu | accounts.zoho.eu |
|
|
191
|
+
| IN | workdrive.zoho.in | projectsapi.zoho.in | accounts.zoho.in |
|
|
192
|
+
| AU | workdrive.zoho.com.au | projectsapi.zoho.com.au | accounts.zoho.com.au |
|
|
193
|
+
|
|
194
|
+
### Troubleshooting
|
|
195
|
+
|
|
196
|
+
- **INVALID_OAUTHSCOPE on V3 `/attachments` endpoint**: Use Method 1 (direct upload via `/restapi/`) instead
|
|
197
|
+
- **No team folders found**: Use `users/me` to get `preferred_team_id`, then query `/teams/{teamId}/teamfolders`
|
|
198
|
+
- **Project folder not found**: Zoho automatically creates project folders; wait a moment after project creation
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
34
202
|
## Available Namespaces
|
|
35
203
|
|
|
36
204
|
### Portal-Level (no projectId needed)
|
|
@@ -46,6 +214,9 @@ ZOHO_PORTAL_ID= # Your Zoho Projects portal ID
|
|
|
46
214
|
## Common Patterns
|
|
47
215
|
|
|
48
216
|
```typescript
|
|
217
|
+
// List with V3 pagination (page/per_page)
|
|
218
|
+
const { data, pageInfo } = await client.projects.list({ page: 1, per_page: 100 });
|
|
219
|
+
|
|
49
220
|
// List all (auto-paginate)
|
|
50
221
|
const allProjects = await client.projects.listAll();
|
|
51
222
|
|
|
@@ -54,12 +225,24 @@ for await (const project of client.projects.iterate()) {
|
|
|
54
225
|
console.log(project.name);
|
|
55
226
|
}
|
|
56
227
|
|
|
57
|
-
//
|
|
58
|
-
await client.tasks.create(projectId, {
|
|
228
|
+
// Create task (V3 uses nested tasklist object)
|
|
229
|
+
await client.tasks.create(projectId, {
|
|
230
|
+
name: 'New task',
|
|
231
|
+
tasklist: { id: tasklistId },
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Update and delete
|
|
59
235
|
await client.tasks.update(projectId, taskId, { status: 'completed' });
|
|
60
236
|
await client.tasks.delete(projectId, taskId);
|
|
61
237
|
```
|
|
62
238
|
|
|
239
|
+
## V3 API Notes
|
|
240
|
+
|
|
241
|
+
- **Pagination**: Uses `page` (1-based) and `per_page` instead of `index`/`range`
|
|
242
|
+
- **IDs**: Returns string IDs, not numbers
|
|
243
|
+
- **Nested objects**: Many fields like `owner`, `status`, `tasklist` are nested objects
|
|
244
|
+
- **Response format**: V3 returns data directly, not wrapped in arrays
|
|
245
|
+
|
|
63
246
|
## Package Documentation
|
|
64
247
|
|
|
65
248
|
- [GitHub Repository](https://github.com/Panoptic-IT-Solutions/zoho-projects-client)
|