termkit 1.7.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,438 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Command: () => Command,
34
+ Option: () => Option,
35
+ Termkit: () => Termkit,
36
+ Variable: () => Variable,
37
+ command: () => command,
38
+ middleware: () => middleware,
39
+ option: () => option,
40
+ parse: () => parse,
41
+ setDefaults: () => setDefaults
42
+ });
43
+ module.exports = __toCommonJS(index_exports);
44
+
45
+ // src/models/Command.ts
46
+ var import_cosmetic = __toESM(require("cosmetic"));
47
+
48
+ // src/helpers/findCommand.ts
49
+ function findCommand(array, commands) {
50
+ for (const command2 of commands) {
51
+ if (array[0] === command2.name) {
52
+ array.shift();
53
+ return command2;
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+
59
+ // src/helpers/findVariable.ts
60
+ function coerce(value, type) {
61
+ if (type === "number") return Number(value);
62
+ if (type === "boolean") return value === "true";
63
+ return value;
64
+ }
65
+ function findVariable(array, variable, commands) {
66
+ if (variable.array) {
67
+ const result = [];
68
+ while (array.length > 0 && !array[0].startsWith("-")) {
69
+ if (commands.includes(array[0])) break;
70
+ result.push(coerce(array.shift(), variable.type));
71
+ }
72
+ if (result.length === 0 && variable.required) throw new Error(`Missing required variable <${variable.name}>`);
73
+ return result.length > 0 ? result : true;
74
+ }
75
+ if (array.length > 0 && !array[0].startsWith("-")) {
76
+ if ((!commands.includes(array[0]) || variable.required) && array[0] !== "help") {
77
+ return coerce(array.shift(), variable.type);
78
+ }
79
+ }
80
+ if (variable.required) throw new Error(`Missing required variable <${variable.name}>`);
81
+ return true;
82
+ }
83
+
84
+ // src/helpers/findCommandVariables.ts
85
+ function findCommandVariables(array, command2) {
86
+ if (!command2.variables) return null;
87
+ const result = {};
88
+ for (const variable of command2.variables) {
89
+ const value = findVariable(array, variable, command2.commandStrings);
90
+ if (value !== true) result[variable.name] = value;
91
+ }
92
+ return Object.keys(result).length > 0 ? result : null;
93
+ }
94
+
95
+ // src/helpers/findOption.ts
96
+ function findOption(string, options) {
97
+ return options.find((o) => o.short === string || o.long === string);
98
+ }
99
+
100
+ // src/helpers/findVariables.ts
101
+ function findVariables(base2, array, variables, commands) {
102
+ const result = {};
103
+ if (!variables) {
104
+ if (base2) result[base2] = true;
105
+ return result;
106
+ }
107
+ if (variables.length > 1 && base2) result[base2] = {};
108
+ for (const variable of variables) {
109
+ const value = findVariable(array, variable, commands);
110
+ if (variables.length > 1 && base2) {
111
+ ;
112
+ result[base2][variable.name] = value;
113
+ } else if (base2) {
114
+ result[base2] = value;
115
+ } else {
116
+ result[variable.name] = value;
117
+ }
118
+ }
119
+ return result;
120
+ }
121
+
122
+ // src/helpers/findOptions.ts
123
+ function findOptions(array, command2) {
124
+ const result = {};
125
+ while (array.length > 0 && array[0].startsWith("-")) {
126
+ if (array[0].startsWith("--")) {
127
+ const raw = array.shift().slice(2);
128
+ const option2 = findOption(raw, command2.optionsArray);
129
+ if (!option2) throw new Error(`Unknown Option: --${raw}`);
130
+ try {
131
+ Object.assign(result, findVariables(option2.long, array, option2.variables, command2.commandStrings));
132
+ } catch (err) {
133
+ ;
134
+ err.message += ` for --${option2.long}`;
135
+ throw err;
136
+ }
137
+ } else {
138
+ let string = array.shift();
139
+ const short = string.slice(1, 2);
140
+ const option2 = findOption(short, command2.optionsArray);
141
+ if (!option2) throw new Error(`Unknown Option: -${short}`);
142
+ string = string.replace(short, "");
143
+ if (string !== "-") array.unshift(string);
144
+ try {
145
+ Object.assign(result, findVariables(option2.long, array, option2.variables, command2.commandStrings));
146
+ } catch (err) {
147
+ ;
148
+ err.message += ` for --${option2.long}`;
149
+ throw err;
150
+ }
151
+ }
152
+ }
153
+ return result;
154
+ }
155
+
156
+ // src/models/Variable.ts
157
+ var Variable = class {
158
+ constructor(data) {
159
+ this.array = false;
160
+ this.name = null;
161
+ this.raw = null;
162
+ this.required = false;
163
+ this.type = "string";
164
+ this.value = null;
165
+ if (!data) return;
166
+ if (data.array) this.array = data.array;
167
+ if (data.name) this.name = data.name;
168
+ if (data.raw) this.raw = data.raw;
169
+ if (data.required) this.required = data.required;
170
+ if (data.type) this.type = data.type;
171
+ if (this.array) this.value = [];
172
+ }
173
+ };
174
+
175
+ // src/helpers/getVariables.ts
176
+ function parseName(raw) {
177
+ const colon = raw.indexOf(":");
178
+ if (colon === -1) return { name: raw, type: "string" };
179
+ return {
180
+ name: raw.slice(0, colon),
181
+ type: raw.slice(colon + 1)
182
+ };
183
+ }
184
+ function getVariables(string) {
185
+ const results = [];
186
+ for (const part of string.split(" ")) {
187
+ const trimmed = part.trim();
188
+ if (!trimmed) continue;
189
+ if (trimmed.startsWith("<") && trimmed.endsWith(">")) {
190
+ const { name, type } = parseName(trimmed.slice(1, -1));
191
+ results.push(new Variable({ name, raw: trimmed, required: true, type }));
192
+ } else if (trimmed.startsWith("[") && trimmed.endsWith("...]")) {
193
+ const { name, type } = parseName(trimmed.slice(1, -4));
194
+ results.push(new Variable({ array: true, name, raw: trimmed, type }));
195
+ } else if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
196
+ const { name, type } = parseName(trimmed.slice(1, -1));
197
+ results.push(new Variable({ name, raw: trimmed, type }));
198
+ } else {
199
+ throw new Error(`Unrecognized variable description: ${trimmed}`);
200
+ }
201
+ }
202
+ return results;
203
+ }
204
+
205
+ // src/models/Option.ts
206
+ var Option = class {
207
+ constructor(data) {
208
+ this.short = null;
209
+ this.long = null;
210
+ this.info = null;
211
+ this.variables = null;
212
+ if (!data) return;
213
+ if (data.short) this.short = data.short;
214
+ if (data.long) this.long = data.long;
215
+ if (data.info) this.info = data.info;
216
+ if (data.variables) this.variables = getVariables(data.variables);
217
+ }
218
+ description(info) {
219
+ this.info = info;
220
+ return this;
221
+ }
222
+ };
223
+
224
+ // src/models/Command.ts
225
+ var Command = class {
226
+ constructor(data) {
227
+ this.actionFunction = null;
228
+ this.commandsArray = [];
229
+ this.commandStrings = ["help"];
230
+ this.info = null;
231
+ this.middlewaresArray = [];
232
+ this.name = null;
233
+ this.optionsArray = [];
234
+ this.variables = null;
235
+ this.versionString = null;
236
+ if (!data) return;
237
+ if (data.info) this.info = data.info;
238
+ if (data.name) this.name = data.name;
239
+ if (data.variables) this.variables = getVariables(data.variables);
240
+ if (data.middlewares) this.middlewaresArray = [...data.middlewares];
241
+ if (data.options) this.optionsArray = [...data.options];
242
+ }
243
+ description(info) {
244
+ this.info = info;
245
+ return this;
246
+ }
247
+ variable(string) {
248
+ const vars = getVariables(string);
249
+ if (!this.variables) {
250
+ this.variables = vars;
251
+ } else {
252
+ this.variables.push(...vars);
253
+ }
254
+ return this;
255
+ }
256
+ action(fn) {
257
+ this.actionFunction = fn;
258
+ return this;
259
+ }
260
+ command(cmd) {
261
+ this.commandsArray.push(cmd);
262
+ return this;
263
+ }
264
+ commands(cmds) {
265
+ this.commandsArray = [...cmds];
266
+ for (const cmd of cmds) {
267
+ if (cmd.name) this.commandStrings.unshift(cmd.name);
268
+ }
269
+ return this;
270
+ }
271
+ middleware(fn) {
272
+ this.middlewaresArray.push(fn);
273
+ return this;
274
+ }
275
+ middlewares(fns) {
276
+ this.middlewaresArray.push(...fns);
277
+ return this;
278
+ }
279
+ option(short, long, variables, info) {
280
+ this.optionsArray.push(new Option({ short, long, variables, info }));
281
+ return this;
282
+ }
283
+ options(opts) {
284
+ this.optionsArray.push(...opts);
285
+ return this;
286
+ }
287
+ version(v) {
288
+ this.versionString = v;
289
+ return this;
290
+ }
291
+ help(_source) {
292
+ const table = [];
293
+ let program = this.name ?? "Program";
294
+ if (this.variables) for (const v of this.variables) program += ` ${v.raw}`;
295
+ if (this.optionsArray.length > 0) program += " [...options]";
296
+ table.push({ title: "\nCommand", info: program, data: [] });
297
+ if (this.versionString) table.push({ title: "Version", info: `v${this.versionString}`, data: [] });
298
+ if (this.info) table.push({ title: "Info", info: this.info, data: [] });
299
+ if (this.optionsArray.length > 0) {
300
+ const section = { title: "Options", data: [] };
301
+ for (const opt of this.optionsArray) {
302
+ let name = "";
303
+ if (opt.short) name = `-${opt.short}`;
304
+ if (opt.short && opt.long) name += ", ";
305
+ if (opt.long) name += `--${opt.long}`;
306
+ if (opt.variables) for (const v of opt.variables) name += ` ${v.raw}`;
307
+ section.data.push([name, opt.info ?? ""]);
308
+ }
309
+ table.push(section);
310
+ }
311
+ if (this.commandsArray.length > 0) {
312
+ const section = { title: "Subcommands", data: [] };
313
+ for (const cmd of this.commandsArray) {
314
+ let name = cmd.name ?? "";
315
+ if (cmd.variables) for (const v of cmd.variables) name += ` ${v.raw}`;
316
+ section.data.push([name, cmd.info ?? ""]);
317
+ }
318
+ table.push(section);
319
+ }
320
+ const padding = {};
321
+ for (const section of table) {
322
+ for (const row of section.data) {
323
+ for (const [i, s] of row.entries()) {
324
+ if (padding[i] === void 0 || s.length > padding[i]) padding[i] = s.length;
325
+ }
326
+ }
327
+ }
328
+ const lines = [];
329
+ for (const section of table) {
330
+ lines.push(section.title ? import_cosmetic.default.cyan.underline.encoder(section.title) : "");
331
+ if (section.info) lines.push(section.info);
332
+ for (const row of section.data) {
333
+ let line = "";
334
+ for (const [i, s] of row.entries()) {
335
+ const padded = padding[i] !== void 0 ? s.padEnd(padding[i]) : s;
336
+ line = line ? `${line} ${padded}` : padded;
337
+ }
338
+ lines.push(line);
339
+ }
340
+ lines.push("");
341
+ }
342
+ for (const line of lines) console.log(line);
343
+ }
344
+ async parse(input) {
345
+ const array = [...input];
346
+ array.splice(0, 2);
347
+ let command2 = this;
348
+ const options = { _source: Array.from(array) };
349
+ while (array.length) {
350
+ if (!array.includes("help")) {
351
+ Object.assign(options, findOptions(array, command2));
352
+ const cmdVars = findCommandVariables(array, command2);
353
+ if (cmdVars) Object.assign(options, cmdVars);
354
+ Object.assign(options, findOptions(array, command2));
355
+ }
356
+ if (array.length) {
357
+ if (!array.includes("help")) {
358
+ for (const mw of command2.middlewaresArray) await mw(options);
359
+ }
360
+ const next = findCommand(array, command2.commandsArray);
361
+ if (!next && array[0] === "help") return command2.help(options._source);
362
+ if (!next) throw new SyntaxError(`Unknown command: ${array[0]}`);
363
+ const name = command2.name ?? "_base";
364
+ if (!options._parents) options._parents = {};
365
+ options._parents[name] = {};
366
+ for (const key of Object.keys(options)) {
367
+ if (!key.startsWith("_")) {
368
+ options._parents[name][key] = options[key];
369
+ delete options[key];
370
+ }
371
+ }
372
+ command2 = next;
373
+ }
374
+ }
375
+ for (const mw of command2.middlewaresArray) await mw(options);
376
+ if (command2.actionFunction) return command2.actionFunction(options);
377
+ if (options._source.length === 2) return command2.help(options._source);
378
+ throw new Error(`No action for command: ${command2.name ?? "_base"}`);
379
+ }
380
+ };
381
+
382
+ // src/models/Termkit.ts
383
+ var _Termkit = class _Termkit {
384
+ static set defaults(obj) {
385
+ _Termkit.commandDefaults = obj;
386
+ }
387
+ static setDefaults(obj) {
388
+ _Termkit.commandDefaults = obj;
389
+ }
390
+ static command(name, variables, info) {
391
+ const cmd = new Command(Object.assign({ name, variables, info }, _Termkit.commandDefaults));
392
+ if (!_Termkit.base) _Termkit.base = cmd;
393
+ return cmd;
394
+ }
395
+ static middleware(action) {
396
+ return action;
397
+ }
398
+ static option(short, long, variables, info) {
399
+ return new Option({ short, long, variables, info });
400
+ }
401
+ static parse(arr) {
402
+ if (!_Termkit.base) throw new Error("No command defined");
403
+ return _Termkit.base.parse(arr);
404
+ }
405
+ };
406
+ _Termkit.base = null;
407
+ _Termkit.commandDefaults = {};
408
+ var Termkit = _Termkit;
409
+
410
+ // src/index.ts
411
+ var base = null;
412
+ var commandDefaults = {};
413
+ var command = (name, variables, info) => {
414
+ const cmd = new Command(Object.assign({ name, variables, info }, commandDefaults));
415
+ if (!base) base = cmd;
416
+ return cmd;
417
+ };
418
+ var middleware = (fn) => fn;
419
+ var option = (short, long, variables, info) => new Option({ short, long, variables, info });
420
+ var parse = (arr) => {
421
+ if (!base) throw new Error("No command defined");
422
+ return base.parse(arr);
423
+ };
424
+ var setDefaults = (data) => {
425
+ commandDefaults = data;
426
+ };
427
+ // Annotate the CommonJS export names for ESM import in node:
428
+ 0 && (module.exports = {
429
+ Command,
430
+ Option,
431
+ Termkit,
432
+ Variable,
433
+ command,
434
+ middleware,
435
+ option,
436
+ parse,
437
+ setDefaults
438
+ });