@crustjs/core 0.0.4 → 0.0.6

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.
Files changed (2) hide show
  1. package/dist/index.d.ts +36 -13
  2. package/package.json +4 -4
package/dist/index.d.ts CHANGED
@@ -128,16 +128,25 @@ interface BooleanMultiFlagDef extends MultiFlagBase {
128
128
  type FlagDef = StringFlagDef | NumberFlagDef | BooleanFlagDef | StringMultiFlagDef | NumberMultiFlagDef | BooleanMultiFlagDef;
129
129
  /** Record mapping flag names to their definitions */
130
130
  type FlagsDef = Record<string, FlagDef>;
131
- /** Extract alias string literals from a single FlagDef */
132
- type ExtractAliases<F extends FlagDef> = F extends {
131
+ /**
132
+ * Extract alias string literals from any value that has an `alias` field.
133
+ *
134
+ * Generalized to work with any shape (`FlagDef`, `FlagSpec`, etc.) —
135
+ * values without an `alias` field resolve to `never`.
136
+ *
137
+ * Includes a `string extends A` guard so non-narrowed aliases (e.g. the
138
+ * broad `string` type from a default generic) resolve to `never` instead
139
+ * of causing false-positive collisions.
140
+ */
141
+ type ExtractAliases<F> = F extends {
133
142
  alias: infer A;
134
- } ? A extends string ? A : A extends readonly string[] ? A[number] : never : never;
143
+ } ? A extends string ? string extends A ? never : A : A extends readonly string[] ? string extends A[number] ? never : A[number] : never : never;
135
144
  /**
136
145
  * Collects aliases from every flag *except* flag K.
137
146
  * Used to detect alias→alias duplicates across different flags.
138
147
  */
139
148
  type AliasesExcluding<
140
- F extends FlagsDef,
149
+ F extends Record<string, unknown>,
141
150
  K extends keyof F & string
142
151
  > = { [J in Exclude<keyof F & string, K>] : ExtractAliases<F[J]> }[Exclude<keyof F & string, K>];
143
152
  /**
@@ -146,13 +155,16 @@ type AliasesExcluding<
146
155
  * or `never` when K's aliases are all unique.
147
156
  */
148
157
  type CollidingAliases<
149
- F extends FlagsDef,
158
+ F extends Record<string, unknown>,
150
159
  K extends keyof F & string
151
160
  > = (ExtractAliases<F[K]> & Exclude<keyof F & string, K>) | (ExtractAliases<F[K]> & AliasesExcluding<F, K>);
152
161
  /**
153
162
  * Per-flag validation mapped type. Resolves to `F` when no collisions exist.
154
163
  * For flags with colliding aliases, adds a branded error property to the
155
- * specific flag definition, causing a type error on that flag's value:
164
+ * specific flag definition, causing a type error on that flag's value.
165
+ *
166
+ * Generalized to work with any `Record<string, unknown>` shape — core uses
167
+ * it with `FlagsDef`, the validate package uses it with `FlagShape`, etc.
156
168
  *
157
169
  * ```
158
170
  * Property 'FIX_ALIAS_COLLISION' is missing in type '{ type: "string"; alias: "minify" }'
@@ -160,13 +172,18 @@ type CollidingAliases<
160
172
  * '{ readonly FIX_ALIAS_COLLISION: "Alias \"minify\" collides with another flag name or alias" }'.
161
173
  * ```
162
174
  */
163
- type ValidateFlagAliases<F extends FlagsDef> = { [K in keyof F & string] : CollidingAliases<F, K> extends never ? F[K] : F[K] & {
175
+ type ValidateFlagAliases<F extends Record<string, unknown>> = { [K in keyof F & string] : CollidingAliases<F, K> extends never ? F[K] : F[K] & {
164
176
  readonly FIX_ALIAS_COLLISION: `Alias "${CollidingAliases<F, K>}" collides with another flag name or alias`;
165
177
  } };
166
178
  /**
167
179
  * Per-arg validation tuple type. Resolves to `A` when the constraint is
168
180
  * satisfied (only the last arg is variadic). For non-last args that have
169
- * `variadic: true`, adds a branded error property to the specific arg:
181
+ * `variadic: true`, adds a branded error property to the specific arg.
182
+ *
183
+ * Generalized to work with any ordered tuple of object-typed definitions —
184
+ * core uses it with `ArgsDef`, the validate package uses it with
185
+ * `ArgSpec[]`, etc. Uses `readonly object[]` to avoid TypeScript's weak
186
+ * type detection (all-optional constraint rejection).
170
187
  *
171
188
  * ```
172
189
  * Property 'FIX_VARIADIC_POSITION' is missing in type '{ name: "files"; ... variadic: true }'
@@ -174,11 +191,11 @@ type ValidateFlagAliases<F extends FlagsDef> = { [K in keyof F & string] : Colli
174
191
  * '{ readonly FIX_VARIADIC_POSITION: "Only the last positional argument can be variadic" }'.
175
192
  * ```
176
193
  */
177
- type ValidateVariadicArgs<A extends ArgsDef> = A extends readonly [infer Head extends ArgDef, ...infer Tail extends readonly ArgDef[]] ? Tail extends readonly [ArgDef, ...ArgDef[]] ? Head extends {
194
+ type ValidateVariadicArgs<A extends readonly object[]> = A extends readonly [infer Head, ...infer Tail extends readonly object[]] ? Tail extends readonly [unknown, ...unknown[]] ? Head extends {
178
195
  variadic: true;
179
196
  } ? readonly [Head & {
180
197
  readonly FIX_VARIADIC_POSITION: "Only the last positional argument can be variadic";
181
- }, ...ValidateVariadicArgs<readonly [...Tail]>] : readonly [Head, ...ValidateVariadicArgs<readonly [...Tail]>] : readonly [Head] : A;
198
+ }, ...ValidateVariadicArgs<Tail>] : readonly [Head, ...ValidateVariadicArgs<Tail>] : readonly [Head] : A;
182
199
  /**
183
200
  * Infer the resolved type for a single ArgDef:
184
201
  *
@@ -377,9 +394,15 @@ interface CommandNotFoundErrorDetails {
377
394
  commandPath: string[];
378
395
  parentCommand: AnyCommand;
379
396
  }
397
+ interface ValidationErrorDetails {
398
+ issues: readonly {
399
+ readonly message: string;
400
+ readonly path: string;
401
+ }[];
402
+ }
380
403
  interface CrustErrorDetailsMap {
381
404
  DEFINITION: undefined;
382
- VALIDATION: undefined;
405
+ VALIDATION: ValidationErrorDetails | undefined;
383
406
  PARSE: undefined;
384
407
  EXECUTION: undefined;
385
408
  COMMAND_NOT_FOUND: CommandNotFoundErrorDetails;
@@ -439,7 +462,7 @@ declare class CrustError<C extends CrustErrorCode = CrustErrorCode> extends Erro
439
462
  readonly details: CrustErrorDetails<C>;
440
463
  /** Optional wrapped original error/value */
441
464
  cause?: unknown;
442
- constructor(code: C, message: string, ...details: CrustErrorDetails<C> extends undefined ? [] | [undefined] : [CrustErrorDetails<C>]);
465
+ constructor(code: C, message: string, ...details: undefined extends CrustErrorDetails<C> ? [] | [CrustErrorDetails<C>] : [CrustErrorDetails<C>]);
443
466
  is<T extends CrustErrorCode>(code: T): this is CrustError<T>;
444
467
  withCause(cause: unknown): this;
445
468
  }
@@ -539,4 +562,4 @@ interface RunOptions {
539
562
  }
540
563
  declare function runCommand(command: AnyCommand, options?: RunOptions): Promise<void>;
541
564
  declare function runMain(command: AnyCommand, options?: RunOptions): Promise<void>;
542
- export { runMain, runCommand, resolveCommand, parseArgs, defineCommand, SetupContext, RunOptions, PluginMiddleware, ParseResult, MiddlewareContext, InferFlags, InferArgs, FlagsDef, FlagDef, CrustPlugin, CrustErrorCode, CrustError, CommandRoute, CommandNotFoundErrorDetails, CommandMeta, CommandDef, CommandContext, Command, ArgsDef, ArgDef, AnyCommand };
565
+ export { runMain, runCommand, resolveCommand, parseArgs, defineCommand, ValidateVariadicArgs, ValidateFlagAliases, SetupContext, RunOptions, PluginMiddleware, ParseResult, MiddlewareContext, InferFlags, InferArgs, FlagsDef, FlagDef, CrustPlugin, CrustErrorCode, CrustError, CommandRoute, CommandNotFoundErrorDetails, CommandMeta, CommandDef, CommandContext, Command, ArgsDef, ArgDef, AnyCommand };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crustjs/core",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Core library for the Crust CLI framework",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -41,10 +41,10 @@
41
41
  "test": "bun test"
42
42
  },
43
43
  "devDependencies": {
44
- "@crustjs/config": "workspace:*",
45
- "bunup": "catalog:"
44
+ "@crustjs/config": "0.0.0",
45
+ "bunup": "^0.16.29"
46
46
  },
47
47
  "peerDependencies": {
48
- "typescript": "catalog:"
48
+ "typescript": "^5"
49
49
  }
50
50
  }