eser 4.0.0 → 4.0.3
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/eser.js +1694 -19
- package/package.json +5 -1
package/eser.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
|
+
};
|
|
7
|
+
|
|
2
8
|
// deno:https://jsr.io/@std/cli/1.0.25/parse_args.ts
|
|
3
9
|
var FLAG_REGEXP = /^(?:-(?:(?<doubleDash>-)(?<negated>no-)?)?)(?<key>.+?)(?:=(?<value>.+?))?$/s;
|
|
4
10
|
var LETTER_REGEXP = /[A-Za-z]/;
|
|
@@ -257,6 +263,44 @@ function parseArgs(args, options) {
|
|
|
257
263
|
return argv;
|
|
258
264
|
}
|
|
259
265
|
|
|
266
|
+
// pkg/@eser/standards/runtime/mod.ts
|
|
267
|
+
var mod_exports2 = {};
|
|
268
|
+
__export(mod_exports2, {
|
|
269
|
+
AlreadyExistsError: () => AlreadyExistsError,
|
|
270
|
+
BROWSER_CAPABILITIES: () => BROWSER_CAPABILITIES,
|
|
271
|
+
BUN_CAPABILITIES: () => BUN_CAPABILITIES,
|
|
272
|
+
DENO_CAPABILITIES: () => DENO_CAPABILITIES,
|
|
273
|
+
FULL_CAPABILITIES: () => FULL_CAPABILITIES,
|
|
274
|
+
NODE_CAPABILITIES: () => NODE_CAPABILITIES,
|
|
275
|
+
NotFoundError: () => NotFoundError,
|
|
276
|
+
ProcessError: () => ProcessError,
|
|
277
|
+
RuntimeCapabilityError: () => RuntimeCapabilityError,
|
|
278
|
+
UNKNOWN_CAPABILITIES: () => UNKNOWN_CAPABILITIES,
|
|
279
|
+
WORKERD_CAPABILITIES: () => WORKERD_CAPABILITIES,
|
|
280
|
+
clearWorkerdEnv: () => clearEnv,
|
|
281
|
+
createRuntime: () => createRuntime,
|
|
282
|
+
detectRuntime: () => detectRuntime,
|
|
283
|
+
getArch: () => getArch,
|
|
284
|
+
getCapabilities: () => getCapabilities,
|
|
285
|
+
getHomedir: () => getHomedir,
|
|
286
|
+
getPlatform: () => getPlatform,
|
|
287
|
+
getPlatformInfo: () => getPlatformInfo,
|
|
288
|
+
getRuntimeVersion: () => getRuntimeVersion,
|
|
289
|
+
getTmpdir: () => getTmpdir,
|
|
290
|
+
hasCapability: () => hasCapability,
|
|
291
|
+
isBrowser: () => isBrowser,
|
|
292
|
+
isBun: () => isBun,
|
|
293
|
+
isDeno: () => isDeno,
|
|
294
|
+
isEdge: () => isEdge,
|
|
295
|
+
isNode: () => isNode,
|
|
296
|
+
isServer: () => isServer,
|
|
297
|
+
isWorkerd: () => isWorkerd,
|
|
298
|
+
populateEnvFromContext: () => populateEnvFromContext,
|
|
299
|
+
posixPath: () => posixPath,
|
|
300
|
+
runtime: () => runtime,
|
|
301
|
+
searchFileHierarchy: () => searchFileHierarchy
|
|
302
|
+
});
|
|
303
|
+
|
|
260
304
|
// pkg/@eser/standards/runtime/types.ts
|
|
261
305
|
var RuntimeCapabilityError = class extends Error {
|
|
262
306
|
capability;
|
|
@@ -276,6 +320,14 @@ var NotFoundError = class extends Error {
|
|
|
276
320
|
this.path = path;
|
|
277
321
|
}
|
|
278
322
|
};
|
|
323
|
+
var AlreadyExistsError = class extends Error {
|
|
324
|
+
path;
|
|
325
|
+
constructor(path) {
|
|
326
|
+
super(`File or directory already exists: ${path}`);
|
|
327
|
+
this.name = "AlreadyExistsError";
|
|
328
|
+
this.path = path;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
279
331
|
var ProcessError = class extends Error {
|
|
280
332
|
cmd;
|
|
281
333
|
code;
|
|
@@ -312,8 +364,152 @@ var detectRuntime = () => {
|
|
|
312
364
|
}
|
|
313
365
|
return "unknown";
|
|
314
366
|
};
|
|
367
|
+
var getRuntimeVersion = () => {
|
|
368
|
+
const runtime2 = detectRuntime();
|
|
369
|
+
switch (runtime2) {
|
|
370
|
+
case "deno": {
|
|
371
|
+
return globalThis.Deno?.version?.deno ?? "unknown";
|
|
372
|
+
}
|
|
373
|
+
case "bun": {
|
|
374
|
+
return globalThis.Bun?.version ?? "unknown";
|
|
375
|
+
}
|
|
376
|
+
case "node": {
|
|
377
|
+
return globalThis.process?.versions?.node ?? "unknown";
|
|
378
|
+
}
|
|
379
|
+
case "workerd": {
|
|
380
|
+
return "unknown";
|
|
381
|
+
}
|
|
382
|
+
case "browser": {
|
|
383
|
+
return globalThis.navigator?.userAgent ?? "unknown";
|
|
384
|
+
}
|
|
385
|
+
default: {
|
|
386
|
+
return "unknown";
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
var isDeno = () => detectRuntime() === "deno";
|
|
391
|
+
var isNode = () => detectRuntime() === "node";
|
|
392
|
+
var isBun = () => detectRuntime() === "bun";
|
|
393
|
+
var isWorkerd = () => detectRuntime() === "workerd";
|
|
394
|
+
var isBrowser = () => detectRuntime() === "browser";
|
|
395
|
+
var isServer = () => {
|
|
396
|
+
const rt = detectRuntime();
|
|
397
|
+
return rt === "deno" || rt === "node" || rt === "bun";
|
|
398
|
+
};
|
|
399
|
+
var isEdge = () => {
|
|
400
|
+
const rt = detectRuntime();
|
|
401
|
+
return rt === "workerd";
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// pkg/@eser/standards/runtime/platform.ts
|
|
405
|
+
var getPlatform = () => {
|
|
406
|
+
if (typeof Deno !== "undefined" && Deno.build?.os) {
|
|
407
|
+
const os = Deno.build.os;
|
|
408
|
+
if (os === "darwin") return "darwin";
|
|
409
|
+
if (os === "linux") return "linux";
|
|
410
|
+
if (os === "windows") return "windows";
|
|
411
|
+
}
|
|
412
|
+
const proc = globalThis.process;
|
|
413
|
+
if (proc?.platform) {
|
|
414
|
+
const platform = proc.platform;
|
|
415
|
+
if (platform === "darwin") return "darwin";
|
|
416
|
+
if (platform === "linux") return "linux";
|
|
417
|
+
if (platform === "win32") return "windows";
|
|
418
|
+
}
|
|
419
|
+
const nav = globalThis.navigator;
|
|
420
|
+
if (nav?.userAgent) {
|
|
421
|
+
const ua = nav.userAgent.toLowerCase();
|
|
422
|
+
if (ua.includes("mac")) return "darwin";
|
|
423
|
+
if (ua.includes("win")) return "windows";
|
|
424
|
+
if (ua.includes("linux")) return "linux";
|
|
425
|
+
}
|
|
426
|
+
return "linux";
|
|
427
|
+
};
|
|
428
|
+
var getArch = () => {
|
|
429
|
+
if (typeof Deno !== "undefined" && Deno.build?.arch) {
|
|
430
|
+
const arch = Deno.build.arch;
|
|
431
|
+
if (arch === "x86_64") return "amd64";
|
|
432
|
+
if (arch === "aarch64") return "arm64";
|
|
433
|
+
}
|
|
434
|
+
const proc = globalThis.process;
|
|
435
|
+
if (proc?.arch) {
|
|
436
|
+
const arch = proc.arch;
|
|
437
|
+
if (arch === "x64") return "amd64";
|
|
438
|
+
if (arch === "arm64") return "arm64";
|
|
439
|
+
}
|
|
440
|
+
const nav = globalThis.navigator;
|
|
441
|
+
if (nav?.userAgent) {
|
|
442
|
+
const ua = nav.userAgent.toLowerCase();
|
|
443
|
+
if (ua.includes("arm64") || ua.includes("aarch64")) return "arm64";
|
|
444
|
+
}
|
|
445
|
+
return "amd64";
|
|
446
|
+
};
|
|
447
|
+
var getHomedir = () => {
|
|
448
|
+
if (typeof Deno !== "undefined" && Deno.env?.get) {
|
|
449
|
+
const home = Deno.env.get("HOME") ?? Deno.env.get("USERPROFILE");
|
|
450
|
+
if (home) return home;
|
|
451
|
+
}
|
|
452
|
+
const proc = globalThis.process;
|
|
453
|
+
if (proc?.env) {
|
|
454
|
+
const home = proc.env.HOME ?? proc.env.USERPROFILE;
|
|
455
|
+
if (home) return home;
|
|
456
|
+
}
|
|
457
|
+
try {
|
|
458
|
+
const os = globalThis.require?.("os");
|
|
459
|
+
if (os?.homedir) {
|
|
460
|
+
return os.homedir();
|
|
461
|
+
}
|
|
462
|
+
} catch {
|
|
463
|
+
}
|
|
464
|
+
const platform = getPlatform();
|
|
465
|
+
if (platform === "windows") {
|
|
466
|
+
return "C:\\Users\\Default";
|
|
467
|
+
}
|
|
468
|
+
return "/home";
|
|
469
|
+
};
|
|
470
|
+
var getTmpdir = () => {
|
|
471
|
+
if (typeof Deno !== "undefined" && Deno.env?.get) {
|
|
472
|
+
const tmp = Deno.env.get("TMPDIR") ?? Deno.env.get("TMP") ?? Deno.env.get("TEMP");
|
|
473
|
+
if (tmp) return tmp;
|
|
474
|
+
}
|
|
475
|
+
const proc = globalThis.process;
|
|
476
|
+
if (proc?.env) {
|
|
477
|
+
const tmp = proc.env.TMPDIR ?? proc.env.TMP ?? proc.env.TEMP;
|
|
478
|
+
if (tmp) return tmp;
|
|
479
|
+
}
|
|
480
|
+
try {
|
|
481
|
+
const os = globalThis.require?.("os");
|
|
482
|
+
if (os?.tmpdir) {
|
|
483
|
+
return os.tmpdir();
|
|
484
|
+
}
|
|
485
|
+
} catch {
|
|
486
|
+
}
|
|
487
|
+
const platform = getPlatform();
|
|
488
|
+
if (platform === "windows") {
|
|
489
|
+
return "C:\\Windows\\Temp";
|
|
490
|
+
}
|
|
491
|
+
return "/tmp";
|
|
492
|
+
};
|
|
493
|
+
var getPlatformInfo = () => {
|
|
494
|
+
return {
|
|
495
|
+
platform: getPlatform(),
|
|
496
|
+
arch: getArch(),
|
|
497
|
+
homedir: getHomedir(),
|
|
498
|
+
tmpdir: getTmpdir()
|
|
499
|
+
};
|
|
500
|
+
};
|
|
315
501
|
|
|
316
502
|
// pkg/@eser/standards/runtime/capabilities.ts
|
|
503
|
+
var FULL_CAPABILITIES = {
|
|
504
|
+
fs: true,
|
|
505
|
+
fsSync: true,
|
|
506
|
+
exec: true,
|
|
507
|
+
process: true,
|
|
508
|
+
env: true,
|
|
509
|
+
stdin: true,
|
|
510
|
+
stdout: true,
|
|
511
|
+
kv: false
|
|
512
|
+
};
|
|
317
513
|
var DENO_CAPABILITIES = {
|
|
318
514
|
fs: true,
|
|
319
515
|
fsSync: true,
|
|
@@ -390,6 +586,9 @@ var getCapabilities = (runtime2) => {
|
|
|
390
586
|
return UNKNOWN_CAPABILITIES;
|
|
391
587
|
}
|
|
392
588
|
};
|
|
589
|
+
var hasCapability = (runtime2, capability) => {
|
|
590
|
+
return getCapabilities(runtime2)[capability];
|
|
591
|
+
};
|
|
393
592
|
|
|
394
593
|
// pkg/@eser/standards/runtime/polyfills/path.ts
|
|
395
594
|
var POSIX_SEP = "/";
|
|
@@ -568,6 +767,33 @@ var posixPath = {
|
|
|
568
767
|
delimiter: POSIX_DELIMITER
|
|
569
768
|
};
|
|
570
769
|
|
|
770
|
+
// pkg/@eser/standards/runtime/file-search.ts
|
|
771
|
+
var searchFileHierarchy = async (startDir, filenames, options = {}) => {
|
|
772
|
+
const { searchParents = false } = options;
|
|
773
|
+
let dir = startDir;
|
|
774
|
+
while (true) {
|
|
775
|
+
for (const name of filenames) {
|
|
776
|
+
const filepath = runtime.path.join(dir, name);
|
|
777
|
+
const exists = await runtime.fs.exists(filepath);
|
|
778
|
+
if (exists) {
|
|
779
|
+
const stat3 = await runtime.fs.stat(filepath);
|
|
780
|
+
if (stat3.isFile) {
|
|
781
|
+
return filepath;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
if (!searchParents) {
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
const parent = runtime.path.dirname(dir);
|
|
789
|
+
if (parent === dir) {
|
|
790
|
+
break;
|
|
791
|
+
}
|
|
792
|
+
dir = parent;
|
|
793
|
+
}
|
|
794
|
+
return void 0;
|
|
795
|
+
};
|
|
796
|
+
|
|
571
797
|
// pkg/@eser/standards/runtime/adapters/workerd.ts
|
|
572
798
|
var createWorkerdFs = () => {
|
|
573
799
|
const throwNotAvailable = () => {
|
|
@@ -625,6 +851,16 @@ var createWorkerdEnv = () => {
|
|
|
625
851
|
}
|
|
626
852
|
};
|
|
627
853
|
};
|
|
854
|
+
var populateEnvFromContext = (env) => {
|
|
855
|
+
for (const [key, value2] of Object.entries(env)) {
|
|
856
|
+
if (typeof value2 === "string") {
|
|
857
|
+
envStorage.set(key, value2);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
var clearEnv = () => {
|
|
862
|
+
envStorage.clear();
|
|
863
|
+
};
|
|
628
864
|
var createWorkerdProcess = () => {
|
|
629
865
|
const throwNotAvailable = () => {
|
|
630
866
|
throw new RuntimeCapabilityError("process", "workerd");
|
|
@@ -655,7 +891,7 @@ var createWorkerdProcess = () => {
|
|
|
655
891
|
var createWorkerdRuntime = () => {
|
|
656
892
|
const fs = createWorkerdFs();
|
|
657
893
|
const path = createWorkerdPath();
|
|
658
|
-
const
|
|
894
|
+
const exec2 = createWorkerdExec();
|
|
659
895
|
const env = createWorkerdEnv();
|
|
660
896
|
const process = createWorkerdProcess();
|
|
661
897
|
return {
|
|
@@ -664,7 +900,7 @@ var createWorkerdRuntime = () => {
|
|
|
664
900
|
capabilities: WORKERD_CAPABILITIES,
|
|
665
901
|
fs,
|
|
666
902
|
path,
|
|
667
|
-
exec,
|
|
903
|
+
exec: exec2,
|
|
668
904
|
env,
|
|
669
905
|
process
|
|
670
906
|
};
|
|
@@ -2265,21 +2501,23 @@ var createDenoPath = () => {
|
|
|
2265
2501
|
var createDenoExec = () => {
|
|
2266
2502
|
return {
|
|
2267
2503
|
async spawn(cmd, args = [], options) {
|
|
2504
|
+
const stdoutMode = options?.stdout ?? "piped";
|
|
2505
|
+
const stderrMode = options?.stderr ?? "piped";
|
|
2268
2506
|
const command = new Deno.Command(cmd, {
|
|
2269
2507
|
args,
|
|
2270
2508
|
cwd: options?.cwd,
|
|
2271
2509
|
env: options?.env,
|
|
2272
2510
|
stdin: options?.stdin ?? "null",
|
|
2273
|
-
stdout:
|
|
2274
|
-
stderr:
|
|
2511
|
+
stdout: stdoutMode,
|
|
2512
|
+
stderr: stderrMode,
|
|
2275
2513
|
signal: options?.signal
|
|
2276
2514
|
});
|
|
2277
2515
|
const result = await command.output();
|
|
2278
2516
|
return {
|
|
2279
2517
|
success: result.success,
|
|
2280
2518
|
code: result.code,
|
|
2281
|
-
stdout: result.stdout,
|
|
2282
|
-
stderr: result.stderr
|
|
2519
|
+
stdout: stdoutMode === "piped" ? result.stdout : new Uint8Array(),
|
|
2520
|
+
stderr: stderrMode === "piped" ? result.stderr : new Uint8Array()
|
|
2283
2521
|
};
|
|
2284
2522
|
},
|
|
2285
2523
|
async exec(cmd, args = [], options) {
|
|
@@ -2385,7 +2623,7 @@ var createDenoProcess = () => {
|
|
|
2385
2623
|
var createDenoRuntime = () => {
|
|
2386
2624
|
const fs = createDenoFs();
|
|
2387
2625
|
const path = createDenoPath();
|
|
2388
|
-
const
|
|
2626
|
+
const exec2 = createDenoExec();
|
|
2389
2627
|
const env = createDenoEnv();
|
|
2390
2628
|
const process = createDenoProcess();
|
|
2391
2629
|
return {
|
|
@@ -2394,7 +2632,7 @@ var createDenoRuntime = () => {
|
|
|
2394
2632
|
capabilities: DENO_CAPABILITIES,
|
|
2395
2633
|
fs,
|
|
2396
2634
|
path,
|
|
2397
|
-
exec,
|
|
2635
|
+
exec: exec2,
|
|
2398
2636
|
env,
|
|
2399
2637
|
process
|
|
2400
2638
|
};
|
|
@@ -2406,7 +2644,7 @@ import * as nodePath from "node:path";
|
|
|
2406
2644
|
import * as nodeOs from "node:os";
|
|
2407
2645
|
import * as nodeChildProcess from "node:child_process";
|
|
2408
2646
|
import nodeProcess from "node:process";
|
|
2409
|
-
import { Buffer } from "node:buffer";
|
|
2647
|
+
import { Buffer as Buffer2 } from "node:buffer";
|
|
2410
2648
|
import { Readable, Writable } from "node:stream";
|
|
2411
2649
|
var createNodeFs = () => {
|
|
2412
2650
|
const mapStats = (stats) => ({
|
|
@@ -2582,8 +2820,8 @@ var createNodeExec = () => {
|
|
|
2582
2820
|
});
|
|
2583
2821
|
proc.on("error", reject);
|
|
2584
2822
|
proc.on("close", (code2) => {
|
|
2585
|
-
const stdout = new Uint8Array(
|
|
2586
|
-
const stderr = new Uint8Array(
|
|
2823
|
+
const stdout = new Uint8Array(Buffer2.concat(stdoutChunks));
|
|
2824
|
+
const stderr = new Uint8Array(Buffer2.concat(stderrChunks));
|
|
2587
2825
|
resolve7({
|
|
2588
2826
|
success: code2 === 0,
|
|
2589
2827
|
code: code2 ?? 1,
|
|
@@ -2657,8 +2895,8 @@ var createNodeExec = () => {
|
|
|
2657
2895
|
return {
|
|
2658
2896
|
success: status.success,
|
|
2659
2897
|
code: status.code,
|
|
2660
|
-
stdout: new Uint8Array(
|
|
2661
|
-
stderr: new Uint8Array(
|
|
2898
|
+
stdout: new Uint8Array(Buffer2.concat(stdoutChunks)),
|
|
2899
|
+
stderr: new Uint8Array(Buffer2.concat(stderrChunks))
|
|
2662
2900
|
};
|
|
2663
2901
|
},
|
|
2664
2902
|
kill: (signal) => {
|
|
@@ -2720,7 +2958,7 @@ var createNodeProcess = () => {
|
|
|
2720
2958
|
var createNodeRuntime = () => {
|
|
2721
2959
|
const fs = createNodeFs();
|
|
2722
2960
|
const path = createNodePath();
|
|
2723
|
-
const
|
|
2961
|
+
const exec2 = createNodeExec();
|
|
2724
2962
|
const env = createNodeEnv();
|
|
2725
2963
|
const process = createNodeProcess();
|
|
2726
2964
|
return {
|
|
@@ -2729,7 +2967,7 @@ var createNodeRuntime = () => {
|
|
|
2729
2967
|
capabilities: NODE_CAPABILITIES,
|
|
2730
2968
|
fs,
|
|
2731
2969
|
path,
|
|
2732
|
-
exec,
|
|
2970
|
+
exec: exec2,
|
|
2733
2971
|
env,
|
|
2734
2972
|
process
|
|
2735
2973
|
};
|
|
@@ -3041,7 +3279,7 @@ var createBunProcess = () => {
|
|
|
3041
3279
|
var createBunRuntime = () => {
|
|
3042
3280
|
const fs = createBunFs();
|
|
3043
3281
|
const path = createBunPath();
|
|
3044
|
-
const
|
|
3282
|
+
const exec2 = createBunExec();
|
|
3045
3283
|
const env = createBunEnv();
|
|
3046
3284
|
const process = createBunProcess();
|
|
3047
3285
|
return {
|
|
@@ -3050,7 +3288,7 @@ var createBunRuntime = () => {
|
|
|
3050
3288
|
capabilities: BUN_CAPABILITIES,
|
|
3051
3289
|
fs,
|
|
3052
3290
|
path,
|
|
3053
|
-
exec,
|
|
3291
|
+
exec: exec2,
|
|
3054
3292
|
env,
|
|
3055
3293
|
process
|
|
3056
3294
|
};
|
|
@@ -3181,6 +3419,11 @@ function code(open, close) {
|
|
|
3181
3419
|
function run(str2, code2) {
|
|
3182
3420
|
return enabled ? `${code2.open}${str2.replace(code2.regexp, code2.open)}${code2.close}` : str2;
|
|
3183
3421
|
}
|
|
3422
|
+
function dim(str2) {
|
|
3423
|
+
return run(str2, code([
|
|
3424
|
+
2
|
|
3425
|
+
], 22));
|
|
3426
|
+
}
|
|
3184
3427
|
function red(str2) {
|
|
3185
3428
|
return run(str2, code([
|
|
3186
3429
|
31
|
|
@@ -8311,10 +8554,1413 @@ var codebaseCommand = async (rawArgs, _parentFlags) => {
|
|
|
8311
8554
|
await def.handler(parsed._.slice(1), parsed);
|
|
8312
8555
|
};
|
|
8313
8556
|
|
|
8557
|
+
// pkg/@eser/shell/args/flags.ts
|
|
8558
|
+
var buildParseOptions = (flags) => {
|
|
8559
|
+
const boolean2 = [];
|
|
8560
|
+
const string = [];
|
|
8561
|
+
const alias = {};
|
|
8562
|
+
const defaultValues = {};
|
|
8563
|
+
for (const flag of flags) {
|
|
8564
|
+
if (flag.type === "boolean") {
|
|
8565
|
+
boolean2.push(flag.name);
|
|
8566
|
+
} else {
|
|
8567
|
+
string.push(flag.name);
|
|
8568
|
+
}
|
|
8569
|
+
if (flag.short !== void 0) {
|
|
8570
|
+
alias[flag.short] = flag.name;
|
|
8571
|
+
}
|
|
8572
|
+
if (flag.default !== void 0) {
|
|
8573
|
+
defaultValues[flag.name] = flag.default;
|
|
8574
|
+
}
|
|
8575
|
+
}
|
|
8576
|
+
return {
|
|
8577
|
+
boolean: boolean2,
|
|
8578
|
+
string,
|
|
8579
|
+
alias,
|
|
8580
|
+
default: defaultValues
|
|
8581
|
+
};
|
|
8582
|
+
};
|
|
8583
|
+
var coerceValue = (value2, type) => {
|
|
8584
|
+
if (value2 === void 0) {
|
|
8585
|
+
return void 0;
|
|
8586
|
+
}
|
|
8587
|
+
switch (type) {
|
|
8588
|
+
case "boolean":
|
|
8589
|
+
return Boolean(value2);
|
|
8590
|
+
case "number":
|
|
8591
|
+
return typeof value2 === "string" ? Number(value2) : value2;
|
|
8592
|
+
case "string":
|
|
8593
|
+
return String(value2);
|
|
8594
|
+
case "string[]":
|
|
8595
|
+
if (Array.isArray(value2)) {
|
|
8596
|
+
return value2.map(String);
|
|
8597
|
+
}
|
|
8598
|
+
return value2 !== void 0 ? [
|
|
8599
|
+
String(value2)
|
|
8600
|
+
] : [];
|
|
8601
|
+
default:
|
|
8602
|
+
return value2;
|
|
8603
|
+
}
|
|
8604
|
+
};
|
|
8605
|
+
var extractFlags = (parsed, flags) => {
|
|
8606
|
+
const result = {};
|
|
8607
|
+
for (const flag of flags) {
|
|
8608
|
+
const value2 = parsed[flag.name];
|
|
8609
|
+
result[flag.name] = coerceValue(value2, flag.type);
|
|
8610
|
+
}
|
|
8611
|
+
return result;
|
|
8612
|
+
};
|
|
8613
|
+
var validateRequiredFlags = (flags, definitions) => {
|
|
8614
|
+
const errors = [];
|
|
8615
|
+
for (const def of definitions) {
|
|
8616
|
+
if (def.required === true) {
|
|
8617
|
+
const value2 = flags[def.name];
|
|
8618
|
+
if (value2 === void 0 || value2 === "" || value2 === false) {
|
|
8619
|
+
errors.push(`Required flag --${def.name} is missing`);
|
|
8620
|
+
}
|
|
8621
|
+
}
|
|
8622
|
+
}
|
|
8623
|
+
return errors;
|
|
8624
|
+
};
|
|
8625
|
+
|
|
8626
|
+
// pkg/@eser/shell/args/help.ts
|
|
8627
|
+
var padRight = (str2, len) => {
|
|
8628
|
+
return str2 + " ".repeat(Math.max(0, len - str2.length));
|
|
8629
|
+
};
|
|
8630
|
+
var formatFlag = (flag) => {
|
|
8631
|
+
let name = `--${flag.name}`;
|
|
8632
|
+
if (flag.short !== void 0) {
|
|
8633
|
+
name = `-${flag.short}, ${name}`;
|
|
8634
|
+
}
|
|
8635
|
+
if (flag.type !== "boolean") {
|
|
8636
|
+
name += ` <${flag.type}>`;
|
|
8637
|
+
}
|
|
8638
|
+
return name;
|
|
8639
|
+
};
|
|
8640
|
+
var generateHelp = (meta, commandPath) => {
|
|
8641
|
+
const lines = [];
|
|
8642
|
+
const fullName = commandPath.join(" ");
|
|
8643
|
+
if (meta.description !== void 0) {
|
|
8644
|
+
lines.push(`${fullName} - ${meta.description}`);
|
|
8645
|
+
} else {
|
|
8646
|
+
lines.push(fullName);
|
|
8647
|
+
}
|
|
8648
|
+
lines.push("");
|
|
8649
|
+
if (meta.usage !== void 0) {
|
|
8650
|
+
lines.push("Usage:");
|
|
8651
|
+
lines.push(` ${meta.usage}`);
|
|
8652
|
+
} else {
|
|
8653
|
+
let usage = fullName;
|
|
8654
|
+
if (meta.children.length > 0) {
|
|
8655
|
+
usage += " <command>";
|
|
8656
|
+
}
|
|
8657
|
+
if (meta.flags.length > 0) {
|
|
8658
|
+
usage += " [options]";
|
|
8659
|
+
}
|
|
8660
|
+
lines.push("Usage:");
|
|
8661
|
+
lines.push(` ${usage}`);
|
|
8662
|
+
}
|
|
8663
|
+
lines.push("");
|
|
8664
|
+
if (meta.children.length > 0) {
|
|
8665
|
+
lines.push("Commands:");
|
|
8666
|
+
const maxLen = Math.max(...meta.children.map((c) => c.name.length));
|
|
8667
|
+
for (const child of meta.children) {
|
|
8668
|
+
const desc = child.description ?? "";
|
|
8669
|
+
lines.push(` ${padRight(child.name, maxLen + 2)}${desc}`);
|
|
8670
|
+
}
|
|
8671
|
+
lines.push("");
|
|
8672
|
+
}
|
|
8673
|
+
if (meta.flags.length > 0) {
|
|
8674
|
+
lines.push("Options:");
|
|
8675
|
+
const formatted = meta.flags.map((f) => ({
|
|
8676
|
+
flag: formatFlag(f),
|
|
8677
|
+
desc: f.description
|
|
8678
|
+
}));
|
|
8679
|
+
const maxLen = Math.max(...formatted.map((f) => f.flag.length));
|
|
8680
|
+
for (const { flag, desc } of formatted) {
|
|
8681
|
+
lines.push(` ${padRight(flag, maxLen + 2)}${desc}`);
|
|
8682
|
+
}
|
|
8683
|
+
lines.push("");
|
|
8684
|
+
}
|
|
8685
|
+
if (meta.examples !== void 0 && meta.examples.length > 0) {
|
|
8686
|
+
lines.push("Examples:");
|
|
8687
|
+
for (const example of meta.examples) {
|
|
8688
|
+
lines.push(` ${example}`);
|
|
8689
|
+
}
|
|
8690
|
+
lines.push("");
|
|
8691
|
+
}
|
|
8692
|
+
if (meta.children.length > 0) {
|
|
8693
|
+
lines.push(`Run '${fullName} <command> --help' for more information on a command.`);
|
|
8694
|
+
}
|
|
8695
|
+
return lines.join("\n");
|
|
8696
|
+
};
|
|
8697
|
+
|
|
8698
|
+
// pkg/@eser/shell/completions/generators/bash.ts
|
|
8699
|
+
var generateFlagCompletions = (flags) => {
|
|
8700
|
+
const parts = [];
|
|
8701
|
+
for (const flag of flags) {
|
|
8702
|
+
parts.push(`--${flag.name}`);
|
|
8703
|
+
if (flag.short !== void 0) {
|
|
8704
|
+
parts.push(`-${flag.short}`);
|
|
8705
|
+
}
|
|
8706
|
+
}
|
|
8707
|
+
return parts.join(" ");
|
|
8708
|
+
};
|
|
8709
|
+
var generateSubcommandCase = (node, prefix) => {
|
|
8710
|
+
if (node.children === void 0 || node.children.length === 0) {
|
|
8711
|
+
return "";
|
|
8712
|
+
}
|
|
8713
|
+
const subcommandNames = node.children.map((c) => c.name).join(" ");
|
|
8714
|
+
const flagCompletions = node.flags !== void 0 ? generateFlagCompletions(node.flags) : "";
|
|
8715
|
+
const completions = [
|
|
8716
|
+
subcommandNames,
|
|
8717
|
+
flagCompletions
|
|
8718
|
+
].filter((s) => s.length > 0).join(" ");
|
|
8719
|
+
let output = ` ${prefix})
|
|
8720
|
+
`;
|
|
8721
|
+
output += ` COMPREPLY=( $(compgen -W "${completions}" -- "\${cur}") )
|
|
8722
|
+
`;
|
|
8723
|
+
output += ` return 0
|
|
8724
|
+
`;
|
|
8725
|
+
output += ` ;;
|
|
8726
|
+
`;
|
|
8727
|
+
for (const child of node.children) {
|
|
8728
|
+
if (child.children !== void 0 && child.children.length > 0) {
|
|
8729
|
+
output += generateSubcommandCase(child, `${prefix} ${child.name}`);
|
|
8730
|
+
}
|
|
8731
|
+
}
|
|
8732
|
+
return output;
|
|
8733
|
+
};
|
|
8734
|
+
var generate = (appName, tree) => {
|
|
8735
|
+
const topLevelCommands = tree.children?.map((c) => c.name).join(" ") ?? "";
|
|
8736
|
+
const topLevelFlags = tree.flags !== void 0 ? generateFlagCompletions(tree.flags) : "";
|
|
8737
|
+
const topLevel = [
|
|
8738
|
+
topLevelCommands,
|
|
8739
|
+
topLevelFlags
|
|
8740
|
+
].filter((s) => s.length > 0).join(" ");
|
|
8741
|
+
let caseClauses = "";
|
|
8742
|
+
if (tree.children !== void 0) {
|
|
8743
|
+
for (const child of tree.children) {
|
|
8744
|
+
caseClauses += generateSubcommandCase(child, child.name);
|
|
8745
|
+
}
|
|
8746
|
+
}
|
|
8747
|
+
return `# ${appName} bash completion
|
|
8748
|
+
# Generated by @eser/shell/completions
|
|
8749
|
+
|
|
8750
|
+
_${appName}_completions() {
|
|
8751
|
+
local cur prev words cword
|
|
8752
|
+
_init_completion || return
|
|
8753
|
+
|
|
8754
|
+
COMPREPLY=()
|
|
8755
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
8756
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
8757
|
+
|
|
8758
|
+
# Build the command path from words
|
|
8759
|
+
local cmd_path=""
|
|
8760
|
+
local i
|
|
8761
|
+
for ((i=1; i<COMP_CWORD; i++)); do
|
|
8762
|
+
case "\${COMP_WORDS[i]}" in
|
|
8763
|
+
-*)
|
|
8764
|
+
# Skip flags
|
|
8765
|
+
;;
|
|
8766
|
+
*)
|
|
8767
|
+
if [[ -n "$cmd_path" ]]; then
|
|
8768
|
+
cmd_path="$cmd_path \${COMP_WORDS[i]}"
|
|
8769
|
+
else
|
|
8770
|
+
cmd_path="\${COMP_WORDS[i]}"
|
|
8771
|
+
fi
|
|
8772
|
+
;;
|
|
8773
|
+
esac
|
|
8774
|
+
done
|
|
8775
|
+
|
|
8776
|
+
case "$cmd_path" in
|
|
8777
|
+
${caseClauses} "")
|
|
8778
|
+
COMPREPLY=( $(compgen -W "${topLevel}" -- "\${cur}") )
|
|
8779
|
+
return 0
|
|
8780
|
+
;;
|
|
8781
|
+
esac
|
|
8782
|
+
}
|
|
8783
|
+
|
|
8784
|
+
complete -F _${appName}_completions ${appName}
|
|
8785
|
+
`;
|
|
8786
|
+
};
|
|
8787
|
+
|
|
8788
|
+
// pkg/@eser/shell/completions/generators/zsh.ts
|
|
8789
|
+
var escapeZsh = (str2) => {
|
|
8790
|
+
return str2.replace(/'/g, "'\\''");
|
|
8791
|
+
};
|
|
8792
|
+
var generateFlagSpecs = (flags) => {
|
|
8793
|
+
const specs = [];
|
|
8794
|
+
for (const flag of flags) {
|
|
8795
|
+
const desc = escapeZsh(flag.description ?? `${flag.name} flag`);
|
|
8796
|
+
if (flag.takesValue === true) {
|
|
8797
|
+
specs.push(`'--${flag.name}=[${desc}]'`);
|
|
8798
|
+
if (flag.short !== void 0) {
|
|
8799
|
+
specs.push(`'-${flag.short}=[${desc}]'`);
|
|
8800
|
+
}
|
|
8801
|
+
} else {
|
|
8802
|
+
specs.push(`'--${flag.name}[${desc}]'`);
|
|
8803
|
+
if (flag.short !== void 0) {
|
|
8804
|
+
specs.push(`'-${flag.short}[${desc}]'`);
|
|
8805
|
+
}
|
|
8806
|
+
}
|
|
8807
|
+
}
|
|
8808
|
+
return specs;
|
|
8809
|
+
};
|
|
8810
|
+
var generateSubcommandSpecs = (children) => {
|
|
8811
|
+
const specs = children.map((c) => {
|
|
8812
|
+
const desc = escapeZsh(c.description ?? c.name);
|
|
8813
|
+
return `'${c.name}:${desc}'`;
|
|
8814
|
+
});
|
|
8815
|
+
return specs.join("\n ");
|
|
8816
|
+
};
|
|
8817
|
+
var generateCommandFunction = (appName, node, path) => {
|
|
8818
|
+
const funcName = path.length === 0 ? `_${appName}` : `_${appName}_${path.join("_")}`;
|
|
8819
|
+
let output = `${funcName}() {
|
|
8820
|
+
`;
|
|
8821
|
+
output += ` local -a commands
|
|
8822
|
+
`;
|
|
8823
|
+
output += ` local -a flags
|
|
8824
|
+
|
|
8825
|
+
`;
|
|
8826
|
+
if (node.flags !== void 0 && node.flags.length > 0) {
|
|
8827
|
+
const flagSpecs = generateFlagSpecs(node.flags);
|
|
8828
|
+
output += ` flags=(
|
|
8829
|
+
${flagSpecs.join("\n ")}
|
|
8830
|
+
)
|
|
8831
|
+
|
|
8832
|
+
`;
|
|
8833
|
+
}
|
|
8834
|
+
if (node.children !== void 0 && node.children.length > 0) {
|
|
8835
|
+
output += ` commands=(
|
|
8836
|
+
`;
|
|
8837
|
+
output += ` ${generateSubcommandSpecs(node.children)}
|
|
8838
|
+
`;
|
|
8839
|
+
output += ` )
|
|
8840
|
+
|
|
8841
|
+
`;
|
|
8842
|
+
output += ` _arguments -C \\
|
|
8843
|
+
`;
|
|
8844
|
+
if (node.flags !== void 0 && node.flags.length > 0) {
|
|
8845
|
+
output += ` "\${flags[@]}" \\
|
|
8846
|
+
`;
|
|
8847
|
+
}
|
|
8848
|
+
output += ` '1: :->command' \\
|
|
8849
|
+
`;
|
|
8850
|
+
output += ` '*::arg:->args'
|
|
8851
|
+
|
|
8852
|
+
`;
|
|
8853
|
+
output += ` case "$state" in
|
|
8854
|
+
`;
|
|
8855
|
+
output += ` command)
|
|
8856
|
+
`;
|
|
8857
|
+
output += ` _describe -t commands 'command' commands
|
|
8858
|
+
`;
|
|
8859
|
+
output += ` ;;
|
|
8860
|
+
`;
|
|
8861
|
+
output += ` args)
|
|
8862
|
+
`;
|
|
8863
|
+
output += ` case "\${words[1]}" in
|
|
8864
|
+
`;
|
|
8865
|
+
for (const child of node.children) {
|
|
8866
|
+
const childPath = [
|
|
8867
|
+
...path,
|
|
8868
|
+
child.name
|
|
8869
|
+
];
|
|
8870
|
+
const childFunc = `_${appName}_${childPath.join("_")}`;
|
|
8871
|
+
output += ` ${child.name})
|
|
8872
|
+
`;
|
|
8873
|
+
output += ` ${childFunc}
|
|
8874
|
+
`;
|
|
8875
|
+
output += ` ;;
|
|
8876
|
+
`;
|
|
8877
|
+
}
|
|
8878
|
+
output += ` esac
|
|
8879
|
+
`;
|
|
8880
|
+
output += ` ;;
|
|
8881
|
+
`;
|
|
8882
|
+
output += ` esac
|
|
8883
|
+
`;
|
|
8884
|
+
} else if (node.flags !== void 0 && node.flags.length > 0) {
|
|
8885
|
+
output += ` _arguments "\${flags[@]}"
|
|
8886
|
+
`;
|
|
8887
|
+
}
|
|
8888
|
+
output += `}
|
|
8889
|
+
|
|
8890
|
+
`;
|
|
8891
|
+
if (node.children !== void 0) {
|
|
8892
|
+
for (const child of node.children) {
|
|
8893
|
+
output += generateCommandFunction(appName, child, [
|
|
8894
|
+
...path,
|
|
8895
|
+
child.name
|
|
8896
|
+
]);
|
|
8897
|
+
}
|
|
8898
|
+
}
|
|
8899
|
+
return output;
|
|
8900
|
+
};
|
|
8901
|
+
var generate2 = (appName, tree) => {
|
|
8902
|
+
let output = `#compdef ${appName}
|
|
8903
|
+
`;
|
|
8904
|
+
output += `# ${appName} zsh completion
|
|
8905
|
+
`;
|
|
8906
|
+
output += `# Generated by @eser/shell/completions
|
|
8907
|
+
|
|
8908
|
+
`;
|
|
8909
|
+
output += generateCommandFunction(appName, tree, []);
|
|
8910
|
+
output += `_${appName} "$@"
|
|
8911
|
+
`;
|
|
8912
|
+
return output;
|
|
8913
|
+
};
|
|
8914
|
+
|
|
8915
|
+
// pkg/@eser/shell/completions/generators/fish.ts
|
|
8916
|
+
var escapeFish = (str2) => {
|
|
8917
|
+
return str2.replace(/'/g, "\\'");
|
|
8918
|
+
};
|
|
8919
|
+
var generateFlagCompletions2 = (appName, flags, condition) => {
|
|
8920
|
+
let output = "";
|
|
8921
|
+
for (const flag of flags) {
|
|
8922
|
+
const desc = escapeFish(flag.description ?? `${flag.name} flag`);
|
|
8923
|
+
let cmd = `complete -c ${appName} ${condition}`;
|
|
8924
|
+
cmd += ` -l ${flag.name}`;
|
|
8925
|
+
if (flag.short !== void 0) {
|
|
8926
|
+
cmd += ` -s ${flag.short}`;
|
|
8927
|
+
}
|
|
8928
|
+
if (flag.takesValue === true) {
|
|
8929
|
+
cmd += " -r";
|
|
8930
|
+
}
|
|
8931
|
+
cmd += ` -d '${desc}'`;
|
|
8932
|
+
output += cmd + "\n";
|
|
8933
|
+
}
|
|
8934
|
+
return output;
|
|
8935
|
+
};
|
|
8936
|
+
var generateCommandCompletions = (appName, node, path) => {
|
|
8937
|
+
let output = "";
|
|
8938
|
+
let condition;
|
|
8939
|
+
if (path.length === 0) {
|
|
8940
|
+
condition = "-n __fish_use_subcommand";
|
|
8941
|
+
} else {
|
|
8942
|
+
const pathConditions = path.map((p) => `__fish_seen_subcommand_from ${p}`).join("; and ");
|
|
8943
|
+
condition = `-n "${pathConditions}"`;
|
|
8944
|
+
}
|
|
8945
|
+
if (node.children !== void 0 && node.children.length > 0) {
|
|
8946
|
+
for (const child of node.children) {
|
|
8947
|
+
const desc = escapeFish(child.description ?? child.name);
|
|
8948
|
+
if (path.length === 0) {
|
|
8949
|
+
output += `complete -c ${appName} -f ${condition} `;
|
|
8950
|
+
output += `-a "${child.name}" -d '${desc}'
|
|
8951
|
+
`;
|
|
8952
|
+
} else {
|
|
8953
|
+
const parentCondition = `-n "__fish_seen_subcommand_from ${path[path.length - 1]}"`;
|
|
8954
|
+
output += `complete -c ${appName} -f ${parentCondition} `;
|
|
8955
|
+
output += `-a "${child.name}" -d '${desc}'
|
|
8956
|
+
`;
|
|
8957
|
+
}
|
|
8958
|
+
}
|
|
8959
|
+
for (const child of node.children) {
|
|
8960
|
+
output += generateCommandCompletions(appName, child, [
|
|
8961
|
+
...path,
|
|
8962
|
+
child.name
|
|
8963
|
+
]);
|
|
8964
|
+
}
|
|
8965
|
+
}
|
|
8966
|
+
if (node.flags !== void 0 && node.flags.length > 0) {
|
|
8967
|
+
output += generateFlagCompletions2(appName, node.flags, condition);
|
|
8968
|
+
}
|
|
8969
|
+
return output;
|
|
8970
|
+
};
|
|
8971
|
+
var generate3 = (appName, tree) => {
|
|
8972
|
+
let output = `# ${appName} fish completion
|
|
8973
|
+
`;
|
|
8974
|
+
output += `# Generated by @eser/shell/completions
|
|
8975
|
+
|
|
8976
|
+
`;
|
|
8977
|
+
output += `complete -c ${appName} -f
|
|
8978
|
+
|
|
8979
|
+
`;
|
|
8980
|
+
output += generateCommandCompletions(appName, tree, []);
|
|
8981
|
+
return output;
|
|
8982
|
+
};
|
|
8983
|
+
|
|
8984
|
+
// pkg/@eser/shell/completions/mod.ts
|
|
8985
|
+
var generate4 = (shell, appName, tree) => {
|
|
8986
|
+
switch (shell) {
|
|
8987
|
+
case "bash":
|
|
8988
|
+
return generate(appName, tree);
|
|
8989
|
+
case "zsh":
|
|
8990
|
+
return generate2(appName, tree);
|
|
8991
|
+
case "fish":
|
|
8992
|
+
return generate3(appName, tree);
|
|
8993
|
+
}
|
|
8994
|
+
};
|
|
8995
|
+
|
|
8996
|
+
// pkg/@eser/shell/args/command.ts
|
|
8997
|
+
var Command = class {
|
|
8998
|
+
#name;
|
|
8999
|
+
#description;
|
|
9000
|
+
#usage;
|
|
9001
|
+
#examples = [];
|
|
9002
|
+
#aliases = [];
|
|
9003
|
+
#flags = [];
|
|
9004
|
+
#persistentFlags = [];
|
|
9005
|
+
#children = [];
|
|
9006
|
+
#handler;
|
|
9007
|
+
#argsConfig = {
|
|
9008
|
+
validation: "none"
|
|
9009
|
+
};
|
|
9010
|
+
#version;
|
|
9011
|
+
#parent;
|
|
9012
|
+
constructor(name) {
|
|
9013
|
+
this.#name = name;
|
|
9014
|
+
}
|
|
9015
|
+
/** Get the command name */
|
|
9016
|
+
get name() {
|
|
9017
|
+
return this.#name;
|
|
9018
|
+
}
|
|
9019
|
+
/** Set command description */
|
|
9020
|
+
description(text) {
|
|
9021
|
+
this.#description = text;
|
|
9022
|
+
return this;
|
|
9023
|
+
}
|
|
9024
|
+
/** Set custom usage string */
|
|
9025
|
+
usage(text) {
|
|
9026
|
+
this.#usage = text;
|
|
9027
|
+
return this;
|
|
9028
|
+
}
|
|
9029
|
+
/** Add usage example */
|
|
9030
|
+
example(text) {
|
|
9031
|
+
this.#examples.push(text);
|
|
9032
|
+
return this;
|
|
9033
|
+
}
|
|
9034
|
+
/** Set command aliases */
|
|
9035
|
+
aliases(...names) {
|
|
9036
|
+
this.#aliases = names;
|
|
9037
|
+
return this;
|
|
9038
|
+
}
|
|
9039
|
+
/** Set version (for root command) */
|
|
9040
|
+
version(v) {
|
|
9041
|
+
this.#version = v;
|
|
9042
|
+
return this;
|
|
9043
|
+
}
|
|
9044
|
+
/** Add a local flag (only available to this command) */
|
|
9045
|
+
flag(def) {
|
|
9046
|
+
this.#flags.push(def);
|
|
9047
|
+
return this;
|
|
9048
|
+
}
|
|
9049
|
+
/** Add a persistent flag (available to this command and all subcommands) */
|
|
9050
|
+
persistentFlag(def) {
|
|
9051
|
+
this.#persistentFlags.push({
|
|
9052
|
+
...def,
|
|
9053
|
+
persistent: true
|
|
9054
|
+
});
|
|
9055
|
+
return this;
|
|
9056
|
+
}
|
|
9057
|
+
/** Configure argument validation */
|
|
9058
|
+
args(validation, count) {
|
|
9059
|
+
if (validation === "exact" && typeof count === "number") {
|
|
9060
|
+
this.#argsConfig = {
|
|
9061
|
+
validation,
|
|
9062
|
+
count
|
|
9063
|
+
};
|
|
9064
|
+
} else if (validation === "min" && typeof count === "number") {
|
|
9065
|
+
this.#argsConfig = {
|
|
9066
|
+
validation,
|
|
9067
|
+
min: count
|
|
9068
|
+
};
|
|
9069
|
+
} else if (validation === "max" && typeof count === "number") {
|
|
9070
|
+
this.#argsConfig = {
|
|
9071
|
+
validation,
|
|
9072
|
+
max: count
|
|
9073
|
+
};
|
|
9074
|
+
} else if (validation === "range" && Array.isArray(count)) {
|
|
9075
|
+
this.#argsConfig = {
|
|
9076
|
+
validation,
|
|
9077
|
+
min: count[0],
|
|
9078
|
+
max: count[1]
|
|
9079
|
+
};
|
|
9080
|
+
} else {
|
|
9081
|
+
this.#argsConfig = {
|
|
9082
|
+
validation
|
|
9083
|
+
};
|
|
9084
|
+
}
|
|
9085
|
+
return this;
|
|
9086
|
+
}
|
|
9087
|
+
/** Add a single subcommand */
|
|
9088
|
+
command(child) {
|
|
9089
|
+
child.#parent = this;
|
|
9090
|
+
this.#children.push(child);
|
|
9091
|
+
return this;
|
|
9092
|
+
}
|
|
9093
|
+
/** Add multiple subcommands */
|
|
9094
|
+
commands(...children) {
|
|
9095
|
+
for (const child of children) {
|
|
9096
|
+
this.command(child);
|
|
9097
|
+
}
|
|
9098
|
+
return this;
|
|
9099
|
+
}
|
|
9100
|
+
/** Set the command handler */
|
|
9101
|
+
run(handler) {
|
|
9102
|
+
this.#handler = handler;
|
|
9103
|
+
return this;
|
|
9104
|
+
}
|
|
9105
|
+
/** Get all flags including inherited persistent flags */
|
|
9106
|
+
#getAllFlags() {
|
|
9107
|
+
const inherited = [];
|
|
9108
|
+
let current = this.#parent;
|
|
9109
|
+
while (current !== void 0) {
|
|
9110
|
+
inherited.push(...current.#persistentFlags);
|
|
9111
|
+
current = current.#parent;
|
|
9112
|
+
}
|
|
9113
|
+
return [
|
|
9114
|
+
...inherited,
|
|
9115
|
+
...this.#persistentFlags,
|
|
9116
|
+
...this.#flags
|
|
9117
|
+
];
|
|
9118
|
+
}
|
|
9119
|
+
/** Get the root command */
|
|
9120
|
+
#getRoot() {
|
|
9121
|
+
if (this.#parent === void 0) {
|
|
9122
|
+
return this;
|
|
9123
|
+
}
|
|
9124
|
+
return this.#parent.#getRoot();
|
|
9125
|
+
}
|
|
9126
|
+
/** Get the command path from root */
|
|
9127
|
+
#getPath() {
|
|
9128
|
+
if (this.#parent === void 0) {
|
|
9129
|
+
return [
|
|
9130
|
+
this.#name
|
|
9131
|
+
];
|
|
9132
|
+
}
|
|
9133
|
+
return [
|
|
9134
|
+
...this.#parent.#getPath(),
|
|
9135
|
+
this.#name
|
|
9136
|
+
];
|
|
9137
|
+
}
|
|
9138
|
+
/** Find a child command by name or alias */
|
|
9139
|
+
#findChild(name) {
|
|
9140
|
+
return this.#children.find((c) => c.#name === name || c.#aliases.includes(name));
|
|
9141
|
+
}
|
|
9142
|
+
/** Validate argument count */
|
|
9143
|
+
#validateArgs(args) {
|
|
9144
|
+
const { validation, count, min, max } = this.#argsConfig;
|
|
9145
|
+
const len = args.length;
|
|
9146
|
+
switch (validation) {
|
|
9147
|
+
case "no-args":
|
|
9148
|
+
if (len > 0) return `This command takes no arguments`;
|
|
9149
|
+
break;
|
|
9150
|
+
case "exact":
|
|
9151
|
+
if (len !== count) {
|
|
9152
|
+
return `Expected exactly ${count} argument(s), got ${len}`;
|
|
9153
|
+
}
|
|
9154
|
+
break;
|
|
9155
|
+
case "min":
|
|
9156
|
+
if (len < (min ?? 0)) {
|
|
9157
|
+
return `Expected at least ${min} argument(s), got ${len}`;
|
|
9158
|
+
}
|
|
9159
|
+
break;
|
|
9160
|
+
case "max":
|
|
9161
|
+
if (len > (max ?? Infinity)) {
|
|
9162
|
+
return `Expected at most ${max} argument(s), got ${len}`;
|
|
9163
|
+
}
|
|
9164
|
+
break;
|
|
9165
|
+
case "range":
|
|
9166
|
+
if (len < (min ?? 0) || len > (max ?? Infinity)) {
|
|
9167
|
+
return `Expected ${min}-${max} arguments, got ${len}`;
|
|
9168
|
+
}
|
|
9169
|
+
break;
|
|
9170
|
+
}
|
|
9171
|
+
return void 0;
|
|
9172
|
+
}
|
|
9173
|
+
/** Parse and execute the command */
|
|
9174
|
+
async parse(argv) {
|
|
9175
|
+
const inputArgs = argv ?? runtime.process.args;
|
|
9176
|
+
await this.#execute(inputArgs, []);
|
|
9177
|
+
}
|
|
9178
|
+
async #execute(argv, parentPath) {
|
|
9179
|
+
const allFlags = this.#getAllFlags();
|
|
9180
|
+
const parseOptions = buildParseOptions(allFlags);
|
|
9181
|
+
const parsed = parseArgs(argv, {
|
|
9182
|
+
...parseOptions,
|
|
9183
|
+
stopEarly: this.#children.length > 0
|
|
9184
|
+
});
|
|
9185
|
+
const flags = extractFlags(parsed, allFlags);
|
|
9186
|
+
const positional = parsed._;
|
|
9187
|
+
if (this.#version !== void 0 && flags["version"] === true) {
|
|
9188
|
+
console.log(`${this.#name} ${this.#version}`);
|
|
9189
|
+
return;
|
|
9190
|
+
}
|
|
9191
|
+
if (flags["help"] === true) {
|
|
9192
|
+
console.log(this.help());
|
|
9193
|
+
return;
|
|
9194
|
+
}
|
|
9195
|
+
const firstArg = positional[0];
|
|
9196
|
+
if (firstArg !== void 0 && this.#children.length > 0) {
|
|
9197
|
+
const child = this.#findChild(firstArg);
|
|
9198
|
+
if (child !== void 0) {
|
|
9199
|
+
await child.#execute(positional.slice(1), [
|
|
9200
|
+
...parentPath,
|
|
9201
|
+
this.#name
|
|
9202
|
+
]);
|
|
9203
|
+
return;
|
|
9204
|
+
}
|
|
9205
|
+
}
|
|
9206
|
+
if (this.#handler === void 0) {
|
|
9207
|
+
console.log(this.help());
|
|
9208
|
+
return;
|
|
9209
|
+
}
|
|
9210
|
+
const flagErrors = validateRequiredFlags(flags, allFlags);
|
|
9211
|
+
if (flagErrors.length > 0) {
|
|
9212
|
+
console.error(flagErrors.join("\n"));
|
|
9213
|
+
runtime.process.exit(1);
|
|
9214
|
+
}
|
|
9215
|
+
const argsError = this.#validateArgs(positional);
|
|
9216
|
+
if (argsError !== void 0) {
|
|
9217
|
+
console.error(argsError);
|
|
9218
|
+
runtime.process.exit(1);
|
|
9219
|
+
}
|
|
9220
|
+
const commandPath = [
|
|
9221
|
+
...parentPath,
|
|
9222
|
+
this.#name
|
|
9223
|
+
];
|
|
9224
|
+
const ctx = {
|
|
9225
|
+
args: positional,
|
|
9226
|
+
flags,
|
|
9227
|
+
root: this.#getRoot(),
|
|
9228
|
+
commandPath
|
|
9229
|
+
};
|
|
9230
|
+
await this.#handler(ctx);
|
|
9231
|
+
}
|
|
9232
|
+
/** Generate help text */
|
|
9233
|
+
help() {
|
|
9234
|
+
const meta = {
|
|
9235
|
+
name: this.#name,
|
|
9236
|
+
description: this.#description,
|
|
9237
|
+
usage: this.#usage,
|
|
9238
|
+
examples: this.#examples,
|
|
9239
|
+
flags: this.#getAllFlags(),
|
|
9240
|
+
children: this.#children.map((c) => ({
|
|
9241
|
+
name: c.#name,
|
|
9242
|
+
description: c.#description,
|
|
9243
|
+
usage: c.#usage,
|
|
9244
|
+
examples: c.#examples,
|
|
9245
|
+
flags: c.#getAllFlags(),
|
|
9246
|
+
children: []
|
|
9247
|
+
}))
|
|
9248
|
+
};
|
|
9249
|
+
return generateHelp(meta, this.#getPath());
|
|
9250
|
+
}
|
|
9251
|
+
/** Build completion tree from command structure */
|
|
9252
|
+
#buildCompletionTree() {
|
|
9253
|
+
const flagsToCompletionFlags = (flags) => {
|
|
9254
|
+
return flags.map((f) => ({
|
|
9255
|
+
name: f.name,
|
|
9256
|
+
short: f.short,
|
|
9257
|
+
description: f.description,
|
|
9258
|
+
takesValue: f.type !== "boolean"
|
|
9259
|
+
}));
|
|
9260
|
+
};
|
|
9261
|
+
const buildNode = (cmd) => ({
|
|
9262
|
+
name: cmd.#name,
|
|
9263
|
+
description: cmd.#description,
|
|
9264
|
+
children: cmd.#children.map(buildNode),
|
|
9265
|
+
flags: flagsToCompletionFlags(cmd.#getAllFlags())
|
|
9266
|
+
});
|
|
9267
|
+
return buildNode(this);
|
|
9268
|
+
}
|
|
9269
|
+
/** Generate shell completion script */
|
|
9270
|
+
completions(shell) {
|
|
9271
|
+
const tree = this.#buildCompletionTree();
|
|
9272
|
+
return generate4(shell, this.#name, tree);
|
|
9273
|
+
}
|
|
9274
|
+
};
|
|
9275
|
+
|
|
9276
|
+
// pkg/@eser/shell/exec/types.ts
|
|
9277
|
+
var CommandError = class extends Error {
|
|
9278
|
+
command;
|
|
9279
|
+
code;
|
|
9280
|
+
stderr;
|
|
9281
|
+
constructor(message, command, code2, stderr) {
|
|
9282
|
+
super(message), this.command = command, this.code = code2, this.stderr = stderr;
|
|
9283
|
+
this.name = "CommandError";
|
|
9284
|
+
}
|
|
9285
|
+
};
|
|
9286
|
+
|
|
9287
|
+
// pkg/@eser/shell/exec/command.ts
|
|
9288
|
+
var decoder = new TextDecoder();
|
|
9289
|
+
var CommandBuilder = class _CommandBuilder {
|
|
9290
|
+
#cmd;
|
|
9291
|
+
#args;
|
|
9292
|
+
#options;
|
|
9293
|
+
constructor(cmd, args = [], options = {}) {
|
|
9294
|
+
this.#cmd = cmd;
|
|
9295
|
+
this.#args = args;
|
|
9296
|
+
this.#options = {
|
|
9297
|
+
throwOnError: true,
|
|
9298
|
+
stdout: "piped",
|
|
9299
|
+
stderr: "piped",
|
|
9300
|
+
...options
|
|
9301
|
+
};
|
|
9302
|
+
}
|
|
9303
|
+
/** Set working directory */
|
|
9304
|
+
cwd(path) {
|
|
9305
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9306
|
+
...this.#options,
|
|
9307
|
+
cwd: path
|
|
9308
|
+
});
|
|
9309
|
+
}
|
|
9310
|
+
/** Set environment variable(s) */
|
|
9311
|
+
env(keyOrVars, value2) {
|
|
9312
|
+
const currentEnv = this.#options.env ?? {};
|
|
9313
|
+
let newEnv;
|
|
9314
|
+
if (typeof keyOrVars === "string" && value2 !== void 0) {
|
|
9315
|
+
newEnv = {
|
|
9316
|
+
...currentEnv,
|
|
9317
|
+
[keyOrVars]: value2
|
|
9318
|
+
};
|
|
9319
|
+
} else if (typeof keyOrVars === "object") {
|
|
9320
|
+
newEnv = {
|
|
9321
|
+
...currentEnv,
|
|
9322
|
+
...keyOrVars
|
|
9323
|
+
};
|
|
9324
|
+
} else {
|
|
9325
|
+
newEnv = currentEnv;
|
|
9326
|
+
}
|
|
9327
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9328
|
+
...this.#options,
|
|
9329
|
+
env: newEnv
|
|
9330
|
+
});
|
|
9331
|
+
}
|
|
9332
|
+
/** Set stdin handling */
|
|
9333
|
+
stdin(option) {
|
|
9334
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9335
|
+
...this.#options,
|
|
9336
|
+
stdin: option
|
|
9337
|
+
});
|
|
9338
|
+
}
|
|
9339
|
+
/** Set stdout handling */
|
|
9340
|
+
stdout(option) {
|
|
9341
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9342
|
+
...this.#options,
|
|
9343
|
+
stdout: option
|
|
9344
|
+
});
|
|
9345
|
+
}
|
|
9346
|
+
/** Set stderr handling */
|
|
9347
|
+
stderr(option) {
|
|
9348
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9349
|
+
...this.#options,
|
|
9350
|
+
stderr: option
|
|
9351
|
+
});
|
|
9352
|
+
}
|
|
9353
|
+
/** Set timeout in milliseconds */
|
|
9354
|
+
timeout(ms) {
|
|
9355
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9356
|
+
...this.#options,
|
|
9357
|
+
timeout: ms
|
|
9358
|
+
});
|
|
9359
|
+
}
|
|
9360
|
+
/** Disable throwing on non-zero exit code */
|
|
9361
|
+
noThrow() {
|
|
9362
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9363
|
+
...this.#options,
|
|
9364
|
+
throwOnError: false
|
|
9365
|
+
});
|
|
9366
|
+
}
|
|
9367
|
+
/** Suppress all output (null stdout and stderr) */
|
|
9368
|
+
quiet() {
|
|
9369
|
+
return new _CommandBuilder(this.#cmd, this.#args, {
|
|
9370
|
+
...this.#options,
|
|
9371
|
+
stdout: "null",
|
|
9372
|
+
stderr: "null"
|
|
9373
|
+
});
|
|
9374
|
+
}
|
|
9375
|
+
/** Print command before execution */
|
|
9376
|
+
printCommand() {
|
|
9377
|
+
const fullCmd = [
|
|
9378
|
+
this.#cmd,
|
|
9379
|
+
...this.#args
|
|
9380
|
+
].join(" ");
|
|
9381
|
+
console.log(`$ ${fullCmd}`);
|
|
9382
|
+
return this;
|
|
9383
|
+
}
|
|
9384
|
+
/** Execute command and return result */
|
|
9385
|
+
async spawn() {
|
|
9386
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9387
|
+
const result = await runtime2.exec.spawn(this.#cmd, this.#args, {
|
|
9388
|
+
cwd: this.#options.cwd,
|
|
9389
|
+
env: this.#options.env,
|
|
9390
|
+
stdin: this.#options.stdin,
|
|
9391
|
+
stdout: this.#options.stdout,
|
|
9392
|
+
stderr: this.#options.stderr
|
|
9393
|
+
});
|
|
9394
|
+
if (!result.success && this.#options.throwOnError === true) {
|
|
9395
|
+
const stderrText = decoder.decode(result.stderr);
|
|
9396
|
+
throw new CommandError(`Command failed with exit code ${result.code}: ${this.#cmd}`, this.#cmd, result.code, stderrText);
|
|
9397
|
+
}
|
|
9398
|
+
return result;
|
|
9399
|
+
}
|
|
9400
|
+
/** Execute and return stdout as trimmed text */
|
|
9401
|
+
async text(stream = "stdout") {
|
|
9402
|
+
const result = await this.spawn();
|
|
9403
|
+
switch (stream) {
|
|
9404
|
+
case "stdout":
|
|
9405
|
+
return decoder.decode(result.stdout).trim();
|
|
9406
|
+
case "stderr":
|
|
9407
|
+
return decoder.decode(result.stderr).trim();
|
|
9408
|
+
case "combined":
|
|
9409
|
+
return (decoder.decode(result.stdout) + decoder.decode(result.stderr)).trim();
|
|
9410
|
+
}
|
|
9411
|
+
}
|
|
9412
|
+
/** Execute and parse stdout as JSON */
|
|
9413
|
+
async json() {
|
|
9414
|
+
const text = await this.text();
|
|
9415
|
+
return JSON.parse(text);
|
|
9416
|
+
}
|
|
9417
|
+
/** Execute and return stdout as lines */
|
|
9418
|
+
async lines() {
|
|
9419
|
+
const text = await this.text();
|
|
9420
|
+
if (text === "") return [];
|
|
9421
|
+
return text.split("\n");
|
|
9422
|
+
}
|
|
9423
|
+
/** Execute and return stdout as bytes */
|
|
9424
|
+
async bytes() {
|
|
9425
|
+
const result = await this.spawn();
|
|
9426
|
+
return result.stdout;
|
|
9427
|
+
}
|
|
9428
|
+
/** Execute and return only the exit code (never throws) */
|
|
9429
|
+
async code() {
|
|
9430
|
+
const result = await this.noThrow().spawn();
|
|
9431
|
+
return result.code;
|
|
9432
|
+
}
|
|
9433
|
+
/** Pipe this command's output to another command */
|
|
9434
|
+
pipe(next) {
|
|
9435
|
+
return new PipedCommandBuilder([
|
|
9436
|
+
this,
|
|
9437
|
+
next
|
|
9438
|
+
]);
|
|
9439
|
+
}
|
|
9440
|
+
/**
|
|
9441
|
+
* Spawn child process with streaming I/O support.
|
|
9442
|
+
* Returns a handle with stdin/stdout/stderr streams for advanced use cases.
|
|
9443
|
+
*
|
|
9444
|
+
* @example
|
|
9445
|
+
* ```ts
|
|
9446
|
+
* const child = exec`deno fmt -`.child();
|
|
9447
|
+
* await input.pipeTo(child.stdin!);
|
|
9448
|
+
* const { stdout } = await child.output();
|
|
9449
|
+
* ```
|
|
9450
|
+
*/
|
|
9451
|
+
child() {
|
|
9452
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9453
|
+
return runtime2.exec.spawnChild(this.#cmd, this.#args, {
|
|
9454
|
+
cwd: this.#options.cwd,
|
|
9455
|
+
env: this.#options.env,
|
|
9456
|
+
stdin: this.#options.stdin ?? "piped",
|
|
9457
|
+
stdout: this.#options.stdout ?? "piped",
|
|
9458
|
+
stderr: this.#options.stderr ?? "piped"
|
|
9459
|
+
});
|
|
9460
|
+
}
|
|
9461
|
+
};
|
|
9462
|
+
var PipedCommandBuilder = class _PipedCommandBuilder {
|
|
9463
|
+
#commands;
|
|
9464
|
+
constructor(commands2) {
|
|
9465
|
+
this.#commands = commands2;
|
|
9466
|
+
}
|
|
9467
|
+
/** Add another command to the pipeline */
|
|
9468
|
+
pipe(next) {
|
|
9469
|
+
return new _PipedCommandBuilder([
|
|
9470
|
+
...this.#commands,
|
|
9471
|
+
next
|
|
9472
|
+
]);
|
|
9473
|
+
}
|
|
9474
|
+
/** Execute the pipeline and return final stdout as text */
|
|
9475
|
+
async text() {
|
|
9476
|
+
let input = "";
|
|
9477
|
+
for (const cmd of this.#commands) {
|
|
9478
|
+
const result = await cmd.spawn();
|
|
9479
|
+
input = decoder.decode(result.stdout);
|
|
9480
|
+
}
|
|
9481
|
+
return input.trim();
|
|
9482
|
+
}
|
|
9483
|
+
/** Execute the pipeline and return final stdout as lines */
|
|
9484
|
+
async lines() {
|
|
9485
|
+
const text = await this.text();
|
|
9486
|
+
if (text === "") return [];
|
|
9487
|
+
return text.split("\n");
|
|
9488
|
+
}
|
|
9489
|
+
};
|
|
9490
|
+
|
|
9491
|
+
// pkg/@eser/shell/exec/parser.ts
|
|
9492
|
+
var parseCommand = (strings, values) => {
|
|
9493
|
+
const parts = [];
|
|
9494
|
+
for (let i = 0; i < strings.length; i++) {
|
|
9495
|
+
const str2 = strings[i];
|
|
9496
|
+
if (str2 !== void 0) {
|
|
9497
|
+
parts.push(str2);
|
|
9498
|
+
}
|
|
9499
|
+
if (i < values.length) {
|
|
9500
|
+
const value2 = values[i];
|
|
9501
|
+
if (Array.isArray(value2)) {
|
|
9502
|
+
parts.push(value2.map((v) => escapeArg(String(v))).join(" "));
|
|
9503
|
+
} else if (value2 !== void 0 && value2 !== null) {
|
|
9504
|
+
parts.push(escapeArg(String(value2)));
|
|
9505
|
+
}
|
|
9506
|
+
}
|
|
9507
|
+
}
|
|
9508
|
+
const fullCommand = parts.join("").trim();
|
|
9509
|
+
return splitCommand(fullCommand);
|
|
9510
|
+
};
|
|
9511
|
+
var escapeArg = (arg) => {
|
|
9512
|
+
if (/[\s"'\\$`]/.test(arg)) {
|
|
9513
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
9514
|
+
}
|
|
9515
|
+
return arg;
|
|
9516
|
+
};
|
|
9517
|
+
var splitCommand = (input) => {
|
|
9518
|
+
const tokens = [];
|
|
9519
|
+
let current = "";
|
|
9520
|
+
let inSingleQuote = false;
|
|
9521
|
+
let inDoubleQuote = false;
|
|
9522
|
+
let escape = false;
|
|
9523
|
+
for (let i = 0; i < input.length; i++) {
|
|
9524
|
+
const char = input[i];
|
|
9525
|
+
if (escape) {
|
|
9526
|
+
current += char;
|
|
9527
|
+
escape = false;
|
|
9528
|
+
continue;
|
|
9529
|
+
}
|
|
9530
|
+
if (char === "\\") {
|
|
9531
|
+
escape = true;
|
|
9532
|
+
continue;
|
|
9533
|
+
}
|
|
9534
|
+
if (char === "'" && !inDoubleQuote) {
|
|
9535
|
+
inSingleQuote = !inSingleQuote;
|
|
9536
|
+
continue;
|
|
9537
|
+
}
|
|
9538
|
+
if (char === '"' && !inSingleQuote) {
|
|
9539
|
+
inDoubleQuote = !inDoubleQuote;
|
|
9540
|
+
continue;
|
|
9541
|
+
}
|
|
9542
|
+
if (char === " " && !inSingleQuote && !inDoubleQuote) {
|
|
9543
|
+
if (current.length > 0) {
|
|
9544
|
+
tokens.push(current);
|
|
9545
|
+
current = "";
|
|
9546
|
+
}
|
|
9547
|
+
continue;
|
|
9548
|
+
}
|
|
9549
|
+
current += char;
|
|
9550
|
+
}
|
|
9551
|
+
if (current.length > 0) {
|
|
9552
|
+
tokens.push(current);
|
|
9553
|
+
}
|
|
9554
|
+
const firstToken = tokens[0];
|
|
9555
|
+
if (firstToken === void 0) {
|
|
9556
|
+
return [
|
|
9557
|
+
"",
|
|
9558
|
+
[]
|
|
9559
|
+
];
|
|
9560
|
+
}
|
|
9561
|
+
return [
|
|
9562
|
+
firstToken,
|
|
9563
|
+
tokens.slice(1)
|
|
9564
|
+
];
|
|
9565
|
+
};
|
|
9566
|
+
|
|
9567
|
+
// pkg/@eser/shell/exec/exec.ts
|
|
9568
|
+
var exec = (strings, ...values) => {
|
|
9569
|
+
const [cmd, args] = parseCommand(strings, values);
|
|
9570
|
+
return new CommandBuilder(cmd, args);
|
|
9571
|
+
};
|
|
9572
|
+
|
|
9573
|
+
// pkg/@eser/shell/env/detector.ts
|
|
9574
|
+
var getHomeDir = () => {
|
|
9575
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9576
|
+
return runtime2.env.get("HOME") ?? "";
|
|
9577
|
+
};
|
|
9578
|
+
var detectShell = () => {
|
|
9579
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9580
|
+
const shellPath = runtime2.env.get("SHELL") ?? "";
|
|
9581
|
+
if (shellPath.includes("zsh")) {
|
|
9582
|
+
return "zsh";
|
|
9583
|
+
}
|
|
9584
|
+
if (shellPath.includes("fish")) {
|
|
9585
|
+
return "fish";
|
|
9586
|
+
}
|
|
9587
|
+
return "bash";
|
|
9588
|
+
};
|
|
9589
|
+
var getRcFilePath = (shell) => {
|
|
9590
|
+
const home = getHomeDir();
|
|
9591
|
+
switch (shell) {
|
|
9592
|
+
case "zsh":
|
|
9593
|
+
return join4(home, ".zshrc");
|
|
9594
|
+
case "bash":
|
|
9595
|
+
return join4(home, ".bashrc");
|
|
9596
|
+
case "fish":
|
|
9597
|
+
return join4(home, ".config", "fish", "config.fish");
|
|
9598
|
+
}
|
|
9599
|
+
};
|
|
9600
|
+
var getCompletionsFilePath = (shell, appName) => {
|
|
9601
|
+
const home = getHomeDir();
|
|
9602
|
+
switch (shell) {
|
|
9603
|
+
case "zsh":
|
|
9604
|
+
return join4(home, ".zshrc");
|
|
9605
|
+
case "bash":
|
|
9606
|
+
return join4(home, ".bashrc");
|
|
9607
|
+
case "fish":
|
|
9608
|
+
return join4(home, ".config", "fish", "completions", `${appName}.fish`);
|
|
9609
|
+
}
|
|
9610
|
+
};
|
|
9611
|
+
var getCompletionEvalLine = (shell, appName) => {
|
|
9612
|
+
return `eval "$(${appName} system completions --shell ${shell})"`;
|
|
9613
|
+
};
|
|
9614
|
+
var getCompletionType = (shell) => {
|
|
9615
|
+
return shell === "fish" ? "file" : "eval";
|
|
9616
|
+
};
|
|
9617
|
+
var getShellConfig = (shell, appName = "eser") => {
|
|
9618
|
+
const detectedShell = shell ?? detectShell();
|
|
9619
|
+
const completionType = getCompletionType(detectedShell);
|
|
9620
|
+
return {
|
|
9621
|
+
shell: detectedShell,
|
|
9622
|
+
rcFile: getRcFilePath(detectedShell),
|
|
9623
|
+
completionType,
|
|
9624
|
+
completionsFile: completionType === "file" ? getCompletionsFilePath(detectedShell, appName) : void 0
|
|
9625
|
+
};
|
|
9626
|
+
};
|
|
9627
|
+
|
|
9628
|
+
// pkg/@eser/cli/commands/handlers/completions-setup.ts
|
|
9629
|
+
var COMPLETION_MARKER = "# eser CLI completions";
|
|
9630
|
+
var APP_NAME = "eser";
|
|
9631
|
+
var readFileOrEmpty = async (path) => {
|
|
9632
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9633
|
+
try {
|
|
9634
|
+
return await runtime2.fs.readTextFile(path);
|
|
9635
|
+
} catch {
|
|
9636
|
+
return "";
|
|
9637
|
+
}
|
|
9638
|
+
};
|
|
9639
|
+
var fileExists = async (path) => {
|
|
9640
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9641
|
+
try {
|
|
9642
|
+
await runtime2.fs.stat(path);
|
|
9643
|
+
return true;
|
|
9644
|
+
} catch {
|
|
9645
|
+
return false;
|
|
9646
|
+
}
|
|
9647
|
+
};
|
|
9648
|
+
var hasCompletions = async (shell) => {
|
|
9649
|
+
const config = getShellConfig(shell, APP_NAME);
|
|
9650
|
+
if (config.completionType === "file") {
|
|
9651
|
+
return await fileExists(config.completionsFile);
|
|
9652
|
+
}
|
|
9653
|
+
const content = await readFileOrEmpty(config.rcFile);
|
|
9654
|
+
const line = getCompletionEvalLine(shell, APP_NAME);
|
|
9655
|
+
return content.includes(line);
|
|
9656
|
+
};
|
|
9657
|
+
var addCompletions = async (shell) => {
|
|
9658
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9659
|
+
const config = getShellConfig(shell, APP_NAME);
|
|
9660
|
+
try {
|
|
9661
|
+
if (config.completionType === "file") {
|
|
9662
|
+
const fishPath = config.completionsFile;
|
|
9663
|
+
const dir = dirname4(fishPath);
|
|
9664
|
+
try {
|
|
9665
|
+
await runtime2.fs.mkdir(dir, {
|
|
9666
|
+
recursive: true
|
|
9667
|
+
});
|
|
9668
|
+
} catch {
|
|
9669
|
+
}
|
|
9670
|
+
const fishScript = `# eser CLI completions
|
|
9671
|
+
# This file is auto-generated. Run 'eser system completions --shell fish' to regenerate.
|
|
9672
|
+
complete -c eser -f
|
|
9673
|
+
complete -c eser -n "__fish_use_subcommand" -a "codebase" -d "Codebase validation and management tools"
|
|
9674
|
+
complete -c eser -n "__fish_use_subcommand" -a "system" -d "System management and setup tools"
|
|
9675
|
+
complete -c eser -n "__fish_use_subcommand" -a "install" -d "Install eser CLI globally"
|
|
9676
|
+
complete -c eser -n "__fish_use_subcommand" -a "update" -d "Update eser CLI to latest version"
|
|
9677
|
+
complete -c eser -n "__fish_seen_subcommand_from system" -a "install" -d "Install eser CLI globally"
|
|
9678
|
+
complete -c eser -n "__fish_seen_subcommand_from system" -a "uninstall" -d "Uninstall eser CLI globally"
|
|
9679
|
+
complete -c eser -n "__fish_seen_subcommand_from system" -a "update" -d "Update eser CLI to latest version"
|
|
9680
|
+
complete -c eser -n "__fish_seen_subcommand_from system" -a "completions" -d "Generate shell completion scripts"
|
|
9681
|
+
`;
|
|
9682
|
+
await runtime2.fs.writeTextFile(fishPath, fishScript);
|
|
9683
|
+
console.log(` ${dim("Created")} ${cyan(fishPath)}`);
|
|
9684
|
+
} else {
|
|
9685
|
+
const content = await readFileOrEmpty(config.rcFile);
|
|
9686
|
+
const line = getCompletionEvalLine(shell, APP_NAME);
|
|
9687
|
+
if (!content.includes(line)) {
|
|
9688
|
+
const addition = `
|
|
9689
|
+
${COMPLETION_MARKER}
|
|
9690
|
+
${line}
|
|
9691
|
+
`;
|
|
9692
|
+
await runtime2.fs.writeTextFile(config.rcFile, content + addition);
|
|
9693
|
+
console.log(` ${dim("Added completions to")} ${cyan(config.rcFile)}`);
|
|
9694
|
+
}
|
|
9695
|
+
}
|
|
9696
|
+
} catch (error) {
|
|
9697
|
+
console.log(yellow(` Warning: Could not add shell completions: ${error instanceof Error ? error.message : String(error)}`));
|
|
9698
|
+
}
|
|
9699
|
+
};
|
|
9700
|
+
var removeCompletions = async (shell) => {
|
|
9701
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9702
|
+
const config = getShellConfig(shell, APP_NAME);
|
|
9703
|
+
try {
|
|
9704
|
+
if (config.completionType === "file") {
|
|
9705
|
+
const fishPath = config.completionsFile;
|
|
9706
|
+
if (await fileExists(fishPath)) {
|
|
9707
|
+
await runtime2.fs.remove(fishPath);
|
|
9708
|
+
console.log(` ${dim("Removed")} ${cyan(fishPath)}`);
|
|
9709
|
+
}
|
|
9710
|
+
} else {
|
|
9711
|
+
const content = await readFileOrEmpty(config.rcFile);
|
|
9712
|
+
if (content === "") {
|
|
9713
|
+
return;
|
|
9714
|
+
}
|
|
9715
|
+
const line = getCompletionEvalLine(shell, APP_NAME);
|
|
9716
|
+
if (!content.includes(line)) {
|
|
9717
|
+
return;
|
|
9718
|
+
}
|
|
9719
|
+
const filtered = content.split("\n").filter((l) => !l.includes("eser system completions")).filter((l) => l !== COMPLETION_MARKER).join("\n").replace(/\n{3,}/g, "\n\n");
|
|
9720
|
+
await runtime2.fs.writeTextFile(config.rcFile, filtered);
|
|
9721
|
+
console.log(` ${dim("Removed completions from")} ${cyan(config.rcFile)}`);
|
|
9722
|
+
}
|
|
9723
|
+
} catch (error) {
|
|
9724
|
+
console.log(yellow(` Warning: Could not remove shell completions: ${error instanceof Error ? error.message : String(error)}`));
|
|
9725
|
+
}
|
|
9726
|
+
};
|
|
9727
|
+
|
|
9728
|
+
// pkg/@eser/cli/commands/handlers/install.ts
|
|
9729
|
+
var INSTALL_CONFIGS = {
|
|
9730
|
+
deno: {
|
|
9731
|
+
cmd: "deno",
|
|
9732
|
+
args: [
|
|
9733
|
+
"install",
|
|
9734
|
+
"-g",
|
|
9735
|
+
"-A",
|
|
9736
|
+
"--name",
|
|
9737
|
+
"eser",
|
|
9738
|
+
"jsr:@eser/cli"
|
|
9739
|
+
]
|
|
9740
|
+
},
|
|
9741
|
+
node: {
|
|
9742
|
+
cmd: "npm",
|
|
9743
|
+
args: [
|
|
9744
|
+
"install",
|
|
9745
|
+
"-g",
|
|
9746
|
+
"eser"
|
|
9747
|
+
]
|
|
9748
|
+
},
|
|
9749
|
+
bun: {
|
|
9750
|
+
cmd: "bun",
|
|
9751
|
+
args: [
|
|
9752
|
+
"install",
|
|
9753
|
+
"-g",
|
|
9754
|
+
"eser"
|
|
9755
|
+
]
|
|
9756
|
+
}
|
|
9757
|
+
};
|
|
9758
|
+
var installHandler = async (_ctx) => {
|
|
9759
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9760
|
+
const runtimeName = detectRuntime();
|
|
9761
|
+
console.log(`Detected runtime: ${cyan(runtimeName)}`);
|
|
9762
|
+
const config = INSTALL_CONFIGS[runtimeName];
|
|
9763
|
+
if (config === void 0) {
|
|
9764
|
+
console.error(red(`
|
|
9765
|
+
Unsupported runtime: ${runtimeName}`));
|
|
9766
|
+
console.error("Global installation is only supported for Deno, Node.js, and Bun.");
|
|
9767
|
+
runtime2.process.exit(1);
|
|
9768
|
+
return;
|
|
9769
|
+
}
|
|
9770
|
+
const { cmd, args } = config;
|
|
9771
|
+
console.log(dim(`Running: ${cmd} ${args.join(" ")}`));
|
|
9772
|
+
console.log("");
|
|
9773
|
+
const result = await exec`${cmd} ${args}`.stdout("inherit").stderr("inherit").noThrow().spawn();
|
|
9774
|
+
if (result.success) {
|
|
9775
|
+
console.log(green("\nInstallation complete!"));
|
|
9776
|
+
console.log(`You can now use ${cyan("eser")} from anywhere in your terminal.`);
|
|
9777
|
+
const shell = detectShell();
|
|
9778
|
+
const alreadyHasCompletions = await hasCompletions(shell);
|
|
9779
|
+
if (!alreadyHasCompletions) {
|
|
9780
|
+
console.log(`
|
|
9781
|
+
Setting up ${cyan(shell)} completions...`);
|
|
9782
|
+
await addCompletions(shell);
|
|
9783
|
+
const shellConfig = getShellConfig(shell);
|
|
9784
|
+
if (shellConfig.completionType === "eval") {
|
|
9785
|
+
console.log(dim(` Restart your shell or run 'source ${shellConfig.rcFile}' to enable completions.`));
|
|
9786
|
+
}
|
|
9787
|
+
}
|
|
9788
|
+
} else {
|
|
9789
|
+
console.error(red("\nInstallation failed."));
|
|
9790
|
+
}
|
|
9791
|
+
runtime2.process.exit(result.code);
|
|
9792
|
+
};
|
|
9793
|
+
|
|
9794
|
+
// pkg/@eser/cli/commands/handlers/uninstall.ts
|
|
9795
|
+
var UNINSTALL_CONFIGS = {
|
|
9796
|
+
deno: {
|
|
9797
|
+
cmd: "deno",
|
|
9798
|
+
args: [
|
|
9799
|
+
"uninstall",
|
|
9800
|
+
"-g",
|
|
9801
|
+
"eser"
|
|
9802
|
+
]
|
|
9803
|
+
},
|
|
9804
|
+
node: {
|
|
9805
|
+
cmd: "npm",
|
|
9806
|
+
args: [
|
|
9807
|
+
"uninstall",
|
|
9808
|
+
"-g",
|
|
9809
|
+
"eser"
|
|
9810
|
+
]
|
|
9811
|
+
},
|
|
9812
|
+
bun: {
|
|
9813
|
+
cmd: "bun",
|
|
9814
|
+
args: [
|
|
9815
|
+
"remove",
|
|
9816
|
+
"-g",
|
|
9817
|
+
"eser"
|
|
9818
|
+
]
|
|
9819
|
+
}
|
|
9820
|
+
};
|
|
9821
|
+
var uninstallHandler = async (_ctx) => {
|
|
9822
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9823
|
+
const runtimeName = detectRuntime();
|
|
9824
|
+
console.log(`Detected runtime: ${cyan(runtimeName)}`);
|
|
9825
|
+
const config = UNINSTALL_CONFIGS[runtimeName];
|
|
9826
|
+
if (config === void 0) {
|
|
9827
|
+
console.error(red(`
|
|
9828
|
+
Unsupported runtime: ${runtimeName}`));
|
|
9829
|
+
console.error("Global uninstallation is only supported for Deno, Node.js, and Bun.");
|
|
9830
|
+
runtime2.process.exit(1);
|
|
9831
|
+
return;
|
|
9832
|
+
}
|
|
9833
|
+
const { cmd, args } = config;
|
|
9834
|
+
const shell = detectShell();
|
|
9835
|
+
console.log(`
|
|
9836
|
+
Removing ${cyan(shell)} completions...`);
|
|
9837
|
+
await removeCompletions(shell);
|
|
9838
|
+
console.log(dim(`
|
|
9839
|
+
Running: ${cmd} ${args.join(" ")}`));
|
|
9840
|
+
console.log("");
|
|
9841
|
+
const result = await exec`${cmd} ${args}`.stdout("inherit").stderr("inherit").noThrow().spawn();
|
|
9842
|
+
if (result.success) {
|
|
9843
|
+
console.log(green("\nUninstallation complete!"));
|
|
9844
|
+
console.log(`The ${cyan("eser")} command has been removed from your system.`);
|
|
9845
|
+
} else {
|
|
9846
|
+
console.error(red("\nUninstallation failed."));
|
|
9847
|
+
}
|
|
9848
|
+
runtime2.process.exit(result.code);
|
|
9849
|
+
};
|
|
9850
|
+
|
|
9851
|
+
// pkg/@eser/cli/commands/handlers/update.ts
|
|
9852
|
+
var UPDATE_CONFIGS = {
|
|
9853
|
+
deno: {
|
|
9854
|
+
cmd: "deno",
|
|
9855
|
+
// Deno doesn't have an update command, so we reinstall with -f (force)
|
|
9856
|
+
args: [
|
|
9857
|
+
"install",
|
|
9858
|
+
"-g",
|
|
9859
|
+
"-A",
|
|
9860
|
+
"-f",
|
|
9861
|
+
"--name",
|
|
9862
|
+
"eser",
|
|
9863
|
+
"jsr:@eser/cli"
|
|
9864
|
+
]
|
|
9865
|
+
},
|
|
9866
|
+
node: {
|
|
9867
|
+
cmd: "npm",
|
|
9868
|
+
args: [
|
|
9869
|
+
"update",
|
|
9870
|
+
"-g",
|
|
9871
|
+
"eser"
|
|
9872
|
+
]
|
|
9873
|
+
},
|
|
9874
|
+
bun: {
|
|
9875
|
+
cmd: "bun",
|
|
9876
|
+
args: [
|
|
9877
|
+
"update",
|
|
9878
|
+
"-g",
|
|
9879
|
+
"eser"
|
|
9880
|
+
]
|
|
9881
|
+
}
|
|
9882
|
+
};
|
|
9883
|
+
var updateHandler = async (_ctx) => {
|
|
9884
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9885
|
+
const runtimeName = detectRuntime();
|
|
9886
|
+
console.log(`Detected runtime: ${cyan(runtimeName)}`);
|
|
9887
|
+
const config = UPDATE_CONFIGS[runtimeName];
|
|
9888
|
+
if (config === void 0) {
|
|
9889
|
+
console.error(red(`
|
|
9890
|
+
Unsupported runtime: ${runtimeName}`));
|
|
9891
|
+
console.error("Global update is only supported for Deno, Node.js, and Bun.");
|
|
9892
|
+
runtime2.process.exit(1);
|
|
9893
|
+
return;
|
|
9894
|
+
}
|
|
9895
|
+
const { cmd, args } = config;
|
|
9896
|
+
console.log(dim(`Running: ${cmd} ${args.join(" ")}`));
|
|
9897
|
+
console.log("");
|
|
9898
|
+
const result = await exec`${cmd} ${args}`.stdout("inherit").stderr("inherit").noThrow().spawn();
|
|
9899
|
+
if (result.success) {
|
|
9900
|
+
console.log(green("\nUpdate complete!"));
|
|
9901
|
+
console.log(`The ${cyan("eser")} command has been updated to the latest version.`);
|
|
9902
|
+
} else {
|
|
9903
|
+
console.error(red("\nUpdate failed."));
|
|
9904
|
+
}
|
|
9905
|
+
runtime2.process.exit(result.code);
|
|
9906
|
+
};
|
|
9907
|
+
|
|
9908
|
+
// pkg/@eser/cli/commands/handlers/completions.ts
|
|
9909
|
+
var getInstallInstructions = (shell) => {
|
|
9910
|
+
const config = getShellConfig(shell, "eser");
|
|
9911
|
+
if (config.completionType === "file") {
|
|
9912
|
+
return `
|
|
9913
|
+
To install, run:
|
|
9914
|
+
|
|
9915
|
+
${dim(`eser system completions --shell fish > ${config.completionsFile}`)}
|
|
9916
|
+
`;
|
|
9917
|
+
}
|
|
9918
|
+
const evalLine = getCompletionEvalLine(shell, "eser");
|
|
9919
|
+
return `
|
|
9920
|
+
To install, add the following to your ${cyan(config.rcFile)}:
|
|
9921
|
+
|
|
9922
|
+
${dim(evalLine)}
|
|
9923
|
+
`;
|
|
9924
|
+
};
|
|
9925
|
+
var completionsHandler = (ctx) => {
|
|
9926
|
+
const { runtime: runtime2 } = mod_exports2;
|
|
9927
|
+
const shellFlag = ctx.flags["shell"];
|
|
9928
|
+
let shell;
|
|
9929
|
+
if (shellFlag !== void 0) {
|
|
9930
|
+
if (![
|
|
9931
|
+
"bash",
|
|
9932
|
+
"zsh",
|
|
9933
|
+
"fish"
|
|
9934
|
+
].includes(shellFlag)) {
|
|
9935
|
+
console.error(red(`Invalid shell: ${shellFlag}`));
|
|
9936
|
+
console.error("Supported shells: bash, zsh, fish");
|
|
9937
|
+
runtime2.process.exit(1);
|
|
9938
|
+
}
|
|
9939
|
+
shell = shellFlag;
|
|
9940
|
+
} else {
|
|
9941
|
+
shell = detectShell();
|
|
9942
|
+
}
|
|
9943
|
+
const rootCommand = ctx.root;
|
|
9944
|
+
const script = rootCommand.completions(shell);
|
|
9945
|
+
if (shellFlag === void 0) {
|
|
9946
|
+
console.log(`Generating ${cyan(shell)} completions...`);
|
|
9947
|
+
console.log(getInstallInstructions(shell));
|
|
9948
|
+
console.log(dim("--- Completion script ---\n"));
|
|
9949
|
+
}
|
|
9950
|
+
console.log(script);
|
|
9951
|
+
};
|
|
9952
|
+
|
|
9953
|
+
// pkg/@eser/cli/commands/system.ts
|
|
9954
|
+
var systemCommand = new Command("system").description("System management and setup tools").command(new Command("install").description("Install eser CLI globally").run(installHandler)).command(new Command("uninstall").description("Uninstall eser CLI globally").run(uninstallHandler)).command(new Command("update").description("Update eser CLI to the latest version").run(updateHandler)).command(new Command("completions").description("Generate shell completion scripts").flag({
|
|
9955
|
+
name: "shell",
|
|
9956
|
+
type: "string",
|
|
9957
|
+
description: "Shell type: bash, zsh, or fish"
|
|
9958
|
+
}).run(completionsHandler));
|
|
9959
|
+
|
|
8314
9960
|
// pkg/@eser/cli/package.json
|
|
8315
9961
|
var package_default = {
|
|
8316
9962
|
name: "@eser/cli",
|
|
8317
|
-
version: "4.0.
|
|
9963
|
+
version: "4.0.3",
|
|
8318
9964
|
type: "module",
|
|
8319
9965
|
exports: "./main.ts",
|
|
8320
9966
|
bin: {
|
|
@@ -8330,14 +9976,43 @@ var package_default = {
|
|
|
8330
9976
|
};
|
|
8331
9977
|
|
|
8332
9978
|
// pkg/@eser/cli/main.ts
|
|
9979
|
+
var wrapCommand = (cmd) => {
|
|
9980
|
+
return async (args, _flags) => {
|
|
9981
|
+
await cmd.parse(args);
|
|
9982
|
+
};
|
|
9983
|
+
};
|
|
9984
|
+
var wrapHandler = (handler, commandName) => {
|
|
9985
|
+
return async (_args, flags) => {
|
|
9986
|
+
const mockRoot = {
|
|
9987
|
+
name: "eser",
|
|
9988
|
+
completions: () => "",
|
|
9989
|
+
help: () => ""
|
|
9990
|
+
};
|
|
9991
|
+
await handler({
|
|
9992
|
+
args: [],
|
|
9993
|
+
flags,
|
|
9994
|
+
root: mockRoot,
|
|
9995
|
+
commandPath: [
|
|
9996
|
+
"eser",
|
|
9997
|
+
commandName
|
|
9998
|
+
]
|
|
9999
|
+
});
|
|
10000
|
+
};
|
|
10001
|
+
};
|
|
8333
10002
|
var commands = {
|
|
8334
|
-
codebase: codebaseCommand
|
|
10003
|
+
codebase: codebaseCommand,
|
|
10004
|
+
system: wrapCommand(systemCommand),
|
|
10005
|
+
install: wrapHandler(installHandler, "install"),
|
|
10006
|
+
update: wrapHandler(updateHandler, "update")
|
|
8335
10007
|
};
|
|
8336
10008
|
var showHelp2 = () => {
|
|
8337
10009
|
console.log("eser - Eser Ozvataf's command-line tooling to access things\n");
|
|
8338
10010
|
console.log("Usage: eser <command> [subcommand] [options]\n");
|
|
8339
10011
|
console.log("Commands:");
|
|
8340
10012
|
console.log(" codebase Codebase validation and management tools");
|
|
10013
|
+
console.log(" system System management and setup tools");
|
|
10014
|
+
console.log(" install Install eser CLI globally (alias for system install)");
|
|
10015
|
+
console.log(" update Update eser CLI to latest version (alias for system update)");
|
|
8341
10016
|
console.log("\nOptions:");
|
|
8342
10017
|
console.log(" -h, --help Show this help message");
|
|
8343
10018
|
console.log(" -v, --version Show version number");
|