Skip to content

Commit 84b8a38

Browse files
committed
chore(vendor/zodJsonSchema): add option to duplicate top-level ref
1 parent bceea60 commit 84b8a38

File tree

4 files changed

+28
-1
lines changed

4 files changed

+28
-1
lines changed

src/_vendor/zod-to-json-schema/Options.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export type Options<Target extends Targets = 'jsonSchema7'> = {
2727
applyRegexFlags: boolean;
2828
emailStrategy: 'format:email' | 'format:idn-email' | 'pattern:zod';
2929
base64Strategy: 'format:binary' | 'contentEncoding:base64' | 'pattern:zod';
30-
nameStrategy: 'ref' | 'title';
30+
nameStrategy: 'ref' | 'duplicate-ref' | 'title';
3131
override?: (
3232
def: ZodTypeDef,
3333
refs: Refs,

src/_vendor/zod-to-json-schema/Refs.ts

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ import { JsonSchema7Type } from './parseDef';
44

55
export type Refs = {
66
seen: Map<ZodTypeDef, Seen>;
7+
/**
8+
* Set of all the `$ref`s we created, e.g. `Set(['#/$defs/ui'])`
9+
* this notable does not include any `definitions` that were
10+
* explicitly given as an option.
11+
*/
12+
seenRefs: Set<string>;
713
currentPath: string[];
814
propertyPath: string[] | undefined;
915
} & Options<Targets>;
@@ -24,6 +30,7 @@ export const getRefs = (options?: string | Partial<Options<Targets>>): Refs => {
2430
..._options,
2531
currentPath: currentPath,
2632
propertyPath: undefined,
33+
seenRefs: new Set(),
2734
seen: new Map(
2835
Object.entries(_options.definitions).map(([name, def]) => [
2936
def._def,

src/_vendor/zod-to-json-schema/parseDef.ts

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ export function parseDef(
8787
const seenSchema = get$ref(seenItem, refs);
8888

8989
if (seenSchema !== undefined) {
90+
if ('$ref' in seenSchema) {
91+
refs.seenRefs.add(seenSchema.$ref);
92+
}
93+
9094
return seenSchema;
9195
}
9296
}

src/_vendor/zod-to-json-schema/zodToJsonSchema.ts

+16
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ const zodToJsonSchema = <Target extends Targets = 'jsonSchema7'>(
6161
main.title = title;
6262
}
6363

64+
const rootRefPath = name ? [...refs.basePath, refs.definitionPath, name].join('/') : null;
65+
6466
const combined: ReturnType<typeof zodToJsonSchema<Target>> =
6567
name === undefined ?
6668
definitions ?
@@ -69,6 +71,20 @@ const zodToJsonSchema = <Target extends Targets = 'jsonSchema7'>(
6971
[refs.definitionPath]: definitions,
7072
}
7173
: main
74+
: refs.nameStrategy === 'duplicate-ref' ?
75+
{
76+
...main,
77+
...(definitions || refs.seenRefs.has(rootRefPath!) ?
78+
{
79+
[refs.definitionPath]: {
80+
...definitions,
81+
// only actually duplicate the schema definition if it was ever referenced
82+
// otherwise the duplication is completely pointless
83+
...(refs.seenRefs.has(rootRefPath!) ? { [name]: main } : undefined),
84+
},
85+
}
86+
: undefined),
87+
}
7288
: {
7389
$ref: [...(refs.$refStrategy === 'relative' ? [] : refs.basePath), refs.definitionPath, name].join(
7490
'/',

0 commit comments

Comments
 (0)