Skip to content

Commit

Permalink
chore(vendor/zodJsonSchema): add option to duplicate top-level ref
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertCraigie committed Aug 7, 2024
1 parent bceea60 commit 84b8a38
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/_vendor/zod-to-json-schema/Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type Options<Target extends Targets = 'jsonSchema7'> = {
applyRegexFlags: boolean;
emailStrategy: 'format:email' | 'format:idn-email' | 'pattern:zod';
base64Strategy: 'format:binary' | 'contentEncoding:base64' | 'pattern:zod';
nameStrategy: 'ref' | 'title';
nameStrategy: 'ref' | 'duplicate-ref' | 'title';
override?: (
def: ZodTypeDef,
refs: Refs,
Expand Down
7 changes: 7 additions & 0 deletions src/_vendor/zod-to-json-schema/Refs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import { JsonSchema7Type } from './parseDef';

export type Refs = {
seen: Map<ZodTypeDef, Seen>;
/**
* Set of all the `$ref`s we created, e.g. `Set(['#/$defs/ui'])`
* this notable does not include any `definitions` that were
* explicitly given as an option.
*/
seenRefs: Set<string>;
currentPath: string[];
propertyPath: string[] | undefined;
} & Options<Targets>;
Expand All @@ -24,6 +30,7 @@ export const getRefs = (options?: string | Partial<Options<Targets>>): Refs => {
..._options,
currentPath: currentPath,
propertyPath: undefined,
seenRefs: new Set(),
seen: new Map(
Object.entries(_options.definitions).map(([name, def]) => [
def._def,
Expand Down
4 changes: 4 additions & 0 deletions src/_vendor/zod-to-json-schema/parseDef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export function parseDef(
const seenSchema = get$ref(seenItem, refs);

if (seenSchema !== undefined) {
if ('$ref' in seenSchema) {
refs.seenRefs.add(seenSchema.$ref);
}

return seenSchema;
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/_vendor/zod-to-json-schema/zodToJsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ const zodToJsonSchema = <Target extends Targets = 'jsonSchema7'>(
main.title = title;
}

const rootRefPath = name ? [...refs.basePath, refs.definitionPath, name].join('/') : null;

const combined: ReturnType<typeof zodToJsonSchema<Target>> =
name === undefined ?
definitions ?
Expand All @@ -69,6 +71,20 @@ const zodToJsonSchema = <Target extends Targets = 'jsonSchema7'>(
[refs.definitionPath]: definitions,
}
: main
: refs.nameStrategy === 'duplicate-ref' ?
{
...main,
...(definitions || refs.seenRefs.has(rootRefPath!) ?
{
[refs.definitionPath]: {
...definitions,
// only actually duplicate the schema definition if it was ever referenced
// otherwise the duplication is completely pointless
...(refs.seenRefs.has(rootRefPath!) ? { [name]: main } : undefined),
},
}
: undefined),
}
: {
$ref: [...(refs.$refStrategy === 'relative' ? [] : refs.basePath), refs.definitionPath, name].join(
'/',
Expand Down

0 comments on commit 84b8a38

Please sign in to comment.