@panoptic-it-solutions/zoho-projects-client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +231 -0
  2. package/dist/auth/token-manager.d.ts +59 -0
  3. package/dist/auth/token-manager.d.ts.map +1 -0
  4. package/dist/auth/token-manager.js +120 -0
  5. package/dist/auth/token-manager.js.map +1 -0
  6. package/dist/client.d.ts +193 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +357 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/errors.d.ts +61 -0
  11. package/dist/errors.d.ts.map +1 -0
  12. package/dist/errors.js +113 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/index.d.ts +7 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +11 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/types/common.d.ts +173 -0
  19. package/dist/types/common.d.ts.map +1 -0
  20. package/dist/types/common.js +56 -0
  21. package/dist/types/common.js.map +1 -0
  22. package/dist/types/index.d.ts +6 -0
  23. package/dist/types/index.d.ts.map +1 -0
  24. package/dist/types/index.js +11 -0
  25. package/dist/types/index.js.map +1 -0
  26. package/dist/types/projects.d.ts +3671 -0
  27. package/dist/types/projects.d.ts.map +1 -0
  28. package/dist/types/projects.js +94 -0
  29. package/dist/types/projects.js.map +1 -0
  30. package/dist/types/tasks.d.ts +2612 -0
  31. package/dist/types/tasks.d.ts.map +1 -0
  32. package/dist/types/tasks.js +127 -0
  33. package/dist/types/tasks.js.map +1 -0
  34. package/dist/types/timelogs.d.ts +13623 -0
  35. package/dist/types/timelogs.d.ts.map +1 -0
  36. package/dist/types/timelogs.js +115 -0
  37. package/dist/types/timelogs.js.map +1 -0
  38. package/dist/types/users.d.ts +695 -0
  39. package/dist/types/users.d.ts.map +1 -0
  40. package/dist/types/users.js +65 -0
  41. package/dist/types/users.js.map +1 -0
  42. package/dist/utils/pagination.d.ts +59 -0
  43. package/dist/utils/pagination.d.ts.map +1 -0
  44. package/dist/utils/pagination.js +84 -0
  45. package/dist/utils/pagination.js.map +1 -0
  46. package/dist/utils/rate-limiter.d.ts +33 -0
  47. package/dist/utils/rate-limiter.d.ts.map +1 -0
  48. package/dist/utils/rate-limiter.js +92 -0
  49. package/dist/utils/rate-limiter.js.map +1 -0
  50. package/package.json +53 -0
package/README.md ADDED
@@ -0,0 +1,231 @@
1
+ # @panoptic-it-solutions/zoho-projects-client
2
+
3
+ TypeScript client for Zoho Projects V3 API with OAuth 2.0 and rate limiting.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @panoptic-it-solutions/zoho-projects-client
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { createZohoProjectsClient } from "@panoptic-it-solutions/zoho-projects-client";
15
+
16
+ const client = createZohoProjectsClient({
17
+ clientId: process.env.ZOHO_CLIENT_ID!,
18
+ clientSecret: process.env.ZOHO_CLIENT_SECRET!,
19
+ refreshToken: process.env.ZOHO_REFRESH_TOKEN!,
20
+ portalId: process.env.ZOHO_PORTAL_ID!,
21
+ });
22
+
23
+ // List projects
24
+ const { data: projects } = await client.projects.list();
25
+
26
+ // Get all projects with auto-pagination
27
+ const allProjects = await client.projects.listAll();
28
+
29
+ // Iterate over projects
30
+ for await (const project of client.projects.iterate()) {
31
+ console.log(project.name);
32
+ }
33
+ ```
34
+
35
+ ## Authentication Setup
36
+
37
+ Zoho requires OAuth 2.0 with a refresh token. Here's how to get one:
38
+
39
+ ### 1. Create a Client
40
+
41
+ 1. Go to [Zoho API Console](https://api-console.zoho.com) (or `.eu`, `.in`, `.com.au` for your region)
42
+ 2. Click **Add Client** → **Server-based Applications**
43
+ 3. Fill in the details and click **Create**
44
+ 4. Copy the **Client ID** and **Client Secret**
45
+
46
+ ### 2. Generate a Refresh Token
47
+
48
+ 1. In API Console, select your client → **Generate Code** → **Self Client**
49
+ 2. Enter scope:
50
+ ```
51
+ ZohoProjects.projects.READ,ZohoProjects.tasks.READ,ZohoProjects.timesheets.READ,ZohoProjects.users.READ,ZohoProjects.portals.READ
52
+ ```
53
+ 3. Click **Create** and copy the authorization code
54
+ 4. Exchange it for a refresh token (within 2 minutes):
55
+
56
+ ```bash
57
+ curl -X POST "https://accounts.zoho.com/oauth/v2/token" \
58
+ -d "grant_type=authorization_code" \
59
+ -d "client_id=YOUR_CLIENT_ID" \
60
+ -d "client_secret=YOUR_CLIENT_SECRET" \
61
+ -d "code=YOUR_AUTH_CODE"
62
+ ```
63
+
64
+ 5. Copy the `refresh_token` from the response (it doesn't expire unless revoked)
65
+
66
+ ## Configuration
67
+
68
+ ```typescript
69
+ const client = createZohoProjectsClient({
70
+ // Required
71
+ clientId: "your_client_id",
72
+ clientSecret: "your_client_secret",
73
+ refreshToken: "your_refresh_token",
74
+ portalId: "your_portal_id",
75
+
76
+ // Optional - defaults shown
77
+ apiUrl: "https://projectsapi.zoho.com", // US region
78
+ accountsUrl: "https://accounts.zoho.com", // US region
79
+ timeout: 30000, // 30 seconds
80
+
81
+ // Optional - for distributed rate limiting
82
+ redis: {
83
+ url: "redis://localhost:6379",
84
+ },
85
+ });
86
+ ```
87
+
88
+ ### Region URLs
89
+
90
+ | Region | API URL | Accounts URL |
91
+ |--------|---------|--------------|
92
+ | US | `https://projectsapi.zoho.com` | `https://accounts.zoho.com` |
93
+ | EU | `https://projectsapi.zoho.eu` | `https://accounts.zoho.eu` |
94
+ | IN | `https://projectsapi.zoho.in` | `https://accounts.zoho.in` |
95
+ | AU | `https://projectsapi.zoho.com.au` | `https://accounts.zoho.com.au` |
96
+
97
+ ## API Reference
98
+
99
+ ### Projects
100
+
101
+ ```typescript
102
+ // List with pagination
103
+ const { data, pageInfo } = await client.projects.list({ index: 0, range: 100 });
104
+
105
+ // Get all projects
106
+ const projects = await client.projects.listAll();
107
+
108
+ // Get single project
109
+ const project = await client.projects.get("project_id");
110
+
111
+ // Iterate with auto-pagination
112
+ for await (const project of client.projects.iterate()) {
113
+ console.log(project.name);
114
+ }
115
+ ```
116
+
117
+ ### Tasks
118
+
119
+ ```typescript
120
+ // List tasks for a project
121
+ const { data } = await client.tasks.list("project_id");
122
+
123
+ // Get all tasks for a project
124
+ const tasks = await client.tasks.listAll("project_id");
125
+
126
+ // Get single task
127
+ const task = await client.tasks.get("project_id", "task_id");
128
+
129
+ // Get all tasks across all projects
130
+ const allTasks = await client.tasks.listAllAcrossProjects();
131
+ ```
132
+
133
+ ### Time Logs
134
+
135
+ Time logs require specific parameters:
136
+
137
+ ```typescript
138
+ // List time logs for a project
139
+ const { data } = await client.timelogs.list("project_id", {
140
+ users_list: "all", // "all" or comma-separated user IDs
141
+ view_type: "month", // "day", "week", "month", or "custom_date"
142
+ date: "12-14-2025", // MM-DD-YYYY format
143
+ bill_status: "All", // "All", "Billable", or "Non Billable"
144
+ component_type: "task", // "task", "bug", or "general"
145
+ });
146
+
147
+ // Get all time logs for a project
148
+ const logs = await client.timelogs.listAll("project_id", {
149
+ users_list: "all",
150
+ view_type: "month",
151
+ date: "12-14-2025",
152
+ bill_status: "All",
153
+ component_type: "task",
154
+ });
155
+ ```
156
+
157
+ ### Users
158
+
159
+ ```typescript
160
+ // List portal users
161
+ const { data } = await client.users.list();
162
+
163
+ // Get all users
164
+ const users = await client.users.listAll();
165
+
166
+ // Get single user
167
+ const user = await client.users.get("user_id");
168
+
169
+ // List users for a project
170
+ const { data: projectUsers } = await client.users.listForProject("project_id");
171
+ ```
172
+
173
+ ## Rate Limiting
174
+
175
+ The client automatically handles Zoho's rate limits:
176
+ - 100 requests per 2 minutes
177
+ - 30-minute lockout on 429 response
178
+
179
+ Uses [Bottleneck](https://github.com/SGrondin/bottleneck) with a safety margin (90 requests per 2 minutes).
180
+
181
+ For distributed deployments, configure Redis:
182
+
183
+ ```typescript
184
+ const client = createZohoProjectsClient({
185
+ // ...
186
+ redis: {
187
+ url: process.env.REDIS_URL!,
188
+ },
189
+ });
190
+ ```
191
+
192
+ ## Error Handling
193
+
194
+ ```typescript
195
+ import {
196
+ ZohoProjectsError,
197
+ ZohoAuthenticationError,
198
+ ZohoRateLimitError,
199
+ ZohoNotFoundError,
200
+ isRateLimitError,
201
+ } from "@panoptic-it-solutions/zoho-projects-client";
202
+
203
+ try {
204
+ const project = await client.projects.get("invalid_id");
205
+ } catch (error) {
206
+ if (error instanceof ZohoNotFoundError) {
207
+ console.log("Project not found");
208
+ } else if (isRateLimitError(error)) {
209
+ console.log(`Rate limited, retry after ${error.lockoutDurationMs}ms`);
210
+ } else if (error instanceof ZohoAuthenticationError) {
211
+ console.log("Invalid credentials");
212
+ }
213
+ }
214
+ ```
215
+
216
+ ## Environment Variables
217
+
218
+ ```env
219
+ ZOHO_CLIENT_ID=your_client_id
220
+ ZOHO_CLIENT_SECRET=your_client_secret
221
+ ZOHO_REFRESH_TOKEN=your_refresh_token
222
+ ZOHO_PORTAL_ID=your_portal_id
223
+
224
+ # Optional - defaults to US region
225
+ ZOHO_API_URL=https://projectsapi.zoho.com
226
+ ZOHO_ACCOUNTS_URL=https://accounts.zoho.com
227
+ ```
228
+
229
+ ## License
230
+
231
+ MIT
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Configuration for the token manager
3
+ */
4
+ export interface TokenManagerConfig {
5
+ clientId: string;
6
+ clientSecret: string;
7
+ refreshToken: string;
8
+ accountsUrl: string;
9
+ }
10
+ /**
11
+ * Manages OAuth 2.0 tokens for Zoho Projects API
12
+ *
13
+ * Features:
14
+ * - Client credentials flow
15
+ * - Automatic token refresh before expiry (at 55 minutes)
16
+ * - Promise deduplication to prevent concurrent refresh requests
17
+ */
18
+ export declare class TokenManager {
19
+ private readonly config;
20
+ private accessToken;
21
+ private expiresAt;
22
+ private refreshPromise;
23
+ private httpClient;
24
+ constructor(config: TokenManagerConfig);
25
+ /**
26
+ * Get a valid access token, refreshing if necessary
27
+ * Safe to call concurrently - only one refresh request will be made
28
+ */
29
+ getValidToken(): Promise<string>;
30
+ /**
31
+ * Check if the current token is valid
32
+ * Returns false if token is null or within 5 minutes of expiry
33
+ */
34
+ private isTokenValid;
35
+ /**
36
+ * Refresh the access token
37
+ * Uses promise deduplication to prevent concurrent refresh requests
38
+ * This is critical for multi-instance deployments
39
+ */
40
+ private refreshToken;
41
+ /**
42
+ * Perform the actual token refresh request
43
+ */
44
+ private doRefresh;
45
+ /**
46
+ * Invalidate the current token
47
+ * Useful when receiving 401 responses to force a refresh
48
+ */
49
+ invalidate(): void;
50
+ /**
51
+ * Get token expiry time for debugging/monitoring
52
+ */
53
+ getExpiresAt(): number;
54
+ /**
55
+ * Get remaining validity in milliseconds
56
+ */
57
+ getRemainingValidityMs(): number;
58
+ }
59
+ //# sourceMappingURL=token-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAYD;;;;;;;GAOG;AACH,qBAAa,YAAY;IAMX,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,cAAc,CAAgC;IACtD,OAAO,CAAC,UAAU,CAAgB;gBAEL,MAAM,EAAE,kBAAkB;IAOvD;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAOtC;;;OAGG;IACH,OAAO,CAAC,YAAY;IASpB;;;;OAIG;YACW,YAAY;IAgB1B;;OAEG;YACW,SAAS;IA6CvB;;;OAGG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,sBAAsB,IAAI,MAAM;CAMjC"}
@@ -0,0 +1,120 @@
1
+ import axios from "axios";
2
+ import { ZohoAuthenticationError } from "../errors.js";
3
+ /**
4
+ * Manages OAuth 2.0 tokens for Zoho Projects API
5
+ *
6
+ * Features:
7
+ * - Client credentials flow
8
+ * - Automatic token refresh before expiry (at 55 minutes)
9
+ * - Promise deduplication to prevent concurrent refresh requests
10
+ */
11
+ export class TokenManager {
12
+ config;
13
+ accessToken = null;
14
+ expiresAt = 0;
15
+ refreshPromise = null;
16
+ httpClient;
17
+ constructor(config) {
18
+ this.config = config;
19
+ this.httpClient = axios.create({
20
+ baseURL: config.accountsUrl,
21
+ timeout: 30000,
22
+ });
23
+ }
24
+ /**
25
+ * Get a valid access token, refreshing if necessary
26
+ * Safe to call concurrently - only one refresh request will be made
27
+ */
28
+ async getValidToken() {
29
+ if (this.isTokenValid()) {
30
+ return this.accessToken;
31
+ }
32
+ return this.refreshToken();
33
+ }
34
+ /**
35
+ * Check if the current token is valid
36
+ * Returns false if token is null or within 5 minutes of expiry
37
+ */
38
+ isTokenValid() {
39
+ if (!this.accessToken) {
40
+ return false;
41
+ }
42
+ // Refresh 5 minutes before expiry
43
+ const bufferMs = 5 * 60 * 1000;
44
+ return Date.now() < this.expiresAt - bufferMs;
45
+ }
46
+ /**
47
+ * Refresh the access token
48
+ * Uses promise deduplication to prevent concurrent refresh requests
49
+ * This is critical for multi-instance deployments
50
+ */
51
+ async refreshToken() {
52
+ // If a refresh is already in progress, wait for it
53
+ if (this.refreshPromise) {
54
+ return this.refreshPromise;
55
+ }
56
+ // Start a new refresh
57
+ this.refreshPromise = this.doRefresh();
58
+ try {
59
+ return await this.refreshPromise;
60
+ }
61
+ finally {
62
+ this.refreshPromise = null;
63
+ }
64
+ }
65
+ /**
66
+ * Perform the actual token refresh request
67
+ */
68
+ async doRefresh() {
69
+ try {
70
+ const response = await this.httpClient.post("/oauth/v2/token", null, {
71
+ params: {
72
+ grant_type: "refresh_token",
73
+ client_id: this.config.clientId,
74
+ client_secret: this.config.clientSecret,
75
+ refresh_token: this.config.refreshToken,
76
+ },
77
+ });
78
+ const data = response.data;
79
+ if (!data.access_token) {
80
+ throw new ZohoAuthenticationError("No access token in response");
81
+ }
82
+ this.accessToken = data.access_token;
83
+ // Set expiry time - tokens are valid for 1 hour (3600 seconds)
84
+ this.expiresAt = Date.now() + data.expires_in * 1000;
85
+ return this.accessToken;
86
+ }
87
+ catch (error) {
88
+ if (axios.isAxiosError(error)) {
89
+ const message = error.response?.data?.error ||
90
+ error.message;
91
+ throw new ZohoAuthenticationError(`Failed to obtain access token: ${message}`, error);
92
+ }
93
+ throw new ZohoAuthenticationError(`Failed to obtain access token: ${error instanceof Error ? error.message : "Unknown error"}`, error instanceof Error ? error : undefined);
94
+ }
95
+ }
96
+ /**
97
+ * Invalidate the current token
98
+ * Useful when receiving 401 responses to force a refresh
99
+ */
100
+ invalidate() {
101
+ this.accessToken = null;
102
+ this.expiresAt = 0;
103
+ }
104
+ /**
105
+ * Get token expiry time for debugging/monitoring
106
+ */
107
+ getExpiresAt() {
108
+ return this.expiresAt;
109
+ }
110
+ /**
111
+ * Get remaining validity in milliseconds
112
+ */
113
+ getRemainingValidityMs() {
114
+ if (!this.accessToken) {
115
+ return 0;
116
+ }
117
+ return Math.max(0, this.expiresAt - Date.now());
118
+ }
119
+ }
120
+ //# sourceMappingURL=token-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/auth/token-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAsBvD;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IAMM;IALrB,WAAW,GAAkB,IAAI,CAAC;IAClC,SAAS,GAAW,CAAC,CAAC;IACtB,cAAc,GAA2B,IAAI,CAAC;IAC9C,UAAU,CAAgB;IAElC,YAA6B,MAA0B;QAA1B,WAAM,GAAN,MAAM,CAAoB;QACrD,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;YAC7B,OAAO,EAAE,MAAM,CAAC,WAAW;YAC3B,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,WAAY,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACK,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,kCAAkC;QAClC,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAC/B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAChD,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,YAAY;QACxB,mDAAmD;QACnD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,cAAc,CAAC;QAC7B,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAEvC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC;QACnC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CACzC,iBAAiB,EACjB,IAAI,EACJ;gBACE,MAAM,EAAE;oBACN,UAAU,EAAE,eAAe;oBAC3B,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;oBAC/B,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;oBACvC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;iBACxC;aACF,CACF,CAAC;YAEF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;YAE3B,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvB,MAAM,IAAI,uBAAuB,CAC/B,6BAA6B,CAC9B,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;YACrC,+DAA+D;YAC/D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YAErD,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,OAAO,GACV,KAAK,CAAC,QAAQ,EAAE,IAA2B,EAAE,KAAK;oBACnD,KAAK,CAAC,OAAO,CAAC;gBAChB,MAAM,IAAI,uBAAuB,CAC/B,kCAAkC,OAAO,EAAE,EAC3C,KAAK,CACN,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,uBAAuB,CAC/B,kCAAkC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,EAC5F,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC;QACX,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC;CACF"}
@@ -0,0 +1,193 @@
1
+ import type Bottleneck from "bottleneck";
2
+ import { TokenManager } from "./auth/token-manager.js";
3
+ import { type Project, type Task, type TimeLog, type User, type ListParams, type TimeLogParams } from "./types/index.js";
4
+ import { type RateLimiterConfig } from "./utils/rate-limiter.js";
5
+ import { type AutoPaginateOptions, type PaginatedResponse } from "./utils/pagination.js";
6
+ /**
7
+ * Configuration for creating a Zoho Projects client
8
+ */
9
+ export interface ZohoProjectsConfig {
10
+ /** OAuth client ID from Zoho Developer Console */
11
+ clientId: string;
12
+ /** OAuth client secret from Zoho Developer Console */
13
+ clientSecret: string;
14
+ /** OAuth refresh token (obtained via authorization code flow) */
15
+ refreshToken: string;
16
+ /** Zoho Projects portal ID */
17
+ portalId: string;
18
+ /** API base URL (default: https://projectsapi.zoho.com) */
19
+ apiUrl?: string;
20
+ /** OAuth accounts URL (default: https://accounts.zoho.com) */
21
+ accountsUrl?: string;
22
+ /** Request timeout in milliseconds (default: 30000) */
23
+ timeout?: number;
24
+ /** Redis configuration for distributed rate limiting */
25
+ redis?: RateLimiterConfig["redis"];
26
+ }
27
+ /**
28
+ * Create a Zoho Projects API client
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const client = createZohoProjectsClient({
33
+ * clientId: process.env.ZOHO_CLIENT_ID!,
34
+ * clientSecret: process.env.ZOHO_CLIENT_SECRET!,
35
+ * portalId: process.env.ZOHO_PORTAL_ID!,
36
+ * });
37
+ *
38
+ * // List all projects
39
+ * const projects = await client.projects.list();
40
+ *
41
+ * // Get all projects with auto-pagination
42
+ * const allProjects = await client.projects.listAll();
43
+ *
44
+ * // Stream projects with async iteration
45
+ * for await (const project of client.projects.iterate()) {
46
+ * console.log(project.name);
47
+ * }
48
+ * ```
49
+ */
50
+ export declare function createZohoProjectsClient(config: ZohoProjectsConfig): {
51
+ /**
52
+ * Projects API
53
+ */
54
+ projects: {
55
+ /**
56
+ * List projects with pagination
57
+ */
58
+ list(params?: ListParams): Promise<PaginatedResponse<Project>>;
59
+ /**
60
+ * Get all projects with auto-pagination
61
+ */
62
+ listAll(options?: AutoPaginateOptions): Promise<Project[]>;
63
+ /**
64
+ * Iterate over all projects with auto-pagination
65
+ */
66
+ iterate(options?: AutoPaginateOptions): AsyncGenerator<Project, void, unknown>;
67
+ /**
68
+ * Get a single project by ID
69
+ */
70
+ get(projectId: string): Promise<Project>;
71
+ };
72
+ /**
73
+ * Tasks API
74
+ */
75
+ tasks: {
76
+ /**
77
+ * List tasks for a project with pagination
78
+ */
79
+ list(projectId: string, params?: ListParams): Promise<PaginatedResponse<Task>>;
80
+ /**
81
+ * Get all tasks for a project with auto-pagination
82
+ */
83
+ listAll(projectId: string, options?: AutoPaginateOptions): Promise<Task[]>;
84
+ /**
85
+ * Iterate over all tasks for a project with auto-pagination
86
+ */
87
+ iterate(projectId: string, options?: AutoPaginateOptions): AsyncGenerator<Task, void, unknown>;
88
+ /**
89
+ * Get a single task by ID
90
+ */
91
+ get(projectId: string, taskId: string): Promise<Task>;
92
+ /**
93
+ * List all tasks across all projects
94
+ * Note: This fetches all projects first, then tasks for each
95
+ */
96
+ listAllAcrossProjects(options?: AutoPaginateOptions): Promise<Task[]>;
97
+ _getProjectsRef: () => {
98
+ /**
99
+ * List projects with pagination
100
+ */
101
+ list(params?: ListParams): Promise<PaginatedResponse<Project>>;
102
+ /**
103
+ * Get all projects with auto-pagination
104
+ */
105
+ listAll(options?: AutoPaginateOptions): Promise<Project[]>;
106
+ /**
107
+ * Iterate over all projects with auto-pagination
108
+ */
109
+ iterate(options?: AutoPaginateOptions): AsyncGenerator<Project, void, unknown>;
110
+ /**
111
+ * Get a single project by ID
112
+ */
113
+ get(projectId: string): Promise<Project>;
114
+ };
115
+ };
116
+ /**
117
+ * Time Logs API
118
+ */
119
+ timelogs: {
120
+ /**
121
+ * List time logs for a project
122
+ */
123
+ list(projectId: string, params: TimeLogParams): Promise<PaginatedResponse<TimeLog>>;
124
+ /**
125
+ * Get all time logs for a project with auto-pagination
126
+ */
127
+ listAll(projectId: string, params: Omit<TimeLogParams, "index" | "range">, options?: AutoPaginateOptions): Promise<TimeLog[]>;
128
+ /**
129
+ * Iterate over all time logs for a project with auto-pagination
130
+ */
131
+ iterate(projectId: string, params: Omit<TimeLogParams, "index" | "range">, options?: AutoPaginateOptions): AsyncGenerator<TimeLog, void, unknown>;
132
+ /**
133
+ * List all time logs across all projects
134
+ */
135
+ listAllAcrossProjects(params: Omit<TimeLogParams, "index" | "range">, options?: AutoPaginateOptions): Promise<TimeLog[]>;
136
+ _getProjectsRef: () => {
137
+ /**
138
+ * List projects with pagination
139
+ */
140
+ list(params?: ListParams): Promise<PaginatedResponse<Project>>;
141
+ /**
142
+ * Get all projects with auto-pagination
143
+ */
144
+ listAll(options?: AutoPaginateOptions): Promise<Project[]>;
145
+ /**
146
+ * Iterate over all projects with auto-pagination
147
+ */
148
+ iterate(options?: AutoPaginateOptions): AsyncGenerator<Project, void, unknown>;
149
+ /**
150
+ * Get a single project by ID
151
+ */
152
+ get(projectId: string): Promise<Project>;
153
+ };
154
+ };
155
+ /**
156
+ * Users API
157
+ */
158
+ users: {
159
+ /**
160
+ * List all users in the portal
161
+ */
162
+ list(params?: ListParams): Promise<PaginatedResponse<User>>;
163
+ /**
164
+ * Get all users with auto-pagination
165
+ */
166
+ listAll(options?: AutoPaginateOptions): Promise<User[]>;
167
+ /**
168
+ * Iterate over all users with auto-pagination
169
+ */
170
+ iterate(options?: AutoPaginateOptions): AsyncGenerator<User, void, unknown>;
171
+ /**
172
+ * Get a single user by ID
173
+ */
174
+ get(userId: string): Promise<User>;
175
+ /**
176
+ * List users for a specific project
177
+ */
178
+ listForProject(projectId: string, params?: ListParams): Promise<PaginatedResponse<User>>;
179
+ };
180
+ /**
181
+ * Get the underlying token manager for advanced use cases
182
+ */
183
+ getTokenManager: () => TokenManager;
184
+ /**
185
+ * Get the underlying rate limiter for monitoring
186
+ */
187
+ getRateLimiter: () => Bottleneck;
188
+ };
189
+ /**
190
+ * Type for the Zoho Projects client
191
+ */
192
+ export type ZohoProjectsClient = ReturnType<typeof createZohoProjectsClient>;
193
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}