zod 3.26.0-canary.20250707T201657 → 3.26.0-canary.20250708T225111

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.
@@ -602,10 +602,10 @@ export declare function promise<T extends core.SomeType>(innerType: T): ZodPromi
602
602
  export interface ZodCustom<O = unknown, I = unknown> extends _ZodType<core.$ZodCustomInternals<O, I>>, core.$ZodCustom<O, I> {
603
603
  }
604
604
  export declare const ZodCustom: core.$constructor<ZodCustom>;
605
- export declare function check<O = unknown>(fn: core.CheckFn<O>, params?: string | core.$ZodCustomParams): core.$ZodCheck<O>;
605
+ export declare function check<O = unknown>(fn: core.CheckFn<O>): core.$ZodCheck<O>;
606
606
  export declare function custom<O>(fn?: (data: unknown) => unknown, _params?: string | core.$ZodCustomParams | undefined): ZodCustom<O, O>;
607
607
  export declare function refine<T>(fn: (arg: NoInfer<T>) => util.MaybeAsync<unknown>, _params?: string | core.$ZodCustomParams): core.$ZodCheck<T>;
608
- export declare function superRefine<T>(fn: (arg: T, payload: RefinementCtx<T>) => void | Promise<void>, params?: string | core.$ZodCustomParams): core.$ZodCheck<T>;
608
+ export declare function superRefine<T>(fn: (arg: T, payload: RefinementCtx<T>) => void | Promise<void>): core.$ZodCheck<T>;
609
609
  type ZodInstanceOfParams = core.Params<ZodCustom, core.$ZodIssueCustom, "type" | "check" | "checks" | "fn" | "abort" | "error" | "params" | "path">;
610
610
  declare function _instanceof<T extends typeof util.Class>(cls: T, params?: ZodInstanceOfParams): ZodCustom<InstanceType<T>, InstanceType<T>>;
611
611
  export { _instanceof as instanceof };
@@ -935,10 +935,10 @@ export const ZodCustom = /*@__PURE__*/ core.$constructor("ZodCustom", (inst, def
935
935
  ZodType.init(inst, def);
936
936
  });
937
937
  // custom checks
938
- export function check(fn, params) {
938
+ export function check(fn) {
939
939
  const ch = new core.$ZodCheck({
940
940
  check: "custom",
941
- ...util.normalizeParams(params),
941
+ // ...util.normalizeParams(params),
942
942
  });
943
943
  ch._zod.check = fn;
944
944
  return ch;
@@ -950,7 +950,7 @@ export function refine(fn, _params = {}) {
950
950
  return core._refine(ZodCustom, fn, _params);
951
951
  }
952
952
  // superRefine
953
- export function superRefine(fn, params) {
953
+ export function superRefine(fn) {
954
954
  const ch = check((payload) => {
955
955
  payload.addIssue = (issue) => {
956
956
  if (typeof issue === "string") {
@@ -969,7 +969,7 @@ export function superRefine(fn, params) {
969
969
  }
970
970
  };
971
971
  return fn(payload.value, payload);
972
- }, params);
972
+ });
973
973
  return ch;
974
974
  }
975
975
  function _instanceof(cls, params = {
@@ -248,11 +248,12 @@ exports.$ZodCheckBigIntFormat = core.$constructor("$ZodCheckBigIntFormat", (inst
248
248
  };
249
249
  });
250
250
  exports.$ZodCheckMaxSize = core.$constructor("$ZodCheckMaxSize", (inst, def) => {
251
+ var _a;
251
252
  exports.$ZodCheck.init(inst, def);
252
- inst._zod.when = (payload) => {
253
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
253
254
  const val = payload.value;
254
255
  return !util.nullish(val) && val.size !== undefined;
255
- };
256
+ });
256
257
  inst._zod.onattach.push((inst) => {
257
258
  const curr = (inst._zod.bag.maximum ?? Number.POSITIVE_INFINITY);
258
259
  if (def.maximum < curr)
@@ -274,11 +275,12 @@ exports.$ZodCheckMaxSize = core.$constructor("$ZodCheckMaxSize", (inst, def) =>
274
275
  };
275
276
  });
276
277
  exports.$ZodCheckMinSize = core.$constructor("$ZodCheckMinSize", (inst, def) => {
278
+ var _a;
277
279
  exports.$ZodCheck.init(inst, def);
278
- inst._zod.when = (payload) => {
280
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
279
281
  const val = payload.value;
280
282
  return !util.nullish(val) && val.size !== undefined;
281
- };
283
+ });
282
284
  inst._zod.onattach.push((inst) => {
283
285
  const curr = (inst._zod.bag.minimum ?? Number.NEGATIVE_INFINITY);
284
286
  if (def.minimum > curr)
@@ -300,11 +302,12 @@ exports.$ZodCheckMinSize = core.$constructor("$ZodCheckMinSize", (inst, def) =>
300
302
  };
301
303
  });
302
304
  exports.$ZodCheckSizeEquals = core.$constructor("$ZodCheckSizeEquals", (inst, def) => {
305
+ var _a;
303
306
  exports.$ZodCheck.init(inst, def);
304
- inst._zod.when = (payload) => {
307
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
305
308
  const val = payload.value;
306
309
  return !util.nullish(val) && val.size !== undefined;
307
- };
310
+ });
308
311
  inst._zod.onattach.push((inst) => {
309
312
  const bag = inst._zod.bag;
310
313
  bag.minimum = def.size;
@@ -329,11 +332,12 @@ exports.$ZodCheckSizeEquals = core.$constructor("$ZodCheckSizeEquals", (inst, de
329
332
  };
330
333
  });
331
334
  exports.$ZodCheckMaxLength = core.$constructor("$ZodCheckMaxLength", (inst, def) => {
335
+ var _a;
332
336
  exports.$ZodCheck.init(inst, def);
333
- inst._zod.when = (payload) => {
337
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
334
338
  const val = payload.value;
335
339
  return !util.nullish(val) && val.length !== undefined;
336
- };
340
+ });
337
341
  inst._zod.onattach.push((inst) => {
338
342
  const curr = (inst._zod.bag.maximum ?? Number.POSITIVE_INFINITY);
339
343
  if (def.maximum < curr)
@@ -357,11 +361,12 @@ exports.$ZodCheckMaxLength = core.$constructor("$ZodCheckMaxLength", (inst, def)
357
361
  };
358
362
  });
359
363
  exports.$ZodCheckMinLength = core.$constructor("$ZodCheckMinLength", (inst, def) => {
364
+ var _a;
360
365
  exports.$ZodCheck.init(inst, def);
361
- inst._zod.when = (payload) => {
366
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
362
367
  const val = payload.value;
363
368
  return !util.nullish(val) && val.length !== undefined;
364
- };
369
+ });
365
370
  inst._zod.onattach.push((inst) => {
366
371
  const curr = (inst._zod.bag.minimum ?? Number.NEGATIVE_INFINITY);
367
372
  if (def.minimum > curr)
@@ -385,11 +390,12 @@ exports.$ZodCheckMinLength = core.$constructor("$ZodCheckMinLength", (inst, def)
385
390
  };
386
391
  });
387
392
  exports.$ZodCheckLengthEquals = core.$constructor("$ZodCheckLengthEquals", (inst, def) => {
393
+ var _a;
388
394
  exports.$ZodCheck.init(inst, def);
389
- inst._zod.when = (payload) => {
395
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
390
396
  const val = payload.value;
391
397
  return !util.nullish(val) && val.length !== undefined;
392
- };
398
+ });
393
399
  inst._zod.onattach.push((inst) => {
394
400
  const bag = inst._zod.bag;
395
401
  bag.minimum = def.length;
@@ -7,6 +7,8 @@ export interface $ZodCheckDef {
7
7
  error?: errors.$ZodErrorMap<never> | undefined;
8
8
  /** If true, no later checks will be executed if this check fails. Default `false`. */
9
9
  abort?: boolean | undefined;
10
+ /** If provided, this check will only be executed if the function returns `true`. Defaults to `payload => z.util.isAborted(payload)`. */
11
+ when?: ((payload: schemas.ParsePayload) => boolean) | undefined;
10
12
  }
11
13
  export interface $ZodCheckInternals<T> {
12
14
  def: $ZodCheckDef;
@@ -14,7 +16,6 @@ export interface $ZodCheckInternals<T> {
14
16
  issc?: errors.$ZodIssueBase;
15
17
  check(payload: schemas.ParsePayload<T>): util.MaybeAsync<void>;
16
18
  onattach: ((schema: schemas.$ZodType) => void)[];
17
- when?: ((payload: schemas.ParsePayload) => boolean) | undefined;
18
19
  }
19
20
  export interface $ZodCheck<in T = never> {
20
21
  _zod: $ZodCheckInternals<T>;
@@ -7,6 +7,8 @@ export interface $ZodCheckDef {
7
7
  error?: errors.$ZodErrorMap<never> | undefined;
8
8
  /** If true, no later checks will be executed if this check fails. Default `false`. */
9
9
  abort?: boolean | undefined;
10
+ /** If provided, this check will only be executed if the function returns `true`. Defaults to `payload => z.util.isAborted(payload)`. */
11
+ when?: ((payload: schemas.ParsePayload) => boolean) | undefined;
10
12
  }
11
13
  export interface $ZodCheckInternals<T> {
12
14
  def: $ZodCheckDef;
@@ -14,7 +16,6 @@ export interface $ZodCheckInternals<T> {
14
16
  issc?: errors.$ZodIssueBase;
15
17
  check(payload: schemas.ParsePayload<T>): util.MaybeAsync<void>;
16
18
  onattach: ((schema: schemas.$ZodType) => void)[];
17
- when?: ((payload: schemas.ParsePayload) => boolean) | undefined;
18
19
  }
19
20
  export interface $ZodCheck<in T = never> {
20
21
  _zod: $ZodCheckInternals<T>;
package/v4/core/checks.js CHANGED
@@ -222,11 +222,12 @@ export const $ZodCheckBigIntFormat = /*@__PURE__*/ core.$constructor("$ZodCheckB
222
222
  };
223
223
  });
224
224
  export const $ZodCheckMaxSize = /*@__PURE__*/ core.$constructor("$ZodCheckMaxSize", (inst, def) => {
225
+ var _a;
225
226
  $ZodCheck.init(inst, def);
226
- inst._zod.when = (payload) => {
227
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
227
228
  const val = payload.value;
228
229
  return !util.nullish(val) && val.size !== undefined;
229
- };
230
+ });
230
231
  inst._zod.onattach.push((inst) => {
231
232
  const curr = (inst._zod.bag.maximum ?? Number.POSITIVE_INFINITY);
232
233
  if (def.maximum < curr)
@@ -248,11 +249,12 @@ export const $ZodCheckMaxSize = /*@__PURE__*/ core.$constructor("$ZodCheckMaxSiz
248
249
  };
249
250
  });
250
251
  export const $ZodCheckMinSize = /*@__PURE__*/ core.$constructor("$ZodCheckMinSize", (inst, def) => {
252
+ var _a;
251
253
  $ZodCheck.init(inst, def);
252
- inst._zod.when = (payload) => {
254
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
253
255
  const val = payload.value;
254
256
  return !util.nullish(val) && val.size !== undefined;
255
- };
257
+ });
256
258
  inst._zod.onattach.push((inst) => {
257
259
  const curr = (inst._zod.bag.minimum ?? Number.NEGATIVE_INFINITY);
258
260
  if (def.minimum > curr)
@@ -274,11 +276,12 @@ export const $ZodCheckMinSize = /*@__PURE__*/ core.$constructor("$ZodCheckMinSiz
274
276
  };
275
277
  });
276
278
  export const $ZodCheckSizeEquals = /*@__PURE__*/ core.$constructor("$ZodCheckSizeEquals", (inst, def) => {
279
+ var _a;
277
280
  $ZodCheck.init(inst, def);
278
- inst._zod.when = (payload) => {
281
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
279
282
  const val = payload.value;
280
283
  return !util.nullish(val) && val.size !== undefined;
281
- };
284
+ });
282
285
  inst._zod.onattach.push((inst) => {
283
286
  const bag = inst._zod.bag;
284
287
  bag.minimum = def.size;
@@ -303,11 +306,12 @@ export const $ZodCheckSizeEquals = /*@__PURE__*/ core.$constructor("$ZodCheckSiz
303
306
  };
304
307
  });
305
308
  export const $ZodCheckMaxLength = /*@__PURE__*/ core.$constructor("$ZodCheckMaxLength", (inst, def) => {
309
+ var _a;
306
310
  $ZodCheck.init(inst, def);
307
- inst._zod.when = (payload) => {
311
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
308
312
  const val = payload.value;
309
313
  return !util.nullish(val) && val.length !== undefined;
310
- };
314
+ });
311
315
  inst._zod.onattach.push((inst) => {
312
316
  const curr = (inst._zod.bag.maximum ?? Number.POSITIVE_INFINITY);
313
317
  if (def.maximum < curr)
@@ -331,11 +335,12 @@ export const $ZodCheckMaxLength = /*@__PURE__*/ core.$constructor("$ZodCheckMaxL
331
335
  };
332
336
  });
333
337
  export const $ZodCheckMinLength = /*@__PURE__*/ core.$constructor("$ZodCheckMinLength", (inst, def) => {
338
+ var _a;
334
339
  $ZodCheck.init(inst, def);
335
- inst._zod.when = (payload) => {
340
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
336
341
  const val = payload.value;
337
342
  return !util.nullish(val) && val.length !== undefined;
338
- };
343
+ });
339
344
  inst._zod.onattach.push((inst) => {
340
345
  const curr = (inst._zod.bag.minimum ?? Number.NEGATIVE_INFINITY);
341
346
  if (def.minimum > curr)
@@ -359,11 +364,12 @@ export const $ZodCheckMinLength = /*@__PURE__*/ core.$constructor("$ZodCheckMinL
359
364
  };
360
365
  });
361
366
  export const $ZodCheckLengthEquals = /*@__PURE__*/ core.$constructor("$ZodCheckLengthEquals", (inst, def) => {
367
+ var _a;
362
368
  $ZodCheck.init(inst, def);
363
- inst._zod.when = (payload) => {
369
+ (_a = inst._zod.def).when ?? (_a.when = (payload) => {
364
370
  const val = payload.value;
365
371
  return !util.nullish(val) && val.length !== undefined;
366
- };
372
+ });
367
373
  inst._zod.onattach.push((inst) => {
368
374
  const bag = inst._zod.bag;
369
375
  bag.minimum = def.length;
@@ -48,6 +48,10 @@ const initializer = (inst, def) => {
48
48
  enumerable: true,
49
49
  // configurable: false,
50
50
  });
51
+ Object.defineProperty(inst, "toString", {
52
+ value: () => inst.message,
53
+ enumerable: false,
54
+ });
51
55
  };
52
56
  exports.$ZodError = (0, core_js_1.$constructor)("$ZodError", initializer);
53
57
  exports.$ZodRealError = (0, core_js_1.$constructor)("$ZodError", initializer, { Parent: Error });
@@ -150,7 +150,9 @@ export type $ZodFormattedError<T, U = string> = {
150
150
  } & util.Flatten<_ZodFormattedError<T, U>>;
151
151
  export declare function formatError<T>(error: $ZodError<T>): $ZodFormattedError<T>;
152
152
  export declare function formatError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodFormattedError<T, U>;
153
- export type $ZodErrorTree<T, U = string> = T extends [any, ...any[]] ? {
153
+ export type $ZodErrorTree<T, U = string> = T extends util.Primitive ? {
154
+ errors: U[];
155
+ } : T extends [any, ...any[]] ? {
154
156
  errors: U[];
155
157
  items?: {
156
158
  [K in keyof T]?: $ZodErrorTree<T[K], U>;
@@ -150,7 +150,9 @@ export type $ZodFormattedError<T, U = string> = {
150
150
  } & util.Flatten<_ZodFormattedError<T, U>>;
151
151
  export declare function formatError<T>(error: $ZodError<T>): $ZodFormattedError<T>;
152
152
  export declare function formatError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodFormattedError<T, U>;
153
- export type $ZodErrorTree<T, U = string> = T extends [any, ...any[]] ? {
153
+ export type $ZodErrorTree<T, U = string> = T extends util.Primitive ? {
154
+ errors: U[];
155
+ } : T extends [any, ...any[]] ? {
154
156
  errors: U[];
155
157
  items?: {
156
158
  [K in keyof T]?: $ZodErrorTree<T[K], U>;
package/v4/core/errors.js CHANGED
@@ -17,6 +17,10 @@ const initializer = (inst, def) => {
17
17
  enumerable: true,
18
18
  // configurable: false,
19
19
  });
20
+ Object.defineProperty(inst, "toString", {
21
+ value: () => inst.message,
22
+ enumerable: false,
23
+ });
20
24
  };
21
25
  export const $ZodError = $constructor("$ZodError", initializer);
22
26
  export const $ZodRealError = $constructor("$ZodError", initializer, { Parent: Error });
@@ -6,7 +6,7 @@ exports.$output = Symbol("ZodOutput");
6
6
  exports.$input = Symbol("ZodInput");
7
7
  class $ZodRegistry {
8
8
  constructor() {
9
- this._map = new WeakMap();
9
+ this._map = new Map();
10
10
  this._idmap = new Map();
11
11
  }
12
12
  add(schema, ..._meta) {
@@ -20,6 +20,11 @@ class $ZodRegistry {
20
20
  }
21
21
  return this;
22
22
  }
23
+ clear() {
24
+ this._map = new Map();
25
+ this._idmap = new Map();
26
+ return this;
27
+ }
23
28
  remove(schema) {
24
29
  const meta = this._map.get(schema);
25
30
  if (meta && typeof meta === "object" && "id" in meta) {
@@ -13,9 +13,10 @@ type MetadataType = Record<string, unknown> | undefined;
13
13
  export declare class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema extends $ZodType = $ZodType> {
14
14
  _meta: Meta;
15
15
  _schema: Schema;
16
- _map: WeakMap<Schema, $replace<Meta, Schema>>;
16
+ _map: Map<Schema, $replace<Meta, Schema>>;
17
17
  _idmap: Map<string, Schema>;
18
18
  add<S extends Schema>(schema: S, ..._meta: undefined extends Meta ? [$replace<Meta, S>?] : [$replace<Meta, S>]): this;
19
+ clear(): this;
19
20
  remove(schema: Schema): this;
20
21
  get<S extends Schema>(schema: S): $replace<Meta, S> | undefined;
21
22
  has(schema: Schema): boolean;
@@ -13,9 +13,10 @@ type MetadataType = Record<string, unknown> | undefined;
13
13
  export declare class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema extends $ZodType = $ZodType> {
14
14
  _meta: Meta;
15
15
  _schema: Schema;
16
- _map: WeakMap<Schema, $replace<Meta, Schema>>;
16
+ _map: Map<Schema, $replace<Meta, Schema>>;
17
17
  _idmap: Map<string, Schema>;
18
18
  add<S extends Schema>(schema: S, ..._meta: undefined extends Meta ? [$replace<Meta, S>?] : [$replace<Meta, S>]): this;
19
+ clear(): this;
19
20
  remove(schema: Schema): this;
20
21
  get<S extends Schema>(schema: S): $replace<Meta, S> | undefined;
21
22
  has(schema: Schema): boolean;
@@ -2,7 +2,7 @@ export const $output = Symbol("ZodOutput");
2
2
  export const $input = Symbol("ZodInput");
3
3
  export class $ZodRegistry {
4
4
  constructor() {
5
- this._map = new WeakMap();
5
+ this._map = new Map();
6
6
  this._idmap = new Map();
7
7
  }
8
8
  add(schema, ..._meta) {
@@ -16,6 +16,11 @@ export class $ZodRegistry {
16
16
  }
17
17
  return this;
18
18
  }
19
+ clear() {
20
+ this._map = new Map();
21
+ this._idmap = new Map();
22
+ return this;
23
+ }
19
24
  remove(schema) {
20
25
  const meta = this._map.get(schema);
21
26
  if (meta && typeof meta === "object" && "id" in meta) {
@@ -65,8 +65,8 @@ exports.$ZodType = core.$constructor("$ZodType", (inst, def) => {
65
65
  let isAborted = util.aborted(payload);
66
66
  let asyncResult;
67
67
  for (const ch of checks) {
68
- if (ch._zod.when) {
69
- const shouldRun = ch._zod.when(payload);
68
+ if (ch._zod.def.when) {
69
+ const shouldRun = ch._zod.def.when(payload);
70
70
  if (!shouldRun)
71
71
  continue;
72
72
  }
@@ -35,8 +35,8 @@ export const $ZodType = /*@__PURE__*/ core.$constructor("$ZodType", (inst, def)
35
35
  let isAborted = util.aborted(payload);
36
36
  let asyncResult;
37
37
  for (const ch of checks) {
38
- if (ch._zod.when) {
39
- const shouldRun = ch._zod.when(payload);
38
+ if (ch._zod.def.when) {
39
+ const shouldRun = ch._zod.def.when(payload);
40
40
  if (!shouldRun)
41
41
  continue;
42
42
  }
@@ -536,6 +536,8 @@ class JSONSchemaGenerator {
536
536
  throw new Error("Unprocessed schema. This is a bug in Zod.");
537
537
  // initialize result with root schema fields
538
538
  // Object.assign(result, seen.cached);
539
+ // returns a ref to the schema
540
+ // defId will be empty if the ref points to an external schema (or #)
539
541
  const makeURI = (entry) => {
540
542
  // comparing the seen objects because sometimes
541
543
  // multiple schemas map to the same seen object.
@@ -545,12 +547,14 @@ class JSONSchemaGenerator {
545
547
  if (params.external) {
546
548
  const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`;
547
549
  // check if schema is in the external registry
548
- if (externalId)
549
- return { ref: params.external.uri(externalId) };
550
+ const uriGenerator = params.external.uri ?? ((id) => id);
551
+ if (externalId) {
552
+ return { ref: uriGenerator(externalId) };
553
+ }
550
554
  // otherwise, add to __shared
551
555
  const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
552
- entry[1].defId = id;
553
- return { defId: id, ref: `${params.external.uri("__shared")}#/${defsSegment}/${id}` };
556
+ entry[1].defId = id; // set defId so it will be reused if needed
557
+ return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
554
558
  }
555
559
  if (entry[1] === root) {
556
560
  return { ref: "#" };
@@ -564,6 +568,7 @@ class JSONSchemaGenerator {
564
568
  // stored cached version in `def` property
565
569
  // remove all properties, set $ref
566
570
  const extractToDef = (entry) => {
571
+ // if the schema is already a reference, do not extract it
567
572
  if (entry[1].schema.$ref) {
568
573
  return;
569
574
  }
@@ -580,14 +585,24 @@ class JSONSchemaGenerator {
580
585
  }
581
586
  schema.$ref = ref;
582
587
  };
588
+ // throw on cycles
589
+ // break cycles
590
+ if (params.cycles === "throw") {
591
+ for (const entry of this.seen.entries()) {
592
+ const seen = entry[1];
593
+ if (seen.cycle) {
594
+ throw new Error("Cycle detected: " +
595
+ `#/${seen.cycle?.join("/")}/<root>` +
596
+ '\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
597
+ }
598
+ }
599
+ }
583
600
  // extract schemas into $defs
584
601
  for (const entry of this.seen.entries()) {
585
602
  const seen = entry[1];
586
603
  // convert root schema to # $ref
587
- // also prevents root schema from being extracted
588
604
  if (schema === entry[0]) {
589
- // do not copy to defs...this is the root schema
590
- extractToDef(entry);
605
+ extractToDef(entry); // this has special handling for the root schema
591
606
  continue;
592
607
  }
593
608
  // extract schemas that are in the external registry
@@ -606,14 +621,8 @@ class JSONSchemaGenerator {
606
621
  }
607
622
  // break cycles
608
623
  if (seen.cycle) {
609
- if (params.cycles === "throw") {
610
- throw new Error("Cycle detected: " +
611
- `#/${seen.cycle?.join("/")}/<root>` +
612
- '\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
613
- }
614
- else if (params.cycles === "ref") {
615
- extractToDef(entry);
616
- }
624
+ // any
625
+ extractToDef(entry);
617
626
  continue;
618
627
  }
619
628
  // extract reused schemas
@@ -671,6 +680,12 @@ class JSONSchemaGenerator {
671
680
  else {
672
681
  console.warn(`Invalid target: ${this.target}`);
673
682
  }
683
+ if (params.external?.uri) {
684
+ const id = params.external.registry.get(schema)?.id;
685
+ if (!id)
686
+ throw new Error("Schema is missing an `id` property");
687
+ result.$id = params.external.uri(id);
688
+ }
674
689
  Object.assign(result, root.def);
675
690
  // build defs object
676
691
  const defs = params.external?.defs ?? {};
@@ -681,12 +696,16 @@ class JSONSchemaGenerator {
681
696
  }
682
697
  }
683
698
  // set definitions in result
684
- if (!params.external && Object.keys(defs).length > 0) {
685
- if (this.target === "draft-2020-12") {
686
- result.$defs = defs;
687
- }
688
- else {
689
- result.definitions = defs;
699
+ if (params.external) {
700
+ }
701
+ else {
702
+ if (Object.keys(defs).length > 0) {
703
+ if (this.target === "draft-2020-12") {
704
+ result.$defs = defs;
705
+ }
706
+ else {
707
+ result.definitions = defs;
708
+ }
690
709
  }
691
710
  }
692
711
  try {
@@ -712,7 +731,7 @@ function toJSONSchema(input, _params) {
712
731
  const schemas = {};
713
732
  const external = {
714
733
  registry: input,
715
- uri: _params?.uri || ((id) => id),
734
+ uri: _params?.uri,
716
735
  defs,
717
736
  };
718
737
  for (const entry of input._idmap.entries()) {
@@ -39,7 +39,7 @@ interface EmitParams {
39
39
  registry: $ZodRegistry<{
40
40
  id?: string | undefined;
41
41
  }>;
42
- uri: (id: string) => string;
42
+ uri?: ((id: string) => string) | undefined;
43
43
  defs: Record<string, JSONSchema.BaseSchema>;
44
44
  } | undefined;
45
45
  }
@@ -39,7 +39,7 @@ interface EmitParams {
39
39
  registry: $ZodRegistry<{
40
40
  id?: string | undefined;
41
41
  }>;
42
- uri: (id: string) => string;
42
+ uri?: ((id: string) => string) | undefined;
43
43
  defs: Record<string, JSONSchema.BaseSchema>;
44
44
  } | undefined;
45
45
  }