@workdynamite/cli 1.0.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 +39 -0
- package/bin/workdynamite.js +3 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +62 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +99 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +24 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/pick.d.ts +3 -0
- package/dist/commands/pick.d.ts.map +1 -0
- package/dist/commands/pick.js +81 -0
- package/dist/commands/pick.js.map +1 -0
- package/dist/commands/projects.d.ts +3 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +119 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +80 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/tasks.d.ts +3 -0
- package/dist/commands/tasks.d.ts.map +1 -0
- package/dist/commands/tasks.js +102 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api.d.ts +70 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +71 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +20 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +55 -0
- package/dist/lib/config.js.map +1 -0
- package/package.json +47 -0
- package/src/commands/config.ts +69 -0
- package/src/commands/login.ts +116 -0
- package/src/commands/logout.ts +21 -0
- package/src/commands/pick.ts +80 -0
- package/src/commands/projects.ts +139 -0
- package/src/commands/status.ts +87 -0
- package/src/commands/tasks.ts +112 -0
- package/src/index.ts +50 -0
- package/src/lib/api.ts +128 -0
- package/src/lib/config.ts +61 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.tasksCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const ora_1 = __importDefault(require("ora"));
|
|
10
|
+
const api_js_1 = require("../lib/api.js");
|
|
11
|
+
const config_js_1 = require("../lib/config.js");
|
|
12
|
+
exports.tasksCommand = new commander_1.Command('tasks')
|
|
13
|
+
.description('List your assigned tasks')
|
|
14
|
+
.option('-p, --project <id>', 'Filter by project ID')
|
|
15
|
+
.option('-s, --state <state>', 'Filter by state (open, in_progress, done)')
|
|
16
|
+
.option('-l, --limit <number>', 'Maximum number of tasks', '20')
|
|
17
|
+
.action(async (options) => {
|
|
18
|
+
if (!(0, config_js_1.isAuthenticated)()) {
|
|
19
|
+
console.log(chalk_1.default.red('Not logged in. Run "workdynamite login" first.'));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const spinner = (0, ora_1.default)('Fetching tasks...').start();
|
|
23
|
+
const config = (0, config_js_1.getConfig)();
|
|
24
|
+
const projectId = options.project || config.default_project;
|
|
25
|
+
const { data, error } = await (0, api_js_1.getTasks)({
|
|
26
|
+
project: projectId,
|
|
27
|
+
state: options.state,
|
|
28
|
+
limit: parseInt(options.limit, 10),
|
|
29
|
+
});
|
|
30
|
+
if (error) {
|
|
31
|
+
spinner.fail(chalk_1.default.red(`Failed to fetch tasks: ${error}`));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
spinner.stop();
|
|
35
|
+
const tasks = data.tasks;
|
|
36
|
+
if (tasks.length === 0) {
|
|
37
|
+
console.log(chalk_1.default.yellow('\nNo tasks assigned to you.'));
|
|
38
|
+
console.log(chalk_1.default.dim('Create tasks in the web app to see them here.'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Group tasks by project
|
|
42
|
+
const tasksByProject = tasks.reduce((acc, task) => {
|
|
43
|
+
const project = task.project || 'No Project';
|
|
44
|
+
if (!acc[project])
|
|
45
|
+
acc[project] = [];
|
|
46
|
+
acc[project].push(task);
|
|
47
|
+
return acc;
|
|
48
|
+
}, {});
|
|
49
|
+
console.log(chalk_1.default.bold('\nš Your Assigned Tasks\n'));
|
|
50
|
+
for (const [project, projectTasks] of Object.entries(tasksByProject)) {
|
|
51
|
+
console.log(chalk_1.default.bold.blue(`${project}`));
|
|
52
|
+
console.log(chalk_1.default.dim('ā'.repeat(50)));
|
|
53
|
+
for (const task of projectTasks) {
|
|
54
|
+
const stateColor = getStateColor(task.state);
|
|
55
|
+
const priorityBadge = getPriorityBadge(task.priority);
|
|
56
|
+
console.log(` ${chalk_1.default.dim('#')}${chalk_1.default.bold(String(task.number).padEnd(5))} ` +
|
|
57
|
+
`${priorityBadge} ` +
|
|
58
|
+
`${task.title.substring(0, 40)}${task.title.length > 40 ? '...' : ''} ` +
|
|
59
|
+
`${stateColor(task.state)}`);
|
|
60
|
+
}
|
|
61
|
+
console.log('');
|
|
62
|
+
}
|
|
63
|
+
console.log(chalk_1.default.dim('ā'.repeat(50)));
|
|
64
|
+
console.log(chalk_1.default.dim(`Showing ${tasks.length} task(s)`));
|
|
65
|
+
console.log(chalk_1.default.dim('\nCommands:'));
|
|
66
|
+
console.log(chalk_1.default.dim(' workdynamite pick <number> Copy task ref to clipboard'));
|
|
67
|
+
console.log(chalk_1.default.dim(' workdynamite pick <number> -w Copy as WIP'));
|
|
68
|
+
console.log('');
|
|
69
|
+
});
|
|
70
|
+
function getStateColor(state) {
|
|
71
|
+
switch (state.toLowerCase()) {
|
|
72
|
+
case 'open':
|
|
73
|
+
case 'todo':
|
|
74
|
+
return chalk_1.default.gray;
|
|
75
|
+
case 'in_progress':
|
|
76
|
+
case 'in progress':
|
|
77
|
+
return chalk_1.default.yellow;
|
|
78
|
+
case 'done':
|
|
79
|
+
case 'completed':
|
|
80
|
+
return chalk_1.default.green;
|
|
81
|
+
case 'blocked':
|
|
82
|
+
return chalk_1.default.red;
|
|
83
|
+
default:
|
|
84
|
+
return chalk_1.default.white;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function getPriorityBadge(priority) {
|
|
88
|
+
switch (priority?.toLowerCase()) {
|
|
89
|
+
case 'critical':
|
|
90
|
+
case 'highest':
|
|
91
|
+
return chalk_1.default.bgRed.white(' !! ');
|
|
92
|
+
case 'high':
|
|
93
|
+
return chalk_1.default.red('[H]');
|
|
94
|
+
case 'medium':
|
|
95
|
+
return chalk_1.default.yellow('[M]');
|
|
96
|
+
case 'low':
|
|
97
|
+
return chalk_1.default.green('[L]');
|
|
98
|
+
default:
|
|
99
|
+
return chalk_1.default.dim('[ā]');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/commands/tasks.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const commander_1 = require("commander");
|
|
4
|
+
const login_js_1 = require("./commands/login.js");
|
|
5
|
+
const logout_js_1 = require("./commands/logout.js");
|
|
6
|
+
const tasks_js_1 = require("./commands/tasks.js");
|
|
7
|
+
const pick_js_1 = require("./commands/pick.js");
|
|
8
|
+
const projects_js_1 = require("./commands/projects.js");
|
|
9
|
+
const status_js_1 = require("./commands/status.js");
|
|
10
|
+
const config_js_1 = require("./commands/config.js");
|
|
11
|
+
const program = new commander_1.Command();
|
|
12
|
+
program
|
|
13
|
+
.name('workdynamite')
|
|
14
|
+
.description('WorkDynamite CLI - Manage tasks from your terminal')
|
|
15
|
+
.version('1.0.0');
|
|
16
|
+
// Register commands
|
|
17
|
+
program.addCommand(login_js_1.loginCommand);
|
|
18
|
+
program.addCommand(logout_js_1.logoutCommand);
|
|
19
|
+
program.addCommand(tasks_js_1.tasksCommand);
|
|
20
|
+
program.addCommand(pick_js_1.pickCommand);
|
|
21
|
+
program.addCommand(projects_js_1.projectsCommand);
|
|
22
|
+
program.addCommand(status_js_1.statusCommand);
|
|
23
|
+
program.addCommand(config_js_1.configCommand);
|
|
24
|
+
// Aliases
|
|
25
|
+
program
|
|
26
|
+
.command('ls')
|
|
27
|
+
.description('Alias for "tasks" - list your assigned tasks')
|
|
28
|
+
.action(async () => {
|
|
29
|
+
await tasks_js_1.tasksCommand.parseAsync(['tasks'], { from: 'user' });
|
|
30
|
+
});
|
|
31
|
+
program
|
|
32
|
+
.command('p <number>')
|
|
33
|
+
.description('Alias for "pick" - copy task reference to clipboard')
|
|
34
|
+
.option('-w, --wip', 'Use WIP prefix')
|
|
35
|
+
.option('-f, --fixes', 'Use Fixes prefix (default)')
|
|
36
|
+
.option('-c, --closes', 'Use Closes prefix')
|
|
37
|
+
.option('-r, --refs', 'Use Refs prefix')
|
|
38
|
+
.action(async (number, options) => {
|
|
39
|
+
const args = ['pick', number];
|
|
40
|
+
if (options.wip)
|
|
41
|
+
args.push('--wip');
|
|
42
|
+
if (options.fixes)
|
|
43
|
+
args.push('--fixes');
|
|
44
|
+
if (options.closes)
|
|
45
|
+
args.push('--closes');
|
|
46
|
+
if (options.refs)
|
|
47
|
+
args.push('--refs');
|
|
48
|
+
await pick_js_1.pickCommand.parseAsync(args, { from: 'user' });
|
|
49
|
+
});
|
|
50
|
+
program.parse();
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,yCAAoC;AACpC,kDAAmD;AACnD,oDAAqD;AACrD,kDAAmD;AACnD,gDAAiD;AACjD,wDAAyD;AACzD,oDAAqD;AACrD,oDAAqD;AAErD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,cAAc,CAAC;KACpB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,uBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,yBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,uBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,qBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,6BAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,yBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,yBAAa,CAAC,CAAC;AAElC,UAAU;AACV,OAAO;KACJ,OAAO,CAAC,IAAI,CAAC;KACb,WAAW,CAAC,8CAA8C,CAAC;KAC3D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,uBAAY,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC;KACrC,MAAM,CAAC,aAAa,EAAE,4BAA4B,CAAC;KACnD,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAAC;KAC3C,MAAM,CAAC,YAAY,EAAE,iBAAiB,CAAC;KACvC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;IAChC,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,IAAI,OAAO,CAAC,GAAG;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,OAAO,CAAC,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,OAAO,CAAC,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAI,OAAO,CAAC,IAAI;QAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,qBAAW,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
interface ApiResponse<T = any> {
|
|
2
|
+
data?: T;
|
|
3
|
+
error?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function initLogin(): Promise<ApiResponse<{
|
|
6
|
+
device_code: string;
|
|
7
|
+
user_code: string;
|
|
8
|
+
verification_uri: string;
|
|
9
|
+
verification_uri_complete: string;
|
|
10
|
+
expires_in: number;
|
|
11
|
+
interval: number;
|
|
12
|
+
}>>;
|
|
13
|
+
export declare function pollLogin(deviceCode: string): Promise<ApiResponse<{
|
|
14
|
+
access_token: string;
|
|
15
|
+
token_type: string;
|
|
16
|
+
user: {
|
|
17
|
+
id: string;
|
|
18
|
+
email: string;
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
message?: string;
|
|
22
|
+
}>>;
|
|
23
|
+
export declare function getMe(): Promise<ApiResponse<{
|
|
24
|
+
user: {
|
|
25
|
+
id: string;
|
|
26
|
+
email: string;
|
|
27
|
+
name: string;
|
|
28
|
+
avatar_url?: string;
|
|
29
|
+
};
|
|
30
|
+
projects_count: number;
|
|
31
|
+
}>>;
|
|
32
|
+
export declare function getProjects(): Promise<ApiResponse<{
|
|
33
|
+
projects: Array<{
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
status: string;
|
|
38
|
+
progress: number;
|
|
39
|
+
role: string;
|
|
40
|
+
}>;
|
|
41
|
+
}>>;
|
|
42
|
+
export interface Task {
|
|
43
|
+
id: string;
|
|
44
|
+
number: number;
|
|
45
|
+
title: string;
|
|
46
|
+
state: string;
|
|
47
|
+
priority: string;
|
|
48
|
+
story_points?: number;
|
|
49
|
+
due_date?: string;
|
|
50
|
+
project: string;
|
|
51
|
+
project_id: string;
|
|
52
|
+
refs: {
|
|
53
|
+
wip: string;
|
|
54
|
+
fixes: string;
|
|
55
|
+
closes: string;
|
|
56
|
+
refs: string;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export declare function getTasks(options?: {
|
|
60
|
+
project?: string;
|
|
61
|
+
state?: string;
|
|
62
|
+
limit?: number;
|
|
63
|
+
}): Promise<ApiResponse<{
|
|
64
|
+
tasks: Task[];
|
|
65
|
+
}>>;
|
|
66
|
+
export declare function getTask(taskId: string): Promise<ApiResponse<{
|
|
67
|
+
task: Task;
|
|
68
|
+
}>>;
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW,CAAC,CAAC,GAAG,GAAG;IAC3B,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA0CD,wBAAsB,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,yBAAyB,EAAE,MAAM,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC,CAKF;AAED,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC,CAKF;AAED,wBAAsB,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IACjD,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC,CAEF;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IACvD,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ,CAAC,CAAC,CAEF;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QACJ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,wBAAsB,QAAQ,CAAC,OAAO,GAAE;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,GAAG,OAAO,CAAC,WAAW,CAAC;IAAE,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CAAC,CAQ/C;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC,CAElF"}
|
package/dist/lib/api.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initLogin = initLogin;
|
|
4
|
+
exports.pollLogin = pollLogin;
|
|
5
|
+
exports.getMe = getMe;
|
|
6
|
+
exports.getProjects = getProjects;
|
|
7
|
+
exports.getTasks = getTasks;
|
|
8
|
+
exports.getTask = getTask;
|
|
9
|
+
const config_js_1 = require("./config.js");
|
|
10
|
+
async function request(endpoint, options = {}) {
|
|
11
|
+
const token = (0, config_js_1.getToken)();
|
|
12
|
+
const apiUrl = (0, config_js_1.getApiUrl)();
|
|
13
|
+
if (!token && !endpoint.startsWith('login/')) {
|
|
14
|
+
return { error: 'Not authenticated. Run "workdynamite login" first.' };
|
|
15
|
+
}
|
|
16
|
+
const url = `${apiUrl}/${endpoint}`;
|
|
17
|
+
const headers = {
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
...(options.headers || {}),
|
|
20
|
+
};
|
|
21
|
+
if (token) {
|
|
22
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(url, {
|
|
26
|
+
...options,
|
|
27
|
+
headers,
|
|
28
|
+
});
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
return { error: data.error || `Request failed with status ${response.status}` };
|
|
32
|
+
}
|
|
33
|
+
return { data };
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
return { error: error.message || 'Network request failed' };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function initLogin() {
|
|
40
|
+
return request('login/init', {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
body: JSON.stringify({}),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async function pollLogin(deviceCode) {
|
|
46
|
+
return request('login/poll', {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
body: JSON.stringify({ device_code: deviceCode }),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function getMe() {
|
|
52
|
+
return request('me');
|
|
53
|
+
}
|
|
54
|
+
async function getProjects() {
|
|
55
|
+
return request('projects');
|
|
56
|
+
}
|
|
57
|
+
async function getTasks(options = {}) {
|
|
58
|
+
const params = new URLSearchParams();
|
|
59
|
+
if (options.project)
|
|
60
|
+
params.set('project', options.project);
|
|
61
|
+
if (options.state)
|
|
62
|
+
params.set('state', options.state);
|
|
63
|
+
if (options.limit)
|
|
64
|
+
params.set('limit', options.limit.toString());
|
|
65
|
+
const query = params.toString();
|
|
66
|
+
return request(`tasks${query ? `?${query}` : ''}`);
|
|
67
|
+
}
|
|
68
|
+
async function getTask(taskId) {
|
|
69
|
+
return request(`tasks/${taskId}`);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface ConfigSchema {
|
|
2
|
+
api_url: string;
|
|
3
|
+
token: string | null;
|
|
4
|
+
default_project: string | null;
|
|
5
|
+
user: {
|
|
6
|
+
id: string;
|
|
7
|
+
email: string;
|
|
8
|
+
name: string;
|
|
9
|
+
} | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function getConfig(): ConfigSchema;
|
|
12
|
+
export declare function setToken(token: string): void;
|
|
13
|
+
export declare function setUser(user: ConfigSchema['user']): void;
|
|
14
|
+
export declare function setDefaultProject(projectId: string | null): void;
|
|
15
|
+
export declare function clearConfig(): void;
|
|
16
|
+
export declare function isAuthenticated(): boolean;
|
|
17
|
+
export declare function getToken(): string | null;
|
|
18
|
+
export declare function getApiUrl(): string;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAEA,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAAC;CACV;AAYD,wBAAgB,SAAS,IAAI,YAAY,CAOxC;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,IAAI,CAExD;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEhE;AAED,wBAAgB,WAAW,IAAI,IAAI,CAIlC;AAED,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,wBAAgB,QAAQ,IAAI,MAAM,GAAG,IAAI,CAExC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getConfig = getConfig;
|
|
7
|
+
exports.setToken = setToken;
|
|
8
|
+
exports.setUser = setUser;
|
|
9
|
+
exports.setDefaultProject = setDefaultProject;
|
|
10
|
+
exports.clearConfig = clearConfig;
|
|
11
|
+
exports.isAuthenticated = isAuthenticated;
|
|
12
|
+
exports.getToken = getToken;
|
|
13
|
+
exports.getApiUrl = getApiUrl;
|
|
14
|
+
const conf_1 = __importDefault(require("conf"));
|
|
15
|
+
const config = new conf_1.default({
|
|
16
|
+
projectName: 'workdynamite',
|
|
17
|
+
defaults: {
|
|
18
|
+
api_url: 'https://tovgfzknrookxgmvibsk.supabase.co/functions/v1/cli-api',
|
|
19
|
+
token: null,
|
|
20
|
+
default_project: null,
|
|
21
|
+
user: null,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
function getConfig() {
|
|
25
|
+
return {
|
|
26
|
+
api_url: config.get('api_url'),
|
|
27
|
+
token: config.get('token'),
|
|
28
|
+
default_project: config.get('default_project'),
|
|
29
|
+
user: config.get('user'),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function setToken(token) {
|
|
33
|
+
config.set('token', token);
|
|
34
|
+
}
|
|
35
|
+
function setUser(user) {
|
|
36
|
+
config.set('user', user);
|
|
37
|
+
}
|
|
38
|
+
function setDefaultProject(projectId) {
|
|
39
|
+
config.set('default_project', projectId);
|
|
40
|
+
}
|
|
41
|
+
function clearConfig() {
|
|
42
|
+
config.set('token', null);
|
|
43
|
+
config.set('user', null);
|
|
44
|
+
config.set('default_project', null);
|
|
45
|
+
}
|
|
46
|
+
function isAuthenticated() {
|
|
47
|
+
return !!config.get('token');
|
|
48
|
+
}
|
|
49
|
+
function getToken() {
|
|
50
|
+
return config.get('token');
|
|
51
|
+
}
|
|
52
|
+
function getApiUrl() {
|
|
53
|
+
return config.get('api_url');
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":";;;;;AAuBA,8BAOC;AAED,4BAEC;AAED,0BAEC;AAED,8CAEC;AAED,kCAIC;AAED,0CAEC;AAED,4BAEC;AAED,8BAEC;AA5DD,gDAAwB;AAaxB,MAAM,MAAM,GAAG,IAAI,cAAI,CAAe;IACpC,WAAW,EAAE,cAAc;IAC3B,QAAQ,EAAE;QACR,OAAO,EAAE,+DAA+D;QACxE,KAAK,EAAE,IAAI;QACX,eAAe,EAAE,IAAI;QACrB,IAAI,EAAE,IAAI;KACX;CACF,CAAC,CAAC;AAEH,SAAgB,SAAS;IACvB,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;QAC9B,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC1B,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9C,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;KACzB,CAAC;AACJ,CAAC;AAED,SAAgB,QAAQ,CAAC,KAAa;IACpC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,SAAgB,OAAO,CAAC,IAA0B;IAChD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,SAAgB,iBAAiB,CAAC,SAAwB;IACxD,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED,SAAgB,WAAW;IACzB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,SAAgB,eAAe;IAC7B,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED,SAAgB,QAAQ;IACtB,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED,SAAgB,SAAS;IACvB,OAAO,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@workdynamite/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "WorkDynamite CLI - Manage tasks from your terminal",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"workdynamite": "./bin/workdynamite.js",
|
|
8
|
+
"wd": "./bin/workdynamite.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"workdynamite",
|
|
18
|
+
"cli",
|
|
19
|
+
"task-management",
|
|
20
|
+
"git",
|
|
21
|
+
"developer-tools"
|
|
22
|
+
],
|
|
23
|
+
"author": "WorkDynamite",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/workdynamite/cli"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"chalk": "^5.3.0",
|
|
31
|
+
"clipboardy": "^4.0.0",
|
|
32
|
+
"commander": "^11.1.0",
|
|
33
|
+
"conf": "^12.0.0",
|
|
34
|
+
"inquirer": "^9.2.12",
|
|
35
|
+
"node-fetch": "^3.3.2",
|
|
36
|
+
"open": "^10.0.3",
|
|
37
|
+
"ora": "^8.0.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/inquirer": "^9.0.7",
|
|
41
|
+
"@types/node": "^20.10.0",
|
|
42
|
+
"typescript": "^5.3.2"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18.0.0"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { setToken, setUser, getConfig, clearConfig, isAuthenticated } from '../lib/config.js';
|
|
5
|
+
import { getMe } from '../lib/api.js';
|
|
6
|
+
|
|
7
|
+
export const configCommand = new Command('config')
|
|
8
|
+
.description('Manage CLI configuration');
|
|
9
|
+
|
|
10
|
+
configCommand
|
|
11
|
+
.command('set-token <token>')
|
|
12
|
+
.description('Set the API token manually')
|
|
13
|
+
.action(async (token) => {
|
|
14
|
+
if (!token.startsWith('wk_')) {
|
|
15
|
+
console.log(chalk.yellow('Warning: Token should start with "wk_"'));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const spinner = ora('Validating token...').start();
|
|
19
|
+
|
|
20
|
+
// Temporarily set the token to validate it
|
|
21
|
+
setToken(token);
|
|
22
|
+
|
|
23
|
+
const { data, error } = await getMe();
|
|
24
|
+
|
|
25
|
+
if (error) {
|
|
26
|
+
// Clear invalid token
|
|
27
|
+
clearConfig();
|
|
28
|
+
spinner.fail(chalk.red(`Invalid token: ${error}`));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
setUser(data!.user);
|
|
33
|
+
spinner.succeed(chalk.green(`Authenticated as ${data!.user.email}`));
|
|
34
|
+
|
|
35
|
+
console.log(chalk.dim('\nYou can now use WorkDynamite CLI commands.'));
|
|
36
|
+
console.log(chalk.dim('Try "workdynamite status" or "workdynamite tasks".\n'));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
configCommand
|
|
40
|
+
.command('show')
|
|
41
|
+
.description('Show current configuration')
|
|
42
|
+
.action(() => {
|
|
43
|
+
const config = getConfig();
|
|
44
|
+
|
|
45
|
+
console.log(chalk.bold('\nāļø Configuration\n'));
|
|
46
|
+
console.log(chalk.dim('ā'.repeat(40)));
|
|
47
|
+
|
|
48
|
+
console.log(` ${chalk.dim('API URL:')} ${config.api_url}`);
|
|
49
|
+
console.log(` ${chalk.dim('Token:')} ${config.token ? `${config.token.substring(0, 12)}...` : chalk.yellow('(not set)')}`);
|
|
50
|
+
console.log(` ${chalk.dim('User:')} ${config.user?.email || chalk.yellow('(not logged in)')}`);
|
|
51
|
+
console.log(` ${chalk.dim('Project:')} ${config.default_project || chalk.dim('(all projects)')}`);
|
|
52
|
+
|
|
53
|
+
console.log(chalk.dim('ā'.repeat(40)));
|
|
54
|
+
console.log('');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
configCommand
|
|
58
|
+
.command('clear')
|
|
59
|
+
.description('Clear all stored configuration')
|
|
60
|
+
.action(() => {
|
|
61
|
+
if (!isAuthenticated()) {
|
|
62
|
+
console.log(chalk.yellow('No configuration to clear.'));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
clearConfig();
|
|
67
|
+
console.log(chalk.green('ā Configuration cleared.'));
|
|
68
|
+
console.log(chalk.dim('Run "workdynamite login" to authenticate again.'));
|
|
69
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import open from 'open';
|
|
5
|
+
import { initLogin, pollLogin, getMe } from '../lib/api.js';
|
|
6
|
+
import { setToken, setUser, isAuthenticated, getConfig } from '../lib/config.js';
|
|
7
|
+
|
|
8
|
+
export const loginCommand = new Command('login')
|
|
9
|
+
.description('Authenticate with WorkDynamite')
|
|
10
|
+
.option('--token <token>', 'Use an existing API token instead of browser auth')
|
|
11
|
+
.action(async (options) => {
|
|
12
|
+
// Check if already authenticated
|
|
13
|
+
if (isAuthenticated()) {
|
|
14
|
+
const config = getConfig();
|
|
15
|
+
console.log(chalk.yellow(`Already logged in as ${config.user?.email}`));
|
|
16
|
+
console.log(chalk.dim('Run "workdynamite logout" to sign out first.'));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// If token provided directly, use it
|
|
21
|
+
if (options.token) {
|
|
22
|
+
const spinner = ora('Validating token...').start();
|
|
23
|
+
|
|
24
|
+
setToken(options.token);
|
|
25
|
+
const { data, error } = await getMe();
|
|
26
|
+
|
|
27
|
+
if (error) {
|
|
28
|
+
setToken('');
|
|
29
|
+
spinner.fail(chalk.red(`Invalid token: ${error}`));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setUser(data!.user);
|
|
34
|
+
spinner.succeed(chalk.green(`Authenticated as ${data!.user.email}`));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Start device authorization flow
|
|
39
|
+
console.log(chalk.bold('\nš WorkDynamite CLI Login\n'));
|
|
40
|
+
|
|
41
|
+
const initSpinner = ora('Initializing login...').start();
|
|
42
|
+
|
|
43
|
+
const { data: initData, error: initError } = await initLogin();
|
|
44
|
+
|
|
45
|
+
if (initError) {
|
|
46
|
+
initSpinner.fail(chalk.red(`Failed to start login: ${initError}`));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
initSpinner.succeed('Login initialized');
|
|
51
|
+
|
|
52
|
+
const { device_code, user_code, verification_uri_complete } = initData!;
|
|
53
|
+
|
|
54
|
+
console.log('\n' + chalk.bold('To complete login:'));
|
|
55
|
+
console.log(chalk.dim('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
56
|
+
console.log(`\n 1. Open this URL in your browser:\n`);
|
|
57
|
+
console.log(` ${chalk.cyan.underline(verification_uri_complete)}\n`);
|
|
58
|
+
console.log(` 2. Enter this code if prompted:\n`);
|
|
59
|
+
console.log(` ${chalk.bold.yellow(user_code)}\n`);
|
|
60
|
+
console.log(chalk.dim('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n'));
|
|
61
|
+
|
|
62
|
+
// Try to open browser automatically
|
|
63
|
+
try {
|
|
64
|
+
await open(verification_uri_complete);
|
|
65
|
+
console.log(chalk.dim('(Browser opened automatically)\n'));
|
|
66
|
+
} catch {
|
|
67
|
+
console.log(chalk.dim('(Open the URL manually)\n'));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Poll for authorization
|
|
71
|
+
const pollSpinner = ora('Waiting for authorization...').start();
|
|
72
|
+
|
|
73
|
+
const maxAttempts = 60; // 5 minutes with 5-second intervals
|
|
74
|
+
let attempts = 0;
|
|
75
|
+
|
|
76
|
+
while (attempts < maxAttempts) {
|
|
77
|
+
await sleep(5000); // Wait 5 seconds between polls
|
|
78
|
+
attempts++;
|
|
79
|
+
|
|
80
|
+
const { data: pollData, error: pollError } = await pollLogin(device_code);
|
|
81
|
+
|
|
82
|
+
if (pollError === 'authorization_pending') {
|
|
83
|
+
pollSpinner.text = `Waiting for authorization... (${Math.floor((maxAttempts - attempts) * 5 / 60)}m remaining)`;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (pollError === 'expired_token') {
|
|
88
|
+
pollSpinner.fail(chalk.red('Authorization expired. Please run login again.'));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (pollError) {
|
|
93
|
+
pollSpinner.fail(chalk.red(`Authorization failed: ${pollError}`));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (pollData) {
|
|
98
|
+
// Authorization successful - but we need the token from the web UI
|
|
99
|
+
pollSpinner.succeed(chalk.green('Authorization complete!'));
|
|
100
|
+
|
|
101
|
+
console.log(chalk.yellow('\nā ļø Please copy the API token shown in your browser.'));
|
|
102
|
+
console.log(chalk.dim('Then run: workdynamite config set-token <your-token>\n'));
|
|
103
|
+
|
|
104
|
+
if (pollData.user) {
|
|
105
|
+
console.log(chalk.dim(`Authorized for: ${pollData.user.email}`));
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
pollSpinner.fail(chalk.red('Authorization timed out. Please try again.'));
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
function sleep(ms: number): Promise<void> {
|
|
115
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
116
|
+
}
|