index.cjs 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  1. "use strict";
  2. var __create = Object.create;
  3. var __defProp = Object.defineProperty;
  4. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  5. var __getOwnPropNames = Object.getOwnPropertyNames;
  6. var __getProtoOf = Object.getPrototypeOf;
  7. var __hasOwnProp = Object.prototype.hasOwnProperty;
  8. var __commonJS = (cb, mod) => function __require() {
  9. return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  10. };
  11. var __export = (target, all) => {
  12. for (var name in all)
  13. __defProp(target, name, { get: all[name], enumerable: true });
  14. };
  15. var __copyProps = (to, from, except, desc) => {
  16. if (from && typeof from === "object" || typeof from === "function") {
  17. for (let key of __getOwnPropNames(from))
  18. if (!__hasOwnProp.call(to, key) && key !== except)
  19. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  20. }
  21. return to;
  22. };
  23. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  24. // If the importer is in node compatibility mode or this is not an ESM
  25. // file that has been converted to a CommonJS file using a Babel-
  26. // compatible transform (i.e. "__esModule" has not been set), then set
  27. // "default" to the CommonJS "module.exports" for node compatibility.
  28. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  29. mod
  30. ));
  31. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  32. // node_modules/.pnpm/clone@2.1.2/node_modules/clone/clone.js
  33. var require_clone = __commonJS({
  34. "node_modules/.pnpm/clone@2.1.2/node_modules/clone/clone.js"(exports2, module2) {
  35. "use strict";
  36. var clone2 = function() {
  37. "use strict";
  38. function _instanceof(obj, type) {
  39. return type != null && obj instanceof type;
  40. }
  41. var nativeMap;
  42. try {
  43. nativeMap = Map;
  44. } catch (_) {
  45. nativeMap = function() {
  46. };
  47. }
  48. var nativeSet;
  49. try {
  50. nativeSet = Set;
  51. } catch (_) {
  52. nativeSet = function() {
  53. };
  54. }
  55. var nativePromise;
  56. try {
  57. nativePromise = Promise;
  58. } catch (_) {
  59. nativePromise = function() {
  60. };
  61. }
  62. function clone3(parent, circular, depth, prototype, includeNonEnumerable) {
  63. if (typeof circular === "object") {
  64. depth = circular.depth;
  65. prototype = circular.prototype;
  66. includeNonEnumerable = circular.includeNonEnumerable;
  67. circular = circular.circular;
  68. }
  69. var allParents = [];
  70. var allChildren = [];
  71. var useBuffer = typeof Buffer != "undefined";
  72. if (typeof circular == "undefined")
  73. circular = true;
  74. if (typeof depth == "undefined")
  75. depth = Infinity;
  76. function _clone(parent2, depth2) {
  77. if (parent2 === null)
  78. return null;
  79. if (depth2 === 0)
  80. return parent2;
  81. var child;
  82. var proto;
  83. if (typeof parent2 != "object") {
  84. return parent2;
  85. }
  86. if (_instanceof(parent2, nativeMap)) {
  87. child = new nativeMap();
  88. } else if (_instanceof(parent2, nativeSet)) {
  89. child = new nativeSet();
  90. } else if (_instanceof(parent2, nativePromise)) {
  91. child = new nativePromise(function(resolve, reject) {
  92. parent2.then(function(value) {
  93. resolve(_clone(value, depth2 - 1));
  94. }, function(err) {
  95. reject(_clone(err, depth2 - 1));
  96. });
  97. });
  98. } else if (clone3.__isArray(parent2)) {
  99. child = [];
  100. } else if (clone3.__isRegExp(parent2)) {
  101. child = new RegExp(parent2.source, __getRegExpFlags(parent2));
  102. if (parent2.lastIndex) child.lastIndex = parent2.lastIndex;
  103. } else if (clone3.__isDate(parent2)) {
  104. child = new Date(parent2.getTime());
  105. } else if (useBuffer && Buffer.isBuffer(parent2)) {
  106. if (Buffer.allocUnsafe) {
  107. child = Buffer.allocUnsafe(parent2.length);
  108. } else {
  109. child = new Buffer(parent2.length);
  110. }
  111. parent2.copy(child);
  112. return child;
  113. } else if (_instanceof(parent2, Error)) {
  114. child = Object.create(parent2);
  115. } else {
  116. if (typeof prototype == "undefined") {
  117. proto = Object.getPrototypeOf(parent2);
  118. child = Object.create(proto);
  119. } else {
  120. child = Object.create(prototype);
  121. proto = prototype;
  122. }
  123. }
  124. if (circular) {
  125. var index = allParents.indexOf(parent2);
  126. if (index != -1) {
  127. return allChildren[index];
  128. }
  129. allParents.push(parent2);
  130. allChildren.push(child);
  131. }
  132. if (_instanceof(parent2, nativeMap)) {
  133. parent2.forEach(function(value, key) {
  134. var keyChild = _clone(key, depth2 - 1);
  135. var valueChild = _clone(value, depth2 - 1);
  136. child.set(keyChild, valueChild);
  137. });
  138. }
  139. if (_instanceof(parent2, nativeSet)) {
  140. parent2.forEach(function(value) {
  141. var entryChild = _clone(value, depth2 - 1);
  142. child.add(entryChild);
  143. });
  144. }
  145. for (var i in parent2) {
  146. var attrs;
  147. if (proto) {
  148. attrs = Object.getOwnPropertyDescriptor(proto, i);
  149. }
  150. if (attrs && attrs.set == null) {
  151. continue;
  152. }
  153. child[i] = _clone(parent2[i], depth2 - 1);
  154. }
  155. if (Object.getOwnPropertySymbols) {
  156. var symbols = Object.getOwnPropertySymbols(parent2);
  157. for (var i = 0; i < symbols.length; i++) {
  158. var symbol = symbols[i];
  159. var descriptor = Object.getOwnPropertyDescriptor(parent2, symbol);
  160. if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
  161. continue;
  162. }
  163. child[symbol] = _clone(parent2[symbol], depth2 - 1);
  164. if (!descriptor.enumerable) {
  165. Object.defineProperty(child, symbol, {
  166. enumerable: false
  167. });
  168. }
  169. }
  170. }
  171. if (includeNonEnumerable) {
  172. var allPropertyNames = Object.getOwnPropertyNames(parent2);
  173. for (var i = 0; i < allPropertyNames.length; i++) {
  174. var propertyName = allPropertyNames[i];
  175. var descriptor = Object.getOwnPropertyDescriptor(parent2, propertyName);
  176. if (descriptor && descriptor.enumerable) {
  177. continue;
  178. }
  179. child[propertyName] = _clone(parent2[propertyName], depth2 - 1);
  180. Object.defineProperty(child, propertyName, {
  181. enumerable: false
  182. });
  183. }
  184. }
  185. return child;
  186. }
  187. return _clone(parent, depth);
  188. }
  189. clone3.clonePrototype = function clonePrototype(parent) {
  190. if (parent === null)
  191. return null;
  192. var c = function() {
  193. };
  194. c.prototype = parent;
  195. return new c();
  196. };
  197. function __objToStr(o) {
  198. return Object.prototype.toString.call(o);
  199. }
  200. clone3.__objToStr = __objToStr;
  201. function __isDate(o) {
  202. return typeof o === "object" && __objToStr(o) === "[object Date]";
  203. }
  204. clone3.__isDate = __isDate;
  205. function __isArray(o) {
  206. return typeof o === "object" && __objToStr(o) === "[object Array]";
  207. }
  208. clone3.__isArray = __isArray;
  209. function __isRegExp(o) {
  210. return typeof o === "object" && __objToStr(o) === "[object RegExp]";
  211. }
  212. clone3.__isRegExp = __isRegExp;
  213. function __getRegExpFlags(re) {
  214. var flags = "";
  215. if (re.global) flags += "g";
  216. if (re.ignoreCase) flags += "i";
  217. if (re.multiline) flags += "m";
  218. return flags;
  219. }
  220. clone3.__getRegExpFlags = __getRegExpFlags;
  221. return clone3;
  222. }();
  223. if (typeof module2 === "object" && module2.exports) {
  224. module2.exports = clone2;
  225. }
  226. }
  227. });
  228. // node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/quote.js
  229. var require_quote = __commonJS({
  230. "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/quote.js"(exports2, module2) {
  231. "use strict";
  232. module2.exports = function quote(xs) {
  233. return xs.map(function(s) {
  234. if (s && typeof s === "object") {
  235. return s.op.replace(/(.)/g, "\\$1");
  236. }
  237. if (/["\s]/.test(s) && !/'/.test(s)) {
  238. return "'" + s.replace(/(['\\])/g, "\\$1") + "'";
  239. }
  240. if (/["'\s]/.test(s)) {
  241. return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
  242. }
  243. return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
  244. }).join(" ");
  245. };
  246. }
  247. });
  248. // node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/parse.js
  249. var require_parse = __commonJS({
  250. "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/parse.js"(exports2, module2) {
  251. "use strict";
  252. var CONTROL = "(?:" + [
  253. "\\|\\|",
  254. "\\&\\&",
  255. ";;",
  256. "\\|\\&",
  257. "\\<\\(",
  258. "\\<\\<\\<",
  259. ">>",
  260. ">\\&",
  261. "<\\&",
  262. "[&;()|<>]"
  263. ].join("|") + ")";
  264. var controlRE = new RegExp("^" + CONTROL + "$");
  265. var META = "|&;()<> \\t";
  266. var SINGLE_QUOTE = '"((\\\\"|[^"])*?)"';
  267. var DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
  268. var hash = /^#$/;
  269. var SQ = "'";
  270. var DQ = '"';
  271. var DS = "$";
  272. var TOKEN = "";
  273. var mult = 4294967296;
  274. for (i = 0; i < 4; i++) {
  275. TOKEN += (mult * Math.random()).toString(16);
  276. }
  277. var i;
  278. var startsWithToken = new RegExp("^" + TOKEN);
  279. function matchAll(s, r) {
  280. var origIndex = r.lastIndex;
  281. var matches = [];
  282. var matchObj;
  283. while (matchObj = r.exec(s)) {
  284. matches.push(matchObj);
  285. if (r.lastIndex === matchObj.index) {
  286. r.lastIndex += 1;
  287. }
  288. }
  289. r.lastIndex = origIndex;
  290. return matches;
  291. }
  292. function getVar(env, pre, key) {
  293. var r = typeof env === "function" ? env(key) : env[key];
  294. if (typeof r === "undefined" && key != "") {
  295. r = "";
  296. } else if (typeof r === "undefined") {
  297. r = "$";
  298. }
  299. if (typeof r === "object") {
  300. return pre + TOKEN + JSON.stringify(r) + TOKEN;
  301. }
  302. return pre + r;
  303. }
  304. function parseInternal(string2, env, opts) {
  305. if (!opts) {
  306. opts = {};
  307. }
  308. var BS = opts.escape || "\\";
  309. var BAREWORD = "(\\" + BS + `['"` + META + `]|[^\\s'"` + META + "])+";
  310. var chunker = new RegExp([
  311. "(" + CONTROL + ")",
  312. // control chars
  313. "(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+"
  314. ].join("|"), "g");
  315. var matches = matchAll(string2, chunker);
  316. if (matches.length === 0) {
  317. return [];
  318. }
  319. if (!env) {
  320. env = {};
  321. }
  322. var commented = false;
  323. return matches.map(function(match) {
  324. var s = match[0];
  325. if (!s || commented) {
  326. return void 0;
  327. }
  328. if (controlRE.test(s)) {
  329. return { op: s };
  330. }
  331. var quote = false;
  332. var esc = false;
  333. var out = "";
  334. var isGlob = false;
  335. var i2;
  336. function parseEnvVar() {
  337. i2 += 1;
  338. var varend;
  339. var varname;
  340. var char = s.charAt(i2);
  341. if (char === "{") {
  342. i2 += 1;
  343. if (s.charAt(i2) === "}") {
  344. throw new Error("Bad substitution: " + s.slice(i2 - 2, i2 + 1));
  345. }
  346. varend = s.indexOf("}", i2);
  347. if (varend < 0) {
  348. throw new Error("Bad substitution: " + s.slice(i2));
  349. }
  350. varname = s.slice(i2, varend);
  351. i2 = varend;
  352. } else if (/[*@#?$!_-]/.test(char)) {
  353. varname = char;
  354. i2 += 1;
  355. } else {
  356. var slicedFromI = s.slice(i2);
  357. varend = slicedFromI.match(/[^\w\d_]/);
  358. if (!varend) {
  359. varname = slicedFromI;
  360. i2 = s.length;
  361. } else {
  362. varname = slicedFromI.slice(0, varend.index);
  363. i2 += varend.index - 1;
  364. }
  365. }
  366. return getVar(env, "", varname);
  367. }
  368. for (i2 = 0; i2 < s.length; i2++) {
  369. var c = s.charAt(i2);
  370. isGlob = isGlob || !quote && (c === "*" || c === "?");
  371. if (esc) {
  372. out += c;
  373. esc = false;
  374. } else if (quote) {
  375. if (c === quote) {
  376. quote = false;
  377. } else if (quote == SQ) {
  378. out += c;
  379. } else {
  380. if (c === BS) {
  381. i2 += 1;
  382. c = s.charAt(i2);
  383. if (c === DQ || c === BS || c === DS) {
  384. out += c;
  385. } else {
  386. out += BS + c;
  387. }
  388. } else if (c === DS) {
  389. out += parseEnvVar();
  390. } else {
  391. out += c;
  392. }
  393. }
  394. } else if (c === DQ || c === SQ) {
  395. quote = c;
  396. } else if (controlRE.test(c)) {
  397. return { op: s };
  398. } else if (hash.test(c)) {
  399. commented = true;
  400. var commentObj = { comment: string2.slice(match.index + i2 + 1) };
  401. if (out.length) {
  402. return [out, commentObj];
  403. }
  404. return [commentObj];
  405. } else if (c === BS) {
  406. esc = true;
  407. } else if (c === DS) {
  408. out += parseEnvVar();
  409. } else {
  410. out += c;
  411. }
  412. }
  413. if (isGlob) {
  414. return { op: "glob", pattern: out };
  415. }
  416. return out;
  417. }).reduce(function(prev, arg) {
  418. return typeof arg === "undefined" ? prev : prev.concat(arg);
  419. }, []);
  420. }
  421. module2.exports = function parse(s, env, opts) {
  422. var mapped = parseInternal(s, env, opts);
  423. if (typeof env !== "function") {
  424. return mapped;
  425. }
  426. return mapped.reduce(function(acc, s2) {
  427. if (typeof s2 === "object") {
  428. return acc.concat(s2);
  429. }
  430. var xs = s2.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g"));
  431. if (xs.length === 1) {
  432. return acc.concat(xs[0]);
  433. }
  434. return acc.concat(xs.filter(Boolean).map(function(x) {
  435. if (startsWithToken.test(x)) {
  436. return JSON.parse(x.split(TOKEN)[1]);
  437. }
  438. return x;
  439. }));
  440. }, []);
  441. };
  442. }
  443. });
  444. // node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/index.js
  445. var require_shell_quote = __commonJS({
  446. "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/index.js"(exports2) {
  447. "use strict";
  448. exports2.quote = require_quote();
  449. exports2.parse = require_parse();
  450. }
  451. });
  452. // src/index.ts
  453. var src_exports = {};
  454. __export(src_exports, {
  455. BroCliError: () => BroCliError,
  456. boolean: () => boolean,
  457. command: () => command2,
  458. commandsInfo: () => commandsInfo,
  459. getCommandNameWithParents: () => getCommandNameWithParents,
  460. handler: () => handler,
  461. number: () => number,
  462. positional: () => positional,
  463. run: () => run,
  464. string: () => string,
  465. test: () => test
  466. });
  467. module.exports = __toCommonJS(src_exports);
  468. // src/brocli-error.ts
  469. var BroCliError = class extends Error {
  470. constructor(message, event) {
  471. const errPrefix = "BroCli error: ";
  472. super(message === void 0 ? message : `${errPrefix}${message}`);
  473. this.event = event;
  474. }
  475. };
  476. // src/command-core.ts
  477. var import_clone = __toESM(require_clone(), 1);
  478. // src/event-handler.ts
  479. var getOptionTypeText = (option) => {
  480. let result = "";
  481. switch (option.type) {
  482. case "boolean":
  483. result = "";
  484. break;
  485. case "number": {
  486. if ((option.minVal ?? option.maxVal) !== void 0) {
  487. let text = "";
  488. if (option.isInt) text = text + `integer `;
  489. if (option.minVal !== void 0) text = text + `[${option.minVal};`;
  490. else text = text + `(\u221E;`;
  491. if (option.maxVal !== void 0) text = text + `${option.maxVal}]`;
  492. else text = text + `\u221E)`;
  493. result = text;
  494. break;
  495. }
  496. if (option.isInt) {
  497. result = "integer";
  498. break;
  499. }
  500. result = "number";
  501. break;
  502. }
  503. case "string": {
  504. if (option.enumVals) {
  505. result = "[ " + option.enumVals.join(" | ") + " ]";
  506. break;
  507. }
  508. result = "string";
  509. break;
  510. }
  511. case "positional": {
  512. result = `${option.isRequired ? "<" : "["}${option.enumVals ? option.enumVals.join("|") : option.name}${option.isRequired ? ">" : "]"}`;
  513. break;
  514. }
  515. }
  516. if (option.isRequired && option.type !== "positional") result = "!" + result.length ? " " : "" + result;
  517. return result;
  518. };
  519. var defaultEventHandler = async (event) => {
  520. switch (event.type) {
  521. case "command_help": {
  522. const command3 = event.command;
  523. const commandName = getCommandNameWithParents(command3);
  524. const cliName = event.name;
  525. const desc = command3.desc ?? command3.shortDesc;
  526. const subs = command3.subcommands?.filter((s) => !s.hidden);
  527. const subcommands = subs && subs.length ? subs : void 0;
  528. if (desc !== void 0) {
  529. console.log(`
  530. ${desc}`);
  531. }
  532. const opts = Object.values(command3.options ?? {}).filter(
  533. (opt) => !opt.config.isHidden
  534. );
  535. const positionals = opts.filter((opt) => opt.config.type === "positional");
  536. const options = opts.filter((opt) => opt.config.type !== "positional");
  537. console.log("\nUsage:");
  538. if (command3.handler) {
  539. console.log(
  540. ` ${cliName ? cliName + " " : ""}${commandName}${positionals.length ? " " + positionals.map(({ config: p }) => getOptionTypeText(p)).join(" ") : ""} [flags]`
  541. );
  542. } else console.log(` ${cliName ? cliName + " " : ""}${commandName} [command]`);
  543. if (command3.aliases) {
  544. console.log(`
  545. Aliases:`);
  546. console.log(` ${[command3.name, ...command3.aliases].join(", ")}`);
  547. }
  548. if (subcommands) {
  549. console.log("\nAvailable Commands:");
  550. const padding = 3;
  551. const maxLength = subcommands.reduce((p, e) => e.name.length > p ? e.name.length : p, 0);
  552. const paddedLength = maxLength + padding;
  553. const preDescPad = 2 + paddedLength;
  554. const data = subcommands.map(
  555. (s) => ` ${s.name.padEnd(paddedLength)}${(() => {
  556. const description = s.shortDesc ?? s.desc;
  557. if (!description?.length) return "";
  558. const split = description.split("\n");
  559. const first = split.shift();
  560. const final = [first, ...split.map((s2) => "".padEnd(preDescPad) + s2)].join("\n");
  561. return final;
  562. })()}`
  563. ).join("\n");
  564. console.log(data);
  565. }
  566. if (options.length) {
  567. const aliasLength = options.reduce((p, e) => {
  568. const currentLength = e.config.aliases.reduce((pa, a) => pa + a.length, 0) + (e.config.aliases.length - 1) * 2 + 1;
  569. return currentLength > p ? currentLength : p;
  570. }, 0);
  571. const paddedAliasLength = aliasLength > 0 ? aliasLength + 1 : 0;
  572. const nameLength = options.reduce((p, e) => {
  573. const typeLen = getOptionTypeText(e.config).length;
  574. const length = typeLen > 0 ? e.config.name.length + 1 + typeLen : e.config.name.length;
  575. return length > p ? length : p;
  576. }, 0) + 3;
  577. const preDescPad = paddedAliasLength + nameLength + 2;
  578. const data = options.map(
  579. ({ config: opt }) => ` ${`${opt.aliases.length ? opt.aliases.join(", ") + "," : ""}`.padEnd(paddedAliasLength)}${`${opt.name}${(() => {
  580. const typeText = getOptionTypeText(opt);
  581. return typeText.length ? " " + typeText : "";
  582. })()}`.padEnd(nameLength)}${(() => {
  583. if (!opt.description?.length) {
  584. return opt.default !== void 0 ? `default: ${JSON.stringify(opt.default)}` : "";
  585. }
  586. const split = opt.description.split("\n");
  587. const first = split.shift();
  588. const def = opt.default !== void 0 ? ` (default: ${JSON.stringify(opt.default)})` : "";
  589. const final = [first, ...split.map((s) => "".padEnd(preDescPad) + s)].join("\n") + def;
  590. return final;
  591. })()}`
  592. ).join("\n");
  593. console.log("\nFlags:");
  594. console.log(data);
  595. }
  596. console.log("\nGlobal flags:");
  597. console.log(` -h, --help help for ${commandName}`);
  598. console.log(` -v, --version version${cliName ? ` for ${cliName}` : ""}`);
  599. if (subcommands) {
  600. console.log(
  601. `
  602. Use "${cliName ? cliName + " " : ""}${commandName} [command] --help" for more information about a command.
  603. `
  604. );
  605. }
  606. return true;
  607. }
  608. case "global_help": {
  609. const cliName = event.name;
  610. const desc = event.description;
  611. const commands = event.commands.filter((c) => !c.hidden);
  612. if (desc !== void 0) {
  613. console.log(`${desc}
  614. `);
  615. }
  616. console.log("Usage:");
  617. console.log(` ${cliName ? cliName + " " : ""}[command]`);
  618. if (commands.length) {
  619. console.log("\nAvailable Commands:");
  620. const padding = 3;
  621. const maxLength = commands.reduce((p, e) => e.name.length > p ? e.name.length : p, 0);
  622. const paddedLength = maxLength + padding;
  623. const data = commands.map(
  624. (c) => ` ${c.name.padEnd(paddedLength)}${(() => {
  625. const desc2 = c.shortDesc ?? c.desc;
  626. if (!desc2?.length) return "";
  627. const split = desc2.split("\n");
  628. const first = split.shift();
  629. const final = [first, ...split.map((s) => "".padEnd(paddedLength + 2) + s)].join("\n");
  630. return final;
  631. })()}`
  632. ).join("\n");
  633. console.log(data);
  634. } else {
  635. console.log("\nNo available commands.");
  636. }
  637. console.log("\nFlags:");
  638. console.log(` -h, --help help${cliName ? ` for ${cliName}` : ""}`);
  639. console.log(` -v, --version version${cliName ? ` for ${cliName}` : ""}`);
  640. console.log("\n");
  641. return true;
  642. }
  643. case "version": {
  644. return true;
  645. }
  646. case "error": {
  647. let msg;
  648. switch (event.violation) {
  649. case "above_max": {
  650. const matchedName = event.offender.namePart;
  651. const data = event.offender.dataPart;
  652. const option = event.option;
  653. const max = option.maxVal;
  654. msg = `Invalid value: number type argument '${matchedName}' expects maximal value of ${max} as an input, got: ${data}`;
  655. break;
  656. }
  657. case "below_min": {
  658. const matchedName = event.offender.namePart;
  659. const data = event.offender.dataPart;
  660. const option = event.option;
  661. const min = option.minVal;
  662. msg = `Invalid value: number type argument '${matchedName}' expects minimal value of ${min} as an input, got: ${data}`;
  663. break;
  664. }
  665. case "expected_int": {
  666. const matchedName = event.offender.namePart;
  667. const data = event.offender.dataPart;
  668. msg = `Invalid value: number type argument '${matchedName}' expects an integer as an input, got: ${data}`;
  669. break;
  670. }
  671. case "invalid_boolean_syntax": {
  672. const matchedName = event.offender.namePart;
  673. const data = event.offender.dataPart;
  674. msg = `Invalid syntax: boolean type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value> | ${matchedName}.
  675. Allowed values: true, false, 0, 1`;
  676. break;
  677. }
  678. case "invalid_string_syntax": {
  679. const matchedName = event.offender.namePart;
  680. msg = `Invalid syntax: string type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value>`;
  681. break;
  682. }
  683. case "invalid_number_syntax": {
  684. const matchedName = event.offender.namePart;
  685. msg = `Invalid syntax: number type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value>`;
  686. break;
  687. }
  688. case "invalid_number_value": {
  689. const matchedName = event.offender.namePart;
  690. const data = event.offender.dataPart;
  691. msg = `Invalid value: number type argument '${matchedName}' expects a number as an input, got: ${data}`;
  692. break;
  693. }
  694. case "enum_violation": {
  695. const matchedName = event.offender.namePart;
  696. const data = event.offender.dataPart;
  697. const option = event.option;
  698. const values = option.enumVals;
  699. msg = option.type === "positional" ? `Invalid value: value for the positional argument '${option.name}' must be either one of the following: ${values.join(", ")}; Received: ${data}` : `Invalid value: value for the argument '${matchedName}' must be either one of the following: ${values.join(", ")}; Received: ${data}`;
  700. break;
  701. }
  702. case "unknown_command_error": {
  703. const msg2 = `Unknown command: '${event.offender}'.
  704. Type '--help' to get help on the cli.`;
  705. console.error(msg2);
  706. return true;
  707. }
  708. case "unknown_subcommand_error": {
  709. const cName = getCommandNameWithParents(event.command);
  710. const msg2 = `Unknown command: ${cName} ${event.offender}.
  711. Type '${cName} --help' to get the help on command.`;
  712. console.error(msg2);
  713. return true;
  714. }
  715. case "missing_args_error": {
  716. const { missing: missingOpts, command: command3 } = event;
  717. msg = `Command '${command3.name}' is missing following required options: ${missingOpts.map((opt) => {
  718. const name = opt.shift();
  719. const aliases = opt;
  720. if (aliases.length) return `${name} [${aliases.join(", ")}]`;
  721. return name;
  722. }).join(", ")}`;
  723. break;
  724. }
  725. case "unrecognized_args_error": {
  726. const { command: command3, unrecognized } = event;
  727. msg = `Unrecognized options for command '${command3.name}': ${unrecognized.join(", ")}`;
  728. break;
  729. }
  730. case "unknown_error": {
  731. const e = event.error;
  732. console.error(typeof e === "object" && e !== null && "message" in e ? e.message : e);
  733. return true;
  734. }
  735. }
  736. console.error(msg);
  737. return true;
  738. }
  739. }
  740. return false;
  741. };
  742. var eventHandlerWrapper = (customEventHandler) => async (event) => await customEventHandler(event) ? true : await defaultEventHandler(event);
  743. // src/util.ts
  744. var import_shell_quote = __toESM(require_shell_quote(), 1);
  745. function isInt(value) {
  746. return value === Math.floor(value);
  747. }
  748. var shellArgs = (str) => (0, import_shell_quote.parse)(str).map((e) => e.toString());
  749. var executeOrLog = async (target) => typeof target === "string" ? console.log(target) : target ? await target() : void 0;
  750. // src/command-core.ts
  751. var generatePrefix = (name) => name.startsWith("-") ? name : name.length > 1 ? `--${name}` : `-${name}`;
  752. var validateOptions = (config) => {
  753. const cloned = (0, import_clone.default)(config);
  754. const entries = [];
  755. const storedNames = [];
  756. const cfgEntries = Object.entries(cloned);
  757. for (const [key, value] of cfgEntries) {
  758. const cfg = value._.config;
  759. if (cfg.name === void 0) cfg.name = key;
  760. if (cfg.type === "positional") continue;
  761. if (cfg.name.includes("=")) {
  762. throw new BroCliError(
  763. `Can't define option '${generatePrefix(cfg.name)}' - option names and aliases cannot contain '='!`
  764. );
  765. }
  766. for (const alias of cfg.aliases) {
  767. if (alias.includes("=")) {
  768. throw new BroCliError(
  769. `Can't define option '${generatePrefix(cfg.name)}' - option names and aliases cannot contain '='!`
  770. );
  771. }
  772. }
  773. cfg.name = generatePrefix(cfg.name);
  774. cfg.aliases = cfg.aliases.map((a) => generatePrefix(a));
  775. }
  776. for (const [key, value] of cfgEntries) {
  777. const cfg = value._.config;
  778. if (cfg.type === "positional") {
  779. entries.push([key, { config: cfg, $output: void 0 }]);
  780. continue;
  781. }
  782. const reservedNames = ["--help", "-h", "--version", "-v"];
  783. const allNames = [cfg.name, ...cfg.aliases];
  784. for (const name of allNames) {
  785. const match = reservedNames.find((n) => n === name);
  786. if (match) throw new BroCliError(`Can't define option '${cfg.name}' - name '${match}' is reserved!`);
  787. }
  788. for (const storage of storedNames) {
  789. const nameOccupier = storage.find((e) => e === cfg.name);
  790. if (!nameOccupier) continue;
  791. throw new BroCliError(
  792. `Can't define option '${cfg.name}' - name is already in use by option '${storage[0]}'!`
  793. );
  794. }
  795. for (const alias of cfg.aliases) {
  796. for (const storage of storedNames) {
  797. const nameOccupier = storage.find((e) => e === alias);
  798. if (!nameOccupier) continue;
  799. throw new BroCliError(
  800. `Can't define option '${cfg.name}' - alias '${alias}' is already in use by option '${storage[0]}'!`
  801. );
  802. }
  803. }
  804. const currentNames = [cfg.name, ...cfg.aliases];
  805. storedNames.push(currentNames);
  806. currentNames.forEach((name, idx) => {
  807. if (currentNames.findIndex((e) => e === name) === idx) return;
  808. throw new BroCliError(
  809. `Can't define option '${cfg.name}' - duplicate alias '${name}'!`
  810. );
  811. });
  812. entries.push([key, { config: cfg, $output: void 0 }]);
  813. }
  814. return Object.fromEntries(entries);
  815. };
  816. var assignParent = (parent, subcommands) => subcommands.forEach((e) => {
  817. e.parent = parent;
  818. if (e.subcommands) assignParent(e, e.subcommands);
  819. });
  820. var command2 = (command3) => {
  821. const allNames = command3.aliases ? [command3.name, ...command3.aliases] : [command3.name];
  822. const cmd = (0, import_clone.default)(command3);
  823. if (command3.subcommands && command3.options && Object.values(command3.options).find((opt) => opt._.config.type === "positional")) {
  824. throw new BroCliError(
  825. `Can't define command '${cmd.name}' - command can't have subcommands and positional args at the same time!`
  826. );
  827. }
  828. if (!command3.handler && !command3.subcommands) {
  829. throw new BroCliError(
  830. `Can't define command '${cmd.name}' - command without subcommands must have a handler present!`
  831. );
  832. }
  833. const processedOptions = command3.options ? validateOptions(command3.options) : void 0;
  834. cmd.options = processedOptions;
  835. cmd.name = cmd.name ?? cmd.aliases?.shift();
  836. if (!cmd.name) throw new BroCliError(`Can't define command without name!`);
  837. cmd.aliases = cmd.aliases?.length ? cmd.aliases : void 0;
  838. if (cmd.name.startsWith("-")) {
  839. throw new BroCliError(`Can't define command '${cmd.name}' - command name can't start with '-'!`);
  840. }
  841. cmd.aliases?.forEach((a) => {
  842. if (a.startsWith("-")) {
  843. throw new BroCliError(`Can't define command '${cmd.name}' - command aliases can't start with '-'!`);
  844. }
  845. });
  846. allNames.forEach((n, i) => {
  847. if (n === "help") {
  848. throw new BroCliError(
  849. `Can't define command '${cmd.name}' - 'help' is a reserved name. If you want to redefine help message - do so in runCli's config.`
  850. );
  851. }
  852. const lCaseName = n?.toLowerCase();
  853. if (lCaseName === "0" || lCaseName === "1" || lCaseName === "true" || lCaseName === "false") {
  854. throw new BroCliError(
  855. `Can't define command '${cmd.name}' - '${n}' is a reserved for boolean values name!`
  856. );
  857. }
  858. const idx = allNames.findIndex((an) => an === n);
  859. if (idx !== i) throw new BroCliError(`Can't define command '${cmd.name}' - duplicate alias '${n}'!`);
  860. });
  861. if (cmd.subcommands) {
  862. assignParent(cmd, cmd.subcommands);
  863. }
  864. return cmd;
  865. };
  866. var getCommandInner = (commands, candidates, args, cliName, cliDescription) => {
  867. const { data: arg, originalIndex: index } = candidates.shift();
  868. const command3 = commands.find((c) => {
  869. const names = c.aliases ? [c.name, ...c.aliases] : [c.name];
  870. const res = names.find((name) => name === arg);
  871. return res;
  872. });
  873. if (!command3) {
  874. return {
  875. command: command3,
  876. args
  877. };
  878. }
  879. const newArgs = removeByIndex(args, index);
  880. if (!candidates.length || !command3.subcommands) {
  881. return {
  882. command: command3,
  883. args: newArgs
  884. };
  885. }
  886. const newCandidates = candidates.map((c) => ({ data: c.data, originalIndex: c.originalIndex - 1 }));
  887. const subcommand = getCommandInner(command3.subcommands, newCandidates, newArgs, cliName, cliDescription);
  888. if (!subcommand.command) {
  889. throw new BroCliError(void 0, {
  890. type: "error",
  891. violation: "unknown_subcommand_error",
  892. name: cliName,
  893. description: cliDescription,
  894. command: command3,
  895. offender: candidates[0].data
  896. });
  897. }
  898. return subcommand;
  899. };
  900. var getCommand = (commands, args, cliName, cliDescription) => {
  901. const candidates = [];
  902. for (let i = 0; i < args.length; ++i) {
  903. const arg = args[i];
  904. if (arg === "--help" || arg === "-h" || arg === "--version" || arg === "-v") {
  905. const lCaseNext = args[i + 1]?.toLowerCase();
  906. if (lCaseNext === "0" || lCaseNext === "1" || lCaseNext === "true" || lCaseNext === "false") ++i;
  907. continue;
  908. }
  909. if (arg?.startsWith("-")) {
  910. if (!arg.includes("=")) ++i;
  911. continue;
  912. }
  913. candidates.push({
  914. data: arg,
  915. originalIndex: i
  916. });
  917. }
  918. if (!candidates.length) {
  919. return {
  920. command: void 0,
  921. args
  922. };
  923. }
  924. const firstCandidate = candidates[0];
  925. if (firstCandidate.data === "help") {
  926. return {
  927. command: "help",
  928. args: removeByIndex(args, firstCandidate.originalIndex)
  929. };
  930. }
  931. const { command: command3, args: argsRes } = getCommandInner(commands, candidates, args, cliName, cliDescription);
  932. if (!command3) {
  933. throw new BroCliError(void 0, {
  934. type: "error",
  935. violation: "unknown_command_error",
  936. commands,
  937. name: cliName,
  938. description: cliDescription,
  939. offender: firstCandidate.data
  940. });
  941. }
  942. return {
  943. command: command3,
  944. args: argsRes
  945. };
  946. };
  947. var parseArg = (command3, options, positionals, arg, nextArg, cliName, cliDescription) => {
  948. let data = void 0;
  949. const argSplit = arg.split("=");
  950. const hasEq = arg.includes("=");
  951. const namePart = argSplit.shift();
  952. const dataPart = hasEq ? argSplit.join("=") : nextArg;
  953. let skipNext = !hasEq;
  954. if (namePart === "--help" || namePart === "-h") {
  955. return {
  956. isHelp: true
  957. };
  958. }
  959. if (namePart === "--version" || namePart === "-v") {
  960. return {
  961. isVersion: true
  962. };
  963. }
  964. if (!arg.startsWith("-")) {
  965. if (!positionals.length) return {};
  966. const pos = positionals.shift();
  967. if (pos[1].enumVals && !pos[1].enumVals.find((val) => val === arg)) {
  968. throw new BroCliError(void 0, {
  969. type: "error",
  970. name: cliName,
  971. description: cliDescription,
  972. violation: "enum_violation",
  973. command: command3,
  974. option: pos[1],
  975. offender: {
  976. dataPart: arg
  977. }
  978. });
  979. }
  980. data = arg;
  981. return {
  982. data,
  983. skipNext: false,
  984. name: pos[0],
  985. option: pos[1]
  986. };
  987. }
  988. const option = options.find(([optKey, opt]) => {
  989. const names = [opt.name, ...opt.aliases];
  990. if (opt.type === "boolean") {
  991. const match = names.find((name) => name === namePart);
  992. if (!match) return false;
  993. let lcaseData = dataPart?.toLowerCase();
  994. if (!hasEq && nextArg?.startsWith("-")) {
  995. data = true;
  996. skipNext = false;
  997. return true;
  998. }
  999. if (lcaseData === void 0 || lcaseData === "" || lcaseData === "true" || lcaseData === "1") {
  1000. data = true;
  1001. return true;
  1002. }
  1003. if (lcaseData === "false" || lcaseData === "0") {
  1004. data = false;
  1005. return true;
  1006. }
  1007. if (!hasEq) {
  1008. data = true;
  1009. skipNext = false;
  1010. return true;
  1011. }
  1012. throw new BroCliError(void 0, {
  1013. type: "error",
  1014. name: cliName,
  1015. description: cliDescription,
  1016. violation: "invalid_boolean_syntax",
  1017. option: opt,
  1018. command: command3,
  1019. offender: {
  1020. namePart,
  1021. dataPart
  1022. }
  1023. });
  1024. } else {
  1025. const match = names.find((name) => name === namePart);
  1026. if (!match) return false;
  1027. if (opt.type === "string") {
  1028. if (!hasEq && nextArg === void 0) {
  1029. throw new BroCliError(void 0, {
  1030. type: "error",
  1031. name: cliName,
  1032. description: cliDescription,
  1033. violation: "invalid_string_syntax",
  1034. option: opt,
  1035. command: command3,
  1036. offender: {
  1037. namePart,
  1038. dataPart
  1039. }
  1040. });
  1041. }
  1042. if (opt.enumVals && !opt.enumVals.find((val) => val === dataPart)) {
  1043. throw new BroCliError(void 0, {
  1044. type: "error",
  1045. name: cliName,
  1046. description: cliDescription,
  1047. violation: "enum_violation",
  1048. option: opt,
  1049. command: command3,
  1050. offender: {
  1051. namePart,
  1052. dataPart
  1053. }
  1054. });
  1055. }
  1056. data = dataPart;
  1057. return true;
  1058. }
  1059. if (!hasEq && nextArg === void 0) {
  1060. throw new BroCliError(void 0, {
  1061. type: "error",
  1062. name: cliName,
  1063. description: cliDescription,
  1064. violation: "invalid_number_syntax",
  1065. option: opt,
  1066. command: command3,
  1067. offender: {
  1068. namePart,
  1069. dataPart
  1070. }
  1071. });
  1072. }
  1073. const numData = Number(dataPart);
  1074. if (isNaN(numData)) {
  1075. throw new BroCliError(void 0, {
  1076. type: "error",
  1077. name: cliName,
  1078. description: cliDescription,
  1079. violation: "invalid_number_value",
  1080. option: opt,
  1081. command: command3,
  1082. offender: {
  1083. namePart,
  1084. dataPart
  1085. }
  1086. });
  1087. }
  1088. if (opt.isInt && !isInt(numData)) {
  1089. throw new BroCliError(void 0, {
  1090. type: "error",
  1091. name: cliName,
  1092. description: cliDescription,
  1093. violation: "expected_int",
  1094. option: opt,
  1095. command: command3,
  1096. offender: {
  1097. namePart,
  1098. dataPart
  1099. }
  1100. });
  1101. }
  1102. if (opt.minVal !== void 0 && numData < opt.minVal) {
  1103. throw new BroCliError(void 0, {
  1104. type: "error",
  1105. name: cliName,
  1106. description: cliDescription,
  1107. violation: "below_min",
  1108. option: opt,
  1109. command: command3,
  1110. offender: {
  1111. namePart,
  1112. dataPart
  1113. }
  1114. });
  1115. }
  1116. if (opt.maxVal !== void 0 && numData > opt.maxVal) {
  1117. throw new BroCliError(void 0, {
  1118. type: "error",
  1119. name: cliName,
  1120. description: cliDescription,
  1121. violation: "above_max",
  1122. option: opt,
  1123. command: command3,
  1124. offender: {
  1125. namePart,
  1126. dataPart
  1127. }
  1128. });
  1129. }
  1130. data = numData;
  1131. return true;
  1132. }
  1133. });
  1134. return {
  1135. data,
  1136. skipNext,
  1137. name: option?.[0],
  1138. option: option?.[1]
  1139. };
  1140. };
  1141. var parseOptions = (command3, args, cliName, cliDescription, omitKeysOfUndefinedOptions) => {
  1142. const options = command3.options;
  1143. const optEntries = Object.entries(options ?? {}).map(
  1144. (opt) => [opt[0], opt[1].config]
  1145. );
  1146. const nonPositionalEntries = optEntries.filter(([key, opt]) => opt.type !== "positional");
  1147. const positionalEntries = optEntries.filter(([key, opt]) => opt.type === "positional");
  1148. const result = {};
  1149. const missingRequiredArr = [];
  1150. const unrecognizedArgsArr = [];
  1151. for (let i = 0; i < args.length; ++i) {
  1152. const arg = args[i];
  1153. const nextArg = args[i + 1];
  1154. const {
  1155. data,
  1156. name,
  1157. option,
  1158. skipNext,
  1159. isHelp,
  1160. isVersion
  1161. } = parseArg(command3, nonPositionalEntries, positionalEntries, arg, nextArg, cliName, cliDescription);
  1162. if (!option) unrecognizedArgsArr.push(arg.split("=")[0]);
  1163. if (skipNext) ++i;
  1164. if (isHelp) return "help";
  1165. if (isVersion) return "version";
  1166. result[name] = data;
  1167. }
  1168. for (const [optKey, option] of optEntries) {
  1169. const data = result[optKey] ?? option.default;
  1170. if (!omitKeysOfUndefinedOptions) {
  1171. result[optKey] = data;
  1172. } else {
  1173. if (data !== void 0) result[optKey] = data;
  1174. }
  1175. if (option.isRequired && result[optKey] === void 0) missingRequiredArr.push([option.name, ...option.aliases]);
  1176. }
  1177. if (missingRequiredArr.length) {
  1178. throw new BroCliError(void 0, {
  1179. type: "error",
  1180. violation: "missing_args_error",
  1181. name: cliName,
  1182. description: cliDescription,
  1183. command: command3,
  1184. missing: missingRequiredArr
  1185. });
  1186. }
  1187. if (unrecognizedArgsArr.length) {
  1188. throw new BroCliError(void 0, {
  1189. type: "error",
  1190. violation: "unrecognized_args_error",
  1191. name: cliName,
  1192. description: cliDescription,
  1193. command: command3,
  1194. unrecognized: unrecognizedArgsArr
  1195. });
  1196. }
  1197. return Object.keys(result).length ? result : void 0;
  1198. };
  1199. var getCommandNameWithParents = (command3) => command3.parent ? `${getCommandNameWithParents(command3.parent)} ${command3.name}` : command3.name;
  1200. var validateCommands = (commands, parent) => {
  1201. const storedNames = {};
  1202. for (const cmd of commands) {
  1203. const storageVals = Object.values(storedNames);
  1204. for (const storage of storageVals) {
  1205. const nameOccupier = storage.find((e) => e === cmd.name);
  1206. if (!nameOccupier) continue;
  1207. throw new BroCliError(
  1208. `Can't define command '${getCommandNameWithParents(cmd)}': name is already in use by command '${parent ? `${getCommandNameWithParents(parent)} ` : ""}${storage[0]}'!`
  1209. );
  1210. }
  1211. if (cmd.aliases) {
  1212. for (const alias of cmd.aliases) {
  1213. for (const storage of storageVals) {
  1214. const nameOccupier = storage.find((e) => e === alias);
  1215. if (!nameOccupier) continue;
  1216. throw new BroCliError(
  1217. `Can't define command '${getCommandNameWithParents(cmd)}': alias '${alias}' is already in use by command '${parent ? `${getCommandNameWithParents(parent)} ` : ""}${storage[0]}'!`
  1218. );
  1219. }
  1220. }
  1221. }
  1222. storedNames[cmd.name] = cmd.aliases ? [cmd.name, ...cmd.aliases] : [cmd.name];
  1223. if (cmd.subcommands) cmd.subcommands = validateCommands(cmd.subcommands, cmd);
  1224. }
  1225. return commands;
  1226. };
  1227. var removeByIndex = (arr, idx) => [...arr.slice(0, idx), ...arr.slice(idx + 1, arr.length)];
  1228. var run = async (commands, config) => {
  1229. const eventHandler = config?.theme ? eventHandlerWrapper(config.theme) : defaultEventHandler;
  1230. const argSource = config?.argSource ?? process.argv;
  1231. const version = config?.version;
  1232. const help = config?.help;
  1233. const omitKeysOfUndefinedOptions = config?.omitKeysOfUndefinedOptions ?? false;
  1234. const cliName = config?.name;
  1235. const cliDescription = config?.description;
  1236. try {
  1237. const processedCmds = validateCommands(commands);
  1238. let args = argSource.slice(2, argSource.length);
  1239. if (!args.length) {
  1240. return help !== void 0 ? await executeOrLog(help) : await eventHandler({
  1241. type: "global_help",
  1242. description: cliDescription,
  1243. name: cliName,
  1244. commands: processedCmds
  1245. });
  1246. }
  1247. const helpIndex = args.findIndex((arg) => arg === "--help" || arg === "-h");
  1248. if (helpIndex !== -1 && (helpIndex > 0 ? args[helpIndex - 1]?.startsWith("-") && !args[helpIndex - 1].includes("=") ? false : true : true)) {
  1249. const command4 = getCommand(processedCmds, args, cliName, cliDescription).command;
  1250. if (typeof command4 === "object") {
  1251. return command4.help !== void 0 ? await executeOrLog(command4.help) : await eventHandler({
  1252. type: "command_help",
  1253. description: cliDescription,
  1254. name: cliName,
  1255. command: command4
  1256. });
  1257. } else {
  1258. return help !== void 0 ? await executeOrLog(help) : await eventHandler({
  1259. type: "global_help",
  1260. description: cliDescription,
  1261. name: cliName,
  1262. commands: processedCmds
  1263. });
  1264. }
  1265. }
  1266. const versionIndex = args.findIndex((arg) => arg === "--version" || arg === "-v");
  1267. if (versionIndex !== -1 && (versionIndex > 0 ? args[versionIndex - 1]?.startsWith("-") ? false : true : true)) {
  1268. return version !== void 0 ? await executeOrLog(version) : await eventHandler({
  1269. type: "version",
  1270. name: cliName,
  1271. description: cliDescription
  1272. });
  1273. }
  1274. const { command: command3, args: newArgs } = getCommand(processedCmds, args, cliName, cliDescription);
  1275. if (!command3) {
  1276. return help !== void 0 ? await executeOrLog(help) : await eventHandler({
  1277. type: "global_help",
  1278. description: cliDescription,
  1279. name: cliName,
  1280. commands: processedCmds
  1281. });
  1282. }
  1283. if (command3 === "help") {
  1284. let helpCommand;
  1285. let newestArgs = newArgs;
  1286. do {
  1287. const res = getCommand(processedCmds, newestArgs, cliName, cliDescription);
  1288. helpCommand = res.command;
  1289. newestArgs = res.args;
  1290. } while (helpCommand === "help");
  1291. return helpCommand ? helpCommand.help !== void 0 ? await executeOrLog(helpCommand.help) : await eventHandler({
  1292. type: "command_help",
  1293. description: cliDescription,
  1294. name: cliName,
  1295. command: helpCommand
  1296. }) : help !== void 0 ? await executeOrLog(help) : await eventHandler({
  1297. type: "global_help",
  1298. description: cliDescription,
  1299. name: cliName,
  1300. commands: processedCmds
  1301. });
  1302. }
  1303. const optionResult = parseOptions(command3, newArgs, cliName, cliDescription, omitKeysOfUndefinedOptions);
  1304. if (optionResult === "help") {
  1305. return command3.help !== void 0 ? await executeOrLog(command3.help) : await eventHandler({
  1306. type: "command_help",
  1307. description: cliDescription,
  1308. name: cliName,
  1309. command: command3
  1310. });
  1311. }
  1312. if (optionResult === "version") {
  1313. return version !== void 0 ? await executeOrLog(version) : await eventHandler({
  1314. type: "version",
  1315. name: cliName,
  1316. description: cliDescription
  1317. });
  1318. }
  1319. if (command3.handler) {
  1320. if (config?.hook) await config.hook("before", command3);
  1321. await command3.handler(command3.transform ? await command3.transform(optionResult) : optionResult);
  1322. if (config?.hook) await config.hook("after", command3);
  1323. return;
  1324. } else {
  1325. return command3.help !== void 0 ? await executeOrLog(command3.help) : await eventHandler({
  1326. type: "command_help",
  1327. description: cliDescription,
  1328. name: cliName,
  1329. command: command3
  1330. });
  1331. }
  1332. } catch (e) {
  1333. if (e instanceof BroCliError) {
  1334. if (e.event) await eventHandler(e.event);
  1335. else {
  1336. if (!config?.noExit) console.error(e.message);
  1337. else return e.message;
  1338. }
  1339. } else {
  1340. await eventHandler({
  1341. type: "error",
  1342. violation: "unknown_error",
  1343. name: cliName,
  1344. description: cliDescription,
  1345. error: e
  1346. });
  1347. }
  1348. if (!config?.noExit) process.exit(1);
  1349. return;
  1350. }
  1351. };
  1352. var handler = (options, handler2) => handler2;
  1353. var test = async (command3, args) => {
  1354. try {
  1355. const cliParsedArgs = shellArgs(args);
  1356. const options = parseOptions(command3, cliParsedArgs, void 0, void 0);
  1357. if (options === "help" || options === "version") {
  1358. return {
  1359. type: options
  1360. };
  1361. }
  1362. return {
  1363. options: command3.transform ? await command3.transform(options) : options,
  1364. type: "handler"
  1365. };
  1366. } catch (e) {
  1367. return {
  1368. type: "error",
  1369. error: e
  1370. };
  1371. }
  1372. };
  1373. var commandsInfo = (commands) => {
  1374. const validated = validateCommands(commands);
  1375. return Object.fromEntries(validated.map((c) => [c.name, {
  1376. name: c.name,
  1377. aliases: (0, import_clone.default)(c.aliases),
  1378. desc: c.desc,
  1379. shortDesc: c.shortDesc,
  1380. isHidden: c.hidden,
  1381. options: c.options ? Object.fromEntries(Object.entries(c.options).map(([key, opt]) => [key, (0, import_clone.default)(opt.config)])) : void 0,
  1382. metadata: (0, import_clone.default)(c.metadata),
  1383. subcommands: c.subcommands ? commandsInfo(c.subcommands) : void 0
  1384. }]));
  1385. };
  1386. // src/option-builder.ts
  1387. var OptionBuilderBase = class _OptionBuilderBase {
  1388. _;
  1389. config = () => this._.config;
  1390. constructor(config) {
  1391. this._ = {
  1392. config: config ?? {
  1393. aliases: [],
  1394. type: "string"
  1395. },
  1396. $output: void 0
  1397. };
  1398. }
  1399. string(name) {
  1400. const config = this.config();
  1401. return new _OptionBuilderBase({ ...config, type: "string", name });
  1402. }
  1403. number(name) {
  1404. const config = this.config();
  1405. return new _OptionBuilderBase({ ...config, type: "number", name });
  1406. }
  1407. boolean(name) {
  1408. const config = this.config();
  1409. return new _OptionBuilderBase({ ...config, type: "boolean", name });
  1410. }
  1411. positional(displayName) {
  1412. const config = this.config();
  1413. return new _OptionBuilderBase({ ...config, type: "positional", name: displayName });
  1414. }
  1415. alias(...aliases) {
  1416. const config = this.config();
  1417. return new _OptionBuilderBase({ ...config, aliases });
  1418. }
  1419. desc(description) {
  1420. const config = this.config();
  1421. return new _OptionBuilderBase({ ...config, description });
  1422. }
  1423. hidden() {
  1424. const config = this.config();
  1425. return new _OptionBuilderBase({ ...config, isHidden: true });
  1426. }
  1427. required() {
  1428. const config = this.config();
  1429. return new _OptionBuilderBase({ ...config, isRequired: true });
  1430. }
  1431. default(value) {
  1432. const config = this.config();
  1433. const enums = config.enumVals;
  1434. if (enums && !enums.find((v) => value === v)) {
  1435. throw new Error(
  1436. `Option enums [ ${enums.join(", ")} ] are incompatible with default value ${value}`
  1437. );
  1438. }
  1439. return new _OptionBuilderBase({ ...config, default: value });
  1440. }
  1441. enum(...values) {
  1442. const config = this.config();
  1443. const defaultVal = config.default;
  1444. if (defaultVal !== void 0 && !values.find((v) => defaultVal === v)) {
  1445. throw new Error(
  1446. `Option enums [ ${values.join(", ")} ] are incompatible with default value ${defaultVal}`
  1447. );
  1448. }
  1449. return new _OptionBuilderBase({ ...config, enumVals: values });
  1450. }
  1451. min(value) {
  1452. const config = this.config();
  1453. const maxVal = config.maxVal;
  1454. if (maxVal !== void 0 && maxVal < value) {
  1455. throw new BroCliError("Unable to define option's min value to be higher than max value!");
  1456. }
  1457. return new _OptionBuilderBase({ ...config, minVal: value });
  1458. }
  1459. max(value) {
  1460. const config = this.config();
  1461. const minVal = config.minVal;
  1462. if (minVal !== void 0 && minVal > value) {
  1463. throw new BroCliError("Unable to define option's max value to be lower than min value!");
  1464. }
  1465. return new _OptionBuilderBase({ ...config, maxVal: value });
  1466. }
  1467. int() {
  1468. const config = this.config();
  1469. return new _OptionBuilderBase({ ...config, isInt: true });
  1470. }
  1471. };
  1472. function string(name) {
  1473. return typeof name === "string" ? new OptionBuilderBase().string(name) : new OptionBuilderBase().string();
  1474. }
  1475. function number(name) {
  1476. return typeof name === "string" ? new OptionBuilderBase().number(name) : new OptionBuilderBase().number();
  1477. }
  1478. function boolean(name) {
  1479. return typeof name === "string" ? new OptionBuilderBase().boolean(name) : new OptionBuilderBase().boolean();
  1480. }
  1481. function positional(displayName) {
  1482. return typeof displayName === "string" ? new OptionBuilderBase().positional(displayName) : new OptionBuilderBase().positional();
  1483. }
  1484. // Annotate the CommonJS export names for ESM import in node:
  1485. 0 && (module.exports = {
  1486. BroCliError,
  1487. boolean,
  1488. command,
  1489. commandsInfo,
  1490. getCommandNameWithParents,
  1491. handler,
  1492. number,
  1493. positional,
  1494. run,
  1495. string,
  1496. test
  1497. });
  1498. //# sourceMappingURL=index.cjs.map