@crustjs/core 0.5.0 → 0.5.2

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.
@@ -569,7 +569,7 @@ type RunOutcome<Result> = {
569
569
  readonly status: "completed";
570
570
  readonly result: Result;
571
571
  } | {
572
- readonly status: "finished";
572
+ readonly status: "handled";
573
573
  readonly by: ExtensionId;
574
574
  } | {
575
575
  readonly status: "failed";
@@ -579,12 +579,13 @@ type RunOutcome<Result> = {
579
579
  type CommandTree = Record<string, CommandShape>;
580
580
  /** Every valid path through a command tree, including the root path (`[]`). */
581
581
  type CommandPath<Tree extends object, Depth extends readonly unknown[] = readonly []> = Depth["length"] extends 15 ? readonly string[] : string extends keyof Tree ? readonly string[] : readonly [] | { [K in keyof Tree & string]: Tree[K] extends CommandShape ? readonly [K, ...CommandPath<Tree[K]["children"], readonly [...Depth, unknown]>] : never; }[keyof Tree & string];
582
- type KnownCommandPath<Path extends readonly string[], Tree> = string extends keyof Tree ? Path : IsStaticTuple<Path> extends true ? string extends Path[number] ? never : Path : never;
582
+ type CommandPathContinuations<Path extends readonly string[], Tree extends object, Prefix extends readonly string[] = readonly []> = Path extends readonly [infer Head extends string, ...infer Tail extends readonly string[]] ? readonly [...Prefix, Head] extends CommandPath<Tree> ? CommandPathContinuations<Tail, Tree, readonly [...Prefix, Head]> : Extract<CommandPath<Tree>, readonly [...Prefix, ...string[]]> : Extract<CommandPath<Tree>, readonly [...Prefix, ...string[]]>;
583
+ type KnownCommandPath<Path extends readonly string[], Tree extends object> = string extends keyof Tree ? Path : IsStaticTuple<Path> extends true ? string extends Path[number] ? never : [Path] extends [CommandPath<Tree>] ? Path : CommandPathContinuations<Path, Tree> : number extends Path["length"] ? CommandPath<Tree> : never;
583
584
  /** Resolve the command shape at a typed path. */
584
585
  type CommandShapeAt<Shape extends CommandShape, Path extends readonly string[]> = Path extends readonly [infer Head, ...infer Tail extends readonly string[]] ? Head extends keyof Shape["children"] ? Shape["children"][Head] extends (infer Child extends CommandShape) ? CommandShapeAt<Child, Tail> : never : string extends Head ? CommandShape : never : Path extends readonly [] ? Shape : CommandShape;
585
- type RunSection<Name extends string, Values> = keyof Values extends never ? { [K in Name]?: never; } : {} extends Values ? { [K in Name]?: Values; } : { [K in Name]: Values; };
586
+ type RunSection<Name extends string, Values> = keyof Values extends never ? {} : {} extends Values ? { [K in Name]?: Values; } : { [K in Name]: Values; };
586
587
  /** Structured values bound directly against the selected command's definitions; no argv is produced. */
587
- type RunInput<Shape extends CommandShape> = RunSection<"args", ArgsDef extends Shape["args"] ? NonNullable<RunInputPayload["args"]> : InputArgs<Shape["args"]>> & RunSection<"flags", FlagsDef extends Shape["flags"] ? NonNullable<RunInputPayload["flags"]> : InputFlags<Shape["flags"]>> & {
588
+ type RunInput<Shape extends CommandShape> = RunSection<"args", ArgsDef extends Shape["args"] ? NonNullable<RunInputPayload["args"]> : InputArgs<Shape["args"]>> & RunSection<"flags", FlagsDef extends Shape["flags"] ? [keyof Shape["flags"]] extends [never] ? {} : NonNullable<RunInputPayload["flags"]> : InputFlags<Shape["flags"]>> & {
588
589
  readonly raw?: readonly string[];
589
590
  };
590
591
  type CompatibleRunValue<Expected, Actual> = Actual extends Expected ? Actual extends object ? Expected extends unknown ? Actual extends Expected ? Actual & { [K in Exclude<keyof Actual, keyof Expected>]: never; } & { [K in keyof Actual & keyof Expected]: CompatibleRunValue<Expected[K], Actual[K]>; } : never : never : Actual : JsonValue extends Expected ? Actual extends JsonCompatible<Actual> ? Actual : never : Expected extends unknown ? CompatibleRunBranch<Expected, Actual> : never;
@@ -592,6 +593,14 @@ type CompatibleRunBranch<Expected, Actual> = Actual extends Expected ? Actual :
592
593
  type CompatibleRunInput<Shape extends CommandShape, Input> = CompatibleRunValue<RunInput<Shape>, Input>;
593
594
  type RunInputArguments<Shape extends CommandShape> = {} extends RunInput<Shape> ? readonly [input?: RunInput<Shape>] : readonly [input: RunInput<Shape>];
594
595
  type RunArguments<Shape extends CommandShape> = readonly [...RunInputArguments<Shape>, options?: InvocationOptions];
596
+ type KeysOf<T> = T extends unknown ? keyof T : never;
597
+ type UnknownRunKeys<Actual, Known> = { [K in keyof Actual as string extends K ? never : number extends K ? never : K extends Known ? never : K]: Actual[K] extends undefined ? Actual[K] : never; };
598
+ type ClosedRunInput<Shape extends CommandShape, Input> = Input extends unknown ? UnknownRunKeys<Input, keyof RunInput<Shape>> & { [K in keyof Input as K extends ("args" | "flags") & keyof RunInput<Shape> ? K : never]: UnknownRunKeys<NonNullable<Input[K]>, KeysOf<NonNullable<RunInput<Shape>[K & keyof RunInput<Shape>]>>>; } : never;
599
+ type CheckedRunInput<Shape extends CommandShape, Input> = [Input] extends [ClosedRunInput<Shape, Input>] ? NonNullable<RunInputArguments<Shape>[0]> : Input & NoInfer<ClosedRunInput<Shape, Input>>;
600
+ type OmittableRunInput<Shape extends CommandShape> = {} extends RunInput<Shape> ? undefined : never;
601
+ type RunWithoutInputThis<Shape extends CommandShape, This> = [Shape] extends [never] ? This : {} extends RunInput<Shape> ? This : This & {
602
+ readonly FIX_MISSING_INPUT: "Pass the command's required arguments or flags";
603
+ };
595
604
  /**
596
605
  * Typed invoker bound to one command in an app, returned by {@link Crust.at}.
597
606
  *
@@ -601,7 +610,8 @@ type RunArguments<Shape extends CommandShape> = readonly [...RunInputArguments<S
601
610
  interface CommandHandle<Shape extends CommandShape> {
602
611
  /** The typed path this handle was created with (`[]` selects the root). */
603
612
  readonly path: readonly string[];
604
- run(...args: RunArguments<Shape>): Promise<RunOutcome<Shape["result"]>>;
613
+ run(this: RunWithoutInputThis<Shape, unknown>): Promise<RunOutcome<Shape["result"]>>;
614
+ run<const Input extends RunInput<Shape> | OmittableRunInput<Shape> = RunInput<Shape>>(input: CheckedRunInput<Shape, Input> | OmittableRunInput<Shape>, options?: InvocationOptions): Promise<RunOutcome<Shape["result"]>>;
605
615
  run<const Input>(input: Input, ...validation: [Input] extends [CompatibleRunInput<Shape, Input>] ? readonly [options?: InvocationOptions] : readonly [invalidInput: never]): Promise<RunOutcome<Shape["result"]>>;
606
616
  }
607
617
  /** Static configuration for a reusable command definition. */
@@ -899,21 +909,17 @@ declare class Crust<Flags extends FlagsDef = {}, A extends ArgsDef = [], Ctx ext
899
909
  */
900
910
  add<const Ds extends readonly CommandDefinition<any, any, any, any>[] = never>(...definitions: Ds & ValidateCommandDefinitions<Ds, Sibs> & ValidateDeclaredDeps<Ctx, Ds> & DefinitionDescendantValuesBrand<Ds, CollisionSp["demands"]> & ValidateDefinitionFlags<Ds, CollisionSp["extension"] | LocalSpellingsOf<CtxFlags>>): AfterAdd<Flags, A, Ctx, Sibs, Sp, Tree, CtxFlags, CollisionSp, Result, Ds, Meta, Caps>;
901
911
  /**
902
- * Define an app-local leaf subcommand inline (root-only sugar for
903
- * `.add(defineCommand(name, recipe))`).
912
+ * Define a subcommand inline (sugar for `.add(defineCommand(name, recipe))`),
913
+ * on the root or inside another command's recipe.
904
914
  *
905
915
  * The recipe builder is seeded with the Contexts and Context-owned flags
906
- * accumulated on this builder so far — the call site. Contexts provided
907
- * after `.command()` are not visible to it, matching the positional runtime
908
- * semantics of `.provide()`. Extract to `defineCommand` when a command needs
909
- * its own file, reuse, or a package. Recipe builders cannot call this
910
- * root-only method.
916
+ * accumulated on this builder so far — the call site. In a recipe, those are
917
+ * its `.use()` and `.provide()` Contexts. Contexts provided after `.command()`
918
+ * are not visible to it, matching the positional runtime semantics of
919
+ * `.provide()`. Extract to `defineCommand` when a command needs its own file
920
+ * or reuse.
911
921
  */
912
- command<const N extends string, B extends AnyCommandDefinitionBuilder>(this: {
913
- readonly _types: {
914
- readonly caps: "app";
915
- };
916
- }, name: N & CommandNameBrand<N> & CommandCollisionBrand<N, Sibs>, recipe: ((command: CommandDefinitionBuilder<{}, [], Ctx, never, LocalSpellingsOf<CtxFlags>, {}, CtxFlags>) => B & ShapeFlagCollisionBrand<ShapeOfBuilder<B>, CollisionSp["extension"]> & ValidateInlineCommandDeps<Ctx, NoInfer<B>>) & NoInfer<DescendantValuesBrand<{
922
+ command<const N extends string, B extends AnyCommandDefinitionBuilder>(name: N & CommandNameBrand<N> & CommandCollisionBrand<N, Sibs>, recipe: ((command: CommandDefinitionBuilder<{}, [], Ctx, never, LocalSpellingsOf<CtxFlags>, {}, CtxFlags>) => B & ShapeFlagCollisionBrand<ShapeOfBuilder<B>, CollisionSp["extension"]> & ValidateInlineCommandDeps<Ctx, NoInfer<B>>) & NoInfer<DescendantValuesBrand<{
917
923
  child: ShapeOfBuilder<B>;
918
924
  }, CollisionSp["demands"]>>): AfterAdd<Flags, A, Ctx, Sibs, Sp, Tree, CtxFlags, CollisionSp, Result, readonly [CommandDefinition<N, readonly [], ShapeOfBuilder<B>, DepsOfBuilder<B>>], Meta, Caps>;
919
925
  private _addDefinitions;
@@ -931,7 +937,7 @@ declare class Crust<Flags extends FlagsDef = {}, A extends ArgsDef = [], Ctx ext
931
937
  }): Promise<CommandSnapshot>;
932
938
  /**
933
939
  * Programmatically invoke a typed command, quietly capturing its output.
934
- * Returns completed, finished, or failed after cleanup without presenting errors.
940
+ * Returns completed, handled, or failed after cleanup without presenting errors.
935
941
  * Use {@link execute} as the streaming terminal adapter.
936
942
  *
937
943
  * @param path - Typed path to the command to invoke (`[]` selects the root)
@@ -940,16 +946,21 @@ declare class Crust<Flags extends FlagsDef = {}, A extends ArgsDef = [], Ctx ext
940
946
  * exposed to Command Actions and Extensions) and an
941
947
  * `AbortSignal` that cancels the invocation
942
948
  */
943
- run<const Path extends CommandPath<Tree>>(this: {
949
+ run<const Path extends readonly string[]>(this: RunWithoutInputThis<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>, {
950
+ readonly _types: {
951
+ readonly caps: "app";
952
+ };
953
+ }>, path: KnownCommandPath<Path, Tree>): Promise<RunOutcome<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>["result"]>>;
954
+ run<const Path extends readonly string[], const Input extends RunInput<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>> | OmittableRunInput<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>> = RunInput<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>>>(this: {
944
955
  readonly _types: {
945
956
  readonly caps: "app";
946
957
  };
947
- }, path: Path & KnownCommandPath<Path, Tree>, ...args: RunArguments<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>>): Promise<RunOutcome<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>["result"]>>;
948
- run<const Path extends CommandPath<Tree>, const Input>(this: {
958
+ }, path: KnownCommandPath<Path, Tree>, input: CheckedRunInput<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>, Input> | OmittableRunInput<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>>, options?: InvocationOptions): Promise<RunOutcome<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>["result"]>>;
959
+ run<const Path extends readonly string[], const Input>(this: {
949
960
  readonly _types: {
950
961
  readonly caps: "app";
951
962
  };
952
- }, path: Path & KnownCommandPath<Path, Tree>, input: Input, ...validation: [Input] extends [CompatibleRunInput<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, NoInfer<Path>>, Input>] ? readonly [options?: InvocationOptions] : readonly [invalidInput: never]): Promise<RunOutcome<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>["result"]>>;
963
+ }, path: KnownCommandPath<Path, Tree>, input: Input, ...validation: [Input] extends [CompatibleRunInput<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, NoInfer<Path>>, Input>] ? readonly [options?: InvocationOptions] : readonly [invalidInput: never]): Promise<RunOutcome<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>["result"]>>;
953
964
  /**
954
965
  * Bind a typed command path into a reusable {@link CommandHandle}.
955
966
  *
@@ -961,11 +972,11 @@ declare class Crust<Flags extends FlagsDef = {}, A extends ArgsDef = [], Ctx ext
961
972
  * @param path - Typed path to the command to bind (`[]` selects the root)
962
973
  * @throws {CrustError} COMMAND_NOT_FOUND when the path does not name a command
963
974
  */
964
- at<const Path extends CommandPath<Tree>>(this: {
975
+ at<const Path extends readonly string[]>(this: {
965
976
  readonly _types: {
966
977
  readonly caps: "app";
967
978
  };
968
- }, path: Path & KnownCommandPath<Path, Tree>): CommandHandle<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>>;
979
+ }, path: KnownCommandPath<Path, Tree>): CommandHandle<CommandShapeAt<CommandShape<A, Flags, Tree, Result>, Path>>;
969
980
  /**
970
981
  * Parse `process.argv`, resolve subcommands, run Extension hooks, and
971
982
  * execute the matched Command Action.
@@ -1111,15 +1122,15 @@ declare class CrustError<C extends CrustErrorCode = CrustErrorCode> extends Erro
1111
1122
  }
1112
1123
  //#endregion
1113
1124
  //#region src/api/extension.d.ts
1114
- declare const finishedBrand: unique symbol;
1115
- /** Opaque token returned by {@link ExtensionContext.finish} to end an invocation successfully. */
1116
- interface Finished {
1117
- readonly [finishedBrand]: true;
1125
+ declare const handledBrand: unique symbol;
1126
+ /** Opaque token returned by {@link ExtensionContext.handled} to end an invocation successfully. */
1127
+ interface Handled {
1128
+ readonly [handledBrand]: true;
1118
1129
  }
1119
1130
  type InvocationOutcome = {
1120
1131
  readonly status: "completed";
1121
1132
  } | {
1122
- readonly status: "finished";
1133
+ readonly status: "handled";
1123
1134
  readonly by: ExtensionId;
1124
1135
  } | {
1125
1136
  readonly status: "failed";
@@ -1234,20 +1245,20 @@ interface ExtensionContext<Defs extends readonly NamedExtensionFlagDef[] = [], D
1234
1245
  * @example
1235
1246
  * ```ts
1236
1247
  * preRun(ctx) {
1237
- * if (ctx.flags.help === true) return ctx.finish();
1248
+ * if (ctx.flags.help === true) return ctx.handled();
1238
1249
  * }
1239
1250
  * ```
1240
1251
  */
1241
- readonly finish: () => Finished;
1252
+ readonly handled: () => Handled;
1242
1253
  }
1243
1254
  interface ExtensionHooks<Defs extends readonly NamedExtensionFlagDef[] = [], Deps extends ContextMap = {}, MetaKeys extends RootMetaKey = never> {
1244
1255
  /**
1245
1256
  * Runs after routing and input binding (argv parsing for `execute()`, structured
1246
1257
  * binding for typed `run()`), before validation, in `.extend()` order.
1247
- * Return `ctx.finish()` to end the invocation successfully; later pre-run hooks,
1258
+ * Return `ctx.handled()` to end the invocation successfully; later pre-run hooks,
1248
1259
  * validation, schemas, Contexts, and the Command Action do not run.
1249
1260
  */
1250
- readonly preRun?: (ctx: ExtensionContext<Defs, Deps, MetaKeys>) => Awaitable<void | Finished>;
1261
+ readonly preRun?: (ctx: ExtensionContext<Defs, Deps, MetaKeys>) => Awaitable<void | Handled>;
1251
1262
  /**
1252
1263
  * Runs after the invocation settles, in reverse `.extend()` order. This is the
1253
1264
  * `finally` slot for cleanup and post-run side effects.
@@ -2201,4 +2212,4 @@ interface ContextBuilder<Name extends string, Use extends readonly AnyContextFac
2201
2212
  declare function defineContext<Name extends string>(name: Name): ContextBuilder<Name>;
2202
2213
  type FactoryValueOf<F extends AnyContextFactory> = F extends ContextFactory<any, any, infer Value, any, any> ? Awaited<Value> : never;
2203
2214
  //#endregion
2204
- export { CrustError as $, SectionConsumer as A, LocalFlagNameBrand as At, ExtensionBuilder as B, InvocationOptions as C, RunInputArguments as Ct, ParsedArgValue as D, CommandSnapshot as Dt, ParseResult as E, ArgSnapshot as Et, BuildArtifacts as F, defineExtensionId as Ft, ExtensionSectionContribution as G, ExtensionFactory as H, BuildFile as I, InvocationOutcome as J, Finished as K, BuildReport as L, ValueType as M, LocalValueBrand as Mt, FlagEnvironment as N, MergeContext as Nt, ParsedFlagValue as O, FlagSnapshot as Ot, parseFlagValues as P, ExtensionId as Pt, CommandNotFoundErrorDetails as Q, Extension as R, InvocationIO as S, RunInput as St, NamedFlagDef as T, defineCommand as Tt, ExtensionFlagDef as U, ExtensionContext as V, ExtensionHooks as W, RootMetaKey as X, NamedExtensionFlagDef as Y, defineExtension as Z, ExecuteOptions as _, CommandTree as _t, ContextInstance as a, EnvErrorDetails as at, InputArgs as b, RootCommandMeta as bt, FactoryValueOf as c, ValidationErrorDetails as ct, ArgDef as d, CommandDefinition as dt, CrustErrorCode as et, ArgsDef as f, CommandDefinitionBuilder as ft, DeclaredDefault as g, CommandShapeAt as gt, CommandSectionInput as h, CommandShape as ht, ContextFactory as i, DefinitionErrorDetails as it, ValidatedInput as j, EmptyArgNameBrand as jt, SectionAudience as k, LocalFlagBrand as kt, contextSources as l, AnyCrust as lt, CommandSection as m, CommandPath as mt, ContextBag as n, CrustErrorDetailsMap as nt, ContextMap as o, EnvIssue as ot, CommandMeta as p, CommandHandle as pt, InferExtensionFlags as q, ContextBuilder as r, CrustErrorJson as rt, ContextSetup as s, ParseErrorDetails as st, AnyContextFactory as t, CrustErrorDetails as tt, defineContext as u, CommandConfig as ut, FlagDef as v, Crust as vt, MergeFlags as w, RunOutcome as wt, InputFlags as x, RunArguments as xt, FlagsDef as y, CrustCommandContext as yt, ExtensionBuildContext as z };
2215
+ export { CrustError as $, SectionConsumer as A, LocalFlagNameBrand as At, ExtensionBuilder as B, InvocationOptions as C, RunInputArguments as Ct, ParsedArgValue as D, CommandSnapshot as Dt, ParseResult as E, ArgSnapshot as Et, BuildArtifacts as F, defineExtensionId as Ft, ExtensionSectionContribution as G, ExtensionFactory as H, BuildFile as I, InvocationOutcome as J, Handled as K, BuildReport as L, ValueType as M, LocalValueBrand as Mt, FlagEnvironment as N, MergeContext as Nt, ParsedFlagValue as O, FlagSnapshot as Ot, parseFlagValues as P, ExtensionId as Pt, CommandNotFoundErrorDetails as Q, Extension as R, InvocationIO as S, RunInput as St, NamedFlagDef as T, defineCommand as Tt, ExtensionFlagDef as U, ExtensionContext as V, ExtensionHooks as W, RootMetaKey as X, NamedExtensionFlagDef as Y, defineExtension as Z, ExecuteOptions as _, CommandTree as _t, ContextInstance as a, EnvErrorDetails as at, InputArgs as b, RootCommandMeta as bt, FactoryValueOf as c, ValidationErrorDetails as ct, ArgDef as d, CommandDefinition as dt, CrustErrorCode as et, ArgsDef as f, CommandDefinitionBuilder as ft, DeclaredDefault as g, CommandShapeAt as gt, CommandSectionInput as h, CommandShape as ht, ContextFactory as i, DefinitionErrorDetails as it, ValidatedInput as j, EmptyArgNameBrand as jt, SectionAudience as k, LocalFlagBrand as kt, contextSources as l, AnyCrust as lt, CommandSection as m, CommandPath as mt, ContextBag as n, CrustErrorDetailsMap as nt, ContextMap as o, EnvIssue as ot, CommandMeta as p, CommandHandle as pt, InferExtensionFlags as q, ContextBuilder as r, CrustErrorJson as rt, ContextSetup as s, ParseErrorDetails as st, AnyContextFactory as t, CrustErrorDetails as tt, defineContext as u, CommandConfig as ut, FlagDef as v, Crust as vt, MergeFlags as w, RunOutcome as wt, InputFlags as x, RunArguments as xt, FlagsDef as y, CrustCommandContext as yt, ExtensionBuildContext as z };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as CrustError, A as SectionConsumer, At as LocalFlagNameBrand, B as ExtensionBuilder, C as InvocationOptions, Ct as RunInputArguments, D as ParsedArgValue, Dt as CommandSnapshot, E as ParseResult, Et as ArgSnapshot, F as BuildArtifacts, Ft as defineExtensionId, G as ExtensionSectionContribution, H as ExtensionFactory, I as BuildFile, J as InvocationOutcome, K as Finished, L as BuildReport, M as ValueType, Mt as LocalValueBrand, Nt as MergeContext, O as ParsedFlagValue, Ot as FlagSnapshot, Pt as ExtensionId, Q as CommandNotFoundErrorDetails, R as Extension, S as InvocationIO, St as RunInput, T as NamedFlagDef, Tt as defineCommand, U as ExtensionFlagDef, V as ExtensionContext, W as ExtensionHooks, X as RootMetaKey, Y as NamedExtensionFlagDef, Z as defineExtension, _ as ExecuteOptions, _t as CommandTree, a as ContextInstance, at as EnvErrorDetails, b as InputArgs, bt as RootCommandMeta, c as FactoryValueOf, ct as ValidationErrorDetails, d as ArgDef, dt as CommandDefinition, et as CrustErrorCode, f as ArgsDef, ft as CommandDefinitionBuilder, gt as CommandShapeAt, h as CommandSectionInput, ht as CommandShape, i as ContextFactory, it as DefinitionErrorDetails, j as ValidatedInput, jt as EmptyArgNameBrand, k as SectionAudience, kt as LocalFlagBrand, l as contextSources, lt as AnyCrust, m as CommandSection, mt as CommandPath, n as ContextBag, nt as CrustErrorDetailsMap, o as ContextMap, ot as EnvIssue, p as CommandMeta, pt as CommandHandle, q as InferExtensionFlags, r as ContextBuilder, rt as CrustErrorJson, s as ContextSetup, st as ParseErrorDetails, t as AnyContextFactory, tt as CrustErrorDetails, u as defineContext, ut as CommandConfig, v as FlagDef, vt as Crust, w as MergeFlags, wt as RunOutcome, x as InputFlags, xt as RunArguments, y as FlagsDef, yt as CrustCommandContext, z as ExtensionBuildContext } from "./context-WQZg1zaQ.js";
1
+ import { $ as CrustError, A as SectionConsumer, At as LocalFlagNameBrand, B as ExtensionBuilder, C as InvocationOptions, Ct as RunInputArguments, D as ParsedArgValue, Dt as CommandSnapshot, E as ParseResult, Et as ArgSnapshot, F as BuildArtifacts, Ft as defineExtensionId, G as ExtensionSectionContribution, H as ExtensionFactory, I as BuildFile, J as InvocationOutcome, K as Handled, L as BuildReport, M as ValueType, Mt as LocalValueBrand, Nt as MergeContext, O as ParsedFlagValue, Ot as FlagSnapshot, Pt as ExtensionId, Q as CommandNotFoundErrorDetails, R as Extension, S as InvocationIO, St as RunInput, T as NamedFlagDef, Tt as defineCommand, U as ExtensionFlagDef, V as ExtensionContext, W as ExtensionHooks, X as RootMetaKey, Y as NamedExtensionFlagDef, Z as defineExtension, _ as ExecuteOptions, _t as CommandTree, a as ContextInstance, at as EnvErrorDetails, b as InputArgs, bt as RootCommandMeta, c as FactoryValueOf, ct as ValidationErrorDetails, d as ArgDef, dt as CommandDefinition, et as CrustErrorCode, f as ArgsDef, ft as CommandDefinitionBuilder, gt as CommandShapeAt, h as CommandSectionInput, ht as CommandShape, i as ContextFactory, it as DefinitionErrorDetails, j as ValidatedInput, jt as EmptyArgNameBrand, k as SectionAudience, kt as LocalFlagBrand, l as contextSources, lt as AnyCrust, m as CommandSection, mt as CommandPath, n as ContextBag, nt as CrustErrorDetailsMap, o as ContextMap, ot as EnvIssue, p as CommandMeta, pt as CommandHandle, q as InferExtensionFlags, r as ContextBuilder, rt as CrustErrorJson, s as ContextSetup, st as ParseErrorDetails, t as AnyContextFactory, tt as CrustErrorDetails, u as defineContext, ut as CommandConfig, v as FlagDef, vt as Crust, w as MergeFlags, wt as RunOutcome, x as InputFlags, xt as RunArguments, y as FlagsDef, yt as CrustCommandContext, z as ExtensionBuildContext } from "./context-VtqvNs9V.js";
2
2
  import { resolveArtifactDir } from "@crustjs/utils/artifacts";
3
3
  //#region src/api/flags.d.ts
4
4
  /** Distribute `Omit<_, "name">` over the {@link ArgDef} union. */
@@ -20,4 +20,4 @@ export declare function defineFlag<const N extends string, const D extends FlagD
20
20
  /** Define and own one positional argument; layout belongs to its consuming command. */
21
21
  export declare function defineArg<const N extends string, const D extends UnnamedArgDef>(name: N & EmptyArgNameBrand<N>, def: D & LocalValueBrand<D>): Named<N, D>;
22
22
  //#endregion
23
- export { type AnyContextFactory, type AnyCrust, type ArgDef, type ArgSnapshot, type ArgsDef, type BuildArtifacts, type BuildFile, type BuildReport, type CommandConfig, type CommandDefinition, type CommandDefinitionBuilder, type CommandHandle, type CommandMeta, type CommandNotFoundErrorDetails, type CommandPath, type CommandSection, type CommandSectionInput, type CommandShape, type CommandShapeAt, type CommandSnapshot, type CommandTree, type ContextBag, type ContextBuilder, type ContextFactory, type ContextInstance, type ContextMap, type ContextSetup, Crust, type CrustCommandContext, CrustError, type CrustErrorCode, type CrustErrorDetails, type CrustErrorDetailsMap, type CrustErrorJson, type DefinitionErrorDetails, type EnvErrorDetails, type EnvIssue, type ExecuteOptions, type Extension, type ExtensionBuildContext, type ExtensionBuilder, type ExtensionContext, type ExtensionFactory, type ExtensionFlagDef, type ExtensionHooks, type ExtensionId, type ExtensionSectionContribution, type FactoryValueOf, type Finished, type FlagDef, type FlagSnapshot, type FlagsDef, type InferExtensionFlags, type InputArgs, type InputFlags, type InvocationIO, type InvocationOptions, type InvocationOutcome, type MergeContext, type MergeFlags, type NamedExtensionFlagDef, type NamedFlagDef, type ParseErrorDetails, type ParseResult, type ParsedArgValue, type ParsedFlagValue, type RootCommandMeta, type RootMetaKey, type RunArguments, type RunInput, type RunInputArguments, type RunOutcome, type SectionAudience, type SectionConsumer, type UnnamedArgDef, type ValidatedInput, type ValidationErrorDetails, type ValueType, contextSources, defineCommand, defineContext, defineExtension, defineExtensionId, resolveArtifactDir };
23
+ export { type AnyContextFactory, type AnyCrust, type ArgDef, type ArgSnapshot, type ArgsDef, type BuildArtifacts, type BuildFile, type BuildReport, type CommandConfig, type CommandDefinition, type CommandDefinitionBuilder, type CommandHandle, type CommandMeta, type CommandNotFoundErrorDetails, type CommandPath, type CommandSection, type CommandSectionInput, type CommandShape, type CommandShapeAt, type CommandSnapshot, type CommandTree, type ContextBag, type ContextBuilder, type ContextFactory, type ContextInstance, type ContextMap, type ContextSetup, Crust, type CrustCommandContext, CrustError, type CrustErrorCode, type CrustErrorDetails, type CrustErrorDetailsMap, type CrustErrorJson, type DefinitionErrorDetails, type EnvErrorDetails, type EnvIssue, type ExecuteOptions, type Extension, type ExtensionBuildContext, type ExtensionBuilder, type ExtensionContext, type ExtensionFactory, type ExtensionFlagDef, type ExtensionHooks, type ExtensionId, type ExtensionSectionContribution, type FactoryValueOf, type FlagDef, type FlagSnapshot, type FlagsDef, type Handled, type InferExtensionFlags, type InputArgs, type InputFlags, type InvocationIO, type InvocationOptions, type InvocationOutcome, type MergeContext, type MergeFlags, type NamedExtensionFlagDef, type NamedFlagDef, type ParseErrorDetails, type ParseResult, type ParsedArgValue, type ParsedFlagValue, type RootCommandMeta, type RootMetaKey, type RunArguments, type RunInput, type RunInputArguments, type RunOutcome, type SectionAudience, type SectionConsumer, type UnnamedArgDef, type ValidatedInput, type ValidationErrorDetails, type ValueType, contextSources, defineCommand, defineContext, defineExtension, defineExtensionId, resolveArtifactDir };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as normalizeFlag, S as normalizeArg, _ as validateContextAvailability, a as runInvocation, b as validateCommandSections, c as cloneCommandNode, d as createCommandNode, f as registerFlag, g as definingOf, h as defineContext, i as resolveTypedPath, l as cloneFlagRegistry, m as contextSources, n as executeInvocation, o as snapshotCommand, p as defineExtension, r as prepareInvocation, u as installExtensionContexts, w as CrustError } from "./invocation-ljkrw2dt.js";
1
+ import { C as normalizeFlag, S as normalizeArg, _ as validateContextAvailability, a as runInvocation, b as validateCommandSections, c as cloneCommandNode, d as createCommandNode, f as registerFlag, g as definingOf, h as defineContext, i as resolveTypedPath, l as cloneFlagRegistry, m as contextSources, n as executeInvocation, o as snapshotCommand, p as defineExtension, r as prepareInvocation, u as installExtensionContexts, w as CrustError } from "./invocation-OsKzCgr-.js";
2
2
  import { resolveArtifactDir } from "@crustjs/utils/artifacts";
3
3
  //#region src/identity.ts
4
4
  /** Mint an Extension identity from any non-blank, trimmed string. */
@@ -307,54 +307,6 @@ function createContextFactory(name, use, ownedFlags, sections, setup) {
307
307
  function defineContext(name) {
308
308
  return createContextBuilder(name, Object.freeze([]), Object.freeze({}), Object.freeze([]));
309
309
  }
310
- function isDisposeCallback(value) {
311
- return typeof value === "function";
312
- }
313
- /**
314
- * Minimal `AsyncDisposableStack` stand-in for runtimes without the global
315
- * (Node 22): LIFO disposal of used resources and deferred callbacks,
316
- * preferring `Symbol.asyncDispose` over `Symbol.dispose`.
317
- *
318
- * ponytail: multiple disposal errors aggregate as `AggregateError` instead of
319
- * the native `SuppressedError` chain; delete this class when Node 22 leaves
320
- * the support floor.
321
- *
322
- * @internal Exported for unit testing and invocation wiring.
323
- */
324
- var FallbackAsyncDisposableStack = class {
325
- #entries = [];
326
- #disposed = false;
327
- #assertPending() {
328
- if (this.#disposed) throw new ReferenceError("AsyncDisposableStack is already disposed");
329
- }
330
- use(value) {
331
- this.#assertPending();
332
- const dispose = hasAsyncDispose(value) ? value[Symbol.asyncDispose] : value[Symbol.dispose];
333
- this.#entries.push(() => dispose.call(value));
334
- return value;
335
- }
336
- defer(onDisposeAsync) {
337
- this.#assertPending();
338
- if (!isDisposeCallback(onDisposeAsync)) throw new TypeError("defer callback is not callable");
339
- this.#entries.push(onDisposeAsync);
340
- }
341
- async [Symbol.asyncDispose]() {
342
- if (this.#disposed) return;
343
- this.#disposed = true;
344
- const errors = [];
345
- for (let index = this.#entries.length - 1; index >= 0; index--) try {
346
- await this.#entries[index]();
347
- } catch (error) {
348
- errors.push(error);
349
- }
350
- if (errors.length === 1) throw errors[0];
351
- if (errors.length > 1) throw new AggregateError(errors, "Disposal failed");
352
- }
353
- };
354
- const DisposalStack = globalThis.AsyncDisposableStack ?? FallbackAsyncDisposableStack;
355
- function hasAsyncDispose(value) {
356
- return typeof value[Symbol.asyncDispose] === "function";
357
- }
358
310
  function isDisposableValue(value) {
359
311
  if (value === null || typeof value !== "object" && typeof value !== "function") return false;
360
312
  const candidate = value;
@@ -514,10 +466,10 @@ function createContextResolver(contexts, io, disposal, signal) {
514
466
  }
515
467
  //#endregion
516
468
  //#region src/api/extension.ts
517
- const FINISHED = Object.freeze({ [Symbol("crust.finished")]: true });
469
+ const HANDLED = Object.freeze({ [Symbol("crust.handled")]: true });
518
470
  /** @internal */
519
- function finishInvocation() {
520
- return FINISHED;
471
+ function handledInvocation() {
472
+ return HANDLED;
521
473
  }
522
474
  function createExtension(state) {
523
475
  const flags = Object.freeze(toFlagsRecord(state.flags));
@@ -1242,7 +1194,7 @@ function bind(command, positionals, flagValues, coerceArg, coerceFlag) {
1242
1194
  *
1243
1195
  * This is a pure parse+coerce function — it never throws for missing required
1244
1196
  * values. Use {@link validateParsed} to enforce required constraints after
1245
- * extensions have had a chance to finish an invocation (e.g. `--help`).
1197
+ * extensions have had a chance to handle an invocation (e.g. `--help`).
1246
1198
  *
1247
1199
  * @param command - The command whose arg/flag definitions drive the parsing
1248
1200
  * @param argv - The argv array to parse (typically `process.argv.slice(2)`)
@@ -1565,62 +1517,6 @@ function resolveCommand(command, argv) {
1565
1517
  };
1566
1518
  }
1567
1519
  //#endregion
1568
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/usingCtx.js
1569
- function _usingCtx() {
1570
- var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
1571
- var n = Error();
1572
- return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
1573
- }, e = {}, n = [];
1574
- function using(r, e) {
1575
- if (null != e) {
1576
- if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
1577
- if (r) var o = e[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
1578
- if (void 0 === o && (o = e[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r)) var t = o;
1579
- if ("function" != typeof o) throw new TypeError("Object is not disposable.");
1580
- t && (o = function o() {
1581
- try {
1582
- t.call(e);
1583
- } catch (r) {
1584
- return Promise.reject(r);
1585
- }
1586
- }), n.push({
1587
- v: e,
1588
- d: o,
1589
- a: r
1590
- });
1591
- } else r && n.push({
1592
- d: e,
1593
- a: r
1594
- });
1595
- return e;
1596
- }
1597
- return {
1598
- e,
1599
- u: using.bind(null, !1),
1600
- a: using.bind(null, !0),
1601
- d: function d() {
1602
- var o, t = this.e, s = 0;
1603
- function next() {
1604
- for (; o = n.pop();) try {
1605
- if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
1606
- if (o.d) {
1607
- var r = o.d.call(o.v);
1608
- if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
1609
- } else s |= 1;
1610
- } catch (r) {
1611
- return err(r);
1612
- }
1613
- if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
1614
- if (t !== e) throw t;
1615
- }
1616
- function err(n) {
1617
- return t = t !== e ? new r(n, t) : n, next();
1618
- }
1619
- return next();
1620
- }
1621
- };
1622
- }
1623
- //#endregion
1624
1520
  //#region src/command/invocation.ts
1625
1521
  const ignoreStreamError = () => {};
1626
1522
  /**
@@ -1672,7 +1568,7 @@ function isAbortError(error) {
1672
1568
  return error.name === "AbortError";
1673
1569
  }
1674
1570
  /**
1675
- * Structural: Node 22 bundles down-level `await using` to a plain `Error`
1571
+ * Structural: down-level bundles can implement `await using` with a plain `Error`
1676
1572
  * carrying `error`/`suppressed`, so `instanceof SuppressedError` cannot be used.
1677
1573
  */
1678
1574
  function isSuppressedError(error) {
@@ -1825,98 +1721,91 @@ function resolveStructuredInput(root, path, input) {
1825
1721
  }
1826
1722
  /** Resolve, parse, and run one invocation without rendering failures. */
1827
1723
  async function dispatch(input, prepared, io, signal, onExtensionContext, onFailure) {
1828
- try {
1829
- var _usingCtx$1 = _usingCtx();
1830
- const { rootNode, extensions } = prepared;
1831
- const { argv, route, parsed } = "argv" in input ? resolveArgvInput(rootNode, input.argv) : resolveStructuredInput(rootNode, input.path, input.input);
1832
- const resolvedNode = route.command;
1833
- const disposal = _usingCtx$1.a(new DisposalStack());
1834
- const contexts = resolvedNode.contexts.map(({ instance }) => instance);
1835
- const resolver = createContextResolver(contexts, io, disposal, signal);
1836
- const rootSnapshot = snapshotCommand(rootNode);
1837
- let commandSnapshot = rootSnapshot;
1838
- for (const name of route.commandPath.slice(1)) commandSnapshot = commandSnapshot.subCommands[name];
1839
- const extensionContext = Object.freeze({
1840
- argv: [...argv],
1841
- rootCommand: rootSnapshot,
1842
- command: commandSnapshot,
1843
- commandPath: Object.freeze([...route.commandPath]),
1844
- args: parsed.args,
1845
- flags: parsed.flags,
1724
+ const { rootNode, extensions } = prepared;
1725
+ const { argv, route, parsed } = "argv" in input ? resolveArgvInput(rootNode, input.argv) : resolveStructuredInput(rootNode, input.path, input.input);
1726
+ const resolvedNode = route.command;
1727
+ await using disposal = new AsyncDisposableStack();
1728
+ const contexts = resolvedNode.contexts.map(({ instance }) => instance);
1729
+ const resolver = createContextResolver(contexts, io, disposal, signal);
1730
+ const rootSnapshot = snapshotCommand(rootNode);
1731
+ let commandSnapshot = rootSnapshot;
1732
+ for (const name of route.commandPath.slice(1)) commandSnapshot = commandSnapshot.subCommands[name];
1733
+ const extensionContext = Object.freeze({
1734
+ argv: [...argv],
1735
+ rootCommand: rootSnapshot,
1736
+ command: commandSnapshot,
1737
+ commandPath: Object.freeze([...route.commandPath]),
1738
+ args: parsed.args,
1739
+ flags: parsed.flags,
1740
+ rawArgs: parsed.rawArgs,
1741
+ signal,
1742
+ ctx: resolver.bag(extensions.flatMap((extension) => extension.use)),
1743
+ handled: handledInvocation,
1744
+ stdout: io.stdout,
1745
+ stderr: io.stderr
1746
+ });
1747
+ onExtensionContext?.(extensionContext);
1748
+ const terminal = async () => {
1749
+ validateParsed(resolvedNode, parsed);
1750
+ const validated = await applySchemas(resolvedNode, parsed);
1751
+ resolver.setValidatedFlags(validated.flags);
1752
+ if (!resolvedNode.run) return;
1753
+ const context = {
1754
+ args: validated.args,
1755
+ flags: validated.flags,
1756
+ ctx: resolver.bag(contexts),
1846
1757
  rawArgs: parsed.rawArgs,
1847
1758
  signal,
1848
- ctx: resolver.bag(extensions.flatMap((extension) => extension.use)),
1849
- finish: finishInvocation,
1759
+ command: extensionContext.command,
1760
+ rootCommand: rootSnapshot,
1850
1761
  stdout: io.stdout,
1851
1762
  stderr: io.stderr
1852
- });
1853
- onExtensionContext?.(extensionContext);
1854
- const terminal = async () => {
1855
- validateParsed(resolvedNode, parsed);
1856
- const validated = await applySchemas(resolvedNode, parsed);
1857
- resolver.setValidatedFlags(validated.flags);
1858
- if (!resolvedNode.run) return;
1859
- const context = {
1860
- args: validated.args,
1861
- flags: validated.flags,
1862
- ctx: resolver.bag(contexts),
1863
- rawArgs: parsed.rawArgs,
1864
- signal,
1865
- command: extensionContext.command,
1866
- rootCommand: rootSnapshot,
1867
- stdout: io.stdout,
1868
- stderr: io.stderr
1869
- };
1870
- return await resolvedNode.run(context);
1871
1763
  };
1872
- let result;
1873
- let outcome = { status: "completed" };
1764
+ return await resolvedNode.run(context);
1765
+ };
1766
+ let result;
1767
+ let outcome = { status: "completed" };
1768
+ try {
1874
1769
  try {
1875
- try {
1876
- for (const extension of extensions) if (await extension.hooks?.preRun?.(extensionContext) === finishInvocation()) {
1877
- outcome = {
1878
- status: "finished",
1879
- by: extension.id
1880
- };
1881
- break;
1882
- }
1883
- if (outcome.status !== "finished") result = await terminal();
1884
- } catch (error) {
1885
- const by = await onFailure?.(error, extensionContext);
1770
+ for (const extension of extensions) if (await extension.hooks?.preRun?.(extensionContext) === handledInvocation()) {
1886
1771
  outcome = {
1887
- status: "failed",
1888
- error,
1889
- ...by === void 0 ? {} : { by }
1772
+ status: "handled",
1773
+ by: extension.id
1890
1774
  };
1775
+ break;
1891
1776
  }
1892
- Object.freeze(outcome);
1893
- let postRunFailed = false;
1894
- let postRunError;
1895
- for (const extension of extensions.toReversed()) try {
1896
- await extension.hooks?.postRun?.(extensionContext, outcome);
1897
- } catch (error) {
1898
- if (outcome.status !== "failed" && !postRunFailed) {
1899
- postRunFailed = true;
1900
- postRunError = error;
1901
- }
1777
+ if (outcome.status !== "handled") result = await terminal();
1778
+ } catch (error) {
1779
+ const by = await onFailure?.(error, extensionContext);
1780
+ outcome = {
1781
+ status: "failed",
1782
+ error,
1783
+ ...by === void 0 ? {} : { by }
1784
+ };
1785
+ }
1786
+ Object.freeze(outcome);
1787
+ let postRunFailed = false;
1788
+ let postRunError;
1789
+ for (const extension of extensions.toReversed()) try {
1790
+ await extension.hooks?.postRun?.(extensionContext, outcome);
1791
+ } catch (error) {
1792
+ if (outcome.status !== "failed" && !postRunFailed) {
1793
+ postRunFailed = true;
1794
+ postRunError = error;
1902
1795
  }
1903
- if (outcome.status === "failed") throw outcome.error;
1904
- if (postRunFailed) throw postRunError;
1905
- } finally {
1906
- await resolver.settle();
1907
1796
  }
1908
- return outcome.status === "finished" ? {
1909
- status: "finished",
1910
- by: outcome.by
1911
- } : {
1912
- status: "completed",
1913
- result
1914
- };
1915
- } catch (_) {
1916
- _usingCtx$1.e = _;
1797
+ if (outcome.status === "failed") throw outcome.error;
1798
+ if (postRunFailed) throw postRunError;
1917
1799
  } finally {
1918
- await _usingCtx$1.d();
1800
+ await resolver.settle();
1919
1801
  }
1802
+ return outcome.status === "handled" ? {
1803
+ status: "handled",
1804
+ by: outcome.by
1805
+ } : {
1806
+ status: "completed",
1807
+ result
1808
+ };
1920
1809
  }
1921
1810
  /** Render one failure through Extension onError hooks, ending in Core's default renderer. */
1922
1811
  async function renderFailure(error, argv, prepared, io, signal, extensionContext, silentDefault = false) {
@@ -1944,7 +1833,7 @@ async function renderFailure(error, argv, prepared, io, signal, extensionContext
1944
1833
  flags: Object.freeze({}),
1945
1834
  rawArgs: [],
1946
1835
  signal,
1947
- finish: finishInvocation,
1836
+ handled: handledInvocation,
1948
1837
  stdout: io.stdout,
1949
1838
  stderr: io.stderr,
1950
1839
  ctx: unavailableContext
package/dist/tooling.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Dt as CommandSnapshot, N as FlagEnvironment, Ot as FlagSnapshot, P as parseFlagValues, Pt as ExtensionId, g as DeclaredDefault, m as CommandSection } from "./context-WQZg1zaQ.js";
1
+ import { Dt as CommandSnapshot, N as FlagEnvironment, Ot as FlagSnapshot, P as parseFlagValues, Pt as ExtensionId, g as DeclaredDefault, m as CommandSection } from "./context-VtqvNs9V.js";
2
2
  import { BUILD_OUT_DIR_ENV } from "@crustjs/utils/artifacts";
3
3
  //#region src/command/invocation.d.ts
4
4
  /**
package/dist/tooling.js CHANGED
@@ -1,4 +1,4 @@
1
- import { s as parseFlagValues, t as SNAPSHOT_PATH_ENV, v as isListed, x as visibleSectionsFor, y as sectionsFor } from "./invocation-ljkrw2dt.js";
1
+ import { s as parseFlagValues, t as SNAPSHOT_PATH_ENV, v as isListed, x as visibleSectionsFor, y as sectionsFor } from "./invocation-OsKzCgr-.js";
2
2
  import { BUILD_OUT_DIR_ENV } from "@crustjs/utils/artifacts";
3
3
  //#region src/command/documentation.ts
4
4
  function isNonFiniteNumber(value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crustjs/core",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Core library for the Crust CLI framework",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -41,11 +41,11 @@
41
41
  "access": "public"
42
42
  },
43
43
  "dependencies": {
44
- "@crustjs/utils": "^0.2.0"
44
+ "@crustjs/utils": "^0.2.1"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@crustjs/config": "0.0.0",
48
- "vite-plus": "1.0.0-rc.0"
48
+ "vite-plus": "1.0.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "typescript": "^7.0.0"
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "engines": {
59
59
  "bun": ">=1.4.0",
60
- "node": ">=22",
60
+ "node": ">=24",
61
61
  "deno": ">=2.8"
62
62
  },
63
63
  "scripts": {