@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.
@@ -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
- /** 검증 함수 — true: 통과, false: 실패. async 함수 허용 (Promise<boolean> 반환 자동으로 async 룰로 등록). */
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
- /** 파라미터 — toJsonSchema 매핑에 사용 */
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
- /** 중첩 DTO 타입. thunk순환 참조 지원. [Dto] 배열. */
21
+ /** Nested DTO type. Thunksupports circular references. [Dto] for arrays. */
29
22
  type?: () => (new (...args: any[]) => any) | (new (...args: any[]) => any)[];
30
- /** 다형성 discriminator 설정type과 함께 사용 */
23
+ /** Polymorphic discriminator configurationused 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
- /** deserialize 방향 매핑 (name과 동시 사용 불가) */
41
+ /** Deserialize direction key mapping (cannot be used with name) */
49
42
  deserializeName?: string;
50
- /** serialize 방향 매핑 (name과 동시 사용 불가) */
43
+ /** Serialize direction key mapping (cannot be used with name) */
51
44
  serializeName?: string;
52
- /** 필드 제외 — true: 양방향, 'deserializeOnly': 역직렬화만, 'serializeOnly': 직렬화만 */
45
+ /** Field exclusion — true: bidirectional, 'deserializeOnly': deserialization only, 'serializeOnly': serialization only */
53
46
  exclude?: boolean | 'deserializeOnly' | 'serializeOnly';
54
- /** 그룹필드 가시성 제어 + validation rule 조건부 적용 */
47
+ /** Groupsfield visibility control + conditional validation rule application */
55
48
  groups?: string[];
56
- /** 조건부 검증false 필드 전체 검증 skip */
49
+ /** Conditional validationskip all field validation when false */
57
50
  when?: (obj: any) => boolean;
58
- /** JSON Schema 커스텀 (프로퍼티 레벨) */
59
- schema?: JsonSchemaOverride;
60
- /** 값 변환 함수 */
51
+ /** Value transform function */
61
52
  transform?: (params: FieldTransformParams) => unknown;
62
- /** transform 방향 제한 */
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, JsonSchemaOverride, ArrayOfMarker } from './field';
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-57gr0v18.js";import"../../index-aegrb1kn.js";export{a as arrayOf,b as Field};
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
@@ -1,38 +1,49 @@
1
1
  /**
2
- * 개별 필드 에러최소 계약(minimum contract).
2
+ * Individual field error — minimum contract.
3
3
  *
4
- * 예약 에러 코드:
5
- * - 'invalidInput': input null, 비객체, 배열일 (path='')
6
- * - 'isObject': 중첩 @Type 필드의 값이 객체가 아닐
7
- * - 'isArray': 배열 중첩 (each:true) 필드의 값이 배열이 아닐
8
- * - 'invalidDiscriminator': discriminator 값이 subTypes에 없을
9
- * - 'conversionFailed': enableImplicitConversion에서 타입 변환 실패
10
- * - 'whitelistViolation': whitelist: true에서 미선언 필드가 input 존재할
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
- * 향후 확장 필드(message, expected, actual ) 반드시 Optional로 추가.
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
- /** 사용자 정의 에러 메시지 데코레이터 message 옵션이 설정된 경우에만 포함 */
17
+ /** User-defined error messageincluded only when the decorator message option is set */
18
18
  readonly message?: string;
19
- /** 사용자 정의 컨텍스트 데코레이터 context 옵션이 설정된 경우에만 포함 */
19
+ /** User-defined contextincluded 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() 검증 실패 시 throw되는 에러.
24
- * errors 배열에 모든 필드 에러가 담겨 있다.
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 class BakerValidationError extends Error {
27
- readonly errors: BakerError[];
28
- /** 검증 대상 DTO 클래스명 (DX-2) */
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() 2회 이상 호출
35
- * - 미봉인 클래스에 deserialize()/serialize() 호출
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 Class 인스턴스 변환 + 검증.
4
- * - 호출 auto-seal (globalRegistry 전체 배치)
5
- * - 성공: Promise<T> 반환
6
- * - 검증 실패: BakerValidationError throw
7
- * - 데코레이터 없는 클래스: SealError throw
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,4 +1,3 @@
1
1
  export { deserialize } from './deserialize';
2
2
  export { serialize } from './serialize';
3
- export { toJsonSchema } from './to-json-schema';
4
- export type { ToJsonSchemaOptions } from './to-json-schema';
3
+ export { validate } from './validate';
@@ -1,8 +1,9 @@
1
1
  import type { RuntimeOptions } from '../interfaces';
2
2
  /**
3
- * Class 인스턴스 plain 객체 변환.
4
- * - 호출 auto-seal (globalRegistry 전체 배치)
5
- * - 무검증 전제 항상 Record<string, unknown> 반환 (또는 Promise)
6
- * - 데코레이터 없는 클래스: SealError throw
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>;
@@ -1,32 +1,32 @@
1
1
  export interface SealOptions {
2
2
  /**
3
- * validation 데코레이터를 타입 힌트로 활용한 자동 변환.
3
+ * Automatic conversion using validation decorators as type hints.
4
4
  * @default false
5
5
  */
6
6
  enableImplicitConversion?: boolean;
7
7
  /**
8
- * input에 해당 키가 없을 클래스 기본값을 사용.
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: 에러 즉시 반환. false(기본): 전체 에러 수집.
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: 미선언 필드 거부. mergeInheritance(Class) key 집합을 허용 목록으로 사용.
19
- * @Exclude 필드도 whitelist 포함 존재는 허용하되 결과에서 제외.
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
- /** 요청별 groups — 요청마다 다를 있으므로 런타임에 전달 */
30
+ /** Per-request groups — passed at runtime since they may vary per request */
31
31
  groups?: string[];
32
32
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
- * 전역 레지스트리데코레이터가 1개라도 부착된 클래스를 자동 등록
2
+ * Global registryautomatically registers classes with at least one decorator attached
3
3
  *
4
- * - ensureMeta()에서 자동 호출
5
- * - seal() Set 순회하여 모든 DTO를 봉인
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 { IsEmailOptions, IsURLOptions, IsBase32Options, IsBase64Options, IsDateStringOptions, IsCurrencyOptions, IsMACAddressOptions, IsIBANOptions, IsISSNOptions, IsFQDNOptions, IsLatLongOptions, IsISO8601Options, IsNumberStringOptions, IsDecimalOptions, IsStrongPasswordOptions, } from './string';
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';