@avandar/acclimate 0.3.4 → 0.4.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/README.md CHANGED
@@ -277,10 +277,13 @@ Acclimate.run(root);
277
277
 
278
278
  ## To do
279
279
 
280
+ - [ ] Add semantic functions such as Acclimate.printSuccess, .printInfo, .printWarn and .printError
281
+ - [ ] Allow user to configure semantic colors with Acclimate.setTheme()
282
+ - [ ] Add a beforeAll() function to handle global args
280
283
  - [ ] Add semantic arguments: e.g. email (which has a default validator)
281
284
  - [ ] Add default `help` command and `--help` option. This should show the CLI
282
285
  description and all param documentation.
283
- - [ ] Make the `description` actually get printed.
286
+ - [x] Make the `description` actually get printed.
284
287
  - [x] Show all CLI param descriptions if command is run with no arguments or if
285
288
  there is a param-related error.
286
289
  - [x] Add helper functions to log to stdout in different colors
package/dist/index.cjs CHANGED
@@ -187,6 +187,7 @@ function createCLI(name) {
187
187
  // src/generateTerminalMessage/generateTerminalMessage.ts
188
188
  var COLOR_CODES = {
189
189
  reset: "\x1B[0m",
190
+ dim: "\x1B[2m",
190
191
  black: "\x1B[30m",
191
192
  red: "\x1B[31m",
192
193
  green: "\x1B[32m",
@@ -235,9 +236,6 @@ function generateTerminalMessage(message, params = {}) {
235
236
  function formatSectionTitle(title) {
236
237
  return `|bright_yellow|${title}|reset|`;
237
238
  }
238
- function formatNoneLine() {
239
- return " |gray|None|reset|";
240
- }
241
239
  function formatDefaultValue(value) {
242
240
  return `|gray|[default: ${JSON.stringify(value)}]|reset|`;
243
241
  }
@@ -257,20 +255,15 @@ function formatParamLine(param) {
257
255
  }
258
256
  function formatSection(title, params) {
259
257
  if (params.length === 0) {
260
- return [formatSectionTitle(title), formatNoneLine()];
258
+ return [];
261
259
  }
262
260
  return [formatSectionTitle(title), ...params.map(formatParamLine)];
263
261
  }
264
- function formatCommandLine(options) {
265
- const { name, description } = options;
266
- const label = description ?? "No description";
267
- return ` |bright_white|${name}|reset| - |gray|${label}|reset|`;
268
- }
269
- function formatAvailableCommandsLine(commands) {
270
- const label = commands.length === 0 ? "None" : commands.map((cmd) => {
271
- return cmd;
272
- }).join(", ");
273
- return `|bright_yellow|Available Commands:|reset| |gray|${label}|reset|`;
262
+ function formatCommandBullets(commands) {
263
+ return commands.map(({ name, description }) => {
264
+ const descLabel = description !== void 0 ? `|gray|${description}|reset|` : `|dim|No description|reset|`;
265
+ return ` \u2022 |bright_white|${name}|reset| - ${descLabel}`;
266
+ });
274
267
  }
275
268
  function _generateHelpTextHelper(cli, options) {
276
269
  const name = cli.getName();
@@ -286,44 +279,36 @@ function _generateHelpTextHelper(cli, options) {
286
279
  const sortedCommands = Object.entries(cli.state.commands).sort(([a], [b]) => {
287
280
  return a.localeCompare(b);
288
281
  });
289
- const commandNames = sortedCommands.map(([commandName]) => {
290
- return commandName;
291
- });
292
282
  const headerLines = [`|bright_cyan|${name}|reset|`];
293
283
  if (description !== void 0) {
294
284
  headerLines.push(` |gray|${description}|reset|`);
295
285
  }
296
286
  let commandSection;
297
- if (level === 2) {
287
+ if (sortedCommands.length === 0) {
288
+ commandSection = [];
289
+ } else if (level === 2) {
290
+ const commandsWithDescriptions = sortedCommands.map(
291
+ ([commandName, commandCLI]) => ({
292
+ name: commandName,
293
+ description: commandCLI.state.description
294
+ })
295
+ );
298
296
  commandSection = [
299
297
  formatSectionTitle("Commands"),
300
- ` ${formatAvailableCommandsLine(commandNames)}`
298
+ ...formatCommandBullets(commandsWithDescriptions)
301
299
  ];
302
- } else if (sortedCommands.length === 0) {
303
- commandSection = [formatSectionTitle("Commands"), formatNoneLine()];
304
300
  } else {
305
- commandSection = [
306
- formatSectionTitle("Commands"),
307
- ...sortedCommands.map(([commandName, commandCLI]) => {
308
- return formatCommandLine({
309
- name: commandName,
310
- description: commandCLI.state.description
311
- });
312
- })
313
- ];
301
+ commandSection = [formatSectionTitle("Commands")];
314
302
  }
315
303
  const sections = [
316
304
  formatSection("Positional Arguments", positionalParams),
317
305
  formatSection("Options", optionParams),
318
306
  formatSection("Global Options", globalOptionParams),
319
307
  commandSection
320
- ];
321
- const lines = [...headerLines, ""];
308
+ ].filter((section) => section.length > 0);
309
+ const lines = [...headerLines];
322
310
  sections.forEach((section, idx) => {
323
- lines.push(...section);
324
- if (idx < sections.length - 1) {
325
- lines.push("");
326
- }
311
+ lines.push("", ...section);
327
312
  });
328
313
  if (level === 1) {
329
314
  const subCommandHelpText = sortedCommands.map(([, commandCLI]) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/CLIError.ts","../src/AcclimateCLI/AcclimateCLI.ts","../src/AcclimateCLI/createCLI/defaultCLIState.ts","../src/AcclimateCLI/createCLI/createCLI.ts","../src/generateTerminalMessage/generateTerminalMessage.ts","../src/AcclimateCLI/generateHelpText/generateHelpText.ts","../src/requestTerminalInput/requestTerminalInput.ts","../src/AcclimateCLI/runCLI/runCLI.ts","../src/Acclimate.ts"],"names":["match","createInterface","stdin","stdout","camelCase"],"mappings":";;;;;;;;AA4CO,IAAM,QAAA,GAAN,MAAM,SAAA,SAAiB,KAAA,CAAM;AAAA,EAClC,OAAO,qBAAqB,OAAA,EAKf;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EACE,OAAA,CAAQ,OAAA,IAAW,CAAA,6BAAA,EAAgC,QAAQ,SAAS,CAAA,CAAA,CAAA;AAAA,MACtE,IAAA,EAAM,yBAAA;AAAA,MACN,SAAS,EAAE,SAAA,EAAW,QAAQ,SAAA,EAAW,UAAA,EAAY,QAAQ,UAAA;AAAW,KACzE,CAAA;AAAA,EACH;AAAA,EACA,OAAO,sBAAsB,OAAA,EAIhB;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EACE,OAAA,CAAQ,OAAA,IAAW,CAAA,iBAAA,EAAoB,QAAQ,UAAU,CAAA,YAAA,CAAA;AAAA,MAC3D,IAAA,EAAM,yBAAA;AAAA,MACN,OAAA,EAAS,EAAE,UAAA,EAAY,OAAA,CAAQ,UAAA;AAAW,KAC3C,CAAA;AAAA,EACH;AAAA,EAEA,OAAO,6BAA6B,OAAA,EAIvB;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EACE,OAAA,CAAQ,OAAA,IACR,CAAA,8BAAA,EAAiC,QAAQ,iBAAiB,CAAA,YAAA,CAAA;AAAA,MAC5D,IAAA,EAAM,iCAAA;AAAA,MACN,OAAA,EAAS,EAAE,iBAAA,EAAmB,OAAA,CAAQ,iBAAA;AAAkB,KACzD,CAAA;AAAA,EACH;AAAA,EAEA,OAAO,cAAc,OAAA,EAIR;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,CAAA,QAAA,EAAW,QAAQ,UAAU,CAAA,WAAA,CAAA;AAAA,MACzD,IAAA,EAAM,gBAAA;AAAA,MACN,OAAA,EAAS,EAAE,UAAA,EAAY,OAAA,CAAQ,UAAA;AAAW,KAC3C,CAAA;AAAA,EACH;AAAA,EAEA,OAAO,sBAAsB,OAAA,EAIhB;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EAAS,QAAQ,OAAA,IAAW,yCAAA;AAAA,MAC5B,IAAA,EAAM,0BAAA;AAAA,MACN,OAAA,EAAS,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA;AAAM,KACjC,CAAA;AAAA,EACH;AAAA,EAEA,OAAO,2BAA2B,OAAA,EAIrB;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EACE,OAAA,CAAQ,OAAA,IACR,CAAA,uCAAA,EAA0C,QAAQ,iBAAiB,CAAA,YAAA,CAAA;AAAA,MACrE,IAAA,EAAM,+BAAA;AAAA,MACN,OAAA,EAAS,EAAE,iBAAA,EAAmB,OAAA,CAAQ,iBAAA;AAAkB,KACzD,CAAA;AAAA,EACH;AAAA,EAEA,OAAO,eAAe,OAAA,EAIT;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,CAAA,SAAA,EAAY,QAAQ,WAAW,CAAA,WAAA,CAAA;AAAA,MAC3D,IAAA,EAAM,iBAAA;AAAA,MACN,OAAA,EAAS,EAAE,WAAA,EAAa,OAAA,CAAQ,WAAA;AAAY,KAC7C,CAAA;AAAA,EACH;AAAA,EAEA,OAAO,WAAW,OAAA,EAGL;AACX,IAAA,OAAO,IAAI,SAAA,CAAS;AAAA,MAClB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,OAAA,EAAS,QAAQ,OAAA,IAAW,0BAAA;AAAA,MAC5B,IAAA,EAAM,aAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH;AAAA,EAEA,YAAY,OAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,wBAAmB,OAAA,CAAQ,OAAO,CAAA,EAAA,EAAK,OAAA,CAAQ,OAAO,CAAA,CAAE,CAAA;AAAA,EAChE;AACF,CAAA;;;AC/IO,SAAS,aAUd,KAAA,EAWA;AACA,EAAA,MAAM,UAAU,KAAA,CAAM,IAAA;AACtB,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IAEA,SAAS,MAAM;AACb,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA,IAEA,MAAA,EAAQ,CACN,MAAA,KAcG;AACH,MAAA,OAAO,YAAA,CAAa;AAAA,QAClB,GAAG,KAAA;AAAA,QACH;AAAA,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,WAAA,EAAa,CACX,WAAA,KAMG;AACH,MAAA,OAAO,YAAA,CAAa;AAAA,QAClB,GAAG,KAAA;AAAA,QACH;AAAA,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,gBAAA,EAAkB,CAIhB,KAAA,KACG;AACH,MAAA,IACE,MAAM,QAAA,IACN,KAAA,CAAM,cAAA,CAAe,IAAA,CAAK,CAAC,CAAA,KAAM;AAC/B,QAAA,OAAO,CAAC,CAAA,CAAE,QAAA;AAAA,MACZ,CAAC,CAAA,EACD;AACA,QAAA,MAAM,SAAS,0BAAA,CAA2B;AAAA,UACxC,OAAA;AAAA,UACA,mBAAmB,KAAA,CAAM,IAAA;AAAA,UACzB,OAAA,EACE;AAAA,SACH,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,YAAA,CAAa;AAAA,QAClB,GAAG,KAAA;AAAA,QACH,cAAA,EAAgB;AAAA,UACd,GAAG,KAAA,CAAM,cAAA;AAAA,UACT,EAAE,GAAG,KAAA,EAAO,QAAA,EAAU,KAAA,CAAM,YAAY,IAAA;AAAK;AAC/C,OAMD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,eAAA,EAAiB,CAA2B,KAAA,KAAa;AACvD,MAAA,MAAM,UAAA,GAAA,CAAc,KAAA,CAAM,OAAA,IAAW,EAAC,EAAG,MAAA;AAAA,QACvC,CAAC,KAAK,KAAA,KAAU;AACd,UAAA,GAAA,CAAI,KAAK,IAAI,KAAA,CAAM,IAAA;AACnB,UAAA,OAAO,GAAA;AAAA,QACT,CAAA;AAAA,QACA;AAAC,OACH;AACA,MAAA,OAAO,YAAA,CAKL;AAAA,QACA,GAAG,KAAA;AAAA,QACH,SAAS,EAAE,GAAG,KAAA,CAAM,OAAA,EAAS,GAAG,UAAA,EAAW;AAAA,QAC3C,gBAAA,EAAkB;AAAA,UAChB,GAAG,KAAA,CAAM,gBAAA;AAAA,UACT,CAAC,KAAA,CAAM,IAAI,GAAG;AAAA;AAChB,OAMD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,SAAA,EAAW,CAA2B,KAAA,KAAa;AACjD,MAAA,MAAM,UAAA,GAAA,CAAc,KAAA,CAAM,OAAA,IAAW,EAAC,EAAG,MAAA;AAAA,QACvC,CAAC,KAAK,KAAA,KAAU;AACd,UAAA,GAAA,CAAI,KAAK,IAAI,KAAA,CAAM,IAAA;AACnB,UAAA,OAAO,GAAA;AAAA,QACT,CAAA;AAAA,QACA;AAAC,OACH;AACA,MAAA,OAAO,YAAA,CAKL;AAAA,QACA,GAAG,KAAA;AAAA,QACH,SAAS,EAAE,GAAG,KAAA,CAAM,OAAA,EAAS,GAAG,UAAA,EAAW;AAAA,QAC3C,UAAA,EAAY,EAAE,GAAG,KAAA,CAAM,YAAY,CAAC,KAAA,CAAM,IAAI,GAAG,KAAA;AAAM,OAMxD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,UAAA,EAAY,CACV,WAAA,EACA,GAAA,KAMG;AACH,MAAA,OAAO,YAAA,CAAa;AAAA,QAClB,GAAG,KAAA;AAAA,QACH,QAAA,EAAU;AAAA,UACR,GAAG,KAAA,CAAM,QAAA;AAAA,UACT,CAAC,WAAW,GAAG;AAAA;AACjB,OAMD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,aAAA,EAAe,CACb,WAAA,KACqD;AACrD,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,QAAA,CAAS,WAAW,CAAA;AACtC,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,MAAM,SAAS,cAAA,CAAe;AAAA,UAC5B,OAAA;AAAA,UACA,WAAA;AAAA,UACA,OAAA,EAAS,YAAY,WAAW,CAAA,WAAA;AAAA,SACjC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,GACF;AACF;;;ACzMO,IAAM,eAAA,GAGT;AAAA,EACF,SAAS,EAAC;AAAA,EACV,WAAA,EAAa,MAAA;AAAA,EACb,UAAU,EAAC;AAAA,EACX,gBAAgB,EAAC;AAAA,EACjB,YAAY,EAAC;AAAA,EACb,kBAAkB,EAAC;AAAA,EACnB,MAAA,EAAQ;AACV,CAAA;;;ACHO,SAAS,UACd,IAAA,EACmE;AACnE,EAAA,OAAO,YAAA,CAAa,EAAE,GAAG,eAAA,EAAiB,MAAM,CAAA;AAClD;;;ACfA,IAAM,WAAA,GAAsC;AAAA,EAC1C,KAAA,EAAO,SAAA;AAAA,EACP,KAAA,EAAO,UAAA;AAAA,EACP,GAAA,EAAK,UAAA;AAAA,EACL,KAAA,EAAO,UAAA;AAAA,EACP,MAAA,EAAQ,UAAA;AAAA,EACR,IAAA,EAAM,UAAA;AAAA,EACN,OAAA,EAAS,UAAA;AAAA,EACT,IAAA,EAAM,UAAA;AAAA,EACN,KAAA,EAAO,UAAA;AAAA,EACP,YAAA,EAAc,UAAA;AAAA,EACd,IAAA,EAAM,UAAA;AAAA,EACN,IAAA,EAAM,UAAA;AAAA,EACN,UAAA,EAAY,UAAA;AAAA,EACZ,YAAA,EAAc,UAAA;AAAA,EACd,aAAA,EAAe,UAAA;AAAA,EACf,WAAA,EAAa,UAAA;AAAA,EACb,cAAA,EAAgB,UAAA;AAAA,EAChB,WAAA,EAAa,UAAA;AAAA,EACb,YAAA,EAAc;AAChB,CAAA;AAEA,IAAM,iBAAA,GAAoB,sBAAA;AAC1B,IAAM,iBAAA,GAAoB,mBAAA;AAM1B,SAAS,iBAAA,CACP,SACA,MAAA,EACQ;AACR,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,iBAAA,EAAmB,CAACA,QAAe,GAAA,KAAgB;AAExE,IAAA,MAAM,KAAA,GAAQ,OAAO,GAAG,CAAA;AACxB,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,OAAO,EAAA;AAAA,IACT;AACA,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB,CAAC,CAAA;AACH;AAEA,SAAS,YAAY,OAAA,EAAiB;AACpC,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,iBAAA,EAAmB,CAACA,QAAO,SAAA,KAAsB;AACtE,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,SAAA,CAAU,WAAA,EAAa,CAAA;AAChD,IAAA,OAAO,IAAA,IAAQA,MAAAA;AAAA,EACjB,CAAC,CAAA;AACH;AAuCO,SAAS,uBAAA,CACd,OAAA,EACA,MAAA,GAAuE,EAAC,EAChE;AACR,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,OAAA,CAAQ,KAAA,CAAM,iBAAiB,CAAC,CAAA;AAC9D,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,OAAA,EAAQ,CAAE,SAAS,SAAS,CAAA;AAC1D,EAAA,MAAM,YACJ,aAAA,IAAiB,CAAC,aAAA,GAAgB,CAAA,EAAG,OAAO,CAAA,OAAA,CAAA,GAAY,OAAA;AAC1D,EAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,SAAA,EAAW,MAAM,CAAA;AACxD,EAAA,OAAO,YAAY,YAAY,CAAA;AACjC;;;ACtEA,SAAS,mBAAmB,KAAA,EAA6B;AACvD,EAAA,OAAO,kBAAkB,KAAK,CAAA,OAAA,CAAA;AAChC;AAEA,SAAS,cAAA,GAAyB;AAChC,EAAA,OAAO,qBAAA;AACT;AAEA,SAAS,mBACP,KAAA,EACQ;AACR,EAAA,OAAO,CAAA,gBAAA,EAAmB,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA,QAAA,CAAA;AACjD;AAEA,SAAS,gBAAgB,KAAA,EAAqC;AAC5D,EAAA,MAAM,WAAA,GAAc,MAAM,WAAA,IAAe,gBAAA;AACzC,EAAA,MAAM,aAAA,GACJ,KAAA,CAAM,QAAA,GAAW,sBAAA,GAAyB,uBAAA;AAC5C,EAAA,MAAM,eACJ,KAAA,CAAM,YAAA,KAAiB,SACrB,kBAAA,CAAmB,KAAA,CAAM,YAAY,CAAA,GACrC,MAAA;AACJ,EAAA,MAAM,SAAA,GACJ,KAAA,CAAM,OAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,GAAI,EAAA;AACzE,EAAA,MAAM,WAAA,GAAc,YAAY,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,EAAA,EAAK,SAAS,KAAK,KAAA,CAAM,IAAA;AAEtE,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,mBAAmB,WAAW,CAAA,OAAA,CAAA;AAAA,IAC9B,CAAA,CAAA,EAAI,KAAA,CAAM,IAAI,CAAA,SAAA,EAAY,aAAa,CAAA,CAAA;AAAA,IACvC,WAAW,WAAW,CAAA,OAAA,CAAA;AAAA,IACtB;AAAA,GACF,CAAE,OAAO,OAAO,CAAA;AAEhB,EAAA,OAAO,QAAA,CAAS,KAAK,GAAG,CAAA;AAC1B;AAEA,SAAS,aAAA,CACP,OACA,MAAA,EACU;AACV,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,OAAO,CAAC,kBAAA,CAAmB,KAAK,CAAA,EAAG,gBAAgB,CAAA;AAAA,EACrD;AAEA,EAAA,OAAO,CAAC,mBAAmB,KAAK,CAAA,EAAG,GAAG,MAAA,CAAO,GAAA,CAAI,eAAe,CAAC,CAAA;AACnE;AAEA,SAAS,kBAAkB,OAAA,EAGhB;AACT,EAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAY,GAAI,OAAA;AAC9B,EAAA,MAAM,QAAQ,WAAA,IAAe,gBAAA;AAC7B,EAAA,OAAO,CAAA,gBAAA,EAAmB,IAAI,CAAA,gBAAA,EAAmB,KAAK,CAAA,OAAA,CAAA;AACxD;AAEA,SAAS,4BAA4B,QAAA,EAA4B;AAC/D,EAAA,MAAM,KAAA,GACJ,SAAS,MAAA,KAAW,CAAA,GAClB,SACA,QAAA,CACG,GAAA,CAAI,CAAC,GAAA,KAAQ;AACZ,IAAA,OAAO,GAAA;AAAA,EACT,CAAC,CAAA,CACA,IAAA,CAAK,IAAI,CAAA;AAChB,EAAA,OAAO,mDAAmD,KAAK,CAAA,OAAA,CAAA;AACjE;AAEA,SAAS,uBAAA,CAUP,KAMA,OAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,IAAI,OAAA,EAAQ;AACzB,EAAA,MAAM,WAAA,GAAc,IAAI,KAAA,CAAM,WAAA;AAC9B,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AAElC,EAAA,MAAM,gBAAA,GAAmB,IAAI,KAAA,CAC1B,cAAA;AACH,EAAA,MAAM,eAAe,MAAA,CAAO,MAAA;AAAA,IAC1B,IAAI,KAAA,CAAM;AAAA,GACZ;AACA,EAAA,MAAM,qBAAqB,MAAA,CAAO,MAAA;AAAA,IAChC,IAAI,KAAA,CAAM;AAAA,GACZ;AACA,EAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,OAAA,CAAQ,GAAA,CAAI,MAAM,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAC,CAAA,KAAM;AAC3E,IAAA,OAAO,CAAA,CAAE,cAAc,CAAC,CAAA;AAAA,EAC1B,CAAC,CAAA;AACD,EAAA,MAAM,eAAe,cAAA,CAAe,GAAA,CAAI,CAAC,CAAC,WAAW,CAAA,KAAM;AACzD,IAAA,OAAO,WAAA;AAAA,EACT,CAAC,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,CAAC,CAAA,aAAA,EAAgB,IAAI,CAAA,OAAA,CAAS,CAAA;AAClD,EAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,IAAA,WAAA,CAAY,IAAA,CAAK,CAAA,QAAA,EAAW,WAAW,CAAA,OAAA,CAAS,CAAA;AAAA,EAClD;AAEA,EAAA,IAAI,cAAA;AACJ,EAAA,IAAI,UAAU,CAAA,EAAG;AACf,IAAA,cAAA,GAAiB;AAAA,MACf,mBAAmB,UAAU,CAAA;AAAA,MAC7B,CAAA,EAAA,EAAK,2BAAA,CAA4B,YAAY,CAAC,CAAA;AAAA,KAChD;AAAA,EACF,CAAA,MAAA,IAAW,cAAA,CAAe,MAAA,KAAW,CAAA,EAAG;AACtC,IAAA,cAAA,GAAiB,CAAC,kBAAA,CAAmB,UAAU,CAAA,EAAG,gBAAgB,CAAA;AAAA,EACpE,CAAA,MAAO;AACL,IAAA,cAAA,GAAiB;AAAA,MACf,mBAAmB,UAAU,CAAA;AAAA,MAC7B,GAAG,cAAA,CAAe,GAAA,CAAI,CAAC,CAAC,WAAA,EAAa,UAAU,CAAA,KAAM;AACnD,QAAA,OAAO,iBAAA,CAAkB;AAAA,UACvB,IAAA,EAAM,WAAA;AAAA,UACN,WAAA,EAAa,WAAW,KAAA,CAAM;AAAA,SAC/B,CAAA;AAAA,MACH,CAAC;AAAA,KACH;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,aAAA,CAAc,wBAAwB,gBAAgB,CAAA;AAAA,IACtD,aAAA,CAAc,WAAW,YAAY,CAAA;AAAA,IACrC,aAAA,CAAc,kBAAkB,kBAAkB,CAAA;AAAA,IAClD;AAAA,GACF;AAEA,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,WAAA,EAAa,EAAE,CAAA;AACjC,EAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,OAAA,EAAS,GAAA,KAAQ;AACjC,IAAA,KAAA,CAAM,IAAA,CAAK,GAAG,OAAO,CAAA;AACrB,IAAA,IAAI,GAAA,GAAM,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC7B,MAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,IACf;AAAA,EACF,CAAC,CAAA;AAED,EAAA,IAAI,UAAU,CAAA,EAAG;AACf,IAAA,MAAM,qBAAqB,cAAA,CAAe,GAAA,CAAI,CAAC,GAAG,UAAU,CAAA,KAAM;AAChE,MAAA,OAAO,uBAAA,CAAwB,UAAA,EAAY,EAAE,KAAA,EAAO,GAAG,CAAA;AAAA,IACzD,CAAC,CAAA;AACD,IAAA,IAAI,kBAAA,CAAmB,SAAS,CAAA,EAAG;AACjC,MAAA,kBAAA,CAAmB,OAAA,CAAQ,CAAC,IAAA,KAAS;AACnC,QAAA,KAAA,CAAM,KAAK,EAAA,EAAI,GAAG,IAAA,CAAK,KAAA,CAAM,IAAI,CAAC,CAAA;AAAA,MACpC,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAS,OAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG,KAAA,GAAQ,CAAC,CAAC,CAAA;AACnD,EAAA,OAAO,KAAA,CACJ,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,IAAA,OAAO,SAAS,EAAA,GAAK,EAAA,GAAK,CAAA,EAAG,MAAM,GAAG,IAAI,CAAA,CAAA;AAAA,EAC5C,CAAC,CAAA,CACA,IAAA,CAAK,IAAI,CAAA;AACd;AAEO,SAAS,iBAUd,GAAA,EAMQ;AACR,EAAA,OAAO,wBAAwB,uBAAA,CAAwB,GAAA,EAAK,EAAE,KAAA,EAAO,CAAA,EAAG,CAAC,CAAA;AAC3E;AC1MA,eAAsB,qBAAqB,OAAA,EAeX;AAC9B,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA,EAAiB,EAAE,QAAA,EAAU,IAAA,EAAM,YAAA;AAAa,GAClD,GAAI,OAAA;AACJ,EAAA,MAAM,MAAA,GACJ,YAAA,KAAiB,MAAA,GAAY,4CAAA,GAC3B,WAAW,EAAA,GACX,4CAAA;AACJ,EAAA,MAAM,aAAA,GACJ,YAAA,KAAiB,MAAA,GAAY,CAAA,WAAA,EAAc,YAAY,CAAA,CAAA,CAAA,GAAM,EAAA;AAC/D,EAAA,MAAM,aAAA,GAAgB,IAAA,KAAS,SAAA,GAAY,eAAA,GAAkB,EAAA;AAC7D,EAAA,MAAM,aAAA,GAAgB,GAAG,OAAO,CAAA,EAAG,aAAa,CAAA,EAAG,aAAa,GAAG,MAAM,CAAA,CAAA,CAAA;AACzE,EAAA,MAAM,MAAA,GAAS,uBAAA,CAAwB,aAAA,EAAe,MAAM,CAAA;AAE5D,EAAA,MAAM,KAAKC,wBAAA,CAAgB,EAAE,OAAOC,eAAA,EAAO,MAAA,EAAQC,kBAAQ,CAAA;AAC3D,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,MAAA,GAAS,MAAM,EAAA,CAAG,QAAA,CAAS,MAAM,CAAA;AACvC,MAAA,MAAM,OAAA,GAAU,OAAO,IAAA,EAAK;AAC5B,MAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,QAAA,IAAI,iBAAiB,KAAA,CAAA,EAAW;AAE9B,UAAA,OACE,OAAO,YAAA,KAAiB,QAAA,GAAW,YAAA,GACjC,OAAO,YAAA,KAAiB,QAAA,GAAW,MAAA,CAAO,YAAY,CAAA,GACtD,YAAA,GAAe,MAAA,GACf,OAAA;AAAA,QAEN;AAEA,QAAA,IAAI,QAAA,EAAU;AACZ,UAAAA,gBAAA,CAAO,KAAA;AAAA,YACL,uBAAA;AAAA,cACE;AAAA;AACF,WACF;AACA,UAAA;AAAA,QACF;AACA,QAAA,OAAO,KAAA,CAAA;AAAA,MACT;AACA,MAAA,IAAI,SAAS,SAAA,EAAW;AACtB,QAAA,MAAM,UAAA,GAAa,QAAQ,WAAA,EAAY;AACvC,QAAA,IAAI,UAAA,KAAe,GAAA,IAAO,UAAA,KAAe,KAAA,EAAO;AAC9C,UAAA,OAAO,MAAA;AAAA,QACT;AACA,QAAA,IAAI,UAAA,KAAe,GAAA,IAAO,UAAA,KAAe,IAAA,EAAM;AAC7C,UAAA,OAAO,OAAA;AAAA,QACT;AACA,QAAAA,gBAAA,CAAO,KAAA;AAAA,UACL,uBAAA;AAAA,YACE;AAAA;AACF,SACF;AACA,QAAA;AAAA,MACF;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF,CAAA,SAAE;AACA,IAAA,EAAA,CAAG,KAAA,EAAM;AAAA,EACX;AACF;;;AC9DA,SAAS,uBAAuB,IAAA,EAAyC;AACvE,EAAA,OAAO,IAAA,CAAK,WAAW,IAAI,CAAA;AAC7B;AAEA,SAAS,oBAAoB,IAAA,EAAsC;AACjE,EAAA,OAAO,IAAA,CAAK,WAAW,GAAG,CAAA;AAC5B;AAEA,SAAS,cAAc,GAAA,EAAiC;AACtD,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,KAAW,CAAA;AACrC;AAEA,SAAS,qBAGP,OAAA,EAA2E;AAC3E,EAAA,MAAM,EAAE,WAAA,EAAa,WAAA,EAAa,OAAA,EAAQ,GAAI,OAAA;AAC9C,EAAA,IAAI,YAAY,SAAA,EAAW;AACzB,IAAA,MAAM,YAAY,WAAA,CAAY,SAAA;AAG9B,IAAA,MAAM,gBAAA,GAAmB,UAAU,WAAW,CAAA;AAC9C,IAAA,IAAI,qBAAqB,IAAA,EAAM;AAC7B,MAAA,OAAO,WAAA;AAAA,IACT;AACA,IAAA,MAAM,SAAS,oBAAA,CAAqB;AAAA,MAClC,OAAA;AAAA,MACA,WAAW,WAAA,CAAY,IAAA;AAAA,MACvB,UAAA,EAAY,WAAA;AAAA,MACZ,OAAA,EACE,OAAO,gBAAA,KAAqB,QAAA,GAAW,gBAAA,GAAmB;AAAA,KAC7D,CAAA;AAAA,EACH;AACA,EAAA,OAAO,WAAA;AACT;AAEA,SAAS,uBAGP,OAAA,EAKqB;AACrB,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,YAAA,EAAc,aAAY,GAAI,OAAA;AAC3D,EAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAO,oBAAA,CAAqB;AAAA,MAC1B,OAAA;AAAA,MACA,WAAA,EAAa,YAAA;AAAA,MACb;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,WAAA,GACJ,WAAA,CAAY,MAAA,GACT,WAAA,CAAY,MAAA,CAAO,UAAU,CAAA,GAE7BH,eAAA,CAAM,WAAA,CAAY,IAAI,CAAA,CACpB,IAAA,CAAK,WAAW,MAAM;AACrB,IAAA,OAAO,UAAA,KAAe,UAAU,KAAA,GAAQ,IAAA;AAAA,EAC1C,CAAC,CAAA,CACA,IAAA,CAAK,QAAA,EAAU,MAAM;AACpB,IAAA,OAAO,MAAA,CAAO,QAAA,CAAS,UAAA,EAAY,EAAE,CAAA;AAAA,EACvC,CAAC,CAAA,CACA,IAAA,CAAK,QAAA,EAAU,MAAM;AACpB,IAAA,OAAO,UAAA;AAAA,EACT,CAAC,CAAA,CACA,UAAA,CAAW,MAAM;AAChB,IAAA,OAAO,UAAA;AAAA,EACT,CAAC,CAAA;AACP,EAAA,OAAO,oBAAA,CAAqB;AAAA,IAC1B,OAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;AAEA,SAAS,eAAA,CASP;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAA,EAQmC;AACjC,EAAA,MAAM,QAAA,GAAW,IAAI,KAAA,CAAM,OAAA;AAC3B,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,iBAAiB,CAAA,CAAE,MAAA;AAAA,IACvC,CAAC,GAAA,EAAK,CAAC,QAAA,EAAU,KAAK,CAAA,KAAM;AAC1B,MAAA,MAAM,KAAA,GAAQ,QAAA;AACd,MAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAK,CAAA,IAAK,KAAA;AACtC,MAAA,GAAA,CAAI,UAAU,CAAA,GAAI,KAAA;AAClB,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IACA;AAAC,GACH;AACF;AAMA,eAAe,YAAY,OAAA,EAEK;AAC9B,EAAA,MAAM,EAAE,WAAU,GAAI,OAAA;AACtB,EAAA,MAAM,aAAa,SAAA,CAAU,UAAA;AAC7B,EAAA,MAAM,cACJ,SAAA,CAAU,WAAA,GAAc,CAAA,EAAA,EAAK,SAAA,CAAU,WAAW,CAAA,CAAA,CAAA,GAAM,EAAA;AAC1D,EAAA,MAAM,WAAA,GACJ,OAAO,UAAA,KAAe,QAAA,GACpB,UAAA,CAAW,UACX,CAAA,yBAAA,EAA4B,SAAA,CAAU,IAAI,CAAA,EAAG,WAAW,CAAA,CAAA;AAC5D,EAAA,MAAM,cAAA,GAAiB,gBAAgB,WAAW,CAAA,OAAA,CAAA;AAClD,EAAA,OAAO,oBAAA,CAAqB;AAAA,IAC1B,OAAA,EAAS,cAAA;AAAA,IACT,QAAQ,EAAC;AAAA,IACT,eAAA,EAAiB;AAAA,MACf,UAAU,SAAA,CAAU,QAAA;AAAA,MACpB,MAAM,SAAA,CAAU,IAAA;AAAA,MAChB,cAAc,SAAA,CAAU;AAAA;AAC1B,GACD,CAAA;AACH;AAEA,eAAe,cASb,OAAA,EAUgB;AAChB,EAAA,MAAM,EAAE,mBAAA,EAAqB,aAAA,EAAe,iBAAA,EAAmB,KAAI,GAAI;AAAA,IACrE,GAAG,OAAA;AAAA,IACH,qBAAqB,eAAA,CAAgB;AAAA,MACnC,mBAAmB,OAAA,CAAQ,mBAAA;AAAA,MAC3B,KAAK,OAAA,CAAQ;AAAA,KACd,CAAA;AAAA,IACD,eAAe,eAAA,CAAgB;AAAA,MAC7B,mBAAmB,OAAA,CAAQ,aAAA;AAAA;AAAA,MAG3B,KAAK,OAAA,CAAQ;AAAA,KACd;AAAA,GACH;AAGA,EAAA,MAAM,QAAA,GAAW,kBAAkB,CAAC,CAAA;AACpC,EAAA,IACE,QAAA,IACA,CAAC,aAAA,CAAc,GAAA,CAAI,KAAA,CAAM,QAAQ,CAAA,IACjC,GAAA,CAAI,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAA,EAC3B;AAEA,IAAA,MAAM,aAAa,MAAA,CAAO,MAAA;AAAA,MACxB,IAAI,KAAA,CAAM;AAAA,KACZ,CAAE,MAAA;AAAA,MACA,CAAC,QAAQ,SAAA,KAAc;AACrB,QAAA,OAAO,MAAA,CAAO,gBAAgB,SAAS,CAAA;AAAA,MACzC,CAAA;AAAA,MACA,GAAA,CAAI,cAAc,QAA4C;AAAA,KAChE;AAGA,IAAA,OAAO,aAAA,CAAc;AAAA,MACnB,iBAAA,EAAmB,iBAAA,CAAkB,KAAA,CAAM,CAAC,CAAA;AAAA,MAC5C,aAAA;AAAA,MACA,mBAAA;AAAA,MACA,GAAA,EAAK;AAAA,KACN,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAI5B,EAAA,IAAI,iBAAA,CAAkB,MAAA,GAAS,GAAA,CAAI,KAAA,CAAM,eAAe,MAAA,EAAQ;AAC9D,IAAA,MAAM,SAAS,qBAAA,CAAsB;AAAA,MACnC,OAAA;AAAA,MACA,OAAO,iBAAA,CAAkB;AAAA,KAC1B,CAAA;AAAA,EACH;AAGA,EAAA,MAAM,uBAAyD,EAAC;AAChE,EAAA,KAAA,MAAW,CAAC,KAAK,SAAS,CAAA,IAAK,IAAI,KAAA,CAAM,cAAA,CAAe,SAAQ,EAAG;AACjE,IAAA,IAAI,MAAA,GAAS,kBAAkB,GAAG,CAAA;AAClC,IAAA,IAAI,SAAA,CAAU,UAAA,IAAc,MAAA,KAAW,MAAA,EAAW;AAChD,MAAA,MAAA,GAAS,MAAM,WAAA,CAAY,EAAE,SAAA,EAAW,CAAA;AAAA,IAC1C;AAEA,IAAA,IAAI,SAAA,CAAU,QAAA,IAAY,MAAA,KAAW,MAAA,EAAW;AAC9C,MAAA,MAAM,SAAS,4BAAA,CAA6B;AAAA,QAC1C,OAAA;AAAA,QACA,mBAAmB,SAAA,CAAU;AAAA,OAC9B,CAAA;AAAA,IACH;AAEA,IAAA,oBAAA,CAAqB,SAAA,CAAU,IAAI,CAAA,GAAI,sBAAA,CAAuB;AAAA,MAC5D,OAAA;AAAA,MACA,UAAA,EAAY,MAAA;AAAA,MACZ,cAAc,SAAA,CAAU,YAAA;AAAA,MACxB,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAGA,EAAA,MAAM,mBAAqD,EAAC;AAC5D,EAAA,KAAA,MAAW,aAAa,MAAA,CAAO,MAAA;AAAA,IAC7B,IAAI,KAAA,CAAM;AAAA,GACZ,EAAG;AACD,IAAA,IAAI,MAAA,GAAS,aAAA,CAAc,SAAA,CAAU,IAAI,CAAA;AACzC,IAAA,IAAI,SAAA,CAAU,UAAA,IAAc,MAAA,KAAW,MAAA,EAAW;AAChD,MAAA,MAAA,GAAS,MAAM,WAAA,CAAY,EAAE,SAAA,EAAW,CAAA;AAAA,IAC1C;AAEA,IAAA,IAAI,SAAA,CAAU,QAAA,IAAY,MAAA,KAAW,MAAA,EAAW;AAC9C,MAAA,MAAM,SAAS,qBAAA,CAAsB;AAAA,QACnC,OAAA;AAAA,QACA,YAAY,SAAA,CAAU;AAAA,OACvB,CAAA;AAAA,IACH;AAEA,IAAA,gBAAA,CAAiBI,oBAAA,CAAU,SAAA,CAAU,IAAI,CAAC,IAAI,sBAAA,CAAuB;AAAA,MACnE,OAAA;AAAA,MACA,UAAA,EAAY,MAAA;AAAA,MACZ,cAAc,SAAA,CAAU,YAAA;AAAA,MACxB,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAGA,EAAA,MAAM,yBAA2D,EAAC;AAClE,EAAA,KAAA,MAAW,aAAa,MAAA,CAAO,MAAA;AAAA,IAC7B,IAAI,KAAA,CAAM;AAAA,GACZ,EAAG;AACD,IAAA,IAAI,MAAA,GAAS,mBAAA,CAAoB,SAAA,CAAU,IAAI,CAAA;AAC/C,IAAA,IAAI,SAAA,CAAU,UAAA,IAAc,MAAA,KAAW,MAAA,EAAW;AAChD,MAAA,MAAA,GAAS,MAAM,WAAA,CAAY,EAAE,SAAA,EAAW,CAAA;AAAA,IAC1C;AAEA,IAAA,IAAI,SAAA,CAAU,QAAA,IAAY,MAAA,KAAW,MAAA,EAAW;AAC9C,MAAA,MAAM,SAAS,qBAAA,CAAsB;AAAA,QACnC,OAAA;AAAA,QACA,YAAY,SAAA,CAAU;AAAA,OACvB,CAAA;AAAA,IACH;AACA,IAAA,sBAAA,CAAuBA,oBAAA,CAAU,SAAA,CAAU,IAAI,CAAC,IAAI,sBAAA,CAAuB;AAAA,MACzE,OAAA;AAAA,MACA,UAAA,EAAY,MAAA;AAAA,MACZ,cAAc,SAAA,CAAU,YAAA;AAAA,MACxB,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAGA,EAAA,MAAM,MAAA,GAAS,IAAI,KAAA,CAAM,MAAA;AACzB,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAA,CAAO;AAAA,MACL,GAAG,oBAAA;AAAA,MACH,GAAG,gBAAA;AAAA,MACH,GAAG;AAAA,KAKJ,CAAA;AACD,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,GAAA,CAAI,gBAAA,CAAiB,GAAG,CAAC,CAAA;AACnC;AAOA,eAAsB,OAAO,OAAA,EAGX;AAChB,EAAA,MAAM,EAAE,KAAA,EAAO,GAAA,EAAI,GAAI,OAAA;AACvB,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,SAAA,CAAU,CAAC,KAAA,KAAU;AAChD,IAAA,OAAO,KAAA,CAAM,WAAW,GAAG,CAAA;AAAA,EAC7B,CAAC,CAAA;AAED,EAAA,MAAM,CAAC,mBAAmB,IAAI,CAAA,GAC5B,mBAAmB,EAAA,GACjB,CAAC,OAAO,EAAE,IACV,CAAC,KAAA,CAAM,MAAM,CAAA,EAAG,cAAc,GAAG,KAAA,CAAM,KAAA,CAAM,cAAc,CAAC,CAAA;AAEhE,EAAA,MAAM,gBAAgD,EAAC;AACvD,EAAA,MAAM,sBAAyD,EAAC;AAChE,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI,cAAwB,EAAC;AAE7B,EAAA,MAAM,EAAE,OAAA,EAAS,gBAAA,EAAiB,GAAI,GAAA,CAAI,KAAA;AAO1C,EAAA,KAAA,MAAW,MAAA,IAAU,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,EAAG;AACrC,IAAA,IAAI,mBAAA,CAAoB,MAAM,CAAA,EAAG;AAC/B,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,MAAM,QAAA,GAAW,WAAA,CAAY,IAAA,CAAK,GAAG,CAAA;AACrC,QAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,YAAY,CAAA,IAAK,YAAA;AAC5C,QAAA,IACE,sBAAA,CAAuB,UAAU,CAAA,IACjC,CAAC,cAAc,gBAAgB,CAAA,IAC/B,gBAAA,CAAiB,UAAU,CAAA,EAC3B;AACA,UAAA,mBAAA,CAAoB,UAAU,CAAA,GAAI,QAAA;AAAA,QACpC,CAAA,MAAO;AACL,UAAA,aAAA,CAAc,UAAU,CAAA,GAAI,QAAA;AAAA,QAC9B;AAAA,MACF;AACA,MAAA,YAAA,GAAe,MAAA;AACf,MAAA,WAAA,GAAc,EAAC;AAAA,IACjB,CAAA,MAAO;AACL,MAAA,WAAA,CAAY,KAAK,MAAM,CAAA;AAAA,IACzB;AAAA,EACF;AAEA,EAAA,MAAM,aAAA,CAAc;AAAA,IAClB,iBAAA;AAAA,IACA,aAAA;AAAA,IACA,mBAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;;;ACrSO,IAAM,SAAA,GAAuB;AAAA,EAClC,SAAA;AAAA,EACA,GAAA,EAAK,CAAC,GAAA,KAAgB;AACpB,IAAA,KAAK,MAAA,CAAO,EAAE,GAAA,EAAK,KAAA,EAAO,QAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA;AAAA,EACnD,CAAA;AAAA,EACA,GAAA,EAAK,CACH,OAAA,EACA,MAAA,GAAuE,EAAC,KACrE;AACH,IAAA,OAAA,CAAQ,GAAA,CAAI,uBAAA,CAAwB,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,EACtD,CAAA;AAAA,EACA,YAAA,EAAc,CAAC,OAAA,KAAY;AACzB,IAAA,OAAO,qBAAqB,OAAO,CAAA;AAAA,EACrC;AACF","file":"index.cjs","sourcesContent":["import type { CLIParamDataType } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype CLIErrorInfo =\n | {\n code: \"already_run\";\n details: undefined;\n }\n | {\n code: \"unknown_command\";\n details: { commandName: string };\n }\n | {\n code: \"invalid_positional_arg_config\";\n details: { positionalArgName: string };\n }\n | {\n code: \"too_many_positional_args\";\n details: { count: number };\n }\n | {\n code: \"missing_required_positional_arg\";\n details: { positionalArgName: string };\n }\n | {\n code: \"missing_required_option\";\n details: { optionName: string };\n }\n | {\n code: \"unknown_option\";\n details: {\n optionName: string;\n };\n }\n | {\n code: \"invalid_cli_param_value\";\n details: {\n paramName: string;\n paramValue: CLIParamDataType;\n };\n }\n | { code: \"unknown_error\"; details: undefined };\n\ntype CLIErrorOptions = { cliName: string; message: string } & CLIErrorInfo;\n\nexport class CLIError extends Error {\n static invalidCLIParamValue(options: {\n cliName: string;\n paramName: string;\n paramValue: CLIParamDataType;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Invalid value for CLI param \"${options.paramName}\"`,\n code: \"invalid_cli_param_value\",\n details: { paramName: options.paramName, paramValue: options.paramValue },\n });\n }\n static missingRequiredOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Required option \"${options.optionName}\" is missing`,\n code: \"missing_required_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static missingRequiredPositionalArg(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Required positional argument \"${options.positionalArgName}\" is missing`,\n code: \"missing_required_positional_arg\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Option \"${options.optionName}\" not found`,\n code: \"unknown_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static tooManyPositionalArgs(options: {\n cliName: string;\n count: number;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"Too many positional arguments provided.\",\n code: \"too_many_positional_args\",\n details: { count: options.count },\n });\n }\n\n static invalidPositionalArgConfig(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Positional argument configuration for \"${options.positionalArgName}\" is invalid`,\n code: \"invalid_positional_arg_config\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownCommand(options: {\n cliName: string;\n commandName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Command \"${options.commandName}\" not found`,\n code: \"unknown_command\",\n details: { commandName: options.commandName },\n });\n }\n\n static alreadyRun(options: {\n cliName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"CLI has already been run\",\n code: \"already_run\",\n details: undefined,\n });\n }\n\n constructor(options: CLIErrorOptions) {\n super(`❌ Error running ${options.cliName}: ${options.message}`);\n }\n}\n","import { CLIError } from \"@/CLIError\";\nimport type {\n AddEntry,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n} from \"./AcclimateCLI.types\";\nimport type { EmptyObject, Simplify } from \"type-fest\";\n\nexport function AcclimateCLI<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, IAcclimateCLI> | EmptyObject,\n>(\n state: CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n> {\n const cliName = state.name;\n return {\n state,\n\n getName: () => {\n return cliName;\n },\n\n action: (\n action: (\n args: Simplify<\n FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >\n >,\n ) => void,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n action,\n });\n },\n\n description: (\n description: string,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n description,\n });\n },\n\n addPositionalArg: <\n PName extends CLIPositionalParamName,\n P extends CLIPositionalParam<PName>,\n >(\n param: P,\n ) => {\n if (\n param.required &&\n state.positionalArgs.some((p) => {\n return !p.required;\n })\n ) {\n throw CLIError.invalidPositionalArgConfig({\n cliName,\n positionalArgName: param.name,\n message:\n \"Required positional arguments must be before optional positional arguments\",\n });\n }\n\n return AcclimateCLI({\n ...state,\n positionalArgs: [\n ...state.positionalArgs,\n { ...param, required: param.required ?? true },\n ],\n } as unknown as CLIState<\n AddEntry<TPositionalParams, P[\"name\"], P>,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addGlobalOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n globalOptionArgs: {\n ...state.globalOptionArgs,\n [param.name]: param,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >);\n },\n\n addOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n optionArgs: { ...state.optionArgs, [param.name]: param },\n } as unknown as CLIState<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addCommand: <C extends CLICommandName, CommandCLI extends IAcclimateCLI>(\n commandName: C,\n cli: CommandCLI,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n > => {\n return AcclimateCLI({\n ...state,\n commands: {\n ...state.commands,\n [commandName]: cli,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n >);\n },\n\n getCommandCLI: <C extends Extract<keyof TCommands, CLICommandName>>(\n commandName: C,\n ): C extends keyof TCommands ? TCommands[C] : never => {\n const cmd = state.commands[commandName];\n if (!cmd) {\n throw CLIError.unknownCommand({\n cliName,\n commandName,\n message: `Command \"${commandName}\" not found`,\n });\n }\n return cmd as C extends keyof TCommands ? TCommands[C] : never;\n },\n };\n}\n","import type { CLIState } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nexport const defaultCLIState: Omit<\n CLIState<EmptyObject, EmptyObject, EmptyObject, EmptyObject>,\n \"name\"\n> = {\n aliases: {},\n description: undefined,\n commands: {},\n positionalArgs: [],\n optionArgs: {},\n globalOptionArgs: {},\n action: undefined,\n};\n","import { AcclimateCLI } from \"../AcclimateCLI\";\nimport { defaultCLIState } from \"./defaultCLIState\";\nimport type { IAcclimateCLI } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\n/**\n * Builder function to create a new CLI instance with a given name.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\nexport function createCLI(\n name: string,\n): IAcclimateCLI<EmptyObject, EmptyObject, EmptyObject, EmptyObject> {\n return AcclimateCLI({ ...defaultCLIState, name });\n}\n","const COLOR_CODES: Record<string, string> = {\n reset: \"\\x1b[0m\",\n black: \"\\x1b[30m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n bright_black: \"\\x1b[90m\",\n gray: \"\\x1b[90m\",\n grey: \"\\x1b[90m\",\n bright_red: \"\\x1b[91m\",\n bright_green: \"\\x1b[92m\",\n bright_yellow: \"\\x1b[93m\",\n bright_blue: \"\\x1b[94m\",\n bright_magenta: \"\\x1b[95m\",\n bright_cyan: \"\\x1b[96m\",\n bright_white: \"\\x1b[97m\",\n};\n\nconst PARAM_TOKEN_REGEX = /\\$([a-zA-Z0-9_]+)\\$/g;\nconst COLOR_TOKEN_REGEX = /\\|([a-zA-Z_]+)\\|/g;\n\n/**\n * Replaces `$token$` placeholders with values from `params`.\n * If a token does not exist in `params`, the placeholder is left unchanged.\n */\nfunction interpolateParams(\n message: string,\n params: Record<string, string | boolean | number | null | undefined>,\n): string {\n return message.replace(PARAM_TOKEN_REGEX, (match: string, key: string) => {\n void match;\n const value = params[key];\n if (value === undefined) {\n return \"\";\n }\n return String(value);\n });\n}\n\nfunction applyColors(message: string) {\n return message.replace(COLOR_TOKEN_REGEX, (match, colorName: string) => {\n const code = COLOR_CODES[colorName.toLowerCase()];\n return code ?? match;\n });\n}\n\n/**\n * Outputs a message intended to be passed directly to `console.log`\n *\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\nexport function generateTerminalMessage(\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n): string {\n const hasColorToken = Boolean(message.match(COLOR_TOKEN_REGEX));\n const endsWithReset = message.trimEnd().endsWith(\"|reset|\");\n const withReset =\n hasColorToken && !endsWithReset ? `${message}|reset|` : message;\n const interpolated = interpolateParams(withReset, params);\n return applyColors(interpolated);\n}\n","import { generateTerminalMessage } from \"@/generateTerminalMessage\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n IAcclimateCLI,\n} from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nconst _SECTION_TITLES = [\n \"Positional Arguments\",\n \"Options\",\n \"Global Options\",\n \"Commands\",\n] as const;\n\ntype SectionTitle = (typeof _SECTION_TITLES)[number];\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n aliases?: readonly string[];\n};\n\nfunction formatSectionTitle(title: SectionTitle): string {\n return `|bright_yellow|${title}|reset|`;\n}\n\nfunction formatNoneLine(): string {\n return \" |gray|None|reset|\";\n}\n\nfunction formatDefaultValue(\n value: CLIParamWithRequired[\"defaultValue\"],\n): string {\n return `|gray|[default: ${JSON.stringify(value)}]|reset|`;\n}\n\nfunction formatParamLine(param: CLIParamWithRequired): string {\n const description = param.description ?? \"No description\";\n const requiredLabel =\n param.required ? \"|red|required|reset|\" : \"|gray|optional|reset|\";\n const defaultLabel =\n param.defaultValue !== undefined ?\n formatDefaultValue(param.defaultValue)\n : undefined;\n const aliasList =\n param.aliases && param.aliases.length > 0 ? param.aliases.join(\", \") : \"\";\n const displayName = aliasList ? `${param.name}, ${aliasList}` : param.name;\n\n const segments = [\n ` |bright_white|${displayName}|reset|`,\n `(${param.type})|reset| ${requiredLabel}`,\n `- |gray|${description}|reset|`,\n defaultLabel,\n ].filter(Boolean);\n\n return segments.join(\" \");\n}\n\nfunction formatSection(\n title: SectionTitle,\n params: readonly CLIParamWithRequired[],\n): string[] {\n if (params.length === 0) {\n return [formatSectionTitle(title), formatNoneLine()];\n }\n\n return [formatSectionTitle(title), ...params.map(formatParamLine)];\n}\n\nfunction formatCommandLine(options: {\n name: string;\n description?: string;\n}): string {\n const { name, description } = options;\n const label = description ?? \"No description\";\n return ` |bright_white|${name}|reset| - |gray|${label}|reset|`;\n}\n\nfunction formatAvailableCommandsLine(commands: string[]): string {\n const label =\n commands.length === 0 ?\n \"None\"\n : commands\n .map((cmd) => {\n return cmd;\n })\n .join(\", \");\n return `|bright_yellow|Available Commands:|reset| |gray|${label}|reset|`;\n}\n\nfunction _generateHelpTextHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n options: { level: 1 | 2 },\n): string {\n const name = cli.getName();\n const description = cli.state.description;\n const level = Number(options.level);\n\n const positionalParams = cli.state\n .positionalArgs as readonly CLIParamWithRequired[];\n const optionParams = Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const globalOptionParams = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const sortedCommands = Object.entries(cli.state.commands).sort(([a], [b]) => {\n return a.localeCompare(b);\n });\n const commandNames = sortedCommands.map(([commandName]) => {\n return commandName;\n });\n\n const headerLines = [`|bright_cyan|${name}|reset|`];\n if (description !== undefined) {\n headerLines.push(` |gray|${description}|reset|`);\n }\n\n let commandSection: string[];\n if (level === 2) {\n commandSection = [\n formatSectionTitle(\"Commands\"),\n ` ${formatAvailableCommandsLine(commandNames)}`,\n ];\n } else if (sortedCommands.length === 0) {\n commandSection = [formatSectionTitle(\"Commands\"), formatNoneLine()];\n } else {\n commandSection = [\n formatSectionTitle(\"Commands\"),\n ...sortedCommands.map(([commandName, commandCLI]) => {\n return formatCommandLine({\n name: commandName,\n description: commandCLI.state.description,\n });\n }),\n ];\n }\n\n const sections = [\n formatSection(\"Positional Arguments\", positionalParams),\n formatSection(\"Options\", optionParams),\n formatSection(\"Global Options\", globalOptionParams),\n commandSection,\n ];\n\n const lines = [...headerLines, \"\"];\n sections.forEach((section, idx) => {\n lines.push(...section);\n if (idx < sections.length - 1) {\n lines.push(\"\");\n }\n });\n\n if (level === 1) {\n const subCommandHelpText = sortedCommands.map(([, commandCLI]) => {\n return _generateHelpTextHelper(commandCLI, { level: 2 });\n });\n if (subCommandHelpText.length > 0) {\n subCommandHelpText.forEach((text) => {\n lines.push(\"\", ...text.split(\"\\n\"));\n });\n }\n }\n\n const indent = \" \".repeat(Math.max(0, level - 1));\n return lines\n .map((line) => {\n return line === \"\" ? \"\" : `${indent}${line}`;\n })\n .join(\"\\n\");\n}\n\nexport function generateHelpText<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): string {\n return generateTerminalMessage(_generateHelpTextHelper(cli, { level: 1 }));\n}\n","import { stdin, stdout } from \"node:process\";\nimport { createInterface } from \"node:readline/promises\";\nimport { generateTerminalMessage } from \"@/generateTerminalMessage\";\n\n/**\n * Prompt the user for terminal input, optionally enforcing a non-empty value.\n */\nexport async function requestTerminalInput(options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n}): Promise<string | undefined> {\n const {\n message,\n params,\n responseOptions: { required, type, defaultValue },\n } = options;\n const notice =\n defaultValue !== undefined ? \" |gray|(press Enter to use default)|reset|\"\n : required ? \"\"\n : \" |gray|(press Enter to leave empty)|reset|\";\n const defaultNotice =\n defaultValue !== undefined ? ` [default: ${defaultValue}]` : \"\";\n const booleanNotice = type === \"boolean\" ? \" |reset|(y/n)\" : \"\";\n const promptMessage = `${message}${defaultNotice}${booleanNotice}${notice} `;\n const prompt = generateTerminalMessage(promptMessage, params);\n\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n while (true) {\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed.length === 0) {\n if (defaultValue !== undefined) {\n // use the default value, parsed to a string\n return (\n typeof defaultValue === \"string\" ? defaultValue\n : typeof defaultValue === \"number\" ? String(defaultValue)\n : defaultValue ? \"true\"\n : \"false\"\n );\n }\n\n if (required) {\n stdout.write(\n generateTerminalMessage(\n \"|red|This value is required.|reset| Please enter a value.\\n\",\n ),\n );\n continue;\n }\n return undefined;\n }\n if (type === \"boolean\") {\n const normalized = trimmed.toLowerCase();\n if (normalized === \"y\" || normalized === \"yes\") {\n return \"true\";\n }\n if (normalized === \"n\" || normalized === \"no\") {\n return \"false\";\n }\n stdout.write(\n generateTerminalMessage(\n \"|red|That was not a valid response.|reset| Please enter y or n.\\n\",\n ),\n );\n continue;\n }\n return answer;\n }\n } finally {\n rl.close();\n }\n}\n","import { camelCase } from \"change-case\";\nimport { match } from \"ts-pattern\";\nimport { generateHelpText } from \"@/AcclimateCLI/generateHelpText/generateHelpText\";\nimport { CLIError } from \"@/CLIError\";\nimport { requestTerminalInput } from \"@/requestTerminalInput\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionAlias,\n CLIOptionParam,\n CLIParam,\n CLIParamDataType,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n ValueOfParam,\n} from \"@/AcclimateCLI/AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nfunction _isValidFullOptionName(name: string): name is CLIFullOptionName {\n return name.startsWith(\"--\");\n}\n\nfunction _isValidOptionAlias(name: string): name is CLIOptionAlias {\n return name.startsWith(\"-\");\n}\n\nfunction isEmptyObject(obj: object): obj is EmptyObject {\n return Object.keys(obj).length === 0;\n}\n\nfunction _validateParsedValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: { parsedValue: PValue; paramConfig: P; cliName: string }): PValue {\n const { parsedValue, paramConfig, cliName } = options;\n if (paramConfig.validator) {\n const validator = paramConfig.validator as (\n value: PValue,\n ) => boolean | string;\n const validationResult = validator(parsedValue);\n if (validationResult === true) {\n return parsedValue;\n }\n throw CLIError.invalidCLIParamValue({\n cliName,\n paramName: paramConfig.name,\n paramValue: parsedValue,\n message:\n typeof validationResult === \"string\" ? validationResult : undefined,\n });\n }\n return parsedValue;\n}\n\nfunction _parseAndValidateValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: {\n cliName: string;\n inputValue: string | undefined;\n defaultValue: PValue | undefined;\n paramConfig: P;\n}): PValue | undefined {\n const { cliName, inputValue, defaultValue, paramConfig } = options;\n if (inputValue === undefined) {\n if (defaultValue === undefined) {\n return undefined;\n }\n return _validateParsedValue({\n cliName,\n parsedValue: defaultValue,\n paramConfig,\n });\n }\n\n const parsedValue =\n paramConfig.parser ?\n (paramConfig.parser(inputValue) as PValue)\n // if no parser was set, we use the default parser\n : (match(paramConfig.type)\n .with(\"boolean\", () => {\n return inputValue === \"false\" ? false : true;\n })\n .with(\"number\", () => {\n return Number.parseInt(inputValue, 10);\n })\n .with(\"string\", () => {\n return inputValue;\n })\n .exhaustive(() => {\n return inputValue;\n }) as PValue);\n return _validateParsedValue({\n cliName,\n parsedValue,\n paramConfig,\n });\n}\n\nfunction _replaceAliases<\n TGlobalOptionArgs extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TOptionArgs extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TPositionalArgs extends\n | Record<CLIPositionalParamName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>({\n aliasedOptionArgs,\n cli,\n}: {\n aliasedOptionArgs: Record<CLIOptionAlias, string>;\n cli: IAcclimateCLI<\n TGlobalOptionArgs,\n TOptionArgs,\n TPositionalArgs,\n TCommands\n >;\n}): Record<CLIOptionAlias, string> {\n const aliasMap = cli.state.aliases;\n return Object.entries(aliasedOptionArgs).reduce(\n (acc, [aliasKey, value]) => {\n const alias = aliasKey as CLIOptionAlias;\n const optionName = aliasMap[alias] ?? alias;\n acc[optionName] = value;\n return acc;\n },\n {} as Record<CLIOptionAlias, string>,\n );\n}\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n};\n\nasync function askForValue(options: {\n argConfig: CLIParamWithRequired;\n}): Promise<string | undefined> {\n const { argConfig } = options;\n const askIfEmpty = argConfig.askIfEmpty;\n const description =\n argConfig.description ? ` (${argConfig.description})` : \"\";\n const baseMessage =\n typeof askIfEmpty === \"object\" ?\n askIfEmpty.message\n : `Please enter a value for ${argConfig.name}${description}`;\n const coloredMessage = `|bright_cyan|${baseMessage}|reset|`;\n return requestTerminalInput({\n message: coloredMessage,\n params: {},\n responseOptions: {\n required: argConfig.required,\n type: argConfig.type,\n defaultValue: argConfig.defaultValue,\n },\n });\n}\n\nasync function _runCLIHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(options: {\n rawPositionalArgs: string[];\n rawOptionArgs: Record<CLIOptionAlias, string>;\n rawGlobalOptionArgs: Record<CLIFullOptionName, string>;\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >;\n}): Promise<void> {\n const { rawGlobalOptionArgs, rawOptionArgs, rawPositionalArgs, cli } = {\n ...options,\n rawGlobalOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawGlobalOptionArgs,\n cli: options.cli,\n }),\n rawOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawOptionArgs,\n\n // TODO(jpsyx): fix that this does not have the CLI may not have all\n cli: options.cli,\n }),\n };\n\n // is the first argument a command?\n const firstArg = rawPositionalArgs[0];\n if (\n firstArg &&\n !isEmptyObject(cli.state.commands) &&\n cli.state.commands[firstArg]\n ) {\n // add the parent's global options to the sub-command\n const commandCLI = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ).reduce(\n (newCmd, argConfig) => {\n return newCmd.addGlobalOption(argConfig);\n },\n cli.getCommandCLI(firstArg as Extract<keyof TCommands, string>) as AnyCLI,\n );\n\n // run the sub-command\n return _runCLIHelper({\n rawPositionalArgs: rawPositionalArgs.slice(1),\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli: commandCLI,\n });\n }\n\n const cliName = cli.getName();\n\n // build the positional arguments dictionary\n // first check that we haven't supplied too many positional arguments\n if (rawPositionalArgs.length > cli.state.positionalArgs.length) {\n throw CLIError.tooManyPositionalArgs({\n cliName,\n count: rawPositionalArgs.length,\n });\n }\n\n // parse positional arguments\n const parsedPositionalArgs: Record<string, CLIParamDataType> = {};\n for (const [idx, argConfig] of cli.state.positionalArgs.entries()) {\n let rawVal = rawPositionalArgs[idx];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredPositionalArg({\n cliName,\n positionalArgName: argConfig.name,\n });\n }\n\n parsedPositionalArgs[argConfig.name] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the options\n const parsedOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n\n parsedOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the global options\n const parsedGlobalOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawGlobalOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n parsedGlobalOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // run the action\n const action = cli.state.action;\n if (action) {\n action({\n ...parsedPositionalArgs,\n ...parsedOptionArgs,\n ...parsedGlobalOptionArgs,\n } as FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >);\n return;\n }\n\n console.log(generateHelpText(cli));\n}\n\n/**\n * Run a CLI instance given an array of inputs.\n *\n * @param options - The options for running the CLI.\n */\nexport async function runCLI(options: {\n input: string[];\n cli: AnyCLI;\n}): Promise<void> {\n const { input, cli } = options;\n const firstOptionIdx = input.findIndex((token) => {\n return token.startsWith(\"-\");\n });\n\n const [rawPositionalArgs, rest] =\n firstOptionIdx === -1 ?\n [input, []]\n : [input.slice(0, firstOptionIdx), input.slice(firstOptionIdx)];\n\n const rawOptionArgs: Record<CLIOptionAlias, string> = {};\n const rawGlobalOptionArgs: Record<CLIFullOptionName, string> = {};\n let currentAlias: CLIOptionAlias | undefined;\n let currentVals: string[] = [];\n\n const { aliases, globalOptionArgs } = cli.state as CLIState<\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIPositionalParamName, CLIOptionParam>,\n Record<CLICommandName, AnyCLI>\n >;\n\n for (const argVal of rest.concat(\"-\")) {\n if (_isValidOptionAlias(argVal)) {\n if (currentAlias) {\n const rawValue = currentVals.join(\" \");\n const optionName = aliases[currentAlias] ?? currentAlias;\n if (\n _isValidFullOptionName(optionName) &&\n !isEmptyObject(globalOptionArgs) &&\n globalOptionArgs[optionName]\n ) {\n rawGlobalOptionArgs[optionName] = rawValue;\n } else {\n rawOptionArgs[optionName] = rawValue;\n }\n }\n currentAlias = argVal;\n currentVals = [];\n } else {\n currentVals.push(argVal);\n }\n }\n\n await _runCLIHelper({\n rawPositionalArgs,\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli,\n });\n}\n","import { createCLI } from \"./AcclimateCLI\";\nimport { runCLI } from \"./AcclimateCLI/runCLI/runCLI\";\nimport { generateTerminalMessage } from \"./generateTerminalMessage\";\nimport { requestTerminalInput } from \"./requestTerminalInput\";\nimport type { AnyCLI, IAcclimateCLI } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype Acclimate = {\n /**\n * Create a new Acclimate CLI instance.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\n createCLI: (name: string) => IAcclimateCLI;\n\n /**\n * Run a CLI instance.\n *\n * It can only be run once. Calling any other methods after `.run()` will\n * throw an error.\n *\n * @param cli - The CLI instance to run.\n */\n run: (cli: AnyCLI) => void;\n\n /**\n * Outputs a message with `console.log`.\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\n log: (\n message: string,\n params?: Record<string, string | boolean | number | null | undefined>,\n ) => void;\n\n /**\n * Prompt the user for interactive input in the terminal.\n *\n * @param options - Prompt configuration.\n * @returns The user's response, or undefined when left empty and optional.\n */\n requestInput: (options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n }) => Promise<string | undefined>;\n};\n\nexport const Acclimate: Acclimate = {\n createCLI,\n run: (cli: AnyCLI) => {\n void runCLI({ cli, input: process.argv.slice(2) });\n },\n log: (\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n ) => {\n console.log(generateTerminalMessage(message, params));\n },\n requestInput: (options) => {\n return requestTerminalInput(options);\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/CLIError.ts","../src/AcclimateCLI/AcclimateCLI.ts","../src/AcclimateCLI/createCLI/defaultCLIState.ts","../src/AcclimateCLI/createCLI/createCLI.ts","../src/generateTerminalMessage/generateTerminalMessage.ts","../src/AcclimateCLI/generateHelpText/generateHelpText.ts","../src/requestTerminalInput/requestTerminalInput.ts","../src/AcclimateCLI/runCLI/runCLI.ts","../src/Acclimate.ts"],"names":["match","createInterface","stdin","stdout","camelCase"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { CLIParamDataType } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype CLIErrorInfo =\n | {\n code: \"already_run\";\n details: undefined;\n }\n | {\n code: \"unknown_command\";\n details: { commandName: string };\n }\n | {\n code: \"invalid_positional_arg_config\";\n details: { positionalArgName: string };\n }\n | {\n code: \"too_many_positional_args\";\n details: { count: number };\n }\n | {\n code: \"missing_required_positional_arg\";\n details: { positionalArgName: string };\n }\n | {\n code: \"missing_required_option\";\n details: { optionName: string };\n }\n | {\n code: \"unknown_option\";\n details: {\n optionName: string;\n };\n }\n | {\n code: \"invalid_cli_param_value\";\n details: {\n paramName: string;\n paramValue: CLIParamDataType;\n };\n }\n | { code: \"unknown_error\"; details: undefined };\n\ntype CLIErrorOptions = { cliName: string; message: string } & CLIErrorInfo;\n\nexport class CLIError extends Error {\n static invalidCLIParamValue(options: {\n cliName: string;\n paramName: string;\n paramValue: CLIParamDataType;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Invalid value for CLI param \"${options.paramName}\"`,\n code: \"invalid_cli_param_value\",\n details: { paramName: options.paramName, paramValue: options.paramValue },\n });\n }\n static missingRequiredOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Required option \"${options.optionName}\" is missing`,\n code: \"missing_required_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static missingRequiredPositionalArg(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Required positional argument \"${options.positionalArgName}\" is missing`,\n code: \"missing_required_positional_arg\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Option \"${options.optionName}\" not found`,\n code: \"unknown_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static tooManyPositionalArgs(options: {\n cliName: string;\n count: number;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"Too many positional arguments provided.\",\n code: \"too_many_positional_args\",\n details: { count: options.count },\n });\n }\n\n static invalidPositionalArgConfig(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Positional argument configuration for \"${options.positionalArgName}\" is invalid`,\n code: \"invalid_positional_arg_config\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownCommand(options: {\n cliName: string;\n commandName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Command \"${options.commandName}\" not found`,\n code: \"unknown_command\",\n details: { commandName: options.commandName },\n });\n }\n\n static alreadyRun(options: {\n cliName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"CLI has already been run\",\n code: \"already_run\",\n details: undefined,\n });\n }\n\n constructor(options: CLIErrorOptions) {\n super(`❌ Error running ${options.cliName}: ${options.message}`);\n }\n}\n","import { CLIError } from \"@/CLIError\";\nimport type {\n AddEntry,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n} from \"./AcclimateCLI.types\";\nimport type { EmptyObject, Simplify } from \"type-fest\";\n\nexport function AcclimateCLI<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, IAcclimateCLI> | EmptyObject,\n>(\n state: CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n> {\n const cliName = state.name;\n return {\n state,\n\n getName: () => {\n return cliName;\n },\n\n action: (\n action: (\n args: Simplify<\n FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >\n >,\n ) => void,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n action,\n });\n },\n\n description: (\n description: string,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n description,\n });\n },\n\n addPositionalArg: <\n PName extends CLIPositionalParamName,\n P extends CLIPositionalParam<PName>,\n >(\n param: P,\n ) => {\n if (\n param.required &&\n state.positionalArgs.some((p) => {\n return !p.required;\n })\n ) {\n throw CLIError.invalidPositionalArgConfig({\n cliName,\n positionalArgName: param.name,\n message:\n \"Required positional arguments must be before optional positional arguments\",\n });\n }\n\n return AcclimateCLI({\n ...state,\n positionalArgs: [\n ...state.positionalArgs,\n { ...param, required: param.required ?? true },\n ],\n } as unknown as CLIState<\n AddEntry<TPositionalParams, P[\"name\"], P>,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addGlobalOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n globalOptionArgs: {\n ...state.globalOptionArgs,\n [param.name]: param,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >);\n },\n\n addOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n optionArgs: { ...state.optionArgs, [param.name]: param },\n } as unknown as CLIState<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addCommand: <C extends CLICommandName, CommandCLI extends IAcclimateCLI>(\n commandName: C,\n cli: CommandCLI,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n > => {\n return AcclimateCLI({\n ...state,\n commands: {\n ...state.commands,\n [commandName]: cli,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n >);\n },\n\n getCommandCLI: <C extends Extract<keyof TCommands, CLICommandName>>(\n commandName: C,\n ): C extends keyof TCommands ? TCommands[C] : never => {\n const cmd = state.commands[commandName];\n if (!cmd) {\n throw CLIError.unknownCommand({\n cliName,\n commandName,\n message: `Command \"${commandName}\" not found`,\n });\n }\n return cmd as C extends keyof TCommands ? TCommands[C] : never;\n },\n };\n}\n","import type { CLIState } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nexport const defaultCLIState: Omit<\n CLIState<EmptyObject, EmptyObject, EmptyObject, EmptyObject>,\n \"name\"\n> = {\n aliases: {},\n description: undefined,\n commands: {},\n positionalArgs: [],\n optionArgs: {},\n globalOptionArgs: {},\n action: undefined,\n};\n","import { AcclimateCLI } from \"../AcclimateCLI\";\nimport { defaultCLIState } from \"./defaultCLIState\";\nimport type { IAcclimateCLI } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\n/**\n * Builder function to create a new CLI instance with a given name.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\nexport function createCLI(\n name: string,\n): IAcclimateCLI<EmptyObject, EmptyObject, EmptyObject, EmptyObject> {\n return AcclimateCLI({ ...defaultCLIState, name });\n}\n","const COLOR_CODES: Record<string, string> = {\n reset: \"\\x1b[0m\",\n dim: \"\\x1b[2m\",\n black: \"\\x1b[30m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n bright_black: \"\\x1b[90m\",\n gray: \"\\x1b[90m\",\n grey: \"\\x1b[90m\",\n bright_red: \"\\x1b[91m\",\n bright_green: \"\\x1b[92m\",\n bright_yellow: \"\\x1b[93m\",\n bright_blue: \"\\x1b[94m\",\n bright_magenta: \"\\x1b[95m\",\n bright_cyan: \"\\x1b[96m\",\n bright_white: \"\\x1b[97m\",\n};\n\nconst PARAM_TOKEN_REGEX = /\\$([a-zA-Z0-9_]+)\\$/g;\nconst COLOR_TOKEN_REGEX = /\\|([a-zA-Z_]+)\\|/g;\n\n/**\n * Replaces `$token$` placeholders with values from `params`.\n * If a token does not exist in `params`, the placeholder is left unchanged.\n */\nfunction interpolateParams(\n message: string,\n params: Record<string, string | boolean | number | null | undefined>,\n): string {\n return message.replace(PARAM_TOKEN_REGEX, (match: string, key: string) => {\n void match;\n const value = params[key];\n if (value === undefined) {\n return \"\";\n }\n return String(value);\n });\n}\n\nfunction applyColors(message: string) {\n return message.replace(COLOR_TOKEN_REGEX, (match, colorName: string) => {\n const code = COLOR_CODES[colorName.toLowerCase()];\n return code ?? match;\n });\n}\n\n/**\n * Outputs a message intended to be passed directly to `console.log`\n *\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\nexport function generateTerminalMessage(\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n): string {\n const hasColorToken = Boolean(message.match(COLOR_TOKEN_REGEX));\n const endsWithReset = message.trimEnd().endsWith(\"|reset|\");\n const withReset =\n hasColorToken && !endsWithReset ? `${message}|reset|` : message;\n const interpolated = interpolateParams(withReset, params);\n return applyColors(interpolated);\n}\n","import { generateTerminalMessage } from \"@/generateTerminalMessage\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n IAcclimateCLI,\n} from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nconst _SECTION_TITLES = [\n \"Positional Arguments\",\n \"Options\",\n \"Global Options\",\n \"Commands\",\n] as const;\n\ntype SectionTitle = (typeof _SECTION_TITLES)[number];\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n aliases?: readonly string[];\n};\n\nfunction formatSectionTitle(title: SectionTitle): string {\n return `|bright_yellow|${title}|reset|`;\n}\n\nfunction formatDefaultValue(\n value: CLIParamWithRequired[\"defaultValue\"],\n): string {\n return `|gray|[default: ${JSON.stringify(value)}]|reset|`;\n}\n\nfunction formatParamLine(param: CLIParamWithRequired): string {\n const description = param.description ?? \"No description\";\n const requiredLabel =\n param.required ? \"|red|required|reset|\" : \"|gray|optional|reset|\";\n const defaultLabel =\n param.defaultValue !== undefined ?\n formatDefaultValue(param.defaultValue)\n : undefined;\n const aliasList =\n param.aliases && param.aliases.length > 0 ? param.aliases.join(\", \") : \"\";\n const displayName = aliasList ? `${param.name}, ${aliasList}` : param.name;\n\n const segments = [\n ` |bright_white|${displayName}|reset|`,\n `(${param.type})|reset| ${requiredLabel}`,\n `- |gray|${description}|reset|`,\n defaultLabel,\n ].filter(Boolean);\n\n return segments.join(\" \");\n}\n\nfunction formatSection(\n title: SectionTitle,\n params: readonly CLIParamWithRequired[],\n): string[] {\n if (params.length === 0) {\n return [];\n }\n\n return [formatSectionTitle(title), ...params.map(formatParamLine)];\n}\n\nfunction formatCommandBullets(\n commands: { name: string; description?: string }[],\n): string[] {\n return commands.map(({ name, description }) => {\n const descLabel =\n description !== undefined ?\n `|gray|${description}|reset|`\n : `|dim|No description|reset|`;\n return ` • |bright_white|${name}|reset| - ${descLabel}`;\n });\n}\n\nfunction _generateHelpTextHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n options: { level: 1 | 2 },\n): string {\n const name = cli.getName();\n const description = cli.state.description;\n const level = Number(options.level);\n\n const positionalParams = cli.state\n .positionalArgs as readonly CLIParamWithRequired[];\n const optionParams = Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const globalOptionParams = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const sortedCommands = Object.entries(cli.state.commands).sort(([a], [b]) => {\n return a.localeCompare(b);\n });\n\n const headerLines = [`|bright_cyan|${name}|reset|`];\n if (description !== undefined) {\n headerLines.push(` |gray|${description}|reset|`);\n }\n\n let commandSection: string[];\n if (sortedCommands.length === 0) {\n commandSection = [];\n } else if (level === 2) {\n const commandsWithDescriptions = sortedCommands.map(\n ([commandName, commandCLI]) => ({\n name: commandName,\n description: commandCLI.state.description,\n }),\n );\n commandSection = [\n formatSectionTitle(\"Commands\"),\n ...formatCommandBullets(commandsWithDescriptions),\n ];\n } else {\n // At level 1, just show the header - sub-commands are rendered recursively below\n commandSection = [formatSectionTitle(\"Commands\")];\n }\n\n const sections = [\n formatSection(\"Positional Arguments\", positionalParams),\n formatSection(\"Options\", optionParams),\n formatSection(\"Global Options\", globalOptionParams),\n commandSection,\n ].filter((section) => section.length > 0);\n\n const lines = [...headerLines];\n sections.forEach((section, idx) => {\n lines.push(\"\", ...section);\n });\n\n if (level === 1) {\n const subCommandHelpText = sortedCommands.map(([, commandCLI]) => {\n return _generateHelpTextHelper(commandCLI, { level: 2 });\n });\n if (subCommandHelpText.length > 0) {\n subCommandHelpText.forEach((text) => {\n lines.push(\"\", ...text.split(\"\\n\"));\n });\n }\n }\n\n const indent = \" \".repeat(Math.max(0, level - 1));\n return lines\n .map((line) => {\n return line === \"\" ? \"\" : `${indent}${line}`;\n })\n .join(\"\\n\");\n}\n\nexport function generateHelpText<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): string {\n return generateTerminalMessage(_generateHelpTextHelper(cli, { level: 1 }));\n}\n","import { stdin, stdout } from \"node:process\";\nimport { createInterface } from \"node:readline/promises\";\nimport { generateTerminalMessage } from \"@/generateTerminalMessage\";\n\n/**\n * Prompt the user for terminal input, optionally enforcing a non-empty value.\n */\nexport async function requestTerminalInput(options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n}): Promise<string | undefined> {\n const {\n message,\n params,\n responseOptions: { required, type, defaultValue },\n } = options;\n const notice =\n defaultValue !== undefined ? \" |gray|(press Enter to use default)|reset|\"\n : required ? \"\"\n : \" |gray|(press Enter to leave empty)|reset|\";\n const defaultNotice =\n defaultValue !== undefined ? ` [default: ${defaultValue}]` : \"\";\n const booleanNotice = type === \"boolean\" ? \" |reset|(y/n)\" : \"\";\n const promptMessage = `${message}${defaultNotice}${booleanNotice}${notice} `;\n const prompt = generateTerminalMessage(promptMessage, params);\n\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n while (true) {\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed.length === 0) {\n if (defaultValue !== undefined) {\n // use the default value, parsed to a string\n return (\n typeof defaultValue === \"string\" ? defaultValue\n : typeof defaultValue === \"number\" ? String(defaultValue)\n : defaultValue ? \"true\"\n : \"false\"\n );\n }\n\n if (required) {\n stdout.write(\n generateTerminalMessage(\n \"|red|This value is required.|reset| Please enter a value.\\n\",\n ),\n );\n continue;\n }\n return undefined;\n }\n if (type === \"boolean\") {\n const normalized = trimmed.toLowerCase();\n if (normalized === \"y\" || normalized === \"yes\") {\n return \"true\";\n }\n if (normalized === \"n\" || normalized === \"no\") {\n return \"false\";\n }\n stdout.write(\n generateTerminalMessage(\n \"|red|That was not a valid response.|reset| Please enter y or n.\\n\",\n ),\n );\n continue;\n }\n return answer;\n }\n } finally {\n rl.close();\n }\n}\n","import { camelCase } from \"change-case\";\nimport { match } from \"ts-pattern\";\nimport { generateHelpText } from \"@/AcclimateCLI/generateHelpText/generateHelpText\";\nimport { CLIError } from \"@/CLIError\";\nimport { requestTerminalInput } from \"@/requestTerminalInput\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionAlias,\n CLIOptionParam,\n CLIParam,\n CLIParamDataType,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n ValueOfParam,\n} from \"@/AcclimateCLI/AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nfunction _isValidFullOptionName(name: string): name is CLIFullOptionName {\n return name.startsWith(\"--\");\n}\n\nfunction _isValidOptionAlias(name: string): name is CLIOptionAlias {\n return name.startsWith(\"-\");\n}\n\nfunction isEmptyObject(obj: object): obj is EmptyObject {\n return Object.keys(obj).length === 0;\n}\n\nfunction _validateParsedValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: { parsedValue: PValue; paramConfig: P; cliName: string }): PValue {\n const { parsedValue, paramConfig, cliName } = options;\n if (paramConfig.validator) {\n const validator = paramConfig.validator as (\n value: PValue,\n ) => boolean | string;\n const validationResult = validator(parsedValue);\n if (validationResult === true) {\n return parsedValue;\n }\n throw CLIError.invalidCLIParamValue({\n cliName,\n paramName: paramConfig.name,\n paramValue: parsedValue,\n message:\n typeof validationResult === \"string\" ? validationResult : undefined,\n });\n }\n return parsedValue;\n}\n\nfunction _parseAndValidateValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: {\n cliName: string;\n inputValue: string | undefined;\n defaultValue: PValue | undefined;\n paramConfig: P;\n}): PValue | undefined {\n const { cliName, inputValue, defaultValue, paramConfig } = options;\n if (inputValue === undefined) {\n if (defaultValue === undefined) {\n return undefined;\n }\n return _validateParsedValue({\n cliName,\n parsedValue: defaultValue,\n paramConfig,\n });\n }\n\n const parsedValue =\n paramConfig.parser ?\n (paramConfig.parser(inputValue) as PValue)\n // if no parser was set, we use the default parser\n : (match(paramConfig.type)\n .with(\"boolean\", () => {\n return inputValue === \"false\" ? false : true;\n })\n .with(\"number\", () => {\n return Number.parseInt(inputValue, 10);\n })\n .with(\"string\", () => {\n return inputValue;\n })\n .exhaustive(() => {\n return inputValue;\n }) as PValue);\n return _validateParsedValue({\n cliName,\n parsedValue,\n paramConfig,\n });\n}\n\nfunction _replaceAliases<\n TGlobalOptionArgs extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TOptionArgs extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TPositionalArgs extends\n | Record<CLIPositionalParamName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>({\n aliasedOptionArgs,\n cli,\n}: {\n aliasedOptionArgs: Record<CLIOptionAlias, string>;\n cli: IAcclimateCLI<\n TGlobalOptionArgs,\n TOptionArgs,\n TPositionalArgs,\n TCommands\n >;\n}): Record<CLIOptionAlias, string> {\n const aliasMap = cli.state.aliases;\n return Object.entries(aliasedOptionArgs).reduce(\n (acc, [aliasKey, value]) => {\n const alias = aliasKey as CLIOptionAlias;\n const optionName = aliasMap[alias] ?? alias;\n acc[optionName] = value;\n return acc;\n },\n {} as Record<CLIOptionAlias, string>,\n );\n}\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n};\n\nasync function askForValue(options: {\n argConfig: CLIParamWithRequired;\n}): Promise<string | undefined> {\n const { argConfig } = options;\n const askIfEmpty = argConfig.askIfEmpty;\n const description =\n argConfig.description ? ` (${argConfig.description})` : \"\";\n const baseMessage =\n typeof askIfEmpty === \"object\" ?\n askIfEmpty.message\n : `Please enter a value for ${argConfig.name}${description}`;\n const coloredMessage = `|bright_cyan|${baseMessage}|reset|`;\n return requestTerminalInput({\n message: coloredMessage,\n params: {},\n responseOptions: {\n required: argConfig.required,\n type: argConfig.type,\n defaultValue: argConfig.defaultValue,\n },\n });\n}\n\nasync function _runCLIHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(options: {\n rawPositionalArgs: string[];\n rawOptionArgs: Record<CLIOptionAlias, string>;\n rawGlobalOptionArgs: Record<CLIFullOptionName, string>;\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >;\n}): Promise<void> {\n const { rawGlobalOptionArgs, rawOptionArgs, rawPositionalArgs, cli } = {\n ...options,\n rawGlobalOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawGlobalOptionArgs,\n cli: options.cli,\n }),\n rawOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawOptionArgs,\n\n // TODO(jpsyx): fix that this does not have the CLI may not have all\n cli: options.cli,\n }),\n };\n\n // is the first argument a command?\n const firstArg = rawPositionalArgs[0];\n if (\n firstArg &&\n !isEmptyObject(cli.state.commands) &&\n cli.state.commands[firstArg]\n ) {\n // add the parent's global options to the sub-command\n const commandCLI = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ).reduce(\n (newCmd, argConfig) => {\n return newCmd.addGlobalOption(argConfig);\n },\n cli.getCommandCLI(firstArg as Extract<keyof TCommands, string>) as AnyCLI,\n );\n\n // run the sub-command\n return _runCLIHelper({\n rawPositionalArgs: rawPositionalArgs.slice(1),\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli: commandCLI,\n });\n }\n\n const cliName = cli.getName();\n\n // build the positional arguments dictionary\n // first check that we haven't supplied too many positional arguments\n if (rawPositionalArgs.length > cli.state.positionalArgs.length) {\n throw CLIError.tooManyPositionalArgs({\n cliName,\n count: rawPositionalArgs.length,\n });\n }\n\n // parse positional arguments\n const parsedPositionalArgs: Record<string, CLIParamDataType> = {};\n for (const [idx, argConfig] of cli.state.positionalArgs.entries()) {\n let rawVal = rawPositionalArgs[idx];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredPositionalArg({\n cliName,\n positionalArgName: argConfig.name,\n });\n }\n\n parsedPositionalArgs[argConfig.name] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the options\n const parsedOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n\n parsedOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the global options\n const parsedGlobalOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawGlobalOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n parsedGlobalOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // run the action\n const action = cli.state.action;\n if (action) {\n action({\n ...parsedPositionalArgs,\n ...parsedOptionArgs,\n ...parsedGlobalOptionArgs,\n } as FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >);\n return;\n }\n\n console.log(generateHelpText(cli));\n}\n\n/**\n * Run a CLI instance given an array of inputs.\n *\n * @param options - The options for running the CLI.\n */\nexport async function runCLI(options: {\n input: string[];\n cli: AnyCLI;\n}): Promise<void> {\n const { input, cli } = options;\n const firstOptionIdx = input.findIndex((token) => {\n return token.startsWith(\"-\");\n });\n\n const [rawPositionalArgs, rest] =\n firstOptionIdx === -1 ?\n [input, []]\n : [input.slice(0, firstOptionIdx), input.slice(firstOptionIdx)];\n\n const rawOptionArgs: Record<CLIOptionAlias, string> = {};\n const rawGlobalOptionArgs: Record<CLIFullOptionName, string> = {};\n let currentAlias: CLIOptionAlias | undefined;\n let currentVals: string[] = [];\n\n const { aliases, globalOptionArgs } = cli.state as CLIState<\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIPositionalParamName, CLIOptionParam>,\n Record<CLICommandName, AnyCLI>\n >;\n\n for (const argVal of rest.concat(\"-\")) {\n if (_isValidOptionAlias(argVal)) {\n if (currentAlias) {\n const rawValue = currentVals.join(\" \");\n const optionName = aliases[currentAlias] ?? currentAlias;\n if (\n _isValidFullOptionName(optionName) &&\n !isEmptyObject(globalOptionArgs) &&\n globalOptionArgs[optionName]\n ) {\n rawGlobalOptionArgs[optionName] = rawValue;\n } else {\n rawOptionArgs[optionName] = rawValue;\n }\n }\n currentAlias = argVal;\n currentVals = [];\n } else {\n currentVals.push(argVal);\n }\n }\n\n await _runCLIHelper({\n rawPositionalArgs,\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli,\n });\n}\n","import { createCLI } from \"./AcclimateCLI\";\nimport { runCLI } from \"./AcclimateCLI/runCLI/runCLI\";\nimport { generateTerminalMessage } from \"./generateTerminalMessage\";\nimport { requestTerminalInput } from \"./requestTerminalInput\";\nimport type { AnyCLI, IAcclimateCLI } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype Acclimate = {\n /**\n * Create a new Acclimate CLI instance.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\n createCLI: (name: string) => IAcclimateCLI;\n\n /**\n * Run a CLI instance.\n *\n * It can only be run once. Calling any other methods after `.run()` will\n * throw an error.\n *\n * @param cli - The CLI instance to run.\n */\n run: (cli: AnyCLI) => void;\n\n /**\n * Outputs a message with `console.log`.\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\n log: (\n message: string,\n params?: Record<string, string | boolean | number | null | undefined>,\n ) => void;\n\n /**\n * Prompt the user for interactive input in the terminal.\n *\n * @param options - Prompt configuration.\n * @returns The user's response, or undefined when left empty and optional.\n */\n requestInput: (options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n }) => Promise<string | undefined>;\n};\n\nexport const Acclimate: Acclimate = {\n createCLI,\n run: (cli: AnyCLI) => {\n void runCLI({ cli, input: process.argv.slice(2) });\n },\n log: (\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n ) => {\n console.log(generateTerminalMessage(message, params));\n },\n requestInput: (options) => {\n return requestTerminalInput(options);\n },\n};\n"]}
package/dist/index.js CHANGED
@@ -185,6 +185,7 @@ function createCLI(name) {
185
185
  // src/generateTerminalMessage/generateTerminalMessage.ts
186
186
  var COLOR_CODES = {
187
187
  reset: "\x1B[0m",
188
+ dim: "\x1B[2m",
188
189
  black: "\x1B[30m",
189
190
  red: "\x1B[31m",
190
191
  green: "\x1B[32m",
@@ -233,9 +234,6 @@ function generateTerminalMessage(message, params = {}) {
233
234
  function formatSectionTitle(title) {
234
235
  return `|bright_yellow|${title}|reset|`;
235
236
  }
236
- function formatNoneLine() {
237
- return " |gray|None|reset|";
238
- }
239
237
  function formatDefaultValue(value) {
240
238
  return `|gray|[default: ${JSON.stringify(value)}]|reset|`;
241
239
  }
@@ -255,20 +253,15 @@ function formatParamLine(param) {
255
253
  }
256
254
  function formatSection(title, params) {
257
255
  if (params.length === 0) {
258
- return [formatSectionTitle(title), formatNoneLine()];
256
+ return [];
259
257
  }
260
258
  return [formatSectionTitle(title), ...params.map(formatParamLine)];
261
259
  }
262
- function formatCommandLine(options) {
263
- const { name, description } = options;
264
- const label = description ?? "No description";
265
- return ` |bright_white|${name}|reset| - |gray|${label}|reset|`;
266
- }
267
- function formatAvailableCommandsLine(commands) {
268
- const label = commands.length === 0 ? "None" : commands.map((cmd) => {
269
- return cmd;
270
- }).join(", ");
271
- return `|bright_yellow|Available Commands:|reset| |gray|${label}|reset|`;
260
+ function formatCommandBullets(commands) {
261
+ return commands.map(({ name, description }) => {
262
+ const descLabel = description !== void 0 ? `|gray|${description}|reset|` : `|dim|No description|reset|`;
263
+ return ` \u2022 |bright_white|${name}|reset| - ${descLabel}`;
264
+ });
272
265
  }
273
266
  function _generateHelpTextHelper(cli, options) {
274
267
  const name = cli.getName();
@@ -284,44 +277,36 @@ function _generateHelpTextHelper(cli, options) {
284
277
  const sortedCommands = Object.entries(cli.state.commands).sort(([a], [b]) => {
285
278
  return a.localeCompare(b);
286
279
  });
287
- const commandNames = sortedCommands.map(([commandName]) => {
288
- return commandName;
289
- });
290
280
  const headerLines = [`|bright_cyan|${name}|reset|`];
291
281
  if (description !== void 0) {
292
282
  headerLines.push(` |gray|${description}|reset|`);
293
283
  }
294
284
  let commandSection;
295
- if (level === 2) {
285
+ if (sortedCommands.length === 0) {
286
+ commandSection = [];
287
+ } else if (level === 2) {
288
+ const commandsWithDescriptions = sortedCommands.map(
289
+ ([commandName, commandCLI]) => ({
290
+ name: commandName,
291
+ description: commandCLI.state.description
292
+ })
293
+ );
296
294
  commandSection = [
297
295
  formatSectionTitle("Commands"),
298
- ` ${formatAvailableCommandsLine(commandNames)}`
296
+ ...formatCommandBullets(commandsWithDescriptions)
299
297
  ];
300
- } else if (sortedCommands.length === 0) {
301
- commandSection = [formatSectionTitle("Commands"), formatNoneLine()];
302
298
  } else {
303
- commandSection = [
304
- formatSectionTitle("Commands"),
305
- ...sortedCommands.map(([commandName, commandCLI]) => {
306
- return formatCommandLine({
307
- name: commandName,
308
- description: commandCLI.state.description
309
- });
310
- })
311
- ];
299
+ commandSection = [formatSectionTitle("Commands")];
312
300
  }
313
301
  const sections = [
314
302
  formatSection("Positional Arguments", positionalParams),
315
303
  formatSection("Options", optionParams),
316
304
  formatSection("Global Options", globalOptionParams),
317
305
  commandSection
318
- ];
319
- const lines = [...headerLines, ""];
306
+ ].filter((section) => section.length > 0);
307
+ const lines = [...headerLines];
320
308
  sections.forEach((section, idx) => {
321
- lines.push(...section);
322
- if (idx < sections.length - 1) {
323
- lines.push("");
324
- }
309
+ lines.push("", ...section);
325
310
  });
326
311
  if (level === 1) {
327
312
  const subCommandHelpText = sortedCommands.map(([, commandCLI]) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/CLIError.ts","../src/AcclimateCLI/AcclimateCLI.ts","../src/AcclimateCLI/createCLI/defaultCLIState.ts","../src/AcclimateCLI/createCLI/createCLI.ts","../src/generateTerminalMessage/generateTerminalMessage.ts","../src/AcclimateCLI/generateHelpText/generateHelpText.ts","../src/requestTerminalInput/requestTerminalInput.ts","../src/AcclimateCLI/runCLI/runCLI.ts","../src/Acclimate.ts"],"names":["match"],"mappings":"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","file":"index.js","sourcesContent":["import type { CLIParamDataType } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype CLIErrorInfo =\n | {\n code: \"already_run\";\n details: undefined;\n }\n | {\n code: \"unknown_command\";\n details: { commandName: string };\n }\n | {\n code: \"invalid_positional_arg_config\";\n details: { positionalArgName: string };\n }\n | {\n code: \"too_many_positional_args\";\n details: { count: number };\n }\n | {\n code: \"missing_required_positional_arg\";\n details: { positionalArgName: string };\n }\n | {\n code: \"missing_required_option\";\n details: { optionName: string };\n }\n | {\n code: \"unknown_option\";\n details: {\n optionName: string;\n };\n }\n | {\n code: \"invalid_cli_param_value\";\n details: {\n paramName: string;\n paramValue: CLIParamDataType;\n };\n }\n | { code: \"unknown_error\"; details: undefined };\n\ntype CLIErrorOptions = { cliName: string; message: string } & CLIErrorInfo;\n\nexport class CLIError extends Error {\n static invalidCLIParamValue(options: {\n cliName: string;\n paramName: string;\n paramValue: CLIParamDataType;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Invalid value for CLI param \"${options.paramName}\"`,\n code: \"invalid_cli_param_value\",\n details: { paramName: options.paramName, paramValue: options.paramValue },\n });\n }\n static missingRequiredOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Required option \"${options.optionName}\" is missing`,\n code: \"missing_required_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static missingRequiredPositionalArg(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Required positional argument \"${options.positionalArgName}\" is missing`,\n code: \"missing_required_positional_arg\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Option \"${options.optionName}\" not found`,\n code: \"unknown_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static tooManyPositionalArgs(options: {\n cliName: string;\n count: number;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"Too many positional arguments provided.\",\n code: \"too_many_positional_args\",\n details: { count: options.count },\n });\n }\n\n static invalidPositionalArgConfig(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Positional argument configuration for \"${options.positionalArgName}\" is invalid`,\n code: \"invalid_positional_arg_config\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownCommand(options: {\n cliName: string;\n commandName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Command \"${options.commandName}\" not found`,\n code: \"unknown_command\",\n details: { commandName: options.commandName },\n });\n }\n\n static alreadyRun(options: {\n cliName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"CLI has already been run\",\n code: \"already_run\",\n details: undefined,\n });\n }\n\n constructor(options: CLIErrorOptions) {\n super(`❌ Error running ${options.cliName}: ${options.message}`);\n }\n}\n","import { CLIError } from \"@/CLIError\";\nimport type {\n AddEntry,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n} from \"./AcclimateCLI.types\";\nimport type { EmptyObject, Simplify } from \"type-fest\";\n\nexport function AcclimateCLI<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, IAcclimateCLI> | EmptyObject,\n>(\n state: CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n> {\n const cliName = state.name;\n return {\n state,\n\n getName: () => {\n return cliName;\n },\n\n action: (\n action: (\n args: Simplify<\n FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >\n >,\n ) => void,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n action,\n });\n },\n\n description: (\n description: string,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n description,\n });\n },\n\n addPositionalArg: <\n PName extends CLIPositionalParamName,\n P extends CLIPositionalParam<PName>,\n >(\n param: P,\n ) => {\n if (\n param.required &&\n state.positionalArgs.some((p) => {\n return !p.required;\n })\n ) {\n throw CLIError.invalidPositionalArgConfig({\n cliName,\n positionalArgName: param.name,\n message:\n \"Required positional arguments must be before optional positional arguments\",\n });\n }\n\n return AcclimateCLI({\n ...state,\n positionalArgs: [\n ...state.positionalArgs,\n { ...param, required: param.required ?? true },\n ],\n } as unknown as CLIState<\n AddEntry<TPositionalParams, P[\"name\"], P>,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addGlobalOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n globalOptionArgs: {\n ...state.globalOptionArgs,\n [param.name]: param,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >);\n },\n\n addOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n optionArgs: { ...state.optionArgs, [param.name]: param },\n } as unknown as CLIState<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addCommand: <C extends CLICommandName, CommandCLI extends IAcclimateCLI>(\n commandName: C,\n cli: CommandCLI,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n > => {\n return AcclimateCLI({\n ...state,\n commands: {\n ...state.commands,\n [commandName]: cli,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n >);\n },\n\n getCommandCLI: <C extends Extract<keyof TCommands, CLICommandName>>(\n commandName: C,\n ): C extends keyof TCommands ? TCommands[C] : never => {\n const cmd = state.commands[commandName];\n if (!cmd) {\n throw CLIError.unknownCommand({\n cliName,\n commandName,\n message: `Command \"${commandName}\" not found`,\n });\n }\n return cmd as C extends keyof TCommands ? TCommands[C] : never;\n },\n };\n}\n","import type { CLIState } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nexport const defaultCLIState: Omit<\n CLIState<EmptyObject, EmptyObject, EmptyObject, EmptyObject>,\n \"name\"\n> = {\n aliases: {},\n description: undefined,\n commands: {},\n positionalArgs: [],\n optionArgs: {},\n globalOptionArgs: {},\n action: undefined,\n};\n","import { AcclimateCLI } from \"../AcclimateCLI\";\nimport { defaultCLIState } from \"./defaultCLIState\";\nimport type { IAcclimateCLI } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\n/**\n * Builder function to create a new CLI instance with a given name.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\nexport function createCLI(\n name: string,\n): IAcclimateCLI<EmptyObject, EmptyObject, EmptyObject, EmptyObject> {\n return AcclimateCLI({ ...defaultCLIState, name });\n}\n","const COLOR_CODES: Record<string, string> = {\n reset: \"\\x1b[0m\",\n black: \"\\x1b[30m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n bright_black: \"\\x1b[90m\",\n gray: \"\\x1b[90m\",\n grey: \"\\x1b[90m\",\n bright_red: \"\\x1b[91m\",\n bright_green: \"\\x1b[92m\",\n bright_yellow: \"\\x1b[93m\",\n bright_blue: \"\\x1b[94m\",\n bright_magenta: \"\\x1b[95m\",\n bright_cyan: \"\\x1b[96m\",\n bright_white: \"\\x1b[97m\",\n};\n\nconst PARAM_TOKEN_REGEX = /\\$([a-zA-Z0-9_]+)\\$/g;\nconst COLOR_TOKEN_REGEX = /\\|([a-zA-Z_]+)\\|/g;\n\n/**\n * Replaces `$token$` placeholders with values from `params`.\n * If a token does not exist in `params`, the placeholder is left unchanged.\n */\nfunction interpolateParams(\n message: string,\n params: Record<string, string | boolean | number | null | undefined>,\n): string {\n return message.replace(PARAM_TOKEN_REGEX, (match: string, key: string) => {\n void match;\n const value = params[key];\n if (value === undefined) {\n return \"\";\n }\n return String(value);\n });\n}\n\nfunction applyColors(message: string) {\n return message.replace(COLOR_TOKEN_REGEX, (match, colorName: string) => {\n const code = COLOR_CODES[colorName.toLowerCase()];\n return code ?? match;\n });\n}\n\n/**\n * Outputs a message intended to be passed directly to `console.log`\n *\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\nexport function generateTerminalMessage(\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n): string {\n const hasColorToken = Boolean(message.match(COLOR_TOKEN_REGEX));\n const endsWithReset = message.trimEnd().endsWith(\"|reset|\");\n const withReset =\n hasColorToken && !endsWithReset ? `${message}|reset|` : message;\n const interpolated = interpolateParams(withReset, params);\n return applyColors(interpolated);\n}\n","import { generateTerminalMessage } from \"@/generateTerminalMessage\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n IAcclimateCLI,\n} from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nconst _SECTION_TITLES = [\n \"Positional Arguments\",\n \"Options\",\n \"Global Options\",\n \"Commands\",\n] as const;\n\ntype SectionTitle = (typeof _SECTION_TITLES)[number];\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n aliases?: readonly string[];\n};\n\nfunction formatSectionTitle(title: SectionTitle): string {\n return `|bright_yellow|${title}|reset|`;\n}\n\nfunction formatNoneLine(): string {\n return \" |gray|None|reset|\";\n}\n\nfunction formatDefaultValue(\n value: CLIParamWithRequired[\"defaultValue\"],\n): string {\n return `|gray|[default: ${JSON.stringify(value)}]|reset|`;\n}\n\nfunction formatParamLine(param: CLIParamWithRequired): string {\n const description = param.description ?? \"No description\";\n const requiredLabel =\n param.required ? \"|red|required|reset|\" : \"|gray|optional|reset|\";\n const defaultLabel =\n param.defaultValue !== undefined ?\n formatDefaultValue(param.defaultValue)\n : undefined;\n const aliasList =\n param.aliases && param.aliases.length > 0 ? param.aliases.join(\", \") : \"\";\n const displayName = aliasList ? `${param.name}, ${aliasList}` : param.name;\n\n const segments = [\n ` |bright_white|${displayName}|reset|`,\n `(${param.type})|reset| ${requiredLabel}`,\n `- |gray|${description}|reset|`,\n defaultLabel,\n ].filter(Boolean);\n\n return segments.join(\" \");\n}\n\nfunction formatSection(\n title: SectionTitle,\n params: readonly CLIParamWithRequired[],\n): string[] {\n if (params.length === 0) {\n return [formatSectionTitle(title), formatNoneLine()];\n }\n\n return [formatSectionTitle(title), ...params.map(formatParamLine)];\n}\n\nfunction formatCommandLine(options: {\n name: string;\n description?: string;\n}): string {\n const { name, description } = options;\n const label = description ?? \"No description\";\n return ` |bright_white|${name}|reset| - |gray|${label}|reset|`;\n}\n\nfunction formatAvailableCommandsLine(commands: string[]): string {\n const label =\n commands.length === 0 ?\n \"None\"\n : commands\n .map((cmd) => {\n return cmd;\n })\n .join(\", \");\n return `|bright_yellow|Available Commands:|reset| |gray|${label}|reset|`;\n}\n\nfunction _generateHelpTextHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n options: { level: 1 | 2 },\n): string {\n const name = cli.getName();\n const description = cli.state.description;\n const level = Number(options.level);\n\n const positionalParams = cli.state\n .positionalArgs as readonly CLIParamWithRequired[];\n const optionParams = Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const globalOptionParams = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const sortedCommands = Object.entries(cli.state.commands).sort(([a], [b]) => {\n return a.localeCompare(b);\n });\n const commandNames = sortedCommands.map(([commandName]) => {\n return commandName;\n });\n\n const headerLines = [`|bright_cyan|${name}|reset|`];\n if (description !== undefined) {\n headerLines.push(` |gray|${description}|reset|`);\n }\n\n let commandSection: string[];\n if (level === 2) {\n commandSection = [\n formatSectionTitle(\"Commands\"),\n ` ${formatAvailableCommandsLine(commandNames)}`,\n ];\n } else if (sortedCommands.length === 0) {\n commandSection = [formatSectionTitle(\"Commands\"), formatNoneLine()];\n } else {\n commandSection = [\n formatSectionTitle(\"Commands\"),\n ...sortedCommands.map(([commandName, commandCLI]) => {\n return formatCommandLine({\n name: commandName,\n description: commandCLI.state.description,\n });\n }),\n ];\n }\n\n const sections = [\n formatSection(\"Positional Arguments\", positionalParams),\n formatSection(\"Options\", optionParams),\n formatSection(\"Global Options\", globalOptionParams),\n commandSection,\n ];\n\n const lines = [...headerLines, \"\"];\n sections.forEach((section, idx) => {\n lines.push(...section);\n if (idx < sections.length - 1) {\n lines.push(\"\");\n }\n });\n\n if (level === 1) {\n const subCommandHelpText = sortedCommands.map(([, commandCLI]) => {\n return _generateHelpTextHelper(commandCLI, { level: 2 });\n });\n if (subCommandHelpText.length > 0) {\n subCommandHelpText.forEach((text) => {\n lines.push(\"\", ...text.split(\"\\n\"));\n });\n }\n }\n\n const indent = \" \".repeat(Math.max(0, level - 1));\n return lines\n .map((line) => {\n return line === \"\" ? \"\" : `${indent}${line}`;\n })\n .join(\"\\n\");\n}\n\nexport function generateHelpText<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): string {\n return generateTerminalMessage(_generateHelpTextHelper(cli, { level: 1 }));\n}\n","import { stdin, stdout } from \"node:process\";\nimport { createInterface } from \"node:readline/promises\";\nimport { generateTerminalMessage } from \"@/generateTerminalMessage\";\n\n/**\n * Prompt the user for terminal input, optionally enforcing a non-empty value.\n */\nexport async function requestTerminalInput(options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n}): Promise<string | undefined> {\n const {\n message,\n params,\n responseOptions: { required, type, defaultValue },\n } = options;\n const notice =\n defaultValue !== undefined ? \" |gray|(press Enter to use default)|reset|\"\n : required ? \"\"\n : \" |gray|(press Enter to leave empty)|reset|\";\n const defaultNotice =\n defaultValue !== undefined ? ` [default: ${defaultValue}]` : \"\";\n const booleanNotice = type === \"boolean\" ? \" |reset|(y/n)\" : \"\";\n const promptMessage = `${message}${defaultNotice}${booleanNotice}${notice} `;\n const prompt = generateTerminalMessage(promptMessage, params);\n\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n while (true) {\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed.length === 0) {\n if (defaultValue !== undefined) {\n // use the default value, parsed to a string\n return (\n typeof defaultValue === \"string\" ? defaultValue\n : typeof defaultValue === \"number\" ? String(defaultValue)\n : defaultValue ? \"true\"\n : \"false\"\n );\n }\n\n if (required) {\n stdout.write(\n generateTerminalMessage(\n \"|red|This value is required.|reset| Please enter a value.\\n\",\n ),\n );\n continue;\n }\n return undefined;\n }\n if (type === \"boolean\") {\n const normalized = trimmed.toLowerCase();\n if (normalized === \"y\" || normalized === \"yes\") {\n return \"true\";\n }\n if (normalized === \"n\" || normalized === \"no\") {\n return \"false\";\n }\n stdout.write(\n generateTerminalMessage(\n \"|red|That was not a valid response.|reset| Please enter y or n.\\n\",\n ),\n );\n continue;\n }\n return answer;\n }\n } finally {\n rl.close();\n }\n}\n","import { camelCase } from \"change-case\";\nimport { match } from \"ts-pattern\";\nimport { generateHelpText } from \"@/AcclimateCLI/generateHelpText/generateHelpText\";\nimport { CLIError } from \"@/CLIError\";\nimport { requestTerminalInput } from \"@/requestTerminalInput\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionAlias,\n CLIOptionParam,\n CLIParam,\n CLIParamDataType,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n ValueOfParam,\n} from \"@/AcclimateCLI/AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nfunction _isValidFullOptionName(name: string): name is CLIFullOptionName {\n return name.startsWith(\"--\");\n}\n\nfunction _isValidOptionAlias(name: string): name is CLIOptionAlias {\n return name.startsWith(\"-\");\n}\n\nfunction isEmptyObject(obj: object): obj is EmptyObject {\n return Object.keys(obj).length === 0;\n}\n\nfunction _validateParsedValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: { parsedValue: PValue; paramConfig: P; cliName: string }): PValue {\n const { parsedValue, paramConfig, cliName } = options;\n if (paramConfig.validator) {\n const validator = paramConfig.validator as (\n value: PValue,\n ) => boolean | string;\n const validationResult = validator(parsedValue);\n if (validationResult === true) {\n return parsedValue;\n }\n throw CLIError.invalidCLIParamValue({\n cliName,\n paramName: paramConfig.name,\n paramValue: parsedValue,\n message:\n typeof validationResult === \"string\" ? validationResult : undefined,\n });\n }\n return parsedValue;\n}\n\nfunction _parseAndValidateValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: {\n cliName: string;\n inputValue: string | undefined;\n defaultValue: PValue | undefined;\n paramConfig: P;\n}): PValue | undefined {\n const { cliName, inputValue, defaultValue, paramConfig } = options;\n if (inputValue === undefined) {\n if (defaultValue === undefined) {\n return undefined;\n }\n return _validateParsedValue({\n cliName,\n parsedValue: defaultValue,\n paramConfig,\n });\n }\n\n const parsedValue =\n paramConfig.parser ?\n (paramConfig.parser(inputValue) as PValue)\n // if no parser was set, we use the default parser\n : (match(paramConfig.type)\n .with(\"boolean\", () => {\n return inputValue === \"false\" ? false : true;\n })\n .with(\"number\", () => {\n return Number.parseInt(inputValue, 10);\n })\n .with(\"string\", () => {\n return inputValue;\n })\n .exhaustive(() => {\n return inputValue;\n }) as PValue);\n return _validateParsedValue({\n cliName,\n parsedValue,\n paramConfig,\n });\n}\n\nfunction _replaceAliases<\n TGlobalOptionArgs extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TOptionArgs extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TPositionalArgs extends\n | Record<CLIPositionalParamName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>({\n aliasedOptionArgs,\n cli,\n}: {\n aliasedOptionArgs: Record<CLIOptionAlias, string>;\n cli: IAcclimateCLI<\n TGlobalOptionArgs,\n TOptionArgs,\n TPositionalArgs,\n TCommands\n >;\n}): Record<CLIOptionAlias, string> {\n const aliasMap = cli.state.aliases;\n return Object.entries(aliasedOptionArgs).reduce(\n (acc, [aliasKey, value]) => {\n const alias = aliasKey as CLIOptionAlias;\n const optionName = aliasMap[alias] ?? alias;\n acc[optionName] = value;\n return acc;\n },\n {} as Record<CLIOptionAlias, string>,\n );\n}\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n};\n\nasync function askForValue(options: {\n argConfig: CLIParamWithRequired;\n}): Promise<string | undefined> {\n const { argConfig } = options;\n const askIfEmpty = argConfig.askIfEmpty;\n const description =\n argConfig.description ? ` (${argConfig.description})` : \"\";\n const baseMessage =\n typeof askIfEmpty === \"object\" ?\n askIfEmpty.message\n : `Please enter a value for ${argConfig.name}${description}`;\n const coloredMessage = `|bright_cyan|${baseMessage}|reset|`;\n return requestTerminalInput({\n message: coloredMessage,\n params: {},\n responseOptions: {\n required: argConfig.required,\n type: argConfig.type,\n defaultValue: argConfig.defaultValue,\n },\n });\n}\n\nasync function _runCLIHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(options: {\n rawPositionalArgs: string[];\n rawOptionArgs: Record<CLIOptionAlias, string>;\n rawGlobalOptionArgs: Record<CLIFullOptionName, string>;\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >;\n}): Promise<void> {\n const { rawGlobalOptionArgs, rawOptionArgs, rawPositionalArgs, cli } = {\n ...options,\n rawGlobalOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawGlobalOptionArgs,\n cli: options.cli,\n }),\n rawOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawOptionArgs,\n\n // TODO(jpsyx): fix that this does not have the CLI may not have all\n cli: options.cli,\n }),\n };\n\n // is the first argument a command?\n const firstArg = rawPositionalArgs[0];\n if (\n firstArg &&\n !isEmptyObject(cli.state.commands) &&\n cli.state.commands[firstArg]\n ) {\n // add the parent's global options to the sub-command\n const commandCLI = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ).reduce(\n (newCmd, argConfig) => {\n return newCmd.addGlobalOption(argConfig);\n },\n cli.getCommandCLI(firstArg as Extract<keyof TCommands, string>) as AnyCLI,\n );\n\n // run the sub-command\n return _runCLIHelper({\n rawPositionalArgs: rawPositionalArgs.slice(1),\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli: commandCLI,\n });\n }\n\n const cliName = cli.getName();\n\n // build the positional arguments dictionary\n // first check that we haven't supplied too many positional arguments\n if (rawPositionalArgs.length > cli.state.positionalArgs.length) {\n throw CLIError.tooManyPositionalArgs({\n cliName,\n count: rawPositionalArgs.length,\n });\n }\n\n // parse positional arguments\n const parsedPositionalArgs: Record<string, CLIParamDataType> = {};\n for (const [idx, argConfig] of cli.state.positionalArgs.entries()) {\n let rawVal = rawPositionalArgs[idx];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredPositionalArg({\n cliName,\n positionalArgName: argConfig.name,\n });\n }\n\n parsedPositionalArgs[argConfig.name] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the options\n const parsedOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n\n parsedOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the global options\n const parsedGlobalOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawGlobalOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n parsedGlobalOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // run the action\n const action = cli.state.action;\n if (action) {\n action({\n ...parsedPositionalArgs,\n ...parsedOptionArgs,\n ...parsedGlobalOptionArgs,\n } as FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >);\n return;\n }\n\n console.log(generateHelpText(cli));\n}\n\n/**\n * Run a CLI instance given an array of inputs.\n *\n * @param options - The options for running the CLI.\n */\nexport async function runCLI(options: {\n input: string[];\n cli: AnyCLI;\n}): Promise<void> {\n const { input, cli } = options;\n const firstOptionIdx = input.findIndex((token) => {\n return token.startsWith(\"-\");\n });\n\n const [rawPositionalArgs, rest] =\n firstOptionIdx === -1 ?\n [input, []]\n : [input.slice(0, firstOptionIdx), input.slice(firstOptionIdx)];\n\n const rawOptionArgs: Record<CLIOptionAlias, string> = {};\n const rawGlobalOptionArgs: Record<CLIFullOptionName, string> = {};\n let currentAlias: CLIOptionAlias | undefined;\n let currentVals: string[] = [];\n\n const { aliases, globalOptionArgs } = cli.state as CLIState<\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIPositionalParamName, CLIOptionParam>,\n Record<CLICommandName, AnyCLI>\n >;\n\n for (const argVal of rest.concat(\"-\")) {\n if (_isValidOptionAlias(argVal)) {\n if (currentAlias) {\n const rawValue = currentVals.join(\" \");\n const optionName = aliases[currentAlias] ?? currentAlias;\n if (\n _isValidFullOptionName(optionName) &&\n !isEmptyObject(globalOptionArgs) &&\n globalOptionArgs[optionName]\n ) {\n rawGlobalOptionArgs[optionName] = rawValue;\n } else {\n rawOptionArgs[optionName] = rawValue;\n }\n }\n currentAlias = argVal;\n currentVals = [];\n } else {\n currentVals.push(argVal);\n }\n }\n\n await _runCLIHelper({\n rawPositionalArgs,\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli,\n });\n}\n","import { createCLI } from \"./AcclimateCLI\";\nimport { runCLI } from \"./AcclimateCLI/runCLI/runCLI\";\nimport { generateTerminalMessage } from \"./generateTerminalMessage\";\nimport { requestTerminalInput } from \"./requestTerminalInput\";\nimport type { AnyCLI, IAcclimateCLI } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype Acclimate = {\n /**\n * Create a new Acclimate CLI instance.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\n createCLI: (name: string) => IAcclimateCLI;\n\n /**\n * Run a CLI instance.\n *\n * It can only be run once. Calling any other methods after `.run()` will\n * throw an error.\n *\n * @param cli - The CLI instance to run.\n */\n run: (cli: AnyCLI) => void;\n\n /**\n * Outputs a message with `console.log`.\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\n log: (\n message: string,\n params?: Record<string, string | boolean | number | null | undefined>,\n ) => void;\n\n /**\n * Prompt the user for interactive input in the terminal.\n *\n * @param options - Prompt configuration.\n * @returns The user's response, or undefined when left empty and optional.\n */\n requestInput: (options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n }) => Promise<string | undefined>;\n};\n\nexport const Acclimate: Acclimate = {\n createCLI,\n run: (cli: AnyCLI) => {\n void runCLI({ cli, input: process.argv.slice(2) });\n },\n log: (\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n ) => {\n console.log(generateTerminalMessage(message, params));\n },\n requestInput: (options) => {\n return requestTerminalInput(options);\n },\n};\n"]}
1
+ {"version":3,"sources":["../src/CLIError.ts","../src/AcclimateCLI/AcclimateCLI.ts","../src/AcclimateCLI/createCLI/defaultCLIState.ts","../src/AcclimateCLI/createCLI/createCLI.ts","../src/generateTerminalMessage/generateTerminalMessage.ts","../src/AcclimateCLI/generateHelpText/generateHelpText.ts","../src/requestTerminalInput/requestTerminalInput.ts","../src/AcclimateCLI/runCLI/runCLI.ts","../src/Acclimate.ts"],"names":["match"],"mappings":"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","file":"index.js","sourcesContent":["import type { CLIParamDataType } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype CLIErrorInfo =\n | {\n code: \"already_run\";\n details: undefined;\n }\n | {\n code: \"unknown_command\";\n details: { commandName: string };\n }\n | {\n code: \"invalid_positional_arg_config\";\n details: { positionalArgName: string };\n }\n | {\n code: \"too_many_positional_args\";\n details: { count: number };\n }\n | {\n code: \"missing_required_positional_arg\";\n details: { positionalArgName: string };\n }\n | {\n code: \"missing_required_option\";\n details: { optionName: string };\n }\n | {\n code: \"unknown_option\";\n details: {\n optionName: string;\n };\n }\n | {\n code: \"invalid_cli_param_value\";\n details: {\n paramName: string;\n paramValue: CLIParamDataType;\n };\n }\n | { code: \"unknown_error\"; details: undefined };\n\ntype CLIErrorOptions = { cliName: string; message: string } & CLIErrorInfo;\n\nexport class CLIError extends Error {\n static invalidCLIParamValue(options: {\n cliName: string;\n paramName: string;\n paramValue: CLIParamDataType;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Invalid value for CLI param \"${options.paramName}\"`,\n code: \"invalid_cli_param_value\",\n details: { paramName: options.paramName, paramValue: options.paramValue },\n });\n }\n static missingRequiredOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ?? `Required option \"${options.optionName}\" is missing`,\n code: \"missing_required_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static missingRequiredPositionalArg(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Required positional argument \"${options.positionalArgName}\" is missing`,\n code: \"missing_required_positional_arg\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownOption(options: {\n cliName: string;\n optionName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Option \"${options.optionName}\" not found`,\n code: \"unknown_option\",\n details: { optionName: options.optionName },\n });\n }\n\n static tooManyPositionalArgs(options: {\n cliName: string;\n count: number;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"Too many positional arguments provided.\",\n code: \"too_many_positional_args\",\n details: { count: options.count },\n });\n }\n\n static invalidPositionalArgConfig(options: {\n cliName: string;\n positionalArgName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message:\n options.message ??\n `Positional argument configuration for \"${options.positionalArgName}\" is invalid`,\n code: \"invalid_positional_arg_config\",\n details: { positionalArgName: options.positionalArgName },\n });\n }\n\n static unknownCommand(options: {\n cliName: string;\n commandName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? `Command \"${options.commandName}\" not found`,\n code: \"unknown_command\",\n details: { commandName: options.commandName },\n });\n }\n\n static alreadyRun(options: {\n cliName: string;\n message?: string;\n }): CLIError {\n return new CLIError({\n cliName: options.cliName,\n message: options.message ?? \"CLI has already been run\",\n code: \"already_run\",\n details: undefined,\n });\n }\n\n constructor(options: CLIErrorOptions) {\n super(`❌ Error running ${options.cliName}: ${options.message}`);\n }\n}\n","import { CLIError } from \"@/CLIError\";\nimport type {\n AddEntry,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n} from \"./AcclimateCLI.types\";\nimport type { EmptyObject, Simplify } from \"type-fest\";\n\nexport function AcclimateCLI<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, IAcclimateCLI> | EmptyObject,\n>(\n state: CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n> {\n const cliName = state.name;\n return {\n state,\n\n getName: () => {\n return cliName;\n },\n\n action: (\n action: (\n args: Simplify<\n FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >\n >,\n ) => void,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n action,\n });\n },\n\n description: (\n description: string,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n > => {\n return AcclimateCLI({\n ...state,\n description,\n });\n },\n\n addPositionalArg: <\n PName extends CLIPositionalParamName,\n P extends CLIPositionalParam<PName>,\n >(\n param: P,\n ) => {\n if (\n param.required &&\n state.positionalArgs.some((p) => {\n return !p.required;\n })\n ) {\n throw CLIError.invalidPositionalArgConfig({\n cliName,\n positionalArgName: param.name,\n message:\n \"Required positional arguments must be before optional positional arguments\",\n });\n }\n\n return AcclimateCLI({\n ...state,\n positionalArgs: [\n ...state.positionalArgs,\n { ...param, required: param.required ?? true },\n ],\n } as unknown as CLIState<\n AddEntry<TPositionalParams, P[\"name\"], P>,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addGlobalOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n globalOptionArgs: {\n ...state.globalOptionArgs,\n [param.name]: param,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n AddEntry<TGlobalOptionParams, P[\"name\"], P>,\n TCommands\n >);\n },\n\n addOption: <P extends CLIOptionParam>(param: P) => {\n const newAliases = (param.aliases ?? []).reduce(\n (acc, alias) => {\n acc[alias] = param.name;\n return acc;\n },\n {} as Record<`-${string}` | `--${string}`, `--${string}`>,\n );\n return AcclimateCLI<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >({\n ...state,\n aliases: { ...state.aliases, ...newAliases },\n optionArgs: { ...state.optionArgs, [param.name]: param },\n } as unknown as CLIState<\n TPositionalParams,\n AddEntry<TOptionParams, P[\"name\"], P>,\n TGlobalOptionParams,\n TCommands\n >);\n },\n\n addCommand: <C extends CLICommandName, CommandCLI extends IAcclimateCLI>(\n commandName: C,\n cli: CommandCLI,\n ): IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n > => {\n return AcclimateCLI({\n ...state,\n commands: {\n ...state.commands,\n [commandName]: cli,\n },\n } as unknown as CLIState<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n AddEntry<TCommands, C, CommandCLI>\n >);\n },\n\n getCommandCLI: <C extends Extract<keyof TCommands, CLICommandName>>(\n commandName: C,\n ): C extends keyof TCommands ? TCommands[C] : never => {\n const cmd = state.commands[commandName];\n if (!cmd) {\n throw CLIError.unknownCommand({\n cliName,\n commandName,\n message: `Command \"${commandName}\" not found`,\n });\n }\n return cmd as C extends keyof TCommands ? TCommands[C] : never;\n },\n };\n}\n","import type { CLIState } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nexport const defaultCLIState: Omit<\n CLIState<EmptyObject, EmptyObject, EmptyObject, EmptyObject>,\n \"name\"\n> = {\n aliases: {},\n description: undefined,\n commands: {},\n positionalArgs: [],\n optionArgs: {},\n globalOptionArgs: {},\n action: undefined,\n};\n","import { AcclimateCLI } from \"../AcclimateCLI\";\nimport { defaultCLIState } from \"./defaultCLIState\";\nimport type { IAcclimateCLI } from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\n/**\n * Builder function to create a new CLI instance with a given name.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\nexport function createCLI(\n name: string,\n): IAcclimateCLI<EmptyObject, EmptyObject, EmptyObject, EmptyObject> {\n return AcclimateCLI({ ...defaultCLIState, name });\n}\n","const COLOR_CODES: Record<string, string> = {\n reset: \"\\x1b[0m\",\n dim: \"\\x1b[2m\",\n black: \"\\x1b[30m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n bright_black: \"\\x1b[90m\",\n gray: \"\\x1b[90m\",\n grey: \"\\x1b[90m\",\n bright_red: \"\\x1b[91m\",\n bright_green: \"\\x1b[92m\",\n bright_yellow: \"\\x1b[93m\",\n bright_blue: \"\\x1b[94m\",\n bright_magenta: \"\\x1b[95m\",\n bright_cyan: \"\\x1b[96m\",\n bright_white: \"\\x1b[97m\",\n};\n\nconst PARAM_TOKEN_REGEX = /\\$([a-zA-Z0-9_]+)\\$/g;\nconst COLOR_TOKEN_REGEX = /\\|([a-zA-Z_]+)\\|/g;\n\n/**\n * Replaces `$token$` placeholders with values from `params`.\n * If a token does not exist in `params`, the placeholder is left unchanged.\n */\nfunction interpolateParams(\n message: string,\n params: Record<string, string | boolean | number | null | undefined>,\n): string {\n return message.replace(PARAM_TOKEN_REGEX, (match: string, key: string) => {\n void match;\n const value = params[key];\n if (value === undefined) {\n return \"\";\n }\n return String(value);\n });\n}\n\nfunction applyColors(message: string) {\n return message.replace(COLOR_TOKEN_REGEX, (match, colorName: string) => {\n const code = COLOR_CODES[colorName.toLowerCase()];\n return code ?? match;\n });\n}\n\n/**\n * Outputs a message intended to be passed directly to `console.log`\n *\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\nexport function generateTerminalMessage(\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n): string {\n const hasColorToken = Boolean(message.match(COLOR_TOKEN_REGEX));\n const endsWithReset = message.trimEnd().endsWith(\"|reset|\");\n const withReset =\n hasColorToken && !endsWithReset ? `${message}|reset|` : message;\n const interpolated = interpolateParams(withReset, params);\n return applyColors(interpolated);\n}\n","import { generateTerminalMessage } from \"@/generateTerminalMessage\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionParam,\n CLIParam,\n CLIPositionalParam,\n CLIPositionalParamName,\n IAcclimateCLI,\n} from \"../AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nconst _SECTION_TITLES = [\n \"Positional Arguments\",\n \"Options\",\n \"Global Options\",\n \"Commands\",\n] as const;\n\ntype SectionTitle = (typeof _SECTION_TITLES)[number];\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n aliases?: readonly string[];\n};\n\nfunction formatSectionTitle(title: SectionTitle): string {\n return `|bright_yellow|${title}|reset|`;\n}\n\nfunction formatDefaultValue(\n value: CLIParamWithRequired[\"defaultValue\"],\n): string {\n return `|gray|[default: ${JSON.stringify(value)}]|reset|`;\n}\n\nfunction formatParamLine(param: CLIParamWithRequired): string {\n const description = param.description ?? \"No description\";\n const requiredLabel =\n param.required ? \"|red|required|reset|\" : \"|gray|optional|reset|\";\n const defaultLabel =\n param.defaultValue !== undefined ?\n formatDefaultValue(param.defaultValue)\n : undefined;\n const aliasList =\n param.aliases && param.aliases.length > 0 ? param.aliases.join(\", \") : \"\";\n const displayName = aliasList ? `${param.name}, ${aliasList}` : param.name;\n\n const segments = [\n ` |bright_white|${displayName}|reset|`,\n `(${param.type})|reset| ${requiredLabel}`,\n `- |gray|${description}|reset|`,\n defaultLabel,\n ].filter(Boolean);\n\n return segments.join(\" \");\n}\n\nfunction formatSection(\n title: SectionTitle,\n params: readonly CLIParamWithRequired[],\n): string[] {\n if (params.length === 0) {\n return [];\n }\n\n return [formatSectionTitle(title), ...params.map(formatParamLine)];\n}\n\nfunction formatCommandBullets(\n commands: { name: string; description?: string }[],\n): string[] {\n return commands.map(({ name, description }) => {\n const descLabel =\n description !== undefined ?\n `|gray|${description}|reset|`\n : `|dim|No description|reset|`;\n return ` • |bright_white|${name}|reset| - ${descLabel}`;\n });\n}\n\nfunction _generateHelpTextHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n options: { level: 1 | 2 },\n): string {\n const name = cli.getName();\n const description = cli.state.description;\n const level = Number(options.level);\n\n const positionalParams = cli.state\n .positionalArgs as readonly CLIParamWithRequired[];\n const optionParams = Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const globalOptionParams = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ) as readonly CLIParamWithRequired[];\n const sortedCommands = Object.entries(cli.state.commands).sort(([a], [b]) => {\n return a.localeCompare(b);\n });\n\n const headerLines = [`|bright_cyan|${name}|reset|`];\n if (description !== undefined) {\n headerLines.push(` |gray|${description}|reset|`);\n }\n\n let commandSection: string[];\n if (sortedCommands.length === 0) {\n commandSection = [];\n } else if (level === 2) {\n const commandsWithDescriptions = sortedCommands.map(\n ([commandName, commandCLI]) => ({\n name: commandName,\n description: commandCLI.state.description,\n }),\n );\n commandSection = [\n formatSectionTitle(\"Commands\"),\n ...formatCommandBullets(commandsWithDescriptions),\n ];\n } else {\n // At level 1, just show the header - sub-commands are rendered recursively below\n commandSection = [formatSectionTitle(\"Commands\")];\n }\n\n const sections = [\n formatSection(\"Positional Arguments\", positionalParams),\n formatSection(\"Options\", optionParams),\n formatSection(\"Global Options\", globalOptionParams),\n commandSection,\n ].filter((section) => section.length > 0);\n\n const lines = [...headerLines];\n sections.forEach((section, idx) => {\n lines.push(\"\", ...section);\n });\n\n if (level === 1) {\n const subCommandHelpText = sortedCommands.map(([, commandCLI]) => {\n return _generateHelpTextHelper(commandCLI, { level: 2 });\n });\n if (subCommandHelpText.length > 0) {\n subCommandHelpText.forEach((text) => {\n lines.push(\"\", ...text.split(\"\\n\"));\n });\n }\n }\n\n const indent = \" \".repeat(Math.max(0, level - 1));\n return lines\n .map((line) => {\n return line === \"\" ? \"\" : `${indent}${line}`;\n })\n .join(\"\\n\");\n}\n\nexport function generateHelpText<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >,\n): string {\n return generateTerminalMessage(_generateHelpTextHelper(cli, { level: 1 }));\n}\n","import { stdin, stdout } from \"node:process\";\nimport { createInterface } from \"node:readline/promises\";\nimport { generateTerminalMessage } from \"@/generateTerminalMessage\";\n\n/**\n * Prompt the user for terminal input, optionally enforcing a non-empty value.\n */\nexport async function requestTerminalInput(options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n}): Promise<string | undefined> {\n const {\n message,\n params,\n responseOptions: { required, type, defaultValue },\n } = options;\n const notice =\n defaultValue !== undefined ? \" |gray|(press Enter to use default)|reset|\"\n : required ? \"\"\n : \" |gray|(press Enter to leave empty)|reset|\";\n const defaultNotice =\n defaultValue !== undefined ? ` [default: ${defaultValue}]` : \"\";\n const booleanNotice = type === \"boolean\" ? \" |reset|(y/n)\" : \"\";\n const promptMessage = `${message}${defaultNotice}${booleanNotice}${notice} `;\n const prompt = generateTerminalMessage(promptMessage, params);\n\n const rl = createInterface({ input: stdin, output: stdout });\n try {\n while (true) {\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed.length === 0) {\n if (defaultValue !== undefined) {\n // use the default value, parsed to a string\n return (\n typeof defaultValue === \"string\" ? defaultValue\n : typeof defaultValue === \"number\" ? String(defaultValue)\n : defaultValue ? \"true\"\n : \"false\"\n );\n }\n\n if (required) {\n stdout.write(\n generateTerminalMessage(\n \"|red|This value is required.|reset| Please enter a value.\\n\",\n ),\n );\n continue;\n }\n return undefined;\n }\n if (type === \"boolean\") {\n const normalized = trimmed.toLowerCase();\n if (normalized === \"y\" || normalized === \"yes\") {\n return \"true\";\n }\n if (normalized === \"n\" || normalized === \"no\") {\n return \"false\";\n }\n stdout.write(\n generateTerminalMessage(\n \"|red|That was not a valid response.|reset| Please enter y or n.\\n\",\n ),\n );\n continue;\n }\n return answer;\n }\n } finally {\n rl.close();\n }\n}\n","import { camelCase } from \"change-case\";\nimport { match } from \"ts-pattern\";\nimport { generateHelpText } from \"@/AcclimateCLI/generateHelpText/generateHelpText\";\nimport { CLIError } from \"@/CLIError\";\nimport { requestTerminalInput } from \"@/requestTerminalInput\";\nimport type {\n AnyCLI,\n CLICommandName,\n CLIFullOptionName,\n CLIOptionAlias,\n CLIOptionParam,\n CLIParam,\n CLIParamDataType,\n CLIPositionalParam,\n CLIPositionalParamName,\n CLIState,\n FullCLIArgValues,\n IAcclimateCLI,\n ValueOfParam,\n} from \"@/AcclimateCLI/AcclimateCLI.types\";\nimport type { EmptyObject } from \"type-fest\";\n\nfunction _isValidFullOptionName(name: string): name is CLIFullOptionName {\n return name.startsWith(\"--\");\n}\n\nfunction _isValidOptionAlias(name: string): name is CLIOptionAlias {\n return name.startsWith(\"-\");\n}\n\nfunction isEmptyObject(obj: object): obj is EmptyObject {\n return Object.keys(obj).length === 0;\n}\n\nfunction _validateParsedValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: { parsedValue: PValue; paramConfig: P; cliName: string }): PValue {\n const { parsedValue, paramConfig, cliName } = options;\n if (paramConfig.validator) {\n const validator = paramConfig.validator as (\n value: PValue,\n ) => boolean | string;\n const validationResult = validator(parsedValue);\n if (validationResult === true) {\n return parsedValue;\n }\n throw CLIError.invalidCLIParamValue({\n cliName,\n paramName: paramConfig.name,\n paramValue: parsedValue,\n message:\n typeof validationResult === \"string\" ? validationResult : undefined,\n });\n }\n return parsedValue;\n}\n\nfunction _parseAndValidateValue<\n P extends CLIParam<string>,\n PValue extends ValueOfParam<P>,\n>(options: {\n cliName: string;\n inputValue: string | undefined;\n defaultValue: PValue | undefined;\n paramConfig: P;\n}): PValue | undefined {\n const { cliName, inputValue, defaultValue, paramConfig } = options;\n if (inputValue === undefined) {\n if (defaultValue === undefined) {\n return undefined;\n }\n return _validateParsedValue({\n cliName,\n parsedValue: defaultValue,\n paramConfig,\n });\n }\n\n const parsedValue =\n paramConfig.parser ?\n (paramConfig.parser(inputValue) as PValue)\n // if no parser was set, we use the default parser\n : (match(paramConfig.type)\n .with(\"boolean\", () => {\n return inputValue === \"false\" ? false : true;\n })\n .with(\"number\", () => {\n return Number.parseInt(inputValue, 10);\n })\n .with(\"string\", () => {\n return inputValue;\n })\n .exhaustive(() => {\n return inputValue;\n }) as PValue);\n return _validateParsedValue({\n cliName,\n parsedValue,\n paramConfig,\n });\n}\n\nfunction _replaceAliases<\n TGlobalOptionArgs extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TOptionArgs extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TPositionalArgs extends\n | Record<CLIPositionalParamName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>({\n aliasedOptionArgs,\n cli,\n}: {\n aliasedOptionArgs: Record<CLIOptionAlias, string>;\n cli: IAcclimateCLI<\n TGlobalOptionArgs,\n TOptionArgs,\n TPositionalArgs,\n TCommands\n >;\n}): Record<CLIOptionAlias, string> {\n const aliasMap = cli.state.aliases;\n return Object.entries(aliasedOptionArgs).reduce(\n (acc, [aliasKey, value]) => {\n const alias = aliasKey as CLIOptionAlias;\n const optionName = aliasMap[alias] ?? alias;\n acc[optionName] = value;\n return acc;\n },\n {} as Record<CLIOptionAlias, string>,\n );\n}\n\ntype CLIParamWithRequired = CLIParam<string> & {\n required: boolean;\n};\n\nasync function askForValue(options: {\n argConfig: CLIParamWithRequired;\n}): Promise<string | undefined> {\n const { argConfig } = options;\n const askIfEmpty = argConfig.askIfEmpty;\n const description =\n argConfig.description ? ` (${argConfig.description})` : \"\";\n const baseMessage =\n typeof askIfEmpty === \"object\" ?\n askIfEmpty.message\n : `Please enter a value for ${argConfig.name}${description}`;\n const coloredMessage = `|bright_cyan|${baseMessage}|reset|`;\n return requestTerminalInput({\n message: coloredMessage,\n params: {},\n responseOptions: {\n required: argConfig.required,\n type: argConfig.type,\n defaultValue: argConfig.defaultValue,\n },\n });\n}\n\nasync function _runCLIHelper<\n TPositionalParams extends\n | Record<CLIPositionalParamName, CLIPositionalParam>\n | EmptyObject,\n TOptionParams extends Record<CLIFullOptionName, CLIOptionParam> | EmptyObject,\n TGlobalOptionParams extends\n | Record<CLIFullOptionName, CLIOptionParam>\n | EmptyObject,\n TCommands extends Record<CLICommandName, AnyCLI> | EmptyObject,\n>(options: {\n rawPositionalArgs: string[];\n rawOptionArgs: Record<CLIOptionAlias, string>;\n rawGlobalOptionArgs: Record<CLIFullOptionName, string>;\n cli: IAcclimateCLI<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams,\n TCommands\n >;\n}): Promise<void> {\n const { rawGlobalOptionArgs, rawOptionArgs, rawPositionalArgs, cli } = {\n ...options,\n rawGlobalOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawGlobalOptionArgs,\n cli: options.cli,\n }),\n rawOptionArgs: _replaceAliases({\n aliasedOptionArgs: options.rawOptionArgs,\n\n // TODO(jpsyx): fix that this does not have the CLI may not have all\n cli: options.cli,\n }),\n };\n\n // is the first argument a command?\n const firstArg = rawPositionalArgs[0];\n if (\n firstArg &&\n !isEmptyObject(cli.state.commands) &&\n cli.state.commands[firstArg]\n ) {\n // add the parent's global options to the sub-command\n const commandCLI = Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n ).reduce(\n (newCmd, argConfig) => {\n return newCmd.addGlobalOption(argConfig);\n },\n cli.getCommandCLI(firstArg as Extract<keyof TCommands, string>) as AnyCLI,\n );\n\n // run the sub-command\n return _runCLIHelper({\n rawPositionalArgs: rawPositionalArgs.slice(1),\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli: commandCLI,\n });\n }\n\n const cliName = cli.getName();\n\n // build the positional arguments dictionary\n // first check that we haven't supplied too many positional arguments\n if (rawPositionalArgs.length > cli.state.positionalArgs.length) {\n throw CLIError.tooManyPositionalArgs({\n cliName,\n count: rawPositionalArgs.length,\n });\n }\n\n // parse positional arguments\n const parsedPositionalArgs: Record<string, CLIParamDataType> = {};\n for (const [idx, argConfig] of cli.state.positionalArgs.entries()) {\n let rawVal = rawPositionalArgs[idx];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredPositionalArg({\n cliName,\n positionalArgName: argConfig.name,\n });\n }\n\n parsedPositionalArgs[argConfig.name] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the options\n const parsedOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.optionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n\n parsedOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // parse the global options\n const parsedGlobalOptionArgs: Record<string, CLIParamDataType> = {};\n for (const argConfig of Object.values(\n cli.state.globalOptionArgs as Record<CLIFullOptionName, CLIOptionParam>,\n )) {\n let rawVal = rawGlobalOptionArgs[argConfig.name];\n if (argConfig.askIfEmpty && rawVal === undefined) {\n rawVal = await askForValue({ argConfig });\n }\n\n if (argConfig.required && rawVal === undefined) {\n throw CLIError.missingRequiredOption({\n cliName,\n optionName: argConfig.name,\n });\n }\n parsedGlobalOptionArgs[camelCase(argConfig.name)] = _parseAndValidateValue({\n cliName,\n inputValue: rawVal,\n defaultValue: argConfig.defaultValue,\n paramConfig: argConfig,\n });\n }\n\n // run the action\n const action = cli.state.action;\n if (action) {\n action({\n ...parsedPositionalArgs,\n ...parsedOptionArgs,\n ...parsedGlobalOptionArgs,\n } as FullCLIArgValues<\n TPositionalParams,\n TOptionParams,\n TGlobalOptionParams\n >);\n return;\n }\n\n console.log(generateHelpText(cli));\n}\n\n/**\n * Run a CLI instance given an array of inputs.\n *\n * @param options - The options for running the CLI.\n */\nexport async function runCLI(options: {\n input: string[];\n cli: AnyCLI;\n}): Promise<void> {\n const { input, cli } = options;\n const firstOptionIdx = input.findIndex((token) => {\n return token.startsWith(\"-\");\n });\n\n const [rawPositionalArgs, rest] =\n firstOptionIdx === -1 ?\n [input, []]\n : [input.slice(0, firstOptionIdx), input.slice(firstOptionIdx)];\n\n const rawOptionArgs: Record<CLIOptionAlias, string> = {};\n const rawGlobalOptionArgs: Record<CLIFullOptionName, string> = {};\n let currentAlias: CLIOptionAlias | undefined;\n let currentVals: string[] = [];\n\n const { aliases, globalOptionArgs } = cli.state as CLIState<\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIFullOptionName, CLIOptionParam>,\n Record<CLIPositionalParamName, CLIOptionParam>,\n Record<CLICommandName, AnyCLI>\n >;\n\n for (const argVal of rest.concat(\"-\")) {\n if (_isValidOptionAlias(argVal)) {\n if (currentAlias) {\n const rawValue = currentVals.join(\" \");\n const optionName = aliases[currentAlias] ?? currentAlias;\n if (\n _isValidFullOptionName(optionName) &&\n !isEmptyObject(globalOptionArgs) &&\n globalOptionArgs[optionName]\n ) {\n rawGlobalOptionArgs[optionName] = rawValue;\n } else {\n rawOptionArgs[optionName] = rawValue;\n }\n }\n currentAlias = argVal;\n currentVals = [];\n } else {\n currentVals.push(argVal);\n }\n }\n\n await _runCLIHelper({\n rawPositionalArgs,\n rawOptionArgs,\n rawGlobalOptionArgs,\n cli,\n });\n}\n","import { createCLI } from \"./AcclimateCLI\";\nimport { runCLI } from \"./AcclimateCLI/runCLI/runCLI\";\nimport { generateTerminalMessage } from \"./generateTerminalMessage\";\nimport { requestTerminalInput } from \"./requestTerminalInput\";\nimport type { AnyCLI, IAcclimateCLI } from \"./AcclimateCLI/AcclimateCLI.types\";\n\ntype Acclimate = {\n /**\n * Create a new Acclimate CLI instance.\n *\n * @param name - The name of the CLI.\n * @returns A new CLI instance.\n */\n createCLI: (name: string) => IAcclimateCLI;\n\n /**\n * Run a CLI instance.\n *\n * It can only be run once. Calling any other methods after `.run()` will\n * throw an error.\n *\n * @param cli - The CLI instance to run.\n */\n run: (cli: AnyCLI) => void;\n\n /**\n * Outputs a message with `console.log`.\n * Supports interpolation using `$varName$` as tokens.\n *\n * Colors can be changed within a message `|<COLOR_NAME>|` tokens.\n * Supported colors are:\n * - black\n * - red\n * - green\n * - yellow\n * - blue\n * - magenta\n * - cyan\n * - white\n * - bright_black|gray|grey\n * - bright_red\n * - bright_green\n * - bright_yellow\n * - bright_blue\n * - bright_magenta\n * - bright_cyan\n * - bright_white\n *\n * The color remains active until another color token is found,\n * or if |reset| is found (which resets the terminal color to the default).\n *\n * @example\n *\n * Acclimate.log(\"Hello $name$\", { name: \"Pablo\" });\n * // \"Hello Pablo\"\n *\n * Acclimate.log(\"|red|Error:|reset| There was an error.\")\n * // \"Error: There was an error.\"\n * // ^ the \"Error:\" portion will be red\n *\n */\n log: (\n message: string,\n params?: Record<string, string | boolean | number | null | undefined>,\n ) => void;\n\n /**\n * Prompt the user for interactive input in the terminal.\n *\n * @param options - Prompt configuration.\n * @returns The user's response, or undefined when left empty and optional.\n */\n requestInput: (options: {\n message: string;\n params: Record<string, string>;\n responseOptions: {\n required: boolean;\n type?: \"string\" | \"number\" | \"boolean\";\n\n /*\n * Default value to use if the user enters an empty response.\n *\n * If the option is `required` and the user doesn't supply a value, we will\n * not show an error if there is a `defaultValue` we can use.\n */\n defaultValue?: string | number | boolean;\n };\n }) => Promise<string | undefined>;\n};\n\nexport const Acclimate: Acclimate = {\n createCLI,\n run: (cli: AnyCLI) => {\n void runCLI({ cli, input: process.argv.slice(2) });\n },\n log: (\n message: string,\n params: Record<string, string | boolean | number | null | undefined> = {},\n ) => {\n console.log(generateTerminalMessage(message, params));\n },\n requestInput: (options) => {\n return requestTerminalInput(options);\n },\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avandar/acclimate",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "A lightweight TypeScript framework for building CLI tools.",
5
5
  "license": "MIT",
6
6
  "type": "module",