@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.cjs CHANGED
@@ -47,14 +47,15 @@ let tsdown = require("tsdown");
47
47
  tsdown = __toESM(tsdown);
48
48
 
49
49
  //#region src/Commands/BuildCommand.ts
50
- var BuildCommand = class extends __h3ravel_core.ConsoleCommand {
50
+ var BuildCommand = class BuildCommand extends __h3ravel_core.ConsoleCommand {
51
51
  /**
52
52
  * The name and signature of the console command.
53
53
  *
54
54
  * @var string
55
55
  */
56
- signature = `build:
57
- {--m|minify=false : Minify your bundle output}
56
+ signature = `build
57
+ {--m|minify : Minify your bundle output}
58
+ {--d|dev : Build for dev but don't watch for changes}
58
59
  `;
59
60
  /**
60
61
  * The console command description.
@@ -70,11 +71,33 @@ var BuildCommand = class extends __h3ravel_core.ConsoleCommand {
70
71
  }
71
72
  }
72
73
  async fire() {
73
- const outDir$1 = env("DIST_DIR", "dist");
74
- const pm = (await (0, preferred_pm.default)(base_path()))?.name ?? "pnpm";
74
+ const outDir$1 = this.option("dev") ? ".h3ravel/serve" : env("DIST_DIR", "dist");
75
75
  const minify = this.option("minify");
76
+ const verbosity = this.getVerbosity();
77
+ const debug = verbosity > 0;
78
+ this.newLine();
79
+ await BuildCommand.build({
80
+ outDir: outDir$1,
81
+ minify,
82
+ verbosity,
83
+ debug,
84
+ mute: false
85
+ });
86
+ this.newLine();
87
+ }
88
+ /**
89
+ * build
90
+ */
91
+ static async build({ debug, minify, mute, verbosity, outDir: outDir$1 } = {
92
+ mute: false,
93
+ debug: false,
94
+ minify: false,
95
+ verbosity: 0,
96
+ outDir: "dist"
97
+ }) {
98
+ const pm = (await (0, preferred_pm.default)(base_path()))?.name ?? "pnpm";
76
99
  const ENV_VARS = {
77
- EXTENDED_DEBUG: Number(this.option("verbose", 0)) > 0 ? "true" : "false",
100
+ EXTENDED_DEBUG: debug ? "true" : "false",
78
101
  CLI_BUILD: "true",
79
102
  NODE_ENV: "production",
80
103
  DIST_DIR: outDir$1,
@@ -84,12 +107,24 @@ var BuildCommand = class extends __h3ravel_core.ConsoleCommand {
84
107
  "info",
85
108
  "warn",
86
109
  "error"
87
- ][Number(this.option("verbose", 0))]
110
+ ][verbosity]
88
111
  };
89
112
  const silent = ENV_VARS.LOG_LEVEL === "silent" ? "--silent" : null;
90
- __h3ravel_shared.Logger.log([["\n INFO ", "bgBlue"], [" Creating Production Bundle", "white"]], "");
91
- console.log("");
92
- await __h3ravel_shared.TaskManager.taskRunner(__h3ravel_shared.Logger.log([[" SUCCESS ", "bgGreen"], [" Production Bundle Created", "white"]], "", false), async () => {
113
+ if (mute) return await (0, execa.execa)(pm, [
114
+ "tsdown",
115
+ silent,
116
+ "--config-loader",
117
+ "unconfig",
118
+ "-c",
119
+ "tsdown.default.config.ts"
120
+ ].filter((e) => e !== null), {
121
+ stdout: "inherit",
122
+ stderr: "inherit",
123
+ cwd: base_path(),
124
+ env: Object.assign({}, process.env, ENV_VARS)
125
+ });
126
+ const type = outDir$1 === "dist" ? "Production" : "Development";
127
+ return await __h3ravel_shared.TaskManager.advancedTaskRunner([[`Creating ${type} Bundle`, "STARTED"], [`${type} Bundle Created`, "COMPLETED"]], async () => {
93
128
  await (0, execa.execa)(pm, [
94
129
  "tsdown",
95
130
  silent,
@@ -103,7 +138,6 @@ var BuildCommand = class extends __h3ravel_core.ConsoleCommand {
103
138
  cwd: base_path(),
104
139
  env: Object.assign({}, process.env, ENV_VARS)
105
140
  });
106
- console.log("");
107
141
  });
108
142
  }
109
143
  };
@@ -112,6 +146,39 @@ var BuildCommand = class extends __h3ravel_core.ConsoleCommand {
112
146
  //#region src/Commands/Command.ts
113
147
  var Command = class extends __h3ravel_core.ConsoleCommand {};
114
148
 
149
+ //#endregion
150
+ //#region src/Commands/HelpCommand.ts
151
+ var HelpCommand = class extends Command {
152
+ /**
153
+ * The name and signature of the console command.
154
+ *
155
+ * @var string
156
+ */
157
+ signature = `help
158
+ {command_name=help : The command name}
159
+ {--format=txt : The output format}
160
+ `;
161
+ /**
162
+ * The console command description.
163
+ *
164
+ * @var string
165
+ */
166
+ description = "Display help for a command";
167
+ async handle() {
168
+ const cmd = this.argument("command_name");
169
+ if (!cmd) {
170
+ this.program.outputHelp();
171
+ return;
172
+ }
173
+ const target = this.program.commands.find((c) => c.name() === cmd);
174
+ if (!target) {
175
+ this.error(`ERROR: Unknown command: ${__h3ravel_shared.Logger.log(cmd, ["italic", "grey"], false)}.`);
176
+ process.exit(1);
177
+ }
178
+ target.outputHelp();
179
+ }
180
+ };
181
+
115
182
  //#endregion
116
183
  //#region src/logo.ts
117
184
  const logo = String.raw`
@@ -148,7 +215,7 @@ const altLogo = String.raw`
148
215
 
149
216
  //#endregion
150
217
  //#region src/Commands/ListCommand.ts
151
- var ListCommand = class extends Command {
218
+ var ListCommand = class ListCommand extends Command {
152
219
  /**
153
220
  * The name and signature of the console command.
154
221
  *
@@ -169,21 +236,11 @@ var ListCommand = class extends Command {
169
236
  }].concat(this.program.options).map((e) => {
170
237
  return __h3ravel_shared.Logger.describe(__h3ravel_shared.Logger.log(" " + [e.short, e.long].filter((e$1) => !!e$1).join(", "), "green", false), e.description, 25, false).join("");
171
238
  });
172
- const grouped = this.program.commands.map((e) => {
239
+ /** Get the program commands */
240
+ const commands = this.program.commands.map((e) => {
173
241
  return __h3ravel_shared.Logger.describe(__h3ravel_shared.Logger.log(" " + e.name(), "green", false), e.description(), 25, false).join("");
174
- }).reduce((acc, cmd) => {
175
- /** strip colors before checking prefix */
176
- const clean = cmd.replace(/\x1b\[\d+m/g, "");
177
- const prefix = clean.includes(":") ? clean.split(":")[0].trim() : "__root__";
178
- acc[prefix] ??= [];
179
- /** keep original with colors */
180
- acc[prefix].push(cmd);
181
- return acc;
182
- }, {});
183
- const list = Object.entries(grouped).map(([group, cmds]) => {
184
- const label = group === "__root__" ? "" : group;
185
- return [__h3ravel_shared.Logger.log(label, "yellow", false), cmds.join("\n")].join("\n");
186
242
  });
243
+ const list = ListCommand.groupItems(commands);
187
244
  /** Ootput the app version */
188
245
  __h3ravel_shared.Logger.log([["H3ravel Framework", "white"], [this.kernel.modulePackage.version, "green"]], " ");
189
246
  console.log("");
@@ -200,6 +257,29 @@ var ListCommand = class extends Command {
200
257
  __h3ravel_shared.Logger.log("Available Commands:", "yellow");
201
258
  console.log(list.join("\n\n").trim());
202
259
  }
260
+ /**
261
+ * Group Commands based on thier names
262
+ *
263
+ * @param commands
264
+ * @returns
265
+ */
266
+ static groupItems(commands, fmtd = false) {
267
+ const grouped = commands.reduce((acc, cmd) => {
268
+ /** strip colors before checking prefix */
269
+ const clean = cmd.replace(/\x1b\[\d+m/g, "");
270
+ const prefix = clean.includes(":") ? clean.split(":")[0].trim() : "__root__";
271
+ acc[prefix] ??= [];
272
+ /** keep original with colors */
273
+ acc[prefix].push(cmd);
274
+ return acc;
275
+ }, {});
276
+ return Object.entries(grouped).map(([group, cmds]) => {
277
+ const label = group === "__root__" ? "" : group;
278
+ let out = [__h3ravel_shared.Logger.log(label, "yellow", false), cmds.join("\n")].join("\n");
279
+ if (fmtd) out += "\n";
280
+ return out;
281
+ });
282
+ }
203
283
  };
204
284
 
205
285
  //#endregion
@@ -375,13 +455,28 @@ var Signature = class Signature {
375
455
  * Trim the string
376
456
  */
377
457
  description = description.trim();
378
- /**
379
- * Parse name modifiers (?, *, ?*)
380
- */
381
458
  let name = namePart;
459
+ let flags;
460
+ let choices = [];
382
461
  let required = /[^a-zA-Z0-9_|-]/.test(name);
383
462
  let multiple = false;
384
463
  let placeholder;
464
+ let defaultValue;
465
+ /**
466
+ * Parse the command name
467
+ */
468
+ if (name.includes("=")) {
469
+ const [rawName, rawDefault] = name.split("=");
470
+ name = rawName.trim();
471
+ const hold = rawName.trim().split("|");
472
+ const holder = (hold.at(1) ?? hold.at(0)).replace("--", "");
473
+ defaultValue = rawDefault.trim();
474
+ placeholder = defaultValue ? `[${holder}]` : `<${holder}>`;
475
+ required = false;
476
+ }
477
+ /**
478
+ * Parse name modifiers (?, *, ?*)
479
+ */
385
480
  if (name.endsWith("?*")) {
386
481
  required = false;
387
482
  multiple = true;
@@ -398,8 +493,6 @@ var Signature = class Signature {
398
493
  * Check if it's a flag option (starts with --)
399
494
  */
400
495
  const isFlag = name.startsWith("--");
401
- let flags;
402
- let defaultValue;
403
496
  if (isFlag) {
404
497
  /**
405
498
  * Parse flags and default values
@@ -421,8 +514,14 @@ var Signature = class Signature {
421
514
  } else flags.push(part);
422
515
  }
423
516
  }
517
+ const desc = description.match(/^([^:]+?)\s*:\s*\[?([\w\s,]+)\]?$/);
518
+ if (match) {
519
+ description = desc?.[1].trim() ?? description;
520
+ choices = desc?.[2].split(",").map((s) => s.trim()).filter(Boolean) ?? choices;
521
+ }
424
522
  options.push({
425
523
  name: isFlag ? flags[flags.length - 1] : name,
524
+ choices,
426
525
  required,
427
526
  multiple,
428
527
  description,
@@ -447,7 +546,7 @@ var Signature = class Signature {
447
546
  static parseSignature(signature, commandClass) {
448
547
  const lines = signature.split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
449
548
  const isHidden = ["#", "^"].includes(lines[0][0]) || /:[#^]/.test(lines[0]);
450
- const baseCommand = lines[0].replace(/[^\w=:-]/g, "");
549
+ const baseCommand = lines[0].split("{")[0].trim().replace(/[^\w:-]/g, "");
451
550
  const description = commandClass.getDescription();
452
551
  const isNamespaceCommand = baseCommand.endsWith(":");
453
552
  /**
@@ -609,10 +708,11 @@ var Musket = class Musket {
609
708
  async build() {
610
709
  this.loadBaseCommands();
611
710
  await this.loadDiscoveredCommands();
612
- return this.initialize();
711
+ return await this.initialize();
613
712
  }
614
713
  loadBaseCommands() {
615
714
  [
715
+ new HelpCommand(this.app, this.kernel),
616
716
  new MakeCommand(this.app, this.kernel),
617
717
  new ListCommand(this.app, this.kernel),
618
718
  new PostinstallCommand(this.app, this.kernel),
@@ -639,32 +739,63 @@ var Musket = class Musket {
639
739
  addCommand(command) {
640
740
  this.commands.push(Signature.parseSignature(command.getSignature(), command));
641
741
  }
642
- initialize() {
742
+ async initialize() {
743
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
744
+ await this.rebuild("help");
745
+ Object.keys(require.cache).forEach((key) => delete require.cache[key]);
746
+ }
643
747
  /** Init the Musket Version */
644
748
  const cliVersion = __h3ravel_shared.Logger.parse([["Musket CLI:", "white"], [this.kernel.consolePackage.version, "green"]], " ", false);
645
749
  /** Init the App Version */
646
750
  const localVersion = __h3ravel_shared.Logger.parse([["H3ravel Framework:", "white"], [this.kernel.modulePackage.version, "green"]], " ", false);
647
751
  const additional = {
648
- quiet: ["-q, --quiet", "Do not output any message"],
752
+ quiet: ["-q, --quiet", "Do not output any message except errors and warnings"],
649
753
  silent: ["--silent", "Do not output any message"],
650
754
  verbose: ["-v, --verbose <number>", "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug"],
651
- lock: ["--lock", "Locked and loaded, do not ask any interactive question"]
755
+ noInteraction: ["-n, --no-interaction", "Do not ask any interactive question"]
652
756
  };
653
- /** Init Commander */
654
- commander.program.name("musket").version(`${cliVersion}\n${localVersion}`).description(altLogo).addOption(new commander.Option(additional.quiet[0], additional.quiet[1]).implies({ silent: true })).addOption(new commander.Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new commander.Option(additional.verbose[0], additional.verbose[1]).choices([
757
+ /**
758
+ * Init Commander
759
+ */
760
+ commander.program.name("musket").version(`${cliVersion}\n${localVersion}`).description(altLogo).configureHelp({ showGlobalOptions: true }).addOption(new commander.Option(additional.quiet[0], additional.quiet[1])).addOption(new commander.Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new commander.Option(additional.verbose[0], additional.verbose[1]).choices([
655
761
  "1",
656
762
  "2",
657
763
  "3"
658
- ])).addOption(new commander.Option(additional.lock[0], additional.lock[1])).action(async () => {
764
+ ])).addOption(new commander.Option(additional.noInteraction[0], additional.noInteraction[1])).action(async () => {
659
765
  const instance = new ListCommand(this.app, this.kernel);
660
766
  instance.setInput(commander.program.opts(), commander.program.args, commander.program.registeredArguments, {}, commander.program);
661
- instance.handle();
767
+ await this.handle(instance);
662
768
  });
663
- /** Create the init Command */
769
+ /**
770
+ * Format the help command display
771
+ */
772
+ commander.program.configureHelp({
773
+ styleTitle: (str) => __h3ravel_shared.Logger.log(str, "yellow", false),
774
+ styleOptionTerm: (str) => __h3ravel_shared.Logger.log(str, "green", false),
775
+ styleArgumentTerm: (str) => __h3ravel_shared.Logger.log(str, "green", false),
776
+ styleSubcommandTerm: (str) => __h3ravel_shared.Logger.log(str, "green", false),
777
+ formatItemList(heading, items) {
778
+ if (items.length < 1) return [];
779
+ if (!heading.includes("Commands:")) return items;
780
+ const c = (str) => str.replace(/[^A-Za-z0-9-,]/g, "").replace("32m", "");
781
+ let flags = items.filter((e) => c(e).startsWith("--") || c(e).includes(",--"));
782
+ if (flags.length > 0) flags = [__h3ravel_shared.Logger.log("\n" + heading + "\n", "yellow", false)].concat(flags);
783
+ const list = items.filter((e) => !c(e).startsWith("--") && !c(e).includes(",--"));
784
+ if (list.length < 1) return flags;
785
+ const _heading = c(heading).includes("Arguments") ? heading : "Available Commands:";
786
+ return flags.concat(__h3ravel_shared.Logger.log(`\n${_heading}`, "yellow", false), ListCommand.groupItems(list, true));
787
+ },
788
+ showGlobalOptions: true
789
+ });
790
+ /**
791
+ * Create the init Command
792
+ */
664
793
  commander.program.command("init").description("Initialize H3ravel.").action(async () => {
665
794
  __h3ravel_shared.Logger.success("Initialized: H3ravel has been initialized!");
666
795
  });
667
- /** Loop through all the available commands */
796
+ /**
797
+ * Loop through all the available commands
798
+ */
668
799
  for (let i = 0; i < this.commands.length; i++) {
669
800
  const command = this.commands[i];
670
801
  const instance = command.commandClass;
@@ -672,13 +803,9 @@ var Musket = class Musket {
672
803
  /**
673
804
  * Initialize the base command
674
805
  */
675
- const cmd = command.isHidden ? commander.program : commander.program.command(command.baseCommand).description(command.description ?? "").addOption(new commander.Option(additional.quiet[0], additional.quiet[1]).implies({ silent: true })).addOption(new commander.Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new commander.Option(additional.verbose[0], additional.verbose[1]).choices([
676
- "1",
677
- "2",
678
- "3"
679
- ])).addOption(new commander.Option(additional.lock[0], additional.lock[1])).action(async () => {
806
+ const cmd = command.isHidden ? commander.program : commander.program.command(command.baseCommand).description(command.description ?? "").action(async () => {
680
807
  instance.setInput(cmd.opts(), cmd.args, cmd.registeredArguments, command, commander.program);
681
- await instance.handle();
808
+ await this.handle(instance);
682
809
  });
683
810
  /**
684
811
  * Add options to the base command if it has any
@@ -690,13 +817,9 @@ var Musket = class Musket {
690
817
  * Initialize the sub commands
691
818
  */
692
819
  command.subCommands.filter((v, i$1, a) => !v.shared && a.findIndex((t) => t.name === v.name) === i$1).forEach((sub) => {
693
- const cmd$1 = commander.program.command(`${command.baseCommand}:${sub.name}`).description(sub.description || "").addOption(new commander.Option(additional.quiet[0], additional.quiet[1]).implies({ silent: true })).addOption(new commander.Option(additional.silent[0], additional.silent[1]).implies({ quiet: true })).addOption(new commander.Option(additional.verbose[0], additional.verbose[1]).choices([
694
- "1",
695
- "2",
696
- "3"
697
- ])).addOption(new commander.Option(additional.lock[0], additional.lock[1])).action(async () => {
820
+ const cmd$1 = commander.program.command(`${command.baseCommand}:${sub.name}`).description(sub.description || "").action(async () => {
698
821
  instance.setInput(cmd$1.opts(), cmd$1.args, cmd$1.registeredArguments, sub, commander.program);
699
- await instance.handle();
822
+ await this.handle(instance);
700
823
  });
701
824
  /**
702
825
  * Add the shared arguments here
@@ -727,20 +850,23 @@ var Musket = class Musket {
727
850
  });
728
851
  cmd.action(async () => {
729
852
  instance.setInput(cmd.opts(), cmd.args, cmd.registeredArguments, command, commander.program);
730
- await instance.handle();
853
+ await this.handle(instance);
731
854
  });
732
855
  }
733
856
  }
734
857
  /** Rebuild the app on every command except fire so we wont need TS */
735
858
  commander.program.hook("preAction", async (_, cmd) => {
736
- if (cmd.name() !== "fire") await (0, tsdown.build)({
737
- ...TsdownConfig_default,
738
- watch: false,
739
- plugins: []
740
- });
859
+ this.rebuild(cmd.name());
741
860
  });
742
861
  return commander.program;
743
862
  }
863
+ async rebuild(name) {
864
+ if (name !== "fire" && name !== "build") await (0, tsdown.build)({
865
+ ...TsdownConfig_default,
866
+ watch: false,
867
+ plugins: []
868
+ });
869
+ }
744
870
  makeOption(opt, cmd, parse, parent) {
745
871
  const description = opt.description?.replace(/\[(\w+)\]/g, (_, k) => parent?.[k] ?? `[${k}]`) ?? "";
746
872
  const type = opt.name.replaceAll("-", "");
@@ -748,17 +874,38 @@ var Musket = class Musket {
748
874
  let flags = opt.flags?.map((f) => f.length === 1 ? `-${f}` : `--${f.replace(/^-+/, "")}`).join(", ") ?? void 0;
749
875
  if (opt.required && !opt.placeholder) flags += ` <${type}>`;
750
876
  else if (opt.placeholder) flags += " " + opt.placeholder;
751
- cmd.option(flags || "", description, opt.defaultValue);
877
+ let optn = new commander.Option(flags || "", description).default(opt.defaultValue);
878
+ if (opt.choices && opt.choices.length) optn = optn.choices(opt.choices ?? []);
879
+ cmd.addOption(optn);
752
880
  } else {
753
881
  let flags = opt.flags?.join(", ") ?? "";
754
882
  if (opt.required && !opt.placeholder) flags += ` <${type}>`;
755
883
  else if (opt.placeholder) flags += " " + opt.placeholder;
756
- cmd.option(flags, description, opt.defaultValue);
884
+ let optn = new commander.Option(flags, description).default(opt.defaultValue);
885
+ if (opt.choices && opt.choices.length) optn = optn.choices(opt.choices ?? []);
886
+ cmd.addOption(optn);
757
887
  }
758
- else cmd.argument(opt.required ? `<${opt.name}>` : `[${opt.name}]`, description, opt.defaultValue);
888
+ else {
889
+ let name = opt.placeholder;
890
+ if (!name) name = opt.required ? `<${opt.name}>` : `[${opt.name}]`;
891
+ let arg = new commander.Argument(name, description);
892
+ if (opt.choices && opt.choices.length) arg = arg.choices(opt.choices ?? []);
893
+ if (opt.defaultValue) arg.default(opt.defaultValue);
894
+ cmd.addArgument(arg);
895
+ }
896
+ }
897
+ async handle(cmd) {
898
+ await new __h3ravel_core.ContainerResolver(this.app).resolveMethodParams(cmd, "handle");
759
899
  }
760
900
  static async parse(kernel) {
761
- return (await new Musket(kernel.app, kernel).build()).parseAsync();
901
+ return (await new Musket(kernel.app, kernel).build()).exitOverride(() => {
902
+ __h3ravel_shared.Logger.log("Unknown command or argument.", "white");
903
+ __h3ravel_shared.Logger.log([
904
+ ["Run", "white"],
905
+ ["`musket --help`", ["grey", "italic"]],
906
+ ["to see available commands.", "white"]
907
+ ], " ");
908
+ }).parseAsync(process.argv).catch((e) => e);
762
909
  }
763
910
  };
764
911
 
@@ -829,6 +976,7 @@ var ConsoleServiceProvider = class extends __h3ravel_core.ServiceProvider {
829
976
  exports.BuildCommand = BuildCommand;
830
977
  exports.Command = Command;
831
978
  exports.ConsoleServiceProvider = ConsoleServiceProvider;
979
+ exports.HelpCommand = HelpCommand;
832
980
  exports.Kernel = Kernel;
833
981
  exports.ListCommand = ListCommand;
834
982
  exports.MakeCommand = MakeCommand;