@clo4/cli 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,519 @@
1
+ // \0rolldown/runtime.js
2
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod, mod.exports), cb = null), mod.exports);
3
+ // src/util.ts
4
+ function isArray(o) {
5
+ return Array.isArray(o);
6
+ }
7
+ /** Convert the value, if any, to an array with 0 or more elements */
8
+ function makeArray(thing) {
9
+ if (thing === void 0) return [];
10
+ if (isArray(thing)) return thing.slice();
11
+ return [thing];
12
+ }
13
+ function assert(expr, msg = "") {
14
+ if (!expr) throw new Error(msg);
15
+ }
16
+ (/* @__PURE__ */ __commonJSMin(((exports) => {
17
+ exports.__esModule = true;
18
+ exports.distance = exports.closest = void 0;
19
+ var peq = /* @__PURE__ */ new Uint32Array(65536);
20
+ var myers_32 = function(a, b) {
21
+ var n = a.length;
22
+ var m = b.length;
23
+ var lst = 1 << n - 1;
24
+ var pv = -1;
25
+ var mv = 0;
26
+ var sc = n;
27
+ var i = n;
28
+ while (i--) peq[a.charCodeAt(i)] |= 1 << i;
29
+ for (i = 0; i < m; i++) {
30
+ var eq = peq[b.charCodeAt(i)];
31
+ var xv = eq | mv;
32
+ eq |= (eq & pv) + pv ^ pv;
33
+ mv |= ~(eq | pv);
34
+ pv &= eq;
35
+ if (mv & lst) sc++;
36
+ if (pv & lst) sc--;
37
+ mv = mv << 1 | 1;
38
+ pv = pv << 1 | ~(xv | mv);
39
+ mv &= xv;
40
+ }
41
+ i = n;
42
+ while (i--) peq[a.charCodeAt(i)] = 0;
43
+ return sc;
44
+ };
45
+ var myers_x = function(b, a) {
46
+ var n = a.length;
47
+ var m = b.length;
48
+ var mhc = [];
49
+ var phc = [];
50
+ var hsize = Math.ceil(n / 32);
51
+ var vsize = Math.ceil(m / 32);
52
+ for (var i = 0; i < hsize; i++) {
53
+ phc[i] = -1;
54
+ mhc[i] = 0;
55
+ }
56
+ var j = 0;
57
+ for (; j < vsize - 1; j++) {
58
+ var mv_1 = 0;
59
+ var pv_1 = -1;
60
+ var start_1 = j * 32;
61
+ var vlen_1 = Math.min(32, m) + start_1;
62
+ for (var k = start_1; k < vlen_1; k++) peq[b.charCodeAt(k)] |= 1 << k;
63
+ for (var i = 0; i < n; i++) {
64
+ var eq = peq[a.charCodeAt(i)];
65
+ var pb = phc[i / 32 | 0] >>> i & 1;
66
+ var mb = mhc[i / 32 | 0] >>> i & 1;
67
+ var xv = eq | mv_1;
68
+ var xh = ((eq | mb) & pv_1) + pv_1 ^ pv_1 | eq | mb;
69
+ var ph = mv_1 | ~(xh | pv_1);
70
+ var mh = pv_1 & xh;
71
+ if (ph >>> 31 ^ pb) phc[i / 32 | 0] ^= 1 << i;
72
+ if (mh >>> 31 ^ mb) mhc[i / 32 | 0] ^= 1 << i;
73
+ ph = ph << 1 | pb;
74
+ mh = mh << 1 | mb;
75
+ pv_1 = mh | ~(xv | ph);
76
+ mv_1 = ph & xv;
77
+ }
78
+ for (var k = start_1; k < vlen_1; k++) peq[b.charCodeAt(k)] = 0;
79
+ }
80
+ var mv = 0;
81
+ var pv = -1;
82
+ var start = j * 32;
83
+ var vlen = Math.min(32, m - start) + start;
84
+ for (var k = start; k < vlen; k++) peq[b.charCodeAt(k)] |= 1 << k;
85
+ var score = m;
86
+ for (var i = 0; i < n; i++) {
87
+ var eq = peq[a.charCodeAt(i)];
88
+ var pb = phc[i / 32 | 0] >>> i & 1;
89
+ var mb = mhc[i / 32 | 0] >>> i & 1;
90
+ var xv = eq | mv;
91
+ var xh = ((eq | mb) & pv) + pv ^ pv | eq | mb;
92
+ var ph = mv | ~(xh | pv);
93
+ var mh = pv & xh;
94
+ score += ph >>> m - 1 & 1;
95
+ score -= mh >>> m - 1 & 1;
96
+ if (ph >>> 31 ^ pb) phc[i / 32 | 0] ^= 1 << i;
97
+ if (mh >>> 31 ^ mb) mhc[i / 32 | 0] ^= 1 << i;
98
+ ph = ph << 1 | pb;
99
+ mh = mh << 1 | mb;
100
+ pv = mh | ~(xv | ph);
101
+ mv = ph & xv;
102
+ }
103
+ for (var k = start; k < vlen; k++) peq[b.charCodeAt(k)] = 0;
104
+ return score;
105
+ };
106
+ var distance = function(a, b) {
107
+ if (a.length < b.length) {
108
+ var tmp = b;
109
+ b = a;
110
+ a = tmp;
111
+ }
112
+ if (b.length === 0) return a.length;
113
+ if (a.length <= 32) return myers_32(a, b);
114
+ return myers_x(a, b);
115
+ };
116
+ exports.distance = distance;
117
+ var closest = function(str, arr) {
118
+ var min_distance = Infinity;
119
+ var min_index = 0;
120
+ for (var i = 0; i < arr.length; i++) {
121
+ var dist = distance(str, arr[i]);
122
+ if (dist < min_distance) {
123
+ min_distance = dist;
124
+ min_index = i;
125
+ }
126
+ }
127
+ return arr[min_index];
128
+ };
129
+ exports.closest = closest;
130
+ })))();
131
+ // src/parse.ts
132
+ /**
133
+ * Returns the minimum number of arguments that satisfies the args.
134
+ *
135
+ * Accepts the raw spec value (a single arg, an array, or `undefined`) so the
136
+ * hot path doesn't have to copy it into an array first.
137
+ */
138
+ function getMinArgs(args) {
139
+ if (args === void 0) return 0;
140
+ if (!isArray(args)) return args.isOptional ? 0 : 1;
141
+ let count = 0;
142
+ for (let i = 0; i < args.length; i++) {
143
+ if (args[i].isOptional) break;
144
+ count++;
145
+ }
146
+ return count;
147
+ }
148
+ /** Returns the maximum number of arguments that satisfies the args. */
149
+ function getMaxArgs(args) {
150
+ if (args === void 0) return 0;
151
+ if (!isArray(args)) return args.isVariadic ? Infinity : 1;
152
+ for (let i = 0; i < args.length; i++) if (args[args.length - 1 - i].isVariadic) return Infinity;
153
+ return args.length;
154
+ }
155
+ // src/testing.ts
156
+ const repr = JSON.stringify;
157
+ /**
158
+ * Run a function once for each `args` property in the spec (recursive)
159
+ *
160
+ * This will convert single args to an array with one item.
161
+ */
162
+ function forEachArgArray(spec, fn, path = []) {
163
+ path = path.concat(spec);
164
+ fn(makeArray(spec.args), path);
165
+ for (const option of makeArray(spec.options)) fn(makeArray(option.args), path);
166
+ for (const subcommand of makeArray(spec.subcommands)) forEachArgArray(subcommand, fn, path);
167
+ }
168
+ /** Run a function once for each `options` property in the spec (recursive) */
169
+ function forEachOptionArray(spec, fn, path = []) {
170
+ path = path.concat(spec);
171
+ fn(makeArray(spec.options), path);
172
+ for (const subcommand of makeArray(spec.subcommands)) forEachOptionArray(subcommand, fn, path);
173
+ }
174
+ /**
175
+ * Run a function once for each `subcommands` property in the spec (recursive)
176
+ *
177
+ * This will also run the function for the root spec itself.
178
+ */
179
+ function forEachSubcommand(spec, fn, path = []) {
180
+ path = path.concat(spec);
181
+ fn(spec, path);
182
+ for (const subcommand of makeArray(spec.subcommands)) forEachSubcommand(subcommand, fn, path);
183
+ }
184
+ function joinNames(names) {
185
+ return makeArray(names).sort((a, b) => a.length - b.length).join("|");
186
+ }
187
+ function namedArrayToString(...parts) {
188
+ return `\`${parts.map((named) => joinNames(named.name)).join(" ")}\``;
189
+ }
190
+ /** Asserts that required arguments do not come after an optional argument */
191
+ function assertRequiredArgumentsDoNotFollowOptionalArguments(spec) {
192
+ forEachArgArray(spec, (args, path) => {
193
+ let remainingMustBeOptional = false;
194
+ let firstOptionalArgIndex = null;
195
+ for (const [index, arg] of args.entries()) if (remainingMustBeOptional) assert(arg.isOptional, `In ${namedArrayToString(...path)}, argument ${arg.name || index} is required, but it must be optional since the argument at index ${firstOptionalArgIndex} is optional`);
196
+ else if (arg.isOptional) {
197
+ remainingMustBeOptional = true;
198
+ firstOptionalArgIndex ??= index;
199
+ }
200
+ });
201
+ }
202
+ /** Asserts that options with `isRepeatable: true` don't have arguments */
203
+ function assertRepeatableOptionsHaveNoArguments(spec) {
204
+ forEachOptionArray(spec, (options, path) => {
205
+ for (const [index, option] of options.entries()) assert(!(option.args && option.isRepeatable), `The option ${namedArrayToString(...path, option)} (index ${index}) has arguments and is repeatable. Repeatable options cannot have arguments, but you can use a variadic argument instead.`);
206
+ });
207
+ }
208
+ /** Asserts that `isRepeatable` is only assigned a positive integer */
209
+ function assertRepeatableOptionsArePositiveIntegers(spec) {
210
+ forEachOptionArray(spec, (options, path) => {
211
+ for (const [index, option] of options.entries()) if (typeof option.isRepeatable === "number") {
212
+ assert(Number.isSafeInteger(option.isRepeatable), `The option ${namedArrayToString(...path, option)} (index ${index}) has its \`isRepeatable\` value set to a number that is not an integer`);
213
+ assert(!(option.isRepeatable < 1), `The option ${namedArrayToString(...path, option)} (index ${index}) has its \`isRepeatable\` value set to a number below 1, which means it can't be used at all`);
214
+ assert(option.isRepeatable !== 1, `The option ${namedArrayToString(...path, option)} (index ${index}) has its \`isRepeatable\` value set to 1, which is no different that omitting the property entirely`);
215
+ }
216
+ });
217
+ }
218
+ /** Asserts that options have unique names in their scope */
219
+ function assertOptionsHaveLocallyUniqueNames(spec) {
220
+ forEachSubcommand(spec, (spec, path) => {
221
+ const optionNames = /* @__PURE__ */ new Set();
222
+ for (const [index, option] of makeArray(spec.options).entries()) for (const name of makeArray(option.name)) {
223
+ assert(!optionNames.has(name), `Option ${namedArrayToString(...path, option)} (index ${index}) has a non-unique name, '${name}'. Option names must be unique.`);
224
+ optionNames.add(name);
225
+ }
226
+ });
227
+ }
228
+ /** Asserts that options don't shadow a persistent option */
229
+ function assertOptionsDoNotShadowPersistentOptions(spec) {
230
+ forEachOptionArray(spec, (options, path) => {
231
+ const persistentOptionNames = new Set(path.slice(0, -1).flatMap((subcommand) => subcommand.options ? subcommand.options.filter((option) => option.isPersistent).flatMap((option) => option.name) : []));
232
+ for (const [index, option] of makeArray(options).entries()) for (const name of makeArray(option.name)) assert(!persistentOptionNames.has(name), `The option ${namedArrayToString(...path, option)} (index ${index}) shadows the name of a persistent option, ${repr(name)}. Option names can't shadow persistent options.`);
233
+ });
234
+ }
235
+ /** Asserts that subcommands don't share a name with a sibling subcommand */
236
+ function assertSubcommandsHaveLocallyUniqueNames(spec) {
237
+ forEachSubcommand(spec, (spec, path) => {
238
+ const names = /* @__PURE__ */ new Set();
239
+ for (const [index, subcommand] of makeArray(spec.subcommands).entries()) for (const name of makeArray(subcommand.name)) {
240
+ assert(!names.has(name), `The subcommand ${namedArrayToString(...path, subcommand)} (index ${index}) has a non-unique name, ${repr(name)}. Subcommand names must be unique among the subcommands in the same array.`);
241
+ names.add(name);
242
+ }
243
+ });
244
+ }
245
+ /**
246
+ * Asserts that option names starting with a single dash aren't longer
247
+ * than two characters, unless parserDirectives.flagsArePosixNoncompliant is
248
+ * set on an ancestor command.
249
+ */
250
+ function assertLongOptionNamesDoNotStartWithSingleDash(spec) {
251
+ forEachOptionArray(spec, (options, path) => {
252
+ if (path.map((command) => command.parserDirectives?.flagsArePosixNoncompliant).filter((value) => value !== void 0).at(-1) || false) return;
253
+ for (const [index, option] of makeArray(options).entries()) for (const name of makeArray(option.name)) assert(!((name.startsWith("-") || name.startsWith("+")) && !name.startsWith("--") && name.length > 2), `Option ${namedArrayToString(...path, option)} (index ${index}) has a name that the parser is unable to parse, as it starts with a single '${name[0]}'. Tokens starting with that character are interpreted as short options, so passing '${name}' will be interpreted as '${Array.from(name.slice(1), (letter) => name[0] + letter).join(" ")}'. \`parserDirectives.flagsArePosixNoncompliant\` must be \`true\` on an ancestor command.`);
254
+ });
255
+ }
256
+ /**
257
+ * Asserts that all option names start with dashes
258
+ */
259
+ function assertOptionNamesStartWithDashes(spec) {
260
+ forEachOptionArray(spec, (options, path) => {
261
+ if (path.map((command) => command.parserDirectives?.flagsArePosixNoncompliant).filter((value) => value !== void 0).at(-1) || false) return;
262
+ for (const [index, option] of makeArray(options).entries()) for (const name of makeArray(option.name)) assert(name.startsWith("-") || name.startsWith("+"), `Option ${namedArrayToString(...path, option)} (index ${index}) doesn't start with a dash or plus, the parser will be unable to find matching options without \`parserDirectives.flagsAreNonPosixCompliant\` being set to 'true' on an ancestor command`);
263
+ });
264
+ }
265
+ /**
266
+ * Asserts that nothing is named exactly '--'
267
+ */
268
+ function assertNothingIsNamedDashDash(spec) {
269
+ forEachOptionArray(spec, (options, path) => {
270
+ for (const [index, option] of makeArray(options).entries()) for (const name of makeArray(option.name)) assert(name !== "--", `Option ${namedArrayToString(...path, option)} (index ${index}) is named '--', which is a special instruction to the parser to treat all following tokens as arguments. This will never be matched`);
271
+ });
272
+ forEachSubcommand(spec, (subcommands, path) => {
273
+ for (const [index, subcommand] of makeArray(subcommands).entries()) for (const name of makeArray(subcommand.name)) assert(name !== "--", `Subcommand ${namedArrayToString(...path, subcommand)} (index ${index}) is named '--', which is a special instruction to the parser to treat all following tokens as arguments. This will never be matched`);
274
+ });
275
+ }
276
+ /**
277
+ * Asserts that no option arg separator is an empty string
278
+ */
279
+ function assertOptionArgSeparatorsHaveCharacters(spec) {
280
+ forEachSubcommand(spec, (subcommands, path) => {
281
+ for (const [index, subcommand] of makeArray(subcommands).entries()) {
282
+ const separators = makeArray(subcommand.parserDirectives?.optionArgSeparators);
283
+ for (const [sepIndex, separator] of separators.entries()) assert(separator !== "", `Subcommand ${namedArrayToString(...path, subcommand)} (index ${index}) has an empty string for an option arg separator at index ${sepIndex}. If you wanted to disable option arg separators, use an empty array.`);
284
+ }
285
+ });
286
+ }
287
+ /**
288
+ * Asserts that options named "+" or "-" takes one arg
289
+ */
290
+ function assertPlusMinusOptionsTakeOneArg(spec) {
291
+ forEachOptionArray(spec, (options, path) => {
292
+ if (path.map((command) => command.parserDirectives?.flagsArePosixNoncompliant).filter((value) => value !== void 0).at(-1) || false) return;
293
+ for (const [index, option] of makeArray(options).entries()) for (const name of makeArray(option.name)) {
294
+ if (name !== "-" && name !== "+") continue;
295
+ assert(option.args && !Array.isArray(option.args), `Option ${namedArrayToString(...path, option)} (index ${index}) must take exactly one argument`);
296
+ }
297
+ });
298
+ }
299
+ /**
300
+ * Asserts that names do not have leading or trailing whitespace
301
+ */
302
+ function assertNamesHaveNoExtraWhitespace(spec) {
303
+ forEachOptionArray(spec, (options, path) => {
304
+ for (const [index, option] of makeArray(options).entries()) for (const name of makeArray(option.name)) assert(name === name.trim(), `Option ${namedArrayToString(...path, option)} (index ${index}) has a name with extra whitespace`);
305
+ });
306
+ forEachSubcommand(spec, (subcommands, path) => {
307
+ for (const [index, subcommand] of makeArray(subcommands).entries()) for (const name of makeArray(subcommand.name)) assert(name === name.trim(), `Subcommand ${namedArrayToString(...path, subcommand)} (index ${index}) has a name with extra whitespace`);
308
+ });
309
+ forEachArgArray(spec, (args, path) => {
310
+ for (const [index, arg] of makeArray(args).entries()) for (const name of makeArray(arg.name)) assert(name === name.trim(), `Arg in ${namedArrayToString(...path)} (at index ${index}) has a name with extra whitespace`);
311
+ });
312
+ }
313
+ /**
314
+ * Asserts that everything has a description
315
+ */
316
+ function assertEverythingHasDescription(spec) {
317
+ assert(spec.description, `Spec has no description`);
318
+ forEachOptionArray(spec, (options, path) => {
319
+ for (const [index, option] of makeArray(options).entries()) assert(option.description, `Option ${namedArrayToString(...path, option)} (index ${index}) has no description`);
320
+ });
321
+ forEachSubcommand(spec, (subcommands, path) => {
322
+ for (const [index, subcommand] of makeArray(subcommands).entries()) assert(subcommand.description, `Subcommand ${namedArrayToString(...path, subcommand)} (index ${index}) has no description`);
323
+ });
324
+ }
325
+ /**
326
+ * Asserts that descriptions have line length < 69
327
+ */
328
+ function assertDescriptionLineLengthUnder69(spec) {
329
+ if (spec.description) assert(spec.description.split("\n").every((line) => line.length <= 68), `Spec has a description line over 68 characters`);
330
+ forEachOptionArray(spec, (options, path) => {
331
+ for (const [index, option] of makeArray(options).entries()) if (option.description) assert(option.description.split("\n").every((line) => line.length <= 68), `Option ${namedArrayToString(...path, option)} (index ${index}) has a description line over 68 characters`);
332
+ });
333
+ forEachSubcommand(spec, (subcommands, path) => {
334
+ for (const [index, subcommand] of makeArray(subcommands).entries()) if (subcommand.description) assert(subcommand.description.split("\n").every((line) => line.length <= 68), `Subcommand ${namedArrayToString(...path, subcommand)} (index ${index}) has a description line over 68 characters`);
335
+ });
336
+ }
337
+ function assertRequiresSeparatorTakesOneArg(spec) {
338
+ forEachOptionArray(spec, (options, path) => {
339
+ for (const [index, option] of makeArray(options).entries()) if (option.requiresSeparator) {
340
+ const args = makeArray(option.args);
341
+ assert(getMinArgs(args) <= 1, `Option ${namedArrayToString(...path, option)} (index ${index}) takes a minimum of ${getMinArgs(args)} arg(s), but because of requiresSeparator, it must instead be 0 or 1`);
342
+ assert(getMaxArgs(args) === 1, `Option ${namedArrayToString(...path, option)} (index ${index}) takes a maximum of ${getMaxArgs(args)} arg(s), but because of requiresSeparator, it's only able to take 1`);
343
+ }
344
+ });
345
+ }
346
+ function assertCommonOptionsArePersistent(spec) {
347
+ const isSameName = (a, b) => {
348
+ if (isArray(a) && isArray(b)) return a.every((item) => b.includes(item)) && b.every((item) => a.includes(item));
349
+ return a === b;
350
+ };
351
+ const failures = [];
352
+ forEachSubcommand(spec, (subcommand, path) => {
353
+ if (!subcommand.subcommands) return;
354
+ for (const option of makeArray(subcommand.options)) {
355
+ const allChildSubcommands = [];
356
+ forEachSubcommand(subcommand, (cmd) => allChildSubcommands.push(cmd));
357
+ if (allChildSubcommands.every((cmd) => makeArray(cmd.options).some((o) => isSameName(option.name, o.name))) && !failures.some(([name]) => isSameName(name, option.name))) failures.push([option.name, namedArrayToString(...path, option)]);
358
+ }
359
+ });
360
+ assert(failures.length === 0, `The following options were also defined by all subcommands. Instead, define the option once, and use \`isPersistent: true\` to persist it across all subcommands.
361
+ ${failures.map(([, line]) => " * " + line).join("\n")}
362
+ `);
363
+ }
364
+ /**
365
+ * Asserts that references to other options by name actually refer to options
366
+ * that exist in scope
367
+ */
368
+ function assertOptionNameReferencesExist(spec) {
369
+ forEachOptionArray(spec, (options, path) => {
370
+ const optionNames = /* @__PURE__ */ new Set([...path.slice(0, -1).flatMap((subcommand) => subcommand.options ? subcommand.options.filter((option) => option.isPersistent).flatMap((option) => option.name) : []), ...options.flatMap((option) => option.name)]);
371
+ for (const [index, option] of makeArray(options).entries()) {
372
+ for (const name of makeArray(option.dependsOn)) assert(optionNames.has(name), `The option ${namedArrayToString(...path, option)} (index ${index}) depends on an option named ${repr(name)}, which doesn't exist in its scope`);
373
+ for (const name of makeArray(option.exclusiveOn)) assert(optionNames.has(name), `The option ${namedArrayToString(...path, option)} (index ${index}) is exclusive on an option named ${repr(name)}, which doesn't exist in its scope`);
374
+ }
375
+ });
376
+ }
377
+ /**
378
+ * Asserts that commands that will match subcommands by prefix do not take arguments
379
+ */
380
+ function assertPrefixMatchCommandsHaveNoArguments(spec) {
381
+ forEachSubcommand(spec, (subcommand, path) => {
382
+ if (!path.some((cmd) => cmd.parserDirectives?.subcommandsMatchUniquePrefix === true)) return;
383
+ assert(!(subcommand.subcommands && subcommand.args), `The command ${namedArrayToString(...path)} has at least one argument and subcommand, but matches subcommands based on unique prefixes. To fix this, use \`parserDirectives: { subcommandsMatchUniquePrefix: false }\``);
384
+ });
385
+ }
386
+ function getName(namingStyle, names) {
387
+ return names[namingStyle];
388
+ }
389
+ async function runStep(context, name, fn) {
390
+ if (context) {
391
+ await context.step(name, fn);
392
+ return;
393
+ }
394
+ await fn();
395
+ }
396
+ /**
397
+ * Validate your CLI in your test suite
398
+ *
399
+ * This enforces certain constraints that the type system cannot. The parser
400
+ * may ignore these issues, producing correct output that _appears_ to be
401
+ * wrong.
402
+ */
403
+ function test(spec, options = {}) {
404
+ const { allowShadowingPersistentOptions = false, allowNoDescription = false, allowLongDescriptionLines = false, allowMatchingSubcommandPrefixAndArgs = false, namingStyle = "sentence" } = options;
405
+ return async (t) => {
406
+ await runStep(t, getName(namingStyle, {
407
+ sentence: "Required arguments don't follow optional arguments",
408
+ function: "assertRequiredArgumentsDoNotFollowOptionalArguments"
409
+ }), () => {
410
+ assertRequiredArgumentsDoNotFollowOptionalArguments(spec);
411
+ });
412
+ await runStep(t, getName(namingStyle, {
413
+ sentence: "Repeatable options don't have arguments",
414
+ function: "assertRepeatableOptionsHaveNoArguments"
415
+ }), () => {
416
+ assertRepeatableOptionsHaveNoArguments(spec);
417
+ });
418
+ await runStep(t, getName(namingStyle, {
419
+ sentence: "Repeatable options that are numbers are integers greater than 1",
420
+ function: "assertRepeatableOptionsArePositiveIntegers"
421
+ }), () => {
422
+ assertRepeatableOptionsArePositiveIntegers(spec);
423
+ });
424
+ await runStep(t, getName(namingStyle, {
425
+ sentence: "Long option names don't start with a single dash",
426
+ function: "assertLongOptionNamesDoNotStartWithSingleDash"
427
+ }), () => {
428
+ assertLongOptionNamesDoNotStartWithSingleDash(spec);
429
+ });
430
+ await runStep(t, getName(namingStyle, {
431
+ sentence: "Option names all start with dashes",
432
+ function: "assertOptionNamesStartWithDashes"
433
+ }), () => {
434
+ assertOptionNamesStartWithDashes(spec);
435
+ });
436
+ await runStep(t, getName(namingStyle, {
437
+ sentence: "Options have locally unique names",
438
+ function: "assertOptionsHaveLocallyUniqueNames"
439
+ }), () => {
440
+ assertOptionsHaveLocallyUniqueNames(spec);
441
+ });
442
+ if (!allowShadowingPersistentOptions) await runStep(t, getName(namingStyle, {
443
+ sentence: "Options don't shadow persistent options",
444
+ function: "assertOptionsDoNotShadowPersistentOptions"
445
+ }), () => {
446
+ assertOptionsDoNotShadowPersistentOptions(spec);
447
+ });
448
+ await runStep(t, getName(namingStyle, {
449
+ sentence: "Subcommands have locally unique names",
450
+ function: "assertSubcommandsHaveLocallyUniqueNames"
451
+ }), () => {
452
+ assertSubcommandsHaveLocallyUniqueNames(spec);
453
+ });
454
+ await runStep(t, getName(namingStyle, {
455
+ sentence: "Nothing is named '--'",
456
+ function: "assertNothingIsNamedDashDash"
457
+ }), () => {
458
+ assertNothingIsNamedDashDash(spec);
459
+ });
460
+ await runStep(t, getName(namingStyle, {
461
+ sentence: "Option arg separators are not an empty string",
462
+ function: "assertOptionArgSeparatorsHaveCharacters"
463
+ }), () => {
464
+ assertOptionArgSeparatorsHaveCharacters(spec);
465
+ });
466
+ await runStep(t, getName(namingStyle, {
467
+ sentence: "Options named '-' or '+' take exactly one argument",
468
+ function: "assertPlusMinusOptionsTakeOneArg"
469
+ }), () => {
470
+ assertPlusMinusOptionsTakeOneArg(spec);
471
+ });
472
+ await runStep(t, getName(namingStyle, {
473
+ sentence: "Names have no extra leading or trailing whitespace",
474
+ function: "assertNamesHaveNoExtraWhitespace"
475
+ }), () => {
476
+ assertNamesHaveNoExtraWhitespace(spec);
477
+ });
478
+ if (!allowNoDescription) await runStep(t, getName(namingStyle, {
479
+ sentence: "Everything has a description",
480
+ function: "assertEverythingHasDescription"
481
+ }), () => {
482
+ assertEverythingHasDescription(spec);
483
+ });
484
+ if (!allowLongDescriptionLines) await runStep(t, getName(namingStyle, {
485
+ sentence: "Each line in descriptions is less than or equal to 68 characters",
486
+ function: "assertDescriptionLineLengthUnder69"
487
+ }), () => {
488
+ assertDescriptionLineLengthUnder69(spec);
489
+ });
490
+ await runStep(t, getName(namingStyle, {
491
+ sentence: "Options with `requiresSeparator` take exactly one argument",
492
+ function: "assertRequiresSeparatorTakesOneArg"
493
+ }), () => {
494
+ assertRequiresSeparatorTakesOneArg(spec);
495
+ });
496
+ await runStep(t, getName(namingStyle, {
497
+ sentence: "Common options are not defined on every subcommand",
498
+ function: "assertCommonOptionsArePersistent"
499
+ }), () => {
500
+ assertCommonOptionsArePersistent(spec);
501
+ });
502
+ await runStep(t, getName(namingStyle, {
503
+ sentence: "References to other options by name are valid",
504
+ function: "assertOptionNameReferencesExist"
505
+ }), () => {
506
+ assertOptionNameReferencesExist(spec);
507
+ });
508
+ if (!allowMatchingSubcommandPrefixAndArgs) await runStep(t, getName(namingStyle, {
509
+ sentence: "Commands with `subcommandsMatchUniquePrefix` don't have arguments and subcommands",
510
+ function: "assertPrefixMatchCommandsHaveNoArguments"
511
+ }), () => {
512
+ assertPrefixMatchCommandsHaveNoArguments(spec);
513
+ });
514
+ };
515
+ }
516
+ const testSpec = test;
517
+ export { assertCommonOptionsArePersistent, assertDescriptionLineLengthUnder69, assertEverythingHasDescription, assertLongOptionNamesDoNotStartWithSingleDash, assertNamesHaveNoExtraWhitespace, assertNothingIsNamedDashDash, assertOptionArgSeparatorsHaveCharacters, assertOptionNameReferencesExist, assertOptionNamesStartWithDashes, assertOptionsDoNotShadowPersistentOptions, assertOptionsHaveLocallyUniqueNames, assertPlusMinusOptionsTakeOneArg, assertPrefixMatchCommandsHaveNoArguments, assertRepeatableOptionsArePositiveIntegers, assertRepeatableOptionsHaveNoArguments, assertRequiredArgumentsDoNotFollowOptionalArguments, assertRequiresSeparatorTakesOneArg, assertSubcommandsHaveLocallyUniqueNames, test, testSpec };
518
+
519
+ //# sourceMappingURL=testing.js.map