@clerc/parser 1.0.0-beta.24 → 1.0.0-beta.26
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.d.ts +14 -15
- package/dist/index.js +24 -26
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -2,16 +2,11 @@
|
|
|
2
2
|
declare class InvalidSchemaError extends Error {
|
|
3
3
|
constructor(message: string);
|
|
4
4
|
}
|
|
5
|
-
declare class MissingRequiredFlagError extends Error {
|
|
6
|
-
constructor(name: string);
|
|
7
|
-
}
|
|
8
5
|
//#endregion
|
|
9
6
|
//#region ../utils/src/types/type-fest.d.ts
|
|
10
7
|
type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
|
11
8
|
type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
12
|
-
|
|
13
|
-
//#region ../utils/src/types/index.d.ts
|
|
14
|
-
type MaybeArray<T> = T | T[];
|
|
9
|
+
type RequireExactlyOneOrNone<T, Keys extends keyof T = keyof T> = ({ [K in Keys]-?: Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, never>> }[Keys] & Omit<T, Keys>) | (Partial<Record<Keys, never>> & Omit<T, Keys>);
|
|
15
10
|
//#endregion
|
|
16
11
|
//#region src/iterator.d.ts
|
|
17
12
|
declare const KNOWN_FLAG = "known-flag";
|
|
@@ -47,20 +42,22 @@ interface TypeFunction<T = unknown> {
|
|
|
47
42
|
*/
|
|
48
43
|
type IgnoreFunction = (type: typeof KNOWN_FLAG | typeof UNKNOWN_FLAG | typeof PARAMETER, arg: string) => boolean;
|
|
49
44
|
type TypeValue<T = unknown> = TypeFunction<T> | readonly [TypeFunction<T>];
|
|
50
|
-
|
|
45
|
+
type Foo = RequireExactlyOneOrNone<{
|
|
46
|
+
/** The default value of the flag. */
|
|
47
|
+
default?: unknown;
|
|
48
|
+
/** Whether the flag is required. */
|
|
49
|
+
required?: boolean;
|
|
50
|
+
}, "default" | "required">;
|
|
51
|
+
type BaseFlagOptions<T extends TypeValue = TypeValue> = Foo & {
|
|
51
52
|
/**
|
|
52
53
|
* The type constructor or a function to convert the string value.
|
|
53
54
|
* To support multiple occurrences of a flag (e.g., --file a --file b), wrap the type in an array: [String], [Number].
|
|
54
55
|
* e.g., String, Number, [String], (val) => val.split(',')
|
|
55
56
|
*/
|
|
56
57
|
type: T;
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
default?: unknown;
|
|
61
|
-
/** Whether the flag is required. */
|
|
62
|
-
required?: boolean;
|
|
63
|
-
}
|
|
58
|
+
/** Short flag alias (single character). */
|
|
59
|
+
short?: string;
|
|
60
|
+
};
|
|
64
61
|
type FlagOptions = (BaseFlagOptions<BooleanConstructor> & {
|
|
65
62
|
/**
|
|
66
63
|
* Whether to enable the `--no-<flag>` syntax to set the value to false.
|
|
@@ -121,6 +118,8 @@ interface ParsedResult<TFlags extends Record<string, any>> {
|
|
|
121
118
|
unknown: Record<string, RawInputType>;
|
|
122
119
|
/** Arguments that were not parsed due to ignore callback. */
|
|
123
120
|
ignored: string[];
|
|
121
|
+
/** List of required flags that were not provided. */
|
|
122
|
+
missingRequiredFlags: string[];
|
|
124
123
|
}
|
|
125
124
|
type InferFlagDefault<T extends FlagDefinitionValue, Fallback> = T extends {
|
|
126
125
|
default: FlagDefaultValue<infer DefaultType>;
|
|
@@ -190,4 +189,4 @@ declare function createParser<T extends FlagsDefinition>(options?: ParserOptions
|
|
|
190
189
|
};
|
|
191
190
|
declare const parse: <T extends FlagsDefinition>(args: string[], options?: ParserOptions<T>) => ParsedResult<InferFlags<T>>;
|
|
192
191
|
//#endregion
|
|
193
|
-
export { BaseFlagOptions, DOUBLE_DASH, Enum, FlagDefaultValue, FlagDefaultValueFunction, FlagDefinitionValue, FlagOptions, FlagsDefinition, IgnoreFunction, InferFlags, InvalidSchemaError, KNOWN_FLAG,
|
|
192
|
+
export { BaseFlagOptions, DOUBLE_DASH, Enum, FlagDefaultValue, FlagDefaultValueFunction, FlagDefinitionValue, FlagOptions, FlagsDefinition, IgnoreFunction, InferFlags, InvalidSchemaError, KNOWN_FLAG, ObjectInputType, PARAMETER, ParsedResult, ParserOptions, Range, RawInputType, Regex, TypeFunction, TypeValue, UNKNOWN_FLAG, createParser, parse };
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,6 @@ var InvalidSchemaError = class extends Error {
|
|
|
5
5
|
this.name = "InvalidSchemaError";
|
|
6
6
|
}
|
|
7
7
|
};
|
|
8
|
-
var MissingRequiredFlagError = class extends Error {
|
|
9
|
-
constructor(name) {
|
|
10
|
-
super(`Missing required flag: ${name}`);
|
|
11
|
-
this.name = "MissingRequiredFlagError";
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
8
|
|
|
15
9
|
//#endregion
|
|
16
10
|
//#region src/flag-types.ts
|
|
@@ -122,7 +116,6 @@ function iterateArgs(args, result, shouldProcessAsFlag, isKnownFlag, ignore, cal
|
|
|
122
116
|
//#endregion
|
|
123
117
|
//#region ../utils/src/index.ts
|
|
124
118
|
const looseIsArray = (arr) => Array.isArray(arr);
|
|
125
|
-
const toArray = (a) => Array.isArray(a) ? a : [a];
|
|
126
119
|
/**
|
|
127
120
|
* Converts a dash- or space-separated string to camelCase.
|
|
128
121
|
* Not using regexp for better performance, because this function is used in parser.
|
|
@@ -161,9 +154,14 @@ function buildConfigsAndAliases(delimiters, flags) {
|
|
|
161
154
|
function validateFlagOptions(name, options) {
|
|
162
155
|
const prefix = `Flag "${name}"`;
|
|
163
156
|
if (Array.isArray(options.type) && options.type.length > 1) throw new InvalidSchemaError(`${prefix} has an invalid type array. Only single-element arrays are allowed to denote multiple occurrences.`);
|
|
157
|
+
if (name.length < 2) throw new InvalidSchemaError(`${prefix} name must be at least 2 characters long.`);
|
|
164
158
|
const names = [name];
|
|
165
|
-
if (options.
|
|
159
|
+
if (options.short) {
|
|
160
|
+
if (options.short.length !== 1) throw new InvalidSchemaError(`${prefix} short flag must be exactly 1 character long.`);
|
|
161
|
+
names.push(options.short);
|
|
162
|
+
}
|
|
166
163
|
if (names.some(isNameInvalid)) throw new InvalidSchemaError(`${prefix} contains reserved characters, which are used as delimiters.`);
|
|
164
|
+
if (options.required && options.default !== void 0) throw new InvalidSchemaError(`${prefix} cannot be both required and have a default value.`);
|
|
167
165
|
}
|
|
168
166
|
for (const [name, config] of Object.entries(flags)) {
|
|
169
167
|
const normalized = normalizeConfig(config);
|
|
@@ -171,10 +169,7 @@ function buildConfigsAndAliases(delimiters, flags) {
|
|
|
171
169
|
configs.set(name, normalized);
|
|
172
170
|
aliases.set(name, name);
|
|
173
171
|
aliases.set(camelCase(name), name);
|
|
174
|
-
if (normalized.
|
|
175
|
-
const list = Array.isArray(normalized.alias) ? normalized.alias : [normalized.alias];
|
|
176
|
-
for (const a of list) aliases.set(a, name);
|
|
177
|
-
}
|
|
172
|
+
if (normalized.short) aliases.set(normalized.short, name);
|
|
178
173
|
}
|
|
179
174
|
return {
|
|
180
175
|
configs,
|
|
@@ -240,7 +235,7 @@ const DOUBLE_DASH = "--";
|
|
|
240
235
|
function createParser(options = {}) {
|
|
241
236
|
const { flags: flagsConfig = {}, delimiters, ignore } = resolveParserOptions(options);
|
|
242
237
|
const { configs, aliases } = buildConfigsAndAliases(delimiters, flagsConfig);
|
|
243
|
-
function resolve(name) {
|
|
238
|
+
function resolve(name, isShortFlag = false) {
|
|
244
239
|
const dotIdx = name.indexOf(".");
|
|
245
240
|
const rootName = dotIdx === -1 ? name : name.slice(0, dotIdx);
|
|
246
241
|
let key = aliases.get(rootName);
|
|
@@ -249,6 +244,7 @@ function createParser(options = {}) {
|
|
|
249
244
|
if (!key) return;
|
|
250
245
|
}
|
|
251
246
|
const config = configs.get(key);
|
|
247
|
+
if (!isShortFlag && config.short === rootName) return;
|
|
252
248
|
return {
|
|
253
249
|
key,
|
|
254
250
|
config,
|
|
@@ -269,21 +265,22 @@ function createParser(options = {}) {
|
|
|
269
265
|
if (len < 2) return false;
|
|
270
266
|
const secondChar = arg.charCodeAt(1);
|
|
271
267
|
if (isLetter(secondChar)) return true;
|
|
272
|
-
if (isDigit(secondChar))
|
|
268
|
+
if (isDigit(secondChar)) {
|
|
269
|
+
const isShortFlag = secondChar !== 45;
|
|
270
|
+
return !!resolve(isShortFlag ? arg[1] : arg.slice(2), isShortFlag);
|
|
271
|
+
}
|
|
273
272
|
if (secondChar === 45 && len > 2) return isLetter(arg.charCodeAt(2));
|
|
274
273
|
return false;
|
|
275
274
|
}
|
|
276
275
|
function isKnownFlag(arg) {
|
|
277
|
-
|
|
278
|
-
if (secondChar === 45) {
|
|
276
|
+
if (arg.charCodeAt(1) === 45) {
|
|
279
277
|
const { rawName } = splitNameAndValue(arg.slice(2), delimiters);
|
|
280
|
-
if (resolve(rawName)) return true;
|
|
278
|
+
if (resolve(rawName, false)) return true;
|
|
281
279
|
if (resolveNegated(rawName)) return true;
|
|
282
280
|
return false;
|
|
283
281
|
}
|
|
284
|
-
if (isDigit(secondChar)) return true;
|
|
285
282
|
const chars = arg.slice(1);
|
|
286
|
-
for (const char of chars) if (!resolve(char)) return false;
|
|
283
|
+
for (const char of chars) if (!resolve(char, true)) return false;
|
|
287
284
|
return true;
|
|
288
285
|
}
|
|
289
286
|
const parse$1 = (args) => {
|
|
@@ -293,7 +290,8 @@ function createParser(options = {}) {
|
|
|
293
290
|
flags: {},
|
|
294
291
|
raw: args,
|
|
295
292
|
unknown: {},
|
|
296
|
-
ignored: []
|
|
293
|
+
ignored: [],
|
|
294
|
+
missingRequiredFlags: []
|
|
297
295
|
};
|
|
298
296
|
iterateArgs(args, result, shouldProcessAsFlag, isKnownFlag, ignore, ({ current, eat, exit, hasNext, index, next, shouldIgnore }) => {
|
|
299
297
|
if (current === DOUBLE_DASH) {
|
|
@@ -310,13 +308,13 @@ function createParser(options = {}) {
|
|
|
310
308
|
result.parameters.push(current);
|
|
311
309
|
return;
|
|
312
310
|
}
|
|
313
|
-
const
|
|
314
|
-
const chars = current.slice(
|
|
315
|
-
if (
|
|
311
|
+
const isShortFlag = !current.startsWith(DOUBLE_DASH);
|
|
312
|
+
const chars = current.slice(isShortFlag ? 1 : 2);
|
|
313
|
+
if (isShortFlag) {
|
|
316
314
|
const charsLen = chars.length;
|
|
317
315
|
for (let j = 0; j < charsLen; j++) {
|
|
318
316
|
const char = chars[j];
|
|
319
|
-
const resolved = resolve(char);
|
|
317
|
+
const resolved = resolve(char, true);
|
|
320
318
|
if (!resolved) {
|
|
321
319
|
result.unknown[char] = true;
|
|
322
320
|
continue;
|
|
@@ -373,7 +371,7 @@ function createParser(options = {}) {
|
|
|
373
371
|
else if (Array.isArray(config.type)) result.flags[key] = isArrayOfType(config.type, Boolean) ? 0 : [];
|
|
374
372
|
else if (config.type === Object) result.flags[key] = {};
|
|
375
373
|
else if (config.type === Boolean) result.flags[key] = false;
|
|
376
|
-
else if (config.required)
|
|
374
|
+
else if (config.required) result.missingRequiredFlags.push(key);
|
|
377
375
|
}
|
|
378
376
|
return result;
|
|
379
377
|
};
|
|
@@ -382,4 +380,4 @@ function createParser(options = {}) {
|
|
|
382
380
|
const parse = (args, options = {}) => createParser(options).parse(args);
|
|
383
381
|
|
|
384
382
|
//#endregion
|
|
385
|
-
export { DOUBLE_DASH, Enum, InvalidSchemaError, KNOWN_FLAG,
|
|
383
|
+
export { DOUBLE_DASH, Enum, InvalidSchemaError, KNOWN_FLAG, PARAMETER, Range, Regex, UNKNOWN_FLAG, createParser, parse };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clerc/parser",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.26",
|
|
4
4
|
"author": "Ray <i@mk1.io> (https://github.com/so1ve)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Clerc parser",
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
"nopt": "^9.0.0",
|
|
57
57
|
"type-flag": "^4.0.3",
|
|
58
58
|
"yargs-parser": "^22.0.0",
|
|
59
|
-
"@clerc/utils": "1.0.0-beta.
|
|
59
|
+
"@clerc/utils": "1.0.0-beta.26"
|
|
60
60
|
}
|
|
61
61
|
}
|