@wildo-ai/zod-decorators 1.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/dist/esm/__mocks__/mime.d.ts +12 -0
- package/dist/esm/__mocks__/mime.d.ts.map +1 -0
- package/dist/esm/__mocks__/mime.js +75 -0
- package/dist/esm/__mocks__/mime.js.map +1 -0
- package/dist/esm/commons.d.ts +26 -0
- package/dist/esm/commons.d.ts.map +1 -0
- package/dist/esm/commons.js +41 -0
- package/dist/esm/commons.js.map +1 -0
- package/dist/esm/currencies.shared.schemas.d.ts +208 -0
- package/dist/esm/currencies.shared.schemas.d.ts.map +1 -0
- package/dist/esm/currencies.shared.schemas.js +228 -0
- package/dist/esm/currencies.shared.schemas.js.map +1 -0
- package/dist/esm/files/agent-file-formats.d.ts +99 -0
- package/dist/esm/files/agent-file-formats.d.ts.map +1 -0
- package/dist/esm/files/agent-file-formats.js +163 -0
- package/dist/esm/files/agent-file-formats.js.map +1 -0
- package/dist/esm/files/extension-nature-map.d.ts +12 -0
- package/dist/esm/files/extension-nature-map.d.ts.map +1 -0
- package/dist/esm/files/extension-nature-map.js +63 -0
- package/dist/esm/files/extension-nature-map.js.map +1 -0
- package/dist/esm/files/file-extensions.enum.d.ts +58 -0
- package/dist/esm/files/file-extensions.enum.d.ts.map +1 -0
- package/dist/esm/files/file-extensions.enum.js +65 -0
- package/dist/esm/files/file-extensions.enum.js.map +1 -0
- package/dist/esm/files/mime-registry.d.ts +72 -0
- package/dist/esm/files/mime-registry.d.ts.map +1 -0
- package/dist/esm/files/mime-registry.js +174 -0
- package/dist/esm/files/mime-registry.js.map +1 -0
- package/dist/esm/files/unified-registry.d.ts +112 -0
- package/dist/esm/files/unified-registry.d.ts.map +1 -0
- package/dist/esm/files/unified-registry.js +190 -0
- package/dist/esm/files/unified-registry.js.map +1 -0
- package/dist/esm/index.d.ts +29 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +36 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/testing/decorated-test-schemas.d.ts +27 -0
- package/dist/esm/testing/decorated-test-schemas.d.ts.map +1 -0
- package/dist/esm/testing/decorated-test-schemas.js +26 -0
- package/dist/esm/testing/decorated-test-schemas.js.map +1 -0
- package/dist/esm/testing.d.ts +6 -0
- package/dist/esm/testing.d.ts.map +1 -0
- package/dist/esm/testing.js +6 -0
- package/dist/esm/testing.js.map +1 -0
- package/dist/esm/zod-bigdecimal.d.ts +193 -0
- package/dist/esm/zod-bigdecimal.d.ts.map +1 -0
- package/dist/esm/zod-bigdecimal.js +274 -0
- package/dist/esm/zod-bigdecimal.js.map +1 -0
- package/dist/esm/zod-code.d.ts +95 -0
- package/dist/esm/zod-code.d.ts.map +1 -0
- package/dist/esm/zod-code.js +160 -0
- package/dist/esm/zod-code.js.map +1 -0
- package/dist/esm/zod-color.d.ts +8 -0
- package/dist/esm/zod-color.d.ts.map +1 -0
- package/dist/esm/zod-color.js +88 -0
- package/dist/esm/zod-color.js.map +1 -0
- package/dist/esm/zod-decorators.types.d.ts +2207 -0
- package/dist/esm/zod-decorators.types.d.ts.map +1 -0
- package/dist/esm/zod-decorators.types.js +771 -0
- package/dist/esm/zod-decorators.types.js.map +1 -0
- package/dist/esm/zod-duration.d.ts +128 -0
- package/dist/esm/zod-duration.d.ts.map +1 -0
- package/dist/esm/zod-duration.js +174 -0
- package/dist/esm/zod-duration.js.map +1 -0
- package/dist/esm/zod-file.d.ts +219 -0
- package/dist/esm/zod-file.d.ts.map +1 -0
- package/dist/esm/zod-file.js +469 -0
- package/dist/esm/zod-file.js.map +1 -0
- package/dist/esm/zod-money.d.ts +223 -0
- package/dist/esm/zod-money.d.ts.map +1 -0
- package/dist/esm/zod-money.js +293 -0
- package/dist/esm/zod-money.js.map +1 -0
- package/dist/esm/zod-phone.d.ts +75 -0
- package/dist/esm/zod-phone.d.ts.map +1 -0
- package/dist/esm/zod-phone.js +116 -0
- package/dist/esm/zod-phone.js.map +1 -0
- package/dist/esm/zod-range.d.ts +87 -0
- package/dist/esm/zod-range.d.ts.map +1 -0
- package/dist/esm/zod-range.js +138 -0
- package/dist/esm/zod-range.js.map +1 -0
- package/dist/esm/zod-utils.shared.d.ts +783 -0
- package/dist/esm/zod-utils.shared.d.ts.map +1 -0
- package/dist/esm/zod-utils.shared.js +2647 -0
- package/dist/esm/zod-utils.shared.js.map +1 -0
- package/dist/esm/zod-versioned.d.ts +150 -0
- package/dist/esm/zod-versioned.d.ts.map +1 -0
- package/dist/esm/zod-versioned.js +172 -0
- package/dist/esm/zod-versioned.js.map +1 -0
- package/dist/esm/zod.module-override.d.ts +413 -0
- package/dist/esm/zod.module-override.d.ts.map +1 -0
- package/dist/esm/zod.module-override.js +1093 -0
- package/dist/esm/zod.module-override.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,1093 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { SCHEMA_METADATA, ZodDecorator } from './zod-decorators.types.js';
|
|
3
|
+
const ApplyableTypeAllTypes = ["ZodString", "ZodNumber", "ZodBigInt", "ZodBoolean", "ZodDate", "ZodEnum", "ZodOptional", "ZodArray", "ZodObject"];
|
|
4
|
+
const ApplyableTypeAllPrimitiveTypes = ["ZodString", "ZodNumber", "ZodBigInt", "ZodBoolean", "ZodDate", "ZodEnum", "ZodOptional"];
|
|
5
|
+
const ApplyableTypeAllArrayTypes = ["ZodArray"];
|
|
6
|
+
const ApplyableTypeAllObjectTypes = ["ZodObject", "ZodRecord", "ZodMap"];
|
|
7
|
+
/**
|
|
8
|
+
* List of Zod methods that return new instances and need wrapping
|
|
9
|
+
*/
|
|
10
|
+
const ZOD_INSTANCE_METHODS_TO_WRAP = [
|
|
11
|
+
'min', 'max', 'length', 'email', 'url', 'uuid', 'nanoid', 'cuid', 'cuid2', 'ulid',
|
|
12
|
+
'regex', 'includes', 'startsWith', 'endsWith', 'datetime', 'date', 'time', 'duration',
|
|
13
|
+
'ip', 'base64', 'trim', 'toLowerCase', 'toUpperCase', 'jwt', 'emoji',
|
|
14
|
+
'optional', 'nullable', 'nullish', 'array', 'or', 'and', 'transform', 'default',
|
|
15
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine',
|
|
16
|
+
'int', 'positive', 'negative', 'nonnegative', 'nonpositive', 'multipleOf', 'finite', 'safe', 'step',
|
|
17
|
+
'nonempty',
|
|
18
|
+
// Object/record methods that return new schema instances (Zod v4)
|
|
19
|
+
'extend', 'merge', 'pick', 'omit', 'partial', 'deepPartial', 'required',
|
|
20
|
+
'strict', 'passthrough', 'strip', 'catchall',
|
|
21
|
+
// Misc helpers that return new schema instances
|
|
22
|
+
'meta', 'prefault'
|
|
23
|
+
];
|
|
24
|
+
// Types that support field-level decorators (hidden, notEditable, sortable, showWhen, draft, etc.): primitives + object roots + arrays
|
|
25
|
+
const ApplyableTypeFormField = [...ApplyableTypeAllPrimitiveTypes, "ZodObject", "ZodArray"];
|
|
26
|
+
export const ZodDecorator_ApplyableType = {
|
|
27
|
+
[ZodDecorator.IS_DB_INDEXED]: [...ApplyableTypeAllPrimitiveTypes, "ZodObject"],
|
|
28
|
+
[ZodDecorator.IS_FOREIGN_KEY]: ["ZodString"],
|
|
29
|
+
[ZodDecorator.IS_HIDDEN]: ApplyableTypeFormField,
|
|
30
|
+
[ZodDecorator.IS_NOT_EDITABLE]: ApplyableTypeFormField,
|
|
31
|
+
// New decorators - apply to all types since they are schema-level metadata
|
|
32
|
+
[ZodDecorator.IS_SUMMARY_FIELD]: ApplyableTypeAllTypes,
|
|
33
|
+
[ZodDecorator.IS_BACKEND_ONLY]: ApplyableTypeAllTypes,
|
|
34
|
+
[ZodDecorator.IS_VIRTUAL]: ApplyableTypeAllTypes,
|
|
35
|
+
[ZodDecorator.IS_DISCRIMINATOR]: ApplyableTypeAllPrimitiveTypes, // Only primitives can be discriminators
|
|
36
|
+
[ZodDecorator.EXCLUDE_FROM_CREATE]: ApplyableTypeAllTypes,
|
|
37
|
+
[ZodDecorator.EXCLUDE_FROM_UPDATE]: ApplyableTypeAllTypes,
|
|
38
|
+
// Database constraint decorators - only strings and numbers can be unique (identifiers, codes, etc.)
|
|
39
|
+
// ZodOptional is included to support chaining like z.string().isUnique().optional()
|
|
40
|
+
[ZodDecorator.IS_UNIQUE]: ['ZodString', 'ZodNumber', 'ZodOptional'],
|
|
41
|
+
// Primary key is only for strings (MongoDB _id is always a string or ObjectId)
|
|
42
|
+
[ZodDecorator.IS_PRIMARY_KEY]: ['ZodString'],
|
|
43
|
+
// TTL (Time To Live) - only for Date fields (MongoDB TTL indexes work on Date fields)
|
|
44
|
+
[ZodDecorator.TTL]: ['ZodDate', 'ZodOptional'],
|
|
45
|
+
// String edit mode convenience decorators - only for strings
|
|
46
|
+
[ZodDecorator.IS_PASSWORD]: ['ZodString', 'ZodOptional'],
|
|
47
|
+
[ZodDecorator.IS_OTP]: ['ZodString', 'ZodOptional'],
|
|
48
|
+
[ZodDecorator.IS_COLOR]: ['ZodString', 'ZodOptional'],
|
|
49
|
+
[ZodDecorator.IS_DRAFT_RELAXED]: ApplyableTypeFormField,
|
|
50
|
+
// FIX-P5-H1: Conditional visibility decorator - apply to all form field types
|
|
51
|
+
[ZodDecorator.SHOW_WHEN]: ApplyableTypeFormField,
|
|
52
|
+
// System enum decorator - marks enum fields as using a system-level enum for labelling
|
|
53
|
+
[ZodDecorator.SYSTEM_ENUM]: ['ZodEnum', 'ZodOptional'],
|
|
54
|
+
// Ephemeral field decorator - only for strings (API keys, tokens, etc.)
|
|
55
|
+
[ZodDecorator.IS_EPHEMERAL]: ['ZodString', 'ZodOptional'],
|
|
56
|
+
// CRDT field decorator — all field types can be CRDT-enabled
|
|
57
|
+
[ZodDecorator.IS_CRDT]: ApplyableTypeAllTypes,
|
|
58
|
+
// Unified {primitive}UI decorators — each constrained to its applicable schema types
|
|
59
|
+
[ZodDecorator.BOOLEAN_UI]: ['ZodBoolean', 'ZodOptional'],
|
|
60
|
+
[ZodDecorator.STRING_UI]: ['ZodString', 'ZodOptional'],
|
|
61
|
+
[ZodDecorator.NUMBER_UI]: ['ZodNumber', 'ZodOptional'],
|
|
62
|
+
[ZodDecorator.ENUM_UI]: ['ZodEnum', 'ZodOptional'],
|
|
63
|
+
[ZodDecorator.DATE_UI]: ['ZodDate', 'ZodOptional'],
|
|
64
|
+
[ZodDecorator.DATETIME_UI]: ['ZodDate', 'ZodOptional'],
|
|
65
|
+
[ZodDecorator.TIME_UI]: ['ZodString', 'ZodOptional'],
|
|
66
|
+
[ZodDecorator.MONEY_UI]: ['ZodObject', 'ZodOptional'],
|
|
67
|
+
[ZodDecorator.CODE_UI]: ['ZodObject', 'ZodOptional'],
|
|
68
|
+
[ZodDecorator.FILE_UI]: ['ZodObject', 'ZodOptional'],
|
|
69
|
+
[ZodDecorator.DURATION_UI]: ['ZodObject', 'ZodOptional'],
|
|
70
|
+
[ZodDecorator.PHONE_UI]: ['ZodString', 'ZodOptional'],
|
|
71
|
+
[ZodDecorator.BIGDECIMAL_UI]: ['ZodString', 'ZodOptional'],
|
|
72
|
+
[ZodDecorator.FOREIGN_KEY_UI]: ['ZodString', 'ZodOptional'],
|
|
73
|
+
[ZodDecorator.ARRAY_UI]: ['ZodArray', 'ZodOptional'],
|
|
74
|
+
[ZodDecorator.OBJECT_UI]: [...ApplyableTypeAllObjectTypes, 'ZodOptional'],
|
|
75
|
+
};
|
|
76
|
+
export const ZodDecorator_FunctionType = {
|
|
77
|
+
isDBIndexed: function () { return addDecorators(this, [ZodDecorator.IS_DB_INDEXED]); },
|
|
78
|
+
isForeignKey: function (params) { return params ? addDecorators(this, [{ ref: ZodDecorator.IS_FOREIGN_KEY, params }]) : addDecorators(this, [ZodDecorator.IS_FOREIGN_KEY]); },
|
|
79
|
+
isHidden: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_HIDDEN, params }]); },
|
|
80
|
+
isNotEditable: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_NOT_EDITABLE, params }]); },
|
|
81
|
+
isSortable: function (params) { return addDecorators(this, [{ ref: ZodDecorator.ARRAY_UI, params: { edit: { isSortable: true, ...params } } }]); },
|
|
82
|
+
// String edit mode convenience composites — structural marker + STRING_UI side effect
|
|
83
|
+
[ZodDecorator.IS_PASSWORD]: function () { return addDecorators(this, [{ ref: ZodDecorator.IS_PASSWORD, params: undefined }, { ref: ZodDecorator.STRING_UI, params: { edit: { editMode: 'password' } } }]); },
|
|
84
|
+
[ZodDecorator.IS_OTP]: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_OTP, params }, { ref: ZodDecorator.STRING_UI, params: { edit: { editMode: 'otp' } } }]); },
|
|
85
|
+
[ZodDecorator.IS_COLOR]: function () { return addDecorators(this, [{ ref: ZodDecorator.IS_COLOR, params: undefined }, { ref: ZodDecorator.STRING_UI, params: { edit: { editMode: 'color' } } }]); },
|
|
86
|
+
// New decorators for resource derived objects rationalization
|
|
87
|
+
isSummaryField: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_SUMMARY_FIELD, params }]); },
|
|
88
|
+
isBackendOnly: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_BACKEND_ONLY, params }]); },
|
|
89
|
+
isVirtual: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_VIRTUAL, params }]); },
|
|
90
|
+
isDiscriminator: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_DISCRIMINATOR, params }]); },
|
|
91
|
+
excludeFromCreate: function () { return addDecorators(this, [ZodDecorator.EXCLUDE_FROM_CREATE]); },
|
|
92
|
+
excludeFromUpdate: function () { return addDecorators(this, [ZodDecorator.EXCLUDE_FROM_UPDATE]); },
|
|
93
|
+
// Database constraint decorators
|
|
94
|
+
isUnique: function (params) { return addDecorators(this, [{ ref: ZodDecorator.IS_UNIQUE, params }]); },
|
|
95
|
+
// isPrimaryKey is a composite decorator: implies excludeFromCreate + isHidden + isUnique(sparse:false) + isDBIndexed
|
|
96
|
+
isPrimaryKey: function () {
|
|
97
|
+
return addDecorators(this, [
|
|
98
|
+
ZodDecorator.IS_PRIMARY_KEY,
|
|
99
|
+
ZodDecorator.EXCLUDE_FROM_CREATE,
|
|
100
|
+
ZodDecorator.IS_HIDDEN,
|
|
101
|
+
ZodDecorator.IS_DB_INDEXED,
|
|
102
|
+
{ ref: ZodDecorator.IS_UNIQUE, params: { scope: 'global', sparse: false } },
|
|
103
|
+
]);
|
|
104
|
+
},
|
|
105
|
+
// TTL (Time To Live) - for automatic document expiration in MongoDB
|
|
106
|
+
ttl: function (params) { return addDecorators(this, [{ ref: ZodDecorator.TTL, params }]); },
|
|
107
|
+
isDraftRelaxed: function () { return addDecorators(this, [ZodDecorator.IS_DRAFT_RELAXED]); },
|
|
108
|
+
// FIX-P5-H1: Conditional visibility decorator
|
|
109
|
+
showWhen: function (params) { return addDecorators(this, [{ ref: ZodDecorator.SHOW_WHEN, params }]); },
|
|
110
|
+
// System enum decorator - marks an enum field as using a system-level enum for i18n labelling
|
|
111
|
+
systemEnum: function (name) { return addDecorators(this, [{ ref: ZodDecorator.SYSTEM_ENUM, params: name }]); },
|
|
112
|
+
// Ephemeral field decorator — composite: marks response-only transient data + sets secret display mode + prevents editing
|
|
113
|
+
isEphemeral: function () { return addDecorators(this, [{ ref: ZodDecorator.IS_EPHEMERAL, params: undefined }, { ref: ZodDecorator.STRING_UI, params: { display: { displayMode: 'secret' } } }, { ref: ZodDecorator.IS_NOT_EDITABLE, params: undefined }]); },
|
|
114
|
+
// CRDT field decorator — boolean marker for future field-level LWW merge
|
|
115
|
+
isCRDT: function () { return addDecorators(this, [ZodDecorator.IS_CRDT]); },
|
|
116
|
+
// Unified {primitive}UI decorators — new API
|
|
117
|
+
booleanUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.BOOLEAN_UI, params }]); },
|
|
118
|
+
stringUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.STRING_UI, params }]); },
|
|
119
|
+
numberUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.NUMBER_UI, params }]); },
|
|
120
|
+
enumUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.ENUM_UI, params }]); },
|
|
121
|
+
dateUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.DATE_UI, params }]); },
|
|
122
|
+
dateTimeUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.DATETIME_UI, params }]); },
|
|
123
|
+
timeUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.TIME_UI, params }]); },
|
|
124
|
+
moneyUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.MONEY_UI, params }]); },
|
|
125
|
+
codeUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.CODE_UI, params }]); },
|
|
126
|
+
fileUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.FILE_UI, params }]); },
|
|
127
|
+
durationUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.DURATION_UI, params }]); },
|
|
128
|
+
phoneUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.PHONE_UI, params }]); },
|
|
129
|
+
bigDecimalUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.BIGDECIMAL_UI, params }]); },
|
|
130
|
+
foreignKeyUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.FOREIGN_KEY_UI, params }]); },
|
|
131
|
+
arrayUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.ARRAY_UI, params }]); },
|
|
132
|
+
objectUI: function (params) { return addDecorators(this, [{ ref: ZodDecorator.OBJECT_UI, params }]); },
|
|
133
|
+
};
|
|
134
|
+
// =============================================================================
|
|
135
|
+
// MAIN ADD UTILITIES
|
|
136
|
+
// =============================================================================
|
|
137
|
+
export function ZodDecorator_FunctionAddDecorators(decorators) {
|
|
138
|
+
return addDecorators(this, decorators);
|
|
139
|
+
}
|
|
140
|
+
export const defaultZodDecoSchemaProperties = {
|
|
141
|
+
enumerable: false,
|
|
142
|
+
writable: false,
|
|
143
|
+
};
|
|
144
|
+
export function addDecorators(schema, decoratorInputs) {
|
|
145
|
+
// Lazy initialization: ensure decorators are loaded when first used
|
|
146
|
+
ensureZodDecoratorsLoaded(z);
|
|
147
|
+
let resultSchema = schema;
|
|
148
|
+
// Apply each decorator in sequence
|
|
149
|
+
for (const decoratorInput of decoratorInputs) {
|
|
150
|
+
resultSchema = (typeof decoratorInput === 'string')
|
|
151
|
+
? applySingleDecorator(resultSchema, decoratorInput)
|
|
152
|
+
: applySingleDecorator(resultSchema, decoratorInput.ref, decoratorInput.params);
|
|
153
|
+
}
|
|
154
|
+
// Add all chainable methods to the final schema
|
|
155
|
+
return addChainableMethods(resultSchema);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Deep-clone a value, preserving function references (React components in `IconLike`).
|
|
159
|
+
* - Primitives & functions: returned by reference
|
|
160
|
+
* - Arrays: cloned recursively
|
|
161
|
+
* - Date, RegExp: cloned via constructors
|
|
162
|
+
* - Plain objects: cloned recursively with independent property copies
|
|
163
|
+
* - Shared sub-objects: cloned once and reused (WeakMap tracks original→clone)
|
|
164
|
+
* - Circular references: safely resolved via the shared-reference map
|
|
165
|
+
*/
|
|
166
|
+
function deepCloneValue(value, seen) {
|
|
167
|
+
if (value === null || value === undefined || typeof value !== 'object') {
|
|
168
|
+
return value;
|
|
169
|
+
}
|
|
170
|
+
if (!seen)
|
|
171
|
+
seen = new WeakMap();
|
|
172
|
+
const cached = seen.get(value);
|
|
173
|
+
if (cached !== undefined)
|
|
174
|
+
return cached;
|
|
175
|
+
if (value instanceof Date) {
|
|
176
|
+
const cloned = new Date(value.getTime());
|
|
177
|
+
seen.set(value, cloned);
|
|
178
|
+
return cloned;
|
|
179
|
+
}
|
|
180
|
+
if (value instanceof RegExp) {
|
|
181
|
+
const cloned = new RegExp(value.source, value.flags);
|
|
182
|
+
seen.set(value, cloned);
|
|
183
|
+
return cloned;
|
|
184
|
+
}
|
|
185
|
+
if (Array.isArray(value)) {
|
|
186
|
+
const cloned = [];
|
|
187
|
+
seen.set(value, cloned);
|
|
188
|
+
for (const v of value)
|
|
189
|
+
cloned.push(deepCloneValue(v, seen));
|
|
190
|
+
return cloned;
|
|
191
|
+
}
|
|
192
|
+
const result = {};
|
|
193
|
+
seen.set(value, result);
|
|
194
|
+
for (const [k, v] of Object.entries(value)) {
|
|
195
|
+
result[k] = deepCloneValue(v, seen);
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Clone a Zod schema with an independent deep-copy of its decorator metadata.
|
|
201
|
+
*
|
|
202
|
+
* Creates a new schema instance that shares the same Zod validation behavior
|
|
203
|
+
* but has independent decorator metadata. Mutations (`.enumUI()`,
|
|
204
|
+
* `.isDBIndexed()`, etc.) on the clone do not affect the original, and vice versa.
|
|
205
|
+
*
|
|
206
|
+
* Function references (React components in `IconLike`) are preserved by reference;
|
|
207
|
+
* all other metadata values (objects, arrays, primitives) are deep-cloned.
|
|
208
|
+
*
|
|
209
|
+
* **Use case:** reusable leaf schemas (enums, strings, numbers) with shared visual
|
|
210
|
+
* config but independent field-level decorators per resource.
|
|
211
|
+
*
|
|
212
|
+
* **Scope limitations:** designed for leaf schemas, NOT for compound types:
|
|
213
|
+
* - **`z.object()`:** field schemas inside the shape remain shared references —
|
|
214
|
+
* mutating a field's decorators on the clone affects the original.
|
|
215
|
+
* - **Wrapper types** (`.optional()`, `.nullable()`, `.array()`, `.pipe()`):
|
|
216
|
+
* the inner schema remains shared. Clone the unwrapped schema first, then wrap.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* // Master enum with common visual config
|
|
221
|
+
* const PriorityEnum = z.enum(Priority)
|
|
222
|
+
* .systemEnum('Priority')
|
|
223
|
+
* .enumUI({ values: { low: { color: 'secondary' }, high: { color: 'destructive' } } });
|
|
224
|
+
*
|
|
225
|
+
* // Each resource gets an independent clone
|
|
226
|
+
* const TodosSchema = z.object({
|
|
227
|
+
* priority: z_clone(PriorityEnum).isDBIndexed().isSummaryField(),
|
|
228
|
+
* });
|
|
229
|
+
* const TasksSchema = z.object({
|
|
230
|
+
* priority: z_clone(PriorityEnum).isNotEditable(),
|
|
231
|
+
* });
|
|
232
|
+
* // TodosSchema.priority has isDBIndexed + isSummaryField — TasksSchema.priority does not
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export function z_clone(schema) {
|
|
236
|
+
const clone = Object.assign(Object.create(Object.getPrototypeOf(schema)), schema);
|
|
237
|
+
const metadata = schema[SCHEMA_METADATA];
|
|
238
|
+
if (metadata) {
|
|
239
|
+
clone[SCHEMA_METADATA] = deepCloneValue(metadata);
|
|
240
|
+
}
|
|
241
|
+
return addChainableMethods(clone);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Deep-merge ENUM_UI decorator params with special handling for the `values` key.
|
|
245
|
+
*
|
|
246
|
+
* - `values` is deep-merged: per-enum-value configs merge individually
|
|
247
|
+
* (e.g., adding an icon to a value that already has a color preserves both).
|
|
248
|
+
* - All other top-level keys are shallow-replaced (e.g., `displayMode` is atomic).
|
|
249
|
+
* - Additive only — you cannot remove a value entry set by a prior call.
|
|
250
|
+
* To visually "clear" a property, set it to `undefined` explicitly.
|
|
251
|
+
*/
|
|
252
|
+
function deepMergeDisplayParams(existing, incoming) {
|
|
253
|
+
const result = { ...existing };
|
|
254
|
+
for (const [key, value] of Object.entries(incoming)) {
|
|
255
|
+
if (key === 'values' &&
|
|
256
|
+
value && typeof value === 'object' &&
|
|
257
|
+
result[key] && typeof result[key] === 'object') {
|
|
258
|
+
const existingValues = result[key];
|
|
259
|
+
const incomingValues = value;
|
|
260
|
+
result[key] = { ...existingValues };
|
|
261
|
+
for (const [enumValue, enumConfig] of Object.entries(incomingValues)) {
|
|
262
|
+
result[key][enumValue] = existingValues[enumValue]
|
|
263
|
+
? { ...existingValues[enumValue], ...enumConfig }
|
|
264
|
+
: enumConfig;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
result[key] = value;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
function applySingleDecorator(schema, decorator, params) {
|
|
274
|
+
// Ensure schema exists before accessing Symbol property
|
|
275
|
+
if (!schema) {
|
|
276
|
+
throw new Error('Invalid schema provided to applySingleDecorator');
|
|
277
|
+
}
|
|
278
|
+
// Get existing metadata from Symbol property with proper type casting
|
|
279
|
+
const currentMetadata = schema[SCHEMA_METADATA] || {};
|
|
280
|
+
// Generic updater function resolution: if params is a function, call it with
|
|
281
|
+
// the current metadata value and use the result. Works for any decorator.
|
|
282
|
+
let resolvedFromUpdater = false;
|
|
283
|
+
if (typeof params === 'function') {
|
|
284
|
+
const existing = currentMetadata[decorator];
|
|
285
|
+
const currentValue = (existing && typeof existing === 'object') ? existing : undefined;
|
|
286
|
+
params = params(currentValue);
|
|
287
|
+
resolvedFromUpdater = true;
|
|
288
|
+
}
|
|
289
|
+
// After function resolution, params is a concrete value (never a function).
|
|
290
|
+
// TypeScript can't narrow this from control flow. Use `rp<D>()` for typed
|
|
291
|
+
// access in cases that read properties; use `p` for simple assignments.
|
|
292
|
+
const p = params;
|
|
293
|
+
function rp() {
|
|
294
|
+
return params;
|
|
295
|
+
}
|
|
296
|
+
// Handle each decorator explicitly.
|
|
297
|
+
// `p` is used instead of `params` for assignments — it's the same value
|
|
298
|
+
// but typed as `any` since TypeScript can't narrow the function union away
|
|
299
|
+
// after the generic resolution above.
|
|
300
|
+
switch (decorator) {
|
|
301
|
+
case ZodDecorator.IS_DB_INDEXED:
|
|
302
|
+
currentMetadata[ZodDecorator.IS_DB_INDEXED] = true;
|
|
303
|
+
break;
|
|
304
|
+
case ZodDecorator.IS_FOREIGN_KEY:
|
|
305
|
+
currentMetadata[ZodDecorator.IS_FOREIGN_KEY] = p ?? true;
|
|
306
|
+
break;
|
|
307
|
+
case ZodDecorator.IS_HIDDEN:
|
|
308
|
+
currentMetadata[ZodDecorator.IS_HIDDEN] = p ?? true;
|
|
309
|
+
break;
|
|
310
|
+
case ZodDecorator.IS_NOT_EDITABLE:
|
|
311
|
+
currentMetadata[ZodDecorator.IS_NOT_EDITABLE] = p ?? true;
|
|
312
|
+
break;
|
|
313
|
+
case ZodDecorator.IS_SUMMARY_FIELD:
|
|
314
|
+
currentMetadata[ZodDecorator.IS_SUMMARY_FIELD] = p ?? true;
|
|
315
|
+
break;
|
|
316
|
+
case ZodDecorator.IS_BACKEND_ONLY:
|
|
317
|
+
currentMetadata[ZodDecorator.IS_BACKEND_ONLY] = p ?? true;
|
|
318
|
+
break;
|
|
319
|
+
case ZodDecorator.IS_VIRTUAL: {
|
|
320
|
+
const vp = rp();
|
|
321
|
+
if (!vp?.calculate) {
|
|
322
|
+
throw new Error('isVirtual decorator requires a calculate function');
|
|
323
|
+
}
|
|
324
|
+
currentMetadata[ZodDecorator.IS_VIRTUAL] = vp;
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
case ZodDecorator.IS_DISCRIMINATOR:
|
|
328
|
+
currentMetadata[ZodDecorator.IS_DISCRIMINATOR] = p ?? true;
|
|
329
|
+
break;
|
|
330
|
+
case ZodDecorator.EXCLUDE_FROM_CREATE:
|
|
331
|
+
currentMetadata[ZodDecorator.EXCLUDE_FROM_CREATE] = true;
|
|
332
|
+
break;
|
|
333
|
+
case ZodDecorator.EXCLUDE_FROM_UPDATE:
|
|
334
|
+
currentMetadata[ZodDecorator.EXCLUDE_FROM_UPDATE] = true;
|
|
335
|
+
break;
|
|
336
|
+
case ZodDecorator.IS_UNIQUE:
|
|
337
|
+
currentMetadata[ZodDecorator.IS_UNIQUE] = p ?? true;
|
|
338
|
+
break;
|
|
339
|
+
case ZodDecorator.IS_PRIMARY_KEY:
|
|
340
|
+
currentMetadata[ZodDecorator.IS_PRIMARY_KEY] = true;
|
|
341
|
+
break;
|
|
342
|
+
case ZodDecorator.TTL:
|
|
343
|
+
currentMetadata[ZodDecorator.TTL] = p;
|
|
344
|
+
break;
|
|
345
|
+
case ZodDecorator.IS_PASSWORD:
|
|
346
|
+
currentMetadata[ZodDecorator.IS_PASSWORD] = true;
|
|
347
|
+
break;
|
|
348
|
+
case ZodDecorator.IS_OTP:
|
|
349
|
+
currentMetadata[ZodDecorator.IS_OTP] = p ?? true;
|
|
350
|
+
break;
|
|
351
|
+
case ZodDecorator.IS_COLOR:
|
|
352
|
+
currentMetadata[ZodDecorator.IS_COLOR] = true;
|
|
353
|
+
break;
|
|
354
|
+
case ZodDecorator.IS_DRAFT_RELAXED:
|
|
355
|
+
currentMetadata[ZodDecorator.IS_DRAFT_RELAXED] = true;
|
|
356
|
+
break;
|
|
357
|
+
case ZodDecorator.SHOW_WHEN:
|
|
358
|
+
currentMetadata[ZodDecorator.SHOW_WHEN] = p;
|
|
359
|
+
break;
|
|
360
|
+
case ZodDecorator.SYSTEM_ENUM:
|
|
361
|
+
currentMetadata[ZodDecorator.SYSTEM_ENUM] = p;
|
|
362
|
+
break;
|
|
363
|
+
case ZodDecorator.IS_EPHEMERAL:
|
|
364
|
+
currentMetadata[ZodDecorator.IS_EPHEMERAL] = true;
|
|
365
|
+
break;
|
|
366
|
+
case ZodDecorator.IS_CRDT:
|
|
367
|
+
currentMetadata[ZodDecorator.IS_CRDT] = true;
|
|
368
|
+
break;
|
|
369
|
+
// Unified {primitive}UI decorators — ENUM_UI uses deep merge for per-value configs, all others use shallow replace
|
|
370
|
+
case ZodDecorator.ENUM_UI: {
|
|
371
|
+
if (!p) {
|
|
372
|
+
currentMetadata[decorator] = true;
|
|
373
|
+
}
|
|
374
|
+
else if (resolvedFromUpdater) {
|
|
375
|
+
currentMetadata[decorator] = p;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
const existing = currentMetadata[decorator];
|
|
379
|
+
currentMetadata[decorator] =
|
|
380
|
+
(existing && typeof existing === 'object')
|
|
381
|
+
? deepMergeDisplayParams(existing, p)
|
|
382
|
+
: p;
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
case ZodDecorator.BOOLEAN_UI:
|
|
387
|
+
case ZodDecorator.STRING_UI:
|
|
388
|
+
case ZodDecorator.NUMBER_UI:
|
|
389
|
+
case ZodDecorator.DATE_UI:
|
|
390
|
+
case ZodDecorator.DATETIME_UI:
|
|
391
|
+
case ZodDecorator.TIME_UI:
|
|
392
|
+
case ZodDecorator.MONEY_UI:
|
|
393
|
+
case ZodDecorator.CODE_UI:
|
|
394
|
+
case ZodDecorator.FILE_UI:
|
|
395
|
+
case ZodDecorator.DURATION_UI:
|
|
396
|
+
case ZodDecorator.PHONE_UI:
|
|
397
|
+
case ZodDecorator.BIGDECIMAL_UI:
|
|
398
|
+
case ZodDecorator.FOREIGN_KEY_UI:
|
|
399
|
+
case ZodDecorator.ARRAY_UI:
|
|
400
|
+
case ZodDecorator.OBJECT_UI: {
|
|
401
|
+
if (!p) {
|
|
402
|
+
currentMetadata[decorator] = true;
|
|
403
|
+
}
|
|
404
|
+
else if (resolvedFromUpdater) {
|
|
405
|
+
currentMetadata[decorator] = p;
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
currentMetadata[decorator] = p;
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Store updated metadata using Symbol
|
|
414
|
+
schema[SCHEMA_METADATA] = currentMetadata;
|
|
415
|
+
return addChainableMethods(schema);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Methods that transform object fields and need special handling for field-level metadata.
|
|
419
|
+
* These methods create new field wrappers and we need to copy field-level metadata.
|
|
420
|
+
*/
|
|
421
|
+
const OBJECT_FIELD_TRANSFORM_METHODS_SET = new Set(['partial', 'deepPartial', 'required']);
|
|
422
|
+
/**
|
|
423
|
+
* Wraps an instance method to preserve SCHEMA_METADATA when it returns a new instance.
|
|
424
|
+
* In Zod v4, methods are on instances not prototypes, so we wrap them individually.
|
|
425
|
+
* Also wraps the result's methods to ensure metadata persists through the entire chain.
|
|
426
|
+
*/
|
|
427
|
+
function wrapInstanceMethod(instance, methodName) {
|
|
428
|
+
const originalMethod = instance[methodName];
|
|
429
|
+
if (typeof originalMethod !== 'function')
|
|
430
|
+
return;
|
|
431
|
+
// Skip if already wrapped
|
|
432
|
+
if (originalMethod.__metadataWrapped)
|
|
433
|
+
return;
|
|
434
|
+
// Use special wrapper for field-transform methods on ZodObject
|
|
435
|
+
const isObjectFieldTransform = OBJECT_FIELD_TRANSFORM_METHODS_SET.has(methodName) &&
|
|
436
|
+
instance.constructor?.name === 'ZodObject';
|
|
437
|
+
const wrappedMethod = function (...args) {
|
|
438
|
+
// Get original shape before transformation (for field-transform methods)
|
|
439
|
+
const originalShape = isObjectFieldTransform ? this.shape : null;
|
|
440
|
+
const originalSchemaMetadata = this[SCHEMA_METADATA];
|
|
441
|
+
const result = originalMethod.apply(this, args);
|
|
442
|
+
// Copy metadata from original to result if it exists and result is different
|
|
443
|
+
if (result && result !== this) {
|
|
444
|
+
// Preserve all decorator metadata (including rangeConfig and currencyConfig)
|
|
445
|
+
if (originalSchemaMetadata && Object.keys(originalSchemaMetadata).length > 0) {
|
|
446
|
+
result[SCHEMA_METADATA] = { ...originalSchemaMetadata };
|
|
447
|
+
}
|
|
448
|
+
// For field-transform methods, copy field-level metadata to new wrapped fields
|
|
449
|
+
if (isObjectFieldTransform && originalShape && result.shape) {
|
|
450
|
+
copyFieldMetadata(originalShape, result.shape);
|
|
451
|
+
}
|
|
452
|
+
// Also wrap the result's methods so metadata persists through subsequent chains
|
|
453
|
+
wrapInstanceMethodsForMetadata(result);
|
|
454
|
+
}
|
|
455
|
+
return result;
|
|
456
|
+
};
|
|
457
|
+
// Mark as wrapped to avoid double-wrapping
|
|
458
|
+
wrappedMethod.__metadataWrapped = true;
|
|
459
|
+
instance[methodName] = wrappedMethod;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Copy field-level metadata from original shape to new shape.
|
|
463
|
+
* Used for methods like .partial() that wrap fields in new types.
|
|
464
|
+
*/
|
|
465
|
+
function copyFieldMetadata(originalShape, newShape) {
|
|
466
|
+
for (const fieldName of Object.keys(originalShape)) {
|
|
467
|
+
const originalField = originalShape[fieldName];
|
|
468
|
+
const newField = newShape[fieldName];
|
|
469
|
+
if (originalField && newField && originalField !== newField) {
|
|
470
|
+
const fieldMetadata = originalField[SCHEMA_METADATA];
|
|
471
|
+
if (fieldMetadata && Object.keys(fieldMetadata).length > 0) {
|
|
472
|
+
newField[SCHEMA_METADATA] = deepCloneValue(fieldMetadata);
|
|
473
|
+
// Also wrap the new field's methods for future chaining
|
|
474
|
+
wrapInstanceMethodsForMetadata(newField);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Wrap only the instance methods (not decorator methods) for metadata preservation.
|
|
481
|
+
* Used when copying metadata to a new schema instance.
|
|
482
|
+
*/
|
|
483
|
+
function wrapInstanceMethodsForMetadata(schema) {
|
|
484
|
+
for (const methodName of ZOD_INSTANCE_METHODS_TO_WRAP) {
|
|
485
|
+
if (typeof schema[methodName] === 'function') {
|
|
486
|
+
wrapInstanceMethod(schema, methodName);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
export function addChainableMethods(schema) {
|
|
491
|
+
const decoratedSchema = schema;
|
|
492
|
+
// CRITICAL: Wrap instance methods that return new instances to preserve metadata
|
|
493
|
+
// In Zod v4, methods are on instances not prototypes
|
|
494
|
+
for (const methodName of ZOD_INSTANCE_METHODS_TO_WRAP) {
|
|
495
|
+
if (typeof decoratedSchema[methodName] === 'function') {
|
|
496
|
+
wrapInstanceMethod(decoratedSchema, methodName);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
const ctorName = decoratedSchema?.constructor?.name;
|
|
500
|
+
for (const decorator of Object.values(ZodDecorator)) {
|
|
501
|
+
const applyable = ZodDecorator_ApplyableType[decorator];
|
|
502
|
+
if (!applyable || !ctorName)
|
|
503
|
+
continue;
|
|
504
|
+
if (!applyable.includes(ctorName))
|
|
505
|
+
continue;
|
|
506
|
+
if (Object.prototype.hasOwnProperty.call(decoratedSchema, decorator))
|
|
507
|
+
continue;
|
|
508
|
+
// Use the actual function from ZodDecorator_FunctionType to preserve composite
|
|
509
|
+
// decorator behavior (e.g., isPrimaryKey sets 5 decorators, isPassword sets 2).
|
|
510
|
+
// Falling back to a generic wrapper should never happen if the table is complete.
|
|
511
|
+
const registeredFn = ZodDecorator_FunctionType[decorator];
|
|
512
|
+
const value = registeredFn
|
|
513
|
+
? (...args) => registeredFn.apply(decoratedSchema, args)
|
|
514
|
+
: (params) => addDecorators(decoratedSchema, [{ ref: decorator, params }]);
|
|
515
|
+
Object.defineProperty(decoratedSchema, decorator, { value, ...defaultZodDecoSchemaProperties });
|
|
516
|
+
}
|
|
517
|
+
if (!decoratedSchema.hasOwnProperty('addDecorators')) {
|
|
518
|
+
Object.defineProperty(decoratedSchema, 'addDecorators', {
|
|
519
|
+
value: (decorators) => addDecorators(decoratedSchema, decorators),
|
|
520
|
+
...defaultZodDecoSchemaProperties
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
return decoratedSchema;
|
|
524
|
+
}
|
|
525
|
+
// =============================================================================
|
|
526
|
+
// ADD DECORATORS
|
|
527
|
+
// =============================================================================
|
|
528
|
+
// -----------------------------------------------------------------------------
|
|
529
|
+
// DB related decorators
|
|
530
|
+
// -----------------------------------------------------------------------------
|
|
531
|
+
export function addDBIndexed(schema) {
|
|
532
|
+
// Lazy initialization: ensure decorators are loaded
|
|
533
|
+
ensureZodDecoratorsLoaded(z);
|
|
534
|
+
return addDecorators(schema, [ZodDecorator.IS_DB_INDEXED]);
|
|
535
|
+
}
|
|
536
|
+
export function addForeignKey(schema) {
|
|
537
|
+
// Lazy initialization: ensure decorators are loaded
|
|
538
|
+
ensureZodDecoratorsLoaded(z);
|
|
539
|
+
return addDecorators(schema, [ZodDecorator.IS_FOREIGN_KEY]);
|
|
540
|
+
}
|
|
541
|
+
// -----------------------------------------------------------------------------
|
|
542
|
+
// FORMS
|
|
543
|
+
// -----------------------------------------------------------------------------
|
|
544
|
+
// addFormInput, addFormTextarea, addFormSelect, etc. — removed.
|
|
545
|
+
// Component selection moved to {primitive}UI({ edit: { component } }).
|
|
546
|
+
export function addHidden(schema, params) {
|
|
547
|
+
ensureZodDecoratorsLoaded(z);
|
|
548
|
+
return addDecorators(schema, [{ ref: ZodDecorator.IS_HIDDEN, params }]);
|
|
549
|
+
}
|
|
550
|
+
export function addNotEditable(schema, params) {
|
|
551
|
+
ensureZodDecoratorsLoaded(z);
|
|
552
|
+
return addDecorators(schema, [{ ref: ZodDecorator.IS_NOT_EDITABLE, params }]);
|
|
553
|
+
}
|
|
554
|
+
export function addSortable(schema, params) {
|
|
555
|
+
ensureZodDecoratorsLoaded(z);
|
|
556
|
+
return addDecorators(schema, [{ ref: ZodDecorator.ARRAY_UI, params: { edit: { isSortable: true, ...params } } }]);
|
|
557
|
+
}
|
|
558
|
+
// -----------------------------------------------------------------------------
|
|
559
|
+
// NEW DECORATOR ADD FUNCTIONS
|
|
560
|
+
// -----------------------------------------------------------------------------
|
|
561
|
+
export function addSummaryField(schema, params) {
|
|
562
|
+
ensureZodDecoratorsLoaded(z);
|
|
563
|
+
return addDecorators(schema, [{ ref: ZodDecorator.IS_SUMMARY_FIELD, params }]);
|
|
564
|
+
}
|
|
565
|
+
export function addBackendOnly(schema, params) {
|
|
566
|
+
ensureZodDecoratorsLoaded(z);
|
|
567
|
+
return addDecorators(schema, [{ ref: ZodDecorator.IS_BACKEND_ONLY, params }]);
|
|
568
|
+
}
|
|
569
|
+
export function addVirtual(schema, params) {
|
|
570
|
+
ensureZodDecoratorsLoaded(z);
|
|
571
|
+
return addDecorators(schema, [{ ref: ZodDecorator.IS_VIRTUAL, params }]);
|
|
572
|
+
}
|
|
573
|
+
export function addDiscriminator(schema, params) {
|
|
574
|
+
ensureZodDecoratorsLoaded(z);
|
|
575
|
+
return addDecorators(schema, [{ ref: ZodDecorator.IS_DISCRIMINATOR, params }]);
|
|
576
|
+
}
|
|
577
|
+
export function addExcludeFromCreate(schema) {
|
|
578
|
+
ensureZodDecoratorsLoaded(z);
|
|
579
|
+
return addDecorators(schema, [ZodDecorator.EXCLUDE_FROM_CREATE]);
|
|
580
|
+
}
|
|
581
|
+
export function addExcludeFromUpdate(schema) {
|
|
582
|
+
ensureZodDecoratorsLoaded(z);
|
|
583
|
+
return addDecorators(schema, [ZodDecorator.EXCLUDE_FROM_UPDATE]);
|
|
584
|
+
}
|
|
585
|
+
export function addUnique(schema, params) {
|
|
586
|
+
ensureZodDecoratorsLoaded(z);
|
|
587
|
+
return addDecorators(schema, [{ ref: ZodDecorator.IS_UNIQUE, params }]);
|
|
588
|
+
}
|
|
589
|
+
// -----------------------------------------------------------------------------
|
|
590
|
+
// DECORATOR DETECTION HELPER FUNCTIONS
|
|
591
|
+
// -----------------------------------------------------------------------------
|
|
592
|
+
/**
|
|
593
|
+
* Recursively get metadata from a schema, traversing through wrapper types.
|
|
594
|
+
*
|
|
595
|
+
* Zod 4's methods like `partial()`, `required()`, `optional()`, `nullable()`, `default()`
|
|
596
|
+
* wrap the original schema in new types. The original decorated schema becomes the `innerType`.
|
|
597
|
+
* This function traverses through these wrappers to find the original metadata.
|
|
598
|
+
*
|
|
599
|
+
* Traversal order:
|
|
600
|
+
* 1. Check if metadata exists directly on the schema
|
|
601
|
+
* 2. If not found, check `_zod.def.innerType` recursively
|
|
602
|
+
* (ZodOptional, ZodNullable, ZodDefault, ZodNonOptional, ZodReadonly, ZodCatch)
|
|
603
|
+
* 3. For ZodEffects (transforms), check `_zod.def.schema`
|
|
604
|
+
* 4. For ZodArray, check `_zod.def.element`
|
|
605
|
+
* 5. For ZodPipe (from .refine()/.superRefine()), check `_zod.def.in`
|
|
606
|
+
*/
|
|
607
|
+
export function getMetadataRecursive(schema) {
|
|
608
|
+
if (!schema)
|
|
609
|
+
return undefined;
|
|
610
|
+
// First check directly on this schema
|
|
611
|
+
const directMetadata = schema[SCHEMA_METADATA];
|
|
612
|
+
if (directMetadata && Object.keys(directMetadata).length > 0) {
|
|
613
|
+
return directMetadata;
|
|
614
|
+
}
|
|
615
|
+
// Access the internal Zod definition
|
|
616
|
+
const def = schema._zod?.def;
|
|
617
|
+
if (!def)
|
|
618
|
+
return undefined;
|
|
619
|
+
// Traverse through wrapper types that use innerType:
|
|
620
|
+
// ZodOptional, ZodNullable, ZodDefault, ZodNonOptional, ZodReadonly, ZodCatch
|
|
621
|
+
if (def.innerType) {
|
|
622
|
+
return getMetadataRecursive(def.innerType);
|
|
623
|
+
}
|
|
624
|
+
// ZodEffects (transforms) have a schema property
|
|
625
|
+
if (def.schema) {
|
|
626
|
+
return getMetadataRecursive(def.schema);
|
|
627
|
+
}
|
|
628
|
+
// ZodArray has element
|
|
629
|
+
if (def.element) {
|
|
630
|
+
return getMetadataRecursive(def.element);
|
|
631
|
+
}
|
|
632
|
+
// ZodPipe (from .refine()/.superRefine()) has 'in' for the input schema
|
|
633
|
+
if (def.in) {
|
|
634
|
+
return getMetadataRecursive(def.in);
|
|
635
|
+
}
|
|
636
|
+
return undefined;
|
|
637
|
+
}
|
|
638
|
+
// Reader functions (is*, get*Params, etc.) are consolidated in zod-utils.shared.ts.
|
|
639
|
+
// Only writers (add*), getMetadataRecursive, and addPrimaryKey remain here.
|
|
640
|
+
/**
|
|
641
|
+
* Apply isPrimaryKey decorator to a schema (composite: excludeFromCreate + isHidden + isUnique + isDBIndexed).
|
|
642
|
+
*/
|
|
643
|
+
export function addPrimaryKey(schema) {
|
|
644
|
+
return addDecorators(schema, [
|
|
645
|
+
ZodDecorator.IS_PRIMARY_KEY,
|
|
646
|
+
ZodDecorator.EXCLUDE_FROM_CREATE,
|
|
647
|
+
ZodDecorator.IS_HIDDEN,
|
|
648
|
+
ZodDecorator.IS_DB_INDEXED,
|
|
649
|
+
{ ref: ZodDecorator.IS_UNIQUE, params: { scope: 'global', sparse: false } },
|
|
650
|
+
]);
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Helper to create a metadata-preserving wrapper for Zod methods that return new instances.
|
|
654
|
+
* In Zod v4, methods like .min(), .max(), etc. return NEW schema instances,
|
|
655
|
+
* which would lose our SCHEMA_METADATA Symbol. This wrapper copies the metadata.
|
|
656
|
+
*/
|
|
657
|
+
function wrapMethodToPreserveMetadata(originalMethod, methodName) {
|
|
658
|
+
return function (...args) {
|
|
659
|
+
const originalMetadata = this[SCHEMA_METADATA];
|
|
660
|
+
const result = originalMethod.apply(this, args);
|
|
661
|
+
// Copy all metadata from original (this) to result if it exists
|
|
662
|
+
// This includes rangeConfig and currencyConfig which are now part of SCHEMA_METADATA
|
|
663
|
+
if (originalMetadata && Object.keys(originalMetadata).length > 0 && result && result !== this) {
|
|
664
|
+
result[SCHEMA_METADATA] = { ...originalMetadata };
|
|
665
|
+
}
|
|
666
|
+
return result;
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Patches all methods on a prototype that might return new instances,
|
|
671
|
+
* ensuring SCHEMA_METADATA is preserved through method chains.
|
|
672
|
+
*/
|
|
673
|
+
function patchPrototypeMethodsForMetadataPreservation(prototype, methodNames) {
|
|
674
|
+
for (const methodName of methodNames) {
|
|
675
|
+
const originalMethod = prototype[methodName];
|
|
676
|
+
if (typeof originalMethod === 'function') {
|
|
677
|
+
prototype[methodName] = wrapMethodToPreserveMetadata(originalMethod, methodName);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Ensures Zod decorators are applied to a specific Zod instance.
|
|
683
|
+
* This is critical when multiple Zod instances exist in the dependency tree.
|
|
684
|
+
* Call this function early in your application startup to ensure decorators work.
|
|
685
|
+
*
|
|
686
|
+
* In Zod v4, many methods return new schema instances (for immutability).
|
|
687
|
+
* We patch these methods to copy SCHEMA_METADATA so decorators survive method chains.
|
|
688
|
+
*
|
|
689
|
+
* @param zodInstance - The Zod instance to apply decorators to (defaults to the imported 'z')
|
|
690
|
+
* @returns true if decorators were already present, false if they were just applied
|
|
691
|
+
*/
|
|
692
|
+
export function ensureZodDecoratorsLoaded(zodInstance = z) {
|
|
693
|
+
// @ts-ignore - Dynamic property access for decorator checking
|
|
694
|
+
const zi = zodInstance;
|
|
695
|
+
// Check if decorators are already applied
|
|
696
|
+
const alreadyLoaded = typeof zodInstance.ZodString.prototype[ZodDecorator.IS_DB_INDEXED] === 'function';
|
|
697
|
+
if (alreadyLoaded) {
|
|
698
|
+
return zodInstance;
|
|
699
|
+
}
|
|
700
|
+
// =============================================================================
|
|
701
|
+
// STEP 1: Patch Zod methods to preserve SCHEMA_METADATA through method chains
|
|
702
|
+
// =============================================================================
|
|
703
|
+
// ZodString methods that return new instances in Zod v4
|
|
704
|
+
const zodStringMethodsToWrap = [
|
|
705
|
+
'min', 'max', 'length', 'email', 'url', 'uuid', 'nanoid', 'cuid', 'cuid2', 'ulid',
|
|
706
|
+
'regex', 'includes', 'startsWith', 'endsWith', 'datetime', 'date', 'time', 'duration',
|
|
707
|
+
'ip', 'base64', 'trim', 'toLowerCase', 'toUpperCase', 'jwt', 'emoji',
|
|
708
|
+
'optional', 'nullable', 'nullish', 'array', 'or', 'and', 'transform', 'default',
|
|
709
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
710
|
+
];
|
|
711
|
+
patchPrototypeMethodsForMetadataPreservation(zodInstance.ZodString.prototype, zodStringMethodsToWrap);
|
|
712
|
+
// ZodNumber methods that return new instances
|
|
713
|
+
const zodNumberMethodsToWrap = [
|
|
714
|
+
'min', 'max', 'int', 'positive', 'negative', 'nonnegative', 'nonpositive',
|
|
715
|
+
'multipleOf', 'finite', 'safe', 'step',
|
|
716
|
+
'optional', 'nullable', 'nullish', 'array', 'or', 'and', 'transform', 'default',
|
|
717
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
718
|
+
];
|
|
719
|
+
patchPrototypeMethodsForMetadataPreservation(zodInstance.ZodNumber.prototype, zodNumberMethodsToWrap);
|
|
720
|
+
// ZodDate methods that return new instances
|
|
721
|
+
const zodDateMethodsToWrap = [
|
|
722
|
+
'min', 'max',
|
|
723
|
+
'optional', 'nullable', 'nullish', 'array', 'or', 'and', 'transform', 'default',
|
|
724
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
725
|
+
];
|
|
726
|
+
patchPrototypeMethodsForMetadataPreservation(zodInstance.ZodDate.prototype, zodDateMethodsToWrap);
|
|
727
|
+
// ZodBoolean methods
|
|
728
|
+
const zodBooleanMethodsToWrap = [
|
|
729
|
+
'optional', 'nullable', 'nullish', 'array', 'or', 'and', 'transform', 'default',
|
|
730
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
731
|
+
];
|
|
732
|
+
patchPrototypeMethodsForMetadataPreservation(zodInstance.ZodBoolean.prototype, zodBooleanMethodsToWrap);
|
|
733
|
+
// ZodArray methods
|
|
734
|
+
const zodArrayMethodsToWrap = [
|
|
735
|
+
'min', 'max', 'length', 'nonempty',
|
|
736
|
+
'optional', 'nullable', 'nullish', 'or', 'and', 'transform', 'default',
|
|
737
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
738
|
+
];
|
|
739
|
+
patchPrototypeMethodsForMetadataPreservation(zodInstance.ZodArray.prototype, zodArrayMethodsToWrap);
|
|
740
|
+
// ZodEnum methods
|
|
741
|
+
const zodEnumMethodsToWrap = [
|
|
742
|
+
'optional', 'nullable', 'nullish', 'array', 'or', 'and', 'transform', 'default',
|
|
743
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
744
|
+
];
|
|
745
|
+
patchPrototypeMethodsForMetadataPreservation(zodInstance.ZodEnum.prototype, zodEnumMethodsToWrap);
|
|
746
|
+
// ZodOptional methods
|
|
747
|
+
const zodOptionalMethodsToWrap = [
|
|
748
|
+
'optional', 'nullable', 'nullish', 'array', 'or', 'and', 'transform', 'default',
|
|
749
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
750
|
+
];
|
|
751
|
+
patchPrototypeMethodsForMetadataPreservation(zodInstance.ZodOptional.prototype, zodOptionalMethodsToWrap);
|
|
752
|
+
// =============================================================================
|
|
753
|
+
// STEP 2: Apply decorator methods to Zod prototypes
|
|
754
|
+
// =============================================================================
|
|
755
|
+
// Apply decorators to this Zod instance
|
|
756
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
757
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
758
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
759
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
760
|
+
// New decorators
|
|
761
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
762
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
763
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
764
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_DISCRIMINATOR] = ZodDecorator_FunctionType[ZodDecorator.IS_DISCRIMINATOR];
|
|
765
|
+
zodInstance.ZodString.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
766
|
+
zodInstance.ZodString.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
767
|
+
// Database constraint decorators
|
|
768
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_UNIQUE] = ZodDecorator_FunctionType[ZodDecorator.IS_UNIQUE];
|
|
769
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_PRIMARY_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_PRIMARY_KEY];
|
|
770
|
+
// String edit mode convenience decorators
|
|
771
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_PASSWORD] = ZodDecorator_FunctionType[ZodDecorator.IS_PASSWORD];
|
|
772
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_OTP] = ZodDecorator_FunctionType[ZodDecorator.IS_OTP];
|
|
773
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_COLOR] = ZodDecorator_FunctionType[ZodDecorator.IS_COLOR];
|
|
774
|
+
// Ephemeral field decorator
|
|
775
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_EPHEMERAL] = ZodDecorator_FunctionType[ZodDecorator.IS_EPHEMERAL];
|
|
776
|
+
// CRDT field decorator
|
|
777
|
+
zodInstance.ZodString.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
778
|
+
// Unified UI decorator
|
|
779
|
+
zodInstance.ZodString.prototype[ZodDecorator.STRING_UI] = ZodDecorator_FunctionType[ZodDecorator.STRING_UI];
|
|
780
|
+
zodInstance.ZodString.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
781
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
782
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
783
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
784
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
785
|
+
// New decorators
|
|
786
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
787
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
788
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
789
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_DISCRIMINATOR] = ZodDecorator_FunctionType[ZodDecorator.IS_DISCRIMINATOR];
|
|
790
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
791
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
792
|
+
// Database constraint decorators
|
|
793
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_UNIQUE] = ZodDecorator_FunctionType[ZodDecorator.IS_UNIQUE];
|
|
794
|
+
// CRDT field decorator
|
|
795
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
796
|
+
// Unified UI decorator
|
|
797
|
+
zodInstance.ZodNumber.prototype[ZodDecorator.NUMBER_UI] = ZodDecorator_FunctionType[ZodDecorator.NUMBER_UI];
|
|
798
|
+
zodInstance.ZodNumber.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
799
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
800
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
801
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
802
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
803
|
+
// New decorators
|
|
804
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
805
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
806
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
807
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
808
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
809
|
+
// CRDT field decorator
|
|
810
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
811
|
+
// Unified UI decorator
|
|
812
|
+
zodInstance.ZodBoolean.prototype[ZodDecorator.BOOLEAN_UI] = ZodDecorator_FunctionType[ZodDecorator.BOOLEAN_UI];
|
|
813
|
+
zodInstance.ZodBoolean.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
814
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
815
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
816
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
817
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
818
|
+
// New decorators
|
|
819
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
820
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
821
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
822
|
+
zodInstance.ZodDate.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
823
|
+
zodInstance.ZodDate.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
824
|
+
// TTL decorator for MongoDB TTL indexes (automatic document expiration)
|
|
825
|
+
zodInstance.ZodDate.prototype[ZodDecorator.TTL] = ZodDecorator_FunctionType[ZodDecorator.TTL];
|
|
826
|
+
// CRDT field decorator
|
|
827
|
+
zodInstance.ZodDate.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
828
|
+
// Unified UI decorator
|
|
829
|
+
zodInstance.ZodDate.prototype[ZodDecorator.DATE_UI] = ZodDecorator_FunctionType[ZodDecorator.DATE_UI];
|
|
830
|
+
zodInstance.ZodDate.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
831
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
832
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
833
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
834
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
835
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.SYSTEM_ENUM] = ZodDecorator_FunctionType[ZodDecorator.SYSTEM_ENUM];
|
|
836
|
+
// New decorators
|
|
837
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
838
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
839
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
840
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_DISCRIMINATOR] = ZodDecorator_FunctionType[ZodDecorator.IS_DISCRIMINATOR];
|
|
841
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
842
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
843
|
+
// Database constraint decorators - optional wrapper types need isUnique for z.string().isUnique().optional() pattern
|
|
844
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_UNIQUE] = ZodDecorator_FunctionType[ZodDecorator.IS_UNIQUE];
|
|
845
|
+
// Ephemeral field decorator
|
|
846
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_EPHEMERAL] = ZodDecorator_FunctionType[ZodDecorator.IS_EPHEMERAL];
|
|
847
|
+
// CRDT field decorator
|
|
848
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
849
|
+
// Unified UI decorators (ZodOptional wraps any primitive)
|
|
850
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.BOOLEAN_UI] = ZodDecorator_FunctionType[ZodDecorator.BOOLEAN_UI];
|
|
851
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.STRING_UI] = ZodDecorator_FunctionType[ZodDecorator.STRING_UI];
|
|
852
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.NUMBER_UI] = ZodDecorator_FunctionType[ZodDecorator.NUMBER_UI];
|
|
853
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.ENUM_UI] = ZodDecorator_FunctionType[ZodDecorator.ENUM_UI];
|
|
854
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.DATE_UI] = ZodDecorator_FunctionType[ZodDecorator.DATE_UI];
|
|
855
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.ARRAY_UI] = ZodDecorator_FunctionType[ZodDecorator.ARRAY_UI];
|
|
856
|
+
zodInstance.ZodOptional.prototype[ZodDecorator.OBJECT_UI] = ZodDecorator_FunctionType[ZodDecorator.OBJECT_UI];
|
|
857
|
+
zodInstance.ZodOptional.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
858
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
859
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
860
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
861
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
862
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.SYSTEM_ENUM] = ZodDecorator_FunctionType[ZodDecorator.SYSTEM_ENUM];
|
|
863
|
+
// New decorators
|
|
864
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
865
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
866
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
867
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_DISCRIMINATOR] = ZodDecorator_FunctionType[ZodDecorator.IS_DISCRIMINATOR];
|
|
868
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
869
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
870
|
+
// CRDT field decorator
|
|
871
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
872
|
+
// Unified UI decorator
|
|
873
|
+
zodInstance.ZodEnum.prototype[ZodDecorator.ENUM_UI] = ZodDecorator_FunctionType[ZodDecorator.ENUM_UI];
|
|
874
|
+
zodInstance.ZodEnum.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
875
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
876
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
877
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
878
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
879
|
+
zodInstance.ZodArray.prototype[ZodDecorator.ARRAY_UI] = ZodDecorator_FunctionType[ZodDecorator.ARRAY_UI];
|
|
880
|
+
zodInstance.ZodArray.prototype.isSortable = ZodDecorator_FunctionType['isSortable'];
|
|
881
|
+
// New decorators
|
|
882
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
883
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
884
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
885
|
+
zodInstance.ZodArray.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
886
|
+
zodInstance.ZodArray.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
887
|
+
// CRDT field decorator
|
|
888
|
+
zodInstance.ZodArray.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
889
|
+
zodInstance.ZodArray.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
890
|
+
// Wrapper types (ZodDefault, ZodNullable) need ALL decorators for chaining
|
|
891
|
+
// e.g. z.date().default(...).excludeFromCreate().isNotEditable().showWhen(...)
|
|
892
|
+
for (const wrapperName of ['ZodDefault', 'ZodNullable']) {
|
|
893
|
+
const wrapperCtor = zi[wrapperName];
|
|
894
|
+
if (wrapperCtor?.prototype) {
|
|
895
|
+
patchPrototypeMethodsForMetadataPreservation(wrapperCtor.prototype, zodOptionalMethodsToWrap);
|
|
896
|
+
for (const [key, fn] of Object.entries(ZodDecorator_FunctionType)) {
|
|
897
|
+
wrapperCtor.prototype[key] = fn;
|
|
898
|
+
}
|
|
899
|
+
wrapperCtor.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
// ZodUnion wrapper type - needs decorators for union fields
|
|
903
|
+
if (zi.ZodUnion?.prototype) {
|
|
904
|
+
patchPrototypeMethodsForMetadataPreservation(zi.ZodUnion.prototype, zodOptionalMethodsToWrap);
|
|
905
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
906
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
907
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
908
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
909
|
+
zi.ZodUnion.prototype[ZodDecorator.SYSTEM_ENUM] = ZodDecorator_FunctionType[ZodDecorator.SYSTEM_ENUM];
|
|
910
|
+
// New decorators
|
|
911
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
912
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
913
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
914
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_DISCRIMINATOR] = ZodDecorator_FunctionType[ZodDecorator.IS_DISCRIMINATOR];
|
|
915
|
+
zi.ZodUnion.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
916
|
+
zi.ZodUnion.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
917
|
+
// CRDT field decorator
|
|
918
|
+
zi.ZodUnion.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
919
|
+
zi.ZodUnion.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
920
|
+
}
|
|
921
|
+
// Object / record decorators
|
|
922
|
+
if (zi.ZodObject?.prototype) {
|
|
923
|
+
zi.ZodObject.prototype[ZodDecorator.OBJECT_UI] = ZodDecorator_FunctionType[ZodDecorator.OBJECT_UI];
|
|
924
|
+
zi.ZodObject.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
925
|
+
zi.ZodObject.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
926
|
+
zi.ZodObject.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
927
|
+
zi.ZodObject.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
928
|
+
zi.ZodObject.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
929
|
+
// CRDT field decorator
|
|
930
|
+
zi.ZodObject.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
931
|
+
zi.ZodObject.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
932
|
+
}
|
|
933
|
+
if (zi.ZodRecord?.prototype) {
|
|
934
|
+
zi.ZodRecord.prototype[ZodDecorator.OBJECT_UI] = ZodDecorator_FunctionType[ZodDecorator.OBJECT_UI];
|
|
935
|
+
// New decorators
|
|
936
|
+
zi.ZodRecord.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
937
|
+
zi.ZodRecord.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
938
|
+
zi.ZodRecord.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
939
|
+
zi.ZodRecord.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
940
|
+
zi.ZodRecord.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
941
|
+
// CRDT field decorator
|
|
942
|
+
zi.ZodRecord.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
943
|
+
zi.ZodRecord.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
944
|
+
}
|
|
945
|
+
// Add support for ZodMap if available
|
|
946
|
+
if (zi.ZodMap?.prototype) {
|
|
947
|
+
patchPrototypeMethodsForMetadataPreservation(zi.ZodMap.prototype, [
|
|
948
|
+
'optional', 'nullable', 'nullish', 'or', 'and', 'transform', 'default',
|
|
949
|
+
'catch', 'describe', 'brand', 'readonly', 'pipe', 'refine', 'superRefine'
|
|
950
|
+
]);
|
|
951
|
+
zi.ZodMap.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
952
|
+
zi.ZodMap.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
953
|
+
zi.ZodMap.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
954
|
+
zi.ZodMap.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
955
|
+
zi.ZodMap.prototype[ZodDecorator.OBJECT_UI] = ZodDecorator_FunctionType[ZodDecorator.OBJECT_UI];
|
|
956
|
+
// New decorators
|
|
957
|
+
zi.ZodMap.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
958
|
+
zi.ZodMap.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
959
|
+
zi.ZodMap.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
960
|
+
zi.ZodMap.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
961
|
+
zi.ZodMap.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
962
|
+
// CRDT field decorator
|
|
963
|
+
zi.ZodMap.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
964
|
+
zi.ZodMap.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
965
|
+
}
|
|
966
|
+
// Helper function to add decorators to Zod string refinement types
|
|
967
|
+
function addDecoratorsToZodStringRefinement(constructorName) {
|
|
968
|
+
const Candidate = zi[constructorName];
|
|
969
|
+
if (Candidate && typeof Candidate === 'object' && 'prototype' in Candidate) {
|
|
970
|
+
const Constructor = Candidate;
|
|
971
|
+
// Patch methods first, then add decorators
|
|
972
|
+
patchPrototypeMethodsForMetadataPreservation(Constructor.prototype, zodStringMethodsToWrap);
|
|
973
|
+
Constructor.prototype[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
974
|
+
Constructor.prototype[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
975
|
+
Constructor.prototype[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
976
|
+
Constructor.prototype[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
977
|
+
// New decorators
|
|
978
|
+
Constructor.prototype[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
979
|
+
Constructor.prototype[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
980
|
+
Constructor.prototype[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
981
|
+
Constructor.prototype[ZodDecorator.IS_DISCRIMINATOR] = ZodDecorator_FunctionType[ZodDecorator.IS_DISCRIMINATOR];
|
|
982
|
+
Constructor.prototype[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
983
|
+
Constructor.prototype[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
984
|
+
// Database constraint decorators - format validators like email/uuid are commonly used as unique identifiers
|
|
985
|
+
Constructor.prototype[ZodDecorator.IS_UNIQUE] = ZodDecorator_FunctionType[ZodDecorator.IS_UNIQUE];
|
|
986
|
+
// Ephemeral field decorator
|
|
987
|
+
Constructor.prototype[ZodDecorator.IS_EPHEMERAL] = ZodDecorator_FunctionType[ZodDecorator.IS_EPHEMERAL];
|
|
988
|
+
// CRDT field decorator
|
|
989
|
+
Constructor.prototype[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
990
|
+
Constructor.prototype.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
// Add decorator support to Zod string refinement types
|
|
994
|
+
addDecoratorsToZodStringRefinement('ZodEmail');
|
|
995
|
+
addDecoratorsToZodStringRefinement('ZodUUID');
|
|
996
|
+
addDecoratorsToZodStringRefinement('ZodURL');
|
|
997
|
+
addDecoratorsToZodStringRefinement('ZodHttpUrl');
|
|
998
|
+
addDecoratorsToZodStringRefinement('ZodHostname');
|
|
999
|
+
addDecoratorsToZodStringRefinement('ZodEmoji');
|
|
1000
|
+
addDecoratorsToZodStringRefinement('ZodBase64');
|
|
1001
|
+
addDecoratorsToZodStringRefinement('ZodBase64Url');
|
|
1002
|
+
addDecoratorsToZodStringRefinement('ZodHex');
|
|
1003
|
+
addDecoratorsToZodStringRefinement('ZodJWT');
|
|
1004
|
+
addDecoratorsToZodStringRefinement('ZodNanoId');
|
|
1005
|
+
addDecoratorsToZodStringRefinement('ZodCuid');
|
|
1006
|
+
addDecoratorsToZodStringRefinement('ZodCuid2');
|
|
1007
|
+
addDecoratorsToZodStringRefinement('ZodULID');
|
|
1008
|
+
addDecoratorsToZodStringRefinement('ZodIPv4');
|
|
1009
|
+
addDecoratorsToZodStringRefinement('ZodIPv6');
|
|
1010
|
+
addDecoratorsToZodStringRefinement('ZodMac');
|
|
1011
|
+
addDecoratorsToZodStringRefinement('ZodCidrV4');
|
|
1012
|
+
addDecoratorsToZodStringRefinement('ZodCidrV6');
|
|
1013
|
+
addDecoratorsToZodStringRefinement('ZodHash');
|
|
1014
|
+
addDecoratorsToZodStringRefinement('ZodISODate');
|
|
1015
|
+
addDecoratorsToZodStringRefinement('ZodISOTime');
|
|
1016
|
+
addDecoratorsToZodStringRefinement('ZodISODatetime');
|
|
1017
|
+
addDecoratorsToZodStringRefinement('ZodISODateTime');
|
|
1018
|
+
addDecoratorsToZodStringRefinement('ZodISODuration');
|
|
1019
|
+
// =============================================================================
|
|
1020
|
+
// STEP 3: Dynamically patch format validator prototypes
|
|
1021
|
+
// In Zod 4, z.email(), z.url() etc. may return schemas whose constructors
|
|
1022
|
+
// aren't exposed on the z namespace. We discover them by creating instances.
|
|
1023
|
+
// =============================================================================
|
|
1024
|
+
const patchedPrototypes = new Set();
|
|
1025
|
+
function patchFormatValidatorPrototype(factoryFn) {
|
|
1026
|
+
try {
|
|
1027
|
+
const schema = factoryFn();
|
|
1028
|
+
const proto = Object.getPrototypeOf(schema);
|
|
1029
|
+
// Skip if already patched or if it's ZodString (already handled)
|
|
1030
|
+
if (!proto || patchedPrototypes.has(proto))
|
|
1031
|
+
return;
|
|
1032
|
+
if (proto === zodInstance.ZodString.prototype)
|
|
1033
|
+
return;
|
|
1034
|
+
// Check if already has decorators
|
|
1035
|
+
if (typeof proto[ZodDecorator.IS_DB_INDEXED] === 'function') {
|
|
1036
|
+
patchedPrototypes.add(proto);
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
// Patch this prototype
|
|
1040
|
+
patchPrototypeMethodsForMetadataPreservation(proto, zodStringMethodsToWrap);
|
|
1041
|
+
proto[ZodDecorator.IS_DB_INDEXED] = ZodDecorator_FunctionType[ZodDecorator.IS_DB_INDEXED];
|
|
1042
|
+
proto[ZodDecorator.IS_FOREIGN_KEY] = ZodDecorator_FunctionType[ZodDecorator.IS_FOREIGN_KEY];
|
|
1043
|
+
proto[ZodDecorator.IS_HIDDEN] = ZodDecorator_FunctionType[ZodDecorator.IS_HIDDEN];
|
|
1044
|
+
proto[ZodDecorator.IS_NOT_EDITABLE] = ZodDecorator_FunctionType[ZodDecorator.IS_NOT_EDITABLE];
|
|
1045
|
+
// New decorators
|
|
1046
|
+
proto[ZodDecorator.IS_SUMMARY_FIELD] = ZodDecorator_FunctionType[ZodDecorator.IS_SUMMARY_FIELD];
|
|
1047
|
+
proto[ZodDecorator.IS_BACKEND_ONLY] = ZodDecorator_FunctionType[ZodDecorator.IS_BACKEND_ONLY];
|
|
1048
|
+
proto[ZodDecorator.IS_VIRTUAL] = ZodDecorator_FunctionType[ZodDecorator.IS_VIRTUAL];
|
|
1049
|
+
proto[ZodDecorator.IS_DISCRIMINATOR] = ZodDecorator_FunctionType[ZodDecorator.IS_DISCRIMINATOR];
|
|
1050
|
+
proto[ZodDecorator.EXCLUDE_FROM_CREATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_CREATE];
|
|
1051
|
+
proto[ZodDecorator.EXCLUDE_FROM_UPDATE] = ZodDecorator_FunctionType[ZodDecorator.EXCLUDE_FROM_UPDATE];
|
|
1052
|
+
// Database constraint decorators - format validators like email/uuid are commonly used as unique identifiers
|
|
1053
|
+
proto[ZodDecorator.IS_UNIQUE] = ZodDecorator_FunctionType[ZodDecorator.IS_UNIQUE];
|
|
1054
|
+
// Format validators like uuid/email/url are still string-backed primitives,
|
|
1055
|
+
// so platform presets must be able to apply string display/edit policies.
|
|
1056
|
+
proto[ZodDecorator.STRING_UI] = ZodDecorator_FunctionType[ZodDecorator.STRING_UI];
|
|
1057
|
+
// Ephemeral field decorator
|
|
1058
|
+
proto[ZodDecorator.IS_EPHEMERAL] = ZodDecorator_FunctionType[ZodDecorator.IS_EPHEMERAL];
|
|
1059
|
+
// CRDT field decorator
|
|
1060
|
+
proto[ZodDecorator.IS_CRDT] = ZodDecorator_FunctionType[ZodDecorator.IS_CRDT];
|
|
1061
|
+
proto.addDecorators = ZodDecorator_FunctionAddDecorators;
|
|
1062
|
+
patchedPrototypes.add(proto);
|
|
1063
|
+
}
|
|
1064
|
+
catch {
|
|
1065
|
+
// Factory function might not exist in this Zod version
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
// Patch all format validators by creating instances
|
|
1069
|
+
patchFormatValidatorPrototype(() => zodInstance.email());
|
|
1070
|
+
patchFormatValidatorPrototype(() => zodInstance.url());
|
|
1071
|
+
patchFormatValidatorPrototype(() => zodInstance.uuid());
|
|
1072
|
+
patchFormatValidatorPrototype(() => zodInstance.cuid());
|
|
1073
|
+
patchFormatValidatorPrototype(() => zodInstance.cuid2());
|
|
1074
|
+
patchFormatValidatorPrototype(() => zodInstance.ulid());
|
|
1075
|
+
patchFormatValidatorPrototype(() => zodInstance.nanoid());
|
|
1076
|
+
patchFormatValidatorPrototype(() => zodInstance.base64());
|
|
1077
|
+
patchFormatValidatorPrototype(() => zodInstance.jwt());
|
|
1078
|
+
patchFormatValidatorPrototype(() => zodInstance.emoji());
|
|
1079
|
+
patchFormatValidatorPrototype(() => zodInstance.ipv4());
|
|
1080
|
+
patchFormatValidatorPrototype(() => zodInstance.ipv6());
|
|
1081
|
+
patchFormatValidatorPrototype(() => zodInstance.cidrv4());
|
|
1082
|
+
patchFormatValidatorPrototype(() => zodInstance.cidrv6());
|
|
1083
|
+
// Patch z.iso.* format validators
|
|
1084
|
+
patchFormatValidatorPrototype(() => zodInstance.iso.datetime());
|
|
1085
|
+
patchFormatValidatorPrototype(() => zodInstance.iso.date());
|
|
1086
|
+
patchFormatValidatorPrototype(() => zodInstance.iso.time());
|
|
1087
|
+
patchFormatValidatorPrototype(() => zodInstance.iso.duration());
|
|
1088
|
+
// Note: z.range() is exported as standalone `z_range()` function.
|
|
1089
|
+
return zodInstance;
|
|
1090
|
+
}
|
|
1091
|
+
// Extend the Zod prototypes with the decorator methods (apply to the default imported instance)
|
|
1092
|
+
ensureZodDecoratorsLoaded(z);
|
|
1093
|
+
//# sourceMappingURL=zod.module-override.js.map
|