@crustjs/core 0.0.12 → 0.0.14

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
@@ -644,8 +644,9 @@ declare class Crust<
644
644
  /**
645
645
  * Set metadata (description, usage) for this command.
646
646
  *
647
- * The command name is already set via the constructor or `.command()`,
648
- * so only `description` and `usage` can be provided here.
647
+ * The command name is already set by the builder source (constructor,
648
+ * `.sub()`, or the child builder passed into `.command(name, cb)`), so
649
+ * only `description` and `usage` can be provided here.
649
650
  *
650
651
  * Returns a new builder with updated metadata. The original builder
651
652
  * is not mutated.
@@ -774,11 +775,13 @@ declare class Crust<
774
775
  */
775
776
  command<N extends string>(name: N, cb: (cmd: Crust<Eff, {}, [], EffectiveFlags<Eff, {}>>) => Crust<any, any, any>): Crust<Inherited, Local, A, Eff>;
776
777
  /**
777
- * Register a pre-built subcommand builder (from `.sub()`).
778
+ * Register a pre-built subcommand builder.
778
779
  *
779
780
  * The builder's name (from its constructor or `.sub()`) is used as the
780
- * subcommand name. This is the complement to `.sub()` for the
781
- * file-splitting pattern.
781
+ * subcommand name. Builders created with `.sub()` inherit the parent's
782
+ * `inherit: true` flags; standalone `new Crust(name)` builders remain
783
+ * isolated. This is the complement to `.sub()` for the file-splitting
784
+ * pattern.
782
785
  *
783
786
  * @param builder - A pre-configured `Crust` builder instance
784
787
  * @returns A new `Crust` instance with the subcommand registered
@@ -881,15 +884,30 @@ declare class CrustError<C extends CrustErrorCode = CrustErrorCode> extends Erro
881
884
  *
882
885
  * Wraps Node's `util.parseArgs` with Crust's enhanced semantics:
883
886
  * positional arg mapping, type coercion, alias expansion, default values,
884
- * required validation, variadic args, and strict mode.
887
+ * variadic args, and strict mode.
888
+ *
889
+ * This is a pure parse+coerce function — it never throws for missing required
890
+ * values. Use {@link validateParsed} to enforce required constraints after
891
+ * middleware has had a chance to intercept (e.g. `--help`).
885
892
  *
886
893
  * @param command - The command whose arg/flag definitions drive the parsing
887
894
  * @param argv - The argv array to parse (typically `process.argv.slice(2)`)
888
895
  * @returns Parsed args, flags, and rawArgs (everything after `--`)
889
- * @throws {CrustError} On unknown flags, missing required args/flags, type coercion failure, or alias collisions
896
+ * @throws {CrustError} On unknown flags, type coercion failure, or alias collisions
890
897
  */
891
898
  declare function parseArgs<
892
899
  A extends ArgsDef = ArgsDef,
893
900
  F extends FlagsDef = FlagsDef
894
901
  >(command: CommandNode, argv: string[]): ParseResult<A, F>;
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 };
902
+ /**
903
+ * Validate a parse result against its command's required-value constraints.
904
+ *
905
+ * Separated from {@link parseArgs} so that middleware (e.g. `--help`) can
906
+ * inspect the parse result before validation errors are surfaced.
907
+ *
908
+ * @param command - The command whose definitions drive the validation
909
+ * @param parsed - The parse result from {@link parseArgs}
910
+ * @throws {CrustError} On missing required args or flags
911
+ */
912
+ declare function validateParsed(command: CommandNode, parsed: ParseResult): void;
913
+ export { validateParsed, 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 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};
2
+ import{a as O,b as $,c as D,d as I}from"./shared/chunk-vt64gs69.js";function B(j){return{meta:{name:j},localFlags:{},effectiveFlags:{},args:void 0,subCommands:{},plugins:[],preRun:void 0,run:void 0,postRun:void 0}}function M(j,q){let J={};for(let[Q,G]of Object.entries(j))if(G.inherit===!0)J[Q]=G;for(let[Q,G]of Object.entries(q))J[Q]=G;return J}function S(j,q){let J=[j.meta.name],Q=j,G=q;while(G.length>0){let H=Q.subCommands;if(!H||Object.keys(H).length===0)break;let Z=G[0];if(!Z||Z.startsWith("-"))break;if(Z in H&&H[Z]){Q=H[Z],J.push(Z),G=G.slice(1);continue}if(Q.run)break;let Y=Object.keys(H);throw new $("COMMAND_NOT_FOUND",`Unknown command "${Z}".`,{input:Z,available:Y,commandPath:[...J],parentCommand:Q})}return{command:Q,argv:G,commandPath:J}}function x(j){for(let[q,J]of Object.entries(j)){if(q.startsWith("no-")){let Q=q.slice(3);throw new $("DEFINITION",`Flag "--${q}" must not use "no-" prefix; define "${Q}" and negate with "--no-${Q}"`)}if(J.short?.startsWith("no-"))throw new $("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 $("DEFINITION",`Alias "--${Q}" on "--${q}" must not use "no-" prefix (reserved for negation)`)}}}var F="CRUST_INTERNAL_VALIDATE_ONLY",T=130,A="__CRUST_VALIDATE_RESULT__";function k(){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 _(j){if(!(j instanceof Error))return!1;return j.name==="CancelledError"}function b(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 $("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 w(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((Z)=>Z.middleware).filter((Z)=>Boolean(Z)),G=-1,H=async(Z)=>{if(Z<=G)throw new $("DEFINITION","Plugin middleware called next() multiple times");if(G=Z,Z===Q.length){await J();return}let Y=Q[Z];if(!Y)throw new $("DEFINITION","Plugin middleware stack is invalid");await Y(q,()=>H(Z+1))};await H(0)}function P(j){let q=[...j.plugins];for(let J of Object.values(j.subCommands))q.push(...P(J));return q}function y(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))y(q);Object.freeze(j.subCommands)}class R{_node;_inheritedFlags;constructor(j){if(!j.trim())throw new $("DEFINITION","meta.name must be a non-empty string");this._node=B(j),this._inheritedFlags={}}static _createChild(j,q){let J=new R(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){x(j);let q={};for(let[J,Q]of Object.entries(j))q[J]={...Q};return this._clone({localFlags:q,effectiveFlags:M(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 $("DEFINITION","Subcommand name must be a non-empty string");let q=M(this._inheritedFlags,this._node.localFlags);return R._createChild(j,q)}command(j,q){if(typeof j==="string"){let H=j;if(!q)throw new $("DEFINITION","command(name, cb) requires a callback");if(!H.trim())throw new $("DEFINITION","Subcommand name must be a non-empty string");if(this._node.subCommands[H])throw new $("DEFINITION",`Subcommand "${H}" is already registered`);let Z=M(this._inheritedFlags,this._node.localFlags),Y=R._createChild(H,Z),z=q(Y),W={...z._node,effectiveFlags:M(z._inheritedFlags,z._node.localFlags)};return this._clone({subCommands:{...this._node.subCommands,[H]:W}})}let J=j,Q=J._node.meta.name;if(!Q.trim())throw new $("DEFINITION","Subcommand name must be a non-empty string");if(this._node.subCommands[Q])throw new $("DEFINITION",`Subcommand "${Q}" is already registered`);let G={...J._node,effectiveFlags:M(J._inheritedFlags,J._node.localFlags)};return this._clone({subCommands:{...this._node.subCommands,[Q]:G}})}async execute(j){let q=j?.argv??process.argv.slice(2),J=this._node,Q=P(J),G=[],H=k(),Z={argv:[...q],rootCommand:J,state:H},Y=b(G);try{await w(Q,Z,Y)}catch(W){if(_(W)){process.exitCode=T;return}if(W instanceof $){console.error(`Error: ${W.message}`),process.exitCode=1;return}let K=W instanceof Error?W.message:String(W);console.error(`Error: ${K}`),process.exitCode=1;return}if(y(J),process.env[F]==="1"){let W=(async()=>{try{let{validateCommandTree:K}=await import("./shared/chunk-5apf3vnv.js");K(J);for(let U of G)console.warn(`Warning: ${U}`);return{ok:!0}}catch(K){let U=K instanceof Error?K.message:String(K);return console.error(U),process.exitCode=1,{ok:!1,error:K}}})();return globalThis[A]=W,await W,process.exit(process.exitCode??0)}for(let W of G)console.warn(`Warning: ${W}`);let z={argv:[...q],rootCommand:J,state:H,route:null,input:null};try{let W,K;try{let U=S(J,[...q]);z.route=U,W=U.command,K=D(W,U.argv),z.input=K}catch(U){await L(Q,z,async()=>{throw U});return}await L(Q,z,async()=>{if(I(W,K),!W.run)return;let U={args:K.args,flags:K.flags,rawArgs:K.rawArgs,command:W},V;try{if(W.preRun)await W.preRun(U);await W.run(U)}catch(X){V=X}if(W.postRun)try{await W.postRun(U)}catch(X){if(!V)V=X;else console.error(`Error in postRun: ${X instanceof Error?X.message:String(X)}`)}if(V)throw V})}catch(W){if(_(W)){process.exitCode=T;return}if(W instanceof $){console.error(`Error: ${W.message}`),process.exitCode=1;return}if(W instanceof Error){let K=new $("EXECUTION",W.message).withCause(W);console.error(`Error: ${K.message}`),process.exitCode=1;return}console.error(`Error: ${String(W)}`),process.exitCode=1}}}export{I as validateParsed,S as resolveCommand,D as parseArgs,F as VALIDATION_MODE_ENV,$ as CrustError,R as Crust};
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{b as Q,c as S,d as W}from"./chunk-vt64gs69.js";function M(B){switch(B.type){case"number":return"1";case"boolean":return"true";default:return"sample"}}function X(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 J=B.args;if(J)for(let j of J){if(j.required!==!0||j.default!==void 0)continue;z.push(M(j))}return z}function _(B){let z=[{command:B,path:[B.meta.name]}],K=new Set;while(z.length>0){let J=z.pop();if(!J)break;let{command:j,path:G}=J;if(K.has(j))continue;K.add(j);try{let H=S(j,X(j));W(j,H)}catch(H){let L=H instanceof Error?H.message:"Unknown validation error";throw new Q("DEFINITION",`Command "${G.join(" ")}" failed runtime validation: ${L}`).withCause(H)}for(let[H,L]of Object.entries(j.subCommands))z.push({command:L,path:[...G,H]})}}export{_ as validateCommandTree};
@@ -0,0 +1,3 @@
1
+ // @bun
2
+ var A=import.meta.require;class W extends Error{code;details;cause;constructor(B,J,...G){super(J);this.name="CrustError",this.code=B,this.details=G[0]}is(B){return this.code===B}withCause(B){return this.cause=B,this}}import{parseArgs as U}from"util";function q(B){let J={},G={};if(!B)return{options:J,aliasToName:G};let z=new Map;for(let j of Object.keys(B))z.set(j,j);for(let[j,H]of Object.entries(B)){if(j.startsWith("no-")){let L=j.slice(3);throw new W("DEFINITION",`Flag "--${j}" must not use "no-" prefix; define "${L}" and negate with "--no-${L}"`)}let K=H.type==="boolean"?"boolean":"string",Q={type:K};if(H.multiple)Q.multiple=!0;if(H.short){if(H.short.startsWith("no-"))throw new W("DEFINITION",`Short alias "-${H.short}" on "--${j}" must not use "no-" prefix (reserved for negation)`);let L=z.get(H.short);if(L)throw new W("DEFINITION",`Alias collision: "-${H.short}" is used by both "--${L}" and "--${j}"`);z.set(H.short,j),G[H.short]=j,Q.short=H.short}if(H.aliases)for(let L of H.aliases){if(L.startsWith("no-"))throw new W("DEFINITION",`Alias "--${L}" on "--${j}" must not use "no-" prefix (reserved for negation)`);let X=z.get(L);if(X)throw new W("DEFINITION",`Alias collision: "${L.length===1?"-":"--"}${L}" is used by both "--${X}" and "--${j}"`);z.set(L,j),G[L]=j;let $={type:K};if(H.multiple)$.multiple=!0;J[L]=$}J[j]=Q}return{options:J,aliasToName:G}}function _(B,J,G){if(J==="number"){let z=Number(B);if(Number.isNaN(z))throw new W("PARSE",`Expected number for ${G}, got "${B}"`);return z}if(J==="boolean")return B==="true"||B==="1";return B}function I(B,J,G){let z=`--${B}`;if(J.multiple&&Array.isArray(G))return J.type==="boolean"?G.filter((j)=>typeof j==="boolean"):G.map((j)=>_(j,J.type,z));if(J.type==="boolean"){if(typeof G==="boolean")return G;throw new W("PARSE",`Expected boolean value for flag "${z}", got ${typeof G}`)}if(typeof G==="string")return _(G,J.type,z);if(G===!0)return J.default??void 0;return G}function M(B,J,G){let z={};for(let j in B){let H=J[j]??j;if(!(H in G))continue;let K=B[j],Q=z[H];if(Q!==void 0&&Array.isArray(Q)&&Array.isArray(K))Q.push(...K);else z[H]=K}return z}function h(B,J,G){if(!B)return{};let z=M(J,G,B),j={};for(let[H,K]of Object.entries(B)){let Q=z[H];if(Q!==void 0){j[H]=I(H,K,Q);continue}j[H]=K.default??void 0}return j}function O(B,J){if(!B)return;for(let[G,z]of Object.entries(B))if(z.required===!0&&z.default===void 0){if(J[G]===void 0)throw new W("VALIDATION",`Missing required flag "--${G}"`)}}function P(B,J){if(!B)return{};let G={},z=0;for(let j of B){let{name:H}=j;if(j.variadic){let K=J.slice(z);G[H]=j.type==="string"?K:K.map((Q)=>_(Q,j.type,`<${H}>`)),z=J.length}else if(z<J.length)G[H]=_(J[z],j.type,`<${H}>`),z++;else G[H]=j.default??void 0}return G}function S(B,J,G){if(!J)return;for(let z of B){if(z==="--")return;if(!z.startsWith("--no-"))continue;let j=z.indexOf("="),H=j===-1?z.slice(5):z.slice(5,j);if(!H)continue;let K=G[H];if(!K)continue;if(K===H)continue;if(J[K]?.type!=="boolean")continue;throw new W("PARSE",`Cannot negate alias "--no-${H}"; use "--no-${K}" instead`)}}function b(B,J){let{args:G,effectiveFlags:z}=B,{options:j,aliasToName:H}=q(z);S(J,z,H);let K;try{K=U({args:J,options:j,strict:!0,allowPositionals:!0,allowNegative:!0,tokens:!0})}catch(Y){if(Y instanceof Error){let Z=Y.message.match(/Unknown option '(.+?)'/);if(Z)throw new W("PARSE",`Unknown flag "${Z[1]}"`).withCause(Y)}throw new W("PARSE","Failed to parse command arguments").withCause(Y)}let Q=[],L=[];if(K.tokens){let Y=!1;for(let Z of K.tokens){if(Z.kind==="option-terminator"){Y=!0;continue}if(Z.kind==="positional")(Y?Q:L).push(Z.value??"")}}else L.push(...K.positionals);let X=h(z,K.values,H);return{args:P(G,L),flags:X,rawArgs:Q}}function E(B,J){let{args:G,effectiveFlags:z}=B,j=J.args,H=J.flags;if(G)for(let K of G){let{name:Q}=K,L=`argument "<${Q}>"`,X=j[Q];if(K.required===!0&&K.default===void 0){if(K.variadic){if(!Array.isArray(X)||X.length===0)throw new W("VALIDATION",`Missing required ${L}`)}else if(X===void 0)throw new W("VALIDATION",`Missing required ${L}`)}}O(z,H)}
3
+ export{A as a,W as b,b as c,E as d};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crustjs/core",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Core library for the Crust CLI framework",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,7 +38,8 @@
38
38
  "build": "bunup",
39
39
  "dev": "bunup --watch",
40
40
  "check:types": "tsc --noEmit",
41
- "test": "bun test"
41
+ "test": "bun test",
42
+ "publish": "bun publish --no-git-checks || true"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@crustjs/config": "0.0.0",
@@ -1,3 +0,0 @@
1
- // @bun
2
- var A=import.meta.require;class W extends Error{code;details;cause;constructor(z,H,...J){super(H);this.name="CrustError",this.code=z,this.details=J[0]}is(z){return this.code===z}withCause(z){return this.cause=z,this}}import{parseArgs as q}from"util";function U(z){let H={},J={};if(!z)return{options:H,aliasToName:J};let B=new Map;for(let j of Object.keys(z))B.set(j,j);for(let[j,G]of Object.entries(z)){if(j.startsWith("no-")){let L=j.slice(3);throw new W("DEFINITION",`Flag "--${j}" must not use "no-" prefix; define "${L}" and negate with "--no-${L}"`)}let K=G.type==="boolean"?"boolean":"string",Q={type:K};if(G.multiple)Q.multiple=!0;if(G.short){if(G.short.startsWith("no-"))throw new W("DEFINITION",`Short alias "-${G.short}" on "--${j}" must not use "no-" prefix (reserved for negation)`);let L=B.get(G.short);if(L)throw new W("DEFINITION",`Alias collision: "-${G.short}" is used by both "--${L}" and "--${j}"`);B.set(G.short,j),J[G.short]=j,Q.short=G.short}if(G.aliases)for(let L of G.aliases){if(L.startsWith("no-"))throw new W("DEFINITION",`Alias "--${L}" on "--${j}" must not use "no-" prefix (reserved for negation)`);let Z=B.get(L);if(Z)throw new W("DEFINITION",`Alias collision: "${L.length===1?"-":"--"}${L}" is used by both "--${Z}" and "--${j}"`);B.set(L,j),J[L]=j;let _={type:K};if(G.multiple)_.multiple=!0;H[L]=_}H[j]=Q}return{options:H,aliasToName:J}}function $(z,H,J){if(H==="number"){let B=Number(z);if(Number.isNaN(B))throw new W("PARSE",`Expected number for ${J}, got "${z}"`);return B}if(H==="boolean")return z==="true"||z==="1";return z}function I(z,H){if(z.default!==void 0)return z.default;if(z.required===!0)throw new W("VALIDATION",`Missing required ${H}`);return}function M(z,H,J){let B=`--${z}`;if(H.multiple&&Array.isArray(J))return H.type==="boolean"?J.filter((j)=>typeof j==="boolean"):J.map((j)=>$(j,H.type,B));if(H.type==="boolean"){if(typeof J==="boolean")return J;throw new W("PARSE",`Expected boolean value for flag "${B}", got ${typeof J}`)}if(typeof J==="string")return $(J,H.type,B);if(J===!0)return H.default??void 0;return J}function h(z,H,J){let B={};for(let j in z){let G=H[j]??j;if(!(G in J))continue;let K=z[j],Q=B[G];if(Q!==void 0&&Array.isArray(Q)&&Array.isArray(K))Q.push(...K);else B[G]=K}return B}function P(z,H,J){if(!z)return{};let B=h(H,J,z),j={};for(let[G,K]of Object.entries(z)){let Q=B[G];if(Q!==void 0){j[G]=M(G,K,Q);continue}j[G]=K.default??void 0}return j}function S(z,H){if(!z)return;for(let[J,B]of Object.entries(z))if(B.required===!0&&B.default===void 0){if(H[J]===void 0)throw new W("VALIDATION",`Missing required flag "--${J}"`)}}function O(z,H){if(!z)return{};let J={},B=0;for(let j of z){let{name:G}=j,K=`argument "<${G}>"`;if(j.variadic){let Q=H.slice(B);if(j.required===!0&&Q.length===0)throw new W("VALIDATION",`Missing required ${K}`);J[G]=j.type==="string"?Q:Q.map((L)=>$(L,j.type,`<${G}>`)),B=H.length}else if(B<H.length)J[G]=$(H[B],j.type,`<${G}>`),B++;else J[G]=I(j,K)}return J}function R(z,H,J){if(!H)return;for(let B of z){if(B==="--")return;if(!B.startsWith("--no-"))continue;let j=B.indexOf("="),G=j===-1?B.slice(5):B.slice(5,j);if(!G)continue;let K=J[G];if(!K)continue;if(K===G)continue;if(H[K]?.type!=="boolean")continue;throw new W("PARSE",`Cannot negate alias "--no-${G}"; use "--no-${K}" instead`)}}function E(z,H){let{args:J,effectiveFlags:B}=z,{options:j,aliasToName:G}=U(B);R(H,B,G);let K;try{K=q({args:H,options:j,strict:!0,allowPositionals:!0,allowNegative:!0,tokens:!0})}catch(X){if(X instanceof Error){let Y=X.message.match(/Unknown option '(.+?)'/);if(Y)throw new W("PARSE",`Unknown flag "${Y[1]}"`).withCause(X)}throw new W("PARSE","Failed to parse command arguments").withCause(X)}let Q=[],L=[];if(K.tokens){let X=!1;for(let Y of K.tokens){if(Y.kind==="option-terminator"){X=!0;continue}if(Y.kind==="positional")(X?Q:L).push(Y.value??"")}}else L.push(...K.positionals);let Z=P(B,K.values,G),_=O(J,L);return S(B,Z),{args:_,flags:Z,rawArgs:Q}}
3
- export{A as a,W as b,E as c};
@@ -1,2 +0,0 @@
1
- // @bun
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};