Open JeongJuhyeon opened 5 months ago
@JeongJuhyeon, yes I know what's the issue:
registry.register
is essentially returning a new schema that has some custom metadata applied to it. So the correct way to achieve what you wanted is to do:
export const ModificationRequest = registry.register("ModificationRequest", z.object({
// ...
}););
// everything else should remain the self
@AGalabov Thanks for the help, this has improved it but part of the problem remains.
const A = registry.register("A", ...));
const B = registry.register("B"., ...));
const C = registry.register("C", ...));
const D = registry.register("D", z.union(
[A, B, C]
)
);
I'm getting the result
components:
schemas:
A: ...
B: ...
C: ...
D:
anyOf:
- type: object
- ...
That is, A B and C don't get reused as part of D, their definitions are inlined again in D.
@JeongJuhyeon can you provide a full reproducible script? We have such a similar test case here: https://github.com/asteasolutions/zod-to-openapi/blob/master/spec/types/union.spec.ts#L26
@AGalabov Repro:
import { extendZodWithOpenApi, OpenApiGeneratorV3, OpenAPIRegistry } from "@asteasolutions/zod-to-openapi";
import YAML from "yaml";
import { z } from "zod";
extendZodWithOpenApi(z);
const registry = new OpenAPIRegistry();
const requestedModificationBaseSchema = z.object({
target: z.enum(["apple", "banana", "grape"]),
});
const requestedModificationBase = registry.register("RequestedModificationBase", requestedModificationBaseSchema);
const RequestedTextModification = registry.register(
"RequestedTextModification",
z.union([z.object({ x: z.number() }), z.object({ y: z.number() })]),
);
const RequestedChairModification = registry.register(
"RequestedChairModification",
z.union([z.object({ z: z.number() }), z.object({ a: z.number() })]),
);
const RequestedSubcategoryModificationSchema = z.union([RequestedTextModification, RequestedChairModification]);
const RequestedSubcategoryModification = registry.register(
"RequestedSubcategoryModification",
RequestedSubcategoryModificationSchema,
);
const ModificationRequestSchema = z.object({
userPageId: z.string(),
modifications: z.array(RequestedSubcategoryModification.and(requestedModificationBase)),
});
console.log("Registering request schema");
const ModificationRequest = registry.register("ModificationRequest", ModificationRequestSchema);
const generatedApiJson = new OpenApiGeneratorV3(registry.definitions).generateDocument({
openapi: "3.0.0",
info: { title: "App API", version: "1.0.0" },
});
console.log("Generated API JSON");
console.log(YAML.stringify(generatedApiJson));
Result:
openapi: 3.0.0
info:
title: App API
version: 1.0.0
components:
schemas:
RequestedModificationBase:
type: object
properties:
target:
type: string
enum:
- apple
- banana
- grape
required:
- target
RequestedTextModification:
anyOf:
- type: object
properties:
x:
type: number
required:
- x
- type: object
properties:
y:
type: number
required:
- y
RequestedChairModification:
anyOf:
- type: object
properties:
z:
type: number
required:
- z
- type: object
properties:
a:
type: number
required:
- a
RequestedSubcategoryModification:
anyOf:
- type: object
properties:
x:
type: number
required:
- x
- type: object
properties:
y:
type: number
required:
- y
- type: object
properties:
z:
type: number
required:
- z
- type: object
properties:
a:
type: number
required:
- a
ModificationRequest:
type: object
properties:
userPageId:
type: string
modifications:
type: array
items:
allOf:
- $ref: "#/components/schemas/RequestedSubcategoryModification"
- $ref: "#/components/schemas/RequestedModificationBase"
required:
- userPageId
- modifications
parameters: {}
paths: {}
"RequestedChairModification" and "RequestedTextModification" are inlined in "RequestedSubcategoryModification" instead of being used as $ref.
@JeongJuhyeon sorry it is taking so long, but free time is hard to find.
I see your example and it turns out the problem is the fact that you are using a union inside the union. I see the problematic piece of code. I'll see what I can do about it.
Hi, new user here. The output I'm getting contains no "$ref" whatsoever despite registering my schema. Any idea what's going wrong here? Fwiw, the generated OpenAPI definitions themselves are correct.
Input:
Output: