@clerc/core 1.0.0-beta.3 → 1.0.0-beta.30

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
@@ -1,22 +1,8 @@
1
- import { ErrorHandler as ErrorHandler$1 } from "lite-emit";
2
-
3
- //#region ../parser/src/flag-types.d.ts
4
-
5
- /**
6
- * Creates a Choices type function that validates the input against allowed values.
7
- * The display name will be formatted as "value1 | value2 | ..." for help output.
8
- *
9
- * @param values - Array of allowed string values
10
- * @returns A FlagTypeFunction that validates and returns the input value
11
- * @throws {Error} If the value is not in the allowed values list
12
- *
13
- * @example
14
- * ```typescript
15
- * const format = Choices(['json', 'yaml', 'xml']);
16
- * // Help output will show: json | yaml | xml
17
- * ```
18
- */
19
- declare function Choices<T extends string>(...values: T[]): FlagTypeFunction<T>;
1
+ //#endregion
2
+ //#region ../parser/src/errors.d.ts
3
+ declare class InvalidSchemaError extends Error {
4
+ constructor(message: string);
5
+ }
20
6
  //#endregion
21
7
  //#region ../utils/src/types/type-fest.d.ts
22
8
  type LiteralUnion<LiteralType, BaseType> = LiteralType | (BaseType & Record<never, never>);
@@ -29,6 +15,7 @@ type MapsSetsOrArrays = ReadonlyMap<unknown, unknown> | WeakMap<WeakKey, unknown
29
15
  type ConditionalDeepPrettify<T, E = never, I$1 = unknown> = T extends E ? T : T extends I$1 ? { [TypeKey in keyof T]: ConditionalDeepPrettify<T[TypeKey], E, I$1> } : T;
30
16
  type DeepPrettify<T, E = never> = ConditionalDeepPrettify<T, E | NonRecursiveType | MapsSetsOrArrays, object>;
31
17
  type IsAny<T> = 0 extends 1 & T ? true : false;
18
+ 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>);
32
19
  //#endregion
33
20
  //#region ../utils/src/types/index.d.ts
34
21
  type MaybeArray<T> = T | T[];
@@ -37,19 +24,24 @@ type UnionToIntersection<U$1> = (U$1 extends any ? (k: U$1) => void : never) ext
37
24
  type CamelCase<S extends string> = S extends `${infer Head} ${infer Tail}` ? `${Head}${Capitalize<CamelCase<Tail>>}` : S extends `${infer Head}-${infer Tail}` ? `${Head}${Capitalize<CamelCase<Tail>>}` : S;
38
25
  //#endregion
39
26
  //#region ../parser/src/types.d.ts
40
- type FlagDefaultValue<T = unknown> = T | (() => T);
27
+ interface FlagDefaultValueFunction<T> {
28
+ (): T;
29
+ display?: string;
30
+ }
31
+ type FlagDefaultValue<T = unknown> = T | FlagDefaultValueFunction<T>;
41
32
  /**
42
33
  * Defines how a string input is converted to the target type T.
43
34
  *
44
35
  * @template T The target type.
45
36
  */
46
- type FlagTypeFunction<T = unknown> = ((value: string) => T) & {
37
+ interface TypeFunction<T = unknown> {
38
+ (value: string): T;
47
39
  /**
48
40
  * Optional display name for the type, useful in help output.
49
41
  * If provided, this will be shown instead of the function name.
50
42
  */
51
- displayName?: string;
52
- };
43
+ display?: string;
44
+ }
53
45
  /**
54
46
  * A callback function to conditionally stop parsing.
55
47
  * When it returns true, parsing stops and remaining arguments are preserved in `ignored`.
@@ -59,19 +51,23 @@ type FlagTypeFunction<T = unknown> = ((value: string) => T) & {
59
51
  * @returns true to stop parsing, false to continue
60
52
  */
61
53
  type IgnoreFunction = (type: typeof KNOWN_FLAG | typeof UNKNOWN_FLAG | typeof PARAMETER, arg: string) => boolean;
62
- type FlagType<T = unknown> = FlagTypeFunction<T> | readonly [FlagTypeFunction<T>];
63
- interface BaseFlagOptions<T extends FlagType = FlagType> {
54
+ type TypeValue<T = unknown> = TypeFunction<T> | readonly [TypeFunction<T>];
55
+ type FlagRequiredOrDefault = RequireExactlyOneOrNone<{
56
+ /** The default value of the flag. */
57
+ default?: unknown;
58
+ /** Whether the flag is required. */
59
+ required?: boolean;
60
+ }, "default" | "required">;
61
+ type BaseFlagOptions<T extends TypeValue = TypeValue> = FlagRequiredOrDefault & {
64
62
  /**
65
63
  * The type constructor or a function to convert the string value.
66
64
  * To support multiple occurrences of a flag (e.g., --file a --file b), wrap the type in an array: [String], [Number].
67
65
  * e.g., String, Number, [String], (val) => val.split(',')
68
66
  */
69
67
  type: T;
70
- /** Aliases for the flag. */
71
- alias?: MaybeArray<string>;
72
- /** The default value of the flag. */
73
- default?: unknown;
74
- }
68
+ /** Short flag alias (single character). */
69
+ short?: string;
70
+ };
75
71
  type FlagOptions = (BaseFlagOptions<BooleanConstructor> & {
76
72
  /**
77
73
  * Whether to enable the `--no-<flag>` syntax to set the value to false.
@@ -84,8 +80,30 @@ type FlagOptions = (BaseFlagOptions<BooleanConstructor> & {
84
80
  }) | (BaseFlagOptions & {
85
81
  negatable?: never;
86
82
  });
87
- type FlagDefinitionValue = FlagOptions | FlagType;
83
+ type FlagDefinitionValue = FlagOptions | TypeValue;
88
84
  type FlagsDefinition = Record<string, FlagDefinitionValue>;
85
+ /**
86
+ * Configuration options for the parser.
87
+ */
88
+ interface ParserOptions<T extends FlagsDefinition = {}> {
89
+ /**
90
+ * Detailed configuration for flags.
91
+ * Supports the full object syntax or a type constructor as a shorthand.
92
+ * The key is the flag name (e.g., "file" for "--file").
93
+ */
94
+ flags?: T;
95
+ /**
96
+ * Delimiters to split flag names and values.
97
+ *
98
+ * @default ['=', ':']
99
+ */
100
+ delimiters?: string[];
101
+ /**
102
+ * A callback function to conditionally stop parsing.
103
+ * When it returns true, parsing stops and remaining arguments are preserved in `ignored`.
104
+ */
105
+ ignore?: IgnoreFunction;
106
+ }
89
107
  type RawInputType = string | boolean;
90
108
  interface ObjectInputType {
91
109
  [key: string]: RawInputType | ObjectInputType;
@@ -110,6 +128,8 @@ interface ParsedResult<TFlags extends Record<string, any>> {
110
128
  unknown: Record<string, RawInputType>;
111
129
  /** Arguments that were not parsed due to ignore callback. */
112
130
  ignored: string[];
131
+ /** List of required flags that were not provided. */
132
+ missingRequiredFlags: string[];
113
133
  }
114
134
  type InferFlagDefault<T extends FlagDefinitionValue, Fallback> = T extends {
115
135
  default: FlagDefaultValue<infer DefaultType>;
@@ -119,13 +139,15 @@ type IsTypeAny<T extends FlagDefinitionValue> = IsAny<T> extends true ? true : T
119
139
  } ? IsAny<Type> extends true ? true : false : false;
120
140
  type _InferFlags<T extends FlagsDefinition> = { [K in keyof T]: IsTypeAny<T[K]> extends true ? any : T[K] extends readonly [BooleanConstructor] | {
121
141
  type: readonly [BooleanConstructor];
122
- } ? number : T[K] extends ObjectConstructor | {
142
+ } ? number | InferFlagDefault<T[K], never> : T[K] extends ObjectConstructor | {
123
143
  type: ObjectConstructor;
124
- } ? ObjectInputType : T[K] extends readonly [FlagType<infer U>] | {
125
- type: readonly [FlagType<infer U>];
126
- } ? U[] | InferFlagDefault<T[K], never> : T[K] extends FlagType<infer U> | {
127
- type: FlagType<infer U>;
128
- } ? U | InferFlagDefault<T[K], [U] extends [boolean] ? never : undefined> : never };
144
+ } ? ObjectInputType | InferFlagDefault<T[K], never> : T[K] extends readonly [TypeValue<infer U>] | {
145
+ type: readonly [TypeValue<infer U>];
146
+ } ? U[] | InferFlagDefault<T[K], never> : T[K] extends TypeValue<infer U> | {
147
+ type: TypeValue<infer U>;
148
+ } ? U | InferFlagDefault<T[K], [U] extends [boolean] ? never : T[K] extends {
149
+ required: true;
150
+ } ? never : undefined> : never };
129
151
  /**
130
152
  * An advanced utility type that infers the exact type of the `flags` object in the parsed result,
131
153
  * based on the provided `flags` configuration object T.
@@ -141,40 +163,95 @@ declare const PARAMETER = "parameter";
141
163
  //#endregion
142
164
  //#region ../parser/src/parse.d.ts
143
165
  declare const DOUBLE_DASH = "--";
166
+ type ParseFunction<T extends FlagsDefinition> = (args: string[]) => ParsedResult<InferFlags<T>>;
167
+ declare function createParser<T extends FlagsDefinition>(options?: ParserOptions<T>): {
168
+ parse: ParseFunction<T>;
169
+ };
170
+ declare const parse: <T extends FlagsDefinition>(args: string[], options?: ParserOptions<T>) => ParsedResult<InferFlags<T>>;
171
+ declare namespace index_d_exports {
172
+ export { BaseFlagOptions, DOUBLE_DASH, FlagDefaultValue, FlagDefaultValueFunction, FlagDefinitionValue, FlagOptions, FlagsDefinition, IgnoreFunction, InferFlags, InvalidSchemaError, KNOWN_FLAG, ObjectInputType, PARAMETER, ParsedResult, ParserOptions, RawInputType, TypeFunction, TypeValue, UNKNOWN_FLAG, createParser, parse };
173
+ }
174
+ //#endregion
175
+ //#region ../advanced-types/src/errors.d.ts
176
+ declare class FlagValidationError extends Error {}
177
+ declare namespace index_d_exports$1 {
178
+ export { Enum, FlagValidationError, Range, Regex };
179
+ }
180
+ /**
181
+ * Creates a Enum type function that validates the input against allowed values.
182
+ * The display name will be formatted as "value1 | value2 | ..." for help output.
183
+ *
184
+ * @param values - Array of allowed string values
185
+ * @returns A TypeFunction that validates and returns the input value
186
+ * @throws {Error} If the value is not in the allowed values list
187
+ *
188
+ * @example
189
+ * ```typescript
190
+ * const format = Enum(['json', 'yaml', 'xml']);
191
+ * // Help output will show: json | yaml | xml
192
+ * ```
193
+ */
194
+ declare function Enum<T extends string>(...values: T[]): TypeFunction<T>;
195
+ /**
196
+ * Creates a range type function that validates the input is a number within the specified range.
197
+ *
198
+ * @param min - The minimum acceptable value (inclusive)
199
+ * @param max - The maximum acceptable value (inclusive)
200
+ * @returns A TypeFunction that validates the input value
201
+ * @throws {Error} If the value is not a number or is outside the specified range
202
+ */
203
+ declare function Range(min: number, max: number): TypeFunction<number>;
204
+ /**
205
+ * Creates a regex type function that validates the input against the provided pattern.
206
+ *
207
+ * @param pattern - The regular expression pattern to validate against
208
+ * @param description - Optional description for display purposes
209
+ * @returns A TypeFunction that validates the input value
210
+ * @throws {Error} If the value does not match the regex pattern
211
+ */
212
+ declare function Regex(pattern: RegExp, description?: string): TypeFunction<string>;
144
213
  //#endregion
145
214
  //#region src/types/clerc.d.ts
146
215
  type ErrorHandler = (error: unknown) => void;
147
216
  //#endregion
148
217
  //#region src/types/flag.d.ts
149
218
  interface FlagCustomOptions {}
150
- type ClercFlagOptions = FlagOptions & FlagCustomOptions;
151
- type ClercGlobalFlagDefinitionValue = ClercFlagOptions | FlagType;
152
- type ClercFlagOptionsWithDescription = ClercFlagOptions & {
153
- description: string;
154
- };
155
- type ClercFlagsDefinition = Record<string, ClercFlagOptionsWithDescription>;
219
+ type ClercFlagOptions = FlagOptions & {
220
+ description?: string;
221
+ } & FlagCustomOptions;
222
+ type ClercFlagDefinitionValue = ClercFlagOptions | TypeValue;
223
+ type ClercFlagsDefinition = Record<string, ClercFlagDefinitionValue>;
156
224
  //#endregion
157
- //#region src/types/parameters.d.ts
158
- type InferParameter<T extends string> = T extends `<${infer Name extends string}...>` | `[${infer Name extends string}...]` ? Record<CamelCase<Name>, string[]> : T extends `<${infer Name extends string}>` ? Record<CamelCase<Name>, string> : T extends `[${infer Name extends string}]` ? Record<CamelCase<Name>, string | undefined> : never;
159
- type InferParameters<T extends string[]> = T extends (infer U extends string)[] ? Prettify<UnionToIntersection<InferParameter<U>>> : never;
225
+ //#region src/types/parameter.d.ts
226
+ interface ParameterCustomOptions {}
227
+ type InferStringParameter<T extends string, Type$1 = string> = T extends `<${infer Name extends string}...>` | `[${infer Name extends string}...]` ? Record<CamelCase<Name>, Type$1[]> : T extends `<${infer Name extends string}>` ? Record<CamelCase<Name>, Type$1> : T extends `[${infer Name extends string}]` ? Record<CamelCase<Name>, Type$1 | undefined> : never;
228
+ type InferParameter<T extends ParameterDefinitionValue> = T extends string ? InferStringParameter<T> : T extends ParameterOptions ? T["type"] extends TypeFunction<infer U> ? InferStringParameter<T["key"], U> : InferStringParameter<T["key"]> : never;
229
+ type InferParameters<T extends readonly ParameterDefinitionValue[]> = T extends readonly (infer U extends ParameterDefinitionValue)[] ? Prettify<UnionToIntersection<InferParameter<U>>> : never;
230
+ type ParameterOptions = {
231
+ key: string;
232
+ description?: string;
233
+ type?: TypeFunction;
234
+ } & ParameterCustomOptions;
235
+ type ParameterDefinitionValue = string | ParameterOptions;
160
236
  //#endregion
161
237
  //#region src/types/context.d.ts
162
238
  type AddStringIndex<T> = T & Record<string, any>;
163
- type InferFlagsWithGlobal<C extends Command, GF extends ClercFlagsDefinition> = AddStringIndex<InferFlags<NonNullable<C["flags"]> & Omit<GF, keyof NonNullable<C["flags"]>>>>;
239
+ type KnownKeys<T> = string extends keyof T ? never : keyof T;
240
+ type InferFlagsWithGlobal<C extends Command, GF extends ClercFlagsDefinition> = AddStringIndex<InferFlags<NonNullable<C["flags"]> & Omit<GF, KnownKeys<NonNullable<C["flags"]>>>>>;
241
+ interface ContextStore {}
164
242
  interface BaseContext<C extends Command = Command, GF extends ClercFlagsDefinition = {}> {
165
- resolved: boolean;
166
243
  command?: C;
167
244
  calledAs?: string;
168
245
  parameters: InferParameters<NonNullable<C["parameters"]>>;
169
246
  flags: InferFlagsWithGlobal<C, GF>;
170
247
  ignored: string[];
171
248
  rawParsed: ParsedResult<InferFlagsWithGlobal<C, GF>>;
172
- missingParameters: boolean;
249
+ store: Partial<ContextStore>;
173
250
  }
174
251
  //#endregion
175
252
  //#region src/types/command.d.ts
176
253
  interface CommandCustomOptions {}
177
- interface CommandOptions<Parameters extends string[] = string[], Flags extends ClercFlagsDefinition = ClercFlagsDefinition> extends CommandCustomOptions {
254
+ interface CommandOptions<Parameters extends readonly ParameterDefinitionValue[] = readonly ParameterDefinitionValue[], Flags extends ClercFlagsDefinition = ClercFlagsDefinition> extends CommandCustomOptions {
178
255
  alias?: MaybeArray<string>;
179
256
  parameters?: Parameters;
180
257
  flags?: Flags;
@@ -183,11 +260,11 @@ interface CommandOptions<Parameters extends string[] = string[], Flags extends C
183
260
  */
184
261
  ignore?: IgnoreFunction;
185
262
  }
186
- interface Command<Name$1 extends string = string, Parameters extends string[] = string[], Flags extends ClercFlagsDefinition = ClercFlagsDefinition> extends CommandOptions<Parameters, Flags> {
263
+ interface Command<Name$1 extends string = string, Parameters extends readonly ParameterDefinitionValue[] = readonly ParameterDefinitionValue[], Flags extends ClercFlagsDefinition = ClercFlagsDefinition> extends CommandOptions<Parameters, Flags> {
187
264
  name: Name$1;
188
- description: string;
265
+ description?: string;
189
266
  }
190
- type CommandWithHandler<Name$1 extends string = string, Parameters extends string[] = string[], Flags extends ClercFlagsDefinition = ClercFlagsDefinition> = Command<Name$1, Parameters, Flags> & {
267
+ type CommandWithHandler<Name$1 extends string = string, Parameters extends readonly ParameterDefinitionValue[] = readonly ParameterDefinitionValue[], Flags extends ClercFlagsDefinition = ClercFlagsDefinition> = Command<Name$1, Parameters, Flags> & {
191
268
  handler?: CommandHandler<Command<Name$1, Parameters, Flags>>;
192
269
  };
193
270
  type CommandsRecord = Record<string, Command>;
@@ -237,23 +314,26 @@ declare class Clerc<Commands extends CommandsRecord = {}, GlobalFlags extends Cl
237
314
  get _version(): string;
238
315
  get _commands(): CommandsMap;
239
316
  get _globalFlags(): GlobalFlags;
317
+ get store(): Partial<ContextStore>;
240
318
  static create(options?: CreateOptions): Clerc;
241
319
  name(name: string): this;
242
320
  scriptName(scriptName: string): this;
243
321
  description(description: string): this;
244
322
  version(version: string): this;
245
323
  use(plugin: Plugin): this;
246
- errorHandler(handler: ErrorHandler$1): this;
247
- command<Name$1 extends string, Parameters extends string[] = [], Flags extends ClercFlagsDefinition = {}>(command: CommandWithHandler<Name$1, [...Parameters], Flags>): Clerc<Commands & Record<string, CommandWithHandler<Name$1, Parameters, Flags>>, GlobalFlags>;
248
- command<Name$1 extends string, Parameters extends string[] = [], Flags extends ClercFlagsDefinition = {}>(name: Name$1 extends keyof Commands ? ["COMMAND ALREADY EXISTS"] : Name$1, description: string, options?: CommandOptions<[...Parameters], Flags>): Clerc<Commands & Record<Name$1, Command<Name$1, Parameters, Flags>>, GlobalFlags>;
249
- globalFlag<Name$1 extends string, Flag extends ClercGlobalFlagDefinitionValue>(name: Name$1, description: string, options: Flag): Clerc<Commands, GlobalFlags & Record<Name$1, Flag>>;
324
+ errorHandler(handler: ErrorHandler): this;
325
+ command<Name$1 extends string, const Parameters extends readonly ParameterDefinitionValue[], Flags extends ClercFlagsDefinition>(command: CommandWithHandler<Name$1, Parameters, Flags>): Clerc<Commands & Record<string, CommandWithHandler<Name$1, Parameters, Flags>>, GlobalFlags>;
326
+ command<Name$1 extends string, const Parameters extends readonly ParameterDefinitionValue[], Flags extends ClercFlagsDefinition>(name: Name$1 extends keyof Commands ? ["COMMAND ALREADY EXISTS"] : Name$1, options?: CommandOptions<Parameters, Flags>): Clerc<Commands & Record<Name$1, Command<Name$1, Parameters, Flags>>, GlobalFlags>;
327
+ command<Name$1 extends string, const Parameters extends readonly ParameterDefinitionValue[], Flags extends ClercFlagsDefinition>(name: Name$1 extends keyof Commands ? ["COMMAND ALREADY EXISTS"] : Name$1, description: string, options?: CommandOptions<Parameters, Flags>): Clerc<Commands & Record<Name$1, Command<Name$1, Parameters, Flags>>, GlobalFlags>;
328
+ globalFlag<Name$1 extends string, Flag extends ClercFlagDefinitionValue>(name: Name$1, description: string, options: Flag): Clerc<Commands, GlobalFlags & Record<Name$1, Flag>>;
329
+ globalFlag<Name$1 extends string, Flag extends ClercFlagDefinitionValue>(name: Name$1, options: Flag): Clerc<Commands, GlobalFlags & Record<Name$1, Flag>>;
250
330
  interceptor(interceptor: Interceptor<Command, GlobalFlags>): this;
251
331
  on<Name$1 extends LiteralUnion<keyof Commands, string>>(name: Name$1, handler: CommandHandler<Commands[Name$1], GlobalFlags>): this;
252
332
  run(): Promise<void>;
253
333
  parse<Run extends boolean = true>(argvOrOptions?: string[] | ParseOptions<Run>): Run extends true ? Promise<void> : this;
254
334
  }
255
335
  //#endregion
256
- //#region src/commands.d.ts
336
+ //#region src/command.d.ts
257
337
  declare function resolveCommand(commandsMap: CommandsMap, parameters: string[]): [Command, string] | [undefined, undefined];
258
338
  //#endregion
259
339
  //#region src/errors.d.ts
@@ -264,23 +344,34 @@ declare class NoSuchCommandError extends Error {
264
344
  declare class NoCommandSpecifiedError extends Error {
265
345
  constructor(text?: string);
266
346
  }
267
- declare class InvalidCommandError extends Error {
268
- constructor(message: string);
269
- }
347
+ declare class InvalidCommandError extends Error {}
270
348
  declare class MissingRequiredMetadataError extends Error {
271
349
  constructor(metadataName: string);
272
350
  }
273
- declare class InvalidParametersError extends Error {
274
- constructor(message: string);
351
+ declare class InvalidParametersError extends Error {}
352
+ declare class MissingRequiredFlagError extends Error {
353
+ constructor(flags: string[]);
275
354
  }
276
355
  //#endregion
277
356
  //#region src/helpers.d.ts
278
- declare const defineCommand: <Name$1 extends string, Parameters extends string[] = [], Flags extends ClercFlagsDefinition = {}>(command: CommandWithHandler<Name$1, [...Parameters], Flags>) => CommandWithHandler<Name$1, [...Parameters], Flags>;
357
+ declare const defineCommand: <Name$1 extends string, const Parameters extends readonly ParameterDefinitionValue[], Flags extends ClercFlagsDefinition>(command: Command<Name$1, Parameters, Flags>, handler?: NoInfer<CommandHandler<Command<Name$1, Parameters, Flags>>>) => CommandWithHandler<Name$1, Parameters, Flags>;
279
358
  //#endregion
280
359
  //#region src/ignore.d.ts
281
360
  declare function createStopAtFirstParameter(): IgnoreFunction;
282
361
  //#endregion
362
+ //#region src/parameter.d.ts
363
+ interface ParameterInfo {
364
+ name: string;
365
+ isRequired: boolean;
366
+ isVariadic: boolean;
367
+ }
368
+ declare function extractParameterInfo(key: string): ParameterInfo;
369
+ //#endregion
283
370
  //#region src/plugin.d.ts
284
371
  declare const definePlugin: (plugin: Plugin) => Plugin;
285
372
  //#endregion
286
- export { BaseContext, Choices, Clerc, ClercFlagOptions, ClercFlagOptionsWithDescription, ClercFlagsDefinition, ClercGlobalFlagDefinitionValue, Command, CommandCustomOptions, CommandHandler, CommandHandlerContext, CommandOptions, CommandWithHandler, CommandsMap, CommandsRecord, DOUBLE_DASH, ErrorHandler, FlagCustomOptions, InferParameters, Interceptor, InterceptorContext, InterceptorHandler, InterceptorNext, InterceptorObject, InvalidCommandError, InvalidParametersError, KNOWN_FLAG, MakeEmitterEvents, MissingRequiredMetadataError, NoCommandSpecifiedError, NoSuchCommandError, PARAMETER, Plugin, UNKNOWN_FLAG, createStopAtFirstParameter, defineCommand, definePlugin, resolveCommand };
373
+ //#region src/utils.d.ts
374
+ declare const normalizeFlagValue: (flag: ClercFlagDefinitionValue) => ClercFlagOptions;
375
+ declare const normalizeParameterValue: (parameter: ParameterDefinitionValue) => ParameterOptions;
376
+ //#endregion
377
+ export { BaseContext, Clerc, ClercFlagDefinitionValue, ClercFlagOptions, ClercFlagsDefinition, Command, CommandCustomOptions, CommandHandler, CommandHandlerContext, CommandOptions, CommandWithHandler, CommandsMap, CommandsRecord, ContextStore, type CreateOptions, DOUBLE_DASH, ErrorHandler, FlagCustomOptions, InferParameters, Interceptor, InterceptorContext, InterceptorHandler, InterceptorNext, InterceptorObject, InvalidCommandError, InvalidParametersError, InvalidSchemaError, KNOWN_FLAG, MakeEmitterEvents, MissingRequiredFlagError, MissingRequiredMetadataError, NoCommandSpecifiedError, NoSuchCommandError, PARAMETER, ParameterCustomOptions, ParameterDefinitionValue, ParameterOptions, type ParseOptions, type index_d_exports as Parser, Plugin, index_d_exports$1 as Types, UNKNOWN_FLAG, createStopAtFirstParameter, defineCommand, definePlugin, extractParameterInfo, normalizeFlagValue, normalizeParameterValue, resolveCommand };
package/dist/index.js CHANGED
@@ -1,8 +1,33 @@
1
- import { Choices, DOUBLE_DASH, DOUBLE_DASH as DOUBLE_DASH$1, KNOWN_FLAG, PARAMETER, PARAMETER as PARAMETER$1, UNKNOWN_FLAG, parse } from "@clerc/parser";
2
- import { camelCase, toArray } from "@clerc/utils";
1
+ import * as Types from "@clerc/advanced-types";
2
+ import { DOUBLE_DASH, DOUBLE_DASH as DOUBLE_DASH$1, InvalidSchemaError, KNOWN_FLAG, PARAMETER, PARAMETER as PARAMETER$1, UNKNOWN_FLAG, parse } from "@clerc/parser";
3
3
  import { LiteEmit } from "lite-emit";
4
4
 
5
- //#region src/commands.ts
5
+ //#region ../utils/src/index.ts
6
+ const looseIsArray = (arr) => Array.isArray(arr);
7
+ const toArray = (a) => Array.isArray(a) ? a : [a];
8
+ /**
9
+ * Converts a dash- or space-separated string to camelCase.
10
+ * Not using regexp for better performance, because this function is used in parser.
11
+ */
12
+ function camelCase(str) {
13
+ const firstIdx = Math.min(str.includes("-") ? str.indexOf("-") : Infinity, str.includes(" ") ? str.indexOf(" ") : Infinity);
14
+ if (firstIdx === Infinity) return str;
15
+ let result = str.slice(0, firstIdx);
16
+ for (let i = firstIdx; i < str.length; i++) if ((str[i] === "-" || str[i] === " ") && i + 1 < str.length) {
17
+ const nextChar = str.charCodeAt(i + 1);
18
+ if (nextChar >= 97 && nextChar <= 122) {
19
+ result += String.fromCharCode(nextChar - 32);
20
+ i++;
21
+ } else {
22
+ result += str[i + 1];
23
+ i++;
24
+ }
25
+ } else if (str[i] !== "-" && str[i] !== " ") result += str[i];
26
+ return result;
27
+ }
28
+
29
+ //#endregion
30
+ //#region src/command.ts
6
31
  function resolveCommand(commandsMap, parameters) {
7
32
  for (let i = parameters.length; i >= 0; i--) {
8
33
  const name = parameters.slice(0, i).join(" ");
@@ -24,19 +49,17 @@ var NoCommandSpecifiedError = class extends Error {
24
49
  super(text);
25
50
  }
26
51
  };
27
- var InvalidCommandError = class extends Error {
28
- constructor(message) {
29
- super(message);
30
- }
31
- };
52
+ var InvalidCommandError = class extends Error {};
32
53
  var MissingRequiredMetadataError = class extends Error {
33
54
  constructor(metadataName) {
34
55
  super(`CLI ${metadataName} is required.`);
35
56
  }
36
57
  };
37
- var InvalidParametersError = class extends Error {
38
- constructor(message) {
39
- super(message);
58
+ var InvalidParametersError = class extends Error {};
59
+ var MissingRequiredFlagError = class extends Error {
60
+ constructor(flags) {
61
+ const s = flags.length > 1 ? "s" : "";
62
+ super(`Missing required flag${s}: ${flags.join(", ")}`);
40
63
  }
41
64
  };
42
65
 
@@ -73,7 +96,18 @@ function compose(inspectors) {
73
96
  }
74
97
 
75
98
  //#endregion
76
- //#region src/parameters.ts
99
+ //#region ../../node_modules/.pnpm/is-platform@1.0.0/node_modules/is-platform/dist/index.mjs
100
+ const IS_DENO = typeof Deno !== "undefined";
101
+ const IS_NODE = typeof process !== "undefined" && !IS_DENO;
102
+ const IS_ELECTRON = process.versions.electron && !process.defaultApp;
103
+
104
+ //#endregion
105
+ //#region src/utils.ts
106
+ const normalizeFlagValue = (flag) => typeof flag === "function" || looseIsArray(flag) ? { type: flag } : flag;
107
+ const normalizeParameterValue = (parameter) => typeof parameter === "string" ? { key: parameter } : parameter;
108
+
109
+ //#endregion
110
+ //#region src/parameter.ts
77
111
  function getParametersToResolve(argv) {
78
112
  const parameters = [];
79
113
  for (const arg of argv) {
@@ -84,15 +118,21 @@ function getParametersToResolve(argv) {
84
118
  }
85
119
  const PARAMETER_REGEX = /^(<|\[)([\w ]+)(\.\.\.)?(\]|>)$/;
86
120
  const isParameterDefinitionBracketsValid = (definition) => definition.startsWith("<") && definition.endsWith(">") || definition.startsWith("[") && definition.endsWith("]");
121
+ function extractParameterInfo(key) {
122
+ const match = key.match(PARAMETER_REGEX);
123
+ if (!match || !isParameterDefinitionBracketsValid(key)) throw new InvalidParametersError(`Invalid parameter definition: ${key}`);
124
+ return {
125
+ name: camelCase(match[2]),
126
+ isRequired: key.startsWith("<"),
127
+ isVariadic: !!match[3]
128
+ };
129
+ }
87
130
  function _parseParameters(definitions, parameters) {
88
131
  const result = {};
89
132
  let hasOptional = false;
90
- for (const [i, definition] of definitions.entries()) {
91
- const match = definition.match(PARAMETER_REGEX);
92
- if (!match || !isParameterDefinitionBracketsValid(definition)) throw new InvalidParametersError(`Invalid parameter definition: ${definition}`);
93
- const name = camelCase(match[2]);
94
- const isVariadic = !!match[3];
95
- const isRequired = definition.startsWith("<");
133
+ for (const [i, def] of definitions.entries()) {
134
+ const normalized = normalizeParameterValue(def);
135
+ const { name, isRequired, isVariadic } = extractParameterInfo(normalized.key);
96
136
  if (name in result) throw new InvalidParametersError(`Duplicate parameter name: ${name}`);
97
137
  if (isVariadic && i !== definitions.length - 1) throw new InvalidParametersError("Variadic parameter must be the last parameter in the definition.");
98
138
  if (isRequired) {
@@ -100,7 +140,10 @@ function _parseParameters(definitions, parameters) {
100
140
  } else hasOptional = true;
101
141
  const value = isVariadic ? parameters.slice(i) : parameters[i];
102
142
  if (isRequired && (isVariadic ? value.length === 0 : value === void 0)) throw new InvalidParametersError(`Missing required ${isVariadic ? "variadic " : ""}parameter: ${name}`);
103
- result[name] = value;
143
+ if (normalized.type) if (isVariadic) result[name] = value.map((v) => normalized.type(v));
144
+ else if (value === void 0) result[name] = value;
145
+ else result[name] = normalized.type(value);
146
+ else result[name] = value;
104
147
  }
105
148
  return result;
106
149
  }
@@ -117,12 +160,6 @@ function parseParameters(definitions, parameters, doubleDashParameters) {
117
160
  }
118
161
  }
119
162
 
120
- //#endregion
121
- //#region ../../node_modules/.pnpm/is-platform@1.0.0/node_modules/is-platform/dist/index.mjs
122
- const IS_DENO = typeof Deno !== "undefined";
123
- const IS_NODE = typeof process !== "undefined" && !IS_DENO;
124
- const IS_ELECTRON = process.versions.electron && !process.defaultApp;
125
-
126
163
  //#endregion
127
164
  //#region src/platform.ts
128
165
  const platformArgv = IS_NODE ? process.argv.slice(IS_ELECTRON ? 1 : 2) : IS_DENO ? Deno.args : [];
@@ -132,8 +169,9 @@ const platformArgv = IS_NODE ? process.argv.slice(IS_ELECTRON ? 1 : 2) : IS_DENO
132
169
  var Clerc = class Clerc {
133
170
  #argv = [];
134
171
  #commands = /* @__PURE__ */ new Map();
135
- #emitter = new LiteEmit({ errorHandler: (error) => this.#handleError(error) });
172
+ #emitter = new LiteEmit();
136
173
  #globalFlags = {};
174
+ #store = {};
137
175
  #interceptors = [];
138
176
  #errorHandlers = [];
139
177
  #name = "";
@@ -164,6 +202,9 @@ var Clerc = class Clerc {
164
202
  get _globalFlags() {
165
203
  return this.#globalFlags;
166
204
  }
205
+ get store() {
206
+ return this.#store;
207
+ }
167
208
  static create(options) {
168
209
  return new Clerc(options);
169
210
  }
@@ -211,13 +252,14 @@ var Clerc = class Clerc {
211
252
  if (this.#commands.has(name)) throw new InvalidCommandError(`Command with name "${name}" already exists.`);
212
253
  for (const alias of aliases) if (this.#commands.has(alias)) throw new InvalidCommandError(`Command with name "${alias}" already exists.`);
213
254
  }
214
- command(nameOrCommandObject, description, options) {
255
+ command(nameOrCommandObject, descriptionOrOptions, options) {
256
+ const isDescription = typeof descriptionOrOptions === "string";
215
257
  const command = typeof nameOrCommandObject === "string" ? {
216
258
  name: nameOrCommandObject,
217
- description,
218
- ...options
259
+ description: isDescription ? descriptionOrOptions : void 0,
260
+ ...isDescription ? options : descriptionOrOptions
219
261
  } : nameOrCommandObject;
220
- const aliases = toArray(options?.alias ?? []);
262
+ const aliases = toArray(command?.alias ?? []);
221
263
  this.#callWithErrorHandler(() => this.#validateCommandNameAndAlias(command.name, aliases));
222
264
  this.#commands.set(command.name, command);
223
265
  for (const alias of aliases) this.#commands.set(alias, {
@@ -227,10 +269,11 @@ var Clerc = class Clerc {
227
269
  if (command.handler) this.on(command.name, command.handler);
228
270
  return this;
229
271
  }
230
- globalFlag(name, description, options) {
272
+ globalFlag(name, descriptionOrOptions, options) {
273
+ const isDescription = typeof descriptionOrOptions === "string";
231
274
  this.#globalFlags[name] = {
232
- description,
233
- ...options
275
+ description: isDescription ? descriptionOrOptions : void 0,
276
+ ...isDescription ? options : descriptionOrOptions
234
277
  };
235
278
  return this;
236
279
  }
@@ -244,7 +287,6 @@ var Clerc = class Clerc {
244
287
  }
245
288
  #validate() {
246
289
  if (!this.#scriptName) throw new MissingRequiredMetadataError("script name");
247
- if (!this.#description) throw new MissingRequiredMetadataError("description");
248
290
  if (!this.#version) throw new MissingRequiredMetadataError("version");
249
291
  }
250
292
  #parseArgv(argv, command) {
@@ -270,20 +312,20 @@ var Clerc = class Clerc {
270
312
  parametersError = e;
271
313
  }
272
314
  const context = {
273
- resolved: !!command,
274
315
  command,
275
316
  calledAs,
276
317
  parameters,
277
318
  flags: parsed.flags,
278
319
  ignored: parsed.ignored,
279
320
  rawParsed: parsed,
280
- missingParameters: !!parametersError
321
+ store: { ...this.#store }
281
322
  };
282
323
  const emitInterceptor = {
283
324
  enforce: "post",
284
- handler: (ctx) => {
325
+ handler: async (ctx) => {
326
+ if (parsed.missingRequiredFlags.length > 0) throw new MissingRequiredFlagError(parsed.missingRequiredFlags);
285
327
  if (parametersError) throw parametersError;
286
- if (command) this.#emitter.emit(command.name, ctx);
328
+ if (command) await this.#emitter.emit(command.name, ctx);
287
329
  else throw parametersToResolve.length > 0 ? new NoSuchCommandError(parametersToResolve.join(" ")) : new NoCommandSpecifiedError();
288
330
  }
289
331
  };
@@ -302,7 +344,10 @@ var Clerc = class Clerc {
302
344
 
303
345
  //#endregion
304
346
  //#region src/helpers.ts
305
- const defineCommand = (command) => command;
347
+ const defineCommand = (command, handler) => ({
348
+ ...command,
349
+ handler
350
+ });
306
351
 
307
352
  //#endregion
308
353
  //#region src/ignore.ts
@@ -322,4 +367,4 @@ function createStopAtFirstParameter() {
322
367
  const definePlugin = (plugin) => plugin;
323
368
 
324
369
  //#endregion
325
- export { Choices, Clerc, DOUBLE_DASH, InvalidCommandError, InvalidParametersError, KNOWN_FLAG, MissingRequiredMetadataError, NoCommandSpecifiedError, NoSuchCommandError, PARAMETER, UNKNOWN_FLAG, createStopAtFirstParameter, defineCommand, definePlugin, resolveCommand };
370
+ export { Clerc, DOUBLE_DASH, InvalidCommandError, InvalidParametersError, InvalidSchemaError, KNOWN_FLAG, MissingRequiredFlagError, MissingRequiredMetadataError, NoCommandSpecifiedError, NoSuchCommandError, PARAMETER, Types, UNKNOWN_FLAG, createStopAtFirstParameter, defineCommand, definePlugin, extractParameterInfo, normalizeFlagValue, normalizeParameterValue, resolveCommand };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerc/core",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.30",
4
4
  "author": "Ray <i@mk1.io> (https://github.com/so1ve)",
5
5
  "type": "module",
6
6
  "description": "Clerc core",
@@ -44,15 +44,12 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "lite-emit": "^3.1.0",
48
- "@clerc/parser": "^1.0.0-beta.3",
49
- "@clerc/utils": "1.0.0-beta.3"
47
+ "lite-emit": "^4.0.0",
48
+ "@clerc/parser": "1.0.0-beta.30",
49
+ "@clerc/advanced-types": "1.0.0-beta.30"
50
50
  },
51
51
  "devDependencies": {
52
- "is-platform": "^1.0.0"
53
- },
54
- "scripts": {
55
- "build": "tsdown",
56
- "watch": "tsdown --watch"
52
+ "is-platform": "^1.0.0",
53
+ "@clerc/utils": "1.0.0-beta.30"
57
54
  }
58
55
  }