@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.
- package/README.md +231 -0
- package/dist/auth/token-manager.d.ts +59 -0
- package/dist/auth/token-manager.d.ts.map +1 -0
- package/dist/auth/token-manager.js +120 -0
- package/dist/auth/token-manager.js.map +1 -0
- package/dist/client.d.ts +193 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +357 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +61 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +113 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/types/common.d.ts +173 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +56 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/projects.d.ts +3671 -0
- package/dist/types/projects.d.ts.map +1 -0
- package/dist/types/projects.js +94 -0
- package/dist/types/projects.js.map +1 -0
- package/dist/types/tasks.d.ts +2612 -0
- package/dist/types/tasks.d.ts.map +1 -0
- package/dist/types/tasks.js +127 -0
- package/dist/types/tasks.js.map +1 -0
- package/dist/types/timelogs.d.ts +13623 -0
- package/dist/types/timelogs.d.ts.map +1 -0
- package/dist/types/timelogs.js +115 -0
- package/dist/types/timelogs.js.map +1 -0
- package/dist/types/users.d.ts +695 -0
- package/dist/types/users.d.ts.map +1 -0
- package/dist/types/users.js +65 -0
- package/dist/types/users.js.map +1 -0
- package/dist/utils/pagination.d.ts +59 -0
- package/dist/utils/pagination.d.ts.map +1 -0
- package/dist/utils/pagination.js +84 -0
- package/dist/utils/pagination.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +33 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +92 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- 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":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -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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"}
|