@crustjs/core 0.0.10 → 0.0.12
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
|
@@ -377,7 +377,7 @@ type MergeFlags<
|
|
|
377
377
|
type EffectiveFlags<
|
|
378
378
|
Inherited extends FlagsDef,
|
|
379
379
|
Local extends FlagsDef
|
|
380
|
-
> = MergeFlags<InheritableFlags<Inherited>, Local>;
|
|
380
|
+
> = string extends keyof Inherited ? Local : MergeFlags<InheritableFlags<Inherited>, Local>;
|
|
381
381
|
/**
|
|
382
382
|
* Infer the resolved type for a single ArgDef:
|
|
383
383
|
*
|
|
@@ -559,27 +559,6 @@ interface CommandNode {
|
|
|
559
559
|
postRun?: (ctx: unknown) => void | Promise<void>;
|
|
560
560
|
}
|
|
561
561
|
/**
|
|
562
|
-
* Creates a new `CommandNode` with all fields initialized to defaults.
|
|
563
|
-
*
|
|
564
|
-
* @param name - The command name.
|
|
565
|
-
* @returns A fresh `CommandNode` with empty flags, no args, no subcommands,
|
|
566
|
-
* no plugins, and no lifecycle handlers.
|
|
567
|
-
*/
|
|
568
|
-
declare function createCommandNode(name: string): CommandNode;
|
|
569
|
-
/**
|
|
570
|
-
* Merges inherited flags (only those with `inherit: true`) with local flags.
|
|
571
|
-
*
|
|
572
|
-
* Local flags override inherited flags with the same key. Non-inheritable
|
|
573
|
-
* flags from the parent are excluded entirely.
|
|
574
|
-
*
|
|
575
|
-
* This is the runtime counterpart of the `EffectiveFlags` utility type.
|
|
576
|
-
*
|
|
577
|
-
* @param inherited - The parent's effective flags (or any FlagsDef).
|
|
578
|
-
* @param local - The current command's locally-defined flags.
|
|
579
|
-
* @returns A new `FlagsDef` containing inherited+local merged flags.
|
|
580
|
-
*/
|
|
581
|
-
declare function computeEffectiveFlags(inherited: FlagsDef, local: FlagsDef): FlagsDef;
|
|
582
|
-
/**
|
|
583
562
|
* The runtime context object passed to `preRun()`, `run()`, and `postRun()`
|
|
584
563
|
* lifecycle hooks on the `Crust` builder.
|
|
585
564
|
*
|
|
@@ -615,6 +594,7 @@ declare const VALIDATION_MODE_ENV = "CRUST_INTERNAL_VALIDATE_ONLY";
|
|
|
615
594
|
* - `Inherited` — flags inherited from a parent command (populated by `.command()`)
|
|
616
595
|
* - `Local` — flags defined on this command via `.flags()`
|
|
617
596
|
* - `A` — positional argument definitions
|
|
597
|
+
* - `Eff` — effective flags (merged inherited + local flags, computed internally)
|
|
618
598
|
*
|
|
619
599
|
* @example
|
|
620
600
|
* ```ts
|
|
@@ -631,13 +611,15 @@ declare const VALIDATION_MODE_ENV = "CRUST_INTERNAL_VALIDATE_ONLY";
|
|
|
631
611
|
declare class Crust<
|
|
632
612
|
Inherited extends FlagsDef = FlagsDef,
|
|
633
613
|
Local extends FlagsDef = FlagsDef,
|
|
634
|
-
A extends ArgsDef = ArgsDef
|
|
614
|
+
A extends ArgsDef = ArgsDef,
|
|
615
|
+
Eff extends FlagsDef = EffectiveFlags<Inherited, Local>
|
|
635
616
|
> {
|
|
636
617
|
/** @internal — Phantom property exposing generic parameters for type-level testing */
|
|
637
618
|
readonly _types: {
|
|
638
619
|
inherited: Inherited;
|
|
639
620
|
local: Local;
|
|
640
621
|
args: A;
|
|
622
|
+
effective: Eff;
|
|
641
623
|
};
|
|
642
624
|
/** @internal */
|
|
643
625
|
readonly _node: CommandNode;
|
|
@@ -654,7 +636,7 @@ declare class Crust<
|
|
|
654
636
|
* @internal — Create a child builder with pre-populated inherited flags.
|
|
655
637
|
* Used by `.command()` to propagate parent flags to the child.
|
|
656
638
|
*/
|
|
657
|
-
static _createChild<I extends FlagsDef>(name: string, inheritedFlags: FlagsDef): Crust<I, {}, []
|
|
639
|
+
static _createChild<I extends FlagsDef>(name: string, inheritedFlags: FlagsDef): Crust<I, {}, [], EffectiveFlags<I, {}>>;
|
|
658
640
|
/**
|
|
659
641
|
* @internal — Clone this builder with a new node, preserving generics.
|
|
660
642
|
*/
|
|
@@ -671,18 +653,22 @@ declare class Crust<
|
|
|
671
653
|
* @param meta - Metadata fields to set (description, usage)
|
|
672
654
|
* @returns A new `Crust` instance with updated metadata
|
|
673
655
|
*/
|
|
674
|
-
meta(meta: Omit<CommandMeta, "name">): Crust<Inherited, Local, A>;
|
|
656
|
+
meta(meta: Omit<CommandMeta, "name">): Crust<Inherited, Local, A, Eff>;
|
|
675
657
|
/**
|
|
676
658
|
* Define local flags for this command.
|
|
677
659
|
*
|
|
678
660
|
* Returns a new builder with updated local flag types. The original
|
|
679
661
|
* builder is not mutated.
|
|
680
662
|
*
|
|
663
|
+
* NOTE: Compile-time inherited/local cross-collision checks are intentionally
|
|
664
|
+
* omitted here to reduce TypeScript type-check cost in large projects.
|
|
665
|
+
* Runtime collision checks still run during parsing and command-tree validation.
|
|
666
|
+
*
|
|
681
667
|
* @param defs - Flag definitions record
|
|
682
668
|
* @returns A new `Crust` instance with the given flags
|
|
683
669
|
* @throws {CrustError} `DEFINITION` if flag names/aliases violate constraints
|
|
684
670
|
*/
|
|
685
|
-
flags<const F extends FlagsDef>(defs: F & ValidateNoPrefixedFlags<ValidateFlagAliases<F>>
|
|
671
|
+
flags<const F extends FlagsDef>(defs: F & ValidateNoPrefixedFlags<ValidateFlagAliases<F>>): Crust<Inherited, F, A, EffectiveFlags<Inherited, F>>;
|
|
686
672
|
/**
|
|
687
673
|
* Define positional arguments for this command.
|
|
688
674
|
*
|
|
@@ -692,7 +678,7 @@ declare class Crust<
|
|
|
692
678
|
* @param defs - Ordered tuple of positional argument definitions
|
|
693
679
|
* @returns A new `Crust` instance with the given args
|
|
694
680
|
*/
|
|
695
|
-
args<const NewA extends ArgsDef>(defs: NewA & ValidateVariadicArgs<NewA>): Crust<Inherited, Local, NewA>;
|
|
681
|
+
args<const NewA extends ArgsDef>(defs: NewA & ValidateVariadicArgs<NewA>): Crust<Inherited, Local, NewA, Eff>;
|
|
696
682
|
/**
|
|
697
683
|
* Set the main command handler.
|
|
698
684
|
*
|
|
@@ -706,7 +692,7 @@ declare class Crust<
|
|
|
706
692
|
* @param handler - The main command handler function
|
|
707
693
|
* @returns A new `Crust` instance with the handler registered
|
|
708
694
|
*/
|
|
709
|
-
run(handler: (ctx: NoInfer<CrustCommandContext<A,
|
|
695
|
+
run(handler: (ctx: NoInfer<CrustCommandContext<A, Eff>>) => void | Promise<void>): Crust<Inherited, Local, A, Eff>;
|
|
710
696
|
/**
|
|
711
697
|
* Set the pre-run lifecycle hook.
|
|
712
698
|
*
|
|
@@ -716,7 +702,7 @@ declare class Crust<
|
|
|
716
702
|
* @param handler - The pre-run handler function
|
|
717
703
|
* @returns A new `Crust` instance with the preRun handler registered
|
|
718
704
|
*/
|
|
719
|
-
preRun(handler: (ctx: NoInfer<CrustCommandContext<A,
|
|
705
|
+
preRun(handler: (ctx: NoInfer<CrustCommandContext<A, Eff>>) => void | Promise<void>): Crust<Inherited, Local, A, Eff>;
|
|
720
706
|
/**
|
|
721
707
|
* Set the post-run lifecycle hook.
|
|
722
708
|
*
|
|
@@ -726,7 +712,7 @@ declare class Crust<
|
|
|
726
712
|
* @param handler - The post-run handler function
|
|
727
713
|
* @returns A new `Crust` instance with the postRun handler registered
|
|
728
714
|
*/
|
|
729
|
-
postRun(handler: (ctx: NoInfer<CrustCommandContext<A,
|
|
715
|
+
postRun(handler: (ctx: NoInfer<CrustCommandContext<A, Eff>>) => void | Promise<void>): Crust<Inherited, Local, A, Eff>;
|
|
730
716
|
/**
|
|
731
717
|
* Register a plugin on this command.
|
|
732
718
|
*
|
|
@@ -740,7 +726,7 @@ declare class Crust<
|
|
|
740
726
|
* @param plugin - The plugin to register
|
|
741
727
|
* @returns A new `Crust` instance with the plugin registered
|
|
742
728
|
*/
|
|
743
|
-
use(plugin: CrustPlugin): Crust<Inherited, Local, A>;
|
|
729
|
+
use(plugin: CrustPlugin): Crust<Inherited, Local, A, Eff>;
|
|
744
730
|
/**
|
|
745
731
|
* Create a subcommand builder pre-typed with this command's inheritable flags.
|
|
746
732
|
*
|
|
@@ -773,7 +759,7 @@ declare class Crust<
|
|
|
773
759
|
* app.command(deployCmd).execute();
|
|
774
760
|
* ```
|
|
775
761
|
*/
|
|
776
|
-
sub<N extends string>(name: N): Crust<
|
|
762
|
+
sub<N extends string>(name: N): Crust<Eff, {}, [], EffectiveFlags<Eff, {}>>;
|
|
777
763
|
/**
|
|
778
764
|
* Register a named subcommand via inline callback.
|
|
779
765
|
*
|
|
@@ -786,7 +772,7 @@ declare class Crust<
|
|
|
786
772
|
* @returns A new `Crust` instance with the subcommand registered
|
|
787
773
|
* @throws {CrustError} `DEFINITION` if name is empty or already registered
|
|
788
774
|
*/
|
|
789
|
-
command<N extends string>(name: N, cb: (cmd: Crust<
|
|
775
|
+
command<N extends string>(name: N, cb: (cmd: Crust<Eff, {}, [], EffectiveFlags<Eff, {}>>) => Crust<any, any, any>): Crust<Inherited, Local, A, Eff>;
|
|
790
776
|
/**
|
|
791
777
|
* Register a pre-built subcommand builder (from `.sub()`).
|
|
792
778
|
*
|
|
@@ -798,7 +784,7 @@ declare class Crust<
|
|
|
798
784
|
* @returns A new `Crust` instance with the subcommand registered
|
|
799
785
|
* @throws {CrustError} `DEFINITION` if builder name is empty or already registered
|
|
800
786
|
*/
|
|
801
|
-
command(builder: Crust<any, any, any>): Crust<Inherited, Local, A>;
|
|
787
|
+
command(builder: Crust<any, any, any>): Crust<Inherited, Local, A, Eff>;
|
|
802
788
|
/**
|
|
803
789
|
* Parse `process.argv`, resolve subcommands, run plugins and middleware,
|
|
804
790
|
* and execute the matched command handler.
|
|
@@ -906,4 +892,4 @@ declare function parseArgs<
|
|
|
906
892
|
A extends ArgsDef = ArgsDef,
|
|
907
893
|
F extends FlagsDef = FlagsDef
|
|
908
894
|
>(command: CommandNode, argv: string[]): ParseResult<A, F>;
|
|
909
|
-
export { resolveCommand, parseArgs,
|
|
895
|
+
export { resolveCommand, parseArgs, ValueType, ValidateVariadicArgs, ValidateNoPrefixedFlags, ValidateFlagAliases, ValidateCrossCollisions, VALIDATION_MODE_ENV, SetupContext, SetupActions, PluginMiddleware, ParseResult, MiddlewareContext, MergeFlags, InheritableFlags, InferFlags, InferArgs, FlagsDef, FlagDef, EffectiveFlags, CrustPlugin, CrustErrorCode, CrustError, CrustCommandContext, Crust, CommandRoute, CommandNode, CommandMeta, ArgsDef, ArgDef };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{a as P,b as Z,c as
|
|
2
|
+
import{a as P,b as Z,c as R}from"./shared/chunk-j245q9xa.js";function _(j){return{meta:{name:j},localFlags:{},effectiveFlags:{},args:void 0,subCommands:{},plugins:[],preRun:void 0,run:void 0,postRun:void 0}}function D(j,q){let J={};for(let[Q,$]of Object.entries(j))if($.inherit===!0)J[Q]=$;for(let[Q,$]of Object.entries(q))J[Q]=$;return J}function I(j,q){let J=[j.meta.name],Q=j,$=q;while($.length>0){let G=Q.subCommands;if(!G||Object.keys(G).length===0)break;let X=$[0];if(!X||X.startsWith("-"))break;if(X in G&&G[X]){Q=G[X],J.push(X),$=$.slice(1);continue}if(Q.run)break;let U=Object.keys(G);throw new Z("COMMAND_NOT_FOUND",`Unknown command "${X}".`,{input:X,available:U,commandPath:[...J],parentCommand:Q})}return{command:Q,argv:$,commandPath:J}}function F(j){for(let[q,J]of Object.entries(j)){if(q.startsWith("no-")){let Q=q.slice(3);throw new Z("DEFINITION",`Flag "--${q}" must not use "no-" prefix; define "${Q}" and negate with "--no-${Q}"`)}if(J.short?.startsWith("no-"))throw new Z("DEFINITION",`Short alias "-${J.short}" on "--${q}" must not use "no-" prefix (reserved for negation)`);if(J.aliases){for(let Q of J.aliases)if(Q.startsWith("no-"))throw new Z("DEFINITION",`Alias "--${Q}" on "--${q}" must not use "no-" prefix (reserved for negation)`)}}}var S="CRUST_INTERNAL_VALIDATE_ONLY",O="__CRUST_VALIDATE_RESULT__";function y(){let j=new Map;return{get(q){return j.get(q)},has(q){return j.has(q)},set(q,J){j.set(q,J)},delete(q){return j.delete(q)}}}function A(j){return{addFlag(q,J,Q){if(J in q.effectiveFlags)j?.push(`Plugin flag "--${J}" on "${q.meta.name}" overrides existing flag`);q.effectiveFlags[J]=Q},addSubCommand(q,J,Q){if(!J.trim())throw new Z("DEFINITION","addSubCommand: name must be a non-empty string");if(q.subCommands[J]){j?.push(`Plugin subcommand "${J}" on "${q.meta.name}" skipped (already exists)`);return}q.subCommands[J]=Q}}}async function x(j,q,J){for(let Q of j){if(!Q.setup)continue;await Q.setup(q,J)}}async function L(j,q,J){let Q=j.map((X)=>X.middleware).filter((X)=>Boolean(X)),$=-1,G=async(X)=>{if(X<=$)throw new Z("DEFINITION","Plugin middleware called next() multiple times");if($=X,X===Q.length){await J();return}let U=Q[X];if(!U)throw new Z("DEFINITION","Plugin middleware stack is invalid");await U(q,()=>G(X+1))};await G(0)}function T(j){let q=[...j.plugins];for(let J of Object.values(j.subCommands))q.push(...T(J));return q}function B(j){if(Object.freeze(j),Object.freeze(j.localFlags),Object.freeze(j.effectiveFlags),Object.freeze(j.meta),Object.freeze(j.plugins),j.args)Object.freeze(j.args);for(let q of Object.values(j.subCommands))B(q);Object.freeze(j.subCommands)}class V{_node;_inheritedFlags;constructor(j){if(!j.trim())throw new Z("DEFINITION","meta.name must be a non-empty string");this._node=_(j),this._inheritedFlags={}}static _createChild(j,q){let J=new V(j);return J._inheritedFlags=q,J}_clone(j){let q=Object.create(Object.getPrototypeOf(this)),J={...this._node,localFlags:{...this._node.localFlags},effectiveFlags:{...this._node.effectiveFlags},subCommands:{...this._node.subCommands},plugins:[...this._node.plugins],meta:{...this._node.meta},args:this._node.args?[...this._node.args]:void 0,...j};return q._node=J,q._inheritedFlags=this._inheritedFlags,q}meta(j){return this._clone({meta:{...this._node.meta,...j}})}flags(j){F(j);let q={};for(let[J,Q]of Object.entries(j))q[J]={...Q};return this._clone({localFlags:q,effectiveFlags:D(this._inheritedFlags,q)})}args(j){let q=j.map((J)=>({...J}));return this._clone({args:q})}run(j){return this._clone({run:j})}preRun(j){return this._clone({preRun:j})}postRun(j){return this._clone({postRun:j})}use(j){return this._clone({plugins:[...this._node.plugins,j]})}sub(j){if(!j.trim())throw new Z("DEFINITION","Subcommand name must be a non-empty string");let q=D(this._inheritedFlags,this._node.localFlags);return V._createChild(j,q)}command(j,q){if(typeof j==="string"){let G=j;if(!q)throw new Z("DEFINITION","command(name, cb) requires a callback");if(!G.trim())throw new Z("DEFINITION","Subcommand name must be a non-empty string");if(this._node.subCommands[G])throw new Z("DEFINITION",`Subcommand "${G}" is already registered`);let X=D(this._inheritedFlags,this._node.localFlags),U=V._createChild(G,X),Y=q(U),W={...Y._node,effectiveFlags:D(Y._inheritedFlags,Y._node.localFlags)};return this._clone({subCommands:{...this._node.subCommands,[G]:W}})}let J=j,Q=J._node.meta.name;if(!Q.trim())throw new Z("DEFINITION","Subcommand name must be a non-empty string");if(this._node.subCommands[Q])throw new Z("DEFINITION",`Subcommand "${Q}" is already registered`);let $={...J._node,effectiveFlags:D(J._inheritedFlags,J._node.localFlags)};return this._clone({subCommands:{...this._node.subCommands,[Q]:$}})}async execute(j){let q=j?.argv??process.argv.slice(2),J=this._node,Q=T(J),$=[],G=y(),X={argv:[...q],rootCommand:J,state:G},U=A($);try{await x(Q,X,U)}catch(W){if(W instanceof Z){console.error(`Error: ${W.message}`),process.exitCode=1;return}let H=W instanceof Error?W.message:String(W);console.error(`Error: ${H}`),process.exitCode=1;return}if(B(J),process.env[S]==="1"){let W=(async()=>{try{let{validateCommandTree:H}=await import("./shared/chunk-yk32fa98.js");H(J);for(let K of $)console.warn(`Warning: ${K}`);return{ok:!0}}catch(H){let K=H instanceof Error?H.message:String(H);return console.error(K),process.exitCode=1,{ok:!1,error:H}}})();return globalThis[O]=W,await W,process.exit(process.exitCode??0)}for(let W of $)console.warn(`Warning: ${W}`);let Y={argv:[...q],rootCommand:J,state:G,route:null,input:null};try{let W,H;try{let K=I(J,[...q]);Y.route=K,W=K.command,H=R(W,K.argv),Y.input=H}catch(K){await L(Q,Y,async()=>{throw K});return}await L(Q,Y,async()=>{if(!W.run)return;let K={args:H.args,flags:H.flags,rawArgs:H.rawArgs,command:W},M;try{if(W.preRun)await W.preRun(K);await W.run(K)}catch(z){M=z}if(W.postRun)try{await W.postRun(K)}catch(z){if(!M)M=z;else console.error(`Error in postRun: ${z instanceof Error?z.message:String(z)}`)}if(M)throw M})}catch(W){if(W instanceof Z){console.error(`Error: ${W.message}`),process.exitCode=1;return}if(W instanceof Error){let H=new Z("EXECUTION",W.message).withCause(W);console.error(`Error: ${H.message}`),process.exitCode=1;return}console.error(`Error: ${String(W)}`),process.exitCode=1}}}export{I as resolveCommand,R as parseArgs,S as VALIDATION_MODE_ENV,Z as CrustError,V as Crust};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{b as P,c as Q}from"./chunk-
|
|
2
|
+
import{b as P,c as Q}from"./chunk-j245q9xa.js";function M(B){switch(B.type){case"number":return"1";case"boolean":return"true";default:return"sample"}}function S(B){let z=[],K=B.effectiveFlags;for(let[j,G]of Object.entries(K)){if(G.required!==!0||G.default!==void 0)continue;if(z.push(`--${j}`),G.type!=="boolean")z.push(M(G))}let H=B.args;if(H)for(let j of H){if(j.required!==!0||j.default!==void 0)continue;z.push(M(j))}return z}function Y(B){let z=[{command:B,path:[B.meta.name]}],K=new Set;while(z.length>0){let H=z.pop();if(!H)break;let{command:j,path:G}=H;if(K.has(j))continue;K.add(j);try{Q(j,S(j))}catch(J){let L=J instanceof Error?J.message:"Unknown validation error";throw new P("DEFINITION",`Command "${G.join(" ")}" failed runtime validation: ${L}`).withCause(J)}for(let[J,L]of Object.entries(j.subCommands))z.push({command:L,path:[...G,J]})}}export{Y as validateCommandTree};
|
package/package.json
CHANGED
|
File without changes
|