@axiomify/cli 5.0.0 → 6.0.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
@@ -2,13 +2,14 @@
2
2
  'use strict';
3
3
 
4
4
  var esbuild = require('esbuild');
5
- var path4 = require('path');
5
+ var path7 = require('path');
6
6
  var fs = require('fs');
7
+ var pc = require('picocolors');
8
+ var fs5 = require('fs/promises');
7
9
  var child_process = require('child_process');
10
+ var net = require('net');
8
11
  var enquirer = require('enquirer');
9
12
  var execa = require('execa');
10
- var fs2 = require('fs/promises');
11
- var pc = require('picocolors');
12
13
 
13
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
15
 
@@ -31,10 +32,10 @@ function _interopNamespace(e) {
31
32
  }
32
33
 
33
34
  var esbuild__namespace = /*#__PURE__*/_interopNamespace(esbuild);
34
- var path4__default = /*#__PURE__*/_interopDefault(path4);
35
+ var path7__default = /*#__PURE__*/_interopDefault(path7);
35
36
  var fs__default = /*#__PURE__*/_interopDefault(fs);
36
- var fs2__default = /*#__PURE__*/_interopDefault(fs2);
37
37
  var pc__default = /*#__PURE__*/_interopDefault(pc);
38
+ var fs5__default = /*#__PURE__*/_interopDefault(fs5);
38
39
 
39
40
  var __create = Object.create;
40
41
  var __defProp = Object.defineProperty;
@@ -48,9 +49,21 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
48
49
  if (typeof require !== "undefined") return require.apply(this, arguments);
49
50
  throw Error('Dynamic require of "' + x + '" is not supported');
50
51
  });
51
- var __commonJS = (cb, mod) => function __require2() {
52
+ var __glob = (map) => (path11) => {
53
+ var fn = map[path11];
54
+ if (fn) return fn();
55
+ throw new Error("Module not found in bundle: " + path11);
56
+ };
57
+ var __esm = (fn, res) => function __init() {
58
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
59
+ };
60
+ var __commonJS = (cb, mod) => function __require3() {
52
61
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
53
62
  };
63
+ var __export = (target, all) => {
64
+ for (var name in all)
65
+ __defProp(target, name, { get: all[name], enumerable: true });
66
+ };
54
67
  var __copyProps = (to, from, except, desc) => {
55
68
  if (from && typeof from === "object" || typeof from === "function") {
56
69
  for (let key of __getOwnPropNames(from))
@@ -77,7 +90,6 @@ var require_error = __commonJS({
77
90
  * @param {number} exitCode suggested exit code which could be used with process.exit
78
91
  * @param {string} code an id string representing the error
79
92
  * @param {string} message human-readable description of the error
80
- * @constructor
81
93
  */
82
94
  constructor(exitCode, code, message) {
83
95
  super(message);
@@ -92,7 +104,6 @@ var require_error = __commonJS({
92
104
  /**
93
105
  * Constructs the InvalidArgumentError class
94
106
  * @param {string} [message] explanation of why argument is invalid
95
- * @constructor
96
107
  */
97
108
  constructor(message) {
98
109
  super(1, "commander.invalidArgument", message);
@@ -153,7 +164,7 @@ var require_argument = __commonJS({
153
164
  return this._name;
154
165
  }
155
166
  /**
156
- * @package internal use only
167
+ * @package
157
168
  */
158
169
  _concatValue(value, previous) {
159
170
  if (previous === this.defaultValue || !Array.isArray(previous)) {
@@ -193,7 +204,9 @@ var require_argument = __commonJS({
193
204
  this.argChoices = values.slice();
194
205
  this.parseArg = (arg, previous) => {
195
206
  if (!this.argChoices.includes(arg)) {
196
- throw new InvalidArgumentError2(`Allowed choices are ${this.argChoices.join(", ")}.`);
207
+ throw new InvalidArgumentError2(
208
+ `Allowed choices are ${this.argChoices.join(", ")}.`
209
+ );
197
210
  }
198
211
  if (this.variadic) {
199
212
  return this._concatValue(arg, previous);
@@ -204,6 +217,8 @@ var require_argument = __commonJS({
204
217
  }
205
218
  /**
206
219
  * Make argument required.
220
+ *
221
+ * @returns {Argument}
207
222
  */
208
223
  argRequired() {
209
224
  this.required = true;
@@ -211,6 +226,8 @@ var require_argument = __commonJS({
211
226
  }
212
227
  /**
213
228
  * Make argument optional.
229
+ *
230
+ * @returns {Argument}
214
231
  */
215
232
  argOptional() {
216
233
  this.required = false;
@@ -261,7 +278,7 @@ var require_help = __commonJS({
261
278
  *
262
279
  * @param {Option} a
263
280
  * @param {Option} b
264
- * @returns number
281
+ * @returns {number}
265
282
  */
266
283
  compareOptions(a, b) {
267
284
  const getSortKey = (option) => {
@@ -284,9 +301,13 @@ var require_help = __commonJS({
284
301
  if (!removeShort && !removeLong) {
285
302
  visibleOptions.push(helpOption);
286
303
  } else if (helpOption.long && !removeLong) {
287
- visibleOptions.push(cmd.createOption(helpOption.long, helpOption.description));
304
+ visibleOptions.push(
305
+ cmd.createOption(helpOption.long, helpOption.description)
306
+ );
288
307
  } else if (helpOption.short && !removeShort) {
289
- visibleOptions.push(cmd.createOption(helpOption.short, helpOption.description));
308
+ visibleOptions.push(
309
+ cmd.createOption(helpOption.short, helpOption.description)
310
+ );
290
311
  }
291
312
  }
292
313
  if (this.sortOptions) {
@@ -304,7 +325,9 @@ var require_help = __commonJS({
304
325
  if (!this.showGlobalOptions) return [];
305
326
  const globalOptions = [];
306
327
  for (let ancestorCmd = cmd.parent; ancestorCmd; ancestorCmd = ancestorCmd.parent) {
307
- const visibleOptions = ancestorCmd.options.filter((option) => !option.hidden);
328
+ const visibleOptions = ancestorCmd.options.filter(
329
+ (option) => !option.hidden
330
+ );
308
331
  globalOptions.push(...visibleOptions);
309
332
  }
310
333
  if (this.sortOptions) {
@@ -459,7 +482,9 @@ var require_help = __commonJS({
459
482
  if (option.defaultValue !== void 0) {
460
483
  const showDefault = option.required || option.optional || option.isBoolean() && typeof option.defaultValue === "boolean";
461
484
  if (showDefault) {
462
- extraInfo.push(`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`);
485
+ extraInfo.push(
486
+ `default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`
487
+ );
463
488
  }
464
489
  }
465
490
  if (option.presetArg !== void 0 && option.optional) {
@@ -488,7 +513,9 @@ var require_help = __commonJS({
488
513
  );
489
514
  }
490
515
  if (argument.defaultValue !== void 0) {
491
- extraInfo.push(`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`);
516
+ extraInfo.push(
517
+ `default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`
518
+ );
492
519
  }
493
520
  if (extraInfo.length > 0) {
494
521
  const extraDescripton = `(${extraInfo.join(", ")})`;
@@ -514,7 +541,11 @@ var require_help = __commonJS({
514
541
  function formatItem(term, description) {
515
542
  if (description) {
516
543
  const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`;
517
- return helper.wrap(fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth);
544
+ return helper.wrap(
545
+ fullText,
546
+ helpWidth - itemIndentWidth,
547
+ termWidth + itemSeparatorWidth
548
+ );
518
549
  }
519
550
  return term;
520
551
  }
@@ -524,30 +555,49 @@ var require_help = __commonJS({
524
555
  let output = [`Usage: ${helper.commandUsage(cmd)}`, ""];
525
556
  const commandDescription = helper.commandDescription(cmd);
526
557
  if (commandDescription.length > 0) {
527
- output = output.concat([helper.wrap(commandDescription, helpWidth, 0), ""]);
558
+ output = output.concat([
559
+ helper.wrap(commandDescription, helpWidth, 0),
560
+ ""
561
+ ]);
528
562
  }
529
563
  const argumentList = helper.visibleArguments(cmd).map((argument) => {
530
- return formatItem(helper.argumentTerm(argument), helper.argumentDescription(argument));
564
+ return formatItem(
565
+ helper.argumentTerm(argument),
566
+ helper.argumentDescription(argument)
567
+ );
531
568
  });
532
569
  if (argumentList.length > 0) {
533
570
  output = output.concat(["Arguments:", formatList(argumentList), ""]);
534
571
  }
535
572
  const optionList = helper.visibleOptions(cmd).map((option) => {
536
- return formatItem(helper.optionTerm(option), helper.optionDescription(option));
573
+ return formatItem(
574
+ helper.optionTerm(option),
575
+ helper.optionDescription(option)
576
+ );
537
577
  });
538
578
  if (optionList.length > 0) {
539
579
  output = output.concat(["Options:", formatList(optionList), ""]);
540
580
  }
541
581
  if (this.showGlobalOptions) {
542
582
  const globalOptionList = helper.visibleGlobalOptions(cmd).map((option) => {
543
- return formatItem(helper.optionTerm(option), helper.optionDescription(option));
583
+ return formatItem(
584
+ helper.optionTerm(option),
585
+ helper.optionDescription(option)
586
+ );
544
587
  });
545
588
  if (globalOptionList.length > 0) {
546
- output = output.concat(["Global Options:", formatList(globalOptionList), ""]);
589
+ output = output.concat([
590
+ "Global Options:",
591
+ formatList(globalOptionList),
592
+ ""
593
+ ]);
547
594
  }
548
595
  }
549
596
  const commandList = helper.visibleCommands(cmd).map((cmd2) => {
550
- return formatItem(helper.subcommandTerm(cmd2), helper.subcommandDescription(cmd2));
597
+ return formatItem(
598
+ helper.subcommandTerm(cmd2),
599
+ helper.subcommandDescription(cmd2)
600
+ );
551
601
  });
552
602
  if (commandList.length > 0) {
553
603
  output = output.concat(["Commands:", formatList(commandList), ""]);
@@ -591,8 +641,11 @@ var require_help = __commonJS({
591
641
  const indentString = " ".repeat(indent);
592
642
  const zeroWidthSpace = "\u200B";
593
643
  const breaks = `\\s${zeroWidthSpace}`;
594
- const regex = new RegExp(`
595
- |.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`, "g");
644
+ const regex = new RegExp(
645
+ `
646
+ |.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`,
647
+ "g"
648
+ );
596
649
  const lines = columnText.match(regex) || [];
597
650
  return leadingStr + lines.map((line, i) => {
598
651
  if (line === "\n") return "";
@@ -691,7 +744,7 @@ var require_option = __commonJS({
691
744
  * .addOption(new Option('--log', 'write logging information to file'))
692
745
  * .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));
693
746
  *
694
- * @param {Object} impliedOptionValues
747
+ * @param {object} impliedOptionValues
695
748
  * @return {Option}
696
749
  */
697
750
  implies(impliedOptionValues) {
@@ -746,7 +799,7 @@ var require_option = __commonJS({
746
799
  return this;
747
800
  }
748
801
  /**
749
- * @package internal use only
802
+ * @package
750
803
  */
751
804
  _concatValue(value, previous) {
752
805
  if (previous === this.defaultValue || !Array.isArray(previous)) {
@@ -764,7 +817,9 @@ var require_option = __commonJS({
764
817
  this.argChoices = values.slice();
765
818
  this.parseArg = (arg, previous) => {
766
819
  if (!this.argChoices.includes(arg)) {
767
- throw new InvalidArgumentError2(`Allowed choices are ${this.argChoices.join(", ")}.`);
820
+ throw new InvalidArgumentError2(
821
+ `Allowed choices are ${this.argChoices.join(", ")}.`
822
+ );
768
823
  }
769
824
  if (this.variadic) {
770
825
  return this._concatValue(arg, previous);
@@ -798,7 +853,7 @@ var require_option = __commonJS({
798
853
  *
799
854
  * @param {string} arg
800
855
  * @return {boolean}
801
- * @package internal use only
856
+ * @package
802
857
  */
803
858
  is(arg) {
804
859
  return this.short === arg || this.long === arg;
@@ -809,7 +864,7 @@ var require_option = __commonJS({
809
864
  * Options are one of boolean, negated, required argument, or optional argument.
810
865
  *
811
866
  * @return {boolean}
812
- * @package internal use only
867
+ * @package
813
868
  */
814
869
  isBoolean() {
815
870
  return !this.required && !this.optional && !this.negate;
@@ -860,7 +915,8 @@ var require_option = __commonJS({
860
915
  let shortFlag;
861
916
  let longFlag;
862
917
  const flagParts = flags.split(/[ |,]+/);
863
- if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1])) shortFlag = flagParts.shift();
918
+ if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1]))
919
+ shortFlag = flagParts.shift();
864
920
  longFlag = flagParts.shift();
865
921
  if (!shortFlag && /^-[^-]$/.test(longFlag)) {
866
922
  shortFlag = longFlag;
@@ -878,7 +934,8 @@ var require_suggestSimilar = __commonJS({
878
934
  "node_modules/commander/lib/suggestSimilar.js"(exports) {
879
935
  var maxDistance = 3;
880
936
  function editDistance(a, b) {
881
- if (Math.abs(a.length - b.length) > maxDistance) return Math.max(a.length, b.length);
937
+ if (Math.abs(a.length - b.length) > maxDistance)
938
+ return Math.max(a.length, b.length);
882
939
  const d = [];
883
940
  for (let i = 0; i <= a.length; i++) {
884
941
  d[i] = [i];
@@ -957,8 +1014,8 @@ var require_command = __commonJS({
957
1014
  "node_modules/commander/lib/command.js"(exports) {
958
1015
  var EventEmitter = __require("events").EventEmitter;
959
1016
  var childProcess = __require("child_process");
960
- var path6 = __require("path");
961
- var fs4 = __require("fs");
1017
+ var path11 = __require("path");
1018
+ var fs9 = __require("fs");
962
1019
  var process2 = __require("process");
963
1020
  var { Argument: Argument2, humanReadableArgName } = require_argument();
964
1021
  var { CommanderError: CommanderError2 } = require_error();
@@ -1070,8 +1127,8 @@ var require_command = __commonJS({
1070
1127
  * .command('stop [service]', 'stop named service, or all if no name supplied');
1071
1128
  *
1072
1129
  * @param {string} nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
1073
- * @param {(Object|string)} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)
1074
- * @param {Object} [execOpts] - configuration options (for executable)
1130
+ * @param {(object | string)} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)
1131
+ * @param {object} [execOpts] - configuration options (for executable)
1075
1132
  * @return {Command} returns new command for action handler, or `this` for executable command
1076
1133
  */
1077
1134
  command(nameAndArgs, actionOptsOrExecDesc, execOpts) {
@@ -1123,8 +1180,8 @@ var require_command = __commonJS({
1123
1180
  * You can customise the help by overriding Help properties using configureHelp(),
1124
1181
  * or with a subclass of Help by overriding createHelp().
1125
1182
  *
1126
- * @param {Object} [configuration] - configuration options
1127
- * @return {(Command|Object)} `this` command for chaining, or stored configuration
1183
+ * @param {object} [configuration] - configuration options
1184
+ * @return {(Command | object)} `this` command for chaining, or stored configuration
1128
1185
  */
1129
1186
  configureHelp(configuration) {
1130
1187
  if (configuration === void 0) return this._helpConfiguration;
@@ -1146,8 +1203,8 @@ var require_command = __commonJS({
1146
1203
  * // functions based on what is being written out
1147
1204
  * outputError(str, write) // used for displaying errors, and not used for displaying help
1148
1205
  *
1149
- * @param {Object} [configuration] - configuration options
1150
- * @return {(Command|Object)} `this` command for chaining, or stored configuration
1206
+ * @param {object} [configuration] - configuration options
1207
+ * @return {(Command | object)} `this` command for chaining, or stored configuration
1151
1208
  */
1152
1209
  configureOutput(configuration) {
1153
1210
  if (configuration === void 0) return this._outputConfiguration;
@@ -1181,7 +1238,7 @@ var require_command = __commonJS({
1181
1238
  * See .command() for creating an attached subcommand which inherits settings from its parent.
1182
1239
  *
1183
1240
  * @param {Command} cmd - new subcommand
1184
- * @param {Object} [opts] - configuration options
1241
+ * @param {object} [opts] - configuration options
1185
1242
  * @return {Command} `this` command for chaining
1186
1243
  */
1187
1244
  addCommand(cmd, opts) {
@@ -1262,10 +1319,14 @@ var require_command = __commonJS({
1262
1319
  addArgument(argument) {
1263
1320
  const previousArgument = this.registeredArguments.slice(-1)[0];
1264
1321
  if (previousArgument && previousArgument.variadic) {
1265
- throw new Error(`only the last argument can be variadic '${previousArgument.name()}'`);
1322
+ throw new Error(
1323
+ `only the last argument can be variadic '${previousArgument.name()}'`
1324
+ );
1266
1325
  }
1267
1326
  if (argument.required && argument.defaultValue !== void 0 && argument.parseArg === void 0) {
1268
- throw new Error(`a default value for a required argument is never used: '${argument.name()}'`);
1327
+ throw new Error(
1328
+ `a default value for a required argument is never used: '${argument.name()}'`
1329
+ );
1269
1330
  }
1270
1331
  this.registeredArguments.push(argument);
1271
1332
  return this;
@@ -1273,6 +1334,7 @@ var require_command = __commonJS({
1273
1334
  /**
1274
1335
  * Customise or override default help command. By default a help command is automatically added if your command has subcommands.
1275
1336
  *
1337
+ * @example
1276
1338
  * program.helpCommand('help [cmd]');
1277
1339
  * program.helpCommand('help [cmd]', 'show help');
1278
1340
  * program.helpCommand(false); // suppress default help command
@@ -1450,7 +1512,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1450
1512
  * Register option if no conflicts found, or throw on conflict.
1451
1513
  *
1452
1514
  * @param {Option} option
1453
- * @api private
1515
+ * @private
1454
1516
  */
1455
1517
  _registerOption(option) {
1456
1518
  const matchingOption = option.short && this._findOption(option.short) || option.long && this._findOption(option.long);
@@ -1466,17 +1528,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
1466
1528
  * Register command if no conflicts found, or throw on conflict.
1467
1529
  *
1468
1530
  * @param {Command} command
1469
- * @api private
1531
+ * @private
1470
1532
  */
1471
1533
  _registerCommand(command) {
1472
1534
  const knownBy = (cmd) => {
1473
1535
  return [cmd.name()].concat(cmd.aliases());
1474
1536
  };
1475
- const alreadyUsed = knownBy(command).find((name) => this._findCommand(name));
1537
+ const alreadyUsed = knownBy(command).find(
1538
+ (name) => this._findCommand(name)
1539
+ );
1476
1540
  if (alreadyUsed) {
1477
1541
  const existingCmd = knownBy(this._findCommand(alreadyUsed)).join("|");
1478
1542
  const newCmd = knownBy(command).join("|");
1479
- throw new Error(`cannot add command '${newCmd}' as already have command '${existingCmd}'`);
1543
+ throw new Error(
1544
+ `cannot add command '${newCmd}' as already have command '${existingCmd}'`
1545
+ );
1480
1546
  }
1481
1547
  this.commands.push(command);
1482
1548
  }
@@ -1493,7 +1559,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1493
1559
  if (option.negate) {
1494
1560
  const positiveLongFlag = option.long.replace(/^--no-/, "--");
1495
1561
  if (!this._findOption(positiveLongFlag)) {
1496
- this.setOptionValueWithSource(name, option.defaultValue === void 0 ? true : option.defaultValue, "default");
1562
+ this.setOptionValueWithSource(
1563
+ name,
1564
+ option.defaultValue === void 0 ? true : option.defaultValue,
1565
+ "default"
1566
+ );
1497
1567
  }
1498
1568
  } else if (option.defaultValue !== void 0) {
1499
1569
  this.setOptionValueWithSource(name, option.defaultValue, "default");
@@ -1534,11 +1604,14 @@ Expecting one of '${allowedValues.join("', '")}'`);
1534
1604
  /**
1535
1605
  * Internal implementation shared by .option() and .requiredOption()
1536
1606
  *
1607
+ * @return {Command} `this` command for chaining
1537
1608
  * @private
1538
1609
  */
1539
1610
  _optionEx(config, flags, description, fn, defaultValue) {
1540
1611
  if (typeof flags === "object" && flags instanceof Option2) {
1541
- throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");
1612
+ throw new Error(
1613
+ "To add an Option object use addOption() instead of option() or requiredOption()"
1614
+ );
1542
1615
  }
1543
1616
  const option = this.createOption(flags, description);
1544
1617
  option.makeOptionMandatory(!!config.mandatory);
@@ -1581,19 +1654,25 @@ Expecting one of '${allowedValues.join("', '")}'`);
1581
1654
  return this._optionEx({}, flags, description, parseArg, defaultValue);
1582
1655
  }
1583
1656
  /**
1584
- * Add a required option which must have a value after parsing. This usually means
1585
- * the option must be specified on the command line. (Otherwise the same as .option().)
1586
- *
1587
- * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.
1588
- *
1589
- * @param {string} flags
1590
- * @param {string} [description]
1591
- * @param {(Function|*)} [parseArg] - custom option processing function or default value
1592
- * @param {*} [defaultValue]
1593
- * @return {Command} `this` command for chaining
1594
- */
1657
+ * Add a required option which must have a value after parsing. This usually means
1658
+ * the option must be specified on the command line. (Otherwise the same as .option().)
1659
+ *
1660
+ * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.
1661
+ *
1662
+ * @param {string} flags
1663
+ * @param {string} [description]
1664
+ * @param {(Function|*)} [parseArg] - custom option processing function or default value
1665
+ * @param {*} [defaultValue]
1666
+ * @return {Command} `this` command for chaining
1667
+ */
1595
1668
  requiredOption(flags, description, parseArg, defaultValue) {
1596
- return this._optionEx({ mandatory: true }, flags, description, parseArg, defaultValue);
1669
+ return this._optionEx(
1670
+ { mandatory: true },
1671
+ flags,
1672
+ description,
1673
+ parseArg,
1674
+ defaultValue
1675
+ );
1597
1676
  }
1598
1677
  /**
1599
1678
  * Alter parsing of short flags with optional values.
@@ -1603,7 +1682,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1603
1682
  * program.combineFlagAndOptionalValue(true); // `-f80` is treated like `--flag=80`, this is the default behaviour
1604
1683
  * program.combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`
1605
1684
  *
1606
- * @param {boolean} [combine=true] - if `true` or omitted, an optional value can be specified directly after the flag.
1685
+ * @param {boolean} [combine] - if `true` or omitted, an optional value can be specified directly after the flag.
1686
+ * @return {Command} `this` command for chaining
1607
1687
  */
1608
1688
  combineFlagAndOptionalValue(combine = true) {
1609
1689
  this._combineFlagAndOptionalValue = !!combine;
@@ -1612,8 +1692,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1612
1692
  /**
1613
1693
  * Allow unknown options on the command line.
1614
1694
  *
1615
- * @param {boolean} [allowUnknown=true] - if `true` or omitted, no error will be thrown
1616
- * for unknown options.
1695
+ * @param {boolean} [allowUnknown] - if `true` or omitted, no error will be thrown for unknown options.
1696
+ * @return {Command} `this` command for chaining
1617
1697
  */
1618
1698
  allowUnknownOption(allowUnknown = true) {
1619
1699
  this._allowUnknownOption = !!allowUnknown;
@@ -1622,8 +1702,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1622
1702
  /**
1623
1703
  * Allow excess command-arguments on the command line. Pass false to make excess arguments an error.
1624
1704
  *
1625
- * @param {boolean} [allowExcess=true] - if `true` or omitted, no error will be thrown
1626
- * for excess arguments.
1705
+ * @param {boolean} [allowExcess] - if `true` or omitted, no error will be thrown for excess arguments.
1706
+ * @return {Command} `this` command for chaining
1627
1707
  */
1628
1708
  allowExcessArguments(allowExcess = true) {
1629
1709
  this._allowExcessArguments = !!allowExcess;
@@ -1634,7 +1714,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1634
1714
  * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.
1635
1715
  * The default behaviour is non-positional and global options may appear anywhere on the command line.
1636
1716
  *
1637
- * @param {boolean} [positional=true]
1717
+ * @param {boolean} [positional]
1718
+ * @return {Command} `this` command for chaining
1638
1719
  */
1639
1720
  enablePositionalOptions(positional = true) {
1640
1721
  this._enablePositionalOptions = !!positional;
@@ -1646,8 +1727,8 @@ Expecting one of '${allowedValues.join("', '")}'`);
1646
1727
  * positional options to have been enabled on the program (parent commands).
1647
1728
  * The default behaviour is non-positional and options may appear before or after command-arguments.
1648
1729
  *
1649
- * @param {boolean} [passThrough=true]
1650
- * for unknown options.
1730
+ * @param {boolean} [passThrough] for unknown options.
1731
+ * @return {Command} `this` command for chaining
1651
1732
  */
1652
1733
  passThroughOptions(passThrough = true) {
1653
1734
  this._passThroughOptions = !!passThrough;
@@ -1659,22 +1740,26 @@ Expecting one of '${allowedValues.join("', '")}'`);
1659
1740
  */
1660
1741
  _checkForBrokenPassThrough() {
1661
1742
  if (this.parent && this._passThroughOptions && !this.parent._enablePositionalOptions) {
1662
- throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`);
1743
+ throw new Error(
1744
+ `passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`
1745
+ );
1663
1746
  }
1664
1747
  }
1665
1748
  /**
1666
- * Whether to store option values as properties on command object,
1667
- * or store separately (specify false). In both cases the option values can be accessed using .opts().
1668
- *
1669
- * @param {boolean} [storeAsProperties=true]
1670
- * @return {Command} `this` command for chaining
1671
- */
1749
+ * Whether to store option values as properties on command object,
1750
+ * or store separately (specify false). In both cases the option values can be accessed using .opts().
1751
+ *
1752
+ * @param {boolean} [storeAsProperties=true]
1753
+ * @return {Command} `this` command for chaining
1754
+ */
1672
1755
  storeOptionsAsProperties(storeAsProperties = true) {
1673
1756
  if (this.options.length) {
1674
1757
  throw new Error("call .storeOptionsAsProperties() before adding options");
1675
1758
  }
1676
1759
  if (Object.keys(this._optionValues).length) {
1677
- throw new Error("call .storeOptionsAsProperties() before setting option values");
1760
+ throw new Error(
1761
+ "call .storeOptionsAsProperties() before setting option values"
1762
+ );
1678
1763
  }
1679
1764
  this._storeOptionsAsProperties = !!storeAsProperties;
1680
1765
  return this;
@@ -1683,7 +1768,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1683
1768
  * Retrieve option value.
1684
1769
  *
1685
1770
  * @param {string} key
1686
- * @return {Object} value
1771
+ * @return {object} value
1687
1772
  */
1688
1773
  getOptionValue(key) {
1689
1774
  if (this._storeOptionsAsProperties) {
@@ -1695,20 +1780,20 @@ Expecting one of '${allowedValues.join("', '")}'`);
1695
1780
  * Store option value.
1696
1781
  *
1697
1782
  * @param {string} key
1698
- * @param {Object} value
1783
+ * @param {object} value
1699
1784
  * @return {Command} `this` command for chaining
1700
1785
  */
1701
1786
  setOptionValue(key, value) {
1702
1787
  return this.setOptionValueWithSource(key, value, void 0);
1703
1788
  }
1704
1789
  /**
1705
- * Store option value and where the value came from.
1706
- *
1707
- * @param {string} key
1708
- * @param {Object} value
1709
- * @param {string} source - expected values are default/config/env/cli/implied
1710
- * @return {Command} `this` command for chaining
1711
- */
1790
+ * Store option value and where the value came from.
1791
+ *
1792
+ * @param {string} key
1793
+ * @param {object} value
1794
+ * @param {string} source - expected values are default/config/env/cli/implied
1795
+ * @return {Command} `this` command for chaining
1796
+ */
1712
1797
  setOptionValueWithSource(key, value, source) {
1713
1798
  if (this._storeOptionsAsProperties) {
1714
1799
  this[key] = value;
@@ -1719,22 +1804,22 @@ Expecting one of '${allowedValues.join("', '")}'`);
1719
1804
  return this;
1720
1805
  }
1721
1806
  /**
1722
- * Get source of option value.
1723
- * Expected values are default | config | env | cli | implied
1724
- *
1725
- * @param {string} key
1726
- * @return {string}
1727
- */
1807
+ * Get source of option value.
1808
+ * Expected values are default | config | env | cli | implied
1809
+ *
1810
+ * @param {string} key
1811
+ * @return {string}
1812
+ */
1728
1813
  getOptionValueSource(key) {
1729
1814
  return this._optionValueSources[key];
1730
1815
  }
1731
1816
  /**
1732
- * Get source of option value. See also .optsWithGlobals().
1733
- * Expected values are default | config | env | cli | implied
1734
- *
1735
- * @param {string} key
1736
- * @return {string}
1737
- */
1817
+ * Get source of option value. See also .optsWithGlobals().
1818
+ * Expected values are default | config | env | cli | implied
1819
+ *
1820
+ * @param {string} key
1821
+ * @return {string}
1822
+ */
1738
1823
  getOptionValueSourceWithGlobals(key) {
1739
1824
  let source;
1740
1825
  this._getCommandAndAncestors().forEach((cmd) => {
@@ -1755,11 +1840,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
1755
1840
  throw new Error("first parameter to parse must be array or undefined");
1756
1841
  }
1757
1842
  parseOptions = parseOptions || {};
1758
- if (argv === void 0) {
1759
- argv = process2.argv;
1760
- if (process2.versions && process2.versions.electron) {
1843
+ if (argv === void 0 && parseOptions.from === void 0) {
1844
+ if (process2.versions?.electron) {
1761
1845
  parseOptions.from = "electron";
1762
1846
  }
1847
+ const execArgv = process2.execArgv ?? [];
1848
+ if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
1849
+ parseOptions.from = "eval";
1850
+ }
1851
+ }
1852
+ if (argv === void 0) {
1853
+ argv = process2.argv;
1763
1854
  }
1764
1855
  this.rawArgs = argv.slice();
1765
1856
  let userArgs;
@@ -1780,26 +1871,38 @@ Expecting one of '${allowedValues.join("', '")}'`);
1780
1871
  case "user":
1781
1872
  userArgs = argv.slice(0);
1782
1873
  break;
1874
+ case "eval":
1875
+ userArgs = argv.slice(1);
1876
+ break;
1783
1877
  default:
1784
- throw new Error(`unexpected parse option { from: '${parseOptions.from}' }`);
1878
+ throw new Error(
1879
+ `unexpected parse option { from: '${parseOptions.from}' }`
1880
+ );
1785
1881
  }
1786
- if (!this._name && this._scriptPath) this.nameFromFilename(this._scriptPath);
1882
+ if (!this._name && this._scriptPath)
1883
+ this.nameFromFilename(this._scriptPath);
1787
1884
  this._name = this._name || "program";
1788
1885
  return userArgs;
1789
1886
  }
1790
1887
  /**
1791
1888
  * Parse `argv`, setting options and invoking commands when defined.
1792
1889
  *
1793
- * The default expectation is that the arguments are from node and have the application as argv[0]
1794
- * and the script being run in argv[1], with user parameters after that.
1890
+ * Use parseAsync instead of parse if any of your action handlers are async.
1891
+ *
1892
+ * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!
1893
+ *
1894
+ * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:
1895
+ * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that
1896
+ * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged
1897
+ * - `'user'`: just user arguments
1795
1898
  *
1796
1899
  * @example
1797
- * program.parse(process.argv);
1798
- * program.parse(); // implicitly use process.argv and auto-detect node vs electron conventions
1900
+ * program.parse(); // parse process.argv and auto-detect electron and special node flags
1901
+ * program.parse(process.argv); // assume argv[0] is app and argv[1] is script
1799
1902
  * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
1800
1903
  *
1801
1904
  * @param {string[]} [argv] - optional, defaults to process.argv
1802
- * @param {Object} [parseOptions] - optionally specify style of options with from: node/user/electron
1905
+ * @param {object} [parseOptions] - optionally specify style of options with from: node/user/electron
1803
1906
  * @param {string} [parseOptions.from] - where the args are from: 'node', 'user', 'electron'
1804
1907
  * @return {Command} `this` command for chaining
1805
1908
  */
@@ -1811,18 +1914,20 @@ Expecting one of '${allowedValues.join("', '")}'`);
1811
1914
  /**
1812
1915
  * Parse `argv`, setting options and invoking commands when defined.
1813
1916
  *
1814
- * Use parseAsync instead of parse if any of your action handlers are async. Returns a Promise.
1917
+ * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!
1815
1918
  *
1816
- * The default expectation is that the arguments are from node and have the application as argv[0]
1817
- * and the script being run in argv[1], with user parameters after that.
1919
+ * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:
1920
+ * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that
1921
+ * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged
1922
+ * - `'user'`: just user arguments
1818
1923
  *
1819
1924
  * @example
1820
- * await program.parseAsync(process.argv);
1821
- * await program.parseAsync(); // implicitly use process.argv and auto-detect node vs electron conventions
1925
+ * await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags
1926
+ * await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script
1822
1927
  * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
1823
1928
  *
1824
1929
  * @param {string[]} [argv]
1825
- * @param {Object} [parseOptions]
1930
+ * @param {object} [parseOptions]
1826
1931
  * @param {string} parseOptions.from - where the args are from: 'node', 'user', 'electron'
1827
1932
  * @return {Promise}
1828
1933
  */
@@ -1841,10 +1946,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
1841
1946
  let launchWithNode = false;
1842
1947
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1843
1948
  function findFile(baseDir, baseName) {
1844
- const localBin = path6.resolve(baseDir, baseName);
1845
- if (fs4.existsSync(localBin)) return localBin;
1846
- if (sourceExt.includes(path6.extname(baseName))) return void 0;
1847
- const foundExt = sourceExt.find((ext) => fs4.existsSync(`${localBin}${ext}`));
1949
+ const localBin = path11.resolve(baseDir, baseName);
1950
+ if (fs9.existsSync(localBin)) return localBin;
1951
+ if (sourceExt.includes(path11.extname(baseName))) return void 0;
1952
+ const foundExt = sourceExt.find(
1953
+ (ext) => fs9.existsSync(`${localBin}${ext}`)
1954
+ );
1848
1955
  if (foundExt) return `${localBin}${foundExt}`;
1849
1956
  return void 0;
1850
1957
  }
@@ -1855,23 +1962,32 @@ Expecting one of '${allowedValues.join("', '")}'`);
1855
1962
  if (this._scriptPath) {
1856
1963
  let resolvedScriptPath;
1857
1964
  try {
1858
- resolvedScriptPath = fs4.realpathSync(this._scriptPath);
1965
+ resolvedScriptPath = fs9.realpathSync(this._scriptPath);
1859
1966
  } catch (err) {
1860
1967
  resolvedScriptPath = this._scriptPath;
1861
1968
  }
1862
- executableDir = path6.resolve(path6.dirname(resolvedScriptPath), executableDir);
1969
+ executableDir = path11.resolve(
1970
+ path11.dirname(resolvedScriptPath),
1971
+ executableDir
1972
+ );
1863
1973
  }
1864
1974
  if (executableDir) {
1865
1975
  let localFile = findFile(executableDir, executableFile);
1866
1976
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1867
- const legacyName = path6.basename(this._scriptPath, path6.extname(this._scriptPath));
1977
+ const legacyName = path11.basename(
1978
+ this._scriptPath,
1979
+ path11.extname(this._scriptPath)
1980
+ );
1868
1981
  if (legacyName !== this._name) {
1869
- localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
1982
+ localFile = findFile(
1983
+ executableDir,
1984
+ `${legacyName}-${subcommand._name}`
1985
+ );
1870
1986
  }
1871
1987
  }
1872
1988
  executableFile = localFile || executableFile;
1873
1989
  }
1874
- launchWithNode = sourceExt.includes(path6.extname(executableFile));
1990
+ launchWithNode = sourceExt.includes(path11.extname(executableFile));
1875
1991
  let proc;
1876
1992
  if (process2.platform !== "win32") {
1877
1993
  if (launchWithNode) {
@@ -1897,12 +2013,18 @@ Expecting one of '${allowedValues.join("', '")}'`);
1897
2013
  });
1898
2014
  }
1899
2015
  const exitCallback = this._exitCallback;
1900
- proc.on("close", (code, _signal) => {
2016
+ proc.on("close", (code) => {
1901
2017
  code = code ?? 1;
1902
2018
  if (!exitCallback) {
1903
2019
  process2.exit(code);
1904
2020
  } else {
1905
- exitCallback(new CommanderError2(code, "commander.executeSubCommandAsync", "(close)"));
2021
+ exitCallback(
2022
+ new CommanderError2(
2023
+ code,
2024
+ "commander.executeSubCommandAsync",
2025
+ "(close)"
2026
+ )
2027
+ );
1906
2028
  }
1907
2029
  });
1908
2030
  proc.on("error", (err) => {
@@ -1919,7 +2041,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1919
2041
  if (!exitCallback) {
1920
2042
  process2.exit(1);
1921
2043
  } else {
1922
- const wrappedError = new CommanderError2(1, "commander.executeSubCommandAsync", "(error)");
2044
+ const wrappedError = new CommanderError2(
2045
+ 1,
2046
+ "commander.executeSubCommandAsync",
2047
+ "(error)"
2048
+ );
1923
2049
  wrappedError.nestedError = err;
1924
2050
  exitCallback(wrappedError);
1925
2051
  }
@@ -1933,7 +2059,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1933
2059
  const subCommand = this._findCommand(commandName);
1934
2060
  if (!subCommand) this.help({ error: true });
1935
2061
  let promiseChain;
1936
- promiseChain = this._chainOrCallSubCommandHook(promiseChain, subCommand, "preSubcommand");
2062
+ promiseChain = this._chainOrCallSubCommandHook(
2063
+ promiseChain,
2064
+ subCommand,
2065
+ "preSubcommand"
2066
+ );
1937
2067
  promiseChain = this._chainOrCall(promiseChain, () => {
1938
2068
  if (subCommand._executableHandler) {
1939
2069
  this._executeSubCommand(subCommand, operands.concat(unknown));
@@ -1957,9 +2087,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1957
2087
  if (subCommand && !subCommand._executableHandler) {
1958
2088
  subCommand.help();
1959
2089
  }
1960
- return this._dispatchSubcommand(subcommandName, [], [
1961
- this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? "--help"
1962
- ]);
2090
+ return this._dispatchSubcommand(
2091
+ subcommandName,
2092
+ [],
2093
+ [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? "--help"]
2094
+ );
1963
2095
  }
1964
2096
  /**
1965
2097
  * Check this.args against expected this.registeredArguments.
@@ -1989,7 +2121,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
1989
2121
  let parsedValue = value;
1990
2122
  if (value !== null && argument.parseArg) {
1991
2123
  const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;
1992
- parsedValue = this._callParseArg(argument, value, previous, invalidValueMessage);
2124
+ parsedValue = this._callParseArg(
2125
+ argument,
2126
+ value,
2127
+ previous,
2128
+ invalidValueMessage
2129
+ );
1993
2130
  }
1994
2131
  return parsedValue;
1995
2132
  };
@@ -2097,7 +2234,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2097
2234
  }
2098
2235
  if (this._defaultCommandName) {
2099
2236
  this._outputHelpIfRequested(unknown);
2100
- return this._dispatchSubcommand(this._defaultCommandName, operands, unknown);
2237
+ return this._dispatchSubcommand(
2238
+ this._defaultCommandName,
2239
+ operands,
2240
+ unknown
2241
+ );
2101
2242
  }
2102
2243
  if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
2103
2244
  this.help({ error: true });
@@ -2116,7 +2257,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
2116
2257
  this._processArguments();
2117
2258
  let promiseChain;
2118
2259
  promiseChain = this._chainOrCallHooks(promiseChain, "preAction");
2119
- promiseChain = this._chainOrCall(promiseChain, () => this._actionHandler(this.processedArgs));
2260
+ promiseChain = this._chainOrCall(
2261
+ promiseChain,
2262
+ () => this._actionHandler(this.processedArgs)
2263
+ );
2120
2264
  if (this.parent) {
2121
2265
  promiseChain = this._chainOrCall(promiseChain, () => {
2122
2266
  this.parent.emit(commandEvent, operands, unknown);
@@ -2153,17 +2297,20 @@ Expecting one of '${allowedValues.join("', '")}'`);
2153
2297
  * Find matching command.
2154
2298
  *
2155
2299
  * @private
2300
+ * @return {Command | undefined}
2156
2301
  */
2157
2302
  _findCommand(name) {
2158
2303
  if (!name) return void 0;
2159
- return this.commands.find((cmd) => cmd._name === name || cmd._aliases.includes(name));
2304
+ return this.commands.find(
2305
+ (cmd) => cmd._name === name || cmd._aliases.includes(name)
2306
+ );
2160
2307
  }
2161
2308
  /**
2162
2309
  * Return an option matching `arg` if any.
2163
2310
  *
2164
2311
  * @param {string} arg
2165
2312
  * @return {Option}
2166
- * @package internal use only
2313
+ * @package
2167
2314
  */
2168
2315
  _findOption(arg) {
2169
2316
  return this.options.find((option) => option.is(arg));
@@ -2189,15 +2336,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2189
2336
  * @private
2190
2337
  */
2191
2338
  _checkForConflictingLocalOptions() {
2192
- const definedNonDefaultOptions = this.options.filter(
2193
- (option) => {
2194
- const optionKey = option.attributeName();
2195
- if (this.getOptionValue(optionKey) === void 0) {
2196
- return false;
2197
- }
2198
- return this.getOptionValueSource(optionKey) !== "default";
2339
+ const definedNonDefaultOptions = this.options.filter((option) => {
2340
+ const optionKey = option.attributeName();
2341
+ if (this.getOptionValue(optionKey) === void 0) {
2342
+ return false;
2199
2343
  }
2200
- );
2344
+ return this.getOptionValueSource(optionKey) !== "default";
2345
+ });
2201
2346
  const optionsWithConflicting = definedNonDefaultOptions.filter(
2202
2347
  (option) => option.conflictsWith.length > 0
2203
2348
  );
@@ -2327,7 +2472,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2327
2472
  /**
2328
2473
  * Return an object containing local option values as key-value pairs.
2329
2474
  *
2330
- * @return {Object}
2475
+ * @return {object}
2331
2476
  */
2332
2477
  opts() {
2333
2478
  if (this._storeOptionsAsProperties) {
@@ -2344,7 +2489,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2344
2489
  /**
2345
2490
  * Return an object containing merged local and global option values as key-value pairs.
2346
2491
  *
2347
- * @return {Object}
2492
+ * @return {object}
2348
2493
  */
2349
2494
  optsWithGlobals() {
2350
2495
  return this._getCommandAndAncestors().reduce(
@@ -2356,13 +2501,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
2356
2501
  * Display error message and exit (or call exitOverride).
2357
2502
  *
2358
2503
  * @param {string} message
2359
- * @param {Object} [errorOptions]
2504
+ * @param {object} [errorOptions]
2360
2505
  * @param {string} [errorOptions.code] - an id string representing the error
2361
2506
  * @param {number} [errorOptions.exitCode] - used with process.exit
2362
2507
  */
2363
2508
  error(message, errorOptions) {
2364
- this._outputConfiguration.outputError(`${message}
2365
- `, this._outputConfiguration.writeErr);
2509
+ this._outputConfiguration.outputError(
2510
+ `${message}
2511
+ `,
2512
+ this._outputConfiguration.writeErr
2513
+ );
2366
2514
  if (typeof this._showHelpAfterError === "string") {
2367
2515
  this._outputConfiguration.writeErr(`${this._showHelpAfterError}
2368
2516
  `);
@@ -2385,7 +2533,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2385
2533
  this.options.forEach((option) => {
2386
2534
  if (option.envVar && option.envVar in process2.env) {
2387
2535
  const optionKey = option.attributeName();
2388
- if (this.getOptionValue(optionKey) === void 0 || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
2536
+ if (this.getOptionValue(optionKey) === void 0 || ["default", "config", "env"].includes(
2537
+ this.getOptionValueSource(optionKey)
2538
+ )) {
2389
2539
  if (option.required || option.optional) {
2390
2540
  this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
2391
2541
  } else {
@@ -2405,9 +2555,18 @@ Expecting one of '${allowedValues.join("', '")}'`);
2405
2555
  const hasCustomOptionValue = (optionKey) => {
2406
2556
  return this.getOptionValue(optionKey) !== void 0 && !["default", "implied"].includes(this.getOptionValueSource(optionKey));
2407
2557
  };
2408
- this.options.filter((option) => option.implied !== void 0 && hasCustomOptionValue(option.attributeName()) && dualHelper.valueFromOption(this.getOptionValue(option.attributeName()), option)).forEach((option) => {
2558
+ this.options.filter(
2559
+ (option) => option.implied !== void 0 && hasCustomOptionValue(option.attributeName()) && dualHelper.valueFromOption(
2560
+ this.getOptionValue(option.attributeName()),
2561
+ option
2562
+ )
2563
+ ).forEach((option) => {
2409
2564
  Object.keys(option.implied).filter((impliedKey) => !hasCustomOptionValue(impliedKey)).forEach((impliedKey) => {
2410
- this.setOptionValueWithSource(impliedKey, option.implied[impliedKey], "implied");
2565
+ this.setOptionValueWithSource(
2566
+ impliedKey,
2567
+ option.implied[impliedKey],
2568
+ "implied"
2569
+ );
2411
2570
  });
2412
2571
  });
2413
2572
  }
@@ -2452,8 +2611,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
2452
2611
  const findBestOptionFromValue = (option2) => {
2453
2612
  const optionKey = option2.attributeName();
2454
2613
  const optionValue = this.getOptionValue(optionKey);
2455
- const negativeOption = this.options.find((target) => target.negate && optionKey === target.attributeName());
2456
- const positiveOption = this.options.find((target) => !target.negate && optionKey === target.attributeName());
2614
+ const negativeOption = this.options.find(
2615
+ (target) => target.negate && optionKey === target.attributeName()
2616
+ );
2617
+ const positiveOption = this.options.find(
2618
+ (target) => !target.negate && optionKey === target.attributeName()
2619
+ );
2457
2620
  if (negativeOption && (negativeOption.presetArg === void 0 && optionValue === false || negativeOption.presetArg !== void 0 && optionValue === negativeOption.presetArg)) {
2458
2621
  return negativeOption;
2459
2622
  }
@@ -2557,11 +2720,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
2557
2720
  * Set the description.
2558
2721
  *
2559
2722
  * @param {string} [str]
2560
- * @param {Object} [argsDescription]
2723
+ * @param {object} [argsDescription]
2561
2724
  * @return {(string|Command)}
2562
2725
  */
2563
2726
  description(str, argsDescription) {
2564
- if (str === void 0 && argsDescription === void 0) return this._description;
2727
+ if (str === void 0 && argsDescription === void 0)
2728
+ return this._description;
2565
2729
  this._description = str;
2566
2730
  if (argsDescription) {
2567
2731
  this._argsDescription = argsDescription;
@@ -2593,11 +2757,14 @@ Expecting one of '${allowedValues.join("', '")}'`);
2593
2757
  if (this.commands.length !== 0 && this.commands[this.commands.length - 1]._executableHandler) {
2594
2758
  command = this.commands[this.commands.length - 1];
2595
2759
  }
2596
- if (alias === command._name) throw new Error("Command alias can't be the same as its name");
2760
+ if (alias === command._name)
2761
+ throw new Error("Command alias can't be the same as its name");
2597
2762
  const matchingCommand = this.parent?._findCommand(alias);
2598
2763
  if (matchingCommand) {
2599
2764
  const existingCmd = [matchingCommand.name()].concat(matchingCommand.aliases()).join("|");
2600
- throw new Error(`cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`);
2765
+ throw new Error(
2766
+ `cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`
2767
+ );
2601
2768
  }
2602
2769
  command._aliases.push(alias);
2603
2770
  return this;
@@ -2660,7 +2827,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2660
2827
  * @return {Command}
2661
2828
  */
2662
2829
  nameFromFilename(filename) {
2663
- this._name = path6.basename(filename, path6.extname(filename));
2830
+ this._name = path11.basename(filename, path11.extname(filename));
2664
2831
  return this;
2665
2832
  }
2666
2833
  /**
@@ -2674,9 +2841,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2674
2841
  * @param {string} [path]
2675
2842
  * @return {(string|null|Command)}
2676
2843
  */
2677
- executableDir(path7) {
2678
- if (path7 === void 0) return this._executableDir;
2679
- this._executableDir = path7;
2844
+ executableDir(path12) {
2845
+ if (path12 === void 0) return this._executableDir;
2846
+ this._executableDir = path12;
2680
2847
  return this;
2681
2848
  }
2682
2849
  /**
@@ -2736,7 +2903,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2736
2903
  this.emit(this._getHelpOption().long);
2737
2904
  }
2738
2905
  this.emit("afterHelp", context2);
2739
- this._getCommandAndAncestors().forEach((command) => command.emit("afterAllHelp", context2));
2906
+ this._getCommandAndAncestors().forEach(
2907
+ (command) => command.emit("afterAllHelp", context2)
2908
+ );
2740
2909
  }
2741
2910
  /**
2742
2911
  * You can pass in flags and a description to customise the built-in help option.
@@ -2769,7 +2938,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2769
2938
  * Returns null if has been disabled with .helpOption(false).
2770
2939
  *
2771
2940
  * @returns {(Option | null)} the help option
2772
- * @package internal use only
2941
+ * @package
2773
2942
  */
2774
2943
  _getHelpOption() {
2775
2944
  if (this._helpOption === void 0) {
@@ -2904,6 +3073,557 @@ var require_commander = __commonJS({
2904
3073
  }
2905
3074
  });
2906
3075
 
3076
+ // ../../node_modules/uWebSockets.js/uws_darwin_arm64_127.node
3077
+ var require_uws_darwin_arm64_127 = __commonJS({
3078
+ "../../node_modules/uWebSockets.js/uws_darwin_arm64_127.node"(exports, module) {
3079
+ module.exports = "./uws_darwin_arm64_127-NGHTXN5Q.node";
3080
+ }
3081
+ });
3082
+
3083
+ // ../../node_modules/uWebSockets.js/uws_darwin_arm64_137.node
3084
+ var require_uws_darwin_arm64_137 = __commonJS({
3085
+ "../../node_modules/uWebSockets.js/uws_darwin_arm64_137.node"(exports, module) {
3086
+ module.exports = "./uws_darwin_arm64_137-ESY6MPLH.node";
3087
+ }
3088
+ });
3089
+
3090
+ // ../../node_modules/uWebSockets.js/uws_darwin_arm64_147.node
3091
+ var require_uws_darwin_arm64_147 = __commonJS({
3092
+ "../../node_modules/uWebSockets.js/uws_darwin_arm64_147.node"(exports, module) {
3093
+ module.exports = "./uws_darwin_arm64_147-V7BKA3SU.node";
3094
+ }
3095
+ });
3096
+
3097
+ // ../../node_modules/uWebSockets.js/uws_darwin_x64_127.node
3098
+ var require_uws_darwin_x64_127 = __commonJS({
3099
+ "../../node_modules/uWebSockets.js/uws_darwin_x64_127.node"(exports, module) {
3100
+ module.exports = "./uws_darwin_x64_127-WIZGG7MS.node";
3101
+ }
3102
+ });
3103
+
3104
+ // ../../node_modules/uWebSockets.js/uws_darwin_x64_137.node
3105
+ var require_uws_darwin_x64_137 = __commonJS({
3106
+ "../../node_modules/uWebSockets.js/uws_darwin_x64_137.node"(exports, module) {
3107
+ module.exports = "./uws_darwin_x64_137-APKZWL4Y.node";
3108
+ }
3109
+ });
3110
+
3111
+ // ../../node_modules/uWebSockets.js/uws_darwin_x64_147.node
3112
+ var require_uws_darwin_x64_147 = __commonJS({
3113
+ "../../node_modules/uWebSockets.js/uws_darwin_x64_147.node"(exports, module) {
3114
+ module.exports = "./uws_darwin_x64_147-W2HKFQZT.node";
3115
+ }
3116
+ });
3117
+
3118
+ // ../../node_modules/uWebSockets.js/uws_linux_arm64_127.node
3119
+ var require_uws_linux_arm64_127 = __commonJS({
3120
+ "../../node_modules/uWebSockets.js/uws_linux_arm64_127.node"(exports, module) {
3121
+ module.exports = "./uws_linux_arm64_127-3CO7NSFJ.node";
3122
+ }
3123
+ });
3124
+
3125
+ // ../../node_modules/uWebSockets.js/uws_linux_arm64_137.node
3126
+ var require_uws_linux_arm64_137 = __commonJS({
3127
+ "../../node_modules/uWebSockets.js/uws_linux_arm64_137.node"(exports, module) {
3128
+ module.exports = "./uws_linux_arm64_137-HWEDGGZV.node";
3129
+ }
3130
+ });
3131
+
3132
+ // ../../node_modules/uWebSockets.js/uws_linux_arm64_147.node
3133
+ var require_uws_linux_arm64_147 = __commonJS({
3134
+ "../../node_modules/uWebSockets.js/uws_linux_arm64_147.node"(exports, module) {
3135
+ module.exports = "./uws_linux_arm64_147-7UCIYMK2.node";
3136
+ }
3137
+ });
3138
+
3139
+ // ../../node_modules/uWebSockets.js/uws_linux_x64_127.node
3140
+ var require_uws_linux_x64_127 = __commonJS({
3141
+ "../../node_modules/uWebSockets.js/uws_linux_x64_127.node"(exports, module) {
3142
+ module.exports = "./uws_linux_x64_127-KA4E76LJ.node";
3143
+ }
3144
+ });
3145
+
3146
+ // ../../node_modules/uWebSockets.js/uws_linux_x64_137.node
3147
+ var require_uws_linux_x64_137 = __commonJS({
3148
+ "../../node_modules/uWebSockets.js/uws_linux_x64_137.node"(exports, module) {
3149
+ module.exports = "./uws_linux_x64_137-DDFLTTJR.node";
3150
+ }
3151
+ });
3152
+
3153
+ // ../../node_modules/uWebSockets.js/uws_linux_x64_147.node
3154
+ var require_uws_linux_x64_147 = __commonJS({
3155
+ "../../node_modules/uWebSockets.js/uws_linux_x64_147.node"(exports, module) {
3156
+ module.exports = "./uws_linux_x64_147-MJSFREL3.node";
3157
+ }
3158
+ });
3159
+
3160
+ // ../../node_modules/uWebSockets.js/uws_win32_x64_127.node
3161
+ var require_uws_win32_x64_127 = __commonJS({
3162
+ "../../node_modules/uWebSockets.js/uws_win32_x64_127.node"(exports, module) {
3163
+ module.exports = "./uws_win32_x64_127-O4US4Y4L.node";
3164
+ }
3165
+ });
3166
+
3167
+ // ../../node_modules/uWebSockets.js/uws_win32_x64_137.node
3168
+ var require_uws_win32_x64_137 = __commonJS({
3169
+ "../../node_modules/uWebSockets.js/uws_win32_x64_137.node"(exports, module) {
3170
+ module.exports = "./uws_win32_x64_137-L5OZROQ7.node";
3171
+ }
3172
+ });
3173
+
3174
+ // ../../node_modules/uWebSockets.js/uws_win32_x64_147.node
3175
+ var require_uws_win32_x64_147 = __commonJS({
3176
+ "../../node_modules/uWebSockets.js/uws_win32_x64_147.node"(exports, module) {
3177
+ module.exports = "./uws_win32_x64_147-D7MGKVRG.node";
3178
+ }
3179
+ });
3180
+
3181
+ // require("./uws_*_*_*.node") in ../../node_modules/uWebSockets.js/uws.js
3182
+ var globRequire_uws______node;
3183
+ var init_ = __esm({
3184
+ 'require("./uws_*_*_*.node") in ../../node_modules/uWebSockets.js/uws.js'() {
3185
+ globRequire_uws______node = __glob({
3186
+ "./uws_darwin_arm64_127.node": () => require_uws_darwin_arm64_127(),
3187
+ "./uws_darwin_arm64_137.node": () => require_uws_darwin_arm64_137(),
3188
+ "./uws_darwin_arm64_147.node": () => require_uws_darwin_arm64_147(),
3189
+ "./uws_darwin_x64_127.node": () => require_uws_darwin_x64_127(),
3190
+ "./uws_darwin_x64_137.node": () => require_uws_darwin_x64_137(),
3191
+ "./uws_darwin_x64_147.node": () => require_uws_darwin_x64_147(),
3192
+ "./uws_linux_arm64_127.node": () => require_uws_linux_arm64_127(),
3193
+ "./uws_linux_arm64_137.node": () => require_uws_linux_arm64_137(),
3194
+ "./uws_linux_arm64_147.node": () => require_uws_linux_arm64_147(),
3195
+ "./uws_linux_x64_127.node": () => require_uws_linux_x64_127(),
3196
+ "./uws_linux_x64_137.node": () => require_uws_linux_x64_137(),
3197
+ "./uws_linux_x64_147.node": () => require_uws_linux_x64_147(),
3198
+ "./uws_win32_x64_127.node": () => require_uws_win32_x64_127(),
3199
+ "./uws_win32_x64_137.node": () => require_uws_win32_x64_137(),
3200
+ "./uws_win32_x64_147.node": () => require_uws_win32_x64_147()
3201
+ });
3202
+ }
3203
+ });
3204
+
3205
+ // ../../node_modules/uWebSockets.js/uws.js
3206
+ var require_uws = __commonJS({
3207
+ "../../node_modules/uWebSockets.js/uws.js"(exports, module) {
3208
+ init_();
3209
+ module.exports = (() => {
3210
+ try {
3211
+ return globRequire_uws______node("./uws_" + process.platform + "_" + process.arch + "_" + process.versions.modules + ".node");
3212
+ } catch (e) {
3213
+ throw new Error("This version of uWS.js (v20.67.0) supports only Node.js versions 22, 24 and 26 on (glibc) Linux, macOS and Windows, on Tier 1 platforms (https://github.com/nodejs/node/blob/master/BUILDING.md#platform-list).\n\n" + e.toString());
3214
+ }
3215
+ })();
3216
+ var MAX_U8 = Math.pow(2, 8) - 1;
3217
+ var MAX_U16 = Math.pow(2, 16) - 1;
3218
+ var textEncoder = new TextEncoder();
3219
+ var toUint8Array = (value) => {
3220
+ if (value === void 0) return new Uint8Array(0);
3221
+ else if (typeof value === "string") return textEncoder.encode(value);
3222
+ else if (value instanceof ArrayBuffer) return new Uint8Array(value);
3223
+ else if (value instanceof SharedArrayBuffer) return new Uint8Array(value);
3224
+ else return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
3225
+ };
3226
+ module.exports.DeclarativeResponse = class DeclarativeResponse {
3227
+ constructor() {
3228
+ this.instructions = [];
3229
+ }
3230
+ // Append instruction and 1-byte length values
3231
+ _appendInstruction(opcode, ...values) {
3232
+ this.instructions.push(opcode);
3233
+ values.forEach((value) => {
3234
+ const uint8Array = toUint8Array(value);
3235
+ if (uint8Array.byteLength > MAX_U8) throw new RangeError("Data length exceeds " + MAX_U8);
3236
+ this.instructions.push(uint8Array.byteLength, ...uint8Array);
3237
+ });
3238
+ }
3239
+ // Append instruction and 2-byte length value
3240
+ _appendInstructionWithLength(opcode, value) {
3241
+ const uint8Array = toUint8Array(value);
3242
+ if (uint8Array.byteLength > MAX_U16) throw new RangeError("Data length exceeds " + MAX_U16);
3243
+ this.instructions.push(opcode, uint8Array.byteLength & 255, uint8Array.byteLength >> 8 & 255, ...uint8Array);
3244
+ }
3245
+ writeHeader(key, value) {
3246
+ return this._appendInstruction(1, key, value), this;
3247
+ }
3248
+ writeBody() {
3249
+ return this.instructions.push(2), this;
3250
+ }
3251
+ writeQueryValue(key) {
3252
+ return this._appendInstruction(3, key), this;
3253
+ }
3254
+ writeHeaderValue(key) {
3255
+ return this._appendInstruction(4, key), this;
3256
+ }
3257
+ write(value) {
3258
+ return this._appendInstructionWithLength(5, value), this;
3259
+ }
3260
+ writeParameterValue(key) {
3261
+ return this._appendInstruction(6, key), this;
3262
+ }
3263
+ writeStatus(status) {
3264
+ return this._appendInstruction(7, status), this;
3265
+ }
3266
+ end(value) {
3267
+ this._appendInstructionWithLength(0, value);
3268
+ return new Uint8Array(this.instructions).buffer;
3269
+ }
3270
+ };
3271
+ }
3272
+ });
3273
+
3274
+ // ../openapi/dist/index.mjs
3275
+ var dist_exports = {};
3276
+ __export(dist_exports, {
3277
+ OpenApiGenerator: () => OpenApiGenerator,
3278
+ Security: () => Security,
3279
+ defineSecuritySchemes: () => defineSecuritySchemes,
3280
+ useOpenAPI: () => useOpenAPI
3281
+ });
3282
+ function zodSchemaToOpenApi(schema) {
3283
+ const s = schema;
3284
+ if (typeof s.toJSONSchema === "function") {
3285
+ const full = s.toJSONSchema({ target: "openApi3_1" });
3286
+ const { $schema: _dropped, ...rest } = full;
3287
+ return rest;
3288
+ }
3289
+ try {
3290
+ const { zodToJsonSchema } = __require2("zod-to-json-schema");
3291
+ return zodToJsonSchema(schema, { target: "openApi3" });
3292
+ } catch {
3293
+ return { type: "object" };
3294
+ }
3295
+ }
3296
+ function isZodSchema(value) {
3297
+ return typeof value === "object" && value !== null && typeof value.safeParse === "function";
3298
+ }
3299
+ function escapeHtml(s) {
3300
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3301
+ }
3302
+ function escapeJsString(s) {
3303
+ return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
3304
+ }
3305
+ function defineSecuritySchemes(schemes) {
3306
+ return {
3307
+ schemes,
3308
+ require: (name, scopes = []) => [{ [name]: scopes }],
3309
+ requireMultiple: (requirements) => {
3310
+ const combined = {};
3311
+ requirements.forEach((req) => {
3312
+ combined[req] = [];
3313
+ });
3314
+ return [combined];
3315
+ }
3316
+ };
3317
+ }
3318
+ function inferSchemaFromPayload(data, depth = 0) {
3319
+ if (depth > 32) return { type: "object" };
3320
+ if (data === null) return { type: "null" };
3321
+ if (Array.isArray(data)) {
3322
+ return {
3323
+ type: "array",
3324
+ items: data.length > 0 ? inferSchemaFromPayload(data[0], depth + 1) : { type: "object" }
3325
+ };
3326
+ }
3327
+ if (typeof data === "object") {
3328
+ const properties = {};
3329
+ for (const [key, value] of Object.entries(data)) {
3330
+ properties[key] = inferSchemaFromPayload(value, depth + 1);
3331
+ }
3332
+ return { type: "object", properties };
3333
+ }
3334
+ return { type: typeof data };
3335
+ }
3336
+ function useOpenAPI(app, options) {
3337
+ const rawPrefix = options.prefix ?? "/docs";
3338
+ const normalizedPrefix = rawPrefix.startsWith("/") ? rawPrefix : `/${rawPrefix}`;
3339
+ const prefix = normalizedPrefix === "/" ? "/" : normalizedPrefix.endsWith("/") ? normalizedPrefix.slice(0, -1) : normalizedPrefix;
3340
+ const docsPaths = prefix === "/" ? ["/"] : [prefix, `${prefix}/`];
3341
+ const docsPathSet = new Set(docsPaths);
3342
+ const specPath = prefix === "/" ? "/openapi.json" : `${prefix}/openapi.json`;
3343
+ const generator = new OpenApiGenerator(app, options);
3344
+ let cachedSpec = null;
3345
+ let cachedSpecJson = null;
3346
+ let emittedPublicDocsWarning = false;
3347
+ if (options.autoInferResponses) {
3348
+ app.addHook("onPostHandler", (req, res, match) => {
3349
+ if (!match?.route) return;
3350
+ if (req.path === specPath || docsPathSet.has(req.path)) {
3351
+ return;
3352
+ }
3353
+ const payload = res.payload;
3354
+ if (payload === void 0) return;
3355
+ if (!cachedSpec) cachedSpec = generator.generate();
3356
+ const path11 = generator.formatPath(match.route.path);
3357
+ const method = match.route.method.toLowerCase();
3358
+ const statusCode = String(res.statusCode);
3359
+ const existingResponse = cachedSpec.paths[path11]?.[method]?.responses?.[statusCode];
3360
+ const isDefault = existingResponse?.description === "Successful response" && existingResponse?.content?.["application/json"]?.schema?.type === "object";
3361
+ if (existingResponse && !isDefault) return;
3362
+ let parsedData = payload;
3363
+ if (typeof payload === "string") {
3364
+ try {
3365
+ parsedData = JSON.parse(payload);
3366
+ } catch {
3367
+ }
3368
+ }
3369
+ if (cachedSpec.paths[path11]?.[method]) {
3370
+ cachedSpec.paths[path11][method].responses[statusCode] = {
3371
+ description: "Auto-inferred response",
3372
+ content: {
3373
+ "application/json": { schema: inferSchemaFromPayload(parsedData) }
3374
+ }
3375
+ };
3376
+ cachedSpecJson = null;
3377
+ }
3378
+ });
3379
+ }
3380
+ const guard = async (req) => {
3381
+ if (!options.protect) {
3382
+ if (process.env.NODE_ENV === "production") {
3383
+ if (!emittedPublicDocsWarning) {
3384
+ emittedPublicDocsWarning = true;
3385
+ console.warn(
3386
+ "[axiomify/openapi] OpenAPI endpoints are not protected. Production access is denied by default. Provide a `protect` function or set `allowPublicInProduction: true` explicitly."
3387
+ );
3388
+ }
3389
+ return options.allowPublicInProduction === true;
3390
+ }
3391
+ return true;
3392
+ }
3393
+ return Boolean(await options.protect(req));
3394
+ };
3395
+ app.route({
3396
+ method: "GET",
3397
+ path: specPath,
3398
+ handler: async (req, res) => {
3399
+ if (!await guard(req)) return res.status(403).send(null, "Forbidden");
3400
+ if (!cachedSpec) cachedSpec = generator.generate();
3401
+ if (!cachedSpecJson) cachedSpecJson = JSON.stringify(cachedSpec);
3402
+ res.status(200).sendRaw(cachedSpecJson, "application/json");
3403
+ }
3404
+ });
3405
+ const docsHandler = async (req, res) => {
3406
+ if (!await guard(req)) return res.status(403).send(null, "Forbidden");
3407
+ if (typeof res.setHeader === "function") {
3408
+ res.setHeader("Content-Security-Policy", DOCS_CSP);
3409
+ } else if (typeof res.header === "function") {
3410
+ res.header("Content-Security-Policy", DOCS_CSP);
3411
+ }
3412
+ const isDev = process.env.NODE_ENV !== "production";
3413
+ const specUrl = isDev ? `${specPath}?t=${Date.now()}` : specPath;
3414
+ const html = `<!DOCTYPE html>
3415
+ <html lang="en">
3416
+ <head>
3417
+ <meta charset="utf-8" />
3418
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
3419
+ <title>${escapeHtml(options.info.title)} - API Docs</title>
3420
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.11.0/swagger-ui.min.css" integrity="sha384-bIuUyBV7i6P7z/kPAs1oeBIf8PMIqVkPVDzzaOL+QH7kWmvCT9HDTWwGVs0L4/9Q" crossorigin="anonymous" referrerpolicy="no-referrer" />
3421
+ </head>
3422
+ <body style="margin: 0; padding: 0;">
3423
+ <div id="swagger-ui"></div>
3424
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.11.0/swagger-ui-bundle.min.js" integrity="sha384-XHDYRdiHvBq7oL4CtkiJKfdVVA5PydxYtssHVtRrvPlha1m+zz8kboiyx/MAsyl3" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
3425
+ <script>
3426
+ window.onload = () => {
3427
+ window.ui = SwaggerUIBundle({
3428
+ url: '${escapeJsString(specUrl)}',
3429
+ dom_id: '#swagger-ui',
3430
+ });
3431
+ };
3432
+ </script>
3433
+ </body>
3434
+ </html>`;
3435
+ res.status(200).sendRaw(html, "text/html");
3436
+ };
3437
+ app.route({
3438
+ method: "GET",
3439
+ path: prefix,
3440
+ handler: docsHandler
3441
+ });
3442
+ }
3443
+ var __require2, OpenApiGenerator, DOCS_CSP, Security;
3444
+ var init_dist = __esm({
3445
+ "../openapi/dist/index.mjs"() {
3446
+ __require2 = /* @__PURE__ */ ((x) => typeof __require !== "undefined" ? __require : typeof Proxy !== "undefined" ? new Proxy(x, {
3447
+ get: (a, b) => (typeof __require !== "undefined" ? __require : a)[b]
3448
+ }) : x)(function(x) {
3449
+ if (typeof __require !== "undefined") return __require.apply(this, arguments);
3450
+ throw Error('Dynamic require of "' + x + '" is not supported');
3451
+ });
3452
+ OpenApiGenerator = class {
3453
+ constructor(app, options) {
3454
+ this.app = app;
3455
+ this.options = options;
3456
+ }
3457
+ app;
3458
+ options;
3459
+ generate() {
3460
+ const spec = {
3461
+ openapi: "3.1.0",
3462
+ info: this.options.info,
3463
+ paths: {}
3464
+ };
3465
+ if (this.options.components) spec.components = this.options.components;
3466
+ if (this.options.security) spec.security = this.options.security;
3467
+ for (const route of this.app.registeredRoutes) {
3468
+ const openApiPath = this.formatPath(route.path);
3469
+ const method = route.method.toLowerCase();
3470
+ const paths = spec.paths;
3471
+ if (!paths[openApiPath]) paths[openApiPath] = {};
3472
+ const s = route.schema ?? {};
3473
+ const operation = {
3474
+ // OAS §4.8.10.2 — summary. Defaults to `${method} ${path}`.
3475
+ summary: s.summary ?? `${route.method} ${route.path}`,
3476
+ // OAS §4.8.10.5 — operationId for client codegen tools.
3477
+ // Auto-synthesised from method+path when omitted:
3478
+ // GET /users/:id → "getUsersById" POST /users → "postUsers"
3479
+ operationId: s.operationId ?? this.synthesiseOperationId(route.method, route.path),
3480
+ parameters: this.extractParameters(route),
3481
+ responses: this.extractResponses(route)
3482
+ };
3483
+ if (s.description) operation.description = s.description;
3484
+ if (s.tags) operation.tags = s.tags;
3485
+ if (s.security !== void 0) operation.security = s.security;
3486
+ if (s.deprecated) operation.deprecated = true;
3487
+ if (s.externalDocs) operation.externalDocs = s.externalDocs;
3488
+ if (s.servers) operation.servers = s.servers;
3489
+ if (s.callbacks) operation.callbacks = s.callbacks;
3490
+ const body = this.extractBody(route);
3491
+ if (body) {
3492
+ if (s.requestBodyDescription) body.description = s.requestBodyDescription;
3493
+ operation.requestBody = body;
3494
+ }
3495
+ paths[openApiPath][method] = operation;
3496
+ }
3497
+ return spec;
3498
+ }
3499
+ /** Translates Axiomify path syntax to OpenAPI: `/users/:id` → `/users/{id}` */
3500
+ formatPath(path11) {
3501
+ return path11.replace(/:([a-zA-Z0-9_]+)/g, "{$1}");
3502
+ }
3503
+ extractParameters(route) {
3504
+ const parameters = [];
3505
+ if (route.schema?.params) {
3506
+ const paramSchema = zodSchemaToOpenApi(route.schema.params);
3507
+ const properties = paramSchema.properties ?? {};
3508
+ for (const [key, prop] of Object.entries(properties)) {
3509
+ parameters.push({ name: key, in: "path", required: true, schema: prop });
3510
+ }
3511
+ }
3512
+ if (route.schema?.query) {
3513
+ const querySchema = zodSchemaToOpenApi(route.schema.query);
3514
+ const properties = querySchema.properties ?? {};
3515
+ const required = querySchema.required ?? [];
3516
+ for (const [key, prop] of Object.entries(properties)) {
3517
+ parameters.push({
3518
+ name: key,
3519
+ in: "query",
3520
+ required: required.includes(key),
3521
+ schema: prop
3522
+ });
3523
+ }
3524
+ }
3525
+ return parameters;
3526
+ }
3527
+ /**
3528
+ * Synthesise a stable, codegen-friendly operationId from method+path
3529
+ * when the route definition doesn't supply one. Example outputs:
3530
+ * GET /users/:id → getUsersById
3531
+ * POST /users → postUsers
3532
+ * GET /users/:id/posts/:pid → getUsersByIdPostsByPid
3533
+ *
3534
+ * Determinism matters here — client codegen produces the same function
3535
+ * names on every run as long as method+path are stable.
3536
+ */
3537
+ synthesiseOperationId(method, path11) {
3538
+ const verb = method.toLowerCase();
3539
+ const parts = [];
3540
+ for (const seg of path11.split("/")) {
3541
+ if (!seg) continue;
3542
+ if (seg.startsWith(":")) {
3543
+ const name = seg.slice(1);
3544
+ parts.push("By", name.charAt(0).toUpperCase() + name.slice(1));
3545
+ } else if (seg === "*") {
3546
+ parts.push("All");
3547
+ } else {
3548
+ parts.push(seg.charAt(0).toUpperCase() + seg.slice(1));
3549
+ }
3550
+ }
3551
+ return verb + parts.join("");
3552
+ }
3553
+ extractBody(route) {
3554
+ if (!route.schema?.body && !route.schema?.files) return void 0;
3555
+ const hasFiles = !!route.schema.files;
3556
+ const contentType = hasFiles ? "multipart/form-data" : "application/json";
3557
+ let finalSchema = { type: "object", properties: {} };
3558
+ if (route.schema.body) {
3559
+ const bodySchema = zodSchemaToOpenApi(route.schema.body);
3560
+ if (bodySchema.type === "object") {
3561
+ finalSchema.properties = { ...bodySchema.properties };
3562
+ if (bodySchema.required) finalSchema.required = bodySchema.required;
3563
+ if (bodySchema.additionalProperties !== void 0) {
3564
+ finalSchema.additionalProperties = bodySchema.additionalProperties;
3565
+ }
3566
+ } else {
3567
+ finalSchema = hasFiles ? { type: "object", properties: { payload: bodySchema } } : bodySchema;
3568
+ }
3569
+ }
3570
+ if (hasFiles) {
3571
+ const files = route.schema.files;
3572
+ const props = finalSchema.properties ?? {};
3573
+ for (const [fieldName, config] of Object.entries(files)) {
3574
+ props[fieldName] = {
3575
+ type: "string",
3576
+ format: "binary",
3577
+ ...config.description ? { description: config.description } : {},
3578
+ ...config.maxSize ? { description: `Max size: ${config.maxSize} bytes` } : {}
3579
+ };
3580
+ }
3581
+ finalSchema.properties = props;
3582
+ }
3583
+ return { required: true, content: { [contentType]: { schema: finalSchema } } };
3584
+ }
3585
+ extractResponses(route) {
3586
+ const descriptions = route.schema?.responseDescriptions ?? {};
3587
+ const defaultResponse = {
3588
+ "200": {
3589
+ description: descriptions["200"] ?? "Successful response",
3590
+ content: { "application/json": { schema: { type: "object" } } }
3591
+ }
3592
+ };
3593
+ if (!route.schema?.response) return defaultResponse;
3594
+ const responseSchema = route.schema.response;
3595
+ const responses = {};
3596
+ if (isZodSchema(responseSchema)) {
3597
+ responses["200"] = {
3598
+ description: descriptions["200"] ?? "Successful response",
3599
+ content: {
3600
+ "application/json": { schema: zodSchemaToOpenApi(responseSchema) }
3601
+ }
3602
+ };
3603
+ } else if (typeof responseSchema === "object" && responseSchema !== null) {
3604
+ for (const [code, schema] of Object.entries(
3605
+ responseSchema
3606
+ )) {
3607
+ responses[code] = {
3608
+ description: descriptions[code] ?? `Response ${code}`,
3609
+ content: {
3610
+ "application/json": { schema: zodSchemaToOpenApi(schema) }
3611
+ }
3612
+ };
3613
+ }
3614
+ }
3615
+ return Object.keys(responses).length > 0 ? responses : defaultResponse;
3616
+ }
3617
+ };
3618
+ DOCS_CSP = "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://unpkg.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: https://validator.swagger.io; worker-src 'self' blob:;";
3619
+ Security = defineSecuritySchemes({
3620
+ bearerAuth: { type: "http", scheme: "bearer" },
3621
+ apiKey: { type: "apiKey", in: "header", name: "X-API-KEY" },
3622
+ basicAuth: { type: "http", scheme: "basic" }
3623
+ });
3624
+ }
3625
+ });
3626
+
2907
3627
  // node_modules/commander/esm.mjs
2908
3628
  var import_index = __toESM(require_commander());
2909
3629
  var {
@@ -2923,12 +3643,12 @@ var {
2923
3643
 
2924
3644
  // package.json
2925
3645
  var package_default = {
2926
- version: "5.0.0"};
3646
+ version: "6.0.0"};
2927
3647
  var ALWAYS_EXTERNAL = ["uWebSockets.js"];
2928
3648
  function getUserExternals(cwd) {
2929
3649
  let pkgExternals = [];
2930
3650
  try {
2931
- const pkgPath = path4__default.default.join(cwd, "package.json");
3651
+ const pkgPath = path7__default.default.join(cwd, "package.json");
2932
3652
  if (fs__default.default.existsSync(pkgPath)) {
2933
3653
  const pkg = JSON.parse(fs__default.default.readFileSync(pkgPath, "utf8"));
2934
3654
  const deps = Object.keys(pkg.dependencies || {});
@@ -2946,8 +3666,8 @@ function getUserExternals(cwd) {
2946
3666
 
2947
3667
  // src/commands/build.ts
2948
3668
  async function buildProject(entry) {
2949
- const entryPath = path4__default.default.resolve(process.cwd(), entry);
2950
- const outPath = path4__default.default.resolve(process.cwd(), "dist/index.js");
3669
+ const entryPath = path7__default.default.resolve(process.cwd(), entry);
3670
+ const outPath = path7__default.default.resolve(process.cwd(), "dist/index.js");
2951
3671
  const userExternals = getUserExternals(process.cwd());
2952
3672
  console.log(`\u{1F528} Building production bundle from ${entry}...`);
2953
3673
  try {
@@ -2967,36 +3687,415 @@ async function buildProject(entry) {
2967
3687
  process.exit(1);
2968
3688
  }
2969
3689
  }
2970
- async function devServer(entry) {
2971
- const entryPath = path4__default.default.resolve(process.cwd(), entry);
2972
- const outPath = path4__default.default.resolve(process.cwd(), ".axiomify/dev.js");
2973
- let child = null;
2974
- let firstBuild = true;
2975
- const startChild = () => {
2976
- child = child_process.spawn("node", [outPath], { stdio: "inherit" });
2977
- child.on("error", (err) => {
2978
- console.error("\u274C Failed to start process:", err);
2979
- });
2980
- };
2981
- const GRACEFUL_KILL_MS = 3e3;
2982
- const restartServer = () => {
2983
- if (child && child.exitCode === null && child.signalCode === null) {
2984
- child.removeAllListeners("exit");
2985
- const oldChild = child;
2986
- oldChild.once("exit", () => {
2987
- startChild();
2988
- });
2989
- oldChild.kill("SIGTERM");
2990
- const forceKill = setTimeout(() => {
2991
- if (oldChild.exitCode === null && oldChild.signalCode === null) {
2992
- oldChild.kill("SIGKILL");
3690
+ function colourMethod(method) {
3691
+ const m = method.toUpperCase();
3692
+ const padded = m.padEnd(7);
3693
+ switch (m) {
3694
+ case "GET":
3695
+ return pc__default.default.bold(pc__default.default.green(padded));
3696
+ case "POST":
3697
+ return pc__default.default.bold(pc__default.default.blue(padded));
3698
+ case "PUT":
3699
+ return pc__default.default.bold(pc__default.default.yellow(padded));
3700
+ case "PATCH":
3701
+ return pc__default.default.bold(pc__default.default.magenta(padded));
3702
+ case "DELETE":
3703
+ return pc__default.default.bold(pc__default.default.red(padded));
3704
+ case "HEAD":
3705
+ return pc__default.default.dim(padded);
3706
+ case "OPTIONS":
3707
+ return pc__default.default.dim(padded);
3708
+ case "WS":
3709
+ return pc__default.default.bold(pc__default.default.cyan(padded));
3710
+ default:
3711
+ return padded;
3712
+ }
3713
+ }
3714
+ var badge = {
3715
+ validation(label) {
3716
+ return pc__default.default.cyan(label);
3717
+ },
3718
+ deprecated() {
3719
+ return pc__default.default.bold(pc__default.default.red("\u2298 DEPRECATED"));
3720
+ },
3721
+ timeout(ms) {
3722
+ return pc__default.default.dim(`${ms}ms`);
3723
+ },
3724
+ tags(tags) {
3725
+ if (!tags.length) return "";
3726
+ return tags.map((t) => pc__default.default.dim(`#${t}`)).join(" ");
3727
+ }
3728
+ };
3729
+ function visibleLength(s) {
3730
+ return s.replace(/\x1b\[[0-9;]*m/g, "").length;
3731
+ }
3732
+ function pad(s, width, align) {
3733
+ const v = visibleLength(s);
3734
+ if (v >= width) return s;
3735
+ const filler = " ".repeat(width - v);
3736
+ return align === "right" ? filler + s : s + filler;
3737
+ }
3738
+ function truncate(s, max) {
3739
+ if (visibleLength(s) <= max) return s;
3740
+ const stripped = s.replace(/\x1b\[[0-9;]*m/g, "");
3741
+ return stripped.slice(0, max - 1) + pc__default.default.dim("\u2026");
3742
+ }
3743
+ function renderTable(columns, rows, terminalWidth = process.stdout.columns || 100) {
3744
+ const widths = columns.map((col, i) => {
3745
+ const headerW = visibleLength(col.header);
3746
+ const cellW = Math.max(
3747
+ headerW,
3748
+ ...rows.map((r) => visibleLength(r[i] ?? ""))
3749
+ );
3750
+ let w = Math.max(headerW, cellW);
3751
+ if (col.minWidth) w = Math.max(w, col.minWidth);
3752
+ if (col.maxWidth) w = Math.min(w, col.maxWidth);
3753
+ return w;
3754
+ });
3755
+ const overheadPerSep = 3;
3756
+ const overhead = (columns.length + 1) * 2 + overheadPerSep * (columns.length - 1);
3757
+ let total = widths.reduce((a, b) => a + b, 0) + overhead;
3758
+ if (total > terminalWidth) {
3759
+ const flexIdx = columns.map((c, i) => ({ c, i })).filter(({ c }) => !c.minWidth).map(({ i }) => i);
3760
+ let excess = total - terminalWidth;
3761
+ for (let pass = 0; pass < 8 && excess > 0; pass++) {
3762
+ for (const i of flexIdx) {
3763
+ if (excess <= 0) break;
3764
+ if (widths[i] > 8) {
3765
+ widths[i]--;
3766
+ excess--;
3767
+ total--;
2993
3768
  }
2994
- }, GRACEFUL_KILL_MS);
2995
- forceKill.unref();
2996
- } else {
2997
- startChild();
3769
+ }
2998
3770
  }
2999
- };
3771
+ }
3772
+ const bar = (l, m, r) => l + widths.map((w) => "\u2500".repeat(w + 2)).join(m) + r;
3773
+ const lines = [];
3774
+ lines.push(pc__default.default.dim(bar("\u250C", "\u252C", "\u2510")));
3775
+ lines.push(
3776
+ pc__default.default.dim("\u2502 ") + columns.map((c, i) => pc__default.default.bold(pad(c.header, widths[i], c.align ?? "left"))).join(pc__default.default.dim(" \u2502 ")) + pc__default.default.dim(" \u2502")
3777
+ );
3778
+ lines.push(pc__default.default.dim(bar("\u251C", "\u253C", "\u2524")));
3779
+ for (const row of rows) {
3780
+ lines.push(
3781
+ pc__default.default.dim("\u2502 ") + columns.map((c, i) => {
3782
+ const cell = row[i] ?? "";
3783
+ const truncated = c.maxWidth ? truncate(cell, widths[i]) : cell;
3784
+ return pad(truncated, widths[i], c.align ?? "left");
3785
+ }).join(pc__default.default.dim(" \u2502 ")) + pc__default.default.dim(" \u2502")
3786
+ );
3787
+ }
3788
+ lines.push(pc__default.default.dim(bar("\u2514", "\u2534", "\u2518")));
3789
+ return lines.join("\n");
3790
+ }
3791
+ function pluralise(n, singular, plural) {
3792
+ return n === 1 ? `${n} ${singular}` : `${n} ${plural ?? singular + "s"}`;
3793
+ }
3794
+ var symbols = {
3795
+ ok: pc__default.default.green("\u2713"),
3796
+ warn: pc__default.default.yellow("\u26A0"),
3797
+ fail: pc__default.default.red("\u2717"),
3798
+ info: pc__default.default.cyan("\u2139"),
3799
+ bullet: pc__default.default.dim("\u2022"),
3800
+ arrow: pc__default.default.dim("\u2192")
3801
+ };
3802
+ async function loadApp(entry) {
3803
+ const entryPath = path7__default.default.resolve(process.cwd(), entry);
3804
+ const tempDir = path7__default.default.resolve(process.cwd(), ".axiomify");
3805
+ const tempPath = path7__default.default.join(tempDir, "inspect.cjs");
3806
+ const userExternals = getUserExternals(process.cwd());
3807
+ await esbuild__namespace.build({
3808
+ entryPoints: [entryPath],
3809
+ bundle: true,
3810
+ platform: "node",
3811
+ format: "cjs",
3812
+ outfile: tempPath,
3813
+ external: [.../* @__PURE__ */ new Set([...userExternals, "node:*"])],
3814
+ // Silence esbuild's own progress chatter — the CLI command above is
3815
+ // responsible for its own user-facing output.
3816
+ logLevel: "error"
3817
+ });
3818
+ try {
3819
+ delete __require.cache[__require.resolve(tempPath)];
3820
+ } catch {
3821
+ }
3822
+ const hangTimer = setTimeout(() => {
3823
+ process.stderr.write(
3824
+ "\n" + pc__default.default.yellow("\u26A0 CLI inspection is taking longer than expected.") + "\n Your entry file may be starting a server unconditionally.\n Wrap the listen() call in " + pc__default.default.cyan("if (require.main === module) { ... }") + " so it only runs when executed directly.\n\n"
3825
+ );
3826
+ }, 5e3);
3827
+ hangTimer.unref();
3828
+ let mod;
3829
+ try {
3830
+ mod = __require(tempPath);
3831
+ } finally {
3832
+ clearTimeout(hangTimer);
3833
+ }
3834
+ const app = mod.app ?? mod.default;
3835
+ if (!app || typeof app.registeredRoutes === "undefined") {
3836
+ await fs5__default.default.rm(tempDir, { recursive: true, force: true }).catch(() => {
3837
+ });
3838
+ throw new Error(
3839
+ "Could not find an exported Axiomify instance.\nEnsure your entry file exports the app:\n export const app = new Axiomify();\nor:\n export default app;"
3840
+ );
3841
+ }
3842
+ const cleanup = async () => {
3843
+ await fs5__default.default.rm(tempDir, { recursive: true, force: true }).catch(() => {
3844
+ });
3845
+ };
3846
+ return { app, cleanup };
3847
+ }
3848
+
3849
+ // src/commands/check.ts
3850
+ function add(ctx, f) {
3851
+ ctx.findings.push(f);
3852
+ }
3853
+ function checkRequestId(ctx) {
3854
+ const onRequest = ctx.app.hooks?.hooks?.onRequest ?? [];
3855
+ if (onRequest.length === 0) {
3856
+ add(ctx, {
3857
+ severity: "warn",
3858
+ area: "observability",
3859
+ message: "`app.enableRequestId()` has not been called",
3860
+ hint: "Distributed-trace correlation will be impossible without an X-Request-Id header. Add `app.enableRequestId()` after construction unless you handle this elsewhere."
3861
+ });
3862
+ return;
3863
+ }
3864
+ add(ctx, {
3865
+ severity: "ok",
3866
+ area: "observability",
3867
+ message: `onRequest hooks: ${onRequest.length} registered`
3868
+ });
3869
+ }
3870
+ function checkEnvVars(ctx) {
3871
+ const expectedInProd = ["JWT_SECRET", "NODE_ENV"];
3872
+ for (const key of expectedInProd) {
3873
+ if (!ctx.envKeys.has(key)) continue;
3874
+ if (process.env[key]) {
3875
+ add(ctx, { severity: "ok", area: "env", message: `${key} is set` });
3876
+ } else {
3877
+ add(ctx, {
3878
+ severity: "warn",
3879
+ area: "env",
3880
+ message: `${key} referenced in source but not set in environment`,
3881
+ hint: key === "JWT_SECRET" ? "Set this before deploying. Generate one via `node -e \"console.log(require('crypto').randomBytes(48).toString('base64'))\"`" : `Ensure ${key} is set in your deployment environment.`
3882
+ });
3883
+ }
3884
+ }
3885
+ }
3886
+ function checkResponseSchemas(ctx) {
3887
+ const routes = ctx.app.registeredRoutes ?? [];
3888
+ const missing = routes.filter(
3889
+ (r) => r.schema?.body && !r.schema?.response
3890
+ );
3891
+ if (missing.length > 0) {
3892
+ add(ctx, {
3893
+ severity: "warn",
3894
+ area: "validation",
3895
+ message: `${missing.length} route${missing.length === 1 ? "" : "s"} with body schema but no response schema`,
3896
+ hint: `Declaring \`schema.response\` pins the API contract \u2014 without it, internal model field names leak to clients and breaking changes go undetected. First offender: ${missing[0].method} ${missing[0].path}`
3897
+ });
3898
+ } else if (routes.length > 0) {
3899
+ add(ctx, {
3900
+ severity: "ok",
3901
+ area: "validation",
3902
+ message: "every route with a body schema also declares a response schema"
3903
+ });
3904
+ }
3905
+ }
3906
+ function checkOpenApiNaming(ctx) {
3907
+ const routes = ctx.app.registeredRoutes ?? [];
3908
+ const usingMeta = routes.filter((r) => r.meta);
3909
+ if (usingMeta.length > 0) {
3910
+ add(ctx, {
3911
+ severity: "fail",
3912
+ area: "api",
3913
+ message: `${usingMeta.length} route${usingMeta.length === 1 ? "" : "s"} use the removed \`meta:\` field`,
3914
+ hint: `The \`meta:\` field was removed in 6.0. Move all metadata into \`schema:\` \u2014 e.g. schema: { tags: ['Users'], summary: '...' }. First offender: ${usingMeta[0].method} ${usingMeta[0].path}`
3915
+ });
3916
+ }
3917
+ const usingOpenapi = routes.filter((r) => r.openapi);
3918
+ if (usingOpenapi.length > 0) {
3919
+ add(ctx, {
3920
+ severity: "fail",
3921
+ area: "api",
3922
+ message: `${usingOpenapi.length} route${usingOpenapi.length === 1 ? "" : "s"} use the removed top-level \`openapi:\` field`,
3923
+ hint: `The separate \`openapi:\` property was removed in 6.1. Move all metadata directly into \`schema:\` alongside your Zod fields. Run \`npx axiomify migrate\` to apply automatically. First offender: ${usingOpenapi[0].method} ${usingOpenapi[0].path}`
3924
+ });
3925
+ }
3926
+ }
3927
+ function checkHealthCheck(ctx) {
3928
+ const routes = ctx.app.registeredRoutes ?? [];
3929
+ const hasHealth = routes.some(
3930
+ (r) => r.method === "GET" && ["/health", "/healthz", "/-/health", "/ping", "/live", "/ready"].some(
3931
+ (p) => r.path === p
3932
+ )
3933
+ );
3934
+ if (hasHealth) {
3935
+ add(ctx, { severity: "ok", area: "ops", message: "health-check route registered" });
3936
+ } else {
3937
+ add(ctx, {
3938
+ severity: "warn",
3939
+ area: "ops",
3940
+ message: "no health-check route detected",
3941
+ hint: 'Kubernetes, ECS, and load balancers expect a `/health` (or similar) endpoint. Register one via `app.healthCheck("/health")` from `@axiomify/core`.'
3942
+ });
3943
+ }
3944
+ }
3945
+ function checkOpenApiExposure(ctx) {
3946
+ const routes = ctx.app.registeredRoutes ?? [];
3947
+ const docsRoute = routes.find(
3948
+ (r) => r.method === "GET" && (r.path === "/docs" || r.path.endsWith("/docs"))
3949
+ );
3950
+ const specRoute = routes.find(
3951
+ (r) => r.method === "GET" && r.path.endsWith("/openapi.json")
3952
+ );
3953
+ if (docsRoute || specRoute) {
3954
+ add(ctx, {
3955
+ severity: "warn",
3956
+ area: "security",
3957
+ message: "OpenAPI docs endpoint is registered",
3958
+ hint: "In production, supply `protect: (req) => ...` to `useOpenAPI()` (or set `allowPublicInProduction: true` if exposure is intentional). The runtime warning is logged on the first request."
3959
+ });
3960
+ }
3961
+ }
3962
+ function checkRoutesLockState(ctx) {
3963
+ if (ctx.app._routesLocked) {
3964
+ add(ctx, {
3965
+ severity: "warn",
3966
+ area: "config",
3967
+ message: "app.lockRoutes() has already been called",
3968
+ hint: "The entry file appears to construct an adapter at the top level. Wrap adapter construction in `if (require.main === module) { ... }` so the CLI can introspect the app without triggering it."
3969
+ });
3970
+ }
3971
+ }
3972
+ function checkSecurityPlugins(ctx) {
3973
+ const onRequest = ctx.app.hooks?.hooks?.onRequest ?? [];
3974
+ if (onRequest.length < 2) {
3975
+ add(ctx, {
3976
+ severity: "warn",
3977
+ area: "security",
3978
+ message: "few onRequest hooks detected \u2014 security plugins may not be registered",
3979
+ hint: "`@axiomify/helmet`, `@axiomify/cors`, and `@axiomify/security` each install onRequest hooks. If you are not using these, ensure equivalent defences are in place elsewhere."
3980
+ });
3981
+ } else {
3982
+ add(ctx, {
3983
+ severity: "ok",
3984
+ area: "security",
3985
+ message: `${onRequest.length} onRequest hooks registered (security plugins likely active)`
3986
+ });
3987
+ }
3988
+ }
3989
+ function collectEnvKeysFromBundle(bundlePath) {
3990
+ const keys = /* @__PURE__ */ new Set();
3991
+ try {
3992
+ const src = fs__default.default.readFileSync(bundlePath, "utf8");
3993
+ const re = /process\.env\.([A-Z][A-Z0-9_]*)|process\.env\[(['"])([A-Z][A-Z0-9_]*)\2\]/g;
3994
+ let m;
3995
+ while ((m = re.exec(src)) !== null) {
3996
+ keys.add(m[1] ?? m[3]);
3997
+ }
3998
+ } catch {
3999
+ }
4000
+ return keys;
4001
+ }
4002
+ function loadPkgJson(cwd) {
4003
+ try {
4004
+ return JSON.parse(fs__default.default.readFileSync(path7__default.default.join(cwd, "package.json"), "utf8"));
4005
+ } catch {
4006
+ return null;
4007
+ }
4008
+ }
4009
+ async function runCheck(entry) {
4010
+ let app;
4011
+ let cleanup = async () => {
4012
+ };
4013
+ let bundlePath = "";
4014
+ try {
4015
+ const loaded = await loadApp(entry);
4016
+ app = loaded.app;
4017
+ cleanup = loaded.cleanup;
4018
+ bundlePath = path7__default.default.resolve(process.cwd(), ".axiomify/inspect.cjs");
4019
+ } catch (err) {
4020
+ console.error(pc__default.default.red("\u2717 Failed to load app:"));
4021
+ console.error(err.message);
4022
+ process.exit(1);
4023
+ }
4024
+ const ctx = {
4025
+ app,
4026
+ cwd: process.cwd(),
4027
+ findings: [],
4028
+ pkgJson: loadPkgJson(process.cwd()),
4029
+ envKeys: collectEnvKeysFromBundle(bundlePath)
4030
+ };
4031
+ checkEnvVars(ctx);
4032
+ checkRequestId(ctx);
4033
+ checkRoutesLockState(ctx);
4034
+ checkOpenApiNaming(ctx);
4035
+ checkSecurityPlugins(ctx);
4036
+ checkOpenApiExposure(ctx);
4037
+ checkResponseSchemas(ctx);
4038
+ checkHealthCheck(ctx);
4039
+ await cleanup();
4040
+ console.log();
4041
+ console.log(pc__default.default.bold(" \u{1F50D} Production-readiness check"));
4042
+ console.log();
4043
+ const sevOrder = { fail: 0, warn: 1, ok: 2 };
4044
+ ctx.findings.sort(
4045
+ (a, b) => sevOrder[a.severity] - sevOrder[b.severity] || a.area.localeCompare(b.area)
4046
+ );
4047
+ const sym = {
4048
+ ok: symbols.ok,
4049
+ warn: symbols.warn,
4050
+ fail: symbols.fail
4051
+ };
4052
+ for (const f of ctx.findings) {
4053
+ const tag = pc__default.default.dim(`[${f.area}]`);
4054
+ console.log(` ${sym[f.severity]} ${tag} ${f.message}`);
4055
+ if (f.hint && f.severity !== "ok") {
4056
+ const wrapped = f.hint.replace(/(.{1,80})(\s+|$)/g, "\n " + pc__default.default.dim("$1"));
4057
+ console.log(wrapped);
4058
+ }
4059
+ }
4060
+ const fails = ctx.findings.filter((f) => f.severity === "fail").length;
4061
+ const warns = ctx.findings.filter((f) => f.severity === "warn").length;
4062
+ const oks = ctx.findings.filter((f) => f.severity === "ok").length;
4063
+ console.log();
4064
+ const summary = ` ${symbols.ok} ${pluralise(oks, "pass", "passes")}` + pc__default.default.dim(" \xB7 ") + (warns > 0 ? `${symbols.warn} ${pluralise(warns, "warning")}` : pc__default.default.dim("0 warnings")) + pc__default.default.dim(" \xB7 ") + (fails > 0 ? `${symbols.fail} ${pluralise(fails, "failure")}` : pc__default.default.dim("0 failures"));
4065
+ console.log(summary);
4066
+ console.log();
4067
+ if (fails > 0) process.exit(1);
4068
+ }
4069
+ async function devServer(entry) {
4070
+ const entryPath = path7__default.default.resolve(process.cwd(), entry);
4071
+ const outPath = path7__default.default.resolve(process.cwd(), ".axiomify/dev.js");
4072
+ let child = null;
4073
+ let firstBuild = true;
4074
+ const startChild = () => {
4075
+ child = child_process.spawn("node", [outPath], { stdio: "inherit" });
4076
+ child.on("error", (err) => {
4077
+ console.error("\u274C Failed to start process:", err);
4078
+ });
4079
+ };
4080
+ const GRACEFUL_KILL_MS = 3e3;
4081
+ const restartServer = () => {
4082
+ if (child && child.exitCode === null && child.signalCode === null) {
4083
+ child.removeAllListeners("exit");
4084
+ const oldChild = child;
4085
+ oldChild.once("exit", () => {
4086
+ startChild();
4087
+ });
4088
+ oldChild.kill("SIGTERM");
4089
+ const forceKill = setTimeout(() => {
4090
+ if (oldChild.exitCode === null && oldChild.signalCode === null) {
4091
+ oldChild.kill("SIGKILL");
4092
+ }
4093
+ }, GRACEFUL_KILL_MS);
4094
+ forceKill.unref();
4095
+ } else {
4096
+ startChild();
4097
+ }
4098
+ };
3000
4099
  const watchPlugin = {
3001
4100
  name: "watch-plugin",
3002
4101
  setup(build3) {
@@ -3049,6 +4148,213 @@ async function devServer(entry) {
3049
4148
  console.log(`\u{1F440} Axiomify Dev Engine watching for changes...`);
3050
4149
  await ctx.watch();
3051
4150
  }
4151
+ function add2(findings, f) {
4152
+ findings.push(f);
4153
+ }
4154
+ function probePort(port) {
4155
+ return new Promise((resolve) => {
4156
+ const server = net.createServer();
4157
+ server.once("error", (err) => {
4158
+ if (err.code === "EADDRINUSE") resolve("busy");
4159
+ else if (err.code === "EACCES") resolve("denied");
4160
+ else resolve("busy");
4161
+ });
4162
+ server.once("listening", () => {
4163
+ server.close(() => resolve("free"));
4164
+ });
4165
+ server.listen(port, "127.0.0.1");
4166
+ });
4167
+ }
4168
+ function checkNodeVersion(findings) {
4169
+ const major = parseInt(process.versions.node.split(".")[0], 10);
4170
+ if (major < 18) {
4171
+ add2(findings, {
4172
+ severity: "fail",
4173
+ area: "node",
4174
+ message: `Node ${process.versions.node} is below the supported minimum`,
4175
+ hint: "Axiomify requires Node 18 or later. Upgrade via nvm: `nvm install 22 && nvm use 22`."
4176
+ });
4177
+ } else if (major > 22) {
4178
+ add2(findings, {
4179
+ severity: "warn",
4180
+ area: "node",
4181
+ message: `Node ${process.versions.node} \u2014 uWebSockets.js has no prebuilt binary for this version`,
4182
+ hint: "Tests and benchmarks that need a real uWS listener will skip; the framework still builds. For a runnable production deploy, downgrade to Node 22 LTS."
4183
+ });
4184
+ } else {
4185
+ add2(findings, {
4186
+ severity: "ok",
4187
+ area: "node",
4188
+ message: `Node ${process.versions.node} (uWS prebuilt available)`
4189
+ });
4190
+ }
4191
+ }
4192
+ function checkPlatform(findings) {
4193
+ if (process.platform === "linux") {
4194
+ add2(findings, {
4195
+ severity: "ok",
4196
+ area: "platform",
4197
+ message: "Linux \u2014 SO_REUSEPORT clustering supported natively"
4198
+ });
4199
+ } else {
4200
+ add2(findings, {
4201
+ severity: "warn",
4202
+ area: "platform",
4203
+ message: `${process.platform} \u2014 \`listenClustered()\` requires \`allowUserspaceProxy: true\``,
4204
+ hint: "Clustering on non-Linux falls back to a userspace L4 proxy that adds two event-loop hops per byte. Single-process `listen()` is the recommended path on this OS."
4205
+ });
4206
+ }
4207
+ }
4208
+ function checkDependencyDrift(findings) {
4209
+ try {
4210
+ const pkgPath = path7__default.default.join(process.cwd(), "package.json");
4211
+ const pkg = JSON.parse(fs__default.default.readFileSync(pkgPath, "utf8"));
4212
+ const all = { ...pkg.dependencies, ...pkg.devDependencies };
4213
+ const axiomifyDeps = Object.entries(all).filter(
4214
+ ([k]) => k.startsWith("@axiomify/")
4215
+ );
4216
+ if (axiomifyDeps.length === 0) {
4217
+ add2(findings, {
4218
+ severity: "warn",
4219
+ area: "deps",
4220
+ message: "No @axiomify/* packages found in package.json",
4221
+ hint: "Run this from the root of a project that uses Axiomify."
4222
+ });
4223
+ return;
4224
+ }
4225
+ const versions = new Set(
4226
+ axiomifyDeps.map(([, v]) => v.replace(/^[\^~]/, "").replace(/^\*$/, "workspace"))
4227
+ );
4228
+ if (versions.size > 1) {
4229
+ add2(findings, {
4230
+ severity: "warn",
4231
+ area: "deps",
4232
+ message: `@axiomify/* packages are on ${versions.size} different versions`,
4233
+ hint: "Mixed @axiomify/* versions can cause subtle compat issues. Pin them all to the same version: " + [...versions].join(", ")
4234
+ });
4235
+ } else {
4236
+ add2(findings, {
4237
+ severity: "ok",
4238
+ area: "deps",
4239
+ message: `${axiomifyDeps.length} @axiomify/* packages aligned (${[...versions][0]})`
4240
+ });
4241
+ }
4242
+ } catch {
4243
+ add2(findings, {
4244
+ severity: "warn",
4245
+ area: "deps",
4246
+ message: "Could not read package.json",
4247
+ hint: "Run `axiomify doctor` from a project root."
4248
+ });
4249
+ }
4250
+ }
4251
+ function checkUwsLoads(findings) {
4252
+ try {
4253
+ require_uws();
4254
+ add2(findings, {
4255
+ severity: "ok",
4256
+ area: "uws",
4257
+ message: "uWebSockets.js loads successfully"
4258
+ });
4259
+ } catch (err) {
4260
+ const msg = String(err.message ?? err);
4261
+ if (msg.includes("Cannot find module")) {
4262
+ add2(findings, {
4263
+ severity: "warn",
4264
+ area: "uws",
4265
+ message: "uWebSockets.js is not installed in this project",
4266
+ hint: "It is a peer dependency of `@axiomify/native`. Install via `npm install --save-optional uWebSockets.js` (the package handles platform selection)."
4267
+ });
4268
+ } else {
4269
+ add2(findings, {
4270
+ severity: "fail",
4271
+ area: "uws",
4272
+ message: "uWebSockets.js native binding failed to load",
4273
+ hint: msg.length > 200 ? msg.slice(0, 200) + "\u2026" : msg
4274
+ });
4275
+ }
4276
+ }
4277
+ }
4278
+ async function checkPortAvailability(findings) {
4279
+ const port = parseInt(process.env.PORT ?? "3000", 10);
4280
+ const state = await probePort(port);
4281
+ if (state === "free") {
4282
+ add2(findings, {
4283
+ severity: "ok",
4284
+ area: "port",
4285
+ message: `Port ${port} is available on 127.0.0.1`
4286
+ });
4287
+ } else if (state === "busy") {
4288
+ add2(findings, {
4289
+ severity: "warn",
4290
+ area: "port",
4291
+ message: `Port ${port} is already in use`,
4292
+ hint: "Stop the conflicting process or set `PORT` to a different value."
4293
+ });
4294
+ } else {
4295
+ add2(findings, {
4296
+ severity: "warn",
4297
+ area: "port",
4298
+ message: `Port ${port}: bind denied (permission)`,
4299
+ hint: "Ports below 1024 typically require root. Use a port \u2265 1024 in development."
4300
+ });
4301
+ }
4302
+ }
4303
+ function checkBuildArtifacts(findings) {
4304
+ const dist = path7__default.default.join(process.cwd(), "dist");
4305
+ if (fs__default.default.existsSync(dist)) {
4306
+ add2(findings, {
4307
+ severity: "ok",
4308
+ area: "build",
4309
+ message: "dist/ exists (recent `axiomify build`)"
4310
+ });
4311
+ } else {
4312
+ add2(findings, {
4313
+ severity: "warn",
4314
+ area: "build",
4315
+ message: "No dist/ directory \u2014 production build has not been run",
4316
+ hint: "Run `axiomify build` before deploying."
4317
+ });
4318
+ }
4319
+ }
4320
+ async function runDoctor() {
4321
+ const findings = [];
4322
+ checkNodeVersion(findings);
4323
+ checkPlatform(findings);
4324
+ checkDependencyDrift(findings);
4325
+ checkUwsLoads(findings);
4326
+ checkBuildArtifacts(findings);
4327
+ await checkPortAvailability(findings);
4328
+ console.log();
4329
+ console.log(pc__default.default.bold(" \u{1FA7A} Axiomify doctor"));
4330
+ console.log();
4331
+ const sevOrder = { fail: 0, warn: 1, ok: 2 };
4332
+ findings.sort(
4333
+ (a, b) => sevOrder[a.severity] - sevOrder[b.severity] || a.area.localeCompare(b.area)
4334
+ );
4335
+ const sym = {
4336
+ ok: symbols.ok,
4337
+ warn: symbols.warn,
4338
+ fail: symbols.fail
4339
+ };
4340
+ for (const f of findings) {
4341
+ const tag = pc__default.default.dim(`[${f.area}]`);
4342
+ console.log(` ${sym[f.severity]} ${tag} ${f.message}`);
4343
+ if (f.hint && f.severity !== "ok") {
4344
+ const wrapped = f.hint.replace(/(.{1,80})(\s+|$)/g, "\n " + pc__default.default.dim("$1"));
4345
+ console.log(wrapped);
4346
+ }
4347
+ }
4348
+ const fails = findings.filter((f) => f.severity === "fail").length;
4349
+ const warns = findings.filter((f) => f.severity === "warn").length;
4350
+ const oks = findings.filter((f) => f.severity === "ok").length;
4351
+ console.log();
4352
+ console.log(
4353
+ ` ${symbols.ok} ${pluralise(oks, "pass", "passes")}` + pc__default.default.dim(" \xB7 ") + (warns > 0 ? `${symbols.warn} ${pluralise(warns, "warning")}` : pc__default.default.dim("0 warnings")) + pc__default.default.dim(" \xB7 ") + (fails > 0 ? `${symbols.fail} ${pluralise(fails, "failure")}` : pc__default.default.dim("0 failures"))
4354
+ );
4355
+ console.log();
4356
+ if (fails > 0) process.exit(1);
4357
+ }
3052
4358
  var DEV_COMMAND_BY_PM = {
3053
4359
  npm: "npm run dev",
3054
4360
  pnpm: "pnpm dev",
@@ -3066,20 +4372,6 @@ async function initProject(targetDir, options = {}) {
3066
4372
  });
3067
4373
  }
3068
4374
  questions.push(
3069
- {
3070
- type: "select",
3071
- name: "adapter",
3072
- message: "Which HTTP adapter do you want to use?",
3073
- choices: [
3074
- "Native (uWS \u2014 Fastest, 50k+ req/s)",
3075
- "Fastify (High-throughput, recommended)",
3076
- "Express (Max ecosystem compatibility)",
3077
- "Hapi (Enterprise, plugin-first)",
3078
- "Node HTTP (Zero dependency)"
3079
- ],
3080
- initial: 0
3081
- // Native is the recommended default
3082
- },
3083
4375
  {
3084
4376
  type: "input",
3085
4377
  name: "description",
@@ -3133,12 +4425,12 @@ async function initProject(targetDir, options = {}) {
3133
4425
  );
3134
4426
  process.exit(1);
3135
4427
  }
3136
- const dir = path4__default.default.resolve(process.cwd(), projectName);
4428
+ const dir = path7__default.default.resolve(process.cwd(), projectName);
3137
4429
  if (fs.existsSync(dir) && !options.force && targetDir) {
3138
4430
  const targets = [
3139
- path4__default.default.join(dir, "package.json"),
3140
- path4__default.default.join(dir, "tsconfig.json"),
3141
- path4__default.default.join(dir, "src", "index.ts")
4431
+ path7__default.default.join(dir, "package.json"),
4432
+ path7__default.default.join(dir, "tsconfig.json"),
4433
+ path7__default.default.join(dir, "src", "index.ts")
3142
4434
  ];
3143
4435
  const collisions = targets.filter((p) => fs.existsSync(p));
3144
4436
  if (collisions.length > 0) {
@@ -3150,28 +4442,11 @@ async function initProject(targetDir, options = {}) {
3150
4442
  process.exit(1);
3151
4443
  }
3152
4444
  }
3153
- await fs2__default.default.mkdir(path4__default.default.join(dir, "src"), { recursive: true });
4445
+ await fs5__default.default.mkdir(path7__default.default.join(dir, "src"), { recursive: true });
3154
4446
  const AXIOMIFY_VERSION = `^${package_default.version}`;
3155
- let adapterPackage = "@axiomify/native";
3156
- let adapterImport = "import { NativeAdapter } from '@axiomify/native';";
3157
- let adapterInit = "const server = new NativeAdapter(app, { port: 3000 });\n server.listen(() => console.log(' Axiomify Native on :3000'));";
3158
- if (answers.adapter.includes("Fastify")) {
3159
- adapterPackage = "@axiomify/fastify";
3160
- adapterImport = "import { FastifyAdapter } from '@axiomify/fastify';";
3161
- adapterInit = "const server = new FastifyAdapter(app);\n await server.listen(3000);\n console.log(' Axiomify Fastify on :3000');";
3162
- } else if (answers.adapter.includes("Express")) {
3163
- adapterPackage = "@axiomify/express";
3164
- adapterImport = "import { ExpressAdapter } from '@axiomify/express';";
3165
- adapterInit = "const server = new ExpressAdapter(app);\n server.listen(3000, () => console.log(' Axiomify Express on :3000'));";
3166
- } else if (answers.adapter.includes("Hapi")) {
3167
- adapterPackage = "@axiomify/hapi";
3168
- adapterImport = "import { HapiAdapter } from '@axiomify/hapi';";
3169
- adapterInit = "const server = new HapiAdapter(app);\n await server.listen(3000);\n console.log(' Axiomify Hapi on :3000');";
3170
- } else if (answers.adapter.includes("HTTP")) {
3171
- adapterPackage = "@axiomify/http";
3172
- adapterImport = "import { HttpAdapter } from '@axiomify/http';";
3173
- adapterInit = "const server = new HttpAdapter(app);\n server.listen(3000, () => console.log(' Axiomify HTTP on :3000'));";
3174
- }
4447
+ const adapterPackage = "@axiomify/native";
4448
+ const adapterImport = "import { NativeAdapter } from '@axiomify/native';";
4449
+ const adapterInit = "const server = new NativeAdapter(app, { port: 3000 });\n server.listen(() => console.log(' Axiomify Native on :3000'));";
3175
4450
  const pkgJson = {
3176
4451
  name: projectName,
3177
4452
  version: "1.0.0",
@@ -3239,14 +4514,14 @@ async function initProject(targetDir, options = {}) {
3239
4514
  "printWidth": 100,
3240
4515
  "tabWidth": 2
3241
4516
  }`;
3242
- await fs2__default.default.writeFile(path4__default.default.join(dir, ".eslintrc.cjs"), eslintConfig);
3243
- await fs2__default.default.writeFile(path4__default.default.join(dir, ".prettierrc"), prettierConfig);
3244
- await fs2__default.default.writeFile(
3245
- path4__default.default.join(dir, ".prettierignore"),
4517
+ await fs5__default.default.writeFile(path7__default.default.join(dir, ".eslintrc.cjs"), eslintConfig);
4518
+ await fs5__default.default.writeFile(path7__default.default.join(dir, ".prettierrc"), prettierConfig);
4519
+ await fs5__default.default.writeFile(
4520
+ path7__default.default.join(dir, ".prettierignore"),
3246
4521
  "dist\nnode_modules\ncoverage\n"
3247
4522
  );
3248
- await fs2__default.default.writeFile(
3249
- path4__default.default.join(dir, ".editorconfig"),
4523
+ await fs5__default.default.writeFile(
4524
+ path7__default.default.join(dir, ".editorconfig"),
3250
4525
  "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
3251
4526
  );
3252
4527
  }
@@ -3307,19 +4582,19 @@ async function initProject(targetDir, options = {}) {
3307
4582
  "coverage",
3308
4583
  "*.log"
3309
4584
  ].join("\n") + "\n";
3310
- await fs2__default.default.writeFile(
3311
- path4__default.default.join(dir, "package.json"),
4585
+ await fs5__default.default.writeFile(
4586
+ path7__default.default.join(dir, "package.json"),
3312
4587
  JSON.stringify(pkgJson, null, 2)
3313
4588
  );
3314
- await fs2__default.default.writeFile(
3315
- path4__default.default.join(dir, "tsconfig.json"),
4589
+ await fs5__default.default.writeFile(
4590
+ path7__default.default.join(dir, "tsconfig.json"),
3316
4591
  JSON.stringify(tsConfig, null, 2)
3317
4592
  );
3318
- await fs2__default.default.writeFile(path4__default.default.join(dir, "src", "index.ts"), indexTs);
3319
- await fs2__default.default.writeFile(path4__default.default.join(dir, ".gitignore"), gitignore);
4593
+ await fs5__default.default.writeFile(path7__default.default.join(dir, "src", "index.ts"), indexTs);
4594
+ await fs5__default.default.writeFile(path7__default.default.join(dir, ".gitignore"), gitignore);
3320
4595
  console.log(pc__default.default.green(`
3321
4596
  \u2705 Axiomify project initialized in ${pc__default.default.bold(dir)}`));
3322
- if (answers.useGit && !fs.existsSync(path4__default.default.join(dir, ".git"))) {
4597
+ if (answers.useGit && !fs.existsSync(path7__default.default.join(dir, ".git"))) {
3323
4598
  try {
3324
4599
  await execa.execa("git", ["init"], { cwd: dir });
3325
4600
  console.log(pc__default.default.green("\u2705 Git repository initialized"));
@@ -3353,63 +4628,644 @@ async function initProject(targetDir, options = {}) {
3353
4628
  \u{1F525} Run "${devCommand}" to start your development server!`)
3354
4629
  );
3355
4630
  }
3356
- async function inspectRoutes(entry) {
3357
- const entryPath = path4__default.default.resolve(process.cwd(), entry);
3358
- const tempPath = path4__default.default.resolve(process.cwd(), ".axiomify/inspect.cjs");
3359
- const userExternals = getUserExternals(process.cwd());
3360
- try {
3361
- await esbuild__namespace.build({
3362
- entryPoints: [entryPath],
3363
- bundle: true,
3364
- platform: "node",
3365
- format: "cjs",
3366
- outfile: tempPath,
3367
- external: [.../* @__PURE__ */ new Set([...userExternals, "node:*"])]
3368
- });
4631
+ var RULES = [
4632
+ {
4633
+ id: "meta-to-schema",
4634
+ description: "`meta:` route field removed \u2014 metadata now lives inside `schema:` alongside Zod fields",
4635
+ // NOTE: This rule renames `meta:` → a comment directing the dev to merge
4636
+ // contents into schema:. A full structural AST merge is out of scope for
4637
+ // the regex codemod; flag it for manual review instead (see report).
4638
+ match: /^(\s*)meta:(\s*\{)/gm,
4639
+ replace: "$1/* TODO(axiomify-migrate): merge meta fields into schema: */ openapi_REMOVE:$2"
4640
+ },
4641
+ {
4642
+ id: "openapi-field-to-schema",
4643
+ description: "`openapi:` top-level route field \u2192 contents merged into `schema:` (removed in 6.1)",
4644
+ // Same conservative approach: flag for manual review via TODO comment.
4645
+ match: /^(\s*)openapi:(\s*\{)/gm,
4646
+ replace: "$1/* TODO(axiomify-migrate): merge openapi fields into schema: */ openapi_REMOVE:$2"
4647
+ },
4648
+ {
4649
+ id: "useSwagger-import",
4650
+ description: "`useSwagger` import \u2192 `useOpenAPI` (the function was never named `useSwagger` in shipped code \u2014 docs were wrong)",
4651
+ match: /\buseSwagger\b/g,
4652
+ replace: "useOpenAPI"
4653
+ },
4654
+ {
4655
+ id: "routePrefix-option",
4656
+ description: "`routePrefix:` \u2192 `prefix:` on `useOpenAPI()` options",
4657
+ match: /(\buseOpenAPI\s*\([\s\S]*?)\brouteprefix(\s*:)/gi,
4658
+ // Naive: just rename the property when it appears inside a useOpenAPI() call.
4659
+ // The capture-group lookbehind avoids touching unrelated `routePrefix`
4660
+ // properties in other contexts.
4661
+ replace: (_match, before, suffix) => `${before}prefix${suffix}`
4662
+ },
4663
+ {
4664
+ id: "RouteMeta-type",
4665
+ description: "`RouteMeta` type \u2192 `OpenApiOperation` (alias removed in 6.0)",
4666
+ // Match `RouteMeta` only as a type position (after `:` or `<` or
4667
+ // `as`) — avoids hitting an unrelated variable named `RouteMeta`.
4668
+ match: /(:\s*|<\s*|\bas\s+)RouteMeta\b/g,
4669
+ replace: "$1OpenApiOperation"
4670
+ },
4671
+ {
4672
+ id: "AppPlugin-type",
4673
+ description: "`AppPlugin` type alias \u2192 `AppConfigurator` (removed in 5.0; runtime accepts 1-arg fns identically)",
4674
+ match: /(:\s*|<\s*|\bas\s+)AppPlugin\b/g,
4675
+ replace: "$1AppConfigurator"
4676
+ }
4677
+ ];
4678
+ async function listSourceFiles(rootAbs) {
4679
+ const out = [];
4680
+ const skip = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".axiomify", "coverage"]);
4681
+ const walk = async (dir) => {
4682
+ let entries;
3369
4683
  try {
3370
- delete __require.cache[__require.resolve(tempPath)];
3371
- } catch (e) {
4684
+ entries = await fs5__default.default.readdir(dir, { withFileTypes: true });
4685
+ } catch {
4686
+ return;
3372
4687
  }
3373
- const inspectionTimeout = setTimeout(() => {
3374
- console.warn(
3375
- "\n\u26A0\uFE0F Route inspection is taking longer than expected.\n Your entry file may be starting a server unconditionally.\n Wrap the listen() call in `if (require.main === module) { ... }`\n so it only runs when the file is executed directly.\n"
3376
- );
3377
- }, 5e3);
3378
- inspectionTimeout.unref();
3379
- const mod = __require(tempPath);
3380
- const app = mod.app || mod.default;
3381
- if (!app || typeof app.registeredRoutes === "undefined") {
3382
- console.error("\u274C Error: Could not find an exported Axiomify instance.");
4688
+ for (const e of entries) {
4689
+ if (e.isDirectory()) {
4690
+ if (skip.has(e.name) || e.name.startsWith(".")) continue;
4691
+ await walk(path7__default.default.join(dir, e.name));
4692
+ } else if (e.isFile()) {
4693
+ const ext = path7__default.default.extname(e.name);
4694
+ if ([".ts", ".tsx", ".js", ".mjs", ".cjs"].includes(ext)) {
4695
+ out.push(path7__default.default.join(dir, e.name));
4696
+ }
4697
+ }
4698
+ }
4699
+ };
4700
+ await walk(rootAbs);
4701
+ return out;
4702
+ }
4703
+ function applyRules(src) {
4704
+ let updated = src;
4705
+ const counts = {};
4706
+ for (const rule of RULES) {
4707
+ const before = updated;
4708
+ if (typeof rule.replace === "string") {
4709
+ updated = updated.replace(rule.match, rule.replace);
4710
+ } else {
4711
+ updated = updated.replace(rule.match, rule.replace);
4712
+ }
4713
+ if (updated !== before) {
4714
+ const matches = before.match(rule.match);
4715
+ counts[rule.id] = matches ? matches.length : 1;
4716
+ }
4717
+ }
4718
+ return { updated, counts };
4719
+ }
4720
+ function renderUnifiedDiff(file, original, updated) {
4721
+ if (original === updated) return "";
4722
+ const origLines = original.split("\n");
4723
+ const updatedLines = updated.split("\n");
4724
+ const out = [];
4725
+ out.push(pc__default.default.bold(`--- ${file}`));
4726
+ out.push(pc__default.default.bold(`+++ ${file}`));
4727
+ const max = Math.max(origLines.length, updatedLines.length);
4728
+ for (let i = 0; i < max; i++) {
4729
+ const a = origLines[i];
4730
+ const b = updatedLines[i];
4731
+ if (a === b) continue;
4732
+ if (a !== void 0) out.push(pc__default.default.red("- " + a));
4733
+ if (b !== void 0) out.push(pc__default.default.green("+ " + b));
4734
+ }
4735
+ return out.join("\n");
4736
+ }
4737
+ async function runMigrate(opts = {}) {
4738
+ const dir = opts.dir ?? "src";
4739
+ const rootAbs = path7__default.default.resolve(process.cwd(), dir);
4740
+ try {
4741
+ const stat = await fs5__default.default.stat(rootAbs);
4742
+ if (!stat.isDirectory()) throw new Error("not a directory");
4743
+ } catch {
4744
+ console.error(
4745
+ pc__default.default.red(`\u2717 ${dir} does not exist or is not a directory.`),
4746
+ `
4747
+ Run from a project root that contains the directory you want to migrate.`
4748
+ );
4749
+ process.exit(1);
4750
+ }
4751
+ const files = await listSourceFiles(rootAbs);
4752
+ if (files.length === 0) {
4753
+ console.log(`${symbols.info} No source files found under ${pc__default.default.cyan(dir)}.`);
4754
+ return;
4755
+ }
4756
+ const results = [];
4757
+ for (const f of files) {
4758
+ const original = await fs5__default.default.readFile(f, "utf8");
4759
+ const { updated, counts } = applyRules(original);
4760
+ if (Object.keys(counts).length > 0) {
4761
+ results.push({ file: f, counts, original, updated });
4762
+ }
4763
+ }
4764
+ console.log();
4765
+ console.log(pc__default.default.bold(" \u{1F504} Axiomify v4 \u2192 v5 migration"));
4766
+ console.log(
4767
+ pc__default.default.dim(
4768
+ ` Scanned ${pluralise(files.length, "file")} under ${path7__default.default.relative(process.cwd(), rootAbs) || "."}/.
4769
+ `
4770
+ )
4771
+ );
4772
+ if (results.length === 0) {
4773
+ console.log(` ${symbols.ok} Nothing to migrate \u2014 all patterns look up to date.`);
4774
+ console.log();
4775
+ return;
4776
+ }
4777
+ const totalsByRule = {};
4778
+ for (const r of results) {
4779
+ for (const [rule, n] of Object.entries(r.counts)) {
4780
+ totalsByRule[rule] = (totalsByRule[rule] ?? 0) + n;
4781
+ }
4782
+ }
4783
+ for (const rule of RULES) {
4784
+ const count = totalsByRule[rule.id];
4785
+ if (!count) continue;
4786
+ console.log(
4787
+ ` ${pc__default.default.cyan(rule.id)} ${pc__default.default.dim("\u2014")} ${rule.description}`
4788
+ );
4789
+ console.log(
4790
+ ` ${symbols.bullet} ${pluralise(count, "change")} across ${pluralise(
4791
+ results.filter((r) => r.counts[rule.id]).length,
4792
+ "file"
4793
+ )}`
4794
+ );
4795
+ }
4796
+ console.log();
4797
+ if (opts.reportOnly) {
4798
+ console.log(pc__default.default.dim(" --report-only: no files were modified."));
4799
+ console.log();
4800
+ return;
4801
+ }
4802
+ if (opts.dryRun) {
4803
+ for (const r of results) {
4804
+ const rel = path7__default.default.relative(process.cwd(), r.file);
4805
+ console.log(renderUnifiedDiff(rel, r.original, r.updated));
4806
+ console.log();
4807
+ }
4808
+ console.log(
4809
+ `${symbols.info} ${pluralise(results.length, "file")} would be modified. Re-run without ${pc__default.default.cyan("--dry-run")} to apply.`
4810
+ );
4811
+ console.log();
4812
+ return;
4813
+ }
4814
+ for (const r of results) {
4815
+ await fs5__default.default.writeFile(r.file, r.updated, "utf8");
4816
+ console.log(` ${symbols.ok} ${pc__default.default.green("Updated")} ${path7__default.default.relative(process.cwd(), r.file)}`);
4817
+ }
4818
+ console.log();
4819
+ console.log(
4820
+ ` ${symbols.ok} ${pluralise(results.length, "file")} migrated, ${pluralise(
4821
+ Object.values(totalsByRule).reduce((a, b) => a + b, 0),
4822
+ "total change"
4823
+ )} applied.`
4824
+ );
4825
+ console.log();
4826
+ console.log(pc__default.default.dim(" Manual review needed for:"));
4827
+ console.log(
4828
+ pc__default.default.dim(
4829
+ ` ${symbols.bullet} Dangling \`AppPlugin\` / \`RouteMeta\` in import statements \u2014 the codemod renames`
4830
+ )
4831
+ );
4832
+ console.log(
4833
+ pc__default.default.dim(
4834
+ ` type USAGES but not the import bindings themselves. TypeScript flags the unused`
4835
+ )
4836
+ );
4837
+ console.log(
4838
+ pc__default.default.dim(
4839
+ ` import; remove it (or run \`tsc --noUnusedLocals\` once and let your editor clean up).`
4840
+ )
4841
+ );
4842
+ console.log(
4843
+ pc__default.default.dim(
4844
+ ` ${symbols.bullet} 5-arg positional \`SerializerFn\` signatures \u2014 the function body needs by-hand updates`
4845
+ )
4846
+ );
4847
+ console.log(
4848
+ pc__default.default.dim(
4849
+ ` ${symbols.bullet} \`new Axiomify()\` callers that relied on automatic \`X-Request-Id\` injection`
4850
+ )
4851
+ );
4852
+ console.log(
4853
+ pc__default.default.dim(
4854
+ ` ${symbols.bullet} JWT secrets \u2014 verify they are \u2265 32 BYTES (not chars) per RFC 7518 \xA73.2`
4855
+ )
4856
+ );
4857
+ console.log();
4858
+ console.log(
4859
+ ` See ${pc__default.default.cyan("docs/migration-v4-to-v5.md")} for the full guide and ` + pc__default.default.cyan("axiomify check") + " to verify the migrated app.\n" + pc__default.default.yellow(" Note: `openapi:` / `meta:` merges into `schema:` require manual review \u2014 check TODO comments.")
4860
+ );
4861
+ console.log();
4862
+ }
4863
+ async function jsonToYaml(obj) {
4864
+ const emit = (v, indent) => {
4865
+ const pad2 = " ".repeat(indent);
4866
+ if (v === null) return "null";
4867
+ if (typeof v === "boolean" || typeof v === "number") return String(v);
4868
+ if (typeof v === "string") {
4869
+ if (/[:#\n\r\t"'{}[\]&*!|>%@`]|^\s|\s$/.test(v) || v === "") {
4870
+ return JSON.stringify(v);
4871
+ }
4872
+ return v;
4873
+ }
4874
+ if (Array.isArray(v)) {
4875
+ if (v.length === 0) return "[]";
4876
+ return v.map((item) => `
4877
+ ${pad2}- ${emit(item, indent + 1).replace(/^/gm, " ").trimStart()}`).join("");
4878
+ }
4879
+ if (typeof v === "object") {
4880
+ const keys = Object.keys(v);
4881
+ if (keys.length === 0) return "{}";
4882
+ return keys.map((k) => {
4883
+ const val = v[k];
4884
+ const rendered = emit(val, indent + 1);
4885
+ if (rendered.startsWith("\n")) return `
4886
+ ${pad2}${k}:${rendered}`;
4887
+ return `
4888
+ ${pad2}${k}: ${rendered}`;
4889
+ }).join("");
4890
+ }
4891
+ return JSON.stringify(v);
4892
+ };
4893
+ return emit(obj, 0).trimStart();
4894
+ }
4895
+ async function emitOpenApi(entry, opts = {}) {
4896
+ let app;
4897
+ let cleanup = async () => {
4898
+ };
4899
+ try {
4900
+ const loaded = await loadApp(entry);
4901
+ app = loaded.app;
4902
+ cleanup = loaded.cleanup;
4903
+ } catch (err) {
4904
+ console.error(pc__default.default.red("\u2717 Failed to load app:"));
4905
+ console.error(err.message);
4906
+ process.exit(1);
4907
+ }
4908
+ try {
4909
+ let OpenApiGenerator2;
4910
+ try {
4911
+ ({ OpenApiGenerator: OpenApiGenerator2 } = await Promise.resolve().then(() => (init_dist(), dist_exports)));
4912
+ } catch {
3383
4913
  console.error(
3384
- "Ensure your entry file exports the app: `export const app = new Axiomify();`"
4914
+ pc__default.default.red("\u2717 @axiomify/openapi is not installed."),
4915
+ "\n Install it:",
4916
+ pc__default.default.cyan("npm install @axiomify/openapi")
3385
4917
  );
3386
4918
  process.exit(1);
3387
4919
  }
3388
- console.log("\n\u{1F9ED} Registered Axiomify Routes:");
3389
- console.log("----------------------------------------------------");
3390
- console.log(`${"METHOD".padEnd(10)} | ${"PATH".padEnd(30)} | VALIDATION`);
3391
- console.log("----------------------------------------------------");
3392
- app.registeredRoutes.forEach((route) => {
3393
- const schemas = [];
3394
- if (route.schema?.body) schemas.push("Body");
3395
- if (route.schema?.query) schemas.push("Query");
3396
- if (route.schema?.params) schemas.push("Params");
3397
- if (route.schema?.response) schemas.push("Response");
3398
- if (route.schema?.files) schemas.push("Files");
3399
- const validationStr = schemas.length > 0 ? schemas.join(", ") : "None";
4920
+ const info = {
4921
+ title: opts.title ?? "API",
4922
+ version: opts.version ?? "1.0.0"
4923
+ };
4924
+ const generator = new OpenApiGenerator2(app, { info });
4925
+ const spec = generator.generate();
4926
+ if (opts.title) spec.info.title = opts.title;
4927
+ if (opts.version) spec.info.version = opts.version;
4928
+ const format = opts.format ?? "json";
4929
+ const serialised = format === "yaml" ? await jsonToYaml(spec) : opts.minify ? JSON.stringify(spec) : JSON.stringify(spec, null, 2);
4930
+ if (opts.output) {
4931
+ const outPath = path7__default.default.resolve(process.cwd(), opts.output);
4932
+ await fs5__default.default.mkdir(path7__default.default.dirname(outPath), { recursive: true });
4933
+ await fs5__default.default.writeFile(outPath, serialised + "\n", "utf8");
4934
+ const routeCount = (app.registeredRoutes ?? []).length;
3400
4935
  console.log(
3401
- `${route.method.padEnd(10)} | ${route.path.padEnd(
3402
- 30
3403
- )} | ${validationStr}`
4936
+ `${pc__default.default.green("\u2713")} OpenAPI spec written to ${pc__default.default.cyan(opts.output)} ` + pc__default.default.dim(`(${routeCount} route${routeCount === 1 ? "" : "s"}, ${format})`)
3404
4937
  );
3405
- });
3406
- console.log("----------------------------------------------------\n");
4938
+ } else {
4939
+ process.stdout.write(serialised + "\n");
4940
+ }
3407
4941
  } catch (error) {
3408
- console.error("\u274C Failed to inspect routes:", error);
4942
+ console.error(pc__default.default.red("\u2717 Failed to generate spec:"), error);
4943
+ process.exit(1);
3409
4944
  } finally {
3410
- await fs2__default.default.rm(path4__default.default.dirname(tempPath), { recursive: true, force: true }).catch(() => {
4945
+ await cleanup();
4946
+ }
4947
+ }
4948
+ function normalise(raw, isWs) {
4949
+ const validation = [];
4950
+ if (raw.schema?.body) validation.push("Body");
4951
+ if (raw.schema?.query) validation.push("Query");
4952
+ if (raw.schema?.params) validation.push("Params");
4953
+ if (raw.schema?.response) validation.push("Response");
4954
+ if (raw.schema?.files) validation.push("Files");
4955
+ if (raw.schema?.message) validation.push("Message");
4956
+ const s = raw.schema ?? {};
4957
+ return {
4958
+ method: isWs ? "WS" : raw.method,
4959
+ path: raw.path,
4960
+ validation,
4961
+ tags: Array.isArray(s.tags) ? s.tags : [],
4962
+ operationId: typeof s.operationId === "string" ? s.operationId : void 0,
4963
+ deprecated: s.deprecated === true,
4964
+ timeout: typeof raw.timeout === "number" && raw.timeout > 0 ? raw.timeout : void 0,
4965
+ plugins: Array.isArray(raw.plugins) ? raw.plugins.length : 0,
4966
+ isWs
4967
+ };
4968
+ }
4969
+ function matchesFilter(route, opts) {
4970
+ if (opts.method) {
4971
+ const wanted = opts.method.split(",").map((m) => m.trim().toUpperCase()).filter(Boolean);
4972
+ if (wanted.length && !wanted.includes(route.method)) return false;
4973
+ }
4974
+ if (opts.filter) {
4975
+ const pat = opts.filter;
4976
+ if (pat.includes("*")) {
4977
+ const re = new RegExp(
4978
+ "^" + pat.split("*").map((s) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*") + "$"
4979
+ );
4980
+ if (!re.test(route.path)) return false;
4981
+ } else if (!route.path.includes(pat)) {
4982
+ return false;
4983
+ }
4984
+ }
4985
+ return true;
4986
+ }
4987
+ function sortRoutes(routes, by) {
4988
+ const methodOrder = {
4989
+ GET: 0,
4990
+ POST: 1,
4991
+ PUT: 2,
4992
+ PATCH: 3,
4993
+ DELETE: 4,
4994
+ HEAD: 5,
4995
+ OPTIONS: 6,
4996
+ WS: 7
4997
+ };
4998
+ return [...routes].sort((a, b) => {
4999
+ if (by === "method") {
5000
+ const am = methodOrder[a.method] ?? 99;
5001
+ const bm = methodOrder[b.method] ?? 99;
5002
+ if (am !== bm) return am - bm;
5003
+ return a.path.localeCompare(b.path);
5004
+ }
5005
+ if (a.path !== b.path) return a.path.localeCompare(b.path);
5006
+ return (methodOrder[a.method] ?? 99) - (methodOrder[b.method] ?? 99);
5007
+ });
5008
+ }
5009
+ async function inspectRoutes(entry, opts = {}) {
5010
+ let app;
5011
+ let cleanup = async () => {
5012
+ };
5013
+ try {
5014
+ const loaded = await loadApp(entry);
5015
+ app = loaded.app;
5016
+ cleanup = loaded.cleanup;
5017
+ } catch (err) {
5018
+ console.error(pc__default.default.red("\u2717 Failed to load app:"));
5019
+ console.error(err.message);
5020
+ process.exit(1);
5021
+ }
5022
+ try {
5023
+ const httpRoutes = (app.registeredRoutes ?? []).map(
5024
+ (r) => normalise(r, false)
5025
+ );
5026
+ const wsRoutes = (app.registeredWsRoutes ?? []).map(
5027
+ (r) => normalise(r, true)
5028
+ );
5029
+ const all = sortRoutes([...httpRoutes, ...wsRoutes], opts.sort ?? "path");
5030
+ const filtered = all.filter((r) => matchesFilter(r, opts));
5031
+ if (opts.json) {
5032
+ process.stdout.write(JSON.stringify(filtered, null, 2) + "\n");
5033
+ return;
5034
+ }
5035
+ if (filtered.length === 0) {
5036
+ console.log(
5037
+ "\n" + symbols.info + pc__default.default.dim(
5038
+ ` No routes match the current filter (${all.length} total registered).
5039
+ `
5040
+ )
5041
+ );
5042
+ return;
5043
+ }
5044
+ console.log();
5045
+ console.log(pc__default.default.bold(" \u{1F9ED} Axiomify routes"));
5046
+ console.log();
5047
+ const columns = [
5048
+ { header: "METHOD", minWidth: 7 },
5049
+ { header: "PATH", minWidth: 20, maxWidth: 60 },
5050
+ { header: "VALIDATION", minWidth: 10, maxWidth: 32 },
5051
+ { header: "META", maxWidth: 40 }
5052
+ ];
5053
+ const rows = filtered.map((r) => {
5054
+ const method = colourMethod(r.method);
5055
+ const path11 = r.deprecated ? pc__default.default.strikethrough(r.path) + " " + badge.deprecated() : r.path;
5056
+ const validation = r.validation.length > 0 ? r.validation.map(badge.validation).join(pc__default.default.dim(",")) : pc__default.default.dim("\u2014");
5057
+ const metaBits = [];
5058
+ if (r.operationId) metaBits.push(pc__default.default.dim(`op:`) + r.operationId);
5059
+ if (r.tags.length) metaBits.push(badge.tags(r.tags));
5060
+ if (r.timeout !== void 0) metaBits.push(badge.timeout(r.timeout));
5061
+ if (r.plugins > 0) metaBits.push(pc__default.default.dim(`+${r.plugins} plugin${r.plugins === 1 ? "" : "s"}`));
5062
+ const meta = metaBits.length ? metaBits.join(" ") : pc__default.default.dim("\u2014");
5063
+ return [method, path11, validation, meta];
3411
5064
  });
5065
+ console.log(renderTable(columns, rows));
5066
+ const byMethod = filtered.reduce((acc, r) => {
5067
+ acc[r.method] = (acc[r.method] ?? 0) + 1;
5068
+ return acc;
5069
+ }, {});
5070
+ const summaryParts = Object.entries(byMethod).sort(([a], [b]) => a.localeCompare(b)).map(([m, n]) => `${colourMethod(m).trimEnd()} ${pc__default.default.bold(String(n))}`);
5071
+ console.log();
5072
+ console.log(
5073
+ ` ${symbols.ok} ${pluralise(filtered.length, "route")}` + (filtered.length < all.length ? pc__default.default.dim(` (filtered from ${all.length})`) : "") + " " + summaryParts.join(pc__default.default.dim(" \xB7 "))
5074
+ );
5075
+ const filteredWs = filtered.filter((r) => r.isWs).length;
5076
+ if (filteredWs > 0) {
5077
+ console.log(
5078
+ pc__default.default.dim(` \u2514 ${pluralise(filteredWs, "WebSocket route")} included`)
5079
+ );
5080
+ }
5081
+ console.log();
5082
+ } catch (error) {
5083
+ console.error(pc__default.default.red("\u2717 Failed to inspect routes:"), error);
5084
+ process.exit(1);
5085
+ } finally {
5086
+ await cleanup();
5087
+ }
5088
+ }
5089
+ var VALID_METHODS = /* @__PURE__ */ new Set([
5090
+ "GET",
5091
+ "POST",
5092
+ "PUT",
5093
+ "PATCH",
5094
+ "DELETE",
5095
+ "OPTIONS",
5096
+ "HEAD",
5097
+ "WS"
5098
+ ]);
5099
+ function pathToFilename(routePath) {
5100
+ const cleaned = routePath.split("/").filter(Boolean).map((seg) => seg.startsWith(":") ? `by-${seg.slice(1)}` : seg).join("-");
5101
+ return cleaned || "root";
5102
+ }
5103
+ function generateRouteSource(method, routePath, opts) {
5104
+ const isWs = method === "WS";
5105
+ const params = routePath.match(/:[a-zA-Z_][a-zA-Z0-9_]*/g) ?? [];
5106
+ const paramKeys = params.map((p) => p.slice(1));
5107
+ const plugins = [];
5108
+ const extraImports = [];
5109
+ if (opts.auth) {
5110
+ plugins.push("requireAuth");
5111
+ extraImports.push(
5112
+ `import { createAuthPlugin } from '@axiomify/auth';
5113
+
5114
+ const requireAuth = createAuthPlugin({
5115
+ secret: process.env.JWT_SECRET!,
5116
+ });`
5117
+ );
5118
+ }
5119
+ if (opts.rateLimit) {
5120
+ plugins.push("limiter");
5121
+ extraImports.push(
5122
+ `import { createRateLimitPlugin, MemoryStore } from '@axiomify/rate-limit';
5123
+
5124
+ // Replace MemoryStore with RedisStore for multi-process / multi-host.
5125
+ const limiter = createRateLimitPlugin({
5126
+ windowMs: 60_000,
5127
+ max: 100,
5128
+ store: new MemoryStore(),
5129
+ });`
5130
+ );
5131
+ }
5132
+ if (isWs) {
5133
+ return [
5134
+ `import type { Axiomify } from '@axiomify/core';`,
5135
+ `import { z } from 'zod';`,
5136
+ extraImports.length ? extraImports.join("\n\n") + "\n" : "",
5137
+ `/**`,
5138
+ ` * Registers WebSocket route ${routePath}.`,
5139
+ ` * Wire this into your entry file:`,
5140
+ ` * import { registerRoute } from './routes/${pathToFilename(routePath)}';`,
5141
+ ` * registerRoute(app);`,
5142
+ ` */`,
5143
+ `export function registerRoute(app: Axiomify): void {`,
5144
+ ` app.ws({`,
5145
+ ` path: '${routePath}',`,
5146
+ paramKeys.length > 0 ? ` schema: {
5147
+ params: z.object({ ${paramKeys.map((k) => `${k}: z.string()`).join(", ")} }),
5148
+ // Define your message shape here \u2014 runtime-validated on every incoming frame.
5149
+ message: z.object({
5150
+ text: z.string(),
5151
+ }),
5152
+ },` : ` schema: {
5153
+ // Define your message shape here \u2014 runtime-validated on every incoming frame.
5154
+ message: z.object({
5155
+ text: z.string(),
5156
+ }),
5157
+ },`,
5158
+ plugins.length > 0 ? ` plugins: [${plugins.join(", ")}],` : "",
5159
+ ` open: (client, _req) => {`,
5160
+ ` client.send({ type: 'welcome' });`,
5161
+ ` },`,
5162
+ ` message: (client, data) => {`,
5163
+ ` // \`data\` is typed and validated from the schema above.`,
5164
+ ` client.send({ echo: data.text });`,
5165
+ ` },`,
5166
+ ` close: (_client, code, reason) => {`,
5167
+ ` console.log('connection closed', code, reason);`,
5168
+ ` },`,
5169
+ ` });`,
5170
+ `}`,
5171
+ ``
5172
+ ].filter(Boolean).join("\n");
5173
+ }
5174
+ return [
5175
+ `import type { Axiomify } from '@axiomify/core';`,
5176
+ `import { z } from 'zod';`,
5177
+ extraImports.length ? extraImports.join("\n\n") + "\n" : "",
5178
+ `/**`,
5179
+ ` * Registers ${method} ${routePath}.`,
5180
+ ` * Wire this into your entry file:`,
5181
+ ` * import { registerRoute } from './routes/${pathToFilename(routePath)}';`,
5182
+ ` * registerRoute(app);`,
5183
+ ` */`,
5184
+ `export function registerRoute(app: Axiomify): void {`,
5185
+ ` app.route({`,
5186
+ ` method: '${method}',`,
5187
+ ` path: '${routePath}',`,
5188
+ ` schema: {`,
5189
+ paramKeys.length > 0 ? ` params: z.object({ ${paramKeys.map((k) => `${k}: z.string()`).join(", ")} }),` : "",
5190
+ method === "POST" || method === "PUT" || method === "PATCH" ? ` body: z.object({
5191
+ // TODO \u2014 define request body shape
5192
+ }),` : "",
5193
+ ` // response: z.object({ /* response shape */ }),`,
5194
+ ` },`,
5195
+ ` // OpenAPI metadata (tags, summary, operationId etc.) lives in schema: too`,
5196
+ ` tags: ['${pathToFilename(routePath).split("-")[0] || "general"}'],`,
5197
+ ` summary: '${method} ${routePath}',`,
5198
+ plugins.length > 0 ? ` plugins: [${plugins.join(", ")}],` : "",
5199
+ ` handler: async (${paramKeys.length > 0 || method !== "GET" ? "req" : "_req"}, res) => {`,
5200
+ method === "POST" ? ` // TODO \u2014 handler logic
5201
+ res.status(201).send({ ok: true });` : method === "DELETE" ? ` // TODO \u2014 handler logic
5202
+ res.status(204).send(null);` : ` // TODO \u2014 handler logic
5203
+ res.send({ ok: true });`,
5204
+ ` },`,
5205
+ ` });`,
5206
+ `}`,
5207
+ ``
5208
+ ].filter(Boolean).join("\n");
5209
+ }
5210
+ async function scaffoldRoute(method, routePath, opts = {}) {
5211
+ const upperMethod = method.toUpperCase();
5212
+ if (!VALID_METHODS.has(upperMethod)) {
5213
+ console.error(
5214
+ pc__default.default.red(`\u2717 Invalid method "${method}".`),
5215
+ `Expected one of: ${[...VALID_METHODS].join(", ")}.`
5216
+ );
5217
+ process.exit(1);
5218
+ }
5219
+ if (!routePath.startsWith("/")) {
5220
+ console.error(
5221
+ pc__default.default.red('\u2717 Path must start with "/".'),
5222
+ `Got: ${routePath}`
5223
+ );
5224
+ process.exit(1);
5225
+ }
5226
+ const dir = opts.dir ?? "src/routes";
5227
+ const filename = pathToFilename(routePath) + ".ts";
5228
+ const fileAbs = path7__default.default.resolve(process.cwd(), dir, filename);
5229
+ const source = generateRouteSource(upperMethod, routePath, opts);
5230
+ if (opts.dryRun) {
5231
+ console.log(pc__default.default.dim(`# would write ${path7__default.default.relative(process.cwd(), fileAbs)}
5232
+ `));
5233
+ console.log(source);
5234
+ return;
5235
+ }
5236
+ let exists = false;
5237
+ try {
5238
+ await fs5__default.default.access(fileAbs);
5239
+ exists = true;
5240
+ } catch {
3412
5241
  }
5242
+ if (exists && !opts.force) {
5243
+ console.log(
5244
+ `${symbols.warn} ${pc__default.default.yellow("Already exists:")} ${path7__default.default.relative(process.cwd(), fileAbs)}
5245
+ Pass ${pc__default.default.cyan("--force")} to overwrite, or pick a different path.`
5246
+ );
5247
+ return;
5248
+ }
5249
+ await fs5__default.default.mkdir(path7__default.default.dirname(fileAbs), { recursive: true });
5250
+ await fs5__default.default.writeFile(fileAbs, source, "utf8");
5251
+ console.log();
5252
+ console.log(
5253
+ `${symbols.ok} ${pc__default.default.green("Created")} ${pc__default.default.cyan(path7__default.default.relative(process.cwd(), fileAbs))}`
5254
+ );
5255
+ console.log();
5256
+ console.log(pc__default.default.dim(" Next steps:"));
5257
+ console.log(
5258
+ ` 1. Wire it into your entry file:
5259
+ ` + pc__default.default.dim(` import { registerRoute } from './routes/${pathToFilename(routePath)}';
5260
+ `) + pc__default.default.dim(` registerRoute(app);`)
5261
+ );
5262
+ console.log(
5263
+ ` 2. Fill in the TODOs in ${pc__default.default.cyan(path7__default.default.relative(process.cwd(), fileAbs))}.`
5264
+ );
5265
+ console.log(
5266
+ ` 3. Verify with ${pc__default.default.cyan("npx axiomify routes")} and ${pc__default.default.cyan("npx axiomify check")}.`
5267
+ );
5268
+ console.log();
3413
5269
  }
3414
5270
 
3415
5271
  // src/index.ts
@@ -3420,5 +5276,37 @@ program2.command("init").description("Bootstrap a new Axiomify project").argumen
3420
5276
  );
3421
5277
  program2.command("dev").description("Start the development server with hot-reload").argument("[entry]", "Entry file", "src/index.ts").action(devServer);
3422
5278
  program2.command("build").description("Compile the application for production").argument("[entry]", "Entry file", "src/index.ts").action(buildProject);
3423
- program2.command("routes").description("Inspect and list all registered routes in the application").argument("[entry]", "Entry file", "src/index.ts").action(inspectRoutes);
5279
+ program2.command("routes").description("Inspect and list all registered HTTP + WebSocket routes").argument("[entry]", "Entry file", "src/index.ts").option("--json", "Emit machine-readable JSON instead of the formatted table", false).option(
5280
+ "-m, --method <list>",
5281
+ "Comma-separated list of methods to include (e.g. GET,POST,WS)"
5282
+ ).option(
5283
+ "-f, --filter <pattern>",
5284
+ 'Path filter \u2014 substring match, or glob with "*" (e.g. /api/v1/*)'
5285
+ ).option(
5286
+ "-s, --sort <by>",
5287
+ 'Sort routes by "method" or "path"',
5288
+ "path"
5289
+ ).action(
5290
+ (entry, options) => inspectRoutes(entry, options)
5291
+ );
5292
+ program2.command("openapi").description("Generate the OpenAPI spec from the app and emit it").argument("[entry]", "Entry file", "src/index.ts").option(
5293
+ "-o, --output <file>",
5294
+ "Write the spec to this file path instead of stdout"
5295
+ ).option("--format <fmt>", 'Output format: "json" (default) or "yaml"', "json").option("--minify", "Minified JSON (single line). Ignored for yaml.", false).option("--title <title>", "Override info.title in the generated spec").option("--spec-version <version>", "Override info.version in the generated spec").action(
5296
+ (entry, options) => emitOpenApi(entry, {
5297
+ ...options,
5298
+ // Map the CLI flag name (`spec-version` → camel `specVersion`) onto
5299
+ // the internal `version` field that emitOpenApi() expects.
5300
+ version: options.specVersion
5301
+ })
5302
+ );
5303
+ program2.command("check").description("Run a static production-readiness audit against the app").argument("[entry]", "Entry file", "src/index.ts").action(runCheck);
5304
+ program2.command("doctor").description("Diagnose the host environment (Node, uWS, ports, dep drift)").action(runDoctor);
5305
+ var scaffold = program2.command("scaffold").description("Generate boilerplate (routes, modules, plugins)");
5306
+ scaffold.command("route <method> <path>").description("Create a new route file under src/routes/").option("--auth", "Include `requireAuth` plugin and import", false).option("--rate-limit", "Include a default rate-limit plugin", false).option("--dry-run", "Print the generated source without writing", false).option("--force", "Overwrite the file if it already exists", false).option("--dir <dir>", "Directory under cwd to create the file in", "src/routes").action(
5307
+ (method, routePath, options) => scaffoldRoute(method, routePath, options)
5308
+ );
5309
+ program2.command("migrate").description("v5 \u2192 v6 codemod: merge meta: fields into schema:, fix routePrefix \u2192 prefix, etc").option("--dry-run", "Show the unified diff without writing", false).option("--report-only", "Print a migration report and exit; do not write", false).option("--dir <dir>", "Directory to scan recursively", "src").action(
5310
+ (options) => runMigrate(options)
5311
+ );
3424
5312
  program2.parse(process.argv);