@wildo-ai/zod-decorators 1.1.11 → 1.1.13
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/commons.d.ts.map +1 -1
- package/dist/esm/commons.js.map +1 -1
- package/dist/esm/currencies.shared.schemas.d.ts.map +1 -1
- package/dist/esm/currencies.shared.schemas.js.map +1 -1
- package/dist/esm/files/agent-file-formats.d.ts.map +1 -1
- package/dist/esm/files/agent-file-formats.js.map +1 -1
- package/dist/esm/files/extension-nature-map.d.ts.map +1 -1
- package/dist/esm/files/extension-nature-map.js.map +1 -1
- package/dist/esm/files/file-extensions.enum.d.ts.map +1 -1
- package/dist/esm/files/file-extensions.enum.js.map +1 -1
- package/dist/esm/files/mime-registry.d.ts.map +1 -1
- package/dist/esm/files/mime-registry.js.map +1 -1
- package/dist/esm/files/unified-registry.d.ts.map +1 -1
- package/dist/esm/files/unified-registry.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/install-bigint-json-encoding.d.ts +1 -1
- package/dist/esm/install-bigint-json-encoding.d.ts.map +1 -1
- package/dist/esm/install-bigint-json-encoding.js +1 -1
- package/dist/esm/install-bigint-json-encoding.js.map +1 -1
- package/dist/esm/testing/decorated-test-schemas.d.ts +7 -7
- package/dist/esm/testing/decorated-test-schemas.d.ts.map +1 -1
- package/dist/esm/testing/decorated-test-schemas.js.map +1 -1
- package/dist/esm/testing.d.ts.map +1 -1
- package/dist/esm/testing.js.map +1 -1
- package/dist/esm/zod-address.d.ts.map +1 -1
- package/dist/esm/zod-address.js.map +1 -1
- package/dist/esm/zod-bigdecimal.d.ts +4 -4
- package/dist/esm/zod-bigdecimal.d.ts.map +1 -1
- package/dist/esm/zod-bigdecimal.js.map +1 -1
- package/dist/esm/zod-code.d.ts +4 -4
- package/dist/esm/zod-code.d.ts.map +1 -1
- package/dist/esm/zod-code.js.map +1 -1
- package/dist/esm/zod-color.d.ts.map +1 -1
- package/dist/esm/zod-color.js.map +1 -1
- package/dist/esm/zod-decorators.types.d.ts +116 -9
- package/dist/esm/zod-decorators.types.d.ts.map +1 -1
- package/dist/esm/zod-decorators.types.js +40 -1
- package/dist/esm/zod-decorators.types.js.map +1 -1
- package/dist/esm/zod-document-sequence.d.ts.map +1 -1
- package/dist/esm/zod-document-sequence.js.map +1 -1
- package/dist/esm/zod-duration.d.ts +6 -6
- package/dist/esm/zod-duration.d.ts.map +1 -1
- package/dist/esm/zod-duration.js.map +1 -1
- package/dist/esm/zod-file.d.ts +5 -4
- package/dist/esm/zod-file.d.ts.map +1 -1
- package/dist/esm/zod-file.js +1 -1
- package/dist/esm/zod-file.js.map +1 -1
- package/dist/esm/zod-money.d.ts +4 -4
- package/dist/esm/zod-money.d.ts.map +1 -1
- package/dist/esm/zod-money.js.map +1 -1
- package/dist/esm/zod-phone.d.ts +4 -4
- package/dist/esm/zod-phone.d.ts.map +1 -1
- package/dist/esm/zod-phone.js.map +1 -1
- package/dist/esm/zod-range.d.ts.map +1 -1
- package/dist/esm/zod-range.js.map +1 -1
- package/dist/esm/zod-utils.shared.d.ts +47 -12
- package/dist/esm/zod-utils.shared.d.ts.map +1 -1
- package/dist/esm/zod-utils.shared.js +143 -40
- package/dist/esm/zod-utils.shared.js.map +1 -1
- package/dist/esm/zod-versioned.d.ts.map +1 -1
- package/dist/esm/zod-versioned.js.map +1 -1
- package/dist/esm/zod-wire-date.d.ts +107 -0
- package/dist/esm/zod-wire-date.d.ts.map +1 -0
- package/dist/esm/zod-wire-date.js +162 -0
- package/dist/esm/zod-wire-date.js.map +1 -0
- package/dist/esm/zod-year-month.d.ts +76 -0
- package/dist/esm/zod-year-month.d.ts.map +1 -0
- package/dist/esm/zod-year-month.js +115 -0
- package/dist/esm/zod-year-month.js.map +1 -0
- package/dist/esm/zod.module-override.d.ts +139 -156
- package/dist/esm/zod.module-override.d.ts.map +1 -1
- package/dist/esm/zod.module-override.js +176 -6
- package/dist/esm/zod.module-override.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -5
|
@@ -116,8 +116,9 @@ export function unwrapSchema(schema) {
|
|
|
116
116
|
* - nested PLAIN object fields, recursively, through `optional` / `nullable` wrappers only. An object
|
|
117
117
|
* nested inside a union, discriminated union, record, intersection, pipe/transform, `readonly` or `lazy`
|
|
118
118
|
* is NOT peeled and keeps re-materialising its defaults — narrower than it could be, never wrong;
|
|
119
|
-
* - an object carrying its own refinement is NOT peeled
|
|
120
|
-
* defaulted key, and would see `undefined`
|
|
119
|
+
* - an object carrying its own refinement is NOT peeled, and neither is one under a wrapper or a default
|
|
120
|
+
* that carries one: a `.refine()` / `.superRefine()` may read a defaulted key, and would see `undefined`
|
|
121
|
+
* (or throw) once that default stopped applying (#3342);
|
|
121
122
|
* - a nested key WITH a default becomes optional without it; a nested key WITHOUT one keeps its declared
|
|
122
123
|
* optionality — a replaced nested object must still carry what it requires;
|
|
123
124
|
* - ARRAYS are left alone: an array element is sent whole, and its defaults describe a new element;
|
|
@@ -127,6 +128,8 @@ export function unwrapSchema(schema) {
|
|
|
127
128
|
* never mutated, so the source schema is untouched.
|
|
128
129
|
*/
|
|
129
130
|
function withoutNestedObjectDefaults(schema) {
|
|
131
|
+
if (ownChecks(schema).length > 0)
|
|
132
|
+
return schema;
|
|
130
133
|
const type = getZodType(schema);
|
|
131
134
|
if (type === 'optional' || type === 'nullable') {
|
|
132
135
|
const inner = getZodDefSchemaProperty(schema, 'innerType');
|
|
@@ -140,16 +143,13 @@ function withoutNestedObjectDefaults(schema) {
|
|
|
140
143
|
if (type !== 'object')
|
|
141
144
|
return schema;
|
|
142
145
|
const def = schema._zod.def;
|
|
143
|
-
if (Array.isArray(def.checks) && def.checks.length > 0)
|
|
144
|
-
return schema;
|
|
145
146
|
const shape = schema.shape;
|
|
146
147
|
const nextShape = {};
|
|
147
148
|
let changed = false;
|
|
148
149
|
for (const [key, field] of Object.entries(shape)) {
|
|
149
150
|
let next;
|
|
150
151
|
if (isZodDefault(field)) {
|
|
151
|
-
|
|
152
|
-
next = peeled ? copySchemaMetadata(field, withoutNestedObjectDefaults(peeled).optional()) : field;
|
|
152
|
+
next = withoutDefault(field);
|
|
153
153
|
}
|
|
154
154
|
else {
|
|
155
155
|
next = withoutNestedObjectDefaults(field);
|
|
@@ -163,6 +163,37 @@ function withoutNestedObjectDefaults(schema) {
|
|
|
163
163
|
const rebuilt = schema.clone({ ...def, shape: nextShape });
|
|
164
164
|
return copySchemaMetadata(schema, rebuilt);
|
|
165
165
|
}
|
|
166
|
+
/** The checks declared on this schema itself, which a rebuilt wrapper does not inherit. */
|
|
167
|
+
function ownChecks(schema) {
|
|
168
|
+
return getZodDefProperty(schema, 'checks') ?? [];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* `check`, run only on what the request sent (#3342). A check declared on a `.default()` always had a value to read, so
|
|
172
|
+
* moved onto the optional that replaces the default it would meet `undefined` on every omitted field, and it has nothing
|
|
173
|
+
* to say about a field the request did not send. Zod's own `when` is what keeps its abort rule beside this.
|
|
174
|
+
*/
|
|
175
|
+
function checkOnWhatWasSent(check) {
|
|
176
|
+
const { when } = check._zod.def;
|
|
177
|
+
const sent = z.check((payload) => (payload.value === undefined ? undefined : check._zod.check(payload)));
|
|
178
|
+
if (when)
|
|
179
|
+
sent._zod.def.when = (payload) => payload.value !== undefined && when(payload);
|
|
180
|
+
return sent;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* A `.default()` field for a PATCH: optional, with nothing to re-materialise, and still held to the checks declared on the
|
|
184
|
+
* default (#3342). Those checks are the wrapper's own, so they are carried over by hand. With a check present, the fields
|
|
185
|
+
* under it keep their defaults, so it reads the value it was written against: the same rule as a refined object. The
|
|
186
|
+
* inner schema stays shared and is never mutated.
|
|
187
|
+
*/
|
|
188
|
+
function withoutDefault(defaulted) {
|
|
189
|
+
const inner = getZodDefSchemaProperty(defaulted, 'innerType');
|
|
190
|
+
if (!inner)
|
|
191
|
+
return defaulted;
|
|
192
|
+
const checks = ownChecks(defaulted);
|
|
193
|
+
if (checks.length === 0)
|
|
194
|
+
return copySchemaMetadata(defaulted, withoutNestedObjectDefaults(inner).optional());
|
|
195
|
+
return copySchemaMetadata(defaulted, inner.optional().check(...checks.map(checkOnWhatWasSent)));
|
|
196
|
+
}
|
|
166
197
|
/**
|
|
167
198
|
* What a BULK update form validates (#2581): `schema` with every child of a child-writable nested object made optional,
|
|
168
199
|
* at every level ({@link isChildWritableObject}).
|
|
@@ -186,6 +217,8 @@ export function withOptionalNestedChildren(schema) {
|
|
|
186
217
|
}
|
|
187
218
|
/** `field` with, if it is a child-writable object, each of its children optional (and so on down). */
|
|
188
219
|
function withOptionalChildrenOf(field) {
|
|
220
|
+
if (ownChecks(field).length > 0)
|
|
221
|
+
return field;
|
|
189
222
|
const type = getZodType(field);
|
|
190
223
|
if (type === 'optional' || type === 'nullable') {
|
|
191
224
|
const inner = getZodDefSchemaProperty(field, 'innerType');
|
|
@@ -267,10 +300,11 @@ function copySchemaMetadata(source, target) {
|
|
|
267
300
|
* optional and does not already accept null.
|
|
268
301
|
* - Default-wrapped fields: the outer `ZodDefault` is peeled, the inner schema
|
|
269
302
|
* (keeping `.int()` / `.min()` / refinements) is made optional, and any
|
|
270
|
-
* decorator metadata
|
|
303
|
+
* decorator metadata or description on the default wrapper (e.g.
|
|
271
304
|
* `.default(0).isSummaryField()`) is carried onto the resulting optional so
|
|
272
|
-
* `getMetadataRecursive` is unchanged.
|
|
273
|
-
* mutated, so the source schema is left
|
|
305
|
+
* `getMetadataRecursive` is unchanged. A check declared ON the default still holds, on what the
|
|
306
|
+
* request sent (#3342). The inner schema is SHARED, never mutated, so the source schema is left
|
|
307
|
+
* intact.
|
|
274
308
|
*
|
|
275
309
|
* Defaults remain correct for CREATE (a new row gets them) — this transform is
|
|
276
310
|
* for the UPDATE DTO only.
|
|
@@ -281,23 +315,11 @@ export function toPatchOptionalField(fieldSchema) {
|
|
|
281
315
|
const nestedPatched = withoutNestedObjectDefaults(fieldSchema);
|
|
282
316
|
return admitsNullClear ? nestedPatched.nullable().optional() : nestedPatched.optional();
|
|
283
317
|
}
|
|
284
|
-
|
|
285
|
-
if (!rawInnerType)
|
|
318
|
+
if (!getZodDefSchemaProperty(fieldSchema, 'innerType'))
|
|
286
319
|
return fieldSchema.optional();
|
|
287
|
-
const innerType = withoutNestedObjectDefaults(rawInnerType);
|
|
288
320
|
// A defaulted field is never null-clearable (see `fieldAdmitsAddedNullClear`), so the peeled
|
|
289
321
|
// inner is made optional WITHOUT a nullable wrapper.
|
|
290
|
-
|
|
291
|
-
const defaultWrapperMetadata = fieldSchema[SCHEMA_METADATA];
|
|
292
|
-
if (defaultWrapperMetadata) {
|
|
293
|
-
const optionalRecord = optionalInner;
|
|
294
|
-
const existing = optionalRecord[SCHEMA_METADATA] ?? {};
|
|
295
|
-
optionalRecord[SCHEMA_METADATA] = {
|
|
296
|
-
...existing,
|
|
297
|
-
...defaultWrapperMetadata,
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
return optionalInner;
|
|
322
|
+
return withoutDefault(fieldSchema);
|
|
301
323
|
}
|
|
302
324
|
/**
|
|
303
325
|
* The value an edit control should contribute to form state, once a "the user emptied this field"
|
|
@@ -608,6 +630,9 @@ export function withArrayElement(arraySchema, element) {
|
|
|
608
630
|
return arraySchema;
|
|
609
631
|
}
|
|
610
632
|
const rebuilt = arraySchema.clone({ ...def, element });
|
|
633
|
+
const decoratorMetadata = arraySchema[SCHEMA_METADATA];
|
|
634
|
+
if (decoratorMetadata !== undefined)
|
|
635
|
+
rebuilt[SCHEMA_METADATA] = decoratorMetadata;
|
|
611
636
|
const registered = z.globalRegistry.get(arraySchema);
|
|
612
637
|
if (registered !== undefined && !z.globalRegistry.has(rebuilt)) {
|
|
613
638
|
const { id: _id, ...carried } = registered;
|
|
@@ -1270,6 +1295,37 @@ export function getUnionObjectMembers(schema) {
|
|
|
1270
1295
|
const options = (getZodDefArrayProperty(schema, 'options') ?? []);
|
|
1271
1296
|
return options.filter((option) => isZodTypeAny(option) && isZodObject(option));
|
|
1272
1297
|
}
|
|
1298
|
+
/**
|
|
1299
|
+
* The value(s) ONE member of a discriminated union holds for its discriminator, read through every wrapper (#2076).
|
|
1300
|
+
*
|
|
1301
|
+
* A member's discriminator is a literal (`z.literal('recurring')`, whose values Zod 4 keeps in an ARRAY under `values`)
|
|
1302
|
+
* or, for the base values a schema family groups into one member, an enum. It is no longer always BARE: the member that
|
|
1303
|
+
* holds the value the base field declares as its `.default()` carries `literal.optional().default(value)`, the one shape
|
|
1304
|
+
* a Zod 4 discriminated union can route an omitted key by. A reader of the bare `def.values` would miss that member, so
|
|
1305
|
+
* a reader of a DECLARED union's member values goes through here. {@link getUnionDiscriminatorKey}'s inference over a
|
|
1306
|
+
* PLAIN union deliberately does not: it asks whether a key discriminates at all, and only a bare literal proves that.
|
|
1307
|
+
*
|
|
1308
|
+
* Non-string literal values (a numeric discriminator) are kept as they are; an enum contributes its string values.
|
|
1309
|
+
*/
|
|
1310
|
+
export function getDiscriminatorMemberValues(memberDiscriminator) {
|
|
1311
|
+
if (!memberDiscriminator)
|
|
1312
|
+
return [];
|
|
1313
|
+
const unwrapped = unwrapSchema(memberDiscriminator);
|
|
1314
|
+
if (getZodType(unwrapped) === 'literal') {
|
|
1315
|
+
return (getZodDefArrayProperty(unwrapped, 'values') ?? [getZodDefProperty(unwrapped, 'value')])
|
|
1316
|
+
.filter((value) => value !== undefined && value !== null);
|
|
1317
|
+
}
|
|
1318
|
+
return getEnumValues(unwrapped);
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Whether a member of a declared discriminated union is the one Zod routes a value WITHOUT the discriminator to (#2076):
|
|
1322
|
+
* its discriminator accepts the key's absence, which Zod 4 reads from the member field's `_zod.values` containing
|
|
1323
|
+
* `undefined` (an `.optional()` under the declared `.default()`).
|
|
1324
|
+
*/
|
|
1325
|
+
function memberTakesOmittedDiscriminator(memberDiscriminator) {
|
|
1326
|
+
const values = memberDiscriminator?._zod?.values;
|
|
1327
|
+
return values instanceof Set && values.has(undefined);
|
|
1328
|
+
}
|
|
1273
1329
|
/**
|
|
1274
1330
|
* Resolve the ONE variant of a discriminated union that a given value belongs to.
|
|
1275
1331
|
*
|
|
@@ -1282,7 +1338,8 @@ export function getUnionObjectMembers(schema) {
|
|
|
1282
1338
|
* The discriminator is {@link getUnionDiscriminatorKey}'s: declared, or carried structurally by a plain
|
|
1283
1339
|
* `z.union` (#1022 — a versioned record's items). For such a plain union a value carrying NO discriminator
|
|
1284
1340
|
* belongs to the one strict member that omits the key, when there is one; for a declared discriminated union
|
|
1285
|
-
* it belongs to
|
|
1341
|
+
* it belongs to the member Zod itself routes it to — the one whose discriminator takes the declared default
|
|
1342
|
+
* (#2076) — and to none when no member does.
|
|
1286
1343
|
*
|
|
1287
1344
|
* Returns `null` when the schema is not a discriminated union, when the value carries no
|
|
1288
1345
|
* discriminator its union can place, or when no variant matches it — all three are "this caller cannot
|
|
@@ -1297,8 +1354,9 @@ export function resolveDiscriminatedUnionVariant(schema, value) {
|
|
|
1297
1354
|
const discriminatorValue = value[discriminator];
|
|
1298
1355
|
const options = (getZodDefArrayProperty(schema, 'options') ?? []);
|
|
1299
1356
|
if (discriminatorValue === undefined) {
|
|
1300
|
-
if (getZodDefStringProperty(schema, 'discriminator'))
|
|
1301
|
-
return null;
|
|
1357
|
+
if (getZodDefStringProperty(schema, 'discriminator')) {
|
|
1358
|
+
return options.find((option) => isZodObject(option) && memberTakesOmittedDiscriminator(getZodObjectShape(option)[discriminator])) ?? null;
|
|
1359
|
+
}
|
|
1302
1360
|
return options.find((option) => isZodObject(option) && getZodObjectShape(option)[discriminator] === undefined) ?? null;
|
|
1303
1361
|
}
|
|
1304
1362
|
for (const option of options) {
|
|
@@ -1309,12 +1367,11 @@ export function resolveDiscriminatedUnionVariant(schema, value) {
|
|
|
1309
1367
|
if (!discriminatorSchema)
|
|
1310
1368
|
continue;
|
|
1311
1369
|
/*
|
|
1312
|
-
* A variant's discriminator is a LITERAL (`z.literal(ICPArchetype.LEGAL_ENTITY)`),
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1370
|
+
* A variant's discriminator is a LITERAL (`z.literal(ICPArchetype.LEGAL_ENTITY)`), or the enum of a family's base
|
|
1371
|
+
* values, possibly under the declared default's wrappers (#2076). Comparing the exact values
|
|
1372
|
+
* `getDiscriminatorMemberValues` reads is what makes the match exact rather than structural.
|
|
1315
1373
|
*/
|
|
1316
|
-
|
|
1317
|
-
if (literalValues.includes(discriminatorValue))
|
|
1374
|
+
if (getDiscriminatorMemberValues(discriminatorSchema).includes(discriminatorValue))
|
|
1318
1375
|
return option;
|
|
1319
1376
|
}
|
|
1320
1377
|
return null;
|
|
@@ -1896,17 +1953,32 @@ export function getObjectLikeFieldSchema(schema, fieldName) {
|
|
|
1896
1953
|
* - a **plain object** (`FieldSchemaType.OBJECT`). A value type stored as an object (money, an address, a duration, a
|
|
1897
1954
|
* file, a versioned object) is ONE value, written whole: `price.amount` alone would leave every row's own currency
|
|
1898
1955
|
* under it.
|
|
1899
|
-
* - with **no refinement
|
|
1900
|
-
* TOGETHER (`start` before `end`), and a write of one child never runs it, so such an
|
|
1956
|
+
* - with **no refinement** (`.refine()`, `.superRefine()`, `.check()`) on the object or on any wrapper around it. A
|
|
1957
|
+
* refinement judges the children TOGETHER (`start` before `end`), and a write of one child never runs it, so such an
|
|
1958
|
+
* object is written whole. A check on the optional, nullable or default around the object counts too (#3342): the form,
|
|
1959
|
+
* the write units and the server all ask this, so a wrapper's check cannot be required by one and skipped by another.
|
|
1901
1960
|
*
|
|
1902
1961
|
* Arrays are never child-writable: an index addresses a position, which is a different element on every row.
|
|
1903
|
-
* Wrappers (optional, nullable, default) are looked through.
|
|
1962
|
+
* Wrappers (optional, nullable, default, readonly, catch, and a pipe's input) are looked through, as `unwrapSchema` does.
|
|
1904
1963
|
*/
|
|
1905
1964
|
export function isChildWritableObject(schema) {
|
|
1906
1965
|
if (getSchemaType(schema) !== FieldSchemaType.OBJECT || getObjectShape(schema) === null)
|
|
1907
1966
|
return false;
|
|
1908
|
-
|
|
1909
|
-
|
|
1967
|
+
// The wrappers `unwrapSchema` looks through, so every layer between the field and its object is asked.
|
|
1968
|
+
let current = schema;
|
|
1969
|
+
while (current) {
|
|
1970
|
+
if (ownChecks(current).length > 0)
|
|
1971
|
+
return false;
|
|
1972
|
+
const type = getZodType(current);
|
|
1973
|
+
if (type === 'pipe')
|
|
1974
|
+
current = getZodDefSchemaProperty(current, 'in');
|
|
1975
|
+
else if (type === 'optional' || type === 'nullable' || type === 'default' || type === 'readonly' || type === 'catch') {
|
|
1976
|
+
current = getZodDefSchemaProperty(current, 'innerType');
|
|
1977
|
+
}
|
|
1978
|
+
else
|
|
1979
|
+
return true;
|
|
1980
|
+
}
|
|
1981
|
+
return true;
|
|
1910
1982
|
}
|
|
1911
1983
|
/**
|
|
1912
1984
|
* The schema of ONE CHILD of a nested object, addressed by a dotted path (`contact.city`, `settings.theme.mode`).
|
|
@@ -2416,6 +2488,13 @@ export function getBackendOnlyParams(schema) {
|
|
|
2416
2488
|
return {}; // Default params when decorator is used without params
|
|
2417
2489
|
return value;
|
|
2418
2490
|
}
|
|
2491
|
+
/**
|
|
2492
|
+
* Whether a backend-only field declares that its value is the subject's own data, disclosed in their access export
|
|
2493
|
+
* (`isBackendOnly({ disclosedToSubject: true })`, #2958). `false` for a field that is not backend-only.
|
|
2494
|
+
*/
|
|
2495
|
+
export function isBackendOnlyFieldDisclosedToSubject(schema) {
|
|
2496
|
+
return getBackendOnlyParams(schema)?.disclosedToSubject === true;
|
|
2497
|
+
}
|
|
2419
2498
|
/**
|
|
2420
2499
|
* Check if a schema field has the isWriteOnlySecret decorator.
|
|
2421
2500
|
*/
|
|
@@ -2548,6 +2627,14 @@ export function isDeciderField(schema) {
|
|
|
2548
2627
|
const metadata = getMetadataRecursive(schema);
|
|
2549
2628
|
return metadata?.[ZodDecorator.IS_DECIDER] === true;
|
|
2550
2629
|
}
|
|
2630
|
+
/**
|
|
2631
|
+
* Are this field's values roles the writer grants (`.isRoleGrant()`, #3248)? Reads through wrapper types, so the marker
|
|
2632
|
+
* is seen whether it was declared before or after `.optional()` / `.default()`.
|
|
2633
|
+
*/
|
|
2634
|
+
export function isRoleGrantField(schema) {
|
|
2635
|
+
const metadata = getMetadataRecursive(schema);
|
|
2636
|
+
return metadata?.[ZodDecorator.IS_ROLE_GRANT] === true;
|
|
2637
|
+
}
|
|
2551
2638
|
/** The names of a row schema's decider fields (`.isDecider()`), across every variant of a polymorphic row. */
|
|
2552
2639
|
export function deciderFieldNames(rowSchema) {
|
|
2553
2640
|
if (!rowSchema)
|
|
@@ -2795,8 +2882,7 @@ export function isPrimaryKeyField(schema) {
|
|
|
2795
2882
|
*
|
|
2796
2883
|
* A business key is the **declaration-side identity** used by the data-seeding
|
|
2797
2884
|
* subsystem to upsert / upgrade / sync seeded rows independently from the
|
|
2798
|
-
* random `_id` (`isPrimaryKey`).
|
|
2799
|
-
* §3.3 for the semantic contract.
|
|
2885
|
+
* random `_id` (`isPrimaryKey`).
|
|
2800
2886
|
*/
|
|
2801
2887
|
export function isBusinessKeyField(schema) {
|
|
2802
2888
|
const metadata = getMetadataRecursive(schema);
|
|
@@ -2816,8 +2902,7 @@ export function getDocumentSequenceParams(schema) {
|
|
|
2816
2902
|
* list of field names, or `undefined` if no composite key is declared.
|
|
2817
2903
|
*
|
|
2818
2904
|
* The composite key is the schema-level analog of `isBusinessKey` — used
|
|
2819
|
-
* when identity is `(orgId, templateKey)` rather than a single field.
|
|
2820
|
-
* `.cursor/plans/seeding-first-class.md` §3.3.
|
|
2905
|
+
* when identity is `(orgId, templateKey)` rather than a single field.
|
|
2821
2906
|
*/
|
|
2822
2907
|
export function getBusinessKeySet(schema) {
|
|
2823
2908
|
return getBusinessKeySetParams(schema)?.fields;
|
|
@@ -2836,6 +2921,24 @@ export function getBusinessKeySetParams(schema) {
|
|
|
2836
2921
|
const params = metadata?.[ZodDecorator.OBJECT_BUSINESS_KEY_SET];
|
|
2837
2922
|
return params?.fields ? params : undefined;
|
|
2838
2923
|
}
|
|
2924
|
+
/**
|
|
2925
|
+
* Every NON-unique compound index an object schema declares with `compoundIndex([...])` (#3142), in declaration order,
|
|
2926
|
+
* or `[]`. Each entry's `fields` are in index order. The ONE reader both storage adapters ask (the MongoDB convertor
|
|
2927
|
+
* and the PostgreSQL planner), so they cannot disagree about which indexes a resource has.
|
|
2928
|
+
*
|
|
2929
|
+
* Only the indexes whose fields this object still HAS: Zod's `.omit()`, `.pick()` and `.extend()` copy the outer
|
|
2930
|
+
* metadata wholesale, so an object derived from one that declared an index would otherwise keep an index naming a field
|
|
2931
|
+
* it dropped, and its storage would refuse to build. An object that lost a field lost the index over it.
|
|
2932
|
+
*/
|
|
2933
|
+
export function getCompoundIndexes(schema) {
|
|
2934
|
+
const declared = getMetadataRecursive(schema)?.[ZodDecorator.OBJECT_COMPOUND_INDEX];
|
|
2935
|
+
if (!Array.isArray(declared))
|
|
2936
|
+
return [];
|
|
2937
|
+
const shape = getZodObjectShape(schema);
|
|
2938
|
+
return declared
|
|
2939
|
+
.filter((index) => index.fields.every((field) => Object.hasOwn(shape, field)))
|
|
2940
|
+
.map((index) => ({ fields: [...index.fields] }));
|
|
2941
|
+
}
|
|
2839
2942
|
/**
|
|
2840
2943
|
* The target set an object declares with `isResourceReference({ targetSet })` (#2471): the object names one row of a
|
|
2841
2944
|
* resource whose type is chosen at run time from that set. `undefined` when the object is not a resource reference.
|