eser 4.0.2 → 4.0.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.
Files changed (2) hide show
  1. package/eser.js +1700 -19
  2. package/package.json +1 -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 exec = createWorkerdExec();
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: options?.stdout ?? "piped",
2274
- stderr: options?.stderr ?? "piped",
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 exec = createDenoExec();
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(Buffer.concat(stdoutChunks));
2586
- const stderr = new Uint8Array(Buffer.concat(stderrChunks));
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(Buffer.concat(stdoutChunks)),
2661
- stderr: new Uint8Array(Buffer.concat(stderrChunks))
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 exec = createNodeExec();
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 exec = createBunExec();
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,1419 @@ 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
+ "-r",
9735
+ "-g",
9736
+ "-A",
9737
+ "--name",
9738
+ "eser",
9739
+ "jsr:@eser/cli"
9740
+ ]
9741
+ },
9742
+ node: {
9743
+ cmd: "npm",
9744
+ args: [
9745
+ "install",
9746
+ "-g",
9747
+ "-f",
9748
+ "eser"
9749
+ ]
9750
+ },
9751
+ bun: {
9752
+ cmd: "bun",
9753
+ args: [
9754
+ "install",
9755
+ "-g",
9756
+ "-f",
9757
+ "eser"
9758
+ ]
9759
+ }
9760
+ };
9761
+ var installHandler = async (_ctx) => {
9762
+ const { runtime: runtime2 } = mod_exports2;
9763
+ const runtimeName = detectRuntime();
9764
+ console.log(`Detected runtime: ${cyan(runtimeName)}`);
9765
+ const config = INSTALL_CONFIGS[runtimeName];
9766
+ if (config === void 0) {
9767
+ console.error(red(`
9768
+ Unsupported runtime: ${runtimeName}`));
9769
+ console.error("Global installation is only supported for Deno, Node.js, and Bun.");
9770
+ runtime2.process.exit(1);
9771
+ return;
9772
+ }
9773
+ const { cmd, args } = config;
9774
+ console.log(dim(`Running: ${cmd} ${args.join(" ")}`));
9775
+ console.log("");
9776
+ const result = await exec`${cmd} ${args}`.stdout("inherit").stderr("inherit").noThrow().spawn();
9777
+ if (result.success) {
9778
+ console.log(green("\nInstallation complete!"));
9779
+ console.log(`You can now use ${cyan("eser")} from anywhere in your terminal.`);
9780
+ const shell = detectShell();
9781
+ const alreadyHasCompletions = await hasCompletions(shell);
9782
+ if (!alreadyHasCompletions) {
9783
+ console.log(`
9784
+ Setting up ${cyan(shell)} completions...`);
9785
+ await addCompletions(shell);
9786
+ const shellConfig = getShellConfig(shell);
9787
+ if (shellConfig.completionType === "eval") {
9788
+ console.log(dim(` Restart your shell or run 'source ${shellConfig.rcFile}' to enable completions.`));
9789
+ }
9790
+ }
9791
+ } else {
9792
+ console.error(red("\nInstallation failed."));
9793
+ }
9794
+ runtime2.process.exit(result.code);
9795
+ };
9796
+
9797
+ // pkg/@eser/cli/commands/handlers/uninstall.ts
9798
+ var UNINSTALL_CONFIGS = {
9799
+ deno: {
9800
+ cmd: "deno",
9801
+ args: [
9802
+ "uninstall",
9803
+ "-g",
9804
+ "eser"
9805
+ ]
9806
+ },
9807
+ node: {
9808
+ cmd: "npm",
9809
+ args: [
9810
+ "uninstall",
9811
+ "-g",
9812
+ "eser"
9813
+ ]
9814
+ },
9815
+ bun: {
9816
+ cmd: "bun",
9817
+ args: [
9818
+ "remove",
9819
+ "-g",
9820
+ "eser"
9821
+ ]
9822
+ }
9823
+ };
9824
+ var uninstallHandler = async (_ctx) => {
9825
+ const { runtime: runtime2 } = mod_exports2;
9826
+ const runtimeName = detectRuntime();
9827
+ console.log(`Detected runtime: ${cyan(runtimeName)}`);
9828
+ const config = UNINSTALL_CONFIGS[runtimeName];
9829
+ if (config === void 0) {
9830
+ console.error(red(`
9831
+ Unsupported runtime: ${runtimeName}`));
9832
+ console.error("Global uninstallation is only supported for Deno, Node.js, and Bun.");
9833
+ runtime2.process.exit(1);
9834
+ return;
9835
+ }
9836
+ const { cmd, args } = config;
9837
+ const shell = detectShell();
9838
+ console.log(`
9839
+ Removing ${cyan(shell)} completions...`);
9840
+ await removeCompletions(shell);
9841
+ console.log(dim(`
9842
+ Running: ${cmd} ${args.join(" ")}`));
9843
+ console.log("");
9844
+ const result = await exec`${cmd} ${args}`.stdout("inherit").stderr("inherit").noThrow().spawn();
9845
+ if (result.success) {
9846
+ console.log(green("\nUninstallation complete!"));
9847
+ console.log(`The ${cyan("eser")} command has been removed from your system.`);
9848
+ } else {
9849
+ console.error(red("\nUninstallation failed."));
9850
+ }
9851
+ runtime2.process.exit(result.code);
9852
+ };
9853
+
9854
+ // pkg/@eser/cli/commands/handlers/update.ts
9855
+ var UPDATE_CONFIGS = {
9856
+ deno: {
9857
+ cmd: "deno",
9858
+ // Deno doesn't have an update command, so we reinstall with -r (reload) and -f (force)
9859
+ args: [
9860
+ "install",
9861
+ "-r",
9862
+ "-g",
9863
+ "-A",
9864
+ "-f",
9865
+ "--name",
9866
+ "eser",
9867
+ "jsr:@eser/cli"
9868
+ ]
9869
+ },
9870
+ node: {
9871
+ cmd: "npm",
9872
+ args: [
9873
+ "update",
9874
+ "-g",
9875
+ "-f",
9876
+ "eser"
9877
+ ]
9878
+ },
9879
+ bun: {
9880
+ cmd: "bun",
9881
+ args: [
9882
+ "update",
9883
+ "-g",
9884
+ "-f",
9885
+ "eser"
9886
+ ]
9887
+ }
9888
+ };
9889
+ var updateHandler = async (_ctx) => {
9890
+ const { runtime: runtime2 } = mod_exports2;
9891
+ const runtimeName = detectRuntime();
9892
+ console.log(`Detected runtime: ${cyan(runtimeName)}`);
9893
+ const config = UPDATE_CONFIGS[runtimeName];
9894
+ if (config === void 0) {
9895
+ console.error(red(`
9896
+ Unsupported runtime: ${runtimeName}`));
9897
+ console.error("Global update is only supported for Deno, Node.js, and Bun.");
9898
+ runtime2.process.exit(1);
9899
+ return;
9900
+ }
9901
+ const { cmd, args } = config;
9902
+ console.log(dim(`Running: ${cmd} ${args.join(" ")}`));
9903
+ console.log("");
9904
+ const result = await exec`${cmd} ${args}`.stdout("inherit").stderr("inherit").noThrow().spawn();
9905
+ if (result.success) {
9906
+ console.log(green("\nUpdate complete!"));
9907
+ console.log(`The ${cyan("eser")} command has been updated to the latest version.`);
9908
+ } else {
9909
+ console.error(red("\nUpdate failed."));
9910
+ }
9911
+ runtime2.process.exit(result.code);
9912
+ };
9913
+
9914
+ // pkg/@eser/cli/commands/handlers/completions.ts
9915
+ var getInstallInstructions = (shell) => {
9916
+ const config = getShellConfig(shell, "eser");
9917
+ if (config.completionType === "file") {
9918
+ return `
9919
+ To install, run:
9920
+
9921
+ ${dim(`eser system completions --shell fish > ${config.completionsFile}`)}
9922
+ `;
9923
+ }
9924
+ const evalLine = getCompletionEvalLine(shell, "eser");
9925
+ return `
9926
+ To install, add the following to your ${cyan(config.rcFile)}:
9927
+
9928
+ ${dim(evalLine)}
9929
+ `;
9930
+ };
9931
+ var completionsHandler = (ctx) => {
9932
+ const { runtime: runtime2 } = mod_exports2;
9933
+ const shellFlag = ctx.flags["shell"];
9934
+ let shell;
9935
+ if (shellFlag !== void 0) {
9936
+ if (![
9937
+ "bash",
9938
+ "zsh",
9939
+ "fish"
9940
+ ].includes(shellFlag)) {
9941
+ console.error(red(`Invalid shell: ${shellFlag}`));
9942
+ console.error("Supported shells: bash, zsh, fish");
9943
+ runtime2.process.exit(1);
9944
+ }
9945
+ shell = shellFlag;
9946
+ } else {
9947
+ shell = detectShell();
9948
+ }
9949
+ const rootCommand = ctx.root;
9950
+ const script = rootCommand.completions(shell);
9951
+ if (shellFlag === void 0) {
9952
+ console.log(`Generating ${cyan(shell)} completions...`);
9953
+ console.log(getInstallInstructions(shell));
9954
+ console.log(dim("--- Completion script ---\n"));
9955
+ }
9956
+ console.log(script);
9957
+ };
9958
+
9959
+ // pkg/@eser/cli/commands/system.ts
9960
+ 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({
9961
+ name: "shell",
9962
+ type: "string",
9963
+ description: "Shell type: bash, zsh, or fish"
9964
+ }).run(completionsHandler));
9965
+
8314
9966
  // pkg/@eser/cli/package.json
8315
9967
  var package_default = {
8316
9968
  name: "@eser/cli",
8317
- version: "4.0.2",
9969
+ version: "4.0.4",
8318
9970
  type: "module",
8319
9971
  exports: "./main.ts",
8320
9972
  bin: {
@@ -8330,14 +9982,43 @@ var package_default = {
8330
9982
  };
8331
9983
 
8332
9984
  // pkg/@eser/cli/main.ts
9985
+ var wrapCommand = (cmd) => {
9986
+ return async (args, _flags) => {
9987
+ await cmd.parse(args);
9988
+ };
9989
+ };
9990
+ var wrapHandler = (handler, commandName) => {
9991
+ return async (_args, flags) => {
9992
+ const mockRoot = {
9993
+ name: "eser",
9994
+ completions: () => "",
9995
+ help: () => ""
9996
+ };
9997
+ await handler({
9998
+ args: [],
9999
+ flags,
10000
+ root: mockRoot,
10001
+ commandPath: [
10002
+ "eser",
10003
+ commandName
10004
+ ]
10005
+ });
10006
+ };
10007
+ };
8333
10008
  var commands = {
8334
- codebase: codebaseCommand
10009
+ codebase: codebaseCommand,
10010
+ system: wrapCommand(systemCommand),
10011
+ install: wrapHandler(installHandler, "install"),
10012
+ update: wrapHandler(updateHandler, "update")
8335
10013
  };
8336
10014
  var showHelp2 = () => {
8337
10015
  console.log("eser - Eser Ozvataf's command-line tooling to access things\n");
8338
10016
  console.log("Usage: eser <command> [subcommand] [options]\n");
8339
10017
  console.log("Commands:");
8340
10018
  console.log(" codebase Codebase validation and management tools");
10019
+ console.log(" system System management and setup tools");
10020
+ console.log(" install Install eser CLI globally (alias for system install)");
10021
+ console.log(" update Update eser CLI to latest version (alias for system update)");
8341
10022
  console.log("\nOptions:");
8342
10023
  console.log(" -h, --help Show this help message");
8343
10024
  console.log(" -v, --version Show version number");