@ztimson/utils 0.23.1 → 0.23.3

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.
@@ -0,0 +1,52 @@
1
+ export type Arg<T = any> = {
2
+ /** Argument/property name */
3
+ name: string;
4
+ /** Argument description for help page */
5
+ desc: string;
6
+ /** Available shorthands */
7
+ flags?: string[];
8
+ /** Argument is not required */
9
+ optional?: boolean;
10
+ /** Default value if argument is not used */
11
+ default?: T;
12
+ /** Collects any unmatched arguments */
13
+ extras?: boolean;
14
+ };
15
+ export declare class ArgParser {
16
+ readonly name: string;
17
+ readonly desc: string;
18
+ readonly argList: (ArgParser | Arg)[];
19
+ readonly examples: string[];
20
+ commands: ArgParser[];
21
+ args: Arg[];
22
+ flags: Arg[];
23
+ defaults: {
24
+ [key: string]: any;
25
+ };
26
+ /**
27
+ * Create a unix-like argument parser to extract flags from the argument list. Can also create help messages.
28
+ *
29
+ * @param {string} name Script name
30
+ * @param {string} desc Help description
31
+ * @param {(ArgParser | Arg[]} argList Array of CLI arguments
32
+ * @param {string[]} examples Additional examples to display
33
+ */
34
+ constructor(name: string, desc: string, argList?: (ArgParser | Arg)[], examples?: string[]);
35
+ /**
36
+ * Parse an array into an arguments dictionary using the configuration.
37
+ *
38
+ * @param {string[]} args Array of arguments to be parsed
39
+ * @returns {object} Dictionary of arguments with defaults applied
40
+ */
41
+ parse(args: string[]): any;
42
+ /**
43
+ * Create help message from the provided description & argument list.
44
+ *
45
+ * @returns {string} Help message
46
+ * @param opts Help options: command - display a commands help, message - override help description
47
+ */
48
+ help(opts?: {
49
+ command?: string;
50
+ message?: string;
51
+ }): string;
52
+ }
package/dist/index.cjs CHANGED
@@ -5,6 +5,119 @@
5
5
  var __defNormalProp = (obj, key, value2) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value: value2 }) : obj[key] = value2;
6
6
  var __publicField = (obj, key, value2) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value2);
7
7
 
8
+ class ArgParser {
9
+ /**
10
+ * Create a unix-like argument parser to extract flags from the argument list. Can also create help messages.
11
+ *
12
+ * @param {string} name Script name
13
+ * @param {string} desc Help description
14
+ * @param {(ArgParser | Arg[]} argList Array of CLI arguments
15
+ * @param {string[]} examples Additional examples to display
16
+ */
17
+ constructor(name, desc, argList = [], examples = []) {
18
+ __publicField(this, "commands", []);
19
+ __publicField(this, "args", []);
20
+ __publicField(this, "flags", []);
21
+ __publicField(this, "defaults");
22
+ this.name = name;
23
+ this.desc = desc;
24
+ this.argList = argList;
25
+ this.examples = examples;
26
+ this.commands = argList.filter((arg) => arg instanceof ArgParser);
27
+ this.args = argList.filter((arg) => {
28
+ var _a;
29
+ return !(arg instanceof ArgParser) && !((_a = arg.flags) == null ? void 0 : _a.length);
30
+ });
31
+ this.flags = [...argList.filter((arg) => !(arg instanceof ArgParser) && arg.flags && arg.flags.length), ...this.flags];
32
+ this.defaults = argList.reduce((acc, arg) => ({ ...acc, [arg.name]: arg["extras"] ? [] : arg.default ?? null }), {});
33
+ this.examples = [
34
+ ...examples,
35
+ `[OPTIONS] ${this.args.map((arg) => (arg.optional ? `[${arg.name.toUpperCase()}]` : arg.name.toUpperCase()) + (arg.extras ? "..." : "")).join(" ")}`,
36
+ this.commands.length ? `[OPTIONS] COMMAND` : null,
37
+ `--help ${this.commands.length ? "[COMMAND]" : ""}`
38
+ ].filter((e) => !!e);
39
+ }
40
+ /**
41
+ * Parse an array into an arguments dictionary using the configuration.
42
+ *
43
+ * @param {string[]} args Array of arguments to be parsed
44
+ * @returns {object} Dictionary of arguments with defaults applied
45
+ */
46
+ parse(args) {
47
+ var _a;
48
+ let extras = [], parsed = { ...this.defaults, "_error": [] }, queue = [...args];
49
+ while (queue.length) {
50
+ let arg = queue.splice(0, 1)[0];
51
+ if (arg[0] == "-") {
52
+ if (arg[1] != "-" && arg.length > 2) {
53
+ queue = [...arg.substring(2).split("").map((a2) => `-${a2}`), ...queue];
54
+ arg = `-${arg[1]}`;
55
+ }
56
+ const combined = arg.split("=");
57
+ const argDef = this.flags.find((flag) => {
58
+ var _a2;
59
+ return (_a2 = flag.flags) == null ? void 0 : _a2.includes(combined[0] || arg);
60
+ });
61
+ if (argDef == null) {
62
+ extras.push(arg);
63
+ continue;
64
+ }
65
+ const value2 = argDef.default === false ? true : argDef.default === true ? false : queue.splice(queue.findIndex((q) => q[0] != "-"), 1)[0] || argDef.default;
66
+ if (value2 == null) parsed["_error"].push(`Option missing value: ${argDef.name || combined[0]}`);
67
+ parsed[argDef.name] = value2;
68
+ } else {
69
+ const c = this.commands.find((command) => command.name == arg);
70
+ if (!!c) {
71
+ const parsedCommand = c.parse(queue.splice(0, queue.length));
72
+ Object.keys(parsedCommand).forEach((key) => {
73
+ if (parsed[key] != parsedCommand[key] && parsedCommand[key] == c.defaults[key])
74
+ delete parsedCommand[key];
75
+ });
76
+ parsed = {
77
+ ...parsed,
78
+ ...parsedCommand,
79
+ _command: c.name
80
+ };
81
+ } else extras.push(arg);
82
+ }
83
+ }
84
+ this.args.filter((arg) => !arg.extras).forEach((arg) => {
85
+ if (!arg.optional && !extras.length) parsed["_error"].push(`Argument missing: ${arg.name.toUpperCase()}`);
86
+ if (extras.length) parsed[arg.name] = extras.splice(0, 1)[0];
87
+ });
88
+ const extraKey = ((_a = this.args.find((arg) => arg.extras)) == null ? void 0 : _a.name) || "_extra";
89
+ parsed[extraKey] = extras;
90
+ return parsed;
91
+ }
92
+ /**
93
+ * Create help message from the provided description & argument list.
94
+ *
95
+ * @returns {string} Help message
96
+ * @param opts Help options: command - display a commands help, message - override help description
97
+ */
98
+ help(opts = {}) {
99
+ const spacer = (text) => Array(24 - text.length || 1).fill(" ").join("");
100
+ if (opts.command) {
101
+ const argParser = this.commands.find((parser) => parser.name == opts.command);
102
+ if (!argParser) throw new Error(`${opts.command.toUpperCase()} is not a command`);
103
+ return argParser.help({ ...opts, command: void 0 });
104
+ }
105
+ let msg = `
106
+
107
+ ${opts.message || this.desc}`;
108
+ msg += "\n\nUsage: " + this.examples.map((ex) => `run ${this.name} ${ex}`).join("\n ");
109
+ if (this.args.length) msg += "\n\n " + this.args.map((arg) => `${arg.name.toUpperCase()}${spacer(arg.name)}${arg.desc}`).join("\n ");
110
+ msg += "\n\nOptions:\n " + this.flags.map((flag) => {
111
+ var _a;
112
+ const flags = ((_a = flag.flags) == null ? void 0 : _a.join(", ")) || "";
113
+ return `${flags}${spacer(flags)}${flag.desc}`;
114
+ }).join("\n ");
115
+ if (this.commands.length) msg += "\n\nCommands:\n " + this.commands.map((command) => `${command.name}${spacer(command.name)}${command.desc}`).join("\n ");
116
+ return `${msg}
117
+
118
+ `;
119
+ }
120
+ }
8
121
  function clean(obj, undefinedOnly = false) {
9
122
  if (obj == null) throw new Error("Cannot clean a NULL value");
10
123
  if (Array.isArray(obj)) {
@@ -110,6 +223,10 @@ var __publicField = (obj, key, value2) => __defNormalProp(obj, typeof key !== "s
110
223
  return json;
111
224
  }
112
225
  }
226
+ function JSONSerialize(obj) {
227
+ if (typeof obj == "object" && obj != null) return JSONSanitize(obj);
228
+ return obj;
229
+ }
113
230
  function JSONSanitize(obj, space) {
114
231
  return JSON.stringify(obj, (key, value2) => {
115
232
  return value2;
@@ -1537,6 +1654,7 @@ var __publicField = (obj, key, value2) => __defNormalProp(obj, typeof key !== "s
1537
1654
  return Object.keys({});
1538
1655
  }
1539
1656
  exports.ASet = ASet;
1657
+ exports.ArgParser = ArgParser;
1540
1658
  exports.BadGatewayError = BadGatewayError;
1541
1659
  exports.BadRequestError = BadRequestError;
1542
1660
  exports.CHAR_LIST = CHAR_LIST;
@@ -1551,6 +1669,7 @@ var __publicField = (obj, key, value2) => __defNormalProp(obj, typeof key !== "s
1551
1669
  exports.InternalServerError = InternalServerError;
1552
1670
  exports.JSONAttemptParse = JSONAttemptParse;
1553
1671
  exports.JSONSanitize = JSONSanitize;
1672
+ exports.JSONSerialize = JSONSerialize;
1554
1673
  exports.LETTER_LIST = LETTER_LIST;
1555
1674
  exports.LOG_LEVEL = LOG_LEVEL;
1556
1675
  exports.Logger = Logger;