zod-nest 0.6.0 → 0.7.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/index.d.mts CHANGED
@@ -28,6 +28,40 @@ interface OverrideContext {
28
28
  }
29
29
  type Override = (ctx: OverrideContext) => void;
30
30
 
31
+ /**
32
+ * Composition layer — emits OpenAPI `allOf` for schemas derived via `extend`.
33
+ *
34
+ * **EXPERIMENTAL (v0.2)**: output shape may change as edge cases surface.
35
+ */
36
+
37
+ /**
38
+ * Lineage record for a composition-derived schema. Read by the override to
39
+ * emit `allOf` instead of a flat body.
40
+ *
41
+ * @experimental v0.2 — shape may change.
42
+ */
43
+ interface LineageEntry {
44
+ readonly op: 'extend';
45
+ readonly parent: z.ZodObject;
46
+ }
47
+ /**
48
+ * Wraps a derived `z.ZodObject` and records the parent → child link so
49
+ * emission rewrites the body to `allOf: [{ $ref: <parent> }, <delta>]`.
50
+ *
51
+ * @experimental v0.2 — output shape may change as the surface stabilizes.
52
+ *
53
+ * @example
54
+ * const Base = z.object({ id: z.string() }).meta({ id: 'Base' });
55
+ * const Child = extend(Base, (s) => s.extend({ role: z.string() }).meta({ id: 'Child' }));
56
+ */
57
+ declare const extend: <P extends z.ZodObject, S extends z.ZodObject>(parent: P, build: (p: P) => S) => S;
58
+ /**
59
+ * Read the lineage entry for a composition-derived schema, or `undefined`.
60
+ *
61
+ * @experimental v0.2 — `LineageEntry` shape may change.
62
+ */
63
+ declare const getLineage: (schema: z.ZodType) => LineageEntry | undefined;
64
+
31
65
  interface ZodNestRegistry {
32
66
  readonly zodRegistry: typeof z.globalRegistry;
33
67
  register(schema: z.ZodType, id: string): void;
@@ -470,4 +504,4 @@ declare class ZodNestDocumentError extends ZodNestError {
470
504
  constructor(code: ZodNestDocumentErrorCode, message: string, details?: Record<string, unknown>);
471
505
  }
472
506
 
473
- export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, type Io, type NormalizedZodNestOptions, type Override, type OverrideContext, type ResponseVariant, type ResponseVariantKind, type SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, type ZodDto, type ZodDtoMarker, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodResponse, type ZodResponseDescription, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, isZodDto, isZodDtoMarker, makeZodDtoMarker, resolveEffectiveStatus, toOpenApi };
507
+ export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, type Io, type LineageEntry, type NormalizedZodNestOptions, type Override, type OverrideContext, type ResponseVariant, type ResponseVariantKind, type SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, type ZodDto, type ZodDtoMarker, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodResponse, type ZodResponseDescription, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, extend, getLineage, isZodDto, isZodDtoMarker, makeZodDtoMarker, resolveEffectiveStatus, toOpenApi };
package/dist/index.d.ts CHANGED
@@ -28,6 +28,40 @@ interface OverrideContext {
28
28
  }
29
29
  type Override = (ctx: OverrideContext) => void;
30
30
 
31
+ /**
32
+ * Composition layer — emits OpenAPI `allOf` for schemas derived via `extend`.
33
+ *
34
+ * **EXPERIMENTAL (v0.2)**: output shape may change as edge cases surface.
35
+ */
36
+
37
+ /**
38
+ * Lineage record for a composition-derived schema. Read by the override to
39
+ * emit `allOf` instead of a flat body.
40
+ *
41
+ * @experimental v0.2 — shape may change.
42
+ */
43
+ interface LineageEntry {
44
+ readonly op: 'extend';
45
+ readonly parent: z.ZodObject;
46
+ }
47
+ /**
48
+ * Wraps a derived `z.ZodObject` and records the parent → child link so
49
+ * emission rewrites the body to `allOf: [{ $ref: <parent> }, <delta>]`.
50
+ *
51
+ * @experimental v0.2 — output shape may change as the surface stabilizes.
52
+ *
53
+ * @example
54
+ * const Base = z.object({ id: z.string() }).meta({ id: 'Base' });
55
+ * const Child = extend(Base, (s) => s.extend({ role: z.string() }).meta({ id: 'Child' }));
56
+ */
57
+ declare const extend: <P extends z.ZodObject, S extends z.ZodObject>(parent: P, build: (p: P) => S) => S;
58
+ /**
59
+ * Read the lineage entry for a composition-derived schema, or `undefined`.
60
+ *
61
+ * @experimental v0.2 — `LineageEntry` shape may change.
62
+ */
63
+ declare const getLineage: (schema: z.ZodType) => LineageEntry | undefined;
64
+
31
65
  interface ZodNestRegistry {
32
66
  readonly zodRegistry: typeof z.globalRegistry;
33
67
  register(schema: z.ZodType, id: string): void;
@@ -470,4 +504,4 @@ declare class ZodNestDocumentError extends ZodNestError {
470
504
  constructor(code: ZodNestDocumentErrorCode, message: string, details?: Record<string, unknown>);
471
505
  }
472
506
 
473
- export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, type Io, type NormalizedZodNestOptions, type Override, type OverrideContext, type ResponseVariant, type ResponseVariantKind, type SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, type ZodDto, type ZodDtoMarker, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodResponse, type ZodResponseDescription, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, isZodDto, isZodDtoMarker, makeZodDtoMarker, resolveEffectiveStatus, toOpenApi };
507
+ export { type ApplyZodNestOptions, COMPONENTS_SCHEMAS_PREFIX, type CreateSerializationException, type CreateValidationException, type CreateZodDtoOptions, DEFAULT_MAX_LOGGED_VALUE_BYTES, DEFAULT_REDACT_KEYS, type Io, type LineageEntry, type NormalizedZodNestOptions, type Override, type OverrideContext, type ResponseVariant, type ResponseVariantKind, type SchemaObject, type ToOpenApiOptions, type ToOpenApiResult, ZOD_DTO_SYMBOL, ZOD_NEST_DTO_EXTENSION, ZOD_NEST_ERROR_DUPLICATE_ID, ZOD_NEST_ERROR_EXTENSION, ZOD_NEST_OPTIONS, ZOD_RESPONSES_METADATA_KEY, type ZodDto, type ZodDtoMarker, ZodNestDocumentError, type ZodNestDocumentErrorCode, ZodNestError, ZodNestModule, type ZodNestModuleOptions, type ZodNestRegistry, ZodNestUnrepresentableError, ZodResponse, type ZodResponseDescription, type ZodResponseOptions, type ZodResponseType, ZodSerializationException, ZodSerializerInterceptor, ZodValidationException, ZodValidationPipe, type ZodValidationPipeArg, type ZodValidationPipeOptions, applyZodNest, createRegistry, createZodDto, defaultRegistry, defaultStatusFor, extend, getLineage, isZodDto, isZodDtoMarker, makeZodDtoMarker, resolveEffectiveStatus, toOpenApi };
package/dist/index.js CHANGED
@@ -24,9 +24,73 @@ var __decorateParam = (index, decorator) => (target, key) => decorator(target, k
24
24
 
25
25
  // src/schema/constants.ts
26
26
  var COMPONENTS_SCHEMAS_PREFIX = "#/components/schemas/";
27
+ var DEFS_PREFIX = "#/$defs/";
27
28
  var ZOD_NEST_ERROR_EXTENSION = "x-zod-nest-error";
28
29
  var ZOD_NEST_ERROR_DUPLICATE_ID = "duplicate-id";
29
30
  var ZOD_NEST_DTO_EXTENSION = "x-zod-nest-dto";
31
+ var lineageMap = /* @__PURE__ */ new WeakMap();
32
+ var propsMap = /* @__PURE__ */ new WeakMap();
33
+ var OPTIONAL_WRAPPER_TYPES = /* @__PURE__ */ new Set(["optional", "default"]);
34
+ var isOptionalProp = (propSchema) => OPTIONAL_WRAPPER_TYPES.has(propSchema._zod.def.type);
35
+ var computeShapeKeys = (schema) => {
36
+ const { shape } = schema;
37
+ const properties = Object.keys(shape);
38
+ const required = properties.filter((key) => {
39
+ const propSchema = shape[key];
40
+ return propSchema !== void 0 && !isOptionalProp(propSchema);
41
+ });
42
+ return { properties, required };
43
+ };
44
+ var extend = (parent, build) => {
45
+ const result = build(parent);
46
+ lineageMap.set(result, { op: "extend", parent });
47
+ if (!propsMap.has(parent)) {
48
+ propsMap.set(parent, computeShapeKeys(parent));
49
+ }
50
+ return result;
51
+ };
52
+ var getLineage = (schema) => lineageMap.get(schema);
53
+ var DEFAULT_BUILD_REF = (id) => `${DEFS_PREFIX}${id}`;
54
+ var createCompositionOverride = (opts) => {
55
+ const { buildRef } = opts;
56
+ return (ctx) => {
57
+ const { jsonSchema, zodSchema } = ctx;
58
+ const entry = lineageMap.get(zodSchema);
59
+ if (entry === void 0) {
60
+ return;
61
+ }
62
+ const parentCache = propsMap.get(entry.parent);
63
+ if (parentCache === void 0) {
64
+ return;
65
+ }
66
+ const parentId = zod.z.globalRegistry.get(entry.parent)?.id;
67
+ if (parentId === void 0) {
68
+ return;
69
+ }
70
+ const childProps = jsonSchema.properties ?? {};
71
+ const childRequired = jsonSchema.required ?? [];
72
+ const parentPropSet = new Set(parentCache.properties);
73
+ const parentReqSet = new Set(parentCache.required);
74
+ const deltaProps = {};
75
+ for (const [key, value] of Object.entries(childProps)) {
76
+ if (parentPropSet.has(key)) {
77
+ continue;
78
+ }
79
+ deltaProps[key] = value;
80
+ }
81
+ const deltaRequired = childRequired.filter((key) => !parentReqSet.has(key));
82
+ const delta = { type: "object", properties: deltaProps };
83
+ if (deltaRequired.length > 0) {
84
+ delta.required = deltaRequired;
85
+ }
86
+ delete jsonSchema.type;
87
+ delete jsonSchema.properties;
88
+ delete jsonSchema.required;
89
+ delete jsonSchema.additionalProperties;
90
+ jsonSchema.allOf = [{ $ref: buildRef(parentId) }, delta];
91
+ jsonSchema.unevaluatedProperties = false;
92
+ };
93
+ };
30
94
 
31
95
  // src/schema/errors.ts
32
96
  var ZodNestError = class extends Error {
@@ -55,7 +119,7 @@ var formatPath = (path) => {
55
119
  };
56
120
 
57
121
  // src/schema/override.ts
58
- var builtInOverride = ({ zodSchema, jsonSchema }) => {
122
+ var primitiveOverride = ({ zodSchema, jsonSchema }) => {
59
123
  const type = zodSchema._zod.def.type;
60
124
  if (type === "bigint") {
61
125
  jsonSchema.type = "integer";
@@ -104,7 +168,6 @@ var combine = (...overrides) => {
104
168
  };
105
169
 
106
170
  // src/schema/post-process.ts
107
- var DEFS_PREFIX = "#/$defs/";
108
171
  var rewriteRefs = (node, selfRef) => {
109
172
  if (Array.isArray(node)) {
110
173
  for (const item of node) {
@@ -147,7 +210,10 @@ var postProcess = (raw) => {
147
210
  // src/schema/engine.ts
148
211
  var buildToJsonSchemaOptions = (params) => {
149
212
  const strict = params.strict ?? true;
150
- const merged = combine(builtInOverride, params.override);
213
+ const compositionOverride = createCompositionOverride({
214
+ buildRef: params.uri ?? DEFAULT_BUILD_REF
215
+ });
216
+ const merged = combine(primitiveOverride, compositionOverride, params.override);
151
217
  const unrepresentableHits = [];
152
218
  const wrapped = (ctx) => {
153
219
  merged(ctx);
@@ -752,7 +818,7 @@ var runPass = (opts, io, knownIds) => {
752
818
  io,
753
819
  override: opts.override,
754
820
  strict: opts.strict,
755
- reused: "ref",
821
+ reused: "inline",
756
822
  uri: URI
757
823
  });
758
824
  const raw = zod.z.toJSONSchema(opts.registry.zodRegistry, built.options);
@@ -1205,6 +1271,8 @@ exports.createRegistry = createRegistry;
1205
1271
  exports.createZodDto = createZodDto;
1206
1272
  exports.defaultRegistry = defaultRegistry;
1207
1273
  exports.defaultStatusFor = defaultStatusFor;
1274
+ exports.extend = extend;
1275
+ exports.getLineage = getLineage;
1208
1276
  exports.isZodDto = isZodDto;
1209
1277
  exports.isZodDtoMarker = isZodDtoMarker;
1210
1278
  exports.makeZodDtoMarker = makeZodDtoMarker;