Skip to content

Commit 991e52a

Browse files
committed
refactor(schema): enhance error feedback message for schema generation
1 parent ca1ec78 commit 991e52a

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

packages/openapi_generator/src/__tests__/schema_generator.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ describe('SchemaGenerator', () => {
10421042
const generator = new SchemaGenerator(spec)
10431043
expect(() =>
10441044
generator.generateZodSchema(undefined as any, 'NonExistent')
1045-
).toThrow('Schema with name NonExistent not found')
1045+
).toThrow('Schema "NonExistent" not found in specification')
10461046
})
10471047

10481048
it('should handle caching of processed schemas', () => {
@@ -1178,7 +1178,7 @@ describe('SchemaGenerator', () => {
11781178
spec.components!.schemas!.Test as OpenAPIV3_1.SchemaObject,
11791179
'Test'
11801180
)
1181-
).toThrow('Base schema BaseSchema not found in processed schemas')
1181+
).toThrow('Base schema "BaseSchema" not found in processed schemas')
11821182
})
11831183
})
11841184
})

packages/openapi_generator/src/schema_generator.ts

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { OpenAPIV3_1 } from 'openapi-types'
2+
import { SchemaValidationError } from './errors'
23
import { toPascalCase } from './utils'
34

45
function isReferenceObject(obj: any): obj is OpenAPIV3_1.ReferenceObject {
@@ -46,14 +47,31 @@ export class SchemaGenerator {
4647
schema: OpenAPIV3_1.SchemaObject | OpenAPIV3_1.ReferenceObject
4748
} {
4849
if (!ref.startsWith('#/components/schemas/')) {
49-
throw new Error(
50-
`Unsupported $ref format: ${ref}. Only local component schema references are supported.`
50+
throw new SchemaValidationError(
51+
`Unsupported $ref format: ${ref}`,
52+
'unknown',
53+
ref,
54+
'Use the format "#/components/schemas/SchemaName" for schema references'
5155
)
5256
}
5357
const name = ref.split('/').pop()
54-
if (!name) throw new Error(`Invalid $ref: ${ref}`)
58+
if (!name) {
59+
throw new SchemaValidationError(
60+
`Invalid $ref path: ${ref}`,
61+
'unknown',
62+
ref,
63+
'Ensure $ref follows "#/components/schemas/SchemaName" format'
64+
)
65+
}
5566
const schema = this.spec.components?.schemas?.[name]
56-
if (!schema) throw new Error(`Schema not found for $ref: ${ref}`)
67+
if (!schema) {
68+
throw new SchemaValidationError(
69+
`Schema not found for $ref: ${ref}`,
70+
name,
71+
ref,
72+
`Check that the schema "${name}" is defined in components.schemas`
73+
)
74+
}
5775
return { name, schema }
5876
}
5977

@@ -63,7 +81,12 @@ export class SchemaGenerator {
6381
): string {
6482
const schema = schemaObject || this.spec.components?.schemas?.[name]
6583
if (!schema) {
66-
throw new Error(`Schema with name ${name} not found.`)
84+
throw new SchemaValidationError(
85+
`Schema "${name}" not found in specification`,
86+
name,
87+
`components.schemas.${name}`,
88+
'Check that the schema is defined in the components.schemas section'
89+
)
6790
}
6891

6992
if (this.processedSchemas.has(name) && !schemaObject) {
@@ -95,8 +118,11 @@ export class SchemaGenerator {
95118
this.processedSchemas.get(baseSchemaName)
96119

97120
if (!baseSchemaString) {
98-
throw new Error(
99-
`Base schema ${baseSchemaName} not found in processed schemas`
121+
throw new SchemaValidationError(
122+
`Base schema "${baseSchemaName}" not found in processed schemas`,
123+
baseSchemaName,
124+
`allOf[0].$ref`,
125+
'Ensure the base schema is defined before using it in allOf'
100126
)
101127
}
102128

@@ -127,10 +153,14 @@ export class SchemaGenerator {
127153
if (schema.oneOf && schema.discriminator) {
128154
const discriminator = schema.discriminator.propertyName
129155
const options = items.map((s) => {
130-
if (!isReferenceObject(s))
131-
throw new Error(
132-
'oneOf with discriminator must use $ref objects'
156+
if (!isReferenceObject(s)) {
157+
throw new SchemaValidationError(
158+
'oneOf with discriminator must use $ref objects',
159+
name,
160+
'oneOf',
161+
'Move inline schemas to components.schemas and reference them with $ref'
133162
)
163+
}
134164
return this.mapSchemaObjectToZod(name, s)
135165
})
136166
const zodSchema = `z.discriminatedUnion('${discriminator}', [${options.join(', ')}])`

0 commit comments

Comments
 (0)