@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 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
- //#endregion
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
- interface BaseFlagOptions<T extends TypeValue = TypeValue> {
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
- /** Aliases for the flag. */
58
- alias?: MaybeArray<string>;
59
- /** The default value of the flag. */
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, MissingRequiredFlagError, ObjectInputType, PARAMETER, ParsedResult, ParserOptions, Range, RawInputType, Regex, TypeFunction, TypeValue, UNKNOWN_FLAG, createParser, parse };
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.alias) names.push(...toArray(options.alias));
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.alias) {
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)) return !!resolve(secondChar !== 45 ? arg[1] : arg.slice(2));
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
- const secondChar = arg.charCodeAt(1);
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 isAlias = !current.startsWith(DOUBLE_DASH);
314
- const chars = current.slice(isAlias ? 1 : 2);
315
- if (isAlias) {
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) throw new MissingRequiredFlagError(key);
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, MissingRequiredFlagError, PARAMETER, Range, Regex, UNKNOWN_FLAG, createParser, parse };
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.24",
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.24"
59
+ "@clerc/utils": "1.0.0-beta.26"
60
60
  }
61
61
  }