@lex-inc/thoughtful 0.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/ENVIRONMENT.md +83 -0
- package/README.md +294 -0
- package/dist/index.js +4513 -0
- package/package.json +51 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4513 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
9
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
|
+
for (let key of __getOwnPropNames(mod))
|
|
12
|
+
if (!__hasOwnProp.call(to, key))
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: () => mod[key],
|
|
15
|
+
enumerable: true
|
|
16
|
+
});
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
20
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
21
|
+
|
|
22
|
+
// ../../node_modules/commander/lib/error.js
|
|
23
|
+
var require_error = __commonJS((exports) => {
|
|
24
|
+
class CommanderError extends Error {
|
|
25
|
+
constructor(exitCode, code, message) {
|
|
26
|
+
super(message);
|
|
27
|
+
Error.captureStackTrace(this, this.constructor);
|
|
28
|
+
this.name = this.constructor.name;
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.exitCode = exitCode;
|
|
31
|
+
this.nestedError = undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class InvalidArgumentError extends CommanderError {
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(1, "commander.invalidArgument", message);
|
|
38
|
+
Error.captureStackTrace(this, this.constructor);
|
|
39
|
+
this.name = this.constructor.name;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.CommanderError = CommanderError;
|
|
43
|
+
exports.InvalidArgumentError = InvalidArgumentError;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// ../../node_modules/commander/lib/argument.js
|
|
47
|
+
var require_argument = __commonJS((exports) => {
|
|
48
|
+
var { InvalidArgumentError } = require_error();
|
|
49
|
+
|
|
50
|
+
class Argument {
|
|
51
|
+
constructor(name, description) {
|
|
52
|
+
this.description = description || "";
|
|
53
|
+
this.variadic = false;
|
|
54
|
+
this.parseArg = undefined;
|
|
55
|
+
this.defaultValue = undefined;
|
|
56
|
+
this.defaultValueDescription = undefined;
|
|
57
|
+
this.argChoices = undefined;
|
|
58
|
+
switch (name[0]) {
|
|
59
|
+
case "<":
|
|
60
|
+
this.required = true;
|
|
61
|
+
this._name = name.slice(1, -1);
|
|
62
|
+
break;
|
|
63
|
+
case "[":
|
|
64
|
+
this.required = false;
|
|
65
|
+
this._name = name.slice(1, -1);
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
this.required = true;
|
|
69
|
+
this._name = name;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
if (this._name.length > 3 && this._name.slice(-3) === "...") {
|
|
73
|
+
this.variadic = true;
|
|
74
|
+
this._name = this._name.slice(0, -3);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
name() {
|
|
78
|
+
return this._name;
|
|
79
|
+
}
|
|
80
|
+
_concatValue(value, previous) {
|
|
81
|
+
if (previous === this.defaultValue || !Array.isArray(previous)) {
|
|
82
|
+
return [value];
|
|
83
|
+
}
|
|
84
|
+
return previous.concat(value);
|
|
85
|
+
}
|
|
86
|
+
default(value, description) {
|
|
87
|
+
this.defaultValue = value;
|
|
88
|
+
this.defaultValueDescription = description;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
argParser(fn) {
|
|
92
|
+
this.parseArg = fn;
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
choices(values) {
|
|
96
|
+
this.argChoices = values.slice();
|
|
97
|
+
this.parseArg = (arg, previous) => {
|
|
98
|
+
if (!this.argChoices.includes(arg)) {
|
|
99
|
+
throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(", ")}.`);
|
|
100
|
+
}
|
|
101
|
+
if (this.variadic) {
|
|
102
|
+
return this._concatValue(arg, previous);
|
|
103
|
+
}
|
|
104
|
+
return arg;
|
|
105
|
+
};
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
argRequired() {
|
|
109
|
+
this.required = true;
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
argOptional() {
|
|
113
|
+
this.required = false;
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function humanReadableArgName(arg) {
|
|
118
|
+
const nameOutput = arg.name() + (arg.variadic === true ? "..." : "");
|
|
119
|
+
return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
|
|
120
|
+
}
|
|
121
|
+
exports.Argument = Argument;
|
|
122
|
+
exports.humanReadableArgName = humanReadableArgName;
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// ../../node_modules/commander/lib/help.js
|
|
126
|
+
var require_help = __commonJS((exports) => {
|
|
127
|
+
var { humanReadableArgName } = require_argument();
|
|
128
|
+
|
|
129
|
+
class Help {
|
|
130
|
+
constructor() {
|
|
131
|
+
this.helpWidth = undefined;
|
|
132
|
+
this.minWidthToWrap = 40;
|
|
133
|
+
this.sortSubcommands = false;
|
|
134
|
+
this.sortOptions = false;
|
|
135
|
+
this.showGlobalOptions = false;
|
|
136
|
+
}
|
|
137
|
+
prepareContext(contextOptions) {
|
|
138
|
+
this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;
|
|
139
|
+
}
|
|
140
|
+
visibleCommands(cmd) {
|
|
141
|
+
const visibleCommands = cmd.commands.filter((cmd2) => !cmd2._hidden);
|
|
142
|
+
const helpCommand = cmd._getHelpCommand();
|
|
143
|
+
if (helpCommand && !helpCommand._hidden) {
|
|
144
|
+
visibleCommands.push(helpCommand);
|
|
145
|
+
}
|
|
146
|
+
if (this.sortSubcommands) {
|
|
147
|
+
visibleCommands.sort((a, b) => {
|
|
148
|
+
return a.name().localeCompare(b.name());
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return visibleCommands;
|
|
152
|
+
}
|
|
153
|
+
compareOptions(a, b) {
|
|
154
|
+
const getSortKey = (option) => {
|
|
155
|
+
return option.short ? option.short.replace(/^-/, "") : option.long.replace(/^--/, "");
|
|
156
|
+
};
|
|
157
|
+
return getSortKey(a).localeCompare(getSortKey(b));
|
|
158
|
+
}
|
|
159
|
+
visibleOptions(cmd) {
|
|
160
|
+
const visibleOptions = cmd.options.filter((option) => !option.hidden);
|
|
161
|
+
const helpOption = cmd._getHelpOption();
|
|
162
|
+
if (helpOption && !helpOption.hidden) {
|
|
163
|
+
const removeShort = helpOption.short && cmd._findOption(helpOption.short);
|
|
164
|
+
const removeLong = helpOption.long && cmd._findOption(helpOption.long);
|
|
165
|
+
if (!removeShort && !removeLong) {
|
|
166
|
+
visibleOptions.push(helpOption);
|
|
167
|
+
} else if (helpOption.long && !removeLong) {
|
|
168
|
+
visibleOptions.push(cmd.createOption(helpOption.long, helpOption.description));
|
|
169
|
+
} else if (helpOption.short && !removeShort) {
|
|
170
|
+
visibleOptions.push(cmd.createOption(helpOption.short, helpOption.description));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (this.sortOptions) {
|
|
174
|
+
visibleOptions.sort(this.compareOptions);
|
|
175
|
+
}
|
|
176
|
+
return visibleOptions;
|
|
177
|
+
}
|
|
178
|
+
visibleGlobalOptions(cmd) {
|
|
179
|
+
if (!this.showGlobalOptions)
|
|
180
|
+
return [];
|
|
181
|
+
const globalOptions = [];
|
|
182
|
+
for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
|
|
183
|
+
const visibleOptions = ancestorCmd.options.filter((option) => !option.hidden);
|
|
184
|
+
globalOptions.push(...visibleOptions);
|
|
185
|
+
}
|
|
186
|
+
if (this.sortOptions) {
|
|
187
|
+
globalOptions.sort(this.compareOptions);
|
|
188
|
+
}
|
|
189
|
+
return globalOptions;
|
|
190
|
+
}
|
|
191
|
+
visibleArguments(cmd) {
|
|
192
|
+
if (cmd._argsDescription) {
|
|
193
|
+
cmd.registeredArguments.forEach((argument) => {
|
|
194
|
+
argument.description = argument.description || cmd._argsDescription[argument.name()] || "";
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
if (cmd.registeredArguments.find((argument) => argument.description)) {
|
|
198
|
+
return cmd.registeredArguments;
|
|
199
|
+
}
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
subcommandTerm(cmd) {
|
|
203
|
+
const args = cmd.registeredArguments.map((arg) => humanReadableArgName(arg)).join(" ");
|
|
204
|
+
return cmd._name + (cmd._aliases[0] ? "|" + cmd._aliases[0] : "") + (cmd.options.length ? " [options]" : "") + (args ? " " + args : "");
|
|
205
|
+
}
|
|
206
|
+
optionTerm(option) {
|
|
207
|
+
return option.flags;
|
|
208
|
+
}
|
|
209
|
+
argumentTerm(argument) {
|
|
210
|
+
return argument.name();
|
|
211
|
+
}
|
|
212
|
+
longestSubcommandTermLength(cmd, helper) {
|
|
213
|
+
return helper.visibleCommands(cmd).reduce((max, command) => {
|
|
214
|
+
return Math.max(max, this.displayWidth(helper.styleSubcommandTerm(helper.subcommandTerm(command))));
|
|
215
|
+
}, 0);
|
|
216
|
+
}
|
|
217
|
+
longestOptionTermLength(cmd, helper) {
|
|
218
|
+
return helper.visibleOptions(cmd).reduce((max, option) => {
|
|
219
|
+
return Math.max(max, this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))));
|
|
220
|
+
}, 0);
|
|
221
|
+
}
|
|
222
|
+
longestGlobalOptionTermLength(cmd, helper) {
|
|
223
|
+
return helper.visibleGlobalOptions(cmd).reduce((max, option) => {
|
|
224
|
+
return Math.max(max, this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))));
|
|
225
|
+
}, 0);
|
|
226
|
+
}
|
|
227
|
+
longestArgumentTermLength(cmd, helper) {
|
|
228
|
+
return helper.visibleArguments(cmd).reduce((max, argument) => {
|
|
229
|
+
return Math.max(max, this.displayWidth(helper.styleArgumentTerm(helper.argumentTerm(argument))));
|
|
230
|
+
}, 0);
|
|
231
|
+
}
|
|
232
|
+
commandUsage(cmd) {
|
|
233
|
+
let cmdName = cmd._name;
|
|
234
|
+
if (cmd._aliases[0]) {
|
|
235
|
+
cmdName = cmdName + "|" + cmd._aliases[0];
|
|
236
|
+
}
|
|
237
|
+
let ancestorCmdNames = "";
|
|
238
|
+
for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
|
|
239
|
+
ancestorCmdNames = ancestorCmd.name() + " " + ancestorCmdNames;
|
|
240
|
+
}
|
|
241
|
+
return ancestorCmdNames + cmdName + " " + cmd.usage();
|
|
242
|
+
}
|
|
243
|
+
commandDescription(cmd) {
|
|
244
|
+
return cmd.description();
|
|
245
|
+
}
|
|
246
|
+
subcommandDescription(cmd) {
|
|
247
|
+
return cmd.summary() || cmd.description();
|
|
248
|
+
}
|
|
249
|
+
optionDescription(option) {
|
|
250
|
+
const extraInfo = [];
|
|
251
|
+
if (option.argChoices) {
|
|
252
|
+
extraInfo.push(`choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
|
|
253
|
+
}
|
|
254
|
+
if (option.defaultValue !== undefined) {
|
|
255
|
+
const showDefault = option.required || option.optional || option.isBoolean() && typeof option.defaultValue === "boolean";
|
|
256
|
+
if (showDefault) {
|
|
257
|
+
extraInfo.push(`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (option.presetArg !== undefined && option.optional) {
|
|
261
|
+
extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);
|
|
262
|
+
}
|
|
263
|
+
if (option.envVar !== undefined) {
|
|
264
|
+
extraInfo.push(`env: ${option.envVar}`);
|
|
265
|
+
}
|
|
266
|
+
if (extraInfo.length > 0) {
|
|
267
|
+
return `${option.description} (${extraInfo.join(", ")})`;
|
|
268
|
+
}
|
|
269
|
+
return option.description;
|
|
270
|
+
}
|
|
271
|
+
argumentDescription(argument) {
|
|
272
|
+
const extraInfo = [];
|
|
273
|
+
if (argument.argChoices) {
|
|
274
|
+
extraInfo.push(`choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
|
|
275
|
+
}
|
|
276
|
+
if (argument.defaultValue !== undefined) {
|
|
277
|
+
extraInfo.push(`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`);
|
|
278
|
+
}
|
|
279
|
+
if (extraInfo.length > 0) {
|
|
280
|
+
const extraDescription = `(${extraInfo.join(", ")})`;
|
|
281
|
+
if (argument.description) {
|
|
282
|
+
return `${argument.description} ${extraDescription}`;
|
|
283
|
+
}
|
|
284
|
+
return extraDescription;
|
|
285
|
+
}
|
|
286
|
+
return argument.description;
|
|
287
|
+
}
|
|
288
|
+
formatHelp(cmd, helper) {
|
|
289
|
+
const termWidth = helper.padWidth(cmd, helper);
|
|
290
|
+
const helpWidth = helper.helpWidth ?? 80;
|
|
291
|
+
function callFormatItem(term, description) {
|
|
292
|
+
return helper.formatItem(term, termWidth, description, helper);
|
|
293
|
+
}
|
|
294
|
+
let output = [
|
|
295
|
+
`${helper.styleTitle("Usage:")} ${helper.styleUsage(helper.commandUsage(cmd))}`,
|
|
296
|
+
""
|
|
297
|
+
];
|
|
298
|
+
const commandDescription = helper.commandDescription(cmd);
|
|
299
|
+
if (commandDescription.length > 0) {
|
|
300
|
+
output = output.concat([
|
|
301
|
+
helper.boxWrap(helper.styleCommandDescription(commandDescription), helpWidth),
|
|
302
|
+
""
|
|
303
|
+
]);
|
|
304
|
+
}
|
|
305
|
+
const argumentList = helper.visibleArguments(cmd).map((argument) => {
|
|
306
|
+
return callFormatItem(helper.styleArgumentTerm(helper.argumentTerm(argument)), helper.styleArgumentDescription(helper.argumentDescription(argument)));
|
|
307
|
+
});
|
|
308
|
+
if (argumentList.length > 0) {
|
|
309
|
+
output = output.concat([
|
|
310
|
+
helper.styleTitle("Arguments:"),
|
|
311
|
+
...argumentList,
|
|
312
|
+
""
|
|
313
|
+
]);
|
|
314
|
+
}
|
|
315
|
+
const optionList = helper.visibleOptions(cmd).map((option) => {
|
|
316
|
+
return callFormatItem(helper.styleOptionTerm(helper.optionTerm(option)), helper.styleOptionDescription(helper.optionDescription(option)));
|
|
317
|
+
});
|
|
318
|
+
if (optionList.length > 0) {
|
|
319
|
+
output = output.concat([
|
|
320
|
+
helper.styleTitle("Options:"),
|
|
321
|
+
...optionList,
|
|
322
|
+
""
|
|
323
|
+
]);
|
|
324
|
+
}
|
|
325
|
+
if (helper.showGlobalOptions) {
|
|
326
|
+
const globalOptionList = helper.visibleGlobalOptions(cmd).map((option) => {
|
|
327
|
+
return callFormatItem(helper.styleOptionTerm(helper.optionTerm(option)), helper.styleOptionDescription(helper.optionDescription(option)));
|
|
328
|
+
});
|
|
329
|
+
if (globalOptionList.length > 0) {
|
|
330
|
+
output = output.concat([
|
|
331
|
+
helper.styleTitle("Global Options:"),
|
|
332
|
+
...globalOptionList,
|
|
333
|
+
""
|
|
334
|
+
]);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const commandList = helper.visibleCommands(cmd).map((cmd2) => {
|
|
338
|
+
return callFormatItem(helper.styleSubcommandTerm(helper.subcommandTerm(cmd2)), helper.styleSubcommandDescription(helper.subcommandDescription(cmd2)));
|
|
339
|
+
});
|
|
340
|
+
if (commandList.length > 0) {
|
|
341
|
+
output = output.concat([
|
|
342
|
+
helper.styleTitle("Commands:"),
|
|
343
|
+
...commandList,
|
|
344
|
+
""
|
|
345
|
+
]);
|
|
346
|
+
}
|
|
347
|
+
return output.join(`
|
|
348
|
+
`);
|
|
349
|
+
}
|
|
350
|
+
displayWidth(str) {
|
|
351
|
+
return stripColor(str).length;
|
|
352
|
+
}
|
|
353
|
+
styleTitle(str) {
|
|
354
|
+
return str;
|
|
355
|
+
}
|
|
356
|
+
styleUsage(str) {
|
|
357
|
+
return str.split(" ").map((word) => {
|
|
358
|
+
if (word === "[options]")
|
|
359
|
+
return this.styleOptionText(word);
|
|
360
|
+
if (word === "[command]")
|
|
361
|
+
return this.styleSubcommandText(word);
|
|
362
|
+
if (word[0] === "[" || word[0] === "<")
|
|
363
|
+
return this.styleArgumentText(word);
|
|
364
|
+
return this.styleCommandText(word);
|
|
365
|
+
}).join(" ");
|
|
366
|
+
}
|
|
367
|
+
styleCommandDescription(str) {
|
|
368
|
+
return this.styleDescriptionText(str);
|
|
369
|
+
}
|
|
370
|
+
styleOptionDescription(str) {
|
|
371
|
+
return this.styleDescriptionText(str);
|
|
372
|
+
}
|
|
373
|
+
styleSubcommandDescription(str) {
|
|
374
|
+
return this.styleDescriptionText(str);
|
|
375
|
+
}
|
|
376
|
+
styleArgumentDescription(str) {
|
|
377
|
+
return this.styleDescriptionText(str);
|
|
378
|
+
}
|
|
379
|
+
styleDescriptionText(str) {
|
|
380
|
+
return str;
|
|
381
|
+
}
|
|
382
|
+
styleOptionTerm(str) {
|
|
383
|
+
return this.styleOptionText(str);
|
|
384
|
+
}
|
|
385
|
+
styleSubcommandTerm(str) {
|
|
386
|
+
return str.split(" ").map((word) => {
|
|
387
|
+
if (word === "[options]")
|
|
388
|
+
return this.styleOptionText(word);
|
|
389
|
+
if (word[0] === "[" || word[0] === "<")
|
|
390
|
+
return this.styleArgumentText(word);
|
|
391
|
+
return this.styleSubcommandText(word);
|
|
392
|
+
}).join(" ");
|
|
393
|
+
}
|
|
394
|
+
styleArgumentTerm(str) {
|
|
395
|
+
return this.styleArgumentText(str);
|
|
396
|
+
}
|
|
397
|
+
styleOptionText(str) {
|
|
398
|
+
return str;
|
|
399
|
+
}
|
|
400
|
+
styleArgumentText(str) {
|
|
401
|
+
return str;
|
|
402
|
+
}
|
|
403
|
+
styleSubcommandText(str) {
|
|
404
|
+
return str;
|
|
405
|
+
}
|
|
406
|
+
styleCommandText(str) {
|
|
407
|
+
return str;
|
|
408
|
+
}
|
|
409
|
+
padWidth(cmd, helper) {
|
|
410
|
+
return Math.max(helper.longestOptionTermLength(cmd, helper), helper.longestGlobalOptionTermLength(cmd, helper), helper.longestSubcommandTermLength(cmd, helper), helper.longestArgumentTermLength(cmd, helper));
|
|
411
|
+
}
|
|
412
|
+
preformatted(str) {
|
|
413
|
+
return /\n[^\S\r\n]/.test(str);
|
|
414
|
+
}
|
|
415
|
+
formatItem(term, termWidth, description, helper) {
|
|
416
|
+
const itemIndent = 2;
|
|
417
|
+
const itemIndentStr = " ".repeat(itemIndent);
|
|
418
|
+
if (!description)
|
|
419
|
+
return itemIndentStr + term;
|
|
420
|
+
const paddedTerm = term.padEnd(termWidth + term.length - helper.displayWidth(term));
|
|
421
|
+
const spacerWidth = 2;
|
|
422
|
+
const helpWidth = this.helpWidth ?? 80;
|
|
423
|
+
const remainingWidth = helpWidth - termWidth - spacerWidth - itemIndent;
|
|
424
|
+
let formattedDescription;
|
|
425
|
+
if (remainingWidth < this.minWidthToWrap || helper.preformatted(description)) {
|
|
426
|
+
formattedDescription = description;
|
|
427
|
+
} else {
|
|
428
|
+
const wrappedDescription = helper.boxWrap(description, remainingWidth);
|
|
429
|
+
formattedDescription = wrappedDescription.replace(/\n/g, `
|
|
430
|
+
` + " ".repeat(termWidth + spacerWidth));
|
|
431
|
+
}
|
|
432
|
+
return itemIndentStr + paddedTerm + " ".repeat(spacerWidth) + formattedDescription.replace(/\n/g, `
|
|
433
|
+
${itemIndentStr}`);
|
|
434
|
+
}
|
|
435
|
+
boxWrap(str, width) {
|
|
436
|
+
if (width < this.minWidthToWrap)
|
|
437
|
+
return str;
|
|
438
|
+
const rawLines = str.split(/\r\n|\n/);
|
|
439
|
+
const chunkPattern = /[\s]*[^\s]+/g;
|
|
440
|
+
const wrappedLines = [];
|
|
441
|
+
rawLines.forEach((line) => {
|
|
442
|
+
const chunks = line.match(chunkPattern);
|
|
443
|
+
if (chunks === null) {
|
|
444
|
+
wrappedLines.push("");
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
let sumChunks = [chunks.shift()];
|
|
448
|
+
let sumWidth = this.displayWidth(sumChunks[0]);
|
|
449
|
+
chunks.forEach((chunk) => {
|
|
450
|
+
const visibleWidth = this.displayWidth(chunk);
|
|
451
|
+
if (sumWidth + visibleWidth <= width) {
|
|
452
|
+
sumChunks.push(chunk);
|
|
453
|
+
sumWidth += visibleWidth;
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
wrappedLines.push(sumChunks.join(""));
|
|
457
|
+
const nextChunk = chunk.trimStart();
|
|
458
|
+
sumChunks = [nextChunk];
|
|
459
|
+
sumWidth = this.displayWidth(nextChunk);
|
|
460
|
+
});
|
|
461
|
+
wrappedLines.push(sumChunks.join(""));
|
|
462
|
+
});
|
|
463
|
+
return wrappedLines.join(`
|
|
464
|
+
`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
function stripColor(str) {
|
|
468
|
+
const sgrPattern = /\x1b\[\d*(;\d*)*m/g;
|
|
469
|
+
return str.replace(sgrPattern, "");
|
|
470
|
+
}
|
|
471
|
+
exports.Help = Help;
|
|
472
|
+
exports.stripColor = stripColor;
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// ../../node_modules/commander/lib/option.js
|
|
476
|
+
var require_option = __commonJS((exports) => {
|
|
477
|
+
var { InvalidArgumentError } = require_error();
|
|
478
|
+
|
|
479
|
+
class Option {
|
|
480
|
+
constructor(flags, description) {
|
|
481
|
+
this.flags = flags;
|
|
482
|
+
this.description = description || "";
|
|
483
|
+
this.required = flags.includes("<");
|
|
484
|
+
this.optional = flags.includes("[");
|
|
485
|
+
this.variadic = /\w\.\.\.[>\]]$/.test(flags);
|
|
486
|
+
this.mandatory = false;
|
|
487
|
+
const optionFlags = splitOptionFlags(flags);
|
|
488
|
+
this.short = optionFlags.shortFlag;
|
|
489
|
+
this.long = optionFlags.longFlag;
|
|
490
|
+
this.negate = false;
|
|
491
|
+
if (this.long) {
|
|
492
|
+
this.negate = this.long.startsWith("--no-");
|
|
493
|
+
}
|
|
494
|
+
this.defaultValue = undefined;
|
|
495
|
+
this.defaultValueDescription = undefined;
|
|
496
|
+
this.presetArg = undefined;
|
|
497
|
+
this.envVar = undefined;
|
|
498
|
+
this.parseArg = undefined;
|
|
499
|
+
this.hidden = false;
|
|
500
|
+
this.argChoices = undefined;
|
|
501
|
+
this.conflictsWith = [];
|
|
502
|
+
this.implied = undefined;
|
|
503
|
+
}
|
|
504
|
+
default(value, description) {
|
|
505
|
+
this.defaultValue = value;
|
|
506
|
+
this.defaultValueDescription = description;
|
|
507
|
+
return this;
|
|
508
|
+
}
|
|
509
|
+
preset(arg) {
|
|
510
|
+
this.presetArg = arg;
|
|
511
|
+
return this;
|
|
512
|
+
}
|
|
513
|
+
conflicts(names) {
|
|
514
|
+
this.conflictsWith = this.conflictsWith.concat(names);
|
|
515
|
+
return this;
|
|
516
|
+
}
|
|
517
|
+
implies(impliedOptionValues) {
|
|
518
|
+
let newImplied = impliedOptionValues;
|
|
519
|
+
if (typeof impliedOptionValues === "string") {
|
|
520
|
+
newImplied = { [impliedOptionValues]: true };
|
|
521
|
+
}
|
|
522
|
+
this.implied = Object.assign(this.implied || {}, newImplied);
|
|
523
|
+
return this;
|
|
524
|
+
}
|
|
525
|
+
env(name) {
|
|
526
|
+
this.envVar = name;
|
|
527
|
+
return this;
|
|
528
|
+
}
|
|
529
|
+
argParser(fn) {
|
|
530
|
+
this.parseArg = fn;
|
|
531
|
+
return this;
|
|
532
|
+
}
|
|
533
|
+
makeOptionMandatory(mandatory = true) {
|
|
534
|
+
this.mandatory = !!mandatory;
|
|
535
|
+
return this;
|
|
536
|
+
}
|
|
537
|
+
hideHelp(hide = true) {
|
|
538
|
+
this.hidden = !!hide;
|
|
539
|
+
return this;
|
|
540
|
+
}
|
|
541
|
+
_concatValue(value, previous) {
|
|
542
|
+
if (previous === this.defaultValue || !Array.isArray(previous)) {
|
|
543
|
+
return [value];
|
|
544
|
+
}
|
|
545
|
+
return previous.concat(value);
|
|
546
|
+
}
|
|
547
|
+
choices(values) {
|
|
548
|
+
this.argChoices = values.slice();
|
|
549
|
+
this.parseArg = (arg, previous) => {
|
|
550
|
+
if (!this.argChoices.includes(arg)) {
|
|
551
|
+
throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(", ")}.`);
|
|
552
|
+
}
|
|
553
|
+
if (this.variadic) {
|
|
554
|
+
return this._concatValue(arg, previous);
|
|
555
|
+
}
|
|
556
|
+
return arg;
|
|
557
|
+
};
|
|
558
|
+
return this;
|
|
559
|
+
}
|
|
560
|
+
name() {
|
|
561
|
+
if (this.long) {
|
|
562
|
+
return this.long.replace(/^--/, "");
|
|
563
|
+
}
|
|
564
|
+
return this.short.replace(/^-/, "");
|
|
565
|
+
}
|
|
566
|
+
attributeName() {
|
|
567
|
+
if (this.negate) {
|
|
568
|
+
return camelcase(this.name().replace(/^no-/, ""));
|
|
569
|
+
}
|
|
570
|
+
return camelcase(this.name());
|
|
571
|
+
}
|
|
572
|
+
is(arg) {
|
|
573
|
+
return this.short === arg || this.long === arg;
|
|
574
|
+
}
|
|
575
|
+
isBoolean() {
|
|
576
|
+
return !this.required && !this.optional && !this.negate;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
class DualOptions {
|
|
581
|
+
constructor(options) {
|
|
582
|
+
this.positiveOptions = new Map;
|
|
583
|
+
this.negativeOptions = new Map;
|
|
584
|
+
this.dualOptions = new Set;
|
|
585
|
+
options.forEach((option) => {
|
|
586
|
+
if (option.negate) {
|
|
587
|
+
this.negativeOptions.set(option.attributeName(), option);
|
|
588
|
+
} else {
|
|
589
|
+
this.positiveOptions.set(option.attributeName(), option);
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
this.negativeOptions.forEach((value, key) => {
|
|
593
|
+
if (this.positiveOptions.has(key)) {
|
|
594
|
+
this.dualOptions.add(key);
|
|
595
|
+
}
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
valueFromOption(value, option) {
|
|
599
|
+
const optionKey = option.attributeName();
|
|
600
|
+
if (!this.dualOptions.has(optionKey))
|
|
601
|
+
return true;
|
|
602
|
+
const preset = this.negativeOptions.get(optionKey).presetArg;
|
|
603
|
+
const negativeValue = preset !== undefined ? preset : false;
|
|
604
|
+
return option.negate === (negativeValue === value);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
function camelcase(str) {
|
|
608
|
+
return str.split("-").reduce((str2, word) => {
|
|
609
|
+
return str2 + word[0].toUpperCase() + word.slice(1);
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
function splitOptionFlags(flags) {
|
|
613
|
+
let shortFlag;
|
|
614
|
+
let longFlag;
|
|
615
|
+
const shortFlagExp = /^-[^-]$/;
|
|
616
|
+
const longFlagExp = /^--[^-]/;
|
|
617
|
+
const flagParts = flags.split(/[ |,]+/).concat("guard");
|
|
618
|
+
if (shortFlagExp.test(flagParts[0]))
|
|
619
|
+
shortFlag = flagParts.shift();
|
|
620
|
+
if (longFlagExp.test(flagParts[0]))
|
|
621
|
+
longFlag = flagParts.shift();
|
|
622
|
+
if (!shortFlag && shortFlagExp.test(flagParts[0]))
|
|
623
|
+
shortFlag = flagParts.shift();
|
|
624
|
+
if (!shortFlag && longFlagExp.test(flagParts[0])) {
|
|
625
|
+
shortFlag = longFlag;
|
|
626
|
+
longFlag = flagParts.shift();
|
|
627
|
+
}
|
|
628
|
+
if (flagParts[0].startsWith("-")) {
|
|
629
|
+
const unsupportedFlag = flagParts[0];
|
|
630
|
+
const baseError = `option creation failed due to '${unsupportedFlag}' in option flags '${flags}'`;
|
|
631
|
+
if (/^-[^-][^-]/.test(unsupportedFlag))
|
|
632
|
+
throw new Error(`${baseError}
|
|
633
|
+
- a short flag is a single dash and a single character
|
|
634
|
+
- either use a single dash and a single character (for a short flag)
|
|
635
|
+
- or use a double dash for a long option (and can have two, like '--ws, --workspace')`);
|
|
636
|
+
if (shortFlagExp.test(unsupportedFlag))
|
|
637
|
+
throw new Error(`${baseError}
|
|
638
|
+
- too many short flags`);
|
|
639
|
+
if (longFlagExp.test(unsupportedFlag))
|
|
640
|
+
throw new Error(`${baseError}
|
|
641
|
+
- too many long flags`);
|
|
642
|
+
throw new Error(`${baseError}
|
|
643
|
+
- unrecognised flag format`);
|
|
644
|
+
}
|
|
645
|
+
if (shortFlag === undefined && longFlag === undefined)
|
|
646
|
+
throw new Error(`option creation failed due to no flags found in '${flags}'.`);
|
|
647
|
+
return { shortFlag, longFlag };
|
|
648
|
+
}
|
|
649
|
+
exports.Option = Option;
|
|
650
|
+
exports.DualOptions = DualOptions;
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
// ../../node_modules/commander/lib/suggestSimilar.js
|
|
654
|
+
var require_suggestSimilar = __commonJS((exports) => {
|
|
655
|
+
var maxDistance = 3;
|
|
656
|
+
function editDistance(a, b) {
|
|
657
|
+
if (Math.abs(a.length - b.length) > maxDistance)
|
|
658
|
+
return Math.max(a.length, b.length);
|
|
659
|
+
const d = [];
|
|
660
|
+
for (let i = 0;i <= a.length; i++) {
|
|
661
|
+
d[i] = [i];
|
|
662
|
+
}
|
|
663
|
+
for (let j = 0;j <= b.length; j++) {
|
|
664
|
+
d[0][j] = j;
|
|
665
|
+
}
|
|
666
|
+
for (let j = 1;j <= b.length; j++) {
|
|
667
|
+
for (let i = 1;i <= a.length; i++) {
|
|
668
|
+
let cost = 1;
|
|
669
|
+
if (a[i - 1] === b[j - 1]) {
|
|
670
|
+
cost = 0;
|
|
671
|
+
} else {
|
|
672
|
+
cost = 1;
|
|
673
|
+
}
|
|
674
|
+
d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
|
|
675
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
676
|
+
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return d[a.length][b.length];
|
|
681
|
+
}
|
|
682
|
+
function suggestSimilar(word, candidates) {
|
|
683
|
+
if (!candidates || candidates.length === 0)
|
|
684
|
+
return "";
|
|
685
|
+
candidates = Array.from(new Set(candidates));
|
|
686
|
+
const searchingOptions = word.startsWith("--");
|
|
687
|
+
if (searchingOptions) {
|
|
688
|
+
word = word.slice(2);
|
|
689
|
+
candidates = candidates.map((candidate) => candidate.slice(2));
|
|
690
|
+
}
|
|
691
|
+
let similar = [];
|
|
692
|
+
let bestDistance = maxDistance;
|
|
693
|
+
const minSimilarity = 0.4;
|
|
694
|
+
candidates.forEach((candidate) => {
|
|
695
|
+
if (candidate.length <= 1)
|
|
696
|
+
return;
|
|
697
|
+
const distance = editDistance(word, candidate);
|
|
698
|
+
const length = Math.max(word.length, candidate.length);
|
|
699
|
+
const similarity = (length - distance) / length;
|
|
700
|
+
if (similarity > minSimilarity) {
|
|
701
|
+
if (distance < bestDistance) {
|
|
702
|
+
bestDistance = distance;
|
|
703
|
+
similar = [candidate];
|
|
704
|
+
} else if (distance === bestDistance) {
|
|
705
|
+
similar.push(candidate);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
similar.sort((a, b) => a.localeCompare(b));
|
|
710
|
+
if (searchingOptions) {
|
|
711
|
+
similar = similar.map((candidate) => `--${candidate}`);
|
|
712
|
+
}
|
|
713
|
+
if (similar.length > 1) {
|
|
714
|
+
return `
|
|
715
|
+
(Did you mean one of ${similar.join(", ")}?)`;
|
|
716
|
+
}
|
|
717
|
+
if (similar.length === 1) {
|
|
718
|
+
return `
|
|
719
|
+
(Did you mean ${similar[0]}?)`;
|
|
720
|
+
}
|
|
721
|
+
return "";
|
|
722
|
+
}
|
|
723
|
+
exports.suggestSimilar = suggestSimilar;
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
// ../../node_modules/commander/lib/command.js
|
|
727
|
+
var require_command = __commonJS((exports) => {
|
|
728
|
+
var EventEmitter = __require("node:events").EventEmitter;
|
|
729
|
+
var childProcess = __require("node:child_process");
|
|
730
|
+
var path = __require("node:path");
|
|
731
|
+
var fs = __require("node:fs");
|
|
732
|
+
var process2 = __require("node:process");
|
|
733
|
+
var { Argument, humanReadableArgName } = require_argument();
|
|
734
|
+
var { CommanderError } = require_error();
|
|
735
|
+
var { Help, stripColor } = require_help();
|
|
736
|
+
var { Option, DualOptions } = require_option();
|
|
737
|
+
var { suggestSimilar } = require_suggestSimilar();
|
|
738
|
+
|
|
739
|
+
class Command extends EventEmitter {
|
|
740
|
+
constructor(name) {
|
|
741
|
+
super();
|
|
742
|
+
this.commands = [];
|
|
743
|
+
this.options = [];
|
|
744
|
+
this.parent = null;
|
|
745
|
+
this._allowUnknownOption = false;
|
|
746
|
+
this._allowExcessArguments = false;
|
|
747
|
+
this.registeredArguments = [];
|
|
748
|
+
this._args = this.registeredArguments;
|
|
749
|
+
this.args = [];
|
|
750
|
+
this.rawArgs = [];
|
|
751
|
+
this.processedArgs = [];
|
|
752
|
+
this._scriptPath = null;
|
|
753
|
+
this._name = name || "";
|
|
754
|
+
this._optionValues = {};
|
|
755
|
+
this._optionValueSources = {};
|
|
756
|
+
this._storeOptionsAsProperties = false;
|
|
757
|
+
this._actionHandler = null;
|
|
758
|
+
this._executableHandler = false;
|
|
759
|
+
this._executableFile = null;
|
|
760
|
+
this._executableDir = null;
|
|
761
|
+
this._defaultCommandName = null;
|
|
762
|
+
this._exitCallback = null;
|
|
763
|
+
this._aliases = [];
|
|
764
|
+
this._combineFlagAndOptionalValue = true;
|
|
765
|
+
this._description = "";
|
|
766
|
+
this._summary = "";
|
|
767
|
+
this._argsDescription = undefined;
|
|
768
|
+
this._enablePositionalOptions = false;
|
|
769
|
+
this._passThroughOptions = false;
|
|
770
|
+
this._lifeCycleHooks = {};
|
|
771
|
+
this._showHelpAfterError = false;
|
|
772
|
+
this._showSuggestionAfterError = true;
|
|
773
|
+
this._savedState = null;
|
|
774
|
+
this._outputConfiguration = {
|
|
775
|
+
writeOut: (str) => process2.stdout.write(str),
|
|
776
|
+
writeErr: (str) => process2.stderr.write(str),
|
|
777
|
+
outputError: (str, write) => write(str),
|
|
778
|
+
getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : undefined,
|
|
779
|
+
getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : undefined,
|
|
780
|
+
getOutHasColors: () => useColor() ?? (process2.stdout.isTTY && process2.stdout.hasColors?.()),
|
|
781
|
+
getErrHasColors: () => useColor() ?? (process2.stderr.isTTY && process2.stderr.hasColors?.()),
|
|
782
|
+
stripColor: (str) => stripColor(str)
|
|
783
|
+
};
|
|
784
|
+
this._hidden = false;
|
|
785
|
+
this._helpOption = undefined;
|
|
786
|
+
this._addImplicitHelpCommand = undefined;
|
|
787
|
+
this._helpCommand = undefined;
|
|
788
|
+
this._helpConfiguration = {};
|
|
789
|
+
}
|
|
790
|
+
copyInheritedSettings(sourceCommand) {
|
|
791
|
+
this._outputConfiguration = sourceCommand._outputConfiguration;
|
|
792
|
+
this._helpOption = sourceCommand._helpOption;
|
|
793
|
+
this._helpCommand = sourceCommand._helpCommand;
|
|
794
|
+
this._helpConfiguration = sourceCommand._helpConfiguration;
|
|
795
|
+
this._exitCallback = sourceCommand._exitCallback;
|
|
796
|
+
this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties;
|
|
797
|
+
this._combineFlagAndOptionalValue = sourceCommand._combineFlagAndOptionalValue;
|
|
798
|
+
this._allowExcessArguments = sourceCommand._allowExcessArguments;
|
|
799
|
+
this._enablePositionalOptions = sourceCommand._enablePositionalOptions;
|
|
800
|
+
this._showHelpAfterError = sourceCommand._showHelpAfterError;
|
|
801
|
+
this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError;
|
|
802
|
+
return this;
|
|
803
|
+
}
|
|
804
|
+
_getCommandAndAncestors() {
|
|
805
|
+
const result = [];
|
|
806
|
+
for (let command = this;command; command = command.parent) {
|
|
807
|
+
result.push(command);
|
|
808
|
+
}
|
|
809
|
+
return result;
|
|
810
|
+
}
|
|
811
|
+
command(nameAndArgs, actionOptsOrExecDesc, execOpts) {
|
|
812
|
+
let desc = actionOptsOrExecDesc;
|
|
813
|
+
let opts = execOpts;
|
|
814
|
+
if (typeof desc === "object" && desc !== null) {
|
|
815
|
+
opts = desc;
|
|
816
|
+
desc = null;
|
|
817
|
+
}
|
|
818
|
+
opts = opts || {};
|
|
819
|
+
const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);
|
|
820
|
+
const cmd = this.createCommand(name);
|
|
821
|
+
if (desc) {
|
|
822
|
+
cmd.description(desc);
|
|
823
|
+
cmd._executableHandler = true;
|
|
824
|
+
}
|
|
825
|
+
if (opts.isDefault)
|
|
826
|
+
this._defaultCommandName = cmd._name;
|
|
827
|
+
cmd._hidden = !!(opts.noHelp || opts.hidden);
|
|
828
|
+
cmd._executableFile = opts.executableFile || null;
|
|
829
|
+
if (args)
|
|
830
|
+
cmd.arguments(args);
|
|
831
|
+
this._registerCommand(cmd);
|
|
832
|
+
cmd.parent = this;
|
|
833
|
+
cmd.copyInheritedSettings(this);
|
|
834
|
+
if (desc)
|
|
835
|
+
return this;
|
|
836
|
+
return cmd;
|
|
837
|
+
}
|
|
838
|
+
createCommand(name) {
|
|
839
|
+
return new Command(name);
|
|
840
|
+
}
|
|
841
|
+
createHelp() {
|
|
842
|
+
return Object.assign(new Help, this.configureHelp());
|
|
843
|
+
}
|
|
844
|
+
configureHelp(configuration) {
|
|
845
|
+
if (configuration === undefined)
|
|
846
|
+
return this._helpConfiguration;
|
|
847
|
+
this._helpConfiguration = configuration;
|
|
848
|
+
return this;
|
|
849
|
+
}
|
|
850
|
+
configureOutput(configuration) {
|
|
851
|
+
if (configuration === undefined)
|
|
852
|
+
return this._outputConfiguration;
|
|
853
|
+
Object.assign(this._outputConfiguration, configuration);
|
|
854
|
+
return this;
|
|
855
|
+
}
|
|
856
|
+
showHelpAfterError(displayHelp = true) {
|
|
857
|
+
if (typeof displayHelp !== "string")
|
|
858
|
+
displayHelp = !!displayHelp;
|
|
859
|
+
this._showHelpAfterError = displayHelp;
|
|
860
|
+
return this;
|
|
861
|
+
}
|
|
862
|
+
showSuggestionAfterError(displaySuggestion = true) {
|
|
863
|
+
this._showSuggestionAfterError = !!displaySuggestion;
|
|
864
|
+
return this;
|
|
865
|
+
}
|
|
866
|
+
addCommand(cmd, opts) {
|
|
867
|
+
if (!cmd._name) {
|
|
868
|
+
throw new Error(`Command passed to .addCommand() must have a name
|
|
869
|
+
- specify the name in Command constructor or using .name()`);
|
|
870
|
+
}
|
|
871
|
+
opts = opts || {};
|
|
872
|
+
if (opts.isDefault)
|
|
873
|
+
this._defaultCommandName = cmd._name;
|
|
874
|
+
if (opts.noHelp || opts.hidden)
|
|
875
|
+
cmd._hidden = true;
|
|
876
|
+
this._registerCommand(cmd);
|
|
877
|
+
cmd.parent = this;
|
|
878
|
+
cmd._checkForBrokenPassThrough();
|
|
879
|
+
return this;
|
|
880
|
+
}
|
|
881
|
+
createArgument(name, description) {
|
|
882
|
+
return new Argument(name, description);
|
|
883
|
+
}
|
|
884
|
+
argument(name, description, fn, defaultValue) {
|
|
885
|
+
const argument = this.createArgument(name, description);
|
|
886
|
+
if (typeof fn === "function") {
|
|
887
|
+
argument.default(defaultValue).argParser(fn);
|
|
888
|
+
} else {
|
|
889
|
+
argument.default(fn);
|
|
890
|
+
}
|
|
891
|
+
this.addArgument(argument);
|
|
892
|
+
return this;
|
|
893
|
+
}
|
|
894
|
+
arguments(names) {
|
|
895
|
+
names.trim().split(/ +/).forEach((detail) => {
|
|
896
|
+
this.argument(detail);
|
|
897
|
+
});
|
|
898
|
+
return this;
|
|
899
|
+
}
|
|
900
|
+
addArgument(argument) {
|
|
901
|
+
const previousArgument = this.registeredArguments.slice(-1)[0];
|
|
902
|
+
if (previousArgument && previousArgument.variadic) {
|
|
903
|
+
throw new Error(`only the last argument can be variadic '${previousArgument.name()}'`);
|
|
904
|
+
}
|
|
905
|
+
if (argument.required && argument.defaultValue !== undefined && argument.parseArg === undefined) {
|
|
906
|
+
throw new Error(`a default value for a required argument is never used: '${argument.name()}'`);
|
|
907
|
+
}
|
|
908
|
+
this.registeredArguments.push(argument);
|
|
909
|
+
return this;
|
|
910
|
+
}
|
|
911
|
+
helpCommand(enableOrNameAndArgs, description) {
|
|
912
|
+
if (typeof enableOrNameAndArgs === "boolean") {
|
|
913
|
+
this._addImplicitHelpCommand = enableOrNameAndArgs;
|
|
914
|
+
return this;
|
|
915
|
+
}
|
|
916
|
+
enableOrNameAndArgs = enableOrNameAndArgs ?? "help [command]";
|
|
917
|
+
const [, helpName, helpArgs] = enableOrNameAndArgs.match(/([^ ]+) *(.*)/);
|
|
918
|
+
const helpDescription = description ?? "display help for command";
|
|
919
|
+
const helpCommand = this.createCommand(helpName);
|
|
920
|
+
helpCommand.helpOption(false);
|
|
921
|
+
if (helpArgs)
|
|
922
|
+
helpCommand.arguments(helpArgs);
|
|
923
|
+
if (helpDescription)
|
|
924
|
+
helpCommand.description(helpDescription);
|
|
925
|
+
this._addImplicitHelpCommand = true;
|
|
926
|
+
this._helpCommand = helpCommand;
|
|
927
|
+
return this;
|
|
928
|
+
}
|
|
929
|
+
addHelpCommand(helpCommand, deprecatedDescription) {
|
|
930
|
+
if (typeof helpCommand !== "object") {
|
|
931
|
+
this.helpCommand(helpCommand, deprecatedDescription);
|
|
932
|
+
return this;
|
|
933
|
+
}
|
|
934
|
+
this._addImplicitHelpCommand = true;
|
|
935
|
+
this._helpCommand = helpCommand;
|
|
936
|
+
return this;
|
|
937
|
+
}
|
|
938
|
+
_getHelpCommand() {
|
|
939
|
+
const hasImplicitHelpCommand = this._addImplicitHelpCommand ?? (this.commands.length && !this._actionHandler && !this._findCommand("help"));
|
|
940
|
+
if (hasImplicitHelpCommand) {
|
|
941
|
+
if (this._helpCommand === undefined) {
|
|
942
|
+
this.helpCommand(undefined, undefined);
|
|
943
|
+
}
|
|
944
|
+
return this._helpCommand;
|
|
945
|
+
}
|
|
946
|
+
return null;
|
|
947
|
+
}
|
|
948
|
+
hook(event, listener) {
|
|
949
|
+
const allowedValues = ["preSubcommand", "preAction", "postAction"];
|
|
950
|
+
if (!allowedValues.includes(event)) {
|
|
951
|
+
throw new Error(`Unexpected value for event passed to hook : '${event}'.
|
|
952
|
+
Expecting one of '${allowedValues.join("', '")}'`);
|
|
953
|
+
}
|
|
954
|
+
if (this._lifeCycleHooks[event]) {
|
|
955
|
+
this._lifeCycleHooks[event].push(listener);
|
|
956
|
+
} else {
|
|
957
|
+
this._lifeCycleHooks[event] = [listener];
|
|
958
|
+
}
|
|
959
|
+
return this;
|
|
960
|
+
}
|
|
961
|
+
exitOverride(fn) {
|
|
962
|
+
if (fn) {
|
|
963
|
+
this._exitCallback = fn;
|
|
964
|
+
} else {
|
|
965
|
+
this._exitCallback = (err) => {
|
|
966
|
+
if (err.code !== "commander.executeSubCommandAsync") {
|
|
967
|
+
throw err;
|
|
968
|
+
} else {}
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
return this;
|
|
972
|
+
}
|
|
973
|
+
_exit(exitCode, code, message) {
|
|
974
|
+
if (this._exitCallback) {
|
|
975
|
+
this._exitCallback(new CommanderError(exitCode, code, message));
|
|
976
|
+
}
|
|
977
|
+
process2.exit(exitCode);
|
|
978
|
+
}
|
|
979
|
+
action(fn) {
|
|
980
|
+
const listener = (args) => {
|
|
981
|
+
const expectedArgsCount = this.registeredArguments.length;
|
|
982
|
+
const actionArgs = args.slice(0, expectedArgsCount);
|
|
983
|
+
if (this._storeOptionsAsProperties) {
|
|
984
|
+
actionArgs[expectedArgsCount] = this;
|
|
985
|
+
} else {
|
|
986
|
+
actionArgs[expectedArgsCount] = this.opts();
|
|
987
|
+
}
|
|
988
|
+
actionArgs.push(this);
|
|
989
|
+
return fn.apply(this, actionArgs);
|
|
990
|
+
};
|
|
991
|
+
this._actionHandler = listener;
|
|
992
|
+
return this;
|
|
993
|
+
}
|
|
994
|
+
createOption(flags, description) {
|
|
995
|
+
return new Option(flags, description);
|
|
996
|
+
}
|
|
997
|
+
_callParseArg(target, value, previous, invalidArgumentMessage) {
|
|
998
|
+
try {
|
|
999
|
+
return target.parseArg(value, previous);
|
|
1000
|
+
} catch (err) {
|
|
1001
|
+
if (err.code === "commander.invalidArgument") {
|
|
1002
|
+
const message = `${invalidArgumentMessage} ${err.message}`;
|
|
1003
|
+
this.error(message, { exitCode: err.exitCode, code: err.code });
|
|
1004
|
+
}
|
|
1005
|
+
throw err;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
_registerOption(option) {
|
|
1009
|
+
const matchingOption = option.short && this._findOption(option.short) || option.long && this._findOption(option.long);
|
|
1010
|
+
if (matchingOption) {
|
|
1011
|
+
const matchingFlag = option.long && this._findOption(option.long) ? option.long : option.short;
|
|
1012
|
+
throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'
|
|
1013
|
+
- already used by option '${matchingOption.flags}'`);
|
|
1014
|
+
}
|
|
1015
|
+
this.options.push(option);
|
|
1016
|
+
}
|
|
1017
|
+
_registerCommand(command) {
|
|
1018
|
+
const knownBy = (cmd) => {
|
|
1019
|
+
return [cmd.name()].concat(cmd.aliases());
|
|
1020
|
+
};
|
|
1021
|
+
const alreadyUsed = knownBy(command).find((name) => this._findCommand(name));
|
|
1022
|
+
if (alreadyUsed) {
|
|
1023
|
+
const existingCmd = knownBy(this._findCommand(alreadyUsed)).join("|");
|
|
1024
|
+
const newCmd = knownBy(command).join("|");
|
|
1025
|
+
throw new Error(`cannot add command '${newCmd}' as already have command '${existingCmd}'`);
|
|
1026
|
+
}
|
|
1027
|
+
this.commands.push(command);
|
|
1028
|
+
}
|
|
1029
|
+
addOption(option) {
|
|
1030
|
+
this._registerOption(option);
|
|
1031
|
+
const oname = option.name();
|
|
1032
|
+
const name = option.attributeName();
|
|
1033
|
+
if (option.negate) {
|
|
1034
|
+
const positiveLongFlag = option.long.replace(/^--no-/, "--");
|
|
1035
|
+
if (!this._findOption(positiveLongFlag)) {
|
|
1036
|
+
this.setOptionValueWithSource(name, option.defaultValue === undefined ? true : option.defaultValue, "default");
|
|
1037
|
+
}
|
|
1038
|
+
} else if (option.defaultValue !== undefined) {
|
|
1039
|
+
this.setOptionValueWithSource(name, option.defaultValue, "default");
|
|
1040
|
+
}
|
|
1041
|
+
const handleOptionValue = (val, invalidValueMessage, valueSource) => {
|
|
1042
|
+
if (val == null && option.presetArg !== undefined) {
|
|
1043
|
+
val = option.presetArg;
|
|
1044
|
+
}
|
|
1045
|
+
const oldValue = this.getOptionValue(name);
|
|
1046
|
+
if (val !== null && option.parseArg) {
|
|
1047
|
+
val = this._callParseArg(option, val, oldValue, invalidValueMessage);
|
|
1048
|
+
} else if (val !== null && option.variadic) {
|
|
1049
|
+
val = option._concatValue(val, oldValue);
|
|
1050
|
+
}
|
|
1051
|
+
if (val == null) {
|
|
1052
|
+
if (option.negate) {
|
|
1053
|
+
val = false;
|
|
1054
|
+
} else if (option.isBoolean() || option.optional) {
|
|
1055
|
+
val = true;
|
|
1056
|
+
} else {
|
|
1057
|
+
val = "";
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
this.setOptionValueWithSource(name, val, valueSource);
|
|
1061
|
+
};
|
|
1062
|
+
this.on("option:" + oname, (val) => {
|
|
1063
|
+
const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
|
|
1064
|
+
handleOptionValue(val, invalidValueMessage, "cli");
|
|
1065
|
+
});
|
|
1066
|
+
if (option.envVar) {
|
|
1067
|
+
this.on("optionEnv:" + oname, (val) => {
|
|
1068
|
+
const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
|
|
1069
|
+
handleOptionValue(val, invalidValueMessage, "env");
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
return this;
|
|
1073
|
+
}
|
|
1074
|
+
_optionEx(config, flags, description, fn, defaultValue) {
|
|
1075
|
+
if (typeof flags === "object" && flags instanceof Option) {
|
|
1076
|
+
throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");
|
|
1077
|
+
}
|
|
1078
|
+
const option = this.createOption(flags, description);
|
|
1079
|
+
option.makeOptionMandatory(!!config.mandatory);
|
|
1080
|
+
if (typeof fn === "function") {
|
|
1081
|
+
option.default(defaultValue).argParser(fn);
|
|
1082
|
+
} else if (fn instanceof RegExp) {
|
|
1083
|
+
const regex = fn;
|
|
1084
|
+
fn = (val, def) => {
|
|
1085
|
+
const m = regex.exec(val);
|
|
1086
|
+
return m ? m[0] : def;
|
|
1087
|
+
};
|
|
1088
|
+
option.default(defaultValue).argParser(fn);
|
|
1089
|
+
} else {
|
|
1090
|
+
option.default(fn);
|
|
1091
|
+
}
|
|
1092
|
+
return this.addOption(option);
|
|
1093
|
+
}
|
|
1094
|
+
option(flags, description, parseArg, defaultValue) {
|
|
1095
|
+
return this._optionEx({}, flags, description, parseArg, defaultValue);
|
|
1096
|
+
}
|
|
1097
|
+
requiredOption(flags, description, parseArg, defaultValue) {
|
|
1098
|
+
return this._optionEx({ mandatory: true }, flags, description, parseArg, defaultValue);
|
|
1099
|
+
}
|
|
1100
|
+
combineFlagAndOptionalValue(combine = true) {
|
|
1101
|
+
this._combineFlagAndOptionalValue = !!combine;
|
|
1102
|
+
return this;
|
|
1103
|
+
}
|
|
1104
|
+
allowUnknownOption(allowUnknown = true) {
|
|
1105
|
+
this._allowUnknownOption = !!allowUnknown;
|
|
1106
|
+
return this;
|
|
1107
|
+
}
|
|
1108
|
+
allowExcessArguments(allowExcess = true) {
|
|
1109
|
+
this._allowExcessArguments = !!allowExcess;
|
|
1110
|
+
return this;
|
|
1111
|
+
}
|
|
1112
|
+
enablePositionalOptions(positional = true) {
|
|
1113
|
+
this._enablePositionalOptions = !!positional;
|
|
1114
|
+
return this;
|
|
1115
|
+
}
|
|
1116
|
+
passThroughOptions(passThrough = true) {
|
|
1117
|
+
this._passThroughOptions = !!passThrough;
|
|
1118
|
+
this._checkForBrokenPassThrough();
|
|
1119
|
+
return this;
|
|
1120
|
+
}
|
|
1121
|
+
_checkForBrokenPassThrough() {
|
|
1122
|
+
if (this.parent && this._passThroughOptions && !this.parent._enablePositionalOptions) {
|
|
1123
|
+
throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
storeOptionsAsProperties(storeAsProperties = true) {
|
|
1127
|
+
if (this.options.length) {
|
|
1128
|
+
throw new Error("call .storeOptionsAsProperties() before adding options");
|
|
1129
|
+
}
|
|
1130
|
+
if (Object.keys(this._optionValues).length) {
|
|
1131
|
+
throw new Error("call .storeOptionsAsProperties() before setting option values");
|
|
1132
|
+
}
|
|
1133
|
+
this._storeOptionsAsProperties = !!storeAsProperties;
|
|
1134
|
+
return this;
|
|
1135
|
+
}
|
|
1136
|
+
getOptionValue(key) {
|
|
1137
|
+
if (this._storeOptionsAsProperties) {
|
|
1138
|
+
return this[key];
|
|
1139
|
+
}
|
|
1140
|
+
return this._optionValues[key];
|
|
1141
|
+
}
|
|
1142
|
+
setOptionValue(key, value) {
|
|
1143
|
+
return this.setOptionValueWithSource(key, value, undefined);
|
|
1144
|
+
}
|
|
1145
|
+
setOptionValueWithSource(key, value, source) {
|
|
1146
|
+
if (this._storeOptionsAsProperties) {
|
|
1147
|
+
this[key] = value;
|
|
1148
|
+
} else {
|
|
1149
|
+
this._optionValues[key] = value;
|
|
1150
|
+
}
|
|
1151
|
+
this._optionValueSources[key] = source;
|
|
1152
|
+
return this;
|
|
1153
|
+
}
|
|
1154
|
+
getOptionValueSource(key) {
|
|
1155
|
+
return this._optionValueSources[key];
|
|
1156
|
+
}
|
|
1157
|
+
getOptionValueSourceWithGlobals(key) {
|
|
1158
|
+
let source;
|
|
1159
|
+
this._getCommandAndAncestors().forEach((cmd) => {
|
|
1160
|
+
if (cmd.getOptionValueSource(key) !== undefined) {
|
|
1161
|
+
source = cmd.getOptionValueSource(key);
|
|
1162
|
+
}
|
|
1163
|
+
});
|
|
1164
|
+
return source;
|
|
1165
|
+
}
|
|
1166
|
+
_prepareUserArgs(argv, parseOptions) {
|
|
1167
|
+
if (argv !== undefined && !Array.isArray(argv)) {
|
|
1168
|
+
throw new Error("first parameter to parse must be array or undefined");
|
|
1169
|
+
}
|
|
1170
|
+
parseOptions = parseOptions || {};
|
|
1171
|
+
if (argv === undefined && parseOptions.from === undefined) {
|
|
1172
|
+
if (process2.versions?.electron) {
|
|
1173
|
+
parseOptions.from = "electron";
|
|
1174
|
+
}
|
|
1175
|
+
const execArgv = process2.execArgv ?? [];
|
|
1176
|
+
if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
|
|
1177
|
+
parseOptions.from = "eval";
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
if (argv === undefined) {
|
|
1181
|
+
argv = process2.argv;
|
|
1182
|
+
}
|
|
1183
|
+
this.rawArgs = argv.slice();
|
|
1184
|
+
let userArgs;
|
|
1185
|
+
switch (parseOptions.from) {
|
|
1186
|
+
case undefined:
|
|
1187
|
+
case "node":
|
|
1188
|
+
this._scriptPath = argv[1];
|
|
1189
|
+
userArgs = argv.slice(2);
|
|
1190
|
+
break;
|
|
1191
|
+
case "electron":
|
|
1192
|
+
if (process2.defaultApp) {
|
|
1193
|
+
this._scriptPath = argv[1];
|
|
1194
|
+
userArgs = argv.slice(2);
|
|
1195
|
+
} else {
|
|
1196
|
+
userArgs = argv.slice(1);
|
|
1197
|
+
}
|
|
1198
|
+
break;
|
|
1199
|
+
case "user":
|
|
1200
|
+
userArgs = argv.slice(0);
|
|
1201
|
+
break;
|
|
1202
|
+
case "eval":
|
|
1203
|
+
userArgs = argv.slice(1);
|
|
1204
|
+
break;
|
|
1205
|
+
default:
|
|
1206
|
+
throw new Error(`unexpected parse option { from: '${parseOptions.from}' }`);
|
|
1207
|
+
}
|
|
1208
|
+
if (!this._name && this._scriptPath)
|
|
1209
|
+
this.nameFromFilename(this._scriptPath);
|
|
1210
|
+
this._name = this._name || "program";
|
|
1211
|
+
return userArgs;
|
|
1212
|
+
}
|
|
1213
|
+
parse(argv, parseOptions) {
|
|
1214
|
+
this._prepareForParse();
|
|
1215
|
+
const userArgs = this._prepareUserArgs(argv, parseOptions);
|
|
1216
|
+
this._parseCommand([], userArgs);
|
|
1217
|
+
return this;
|
|
1218
|
+
}
|
|
1219
|
+
async parseAsync(argv, parseOptions) {
|
|
1220
|
+
this._prepareForParse();
|
|
1221
|
+
const userArgs = this._prepareUserArgs(argv, parseOptions);
|
|
1222
|
+
await this._parseCommand([], userArgs);
|
|
1223
|
+
return this;
|
|
1224
|
+
}
|
|
1225
|
+
_prepareForParse() {
|
|
1226
|
+
if (this._savedState === null) {
|
|
1227
|
+
this.saveStateBeforeParse();
|
|
1228
|
+
} else {
|
|
1229
|
+
this.restoreStateBeforeParse();
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
saveStateBeforeParse() {
|
|
1233
|
+
this._savedState = {
|
|
1234
|
+
_name: this._name,
|
|
1235
|
+
_optionValues: { ...this._optionValues },
|
|
1236
|
+
_optionValueSources: { ...this._optionValueSources }
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
restoreStateBeforeParse() {
|
|
1240
|
+
if (this._storeOptionsAsProperties)
|
|
1241
|
+
throw new Error(`Can not call parse again when storeOptionsAsProperties is true.
|
|
1242
|
+
- either make a new Command for each call to parse, or stop storing options as properties`);
|
|
1243
|
+
this._name = this._savedState._name;
|
|
1244
|
+
this._scriptPath = null;
|
|
1245
|
+
this.rawArgs = [];
|
|
1246
|
+
this._optionValues = { ...this._savedState._optionValues };
|
|
1247
|
+
this._optionValueSources = { ...this._savedState._optionValueSources };
|
|
1248
|
+
this.args = [];
|
|
1249
|
+
this.processedArgs = [];
|
|
1250
|
+
}
|
|
1251
|
+
_checkForMissingExecutable(executableFile, executableDir, subcommandName) {
|
|
1252
|
+
if (fs.existsSync(executableFile))
|
|
1253
|
+
return;
|
|
1254
|
+
const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
|
|
1255
|
+
const executableMissing = `'${executableFile}' does not exist
|
|
1256
|
+
- if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
1257
|
+
- if the default executable name is not suitable, use the executableFile option to supply a custom name or path
|
|
1258
|
+
- ${executableDirMessage}`;
|
|
1259
|
+
throw new Error(executableMissing);
|
|
1260
|
+
}
|
|
1261
|
+
_executeSubCommand(subcommand, args) {
|
|
1262
|
+
args = args.slice();
|
|
1263
|
+
let launchWithNode = false;
|
|
1264
|
+
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1265
|
+
function findFile(baseDir, baseName) {
|
|
1266
|
+
const localBin = path.resolve(baseDir, baseName);
|
|
1267
|
+
if (fs.existsSync(localBin))
|
|
1268
|
+
return localBin;
|
|
1269
|
+
if (sourceExt.includes(path.extname(baseName)))
|
|
1270
|
+
return;
|
|
1271
|
+
const foundExt = sourceExt.find((ext) => fs.existsSync(`${localBin}${ext}`));
|
|
1272
|
+
if (foundExt)
|
|
1273
|
+
return `${localBin}${foundExt}`;
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
this._checkForMissingMandatoryOptions();
|
|
1277
|
+
this._checkForConflictingOptions();
|
|
1278
|
+
let executableFile = subcommand._executableFile || `${this._name}-${subcommand._name}`;
|
|
1279
|
+
let executableDir = this._executableDir || "";
|
|
1280
|
+
if (this._scriptPath) {
|
|
1281
|
+
let resolvedScriptPath;
|
|
1282
|
+
try {
|
|
1283
|
+
resolvedScriptPath = fs.realpathSync(this._scriptPath);
|
|
1284
|
+
} catch {
|
|
1285
|
+
resolvedScriptPath = this._scriptPath;
|
|
1286
|
+
}
|
|
1287
|
+
executableDir = path.resolve(path.dirname(resolvedScriptPath), executableDir);
|
|
1288
|
+
}
|
|
1289
|
+
if (executableDir) {
|
|
1290
|
+
let localFile = findFile(executableDir, executableFile);
|
|
1291
|
+
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1292
|
+
const legacyName = path.basename(this._scriptPath, path.extname(this._scriptPath));
|
|
1293
|
+
if (legacyName !== this._name) {
|
|
1294
|
+
localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
executableFile = localFile || executableFile;
|
|
1298
|
+
}
|
|
1299
|
+
launchWithNode = sourceExt.includes(path.extname(executableFile));
|
|
1300
|
+
let proc;
|
|
1301
|
+
if (process2.platform !== "win32") {
|
|
1302
|
+
if (launchWithNode) {
|
|
1303
|
+
args.unshift(executableFile);
|
|
1304
|
+
args = incrementNodeInspectorPort(process2.execArgv).concat(args);
|
|
1305
|
+
proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
|
|
1306
|
+
} else {
|
|
1307
|
+
proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
|
|
1308
|
+
}
|
|
1309
|
+
} else {
|
|
1310
|
+
this._checkForMissingExecutable(executableFile, executableDir, subcommand._name);
|
|
1311
|
+
args.unshift(executableFile);
|
|
1312
|
+
args = incrementNodeInspectorPort(process2.execArgv).concat(args);
|
|
1313
|
+
proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
|
|
1314
|
+
}
|
|
1315
|
+
if (!proc.killed) {
|
|
1316
|
+
const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
|
|
1317
|
+
signals.forEach((signal) => {
|
|
1318
|
+
process2.on(signal, () => {
|
|
1319
|
+
if (proc.killed === false && proc.exitCode === null) {
|
|
1320
|
+
proc.kill(signal);
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
const exitCallback = this._exitCallback;
|
|
1326
|
+
proc.on("close", (code) => {
|
|
1327
|
+
code = code ?? 1;
|
|
1328
|
+
if (!exitCallback) {
|
|
1329
|
+
process2.exit(code);
|
|
1330
|
+
} else {
|
|
1331
|
+
exitCallback(new CommanderError(code, "commander.executeSubCommandAsync", "(close)"));
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
proc.on("error", (err) => {
|
|
1335
|
+
if (err.code === "ENOENT") {
|
|
1336
|
+
this._checkForMissingExecutable(executableFile, executableDir, subcommand._name);
|
|
1337
|
+
} else if (err.code === "EACCES") {
|
|
1338
|
+
throw new Error(`'${executableFile}' not executable`);
|
|
1339
|
+
}
|
|
1340
|
+
if (!exitCallback) {
|
|
1341
|
+
process2.exit(1);
|
|
1342
|
+
} else {
|
|
1343
|
+
const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
|
|
1344
|
+
wrappedError.nestedError = err;
|
|
1345
|
+
exitCallback(wrappedError);
|
|
1346
|
+
}
|
|
1347
|
+
});
|
|
1348
|
+
this.runningCommand = proc;
|
|
1349
|
+
}
|
|
1350
|
+
_dispatchSubcommand(commandName, operands, unknown) {
|
|
1351
|
+
const subCommand = this._findCommand(commandName);
|
|
1352
|
+
if (!subCommand)
|
|
1353
|
+
this.help({ error: true });
|
|
1354
|
+
subCommand._prepareForParse();
|
|
1355
|
+
let promiseChain;
|
|
1356
|
+
promiseChain = this._chainOrCallSubCommandHook(promiseChain, subCommand, "preSubcommand");
|
|
1357
|
+
promiseChain = this._chainOrCall(promiseChain, () => {
|
|
1358
|
+
if (subCommand._executableHandler) {
|
|
1359
|
+
this._executeSubCommand(subCommand, operands.concat(unknown));
|
|
1360
|
+
} else {
|
|
1361
|
+
return subCommand._parseCommand(operands, unknown);
|
|
1362
|
+
}
|
|
1363
|
+
});
|
|
1364
|
+
return promiseChain;
|
|
1365
|
+
}
|
|
1366
|
+
_dispatchHelpCommand(subcommandName) {
|
|
1367
|
+
if (!subcommandName) {
|
|
1368
|
+
this.help();
|
|
1369
|
+
}
|
|
1370
|
+
const subCommand = this._findCommand(subcommandName);
|
|
1371
|
+
if (subCommand && !subCommand._executableHandler) {
|
|
1372
|
+
subCommand.help();
|
|
1373
|
+
}
|
|
1374
|
+
return this._dispatchSubcommand(subcommandName, [], [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? "--help"]);
|
|
1375
|
+
}
|
|
1376
|
+
_checkNumberOfArguments() {
|
|
1377
|
+
this.registeredArguments.forEach((arg, i) => {
|
|
1378
|
+
if (arg.required && this.args[i] == null) {
|
|
1379
|
+
this.missingArgument(arg.name());
|
|
1380
|
+
}
|
|
1381
|
+
});
|
|
1382
|
+
if (this.registeredArguments.length > 0 && this.registeredArguments[this.registeredArguments.length - 1].variadic) {
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
if (this.args.length > this.registeredArguments.length) {
|
|
1386
|
+
this._excessArguments(this.args);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
_processArguments() {
|
|
1390
|
+
const myParseArg = (argument, value, previous) => {
|
|
1391
|
+
let parsedValue = value;
|
|
1392
|
+
if (value !== null && argument.parseArg) {
|
|
1393
|
+
const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;
|
|
1394
|
+
parsedValue = this._callParseArg(argument, value, previous, invalidValueMessage);
|
|
1395
|
+
}
|
|
1396
|
+
return parsedValue;
|
|
1397
|
+
};
|
|
1398
|
+
this._checkNumberOfArguments();
|
|
1399
|
+
const processedArgs = [];
|
|
1400
|
+
this.registeredArguments.forEach((declaredArg, index) => {
|
|
1401
|
+
let value = declaredArg.defaultValue;
|
|
1402
|
+
if (declaredArg.variadic) {
|
|
1403
|
+
if (index < this.args.length) {
|
|
1404
|
+
value = this.args.slice(index);
|
|
1405
|
+
if (declaredArg.parseArg) {
|
|
1406
|
+
value = value.reduce((processed, v) => {
|
|
1407
|
+
return myParseArg(declaredArg, v, processed);
|
|
1408
|
+
}, declaredArg.defaultValue);
|
|
1409
|
+
}
|
|
1410
|
+
} else if (value === undefined) {
|
|
1411
|
+
value = [];
|
|
1412
|
+
}
|
|
1413
|
+
} else if (index < this.args.length) {
|
|
1414
|
+
value = this.args[index];
|
|
1415
|
+
if (declaredArg.parseArg) {
|
|
1416
|
+
value = myParseArg(declaredArg, value, declaredArg.defaultValue);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
processedArgs[index] = value;
|
|
1420
|
+
});
|
|
1421
|
+
this.processedArgs = processedArgs;
|
|
1422
|
+
}
|
|
1423
|
+
_chainOrCall(promise, fn) {
|
|
1424
|
+
if (promise && promise.then && typeof promise.then === "function") {
|
|
1425
|
+
return promise.then(() => fn());
|
|
1426
|
+
}
|
|
1427
|
+
return fn();
|
|
1428
|
+
}
|
|
1429
|
+
_chainOrCallHooks(promise, event) {
|
|
1430
|
+
let result = promise;
|
|
1431
|
+
const hooks = [];
|
|
1432
|
+
this._getCommandAndAncestors().reverse().filter((cmd) => cmd._lifeCycleHooks[event] !== undefined).forEach((hookedCommand) => {
|
|
1433
|
+
hookedCommand._lifeCycleHooks[event].forEach((callback) => {
|
|
1434
|
+
hooks.push({ hookedCommand, callback });
|
|
1435
|
+
});
|
|
1436
|
+
});
|
|
1437
|
+
if (event === "postAction") {
|
|
1438
|
+
hooks.reverse();
|
|
1439
|
+
}
|
|
1440
|
+
hooks.forEach((hookDetail) => {
|
|
1441
|
+
result = this._chainOrCall(result, () => {
|
|
1442
|
+
return hookDetail.callback(hookDetail.hookedCommand, this);
|
|
1443
|
+
});
|
|
1444
|
+
});
|
|
1445
|
+
return result;
|
|
1446
|
+
}
|
|
1447
|
+
_chainOrCallSubCommandHook(promise, subCommand, event) {
|
|
1448
|
+
let result = promise;
|
|
1449
|
+
if (this._lifeCycleHooks[event] !== undefined) {
|
|
1450
|
+
this._lifeCycleHooks[event].forEach((hook) => {
|
|
1451
|
+
result = this._chainOrCall(result, () => {
|
|
1452
|
+
return hook(this, subCommand);
|
|
1453
|
+
});
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
return result;
|
|
1457
|
+
}
|
|
1458
|
+
_parseCommand(operands, unknown) {
|
|
1459
|
+
const parsed = this.parseOptions(unknown);
|
|
1460
|
+
this._parseOptionsEnv();
|
|
1461
|
+
this._parseOptionsImplied();
|
|
1462
|
+
operands = operands.concat(parsed.operands);
|
|
1463
|
+
unknown = parsed.unknown;
|
|
1464
|
+
this.args = operands.concat(unknown);
|
|
1465
|
+
if (operands && this._findCommand(operands[0])) {
|
|
1466
|
+
return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);
|
|
1467
|
+
}
|
|
1468
|
+
if (this._getHelpCommand() && operands[0] === this._getHelpCommand().name()) {
|
|
1469
|
+
return this._dispatchHelpCommand(operands[1]);
|
|
1470
|
+
}
|
|
1471
|
+
if (this._defaultCommandName) {
|
|
1472
|
+
this._outputHelpIfRequested(unknown);
|
|
1473
|
+
return this._dispatchSubcommand(this._defaultCommandName, operands, unknown);
|
|
1474
|
+
}
|
|
1475
|
+
if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
|
|
1476
|
+
this.help({ error: true });
|
|
1477
|
+
}
|
|
1478
|
+
this._outputHelpIfRequested(parsed.unknown);
|
|
1479
|
+
this._checkForMissingMandatoryOptions();
|
|
1480
|
+
this._checkForConflictingOptions();
|
|
1481
|
+
const checkForUnknownOptions = () => {
|
|
1482
|
+
if (parsed.unknown.length > 0) {
|
|
1483
|
+
this.unknownOption(parsed.unknown[0]);
|
|
1484
|
+
}
|
|
1485
|
+
};
|
|
1486
|
+
const commandEvent = `command:${this.name()}`;
|
|
1487
|
+
if (this._actionHandler) {
|
|
1488
|
+
checkForUnknownOptions();
|
|
1489
|
+
this._processArguments();
|
|
1490
|
+
let promiseChain;
|
|
1491
|
+
promiseChain = this._chainOrCallHooks(promiseChain, "preAction");
|
|
1492
|
+
promiseChain = this._chainOrCall(promiseChain, () => this._actionHandler(this.processedArgs));
|
|
1493
|
+
if (this.parent) {
|
|
1494
|
+
promiseChain = this._chainOrCall(promiseChain, () => {
|
|
1495
|
+
this.parent.emit(commandEvent, operands, unknown);
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
promiseChain = this._chainOrCallHooks(promiseChain, "postAction");
|
|
1499
|
+
return promiseChain;
|
|
1500
|
+
}
|
|
1501
|
+
if (this.parent && this.parent.listenerCount(commandEvent)) {
|
|
1502
|
+
checkForUnknownOptions();
|
|
1503
|
+
this._processArguments();
|
|
1504
|
+
this.parent.emit(commandEvent, operands, unknown);
|
|
1505
|
+
} else if (operands.length) {
|
|
1506
|
+
if (this._findCommand("*")) {
|
|
1507
|
+
return this._dispatchSubcommand("*", operands, unknown);
|
|
1508
|
+
}
|
|
1509
|
+
if (this.listenerCount("command:*")) {
|
|
1510
|
+
this.emit("command:*", operands, unknown);
|
|
1511
|
+
} else if (this.commands.length) {
|
|
1512
|
+
this.unknownCommand();
|
|
1513
|
+
} else {
|
|
1514
|
+
checkForUnknownOptions();
|
|
1515
|
+
this._processArguments();
|
|
1516
|
+
}
|
|
1517
|
+
} else if (this.commands.length) {
|
|
1518
|
+
checkForUnknownOptions();
|
|
1519
|
+
this.help({ error: true });
|
|
1520
|
+
} else {
|
|
1521
|
+
checkForUnknownOptions();
|
|
1522
|
+
this._processArguments();
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
_findCommand(name) {
|
|
1526
|
+
if (!name)
|
|
1527
|
+
return;
|
|
1528
|
+
return this.commands.find((cmd) => cmd._name === name || cmd._aliases.includes(name));
|
|
1529
|
+
}
|
|
1530
|
+
_findOption(arg) {
|
|
1531
|
+
return this.options.find((option) => option.is(arg));
|
|
1532
|
+
}
|
|
1533
|
+
_checkForMissingMandatoryOptions() {
|
|
1534
|
+
this._getCommandAndAncestors().forEach((cmd) => {
|
|
1535
|
+
cmd.options.forEach((anOption) => {
|
|
1536
|
+
if (anOption.mandatory && cmd.getOptionValue(anOption.attributeName()) === undefined) {
|
|
1537
|
+
cmd.missingMandatoryOptionValue(anOption);
|
|
1538
|
+
}
|
|
1539
|
+
});
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
_checkForConflictingLocalOptions() {
|
|
1543
|
+
const definedNonDefaultOptions = this.options.filter((option) => {
|
|
1544
|
+
const optionKey = option.attributeName();
|
|
1545
|
+
if (this.getOptionValue(optionKey) === undefined) {
|
|
1546
|
+
return false;
|
|
1547
|
+
}
|
|
1548
|
+
return this.getOptionValueSource(optionKey) !== "default";
|
|
1549
|
+
});
|
|
1550
|
+
const optionsWithConflicting = definedNonDefaultOptions.filter((option) => option.conflictsWith.length > 0);
|
|
1551
|
+
optionsWithConflicting.forEach((option) => {
|
|
1552
|
+
const conflictingAndDefined = definedNonDefaultOptions.find((defined) => option.conflictsWith.includes(defined.attributeName()));
|
|
1553
|
+
if (conflictingAndDefined) {
|
|
1554
|
+
this._conflictingOption(option, conflictingAndDefined);
|
|
1555
|
+
}
|
|
1556
|
+
});
|
|
1557
|
+
}
|
|
1558
|
+
_checkForConflictingOptions() {
|
|
1559
|
+
this._getCommandAndAncestors().forEach((cmd) => {
|
|
1560
|
+
cmd._checkForConflictingLocalOptions();
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
parseOptions(argv) {
|
|
1564
|
+
const operands = [];
|
|
1565
|
+
const unknown = [];
|
|
1566
|
+
let dest = operands;
|
|
1567
|
+
const args = argv.slice();
|
|
1568
|
+
function maybeOption(arg) {
|
|
1569
|
+
return arg.length > 1 && arg[0] === "-";
|
|
1570
|
+
}
|
|
1571
|
+
let activeVariadicOption = null;
|
|
1572
|
+
while (args.length) {
|
|
1573
|
+
const arg = args.shift();
|
|
1574
|
+
if (arg === "--") {
|
|
1575
|
+
if (dest === unknown)
|
|
1576
|
+
dest.push(arg);
|
|
1577
|
+
dest.push(...args);
|
|
1578
|
+
break;
|
|
1579
|
+
}
|
|
1580
|
+
if (activeVariadicOption && !maybeOption(arg)) {
|
|
1581
|
+
this.emit(`option:${activeVariadicOption.name()}`, arg);
|
|
1582
|
+
continue;
|
|
1583
|
+
}
|
|
1584
|
+
activeVariadicOption = null;
|
|
1585
|
+
if (maybeOption(arg)) {
|
|
1586
|
+
const option = this._findOption(arg);
|
|
1587
|
+
if (option) {
|
|
1588
|
+
if (option.required) {
|
|
1589
|
+
const value = args.shift();
|
|
1590
|
+
if (value === undefined)
|
|
1591
|
+
this.optionMissingArgument(option);
|
|
1592
|
+
this.emit(`option:${option.name()}`, value);
|
|
1593
|
+
} else if (option.optional) {
|
|
1594
|
+
let value = null;
|
|
1595
|
+
if (args.length > 0 && !maybeOption(args[0])) {
|
|
1596
|
+
value = args.shift();
|
|
1597
|
+
}
|
|
1598
|
+
this.emit(`option:${option.name()}`, value);
|
|
1599
|
+
} else {
|
|
1600
|
+
this.emit(`option:${option.name()}`);
|
|
1601
|
+
}
|
|
1602
|
+
activeVariadicOption = option.variadic ? option : null;
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
if (arg.length > 2 && arg[0] === "-" && arg[1] !== "-") {
|
|
1607
|
+
const option = this._findOption(`-${arg[1]}`);
|
|
1608
|
+
if (option) {
|
|
1609
|
+
if (option.required || option.optional && this._combineFlagAndOptionalValue) {
|
|
1610
|
+
this.emit(`option:${option.name()}`, arg.slice(2));
|
|
1611
|
+
} else {
|
|
1612
|
+
this.emit(`option:${option.name()}`);
|
|
1613
|
+
args.unshift(`-${arg.slice(2)}`);
|
|
1614
|
+
}
|
|
1615
|
+
continue;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
if (/^--[^=]+=/.test(arg)) {
|
|
1619
|
+
const index = arg.indexOf("=");
|
|
1620
|
+
const option = this._findOption(arg.slice(0, index));
|
|
1621
|
+
if (option && (option.required || option.optional)) {
|
|
1622
|
+
this.emit(`option:${option.name()}`, arg.slice(index + 1));
|
|
1623
|
+
continue;
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
if (maybeOption(arg)) {
|
|
1627
|
+
dest = unknown;
|
|
1628
|
+
}
|
|
1629
|
+
if ((this._enablePositionalOptions || this._passThroughOptions) && operands.length === 0 && unknown.length === 0) {
|
|
1630
|
+
if (this._findCommand(arg)) {
|
|
1631
|
+
operands.push(arg);
|
|
1632
|
+
if (args.length > 0)
|
|
1633
|
+
unknown.push(...args);
|
|
1634
|
+
break;
|
|
1635
|
+
} else if (this._getHelpCommand() && arg === this._getHelpCommand().name()) {
|
|
1636
|
+
operands.push(arg);
|
|
1637
|
+
if (args.length > 0)
|
|
1638
|
+
operands.push(...args);
|
|
1639
|
+
break;
|
|
1640
|
+
} else if (this._defaultCommandName) {
|
|
1641
|
+
unknown.push(arg);
|
|
1642
|
+
if (args.length > 0)
|
|
1643
|
+
unknown.push(...args);
|
|
1644
|
+
break;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
if (this._passThroughOptions) {
|
|
1648
|
+
dest.push(arg);
|
|
1649
|
+
if (args.length > 0)
|
|
1650
|
+
dest.push(...args);
|
|
1651
|
+
break;
|
|
1652
|
+
}
|
|
1653
|
+
dest.push(arg);
|
|
1654
|
+
}
|
|
1655
|
+
return { operands, unknown };
|
|
1656
|
+
}
|
|
1657
|
+
opts() {
|
|
1658
|
+
if (this._storeOptionsAsProperties) {
|
|
1659
|
+
const result = {};
|
|
1660
|
+
const len = this.options.length;
|
|
1661
|
+
for (let i = 0;i < len; i++) {
|
|
1662
|
+
const key = this.options[i].attributeName();
|
|
1663
|
+
result[key] = key === this._versionOptionName ? this._version : this[key];
|
|
1664
|
+
}
|
|
1665
|
+
return result;
|
|
1666
|
+
}
|
|
1667
|
+
return this._optionValues;
|
|
1668
|
+
}
|
|
1669
|
+
optsWithGlobals() {
|
|
1670
|
+
return this._getCommandAndAncestors().reduce((combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()), {});
|
|
1671
|
+
}
|
|
1672
|
+
error(message, errorOptions) {
|
|
1673
|
+
this._outputConfiguration.outputError(`${message}
|
|
1674
|
+
`, this._outputConfiguration.writeErr);
|
|
1675
|
+
if (typeof this._showHelpAfterError === "string") {
|
|
1676
|
+
this._outputConfiguration.writeErr(`${this._showHelpAfterError}
|
|
1677
|
+
`);
|
|
1678
|
+
} else if (this._showHelpAfterError) {
|
|
1679
|
+
this._outputConfiguration.writeErr(`
|
|
1680
|
+
`);
|
|
1681
|
+
this.outputHelp({ error: true });
|
|
1682
|
+
}
|
|
1683
|
+
const config = errorOptions || {};
|
|
1684
|
+
const exitCode = config.exitCode || 1;
|
|
1685
|
+
const code = config.code || "commander.error";
|
|
1686
|
+
this._exit(exitCode, code, message);
|
|
1687
|
+
}
|
|
1688
|
+
_parseOptionsEnv() {
|
|
1689
|
+
this.options.forEach((option) => {
|
|
1690
|
+
if (option.envVar && option.envVar in process2.env) {
|
|
1691
|
+
const optionKey = option.attributeName();
|
|
1692
|
+
if (this.getOptionValue(optionKey) === undefined || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
|
|
1693
|
+
if (option.required || option.optional) {
|
|
1694
|
+
this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
|
|
1695
|
+
} else {
|
|
1696
|
+
this.emit(`optionEnv:${option.name()}`);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1702
|
+
_parseOptionsImplied() {
|
|
1703
|
+
const dualHelper = new DualOptions(this.options);
|
|
1704
|
+
const hasCustomOptionValue = (optionKey) => {
|
|
1705
|
+
return this.getOptionValue(optionKey) !== undefined && !["default", "implied"].includes(this.getOptionValueSource(optionKey));
|
|
1706
|
+
};
|
|
1707
|
+
this.options.filter((option) => option.implied !== undefined && hasCustomOptionValue(option.attributeName()) && dualHelper.valueFromOption(this.getOptionValue(option.attributeName()), option)).forEach((option) => {
|
|
1708
|
+
Object.keys(option.implied).filter((impliedKey) => !hasCustomOptionValue(impliedKey)).forEach((impliedKey) => {
|
|
1709
|
+
this.setOptionValueWithSource(impliedKey, option.implied[impliedKey], "implied");
|
|
1710
|
+
});
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
missingArgument(name) {
|
|
1714
|
+
const message = `error: missing required argument '${name}'`;
|
|
1715
|
+
this.error(message, { code: "commander.missingArgument" });
|
|
1716
|
+
}
|
|
1717
|
+
optionMissingArgument(option) {
|
|
1718
|
+
const message = `error: option '${option.flags}' argument missing`;
|
|
1719
|
+
this.error(message, { code: "commander.optionMissingArgument" });
|
|
1720
|
+
}
|
|
1721
|
+
missingMandatoryOptionValue(option) {
|
|
1722
|
+
const message = `error: required option '${option.flags}' not specified`;
|
|
1723
|
+
this.error(message, { code: "commander.missingMandatoryOptionValue" });
|
|
1724
|
+
}
|
|
1725
|
+
_conflictingOption(option, conflictingOption) {
|
|
1726
|
+
const findBestOptionFromValue = (option2) => {
|
|
1727
|
+
const optionKey = option2.attributeName();
|
|
1728
|
+
const optionValue = this.getOptionValue(optionKey);
|
|
1729
|
+
const negativeOption = this.options.find((target) => target.negate && optionKey === target.attributeName());
|
|
1730
|
+
const positiveOption = this.options.find((target) => !target.negate && optionKey === target.attributeName());
|
|
1731
|
+
if (negativeOption && (negativeOption.presetArg === undefined && optionValue === false || negativeOption.presetArg !== undefined && optionValue === negativeOption.presetArg)) {
|
|
1732
|
+
return negativeOption;
|
|
1733
|
+
}
|
|
1734
|
+
return positiveOption || option2;
|
|
1735
|
+
};
|
|
1736
|
+
const getErrorMessage = (option2) => {
|
|
1737
|
+
const bestOption = findBestOptionFromValue(option2);
|
|
1738
|
+
const optionKey = bestOption.attributeName();
|
|
1739
|
+
const source = this.getOptionValueSource(optionKey);
|
|
1740
|
+
if (source === "env") {
|
|
1741
|
+
return `environment variable '${bestOption.envVar}'`;
|
|
1742
|
+
}
|
|
1743
|
+
return `option '${bestOption.flags}'`;
|
|
1744
|
+
};
|
|
1745
|
+
const message = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;
|
|
1746
|
+
this.error(message, { code: "commander.conflictingOption" });
|
|
1747
|
+
}
|
|
1748
|
+
unknownOption(flag) {
|
|
1749
|
+
if (this._allowUnknownOption)
|
|
1750
|
+
return;
|
|
1751
|
+
let suggestion = "";
|
|
1752
|
+
if (flag.startsWith("--") && this._showSuggestionAfterError) {
|
|
1753
|
+
let candidateFlags = [];
|
|
1754
|
+
let command = this;
|
|
1755
|
+
do {
|
|
1756
|
+
const moreFlags = command.createHelp().visibleOptions(command).filter((option) => option.long).map((option) => option.long);
|
|
1757
|
+
candidateFlags = candidateFlags.concat(moreFlags);
|
|
1758
|
+
command = command.parent;
|
|
1759
|
+
} while (command && !command._enablePositionalOptions);
|
|
1760
|
+
suggestion = suggestSimilar(flag, candidateFlags);
|
|
1761
|
+
}
|
|
1762
|
+
const message = `error: unknown option '${flag}'${suggestion}`;
|
|
1763
|
+
this.error(message, { code: "commander.unknownOption" });
|
|
1764
|
+
}
|
|
1765
|
+
_excessArguments(receivedArgs) {
|
|
1766
|
+
if (this._allowExcessArguments)
|
|
1767
|
+
return;
|
|
1768
|
+
const expected = this.registeredArguments.length;
|
|
1769
|
+
const s = expected === 1 ? "" : "s";
|
|
1770
|
+
const forSubcommand = this.parent ? ` for '${this.name()}'` : "";
|
|
1771
|
+
const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${receivedArgs.length}.`;
|
|
1772
|
+
this.error(message, { code: "commander.excessArguments" });
|
|
1773
|
+
}
|
|
1774
|
+
unknownCommand() {
|
|
1775
|
+
const unknownName = this.args[0];
|
|
1776
|
+
let suggestion = "";
|
|
1777
|
+
if (this._showSuggestionAfterError) {
|
|
1778
|
+
const candidateNames = [];
|
|
1779
|
+
this.createHelp().visibleCommands(this).forEach((command) => {
|
|
1780
|
+
candidateNames.push(command.name());
|
|
1781
|
+
if (command.alias())
|
|
1782
|
+
candidateNames.push(command.alias());
|
|
1783
|
+
});
|
|
1784
|
+
suggestion = suggestSimilar(unknownName, candidateNames);
|
|
1785
|
+
}
|
|
1786
|
+
const message = `error: unknown command '${unknownName}'${suggestion}`;
|
|
1787
|
+
this.error(message, { code: "commander.unknownCommand" });
|
|
1788
|
+
}
|
|
1789
|
+
version(str, flags, description) {
|
|
1790
|
+
if (str === undefined)
|
|
1791
|
+
return this._version;
|
|
1792
|
+
this._version = str;
|
|
1793
|
+
flags = flags || "-V, --version";
|
|
1794
|
+
description = description || "output the version number";
|
|
1795
|
+
const versionOption = this.createOption(flags, description);
|
|
1796
|
+
this._versionOptionName = versionOption.attributeName();
|
|
1797
|
+
this._registerOption(versionOption);
|
|
1798
|
+
this.on("option:" + versionOption.name(), () => {
|
|
1799
|
+
this._outputConfiguration.writeOut(`${str}
|
|
1800
|
+
`);
|
|
1801
|
+
this._exit(0, "commander.version", str);
|
|
1802
|
+
});
|
|
1803
|
+
return this;
|
|
1804
|
+
}
|
|
1805
|
+
description(str, argsDescription) {
|
|
1806
|
+
if (str === undefined && argsDescription === undefined)
|
|
1807
|
+
return this._description;
|
|
1808
|
+
this._description = str;
|
|
1809
|
+
if (argsDescription) {
|
|
1810
|
+
this._argsDescription = argsDescription;
|
|
1811
|
+
}
|
|
1812
|
+
return this;
|
|
1813
|
+
}
|
|
1814
|
+
summary(str) {
|
|
1815
|
+
if (str === undefined)
|
|
1816
|
+
return this._summary;
|
|
1817
|
+
this._summary = str;
|
|
1818
|
+
return this;
|
|
1819
|
+
}
|
|
1820
|
+
alias(alias) {
|
|
1821
|
+
if (alias === undefined)
|
|
1822
|
+
return this._aliases[0];
|
|
1823
|
+
let command = this;
|
|
1824
|
+
if (this.commands.length !== 0 && this.commands[this.commands.length - 1]._executableHandler) {
|
|
1825
|
+
command = this.commands[this.commands.length - 1];
|
|
1826
|
+
}
|
|
1827
|
+
if (alias === command._name)
|
|
1828
|
+
throw new Error("Command alias can't be the same as its name");
|
|
1829
|
+
const matchingCommand = this.parent?._findCommand(alias);
|
|
1830
|
+
if (matchingCommand) {
|
|
1831
|
+
const existingCmd = [matchingCommand.name()].concat(matchingCommand.aliases()).join("|");
|
|
1832
|
+
throw new Error(`cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`);
|
|
1833
|
+
}
|
|
1834
|
+
command._aliases.push(alias);
|
|
1835
|
+
return this;
|
|
1836
|
+
}
|
|
1837
|
+
aliases(aliases) {
|
|
1838
|
+
if (aliases === undefined)
|
|
1839
|
+
return this._aliases;
|
|
1840
|
+
aliases.forEach((alias) => this.alias(alias));
|
|
1841
|
+
return this;
|
|
1842
|
+
}
|
|
1843
|
+
usage(str) {
|
|
1844
|
+
if (str === undefined) {
|
|
1845
|
+
if (this._usage)
|
|
1846
|
+
return this._usage;
|
|
1847
|
+
const args = this.registeredArguments.map((arg) => {
|
|
1848
|
+
return humanReadableArgName(arg);
|
|
1849
|
+
});
|
|
1850
|
+
return [].concat(this.options.length || this._helpOption !== null ? "[options]" : [], this.commands.length ? "[command]" : [], this.registeredArguments.length ? args : []).join(" ");
|
|
1851
|
+
}
|
|
1852
|
+
this._usage = str;
|
|
1853
|
+
return this;
|
|
1854
|
+
}
|
|
1855
|
+
name(str) {
|
|
1856
|
+
if (str === undefined)
|
|
1857
|
+
return this._name;
|
|
1858
|
+
this._name = str;
|
|
1859
|
+
return this;
|
|
1860
|
+
}
|
|
1861
|
+
nameFromFilename(filename) {
|
|
1862
|
+
this._name = path.basename(filename, path.extname(filename));
|
|
1863
|
+
return this;
|
|
1864
|
+
}
|
|
1865
|
+
executableDir(path2) {
|
|
1866
|
+
if (path2 === undefined)
|
|
1867
|
+
return this._executableDir;
|
|
1868
|
+
this._executableDir = path2;
|
|
1869
|
+
return this;
|
|
1870
|
+
}
|
|
1871
|
+
helpInformation(contextOptions) {
|
|
1872
|
+
const helper = this.createHelp();
|
|
1873
|
+
const context = this._getOutputContext(contextOptions);
|
|
1874
|
+
helper.prepareContext({
|
|
1875
|
+
error: context.error,
|
|
1876
|
+
helpWidth: context.helpWidth,
|
|
1877
|
+
outputHasColors: context.hasColors
|
|
1878
|
+
});
|
|
1879
|
+
const text = helper.formatHelp(this, helper);
|
|
1880
|
+
if (context.hasColors)
|
|
1881
|
+
return text;
|
|
1882
|
+
return this._outputConfiguration.stripColor(text);
|
|
1883
|
+
}
|
|
1884
|
+
_getOutputContext(contextOptions) {
|
|
1885
|
+
contextOptions = contextOptions || {};
|
|
1886
|
+
const error = !!contextOptions.error;
|
|
1887
|
+
let baseWrite;
|
|
1888
|
+
let hasColors;
|
|
1889
|
+
let helpWidth;
|
|
1890
|
+
if (error) {
|
|
1891
|
+
baseWrite = (str) => this._outputConfiguration.writeErr(str);
|
|
1892
|
+
hasColors = this._outputConfiguration.getErrHasColors();
|
|
1893
|
+
helpWidth = this._outputConfiguration.getErrHelpWidth();
|
|
1894
|
+
} else {
|
|
1895
|
+
baseWrite = (str) => this._outputConfiguration.writeOut(str);
|
|
1896
|
+
hasColors = this._outputConfiguration.getOutHasColors();
|
|
1897
|
+
helpWidth = this._outputConfiguration.getOutHelpWidth();
|
|
1898
|
+
}
|
|
1899
|
+
const write = (str) => {
|
|
1900
|
+
if (!hasColors)
|
|
1901
|
+
str = this._outputConfiguration.stripColor(str);
|
|
1902
|
+
return baseWrite(str);
|
|
1903
|
+
};
|
|
1904
|
+
return { error, write, hasColors, helpWidth };
|
|
1905
|
+
}
|
|
1906
|
+
outputHelp(contextOptions) {
|
|
1907
|
+
let deprecatedCallback;
|
|
1908
|
+
if (typeof contextOptions === "function") {
|
|
1909
|
+
deprecatedCallback = contextOptions;
|
|
1910
|
+
contextOptions = undefined;
|
|
1911
|
+
}
|
|
1912
|
+
const outputContext = this._getOutputContext(contextOptions);
|
|
1913
|
+
const eventContext = {
|
|
1914
|
+
error: outputContext.error,
|
|
1915
|
+
write: outputContext.write,
|
|
1916
|
+
command: this
|
|
1917
|
+
};
|
|
1918
|
+
this._getCommandAndAncestors().reverse().forEach((command) => command.emit("beforeAllHelp", eventContext));
|
|
1919
|
+
this.emit("beforeHelp", eventContext);
|
|
1920
|
+
let helpInformation = this.helpInformation({ error: outputContext.error });
|
|
1921
|
+
if (deprecatedCallback) {
|
|
1922
|
+
helpInformation = deprecatedCallback(helpInformation);
|
|
1923
|
+
if (typeof helpInformation !== "string" && !Buffer.isBuffer(helpInformation)) {
|
|
1924
|
+
throw new Error("outputHelp callback must return a string or a Buffer");
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
outputContext.write(helpInformation);
|
|
1928
|
+
if (this._getHelpOption()?.long) {
|
|
1929
|
+
this.emit(this._getHelpOption().long);
|
|
1930
|
+
}
|
|
1931
|
+
this.emit("afterHelp", eventContext);
|
|
1932
|
+
this._getCommandAndAncestors().forEach((command) => command.emit("afterAllHelp", eventContext));
|
|
1933
|
+
}
|
|
1934
|
+
helpOption(flags, description) {
|
|
1935
|
+
if (typeof flags === "boolean") {
|
|
1936
|
+
if (flags) {
|
|
1937
|
+
this._helpOption = this._helpOption ?? undefined;
|
|
1938
|
+
} else {
|
|
1939
|
+
this._helpOption = null;
|
|
1940
|
+
}
|
|
1941
|
+
return this;
|
|
1942
|
+
}
|
|
1943
|
+
flags = flags ?? "-h, --help";
|
|
1944
|
+
description = description ?? "display help for command";
|
|
1945
|
+
this._helpOption = this.createOption(flags, description);
|
|
1946
|
+
return this;
|
|
1947
|
+
}
|
|
1948
|
+
_getHelpOption() {
|
|
1949
|
+
if (this._helpOption === undefined) {
|
|
1950
|
+
this.helpOption(undefined, undefined);
|
|
1951
|
+
}
|
|
1952
|
+
return this._helpOption;
|
|
1953
|
+
}
|
|
1954
|
+
addHelpOption(option) {
|
|
1955
|
+
this._helpOption = option;
|
|
1956
|
+
return this;
|
|
1957
|
+
}
|
|
1958
|
+
help(contextOptions) {
|
|
1959
|
+
this.outputHelp(contextOptions);
|
|
1960
|
+
let exitCode = Number(process2.exitCode ?? 0);
|
|
1961
|
+
if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
|
|
1962
|
+
exitCode = 1;
|
|
1963
|
+
}
|
|
1964
|
+
this._exit(exitCode, "commander.help", "(outputHelp)");
|
|
1965
|
+
}
|
|
1966
|
+
addHelpText(position, text) {
|
|
1967
|
+
const allowedValues = ["beforeAll", "before", "after", "afterAll"];
|
|
1968
|
+
if (!allowedValues.includes(position)) {
|
|
1969
|
+
throw new Error(`Unexpected value for position to addHelpText.
|
|
1970
|
+
Expecting one of '${allowedValues.join("', '")}'`);
|
|
1971
|
+
}
|
|
1972
|
+
const helpEvent = `${position}Help`;
|
|
1973
|
+
this.on(helpEvent, (context) => {
|
|
1974
|
+
let helpStr;
|
|
1975
|
+
if (typeof text === "function") {
|
|
1976
|
+
helpStr = text({ error: context.error, command: context.command });
|
|
1977
|
+
} else {
|
|
1978
|
+
helpStr = text;
|
|
1979
|
+
}
|
|
1980
|
+
if (helpStr) {
|
|
1981
|
+
context.write(`${helpStr}
|
|
1982
|
+
`);
|
|
1983
|
+
}
|
|
1984
|
+
});
|
|
1985
|
+
return this;
|
|
1986
|
+
}
|
|
1987
|
+
_outputHelpIfRequested(args) {
|
|
1988
|
+
const helpOption = this._getHelpOption();
|
|
1989
|
+
const helpRequested = helpOption && args.find((arg) => helpOption.is(arg));
|
|
1990
|
+
if (helpRequested) {
|
|
1991
|
+
this.outputHelp();
|
|
1992
|
+
this._exit(0, "commander.helpDisplayed", "(outputHelp)");
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
function incrementNodeInspectorPort(args) {
|
|
1997
|
+
return args.map((arg) => {
|
|
1998
|
+
if (!arg.startsWith("--inspect")) {
|
|
1999
|
+
return arg;
|
|
2000
|
+
}
|
|
2001
|
+
let debugOption;
|
|
2002
|
+
let debugHost = "127.0.0.1";
|
|
2003
|
+
let debugPort = "9229";
|
|
2004
|
+
let match;
|
|
2005
|
+
if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {
|
|
2006
|
+
debugOption = match[1];
|
|
2007
|
+
} else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null) {
|
|
2008
|
+
debugOption = match[1];
|
|
2009
|
+
if (/^\d+$/.test(match[3])) {
|
|
2010
|
+
debugPort = match[3];
|
|
2011
|
+
} else {
|
|
2012
|
+
debugHost = match[3];
|
|
2013
|
+
}
|
|
2014
|
+
} else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/)) !== null) {
|
|
2015
|
+
debugOption = match[1];
|
|
2016
|
+
debugHost = match[3];
|
|
2017
|
+
debugPort = match[4];
|
|
2018
|
+
}
|
|
2019
|
+
if (debugOption && debugPort !== "0") {
|
|
2020
|
+
return `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;
|
|
2021
|
+
}
|
|
2022
|
+
return arg;
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
2025
|
+
function useColor() {
|
|
2026
|
+
if (process2.env.NO_COLOR || process2.env.FORCE_COLOR === "0" || process2.env.FORCE_COLOR === "false")
|
|
2027
|
+
return false;
|
|
2028
|
+
if (process2.env.FORCE_COLOR || process2.env.CLICOLOR_FORCE !== undefined)
|
|
2029
|
+
return true;
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
exports.Command = Command;
|
|
2033
|
+
exports.useColor = useColor;
|
|
2034
|
+
});
|
|
2035
|
+
|
|
2036
|
+
// ../../node_modules/commander/index.js
|
|
2037
|
+
var require_commander = __commonJS((exports) => {
|
|
2038
|
+
var { Argument } = require_argument();
|
|
2039
|
+
var { Command } = require_command();
|
|
2040
|
+
var { CommanderError, InvalidArgumentError } = require_error();
|
|
2041
|
+
var { Help } = require_help();
|
|
2042
|
+
var { Option } = require_option();
|
|
2043
|
+
exports.program = new Command;
|
|
2044
|
+
exports.createCommand = (name) => new Command(name);
|
|
2045
|
+
exports.createOption = (flags, description) => new Option(flags, description);
|
|
2046
|
+
exports.createArgument = (name, description) => new Argument(name, description);
|
|
2047
|
+
exports.Command = Command;
|
|
2048
|
+
exports.Option = Option;
|
|
2049
|
+
exports.Argument = Argument;
|
|
2050
|
+
exports.Help = Help;
|
|
2051
|
+
exports.CommanderError = CommanderError;
|
|
2052
|
+
exports.InvalidArgumentError = InvalidArgumentError;
|
|
2053
|
+
exports.InvalidOptionArgumentError = InvalidArgumentError;
|
|
2054
|
+
});
|
|
2055
|
+
|
|
2056
|
+
// ../../node_modules/commander/esm.mjs
|
|
2057
|
+
var import__ = __toESM(require_commander(), 1);
|
|
2058
|
+
var {
|
|
2059
|
+
program,
|
|
2060
|
+
createCommand,
|
|
2061
|
+
createArgument,
|
|
2062
|
+
createOption,
|
|
2063
|
+
CommanderError,
|
|
2064
|
+
InvalidArgumentError,
|
|
2065
|
+
InvalidOptionArgumentError,
|
|
2066
|
+
Command,
|
|
2067
|
+
Argument,
|
|
2068
|
+
Option,
|
|
2069
|
+
Help
|
|
2070
|
+
} = import__.default;
|
|
2071
|
+
|
|
2072
|
+
// src/index.ts
|
|
2073
|
+
import { readFileSync } from "node:fs";
|
|
2074
|
+
import { fileURLToPath } from "node:url";
|
|
2075
|
+
import { dirname, join } from "node:path";
|
|
2076
|
+
|
|
2077
|
+
// src/config.ts
|
|
2078
|
+
import fs from "node:fs";
|
|
2079
|
+
import os from "node:os";
|
|
2080
|
+
import path from "node:path";
|
|
2081
|
+
var ENV_API_URL = process.env.THOUGHTFUL_API_URL;
|
|
2082
|
+
var ENV_NO_COLOR = process.env.THOUGHTFUL_NO_COLOR === "1" || process.env.THOUGHTFUL_NO_COLOR === "true";
|
|
2083
|
+
var ENV_DEBUG = process.env.THOUGHTFUL_DEBUG === "1" || process.env.THOUGHTFUL_DEBUG === "true";
|
|
2084
|
+
var PRODUCTION_API_URL = "https://www.thoughtful.app";
|
|
2085
|
+
var DEVELOPMENT_API_URL = "http://localhost:3000";
|
|
2086
|
+
var environmentOverride = null;
|
|
2087
|
+
function setEnvironmentOverride(env) {
|
|
2088
|
+
environmentOverride = env;
|
|
2089
|
+
}
|
|
2090
|
+
function getDefaultApiUrl() {
|
|
2091
|
+
if (environmentOverride === "dev") {
|
|
2092
|
+
return DEVELOPMENT_API_URL;
|
|
2093
|
+
}
|
|
2094
|
+
if (environmentOverride === "prod") {
|
|
2095
|
+
return PRODUCTION_API_URL;
|
|
2096
|
+
}
|
|
2097
|
+
if (ENV_API_URL) {
|
|
2098
|
+
return ENV_API_URL;
|
|
2099
|
+
}
|
|
2100
|
+
return PRODUCTION_API_URL;
|
|
2101
|
+
}
|
|
2102
|
+
function getXdgConfigHome() {
|
|
2103
|
+
return process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config");
|
|
2104
|
+
}
|
|
2105
|
+
var LEGACY_CONFIG_DIR = path.join(os.homedir(), ".thoughtful");
|
|
2106
|
+
var LEGACY_CONFIG_FILE = path.join(LEGACY_CONFIG_DIR, "config.json");
|
|
2107
|
+
var CONFIG_DIR = path.join(getXdgConfigHome(), "thoughtful");
|
|
2108
|
+
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
2109
|
+
var env = {
|
|
2110
|
+
noColor: ENV_NO_COLOR,
|
|
2111
|
+
debug: ENV_DEBUG
|
|
2112
|
+
};
|
|
2113
|
+
function migrateLegacyConfig() {
|
|
2114
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
if (fs.existsSync(LEGACY_CONFIG_FILE)) {
|
|
2118
|
+
try {
|
|
2119
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
2120
|
+
fs.copyFileSync(LEGACY_CONFIG_FILE, CONFIG_FILE);
|
|
2121
|
+
fs.chmodSync(CONFIG_FILE, 384);
|
|
2122
|
+
if (env.debug) {
|
|
2123
|
+
console.error(`[DEBUG] Migrated config from ${LEGACY_CONFIG_FILE} to ${CONFIG_FILE}`);
|
|
2124
|
+
}
|
|
2125
|
+
} catch (error) {
|
|
2126
|
+
if (env.debug) {
|
|
2127
|
+
console.error(`[DEBUG] Failed to migrate legacy config: ${error}`);
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
function ensureConfigDir() {
|
|
2133
|
+
migrateLegacyConfig();
|
|
2134
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
2135
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
function loadConfig() {
|
|
2139
|
+
ensureConfigDir();
|
|
2140
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
2141
|
+
return {
|
|
2142
|
+
apiUrl: getDefaultApiUrl()
|
|
2143
|
+
};
|
|
2144
|
+
}
|
|
2145
|
+
try {
|
|
2146
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
2147
|
+
const fileConfig = JSON.parse(content);
|
|
2148
|
+
const config = {
|
|
2149
|
+
apiUrl: PRODUCTION_API_URL,
|
|
2150
|
+
...fileConfig
|
|
2151
|
+
};
|
|
2152
|
+
if (environmentOverride || ENV_API_URL) {
|
|
2153
|
+
config.apiUrl = getDefaultApiUrl();
|
|
2154
|
+
}
|
|
2155
|
+
return config;
|
|
2156
|
+
} catch {
|
|
2157
|
+
return {
|
|
2158
|
+
apiUrl: getDefaultApiUrl()
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
function saveConfig(config) {
|
|
2163
|
+
ensureConfigDir();
|
|
2164
|
+
let fileApiUrl;
|
|
2165
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
2166
|
+
try {
|
|
2167
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
2168
|
+
const fileConfig = JSON.parse(content);
|
|
2169
|
+
fileApiUrl = fileConfig.apiUrl;
|
|
2170
|
+
} catch {}
|
|
2171
|
+
}
|
|
2172
|
+
const configToSave = { ...config };
|
|
2173
|
+
if ((environmentOverride || ENV_API_URL) && fileApiUrl) {
|
|
2174
|
+
const overrideUrl = getDefaultApiUrl();
|
|
2175
|
+
if (config.apiUrl === overrideUrl) {
|
|
2176
|
+
configToSave.apiUrl = fileApiUrl;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(configToSave, null, 2), {
|
|
2180
|
+
mode: 384
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
function updateConfig(updates) {
|
|
2184
|
+
const config = loadConfig();
|
|
2185
|
+
const newConfig = { ...config, ...updates };
|
|
2186
|
+
saveConfig(newConfig);
|
|
2187
|
+
return newConfig;
|
|
2188
|
+
}
|
|
2189
|
+
function clearAuth() {
|
|
2190
|
+
const config = loadConfig();
|
|
2191
|
+
const newConfig = {
|
|
2192
|
+
apiUrl: config.apiUrl
|
|
2193
|
+
};
|
|
2194
|
+
saveConfig(newConfig);
|
|
2195
|
+
}
|
|
2196
|
+
function isLoggedIn() {
|
|
2197
|
+
const config = loadConfig();
|
|
2198
|
+
return Boolean(config.accessToken);
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
// ../../node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
2202
|
+
var ANSI_BACKGROUND_OFFSET = 10;
|
|
2203
|
+
var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
|
|
2204
|
+
var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
|
|
2205
|
+
var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
|
|
2206
|
+
var styles = {
|
|
2207
|
+
modifier: {
|
|
2208
|
+
reset: [0, 0],
|
|
2209
|
+
bold: [1, 22],
|
|
2210
|
+
dim: [2, 22],
|
|
2211
|
+
italic: [3, 23],
|
|
2212
|
+
underline: [4, 24],
|
|
2213
|
+
overline: [53, 55],
|
|
2214
|
+
inverse: [7, 27],
|
|
2215
|
+
hidden: [8, 28],
|
|
2216
|
+
strikethrough: [9, 29]
|
|
2217
|
+
},
|
|
2218
|
+
color: {
|
|
2219
|
+
black: [30, 39],
|
|
2220
|
+
red: [31, 39],
|
|
2221
|
+
green: [32, 39],
|
|
2222
|
+
yellow: [33, 39],
|
|
2223
|
+
blue: [34, 39],
|
|
2224
|
+
magenta: [35, 39],
|
|
2225
|
+
cyan: [36, 39],
|
|
2226
|
+
white: [37, 39],
|
|
2227
|
+
blackBright: [90, 39],
|
|
2228
|
+
gray: [90, 39],
|
|
2229
|
+
grey: [90, 39],
|
|
2230
|
+
redBright: [91, 39],
|
|
2231
|
+
greenBright: [92, 39],
|
|
2232
|
+
yellowBright: [93, 39],
|
|
2233
|
+
blueBright: [94, 39],
|
|
2234
|
+
magentaBright: [95, 39],
|
|
2235
|
+
cyanBright: [96, 39],
|
|
2236
|
+
whiteBright: [97, 39]
|
|
2237
|
+
},
|
|
2238
|
+
bgColor: {
|
|
2239
|
+
bgBlack: [40, 49],
|
|
2240
|
+
bgRed: [41, 49],
|
|
2241
|
+
bgGreen: [42, 49],
|
|
2242
|
+
bgYellow: [43, 49],
|
|
2243
|
+
bgBlue: [44, 49],
|
|
2244
|
+
bgMagenta: [45, 49],
|
|
2245
|
+
bgCyan: [46, 49],
|
|
2246
|
+
bgWhite: [47, 49],
|
|
2247
|
+
bgBlackBright: [100, 49],
|
|
2248
|
+
bgGray: [100, 49],
|
|
2249
|
+
bgGrey: [100, 49],
|
|
2250
|
+
bgRedBright: [101, 49],
|
|
2251
|
+
bgGreenBright: [102, 49],
|
|
2252
|
+
bgYellowBright: [103, 49],
|
|
2253
|
+
bgBlueBright: [104, 49],
|
|
2254
|
+
bgMagentaBright: [105, 49],
|
|
2255
|
+
bgCyanBright: [106, 49],
|
|
2256
|
+
bgWhiteBright: [107, 49]
|
|
2257
|
+
}
|
|
2258
|
+
};
|
|
2259
|
+
var modifierNames = Object.keys(styles.modifier);
|
|
2260
|
+
var foregroundColorNames = Object.keys(styles.color);
|
|
2261
|
+
var backgroundColorNames = Object.keys(styles.bgColor);
|
|
2262
|
+
var colorNames = [...foregroundColorNames, ...backgroundColorNames];
|
|
2263
|
+
function assembleStyles() {
|
|
2264
|
+
const codes = new Map;
|
|
2265
|
+
for (const [groupName, group] of Object.entries(styles)) {
|
|
2266
|
+
for (const [styleName, style] of Object.entries(group)) {
|
|
2267
|
+
styles[styleName] = {
|
|
2268
|
+
open: `\x1B[${style[0]}m`,
|
|
2269
|
+
close: `\x1B[${style[1]}m`
|
|
2270
|
+
};
|
|
2271
|
+
group[styleName] = styles[styleName];
|
|
2272
|
+
codes.set(style[0], style[1]);
|
|
2273
|
+
}
|
|
2274
|
+
Object.defineProperty(styles, groupName, {
|
|
2275
|
+
value: group,
|
|
2276
|
+
enumerable: false
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
Object.defineProperty(styles, "codes", {
|
|
2280
|
+
value: codes,
|
|
2281
|
+
enumerable: false
|
|
2282
|
+
});
|
|
2283
|
+
styles.color.close = "\x1B[39m";
|
|
2284
|
+
styles.bgColor.close = "\x1B[49m";
|
|
2285
|
+
styles.color.ansi = wrapAnsi16();
|
|
2286
|
+
styles.color.ansi256 = wrapAnsi256();
|
|
2287
|
+
styles.color.ansi16m = wrapAnsi16m();
|
|
2288
|
+
styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
|
|
2289
|
+
styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
|
|
2290
|
+
styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
|
|
2291
|
+
Object.defineProperties(styles, {
|
|
2292
|
+
rgbToAnsi256: {
|
|
2293
|
+
value(red, green, blue) {
|
|
2294
|
+
if (red === green && green === blue) {
|
|
2295
|
+
if (red < 8) {
|
|
2296
|
+
return 16;
|
|
2297
|
+
}
|
|
2298
|
+
if (red > 248) {
|
|
2299
|
+
return 231;
|
|
2300
|
+
}
|
|
2301
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
2302
|
+
}
|
|
2303
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
2304
|
+
},
|
|
2305
|
+
enumerable: false
|
|
2306
|
+
},
|
|
2307
|
+
hexToRgb: {
|
|
2308
|
+
value(hex) {
|
|
2309
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
|
|
2310
|
+
if (!matches) {
|
|
2311
|
+
return [0, 0, 0];
|
|
2312
|
+
}
|
|
2313
|
+
let [colorString] = matches;
|
|
2314
|
+
if (colorString.length === 3) {
|
|
2315
|
+
colorString = [...colorString].map((character) => character + character).join("");
|
|
2316
|
+
}
|
|
2317
|
+
const integer = Number.parseInt(colorString, 16);
|
|
2318
|
+
return [
|
|
2319
|
+
integer >> 16 & 255,
|
|
2320
|
+
integer >> 8 & 255,
|
|
2321
|
+
integer & 255
|
|
2322
|
+
];
|
|
2323
|
+
},
|
|
2324
|
+
enumerable: false
|
|
2325
|
+
},
|
|
2326
|
+
hexToAnsi256: {
|
|
2327
|
+
value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
|
|
2328
|
+
enumerable: false
|
|
2329
|
+
},
|
|
2330
|
+
ansi256ToAnsi: {
|
|
2331
|
+
value(code) {
|
|
2332
|
+
if (code < 8) {
|
|
2333
|
+
return 30 + code;
|
|
2334
|
+
}
|
|
2335
|
+
if (code < 16) {
|
|
2336
|
+
return 90 + (code - 8);
|
|
2337
|
+
}
|
|
2338
|
+
let red;
|
|
2339
|
+
let green;
|
|
2340
|
+
let blue;
|
|
2341
|
+
if (code >= 232) {
|
|
2342
|
+
red = ((code - 232) * 10 + 8) / 255;
|
|
2343
|
+
green = red;
|
|
2344
|
+
blue = red;
|
|
2345
|
+
} else {
|
|
2346
|
+
code -= 16;
|
|
2347
|
+
const remainder = code % 36;
|
|
2348
|
+
red = Math.floor(code / 36) / 5;
|
|
2349
|
+
green = Math.floor(remainder / 6) / 5;
|
|
2350
|
+
blue = remainder % 6 / 5;
|
|
2351
|
+
}
|
|
2352
|
+
const value = Math.max(red, green, blue) * 2;
|
|
2353
|
+
if (value === 0) {
|
|
2354
|
+
return 30;
|
|
2355
|
+
}
|
|
2356
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
2357
|
+
if (value === 2) {
|
|
2358
|
+
result += 60;
|
|
2359
|
+
}
|
|
2360
|
+
return result;
|
|
2361
|
+
},
|
|
2362
|
+
enumerable: false
|
|
2363
|
+
},
|
|
2364
|
+
rgbToAnsi: {
|
|
2365
|
+
value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
|
|
2366
|
+
enumerable: false
|
|
2367
|
+
},
|
|
2368
|
+
hexToAnsi: {
|
|
2369
|
+
value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
|
|
2370
|
+
enumerable: false
|
|
2371
|
+
}
|
|
2372
|
+
});
|
|
2373
|
+
return styles;
|
|
2374
|
+
}
|
|
2375
|
+
var ansiStyles = assembleStyles();
|
|
2376
|
+
var ansi_styles_default = ansiStyles;
|
|
2377
|
+
|
|
2378
|
+
// ../../node_modules/chalk/source/vendor/supports-color/index.js
|
|
2379
|
+
import process2 from "node:process";
|
|
2380
|
+
import os2 from "node:os";
|
|
2381
|
+
import tty from "node:tty";
|
|
2382
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
|
|
2383
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
2384
|
+
const position = argv.indexOf(prefix + flag);
|
|
2385
|
+
const terminatorPosition = argv.indexOf("--");
|
|
2386
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
2387
|
+
}
|
|
2388
|
+
var { env: env2 } = process2;
|
|
2389
|
+
var flagForceColor;
|
|
2390
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
2391
|
+
flagForceColor = 0;
|
|
2392
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
2393
|
+
flagForceColor = 1;
|
|
2394
|
+
}
|
|
2395
|
+
function envForceColor() {
|
|
2396
|
+
if ("FORCE_COLOR" in env2) {
|
|
2397
|
+
if (env2.FORCE_COLOR === "true") {
|
|
2398
|
+
return 1;
|
|
2399
|
+
}
|
|
2400
|
+
if (env2.FORCE_COLOR === "false") {
|
|
2401
|
+
return 0;
|
|
2402
|
+
}
|
|
2403
|
+
return env2.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env2.FORCE_COLOR, 10), 3);
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
function translateLevel(level) {
|
|
2407
|
+
if (level === 0) {
|
|
2408
|
+
return false;
|
|
2409
|
+
}
|
|
2410
|
+
return {
|
|
2411
|
+
level,
|
|
2412
|
+
hasBasic: true,
|
|
2413
|
+
has256: level >= 2,
|
|
2414
|
+
has16m: level >= 3
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
2418
|
+
const noFlagForceColor = envForceColor();
|
|
2419
|
+
if (noFlagForceColor !== undefined) {
|
|
2420
|
+
flagForceColor = noFlagForceColor;
|
|
2421
|
+
}
|
|
2422
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
2423
|
+
if (forceColor === 0) {
|
|
2424
|
+
return 0;
|
|
2425
|
+
}
|
|
2426
|
+
if (sniffFlags) {
|
|
2427
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
2428
|
+
return 3;
|
|
2429
|
+
}
|
|
2430
|
+
if (hasFlag("color=256")) {
|
|
2431
|
+
return 2;
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
if ("TF_BUILD" in env2 && "AGENT_NAME" in env2) {
|
|
2435
|
+
return 1;
|
|
2436
|
+
}
|
|
2437
|
+
if (haveStream && !streamIsTTY && forceColor === undefined) {
|
|
2438
|
+
return 0;
|
|
2439
|
+
}
|
|
2440
|
+
const min = forceColor || 0;
|
|
2441
|
+
if (env2.TERM === "dumb") {
|
|
2442
|
+
return min;
|
|
2443
|
+
}
|
|
2444
|
+
if (process2.platform === "win32") {
|
|
2445
|
+
const osRelease = os2.release().split(".");
|
|
2446
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
2447
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
2448
|
+
}
|
|
2449
|
+
return 1;
|
|
2450
|
+
}
|
|
2451
|
+
if ("CI" in env2) {
|
|
2452
|
+
if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => (key in env2))) {
|
|
2453
|
+
return 3;
|
|
2454
|
+
}
|
|
2455
|
+
if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => (sign in env2)) || env2.CI_NAME === "codeship") {
|
|
2456
|
+
return 1;
|
|
2457
|
+
}
|
|
2458
|
+
return min;
|
|
2459
|
+
}
|
|
2460
|
+
if ("TEAMCITY_VERSION" in env2) {
|
|
2461
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env2.TEAMCITY_VERSION) ? 1 : 0;
|
|
2462
|
+
}
|
|
2463
|
+
if (env2.COLORTERM === "truecolor") {
|
|
2464
|
+
return 3;
|
|
2465
|
+
}
|
|
2466
|
+
if (env2.TERM === "xterm-kitty") {
|
|
2467
|
+
return 3;
|
|
2468
|
+
}
|
|
2469
|
+
if (env2.TERM === "xterm-ghostty") {
|
|
2470
|
+
return 3;
|
|
2471
|
+
}
|
|
2472
|
+
if (env2.TERM === "wezterm") {
|
|
2473
|
+
return 3;
|
|
2474
|
+
}
|
|
2475
|
+
if ("TERM_PROGRAM" in env2) {
|
|
2476
|
+
const version = Number.parseInt((env2.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
2477
|
+
switch (env2.TERM_PROGRAM) {
|
|
2478
|
+
case "iTerm.app": {
|
|
2479
|
+
return version >= 3 ? 3 : 2;
|
|
2480
|
+
}
|
|
2481
|
+
case "Apple_Terminal": {
|
|
2482
|
+
return 2;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
if (/-256(color)?$/i.test(env2.TERM)) {
|
|
2487
|
+
return 2;
|
|
2488
|
+
}
|
|
2489
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env2.TERM)) {
|
|
2490
|
+
return 1;
|
|
2491
|
+
}
|
|
2492
|
+
if ("COLORTERM" in env2) {
|
|
2493
|
+
return 1;
|
|
2494
|
+
}
|
|
2495
|
+
return min;
|
|
2496
|
+
}
|
|
2497
|
+
function createSupportsColor(stream, options = {}) {
|
|
2498
|
+
const level = _supportsColor(stream, {
|
|
2499
|
+
streamIsTTY: stream && stream.isTTY,
|
|
2500
|
+
...options
|
|
2501
|
+
});
|
|
2502
|
+
return translateLevel(level);
|
|
2503
|
+
}
|
|
2504
|
+
var supportsColor = {
|
|
2505
|
+
stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
|
|
2506
|
+
stderr: createSupportsColor({ isTTY: tty.isatty(2) })
|
|
2507
|
+
};
|
|
2508
|
+
var supports_color_default = supportsColor;
|
|
2509
|
+
|
|
2510
|
+
// ../../node_modules/chalk/source/utilities.js
|
|
2511
|
+
function stringReplaceAll(string, substring, replacer) {
|
|
2512
|
+
let index = string.indexOf(substring);
|
|
2513
|
+
if (index === -1) {
|
|
2514
|
+
return string;
|
|
2515
|
+
}
|
|
2516
|
+
const substringLength = substring.length;
|
|
2517
|
+
let endIndex = 0;
|
|
2518
|
+
let returnValue = "";
|
|
2519
|
+
do {
|
|
2520
|
+
returnValue += string.slice(endIndex, index) + substring + replacer;
|
|
2521
|
+
endIndex = index + substringLength;
|
|
2522
|
+
index = string.indexOf(substring, endIndex);
|
|
2523
|
+
} while (index !== -1);
|
|
2524
|
+
returnValue += string.slice(endIndex);
|
|
2525
|
+
return returnValue;
|
|
2526
|
+
}
|
|
2527
|
+
function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
2528
|
+
let endIndex = 0;
|
|
2529
|
+
let returnValue = "";
|
|
2530
|
+
do {
|
|
2531
|
+
const gotCR = string[index - 1] === "\r";
|
|
2532
|
+
returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? `\r
|
|
2533
|
+
` : `
|
|
2534
|
+
`) + postfix;
|
|
2535
|
+
endIndex = index + 1;
|
|
2536
|
+
index = string.indexOf(`
|
|
2537
|
+
`, endIndex);
|
|
2538
|
+
} while (index !== -1);
|
|
2539
|
+
returnValue += string.slice(endIndex);
|
|
2540
|
+
return returnValue;
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
// ../../node_modules/chalk/source/index.js
|
|
2544
|
+
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
2545
|
+
var GENERATOR = Symbol("GENERATOR");
|
|
2546
|
+
var STYLER = Symbol("STYLER");
|
|
2547
|
+
var IS_EMPTY = Symbol("IS_EMPTY");
|
|
2548
|
+
var levelMapping = [
|
|
2549
|
+
"ansi",
|
|
2550
|
+
"ansi",
|
|
2551
|
+
"ansi256",
|
|
2552
|
+
"ansi16m"
|
|
2553
|
+
];
|
|
2554
|
+
var styles2 = Object.create(null);
|
|
2555
|
+
var applyOptions = (object, options = {}) => {
|
|
2556
|
+
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
|
|
2557
|
+
throw new Error("The `level` option should be an integer from 0 to 3");
|
|
2558
|
+
}
|
|
2559
|
+
const colorLevel = stdoutColor ? stdoutColor.level : 0;
|
|
2560
|
+
object.level = options.level === undefined ? colorLevel : options.level;
|
|
2561
|
+
};
|
|
2562
|
+
var chalkFactory = (options) => {
|
|
2563
|
+
const chalk = (...strings) => strings.join(" ");
|
|
2564
|
+
applyOptions(chalk, options);
|
|
2565
|
+
Object.setPrototypeOf(chalk, createChalk.prototype);
|
|
2566
|
+
return chalk;
|
|
2567
|
+
};
|
|
2568
|
+
function createChalk(options) {
|
|
2569
|
+
return chalkFactory(options);
|
|
2570
|
+
}
|
|
2571
|
+
Object.setPrototypeOf(createChalk.prototype, Function.prototype);
|
|
2572
|
+
for (const [styleName, style] of Object.entries(ansi_styles_default)) {
|
|
2573
|
+
styles2[styleName] = {
|
|
2574
|
+
get() {
|
|
2575
|
+
const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
|
|
2576
|
+
Object.defineProperty(this, styleName, { value: builder });
|
|
2577
|
+
return builder;
|
|
2578
|
+
}
|
|
2579
|
+
};
|
|
2580
|
+
}
|
|
2581
|
+
styles2.visible = {
|
|
2582
|
+
get() {
|
|
2583
|
+
const builder = createBuilder(this, this[STYLER], true);
|
|
2584
|
+
Object.defineProperty(this, "visible", { value: builder });
|
|
2585
|
+
return builder;
|
|
2586
|
+
}
|
|
2587
|
+
};
|
|
2588
|
+
var getModelAnsi = (model, level, type, ...arguments_) => {
|
|
2589
|
+
if (model === "rgb") {
|
|
2590
|
+
if (level === "ansi16m") {
|
|
2591
|
+
return ansi_styles_default[type].ansi16m(...arguments_);
|
|
2592
|
+
}
|
|
2593
|
+
if (level === "ansi256") {
|
|
2594
|
+
return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
|
|
2595
|
+
}
|
|
2596
|
+
return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
|
|
2597
|
+
}
|
|
2598
|
+
if (model === "hex") {
|
|
2599
|
+
return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
|
|
2600
|
+
}
|
|
2601
|
+
return ansi_styles_default[type][model](...arguments_);
|
|
2602
|
+
};
|
|
2603
|
+
var usedModels = ["rgb", "hex", "ansi256"];
|
|
2604
|
+
for (const model of usedModels) {
|
|
2605
|
+
styles2[model] = {
|
|
2606
|
+
get() {
|
|
2607
|
+
const { level } = this;
|
|
2608
|
+
return function(...arguments_) {
|
|
2609
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
|
|
2610
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
2611
|
+
};
|
|
2612
|
+
}
|
|
2613
|
+
};
|
|
2614
|
+
const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
|
|
2615
|
+
styles2[bgModel] = {
|
|
2616
|
+
get() {
|
|
2617
|
+
const { level } = this;
|
|
2618
|
+
return function(...arguments_) {
|
|
2619
|
+
const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
|
|
2620
|
+
return createBuilder(this, styler, this[IS_EMPTY]);
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2625
|
+
var proto = Object.defineProperties(() => {}, {
|
|
2626
|
+
...styles2,
|
|
2627
|
+
level: {
|
|
2628
|
+
enumerable: true,
|
|
2629
|
+
get() {
|
|
2630
|
+
return this[GENERATOR].level;
|
|
2631
|
+
},
|
|
2632
|
+
set(level) {
|
|
2633
|
+
this[GENERATOR].level = level;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
});
|
|
2637
|
+
var createStyler = (open, close, parent) => {
|
|
2638
|
+
let openAll;
|
|
2639
|
+
let closeAll;
|
|
2640
|
+
if (parent === undefined) {
|
|
2641
|
+
openAll = open;
|
|
2642
|
+
closeAll = close;
|
|
2643
|
+
} else {
|
|
2644
|
+
openAll = parent.openAll + open;
|
|
2645
|
+
closeAll = close + parent.closeAll;
|
|
2646
|
+
}
|
|
2647
|
+
return {
|
|
2648
|
+
open,
|
|
2649
|
+
close,
|
|
2650
|
+
openAll,
|
|
2651
|
+
closeAll,
|
|
2652
|
+
parent
|
|
2653
|
+
};
|
|
2654
|
+
};
|
|
2655
|
+
var createBuilder = (self, _styler, _isEmpty) => {
|
|
2656
|
+
const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
|
|
2657
|
+
Object.setPrototypeOf(builder, proto);
|
|
2658
|
+
builder[GENERATOR] = self;
|
|
2659
|
+
builder[STYLER] = _styler;
|
|
2660
|
+
builder[IS_EMPTY] = _isEmpty;
|
|
2661
|
+
return builder;
|
|
2662
|
+
};
|
|
2663
|
+
var applyStyle = (self, string) => {
|
|
2664
|
+
if (self.level <= 0 || !string) {
|
|
2665
|
+
return self[IS_EMPTY] ? "" : string;
|
|
2666
|
+
}
|
|
2667
|
+
let styler = self[STYLER];
|
|
2668
|
+
if (styler === undefined) {
|
|
2669
|
+
return string;
|
|
2670
|
+
}
|
|
2671
|
+
const { openAll, closeAll } = styler;
|
|
2672
|
+
if (string.includes("\x1B")) {
|
|
2673
|
+
while (styler !== undefined) {
|
|
2674
|
+
string = stringReplaceAll(string, styler.close, styler.open);
|
|
2675
|
+
styler = styler.parent;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
const lfIndex = string.indexOf(`
|
|
2679
|
+
`);
|
|
2680
|
+
if (lfIndex !== -1) {
|
|
2681
|
+
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
|
|
2682
|
+
}
|
|
2683
|
+
return openAll + string + closeAll;
|
|
2684
|
+
};
|
|
2685
|
+
Object.defineProperties(createChalk.prototype, styles2);
|
|
2686
|
+
var chalk = createChalk();
|
|
2687
|
+
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
2688
|
+
var source_default = chalk;
|
|
2689
|
+
|
|
2690
|
+
// src/output.ts
|
|
2691
|
+
var globalOptions = {};
|
|
2692
|
+
function setGlobalOptions(options) {
|
|
2693
|
+
globalOptions = { ...options };
|
|
2694
|
+
}
|
|
2695
|
+
function isTTY() {
|
|
2696
|
+
return Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
2697
|
+
}
|
|
2698
|
+
function shouldDisableColors() {
|
|
2699
|
+
if (process.env.NO_COLOR !== undefined) {
|
|
2700
|
+
return true;
|
|
2701
|
+
}
|
|
2702
|
+
if (process.env.THOUGHTFUL_NO_COLOR === "1" || process.env.THOUGHTFUL_NO_COLOR === "true") {
|
|
2703
|
+
return true;
|
|
2704
|
+
}
|
|
2705
|
+
if (process.env.TERM === "dumb") {
|
|
2706
|
+
return true;
|
|
2707
|
+
}
|
|
2708
|
+
if (!isTTY()) {
|
|
2709
|
+
return true;
|
|
2710
|
+
}
|
|
2711
|
+
if (globalOptions.noColor) {
|
|
2712
|
+
return true;
|
|
2713
|
+
}
|
|
2714
|
+
if (globalOptions.json) {
|
|
2715
|
+
return true;
|
|
2716
|
+
}
|
|
2717
|
+
return false;
|
|
2718
|
+
}
|
|
2719
|
+
var c = {
|
|
2720
|
+
blue: (text) => shouldDisableColors() ? text : source_default.blue(text),
|
|
2721
|
+
green: (text) => shouldDisableColors() ? text : source_default.green(text),
|
|
2722
|
+
yellow: (text) => shouldDisableColors() ? text : source_default.yellow(text),
|
|
2723
|
+
red: (text) => shouldDisableColors() ? text : source_default.red(text),
|
|
2724
|
+
gray: (text) => shouldDisableColors() ? text : source_default.gray(text),
|
|
2725
|
+
white: (text) => shouldDisableColors() ? text : source_default.white(text),
|
|
2726
|
+
cyan: (text) => shouldDisableColors() ? text : source_default.cyan(text)
|
|
2727
|
+
};
|
|
2728
|
+
function isQuiet() {
|
|
2729
|
+
return Boolean(globalOptions.quiet);
|
|
2730
|
+
}
|
|
2731
|
+
function isJson() {
|
|
2732
|
+
return Boolean(globalOptions.json);
|
|
2733
|
+
}
|
|
2734
|
+
function log(message) {
|
|
2735
|
+
if (!isQuiet() && !isJson()) {
|
|
2736
|
+
console.log(message);
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
function logError(message) {
|
|
2740
|
+
if (!isJson()) {
|
|
2741
|
+
console.error(message);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
function outputJson(data) {
|
|
2745
|
+
console.log(JSON.stringify(data));
|
|
2746
|
+
}
|
|
2747
|
+
function isNoInput() {
|
|
2748
|
+
return Boolean(globalOptions.noInput);
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2751
|
+
// src/client.ts
|
|
2752
|
+
class ApiError extends Error {
|
|
2753
|
+
status;
|
|
2754
|
+
statusText;
|
|
2755
|
+
body;
|
|
2756
|
+
constructor(status, statusText, body) {
|
|
2757
|
+
super(`API Error: ${status} ${statusText}`);
|
|
2758
|
+
this.status = status;
|
|
2759
|
+
this.statusText = statusText;
|
|
2760
|
+
this.body = body;
|
|
2761
|
+
this.name = "ApiError";
|
|
2762
|
+
}
|
|
2763
|
+
isValidationError() {
|
|
2764
|
+
return this.status === 400 || this.status === 422;
|
|
2765
|
+
}
|
|
2766
|
+
isOperationalError() {
|
|
2767
|
+
return this.status >= 500 || this.status === 401 || this.status === 403;
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
class ValidationError extends Error {
|
|
2772
|
+
constructor(message) {
|
|
2773
|
+
super(message);
|
|
2774
|
+
this.name = "ValidationError";
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
class ThoughtfulClient {
|
|
2779
|
+
config;
|
|
2780
|
+
constructor() {
|
|
2781
|
+
this.config = loadConfig();
|
|
2782
|
+
}
|
|
2783
|
+
async refreshTokens() {
|
|
2784
|
+
const refreshToken = this.config.refreshToken;
|
|
2785
|
+
if (!refreshToken) {
|
|
2786
|
+
return false;
|
|
2787
|
+
}
|
|
2788
|
+
try {
|
|
2789
|
+
const res = await fetch(`${this.config.apiUrl}/api/auth/mobile/refresh`, {
|
|
2790
|
+
method: "POST",
|
|
2791
|
+
headers: {
|
|
2792
|
+
"Content-Type": "application/json"
|
|
2793
|
+
},
|
|
2794
|
+
body: JSON.stringify({ refreshToken })
|
|
2795
|
+
});
|
|
2796
|
+
if (!res.ok) {
|
|
2797
|
+
return false;
|
|
2798
|
+
}
|
|
2799
|
+
const data = await res.json();
|
|
2800
|
+
const expiresAt = new Date(Date.now() + 55 * 60 * 1000);
|
|
2801
|
+
this.config = updateConfig({
|
|
2802
|
+
accessToken: data.accessToken,
|
|
2803
|
+
refreshToken: data.refreshToken,
|
|
2804
|
+
tokenExpiresAt: expiresAt.toISOString()
|
|
2805
|
+
});
|
|
2806
|
+
return true;
|
|
2807
|
+
} catch {
|
|
2808
|
+
return false;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
async ensureValidToken() {
|
|
2812
|
+
if (!this.config.accessToken) {
|
|
2813
|
+
throw new Error("Not logged in. Run 'thoughtful login' first.");
|
|
2814
|
+
}
|
|
2815
|
+
if (this.config.tokenExpiresAt) {
|
|
2816
|
+
const expiresAt = new Date(this.config.tokenExpiresAt);
|
|
2817
|
+
const now = new Date;
|
|
2818
|
+
if (expiresAt <= now) {
|
|
2819
|
+
const refreshed = await this.refreshTokens();
|
|
2820
|
+
if (!refreshed) {
|
|
2821
|
+
clearAuth();
|
|
2822
|
+
throw new Error("Session expired. Please run 'thoughtful login' again.");
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
async request(path2, options) {
|
|
2828
|
+
const { skipAuth, ...fetchOptions } = options ?? {};
|
|
2829
|
+
if (!skipAuth) {
|
|
2830
|
+
await this.ensureValidToken();
|
|
2831
|
+
}
|
|
2832
|
+
const headers = {
|
|
2833
|
+
"Content-Type": "application/json",
|
|
2834
|
+
...fetchOptions.headers
|
|
2835
|
+
};
|
|
2836
|
+
if (!skipAuth && this.config.accessToken) {
|
|
2837
|
+
headers["Authorization"] = `Bearer ${this.config.accessToken}`;
|
|
2838
|
+
}
|
|
2839
|
+
const res = await fetch(`${this.config.apiUrl}${path2}`, {
|
|
2840
|
+
...fetchOptions,
|
|
2841
|
+
headers
|
|
2842
|
+
});
|
|
2843
|
+
if (!res.ok) {
|
|
2844
|
+
if (res.status === 401 && !skipAuth) {
|
|
2845
|
+
const refreshed = await this.refreshTokens();
|
|
2846
|
+
if (refreshed) {
|
|
2847
|
+
headers["Authorization"] = `Bearer ${this.config.accessToken}`;
|
|
2848
|
+
const retryRes = await fetch(`${this.config.apiUrl}${path2}`, {
|
|
2849
|
+
...fetchOptions,
|
|
2850
|
+
headers
|
|
2851
|
+
});
|
|
2852
|
+
if (retryRes.ok) {
|
|
2853
|
+
return retryRes.json();
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
clearAuth();
|
|
2857
|
+
throw new Error("Session expired. Please run 'thoughtful login' again.");
|
|
2858
|
+
}
|
|
2859
|
+
let body;
|
|
2860
|
+
const text2 = await res.text();
|
|
2861
|
+
try {
|
|
2862
|
+
body = JSON.parse(text2);
|
|
2863
|
+
} catch {
|
|
2864
|
+
body = text2;
|
|
2865
|
+
}
|
|
2866
|
+
throw new ApiError(res.status, res.statusText, body);
|
|
2867
|
+
}
|
|
2868
|
+
const text = await res.text();
|
|
2869
|
+
if (!text) {
|
|
2870
|
+
return {};
|
|
2871
|
+
}
|
|
2872
|
+
return JSON.parse(text);
|
|
2873
|
+
}
|
|
2874
|
+
async sendVerificationCode(email) {
|
|
2875
|
+
return this.request("/api/auth/mobile/send-code", {
|
|
2876
|
+
method: "POST",
|
|
2877
|
+
body: JSON.stringify({ email }),
|
|
2878
|
+
skipAuth: true
|
|
2879
|
+
});
|
|
2880
|
+
}
|
|
2881
|
+
async verifyCode(email, code) {
|
|
2882
|
+
return this.request("/api/auth/mobile/verify-code", {
|
|
2883
|
+
method: "POST",
|
|
2884
|
+
body: JSON.stringify({ email, code }),
|
|
2885
|
+
skipAuth: true
|
|
2886
|
+
});
|
|
2887
|
+
}
|
|
2888
|
+
async getMembershipsAndWorkspaces() {
|
|
2889
|
+
return this.request("/api/mobile/memberships-workspaces");
|
|
2890
|
+
}
|
|
2891
|
+
async setMembership(membershipId) {
|
|
2892
|
+
return this.request("/api/mobile/set-membership", {
|
|
2893
|
+
method: "POST",
|
|
2894
|
+
body: JSON.stringify({ membershipId })
|
|
2895
|
+
});
|
|
2896
|
+
}
|
|
2897
|
+
async setWorkspace(workspaceId) {
|
|
2898
|
+
return this.request("/api/mobile/set-workspace", {
|
|
2899
|
+
method: "POST",
|
|
2900
|
+
body: JSON.stringify({ workspaceId })
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
async getPages() {
|
|
2904
|
+
return this.request("/api/cli/pages");
|
|
2905
|
+
}
|
|
2906
|
+
async getPage(slug) {
|
|
2907
|
+
return this.request(`/api/cli/pages/${encodeURIComponent(slug)}`);
|
|
2908
|
+
}
|
|
2909
|
+
async createPage(data) {
|
|
2910
|
+
return this.request("/api/cli/pages", {
|
|
2911
|
+
method: "POST",
|
|
2912
|
+
body: JSON.stringify(data)
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
async updatePage(slug, data) {
|
|
2916
|
+
return this.request(`/api/cli/pages/${encodeURIComponent(slug)}`, {
|
|
2917
|
+
method: "PATCH",
|
|
2918
|
+
body: JSON.stringify(data)
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2921
|
+
async deletePage(slug) {
|
|
2922
|
+
return this.request(`/api/cli/pages/${encodeURIComponent(slug)}`, {
|
|
2923
|
+
method: "DELETE"
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
async searchPages(query) {
|
|
2927
|
+
return this.request(`/api/cli/pages/search?q=${encodeURIComponent(query)}`);
|
|
2928
|
+
}
|
|
2929
|
+
async getThreads() {
|
|
2930
|
+
return this.request("/api/cli/threads");
|
|
2931
|
+
}
|
|
2932
|
+
async createThread(message) {
|
|
2933
|
+
return this.request("/api/cli/threads", {
|
|
2934
|
+
method: "POST",
|
|
2935
|
+
body: JSON.stringify({ message })
|
|
2936
|
+
});
|
|
2937
|
+
}
|
|
2938
|
+
async getThreadMessages(threadId) {
|
|
2939
|
+
return this.request(`/api/cli/threads/${encodeURIComponent(threadId)}/messages`);
|
|
2940
|
+
}
|
|
2941
|
+
async sendThreadMessage(threadId, message) {
|
|
2942
|
+
return this.request(`/api/cli/threads/${encodeURIComponent(threadId)}/messages`, {
|
|
2943
|
+
method: "POST",
|
|
2944
|
+
body: JSON.stringify({ message })
|
|
2945
|
+
});
|
|
2946
|
+
}
|
|
2947
|
+
async sendMessageWithResponse(threadId, message) {
|
|
2948
|
+
return this.request(`/api/cli/threads/${encodeURIComponent(threadId)}/respond`, {
|
|
2949
|
+
method: "POST",
|
|
2950
|
+
body: JSON.stringify({ message })
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
2953
|
+
async createWorkspace(name) {
|
|
2954
|
+
return this.request("/api/cli/workspaces", {
|
|
2955
|
+
method: "POST",
|
|
2956
|
+
body: JSON.stringify({ name })
|
|
2957
|
+
});
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
function createClient() {
|
|
2961
|
+
return new ThoughtfulClient;
|
|
2962
|
+
}
|
|
2963
|
+
function handleApiError(error) {
|
|
2964
|
+
let exitCode = 1;
|
|
2965
|
+
const json = isJson();
|
|
2966
|
+
if (error instanceof ApiError) {
|
|
2967
|
+
if (error.isValidationError()) {
|
|
2968
|
+
exitCode = 2;
|
|
2969
|
+
}
|
|
2970
|
+
if (json) {
|
|
2971
|
+
outputJson({
|
|
2972
|
+
error: true,
|
|
2973
|
+
status: error.status,
|
|
2974
|
+
message: error.message,
|
|
2975
|
+
details: error.body
|
|
2976
|
+
});
|
|
2977
|
+
} else {
|
|
2978
|
+
logError(c.red(`Error: ${error.message}`));
|
|
2979
|
+
if (error.body && typeof error.body === "object" && "error" in error.body) {
|
|
2980
|
+
logError(c.gray(error.body.error));
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
} else if (error instanceof ValidationError) {
|
|
2984
|
+
exitCode = 2;
|
|
2985
|
+
if (json) {
|
|
2986
|
+
outputJson({ error: true, message: error.message });
|
|
2987
|
+
} else {
|
|
2988
|
+
logError(c.red(`Error: ${error.message}`));
|
|
2989
|
+
}
|
|
2990
|
+
} else if (error instanceof Error) {
|
|
2991
|
+
if (json) {
|
|
2992
|
+
outputJson({ error: true, message: error.message });
|
|
2993
|
+
} else {
|
|
2994
|
+
logError(c.red(`Error: ${error.message}`));
|
|
2995
|
+
}
|
|
2996
|
+
} else {
|
|
2997
|
+
if (json) {
|
|
2998
|
+
outputJson({ error: true, message: "Unknown error" });
|
|
2999
|
+
} else {
|
|
3000
|
+
logError(c.red("An unknown error occurred"));
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
process.exit(exitCode);
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
// src/prompt.ts
|
|
3007
|
+
import readline from "node:readline";
|
|
3008
|
+
function prompt(question, options = {}) {
|
|
3009
|
+
const { secure = false, required = false } = options;
|
|
3010
|
+
if (isNoInput()) {
|
|
3011
|
+
const error = new Error(`Interactive input is disabled (--no-input flag set). ${required ? "This input is required." : ""}`);
|
|
3012
|
+
return Promise.reject(error);
|
|
3013
|
+
}
|
|
3014
|
+
if (!isTTY()) {
|
|
3015
|
+
const error = new Error(`Cannot prompt for input: stdin is not a TTY. ${required ? "This input is required." : ""}`);
|
|
3016
|
+
return Promise.reject(error);
|
|
3017
|
+
}
|
|
3018
|
+
return new Promise((resolve, reject) => {
|
|
3019
|
+
const rl = readline.createInterface({
|
|
3020
|
+
input: process.stdin,
|
|
3021
|
+
output: process.stdout
|
|
3022
|
+
});
|
|
3023
|
+
if (secure) {
|
|
3024
|
+
process.stdout.write(question);
|
|
3025
|
+
const stdin = process.stdin;
|
|
3026
|
+
const originalSetRawMode = stdin.setRawMode?.bind(stdin);
|
|
3027
|
+
if (originalSetRawMode) {
|
|
3028
|
+
originalSetRawMode(true);
|
|
3029
|
+
}
|
|
3030
|
+
stdin.resume();
|
|
3031
|
+
stdin.setEncoding("utf8");
|
|
3032
|
+
let input = "";
|
|
3033
|
+
const onData = (char) => {
|
|
3034
|
+
const c2 = char.toString();
|
|
3035
|
+
switch (c2) {
|
|
3036
|
+
case `
|
|
3037
|
+
`:
|
|
3038
|
+
case "\r":
|
|
3039
|
+
case "\x04":
|
|
3040
|
+
stdin.pause();
|
|
3041
|
+
stdin.removeListener("data", onData);
|
|
3042
|
+
if (originalSetRawMode) {
|
|
3043
|
+
originalSetRawMode(false);
|
|
3044
|
+
}
|
|
3045
|
+
rl.close();
|
|
3046
|
+
process.stdout.write(`
|
|
3047
|
+
`);
|
|
3048
|
+
resolve(input.trim());
|
|
3049
|
+
break;
|
|
3050
|
+
case "\x03":
|
|
3051
|
+
stdin.pause();
|
|
3052
|
+
stdin.removeListener("data", onData);
|
|
3053
|
+
if (originalSetRawMode) {
|
|
3054
|
+
originalSetRawMode(false);
|
|
3055
|
+
}
|
|
3056
|
+
rl.close();
|
|
3057
|
+
process.stdout.write(`
|
|
3058
|
+
`);
|
|
3059
|
+
reject(new Error("User cancelled input (Ctrl+C)"));
|
|
3060
|
+
break;
|
|
3061
|
+
case "":
|
|
3062
|
+
case "\b":
|
|
3063
|
+
if (input.length > 0) {
|
|
3064
|
+
input = input.slice(0, -1);
|
|
3065
|
+
process.stdout.write("\b \b");
|
|
3066
|
+
}
|
|
3067
|
+
break;
|
|
3068
|
+
default:
|
|
3069
|
+
if (c2.charCodeAt(0) >= 32 && c2.charCodeAt(0) < 127) {
|
|
3070
|
+
input += c2;
|
|
3071
|
+
process.stdout.write("*");
|
|
3072
|
+
}
|
|
3073
|
+
break;
|
|
3074
|
+
}
|
|
3075
|
+
};
|
|
3076
|
+
stdin.on("data", onData);
|
|
3077
|
+
} else {
|
|
3078
|
+
rl.question(question, (answer) => {
|
|
3079
|
+
rl.close();
|
|
3080
|
+
resolve(answer.trim());
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
});
|
|
3084
|
+
}
|
|
3085
|
+
async function confirm(question, options = {}) {
|
|
3086
|
+
const { defaultValue = false } = options;
|
|
3087
|
+
if (isNoInput()) {
|
|
3088
|
+
throw new Error("Interactive confirmation is disabled (--no-input flag set)");
|
|
3089
|
+
}
|
|
3090
|
+
if (!isTTY()) {
|
|
3091
|
+
throw new Error("Cannot prompt for confirmation: stdin is not a TTY");
|
|
3092
|
+
}
|
|
3093
|
+
const suffix = defaultValue ? " (Y/n) " : " (y/N) ";
|
|
3094
|
+
const answer = await prompt(question + suffix);
|
|
3095
|
+
if (!answer) {
|
|
3096
|
+
return defaultValue;
|
|
3097
|
+
}
|
|
3098
|
+
const normalized = answer.toLowerCase();
|
|
3099
|
+
return normalized === "y" || normalized === "yes";
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
// src/commands/auth.ts
|
|
3103
|
+
function registerAuthCommands(program2) {
|
|
3104
|
+
program2.command("login").description("Log in to Thoughtful").option("--email <email>", "Email address for login (skips email prompt)").option("--code <code>", "Verification code (skips code prompt, requires --email)").addHelpText("after", `
|
|
3105
|
+
Examples:
|
|
3106
|
+
$ thoughtful login
|
|
3107
|
+
Email: alice@example.com
|
|
3108
|
+
Enter code: ******
|
|
3109
|
+
|
|
3110
|
+
$ thoughtful login --email alice@example.com --code 123456
|
|
3111
|
+
Successfully logged in as alice@example.com
|
|
3112
|
+
|
|
3113
|
+
$ thoughtful login --json
|
|
3114
|
+
{"success":true,"user":{...},"workspace":{...}}
|
|
3115
|
+
|
|
3116
|
+
$ thoughtful login --no-input --email alice@example.com --code 123456
|
|
3117
|
+
Successfully logged in as alice@example.com
|
|
3118
|
+
`).action(async (options) => {
|
|
3119
|
+
try {
|
|
3120
|
+
if (isLoggedIn()) {
|
|
3121
|
+
const config = loadConfig();
|
|
3122
|
+
if (isJson()) {
|
|
3123
|
+
outputJson({
|
|
3124
|
+
success: false,
|
|
3125
|
+
message: "Already logged in",
|
|
3126
|
+
email: config.user?.email
|
|
3127
|
+
});
|
|
3128
|
+
} else {
|
|
3129
|
+
log(c.yellow(`Already logged in as ${config.user?.email}. Use 'thoughtful logout' first to log in as a different user.`));
|
|
3130
|
+
}
|
|
3131
|
+
return;
|
|
3132
|
+
}
|
|
3133
|
+
const client = createClient();
|
|
3134
|
+
if (!isJson()) {
|
|
3135
|
+
log(c.blue("Thoughtful CLI Login"));
|
|
3136
|
+
log("");
|
|
3137
|
+
}
|
|
3138
|
+
let email = options.email;
|
|
3139
|
+
if (!email) {
|
|
3140
|
+
try {
|
|
3141
|
+
email = await prompt("Email: ", { required: true });
|
|
3142
|
+
} catch (error) {
|
|
3143
|
+
if (error instanceof Error) {
|
|
3144
|
+
throw new ValidationError(`Email is required. ${error.message} Provide --email flag for non-interactive mode.`);
|
|
3145
|
+
}
|
|
3146
|
+
throw error;
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
if (!email) {
|
|
3150
|
+
throw new ValidationError("Email is required");
|
|
3151
|
+
}
|
|
3152
|
+
let code = options.code;
|
|
3153
|
+
if (!code) {
|
|
3154
|
+
if (!isJson()) {
|
|
3155
|
+
log(c.gray("Sending verification code..."));
|
|
3156
|
+
}
|
|
3157
|
+
await client.sendVerificationCode(email);
|
|
3158
|
+
if (!isJson()) {
|
|
3159
|
+
log(c.green("Verification code sent! Check your email."));
|
|
3160
|
+
log("");
|
|
3161
|
+
}
|
|
3162
|
+
try {
|
|
3163
|
+
code = await prompt("Enter code: ", { secure: true, required: true });
|
|
3164
|
+
} catch (error) {
|
|
3165
|
+
if (error instanceof Error) {
|
|
3166
|
+
throw new ValidationError(`Verification code is required. ${error.message} Provide --code flag for non-interactive mode.`);
|
|
3167
|
+
}
|
|
3168
|
+
throw error;
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
if (!code) {
|
|
3172
|
+
throw new ValidationError("Verification code is required");
|
|
3173
|
+
}
|
|
3174
|
+
const result = await client.verifyCode(email, code);
|
|
3175
|
+
const expiresAt = new Date(Date.now() + 55 * 60 * 1000);
|
|
3176
|
+
updateConfig({
|
|
3177
|
+
accessToken: result.accessToken,
|
|
3178
|
+
refreshToken: result.refreshToken,
|
|
3179
|
+
tokenExpiresAt: expiresAt.toISOString(),
|
|
3180
|
+
activeOrgId: result.workspace.organizationId,
|
|
3181
|
+
activeWorkspaceId: result.workspace.id,
|
|
3182
|
+
user: {
|
|
3183
|
+
id: result.user.id,
|
|
3184
|
+
email: result.user.email,
|
|
3185
|
+
displayName: result.user.displayName
|
|
3186
|
+
}
|
|
3187
|
+
});
|
|
3188
|
+
if (isJson()) {
|
|
3189
|
+
outputJson({
|
|
3190
|
+
success: true,
|
|
3191
|
+
user: {
|
|
3192
|
+
id: result.user.id,
|
|
3193
|
+
email: result.user.email,
|
|
3194
|
+
displayName: result.user.displayName
|
|
3195
|
+
},
|
|
3196
|
+
workspace: {
|
|
3197
|
+
id: result.workspace.id,
|
|
3198
|
+
name: result.workspace.name
|
|
3199
|
+
}
|
|
3200
|
+
});
|
|
3201
|
+
} else {
|
|
3202
|
+
log("");
|
|
3203
|
+
log(c.green(`Successfully logged in as ${result.user.email}`));
|
|
3204
|
+
log(c.gray(`Workspace: ${result.workspace.name}`));
|
|
3205
|
+
}
|
|
3206
|
+
} catch (error) {
|
|
3207
|
+
handleApiError(error);
|
|
3208
|
+
}
|
|
3209
|
+
});
|
|
3210
|
+
program2.command("logout").description("Log out from Thoughtful").addHelpText("after", `
|
|
3211
|
+
Examples:
|
|
3212
|
+
$ thoughtful logout
|
|
3213
|
+
Successfully logged out
|
|
3214
|
+
|
|
3215
|
+
$ thoughtful logout --json
|
|
3216
|
+
{"success":true}
|
|
3217
|
+
`).action(() => {
|
|
3218
|
+
if (!isLoggedIn()) {
|
|
3219
|
+
if (isJson()) {
|
|
3220
|
+
outputJson({ success: true, message: "Not logged in" });
|
|
3221
|
+
} else {
|
|
3222
|
+
log(c.yellow("Not logged in"));
|
|
3223
|
+
}
|
|
3224
|
+
return;
|
|
3225
|
+
}
|
|
3226
|
+
clearAuth();
|
|
3227
|
+
if (isJson()) {
|
|
3228
|
+
outputJson({ success: true });
|
|
3229
|
+
} else {
|
|
3230
|
+
log(c.green("Successfully logged out"));
|
|
3231
|
+
}
|
|
3232
|
+
});
|
|
3233
|
+
program2.command("whoami").description("Show current user and workspace").addHelpText("after", `
|
|
3234
|
+
Examples:
|
|
3235
|
+
$ thoughtful whoami
|
|
3236
|
+
Current Session
|
|
3237
|
+
User: alice@example.com
|
|
3238
|
+
Name: Alice Smith
|
|
3239
|
+
Organization: Acme Corp
|
|
3240
|
+
Workspace: Engineering
|
|
3241
|
+
|
|
3242
|
+
$ thoughtful whoami --json
|
|
3243
|
+
{"user":{...},"organization":{...},"workspace":{...}}
|
|
3244
|
+
`).action(async () => {
|
|
3245
|
+
try {
|
|
3246
|
+
if (!isLoggedIn()) {
|
|
3247
|
+
if (isJson()) {
|
|
3248
|
+
outputJson({ error: true, message: "Not logged in" });
|
|
3249
|
+
} else {
|
|
3250
|
+
log(c.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3251
|
+
}
|
|
3252
|
+
process.exit(1);
|
|
3253
|
+
}
|
|
3254
|
+
const config = loadConfig();
|
|
3255
|
+
const client = createClient();
|
|
3256
|
+
const data = await client.getMembershipsAndWorkspaces();
|
|
3257
|
+
const activeMembership = data.memberships.find((m) => m.id === data.activeMembershipId);
|
|
3258
|
+
const activeWorkspace = data.workspaces.find((w) => w.id === data.activeWorkspaceId);
|
|
3259
|
+
if (isJson()) {
|
|
3260
|
+
outputJson({
|
|
3261
|
+
user: config.user,
|
|
3262
|
+
organization: activeMembership ? {
|
|
3263
|
+
id: activeMembership.organizationId,
|
|
3264
|
+
name: activeMembership.organizationName,
|
|
3265
|
+
domain: activeMembership.organizationDomain
|
|
3266
|
+
} : null,
|
|
3267
|
+
workspace: activeWorkspace ? {
|
|
3268
|
+
id: activeWorkspace.id,
|
|
3269
|
+
name: activeWorkspace.name
|
|
3270
|
+
} : null
|
|
3271
|
+
});
|
|
3272
|
+
} else {
|
|
3273
|
+
log(c.blue("Current Session"));
|
|
3274
|
+
log("");
|
|
3275
|
+
log(` ${c.gray("User:")} ${config.user?.email}`);
|
|
3276
|
+
if (config.user?.displayName) {
|
|
3277
|
+
log(` ${c.gray("Name:")} ${config.user.displayName}`);
|
|
3278
|
+
}
|
|
3279
|
+
if (activeMembership) {
|
|
3280
|
+
log(` ${c.gray("Organization:")} ${activeMembership.organizationName}`);
|
|
3281
|
+
}
|
|
3282
|
+
if (activeWorkspace) {
|
|
3283
|
+
log(` ${c.gray("Workspace:")} ${activeWorkspace.name}`);
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
} catch (error) {
|
|
3287
|
+
handleApiError(error);
|
|
3288
|
+
}
|
|
3289
|
+
});
|
|
3290
|
+
}
|
|
3291
|
+
|
|
3292
|
+
// src/commands/orgs.ts
|
|
3293
|
+
function registerOrgsCommands(program2) {
|
|
3294
|
+
const orgs = program2.command("orgs").description("Manage organizations").addHelpText("after", `
|
|
3295
|
+
Examples:
|
|
3296
|
+
$ thoughtful orgs list
|
|
3297
|
+
$ thoughtful orgs switch org_abc123
|
|
3298
|
+
$ thoughtful orgs list --json | jq '.organizations[] | select(.active)'
|
|
3299
|
+
`);
|
|
3300
|
+
orgs.command("list").description("List organizations you belong to").option("--json", "Output as JSON").addHelpText("after", `
|
|
3301
|
+
Examples:
|
|
3302
|
+
$ thoughtful orgs list
|
|
3303
|
+
Organizations
|
|
3304
|
+
* Acme Corp (acme.com)
|
|
3305
|
+
ID: org_abc123
|
|
3306
|
+
Consulting Inc
|
|
3307
|
+
ID: org_xyz789
|
|
3308
|
+
|
|
3309
|
+
$ thoughtful orgs list --json
|
|
3310
|
+
{"organizations":[{"id":"org_abc123","name":"Acme Corp","domain":"acme.com","active":true},...]}
|
|
3311
|
+
`).action(async (options) => {
|
|
3312
|
+
const json = options.json;
|
|
3313
|
+
try {
|
|
3314
|
+
if (!isLoggedIn()) {
|
|
3315
|
+
if (json) {
|
|
3316
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3317
|
+
} else {
|
|
3318
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3319
|
+
}
|
|
3320
|
+
process.exit(1);
|
|
3321
|
+
}
|
|
3322
|
+
const client = createClient();
|
|
3323
|
+
const data = await client.getMembershipsAndWorkspaces();
|
|
3324
|
+
if (json) {
|
|
3325
|
+
console.log(JSON.stringify({
|
|
3326
|
+
organizations: data.memberships.map((m) => ({
|
|
3327
|
+
id: m.organizationId,
|
|
3328
|
+
name: m.organizationName,
|
|
3329
|
+
domain: m.organizationDomain,
|
|
3330
|
+
active: m.id === data.activeMembershipId
|
|
3331
|
+
}))
|
|
3332
|
+
}));
|
|
3333
|
+
} else {
|
|
3334
|
+
console.log(source_default.blue("Organizations"));
|
|
3335
|
+
console.log();
|
|
3336
|
+
if (data.memberships.length === 0) {
|
|
3337
|
+
console.log(source_default.gray(" No organizations found"));
|
|
3338
|
+
return;
|
|
3339
|
+
}
|
|
3340
|
+
for (const m of data.memberships) {
|
|
3341
|
+
const isActive = m.id === data.activeMembershipId;
|
|
3342
|
+
const marker = isActive ? source_default.green("*") : " ";
|
|
3343
|
+
const name = isActive ? source_default.white(m.organizationName) : source_default.gray(m.organizationName);
|
|
3344
|
+
const domain = m.organizationDomain ? source_default.gray(` (${m.organizationDomain})`) : "";
|
|
3345
|
+
console.log(` ${marker} ${name}${domain}`);
|
|
3346
|
+
console.log(source_default.gray(` ID: ${m.organizationId}`));
|
|
3347
|
+
}
|
|
3348
|
+
console.log();
|
|
3349
|
+
console.log(source_default.gray("* = active organization"));
|
|
3350
|
+
}
|
|
3351
|
+
} catch (error) {
|
|
3352
|
+
handleApiError(error);
|
|
3353
|
+
}
|
|
3354
|
+
});
|
|
3355
|
+
orgs.command("switch <org-id>").description("Switch to a different organization").option("--json", "Output as JSON").addHelpText("after", `
|
|
3356
|
+
Examples:
|
|
3357
|
+
$ thoughtful orgs switch org_abc123
|
|
3358
|
+
Switched to organization: Acme Corp
|
|
3359
|
+
Workspace: Engineering
|
|
3360
|
+
|
|
3361
|
+
$ thoughtful orgs switch org_abc123 --json
|
|
3362
|
+
{"success":true,"organization":{...},"workspace":{...}}
|
|
3363
|
+
`).action(async (orgId, options) => {
|
|
3364
|
+
const json = options.json;
|
|
3365
|
+
try {
|
|
3366
|
+
if (!isLoggedIn()) {
|
|
3367
|
+
if (json) {
|
|
3368
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3369
|
+
} else {
|
|
3370
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3371
|
+
}
|
|
3372
|
+
process.exit(1);
|
|
3373
|
+
}
|
|
3374
|
+
const client = createClient();
|
|
3375
|
+
const data = await client.getMembershipsAndWorkspaces();
|
|
3376
|
+
const membership = data.memberships.find((m) => m.organizationId === orgId);
|
|
3377
|
+
if (!membership) {
|
|
3378
|
+
const availableList = data.memberships.map((m) => `${m.organizationName} (${m.organizationId})`).join(", ");
|
|
3379
|
+
const message = json ? `Organization '${orgId}' not found` : `Organization '${orgId}' not found. Available organizations: ${availableList}`;
|
|
3380
|
+
throw new ValidationError(message);
|
|
3381
|
+
}
|
|
3382
|
+
const result = await client.setMembership(membership.id);
|
|
3383
|
+
const expiresAt = new Date(Date.now() + 55 * 60 * 1000);
|
|
3384
|
+
updateConfig({
|
|
3385
|
+
accessToken: result.accessToken,
|
|
3386
|
+
refreshToken: result.refreshToken,
|
|
3387
|
+
tokenExpiresAt: expiresAt.toISOString(),
|
|
3388
|
+
activeOrgId: membership.organizationId,
|
|
3389
|
+
activeWorkspaceId: result.workspace.id
|
|
3390
|
+
});
|
|
3391
|
+
if (json) {
|
|
3392
|
+
console.log(JSON.stringify({
|
|
3393
|
+
success: true,
|
|
3394
|
+
organization: {
|
|
3395
|
+
id: membership.organizationId,
|
|
3396
|
+
name: membership.organizationName
|
|
3397
|
+
},
|
|
3398
|
+
workspace: {
|
|
3399
|
+
id: result.workspace.id,
|
|
3400
|
+
name: result.workspace.name
|
|
3401
|
+
}
|
|
3402
|
+
}));
|
|
3403
|
+
} else {
|
|
3404
|
+
console.log(source_default.green(`Switched to organization: ${membership.organizationName}`));
|
|
3405
|
+
console.log(source_default.gray(`Workspace: ${result.workspace.name}`));
|
|
3406
|
+
}
|
|
3407
|
+
} catch (error) {
|
|
3408
|
+
handleApiError(error);
|
|
3409
|
+
}
|
|
3410
|
+
});
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3413
|
+
// src/commands/workspaces.ts
|
|
3414
|
+
function registerWorkspacesCommands(program2) {
|
|
3415
|
+
const workspaces = program2.command("workspaces").description("Manage workspaces").addHelpText("after", `
|
|
3416
|
+
Examples:
|
|
3417
|
+
$ thoughtful workspaces list
|
|
3418
|
+
$ thoughtful workspaces create "New Project Team"
|
|
3419
|
+
$ thoughtful workspaces switch ws_abc123
|
|
3420
|
+
$ thoughtful workspaces list --json | jq '.workspaces[] | select(.active)'
|
|
3421
|
+
`);
|
|
3422
|
+
workspaces.command("list").description("List workspaces in current organization").option("--json", "Output as JSON").addHelpText("after", `
|
|
3423
|
+
Examples:
|
|
3424
|
+
$ thoughtful workspaces list
|
|
3425
|
+
Workspaces
|
|
3426
|
+
* Engineering
|
|
3427
|
+
Product development workspace
|
|
3428
|
+
ID: ws_abc123
|
|
3429
|
+
Marketing
|
|
3430
|
+
Marketing team workspace
|
|
3431
|
+
ID: ws_xyz789
|
|
3432
|
+
|
|
3433
|
+
$ thoughtful workspaces list --json
|
|
3434
|
+
{"workspaces":[{"id":"ws_abc123","name":"Engineering","description":"Product development workspace","active":true},...]}
|
|
3435
|
+
`).action(async (options) => {
|
|
3436
|
+
const json = options.json;
|
|
3437
|
+
try {
|
|
3438
|
+
if (!isLoggedIn()) {
|
|
3439
|
+
if (json) {
|
|
3440
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3441
|
+
} else {
|
|
3442
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3443
|
+
}
|
|
3444
|
+
process.exit(1);
|
|
3445
|
+
}
|
|
3446
|
+
const client = createClient();
|
|
3447
|
+
const data = await client.getMembershipsAndWorkspaces();
|
|
3448
|
+
if (json) {
|
|
3449
|
+
console.log(JSON.stringify({
|
|
3450
|
+
workspaces: data.workspaces.map((w) => ({
|
|
3451
|
+
id: w.id,
|
|
3452
|
+
name: w.name,
|
|
3453
|
+
description: w.description,
|
|
3454
|
+
active: w.id === data.activeWorkspaceId
|
|
3455
|
+
}))
|
|
3456
|
+
}));
|
|
3457
|
+
} else {
|
|
3458
|
+
console.log(source_default.blue("Workspaces"));
|
|
3459
|
+
console.log();
|
|
3460
|
+
if (data.workspaces.length === 0) {
|
|
3461
|
+
console.log(source_default.gray(" No workspaces found"));
|
|
3462
|
+
return;
|
|
3463
|
+
}
|
|
3464
|
+
for (const w of data.workspaces) {
|
|
3465
|
+
const isActive = w.id === data.activeWorkspaceId;
|
|
3466
|
+
const marker = isActive ? source_default.green("*") : " ";
|
|
3467
|
+
const name = isActive ? source_default.white(w.name) : source_default.gray(w.name);
|
|
3468
|
+
console.log(` ${marker} ${name}`);
|
|
3469
|
+
if (w.description) {
|
|
3470
|
+
console.log(source_default.gray(` ${w.description}`));
|
|
3471
|
+
}
|
|
3472
|
+
console.log(source_default.gray(` ID: ${w.id}`));
|
|
3473
|
+
}
|
|
3474
|
+
console.log();
|
|
3475
|
+
console.log(source_default.gray("* = active workspace"));
|
|
3476
|
+
}
|
|
3477
|
+
} catch (error) {
|
|
3478
|
+
handleApiError(error);
|
|
3479
|
+
}
|
|
3480
|
+
});
|
|
3481
|
+
workspaces.command("switch <workspace-id>").description("Switch to a different workspace").option("--json", "Output as JSON").addHelpText("after", `
|
|
3482
|
+
Examples:
|
|
3483
|
+
$ thoughtful workspaces switch ws_abc123
|
|
3484
|
+
Switched to workspace: Engineering
|
|
3485
|
+
|
|
3486
|
+
$ thoughtful workspaces switch ws_abc123 --json
|
|
3487
|
+
{"success":true,"workspace":{"id":"ws_abc123","name":"Engineering"}}
|
|
3488
|
+
`).action(async (workspaceId, options) => {
|
|
3489
|
+
const json = options.json;
|
|
3490
|
+
try {
|
|
3491
|
+
if (!isLoggedIn()) {
|
|
3492
|
+
if (json) {
|
|
3493
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3494
|
+
} else {
|
|
3495
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3496
|
+
}
|
|
3497
|
+
process.exit(1);
|
|
3498
|
+
}
|
|
3499
|
+
const client = createClient();
|
|
3500
|
+
const data = await client.getMembershipsAndWorkspaces();
|
|
3501
|
+
const workspace = data.workspaces.find((w) => w.id === workspaceId);
|
|
3502
|
+
if (!workspace) {
|
|
3503
|
+
const availableList = data.workspaces.map((w) => `${w.name} (${w.id})`).join(", ");
|
|
3504
|
+
const message = json ? `Workspace '${workspaceId}' not found` : `Workspace '${workspaceId}' not found. Available workspaces: ${availableList}`;
|
|
3505
|
+
throw new ValidationError(message);
|
|
3506
|
+
}
|
|
3507
|
+
const result = await client.setWorkspace(workspaceId);
|
|
3508
|
+
const expiresAt = new Date(Date.now() + 55 * 60 * 1000);
|
|
3509
|
+
updateConfig({
|
|
3510
|
+
accessToken: result.accessToken,
|
|
3511
|
+
refreshToken: result.refreshToken,
|
|
3512
|
+
tokenExpiresAt: expiresAt.toISOString(),
|
|
3513
|
+
activeWorkspaceId: workspaceId
|
|
3514
|
+
});
|
|
3515
|
+
if (json) {
|
|
3516
|
+
console.log(JSON.stringify({
|
|
3517
|
+
success: true,
|
|
3518
|
+
workspace: {
|
|
3519
|
+
id: workspace.id,
|
|
3520
|
+
name: workspace.name
|
|
3521
|
+
}
|
|
3522
|
+
}));
|
|
3523
|
+
} else {
|
|
3524
|
+
console.log(source_default.green(`Switched to workspace: ${workspace.name}`));
|
|
3525
|
+
}
|
|
3526
|
+
} catch (error) {
|
|
3527
|
+
handleApiError(error);
|
|
3528
|
+
}
|
|
3529
|
+
});
|
|
3530
|
+
workspaces.command("create <name>").description("Create a new workspace").option("--json", "Output as JSON").addHelpText("after", `
|
|
3531
|
+
Examples:
|
|
3532
|
+
$ thoughtful workspaces create "New Project Team"
|
|
3533
|
+
Created workspace: New Project Team
|
|
3534
|
+
ID: ws_newid123
|
|
3535
|
+
Switched to the new workspace.
|
|
3536
|
+
|
|
3537
|
+
$ thoughtful workspaces create "Sales Team" --json
|
|
3538
|
+
{"success":true,"workspace":{"id":"ws_newid123","name":"Sales Team"}}
|
|
3539
|
+
`).action(async (name, options) => {
|
|
3540
|
+
const json = options.json;
|
|
3541
|
+
try {
|
|
3542
|
+
if (!isLoggedIn()) {
|
|
3543
|
+
if (json) {
|
|
3544
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3545
|
+
} else {
|
|
3546
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3547
|
+
}
|
|
3548
|
+
process.exit(1);
|
|
3549
|
+
}
|
|
3550
|
+
const client = createClient();
|
|
3551
|
+
const result = await client.createWorkspace(name);
|
|
3552
|
+
const expiresAt = new Date(Date.now() + 55 * 60 * 1000);
|
|
3553
|
+
updateConfig({
|
|
3554
|
+
accessToken: result.accessToken,
|
|
3555
|
+
refreshToken: result.refreshToken,
|
|
3556
|
+
tokenExpiresAt: expiresAt.toISOString(),
|
|
3557
|
+
activeWorkspaceId: result.workspace.id
|
|
3558
|
+
});
|
|
3559
|
+
if (json) {
|
|
3560
|
+
console.log(JSON.stringify({
|
|
3561
|
+
success: true,
|
|
3562
|
+
workspace: {
|
|
3563
|
+
id: result.workspace.id,
|
|
3564
|
+
name: result.workspace.name
|
|
3565
|
+
}
|
|
3566
|
+
}));
|
|
3567
|
+
} else {
|
|
3568
|
+
console.log(source_default.green(`Created workspace: ${result.workspace.name}`));
|
|
3569
|
+
console.log(source_default.gray(`ID: ${result.workspace.id}`));
|
|
3570
|
+
console.log(source_default.gray("Switched to the new workspace."));
|
|
3571
|
+
}
|
|
3572
|
+
} catch (error) {
|
|
3573
|
+
handleApiError(error);
|
|
3574
|
+
}
|
|
3575
|
+
});
|
|
3576
|
+
}
|
|
3577
|
+
|
|
3578
|
+
// src/commands/pages.ts
|
|
3579
|
+
function buildTree(pages) {
|
|
3580
|
+
const nodeMap = new Map;
|
|
3581
|
+
const roots = [];
|
|
3582
|
+
for (const page of pages) {
|
|
3583
|
+
nodeMap.set(page.id, { ...page, children: [] });
|
|
3584
|
+
}
|
|
3585
|
+
for (const page of pages) {
|
|
3586
|
+
const node = nodeMap.get(page.id);
|
|
3587
|
+
if (page.parentId) {
|
|
3588
|
+
const parent = nodeMap.get(page.parentId);
|
|
3589
|
+
if (parent) {
|
|
3590
|
+
parent.children.push(node);
|
|
3591
|
+
} else {
|
|
3592
|
+
roots.push(node);
|
|
3593
|
+
}
|
|
3594
|
+
} else {
|
|
3595
|
+
roots.push(node);
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3598
|
+
return roots;
|
|
3599
|
+
}
|
|
3600
|
+
function printTree(nodes, prefix = "", isLast = true) {
|
|
3601
|
+
for (let i = 0;i < nodes.length; i++) {
|
|
3602
|
+
const node = nodes[i];
|
|
3603
|
+
const isLastNode = i === nodes.length - 1;
|
|
3604
|
+
const connector = prefix === "" ? "" : isLastNode ? "└─ " : "├─ ";
|
|
3605
|
+
const status = node.status ? source_default.gray(` [${node.status}]`) : "";
|
|
3606
|
+
const owner = node.ownerName ? source_default.gray(` @${node.ownerName}`) : "";
|
|
3607
|
+
console.log(`${prefix}${connector}${source_default.white(node.title)}${status}${owner}`);
|
|
3608
|
+
console.log(`${prefix}${isLastNode ? " " : "│ "}${source_default.gray(node.slug)}`);
|
|
3609
|
+
if (node.children.length > 0) {
|
|
3610
|
+
const newPrefix = prefix + (isLastNode ? " " : "│ ");
|
|
3611
|
+
printTree(node.children, newPrefix, isLastNode);
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
function registerPagesCommands(program2) {
|
|
3616
|
+
const pages = program2.command("pages").description("Manage pages").addHelpText("after", `
|
|
3617
|
+
Examples:
|
|
3618
|
+
$ thoughtful pages list
|
|
3619
|
+
$ thoughtful pages create "New Feature" --parent roadmap
|
|
3620
|
+
$ thoughtful pages get roadmap
|
|
3621
|
+
$ thoughtful pages search "quarterly goals"
|
|
3622
|
+
$ thoughtful pages update roadmap --status completed
|
|
3623
|
+
$ thoughtful pages delete old-draft --yes
|
|
3624
|
+
`);
|
|
3625
|
+
pages.command("list").description("List all pages").option("--flat", "Show flat list instead of tree").option("--json", "Output as JSON").addHelpText("after", `
|
|
3626
|
+
Examples:
|
|
3627
|
+
$ thoughtful pages list
|
|
3628
|
+
Pages
|
|
3629
|
+
└─ Roadmap
|
|
3630
|
+
roadmap
|
|
3631
|
+
├─ Q1 Goals [active] @alice
|
|
3632
|
+
q1-goals
|
|
3633
|
+
└─ Q2 Goals [draft]
|
|
3634
|
+
q2-goals
|
|
3635
|
+
|
|
3636
|
+
$ thoughtful pages list --flat
|
|
3637
|
+
Pages
|
|
3638
|
+
Roadmap
|
|
3639
|
+
roadmap
|
|
3640
|
+
Q1 Goals [active] @alice
|
|
3641
|
+
q1-goals
|
|
3642
|
+
|
|
3643
|
+
$ thoughtful pages list --json
|
|
3644
|
+
{"pages":[{"id":"pg_123","slug":"roadmap","title":"Roadmap",...},...]}
|
|
3645
|
+
`).action(async (options) => {
|
|
3646
|
+
const json = options.json;
|
|
3647
|
+
const flat = options.flat;
|
|
3648
|
+
try {
|
|
3649
|
+
if (!isLoggedIn()) {
|
|
3650
|
+
if (json) {
|
|
3651
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3652
|
+
} else {
|
|
3653
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3654
|
+
}
|
|
3655
|
+
process.exit(1);
|
|
3656
|
+
}
|
|
3657
|
+
const client = createClient();
|
|
3658
|
+
const data = await client.getPages();
|
|
3659
|
+
if (json) {
|
|
3660
|
+
console.log(JSON.stringify(data));
|
|
3661
|
+
return;
|
|
3662
|
+
}
|
|
3663
|
+
if (data.pages.length === 0) {
|
|
3664
|
+
console.log(source_default.gray("No pages found"));
|
|
3665
|
+
return;
|
|
3666
|
+
}
|
|
3667
|
+
console.log(source_default.blue("Pages"));
|
|
3668
|
+
console.log();
|
|
3669
|
+
if (flat) {
|
|
3670
|
+
for (const page of data.pages) {
|
|
3671
|
+
const status = page.status ? source_default.gray(` [${page.status}]`) : "";
|
|
3672
|
+
const owner = page.ownerName ? source_default.gray(` @${page.ownerName}`) : "";
|
|
3673
|
+
console.log(` ${source_default.white(page.title)}${status}${owner}`);
|
|
3674
|
+
console.log(` ${source_default.gray(page.slug)}`);
|
|
3675
|
+
console.log();
|
|
3676
|
+
}
|
|
3677
|
+
} else {
|
|
3678
|
+
const tree = buildTree(data.pages);
|
|
3679
|
+
printTree(tree);
|
|
3680
|
+
}
|
|
3681
|
+
} catch (error) {
|
|
3682
|
+
handleApiError(error);
|
|
3683
|
+
}
|
|
3684
|
+
});
|
|
3685
|
+
pages.command("get <slug>").description("Get page details").option("--json", "Output as JSON").addHelpText("after", `
|
|
3686
|
+
Examples:
|
|
3687
|
+
$ thoughtful pages get roadmap
|
|
3688
|
+
Roadmap
|
|
3689
|
+
Slug: roadmap
|
|
3690
|
+
ID: pg_abc123
|
|
3691
|
+
Status: active
|
|
3692
|
+
Owner: Alice Smith
|
|
3693
|
+
Created: 1/15/2025, 10:30:00 AM
|
|
3694
|
+
Updated: 1/18/2025, 3:45:00 PM
|
|
3695
|
+
|
|
3696
|
+
$ thoughtful pages get roadmap --json
|
|
3697
|
+
{"page":{"id":"pg_abc123","slug":"roadmap","title":"Roadmap",...}}
|
|
3698
|
+
`).action(async (slug, options) => {
|
|
3699
|
+
const json = options.json;
|
|
3700
|
+
try {
|
|
3701
|
+
if (!isLoggedIn()) {
|
|
3702
|
+
if (json) {
|
|
3703
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3704
|
+
} else {
|
|
3705
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3706
|
+
}
|
|
3707
|
+
process.exit(1);
|
|
3708
|
+
}
|
|
3709
|
+
const client = createClient();
|
|
3710
|
+
const data = await client.getPage(slug);
|
|
3711
|
+
if (json) {
|
|
3712
|
+
console.log(JSON.stringify(data));
|
|
3713
|
+
return;
|
|
3714
|
+
}
|
|
3715
|
+
const page = data.page;
|
|
3716
|
+
console.log(source_default.blue(page.title));
|
|
3717
|
+
console.log();
|
|
3718
|
+
console.log(` ${source_default.gray("Slug:")} ${page.slug}`);
|
|
3719
|
+
console.log(` ${source_default.gray("ID:")} ${page.id}`);
|
|
3720
|
+
if (page.status) {
|
|
3721
|
+
console.log(` ${source_default.gray("Status:")} ${page.status}`);
|
|
3722
|
+
}
|
|
3723
|
+
if (page.ownerName) {
|
|
3724
|
+
console.log(` ${source_default.gray("Owner:")} ${page.ownerName}`);
|
|
3725
|
+
}
|
|
3726
|
+
if (page.parentSlug) {
|
|
3727
|
+
console.log(` ${source_default.gray("Parent:")} ${page.parentSlug}`);
|
|
3728
|
+
}
|
|
3729
|
+
console.log(` ${source_default.gray("Created:")} ${new Date(page.createdAt).toLocaleString()}`);
|
|
3730
|
+
console.log(` ${source_default.gray("Updated:")} ${new Date(page.updatedAt).toLocaleString()}`);
|
|
3731
|
+
if (page.description) {
|
|
3732
|
+
console.log();
|
|
3733
|
+
console.log(source_default.gray("Description:"));
|
|
3734
|
+
console.log(page.description);
|
|
3735
|
+
}
|
|
3736
|
+
} catch (error) {
|
|
3737
|
+
handleApiError(error);
|
|
3738
|
+
}
|
|
3739
|
+
});
|
|
3740
|
+
pages.command("create [title]").description("Create a new page (use '-' to read title from stdin)").option("--parent <slug>", "Parent page slug").option("--owner <email>", "Owner email").option("--status <status>", "Page status").option("--json", "Output as JSON").addHelpText("after", `
|
|
3741
|
+
Examples:
|
|
3742
|
+
$ thoughtful pages create "Q3 Goals"
|
|
3743
|
+
Created page: Q3 Goals
|
|
3744
|
+
Slug: q3-goals
|
|
3745
|
+
|
|
3746
|
+
$ thoughtful pages create "Q3 Goals" --parent roadmap --owner alice@example.com --status draft
|
|
3747
|
+
Created page: Q3 Goals
|
|
3748
|
+
Slug: q3-goals
|
|
3749
|
+
|
|
3750
|
+
$ echo "Project Plan" | thoughtful pages create -
|
|
3751
|
+
Created page: Project Plan
|
|
3752
|
+
Slug: project-plan
|
|
3753
|
+
|
|
3754
|
+
$ thoughtful pages create "Project Plan" --json
|
|
3755
|
+
{"success":true,"page":{"id":"pg_new123","slug":"project-plan","title":"Project Plan"}}
|
|
3756
|
+
`).action(async (titleArg, options) => {
|
|
3757
|
+
const json = options.json;
|
|
3758
|
+
try {
|
|
3759
|
+
if (!isLoggedIn()) {
|
|
3760
|
+
if (json) {
|
|
3761
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3762
|
+
} else {
|
|
3763
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3764
|
+
}
|
|
3765
|
+
process.exit(1);
|
|
3766
|
+
}
|
|
3767
|
+
let title;
|
|
3768
|
+
if (titleArg === "-" || !titleArg && !process.stdin.isTTY) {
|
|
3769
|
+
const chunks = [];
|
|
3770
|
+
for await (const chunk of process.stdin) {
|
|
3771
|
+
chunks.push(chunk);
|
|
3772
|
+
}
|
|
3773
|
+
title = Buffer.concat(chunks).toString("utf-8").trim();
|
|
3774
|
+
if (!title) {
|
|
3775
|
+
throw new ValidationError("No title provided via stdin");
|
|
3776
|
+
}
|
|
3777
|
+
} else if (titleArg) {
|
|
3778
|
+
title = titleArg;
|
|
3779
|
+
} else {
|
|
3780
|
+
throw new ValidationError("Title is required. Use '-' to read from stdin.");
|
|
3781
|
+
}
|
|
3782
|
+
const client = createClient();
|
|
3783
|
+
const data = await client.createPage({
|
|
3784
|
+
title,
|
|
3785
|
+
parentSlug: options.parent,
|
|
3786
|
+
ownerEmail: options.owner,
|
|
3787
|
+
status: options.status
|
|
3788
|
+
});
|
|
3789
|
+
if (json) {
|
|
3790
|
+
console.log(JSON.stringify({ success: true, page: data.page }));
|
|
3791
|
+
} else {
|
|
3792
|
+
console.log(source_default.green(`Created page: ${data.page.title}`));
|
|
3793
|
+
console.log(source_default.gray(`Slug: ${data.page.slug}`));
|
|
3794
|
+
}
|
|
3795
|
+
} catch (error) {
|
|
3796
|
+
handleApiError(error);
|
|
3797
|
+
}
|
|
3798
|
+
});
|
|
3799
|
+
pages.command("update <slug>").description("Update a page").option("--title <title>", "New title").option("--status <status>", "New status").option("--owner <email>", "New owner email").option("--dry-run", "Show what would be updated without making changes").option("--json", "Output as JSON").addHelpText("after", `
|
|
3800
|
+
Examples:
|
|
3801
|
+
$ thoughtful pages update roadmap --status completed
|
|
3802
|
+
Updated page: Roadmap
|
|
3803
|
+
|
|
3804
|
+
$ thoughtful pages update q1-goals --title "Q1 2025 Goals" --owner bob@example.com
|
|
3805
|
+
Updated page: Q1 2025 Goals
|
|
3806
|
+
|
|
3807
|
+
$ thoughtful pages update roadmap --status active --dry-run
|
|
3808
|
+
Dry run mode - no changes will be made
|
|
3809
|
+
Page: roadmap
|
|
3810
|
+
Updates:
|
|
3811
|
+
status: active
|
|
3812
|
+
|
|
3813
|
+
$ thoughtful pages update roadmap --status active --json
|
|
3814
|
+
{"success":true,"page":{"id":"pg_abc123","slug":"roadmap","title":"Roadmap","status":"active"}}
|
|
3815
|
+
`).action(async (slug, options) => {
|
|
3816
|
+
const json = options.json;
|
|
3817
|
+
const dryRun = options.dryRun;
|
|
3818
|
+
try {
|
|
3819
|
+
if (!isLoggedIn()) {
|
|
3820
|
+
if (json) {
|
|
3821
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3822
|
+
} else {
|
|
3823
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3824
|
+
}
|
|
3825
|
+
process.exit(1);
|
|
3826
|
+
}
|
|
3827
|
+
const updates = {};
|
|
3828
|
+
if (options.title)
|
|
3829
|
+
updates.title = options.title;
|
|
3830
|
+
if (options.status)
|
|
3831
|
+
updates.status = options.status;
|
|
3832
|
+
if (options.owner)
|
|
3833
|
+
updates.ownerEmail = options.owner;
|
|
3834
|
+
if (Object.keys(updates).length === 0) {
|
|
3835
|
+
throw new ValidationError("No updates specified. Use --title, --status, or --owner");
|
|
3836
|
+
}
|
|
3837
|
+
if (dryRun) {
|
|
3838
|
+
if (json) {
|
|
3839
|
+
console.log(JSON.stringify({
|
|
3840
|
+
dryRun: true,
|
|
3841
|
+
slug,
|
|
3842
|
+
updates,
|
|
3843
|
+
message: "No changes made (dry run)"
|
|
3844
|
+
}));
|
|
3845
|
+
} else {
|
|
3846
|
+
console.log(source_default.blue("Dry run mode - no changes will be made"));
|
|
3847
|
+
console.log();
|
|
3848
|
+
console.log(source_default.gray(`Page: ${slug}`));
|
|
3849
|
+
console.log(source_default.gray("Updates:"));
|
|
3850
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
3851
|
+
console.log(` ${source_default.gray(`${key}:`)} ${value}`);
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
return;
|
|
3855
|
+
}
|
|
3856
|
+
const client = createClient();
|
|
3857
|
+
const data = await client.updatePage(slug, updates);
|
|
3858
|
+
if (json) {
|
|
3859
|
+
console.log(JSON.stringify({ success: true, page: data.page }));
|
|
3860
|
+
} else {
|
|
3861
|
+
console.log(source_default.green(`Updated page: ${data.page.title}`));
|
|
3862
|
+
}
|
|
3863
|
+
} catch (error) {
|
|
3864
|
+
handleApiError(error);
|
|
3865
|
+
}
|
|
3866
|
+
});
|
|
3867
|
+
pages.command("delete <slug>").description("Delete a page").option("-y, --yes", "Skip confirmation").option("--dry-run", "Show what would be deleted without making changes").option("--json", "Output as JSON").addHelpText("after", `
|
|
3868
|
+
Examples:
|
|
3869
|
+
$ thoughtful pages delete old-draft
|
|
3870
|
+
Are you sure you want to delete 'old-draft'? (y/N) y
|
|
3871
|
+
Deleted page: old-draft
|
|
3872
|
+
|
|
3873
|
+
$ thoughtful pages delete old-draft --yes
|
|
3874
|
+
Deleted page: old-draft
|
|
3875
|
+
|
|
3876
|
+
$ thoughtful pages delete old-draft --dry-run
|
|
3877
|
+
Dry run mode - no changes will be made
|
|
3878
|
+
Would delete page: old-draft
|
|
3879
|
+
|
|
3880
|
+
$ thoughtful pages delete old-draft --yes --json
|
|
3881
|
+
{"success":true}
|
|
3882
|
+
`).action(async (slug, options) => {
|
|
3883
|
+
const json = options.json;
|
|
3884
|
+
const skipConfirm = options.yes;
|
|
3885
|
+
const dryRun = options.dryRun;
|
|
3886
|
+
try {
|
|
3887
|
+
if (!isLoggedIn()) {
|
|
3888
|
+
if (json) {
|
|
3889
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3890
|
+
} else {
|
|
3891
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3892
|
+
}
|
|
3893
|
+
process.exit(1);
|
|
3894
|
+
}
|
|
3895
|
+
if (dryRun) {
|
|
3896
|
+
if (json) {
|
|
3897
|
+
console.log(JSON.stringify({
|
|
3898
|
+
dryRun: true,
|
|
3899
|
+
slug,
|
|
3900
|
+
message: "No changes made (dry run)"
|
|
3901
|
+
}));
|
|
3902
|
+
} else {
|
|
3903
|
+
console.log(source_default.blue("Dry run mode - no changes will be made"));
|
|
3904
|
+
console.log();
|
|
3905
|
+
console.log(source_default.gray(`Would delete page: ${slug}`));
|
|
3906
|
+
}
|
|
3907
|
+
return;
|
|
3908
|
+
}
|
|
3909
|
+
if (!skipConfirm && !json) {
|
|
3910
|
+
try {
|
|
3911
|
+
const shouldDelete = await confirm(`Are you sure you want to delete '${slug}'?`, { defaultValue: false });
|
|
3912
|
+
if (!shouldDelete) {
|
|
3913
|
+
console.log(source_default.yellow("Cancelled"));
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
} catch (error) {
|
|
3917
|
+
if (error instanceof Error) {
|
|
3918
|
+
throw new ValidationError(`Cannot confirm deletion. ${error.message} Use --yes flag to skip confirmation.`);
|
|
3919
|
+
}
|
|
3920
|
+
throw error;
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
const client = createClient();
|
|
3924
|
+
await client.deletePage(slug);
|
|
3925
|
+
if (json) {
|
|
3926
|
+
console.log(JSON.stringify({ success: true }));
|
|
3927
|
+
} else {
|
|
3928
|
+
console.log(source_default.green(`Deleted page: ${slug}`));
|
|
3929
|
+
}
|
|
3930
|
+
} catch (error) {
|
|
3931
|
+
handleApiError(error);
|
|
3932
|
+
}
|
|
3933
|
+
});
|
|
3934
|
+
pages.command("search <query>").description("Search pages").option("--json", "Output as JSON").addHelpText("after", `
|
|
3935
|
+
Examples:
|
|
3936
|
+
$ thoughtful pages search "quarterly goals"
|
|
3937
|
+
Search results for 'quarterly goals'
|
|
3938
|
+
Q1 Goals [active]
|
|
3939
|
+
q1-goals
|
|
3940
|
+
Planning and objectives for Q1 2025
|
|
3941
|
+
|
|
3942
|
+
Q2 Goals [draft]
|
|
3943
|
+
q2-goals
|
|
3944
|
+
|
|
3945
|
+
$ thoughtful pages search "roadmap" --json
|
|
3946
|
+
{"pages":[{"id":"pg_123","slug":"roadmap","title":"Roadmap",...},...]}
|
|
3947
|
+
`).action(async (query, options) => {
|
|
3948
|
+
const json = options.json;
|
|
3949
|
+
try {
|
|
3950
|
+
if (!isLoggedIn()) {
|
|
3951
|
+
if (json) {
|
|
3952
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
3953
|
+
} else {
|
|
3954
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
3955
|
+
}
|
|
3956
|
+
process.exit(1);
|
|
3957
|
+
}
|
|
3958
|
+
const client = createClient();
|
|
3959
|
+
const data = await client.searchPages(query);
|
|
3960
|
+
if (json) {
|
|
3961
|
+
console.log(JSON.stringify(data));
|
|
3962
|
+
return;
|
|
3963
|
+
}
|
|
3964
|
+
if (data.pages.length === 0) {
|
|
3965
|
+
console.log(source_default.gray(`No pages found matching '${query}'`));
|
|
3966
|
+
return;
|
|
3967
|
+
}
|
|
3968
|
+
console.log(source_default.blue(`Search results for '${query}'`));
|
|
3969
|
+
console.log();
|
|
3970
|
+
for (const page of data.pages) {
|
|
3971
|
+
const status = page.status ? source_default.gray(` [${page.status}]`) : "";
|
|
3972
|
+
console.log(` ${source_default.white(page.title)}${status}`);
|
|
3973
|
+
console.log(` ${source_default.gray(page.slug)}`);
|
|
3974
|
+
if (page.description) {
|
|
3975
|
+
const desc = page.description.length > 100 ? page.description.slice(0, 100) + "..." : page.description;
|
|
3976
|
+
console.log(` ${source_default.gray(desc)}`);
|
|
3977
|
+
}
|
|
3978
|
+
console.log();
|
|
3979
|
+
}
|
|
3980
|
+
} catch (error) {
|
|
3981
|
+
handleApiError(error);
|
|
3982
|
+
}
|
|
3983
|
+
});
|
|
3984
|
+
}
|
|
3985
|
+
|
|
3986
|
+
// src/commands/chat.ts
|
|
3987
|
+
function registerChatCommands(program2) {
|
|
3988
|
+
const threads = program2.command("threads").description("Manage chat threads").addHelpText("after", `
|
|
3989
|
+
Examples:
|
|
3990
|
+
$ thoughtful threads list
|
|
3991
|
+
$ thoughtful threads new "What's the status of project X?"
|
|
3992
|
+
$ thoughtful threads show thread_abc123
|
|
3993
|
+
$ thoughtful threads send thread_abc123 "Can you provide more details?"
|
|
3994
|
+
`);
|
|
3995
|
+
threads.command("list").description("List recent chat threads").option("--json", "Output as JSON").addHelpText("after", `
|
|
3996
|
+
Examples:
|
|
3997
|
+
$ thoughtful threads list
|
|
3998
|
+
Chat Threads
|
|
3999
|
+
Project Status Discussion
|
|
4000
|
+
ID: thread_abc123
|
|
4001
|
+
Last activity: 1/18/2025
|
|
4002
|
+
|
|
4003
|
+
Weekly Planning
|
|
4004
|
+
ID: thread_xyz789
|
|
4005
|
+
Last activity: 1/15/2025
|
|
4006
|
+
|
|
4007
|
+
$ thoughtful threads list --json
|
|
4008
|
+
{"threads":[{"providerThreadId":"thread_abc123","title":"Project Status Discussion",...},...]}
|
|
4009
|
+
`).action(async (options) => {
|
|
4010
|
+
const json = options.json;
|
|
4011
|
+
try {
|
|
4012
|
+
if (!isLoggedIn()) {
|
|
4013
|
+
if (json) {
|
|
4014
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
4015
|
+
} else {
|
|
4016
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
4017
|
+
}
|
|
4018
|
+
process.exit(1);
|
|
4019
|
+
}
|
|
4020
|
+
const client = createClient();
|
|
4021
|
+
const data = await client.getThreads();
|
|
4022
|
+
if (json) {
|
|
4023
|
+
console.log(JSON.stringify(data));
|
|
4024
|
+
return;
|
|
4025
|
+
}
|
|
4026
|
+
if (data.threads.length === 0) {
|
|
4027
|
+
console.log(source_default.gray("No chat threads found"));
|
|
4028
|
+
return;
|
|
4029
|
+
}
|
|
4030
|
+
console.log(source_default.blue("Chat Threads"));
|
|
4031
|
+
console.log();
|
|
4032
|
+
for (const thread of data.threads) {
|
|
4033
|
+
const title = thread.title || source_default.gray("(untitled)");
|
|
4034
|
+
const date = thread.lastMessageAt ? new Date(thread.lastMessageAt).toLocaleDateString() : new Date(thread.createdAt).toLocaleDateString();
|
|
4035
|
+
console.log(` ${source_default.white(title)}`);
|
|
4036
|
+
console.log(` ${source_default.gray(`ID: ${thread.providerThreadId}`)}`);
|
|
4037
|
+
console.log(` ${source_default.gray(`Last activity: ${date}`)}`);
|
|
4038
|
+
console.log();
|
|
4039
|
+
}
|
|
4040
|
+
} catch (error) {
|
|
4041
|
+
handleApiError(error);
|
|
4042
|
+
}
|
|
4043
|
+
});
|
|
4044
|
+
threads.command("new [message]").description("Start a new chat thread").option("--json", "Output as JSON").option("--no-ai", "Don't trigger AI response").addHelpText("after", `
|
|
4045
|
+
Examples:
|
|
4046
|
+
$ thoughtful threads new
|
|
4047
|
+
Created new chat thread
|
|
4048
|
+
Thread ID: thread_abc123
|
|
4049
|
+
|
|
4050
|
+
$ thoughtful threads new "What's the status of project X?"
|
|
4051
|
+
Created new chat thread
|
|
4052
|
+
Thread ID: thread_abc123
|
|
4053
|
+
|
|
4054
|
+
AI Response:
|
|
4055
|
+
Based on the latest updates...
|
|
4056
|
+
|
|
4057
|
+
$ thoughtful threads new "What are our Q1 goals?" --json
|
|
4058
|
+
{"success":true,"thread":{"providerThreadId":"thread_abc123"},"aiResponse":{...}}
|
|
4059
|
+
|
|
4060
|
+
$ thoughtful threads new "Hello" --no-ai
|
|
4061
|
+
Created new chat thread
|
|
4062
|
+
Thread ID: thread_abc123
|
|
4063
|
+
Sent initial message
|
|
4064
|
+
`).action(async (message, options) => {
|
|
4065
|
+
const json = options.json;
|
|
4066
|
+
const triggerAi = options.ai !== false;
|
|
4067
|
+
try {
|
|
4068
|
+
if (!isLoggedIn()) {
|
|
4069
|
+
if (json) {
|
|
4070
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
4071
|
+
} else {
|
|
4072
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
4073
|
+
}
|
|
4074
|
+
process.exit(1);
|
|
4075
|
+
}
|
|
4076
|
+
const client = createClient();
|
|
4077
|
+
if (message && triggerAi) {
|
|
4078
|
+
const threadData = await client.createThread();
|
|
4079
|
+
const threadId = threadData.thread.providerThreadId;
|
|
4080
|
+
if (json) {
|
|
4081
|
+
console.log(JSON.stringify({ success: true, thread: { providerThreadId: threadId } }));
|
|
4082
|
+
} else {
|
|
4083
|
+
console.log(source_default.green("Created new chat thread"));
|
|
4084
|
+
console.log(source_default.gray(`Thread ID: ${threadId}`));
|
|
4085
|
+
console.log();
|
|
4086
|
+
}
|
|
4087
|
+
const response = await client.sendMessageWithResponse(threadId, message);
|
|
4088
|
+
if (json) {
|
|
4089
|
+
console.log(JSON.stringify({ success: true, ...response }));
|
|
4090
|
+
} else {
|
|
4091
|
+
console.log(source_default.bold("AI Response:"));
|
|
4092
|
+
console.log(response.aiResponse.content);
|
|
4093
|
+
}
|
|
4094
|
+
} else {
|
|
4095
|
+
const data = await client.createThread(message);
|
|
4096
|
+
if (json) {
|
|
4097
|
+
console.log(JSON.stringify({ success: true, ...data }));
|
|
4098
|
+
} else {
|
|
4099
|
+
console.log(source_default.green("Created new chat thread"));
|
|
4100
|
+
console.log(source_default.gray(`Thread ID: ${data.thread.providerThreadId}`));
|
|
4101
|
+
if (message) {
|
|
4102
|
+
console.log(source_default.gray("Sent initial message"));
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
} catch (error) {
|
|
4107
|
+
handleApiError(error);
|
|
4108
|
+
}
|
|
4109
|
+
});
|
|
4110
|
+
threads.command("show <thread-id>").description("Show messages in a thread").option("--json", "Output as JSON").addHelpText("after", `
|
|
4111
|
+
Examples:
|
|
4112
|
+
$ thoughtful threads show thread_abc123
|
|
4113
|
+
Thread thread_abc123
|
|
4114
|
+
|
|
4115
|
+
You (1/18/2025, 10:30:00 AM)
|
|
4116
|
+
What's the status of project X?
|
|
4117
|
+
|
|
4118
|
+
Assistant (1/18/2025, 10:30:15 AM)
|
|
4119
|
+
Project X is currently in the testing phase...
|
|
4120
|
+
|
|
4121
|
+
$ thoughtful threads show thread_abc123 --json
|
|
4122
|
+
{"messages":[{"role":"user","content":"What's the status of project X?",...},...]}
|
|
4123
|
+
`).action(async (threadId, options) => {
|
|
4124
|
+
const json = options.json;
|
|
4125
|
+
try {
|
|
4126
|
+
if (!isLoggedIn()) {
|
|
4127
|
+
if (json) {
|
|
4128
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
4129
|
+
} else {
|
|
4130
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
4131
|
+
}
|
|
4132
|
+
process.exit(1);
|
|
4133
|
+
}
|
|
4134
|
+
const client = createClient();
|
|
4135
|
+
const data = await client.getThreadMessages(threadId);
|
|
4136
|
+
if (json) {
|
|
4137
|
+
console.log(JSON.stringify(data));
|
|
4138
|
+
return;
|
|
4139
|
+
}
|
|
4140
|
+
if (data.messages.length === 0) {
|
|
4141
|
+
console.log(source_default.gray("No messages in this thread"));
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
console.log(source_default.blue(`Thread ${threadId}`));
|
|
4145
|
+
console.log();
|
|
4146
|
+
for (const msg of data.messages) {
|
|
4147
|
+
const roleColor = msg.role === "user" ? source_default.cyan : source_default.green;
|
|
4148
|
+
const roleLabel = msg.role === "user" ? "You" : "Assistant";
|
|
4149
|
+
const date = new Date(msg.createdAt).toLocaleString();
|
|
4150
|
+
console.log(`${roleColor(roleLabel)} ${source_default.gray(`(${date})`)}`);
|
|
4151
|
+
console.log(msg.content);
|
|
4152
|
+
console.log();
|
|
4153
|
+
}
|
|
4154
|
+
} catch (error) {
|
|
4155
|
+
handleApiError(error);
|
|
4156
|
+
}
|
|
4157
|
+
});
|
|
4158
|
+
threads.command("send <thread-id> [message...]").description("Send a message to a thread and get AI response (use '-' to read from stdin)").option("--json", "Output as JSON").option("--no-ai", "Don't trigger AI response").addHelpText("after", `
|
|
4159
|
+
Examples:
|
|
4160
|
+
$ thoughtful threads send thread_abc123 "Can you provide more details?"
|
|
4161
|
+
Sent message
|
|
4162
|
+
|
|
4163
|
+
AI Response:
|
|
4164
|
+
Sure! Here are the details...
|
|
4165
|
+
|
|
4166
|
+
$ thoughtful threads send thread_abc123 What is the next milestone?
|
|
4167
|
+
Sent message
|
|
4168
|
+
|
|
4169
|
+
AI Response:
|
|
4170
|
+
The next milestone is scheduled for...
|
|
4171
|
+
|
|
4172
|
+
$ echo "What are the blockers?" | thoughtful threads send thread_abc123 -
|
|
4173
|
+
Sent message
|
|
4174
|
+
|
|
4175
|
+
AI Response:
|
|
4176
|
+
Currently, the main blockers are...
|
|
4177
|
+
|
|
4178
|
+
$ thoughtful threads send thread_abc123 "Update please" --json
|
|
4179
|
+
{"success":true,"userMessage":{...},"aiResponse":{...}}
|
|
4180
|
+
|
|
4181
|
+
$ thoughtful threads send thread_abc123 "Just a note" --no-ai
|
|
4182
|
+
Message sent
|
|
4183
|
+
`).action(async (threadId, messageParts, options) => {
|
|
4184
|
+
const json = options.json;
|
|
4185
|
+
const triggerAi = options.ai !== false;
|
|
4186
|
+
try {
|
|
4187
|
+
if (!isLoggedIn()) {
|
|
4188
|
+
if (json) {
|
|
4189
|
+
console.log(JSON.stringify({ error: true, message: "Not logged in" }));
|
|
4190
|
+
} else {
|
|
4191
|
+
console.log(source_default.yellow("Not logged in. Run 'thoughtful login' first."));
|
|
4192
|
+
}
|
|
4193
|
+
process.exit(1);
|
|
4194
|
+
}
|
|
4195
|
+
let message;
|
|
4196
|
+
if (messageParts.length === 1 && messageParts[0] === "-" || messageParts.length === 0 && !process.stdin.isTTY) {
|
|
4197
|
+
const chunks = [];
|
|
4198
|
+
for await (const chunk of process.stdin) {
|
|
4199
|
+
chunks.push(chunk);
|
|
4200
|
+
}
|
|
4201
|
+
message = Buffer.concat(chunks).toString("utf-8").trim();
|
|
4202
|
+
if (!message) {
|
|
4203
|
+
throw new ValidationError("No message provided via stdin");
|
|
4204
|
+
}
|
|
4205
|
+
} else if (messageParts.length > 0) {
|
|
4206
|
+
message = messageParts.join(" ");
|
|
4207
|
+
} else {
|
|
4208
|
+
throw new ValidationError("Message is required. Use '-' to read from stdin.");
|
|
4209
|
+
}
|
|
4210
|
+
const client = createClient();
|
|
4211
|
+
if (triggerAi) {
|
|
4212
|
+
const data = await client.sendMessageWithResponse(threadId, message);
|
|
4213
|
+
if (json) {
|
|
4214
|
+
console.log(JSON.stringify({ success: true, ...data }));
|
|
4215
|
+
} else {
|
|
4216
|
+
console.log(source_default.gray("Sent message"));
|
|
4217
|
+
console.log();
|
|
4218
|
+
console.log(source_default.bold("AI Response:"));
|
|
4219
|
+
console.log(data.aiResponse.content);
|
|
4220
|
+
}
|
|
4221
|
+
} else {
|
|
4222
|
+
const data = await client.sendThreadMessage(threadId, message);
|
|
4223
|
+
if (json) {
|
|
4224
|
+
console.log(JSON.stringify({ success: true, message: data.message }));
|
|
4225
|
+
} else {
|
|
4226
|
+
console.log(source_default.green("Message sent"));
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
} catch (error) {
|
|
4230
|
+
handleApiError(error);
|
|
4231
|
+
}
|
|
4232
|
+
});
|
|
4233
|
+
}
|
|
4234
|
+
|
|
4235
|
+
// src/commands/completion.ts
|
|
4236
|
+
var bashCompletion = `
|
|
4237
|
+
# Bash completion for thoughtful CLI
|
|
4238
|
+
# Add this to your ~/.bashrc or ~/.bash_profile:
|
|
4239
|
+
# eval "$(thoughtful completion bash)"
|
|
4240
|
+
|
|
4241
|
+
_thoughtful_completion() {
|
|
4242
|
+
local cur prev opts
|
|
4243
|
+
COMPREPLY=()
|
|
4244
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
4245
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
4246
|
+
|
|
4247
|
+
# Top-level commands
|
|
4248
|
+
if [ \${COMP_CWORD} -eq 1 ]; then
|
|
4249
|
+
opts="login logout whoami orgs workspaces pages threads completion help"
|
|
4250
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
4251
|
+
return 0
|
|
4252
|
+
fi
|
|
4253
|
+
|
|
4254
|
+
# Subcommands
|
|
4255
|
+
case "\${COMP_WORDS[1]}" in
|
|
4256
|
+
orgs)
|
|
4257
|
+
if [ \${COMP_CWORD} -eq 2 ]; then
|
|
4258
|
+
opts="list switch"
|
|
4259
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
4260
|
+
fi
|
|
4261
|
+
;;
|
|
4262
|
+
workspaces)
|
|
4263
|
+
if [ \${COMP_CWORD} -eq 2 ]; then
|
|
4264
|
+
opts="list switch create"
|
|
4265
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
4266
|
+
fi
|
|
4267
|
+
;;
|
|
4268
|
+
pages)
|
|
4269
|
+
if [ \${COMP_CWORD} -eq 2 ]; then
|
|
4270
|
+
opts="list get create update delete search"
|
|
4271
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
4272
|
+
fi
|
|
4273
|
+
;;
|
|
4274
|
+
threads)
|
|
4275
|
+
if [ \${COMP_CWORD} -eq 2 ]; then
|
|
4276
|
+
opts="list new show send"
|
|
4277
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
4278
|
+
fi
|
|
4279
|
+
;;
|
|
4280
|
+
completion)
|
|
4281
|
+
if [ \${COMP_CWORD} -eq 2 ]; then
|
|
4282
|
+
opts="bash zsh fish"
|
|
4283
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
4284
|
+
fi
|
|
4285
|
+
;;
|
|
4286
|
+
esac
|
|
4287
|
+
|
|
4288
|
+
# Options
|
|
4289
|
+
case "\${prev}" in
|
|
4290
|
+
--parent|--owner|--status|--title)
|
|
4291
|
+
# No completion for these
|
|
4292
|
+
return 0
|
|
4293
|
+
;;
|
|
4294
|
+
*)
|
|
4295
|
+
# Suggest flags
|
|
4296
|
+
if [[ \${cur} == -* ]]; then
|
|
4297
|
+
opts="--json --help --flat --yes"
|
|
4298
|
+
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
4299
|
+
fi
|
|
4300
|
+
;;
|
|
4301
|
+
esac
|
|
4302
|
+
}
|
|
4303
|
+
|
|
4304
|
+
complete -F _thoughtful_completion thoughtful
|
|
4305
|
+
`;
|
|
4306
|
+
var zshCompletion = `
|
|
4307
|
+
# Zsh completion for thoughtful CLI
|
|
4308
|
+
# Add this to your ~/.zshrc:
|
|
4309
|
+
# eval "$(thoughtful completion zsh)"
|
|
4310
|
+
|
|
4311
|
+
#compdef thoughtful
|
|
4312
|
+
|
|
4313
|
+
_thoughtful() {
|
|
4314
|
+
local line state
|
|
4315
|
+
|
|
4316
|
+
_arguments -C \\
|
|
4317
|
+
"1: :->cmds" \\
|
|
4318
|
+
"*::arg:->args"
|
|
4319
|
+
|
|
4320
|
+
case "$state" in
|
|
4321
|
+
cmds)
|
|
4322
|
+
_values "thoughtful commands" \\
|
|
4323
|
+
"login[Log in to Thoughtful]" \\
|
|
4324
|
+
"logout[Log out]" \\
|
|
4325
|
+
"whoami[Show current user info]" \\
|
|
4326
|
+
"orgs[Manage organizations]" \\
|
|
4327
|
+
"workspaces[Manage workspaces]" \\
|
|
4328
|
+
"pages[Manage pages]" \\
|
|
4329
|
+
"threads[Manage chat threads]" \\
|
|
4330
|
+
"completion[Generate shell completion scripts]" \\
|
|
4331
|
+
"help[Display help information]"
|
|
4332
|
+
;;
|
|
4333
|
+
args)
|
|
4334
|
+
case $line[1] in
|
|
4335
|
+
orgs)
|
|
4336
|
+
_values "orgs commands" \\
|
|
4337
|
+
"list[List organizations]" \\
|
|
4338
|
+
"switch[Switch to a different organization]"
|
|
4339
|
+
;;
|
|
4340
|
+
workspaces)
|
|
4341
|
+
_values "workspaces commands" \\
|
|
4342
|
+
"list[List workspaces]" \\
|
|
4343
|
+
"switch[Switch to a different workspace]" \\
|
|
4344
|
+
"create[Create a new workspace]"
|
|
4345
|
+
;;
|
|
4346
|
+
pages)
|
|
4347
|
+
_values "pages commands" \\
|
|
4348
|
+
"list[List all pages]" \\
|
|
4349
|
+
"get[Get page details]" \\
|
|
4350
|
+
"create[Create a new page]" \\
|
|
4351
|
+
"update[Update a page]" \\
|
|
4352
|
+
"delete[Delete a page]" \\
|
|
4353
|
+
"search[Search pages]"
|
|
4354
|
+
;;
|
|
4355
|
+
threads)
|
|
4356
|
+
_values "threads commands" \\
|
|
4357
|
+
"list[List recent chat threads]" \\
|
|
4358
|
+
"new[Start a new chat thread]" \\
|
|
4359
|
+
"show[Show messages in a thread]" \\
|
|
4360
|
+
"send[Send a message to a thread]"
|
|
4361
|
+
;;
|
|
4362
|
+
completion)
|
|
4363
|
+
_values "completion shells" \\
|
|
4364
|
+
"bash[Generate bash completion script]" \\
|
|
4365
|
+
"zsh[Generate zsh completion script]" \\
|
|
4366
|
+
"fish[Generate fish completion script]"
|
|
4367
|
+
;;
|
|
4368
|
+
esac
|
|
4369
|
+
;;
|
|
4370
|
+
esac
|
|
4371
|
+
}
|
|
4372
|
+
|
|
4373
|
+
_thoughtful
|
|
4374
|
+
`;
|
|
4375
|
+
var fishCompletion = `
|
|
4376
|
+
# Fish completion for thoughtful CLI
|
|
4377
|
+
# Add this to your ~/.config/fish/completions/thoughtful.fish:
|
|
4378
|
+
# thoughtful completion fish > ~/.config/fish/completions/thoughtful.fish
|
|
4379
|
+
|
|
4380
|
+
# Remove old completions
|
|
4381
|
+
complete -c thoughtful -e
|
|
4382
|
+
|
|
4383
|
+
# Top-level commands
|
|
4384
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "login" -d "Log in to Thoughtful"
|
|
4385
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "logout" -d "Log out"
|
|
4386
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "whoami" -d "Show current user info"
|
|
4387
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "orgs" -d "Manage organizations"
|
|
4388
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "workspaces" -d "Manage workspaces"
|
|
4389
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "pages" -d "Manage pages"
|
|
4390
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "threads" -d "Manage chat threads"
|
|
4391
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "completion" -d "Generate shell completion scripts"
|
|
4392
|
+
complete -c thoughtful -f -n "__fish_use_subcommand" -a "help" -d "Display help information"
|
|
4393
|
+
|
|
4394
|
+
# orgs subcommands
|
|
4395
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from orgs; and not __fish_seen_subcommand_from list switch" -a "list" -d "List organizations"
|
|
4396
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from orgs; and not __fish_seen_subcommand_from list switch" -a "switch" -d "Switch to a different organization"
|
|
4397
|
+
|
|
4398
|
+
# workspaces subcommands
|
|
4399
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from workspaces; and not __fish_seen_subcommand_from list switch create" -a "list" -d "List workspaces"
|
|
4400
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from workspaces; and not __fish_seen_subcommand_from list switch create" -a "switch" -d "Switch to a different workspace"
|
|
4401
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from workspaces; and not __fish_seen_subcommand_from list switch create" -a "create" -d "Create a new workspace"
|
|
4402
|
+
|
|
4403
|
+
# pages subcommands
|
|
4404
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from pages; and not __fish_seen_subcommand_from list get create update delete search" -a "list" -d "List all pages"
|
|
4405
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from pages; and not __fish_seen_subcommand_from list get create update delete search" -a "get" -d "Get page details"
|
|
4406
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from pages; and not __fish_seen_subcommand_from list get create update delete search" -a "create" -d "Create a new page"
|
|
4407
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from pages; and not __fish_seen_subcommand_from list get create update delete search" -a "update" -d "Update a page"
|
|
4408
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from pages; and not __fish_seen_subcommand_from list get create update delete search" -a "delete" -d "Delete a page"
|
|
4409
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from pages; and not __fish_seen_subcommand_from list get create update delete search" -a "search" -d "Search pages"
|
|
4410
|
+
|
|
4411
|
+
# threads subcommands
|
|
4412
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from threads; and not __fish_seen_subcommand_from list new show send" -a "list" -d "List recent chat threads"
|
|
4413
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from threads; and not __fish_seen_subcommand_from list new show send" -a "new" -d "Start a new chat thread"
|
|
4414
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from threads; and not __fish_seen_subcommand_from list new show send" -a "show" -d "Show messages in a thread"
|
|
4415
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from threads; and not __fish_seen_subcommand_from list new show send" -a "send" -d "Send a message to a thread"
|
|
4416
|
+
|
|
4417
|
+
# completion subcommands
|
|
4418
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from completion; and not __fish_seen_subcommand_from bash zsh fish" -a "bash" -d "Generate bash completion script"
|
|
4419
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from completion; and not __fish_seen_subcommand_from bash zsh fish" -a "zsh" -d "Generate zsh completion script"
|
|
4420
|
+
complete -c thoughtful -f -n "__fish_seen_subcommand_from completion; and not __fish_seen_subcommand_from bash zsh fish" -a "fish" -d "Generate fish completion script"
|
|
4421
|
+
|
|
4422
|
+
# Global options
|
|
4423
|
+
complete -c thoughtful -l json -d "Output as JSON"
|
|
4424
|
+
complete -c thoughtful -l help -d "Display help"
|
|
4425
|
+
complete -c thoughtful -l flat -d "Show flat list instead of tree"
|
|
4426
|
+
complete -c thoughtful -l yes -s y -d "Skip confirmation"
|
|
4427
|
+
complete -c thoughtful -l parent -d "Parent page slug"
|
|
4428
|
+
complete -c thoughtful -l owner -d "Owner email"
|
|
4429
|
+
complete -c thoughtful -l status -d "Page status"
|
|
4430
|
+
complete -c thoughtful -l title -d "Page title"
|
|
4431
|
+
`;
|
|
4432
|
+
function registerCompletionCommand(program2) {
|
|
4433
|
+
const completion = program2.command("completion").description("Generate shell completion scripts");
|
|
4434
|
+
completion.command("bash").description("Generate bash completion script").action(() => {
|
|
4435
|
+
console.log(bashCompletion);
|
|
4436
|
+
});
|
|
4437
|
+
completion.command("zsh").description("Generate zsh completion script").action(() => {
|
|
4438
|
+
console.log(zshCompletion);
|
|
4439
|
+
});
|
|
4440
|
+
completion.command("fish").description("Generate fish completion script").action(() => {
|
|
4441
|
+
console.log(fishCompletion);
|
|
4442
|
+
});
|
|
4443
|
+
completion.action(() => {
|
|
4444
|
+
console.log(source_default.blue("Shell Completion Installation"));
|
|
4445
|
+
console.log();
|
|
4446
|
+
console.log("Generate completion scripts for your shell:");
|
|
4447
|
+
console.log();
|
|
4448
|
+
console.log(source_default.cyan("Bash:"));
|
|
4449
|
+
console.log(" Add to ~/.bashrc:");
|
|
4450
|
+
console.log(source_default.gray(' eval "$(thoughtful completion bash)"'));
|
|
4451
|
+
console.log();
|
|
4452
|
+
console.log(source_default.cyan("Zsh:"));
|
|
4453
|
+
console.log(" Add to ~/.zshrc:");
|
|
4454
|
+
console.log(source_default.gray(' eval "$(thoughtful completion zsh)"'));
|
|
4455
|
+
console.log();
|
|
4456
|
+
console.log(source_default.cyan("Fish:"));
|
|
4457
|
+
console.log(" Save to completions directory:");
|
|
4458
|
+
console.log(source_default.gray(" thoughtful completion fish > ~/.config/fish/completions/thoughtful.fish"));
|
|
4459
|
+
console.log();
|
|
4460
|
+
console.log("After adding the completion script, restart your shell or source the config file.");
|
|
4461
|
+
});
|
|
4462
|
+
}
|
|
4463
|
+
|
|
4464
|
+
// src/index.ts
|
|
4465
|
+
var __filename2 = fileURLToPath(import.meta.url);
|
|
4466
|
+
var __dirname2 = dirname(__filename2);
|
|
4467
|
+
var packageJsonPath = join(__dirname2, "..", "package.json");
|
|
4468
|
+
var packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
4469
|
+
var version = packageJson.version;
|
|
4470
|
+
var program2 = new Command;
|
|
4471
|
+
program2.name("thoughtful").description("CLI for interacting with your Thoughtful workspace").version(version).option("--json", "Output as JSON").option("--no-color", "Disable colored output").option("-q, --quiet", "Suppress non-essential output").option("-v, --verbose", "Show verbose output").option("--no-input", "Disable interactive prompts (requires all inputs via flags)").option("--dev", "Use development API (http://localhost:3000)").option("--prod", "Use production API (https://www.thoughtful.app)").hook("preAction", (thisCommand) => {
|
|
4472
|
+
const opts = thisCommand.opts();
|
|
4473
|
+
if (opts.dev && opts.prod) {
|
|
4474
|
+
console.error("Error: Cannot specify both --dev and --prod flags");
|
|
4475
|
+
process.exit(1);
|
|
4476
|
+
}
|
|
4477
|
+
if (opts.dev) {
|
|
4478
|
+
setEnvironmentOverride("dev");
|
|
4479
|
+
} else if (opts.prod) {
|
|
4480
|
+
setEnvironmentOverride("prod");
|
|
4481
|
+
}
|
|
4482
|
+
setGlobalOptions({
|
|
4483
|
+
json: opts.json,
|
|
4484
|
+
noColor: opts.color === false,
|
|
4485
|
+
quiet: opts.quiet,
|
|
4486
|
+
verbose: opts.verbose,
|
|
4487
|
+
noInput: opts.input === false
|
|
4488
|
+
});
|
|
4489
|
+
}).addHelpText("after", `
|
|
4490
|
+
Examples:
|
|
4491
|
+
$ thoughtful login
|
|
4492
|
+
$ thoughtful whoami
|
|
4493
|
+
|
|
4494
|
+
$ thoughtful pages list
|
|
4495
|
+
$ thoughtful pages create "Project Plan" --parent roadmap --owner alice@example.com
|
|
4496
|
+
$ thoughtful pages search "quarterly goals"
|
|
4497
|
+
|
|
4498
|
+
$ thoughtful orgs list
|
|
4499
|
+
$ thoughtful workspaces switch ws_abc123
|
|
4500
|
+
|
|
4501
|
+
$ thoughtful threads new "What's the status of project X?"
|
|
4502
|
+
$ thoughtful threads list --json | jq '.threads[0]'
|
|
4503
|
+
|
|
4504
|
+
For more help on a specific command, run:
|
|
4505
|
+
$ thoughtful <command> --help
|
|
4506
|
+
`);
|
|
4507
|
+
registerAuthCommands(program2);
|
|
4508
|
+
registerOrgsCommands(program2);
|
|
4509
|
+
registerWorkspacesCommands(program2);
|
|
4510
|
+
registerPagesCommands(program2);
|
|
4511
|
+
registerChatCommands(program2);
|
|
4512
|
+
registerCompletionCommand(program2);
|
|
4513
|
+
program2.parse();
|