@devkitvault/recall 1.0.0 → 1.0.2
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 +11 -22
- package/dist/commands/alias.js +84 -0
- package/dist/commands/approve.js +108 -0
- package/dist/commands/audit.js +58 -0
- package/dist/commands/auth/forgot.js +33 -0
- package/dist/commands/auth/index.js +16 -0
- package/dist/commands/auth/login.js +151 -0
- package/dist/commands/auth/logout.js +15 -0
- package/dist/commands/auth/register.js +84 -0
- package/dist/commands/auth/reset.js +43 -0
- package/dist/commands/completion.js +158 -0
- package/dist/commands/config.js +89 -0
- package/dist/commands/delete.js +58 -0
- package/dist/commands/doctor.js +106 -0
- package/dist/commands/env.js +135 -0
- package/dist/commands/export.js +68 -0
- package/dist/commands/feedback.js +25 -0
- package/dist/commands/group.js +206 -0
- package/dist/commands/history.js +41 -0
- package/dist/commands/import.js +126 -0
- package/dist/commands/list.js +69 -0
- package/dist/commands/org.js +408 -0
- package/dist/commands/pin.js +30 -0
- package/dist/commands/run.js +55 -0
- package/dist/commands/save.js +73 -0
- package/dist/commands/search.js +82 -0
- package/dist/commands/share.js +88 -0
- package/dist/commands/snippet.js +147 -0
- package/dist/commands/support.js +96 -0
- package/dist/commands/sync.js +80 -0
- package/dist/commands/template.js +177 -0
- package/dist/commands/update.js +66 -0
- package/dist/commands/upgrade.js +122 -0
- package/dist/commands/whoami.js +70 -0
- package/dist/index.js +71 -0
- package/dist/lib/api.js +51 -0
- package/dist/lib/auth.js +88 -0
- package/dist/lib/config.js +37 -0
- package/package.json +12 -7
- package/bin/recall.js +0 -169
|
@@ -0,0 +1,206 @@
|
|
|
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.groupCommand = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
9
|
+
const commander_1 = require("commander");
|
|
10
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
11
|
+
const ora_1 = __importDefault(require("ora"));
|
|
12
|
+
const api_1 = require("../lib/api");
|
|
13
|
+
const auth_1 = require("../lib/auth");
|
|
14
|
+
function planError(err) {
|
|
15
|
+
if (err instanceof api_1.ApiError && err.status === 403) {
|
|
16
|
+
console.log(chalk_1.default.yellow('\n Groups require a Pro plan.'));
|
|
17
|
+
console.log(chalk_1.default.dim(` Upgrade at ${chalk_1.default.white('https://devkitvault.com/recall/upgrade')}`));
|
|
18
|
+
console.log(chalk_1.default.dim(' Or run: recall upgrade\n'));
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const groupCreate = new commander_1.Command('create')
|
|
24
|
+
.argument('<name>', 'Group name')
|
|
25
|
+
.description('Create a new command group')
|
|
26
|
+
.action(async (name) => {
|
|
27
|
+
const token = await (0, auth_1.requireAuth)();
|
|
28
|
+
const spinner = (0, ora_1.default)(`Creating group "${name}"...`).start();
|
|
29
|
+
try {
|
|
30
|
+
await api_1.ApiClient.post('/groups', { name }, token);
|
|
31
|
+
spinner.succeed(chalk_1.default.green(`Group "${name}" created`));
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
spinner.stop();
|
|
35
|
+
if (!planError(err)) {
|
|
36
|
+
if (err instanceof api_1.ApiError && err.status === 409) {
|
|
37
|
+
console.error(chalk_1.default.red(`\n Group "${name}" already exists\n`));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.error(chalk_1.default.red('\n Failed to create group\n'));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
const groupList = new commander_1.Command('list')
|
|
46
|
+
.description('List all your groups')
|
|
47
|
+
.action(async () => {
|
|
48
|
+
const token = await (0, auth_1.requireAuth)();
|
|
49
|
+
const spinner = (0, ora_1.default)('Fetching groups...').start();
|
|
50
|
+
try {
|
|
51
|
+
const { groups } = await api_1.ApiClient.get('/groups', token);
|
|
52
|
+
spinner.stop();
|
|
53
|
+
if (!groups.length) {
|
|
54
|
+
console.log(chalk_1.default.dim('\n No groups yet. Run: recall group create <name>\n'));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const table = new cli_table3_1.default({
|
|
58
|
+
head: [chalk_1.default.cyan('Name'), chalk_1.default.cyan('Commands')],
|
|
59
|
+
style: { head: [], border: ['grey'] },
|
|
60
|
+
colWidths: [30, 12],
|
|
61
|
+
});
|
|
62
|
+
for (const g of groups) {
|
|
63
|
+
table.push([g.name, g.commandCount]);
|
|
64
|
+
}
|
|
65
|
+
console.log(table.toString());
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
spinner.stop();
|
|
69
|
+
planError(err);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const groupShow = new commander_1.Command('show')
|
|
73
|
+
.argument('<name>', 'Group name')
|
|
74
|
+
.description('List commands in a group')
|
|
75
|
+
.action(async (name) => {
|
|
76
|
+
const token = await (0, auth_1.requireAuth)();
|
|
77
|
+
const spinner = (0, ora_1.default)(`Fetching group "${name}"...`).start();
|
|
78
|
+
try {
|
|
79
|
+
const group = await api_1.ApiClient.get(`/groups/by-name/${encodeURIComponent(name)}`, token);
|
|
80
|
+
const { commands } = await api_1.ApiClient.get(`/groups/${group.id}/commands`, token);
|
|
81
|
+
spinner.stop();
|
|
82
|
+
if (!commands.length) {
|
|
83
|
+
console.log(chalk_1.default.dim(`\n No commands in "${name}" yet.\n`));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
console.log(chalk_1.default.bold(`\n ${name}\n`));
|
|
87
|
+
const table = new cli_table3_1.default({
|
|
88
|
+
head: [chalk_1.default.cyan('Name'), chalk_1.default.cyan('Command'), chalk_1.default.cyan('Tags')],
|
|
89
|
+
style: { head: [], border: ['grey'] },
|
|
90
|
+
colWidths: [20, 46, 18],
|
|
91
|
+
wordWrap: true,
|
|
92
|
+
});
|
|
93
|
+
for (const cmd of commands) {
|
|
94
|
+
table.push([
|
|
95
|
+
cmd.name ?? chalk_1.default.dim('—'),
|
|
96
|
+
cmd.command.length > 44
|
|
97
|
+
? cmd.command.slice(0, 44) + '…'
|
|
98
|
+
: cmd.command,
|
|
99
|
+
(cmd.tags ?? []).join(', ') || chalk_1.default.dim('—'),
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
console.log(table.toString());
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
spinner.stop();
|
|
106
|
+
if (!planError(err)) {
|
|
107
|
+
console.error(chalk_1.default.red(`\n Group "${name}" not found\n`));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const groupAdd = new commander_1.Command('add')
|
|
112
|
+
.argument('<command-name>', 'Command name')
|
|
113
|
+
.argument('<group-name>', 'Group name')
|
|
114
|
+
.description('Add a command to a group')
|
|
115
|
+
.action(async (commandName, groupName) => {
|
|
116
|
+
const token = await (0, auth_1.requireAuth)();
|
|
117
|
+
const spinner = (0, ora_1.default)('Adding to group...').start();
|
|
118
|
+
try {
|
|
119
|
+
const cmd = await api_1.ApiClient.get(`/commands/by-name/${encodeURIComponent(commandName)}`, token);
|
|
120
|
+
const group = await api_1.ApiClient.get(`/groups/by-name/${encodeURIComponent(groupName)}`, token);
|
|
121
|
+
await api_1.ApiClient.patch(`/commands/${cmd.id}/group`, { groupId: group.id }, token);
|
|
122
|
+
spinner.succeed(chalk_1.default.green(`Added "${commandName}" to group "${groupName}"`));
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
spinner.stop();
|
|
126
|
+
if (!planError(err)) {
|
|
127
|
+
console.error(chalk_1.default.red('\n Failed to add command to group\n'));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
const groupRemove = new commander_1.Command('remove')
|
|
132
|
+
.argument('<command-name>', 'Command name')
|
|
133
|
+
.description('Remove a command from its group')
|
|
134
|
+
.action(async (commandName) => {
|
|
135
|
+
const token = await (0, auth_1.requireAuth)();
|
|
136
|
+
const spinner = (0, ora_1.default)('Removing from group...').start();
|
|
137
|
+
try {
|
|
138
|
+
const cmd = await api_1.ApiClient.get(`/commands/by-name/${encodeURIComponent(commandName)}`, token);
|
|
139
|
+
await api_1.ApiClient.delete(`/commands/${cmd.id}/group`, token);
|
|
140
|
+
spinner.succeed(chalk_1.default.green(`Removed "${commandName}" from its group`));
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
spinner.stop();
|
|
144
|
+
if (!planError(err)) {
|
|
145
|
+
console.error(chalk_1.default.red('\n Failed to remove command from group\n'));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
const groupDelete = new commander_1.Command('delete')
|
|
150
|
+
.argument('<name>', 'Group name')
|
|
151
|
+
.description('Delete a group (commands are kept)')
|
|
152
|
+
.action(async (name) => {
|
|
153
|
+
const token = await (0, auth_1.requireAuth)();
|
|
154
|
+
const spinner = (0, ora_1.default)(`Looking up "${name}"...`).start();
|
|
155
|
+
try {
|
|
156
|
+
const group = await api_1.ApiClient.get(`/groups/by-name/${encodeURIComponent(name)}`, token);
|
|
157
|
+
spinner.stop();
|
|
158
|
+
const { confirm } = await inquirer_1.default.prompt([{
|
|
159
|
+
type: 'confirm',
|
|
160
|
+
name: 'confirm',
|
|
161
|
+
message: chalk_1.default.red(`Delete group "${name}"? Commands will be kept.`),
|
|
162
|
+
default: false,
|
|
163
|
+
}]);
|
|
164
|
+
if (!confirm) {
|
|
165
|
+
console.log(chalk_1.default.dim('\n Cancelled.\n'));
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const deleteSpinner = (0, ora_1.default)('Deleting...').start();
|
|
169
|
+
await api_1.ApiClient.delete(`/groups/${group.id}`, token);
|
|
170
|
+
deleteSpinner.succeed(chalk_1.default.green(`Deleted group "${name}"`));
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
spinner.stop();
|
|
174
|
+
if (!planError(err)) {
|
|
175
|
+
console.error(chalk_1.default.red(`\n Group "${name}" not found\n`));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
const groupRename = new commander_1.Command('rename')
|
|
180
|
+
.argument('<old-name>', 'Current group name')
|
|
181
|
+
.argument('<new-name>', 'New group name')
|
|
182
|
+
.description('Rename a group')
|
|
183
|
+
.action(async (oldName, newName) => {
|
|
184
|
+
const token = await (0, auth_1.requireAuth)();
|
|
185
|
+
const spinner = (0, ora_1.default)('Renaming...').start();
|
|
186
|
+
try {
|
|
187
|
+
const group = await api_1.ApiClient.get(`/groups/by-name/${encodeURIComponent(oldName)}`, token);
|
|
188
|
+
await api_1.ApiClient.patch(`/groups/${group.id}`, { name: newName }, token);
|
|
189
|
+
spinner.succeed(chalk_1.default.green(`Renamed "${oldName}" to "${newName}"`));
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
spinner.stop();
|
|
193
|
+
if (!planError(err)) {
|
|
194
|
+
console.error(chalk_1.default.red('\n Failed to rename group\n'));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
exports.groupCommand = new commander_1.Command('group')
|
|
199
|
+
.description('Manage command groups (Pro plan)')
|
|
200
|
+
.addCommand(groupCreate)
|
|
201
|
+
.addCommand(groupList)
|
|
202
|
+
.addCommand(groupShow)
|
|
203
|
+
.addCommand(groupAdd)
|
|
204
|
+
.addCommand(groupRemove)
|
|
205
|
+
.addCommand(groupDelete)
|
|
206
|
+
.addCommand(groupRename);
|
|
@@ -0,0 +1,41 @@
|
|
|
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.historyCommand = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const ora_1 = __importDefault(require("ora"));
|
|
10
|
+
const api_1 = require("../lib/api");
|
|
11
|
+
const auth_1 = require("../lib/auth");
|
|
12
|
+
exports.historyCommand = new commander_1.Command('history')
|
|
13
|
+
.description('Show your command run history')
|
|
14
|
+
.option('-l, --limit <n>', 'Number of entries to show', '20')
|
|
15
|
+
.action(async (opts) => {
|
|
16
|
+
const token = await (0, auth_1.requireAuth)();
|
|
17
|
+
const spinner = (0, ora_1.default)('Fetching history...').start();
|
|
18
|
+
try {
|
|
19
|
+
const { history } = await api_1.ApiClient.get(`/commands/history?limit=${opts.limit}`, token);
|
|
20
|
+
spinner.stop();
|
|
21
|
+
if (!history.length) {
|
|
22
|
+
console.log(chalk_1.default.dim('\n No history yet. Run some commands first.\n'));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(chalk_1.default.bold(`\n Last ${history.length} runs\n`));
|
|
26
|
+
for (const entry of history) {
|
|
27
|
+
const time = new Date(entry.ranAt);
|
|
28
|
+
const timeStr = time.toLocaleString();
|
|
29
|
+
const name = entry.command?.name
|
|
30
|
+
? chalk_1.default.white(entry.command.name)
|
|
31
|
+
: chalk_1.default.dim('unnamed');
|
|
32
|
+
const cmd = chalk_1.default.dim(entry.command?.command?.slice(0, 50) +
|
|
33
|
+
(entry.command?.command?.length > 50 ? '…' : ''));
|
|
34
|
+
console.log(` ${chalk_1.default.dim(timeStr)} ${name} ${cmd}`);
|
|
35
|
+
}
|
|
36
|
+
console.log();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
spinner.fail(chalk_1.default.red('Failed to fetch history'));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
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.importCommand = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const api_1 = require("../lib/api");
|
|
13
|
+
const auth_1 = require("../lib/auth");
|
|
14
|
+
function parseJSON(content) {
|
|
15
|
+
const data = JSON.parse(content);
|
|
16
|
+
if (!Array.isArray(data))
|
|
17
|
+
throw new Error('JSON must be an array of commands');
|
|
18
|
+
return data.map((item) => ({
|
|
19
|
+
command: item.command,
|
|
20
|
+
name: item.name,
|
|
21
|
+
tags: item.tags ?? [],
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
function parseSh(content) {
|
|
25
|
+
const lines = content.split('\n');
|
|
26
|
+
const entries = [];
|
|
27
|
+
let currentName;
|
|
28
|
+
let currentTags = [];
|
|
29
|
+
for (const raw of lines) {
|
|
30
|
+
const line = raw.trim();
|
|
31
|
+
// skip empty lines and shebang
|
|
32
|
+
if (!line || line.startsWith('#!'))
|
|
33
|
+
continue;
|
|
34
|
+
if (line.startsWith('# tags:')) {
|
|
35
|
+
currentTags = line
|
|
36
|
+
.replace('# tags:', '')
|
|
37
|
+
.split(',')
|
|
38
|
+
.map(t => t.trim())
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (line.startsWith('#')) {
|
|
43
|
+
currentName = line.replace('#', '').trim();
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
// it's a command
|
|
47
|
+
entries.push({
|
|
48
|
+
command: line,
|
|
49
|
+
name: currentName,
|
|
50
|
+
tags: currentTags,
|
|
51
|
+
});
|
|
52
|
+
// reset
|
|
53
|
+
currentName = undefined;
|
|
54
|
+
currentTags = [];
|
|
55
|
+
}
|
|
56
|
+
return entries;
|
|
57
|
+
}
|
|
58
|
+
exports.importCommand = new commander_1.Command('import')
|
|
59
|
+
.description('Import commands from a JSON or shell script file')
|
|
60
|
+
.argument('<file>', 'Path to the file to import')
|
|
61
|
+
.option('-s, --skip-duplicates', 'Skip commands that already exist by name')
|
|
62
|
+
.action(async (file, opts) => {
|
|
63
|
+
const token = await (0, auth_1.requireAuth)();
|
|
64
|
+
const filePath = path_1.default.resolve(file);
|
|
65
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
66
|
+
console.error(chalk_1.default.red(`\n File not found: ${filePath}\n`));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const content = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
70
|
+
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
71
|
+
let entries = [];
|
|
72
|
+
try {
|
|
73
|
+
if (ext === '.json') {
|
|
74
|
+
entries = parseJSON(content);
|
|
75
|
+
}
|
|
76
|
+
else if (ext === '.sh' || ext === '.bash') {
|
|
77
|
+
entries = parseSh(content);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// try JSON first, then sh
|
|
81
|
+
try {
|
|
82
|
+
entries = parseJSON(content);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
entries = parseSh(content);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
console.error(chalk_1.default.red(`\n Failed to parse file: ${err.message}\n`));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
if (!entries.length) {
|
|
94
|
+
console.log(chalk_1.default.dim('\n No commands found in file.\n'));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
console.log(chalk_1.default.dim(`\n Found ${entries.length} command${entries.length === 1 ? '' : 's'} to import\n`));
|
|
98
|
+
let imported = 0;
|
|
99
|
+
let skipped = 0;
|
|
100
|
+
let failed = 0;
|
|
101
|
+
for (const entry of entries) {
|
|
102
|
+
const spinner = (0, ora_1.default)(`Importing: ${chalk_1.default.white(entry.name ?? entry.command.slice(0, 40))}`).start();
|
|
103
|
+
try {
|
|
104
|
+
await api_1.ApiClient.post('/commands', {
|
|
105
|
+
command: entry.command,
|
|
106
|
+
name: entry.name,
|
|
107
|
+
tags: entry.tags,
|
|
108
|
+
}, token);
|
|
109
|
+
spinner.succeed(chalk_1.default.green(`Imported: ${entry.name ?? entry.command.slice(0, 40)}`));
|
|
110
|
+
imported++;
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
if (opts.skipDuplicates && err.status === 409) {
|
|
114
|
+
spinner.warn(chalk_1.default.yellow(`Skipped: ${entry.name ?? entry.command.slice(0, 40)}`));
|
|
115
|
+
skipped++;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
spinner.fail(chalk_1.default.red(`Failed: ${entry.name ?? entry.command.slice(0, 40)}`));
|
|
119
|
+
failed++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
console.log();
|
|
124
|
+
console.log(` ${chalk_1.default.green(`${imported} imported`)} ${chalk_1.default.yellow(`${skipped} skipped`)} ${chalk_1.default.red(`${failed} failed`)}`);
|
|
125
|
+
console.log();
|
|
126
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
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.listCommand = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const cli_table3_1 = __importDefault(require("cli-table3"));
|
|
9
|
+
const commander_1 = require("commander");
|
|
10
|
+
const ora_1 = __importDefault(require("ora"));
|
|
11
|
+
const api_1 = require("../lib/api");
|
|
12
|
+
const auth_1 = require("../lib/auth");
|
|
13
|
+
exports.listCommand = new commander_1.Command('list')
|
|
14
|
+
.description('List your saved commands')
|
|
15
|
+
.option('-t, --tag <tag>', 'Filter by tag')
|
|
16
|
+
.option('-g, --group <group>', 'Filter by group (Pro)')
|
|
17
|
+
.option('-s, --search <q>', 'Search by keyword')
|
|
18
|
+
.option('-p, --pinned', 'Show pinned only')
|
|
19
|
+
.action(async (opts) => {
|
|
20
|
+
const token = await (0, auth_1.requireAuth)();
|
|
21
|
+
const spinner = (0, ora_1.default)('Fetching...').start();
|
|
22
|
+
try {
|
|
23
|
+
const params = new URLSearchParams();
|
|
24
|
+
if (opts.tag)
|
|
25
|
+
params.set('tag', opts.tag);
|
|
26
|
+
if (opts.group)
|
|
27
|
+
params.set('group', opts.group);
|
|
28
|
+
if (opts.search)
|
|
29
|
+
params.set('search', opts.search);
|
|
30
|
+
const { commands } = await api_1.ApiClient.get(`/commands?${params}`, token);
|
|
31
|
+
spinner.stop();
|
|
32
|
+
let result = commands;
|
|
33
|
+
// Filter pinned only
|
|
34
|
+
if (opts.pinned)
|
|
35
|
+
result = result.filter((c) => c.pinned);
|
|
36
|
+
// Sort: pinned first, then by createdAt
|
|
37
|
+
result.sort((a, b) => {
|
|
38
|
+
if (a.pinned && !b.pinned)
|
|
39
|
+
return -1;
|
|
40
|
+
if (!a.pinned && b.pinned)
|
|
41
|
+
return 1;
|
|
42
|
+
return 0;
|
|
43
|
+
});
|
|
44
|
+
if (!result.length) {
|
|
45
|
+
console.log(chalk_1.default.dim('\n No commands found.\n'));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const table = new cli_table3_1.default({
|
|
49
|
+
head: [chalk_1.default.cyan('Pin'), chalk_1.default.cyan('Name'), chalk_1.default.cyan('Command'), chalk_1.default.cyan('Tags')],
|
|
50
|
+
style: { head: [], border: ['grey'] },
|
|
51
|
+
colWidths: [5, 18, 44, 18],
|
|
52
|
+
wordWrap: true,
|
|
53
|
+
});
|
|
54
|
+
for (const cmd of result) {
|
|
55
|
+
table.push([
|
|
56
|
+
cmd.pinned ? chalk_1.default.yellow('★') : chalk_1.default.dim('·'),
|
|
57
|
+
cmd.name ?? chalk_1.default.dim('—'),
|
|
58
|
+
cmd.command.length > 42
|
|
59
|
+
? cmd.command.slice(0, 42) + '…'
|
|
60
|
+
: cmd.command,
|
|
61
|
+
(cmd.tags ?? []).join(', ') || chalk_1.default.dim('—'),
|
|
62
|
+
]);
|
|
63
|
+
}
|
|
64
|
+
console.log(table.toString());
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
spinner.fail(chalk_1.default.red('Failed to fetch commands'));
|
|
68
|
+
}
|
|
69
|
+
});
|