@zipbul/baker 1.0.0 → 1.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/README.md +45 -6
- package/dist/index-70ggmxsa.js +6 -0
- package/dist/index-gcptd79v.js +6 -0
- package/dist/index.js +194 -137
- package/dist/src/collect.d.ts +3 -3
- package/dist/src/configure.d.ts +13 -13
- package/dist/src/create-rule.d.ts +7 -7
- package/dist/src/decorators/field.d.ts +32 -20
- package/dist/src/decorators/index.js +1 -1
- package/dist/src/errors.d.ts +17 -17
- package/dist/src/functions/deserialize.d.ts +6 -5
- package/dist/src/functions/serialize.d.ts +5 -4
- package/dist/src/functions/to-json-schema.d.ts +7 -7
- package/dist/src/interfaces.d.ts +7 -7
- package/dist/src/registry.d.ts +4 -4
- package/dist/src/rules/index.js +4 -4
- package/dist/src/rules/object.d.ts +1 -1
- package/dist/src/seal/circular-analyzer.d.ts +4 -4
- package/dist/src/seal/expose-validator.d.ts +6 -6
- package/dist/src/seal/seal.d.ts +16 -16
- package/dist/src/seal/serialize-builder.d.ts +2 -2
- package/dist/src/symbols.d.ts +5 -5
- package/dist/src/symbols.js +1 -1
- package/dist/src/types.d.ts +34 -28
- package/package.json +1 -1
- package/dist/index-57gr0v18.js +0 -6
- package/dist/index-aegrb1kn.js +0 -6
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Baker gives you a **single `@Field()` decorator** that combines validation, tran
|
|
|
39
39
|
- **Single decorator** — `@Field()` replaces 30+ individual decorators
|
|
40
40
|
- **80+ built-in rules** — `isString`, `min()`, `isEmail()` and more, composed as arguments
|
|
41
41
|
- **Inline code generation** — auto-seal compiles validators at first `deserialize()`/`serialize()` call
|
|
42
|
-
- **Unified validate + transform** — `deserialize()` and `serialize()` in one async
|
|
42
|
+
- **Unified validate + transform** — `deserialize()` and `serialize()` in one call (sync DTOs skip async overhead)
|
|
43
43
|
- **Zero reflect-metadata** — no `reflect-metadata` import needed
|
|
44
44
|
- **Circular reference detection** — automatic static analysis at seal time
|
|
45
45
|
- **Group-based validation** — apply different rules per request with `groups`
|
|
@@ -49,6 +49,8 @@ Baker gives you a **single `@Field()` decorator** that combines validation, tran
|
|
|
49
49
|
- **Whitelist mode** — reject undeclared fields with `configure({ forbidUnknown: true })`
|
|
50
50
|
- **Class inheritance** — child DTOs inherit parent `@Field()` decorators automatically
|
|
51
51
|
- **Async transforms** — transform functions can be async
|
|
52
|
+
- **Map/Set support** — auto-convert between `Map`/`Set` and JSON-compatible types
|
|
53
|
+
- **Per-field error messages** — `message` and `context` options on `@Field()` for custom errors
|
|
52
54
|
|
|
53
55
|
---
|
|
54
56
|
|
|
@@ -161,16 +163,29 @@ interface FieldOptions {
|
|
|
161
163
|
schema?: JsonSchemaOverride; // JSON Schema metadata
|
|
162
164
|
transform?: (params: FieldTransformParams) => unknown;
|
|
163
165
|
transformDirection?: 'deserializeOnly' | 'serializeOnly';
|
|
166
|
+
message?: string | ((args: MessageArgs) => string); // Error message for all rules
|
|
167
|
+
context?: unknown; // Error context for all rules
|
|
168
|
+
mapValue?: () => Constructor; // Map value DTO type
|
|
169
|
+
setValue?: () => Constructor; // Set element DTO type
|
|
164
170
|
}
|
|
165
171
|
```
|
|
166
172
|
|
|
167
|
-
### Per-
|
|
173
|
+
### Per-field Error Messages
|
|
168
174
|
|
|
169
|
-
|
|
175
|
+
Use `message` and `context` to customize validation error output:
|
|
170
176
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
177
|
+
```typescript
|
|
178
|
+
@Field(isString, minLength(3), { message: 'Name is invalid' })
|
|
179
|
+
name!: string;
|
|
180
|
+
|
|
181
|
+
@Field(isEmail(), {
|
|
182
|
+
message: ({ property, value }) => `${property} got bad value: ${value}`,
|
|
183
|
+
context: { severity: 'error' },
|
|
184
|
+
})
|
|
185
|
+
email!: string;
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The `message` and `context` are applied to all rules on the field. They appear in `BakerError.message` and `BakerError.context` on validation failure.
|
|
174
189
|
|
|
175
190
|
### `arrayOf()` — Array Element Validation
|
|
176
191
|
|
|
@@ -446,6 +461,30 @@ class PetOwnerDto {
|
|
|
446
461
|
|
|
447
462
|
Discriminator works in both directions — `deserialize()` switches on the property value, `serialize()` dispatches via `instanceof`.
|
|
448
463
|
|
|
464
|
+
### Map / Set Collections
|
|
465
|
+
|
|
466
|
+
Baker auto-converts between `Map`/`Set` and JSON-compatible types:
|
|
467
|
+
|
|
468
|
+
```typescript
|
|
469
|
+
// Set<primitive>: JSON array ↔ Set
|
|
470
|
+
@Field({ type: () => Set })
|
|
471
|
+
tags!: Set<string>;
|
|
472
|
+
|
|
473
|
+
// Set<DTO>: JSON array of objects ↔ Set of DTO instances
|
|
474
|
+
@Field({ type: () => Set, setValue: () => TagDto })
|
|
475
|
+
tags!: Set<TagDto>;
|
|
476
|
+
|
|
477
|
+
// Map<string, primitive>: JSON object ↔ Map
|
|
478
|
+
@Field({ type: () => Map })
|
|
479
|
+
config!: Map<string, unknown>;
|
|
480
|
+
|
|
481
|
+
// Map<string, DTO>: JSON object ↔ Map of DTO instances
|
|
482
|
+
@Field({ type: () => Map, mapValue: () => PriceDto })
|
|
483
|
+
prices!: Map<string, PriceDto>;
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Map keys are always strings (JSON constraint). JSON Schema maps `Set` to `{ type: 'array', uniqueItems: true }` and `Map` to `{ type: 'object', additionalProperties: ... }`.
|
|
487
|
+
|
|
449
488
|
---
|
|
450
489
|
|
|
451
490
|
## Inheritance
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{e as Q}from"./index-70ggmxsa.js";var T=new Set;function U(b,G){if(!Object.prototype.hasOwnProperty.call(b,Q))b[Q]=Object.create(null),T.add(b);let j=b[Q];return j[G]??={validation:[],transform:[],expose:[],exclude:null,type:null,flags:{},schema:null}}function X(b){return b[Symbol.toStringTag]==="AsyncFunction"}var $=Symbol.for("baker:arrayOf");function W(...b){let G={rules:b};return G[$]=!0,G}function v(b){return typeof b==="object"&&b!==null&&b[$]===!0}var N=new Set(["type","discriminator","keepDiscriminatorProperty","rules","optional","nullable","name","deserializeName","serializeName","exclude","groups","when","schema","transform","transformDirection","message","context","mapValue","setValue"]);function Z(b){if(typeof b==="function")return!1;if(typeof b!=="object"||b===null)return!1;if(v(b))return!1;let G=Object.keys(b);if(G.length===0)return!0;return G.some((j)=>N.has(j))}function P(b){if(b.length===0)return{rules:[],options:{}};if(b.length===1&&Z(b[0])){let j=b[0];return{rules:j.rules??[],options:j}}let G=b[b.length-1];if(Z(G)){let j=G,B=b.slice(0,-1);if(j.rules)B=[...B,...j.rules];return{rules:B,options:j}}return{rules:b,options:{}}}function S(b,G,j){for(let B of G)if(v(B))for(let J of B.rules){let q={rule:J,each:!0,groups:j.groups};if(j.message!==void 0)q.message=j.message;if(j.context!==void 0)q.context=j.context;b.validation.push(q)}else{let J={rule:B,groups:j.groups};if(j.message!==void 0)J.message=j.message;if(j.context!==void 0)J.context=j.context;b.validation.push(J)}}function V(b,G){if(G.name)b.expose.push({name:G.name,groups:G.groups});else if(G.deserializeName||G.serializeName){if(G.deserializeName)b.expose.push({name:G.deserializeName,deserializeOnly:!0,groups:G.groups});if(G.serializeName)b.expose.push({name:G.serializeName,serializeOnly:!0,groups:G.groups})}else if(G.groups)b.expose.push({groups:G.groups});else b.expose.push({})}function H(b,G){if(!G.transform)return;let j=G.transform,J=X(j)?async(z)=>j({value:z.value,key:z.key,obj:z.obj,direction:z.type}):(z)=>j({value:z.value,key:z.key,obj:z.obj,direction:z.type});if(G.transformDirection&&G.transformDirection!=="deserializeOnly"&&G.transformDirection!=="serializeOnly")throw Error(`Invalid transformDirection: "${G.transformDirection}". Expected 'deserializeOnly' or 'serializeOnly'.`);let q={};if(G.transformDirection==="deserializeOnly")q.deserializeOnly=!0;if(G.transformDirection==="serializeOnly")q.serializeOnly=!0;b.transform.push({fn:J,options:Object.keys(q).length>0?q:void 0})}function d(...b){return(G,j)=>{let B=G.constructor,q=U(B,j),{rules:z,options:w}=P(b);if(S(q,z,w),w.optional)q.flags.isOptional=!0;if(w.nullable)q.flags.isNullable=!0;if(w.when)q.flags.validateIf=w.when;if(w.type)q.type={fn:w.type,discriminator:w.discriminator,keepDiscriminatorProperty:w.keepDiscriminatorProperty,collectionValue:w.mapValue??w.setValue};if(V(q,w),w.exclude){if(w.exclude===!0)q.exclude={};else if(w.exclude==="deserializeOnly")q.exclude={deserializeOnly:!0};else if(w.exclude==="serializeOnly")q.exclude={serializeOnly:!0}}if(H(q,w),w.schema)if(typeof q.schema==="function");else q.schema={...q.schema??{},...w.schema}}}
|
|
3
|
+
export{T as a,X as b,W as c,d};
|
|
4
|
+
|
|
5
|
+
//# debugId=31CC953F620CB89C64756E2164756E21
|
|
6
|
+
//# sourceMappingURL=index-gcptd79v.js.map
|