@zipbul/baker 2.0.0 → 2.2.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 +155 -107
- package/dist/index-03cysbck.js +3 -0
- package/dist/index-dcbd798a.js +3 -0
- package/dist/index-jp2yjd6g.js +3 -0
- package/dist/index-mw7met6r.js +3 -0
- package/dist/index-xdn55cz3.js +0 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +296 -206
- package/dist/src/configure.d.ts +1 -6
- package/dist/src/create-rule.d.ts +1 -1
- package/dist/src/decorators/field.d.ts +4 -12
- package/dist/src/decorators/index.d.ts +1 -1
- package/dist/src/decorators/index.js +1 -4
- package/dist/src/errors.d.ts +4 -3
- package/dist/src/functions/deserialize.d.ts +4 -3
- package/dist/src/functions/serialize.d.ts +3 -2
- package/dist/src/functions/validate.d.ts +6 -4
- package/dist/src/rule-plan.d.ts +30 -0
- package/dist/src/rules/array.d.ts +1 -1
- package/dist/src/rules/common.d.ts +2 -2
- package/dist/src/rules/index.d.ts +1 -1
- package/dist/src/rules/index.js +18 -11
- package/dist/src/rules/number.d.ts +2 -2
- package/dist/src/rules/string.d.ts +11 -9
- package/dist/src/rules/typechecker.d.ts +6 -6
- package/dist/src/seal/codegen-utils.d.ts +7 -0
- package/dist/src/seal/deserialize-builder.d.ts +2 -1
- package/dist/src/seal/seal.d.ts +1 -1
- package/dist/src/symbols.js +1 -4
- package/dist/src/transformers/collection.transformer.d.ts +3 -0
- package/dist/src/transformers/date.transformer.d.ts +4 -0
- package/dist/src/transformers/index.d.ts +8 -0
- package/dist/src/transformers/index.js +2 -0
- package/dist/src/transformers/luxon.transformer.d.ts +6 -0
- package/dist/src/transformers/moment.transformer.d.ts +5 -0
- package/dist/src/transformers/number.transformer.d.ts +2 -0
- package/dist/src/transformers/string.transformer.d.ts +4 -0
- package/dist/src/types.d.ts +48 -8
- package/dist/src/utils.d.ts +2 -0
- package/package.json +28 -4
- package/dist/index-btgens0c.js +0 -6
- package/dist/index-k369bbht.js +0 -6
package/README.md
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
# @zipbul/baker
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The fastest decorator-based DTO validation library for TypeScript. Generates optimized validation and serialization code on first seal, then reuses the sealed executors on every call.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
bun add @zipbul/baker
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Zero `reflect-metadata`. Sealed codegen. 1,975 tests. 99%+ line coverage.
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
### `deserialize<T>(Class, input, options?): T | BakerErrors | Promise<T | BakerErrors>`
|
|
14
|
-
|
|
15
|
-
Validates input and creates a class instance. Sync DTOs return directly. Async DTOs (async transform/rules) return Promise. Always safe to `await`.
|
|
11
|
+
## Quick Start
|
|
16
12
|
|
|
17
13
|
```typescript
|
|
18
14
|
import { deserialize, isBakerError, Field } from '@zipbul/baker';
|
|
@@ -24,92 +20,82 @@ class UserDto {
|
|
|
24
20
|
@Field(isString, isEmail()) email!: string;
|
|
25
21
|
}
|
|
26
22
|
|
|
27
|
-
const result = await deserialize(UserDto, {
|
|
23
|
+
const result = await deserialize(UserDto, {
|
|
24
|
+
name: 'Alice', age: 30, email: 'alice@test.com',
|
|
25
|
+
});
|
|
28
26
|
|
|
29
27
|
if (isBakerError(result)) {
|
|
30
|
-
console.log(result.errors); // { path:
|
|
28
|
+
console.log(result.errors); // [{ path: 'email', code: 'isEmail' }]
|
|
31
29
|
} else {
|
|
32
|
-
console.log(result.name);
|
|
30
|
+
console.log(result.name); // 'Alice' — typed as UserDto
|
|
33
31
|
}
|
|
34
32
|
```
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
## Why Baker?
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
Baker generates optimized JavaScript functions once on first seal, then executes them on every call.
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
| Feature | baker | class-validator | Zod |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| Valid path (5 fields) | **fast sealed path** | slower | slower |
|
|
41
|
+
| Invalid path (5 fields) | **fast sealed path** | slower | slower |
|
|
42
|
+
| Approach | AOT code generation | Runtime interpretation | Schema method chain |
|
|
43
|
+
| Decorators | `@Field` (unified) | 30+ individual | N/A |
|
|
44
|
+
| `reflect-metadata` | Not needed | Required | N/A |
|
|
45
|
+
| Sync DTO return | Direct value | Promise | Direct value |
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
import { validate, isBakerError } from '@zipbul/baker';
|
|
47
|
+
## Performance
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
if (isBakerError(result)) { /* errors */ }
|
|
47
|
-
```
|
|
49
|
+
Benchmarked against multiple libraries on simple, nested, array, and error-collection scenarios. Exact numbers vary by machine and runtime.
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
See [`bench/`](./bench) for the current benchmark suite and exact scenarios.
|
|
50
52
|
|
|
51
|
-
|
|
53
|
+
## API
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
const result = await validate('hello@test.com', isString, isEmail());
|
|
55
|
-
// result === true
|
|
56
|
-
```
|
|
55
|
+
### `deserialize<T>(Class, input, options?)`
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
Returns `T | BakerErrors` for sync DTOs, `Promise<T | BakerErrors>` for async DTOs. Never throws on validation failure.
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
### `serialize<T>(instance, options?)`
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
import { serialize } from '@zipbul/baker';
|
|
61
|
+
Returns `Record<string, unknown>` for sync DTOs, `Promise<Record<string, unknown>>` for async DTOs. No validation.
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
```
|
|
63
|
+
### `validate(Class, input, options?)` / `validate(input, ...rules)`
|
|
67
64
|
|
|
68
|
-
|
|
65
|
+
DTO-level or ad-hoc single-value validation. Returns `true | BakerErrors` for sync paths, `Promise<true | BakerErrors>` for async paths.
|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
### `isBakerError(value)`
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
interface BakerError {
|
|
74
|
-
readonly path: string; // 'name', 'address.city', 'items[0].value'
|
|
75
|
-
readonly code: string; // 'isString', 'minLength', 'invalidInput'
|
|
76
|
-
readonly message?: string; // custom message if set
|
|
77
|
-
readonly context?: unknown; // custom context if set
|
|
78
|
-
}
|
|
79
|
-
```
|
|
69
|
+
Type guard. Narrows result to `BakerErrors` containing `{ path, code, message?, context? }[]`.
|
|
80
70
|
|
|
81
|
-
### `configure(config)
|
|
71
|
+
### `configure(config)`
|
|
82
72
|
|
|
83
|
-
Global configuration. Call before first
|
|
73
|
+
Global configuration. Call before first deserialize/serialize/validate. Calling it after auto-seal throws `SealError`.
|
|
84
74
|
|
|
85
75
|
```typescript
|
|
86
|
-
import { configure } from '@zipbul/baker';
|
|
87
|
-
|
|
88
76
|
configure({
|
|
89
|
-
autoConvert: true, // "123" → 123
|
|
90
|
-
allowClassDefaults: true, // use class field initializers for missing keys
|
|
91
|
-
stopAtFirstError: true, // return on first validation failure
|
|
92
|
-
forbidUnknown: true, // reject undeclared fields
|
|
77
|
+
autoConvert: true, // coerce "123" → 123
|
|
78
|
+
allowClassDefaults: true, // use class field initializers for missing keys
|
|
79
|
+
stopAtFirstError: true, // return on first validation failure
|
|
80
|
+
forbidUnknown: true, // reject undeclared fields
|
|
93
81
|
});
|
|
94
82
|
```
|
|
95
83
|
|
|
96
|
-
### `createRule(name, validate)
|
|
84
|
+
### `createRule(name, validate)`
|
|
97
85
|
|
|
98
|
-
|
|
86
|
+
Custom validation rule.
|
|
99
87
|
|
|
100
88
|
```typescript
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const isUnique = createRule({
|
|
106
|
-
name: 'isUnique',
|
|
107
|
-
validate: async (v) => await db.checkUnique(v),
|
|
108
|
-
constraints: { table: 'users' },
|
|
89
|
+
const isEven = createRule({
|
|
90
|
+
name: 'isEven',
|
|
91
|
+
validate: (v) => typeof v === 'number' && v % 2 === 0,
|
|
92
|
+
requiresType: 'number',
|
|
109
93
|
});
|
|
110
94
|
```
|
|
111
95
|
|
|
112
|
-
##
|
|
96
|
+
## @Field Decorator
|
|
97
|
+
|
|
98
|
+
One decorator for everything — replaces 30+ individual decorators from class-validator.
|
|
113
99
|
|
|
114
100
|
```typescript
|
|
115
101
|
@Field(...rules)
|
|
@@ -119,43 +105,103 @@ const isUnique = createRule({
|
|
|
119
105
|
|
|
120
106
|
### Options
|
|
121
107
|
|
|
108
|
+
| Option | Type | Description |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `type` | `() => Dto \| [Dto]` | Nested DTO. `[Dto]` for arrays |
|
|
111
|
+
| `discriminator` | `{ property, subTypes }` | Polymorphic dispatch |
|
|
112
|
+
| `optional` | `boolean` | Allow undefined |
|
|
113
|
+
| `nullable` | `boolean` | Allow null |
|
|
114
|
+
| `name` | `string` | Bidirectional key mapping |
|
|
115
|
+
| `deserializeName` | `string` | Input key mapping |
|
|
116
|
+
| `serializeName` | `string` | Output key mapping |
|
|
117
|
+
| `exclude` | `boolean \| 'deserializeOnly' \| 'serializeOnly'` | Field exclusion |
|
|
118
|
+
| `groups` | `string[]` | Conditional visibility |
|
|
119
|
+
| `when` | `(obj) => boolean` | Conditional validation |
|
|
120
|
+
| `transform` | `Transformer \| Transformer[]` | Value transformer |
|
|
121
|
+
| `message` | `string \| (args) => string` | Error message override |
|
|
122
|
+
| `context` | `unknown` | Error context |
|
|
123
|
+
| `mapValue` | `() => Dto` | Map value DTO |
|
|
124
|
+
| `setValue` | `() => Dto` | Set element DTO |
|
|
125
|
+
|
|
126
|
+
## Transformers
|
|
127
|
+
|
|
128
|
+
Bidirectional value transformers with separate `deserialize` and `serialize` methods.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import type { Transformer } from '@zipbul/baker';
|
|
132
|
+
|
|
133
|
+
const centsTransformer: Transformer = {
|
|
134
|
+
deserialize: ({ value }) => typeof value === 'number' ? value * 100 : value,
|
|
135
|
+
serialize: ({ value }) => typeof value === 'number' ? value / 100 : value,
|
|
136
|
+
};
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Built-in Transformers
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import {
|
|
143
|
+
trimTransformer, toLowerCaseTransformer, toUpperCaseTransformer,
|
|
144
|
+
roundTransformer, unixSecondsTransformer, unixMillisTransformer,
|
|
145
|
+
isoStringTransformer, csvTransformer, jsonTransformer,
|
|
146
|
+
} from '@zipbul/baker/transformers';
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
| Transformer | deserialize | serialize |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| `trimTransformer` | trim string | trim string |
|
|
152
|
+
| `toLowerCaseTransformer` | lowercase | lowercase |
|
|
153
|
+
| `toUpperCaseTransformer` | uppercase | uppercase |
|
|
154
|
+
| `roundTransformer(n?)` | round to n decimals | round to n decimals |
|
|
155
|
+
| `unixSecondsTransformer` | unix seconds → Date | Date → unix seconds |
|
|
156
|
+
| `unixMillisTransformer` | unix ms → Date | Date → unix ms |
|
|
157
|
+
| `isoStringTransformer` | ISO string → Date | Date → ISO string |
|
|
158
|
+
| `csvTransformer(sep?)` | `"a,b"` → `["a","b"]` | `["a","b"]` → `"a,b"` |
|
|
159
|
+
| `jsonTransformer` | JSON string → object | object → JSON string |
|
|
160
|
+
|
|
161
|
+
### Transform Array Order
|
|
162
|
+
|
|
163
|
+
Multiple transformers apply as a codec stack:
|
|
164
|
+
- **Deserialize**: left to right — `[A, B, C]` applies A, then B, then C
|
|
165
|
+
- **Serialize**: right to left — `[A, B, C]` applies C, then B, then A
|
|
166
|
+
|
|
122
167
|
```typescript
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
when?: (obj: any) => boolean; // conditional validation
|
|
139
|
-
transform?: (params: FieldTransformParams) => unknown; // value transform
|
|
140
|
-
transformDirection?: 'deserializeOnly' | 'serializeOnly'; // transform direction
|
|
141
|
-
message?: string | ((args) => string); // error message override
|
|
142
|
-
context?: unknown; // error context
|
|
143
|
-
mapValue?: () => DtoClass; // Map value DTO
|
|
144
|
-
setValue?: () => DtoClass; // Set element DTO
|
|
168
|
+
@Field(isString, { transform: [trimTransformer, toLowerCaseTransformer] })
|
|
169
|
+
email!: string;
|
|
170
|
+
// deserialize " HELLO " → trim → toLowerCase → "hello"
|
|
171
|
+
// serialize "hello" → toLowerCase → trim → "hello"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Optional Peer Transformers
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// bun add luxon
|
|
178
|
+
import { luxonTransformer } from '@zipbul/baker/transformers';
|
|
179
|
+
const luxon = await luxonTransformer({ zone: 'Asia/Seoul' });
|
|
180
|
+
|
|
181
|
+
class EventDto {
|
|
182
|
+
@Field({ transform: luxon }) startAt!: DateTime;
|
|
145
183
|
}
|
|
146
184
|
```
|
|
147
185
|
|
|
186
|
+
```typescript
|
|
187
|
+
// bun add moment
|
|
188
|
+
import { momentTransformer } from '@zipbul/baker/transformers';
|
|
189
|
+
const mt = await momentTransformer({ format: 'YYYY-MM-DD' });
|
|
190
|
+
```
|
|
191
|
+
|
|
148
192
|
## Rules
|
|
149
193
|
|
|
194
|
+
104 built-in validation rules.
|
|
195
|
+
|
|
150
196
|
### Type Checkers
|
|
151
197
|
|
|
152
|
-
`isString`, `isInt`, `isBoolean`, `isDate`, `isArray`, `isObject` — constants, no `()
|
|
198
|
+
`isString`, `isInt`, `isBoolean`, `isDate`, `isArray`, `isObject` — constants, no `()` needed.
|
|
153
199
|
|
|
154
|
-
`isNumber(options?)`, `isEnum(entity)` — factories,
|
|
200
|
+
`isNumber(options?)`, `isEnum(entity)` — factories, require `()`.
|
|
155
201
|
|
|
156
202
|
### Numbers
|
|
157
203
|
|
|
158
|
-
`min(n)`, `max(n)`, `
|
|
204
|
+
`min(n)`, `max(n)`, `isPositive`, `isNegative`, `isDivisibleBy(n)`
|
|
159
205
|
|
|
160
206
|
### Strings
|
|
161
207
|
|
|
@@ -163,7 +209,7 @@ interface FieldOptions {
|
|
|
163
209
|
|
|
164
210
|
### Formats
|
|
165
211
|
|
|
166
|
-
`isEmail()`, `isURL()`, `isUUID(version?)`, `isIP(version?)`, `isISO8601()`, `isJSON`, `isJWT`, `isCreditCard`, `isIBAN()`, `isFQDN()`, `isMACAddress()`, `isBase64()`, `isHexColor`, `isSemVer`, `isMongoId`, `isPhoneNumber`, `isStrongPassword()`
|
|
212
|
+
`isEmail()`, `isURL()`, `isUUID(version?)`, `isIP(version?)`, `isISO8601()`, `isJSON`, `isJWT`, `isCreditCard`, `isIBAN()`, `isFQDN()`, `isMACAddress()`, `isBase64()`, `isHexColor`, `isSemVer`, `isMongoId`, `isPhoneNumber()`, `isStrongPassword()`, `isULID()`, `isCUID2()`
|
|
167
213
|
|
|
168
214
|
### Arrays
|
|
169
215
|
|
|
@@ -199,7 +245,7 @@ class UserDto {
|
|
|
199
245
|
```typescript
|
|
200
246
|
class UserDto {
|
|
201
247
|
@Field({ type: () => Set as any, setValue: () => TagDto }) tags!: Set<TagDto>;
|
|
202
|
-
@Field({ type: () => Map as any, mapValue: () =>
|
|
248
|
+
@Field({ type: () => Map as any, mapValue: () => PriceDto }) prices!: Map<string, PriceDto>;
|
|
203
249
|
}
|
|
204
250
|
```
|
|
205
251
|
|
|
@@ -233,34 +279,36 @@ class UserDto extends BaseDto {
|
|
|
233
279
|
}
|
|
234
280
|
```
|
|
235
281
|
|
|
236
|
-
##
|
|
282
|
+
## FAQ
|
|
237
283
|
|
|
238
|
-
|
|
239
|
-
// Functions
|
|
240
|
-
import { deserialize, validate, serialize, configure, createRule } from '@zipbul/baker';
|
|
284
|
+
### When should I use baker instead of class-validator?
|
|
241
285
|
|
|
242
|
-
|
|
243
|
-
import { Field, arrayOf } from '@zipbul/baker';
|
|
286
|
+
When performance matters. baker is 163x faster on valid input and 109x faster on invalid input, while providing the same decorator-based DX. baker also eliminates the `reflect-metadata` dependency.
|
|
244
287
|
|
|
245
|
-
|
|
246
|
-
import { isBakerError, SealError } from '@zipbul/baker';
|
|
288
|
+
### How does baker compare to Zod?
|
|
247
289
|
|
|
248
|
-
|
|
249
|
-
import type {
|
|
250
|
-
BakerError, BakerErrors, FieldOptions, FieldTransformParams,
|
|
251
|
-
ArrayOfMarker, EmittableRule, BakerConfig, ConfigureResult, RuntimeOptions,
|
|
252
|
-
} from '@zipbul/baker';
|
|
290
|
+
Zod uses schema method chains (`z.string().email()`), baker uses decorators (`@Field(isString, isEmail())`). baker is 16x faster on valid input because it generates optimized code at definition time instead of interpreting schemas at runtime. Choose Zod if you need schema-first design; choose baker if you need class-based DTOs with maximum performance.
|
|
253
291
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
292
|
+
### Does baker support async validation?
|
|
293
|
+
|
|
294
|
+
Yes. If any rule or transformer is async, baker automatically detects it at seal time and generates an async executor. Sync DTOs return values directly without Promise wrapping.
|
|
295
|
+
|
|
296
|
+
### Can I use baker with NestJS?
|
|
257
297
|
|
|
258
|
-
|
|
298
|
+
Yes. baker's `@Field` decorator works alongside NestJS pipes. Use `deserialize()` in a custom validation pipe.
|
|
259
299
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
300
|
+
### How does the AOT code generation work?
|
|
301
|
+
|
|
302
|
+
On the first call to `deserialize`/`serialize`/`validate`, baker seals all registered DTOs: it analyzes field metadata, generates optimized JavaScript validation functions via `new Function()`, and caches them. Subsequent calls execute the pre-compiled functions directly.
|
|
303
|
+
|
|
304
|
+
## Exports
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
import { deserialize, validate, serialize, configure, createRule, Field, arrayOf, isBakerError, SealError } from '@zipbul/baker';
|
|
308
|
+
import type { Transformer, TransformParams, BakerError, BakerErrors, FieldOptions, EmittableRule, RuntimeOptions } from '@zipbul/baker';
|
|
309
|
+
import { isString, isEmail, isULID, isCUID2, ... } from '@zipbul/baker/rules';
|
|
310
|
+
import { trimTransformer, jsonTransformer, ... } from '@zipbul/baker/transformers';
|
|
311
|
+
```
|
|
264
312
|
|
|
265
313
|
## License
|
|
266
314
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{o as C}from"./index-jp2yjd6g.js";var H=new Set;function J(h,G){if(!Object.prototype.hasOwnProperty.call(h,C))h[C]=Object.create(null),H.add(h);let S=h[C];return S[G]??={validation:[],transform:[],expose:[],exclude:null,type:null,flags:{}}}function Q(h){return h[Symbol.toStringTag]==="AsyncFunction"}function U(h){return(typeof h==="object"||typeof h==="function")&&h!==null&&typeof h.then==="function"}var $=Symbol.for("baker:arrayOf");function M(...h){let G={rules:h};return G[$]=!0,G}function N(h){return typeof h==="object"&&h!==null&&h[$]===!0}var V=new Set(["type","discriminator","keepDiscriminatorProperty","rules","optional","nullable","name","deserializeName","serializeName","exclude","groups","when","transform","message","context","mapValue","setValue"]);function X(h){if(typeof h==="function")return!1;if(typeof h!=="object"||h===null)return!1;if(N(h))return!1;let G=Object.keys(h);if(G.length===0)return!0;return G.some((S)=>V.has(S))}function I(h){if(h.length===0)return{rules:[],options:{}};if(h.length===1&&X(h[0])){let S=h[0];return{rules:S.rules??[],options:S}}let G=h[h.length-1];if(X(G)){let S=G,q=h.slice(0,-1);if(S.rules)q=[...q,...S.rules];return{rules:q,options:S}}return{rules:h,options:{}}}function L(h,G,S){for(let q of G)if(N(q))for(let w of q.rules){let b={rule:w,each:!0,groups:S.groups};if(S.message!==void 0)b.message=S.message;if(S.context!==void 0)b.context=S.context;h.validation.push(b)}else{let w={rule:q,groups:S.groups};if(S.message!==void 0)w.message=S.message;if(S.context!==void 0)w.context=S.context;h.validation.push(w)}}function E(h,G){if(G.name)h.expose.push({name:G.name,groups:G.groups});else if(G.deserializeName||G.serializeName){if(G.deserializeName)h.expose.push({name:G.deserializeName,deserializeOnly:!0,groups:G.groups});if(G.serializeName)h.expose.push({name:G.serializeName,serializeOnly:!0,groups:G.groups})}else if(G.groups)h.expose.push({groups:G.groups});else h.expose.push({})}function Z(h,G,S){let q=Q(S);return{fn:(b)=>{let B=S(b);if(!q&&U(B))throw Error(`@Field(${h}) ${G} transform returned Promise. Declare the transform with async if it is asynchronous.`);return B},isAsync:q}}function P(h,G,S){if(!S.transform)return;let q=Array.isArray(S.transform)?S.transform:[S.transform];for(let w of q){let b=Z(G,"deserialize",w.deserialize),B=Z(G,"serialize",w.serialize);h.transform.push({fn:b.fn,isAsync:b.isAsync,options:{deserializeOnly:!0}},{fn:B.fn,isAsync:B.isAsync,options:{serializeOnly:!0}})}}function v(...h){return(G,S)=>{let q=G.constructor,w=S,b=J(q,w),{rules:B,options:j}=I(h);if(L(b,B,j),j.optional)b.flags.isOptional=!0;if(j.nullable)b.flags.isNullable=!0;if(j.when)b.flags.validateIf=j.when;if(j.type)b.type={fn:j.type,discriminator:j.discriminator,keepDiscriminatorProperty:j.keepDiscriminatorProperty,collectionValue:j.mapValue??j.setValue};if(E(b,j),j.exclude){if(j.exclude===!0)b.exclude={};else if(j.exclude==="deserializeOnly")b.exclude={deserializeOnly:!0};else if(j.exclude==="serializeOnly")b.exclude={serializeOnly:!0}}P(b,w,j)}}
|
|
3
|
+
export{H as j,Q as k,U as l,M as m,v as n};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var I=()=>({kind:"value"}),Y=(w=I())=>({kind:"member",object:w,property:"length"}),Z=(w=I())=>({kind:"call0",object:w,method:"getTime"}),O=(w)=>({kind:"literal",value:w}),_=(w,z,A)=>({kind:"compare",left:w,op:z,right:typeof A==="number"?O(A):A});var $=(...w)=>({kind:"or",checks:w});function L(w){return Q({name:w.name,requiresType:w.requiresType,constraints:w.constraints,plan:w.plan,validate:w.validate,emit:(z,A)=>U(z,A,w.name,w.plan)})}function Q(w){let z=(A)=>w.validate(A);if(z.emit=w.emit,z.ruleName=w.name,w.requiresType!==void 0)z.requiresType=w.requiresType;if(z.constraints=w.constraints??{},w.isAsync)z.isAsync=!0;if(w.plan)z.plan=w.plan;return z}function U(w,z,A,B,F,K){let M=K?W(B.failure):B.failure;return`if (${J(M,w,F)}) ${z.fail(A)};`}function W(w){if(w.kind==="compare")return w;let z=w.checks.filter((A)=>!X(A));if(z.length===0)return w;if(z.length===1)return z[0];return{kind:w.kind,checks:z}}function X(w){if(w.kind!=="compare"||w.op!=="!==")return!1;return H(w.left,w.right)}function H(w,z){if(w.kind!==z.kind)return!1;if(w.kind==="value")return!0;if(w.kind==="literal")return w.value===z.value;if(w.kind==="member")return H(w.object,z.object);if(w.kind==="call0")return w.method===z.method&&H(w.object,z.object);return!1}function J(w,z,A){if(w.kind==="compare")return`${D(w.left,z,A)} ${w.op} ${D(w.right,z,A)}`;let B=w.kind==="and"?" && ":" || ";return`(${w.checks.map((F)=>J(F,z,A)).join(B)})`}function D(w,z,A){switch(w.kind){case"value":return z;case"literal":return String(w.value);case"member":return A?.length??`${D(w.object,z,A)}.length`;case"call0":return A?.time??`${D(w.object,z,A)}.getTime()`}}
|
|
3
|
+
export{I as a,Y as b,Z as c,O as d,_ as e,$ as f,L as g,Q as h,U as i};
|
package/dist/index-xdn55cz3.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,9 @@ export { serialize } from './src/functions/serialize';
|
|
|
4
4
|
export { configure } from './src/configure';
|
|
5
5
|
export { createRule } from './src/create-rule';
|
|
6
6
|
export { Field, arrayOf } from './src/decorators/index';
|
|
7
|
-
export type { FieldOptions,
|
|
7
|
+
export type { FieldOptions, ArrayOfMarker } from './src/decorators/index';
|
|
8
8
|
export type { BakerError, BakerErrors } from './src/errors';
|
|
9
9
|
export { isBakerError, SealError } from './src/errors';
|
|
10
|
-
export type { EmittableRule } from './src/types';
|
|
11
|
-
export type { BakerConfig
|
|
10
|
+
export type { EmittableRule, Transformer, TransformParams } from './src/types';
|
|
11
|
+
export type { BakerConfig } from './src/configure';
|
|
12
12
|
export type { RuntimeOptions } from './src/interfaces';
|