@rtpaulino/entity 0.23.0 → 0.24.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.
@@ -48,31 +48,31 @@ import { ValidationError } from './validation-error.js';
48
48
  ]);
49
49
  }
50
50
  /**
51
- * Prepends a property path to all problems in a ValidationError.
51
+ * Prepends a property path to all problems.
52
52
  * Problems with empty property names get the path directly.
53
53
  * Problems starting with '[' get the path without a dot separator.
54
54
  * Other problems get the path with a dot separator.
55
55
  *
56
56
  * @param propertyPath - The property path to prepend (e.g., 'user', 'items[0]')
57
- * @param error - The ValidationError containing problems to process
57
+ * @param problems - The array of Problems to process
58
58
  * @returns Array of Problems with the property path prepended
59
59
  *
60
60
  * @example
61
61
  * ```typescript
62
- * const error = new ValidationError([
62
+ * const problems = [
63
63
  * new Problem({ property: '', message: 'Invalid type' }),
64
64
  * new Problem({ property: 'name', message: 'Required' }),
65
65
  * new Problem({ property: '[0]', message: 'Invalid element' })
66
- * ]);
67
- * const problems = prependPropertyPath('user', error);
66
+ * ];
67
+ * const result = prependPropertyPath('user', problems);
68
68
  * // [
69
69
  * // { property: 'user', message: 'Invalid type' },
70
70
  * // { property: 'user.name', message: 'Required' },
71
71
  * // { property: 'user[0]', message: 'Invalid element' }
72
72
  * // ]
73
73
  * ```
74
- */ export function prependPropertyPath(propertyPath, error) {
75
- return error.problems.map((problem)=>{
74
+ */ export function prependPropertyPath(propertyPath, problems) {
75
+ return problems.map((problem)=>{
76
76
  return new Problem({
77
77
  property: combinePropertyPaths(propertyPath, problem.property),
78
78
  message: problem.message
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/validation-utils.ts"],"sourcesContent":["import { Problem } from './problem.js';\nimport { ValidationError } from './validation-error.js';\n\n/**\n * Combines a property path prefix with a suffix according to deterministic rules:\n * - If suffix is empty, returns prefix\n * - If suffix starts with '[', concatenates without separator (e.g., 'items' + '[0]' → 'items[0]')\n * - Otherwise, concatenates with dot separator (e.g., 'user' + 'name' → 'user.name')\n *\n * @param prefix - The property path to prepend\n * @param suffix - The property path to append\n * @returns The combined property path\n *\n * @example\n * ```typescript\n * combinePropertyPaths('user', '') // 'user'\n * combinePropertyPaths('user', 'name') // 'user.name'\n * combinePropertyPaths('items', '[0]') // 'items[0]'\n * combinePropertyPaths('[0]', 'name') // '[0].name'\n * ```\n */\nexport function combinePropertyPaths(prefix: string, suffix: string): string {\n if (suffix === '') {\n return prefix;\n }\n if (suffix.startsWith('[')) {\n return `${prefix}${suffix}`;\n }\n return `${prefix}.${suffix}`;\n}\n\n/**\n * Creates a ValidationError with a single problem that has an empty property.\n * This is used when reporting errors at the current scope level, where the caller\n * will prepend the appropriate context path.\n *\n * @param message - The error message\n * @returns A ValidationError with a single problem with empty property\n *\n * @example\n * ```typescript\n * throw createValidationError('Expects a string but received number');\n * // Creates: ValidationError([{ property: '', message: 'Expects a string but received number' }])\n * ```\n */\nexport function createValidationError(message: string): ValidationError {\n return new ValidationError([\n new Problem({\n property: '',\n message,\n }),\n ]);\n}\n\n/**\n * Prepends a property path to all problems in a ValidationError.\n * Problems with empty property names get the path directly.\n * Problems starting with '[' get the path without a dot separator.\n * Other problems get the path with a dot separator.\n *\n * @param propertyPath - The property path to prepend (e.g., 'user', 'items[0]')\n * @param error - The ValidationError containing problems to process\n * @returns Array of Problems with the property path prepended\n *\n * @example\n * ```typescript\n * const error = new ValidationError([\n * new Problem({ property: '', message: 'Invalid type' }),\n * new Problem({ property: 'name', message: 'Required' }),\n * new Problem({ property: '[0]', message: 'Invalid element' })\n * ]);\n * const problems = prependPropertyPath('user', error);\n * // [\n * // { property: 'user', message: 'Invalid type' },\n * // { property: 'user.name', message: 'Required' },\n * // { property: 'user[0]', message: 'Invalid element' }\n * // ]\n * ```\n */\nexport function prependPropertyPath(\n propertyPath: string,\n error: ValidationError,\n): Problem[] {\n return error.problems.map((problem) => {\n return new Problem({\n property: combinePropertyPaths(propertyPath, problem.property),\n message: problem.message,\n });\n });\n}\n\n/**\n * Prepends an array index to all problems in a ValidationError.\n * Problems with empty property get `[index]` directly.\n * Problems with non-empty property get `[index].property` format.\n *\n * @param index - The array index to prepend\n * @param error - The ValidationError containing problems to process\n * @returns Array of Problems with the array index prepended\n *\n * @example\n * ```typescript\n * const error = new ValidationError([\n * new Problem({ property: '', message: 'Invalid type' }),\n * new Problem({ property: 'name', message: 'Required' })\n * ]);\n * const problems = prependArrayIndex(0, error);\n * // [\n * // { property: '[0]', message: 'Invalid type' },\n * // { property: '[0].name', message: 'Required' }\n * // ]\n * ```\n */\nexport function prependArrayIndex(\n index: number,\n error: ValidationError,\n): Problem[] {\n return error.problems.map((problem) => {\n return new Problem({\n property: combinePropertyPaths(`[${index}]`, problem.property),\n message: problem.message,\n });\n });\n}\n"],"names":["Problem","ValidationError","combinePropertyPaths","prefix","suffix","startsWith","createValidationError","message","property","prependPropertyPath","propertyPath","error","problems","map","problem","prependArrayIndex","index"],"mappings":"AAAA,SAASA,OAAO,QAAQ,eAAe;AACvC,SAASC,eAAe,QAAQ,wBAAwB;AAExD;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASC,qBAAqBC,MAAc,EAAEC,MAAc;IACjE,IAAIA,WAAW,IAAI;QACjB,OAAOD;IACT;IACA,IAAIC,OAAOC,UAAU,CAAC,MAAM;QAC1B,OAAO,GAAGF,SAASC,QAAQ;IAC7B;IACA,OAAO,GAAGD,OAAO,CAAC,EAAEC,QAAQ;AAC9B;AAEA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASE,sBAAsBC,OAAe;IACnD,OAAO,IAAIN,gBAAgB;QACzB,IAAID,QAAQ;YACVQ,UAAU;YACVD;QACF;KACD;AACH;AAEA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASE,oBACdC,YAAoB,EACpBC,KAAsB;IAEtB,OAAOA,MAAMC,QAAQ,CAACC,GAAG,CAAC,CAACC;QACzB,OAAO,IAAId,QAAQ;YACjBQ,UAAUN,qBAAqBQ,cAAcI,QAAQN,QAAQ;YAC7DD,SAASO,QAAQP,OAAO;QAC1B;IACF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,SAASQ,kBACdC,KAAa,EACbL,KAAsB;IAEtB,OAAOA,MAAMC,QAAQ,CAACC,GAAG,CAAC,CAACC;QACzB,OAAO,IAAId,QAAQ;YACjBQ,UAAUN,qBAAqB,CAAC,CAAC,EAAEc,MAAM,CAAC,CAAC,EAAEF,QAAQN,QAAQ;YAC7DD,SAASO,QAAQP,OAAO;QAC1B;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/lib/validation-utils.ts"],"sourcesContent":["import { Problem } from './problem.js';\nimport { ValidationError } from './validation-error.js';\n\n/**\n * Combines a property path prefix with a suffix according to deterministic rules:\n * - If suffix is empty, returns prefix\n * - If suffix starts with '[', concatenates without separator (e.g., 'items' + '[0]' → 'items[0]')\n * - Otherwise, concatenates with dot separator (e.g., 'user' + 'name' → 'user.name')\n *\n * @param prefix - The property path to prepend\n * @param suffix - The property path to append\n * @returns The combined property path\n *\n * @example\n * ```typescript\n * combinePropertyPaths('user', '') // 'user'\n * combinePropertyPaths('user', 'name') // 'user.name'\n * combinePropertyPaths('items', '[0]') // 'items[0]'\n * combinePropertyPaths('[0]', 'name') // '[0].name'\n * ```\n */\nexport function combinePropertyPaths(prefix: string, suffix: string): string {\n if (suffix === '') {\n return prefix;\n }\n if (suffix.startsWith('[')) {\n return `${prefix}${suffix}`;\n }\n return `${prefix}.${suffix}`;\n}\n\n/**\n * Creates a ValidationError with a single problem that has an empty property.\n * This is used when reporting errors at the current scope level, where the caller\n * will prepend the appropriate context path.\n *\n * @param message - The error message\n * @returns A ValidationError with a single problem with empty property\n *\n * @example\n * ```typescript\n * throw createValidationError('Expects a string but received number');\n * // Creates: ValidationError([{ property: '', message: 'Expects a string but received number' }])\n * ```\n */\nexport function createValidationError(message: string): ValidationError {\n return new ValidationError([\n new Problem({\n property: '',\n message,\n }),\n ]);\n}\n\n/**\n * Prepends a property path to all problems.\n * Problems with empty property names get the path directly.\n * Problems starting with '[' get the path without a dot separator.\n * Other problems get the path with a dot separator.\n *\n * @param propertyPath - The property path to prepend (e.g., 'user', 'items[0]')\n * @param problems - The array of Problems to process\n * @returns Array of Problems with the property path prepended\n *\n * @example\n * ```typescript\n * const problems = [\n * new Problem({ property: '', message: 'Invalid type' }),\n * new Problem({ property: 'name', message: 'Required' }),\n * new Problem({ property: '[0]', message: 'Invalid element' })\n * ];\n * const result = prependPropertyPath('user', problems);\n * // [\n * // { property: 'user', message: 'Invalid type' },\n * // { property: 'user.name', message: 'Required' },\n * // { property: 'user[0]', message: 'Invalid element' }\n * // ]\n * ```\n */\nexport function prependPropertyPath(\n propertyPath: string,\n problems: Problem[],\n): Problem[] {\n return problems.map((problem) => {\n return new Problem({\n property: combinePropertyPaths(propertyPath, problem.property),\n message: problem.message,\n });\n });\n}\n\n/**\n * Prepends an array index to all problems in a ValidationError.\n * Problems with empty property get `[index]` directly.\n * Problems with non-empty property get `[index].property` format.\n *\n * @param index - The array index to prepend\n * @param error - The ValidationError containing problems to process\n * @returns Array of Problems with the array index prepended\n *\n * @example\n * ```typescript\n * const error = new ValidationError([\n * new Problem({ property: '', message: 'Invalid type' }),\n * new Problem({ property: 'name', message: 'Required' })\n * ]);\n * const problems = prependArrayIndex(0, error);\n * // [\n * // { property: '[0]', message: 'Invalid type' },\n * // { property: '[0].name', message: 'Required' }\n * // ]\n * ```\n */\nexport function prependArrayIndex(\n index: number,\n error: ValidationError,\n): Problem[] {\n return error.problems.map((problem) => {\n return new Problem({\n property: combinePropertyPaths(`[${index}]`, problem.property),\n message: problem.message,\n });\n });\n}\n"],"names":["Problem","ValidationError","combinePropertyPaths","prefix","suffix","startsWith","createValidationError","message","property","prependPropertyPath","propertyPath","problems","map","problem","prependArrayIndex","index","error"],"mappings":"AAAA,SAASA,OAAO,QAAQ,eAAe;AACvC,SAASC,eAAe,QAAQ,wBAAwB;AAExD;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASC,qBAAqBC,MAAc,EAAEC,MAAc;IACjE,IAAIA,WAAW,IAAI;QACjB,OAAOD;IACT;IACA,IAAIC,OAAOC,UAAU,CAAC,MAAM;QAC1B,OAAO,GAAGF,SAASC,QAAQ;IAC7B;IACA,OAAO,GAAGD,OAAO,CAAC,EAAEC,QAAQ;AAC9B;AAEA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASE,sBAAsBC,OAAe;IACnD,OAAO,IAAIN,gBAAgB;QACzB,IAAID,QAAQ;YACVQ,UAAU;YACVD;QACF;KACD;AACH;AAEA;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASE,oBACdC,YAAoB,EACpBC,QAAmB;IAEnB,OAAOA,SAASC,GAAG,CAAC,CAACC;QACnB,OAAO,IAAIb,QAAQ;YACjBQ,UAAUN,qBAAqBQ,cAAcG,QAAQL,QAAQ;YAC7DD,SAASM,QAAQN,OAAO;QAC1B;IACF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,SAASO,kBACdC,KAAa,EACbC,KAAsB;IAEtB,OAAOA,MAAML,QAAQ,CAACC,GAAG,CAAC,CAACC;QACzB,OAAO,IAAIb,QAAQ;YACjBQ,UAAUN,qBAAqB,CAAC,CAAC,EAAEa,MAAM,CAAC,CAAC,EAAEF,QAAQL,QAAQ;YAC7DD,SAASM,QAAQN,OAAO;QAC1B;IACF;AACF"}
@@ -1,5 +1,12 @@
1
1
  import type { PropertyOptions, PropertyValidator } from './types.js';
2
2
  import type { z } from 'zod';
3
+ /**
4
+ * Creates property options for a Zod schema property
5
+ * Used internally by ZodProperty decorator and EntityProps.Zod helper
6
+ */
7
+ export declare function zodPropertyOptions<T = any>(schema: z.ZodTypeAny, options?: Omit<PropertyOptions<T, any>, 'type' | 'deserialize' | 'serialize' | 'passthrough' | 'validators'> & {
8
+ validators?: PropertyValidator<T>[];
9
+ }): PropertyOptions<T, any>;
3
10
  /**
4
11
  * Helper decorator for Zod schema properties.
5
12
  * Validates values using a Zod schema during deserialization.
@@ -1 +1 @@
1
- {"version":3,"file":"zod-property.d.ts","sourceRoot":"","sources":["../../src/lib/zod-property.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGrE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6B7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,wBAAgB,WAAW,CAAC,CAAC,GAAG,GAAG,EACjC,MAAM,EAAE,CAAC,CAAC,UAAU,EACpB,OAAO,CAAC,EAAE,IAAI,CACZ,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,EACvB,MAAM,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,YAAY,CACpE,GAAG;IACF,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;CACrC,GACA,iBAAiB,CAkBnB"}
1
+ {"version":3,"file":"zod-property.d.ts","sourceRoot":"","sources":["../../src/lib/zod-property.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGrE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6B7B;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,GAAG,EACxC,MAAM,EAAE,CAAC,CAAC,UAAU,EACpB,OAAO,CAAC,EAAE,IAAI,CACZ,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,EACvB,MAAM,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,YAAY,CACpE,GAAG;IACF,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;CACrC,GACA,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,CAkBzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,wBAAgB,WAAW,CAAC,CAAC,GAAG,GAAG,EACjC,MAAM,EAAE,CAAC,CAAC,UAAU,EACpB,OAAO,CAAC,EAAE,IAAI,CACZ,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,EACvB,MAAM,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,GAAG,YAAY,CACpE,GAAG;IACF,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;CACrC,GACA,iBAAiB,CAEnB"}
@@ -24,6 +24,27 @@ import { ValidationError } from './validation-error.js';
24
24
  });
25
25
  });
26
26
  }
27
+ /**
28
+ * Creates property options for a Zod schema property
29
+ * Used internally by ZodProperty decorator and EntityProps.Zod helper
30
+ */ export function zodPropertyOptions(schema, options) {
31
+ return {
32
+ ...options,
33
+ default: options?.default,
34
+ type: ()=>Object,
35
+ serialize: (value)=>value,
36
+ deserialize: (value)=>{
37
+ const result = schema.safeParse(value);
38
+ if (result.success) {
39
+ return result.data;
40
+ } else {
41
+ const problems = zodIssuesToProblems(result.error.issues);
42
+ throw new ValidationError(problems);
43
+ }
44
+ },
45
+ validators: options?.validators
46
+ };
47
+ }
27
48
  /**
28
49
  * Helper decorator for Zod schema properties.
29
50
  * Validates values using a Zod schema during deserialization.
@@ -54,22 +75,7 @@ import { ValidationError } from './validation-error.js';
54
75
  * ```
55
76
  */ // TODO: fix type inference
56
77
  export function ZodProperty(schema, options) {
57
- return Property({
58
- ...options,
59
- default: options?.default,
60
- type: ()=>Object,
61
- serialize: (value)=>value,
62
- deserialize: (value)=>{
63
- const result = schema.safeParse(value);
64
- if (result.success) {
65
- return result.data;
66
- } else {
67
- const problems = zodIssuesToProblems(result.error.issues);
68
- throw new ValidationError(problems);
69
- }
70
- },
71
- validators: options?.validators
72
- });
78
+ return Property(zodPropertyOptions(schema, options));
73
79
  }
74
80
 
75
81
  //# sourceMappingURL=zod-property.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/zod-property.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Property } from './property.js';\nimport type { PropertyOptions, PropertyValidator } from './types.js';\nimport { Problem } from './problem.js';\nimport { ValidationError } from './validation-error.js';\nimport type { z } from 'zod';\n\n/**\n * Converts Zod issues to Problem array\n * @param issues - Zod validation issues\n * @returns Array of Problems with proper property paths\n */\nfunction zodIssuesToProblems(issues: z.core.$ZodIssue[]): Problem[] {\n return issues.map((issue: any) => {\n const path = issue.path || [];\n\n let propertyPath = '';\n for (const segment of path) {\n if (typeof segment === 'number') {\n propertyPath += `[${segment}]`;\n } else if (propertyPath === '') {\n propertyPath = segment;\n } else {\n propertyPath += `.${segment}`;\n }\n }\n\n return new Problem({\n property: propertyPath,\n message: issue.message || 'Validation failed',\n });\n });\n}\n\n/**\n * Helper decorator for Zod schema properties.\n * Validates values using a Zod schema during deserialization.\n * Validation failures throw ValidationError (hard errors).\n *\n * When validation succeeds, applies any Zod transformations to the value.\n *\n * @param schema - The Zod schema to validate against\n * @param options - Additional property options (optional, array, etc.)\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const UserSchema = z.object({\n * name: z.string().min(3),\n * age: z.number().int().min(0)\n * });\n *\n * @Entity()\n * class User {\n * @ZodProperty(UserSchema)\n * data!: z.infer<typeof UserSchema>;\n *\n * @ZodProperty(z.string().email(), { optional: true })\n * email?: string;\n * }\n * ```\n */\n// TODO: fix type inference\nexport function ZodProperty<T = any>(\n schema: z.ZodTypeAny,\n options?: Omit<\n PropertyOptions<T, any>,\n 'type' | 'deserialize' | 'serialize' | 'passthrough' | 'validators'\n > & {\n validators?: PropertyValidator<T>[];\n },\n): PropertyDecorator {\n return Property({\n ...options,\n default: options?.default as any,\n type: () => Object,\n serialize: (value: any) => value,\n deserialize: (value: unknown): any => {\n const result = schema.safeParse(value);\n\n if (result.success) {\n return result.data as T;\n } else {\n const problems = zodIssuesToProblems(result.error.issues);\n throw new ValidationError(problems);\n }\n },\n validators: options?.validators as any,\n });\n}\n"],"names":["Property","Problem","ValidationError","zodIssuesToProblems","issues","map","issue","path","propertyPath","segment","property","message","ZodProperty","schema","options","default","type","Object","serialize","value","deserialize","result","safeParse","success","data","problems","error","validators"],"mappings":"AAAA,qDAAqD,GACrD,SAASA,QAAQ,QAAQ,gBAAgB;AAEzC,SAASC,OAAO,QAAQ,eAAe;AACvC,SAASC,eAAe,QAAQ,wBAAwB;AAGxD;;;;CAIC,GACD,SAASC,oBAAoBC,MAA0B;IACrD,OAAOA,OAAOC,GAAG,CAAC,CAACC;QACjB,MAAMC,OAAOD,MAAMC,IAAI,IAAI,EAAE;QAE7B,IAAIC,eAAe;QACnB,KAAK,MAAMC,WAAWF,KAAM;YAC1B,IAAI,OAAOE,YAAY,UAAU;gBAC/BD,gBAAgB,CAAC,CAAC,EAAEC,QAAQ,CAAC,CAAC;YAChC,OAAO,IAAID,iBAAiB,IAAI;gBAC9BA,eAAeC;YACjB,OAAO;gBACLD,gBAAgB,CAAC,CAAC,EAAEC,SAAS;YAC/B;QACF;QAEA,OAAO,IAAIR,QAAQ;YACjBS,UAAUF;YACVG,SAASL,MAAMK,OAAO,IAAI;QAC5B;IACF;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BC,GACD,2BAA2B;AAC3B,OAAO,SAASC,YACdC,MAAoB,EACpBC,OAKC;IAED,OAAOd,SAAS;QACd,GAAGc,OAAO;QACVC,SAASD,SAASC;QAClBC,MAAM,IAAMC;QACZC,WAAW,CAACC,QAAeA;QAC3BC,aAAa,CAACD;YACZ,MAAME,SAASR,OAAOS,SAAS,CAACH;YAEhC,IAAIE,OAAOE,OAAO,EAAE;gBAClB,OAAOF,OAAOG,IAAI;YACpB,OAAO;gBACL,MAAMC,WAAWtB,oBAAoBkB,OAAOK,KAAK,CAACtB,MAAM;gBACxD,MAAM,IAAIF,gBAAgBuB;YAC5B;QACF;QACAE,YAAYb,SAASa;IACvB;AACF"}
1
+ {"version":3,"sources":["../../src/lib/zod-property.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { Property } from './property.js';\nimport type { PropertyOptions, PropertyValidator } from './types.js';\nimport { Problem } from './problem.js';\nimport { ValidationError } from './validation-error.js';\nimport type { z } from 'zod';\n\n/**\n * Converts Zod issues to Problem array\n * @param issues - Zod validation issues\n * @returns Array of Problems with proper property paths\n */\nfunction zodIssuesToProblems(issues: z.core.$ZodIssue[]): Problem[] {\n return issues.map((issue: any) => {\n const path = issue.path || [];\n\n let propertyPath = '';\n for (const segment of path) {\n if (typeof segment === 'number') {\n propertyPath += `[${segment}]`;\n } else if (propertyPath === '') {\n propertyPath = segment;\n } else {\n propertyPath += `.${segment}`;\n }\n }\n\n return new Problem({\n property: propertyPath,\n message: issue.message || 'Validation failed',\n });\n });\n}\n\n/**\n * Creates property options for a Zod schema property\n * Used internally by ZodProperty decorator and EntityProps.Zod helper\n */\nexport function zodPropertyOptions<T = any>(\n schema: z.ZodTypeAny,\n options?: Omit<\n PropertyOptions<T, any>,\n 'type' | 'deserialize' | 'serialize' | 'passthrough' | 'validators'\n > & {\n validators?: PropertyValidator<T>[];\n },\n): PropertyOptions<T, any> {\n return {\n ...options,\n default: options?.default as any,\n type: () => Object,\n serialize: (value: any) => value,\n deserialize: (value: unknown): any => {\n const result = schema.safeParse(value);\n\n if (result.success) {\n return result.data as T;\n } else {\n const problems = zodIssuesToProblems(result.error.issues);\n throw new ValidationError(problems);\n }\n },\n validators: options?.validators as any,\n };\n}\n\n/**\n * Helper decorator for Zod schema properties.\n * Validates values using a Zod schema during deserialization.\n * Validation failures throw ValidationError (hard errors).\n *\n * When validation succeeds, applies any Zod transformations to the value.\n *\n * @param schema - The Zod schema to validate against\n * @param options - Additional property options (optional, array, etc.)\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * const UserSchema = z.object({\n * name: z.string().min(3),\n * age: z.number().int().min(0)\n * });\n *\n * @Entity()\n * class User {\n * @ZodProperty(UserSchema)\n * data!: z.infer<typeof UserSchema>;\n *\n * @ZodProperty(z.string().email(), { optional: true })\n * email?: string;\n * }\n * ```\n */\n// TODO: fix type inference\nexport function ZodProperty<T = any>(\n schema: z.ZodTypeAny,\n options?: Omit<\n PropertyOptions<T, any>,\n 'type' | 'deserialize' | 'serialize' | 'passthrough' | 'validators'\n > & {\n validators?: PropertyValidator<T>[];\n },\n): PropertyDecorator {\n return Property(zodPropertyOptions(schema, options));\n}\n"],"names":["Property","Problem","ValidationError","zodIssuesToProblems","issues","map","issue","path","propertyPath","segment","property","message","zodPropertyOptions","schema","options","default","type","Object","serialize","value","deserialize","result","safeParse","success","data","problems","error","validators","ZodProperty"],"mappings":"AAAA,qDAAqD,GACrD,SAASA,QAAQ,QAAQ,gBAAgB;AAEzC,SAASC,OAAO,QAAQ,eAAe;AACvC,SAASC,eAAe,QAAQ,wBAAwB;AAGxD;;;;CAIC,GACD,SAASC,oBAAoBC,MAA0B;IACrD,OAAOA,OAAOC,GAAG,CAAC,CAACC;QACjB,MAAMC,OAAOD,MAAMC,IAAI,IAAI,EAAE;QAE7B,IAAIC,eAAe;QACnB,KAAK,MAAMC,WAAWF,KAAM;YAC1B,IAAI,OAAOE,YAAY,UAAU;gBAC/BD,gBAAgB,CAAC,CAAC,EAAEC,QAAQ,CAAC,CAAC;YAChC,OAAO,IAAID,iBAAiB,IAAI;gBAC9BA,eAAeC;YACjB,OAAO;gBACLD,gBAAgB,CAAC,CAAC,EAAEC,SAAS;YAC/B;QACF;QAEA,OAAO,IAAIR,QAAQ;YACjBS,UAAUF;YACVG,SAASL,MAAMK,OAAO,IAAI;QAC5B;IACF;AACF;AAEA;;;CAGC,GACD,OAAO,SAASC,mBACdC,MAAoB,EACpBC,OAKC;IAED,OAAO;QACL,GAAGA,OAAO;QACVC,SAASD,SAASC;QAClBC,MAAM,IAAMC;QACZC,WAAW,CAACC,QAAeA;QAC3BC,aAAa,CAACD;YACZ,MAAME,SAASR,OAAOS,SAAS,CAACH;YAEhC,IAAIE,OAAOE,OAAO,EAAE;gBAClB,OAAOF,OAAOG,IAAI;YACpB,OAAO;gBACL,MAAMC,WAAWtB,oBAAoBkB,OAAOK,KAAK,CAACtB,MAAM;gBACxD,MAAM,IAAIF,gBAAgBuB;YAC5B;QACF;QACAE,YAAYb,SAASa;IACvB;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BC,GACD,2BAA2B;AAC3B,OAAO,SAASC,YACdf,MAAoB,EACpBC,OAKC;IAED,OAAOd,SAASY,mBAAmBC,QAAQC;AAC7C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rtpaulino/entity",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",