@zipbul/baker 2.2.0 → 3.0.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 +256 -0
- package/MIGRATION-3.0.md +104 -0
- package/README.md +109 -63
- package/dist/index.d.ts +7 -6
- package/dist/index.js +10 -321
- package/dist/src/collect.d.ts +13 -10
- package/dist/src/collect.js +26 -0
- package/dist/src/configure.d.ts +8 -6
- package/dist/src/configure.js +43 -0
- package/dist/src/create-rule.js +41 -0
- package/dist/src/decorators/field.d.ts +22 -18
- package/dist/src/decorators/field.js +268 -0
- package/dist/src/decorators/index.d.ts +1 -0
- package/dist/src/decorators/index.js +2 -2
- package/dist/src/decorators/recipe.d.ts +17 -0
- package/dist/src/decorators/recipe.js +23 -0
- package/dist/src/errors.d.ts +27 -17
- package/dist/src/errors.js +52 -0
- package/dist/src/functions/check-call-options.d.ts +8 -0
- package/dist/src/functions/check-call-options.js +51 -0
- package/dist/src/functions/deserialize.d.ts +13 -6
- package/dist/src/functions/deserialize.js +57 -0
- package/dist/src/functions/serialize.d.ts +10 -4
- package/dist/src/functions/serialize.js +52 -0
- package/dist/src/functions/validate.d.ts +13 -10
- package/dist/src/functions/validate.js +49 -0
- package/dist/src/interfaces.d.ts +1 -1
- package/dist/src/interfaces.js +4 -0
- package/dist/src/meta-access.d.ts +19 -0
- package/dist/src/meta-access.js +75 -0
- package/dist/src/registry.js +8 -0
- package/dist/src/rule-metadata.d.ts +11 -0
- package/dist/src/rule-metadata.js +17 -0
- package/dist/src/rule-plan.d.ts +10 -11
- package/dist/src/rule-plan.js +117 -0
- package/dist/src/rules/array.d.ts +7 -6
- package/dist/src/rules/array.js +96 -0
- package/dist/src/rules/common.js +77 -0
- package/dist/src/rules/date.js +35 -0
- package/dist/src/rules/index.d.ts +2 -4
- package/dist/src/rules/index.js +8 -21
- package/dist/src/rules/locales.d.ts +5 -4
- package/dist/src/rules/locales.js +249 -0
- package/dist/src/rules/number.js +79 -0
- package/dist/src/rules/object.d.ts +1 -1
- package/dist/src/rules/object.js +49 -0
- package/dist/src/rules/string.d.ts +83 -80
- package/dist/src/rules/string.js +1998 -0
- package/dist/src/rules/typechecker.js +143 -0
- package/dist/src/seal/circular-analyzer.js +63 -0
- package/dist/src/seal/codegen-utils.js +18 -0
- package/dist/src/seal/deserialize-builder.d.ts +8 -4
- package/dist/src/seal/deserialize-builder.js +1546 -0
- package/dist/src/seal/expose-validator.d.ts +3 -2
- package/dist/src/seal/expose-validator.js +65 -0
- package/dist/src/seal/seal-state.d.ts +10 -0
- package/dist/src/seal/seal-state.js +18 -0
- package/dist/src/seal/seal.d.ts +22 -21
- package/dist/src/seal/seal.js +431 -0
- package/dist/src/seal/serialize-builder.d.ts +3 -2
- package/dist/src/seal/serialize-builder.js +374 -0
- package/dist/src/seal/validate-meta.d.ts +13 -0
- package/dist/src/seal/validate-meta.js +61 -0
- package/dist/src/symbols.d.ts +1 -1
- package/dist/src/symbols.js +13 -2
- package/dist/src/transformers/collection.transformer.js +25 -0
- package/dist/src/transformers/date.transformer.js +18 -0
- package/dist/src/transformers/index.js +6 -2
- package/dist/src/transformers/luxon.transformer.d.ts +4 -2
- package/dist/src/transformers/luxon.transformer.js +34 -0
- package/dist/src/transformers/moment.transformer.d.ts +4 -2
- package/dist/src/transformers/moment.transformer.js +32 -0
- package/dist/src/transformers/number.transformer.js +8 -0
- package/dist/src/transformers/string.transformer.js +12 -0
- package/dist/src/types.d.ts +27 -25
- package/dist/src/types.js +1 -0
- package/dist/src/utils.d.ts +2 -2
- package/dist/src/utils.js +10 -0
- package/package.json +80 -67
- package/dist/index-03cysbck.js +0 -3
- package/dist/index-dcbd798a.js +0 -3
- package/dist/index-jp2yjd6g.js +0 -3
- package/dist/index-mw7met6r.js +0 -3
- package/dist/index-xdn55cz3.js +0 -1
- package/dist/src/functions/_run-sealed.d.ts +0 -7
- package/dist/src/functions/index.d.ts +0 -3
- package/dist/src/seal/index.d.ts +0 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# @zipbul/baker
|
|
2
|
+
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 421fd54: 3.0 — error system redesign and API hardening (breaking).
|
|
8
|
+
|
|
9
|
+
**Error channel.** A single `BakerError` class is now thrown for every developer/config/schema
|
|
10
|
+
misuse (it carries `cause`). The validation-result types are renamed for clarity:
|
|
11
|
+
|
|
12
|
+
- `SealError` → `BakerError` (the thrown class)
|
|
13
|
+
- the field-error interface `BakerError` → `BakerIssue`
|
|
14
|
+
- `BakerErrors` → `BakerIssueSet`
|
|
15
|
+
- `isBakerError` → `isBakerIssueSet`
|
|
16
|
+
|
|
17
|
+
The split is now explicit: **throw `BakerError`** for misuse discoverable without input;
|
|
18
|
+
**return `BakerIssueSet`** for external-input validation failures from `deserialize`/`validate`.
|
|
19
|
+
|
|
20
|
+
**API hardening.** `validate(Class, input)` is DTO-only (the ad-hoc `validate(value, ...rules)`
|
|
21
|
+
mode was removed — call a rule directly instead). `configure()` rejects unknown keys and
|
|
22
|
+
post-`seal()` calls, and seal-time options can no longer be passed per-call.
|
|
23
|
+
|
|
24
|
+
See `MIGRATION-3.0.md` for the full upgrade guide.
|
|
25
|
+
|
|
26
|
+
### Minor Changes
|
|
27
|
+
|
|
28
|
+
- 421fd54: Add the `isHttpToken` rule — validates the RFC 9110 §5.6.2 HTTP `token` production
|
|
29
|
+
(`1*tchar`), used for HTTP method names and header field-names. Usable as a predicate
|
|
30
|
+
(`isHttpToken(value)`) or as `@Field(isHttpToken)`, and exported from `@zipbul/baker/rules`.
|
|
31
|
+
|
|
32
|
+
## 3.0.0
|
|
33
|
+
|
|
34
|
+
### DX reform — breaking changes
|
|
35
|
+
|
|
36
|
+
- **Auto-seal removed.** Call `seal()` once at app startup, after every DTO module is loaded. Without it, the first `deserialize` / `serialize` / `validate` call throws `SealError`.
|
|
37
|
+
- Migration: import `seal` and call `seal()` once before any deserialize/serialize/validate call. For tests, call `seal()` after each `unseal()` / `configure(...)` reconfiguration.
|
|
38
|
+
- **Per-call options are validated.** Only `groups` is a valid per-call option. Passing any other key (`stopAtFirstError`, `autoConvert`, `allowClassDefaults`, `forbidUnknown`, `debug`, …) throws `SealError`. Move those keys into `configure({...})` before `seal()`.
|
|
39
|
+
- **`@Field` argument validation.** Passing a non-rule value (e.g. `@Field(isNumber)` instead of `@Field(isNumber())`) now throws `SealError` immediately with the four valid forms listed in the message.
|
|
40
|
+
- **Map non-string keys.** Serializing a `Map<K, V>` whose key is not a `string` throws `TypeError` — previously the key was silently coerced via `[object Object]` and collided.
|
|
41
|
+
|
|
42
|
+
### API additions
|
|
43
|
+
|
|
44
|
+
- `seal(...classes?)` — explicit AOT seal trigger.
|
|
45
|
+
- `deserializeSync<T>` / `deserializeAsync<T>` / `serializeSync<T>` / `serializeAsync<T>` / `validateSync` / `validateAsync` — strict variants. `*Sync` throws `SealError` when the DTO is async on the relevant direction; `*Async` always returns `Promise`.
|
|
46
|
+
|
|
47
|
+
### Defect fixes
|
|
48
|
+
|
|
49
|
+
- **F-1** `circular-analyzer.walk()` now walks `meta.type.collectionValue` — Set/Map nested DTO cycles are caught at seal time, no more `stack overflow` at runtime.
|
|
50
|
+
- **F-2** Discriminator / Set·Map / inheritance invariants now run before codegen via the new `validate-meta` pass — invalid metadata throws `SealError` with a precise message instead of producing invalid generated JS.
|
|
51
|
+
- **F-3** Discriminator default branch now reports `context: { received, validSubTypes: [...] }` so callers can show the user the allowed values.
|
|
52
|
+
- **F-4** Per-call options other than `groups` are rejected with `SealError` instead of being silently dropped.
|
|
53
|
+
- **F-8** FR passport regex now anchors both ends (`/^[A-Z0-9]{9}$/i`).
|
|
54
|
+
- **F-9** `MAGNET_URI_RE` is anchored on the trailing end.
|
|
55
|
+
- **N-3** Circular-detection `WeakSet` is now allocated per call via `Symbol.for('baker:circular-seen')` threaded through `_opts` — concurrent async calls no longer false-circular on shared input objects.
|
|
56
|
+
- **N-4** `extractCode` checks `Object.hasOwn(input, key)` before reading — prototype-chain values no longer leak into DTO results.
|
|
57
|
+
- **N-6** `mergeInheritance` validation dedup now compares by `ruleName`, so a child redeclaring the same rule (e.g. `minLength(5)`) replaces the parent's rule instead of producing duplicate errors.
|
|
58
|
+
|
|
59
|
+
### Dead code
|
|
60
|
+
|
|
61
|
+
- `src/functions/_run-sealed.ts` removed. The corresponding internal-only tests in `test/e2e/change-coverage.test.ts` were dropped — their coverage is now provided by public-API tests.
|
|
62
|
+
|
|
63
|
+
## 2.2.0
|
|
64
|
+
|
|
65
|
+
### Minor Changes
|
|
66
|
+
|
|
67
|
+
- 78d701a: feat: validate-only executor with inline nested code generation
|
|
68
|
+
|
|
69
|
+
- Add `_validate` sealed executor — validates input without Object.create or property assignment
|
|
70
|
+
- validate() now uses dedicated `_validate` executor instead of routing through `_deserialize`
|
|
71
|
+
- Inline nested DTO validation: nested DTO fields are expanded directly into the parent function body, eliminating per-item function call overhead
|
|
72
|
+
- Recursive inline for all nesting patterns: nested objects, arrays of nested, discriminator, collections (Set/Map), transforms, groups
|
|
73
|
+
- Only circular references fall back to function call (physically impossible to inline)
|
|
74
|
+
- 14 refs-based validators converted to inline emit (isISBN, isISIN, isIBAN, isFQDN, etc.)
|
|
75
|
+
- Type gate dead code removal: 11 redundant checks eliminated in gated paths
|
|
76
|
+
- Rule Plan IR `stripSelfComparison` for AST-level optimization inside type gates
|
|
77
|
+
- Shared codegen utilities extracted to `codegen-utils.ts`
|
|
78
|
+
- GEN constants centralized in serialize-builder to prevent typo-related bugs
|
|
79
|
+
- `makeRule`/`makePlannedRule` factory functions for cleaner rule creation
|
|
80
|
+
- Sync/async contract enforcement for declared-sync rules
|
|
81
|
+
|
|
82
|
+
Performance:
|
|
83
|
+
|
|
84
|
+
- validate() nested 3-level: 8.79ns (typebox: 11.56ns) — 1.3x faster than typebox
|
|
85
|
+
- validate() array 1000 items: 2.35µs (typebox: 2.37µs) — equivalent to typebox
|
|
86
|
+
- validate() vs deserialize(): 2-5x faster across all benchmarks
|
|
87
|
+
- Zero memory leaks verified under 10M sustained operations
|
|
88
|
+
- 26.6M ops/sec throughput (validate valid, flat DTO)
|
|
89
|
+
|
|
90
|
+
## 2.1.0
|
|
91
|
+
|
|
92
|
+
### Minor Changes
|
|
93
|
+
|
|
94
|
+
- 5696199: feat: Transformer interface, built-in transformers, isULID, isCUID2
|
|
95
|
+
|
|
96
|
+
### Breaking Changes
|
|
97
|
+
|
|
98
|
+
- `FieldOptions.transform` now accepts `Transformer | Transformer[]` instead of function
|
|
99
|
+
- `FieldTransformParams`, `FieldTransformFn` types removed — use `Transformer` interface
|
|
100
|
+
- `transformDirection` option removed — use passthrough in the unused direction method
|
|
101
|
+
- Serialize direction applies transforms in reverse order (codec stack)
|
|
102
|
+
|
|
103
|
+
### New Features
|
|
104
|
+
|
|
105
|
+
- `Transformer` interface with separate `deserialize`/`serialize` methods
|
|
106
|
+
- `transform` option accepts arrays — serialize applies in reverse order
|
|
107
|
+
- `type` + `transform` combination support in serialize (nested serialize → transform)
|
|
108
|
+
- 9 built-in core transformers: trim, toLowerCase, toUpperCase, round, unixSeconds, unixMillis, isoString, csv, json
|
|
109
|
+
- 2 optional peer transformers: luxon, moment (async factory, `await import()`)
|
|
110
|
+
- `isULID()` validator
|
|
111
|
+
- `isCUID2()` validator
|
|
112
|
+
- `@zipbul/baker/transformers` subpath export
|
|
113
|
+
|
|
114
|
+
### Improvements
|
|
115
|
+
|
|
116
|
+
- `when` callback typed as `(obj: Record<string, any>)` instead of `any`
|
|
117
|
+
- Sourcemap removed from build output
|
|
118
|
+
- README rewritten with GEO optimization (FAQ, benchmarks, comparison tables)
|
|
119
|
+
- package.json description and keywords optimized
|
|
120
|
+
|
|
121
|
+
## 2.0.0
|
|
122
|
+
|
|
123
|
+
### Major Changes
|
|
124
|
+
|
|
125
|
+
- 5d01955: feat!: v2 API overhaul — isBakerError, validate, performance optimization
|
|
126
|
+
|
|
127
|
+
### Breaking Changes
|
|
128
|
+
|
|
129
|
+
- `deserialize()` no longer throws on validation failure — returns `T | BakerErrors | Promise<T | BakerErrors>`
|
|
130
|
+
- `serialize()` returns directly for sync DTOs — `Record<string, unknown> | Promise<Record<string, unknown>>`
|
|
131
|
+
- `BakerValidationError` class removed — use `isBakerError()` type guard
|
|
132
|
+
- `toJsonSchema()` removed
|
|
133
|
+
- `@Schema` decorator and `schema` field option removed
|
|
134
|
+
- `JsonSchemaOverride`, `ToJsonSchemaOptions` types removed
|
|
135
|
+
- `BAKER_ERROR` symbol no longer exported (internal only)
|
|
136
|
+
- `README.ko.md` removed
|
|
137
|
+
|
|
138
|
+
### New Features
|
|
139
|
+
|
|
140
|
+
- `validate(Class, input, options?)` — DTO-level validation without instantiation
|
|
141
|
+
- `validate(input, ...rules)` — ad-hoc single value validation
|
|
142
|
+
- `isBakerError()` — type guard for narrowing validation results
|
|
143
|
+
- Sync DTOs return directly (no Promise wrapper) across all APIs
|
|
144
|
+
- Memory leak detection CI step
|
|
145
|
+
|
|
146
|
+
### Performance
|
|
147
|
+
|
|
148
|
+
- Valid path: 188ns → 38ns (5x improvement)
|
|
149
|
+
- Invalid path: 6.08µs → 76ns (80x improvement)
|
|
150
|
+
|
|
151
|
+
### Bug Fixes
|
|
152
|
+
|
|
153
|
+
- WeakSet circular detection false positive on same-object reuse
|
|
154
|
+
- serialize-builder async discriminator array syntax error
|
|
155
|
+
- 13 rules missing constraints in metadata
|
|
156
|
+
|
|
157
|
+
## 1.1.0
|
|
158
|
+
|
|
159
|
+
### Minor Changes
|
|
160
|
+
|
|
161
|
+
- b27cdf6: ## New Features
|
|
162
|
+
|
|
163
|
+
- **Sync API optimization** — `deserialize()` and `serialize()` are no longer `async function`. Sync DTOs (no async transforms/rules) skip `Promise` allocation via `Promise.resolve()`. Async DTOs use the executor's native `Promise`. Return type remains `Promise<T>` for backward compatibility.
|
|
164
|
+
|
|
165
|
+
- **Map/Set auto-conversion** — New `type: () => Map` and `type: () => Set` support in `@Field()`:
|
|
166
|
+
|
|
167
|
+
- `Set<T>`: JSON array ↔ `Set`, with optional `setValue: () => DtoClass` for nested DTOs
|
|
168
|
+
- `Map<string, T>`: JSON object ↔ `Map`, with optional `mapValue: () => DtoClass` for nested DTOs
|
|
169
|
+
- JSON Schema: Set → `{ type: 'array', uniqueItems: true }`, Map → `{ type: 'object', additionalProperties }`
|
|
170
|
+
|
|
171
|
+
- **Per-field error messages** — `message` and `context` options on `@Field()` apply to all rules on the field. Supports static strings, dynamic functions with `{ property, value, constraints }`, and arbitrary context values including falsy ones (`0`, `false`, `''`).
|
|
172
|
+
|
|
173
|
+
## Chores
|
|
174
|
+
|
|
175
|
+
- Translate all Korean comments and documentation to English (82 files)
|
|
176
|
+
- Delete REVIEW.md (all 42 items completed)
|
|
177
|
+
- 1808 tests, 2639 assertions
|
|
178
|
+
|
|
179
|
+
## 1.0.0
|
|
180
|
+
|
|
181
|
+
### Major Changes
|
|
182
|
+
|
|
183
|
+
- b7ea675: ## Breaking Changes
|
|
184
|
+
|
|
185
|
+
- **`@Field()` unified decorator** — Replaces 30+ individual decorators with a single `@Field()` that accepts rules as arguments and options as an object.
|
|
186
|
+
- **Auto-seal** — `seal()` removed. DTOs auto-seal on first `deserialize()`/`serialize()` call.
|
|
187
|
+
- **`configure()` replaces `seal()` options** — `configure({ autoConvert, stopAtFirstError, forbidUnknown, ... })`.
|
|
188
|
+
- **`configure()` returns `{ warnings: string[] }`** instead of `void`.
|
|
189
|
+
- **`enableCircularCheck` removed** — Circular detection always runs automatically.
|
|
190
|
+
- **`stripUnknown` renamed to `forbidUnknown`** — `stripUnknown` kept as deprecated alias.
|
|
191
|
+
|
|
192
|
+
## Bug Fixes
|
|
193
|
+
|
|
194
|
+
- C-1: Fix analyzeAsync discriminator visited Set sharing (infinite recursion risk)
|
|
195
|
+
- C-2: Fix Set/Map stopAtFirstError error path missing element index
|
|
196
|
+
- C-3: Fix discriminator JSON Schema $ref+properties sibling (allOf wrapper)
|
|
197
|
+
- C-5: Throw on isDivisibleBy(0)
|
|
198
|
+
- C-6: Fix isURL accepting ports 65536-99999
|
|
199
|
+
- C-7: Fix isNumber maxDecimalPlaces scientific notation bypass
|
|
200
|
+
- C-8: Implement serialize discriminator with instanceof dispatch
|
|
201
|
+
- C-9: Fix nullable $ref invalid JSON Schema (oneOf wrapper)
|
|
202
|
+
- C-11: Null guard for nested array serialize
|
|
203
|
+
- C-12: Throw on min(NaN)/max(Infinity)
|
|
204
|
+
- C-13~C-17, B-1~B-11: 11 additional safety guards and silent failure fixes
|
|
205
|
+
|
|
206
|
+
## New Features
|
|
207
|
+
|
|
208
|
+
- Debug mode: `configure({ debug: true })`
|
|
209
|
+
- `onUnmappedRule` callback for `toJsonSchema()`
|
|
210
|
+
- `forbidUnknown` option (renamed from `stripUnknown`)
|
|
211
|
+
|
|
212
|
+
## Refactoring
|
|
213
|
+
|
|
214
|
+
- Decompose buildRulesCode (250 lines → 5 functions) and Field() (125 lines → 4 helpers)
|
|
215
|
+
- Deduplicate Array/Set/Map each codegen, extract GEN constants, strategy pattern for nullable/optional
|
|
216
|
+
- 1730 tests, 2509 assertions, 99.94% Funcs / 99.83% Lines
|
|
217
|
+
|
|
218
|
+
## 0.1.2
|
|
219
|
+
|
|
220
|
+
### Patch Changes
|
|
221
|
+
|
|
222
|
+
- 76657db: fix: pin CI Bun version to 1.3.9 to avoid 1.3.10 bundler regression, optimize isIn/isNotIn with Set, improve npm packaging and test coverage
|
|
223
|
+
|
|
224
|
+
## 0.1.1
|
|
225
|
+
|
|
226
|
+
### Patch Changes
|
|
227
|
+
|
|
228
|
+
- 95ce993: Add coverage badge gist configuration
|
|
229
|
+
|
|
230
|
+
## 0.1.0
|
|
231
|
+
|
|
232
|
+
### Minor Changes
|
|
233
|
+
|
|
234
|
+
- 214f664: ### Breaking Changes
|
|
235
|
+
|
|
236
|
+
- Remove `src/aot/` module and `@zipbul/baker/aot` subpath export. The zipbul CLI now reads baker decorators directly via AST.
|
|
237
|
+
- `MessageArgs.constraints` type changed from `unknown[]` to `Record<string, unknown>`.
|
|
238
|
+
- Default behavior for fields without `@IsOptional`/`@IsNullable`: `undefined`/`null` input now emits `isDefined` error code instead of falling through to type gate errors (e.g., `isString`).
|
|
239
|
+
|
|
240
|
+
### Features
|
|
241
|
+
|
|
242
|
+
- **`@Nested(fn, opts?)`** — Single-decorator shorthand for `@ValidateNested()` + `@Type(fn)` with discriminator support.
|
|
243
|
+
- **`@IsNullable()`** — Allow `null` (skip validation), reject `undefined`. Complements `@IsOptional()` for OAS 3.0 `nullable: true` semantics.
|
|
244
|
+
- **`@Schema(schema)`** — Attach JSON Schema Draft 2020-12 metadata at class or property level. Supports object and function forms.
|
|
245
|
+
- **`toJsonSchema(Class, opts?)`** — Generate JSON Schema Draft 2020-12 from DTO decorators. Supports `direction`, `groups`, circular references, discriminator `oneOf`, and `@Schema()` overrides.
|
|
246
|
+
- **`seal({ whitelist: true })`** — Reject undeclared fields with `whitelistViolation` error code.
|
|
247
|
+
- **`@Min(n, { exclusive: true })` / `@Max(n, { exclusive: true })`** — Exclusive minimum/maximum support.
|
|
248
|
+
- **`enableImplicitConversion`** — Automatic type conversion (string/number/boolean/date) based on `requiresType` and `@Type()` hints.
|
|
249
|
+
- **`EmittableRule.constraints`** — All built-in rules now expose their parameters via `constraints` for JSON Schema mapping and `message` callback access.
|
|
250
|
+
- **`requiresType` expansion** — Added `'boolean'` and `'date'` variants. Fixed silent rule loss for non-string/non-number `requiresType` values.
|
|
251
|
+
|
|
252
|
+
### Internal
|
|
253
|
+
|
|
254
|
+
- Upgrade `@zipbul/result` from `^0.0.3` to `^0.1.4` and adopt `Result<T, E>` / `ResultAsync<T, E>` type aliases.
|
|
255
|
+
- Fix seal placeholder to throw `SealError` instead of bare `Error`.
|
|
256
|
+
- Remove dead branch in deserialize input type guard.
|
package/MIGRATION-3.0.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Baker 2.x → 3.x Migration
|
|
2
|
+
|
|
3
|
+
This release replaces the implicit "auto-seal on first call" model with explicit, user-triggered `seal()`. It also tightens per-call options validation and adds strict sync/async variants.
|
|
4
|
+
|
|
5
|
+
## Required changes
|
|
6
|
+
|
|
7
|
+
### 1. Call `seal()` once at app startup
|
|
8
|
+
|
|
9
|
+
**Before**
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
// Module load registers DTOs; first deserialize implicitly seals everything.
|
|
13
|
+
const r = await deserialize(UserDto, payload);
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**After**
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { seal, deserialize } from '@zipbul/baker';
|
|
20
|
+
// Call after every DTO module has been imported (before HTTP server / job runner starts).
|
|
21
|
+
seal();
|
|
22
|
+
const r = await deserialize(UserDto, payload);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`deserialize` / `serialize` / `validate` throw `BakerError` if the DTO is not sealed.
|
|
26
|
+
|
|
27
|
+
### 2. Move per-call options into `configure(...)`
|
|
28
|
+
|
|
29
|
+
Only `groups` survives as a per-call option.
|
|
30
|
+
|
|
31
|
+
**Before**
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
await deserialize(UserDto, payload, { stopAtFirstError: true });
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**After**
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { configure, seal } from '@zipbul/baker';
|
|
41
|
+
configure({ stopAtFirstError: true });
|
|
42
|
+
seal();
|
|
43
|
+
await deserialize(UserDto, payload);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
All other keys (`stopAtFirstError`, `autoConvert`, `allowClassDefaults`, `forbidUnknown`, `debug`) and their legacy `SealOptions` aliases (`enableImplicitConversion`, `exposeDefaultValues`, `whitelist`) now throw `BakerError` when passed per-call.
|
|
47
|
+
|
|
48
|
+
### 3. `configure()` must run before `seal()`
|
|
49
|
+
|
|
50
|
+
After `seal()`, `configure(...)` throws `BakerError`. Tests that need to reconfigure must call the test-only `unseal()` helper, change config, then `seal()` again.
|
|
51
|
+
|
|
52
|
+
### 4. `@Field` argument validation is strict
|
|
53
|
+
|
|
54
|
+
Passing a non-rule value (factory not invoked, primitive, plain function without `.emit` / `.ruleName`) throws `BakerError` at decorator-evaluation time with the four valid forms listed.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
@Field(isNumber) // ✗ factory not invoked → BakerError
|
|
58
|
+
@Field(isNumber()) // ✓
|
|
59
|
+
@Field(isString) // ✓ constant rule
|
|
60
|
+
@Field() // ✓ marker only
|
|
61
|
+
@Field(isString, { optional: true }) // ✓
|
|
62
|
+
@Field({ type: () => NestedDto }) // ✓
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 5. `Map<K, V>` requires string keys at serialize
|
|
66
|
+
|
|
67
|
+
Serializing a `Map` with non-string keys throws `TypeError`. Previously the key was silently coerced via `String(key)`, producing collisions like `'[object Object]'`.
|
|
68
|
+
|
|
69
|
+
### 6. New strict sync/async variants
|
|
70
|
+
|
|
71
|
+
Six new entry points enforce the call-direction asymmetry at the type level:
|
|
72
|
+
|
|
73
|
+
| Integrated | Strict sync | Strict async |
|
|
74
|
+
| ------------- | ----------------- | ------------------ |
|
|
75
|
+
| `deserialize` | `deserializeSync` | `deserializeAsync` |
|
|
76
|
+
| `serialize` | `serializeSync` | `serializeAsync` |
|
|
77
|
+
| `validate` | `validateSync` | `validateAsync` |
|
|
78
|
+
|
|
79
|
+
`*Sync` throws `BakerError` if the DTO is async on that direction (e.g. async transform on deserialize side for `deserializeSync`). `*Async` always returns `Promise` (sync DTOs are wrapped via `Promise.resolve`). The integrated `deserialize` / `serialize` / `validate` remain available for ergonomic use.
|
|
80
|
+
|
|
81
|
+
## Defect fixes (no migration needed)
|
|
82
|
+
|
|
83
|
+
The following bugs in 2.x are silently fixed in 3.x:
|
|
84
|
+
|
|
85
|
+
- **Set/Map nested DTO cycles** no longer cause stack overflow (`circular-analyzer` now walks `collectionValue`).
|
|
86
|
+
- **Set/Map value DTOs marked async** now correctly propagate `_isAsync` / `_isSerializeAsync` to the parent.
|
|
87
|
+
- **Discriminator with empty `subTypes`** throws `BakerError` at seal time instead of producing invalid generated JS.
|
|
88
|
+
- **Concurrent async deserialize on the same input** no longer reports a false `circular` error (per-call `WeakSet` via `Symbol.for('baker:circular-seen')`).
|
|
89
|
+
- **`Object.hasOwn` checks** prevent prototype-chain values from leaking into DTO results.
|
|
90
|
+
- **Discriminator default branch** error now reports `context: { received, validSubTypes: [...] }`.
|
|
91
|
+
- **FR passport regex** now anchors both ends.
|
|
92
|
+
- **MAGNET URI regex** now anchors the trailing end.
|
|
93
|
+
- **Inheritance dedup** now compares by `ruleName` — a child re-declaring the same rule replaces the parent's rule.
|
|
94
|
+
- **`seal(Class)` failure** is now transactional: a failed seal removes the placeholder so retry can succeed.
|
|
95
|
+
- **`collectionValue` thunk** errors are wrapped in `BakerError` with the field name.
|
|
96
|
+
|
|
97
|
+
## Removed APIs
|
|
98
|
+
|
|
99
|
+
- `_runSealed` (was internal, but some test code depended on it). Use the public functions instead.
|
|
100
|
+
|
|
101
|
+
## Notes
|
|
102
|
+
|
|
103
|
+
- The decorator-side registry (`globalRegistry`) is still used internally as an index of decorated classes so `seal()` (no args) can seal everything. This is not auto-seal — `seal()` must be called explicitly.
|
|
104
|
+
- `unseal()` is exported by `test/integration/helpers/unseal.ts` for testing only. It is not part of the public API.
|
package/README.md
CHANGED
|
@@ -6,12 +6,12 @@ The fastest decorator-based DTO validation library for TypeScript. Generates opt
|
|
|
6
6
|
bun add @zipbul/baker
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
Zero `reflect-metadata`. Sealed codegen.
|
|
9
|
+
Zero `reflect-metadata`. Sealed codegen. 99%+ line coverage.
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { deserialize,
|
|
14
|
+
import { deserialize, isBakerIssueSet, Field, seal } from '@zipbul/baker';
|
|
15
15
|
import { isString, isNumber, isEmail, min, minLength } from '@zipbul/baker/rules';
|
|
16
16
|
|
|
17
17
|
class UserDto {
|
|
@@ -20,14 +20,19 @@ class UserDto {
|
|
|
20
20
|
@Field(isString, isEmail()) email!: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
// Call once at app startup, after all DTOs are loaded.
|
|
24
|
+
seal();
|
|
25
|
+
|
|
23
26
|
const result = await deserialize(UserDto, {
|
|
24
|
-
name: 'Alice',
|
|
27
|
+
name: 'Alice',
|
|
28
|
+
age: 30,
|
|
29
|
+
email: 'alice@test.com',
|
|
25
30
|
});
|
|
26
31
|
|
|
27
|
-
if (
|
|
32
|
+
if (isBakerIssueSet(result)) {
|
|
28
33
|
console.log(result.errors); // [{ path: 'email', code: 'isEmail' }]
|
|
29
34
|
} else {
|
|
30
|
-
console.log(result.name);
|
|
35
|
+
console.log(result.name); // 'Alice' — typed as UserDto
|
|
31
36
|
}
|
|
32
37
|
```
|
|
33
38
|
|
|
@@ -35,14 +40,14 @@ if (isBakerError(result)) {
|
|
|
35
40
|
|
|
36
41
|
Baker generates optimized JavaScript functions once on first seal, then executes them on every call.
|
|
37
42
|
|
|
38
|
-
| Feature
|
|
39
|
-
|
|
40
|
-
| Valid path (5 fields)
|
|
41
|
-
| Invalid path (5 fields) | **fast sealed path** | slower
|
|
42
|
-
| Approach
|
|
43
|
-
| Decorators
|
|
44
|
-
| `reflect-metadata`
|
|
45
|
-
| Sync DTO return
|
|
43
|
+
| Feature | baker | class-validator | Zod |
|
|
44
|
+
| ----------------------- | -------------------- | ---------------------- | ------------------- |
|
|
45
|
+
| Valid path (5 fields) | **fast sealed path** | slower | slower |
|
|
46
|
+
| Invalid path (5 fields) | **fast sealed path** | slower | slower |
|
|
47
|
+
| Approach | AOT code generation | Runtime interpretation | Schema method chain |
|
|
48
|
+
| Decorators | `@Field` (unified) | 30+ individual | N/A |
|
|
49
|
+
| `reflect-metadata` | Not needed | Required | N/A |
|
|
50
|
+
| Sync DTO return | Direct value | Promise | Direct value |
|
|
46
51
|
|
|
47
52
|
## Performance
|
|
48
53
|
|
|
@@ -52,32 +57,52 @@ See [`bench/`](./bench) for the current benchmark suite and exact scenarios.
|
|
|
52
57
|
|
|
53
58
|
## API
|
|
54
59
|
|
|
60
|
+
### `seal(...classes?)`
|
|
61
|
+
|
|
62
|
+
**Required.** Call once at app startup, after every DTO module has been imported. With no arguments, seals every class registered via `@Field` so far. With class arguments, seals only those (and any nested DTOs they reach). Idempotent.
|
|
63
|
+
|
|
64
|
+
`deserialize` / `serialize` / `validate` throw `BakerError` if the DTO is not sealed. Tests that need to mutate decorator metadata should call `seal()` after each `configure(...)` reconfiguration.
|
|
65
|
+
|
|
55
66
|
### `deserialize<T>(Class, input, options?)`
|
|
56
67
|
|
|
57
|
-
Returns `T |
|
|
68
|
+
Returns `T | BakerIssueSet` for sync DTOs, `Promise<T | BakerIssueSet>` for async DTOs. Never throws on validation failure.
|
|
69
|
+
|
|
70
|
+
If the DTO has any async rule or transformer, `deserialize` returns a `Promise`. Otherwise it returns the value directly. For full type safety pick a strict variant (see below).
|
|
71
|
+
|
|
72
|
+
### `deserializeSync<T>` / `deserializeAsync<T>`
|
|
73
|
+
|
|
74
|
+
Strict variants. `deserializeSync` throws `BakerError` if the DTO is async on the deserialize side. `deserializeAsync` always returns `Promise` (sync DTOs are wrapped via `Promise.resolve`).
|
|
58
75
|
|
|
59
76
|
### `serialize<T>(instance, options?)`
|
|
60
77
|
|
|
61
|
-
Returns `Record<string, unknown>` for sync DTOs, `Promise<Record<string, unknown>>` for async DTOs. No validation.
|
|
78
|
+
Returns `Record<string, unknown>` for sync DTOs, `Promise<Record<string, unknown>>` for async DTOs. No validation. Async asymmetry: `_isSerializeAsync` is independent of `_isAsync` — a DTO can be async on deserialize but sync on serialize, and vice versa.
|
|
79
|
+
|
|
80
|
+
### `serializeSync<T>` / `serializeAsync<T>`
|
|
62
81
|
|
|
63
|
-
|
|
82
|
+
Strict variants. `serializeSync` throws `BakerError` if the DTO is async on the serialize side.
|
|
64
83
|
|
|
65
|
-
|
|
84
|
+
### `validate(Class, input, options?)`
|
|
66
85
|
|
|
67
|
-
|
|
86
|
+
Validates `input` against a decorated class's schema. Returns `true | BakerIssueSet` for sync paths, `Promise<true | BakerIssueSet>` for async paths. To validate a single primitive without a DTO, call the rule directly (e.g. `isEmail()(value)`).
|
|
68
87
|
|
|
69
|
-
|
|
88
|
+
### `validateSync` / `validateAsync`
|
|
89
|
+
|
|
90
|
+
Strict variants. `validateSync` throws `BakerError` if the DTO is async; `validateAsync` always returns `Promise`.
|
|
91
|
+
|
|
92
|
+
### `isBakerIssueSet(value)`
|
|
93
|
+
|
|
94
|
+
Type guard. Narrows result to `BakerIssueSet` containing `{ path, code, message?, context? }[]`.
|
|
70
95
|
|
|
71
96
|
### `configure(config)`
|
|
72
97
|
|
|
73
|
-
Global configuration.
|
|
98
|
+
Global configuration. Must be called **before** `seal()`. After seal, `configure(...)` throws `BakerError`; reconfiguring requires `unseal()` (test-only helper) + `configure(...)` + `seal()` again.
|
|
74
99
|
|
|
75
100
|
```typescript
|
|
76
101
|
configure({
|
|
77
|
-
autoConvert: true,
|
|
102
|
+
autoConvert: true, // coerce "123" → 123
|
|
78
103
|
allowClassDefaults: true, // use class field initializers for missing keys
|
|
79
|
-
stopAtFirstError: true,
|
|
80
|
-
forbidUnknown: true,
|
|
104
|
+
stopAtFirstError: true, // return on first validation failure
|
|
105
|
+
forbidUnknown: true, // reject undeclared fields
|
|
81
106
|
});
|
|
82
107
|
```
|
|
83
108
|
|
|
@@ -88,7 +113,7 @@ Custom validation rule.
|
|
|
88
113
|
```typescript
|
|
89
114
|
const isEven = createRule({
|
|
90
115
|
name: 'isEven',
|
|
91
|
-
validate:
|
|
116
|
+
validate: v => typeof v === 'number' && v % 2 === 0,
|
|
92
117
|
requiresType: 'number',
|
|
93
118
|
});
|
|
94
119
|
```
|
|
@@ -97,31 +122,36 @@ const isEven = createRule({
|
|
|
97
122
|
|
|
98
123
|
One decorator for everything — replaces 30+ individual decorators from class-validator.
|
|
99
124
|
|
|
125
|
+
Only fields decorated with `@Field` participate in validation, deserialization, and serialization. Undecorated fields are silently absent from results — they are not part of the DTO contract.
|
|
126
|
+
|
|
100
127
|
```typescript
|
|
101
128
|
@Field(...rules)
|
|
102
129
|
@Field(...rules, options)
|
|
103
130
|
@Field(options)
|
|
131
|
+
@Field() // marker-only (no rules)
|
|
104
132
|
```
|
|
105
133
|
|
|
134
|
+
Each rule must be an emittable rule object created via `createRule()` or one of the built-in rule factories. Passing a raw function (e.g. `@Field(isNumber)` instead of `@Field(isNumber())`) throws `BakerError` at decorator-evaluation time.
|
|
135
|
+
|
|
106
136
|
### Options
|
|
107
137
|
|
|
108
|
-
| Option
|
|
109
|
-
|
|
110
|
-
| `type`
|
|
111
|
-
| `discriminator`
|
|
112
|
-
| `optional`
|
|
113
|
-
| `nullable`
|
|
114
|
-
| `name`
|
|
115
|
-
| `deserializeName` | `string`
|
|
116
|
-
| `serializeName`
|
|
117
|
-
| `exclude`
|
|
118
|
-
| `groups`
|
|
119
|
-
| `when`
|
|
120
|
-
| `transform`
|
|
121
|
-
| `message`
|
|
122
|
-
| `context`
|
|
123
|
-
| `mapValue`
|
|
124
|
-
| `setValue`
|
|
138
|
+
| Option | Type | Description |
|
|
139
|
+
| ----------------- | ------------------------------------------------- | ------------------------------ |
|
|
140
|
+
| `type` | `() => Dto \| [Dto]` | Nested DTO. `[Dto]` for arrays |
|
|
141
|
+
| `discriminator` | `{ property, subTypes }` | Polymorphic dispatch |
|
|
142
|
+
| `optional` | `boolean` | Allow undefined |
|
|
143
|
+
| `nullable` | `boolean` | Allow null |
|
|
144
|
+
| `name` | `string` | Bidirectional key mapping |
|
|
145
|
+
| `deserializeName` | `string` | Input key mapping |
|
|
146
|
+
| `serializeName` | `string` | Output key mapping |
|
|
147
|
+
| `exclude` | `boolean \| 'deserializeOnly' \| 'serializeOnly'` | Field exclusion |
|
|
148
|
+
| `groups` | `string[]` | Conditional visibility |
|
|
149
|
+
| `when` | `(obj) => boolean` | Conditional validation |
|
|
150
|
+
| `transform` | `Transformer \| Transformer[]` | Value transformer |
|
|
151
|
+
| `message` | `string \| (args) => string` | Error message override |
|
|
152
|
+
| `context` | `unknown` | Error context |
|
|
153
|
+
| `mapValue` | `() => Dto` | Map value DTO |
|
|
154
|
+
| `setValue` | `() => Dto` | Set element DTO |
|
|
125
155
|
|
|
126
156
|
## Transformers
|
|
127
157
|
|
|
@@ -131,8 +161,8 @@ Bidirectional value transformers with separate `deserialize` and `serialize` met
|
|
|
131
161
|
import type { Transformer } from '@zipbul/baker';
|
|
132
162
|
|
|
133
163
|
const centsTransformer: Transformer = {
|
|
134
|
-
deserialize: ({ value }) => typeof value === 'number' ? value * 100 : value,
|
|
135
|
-
serialize: ({ value }) => typeof value === 'number' ? value / 100 : value,
|
|
164
|
+
deserialize: ({ value }) => (typeof value === 'number' ? value * 100 : value),
|
|
165
|
+
serialize: ({ value }) => (typeof value === 'number' ? value / 100 : value),
|
|
136
166
|
};
|
|
137
167
|
```
|
|
138
168
|
|
|
@@ -140,27 +170,34 @@ const centsTransformer: Transformer = {
|
|
|
140
170
|
|
|
141
171
|
```typescript
|
|
142
172
|
import {
|
|
143
|
-
trimTransformer,
|
|
144
|
-
|
|
145
|
-
|
|
173
|
+
trimTransformer,
|
|
174
|
+
toLowerCaseTransformer,
|
|
175
|
+
toUpperCaseTransformer,
|
|
176
|
+
roundTransformer,
|
|
177
|
+
unixSecondsTransformer,
|
|
178
|
+
unixMillisTransformer,
|
|
179
|
+
isoStringTransformer,
|
|
180
|
+
csvTransformer,
|
|
181
|
+
jsonTransformer,
|
|
146
182
|
} from '@zipbul/baker/transformers';
|
|
147
183
|
```
|
|
148
184
|
|
|
149
|
-
| Transformer
|
|
150
|
-
|
|
151
|
-
| `trimTransformer`
|
|
152
|
-
| `toLowerCaseTransformer` | lowercase
|
|
153
|
-
| `toUpperCaseTransformer` | uppercase
|
|
154
|
-
| `roundTransformer(n?)`
|
|
155
|
-
| `unixSecondsTransformer` | unix seconds → Date
|
|
156
|
-
| `unixMillisTransformer`
|
|
157
|
-
| `isoStringTransformer`
|
|
158
|
-
| `csvTransformer(sep?)`
|
|
159
|
-
| `jsonTransformer`
|
|
185
|
+
| Transformer | deserialize | serialize |
|
|
186
|
+
| ------------------------ | -------------------------- | -------------------------- |
|
|
187
|
+
| `trimTransformer` | trim string | trim string |
|
|
188
|
+
| `toLowerCaseTransformer` | lowercase | lowercase |
|
|
189
|
+
| `toUpperCaseTransformer` | uppercase | uppercase |
|
|
190
|
+
| `roundTransformer(n?)` | round to n decimals | round to n decimals |
|
|
191
|
+
| `unixSecondsTransformer` | unix seconds → Date | Date → unix seconds |
|
|
192
|
+
| `unixMillisTransformer` | unix ms → Date | Date → unix ms |
|
|
193
|
+
| `isoStringTransformer` | ISO string → Date | Date → ISO string |
|
|
194
|
+
| `csvTransformer(sep?)` | `"a,b"` → `["a","b"]` | `["a","b"]` → `"a,b"` |
|
|
195
|
+
| `jsonTransformer` | JSON string → object | object → JSON string |
|
|
160
196
|
|
|
161
197
|
### Transform Array Order
|
|
162
198
|
|
|
163
199
|
Multiple transformers apply as a codec stack:
|
|
200
|
+
|
|
164
201
|
- **Deserialize**: left to right — `[A, B, C]` applies A, then B, then C
|
|
165
202
|
- **Serialize**: right to left — `[A, B, C]` applies C, then B, then A
|
|
166
203
|
|
|
@@ -189,9 +226,11 @@ import { momentTransformer } from '@zipbul/baker/transformers';
|
|
|
189
226
|
const mt = await momentTransformer({ format: 'YYYY-MM-DD' });
|
|
190
227
|
```
|
|
191
228
|
|
|
229
|
+
> **Note on `format`**: The `format` option in `luxonTransformer` / `momentTransformer` controls the **serialize-side output only**. On deserialize, both transformers parse the input with the library's default parser (ISO-first for Luxon, lenient parser for Moment). Using a lossy format like `'YYYY-MM-DD'` makes the transformer one-way — `serialize → deserialize` will not recover the original time of day. If you need a lossless roundtrip, omit `format` (defaults to ISO 8601).
|
|
230
|
+
|
|
192
231
|
## Rules
|
|
193
232
|
|
|
194
|
-
|
|
233
|
+
105 built-in validation rules.
|
|
195
234
|
|
|
196
235
|
### Type Checkers
|
|
197
236
|
|
|
@@ -209,7 +248,7 @@ const mt = await momentTransformer({ format: 'YYYY-MM-DD' });
|
|
|
209
248
|
|
|
210
249
|
### Formats
|
|
211
250
|
|
|
212
|
-
`isEmail()`, `isURL()`, `isUUID(version?)`, `isIP(version?)`, `isISO8601()`, `isJSON`, `isJWT`, `isCreditCard`, `isIBAN()`, `isFQDN()`, `isMACAddress()`, `isBase64()`, `isHexColor`, `isSemVer`, `isMongoId`, `isPhoneNumber()`, `isStrongPassword()`, `isULID()`, `isCUID2()`
|
|
251
|
+
`isEmail()`, `isURL()`, `isUUID(version?)`, `isIP(version?)`, `isISO8601()`, `isJSON`, `isJWT`, `isCreditCard`, `isIBAN()`, `isFQDN()`, `isMACAddress()`, `isBase64()`, `isHexColor`, `isSemVer`, `isMongoId`, `isPhoneNumber()`, `isStrongPassword()`, `isULID()`, `isCUID2()`, `isHttpToken`
|
|
213
252
|
|
|
214
253
|
### Arrays
|
|
215
254
|
|
|
@@ -262,7 +301,8 @@ class PetOwner {
|
|
|
262
301
|
{ value: DogDto, name: 'dog' },
|
|
263
302
|
],
|
|
264
303
|
},
|
|
265
|
-
})
|
|
304
|
+
})
|
|
305
|
+
pet!: CatDto | DogDto;
|
|
266
306
|
}
|
|
267
307
|
```
|
|
268
308
|
|
|
@@ -299,13 +339,19 @@ Yes. baker's `@Field` decorator works alongside NestJS pipes. Use `deserialize()
|
|
|
299
339
|
|
|
300
340
|
### How does the AOT code generation work?
|
|
301
341
|
|
|
302
|
-
|
|
342
|
+
Calling `seal()` once at app startup walks every registered DTO, analyzes field metadata, generates optimized JavaScript validation functions via `new Function()`, and caches them. Subsequent `deserialize`/`serialize`/`validate` calls execute the pre-compiled functions directly. There is no auto-seal — forgetting to call `seal()` raises `BakerError` on first use.
|
|
303
343
|
|
|
304
344
|
## Exports
|
|
305
345
|
|
|
306
346
|
```typescript
|
|
307
|
-
import {
|
|
308
|
-
|
|
347
|
+
import {
|
|
348
|
+
seal,
|
|
349
|
+
deserialize, deserializeSync, deserializeAsync,
|
|
350
|
+
validate, validateSync, validateAsync,
|
|
351
|
+
serialize, serializeSync, serializeAsync,
|
|
352
|
+
configure, createRule, Field, arrayOf, isBakerIssueSet, BakerError,
|
|
353
|
+
} from '@zipbul/baker';
|
|
354
|
+
import type { Transformer, TransformParams, BakerError, BakerIssueSet, FieldOptions, EmittableRule, RuntimeOptions } from '@zipbul/baker';
|
|
309
355
|
import { isString, isEmail, isULID, isCUID2, ... } from '@zipbul/baker/rules';
|
|
310
356
|
import { trimTransformer, jsonTransformer, ... } from '@zipbul/baker/transformers';
|
|
311
357
|
```
|