@panoptic-it-solutions/zoho-projects-client 0.2.1 → 0.2.3
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 +235 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,46 @@ TypeScript client for Zoho Projects V3 API with OAuth 2.0 and rate limiting.
|
|
|
8
8
|
npm install @panoptic-it-solutions/zoho-projects-client
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## AI Agent Setup (Claude Code)
|
|
12
|
+
|
|
13
|
+
For projects using Claude Code or other AI coding assistants, run the init command to set up helpful slash commands and documentation:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @panoptic-it-solutions/zoho-projects-client init
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### What it sets up
|
|
20
|
+
|
|
21
|
+
| File/Directory | Description |
|
|
22
|
+
|----------------|-------------|
|
|
23
|
+
| `.claude/commands/zoho-projects.md` | Full API reference with all namespaces and methods |
|
|
24
|
+
| `.claude/commands/zoho-auth.md` | OAuth 2.0 setup guide |
|
|
25
|
+
| `.claude/commands/zoho-examples.md` | Common usage patterns and examples |
|
|
26
|
+
| `CLAUDE.md` | Project context file for AI assistants |
|
|
27
|
+
|
|
28
|
+
### Available Slash Commands
|
|
29
|
+
|
|
30
|
+
After setup, use these commands in Claude Code:
|
|
31
|
+
|
|
32
|
+
- `/zoho-projects` - Complete API reference
|
|
33
|
+
- `/zoho-auth` - OAuth authentication setup guide
|
|
34
|
+
- `/zoho-examples` - Code examples and patterns
|
|
35
|
+
|
|
36
|
+
### Options
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Include type definitions for enhanced AI visibility
|
|
40
|
+
npx @panoptic-it-solutions/zoho-projects-client init --with-types
|
|
41
|
+
|
|
42
|
+
# Skip npm install (if already installed)
|
|
43
|
+
npx @panoptic-it-solutions/zoho-projects-client init --skip-install
|
|
44
|
+
|
|
45
|
+
# Show help
|
|
46
|
+
npx @panoptic-it-solutions/zoho-projects-client init --help
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The `--with-types` option copies TypeScript definitions to `.ai-types/` for AI assistants that benefit from having type information in the project.
|
|
50
|
+
|
|
11
51
|
## Quick Start
|
|
12
52
|
|
|
13
53
|
```typescript
|
|
@@ -48,7 +88,7 @@ Zoho requires OAuth 2.0 with a refresh token. Here's how to get one:
|
|
|
48
88
|
1. In API Console, select your client → **Generate Code** → **Self Client**
|
|
49
89
|
2. Enter scope:
|
|
50
90
|
```
|
|
51
|
-
ZohoProjects.projects.
|
|
91
|
+
ZohoProjects.projects.ALL,ZohoProjects.tasks.ALL,ZohoProjects.timesheets.ALL,ZohoProjects.users.ALL,ZohoProjects.portals.ALL,ZohoProjects.bugs.ALL,ZohoProjects.events.ALL,ZohoProjects.forums.ALL,ZohoProjects.documents.ALL
|
|
52
92
|
```
|
|
53
93
|
3. Click **Create** and copy the authorization code
|
|
54
94
|
4. Exchange it for a refresh token (within 2 minutes):
|
|
@@ -94,6 +134,55 @@ const client = createZohoProjectsClient({
|
|
|
94
134
|
| IN | `https://projectsapi.zoho.in` | `https://accounts.zoho.in` |
|
|
95
135
|
| AU | `https://projectsapi.zoho.com.au` | `https://accounts.zoho.com.au` |
|
|
96
136
|
|
|
137
|
+
## Available APIs
|
|
138
|
+
|
|
139
|
+
The client provides access to 26 API namespaces:
|
|
140
|
+
|
|
141
|
+
### Portal-Level APIs (no projectId required)
|
|
142
|
+
|
|
143
|
+
| Namespace | Description |
|
|
144
|
+
|-----------|-------------|
|
|
145
|
+
| `projects` | Project management |
|
|
146
|
+
| `users` | Portal users |
|
|
147
|
+
| `tags` | Tags/labels |
|
|
148
|
+
| `roles` | User roles |
|
|
149
|
+
| `profiles` | Permission profiles |
|
|
150
|
+
| `clients` | Client companies |
|
|
151
|
+
| `contacts` | Client contacts |
|
|
152
|
+
| `groups` | Project groups |
|
|
153
|
+
| `leaves` | Leave requests |
|
|
154
|
+
| `teams` | Team management |
|
|
155
|
+
| `portals` | Portal information |
|
|
156
|
+
| `modules` | Portal modules |
|
|
157
|
+
| `dashboards` | Dashboards & widgets |
|
|
158
|
+
| `reports` | Report execution |
|
|
159
|
+
| `search` | Global search |
|
|
160
|
+
| `trash` | Deleted items |
|
|
161
|
+
|
|
162
|
+
### Project-Scoped APIs (require projectId)
|
|
163
|
+
|
|
164
|
+
| Namespace | Description |
|
|
165
|
+
|-----------|-------------|
|
|
166
|
+
| `tasks` | Task management |
|
|
167
|
+
| `tasklists` | Task list management |
|
|
168
|
+
| `phases` | Project phases/milestones |
|
|
169
|
+
| `issues` | Bug/issue tracking |
|
|
170
|
+
| `forums` | Discussion forums |
|
|
171
|
+
| `events` | Calendar events |
|
|
172
|
+
| `timelogs` | Time tracking |
|
|
173
|
+
| `timers` | Active timers |
|
|
174
|
+
| `attachments` | File attachments |
|
|
175
|
+
| `documents` | Project documents |
|
|
176
|
+
| `blueprints` | Workflow blueprints |
|
|
177
|
+
| `customviews` | Custom views |
|
|
178
|
+
|
|
179
|
+
### Polymorphic APIs
|
|
180
|
+
|
|
181
|
+
| Namespace | Description |
|
|
182
|
+
|-----------|-------------|
|
|
183
|
+
| `comments` | Comments on tasks, issues, forums |
|
|
184
|
+
| `followers` | Followers on tasks, issues, forums |
|
|
185
|
+
|
|
97
186
|
## API Reference
|
|
98
187
|
|
|
99
188
|
### Projects
|
|
@@ -102,16 +191,19 @@ const client = createZohoProjectsClient({
|
|
|
102
191
|
// List with pagination
|
|
103
192
|
const { data, pageInfo } = await client.projects.list({ index: 0, range: 100 });
|
|
104
193
|
|
|
105
|
-
// Get all projects
|
|
194
|
+
// Get all projects (auto-pagination)
|
|
106
195
|
const projects = await client.projects.listAll();
|
|
107
196
|
|
|
108
|
-
//
|
|
109
|
-
const project = await client.projects.get("project_id");
|
|
110
|
-
|
|
111
|
-
// Iterate with auto-pagination
|
|
197
|
+
// Iterate (memory-efficient)
|
|
112
198
|
for await (const project of client.projects.iterate()) {
|
|
113
199
|
console.log(project.name);
|
|
114
200
|
}
|
|
201
|
+
|
|
202
|
+
// CRUD operations
|
|
203
|
+
const project = await client.projects.get("project_id");
|
|
204
|
+
const newProject = await client.projects.create({ name: "My Project" });
|
|
205
|
+
await client.projects.update("project_id", { name: "Updated Name" });
|
|
206
|
+
await client.projects.delete("project_id");
|
|
115
207
|
```
|
|
116
208
|
|
|
117
209
|
### Tasks
|
|
@@ -123,11 +215,14 @@ const { data } = await client.tasks.list("project_id");
|
|
|
123
215
|
// Get all tasks for a project
|
|
124
216
|
const tasks = await client.tasks.listAll("project_id");
|
|
125
217
|
|
|
126
|
-
// Get single task
|
|
127
|
-
const task = await client.tasks.get("project_id", "task_id");
|
|
128
|
-
|
|
129
218
|
// Get all tasks across all projects
|
|
130
219
|
const allTasks = await client.tasks.listAllAcrossProjects();
|
|
220
|
+
|
|
221
|
+
// CRUD operations
|
|
222
|
+
const task = await client.tasks.get("project_id", "task_id");
|
|
223
|
+
await client.tasks.create("project_id", { name: "New Task", tasklist_id: "list_id" });
|
|
224
|
+
await client.tasks.update("project_id", "task_id", { status: "completed" });
|
|
225
|
+
await client.tasks.delete("project_id", "task_id");
|
|
131
226
|
```
|
|
132
227
|
|
|
133
228
|
### Time Logs
|
|
@@ -139,35 +234,149 @@ Time logs require specific parameters:
|
|
|
139
234
|
const { data } = await client.timelogs.list("project_id", {
|
|
140
235
|
users_list: "all", // "all" or comma-separated user IDs
|
|
141
236
|
view_type: "month", // "day", "week", "month", or "custom_date"
|
|
142
|
-
date: "
|
|
237
|
+
date: "01-15-2025", // MM-DD-YYYY format
|
|
143
238
|
bill_status: "All", // "All", "Billable", or "Non Billable"
|
|
144
239
|
component_type: "task", // "task", "bug", or "general"
|
|
145
240
|
});
|
|
146
241
|
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
bill_status: "
|
|
153
|
-
|
|
242
|
+
// Create time logs
|
|
243
|
+
await client.timelogs.createForTask("project_id", {
|
|
244
|
+
task_id: "task_id",
|
|
245
|
+
date: "01-15-2025",
|
|
246
|
+
hours: "2",
|
|
247
|
+
bill_status: "Billable",
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
await client.timelogs.createForBug("project_id", {
|
|
251
|
+
bug_id: "bug_id",
|
|
252
|
+
date: "01-15-2025",
|
|
253
|
+
hours: "1",
|
|
254
|
+
bill_status: "Non Billable",
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
await client.timelogs.createGeneral("project_id", {
|
|
258
|
+
name: "Meeting",
|
|
259
|
+
date: "01-15-2025",
|
|
260
|
+
hours: "1",
|
|
261
|
+
bill_status: "Non Billable",
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Issues (Bugs)
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const { data } = await client.issues.list("project_id");
|
|
269
|
+
const issue = await client.issues.get("project_id", "issue_id");
|
|
270
|
+
await client.issues.create("project_id", { title: "Bug report" });
|
|
271
|
+
await client.issues.update("project_id", "issue_id", { status: "fixed" });
|
|
272
|
+
await client.issues.delete("project_id", "issue_id");
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Comments (Polymorphic)
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Comments on tasks
|
|
279
|
+
const taskComments = client.comments.forTask("project_id", "task_id");
|
|
280
|
+
const { data } = await taskComments.list();
|
|
281
|
+
await taskComments.create({ content: "Great work!" });
|
|
282
|
+
|
|
283
|
+
// Comments on issues
|
|
284
|
+
const issueComments = client.comments.forIssue("project_id", "issue_id");
|
|
285
|
+
await issueComments.list();
|
|
286
|
+
|
|
287
|
+
// Comments on forums
|
|
288
|
+
const forumComments = client.comments.forForum("project_id", "forum_id");
|
|
289
|
+
await forumComments.list();
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Followers (Polymorphic)
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// Followers on tasks
|
|
296
|
+
const taskFollowers = client.followers.forTask("project_id", "task_id");
|
|
297
|
+
const { data } = await taskFollowers.list();
|
|
298
|
+
await taskFollowers.add({ user_ids: ["user_1", "user_2"] });
|
|
299
|
+
await taskFollowers.remove("user_id");
|
|
300
|
+
|
|
301
|
+
// Followers on issues
|
|
302
|
+
const issueFollowers = client.followers.forIssue("project_id", "issue_id");
|
|
303
|
+
await issueFollowers.list();
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Search
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// Global search
|
|
310
|
+
const results = await client.search.query({ search_term: "keyword" });
|
|
311
|
+
|
|
312
|
+
// Search with filters
|
|
313
|
+
const taskResults = await client.search.query({
|
|
314
|
+
search_term: "keyword",
|
|
315
|
+
entity_type: "task",
|
|
154
316
|
});
|
|
317
|
+
|
|
318
|
+
// Convenience methods
|
|
319
|
+
await client.search.tasks("keyword");
|
|
320
|
+
await client.search.issues("keyword");
|
|
321
|
+
await client.search.projects("keyword");
|
|
322
|
+
|
|
323
|
+
// Search within a project
|
|
324
|
+
await client.search.inProject("project_id", { search_term: "keyword" });
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Trash
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
// List deleted items
|
|
331
|
+
const { data } = await client.trash.list();
|
|
332
|
+
const projectTrash = await client.trash.list({ entity_type: "task" });
|
|
333
|
+
|
|
334
|
+
// Restore from trash
|
|
335
|
+
await client.trash.restore("task", "item_id");
|
|
336
|
+
|
|
337
|
+
// Permanently delete
|
|
338
|
+
await client.trash.permanentDelete("task", "item_id");
|
|
339
|
+
|
|
340
|
+
// Empty trash
|
|
341
|
+
await client.trash.empty(); // All items
|
|
342
|
+
await client.trash.empty("task"); // Only tasks
|
|
155
343
|
```
|
|
156
344
|
|
|
157
|
-
###
|
|
345
|
+
### Timers
|
|
158
346
|
|
|
159
347
|
```typescript
|
|
160
|
-
//
|
|
161
|
-
const
|
|
348
|
+
// Get active timer for current user
|
|
349
|
+
const timer = await client.timers.getActive("project_id");
|
|
350
|
+
|
|
351
|
+
// Start/stop timer on a task
|
|
352
|
+
await client.timers.startForTask("project_id", "task_id");
|
|
353
|
+
await client.timers.stop("project_id");
|
|
354
|
+
|
|
355
|
+
// Start/stop timer on a bug
|
|
356
|
+
await client.timers.startForBug("project_id", "bug_id");
|
|
357
|
+
```
|
|
162
358
|
|
|
163
|
-
|
|
164
|
-
const users = await client.users.listAll();
|
|
359
|
+
### Teams
|
|
165
360
|
|
|
166
|
-
|
|
167
|
-
const
|
|
361
|
+
```typescript
|
|
362
|
+
const { data } = await client.teams.list();
|
|
363
|
+
const team = await client.teams.get("team_id");
|
|
364
|
+
await client.teams.create({ name: "Engineering" });
|
|
365
|
+
await client.teams.addMembers("team_id", { user_ids: ["user_1", "user_2"] });
|
|
366
|
+
await client.teams.removeMember("team_id", "user_id");
|
|
367
|
+
```
|
|
168
368
|
|
|
169
|
-
|
|
170
|
-
|
|
369
|
+
### Dashboards & Widgets
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
// Dashboards
|
|
373
|
+
const { data } = await client.dashboards.list();
|
|
374
|
+
const dashboard = await client.dashboards.get("dashboard_id");
|
|
375
|
+
|
|
376
|
+
// Widgets within a dashboard
|
|
377
|
+
const widgets = client.dashboards.widgets("dashboard_id");
|
|
378
|
+
const { data: widgetList } = await widgets.list();
|
|
379
|
+
await widgets.create({ name: "Task Chart", type: "chart" });
|
|
171
380
|
```
|
|
172
381
|
|
|
173
382
|
## Rate Limiting
|
package/package.json
CHANGED