@f5-sales-demo/pi-utils 20.2.2 → 20.2.4
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/package.json +2 -2
- package/src/cli.ts +32 -12
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5-sales-demo/pi-utils",
|
|
4
|
-
"version": "20.2.
|
|
4
|
+
"version": "20.2.4",
|
|
5
5
|
"description": "Shared utilities for pi packages",
|
|
6
6
|
"homepage": "https://github.com/f5-sales-demo/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/bun": "^1.3",
|
|
42
|
-
"@f5-sales-demo/pi-natives": "20.2.
|
|
42
|
+
"@f5-sales-demo/pi-natives": "20.2.4"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"bun": ">=1.3.7"
|
package/src/cli.ts
CHANGED
|
@@ -98,6 +98,9 @@ export interface ParseOutput<
|
|
|
98
98
|
argv: string[];
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/** Invalid command-line syntax that callers should report as a usage error. */
|
|
102
|
+
export class CliUsageError extends Error {}
|
|
103
|
+
|
|
101
104
|
// ---------------------------------------------------------------------------
|
|
102
105
|
// Command base class
|
|
103
106
|
// ---------------------------------------------------------------------------
|
|
@@ -173,12 +176,19 @@ export abstract class Command {
|
|
|
173
176
|
|
|
174
177
|
// strict=false when command declares args (positionals must pass through)
|
|
175
178
|
// or when the command itself opts out
|
|
176
|
-
const { values: rawValues, positionals } =
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
const { values: rawValues, positionals } = (() => {
|
|
180
|
+
try {
|
|
181
|
+
return nodeParseArgs({
|
|
182
|
+
args: this.argv,
|
|
183
|
+
options,
|
|
184
|
+
allowPositionals: true,
|
|
185
|
+
strict,
|
|
186
|
+
});
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if (error instanceof TypeError) throw new CliUsageError(error.message);
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
})();
|
|
182
192
|
|
|
183
193
|
// Convert raw values to proper types and validate
|
|
184
194
|
const flags: Record<string, unknown> = {};
|
|
@@ -190,7 +200,7 @@ export abstract class Command {
|
|
|
190
200
|
} else {
|
|
191
201
|
const n = Number.parseInt(raw as string, 10);
|
|
192
202
|
if (Number.isNaN(n)) {
|
|
193
|
-
throw new
|
|
203
|
+
throw new CliUsageError(`Expected integer for --${name}, got "${raw}"`);
|
|
194
204
|
}
|
|
195
205
|
flags[name] = n;
|
|
196
206
|
}
|
|
@@ -203,14 +213,16 @@ export abstract class Command {
|
|
|
203
213
|
// Validate options constraint
|
|
204
214
|
if (val !== undefined && desc.options && !Array.isArray(val)) {
|
|
205
215
|
if (!desc.options.includes(val as string)) {
|
|
206
|
-
throw new
|
|
216
|
+
throw new CliUsageError(
|
|
217
|
+
`Expected --${name} to be one of: ${[...desc.options].join(", ")}; got "${val}"`,
|
|
218
|
+
);
|
|
207
219
|
}
|
|
208
220
|
}
|
|
209
221
|
flags[name] = val;
|
|
210
222
|
}
|
|
211
223
|
// Validate required
|
|
212
224
|
if (desc.required && flags[name] === undefined) {
|
|
213
|
-
throw new
|
|
225
|
+
throw new CliUsageError(`Missing required flag: --${name}`);
|
|
214
226
|
}
|
|
215
227
|
}
|
|
216
228
|
|
|
@@ -229,13 +241,15 @@ export abstract class Command {
|
|
|
229
241
|
}
|
|
230
242
|
// Validate required
|
|
231
243
|
if (desc.required && args[argName] === undefined) {
|
|
232
|
-
throw new
|
|
244
|
+
throw new CliUsageError(`Missing required argument: ${argName}`);
|
|
233
245
|
}
|
|
234
246
|
// Validate options constraint
|
|
235
247
|
const argVal = args[argName];
|
|
236
248
|
if (argVal !== undefined && desc.options && typeof argVal === "string") {
|
|
237
249
|
if (!desc.options.includes(argVal)) {
|
|
238
|
-
throw new
|
|
250
|
+
throw new CliUsageError(
|
|
251
|
+
`Expected ${argName} to be one of: ${[...desc.options].join(", ")}; got "${argVal}"`,
|
|
252
|
+
);
|
|
239
253
|
}
|
|
240
254
|
}
|
|
241
255
|
}
|
|
@@ -418,7 +432,13 @@ export async function run(opts: RunOptions): Promise<void> {
|
|
|
418
432
|
const Cmd = await entry.load();
|
|
419
433
|
const config: CliConfig = { bin, version, commands: new Map([[entry.name, Cmd]]) };
|
|
420
434
|
const instance = new Cmd(commandArgv, config);
|
|
421
|
-
|
|
435
|
+
try {
|
|
436
|
+
await instance.run();
|
|
437
|
+
} catch (error) {
|
|
438
|
+
if (!(error instanceof CliUsageError)) throw error;
|
|
439
|
+
process.stderr.write(`Error: ${error.message}\n`);
|
|
440
|
+
process.exitCode = 2;
|
|
441
|
+
}
|
|
422
442
|
}
|
|
423
443
|
|
|
424
444
|
/** Resolve all command loaders for help/alias display. */
|