Skip to content

Commit bd5b3e2

Browse files
authored
fix(zod): restore file context before each processZodNode call in preprocessAllSchemasInFile (#148)
1 parent 63d6b98 commit bd5b3e2

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

packages/openapi-core/src/schema/zod/zod-converter.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2379,6 +2379,11 @@ export class ZodSchemaConverter {
23792379
if (!this.getStoredSchema(schemaName)) {
23802380
logger.debug(`Pre-processing Zod schema: ${schemaName}`);
23812381
this.processingSchemas.add(schemaName);
2382+
// Restore context in case a recursive preprocessAllSchemasInFile call
2383+
// (triggered by processZodNode resolving an import) overwrote these fields.
2384+
this.currentFilePath = filePath;
2385+
this.currentAST = ast;
2386+
this.currentImports = importedModules;
23822387
const schema = this.processZodNode(declaration.init);
23832388
this.processingSchemas.delete(schemaName);
23842389
if (schema) {
@@ -2411,6 +2416,11 @@ export class ZodSchemaConverter {
24112416
if (!this.getStoredSchema(schemaName) && !this.processingSchemas.has(schemaName)) {
24122417
logger.debug(`Pre-processing Zod schema: ${schemaName}`);
24132418
this.processingSchemas.add(schemaName);
2419+
// Restore context in case a recursive preprocessAllSchemasInFile call
2420+
// (triggered by processZodNode resolving an import) overwrote these fields.
2421+
this.currentFilePath = filePath;
2422+
this.currentAST = ast;
2423+
this.currentImports = importedModules;
24142424
const schema = this.processZodNode(declaration.init);
24152425
this.processingSchemas.delete(schemaName);
24162426
if (schema) {

tests/integration/regressions/zod-structure-regressions.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,50 @@ describe("Zod structure regressions", () => {
122122
fs.rmSync(testDir, { recursive: true, force: true });
123123
}
124124
});
125+
126+
it("preserves spread base-shape properties when file also imports external schemas", () => {
127+
const testDir = createTestDir("nxog-spread-import-");
128+
129+
fs.writeFileSync(
130+
path.join(testDir, "addressSchema.ts"),
131+
`
132+
import { z } from "zod";
133+
export const addressSchema = z.object({
134+
street: z.string().describe("Street name"),
135+
});
136+
`.trim(),
137+
);
138+
139+
fs.writeFileSync(
140+
path.join(testDir, "base.ts"),
141+
`
142+
import { z } from "zod";
143+
import { addressSchema } from "./addressSchema";
144+
145+
const personBaseShape = {
146+
name: z.string().describe("Full name"),
147+
age: z.number().int().describe("Age in years"),
148+
};
149+
150+
export const employeeSchema = z
151+
.object({
152+
...personBaseShape,
153+
role: z.string().describe("Job role"),
154+
})
155+
.meta({ id: "Employee" });
156+
`.trim(),
157+
);
158+
159+
try {
160+
const converter = new ZodSchemaConverter(testDir);
161+
const schema = converter.convertZodSchemaToOpenApi("Employee");
162+
163+
expect(schema?.properties?.name).toBeDefined();
164+
expect(schema?.properties?.age).toBeDefined();
165+
expect(schema?.properties?.role).toBeDefined();
166+
expect(schema?.required).toEqual(expect.arrayContaining(["name", "age", "role"]));
167+
} finally {
168+
fs.rmSync(testDir, { recursive: true, force: true });
169+
}
170+
});
125171
});

0 commit comments

Comments
 (0)