@zipbul/baker 1.0.0 → 2.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/README.md +150 -471
- package/dist/index-btgens0c.js +6 -0
- package/dist/index-k369bbht.js +6 -0
- package/dist/index.d.ts +5 -6
- package/dist/index.js +221 -161
- package/dist/src/collect.d.ts +3 -5
- package/dist/src/configure.d.ts +10 -16
- package/dist/src/create-rule.d.ts +7 -7
- package/dist/src/decorators/field.d.ts +31 -28
- package/dist/src/decorators/index.d.ts +1 -1
- package/dist/src/decorators/index.js +1 -1
- package/dist/src/errors.d.ts +33 -22
- package/dist/src/functions/_run-sealed.d.ts +7 -0
- package/dist/src/functions/deserialize.d.ts +8 -6
- package/dist/src/functions/index.d.ts +1 -2
- package/dist/src/functions/serialize.d.ts +6 -5
- package/dist/src/functions/validate.d.ts +13 -0
- package/dist/src/interfaces.d.ts +7 -7
- package/dist/src/registry.d.ts +4 -4
- package/dist/src/rules/index.d.ts +1 -1
- package/dist/src/rules/index.js +9 -9
- package/dist/src/rules/object.d.ts +1 -1
- package/dist/src/rules/string.d.ts +6 -48
- 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 +4 -6
- package/dist/src/symbols.js +2 -2
- package/dist/src/types.d.ts +34 -84
- package/package.json +13 -3
- package/README.ko.md +0 -588
- package/dist/index-57gr0v18.js +0 -6
- package/dist/index-aegrb1kn.js +0 -6
- package/dist/src/functions/to-json-schema.d.ts +0 -20
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import type { EmittableRule } from './types';
|
|
2
2
|
export interface CreateRuleOptions {
|
|
3
|
-
/**
|
|
3
|
+
/** Rule name. Used as the error code. */
|
|
4
4
|
name: string;
|
|
5
|
-
/**
|
|
5
|
+
/** Validation function — true: pass, false: fail. Async functions allowed (automatically registered as async rule when returning Promise<boolean>). */
|
|
6
6
|
validate: (value: unknown) => boolean | Promise<boolean>;
|
|
7
|
-
/**
|
|
7
|
+
/** Rule parameters */
|
|
8
8
|
constraints?: Record<string, unknown>;
|
|
9
|
-
/**
|
|
9
|
+
/** Type assumed by this rule — used for type gate optimization */
|
|
10
10
|
requiresType?: 'string' | 'number' | 'boolean' | 'date';
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Creates a user-defined validation rule.
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
|
-
* //
|
|
16
|
+
* // Simple form
|
|
17
17
|
* const koreanPhone = createRule('koreanPhone', (v) => /^01[016789]/.test(v as string));
|
|
18
18
|
*
|
|
19
|
-
* //
|
|
19
|
+
* // Options form
|
|
20
20
|
* const isEven = createRule({
|
|
21
21
|
* name: 'isEven',
|
|
22
22
|
* validate: (v) => typeof v === 'number' && v % 2 === 0,
|
|
@@ -4,7 +4,7 @@ export interface ArrayOfMarker {
|
|
|
4
4
|
readonly rules: EmittableRule[];
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Apply rules to each element of an array.
|
|
8
8
|
*
|
|
9
9
|
* @example
|
|
10
10
|
* @Field(arrayOf(isString(), minLength(1)))
|
|
@@ -17,17 +17,10 @@ export interface FieldTransformParams {
|
|
|
17
17
|
obj: Record<string, unknown>;
|
|
18
18
|
direction: 'deserialize' | 'serialize';
|
|
19
19
|
}
|
|
20
|
-
export interface JsonSchemaOverride {
|
|
21
|
-
title?: string;
|
|
22
|
-
description?: string;
|
|
23
|
-
default?: unknown;
|
|
24
|
-
examples?: unknown[];
|
|
25
|
-
[key: string]: unknown;
|
|
26
|
-
}
|
|
27
20
|
export interface FieldOptions {
|
|
28
|
-
/**
|
|
21
|
+
/** Nested DTO type. Thunk — supports circular references. [Dto] for arrays. */
|
|
29
22
|
type?: () => (new (...args: any[]) => any) | (new (...args: any[]) => any)[];
|
|
30
|
-
/**
|
|
23
|
+
/** Polymorphic discriminator configuration — used with type */
|
|
31
24
|
discriminator?: {
|
|
32
25
|
property: string;
|
|
33
26
|
subTypes: {
|
|
@@ -35,40 +28,50 @@ export interface FieldOptions {
|
|
|
35
28
|
name: string;
|
|
36
29
|
}[];
|
|
37
30
|
};
|
|
38
|
-
/** discriminator
|
|
31
|
+
/** Whether to keep the discriminator property in the result object */
|
|
39
32
|
keepDiscriminatorProperty?: boolean;
|
|
40
|
-
/**
|
|
33
|
+
/** Validation rules array */
|
|
41
34
|
rules?: (EmittableRule | ArrayOfMarker)[];
|
|
42
|
-
/** undefined
|
|
35
|
+
/** Allow undefined */
|
|
43
36
|
optional?: boolean;
|
|
44
|
-
/** null
|
|
37
|
+
/** Allow null */
|
|
45
38
|
nullable?: boolean;
|
|
46
|
-
/** JSON
|
|
39
|
+
/** JSON key mapping (bidirectional) */
|
|
47
40
|
name?: string;
|
|
48
|
-
/**
|
|
41
|
+
/** Deserialize direction key mapping (cannot be used with name) */
|
|
49
42
|
deserializeName?: string;
|
|
50
|
-
/**
|
|
43
|
+
/** Serialize direction key mapping (cannot be used with name) */
|
|
51
44
|
serializeName?: string;
|
|
52
|
-
/**
|
|
45
|
+
/** Field exclusion — true: bidirectional, 'deserializeOnly': deserialization only, 'serializeOnly': serialization only */
|
|
53
46
|
exclude?: boolean | 'deserializeOnly' | 'serializeOnly';
|
|
54
|
-
/**
|
|
47
|
+
/** Groups — field visibility control + conditional validation rule application */
|
|
55
48
|
groups?: string[];
|
|
56
|
-
/**
|
|
49
|
+
/** Conditional validation — skip all field validation when false */
|
|
57
50
|
when?: (obj: any) => boolean;
|
|
58
|
-
/**
|
|
59
|
-
schema?: JsonSchemaOverride;
|
|
60
|
-
/** 값 변환 함수 */
|
|
51
|
+
/** Value transform function */
|
|
61
52
|
transform?: (params: FieldTransformParams) => unknown;
|
|
62
|
-
/**
|
|
53
|
+
/** Transform direction restriction */
|
|
63
54
|
transformDirection?: 'deserializeOnly' | 'serializeOnly';
|
|
55
|
+
/** Error message on validation failure — applied to all rules of the field (rule's own message takes precedence) */
|
|
56
|
+
message?: string | ((args: {
|
|
57
|
+
property: string;
|
|
58
|
+
value: unknown;
|
|
59
|
+
constraints: Record<string, unknown>;
|
|
60
|
+
}) => string);
|
|
61
|
+
/** Error context on validation failure — applied to all rules of the field (rule's own context takes precedence) */
|
|
62
|
+
context?: unknown;
|
|
63
|
+
/** Nested DTO class thunk for Map values — used with type: () => Map */
|
|
64
|
+
mapValue?: () => new (...args: any[]) => any;
|
|
65
|
+
/** Nested DTO class thunk for Set elements — used with type: () => Set */
|
|
66
|
+
setValue?: () => new (...args: any[]) => any;
|
|
64
67
|
}
|
|
65
68
|
type RuleArg = EmittableRule | ArrayOfMarker;
|
|
66
|
-
/** @Field() —
|
|
69
|
+
/** @Field() — empty field registration */
|
|
67
70
|
export declare function Field(): PropertyDecorator;
|
|
68
|
-
/** @Field(isString(), email()) —
|
|
71
|
+
/** @Field(isString(), email()) — variadic rules */
|
|
69
72
|
export declare function Field(...rules: RuleArg[]): PropertyDecorator;
|
|
70
|
-
/** @Field({ type: () => Dto }) —
|
|
73
|
+
/** @Field({ type: () => Dto }) — options object */
|
|
71
74
|
export declare function Field(options: FieldOptions): PropertyDecorator;
|
|
72
|
-
/** @Field(isString(), { optional: true }) —
|
|
75
|
+
/** @Field(isString(), { optional: true }) — rules + options mixed */
|
|
73
76
|
export declare function Field(...rulesAndOptions: [...RuleArg[], FieldOptions]): PropertyDecorator;
|
|
74
77
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Field, arrayOf } from './field';
|
|
2
|
-
export type { FieldOptions, FieldTransformParams,
|
|
2
|
+
export type { FieldOptions, FieldTransformParams, ArrayOfMarker } from './field';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import"../../index-xdn55cz3.js";import{c as a,d as b}from"../../index-
|
|
2
|
+
import"../../index-xdn55cz3.js";import{c as a,d as b}from"../../index-btgens0c.js";import"../../index-k369bbht.js";export{a as arrayOf,b as Field};
|
|
3
3
|
|
|
4
4
|
//# debugId=9E4BFE621FA3997464756E2164756E21
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -1,38 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Individual field error — minimum contract.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* - 'invalidInput': input
|
|
6
|
-
* - 'isObject':
|
|
7
|
-
* - 'isArray':
|
|
8
|
-
* - 'invalidDiscriminator': discriminator
|
|
9
|
-
* - 'conversionFailed':
|
|
10
|
-
* - 'whitelistViolation':
|
|
4
|
+
* Reserved error codes:
|
|
5
|
+
* - 'invalidInput': when input is null, non-object, or array (path='')
|
|
6
|
+
* - 'isObject': when a nested @Type field's value is not an object
|
|
7
|
+
* - 'isArray': when an array-nested (each:true) field's value is not an array
|
|
8
|
+
* - 'invalidDiscriminator': when the discriminator value is not in subTypes
|
|
9
|
+
* - 'conversionFailed': when type conversion fails in enableImplicitConversion
|
|
10
|
+
* - 'whitelistViolation': when undeclared fields exist in input with whitelist: true
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Future extension fields (message, expected, actual, etc.) must be added as Optional.
|
|
13
13
|
*/
|
|
14
14
|
export interface BakerError {
|
|
15
15
|
readonly path: string;
|
|
16
16
|
readonly code: string;
|
|
17
|
-
/**
|
|
17
|
+
/** User-defined error message — included only when the decorator message option is set */
|
|
18
18
|
readonly message?: string;
|
|
19
|
-
/**
|
|
19
|
+
/** User-defined context — included only when the decorator context option is set */
|
|
20
20
|
readonly context?: unknown;
|
|
21
21
|
}
|
|
22
|
+
/** Symbol tag for isBakerError() type guard — collision-proof discriminator */
|
|
23
|
+
export declare const BAKER_ERROR: unique symbol;
|
|
24
|
+
/** Validation failure — returned by deserialize() on invalid input */
|
|
25
|
+
export interface BakerErrors {
|
|
26
|
+
readonly [BAKER_ERROR]: true;
|
|
27
|
+
readonly errors: readonly BakerError[];
|
|
28
|
+
}
|
|
22
29
|
/**
|
|
23
|
-
* deserialize()
|
|
24
|
-
*
|
|
30
|
+
* Type guard — narrows deserialize() result to BakerErrors.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const result = await deserialize(UserDto, input);
|
|
34
|
+
* if (isBakerError(result)) {
|
|
35
|
+
* result.errors // readonly BakerError[]
|
|
36
|
+
* } else {
|
|
37
|
+
* result // UserDto
|
|
38
|
+
* }
|
|
25
39
|
*/
|
|
26
|
-
export declare
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
readonly className?: string;
|
|
30
|
-
constructor(errors: BakerError[], className?: string);
|
|
31
|
-
}
|
|
40
|
+
export declare function isBakerError(value: unknown): value is BakerErrors;
|
|
41
|
+
/** @internal — create BakerErrors object */
|
|
42
|
+
export declare function _toBakerErrors(errors: BakerError[]): BakerErrors;
|
|
32
43
|
/**
|
|
33
|
-
*
|
|
34
|
-
* - seal()
|
|
35
|
-
* -
|
|
44
|
+
* Seal-related error:
|
|
45
|
+
* - When seal() is called more than once
|
|
46
|
+
* - When deserialize()/serialize() is called on an unsealed class
|
|
36
47
|
*/
|
|
37
48
|
export declare class SealError extends Error {
|
|
38
49
|
constructor(message: string);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BakerErrors } from '../errors';
|
|
2
|
+
import type { RuntimeOptions } from '../interfaces';
|
|
3
|
+
/**
|
|
4
|
+
* @internal — shared seal+dispatch+unwrap for deserialize and validate.
|
|
5
|
+
* Calls sealed._deserialize, converts Result to BakerErrors, maps success via onSuccess.
|
|
6
|
+
*/
|
|
7
|
+
export declare function _runSealed<S>(Class: Function, input: unknown, options: RuntimeOptions | undefined, onSuccess: (result: any) => S): S | BakerErrors | Promise<S | BakerErrors>;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { BakerErrors } from '../errors';
|
|
1
2
|
import type { RuntimeOptions } from '../interfaces';
|
|
2
3
|
/**
|
|
3
|
-
* input
|
|
4
|
-
* -
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
4
|
+
* Converts input to a Class instance + validates.
|
|
5
|
+
* - Auto-seals on first call (batches entire globalRegistry)
|
|
6
|
+
* - Sync DTOs return directly, async DTOs return Promise
|
|
7
|
+
* - Success: T
|
|
8
|
+
* - Validation failure: BakerErrors (use isBakerError() to narrow)
|
|
9
|
+
* - Class without decorators: throws SealError
|
|
8
10
|
*/
|
|
9
|
-
export declare function deserialize<T>(Class: new (...args: any[]) => T, input: unknown, options?: RuntimeOptions): Promise<T>;
|
|
11
|
+
export declare function deserialize<T>(Class: new (...args: any[]) => T, input: unknown, options?: RuntimeOptions): T | BakerErrors | Promise<T | BakerErrors>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { RuntimeOptions } from '../interfaces';
|
|
2
2
|
/**
|
|
3
|
-
* Class
|
|
4
|
-
* -
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
3
|
+
* Converts a Class instance to a plain object.
|
|
4
|
+
* - Auto-seals on first call (batches entire globalRegistry)
|
|
5
|
+
* - Sync DTOs return directly, async DTOs return Promise
|
|
6
|
+
* - No validation — always returns Record<string, unknown>
|
|
7
|
+
* - Class without decorators: throws SealError
|
|
7
8
|
*/
|
|
8
|
-
export declare function serialize<T>(instance: T, options?: RuntimeOptions): Promise<Record<string, unknown>>;
|
|
9
|
+
export declare function serialize<T>(instance: T, options?: RuntimeOptions): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BakerErrors } from '../errors';
|
|
2
|
+
import type { EmittableRule } from '../types';
|
|
3
|
+
import type { RuntimeOptions } from '../interfaces';
|
|
4
|
+
/**
|
|
5
|
+
* DTO-level validation — validates input against a decorated class.
|
|
6
|
+
* Sync DTOs return directly, async DTOs return Promise.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validate<T>(Class: new (...args: any[]) => T, input: unknown, options?: RuntimeOptions): true | BakerErrors | Promise<true | BakerErrors>;
|
|
9
|
+
/**
|
|
10
|
+
* Ad-hoc validation — validates a single value against one or more rules.
|
|
11
|
+
* Sync rules return directly, async rules return Promise.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validate(input: unknown, ...rules: EmittableRule[]): true | BakerErrors | Promise<true | BakerErrors>;
|
package/dist/src/interfaces.d.ts
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
export interface SealOptions {
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Automatic conversion using validation decorators as type hints.
|
|
4
4
|
* @default false
|
|
5
5
|
*/
|
|
6
6
|
enableImplicitConversion?: boolean;
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Use class default values when the key is missing from input.
|
|
9
9
|
* @default false
|
|
10
10
|
*/
|
|
11
11
|
exposeDefaultValues?: boolean;
|
|
12
12
|
/**
|
|
13
|
-
* true:
|
|
13
|
+
* true: return immediately on first error. false (default): collect all errors.
|
|
14
14
|
* @default false
|
|
15
15
|
*/
|
|
16
16
|
stopAtFirstError?: boolean;
|
|
17
17
|
/**
|
|
18
|
-
* true:
|
|
19
|
-
* @Exclude
|
|
18
|
+
* true: reject undeclared fields. Uses the key set from mergeInheritance(Class) as the allowlist.
|
|
19
|
+
* @Exclude fields are also included in the whitelist — their presence is allowed but they are excluded from the result.
|
|
20
20
|
* @default false
|
|
21
21
|
*/
|
|
22
22
|
whitelist?: boolean;
|
|
23
23
|
/**
|
|
24
|
-
* true:
|
|
24
|
+
* true: include field exclusion reasons as comments in generated code.
|
|
25
25
|
* @default false
|
|
26
26
|
*/
|
|
27
27
|
debug?: boolean;
|
|
28
28
|
}
|
|
29
29
|
export interface RuntimeOptions {
|
|
30
|
-
/**
|
|
30
|
+
/** Per-request groups — passed at runtime since they may vary per request */
|
|
31
31
|
groups?: string[];
|
|
32
32
|
}
|
package/dist/src/registry.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Global registry — automatically registers classes with at least one decorator attached
|
|
3
3
|
*
|
|
4
|
-
* - ensureMeta()
|
|
5
|
-
* - seal()
|
|
6
|
-
* -
|
|
4
|
+
* - Automatically called from ensureMeta()
|
|
5
|
+
* - seal() iterates this Set to seal all DTOs
|
|
6
|
+
* - Metadata is not stored here — used only as an index (which classes are registered)
|
|
7
7
|
*/
|
|
8
8
|
export declare const globalRegistry: Set<Function>;
|
|
@@ -4,7 +4,7 @@ export { min, max, isPositive, isNegative, isDivisibleBy } from './number';
|
|
|
4
4
|
export { minDate, maxDate } from './date';
|
|
5
5
|
export { equals, notEquals, isEmpty, isNotEmpty, isIn, isNotIn } from './common';
|
|
6
6
|
export { minLength, maxLength, length, contains, notContains, matches, isLowercase, isUppercase, isAscii, isAlpha, isAlphanumeric, isBooleanString, isNumberString, isDecimal, isFullWidth, isHalfWidth, isVariableWidth, isMultibyte, isSurrogatePair, isHexadecimal, isOctal, isEmail, isURL, isUUID, isIP, isHexColor, isRgbColor, isHSL, isMACAddress, isISBN, isISIN, isISO8601, isISRC, isISSN, isJWT, isLatLong, isLocale, isDataURI, isFQDN, isPort, isEAN, isISO31661Alpha2, isISO31661Alpha3, isBIC, isFirebasePushId, isSemVer, isMongoId, isJSON, isBase32, isBase58, isBase64, isDateString, isMimeType, isCurrency, isMagnetURI, isCreditCard, isIBAN, isByteLength, isHash, isRFC3339, isMilitaryTime, isLatitude, isLongitude, isEthereumAddress, isBtcAddress, isISO4217CurrencyCode, isPhoneNumber, isStrongPassword, isTaxId, } from './string';
|
|
7
|
-
export type {
|
|
7
|
+
export type { IsURLOptions, IsBase64Options, IsMACAddressOptions, IsIBANOptions, IsISSNOptions, IsFQDNOptions, IsISO8601Options, IsNumberStringOptions, IsStrongPasswordOptions, } from './string';
|
|
8
8
|
export { arrayContains, arrayNotContains, arrayMinSize, arrayMaxSize, arrayUnique, arrayNotEmpty, } from './array';
|
|
9
9
|
export { isNotEmptyObject, isInstance } from './object';
|
|
10
10
|
export type { IsNotEmptyObjectOptions } from './object';
|