@zipbul/baker 5.0.0 → 5.1.0

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.
@@ -2,21 +2,20 @@ import type { SealOptions } from '../interfaces';
2
2
  import type { RawClassMeta, SealedExecutors } from '../types';
3
3
  /** @internal Placeholder executor for circular dependency detection during seal */
4
4
  declare function circularPlaceholder(className: string): SealedExecutors<unknown>;
5
+ /** Canonical fingerprint of a SealOptions — the 5 booleans in fixed order. `{}` and a fully-defaulted
6
+ * object both map to "00000", so `new Baker()` and `new Baker({})` share a cache key. */
7
+ declare function configFingerprint(o: SealOptions): string;
8
+ declare function getCached(cls: Function, fp: string): SealedExecutors<unknown> | undefined;
9
+ /** Test-only: drop a single class's cached executors so a re-seal recompiles it. */
10
+ declare function clearCached(cls: Function): void;
5
11
  /**
6
- * @internal used by serialize/deserialize. Returns the sealed executor.
7
- * Throws if the class was never sealed. Seal a class via `new Baker().seal()` first.
12
+ * Test-only: drop the ENTIRE cache. Used by `unseal()` so a test that re-seals classes starts from a
13
+ * clean slate a whole-cache reset (vs per-class) is the only way to avoid the partial-clear state
14
+ * where a cached root still references a nested whose entry was dropped (a root + its nested are always
15
+ * compiled together, so they must be invalidated together).
8
16
  */
9
- declare function ensureSealed(Class: Function): SealedExecutors<unknown>;
10
- /**
11
- * Seal every class in `registry` with `options`. The core used by `new Baker().seal()`.
12
- * Transactional: on any failure every class sealed by this call is rolled back. Clears `registry`
13
- * on success.
14
- *
15
- * A class already sealed (e.g. a shared value-type DTO reached from another Baker's roots) is
16
- * reused as-is — class identity is the isolation boundary, so a shared class carries one sealed
17
- * behaviour. Distinct classes stay fully isolated because each is sealed with its Baker's options.
18
- */
19
- declare function sealRegistry(registry: Set<Function>, options: SealOptions): void;
17
+ declare function clearAllCached(): void;
18
+ declare function sealRegistry(registry: Set<Function>, options: SealOptions, executors: Map<Function, SealedExecutors<unknown>>): void;
20
19
  /**
21
20
  * Merges RAW metadata child-first along the prototype chain of Class.
22
21
  *
@@ -29,4 +28,4 @@ declare function sealRegistry(registry: Set<Function>, options: SealOptions): vo
29
28
  * - flags: child takes priority, only missing flags are supplemented from parent
30
29
  */
31
30
  declare function mergeInheritance(Class: Function): RawClassMeta;
32
- export { ensureSealed, sealRegistry, mergeInheritance, circularPlaceholder };
31
+ export { sealRegistry, mergeInheritance, circularPlaceholder, getCached, configFingerprint, clearCached, clearAllCached };
@@ -1 +1 @@
1
- import{CollectionType as O,Direction as w}from"../enums.js";import{BakerError as F}from"../errors.js";import{deleteSealed as z,freezeRaw as S,getRaw as I,getSealed as h,hasRawOwn as E,hasSealedOwn as R,setSealed as k}from"../meta-access.js";import{isAsyncFunction as v}from"../utils.js";import{analyzeCircular as A}from"./circular-analyzer.js";import{buildDeserializeCode as f,buildValidateCode as g}from"./deserialize-builder.js";import{validateExposeStacks as u}from"./expose-validator.js";import{buildSerializeCode as y}from"./serialize-builder.js";import{validateMeta as p}from"./validate-meta.js";const C=new Set(["__proto__","constructor","prototype"]);const _=new Set([Number,String,Boolean,Date]);function circularPlaceholder(H){const j=`Circular dependency during seal: ${H} is still being sealed`;return{deserialize(){throw new F(j)},serialize(){throw new F(j)},validate(){throw new F(j)},isAsync:!1,isSerializeAsync:!1}}function b(H,j,J){const Q=j===w.Deserialize?"isAsync":"isSerializeAsync",q=J??new Set,L=(W)=>{if(q.has(W))return!1;q.add(W);const U=h(W);if(U?.merged)return U[Q]===!0;return b(mergeInheritance(W),j,q)};for(const W of Object.values(H)){if(j===w.Deserialize&&W.validation.some((U)=>U.rule.isAsync))return!0;for(const U of W.transform){if(j===w.Deserialize?U.options?.serializeOnly:U.options?.deserializeOnly)continue;if(U.isAsync??v(U.fn))return!0}if(n(W).some(L))return!0}return!1}function n(H){const j=H.type;if(!j)return[];const J=[];if(j.resolvedClass)J.push(j.resolvedClass);if(j.resolvedCollectionValue)J.push(j.resolvedCollectionValue);if(j.discriminator)for(const Q of j.discriminator.subTypes)J.push(Q.value);if(J.length===0&&j.fn){const Q=j.fn();if(Q===Map||Q===Set){const q=j.collectionValue?.();if(typeof q==="function"&&!_.has(q))J.push(q)}else{const q=Array.isArray(Q)?Q[0]:Q;if(typeof q==="function"&&!_.has(q))J.push(q)}}return J}function ensureSealed(H){const j=h(H);if(!j){const J=H.name||"<anonymous class>";throw new F(`${J} is not sealed. Call your baker's seal() (new Baker().seal()) at app startup before deserialize/validate/serialize. (If ${J} has no @Field decorators, decorate at least one property.)`)}return j}function sealRegistry(H,j){const J=new Set;try{for(const Q of H)P(Q,j,J)}catch(Q){for(const q of J)z(q);throw Q}for(const Q of J)S(Q);H.clear()}function P(H,j,J){if(R(H))return;const Q=circularPlaceholder(H.name);k(H,Q);try{const q=mergeInheritance(H);for(const K of Object.keys(q))if(C.has(K))throw new F(`${H.name}: field name '${K}' is not allowed (reserved property name)`);for(const[K,G]of Object.entries(q)){if(!G.type?.fn)continue;let $;try{$=G.type.fn()}catch(M){throw new F(`${H.name}.${K}: type function threw: ${M.message}`,{cause:M})}if($===Map||$===Set){const M=$===Map?O.Map:O.Set,B={...G.type,collection:M,isArray:!1};if(G.type.collectionValue){let V;try{V=G.type.collectionValue()}catch(T){throw new F(`${H.name}.${K}: collectionValue function threw: ${T.message}`,{cause:T})}if(V!=null&&typeof V==="function"&&!_.has(V))B.resolvedCollectionValue=V}q[K]={...G,type:B};continue}const x=Array.isArray($),N=x?$[0]:$;if(N==null||typeof N!=="function")throw new F(`${H.name}: @Type/@Field type must return a constructor or [constructor], got ${String(N)}`);const D={...G.type,isArray:x};if(!_.has(N)){D.resolvedClass=N;if(!G.flags.validateNested||!G.flags.validateNestedEach){G.flags={...G.flags};if(!G.flags.validateNested)G.flags.validateNested=!0;if(x&&!G.flags.validateNestedEach)G.flags.validateNestedEach=!0}}q[K]={...G,type:D}}u(q,H.name);p(H,q);const L=A(H);for(const K of Object.values(q)){if(K.type?.resolvedClass)P(K.type.resolvedClass,j,J);if(K.type?.resolvedCollectionValue)P(K.type.resolvedCollectionValue,j,J);if(K.type?.discriminator)for(const G of K.type.discriminator.subTypes)P(G.value,j,J)}const W=b(q,w.Deserialize),U=b(q,w.Serialize),Z=f(H,q,j,L,W),X=g(H,q,j,L,W),Y=y(H,q,j,U);Object.assign(Q,{deserialize:Z,serialize:Y,validate:X,isAsync:W,isSerializeAsync:U,merged:q})}catch(q){z(H);throw q}J?.add(H)}function mergeInheritance(H){const j=[];let J=H;while(J&&J!==Object){if(E(J))j.push(J);const L=Object.getPrototypeOf(J);J=L===J?null:L}const Q=Object.create(null),q=j.length>1;for(const L of j){const W=I(L);for(const[U,Z]of Object.entries(W))if(!Q[U])Q[U]=q?{validation:[...Z.validation],transform:[...Z.transform],expose:[...Z.expose],exclude:Z.exclude,type:Z.type,flags:{...Z.flags}}:Z;else{const X=Q[U],Y=Z;for(const $ of Y.validation)if(!X.validation.some((x)=>x.rule.ruleName===$.rule.ruleName))X.validation.push($);if(X.transform.length===0&&Y.transform.length>0)X.transform=[...Y.transform];if(X.expose.length===0&&Y.expose.length>0)X.expose=[...Y.expose];if(X.exclude===null&&Y.exclude!==null)X.exclude=Y.exclude;if(X.type===null&&Y.type!==null)X.type=Y.type;const K=X.flags,G=Y.flags;if(G.isOptional!==void 0&&K.isOptional===void 0)K.isOptional=G.isOptional;if(G.isDefined!==void 0&&K.isDefined===void 0)K.isDefined=G.isDefined;if(G.validateIf!==void 0&&K.validateIf===void 0)K.validateIf=G.validateIf;if(G.isNullable!==void 0&&K.isNullable===void 0)K.isNullable=G.isNullable;if(G.validateNested!==void 0&&K.validateNested===void 0)K.validateNested=G.validateNested;if(G.validateNestedEach!==void 0&&K.validateNestedEach===void 0)K.validateNestedEach=G.validateNestedEach}}return Q}export{ensureSealed,sealRegistry,mergeInheritance,circularPlaceholder};
1
+ import{CollectionType as R,Direction as P}from"../enums.js";import{BakerError as F}from"../errors.js";import{getRaw as h,hasRawOwn as x}from"../meta-access.js";import{isAsyncFunction as v}from"../utils.js";import{analyzeCircular as g}from"./circular-analyzer.js";import{buildDeserializeCode as f,buildValidateCode as y}from"./deserialize-builder.js";import{validateExposeStacks as u}from"./expose-validator.js";import{buildSerializeCode as C}from"./serialize-builder.js";import{validateMeta as p}from"./validate-meta.js";const n=new Set(["__proto__","constructor","prototype"]);const D=new Set([Number,String,Boolean,Date]);function circularPlaceholder(j){const G=`Circular dependency during seal: ${j} is still being sealed`;return{deserialize(){throw new F(G)},serialize(){throw new F(G)},validate(){throw new F(G)},isAsync:!1,isSerializeAsync:!1}}function O(j,G,H,J){const K=G===P.Deserialize?"isAsync":"isSerializeAsync",W=J??new Set,L=(Q)=>{if(W.has(Q))return!1;W.add(Q);const q=H(Q);if(q?.merged)return q[K]===!0;return O(mergeInheritance(Q),G,H,W)};for(const Q of Object.values(j)){if(G===P.Deserialize&&Q.validation.some((q)=>q.rule.isAsync))return!0;for(const q of Q.transform){if(G===P.Deserialize?q.options?.serializeOnly:q.options?.deserializeOnly)continue;if(q.isAsync??v(q.fn))return!0}if(k(Q).some(L))return!0}return!1}function k(j){const G=j.type;if(!G)return[];const H=[];if(G.resolvedClass)H.push(G.resolvedClass);if(G.resolvedCollectionValue)H.push(G.resolvedCollectionValue);if(G.discriminator)for(const J of G.discriminator.subTypes)H.push(J.value);if(H.length===0&&G.fn){const J=G.fn();if(J===Map||J===Set){const K=G.collectionValue?.();if(typeof K==="function"&&!D.has(K))H.push(K)}else{const K=Array.isArray(J)?J[0]:J;if(typeof K==="function"&&!D.has(K))H.push(K)}}return H}let _=new WeakMap;function configFingerprint(j){return(j.enableImplicitConversion?"1":"0")+(j.exposeDefaultValues?"1":"0")+(j.stopAtFirstError?"1":"0")+(j.whitelist?"1":"0")+(j.debug?"1":"0")}function getCached(j,G){return _.get(j)?.get(G)}function clearCached(j){_.delete(j)}function clearAllCached(){_=new WeakMap}function d(j,G,H){let J=_.get(j);if(J===void 0){J=new Map;_.set(j,J)}J.set(G,H)}function sealRegistry(j,G,H){const J=configFingerprint(G),K=new Set;try{for(const W of j)M(W,H,J,G,K)}catch(W){H.clear();throw W}for(const W of K)d(W,J,H.get(W));j.clear()}function M(j,G,H,J,K){if(G.has(j))return;const W=getCached(j,H);if(W!==void 0){G.set(j,W);if(W.merged)for(const q of Object.values(W.merged))for(const Y of k(q))M(Y,G,H,J,K);return}const L=circularPlaceholder(j.name);G.set(j,L);const Q=(q)=>G.get(q);try{const q=mergeInheritance(j);for(const $ of Object.keys(q))if(n.has($))throw new F(`${j.name}: field name '${$}' is not allowed (reserved property name)`);for(const[$,U]of Object.entries(q)){if(!U.type?.fn)continue;let w;try{w=U.type.fn()}catch(B){throw new F(`${j.name}.${$}: type function threw: ${B.message}`,{cause:B})}if(w===Map||w===Set){const B=w===Map?R.Map:R.Set,I={...U.type,collection:B,isArray:!1};if(U.type.collectionValue){let V;try{V=U.type.collectionValue()}catch(E){throw new F(`${j.name}.${$}: collectionValue function threw: ${E.message}`,{cause:E})}if(V!=null&&typeof V==="function"&&!D.has(V))I.resolvedCollectionValue=V}q[$]={...U,type:I};continue}const T=Array.isArray(w),N=T?w[0]:w;if(N==null||typeof N!=="function")throw new F(`${j.name}: @Type/@Field type must return a constructor or [constructor], got ${String(N)}`);const z={...U.type,isArray:T};if(!D.has(N)){z.resolvedClass=N;if(!U.flags.validateNested||!U.flags.validateNestedEach){U.flags={...U.flags};if(!U.flags.validateNested)U.flags.validateNested=!0;if(T&&!U.flags.validateNestedEach)U.flags.validateNestedEach=!0}}q[$]={...U,type:z}}u(q,j.name);p(j,q);const Y=g(j);for(const $ of Object.values(q)){if($.type?.resolvedClass)M($.type.resolvedClass,G,H,J,K);if($.type?.resolvedCollectionValue)M($.type.resolvedCollectionValue,G,H,J,K);if($.type?.discriminator)for(const U of $.type.discriminator.subTypes)M(U.value,G,H,J,K)}const X=O(q,P.Deserialize,Q),Z=O(q,P.Serialize,Q),b=f(j,q,J,Y,X,Q),S=y(j,q,J,Y,X,Q),A=C(j,q,J,Z,Q);Object.assign(L,{deserialize:b,serialize:A,validate:S,isAsync:X,isSerializeAsync:Z,merged:q})}catch(q){G.delete(j);throw q}K?.add(j)}function mergeInheritance(j){const G=[];let H=j;while(H&&H!==Object){if(x(H))G.push(H);const K=Object.getPrototypeOf(H);H=K===H?null:K}const J=Object.create(null);for(const K of G){const W=h(K);for(const[L,Q]of Object.entries(W))if(!J[L])J[L]={...Q,validation:[...Q.validation],transform:[...Q.transform],expose:[...Q.expose],exclude:Q.exclude,type:Q.type,flags:{...Q.flags}};else{const q=J[L],Y=Q;for(const b of Y.validation)if(!q.validation.some((S)=>S.rule.ruleName===b.rule.ruleName))q.validation.push(b);if(q.transform.length===0&&Y.transform.length>0)q.transform=[...Y.transform];if(q.expose.length===0&&Y.expose.length>0)q.expose=[...Y.expose];if(q.exclude===null&&Y.exclude!==null)q.exclude=Y.exclude;if(q.type===null&&Y.type!==null)q.type=Y.type;const X=q.flags,Z=Y.flags;if(Z.isOptional!==void 0&&X.isOptional===void 0)X.isOptional=Z.isOptional;if(Z.isDefined!==void 0&&X.isDefined===void 0)X.isDefined=Z.isDefined;if(Z.validateIf!==void 0&&X.validateIf===void 0)X.validateIf=Z.validateIf;if(Z.isNullable!==void 0&&X.isNullable===void 0)X.isNullable=Z.isNullable;if(Z.validateNested!==void 0&&X.validateNested===void 0)X.validateNested=Z.validateNested;if(Z.validateNestedEach!==void 0&&X.validateNestedEach===void 0)X.validateNestedEach=Z.validateNestedEach}}return J}export{sealRegistry,mergeInheritance,circularPlaceholder,getCached,configFingerprint,clearCached,clearAllCached};
@@ -1,8 +1,8 @@
1
1
  import type { SealOptions, RuntimeOptions } from '../interfaces';
2
- import type { RawClassMeta } from '../types';
2
+ import type { RawClassMeta, SealedExecutors } from '../types';
3
3
  /**
4
4
  * Generate serialize executor code.
5
5
  * Assumes no validation — always returns Record<string, unknown> (§4.3).
6
6
  */
7
- declare function buildSerializeCode<T>(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, isAsync: boolean): (instance: T, opts?: RuntimeOptions) => Record<string, unknown> | Promise<Record<string, unknown>>;
7
+ declare function buildSerializeCode<T>(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, isAsync: boolean, resolve: (cls: Function) => SealedExecutors<unknown> | undefined): (instance: T, opts?: RuntimeOptions) => Record<string, unknown> | Promise<Record<string, unknown>>;
8
8
  export { buildSerializeCode };
@@ -1,70 +1,70 @@
1
- import{CollectionType as c}from"../enums.js";import{BakerError as p}from"../errors.js";import{getSealed as A}from"../meta-access.js";import{sanitizeKey as E,buildGroupsHasExpr as m}from"./codegen-utils.js";const j={out:"__bk$out",fieldVal:"__bk$fv_",groups:"__bk$groups",group0:"__bk$group0",groupsSet:"__bk$groupsSet",setArr:"__bk$sa",setItem:"__bk$si",mapObj:"__bk$m",mapEntry:"__bk$me",serResult:"__bk$sr",outItem:"__bk$out_item",discArr:"__bk$da",discIdx:"__bk$di",nestedArr:"__bk$na",nestedIdx:"__bk$ni",nestedItem:"__bk$nitem"};function u(U,q){const L=q.find((R)=>R.serializeOnly&&R.name);if(L)return L.name;const M=q.find((R)=>!R.deserializeOnly&&!R.serializeOnly&&R.name);if(M)return M.name;return U}function y(U){let q=null;for(const L of U){if(L.deserializeOnly)continue;if(!L.groups||L.groups.length===0)return;if(q===null)q=new Set;for(const M of L.groups)q.add(M)}return q===null?void 0:[...q]}function x(U,q,L,M){if(L.length===0)return null;if(L.length===1){const Y=L[0],W=M.length;M.push(Y.fn);const Z=`refs[${W}]({value:${U},key:${JSON.stringify(q)},obj:instance})`;return Y.isAsync?`(await ${Z})`:Z}if(L.length===2){const Y=L[1],W=L[0],Z=M.length;M.push(Y.fn);const F=M.length;M.push(W.fn);const z=`refs[${Z}]({value:${U},key:${JSON.stringify(q)},obj:instance})`,Q=Y.isAsync?`(await ${z})`:z,_=`refs[${F}]({value:${Q},key:${JSON.stringify(q)},obj:instance})`;return W.isAsync?`(await ${_})`:_}let R=U;for(let Y=L.length-1;Y>=0;Y-=1){const W=L[Y],Z=M.length;M.push(W.fn);const F=`refs[${Z}]({value:${R},key:${JSON.stringify(q)},obj:instance})`;R=W.isAsync?`(await ${F})`:F}return R}function T(U,q,L,M){const R=x(U,q,L,M);return R?`
2
- ${U} = ${R};`:""}function buildSerializeCode(U,q,L,M){const R=[],Y=[];let W=`'use strict';
1
+ import{CollectionType as c}from"../enums.js";import{BakerError as p}from"../errors.js";import{sanitizeKey as E,buildGroupsHasExpr as m}from"./codegen-utils.js";const j={out:"__bk$out",fieldVal:"__bk$fv_",groups:"__bk$groups",group0:"__bk$group0",groupsSet:"__bk$groupsSet",setArr:"__bk$sa",setItem:"__bk$si",mapObj:"__bk$m",mapEntry:"__bk$me",serResult:"__bk$sr",outItem:"__bk$out_item",discArr:"__bk$da",discIdx:"__bk$di",nestedArr:"__bk$na",nestedIdx:"__bk$ni",nestedItem:"__bk$nitem"};function u(U,q){const M=q.find((R)=>R.serializeOnly&&R.name);if(M)return M.name;const Q=q.find((R)=>!R.deserializeOnly&&!R.serializeOnly&&R.name);if(Q)return Q.name;return U}function y(U){let q=null;for(const M of U){if(M.deserializeOnly)continue;if(!M.groups||M.groups.length===0)return;if(q===null)q=new Set;for(const Q of M.groups)q.add(Q)}return q===null?void 0:[...q]}function x(U,q,M,Q){if(M.length===0)return null;if(M.length===1){const X=M[0],Z=Q.length;Q.push(X.fn);const W=`refs[${Z}]({value:${U},key:${JSON.stringify(q)},obj:instance})`;return X.isAsync?`(await ${W})`:W}if(M.length===2){const X=M[1],Z=M[0],W=Q.length;Q.push(X.fn);const B=Q.length;Q.push(Z.fn);const D=`refs[${W}]({value:${U},key:${JSON.stringify(q)},obj:instance})`,I=X.isAsync?`(await ${D})`:D,L=`refs[${B}]({value:${I},key:${JSON.stringify(q)},obj:instance})`;return Z.isAsync?`(await ${L})`:L}let R=U;for(let X=M.length-1;X>=0;X-=1){const Z=M[X],W=Q.length;Q.push(Z.fn);const B=`refs[${W}]({value:${R},key:${JSON.stringify(q)},obj:instance})`;R=Z.isAsync?`(await ${B})`:B}return R}function T(U,q,M,Q){const R=x(U,q,M,Q);return R?`
2
+ ${U} = ${R};`:""}function buildSerializeCode(U,q,M,Q,R){const X=[],Z=[];let W=`'use strict';
3
3
  `;W+=`var ${j.out} = {};
4
- `;if(Object.values(q).some((_)=>{const v=y(_.expose);return v&&v.length>0})){W+=`var ${j.groups} = opts && opts.groups;
4
+ `;if(Object.values(q).some((P)=>{const O=y(P.expose);return O&&O.length>0})){W+=`var ${j.groups} = opts && opts.groups;
5
5
  `;W+=`var ${j.group0} = ${j.groups} && ${j.groups}.length === 1 ? ${j.groups}[0] : null;
6
6
  `;W+=`var ${j.groupsSet} = ${j.groups} && ${j.groups}.length > 1 ? new Set(${j.groups}) : null;
7
- `}for(const[_,v]of Object.entries(q))W+=f(_,v,R,Y,M,L,U.name);W+=`return ${j.out};
8
- `;const F=U.name.replace(/[^\w$.-]/g,"_");W+=`//# sourceURL=baker://${F}/serialize
9
- `;return Function("refs","execs","BakerError",`return ${M?"async function":"function"}(instance, opts) { `+W+" }")(R,Y,p)}function f(U,q,L,M,R,Y,W=""){if(q.exclude){if(!q.exclude.deserializeOnly){if(Y?.debug){const X=q.exclude.serializeOnly?"serializeOnly":"bidirectional";return`// [baker] field ${JSON.stringify(U)} excluded (${X} @Exclude)
10
- `}return""}}if(q.expose.length>0&&q.expose.every((X)=>X.deserializeOnly)){if(Y?.debug)return`// [baker] field ${JSON.stringify(U)} excluded (all @Expose entries are deserializeOnly)
11
- `;return""}const Z=u(U,q.expose),F=y(q.expose),z=E(U),Q=`${j.fieldVal}${z}`;let _="";_+=`var ${Q} = instance[${JSON.stringify(U)}];
12
- `;let v="",S="";if(F&&F.length>0){v=`if ((${j.group0} !== null || ${j.groupsSet}) && (${m(j.group0,j.groupsSet,F)})) {
7
+ `}for(const[P,O]of Object.entries(q))W+=f(P,O,X,Z,Q,R,M,U.name);W+=`return ${j.out};
8
+ `;const D=U.name.replace(/[^\w$.-]/g,"_");W+=`//# sourceURL=baker://${D}/serialize
9
+ `;return Function("refs","execs","BakerError",`return ${Q?"async function":"function"}(instance, opts) { `+W+" }")(X,Z,p)}function f(U,q,M,Q,R,X,Z,W=""){if(q.exclude){if(!q.exclude.deserializeOnly){if(Z?.debug){const Y=q.exclude.serializeOnly?"serializeOnly":"bidirectional";return`// [baker] field ${JSON.stringify(U)} excluded (${Y} @Exclude)
10
+ `}return""}}if(q.expose.length>0&&q.expose.every((Y)=>Y.deserializeOnly)){if(Z?.debug)return`// [baker] field ${JSON.stringify(U)} excluded (all @Expose entries are deserializeOnly)
11
+ `;return""}const B=u(U,q.expose),D=y(q.expose),I=E(U),L=`${j.fieldVal}${I}`;let P="";P+=`var ${L} = instance[${JSON.stringify(U)}];
12
+ `;let O="",S="";if(D&&D.length>0){O=`if ((${j.group0} !== null || ${j.groupsSet}) && (${m(j.group0,j.groupsSet,D)})) {
13
13
  `;S=`}
14
- `}let H="";const b=q.flags.isOptional,g=q.transform.filter((X)=>!X.options?.deserializeOnly);if(q.type?.collection){const X=`${j.out}[${JSON.stringify(Z)}]`,$=q.type.collection;let J;if($===c.Set)if(q.type.resolvedCollectionValue){const B=A(q.type.resolvedCollectionValue),D=M.length;M.push(B);if(R)J=`{ var __ser_ps = []; for (var __ser_item of ${Q}) { __ser_ps.push(__ser_item == null ? __ser_item : execs[${D}].serialize(__ser_item, opts)); } ${X} = await Promise.all(__ser_ps); }`;else{J=`var ${j.setArr} = [];
15
- `;J+=` for (var ${j.setItem} of ${Q}) {
16
- `;J+=` ${j.setArr}.push(${j.setItem} == null ? ${j.setItem} : execs[${D}].serialize(${j.setItem}, opts));
14
+ `}let $="";const b=q.flags.isOptional,V=q.transform.filter((Y)=>!Y.options?.deserializeOnly);if(q.type?.collection){const Y=`${j.out}[${JSON.stringify(B)}]`,_=q.type.collection;let J;if(_===c.Set)if(q.type.resolvedCollectionValue){const F=X(q.type.resolvedCollectionValue),h=Q.length;Q.push(F);if(R)J=`{ var __ser_ps = []; for (var __ser_item of ${L}) { __ser_ps.push(__ser_item == null ? __ser_item : execs[${h}].serialize(__ser_item, opts)); } ${Y} = await Promise.all(__ser_ps); }`;else{J=`var ${j.setArr} = [];
15
+ `;J+=` for (var ${j.setItem} of ${L}) {
16
+ `;J+=` ${j.setArr}.push(${j.setItem} == null ? ${j.setItem} : execs[${h}].serialize(${j.setItem}, opts));
17
17
  `;J+=` }
18
- `;J+=` ${X} = ${j.setArr};`}}else J=`${X} = [...${Q}];`;else{const B=`if (typeof ${j.mapEntry}[0] !== 'string') { throw new BakerError(${JSON.stringify(W)} + ': Map field ' + ${JSON.stringify(U)} + ' has non-string key (' + typeof ${j.mapEntry}[0] + '). Map serialization requires string keys.'); }
19
- `;if(q.type.resolvedCollectionValue){const D=A(q.type.resolvedCollectionValue),O=M.length;M.push(D);const w=R?"await ":"";J=`var ${j.mapObj} = Object.create(null);
20
- `;J+=` for (var ${j.mapEntry} of ${Q}) {
21
- `;J+=` ${B}`;J+=`${j.mapObj}[${j.mapEntry}[0]] = ${j.mapEntry}[1] == null ? ${j.mapEntry}[1] : ${w}execs[${O}].serialize(${j.mapEntry}[1], opts);
18
+ `;J+=` ${Y} = ${j.setArr};`}}else J=`${Y} = [...${L}];`;else{const F=`if (typeof ${j.mapEntry}[0] !== 'string') { throw new BakerError(${JSON.stringify(W)} + ': Map field ' + ${JSON.stringify(U)} + ' has non-string key (' + typeof ${j.mapEntry}[0] + '). Map serialization requires string keys.'); }
19
+ `;if(q.type.resolvedCollectionValue){const h=X(q.type.resolvedCollectionValue),z=Q.length;Q.push(h);const v=R?"await ":"";J=`var ${j.mapObj} = Object.create(null);
20
+ `;J+=` for (var ${j.mapEntry} of ${L}) {
21
+ `;J+=` ${F}`;J+=`${j.mapObj}[${j.mapEntry}[0]] = ${j.mapEntry}[1] == null ? ${j.mapEntry}[1] : ${v}execs[${z}].serialize(${j.mapEntry}[1], opts);
22
22
  `;J+=` }
23
- `;J+=` ${X} = ${j.mapObj};`}else{J=`var ${j.mapObj} = Object.create(null);
24
- `;J+=` for (var ${j.mapEntry} of ${Q}) {
25
- `;J+=` ${B}`;J+=`${j.mapObj}[${j.mapEntry}[0]] = ${j.mapEntry}[1];
23
+ `;J+=` ${Y} = ${j.mapObj};`}else{J=`var ${j.mapObj} = Object.create(null);
24
+ `;J+=` for (var ${j.mapEntry} of ${L}) {
25
+ `;J+=` ${F}`;J+=`${j.mapObj}[${j.mapEntry}[0]] = ${j.mapEntry}[1];
26
26
  `;J+=` }
27
- `;J+=` ${X} = ${j.mapObj};`}}J+=T(X,U,g,L);if(b)H=`if (${Q} !== undefined && ${Q} !== null) {
27
+ `;J+=` ${Y} = ${j.mapObj};`}}J+=T(Y,U,V,M);if(b)$=`if (${L} !== undefined && ${L} !== null) {
28
28
  ${J}
29
- } else if (${Q} === null) {
30
- ${X} = null;
29
+ } else if (${L} === null) {
30
+ ${Y} = null;
31
31
  }
32
- `;else H=`if (${Q} != null) {
32
+ `;else $=`if (${L} != null) {
33
33
  ${J}
34
34
  } else {
35
- ${X} = ${Q};
35
+ ${Y} = ${L};
36
36
  }
37
- `;_+=v+H+S;return _}if(q.type?.resolvedClass||q.type?.discriminator||q.type?.fn&&q.flags.validateNested){const X=q.type?.isArray||q.flags.validateNestedEach||q.validation.some((B)=>B.each),$=`${j.out}[${JSON.stringify(Z)}]`;let J;if(q.type.discriminator){const{property:B,subTypes:D}=q.type.discriminator,O=q.type.keepDiscriminatorProperty!==!1,w=[...D].sort((P,I)=>{if(P.value.prototype instanceof I.value)return-1;if(I.value.prototype instanceof P.value)return 1;return 0}),K=(P,I)=>{let h="";for(let k=0;k<w.length;k++){const V=w[k],N=A(V.value),C=M.length;M.push(N);const G=L.length;L.push(V.value);h+=`${k===0?"if":"} else if"} (${P} instanceof refs[${G}]) {
38
- `;h+=` var ${j.serResult} = ${I}execs[${C}].serialize(${P}, opts);
39
- `;if(O)h+=` ${j.serResult}[${JSON.stringify(B)}] = ${JSON.stringify(V.name)};
40
- `;h+=` ${j.outItem} = ${j.serResult};
41
- `}h+=`} else { ${j.outItem} = `+P+`; }
42
- `;return h};if(X){const P=R?"await ":"";if(R)J=`${$} = await Promise.all(${Q}.map(async function(__ser_item) {
37
+ `;P+=O+$+S;return P}if(q.type?.resolvedClass||q.type?.discriminator||q.type?.fn&&q.flags.validateNested){const Y=q.type?.isArray||q.flags.validateNestedEach||q.validation.some((F)=>F.each),_=`${j.out}[${JSON.stringify(B)}]`;let J;if(q.type.discriminator){const{property:F,subTypes:h}=q.type.discriminator,z=q.type.keepDiscriminatorProperty!==!1,v=[...h].sort((H,k)=>{if(H.value.prototype instanceof k.value)return-1;if(k.value.prototype instanceof H.value)return 1;return 0}),K=(H,k)=>{let w="";for(let A=0;A<v.length;A++){const g=v[A],N=X(g.value),C=Q.length;Q.push(N);const G=M.length;M.push(g.value);w+=`${A===0?"if":"} else if"} (${H} instanceof refs[${G}]) {
38
+ `;w+=` var ${j.serResult} = ${k}execs[${C}].serialize(${H}, opts);
39
+ `;if(z)w+=` ${j.serResult}[${JSON.stringify(F)}] = ${JSON.stringify(g.name)};
40
+ `;w+=` ${j.outItem} = ${j.serResult};
41
+ `}w+=`} else { ${j.outItem} = `+H+`; }
42
+ `;return w};if(Y){const H=R?"await ":"";if(R)J=`${_} = await Promise.all(${L}.map(async function(__ser_item) {
43
43
  `;else{J=`var ${j.discArr} = [];
44
- `;J+=` for (var ${j.discIdx}=0; ${j.discIdx}<${Q}.length; ${j.discIdx}++) {
45
- `;J+=` var __ser_item = ${Q}[${j.discIdx}];
44
+ `;J+=` for (var ${j.discIdx}=0; ${j.discIdx}<${L}.length; ${j.discIdx}++) {
45
+ `;J+=` var __ser_item = ${L}[${j.discIdx}];
46
46
  `}J+=` var ${j.outItem};
47
- `;J+=K("__ser_item",P);if(R){J+=` return ${j.outItem};
47
+ `;J+=K("__ser_item",H);if(R){J+=` return ${j.outItem};
48
48
  `;J+="}));"}else{J+=` ${j.discArr}.push(${j.outItem});
49
49
  `;J+=` }
50
- `;J+=` ${$} = ${j.discArr};`}}else{const P=R?"await ":"";J=`var ${j.outItem};
51
- `;J+=K(Q,P);J+=`${$} = ${j.outItem};`}}else{const B=q.type.resolvedClass??q.type.fn(),D=A(B),O=M.length;M.push(D);if(X)if(R)J=`${$} = await Promise.all(${Q}.map(async function(__ser_item) { return __ser_item == null ? __ser_item : await execs[${O}].serialize(__ser_item, opts); }));`;else{J=`var ${j.nestedArr} = [];
52
- `;J+=` for (var ${j.nestedIdx}=0; ${j.nestedIdx}<${Q}.length; ${j.nestedIdx}++) {
53
- `;J+=` var ${j.nestedItem} = ${Q}[${j.nestedIdx}];
54
- `;J+=` ${j.nestedArr}.push(${j.nestedItem} == null ? ${j.nestedItem} : execs[${O}].serialize(${j.nestedItem}, opts));
50
+ `;J+=` ${_} = ${j.discArr};`}}else{const H=R?"await ":"";J=`var ${j.outItem};
51
+ `;J+=K(L,H);J+=`${_} = ${j.outItem};`}}else{const F=q.type.resolvedClass??q.type.fn(),h=X(F),z=Q.length;Q.push(h);if(Y)if(R)J=`${_} = await Promise.all(${L}.map(async function(__ser_item) { return __ser_item == null ? __ser_item : await execs[${z}].serialize(__ser_item, opts); }));`;else{J=`var ${j.nestedArr} = [];
52
+ `;J+=` for (var ${j.nestedIdx}=0; ${j.nestedIdx}<${L}.length; ${j.nestedIdx}++) {
53
+ `;J+=` var ${j.nestedItem} = ${L}[${j.nestedIdx}];
54
+ `;J+=` ${j.nestedArr}.push(${j.nestedItem} == null ? ${j.nestedItem} : execs[${z}].serialize(${j.nestedItem}, opts));
55
55
  `;J+=` }
56
- `;J+=` ${$} = ${j.nestedArr};`}else J=`${$} = ${R?"await ":""}execs[${O}].serialize(${Q}, opts);`}J+=T($,U,g,L);if(b)H=`if (${Q} !== undefined && ${Q} !== null) {
56
+ `;J+=` ${_} = ${j.nestedArr};`}else J=`${_} = ${R?"await ":""}execs[${z}].serialize(${L}, opts);`}J+=T(_,U,V,M);if(b)$=`if (${L} !== undefined && ${L} !== null) {
57
57
  ${J}
58
- } else if (${Q} === null) {
59
- ${$} = null;
58
+ } else if (${L} === null) {
59
+ ${_} = null;
60
60
  }
61
- `;else H=`if (${Q} != null) {
61
+ `;else $=`if (${L} != null) {
62
62
  ${J}
63
63
  } else {
64
- ${$} = ${Q};
64
+ ${_} = ${L};
65
65
  }
66
- `}else{const X=n(U,Z,Q,q,L);if(b){H+=`if (${Q} !== undefined) {
67
- `;H+=" "+X+`
68
- `;H+=`}
69
- `}else H+=X+`
70
- `}_+=v+H+S;return _}function n(U,q,L,M,R){const Y=`${j.out}[${JSON.stringify(q)}]`,W=M.transform.filter((Z)=>!Z.options?.deserializeOnly);if(W.length>0){const Z=x(L,U,W,R);return`${Y} = ${Z};`}return`${Y} = ${L};`}export{buildSerializeCode};
66
+ `}else{const Y=n(U,B,L,q,M);if(b){$+=`if (${L} !== undefined) {
67
+ `;$+=" "+Y+`
68
+ `;$+=`}
69
+ `}else $+=Y+`
70
+ `}P+=O+$+S;return P}function n(U,q,M,Q,R){const X=`${j.out}[${JSON.stringify(q)}]`,Z=Q.transform.filter((W)=>!W.options?.deserializeOnly);if(Z.length>0){const W=x(M,U,Z,R);return`${X} = ${W};`}return`${X} = ${M};`}export{buildSerializeCode};
@@ -1,8 +1,6 @@
1
1
  /**
2
- * 2 Symbols — zero external storage, zero global pollution
3
- * Uses Symbol.for: allows AOT code and runtime code to share the same Symbol via the global registry
2
+ * RAW symbol — zero external storage, zero global pollution.
3
+ * Uses Symbol.for: allows AOT code and runtime code to share the same Symbol via the global registry.
4
4
  */
5
5
  /** Tier 1 collection metadata (stored on Class[Symbol.metadata] by decorators) */
6
6
  export declare const RAW: unique symbol;
7
- /** Tier 2 seal result (dual executor stored on Class at seal time) */
8
- export declare const SEALED: unique symbol;
@@ -1 +1 @@
1
- Symbol.metadata??=Symbol.for("Symbol.metadata");export const RAW=Symbol.for("baker:raw");export const SEALED=Symbol.for("baker:sealed");
1
+ Symbol.metadata??=Symbol.for("Symbol.metadata");export const RAW=Symbol.for("baker:raw");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zipbul/baker",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Bun-only AOT decorator-based DTO validation & serialization. class-validator DX, sealed code generation, zero reflect-metadata.",
5
5
  "keywords": [
6
6
  "aot",