@h3ravel/console 11.7.1 → 11.9.0

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/dist/index.js CHANGED
@@ -1,25 +1,31 @@
1
+ import { createRequire } from "node:module";
1
2
  import { FileSystem, Logger, TaskManager } from "@h3ravel/shared";
2
- import { Application, ConsoleCommand, ConsoleKernel, ServiceProvider } from "@h3ravel/core";
3
+ import { Application, ConsoleCommand, ConsoleKernel, ContainerResolver, ServiceProvider } from "@h3ravel/core";
3
4
  import { execa } from "execa";
4
5
  import preferredPM from "preferred-pm";
5
6
  import { glob, mkdir, readFile, rm, writeFile } from "node:fs/promises";
6
7
  import { Str } from "@h3ravel/support";
7
8
  import nodepath from "node:path";
8
- import { Option, program } from "commander";
9
+ import { Argument, Option, program } from "commander";
9
10
  import { existsSync } from "node:fs";
10
11
  import { fork } from "child_process";
11
12
  import { dirname, join, resolve } from "path";
12
13
  import { build } from "tsdown";
13
14
 
15
+ //#region rolldown:runtime
16
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
17
+
18
+ //#endregion
14
19
  //#region src/Commands/BuildCommand.ts
15
- var BuildCommand = class extends ConsoleCommand {
20
+ var BuildCommand = class BuildCommand extends ConsoleCommand {
16
21
  /**
17
22
  * The name and signature of the console command.
18
23
  *
19
24
  * @var string
20
25
  */
21
- signature = `build:
22
- {--m|minify=false : Minify your bundle output}
26
+ signature = `build
27
+ {--m|minify : Minify your bundle output}
28
+ {--d|dev : Build for dev but don't watch for changes}
23
29
  `;
24
30
  /**
25
31
  * The console command description.
@@ -35,11 +41,33 @@ var BuildCommand = class extends ConsoleCommand {
35
41
  }
36
42
  }
37
43
  async fire() {
38
- const outDir$1 = env("DIST_DIR", "dist");
39
- const pm = (await preferredPM(base_path()))?.name ?? "pnpm";
44
+ const outDir$1 = this.option("dev") ? ".h3ravel/serve" : env("DIST_DIR", "dist");
40
45
  const minify = this.option("minify");
46
+ const verbosity = this.getVerbosity();
47
+ const debug = verbosity > 0;
48
+ this.newLine();
49
+ await BuildCommand.build({
50
+ outDir: outDir$1,
51
+ minify,
52
+ verbosity,
53
+ debug,
54
+ mute: false
55
+ });
56
+ this.newLine();
57
+ }
58
+ /**
59
+ * build
60
+ */
61
+ static async build({ debug, minify, mute, verbosity, outDir: outDir$1 } = {
62
+ mute: false,
63
+ debug: false,
64
+ minify: false,
65
+ verbosity: 0,
66
+ outDir: "dist"
67
+ }) {
68
+ const pm = (await preferredPM(base_path()))?.name ?? "pnpm";
41
69
  const ENV_VARS = {
42
- EXTENDED_DEBUG: Number(this.option("verbose", 0)) > 0 ? "true" : "false",
70
+ EXTENDED_DEBUG: debug ? "true" : "false",
43
71
  CLI_BUILD: "true",
44
72
  NODE_ENV: "production",
45
73
  DIST_DIR: outDir$1,
@@ -49,12 +77,24 @@ var BuildCommand = class extends ConsoleCommand {
49
77
  "info",
50
78
  "warn",
51
79
  "error"
52
- ][Number(this.option("verbose", 0))]
80
+ ][verbosity]
53
81
  };
54
82
  const silent = ENV_VARS.LOG_LEVEL === "silent" ? "--silent" : null;
55
- Logger.log([["\n INFO ", "bgBlue"], [" Creating Production Bundle", "white"]], "");
56
- console.log("");
57
- await TaskManager.taskRunner(Logger.log([[" SUCCESS ", "bgGreen"], [" Production Bundle Created", "white"]], "", false), async () => {
83
+ if (mute) return await execa(pm, [
84
+ "tsdown",
85
+ silent,
86
+ "--config-loader",
87
+ "unconfig",
88
+ "-c",
89
+ "tsdown.default.config.ts"
90
+ ].filter((e) => e !== null), {
91
+ stdout: "inherit",
92
+ stderr: "inherit",
93
+ cwd: base_path(),
94
+ env: Object.assign({}, process.env, ENV_VARS)
95
+ });
96
+ const type = outDir$1 === "dist" ? "Production" : "Development";
97
+ return await TaskManager.advancedTaskRunner([[`Creating ${type} Bundle`, "STARTED"], [`${type} Bundle Created`, "COMPLETED"]], async () => {
58
98
  await execa(pm, [
59
99
  "tsdown",
60
100
  silent,
@@ -68,7 +108,6 @@ var BuildCommand = class extends ConsoleCommand {
68
108
  cwd: base_path(),
69
109
  env: Object.assign({}, process.env, ENV_VARS)
70
110
  });
71
- console.log("");
72
111
  });
73
112
  }
74
113
  };
@@ -77,6 +116,39 @@ var BuildCommand = class extends ConsoleCommand {
77
116
  //#region src/Commands/Command.ts
78
117
  var Command = class extends ConsoleCommand {};
79
118
 
119
+ //#endregion
120
+ //#region src/Commands/HelpCommand.ts
121
+ var HelpCommand = class extends Command {
122
+ /**
123
+ * The name and signature of the console command.
124
+ *
125
+ * @var string
126
+ */
127
+ signature = `help
128
+ {command_name=help : The command name}
129
+ {--format=txt : The output format}
130
+ `;
131
+ /**
132
+ * The console command description.
133
+ *
134
+ * @var string
135
+ */
136
+ description = "Display help for a command";
137
+ async handle() {
138
+ const cmd = this.argument("command_name");
139
+ if (!cmd) {
140
+ this.program.outputHelp();
141
+ return;
142
+ }
143
+ const target = this.program.commands.find((c) => c.name() === cmd);
144
+ if (!target) {
145
+ this.error(`ERROR: Unknown command: ${Logger.log(cmd, ["italic", "grey"], false)}.`);
146
+ process.exit(1);
147
+ }
148
+ target.outputHelp();
149
+ }
150
+ };
151
+
80
152
  //#endregion
81
153
  //#region src/logo.ts
82
154
  const logo = String.raw`
@@ -113,7 +185,7 @@ const altLogo = String.raw`
113
185
 
114
186
  //#endregion
115
187
  //#region src/Commands/ListCommand.ts
116
- var ListCommand = class extends Command {
188
+ var ListCommand = class ListCommand extends Command {
117
189
  /**
118
190
  * The name and signature of the console command.
119
191
  *
@@ -134,21 +206,11 @@ var ListCommand = class extends Command {
134
206
  }].concat(this.program.options).map((e) => {
135
207
  return Logger.describe(Logger.log(" " + [e.short, e.long].filter((e$1) => !!e$1).join(", "), "green", false), e.description, 25, false).join("");
136
208
  });
137
- const grouped = this.program.commands.map((e) => {
209
+ /** Get the program commands */
210
+ const commands = this.program.commands.map((e) => {
138
211
  return Logger.describe(Logger.log(" " + e.name(), "green", false), e.description(), 25, false).join("");
139
- }).reduce((acc, cmd) => {
140
- /** strip colors before checking prefix */
141
- const clean = cmd.replace(/\x1b\[\d+m/g, "");
142
- const prefix = clean.includes(":") ? clean.split(":")[0].trim() : "__root__";
143
- acc[prefix] ??= [];
144
- /** keep original with colors */
145
- acc[prefix].push(cmd);
146
- return acc;
147
- }, {});
148
- const list = Object.entries(grouped).map(([group, cmds]) => {
149
- const label = group === "__root__" ? "" : group;
150
- return [Logger.log(label, "yellow", false), cmds.join("\n")].join("\n");
151
212
  });
213
+ const list = ListCommand.groupItems(commands);
152
214
  /** Ootput the app version */
153
215
  Logger.log([["H3ravel Framework", "white"], [this.kernel.modulePackage.version, "green"]], " ");
154
216
  console.log("");
@@ -165,6 +227,29 @@ var ListCommand = class extends Command {
165
227
  Logger.log("Available Commands:", "yellow");
166
228
  console.log(list.join("\n\n").trim());
167
229
  }
230
+ /**
231
+ * Group Commands based on thier names
232
+ *
233
+ * @param commands
234
+ * @returns
235
+ */
236
+ static groupItems(commands, fmtd = false) {
237
+ const grouped = commands.reduce((acc, cmd) => {
238
+ /** strip colors before checking prefix */
239
+ const clean = cmd.replace(/\x1b\[\d+m/g, "");
240
+ const prefix = clean.includes(":") ? clean.split(":")[0].trim() : "__root__";
241
+ acc[prefix] ??= [];
242
+ /** keep original with colors */
243
+ acc[prefix].push(cmd);
244
+ return acc;
245
+ }, {});
246
+ return Object.entries(grouped).map(([group, cmds]) => {
247
+ const label = group === "__root__" ? "" : group;
248
+ let out = [Logger.log(label, "yellow", false), cmds.join("\n")].join("\n");
249
+ if (fmtd) out += "\n";
250
+ return out;
251
+ });
252
+ }
168
253
  };
169
254
 
170
255
  //#endregion
@@ -340,13 +425,28 @@ var Signature = class Signature {
340
425
  * Trim the string
341
426
  */
342
427
  description = description.trim();
343
- /**
344
- * Parse name modifiers (?, *, ?*)
345
- */
346
428
  let name = namePart;
429
+ let flags;
430
+ let choices = [];
347
431
  let required = /[^a-zA-Z0-9_|-]/.test(name);
348
432
  let multiple = false;
349
433
  let placeholder;
434
+ let defaultValue;
435
+ /**
436
+ * Parse the command name
437
+ */
438
+ if (name.includes("=")) {
439
+ const [rawName, rawDefault] = name.split("=");
440
+ name = rawName.trim();
441
+ const hold = rawName.trim().split("|");
442
+ const holder = (hold.at(1) ?? hold.at(0)).replace("--", "");
443
+ defaultValue = rawDefault.trim();
444
+ placeholder = defaultValue ? `[${holder}]` : `<${holder}>`;
445
+ required = false;
446
+ }
447
+ /**
448
+ * Parse name modifiers (?, *, ?*)
449
+ */
350
450
  if (name.endsWith("?*")) {
351
451
  required = false;
352
452
  multiple = true;
@@ -363,8 +463,6 @@ var Signature = class Signature {
363
463
  * Check if it's a flag option (starts with --)
364
464
  */
365
465
  const isFlag = name.startsWith("--");
366
- let flags;
367
- let defaultValue;
368
466
  if (isFlag) {
369
467
  /**
370
468
  * Parse flags and default values
@@ -386,8 +484,14 @@ var Signature = class Signature {
386
484
  } else flags.push(part);
387
485
  }
388
486
  }
487
+ const desc = description.match(/^([^:]+?)\s*:\s*\[?([\w\s,]+)\]?$/);
488
+ if (match) {
489
+ description = desc?.[1].trim() ?? description;
490
+ choices = desc?.[2].split(",").map((s) => s.trim()).filter(Boolean) ?? choices;
491
+ }
389
492
  options.push({
390
493
  name: isFlag ? flags[flags.length - 1] : name,
494
+ choices,
391
495
  required,
392
496
  multiple,
393
497
  description,
@@ -412,7 +516,7 @@ var Signature = class Signature {
412
516
  static parseSignature(signature, commandClass) {
413
517
  const lines = signature.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
414
518
  const isHidden = ["#", "^"].includes(lines[0][0]) || /:[#^]/.test(lines[0]);
415
- const baseCommand = lines[0].replace(/[^\w=:-]/g, "");
519
+ const baseCommand = lines[0].split("{")[0].trim().replace(/[^\w:-]/g, "");
416
520
  const description = commandClass.getDescription();
417
521
  const isNamespaceCommand = baseCommand.endsWith(":");
418
522
  /**
@@ -574,10 +678,11 @@ var Musket = class Musket {
574
678
  async build() {
575
679
  this.loadBaseCommands();
576
680
  await this.loadDiscoveredCommands();
577
- return this.initialize();
681
+ return await this.initialize();
578
682
  }
579
683
  loadBaseCommands() {
580
684
  [
685
+ new HelpCommand(this.app, this.kernel),
581
686
  new MakeCommand(this.app, this.kernel),
582
687
  new ListCommand(this.app, this.kernel),
583
688
  new PostinstallCommand(this.app, this.kernel),
@@ -604,32 +709,63 @@ var Musket = class Musket {
604
709
  addCommand(command) {
605
710
  this.commands.push(Signature.parseSignature(command.getSignature(), command));
606
711
  }
607
- initialize() {
712
+ async initialize() {
713
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
714
+ await this.rebuild("help");
715
+ Object.keys(__require.cache).forEach((key) => delete __require.cache[key]);
716
+ }
608
717
  /** Init the Musket Version */
609
718
  const cliVersion = Logger.parse([["Musket CLI:", "white"], [this.kernel.consolePackage.version, "green"]], " ", false);
610
719
  /** Init the App Version */
611
720
  const localVersion = Logger.parse([["H3ravel Framework:", "white"], [this.kernel.modulePackage.version, "green"]], " ", false);
612
721
  const additional = {
613
- quiet: ["-q, --quiet", "Do not output any message"],
722
+ quiet: ["-q, --quiet", "Do not output any message except errors and warnings"],
614
723
  silent: ["--silent", "Do not output any message"],
615
724
  verbose: ["-v, --verbose <number>", "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug"],
616
- lock: ["--lock", "Locked and loaded, do not ask any interactive question"]
725
+ noInteraction: ["-n, --no-interaction", "Do not ask any interactive question"]
617
726
  };
618
- /** Init Commander */
619
- program.name("musket").version(`${cliVersion}\n${localVersion}`).description(altLogo).addOption(new Option(additional.quiet[0], additional.quiet[1]).implies({ silent: true })).addOption(new Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new Option(additional.verbose[0], additional.verbose[1]).choices([
727
+ /**
728
+ * Init Commander
729
+ */
730
+ program.name("musket").version(`${cliVersion}\n${localVersion}`).description(altLogo).configureHelp({ showGlobalOptions: true }).addOption(new Option(additional.quiet[0], additional.quiet[1])).addOption(new Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new Option(additional.verbose[0], additional.verbose[1]).choices([
620
731
  "1",
621
732
  "2",
622
733
  "3"
623
- ])).addOption(new Option(additional.lock[0], additional.lock[1])).action(async () => {
734
+ ])).addOption(new Option(additional.noInteraction[0], additional.noInteraction[1])).action(async () => {
624
735
  const instance = new ListCommand(this.app, this.kernel);
625
736
  instance.setInput(program.opts(), program.args, program.registeredArguments, {}, program);
626
- instance.handle();
737
+ await this.handle(instance);
627
738
  });
628
- /** Create the init Command */
739
+ /**
740
+ * Format the help command display
741
+ */
742
+ program.configureHelp({
743
+ styleTitle: (str) => Logger.log(str, "yellow", false),
744
+ styleOptionTerm: (str) => Logger.log(str, "green", false),
745
+ styleArgumentTerm: (str) => Logger.log(str, "green", false),
746
+ styleSubcommandTerm: (str) => Logger.log(str, "green", false),
747
+ formatItemList(heading, items) {
748
+ if (items.length < 1) return [];
749
+ if (!heading.includes("Commands:")) return items;
750
+ const c = (str) => str.replace(/[^A-Za-z0-9-,]/g, "").replace("32m", "");
751
+ let flags = items.filter((e) => c(e).startsWith("--") || c(e).includes(",--"));
752
+ if (flags.length > 0) flags = [Logger.log("\n" + heading + "\n", "yellow", false)].concat(flags);
753
+ const list = items.filter((e) => !c(e).startsWith("--") && !c(e).includes(",--"));
754
+ if (list.length < 1) return flags;
755
+ const _heading = c(heading).includes("Arguments") ? heading : "Available Commands:";
756
+ return flags.concat(Logger.log(`\n${_heading}`, "yellow", false), ListCommand.groupItems(list, true));
757
+ },
758
+ showGlobalOptions: true
759
+ });
760
+ /**
761
+ * Create the init Command
762
+ */
629
763
  program.command("init").description("Initialize H3ravel.").action(async () => {
630
764
  Logger.success("Initialized: H3ravel has been initialized!");
631
765
  });
632
- /** Loop through all the available commands */
766
+ /**
767
+ * Loop through all the available commands
768
+ */
633
769
  for (let i = 0; i < this.commands.length; i++) {
634
770
  const command = this.commands[i];
635
771
  const instance = command.commandClass;
@@ -637,13 +773,9 @@ var Musket = class Musket {
637
773
  /**
638
774
  * Initialize the base command
639
775
  */
640
- const cmd = command.isHidden ? program : program.command(command.baseCommand).description(command.description ?? "").addOption(new Option(additional.quiet[0], additional.quiet[1]).implies({ silent: true })).addOption(new Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new Option(additional.verbose[0], additional.verbose[1]).choices([
641
- "1",
642
- "2",
643
- "3"
644
- ])).addOption(new Option(additional.lock[0], additional.lock[1])).action(async () => {
776
+ const cmd = command.isHidden ? program : program.command(command.baseCommand).description(command.description ?? "").action(async () => {
645
777
  instance.setInput(cmd.opts(), cmd.args, cmd.registeredArguments, command, program);
646
- await instance.handle();
778
+ await this.handle(instance);
647
779
  });
648
780
  /**
649
781
  * Add options to the base command if it has any
@@ -655,13 +787,9 @@ var Musket = class Musket {
655
787
  * Initialize the sub commands
656
788
  */
657
789
  command.subCommands.filter((v, i$1, a) => !v.shared && a.findIndex((t) => t.name === v.name) === i$1).forEach((sub) => {
658
- const cmd$1 = program.command(`${command.baseCommand}:${sub.name}`).description(sub.description || "").addOption(new Option(additional.quiet[0], additional.quiet[1]).implies({ silent: true })).addOption(new Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new Option(additional.verbose[0], additional.verbose[1]).choices([
659
- "1",
660
- "2",
661
- "3"
662
- ])).addOption(new Option(additional.lock[0], additional.lock[1])).action(async () => {
790
+ const cmd$1 = program.command(`${command.baseCommand}:${sub.name}`).description(sub.description || "").action(async () => {
663
791
  instance.setInput(cmd$1.opts(), cmd$1.args, cmd$1.registeredArguments, sub, program);
664
- await instance.handle();
792
+ await this.handle(instance);
665
793
  });
666
794
  /**
667
795
  * Add the shared arguments here
@@ -692,20 +820,23 @@ var Musket = class Musket {
692
820
  });
693
821
  cmd.action(async () => {
694
822
  instance.setInput(cmd.opts(), cmd.args, cmd.registeredArguments, command, program);
695
- await instance.handle();
823
+ await this.handle(instance);
696
824
  });
697
825
  }
698
826
  }
699
827
  /** Rebuild the app on every command except fire so we wont need TS */
700
828
  program.hook("preAction", async (_, cmd) => {
701
- if (cmd.name() !== "fire") await build({
702
- ...TsdownConfig_default,
703
- watch: false,
704
- plugins: []
705
- });
829
+ this.rebuild(cmd.name());
706
830
  });
707
831
  return program;
708
832
  }
833
+ async rebuild(name) {
834
+ if (name !== "fire" && name !== "build") await build({
835
+ ...TsdownConfig_default,
836
+ watch: false,
837
+ plugins: []
838
+ });
839
+ }
709
840
  makeOption(opt, cmd, parse, parent) {
710
841
  const description = opt.description?.replace(/\[(\w+)\]/g, (_, k) => parent?.[k] ?? `[${k}]`) ?? "";
711
842
  const type = opt.name.replaceAll("-", "");
@@ -713,17 +844,38 @@ var Musket = class Musket {
713
844
  let flags = opt.flags?.map((f) => f.length === 1 ? `-${f}` : `--${f.replace(/^-+/, "")}`).join(", ") ?? void 0;
714
845
  if (opt.required && !opt.placeholder) flags += ` <${type}>`;
715
846
  else if (opt.placeholder) flags += " " + opt.placeholder;
716
- cmd.option(flags || "", description, opt.defaultValue);
847
+ let optn = new Option(flags || "", description).default(opt.defaultValue);
848
+ if (opt.choices && opt.choices.length) optn = optn.choices(opt.choices ?? []);
849
+ cmd.addOption(optn);
717
850
  } else {
718
851
  let flags = opt.flags?.join(", ") ?? "";
719
852
  if (opt.required && !opt.placeholder) flags += ` <${type}>`;
720
853
  else if (opt.placeholder) flags += " " + opt.placeholder;
721
- cmd.option(flags, description, opt.defaultValue);
854
+ let optn = new Option(flags, description).default(opt.defaultValue);
855
+ if (opt.choices && opt.choices.length) optn = optn.choices(opt.choices ?? []);
856
+ cmd.addOption(optn);
722
857
  }
723
- else cmd.argument(opt.required ? `<${opt.name}>` : `[${opt.name}]`, description, opt.defaultValue);
858
+ else {
859
+ let name = opt.placeholder;
860
+ if (!name) name = opt.required ? `<${opt.name}>` : `[${opt.name}]`;
861
+ let arg = new Argument(name, description);
862
+ if (opt.choices && opt.choices.length) arg = arg.choices(opt.choices ?? []);
863
+ if (opt.defaultValue) arg.default(opt.defaultValue);
864
+ cmd.addArgument(arg);
865
+ }
866
+ }
867
+ async handle(cmd) {
868
+ await new ContainerResolver(this.app).resolveMethodParams(cmd, "handle");
724
869
  }
725
870
  static async parse(kernel) {
726
- return (await new Musket(kernel.app, kernel).build()).parseAsync();
871
+ return (await new Musket(kernel.app, kernel).build()).exitOverride(() => {
872
+ Logger.log("Unknown command or argument.", "white");
873
+ Logger.log([
874
+ ["Run", "white"],
875
+ ["`musket --help`", ["grey", "italic"]],
876
+ ["to see available commands.", "white"]
877
+ ], " ");
878
+ }).parseAsync(process.argv).catch((e) => e);
727
879
  }
728
880
  };
729
881
 
@@ -791,5 +943,5 @@ var ConsoleServiceProvider = class extends ServiceProvider {
791
943
  };
792
944
 
793
945
  //#endregion
794
- export { BuildCommand, Command, ConsoleServiceProvider, Kernel, ListCommand, MakeCommand, Musket, PostinstallCommand, Signature, TsDownConfig, altLogo, logo };
946
+ export { BuildCommand, Command, ConsoleServiceProvider, HelpCommand, Kernel, ListCommand, MakeCommand, Musket, PostinstallCommand, Signature, TsDownConfig, altLogo, logo };
795
947
  //# sourceMappingURL=index.js.map