@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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @zipbul/baker
2
2
 
3
+ ## 5.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2d61542: Baker-scoped runtime: `deserialize`/`validate`/`serialize` (plus the `*Sync`/`*Async`
8
+ variants) are now methods on a `Baker` instance — `app.deserialize(Dto, input)`. Each
9
+ baker compiles its own executor per class into its own map, so the **same class sealed by
10
+ two bakers with different configs behaves per each baker's config** — apps in one process
11
+ never mix. An undecorated subclass resolves to its nearest sealed ancestor within that
12
+ baker. Same-config bakers transparently share one compiled executor via a `(class, config)`
13
+ cache (compile once, no behavior change).
14
+
15
+ **BREAKING CHANGE:** the global `deserialize`/`validate`/`serialize` functions (and their
16
+ `*Sync`/`*Async` variants) are removed from the package entry, along with the published
17
+ `SEALED` symbol (`RAW` remains on `@zipbul/baker/symbols`). Migrate `deserialize(Dto, input)`
18
+ to `app.deserialize(Dto, input)` on the `Baker` instance that sealed the class.
19
+
3
20
  ## 5.0.0
4
21
 
5
22
  ### Major Changes
package/README.md CHANGED
@@ -27,7 +27,7 @@ Zero `reflect-metadata`. Sealed codegen.
27
27
  ## Quick Start
28
28
 
29
29
  ```typescript
30
- import { Baker, Field, deserialize, isBakerIssueSet } from '@zipbul/baker';
30
+ import { Baker, Field, isBakerIssueSet } from '@zipbul/baker';
31
31
  import { isString, isNumber, isEmail, min, minLength } from '@zipbul/baker/rules';
32
32
 
33
33
  const baker = new Baker();
@@ -43,7 +43,7 @@ class UserDto {
43
43
  baker.seal();
44
44
 
45
45
  // All rules here are sync, so deserialize returns the value directly (no await).
46
- const result = deserialize(UserDto, {
46
+ const result = baker.deserialize(UserDto, {
47
47
  name: 'Alice',
48
48
  age: 30,
49
49
  email: 'alice@test.com',
@@ -67,7 +67,7 @@ if (isBakerIssueSet(result)) {
67
67
  | `@app.Recipe` | Marks a class as a DTO of that baker. Only `@Field` properties are part of the contract. |
68
68
  | `@Field(...rules)` | Declares a validated field. Global — works with any baker. |
69
69
  | `app.seal()` | Compiles that baker's DTOs into executor functions. Call once, at startup. |
70
- | `deserialize` / `validate` / `serialize` | Global run the sealed executors stored on the class: parse+validate, validate-only, or emit a plain object. |
70
+ | `app.deserialize` / `app.validate` / `app.serialize` | Run that baker's compiled executors: parse+validate, validate-only, or emit a plain object. |
71
71
 
72
72
  > Examples below assume a `const baker = new Baker()` in scope and a single `baker.seal()` after the DTOs are defined.
73
73
 
@@ -143,8 +143,8 @@ class UserDto {
143
143
  displayName!: string;
144
144
  }
145
145
 
146
- deserialize(UserDto, input); // `ssn` is skipped
147
- deserialize(UserDto, input, { groups: ['admin'] }); // `ssn` is included
146
+ baker.deserialize(UserDto, input); // `ssn` is skipped
147
+ baker.deserialize(UserDto, input, { groups: ['admin'] }); // `ssn` is included
148
148
  ```
149
149
 
150
150
  A field with no `groups` is always included; a field tagged with `groups` participates only when a matching group is passed via [runtime options](#runtime-options). See [`RuntimeOptions`](#runtime-options) for the call-site shape.
@@ -351,9 +351,9 @@ const app = new Baker({
351
351
  });
352
352
  ```
353
353
 
354
- `deserialize` / `serialize` / `validate` are global they read the sealed executor off the class — and throw `BakerError` if the class is not sealed.
354
+ `app.deserialize` / `app.serialize` / `app.validate` run that baker's compiled executors and throw `BakerError` if the class was not sealed by this baker.
355
355
 
356
- **Isolation:** distinct classes are fully isolated (each sealed with its baker's config). A class shared across bakers is sealed once (first seal wins) use separate classes if you need different config.
356
+ **Isolation:** each baker compiles its own executor per class into its own map, so the **same class sealed by two bakers behaves per each baker's config** — apps never mix. (An undecorated subclass resolves to its nearest sealed ancestor within that baker.)
357
357
 
358
358
  ### `deserialize` / `serialize` / `validate`
359
359
 
@@ -418,7 +418,7 @@ baker separates two failure modes:
418
418
  - **`BakerIssueSet` (returned)** — a validation failure. `deserialize` and `validate` return it instead of throwing. Guard with `isBakerIssueSet` and read `.errors`.
419
419
 
420
420
  ```typescript
421
- const result = deserialize(UserDto, input);
421
+ const result = baker.deserialize(UserDto, input);
422
422
 
423
423
  if (isBakerIssueSet(result)) {
424
424
  for (const issue of result.errors) {
@@ -445,11 +445,11 @@ Yes. If any rule or transformer is async, baker automatically detects it at seal
445
445
 
446
446
  ### Can I use baker with NestJS?
447
447
 
448
- Yes. baker's `@Field` decorator works alongside NestJS pipes. Use `deserialize()` in a custom validation pipe.
448
+ Yes. baker's `@Field` decorator works alongside NestJS pipes. Use `app.deserialize()` (your `Baker` instance) in a custom validation pipe.
449
449
 
450
450
  ### How does the AOT code generation work?
451
451
 
452
- Calling `app.seal()` once at startup walks the baker's DTOs (and their nested DTOs), analyzes field metadata, generates optimized JavaScript executor functions, and stores them on each class. Subsequent `deserialize` / `serialize` / `validate` calls run the pre-compiled functions directly. There is no auto-seal — using a DTO before `app.seal()` raises `BakerError`.
452
+ Calling `app.seal()` once at startup walks the baker's DTOs (and their nested DTOs), analyzes field metadata, generates optimized JavaScript executor functions, and stores them in that baker's map. Subsequent `app.deserialize` / `app.serialize` / `app.validate` calls run the pre-compiled functions directly. There is no auto-seal — using a DTO before `app.seal()` raises `BakerError`.
453
453
 
454
454
  > baker builds its executors with `new Function()`. Under a strict Content-Security-Policy this requires `'unsafe-eval'`; baker will not run in environments that forbid runtime code generation.
455
455
 
@@ -457,10 +457,7 @@ Calling `app.seal()` once at startup walks the baker's DTOs (and their nested DT
457
457
 
458
458
  ```typescript
459
459
  import {
460
- Baker,
461
- deserialize, deserializeSync, deserializeAsync,
462
- validate, validateSync, validateAsync,
463
- serialize, serializeSync, serializeAsync,
460
+ Baker, // .deserialize / .validate / .serialize (+ *Sync / *Async) live on the instance
464
461
  createRule, Field, arrayOf, isBakerIssueSet, BakerError, RequiredType, ExcludeMode,
465
462
  } from '@zipbul/baker';
466
463
  import type { Transformer, TransformParams, BakerIssue, BakerIssueSet, FieldOptions, EmittableRule, RuntimeOptions, BakerConfig } from '@zipbul/baker';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,3 @@
1
- export { deserialize, deserializeSync, deserializeAsync } from './src/functions/deserialize';
2
- export { validate, validateSync, validateAsync } from './src/functions/validate';
3
- export { serialize, serializeSync, serializeAsync } from './src/functions/serialize';
4
1
  export { createRule } from './src/create-rule';
5
2
  export { Field, arrayOf } from './src/decorators/index';
6
3
  export type { FieldOptions, ArrayOfMarker } from './src/decorators/index';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{deserialize,deserializeSync,deserializeAsync}from"./src/functions/deserialize.js";export{validate,validateSync,validateAsync}from"./src/functions/validate.js";export{serialize,serializeSync,serializeAsync}from"./src/functions/serialize.js";export{createRule}from"./src/create-rule.js";export{Field,arrayOf}from"./src/decorators/index.js";export{Baker}from"./src/baker.js";export{ExcludeMode,RequiredType}from"./src/enums.js";export{isBakerIssueSet,BakerError}from"./src/errors.js";
1
+ export{createRule}from"./src/create-rule.js";export{Field,arrayOf}from"./src/decorators/index.js";export{Baker}from"./src/baker.js";export{ExcludeMode,RequiredType}from"./src/enums.js";export{isBakerIssueSet,BakerError}from"./src/errors.js";
@@ -1,20 +1,22 @@
1
1
  import type { BakerConfig } from './configure';
2
+ import type { BakerIssueSet } from './errors';
3
+ import type { RuntimeOptions } from './interfaces';
2
4
  /**
3
- * A baker — an isolated registration + seal boundary. Each `new Baker()` owns its own registry and
4
- * config, so multiple bakers in one process (or a bundler-duplicated copy of the library) never
5
- * fragment each other. `@Field`, the rule factories, and `deserialize`/`serialize`/`validate` stay
6
- * global they read the metadata/executor stored on the class itself — so only the class-collecting
7
- * `Recipe` and `seal` belong to the instance.
5
+ * A baker — an isolated registration + seal + runtime boundary. Each `new Baker()` owns its own
6
+ * registry, config, and compiled executors, so multiple bakers in one process (or a bundler-duplicated
7
+ * copy of the library) never fragment each other. `@Field` and the rule factories stay global (they
8
+ * write class-intrinsic schema); registration (`Recipe`), sealing (`seal`), and running
9
+ * (`deserialize`/`serialize`/`validate`) all belong to the instance.
8
10
  *
9
11
  * ```ts
10
12
  * const app = new Baker({ autoConvert: true });
11
13
  * @app.Recipe class UserDto { @Field(isString) name!: string }
12
14
  * app.seal();
13
- * deserialize(UserDto, input);
15
+ * app.deserialize(UserDto, input);
14
16
  * ```
15
17
  *
16
- * Isolation boundary is class identity: distinct classes are fully isolated (each sealed with its
17
- * baker's config); a class shared across bakers is reused as one sealed form.
18
+ * Isolation boundary is class identity, scoped per baker: the SAME class sealed by two bakers with
19
+ * different configs behaves per each baker's config (each compiles its own executor into its own map).
18
20
  *
19
21
  * `Recipe` and `seal` are arrow-field properties, not prototype methods, by design: `@app.Recipe`
20
22
  * is applied as a detached value (the runtime calls the decorator with no `this` receiver), so it
@@ -28,4 +30,13 @@ export declare class Baker {
28
30
  readonly Recipe: (value: Function, _context: ClassDecoratorContext) => void;
29
31
  /** Seal every root registered to this baker (and its nested DTOs) with this baker's config. */
30
32
  readonly seal: () => void;
33
+ deserialize: <T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions) => T | BakerIssueSet | Promise<T | BakerIssueSet>;
34
+ deserializeSync: <T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions) => T | BakerIssueSet;
35
+ deserializeAsync: <T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions) => Promise<T | BakerIssueSet>;
36
+ validate: <T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions) => true | BakerIssueSet | Promise<true | BakerIssueSet>;
37
+ validateSync: <T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions) => true | BakerIssueSet;
38
+ validateAsync: <T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions) => Promise<true | BakerIssueSet>;
39
+ serialize: <T>(instance: T, options?: RuntimeOptions) => Record<string, unknown> | Promise<Record<string, unknown>>;
40
+ serializeSync: <T>(instance: T, options?: RuntimeOptions) => Record<string, unknown>;
41
+ serializeAsync: <T>(instance: T, options?: RuntimeOptions) => Promise<Record<string, unknown>>;
31
42
  }
package/dist/src/baker.js CHANGED
@@ -1 +1 @@
1
- export class Baker{#j=new Set;#q;#x=!1;constructor(j){this.#q=j===void 0?Object.freeze({}):q(j)}Recipe=(j,A)=>{this.#j.add(j)};seal=()=>{if(this.#x)return;x(this.#j,this.#q);this.#x=!0}}import{normalizeConfig as q}from"./configure.js";import{sealRegistry as x}from"./seal/seal.js";
1
+ export class Baker{#G=new Set;#F=new Map;#H;#I=!1;constructor(j){this.#H=j===void 0?Object.freeze({}):K(j)}Recipe=(j,F)=>{this.#G.add(j)};seal=()=>{if(this.#I)return;_(this.#G,this.#H,this.#F);this.#I=!0};#j(j){let F=j;while(F){const H=this.#F.get(F);if(H){if(F!==j)this.#F.set(j,H);return H}const J=Object.getPrototypeOf(F);F=typeof J==="function"?J:null}const G=j.name||"<anonymous class>";throw new L(`${G} is not sealed by this baker`)}deserialize=(j,F,G)=>M(this.#j(j),F,G);deserializeSync=(j,F,G)=>N(this.#j(j),j.name,F,G);deserializeAsync=(j,F,G)=>P(this.#j(j),F,G);validate=(j,F,G)=>X(this.#j(j),F,G);validateSync=(j,F,G)=>Y(this.#j(j),j.name,F,G);validateAsync=(j,F,G)=>Z(this.#j(j),F,G);serialize=(j,F)=>Q(this.#j(I(j,"serialize")),j,F);serializeSync=(j,F)=>{const G=I(j,"serializeSync");return U(this.#j(G),G.name,j,F)};serializeAsync=(j,F)=>W(this.#j(I(j,"serializeAsync")),j,F)}import{normalizeConfig as K}from"./configure.js";import{BakerError as L}from"./errors.js";import{runDeserialize as M,runDeserializeSync as N,runDeserializeAsync as P}from"./functions/deserialize.js";import{resolveSerializeClass as I,runSerialize as Q,runSerializeSync as U,runSerializeAsync as W}from"./functions/serialize.js";import{runValidate as X,runValidateSync as Y,runValidateAsync as Z}from"./functions/validate.js";import{sealRegistry as _}from"./seal/seal.js";
@@ -1,19 +1,7 @@
1
1
  import type { RuntimeOptions } from '../interfaces';
2
+ import type { SealedExecutors } from '../types';
2
3
  import { type BakerIssueSet } from '../errors';
3
- /**
4
- * Converts input to a Class instance + validates.
5
- * - Requires the class's baker to be sealed (`new Baker().seal()`) beforehand; throws `BakerError` if not sealed
6
- * - Sync DTOs return directly; async DTOs return Promise
7
- * - Success: T
8
- * - Validation failure: BakerIssueSet (use isBakerIssueSet() to narrow)
9
- */
10
- export declare function deserialize<T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions): T | BakerIssueSet | Promise<T | BakerIssueSet>;
11
- /**
12
- * Sync-asserted deserialize. Throws `BakerError` if Class has any async rule/transform
13
- * on the deserialize side.
14
- */
15
- export declare function deserializeSync<T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions): T | BakerIssueSet;
16
- /**
17
- * Async-asserted deserialize. Always returns Promise (sync DTOs are wrapped via Promise.resolve).
18
- */
19
- export declare function deserializeAsync<T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions): Promise<T | BakerIssueSet>;
4
+ declare function runDeserialize<T>(sealed: SealedExecutors<unknown>, input: unknown, options?: RuntimeOptions): T | BakerIssueSet | Promise<T | BakerIssueSet>;
5
+ declare function runDeserializeSync<T>(sealed: SealedExecutors<unknown>, className: string, input: unknown, options?: RuntimeOptions): T | BakerIssueSet;
6
+ declare function runDeserializeAsync<T>(sealed: SealedExecutors<unknown>, input: unknown, options?: RuntimeOptions): Promise<T | BakerIssueSet>;
7
+ export { runDeserialize, runDeserializeSync, runDeserializeAsync };
@@ -1 +1 @@
1
- import{isErr as H}from"@zipbul/result";import{toBakerIssueSet as J,BakerError as M}from"../errors.js";import{ensureSealed as K}from"../seal/seal.js";import{checkCallOptions as L}from"./check-call-options.js";export function deserialize(F,j,G){const q=L(G),g=K(F);if(g.isAsync)return g.deserialize(j,q).then((x)=>{if(H(x))return J(x.data);return x});const f=g.deserialize(j,q);if(H(f))return J(f.data);return f}export function deserializeSync(F,j,G){const q=L(G),g=K(F);if(g.isAsync)throw new M(`deserializeSync(${F.name}): DTO has async rules/transforms. Use deserializeAsync() instead.`);const f=g.deserialize(j,q);if(H(f))return J(f.data);return f}export function deserializeAsync(F,j,G){const q=L(G),g=K(F);if(g.isAsync)return g.deserialize(j,q).then((x)=>{if(H(x))return J(x.data);return x});const f=g.deserialize(j,q);if(H(f))return Promise.resolve(J(f.data));return Promise.resolve(f)}
1
+ import{isErr as x}from"@zipbul/result";import{toBakerIssueSet as F,BakerError as H}from"../errors.js";import{checkCallOptions as G}from"./check-call-options.js";function runDeserialize(g,q,w){const v=G(w);if(g.isAsync)return g.deserialize(q,v).then((f)=>{if(x(f))return F(f.data);return f});const j=g.deserialize(q,v);if(x(j))return F(j.data);return j}function runDeserializeSync(g,q,w,v){const j=G(v);if(g.isAsync)throw new H(`deserializeSync(${q}): DTO has async rules/transforms. Use deserializeAsync() instead.`);const f=g.deserialize(w,j);if(x(f))return F(f.data);return f}function runDeserializeAsync(g,q,w){const v=G(w);if(g.isAsync)return g.deserialize(q,v).then((f)=>{if(x(f))return F(f.data);return f});const j=g.deserialize(q,v);if(x(j))return Promise.resolve(F(j.data));return Promise.resolve(j)}export{runDeserialize,runDeserializeSync,runDeserializeAsync};
@@ -1,16 +1,11 @@
1
1
  import type { RuntimeOptions } from '../interfaces';
2
+ import type { SealedExecutors } from '../types';
2
3
  /**
3
- * Converts a Class instance to a plain object.
4
- * - Requires the class's baker to be sealed (`new Baker().seal()`) beforehand; throws `BakerError` if not sealed
5
- * - Sync DTOs return directly; async DTOs return Promise
6
- * - No validation — always returns Record<string, unknown>
4
+ * Forgery check shared by the Baker serialize methods. Returns the validated constructor; resolution
5
+ * to a sealed executor is done by the caller from its baker map.
7
6
  */
8
- export declare function serialize<T>(instance: T, options?: RuntimeOptions): Record<string, unknown> | Promise<Record<string, unknown>>;
9
- /**
10
- * Sync-asserted serialize. Throws `BakerError` if Class has any async transform on the serialize side.
11
- */
12
- export declare function serializeSync<T>(instance: T, options?: RuntimeOptions): Record<string, unknown>;
13
- /**
14
- * Async-asserted serialize. Always returns Promise (sync DTOs are wrapped via Promise.resolve).
15
- */
16
- export declare function serializeAsync<T>(instance: T, options?: RuntimeOptions): Promise<Record<string, unknown>>;
7
+ declare function resolveSerializeClass(instance: unknown, fnName: string): Function;
8
+ declare function runSerialize<T>(sealed: SealedExecutors<unknown>, instance: T, options?: RuntimeOptions): Record<string, unknown> | Promise<Record<string, unknown>>;
9
+ declare function runSerializeSync<T>(sealed: SealedExecutors<unknown>, className: string, instance: T, options?: RuntimeOptions): Record<string, unknown>;
10
+ declare function runSerializeAsync<T>(sealed: SealedExecutors<unknown>, instance: T, options?: RuntimeOptions): Promise<Record<string, unknown>>;
11
+ export { resolveSerializeClass, runSerialize, runSerializeSync, runSerializeAsync };
@@ -1 +1 @@
1
- import{BakerError as x}from"../errors.js";import{ensureSealed as I}from"../seal/seal.js";import{checkCallOptions as F}from"./check-call-options.js";function G(b,q){if(b==null||typeof b!=="object")throw new x(`${q}: expected a class instance, got ${b===null?"null":typeof b}`);const g=b.constructor;if(typeof g!=="function")throw new x(`${q}: instance has no constructor`);if(g===Object||!(b instanceof g))throw new x(`${q}: received a plain object. Pass an instance of a DTO class decorated with @Field.`);return I(g)}export function serialize(b,q){const g=F(q),j=G(b,"serialize");return j.isSerializeAsync?j.serialize(b,g):j.serialize(b,g)}export function serializeSync(b,q){const g=F(q),j=G(b,"serializeSync");if(j.isSerializeAsync){const H=b.constructor.name;throw new x(`serializeSync(${H}): DTO has async serialize transforms. Use serializeAsync() instead.`)}return j.serialize(b,g)}export function serializeAsync(b,q){const g=F(q),j=G(b,"serializeAsync");return j.isSerializeAsync?j.serialize(b,g):Promise.resolve(j.serialize(b,g))}
1
+ import{BakerError as w}from"../errors.js";import{checkCallOptions as x}from"./check-call-options.js";function resolveSerializeClass(b,g){if(b==null||typeof b!=="object")throw new w(`${g}: expected a class instance, got ${b===null?"null":typeof b}`);const j=b.constructor;if(typeof j!=="function")throw new w(`${g}: instance has no constructor`);if(j===Object||!(b instanceof j))throw new w(`${g}: received a plain object. Pass an instance of a DTO class decorated with @Field.`);return j}function runSerialize(b,g,j){const q=x(j);return b.isSerializeAsync?b.serialize(g,q):b.serialize(g,q)}function runSerializeSync(b,g,j,q){const D=x(q);if(b.isSerializeAsync)throw new w(`serializeSync(${g}): DTO has async serialize transforms. Use serializeAsync() instead.`);return b.serialize(j,D)}function runSerializeAsync(b,g,j){const q=x(j);return b.isSerializeAsync?b.serialize(g,q):Promise.resolve(b.serialize(g,q))}export{resolveSerializeClass,runSerialize,runSerializeSync,runSerializeAsync};
@@ -1,18 +1,7 @@
1
1
  import type { BakerIssueSet } from '../errors';
2
2
  import type { RuntimeOptions } from '../interfaces';
3
- /**
4
- * DTO-level validation validates `input` against a decorated class's schema.
5
- * Sync DTOs return directly; async DTOs return Promise. To validate a single primitive without a
6
- * DTO, call the rule directly (e.g. `isEmail()(value)`).
7
- */
8
- declare function validate<T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions): true | BakerIssueSet | Promise<true | BakerIssueSet>;
9
- /**
10
- * Sync-asserted validate. Throws `BakerError` if Class has any async rule/transform
11
- * on the deserialize/validate side. Use when caller code assumes sync return.
12
- */
13
- declare function validateSync<T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions): true | BakerIssueSet;
14
- /**
15
- * Async-asserted validate. Always returns Promise (sync DTOs are wrapped via Promise.resolve).
16
- */
17
- declare function validateAsync<T>(Class: new (...args: never[]) => T, input: unknown, options?: RuntimeOptions): Promise<true | BakerIssueSet>;
18
- export { validate, validateSync, validateAsync };
3
+ import type { SealedExecutors } from '../types';
4
+ declare function runValidate(sealed: SealedExecutors<unknown>, input: unknown, options?: RuntimeOptions): true | BakerIssueSet | Promise<true | BakerIssueSet>;
5
+ declare function runValidateSync(sealed: SealedExecutors<unknown>, className: string, input: unknown, options?: RuntimeOptions): true | BakerIssueSet;
6
+ declare function runValidateAsync(sealed: SealedExecutors<unknown>, input: unknown, options?: RuntimeOptions): Promise<true | BakerIssueSet>;
7
+ export { runValidate, runValidateSync, runValidateAsync };
@@ -1 +1 @@
1
- import{toBakerIssueSet as F,BakerError as J}from"../errors.js";import{ensureSealed as G}from"../seal/seal.js";import{checkCallOptions as H}from"./check-call-options.js";function validate(q,g,x){const j=H(x),b=G(q);if(b.isAsync)return b.validate(g,j).then((z)=>z===null?!0:F(z));const f=b.validate(g,j);return f===null?!0:F(f)}function validateSync(q,g,x){const j=H(x),b=G(q);if(b.isAsync)throw new J(`validateSync(${q.name}): DTO has async rules/transforms. Use validateAsync() instead.`);const f=b.validate(g,j);return f===null?!0:F(f)}function validateAsync(q,g,x){const j=H(x),b=G(q);if(b.isAsync)return b.validate(g,j).then((z)=>z===null?!0:F(z));const f=b.validate(g,j);return Promise.resolve(f===null?!0:F(f))}export{validate,validateSync,validateAsync};
1
+ import{toBakerIssueSet as w,BakerError as z}from"../errors.js";import{checkCallOptions as x}from"./check-call-options.js";function runValidate(b,g,v){const j=x(v);if(b.isAsync)return b.validate(g,j).then((f)=>f===null?!0:w(f));const q=b.validate(g,j);return q===null?!0:w(q)}function runValidateSync(b,g,v,j){const q=x(j);if(b.isAsync)throw new z(`validateSync(${g}): DTO has async rules/transforms. Use validateAsync() instead.`);const f=b.validate(v,q);return f===null?!0:w(f)}function runValidateAsync(b,g,v){const j=x(v);if(b.isAsync)return b.validate(g,j).then((f)=>f===null?!0:w(f));const q=b.validate(g,j);return Promise.resolve(q===null?!0:w(q))}export{runValidate,runValidateSync,runValidateAsync};
@@ -1,10 +1,4 @@
1
- import type { RawClassMeta, SealedExecutors } from './types';
2
- export declare function getSealed(cls: Function): SealedExecutors<unknown> | undefined;
3
- /** Same as getSealed but throws if the class is not sealed — for callers that establish the invariant elsewhere. */
4
- export declare function requireSealed(cls: Function): SealedExecutors<unknown>;
5
- export declare function setSealed(cls: Function, exec: SealedExecutors<unknown>): void;
6
- export declare function hasSealedOwn(cls: Function): boolean;
7
- export declare function deleteSealed(cls: Function): void;
1
+ import type { RawClassMeta } from './types';
8
2
  export declare function deleteRaw(cls: Function): void;
9
3
  export declare function getRaw(cls: Function): RawClassMeta | undefined;
10
4
  /** Same as getRaw but throws if the class has no @Field decorators — for callers that establish the invariant elsewhere. */
@@ -16,4 +10,3 @@ export declare function setRaw(cls: Function, raw: RawClassMeta): void;
16
10
  * the dual own-check keeps mergeInheritance from double-counting inherited fields.
17
11
  */
18
12
  export declare function hasRawOwn(cls: Function): boolean;
19
- export declare function freezeRaw(cls: Function): void;
@@ -1 +1 @@
1
- import{RAW as B,SEALED as q}from"./symbols.js";function C(j){return j[Symbol.metadata]??void 0}function F(j){if(!Object.hasOwn(j,Symbol.metadata))Object.defineProperty(j,Symbol.metadata,{value:{},writable:!0,configurable:!0,enumerable:!1});return j[Symbol.metadata]}export function getSealed(j){return j[q]}export function requireSealed(j){const k=j[q];if(k===void 0)throw Error(`${j.name||"<anonymous>"}: class is not sealed`);return k}export function setSealed(j,k){j[q]=k}export function hasSealedOwn(j){return Object.hasOwn(j,q)}export function deleteSealed(j){delete j[q]}export function deleteRaw(j){if(Object.hasOwn(j,Symbol.metadata))delete j[Symbol.metadata][B]}export function getRaw(j){return C(j)?.[B]}export function requireRaw(j){const k=getRaw(j);if(k===void 0)throw Error(`${j.name||"<anonymous>"}: class has no @Field decorators`);return k}export function setRaw(j,k){F(j)[B]=k}export function hasRawOwn(j){if(!Object.hasOwn(j,Symbol.metadata))return!1;const k=j[Symbol.metadata];return k!=null&&Object.hasOwn(k,B)}export function freezeRaw(j){if(!hasRawOwn(j))return;Object.freeze(getRaw(j))}
1
+ import{RAW as x}from"./symbols.js";function z(j){return j[Symbol.metadata]??void 0}function B(j){if(!Object.hasOwn(j,Symbol.metadata))Object.defineProperty(j,Symbol.metadata,{value:{},writable:!0,configurable:!0,enumerable:!1});return j[Symbol.metadata]}export function deleteRaw(j){if(Object.hasOwn(j,Symbol.metadata))delete j[Symbol.metadata][x]}export function getRaw(j){return z(j)?.[x]}export function requireRaw(j){const q=getRaw(j);if(q===void 0)throw Error(`${j.name||"<anonymous>"}: class has no @Field decorators`);return q}export function setRaw(j,q){B(j)[x]=q}export function hasRawOwn(j){if(!Object.hasOwn(j,Symbol.metadata))return!1;const q=j[Symbol.metadata];return q!=null&&Object.hasOwn(q,x)}
@@ -1,10 +1,10 @@
1
1
  import type { Result, ResultAsync } from '@zipbul/result';
2
2
  import type { SealOptions, RuntimeOptions } from '../interfaces';
3
- import type { RawClassMeta } from '../types';
3
+ import type { RawClassMeta, SealedExecutors } from '../types';
4
4
  import { type BakerIssue } from '../errors';
5
5
  type DeserializeExecutor<T> = (input: unknown, opts?: RuntimeOptions) => Result<T, BakerIssue[]> | ResultAsync<T, BakerIssue[]>;
6
6
  type ValidateExecutor = (input: unknown, opts?: RuntimeOptions) => BakerIssue[] | null | Promise<BakerIssue[] | null>;
7
- declare function buildDeserializeCode<T>(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, needsCircularCheck: boolean, isAsync: boolean): DeserializeExecutor<T>;
8
- declare function buildDeserializeCode(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, needsCircularCheck: boolean, isAsync: boolean, validateOnly: true): ValidateExecutor;
9
- declare function buildValidateCode(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, needsCircularCheck: boolean, isAsync: boolean): ValidateExecutor;
7
+ declare function buildDeserializeCode<T>(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, needsCircularCheck: boolean, isAsync: boolean, resolve: (cls: Function) => SealedExecutors<unknown> | undefined): DeserializeExecutor<T>;
8
+ declare function buildDeserializeCode(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, needsCircularCheck: boolean, isAsync: boolean, resolve: (cls: Function) => SealedExecutors<unknown> | undefined, validateOnly: true): ValidateExecutor;
9
+ declare function buildValidateCode(Class: Function, merged: RawClassMeta, options: SealOptions | undefined, needsCircularCheck: boolean, isAsync: boolean, resolve: (cls: Function) => SealedExecutors<unknown> | undefined): ValidateExecutor;
10
10
  export { buildDeserializeCode, buildValidateCode };