@devpad/cli 1.0.1
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/dist/index.d.ts +2 -0
- package/dist/index.js +531 -0
- package/package.json +62 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { ApiClient, getTool } from "@devpad/api";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
import { Table } from "console-table-printer";
|
|
7
|
+
// Helper to get API client
|
|
8
|
+
function getApiClient() {
|
|
9
|
+
const apiKey = process.env.DEVPAD_API_KEY || Bun.env.DEVPAD_API_KEY;
|
|
10
|
+
const baseUrl = process.env.DEVPAD_BASE_URL || "https://devpad.tools/api/v0";
|
|
11
|
+
if (!apiKey) {
|
|
12
|
+
console.error(chalk.red("Error: DEVPAD_API_KEY environment variable is required"));
|
|
13
|
+
console.error(chalk.yellow("Get your API key from https://devpad.tools/account"));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
return new ApiClient({
|
|
17
|
+
api_key: apiKey,
|
|
18
|
+
base_url: baseUrl,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
// Helper to handle errors
|
|
22
|
+
function handleError(error) {
|
|
23
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
24
|
+
console.error(chalk.red(`Error: ${message}`));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
// Helper to format output
|
|
28
|
+
function formatOutput(data, format = "json") {
|
|
29
|
+
if (format === "json") {
|
|
30
|
+
console.log(JSON.stringify(data, null, 2));
|
|
31
|
+
}
|
|
32
|
+
else if (format === "table" && Array.isArray(data)) {
|
|
33
|
+
const table = new Table();
|
|
34
|
+
data.forEach(item => table.addRow(item));
|
|
35
|
+
table.printTable();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
console.log(data);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const program = new Command();
|
|
42
|
+
program.name("devpad").description("CLI for devpad project and task management").version("0.1.0");
|
|
43
|
+
// Projects command group
|
|
44
|
+
const projects = program.command("projects").description("Manage projects");
|
|
45
|
+
projects
|
|
46
|
+
.command("list")
|
|
47
|
+
.description("List all projects")
|
|
48
|
+
.option("--private", "Include private projects", true)
|
|
49
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
50
|
+
.action(async (options) => {
|
|
51
|
+
const spinner = ora("Fetching projects...").start();
|
|
52
|
+
try {
|
|
53
|
+
const tool = getTool("devpad_projects_list");
|
|
54
|
+
if (!tool)
|
|
55
|
+
throw new Error("Tool not found");
|
|
56
|
+
const client = getApiClient();
|
|
57
|
+
const result = await tool.execute(client, { private: options.private });
|
|
58
|
+
spinner.succeed("Projects fetched");
|
|
59
|
+
formatOutput(result, options.format);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
spinner.fail("Failed to fetch projects");
|
|
63
|
+
handleError(error);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
projects
|
|
67
|
+
.command("get <idOrName>")
|
|
68
|
+
.description("Get a project by ID or name")
|
|
69
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
70
|
+
.action(async (idOrName, options) => {
|
|
71
|
+
const spinner = ora("Fetching project...").start();
|
|
72
|
+
try {
|
|
73
|
+
const tool = getTool("devpad_projects_get");
|
|
74
|
+
if (!tool)
|
|
75
|
+
throw new Error("Tool not found");
|
|
76
|
+
const client = getApiClient();
|
|
77
|
+
// Try ID first, then name
|
|
78
|
+
const input = idOrName.includes("-") ? { id: idOrName } : { name: idOrName };
|
|
79
|
+
const result = await tool.execute(client, input);
|
|
80
|
+
spinner.succeed("Project fetched");
|
|
81
|
+
formatOutput(result, options.format);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
spinner.fail("Failed to fetch project");
|
|
85
|
+
handleError(error);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
projects
|
|
89
|
+
.command("create")
|
|
90
|
+
.description("Create a new project")
|
|
91
|
+
.requiredOption("-n, --name <name>", "Project name")
|
|
92
|
+
.option("-d, --description <description>", "Project description")
|
|
93
|
+
.option("--private", "Make project private", false)
|
|
94
|
+
.action(async (options) => {
|
|
95
|
+
const spinner = ora("Creating project...").start();
|
|
96
|
+
try {
|
|
97
|
+
const tool = getTool("devpad_projects_upsert");
|
|
98
|
+
if (!tool)
|
|
99
|
+
throw new Error("Tool not found");
|
|
100
|
+
const client = getApiClient();
|
|
101
|
+
const result = await tool.execute(client, {
|
|
102
|
+
name: options.name,
|
|
103
|
+
description: options.description,
|
|
104
|
+
private: options.private,
|
|
105
|
+
});
|
|
106
|
+
spinner.succeed(`Project "${result.name}" created`);
|
|
107
|
+
console.log(chalk.green(`ID: ${result.id}`));
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
spinner.fail("Failed to create project");
|
|
111
|
+
handleError(error);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
projects
|
|
115
|
+
.command("delete <id>")
|
|
116
|
+
.description("Delete a project")
|
|
117
|
+
.option("-y, --yes", "Skip confirmation", false)
|
|
118
|
+
.action(async (id, options) => {
|
|
119
|
+
if (!options.yes) {
|
|
120
|
+
console.log(chalk.yellow("Are you sure you want to delete this project? Use --yes to confirm"));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const spinner = ora("Deleting project...").start();
|
|
124
|
+
try {
|
|
125
|
+
const tool = getTool("devpad_projects_delete");
|
|
126
|
+
if (!tool)
|
|
127
|
+
throw new Error("Tool not found");
|
|
128
|
+
const client = getApiClient();
|
|
129
|
+
await tool.execute(client, { id });
|
|
130
|
+
spinner.succeed("Project deleted");
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
spinner.fail("Failed to delete project");
|
|
134
|
+
handleError(error);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
projects
|
|
138
|
+
.command("history <id>")
|
|
139
|
+
.description("Get project history")
|
|
140
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
141
|
+
.action(async (id, options) => {
|
|
142
|
+
const spinner = ora("Fetching project history...").start();
|
|
143
|
+
try {
|
|
144
|
+
const tool = getTool("devpad_projects_history");
|
|
145
|
+
if (!tool)
|
|
146
|
+
throw new Error("Tool not found");
|
|
147
|
+
const client = getApiClient();
|
|
148
|
+
const result = await tool.execute(client, { project_id: id });
|
|
149
|
+
spinner.succeed("Project history fetched");
|
|
150
|
+
formatOutput(result, options.format);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
spinner.fail("Failed to fetch project history");
|
|
154
|
+
handleError(error);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// Tasks command group
|
|
158
|
+
const tasks = program.command("tasks").description("Manage tasks");
|
|
159
|
+
tasks
|
|
160
|
+
.command("list")
|
|
161
|
+
.description("List tasks")
|
|
162
|
+
.option("-p, --project <id>", "Filter by project ID")
|
|
163
|
+
.option("-t, --tag <id>", "Filter by tag ID")
|
|
164
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
165
|
+
.action(async (options) => {
|
|
166
|
+
const spinner = ora("Fetching tasks...").start();
|
|
167
|
+
try {
|
|
168
|
+
const tool = getTool("devpad_tasks_list");
|
|
169
|
+
if (!tool)
|
|
170
|
+
throw new Error("Tool not found");
|
|
171
|
+
const client = getApiClient();
|
|
172
|
+
const result = await tool.execute(client, {
|
|
173
|
+
project_id: options.project,
|
|
174
|
+
tag_id: options.tag,
|
|
175
|
+
});
|
|
176
|
+
spinner.succeed("Tasks fetched");
|
|
177
|
+
formatOutput(result, options.format);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
spinner.fail("Failed to fetch tasks");
|
|
181
|
+
handleError(error);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
tasks
|
|
185
|
+
.command("get <id>")
|
|
186
|
+
.description("Get a task by ID")
|
|
187
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
188
|
+
.action(async (id, options) => {
|
|
189
|
+
const spinner = ora("Fetching task...").start();
|
|
190
|
+
try {
|
|
191
|
+
const tool = getTool("devpad_tasks_get");
|
|
192
|
+
if (!tool)
|
|
193
|
+
throw new Error("Tool not found");
|
|
194
|
+
const client = getApiClient();
|
|
195
|
+
const result = await tool.execute(client, { id });
|
|
196
|
+
spinner.succeed("Task fetched");
|
|
197
|
+
formatOutput(result, options.format);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
spinner.fail("Failed to fetch task");
|
|
201
|
+
handleError(error);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
tasks
|
|
205
|
+
.command("create")
|
|
206
|
+
.description("Create a new task")
|
|
207
|
+
.requiredOption("-t, --title <title>", "Task title")
|
|
208
|
+
.requiredOption("-p, --project <id>", "Project ID")
|
|
209
|
+
.option("-s, --summary <summary>", "Task summary")
|
|
210
|
+
.option("--priority <priority>", "Task priority (low|medium|high)", "medium")
|
|
211
|
+
.option("--status <status>", "Task status (todo|in_progress|done)", "todo")
|
|
212
|
+
.action(async (options) => {
|
|
213
|
+
const spinner = ora("Creating task...").start();
|
|
214
|
+
try {
|
|
215
|
+
const tool = getTool("devpad_tasks_upsert");
|
|
216
|
+
if (!tool)
|
|
217
|
+
throw new Error("Tool not found");
|
|
218
|
+
const client = getApiClient();
|
|
219
|
+
const result = await tool.execute(client, {
|
|
220
|
+
title: options.title,
|
|
221
|
+
project_id: options.project,
|
|
222
|
+
summary: options.summary,
|
|
223
|
+
priority: options.priority.toUpperCase(),
|
|
224
|
+
progress: options.status === "done" ? "DONE" : options.status === "in_progress" ? "IN_PROGRESS" : "TODO",
|
|
225
|
+
});
|
|
226
|
+
spinner.succeed(`Task "${result.title}" created`);
|
|
227
|
+
console.log(chalk.green(`ID: ${result.id}`));
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
spinner.fail("Failed to create task");
|
|
231
|
+
handleError(error);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
tasks
|
|
235
|
+
.command("done <id>")
|
|
236
|
+
.description("Mark a task as done")
|
|
237
|
+
.action(async (id) => {
|
|
238
|
+
const spinner = ora("Marking task as done...").start();
|
|
239
|
+
try {
|
|
240
|
+
const tool = getTool("devpad_tasks_upsert");
|
|
241
|
+
if (!tool)
|
|
242
|
+
throw new Error("Tool not found");
|
|
243
|
+
const client = getApiClient();
|
|
244
|
+
const result = await tool.execute(client, {
|
|
245
|
+
id,
|
|
246
|
+
progress: "DONE",
|
|
247
|
+
});
|
|
248
|
+
spinner.succeed(`Task "${result.title}" marked as done`);
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
spinner.fail("Failed to update task");
|
|
252
|
+
handleError(error);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
tasks
|
|
256
|
+
.command("todo <id>")
|
|
257
|
+
.description("Mark a task as todo")
|
|
258
|
+
.action(async (id) => {
|
|
259
|
+
const spinner = ora("Marking task as todo...").start();
|
|
260
|
+
try {
|
|
261
|
+
const tool = getTool("devpad_tasks_upsert");
|
|
262
|
+
if (!tool)
|
|
263
|
+
throw new Error("Tool not found");
|
|
264
|
+
const client = getApiClient();
|
|
265
|
+
const result = await tool.execute(client, {
|
|
266
|
+
id,
|
|
267
|
+
progress: "TODO",
|
|
268
|
+
});
|
|
269
|
+
spinner.succeed(`Task "${result.title}" marked as todo`);
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
spinner.fail("Failed to update task");
|
|
273
|
+
handleError(error);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
tasks
|
|
277
|
+
.command("delete <id>")
|
|
278
|
+
.description("Delete a task")
|
|
279
|
+
.option("-y, --yes", "Skip confirmation", false)
|
|
280
|
+
.action(async (id, options) => {
|
|
281
|
+
if (!options.yes) {
|
|
282
|
+
console.log(chalk.yellow("Are you sure you want to delete this task? Use --yes to confirm"));
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const spinner = ora("Deleting task...").start();
|
|
286
|
+
try {
|
|
287
|
+
const tool = getTool("devpad_tasks_delete");
|
|
288
|
+
if (!tool)
|
|
289
|
+
throw new Error("Tool not found");
|
|
290
|
+
const client = getApiClient();
|
|
291
|
+
await tool.execute(client, { id });
|
|
292
|
+
spinner.succeed("Task deleted");
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
spinner.fail("Failed to delete task");
|
|
296
|
+
handleError(error);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
tasks
|
|
300
|
+
.command("history <id>")
|
|
301
|
+
.description("Get task history")
|
|
302
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
303
|
+
.action(async (id, options) => {
|
|
304
|
+
const spinner = ora("Fetching task history...").start();
|
|
305
|
+
try {
|
|
306
|
+
const tool = getTool("devpad_tasks_history");
|
|
307
|
+
if (!tool)
|
|
308
|
+
throw new Error("Tool not found");
|
|
309
|
+
const client = getApiClient();
|
|
310
|
+
const result = await tool.execute(client, { task_id: id });
|
|
311
|
+
spinner.succeed("Task history fetched");
|
|
312
|
+
formatOutput(result, options.format);
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
spinner.fail("Failed to fetch task history");
|
|
316
|
+
handleError(error);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
// Milestones command group
|
|
320
|
+
const milestones = program.command("milestones").description("Manage milestones");
|
|
321
|
+
milestones
|
|
322
|
+
.command("list")
|
|
323
|
+
.description("List milestones")
|
|
324
|
+
.option("-p, --project <id>", "Filter by project ID")
|
|
325
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
326
|
+
.action(async (options) => {
|
|
327
|
+
const spinner = ora("Fetching milestones...").start();
|
|
328
|
+
try {
|
|
329
|
+
const tool = getTool("devpad_milestones_list");
|
|
330
|
+
if (!tool)
|
|
331
|
+
throw new Error("Tool not found");
|
|
332
|
+
const client = getApiClient();
|
|
333
|
+
const result = await tool.execute(client, {
|
|
334
|
+
project_id: options.project,
|
|
335
|
+
});
|
|
336
|
+
spinner.succeed("Milestones fetched");
|
|
337
|
+
formatOutput(result, options.format);
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
spinner.fail("Failed to fetch milestones");
|
|
341
|
+
handleError(error);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
milestones
|
|
345
|
+
.command("create")
|
|
346
|
+
.description("Create a new milestone")
|
|
347
|
+
.requiredOption("-n, --name <name>", "Milestone name")
|
|
348
|
+
.requiredOption("-p, --project <id>", "Project ID")
|
|
349
|
+
.option("-d, --description <description>", "Milestone description")
|
|
350
|
+
.option("--target-time <time>", "Target completion time")
|
|
351
|
+
.option("--target-version <version>", "Target version")
|
|
352
|
+
.action(async (options) => {
|
|
353
|
+
const spinner = ora("Creating milestone...").start();
|
|
354
|
+
try {
|
|
355
|
+
const tool = getTool("devpad_milestones_upsert");
|
|
356
|
+
if (!tool)
|
|
357
|
+
throw new Error("Tool not found");
|
|
358
|
+
const client = getApiClient();
|
|
359
|
+
const result = await tool.execute(client, {
|
|
360
|
+
name: options.name,
|
|
361
|
+
project_id: options.project,
|
|
362
|
+
description: options.description,
|
|
363
|
+
target_time: options.targetTime,
|
|
364
|
+
target_version: options.targetVersion,
|
|
365
|
+
});
|
|
366
|
+
spinner.succeed(`Milestone "${result.name}" created`);
|
|
367
|
+
console.log(chalk.green(`ID: ${result.id}`));
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
spinner.fail("Failed to create milestone");
|
|
371
|
+
handleError(error);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
// Goals command group
|
|
375
|
+
const goals = program.command("goals").description("Manage goals");
|
|
376
|
+
goals
|
|
377
|
+
.command("list")
|
|
378
|
+
.description("List goals")
|
|
379
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
380
|
+
.action(async (options) => {
|
|
381
|
+
const spinner = ora("Fetching goals...").start();
|
|
382
|
+
try {
|
|
383
|
+
const tool = getTool("devpad_goals_list");
|
|
384
|
+
if (!tool)
|
|
385
|
+
throw new Error("Tool not found");
|
|
386
|
+
const client = getApiClient();
|
|
387
|
+
const result = await tool.execute(client, {});
|
|
388
|
+
spinner.succeed("Goals fetched");
|
|
389
|
+
formatOutput(result, options.format);
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
spinner.fail("Failed to fetch goals");
|
|
393
|
+
handleError(error);
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
goals
|
|
397
|
+
.command("create")
|
|
398
|
+
.description("Create a new goal")
|
|
399
|
+
.requiredOption("-n, --name <name>", "Goal name")
|
|
400
|
+
.requiredOption("-m, --milestone <id>", "Milestone ID")
|
|
401
|
+
.option("-d, --description <description>", "Goal description")
|
|
402
|
+
.option("--target-time <time>", "Target completion time")
|
|
403
|
+
.action(async (options) => {
|
|
404
|
+
const spinner = ora("Creating goal...").start();
|
|
405
|
+
try {
|
|
406
|
+
const tool = getTool("devpad_goals_upsert");
|
|
407
|
+
if (!tool)
|
|
408
|
+
throw new Error("Tool not found");
|
|
409
|
+
const client = getApiClient();
|
|
410
|
+
const result = await tool.execute(client, {
|
|
411
|
+
name: options.name,
|
|
412
|
+
milestone_id: options.milestone,
|
|
413
|
+
description: options.description,
|
|
414
|
+
target_time: options.targetTime,
|
|
415
|
+
});
|
|
416
|
+
spinner.succeed(`Goal "${result.name}" created`);
|
|
417
|
+
console.log(chalk.green(`ID: ${result.id}`));
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
spinner.fail("Failed to create goal");
|
|
421
|
+
handleError(error);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
// Tags command group
|
|
425
|
+
const tags = program.command("tags").description("Manage tags");
|
|
426
|
+
tags.command("list")
|
|
427
|
+
.description("List tags")
|
|
428
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
429
|
+
.action(async (options) => {
|
|
430
|
+
const spinner = ora("Fetching tags...").start();
|
|
431
|
+
try {
|
|
432
|
+
const tool = getTool("devpad_tags_list");
|
|
433
|
+
if (!tool)
|
|
434
|
+
throw new Error("Tool not found");
|
|
435
|
+
const client = getApiClient();
|
|
436
|
+
const result = await tool.execute(client, {});
|
|
437
|
+
spinner.succeed("Tags fetched");
|
|
438
|
+
formatOutput(result, options.format);
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
spinner.fail("Failed to fetch tags");
|
|
442
|
+
handleError(error);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
// GitHub command group
|
|
446
|
+
const github = program.command("github").description("GitHub integration");
|
|
447
|
+
github
|
|
448
|
+
.command("repos")
|
|
449
|
+
.description("List GitHub repositories")
|
|
450
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
451
|
+
.action(async (options) => {
|
|
452
|
+
const spinner = ora("Fetching GitHub repositories...").start();
|
|
453
|
+
try {
|
|
454
|
+
const tool = getTool("devpad_github_repos");
|
|
455
|
+
if (!tool)
|
|
456
|
+
throw new Error("Tool not found");
|
|
457
|
+
const client = getApiClient();
|
|
458
|
+
const result = await tool.execute(client, {});
|
|
459
|
+
spinner.succeed("Repositories fetched");
|
|
460
|
+
formatOutput(result, options.format);
|
|
461
|
+
}
|
|
462
|
+
catch (error) {
|
|
463
|
+
spinner.fail("Failed to fetch repositories");
|
|
464
|
+
handleError(error);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
github
|
|
468
|
+
.command("branches <owner> <repo>")
|
|
469
|
+
.description("List branches for a GitHub repository")
|
|
470
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
471
|
+
.action(async (owner, repo, options) => {
|
|
472
|
+
const spinner = ora("Fetching branches...").start();
|
|
473
|
+
try {
|
|
474
|
+
const tool = getTool("devpad_github_branches");
|
|
475
|
+
if (!tool)
|
|
476
|
+
throw new Error("Tool not found");
|
|
477
|
+
const client = getApiClient();
|
|
478
|
+
const result = await tool.execute(client, { owner, repo });
|
|
479
|
+
spinner.succeed("Branches fetched");
|
|
480
|
+
formatOutput(result, options.format);
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
spinner.fail("Failed to fetch branches");
|
|
484
|
+
handleError(error);
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
// User command group
|
|
488
|
+
const user = program.command("user").description("User preferences and history");
|
|
489
|
+
user.command("history")
|
|
490
|
+
.description("Get user activity history")
|
|
491
|
+
.option("-f, --format <format>", "Output format (json|table)", "json")
|
|
492
|
+
.action(async (options) => {
|
|
493
|
+
const spinner = ora("Fetching user history...").start();
|
|
494
|
+
try {
|
|
495
|
+
const tool = getTool("devpad_user_history");
|
|
496
|
+
if (!tool)
|
|
497
|
+
throw new Error("Tool not found");
|
|
498
|
+
const client = getApiClient();
|
|
499
|
+
const result = await tool.execute(client, {});
|
|
500
|
+
spinner.succeed("User history fetched");
|
|
501
|
+
formatOutput(result, options.format);
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
spinner.fail("Failed to fetch user history");
|
|
505
|
+
handleError(error);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
user.command("preferences")
|
|
509
|
+
.description("Update user preferences")
|
|
510
|
+
.requiredOption("-u, --user-id <id>", "User ID")
|
|
511
|
+
.requiredOption("-v, --view <view>", "Task view preference (list|grid)")
|
|
512
|
+
.action(async (options) => {
|
|
513
|
+
const spinner = ora("Updating preferences...").start();
|
|
514
|
+
try {
|
|
515
|
+
const tool = getTool("devpad_user_preferences");
|
|
516
|
+
if (!tool)
|
|
517
|
+
throw new Error("Tool not found");
|
|
518
|
+
const client = getApiClient();
|
|
519
|
+
await tool.execute(client, {
|
|
520
|
+
id: options.userId,
|
|
521
|
+
task_view: options.view,
|
|
522
|
+
});
|
|
523
|
+
spinner.succeed("Preferences updated");
|
|
524
|
+
}
|
|
525
|
+
catch (error) {
|
|
526
|
+
spinner.fail("Failed to update preferences");
|
|
527
|
+
handleError(error);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
// Parse and execute
|
|
531
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@devpad/cli",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Command line interface for devpad project management",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"devpad": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "bunx tsc",
|
|
16
|
+
"test": "bun test",
|
|
17
|
+
"prepublishOnly": "bun run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"devpad",
|
|
21
|
+
"cli",
|
|
22
|
+
"command-line",
|
|
23
|
+
"project-management",
|
|
24
|
+
"task-management",
|
|
25
|
+
"todo"
|
|
26
|
+
],
|
|
27
|
+
"author": {
|
|
28
|
+
"name": "f0rbit",
|
|
29
|
+
"url": "https://github.com/f0rbit"
|
|
30
|
+
},
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://devpad.tools",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/f0rbit/devpad.git",
|
|
36
|
+
"directory": "packages/cli"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/f0rbit/devpad/issues"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public",
|
|
43
|
+
"registry": "https://registry.npmjs.org/"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@devpad/api": "^1.0.1",
|
|
47
|
+
"@devpad/schema": "workspace:*",
|
|
48
|
+
"commander": "^12.0.0",
|
|
49
|
+
"chalk": "^5.3.0",
|
|
50
|
+
"ora": "^8.0.1",
|
|
51
|
+
"console-table-printer": "^2.12.1",
|
|
52
|
+
"zod": "^3.22.4"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^20.11.24",
|
|
56
|
+
"bun-types": "latest",
|
|
57
|
+
"typescript": "^5.9.2"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=18.0.0"
|
|
61
|
+
}
|
|
62
|
+
}
|