Skip to content

Commit f437de8

Browse files
committed
chore: update json schema adapter method
1 parent e16a24b commit f437de8

File tree

1 file changed

+64
-22
lines changed

1 file changed

+64
-22
lines changed

packages/core/src/types/json-schema-adapter.ts

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ function transformJSONSchemaToNodeType(
6969
return { type: 'object' };
7070
} else if (schema.additionalProperties === false) {
7171
return { type: 'object', properties: {} };
72+
} else {
73+
// Handle case where additionalProperties is a schema
74+
return { type: 'object' };
7275
}
7376
}
7477

@@ -97,31 +100,70 @@ function transformJSONSchemaToNodeType(
97100
if (!discriminatedPropertyName) {
98101
throw new Error(`Unexpected discriminator without a propertyName in ${propertyName}.`);
99102
}
100-
const oneOfs = schema.oneOf.map((option, i) => {
101-
if (typeof option === 'boolean') {
102-
throw new Error(
103-
`Unexpected boolean schema in ${propertyName} at position ${i} in oneOf.`
104-
);
105-
}
106-
const discriminatedProperty = option?.properties?.[discriminatedPropertyName];
107-
if (!discriminatedProperty || typeof discriminatedProperty === 'boolean') {
108-
throw new Error(
109-
`Unexpected property '${discriminatedProperty}' schema in ${propertyName} at position ${i} in oneOf.`
110-
);
111-
}
112-
const name = discriminatedProperty.const as string;
113-
return transformJSONSchemaToNodeType(name, option, ctx);
114-
});
115-
116-
return (value: unknown, key: string) => {
117-
if (isPlainObject(value)) {
118-
const discriminatedTypeName = value[discriminatedPropertyName];
119-
if (typeof discriminatedTypeName === 'string' && ctx[discriminatedTypeName]) {
120-
return discriminatedTypeName;
103+
104+
// Create a NodeType that represents the discriminated union
105+
// Extract common properties from all oneOf options
106+
const commonProperties: Record<string, PropType | ResolveTypeFn> = {};
107+
108+
// Find properties that exist in all oneOf options
109+
if (schema.oneOf && schema.oneOf.length > 0) {
110+
const firstOption = schema.oneOf[0] as any;
111+
if (firstOption && firstOption.properties) {
112+
for (const [propName, propSchema] of Object.entries(firstOption.properties)) {
113+
// Check if this property exists in all oneOf options
114+
const existsInAll = schema.oneOf.every(
115+
(option: any) => option && option.properties && option.properties[propName]
116+
);
117+
118+
if (existsInAll) {
119+
// Special handling for the discriminator property - it should resolve to specific types
120+
if (propName === discriminatedPropertyName) {
121+
commonProperties[propName] = (value: any) => {
122+
if (
123+
isPlainObject(value) &&
124+
typeof value[discriminatedPropertyName] === 'string'
125+
) {
126+
const typeName = value[discriminatedPropertyName];
127+
if (ctx[typeName]) {
128+
return typeName;
129+
}
130+
}
131+
// Fallback to the property schema
132+
const fallbackType = transformJSONSchemaToNodeType(
133+
`${propertyName}.${propName}`,
134+
propSchema as JSONSchema,
135+
ctx
136+
);
137+
return typeof fallbackType === 'string' ? fallbackType : (propSchema as PropType);
138+
};
139+
} else {
140+
// For other common properties, we need to process them inline
141+
// rather than creating separate type references to avoid "Unknown type" errors
142+
const processedType = transformJSONSchemaToNodeType(
143+
`${propertyName}_${propName}`, // Use a unique name that won't conflict
144+
propSchema as JSONSchema,
145+
ctx
146+
);
147+
148+
// If it returned a type name, we need to use that reference
149+
// If it returned an inline type, use that directly
150+
if (typeof processedType === 'string') {
151+
commonProperties[propName] = processedType;
152+
} else {
153+
// For inline types (like arrays, primitives), use them directly
154+
commonProperties[propName] = processedType;
155+
}
156+
}
157+
}
121158
}
122159
}
123-
return findOneOf(schema.oneOf as JSONSchema[], oneOfs)(value, key);
160+
}
161+
162+
ctx[propertyName] = {
163+
properties: commonProperties,
124164
};
165+
166+
return propertyName;
125167
} else {
126168
const oneOfs = schema.oneOf.map((option, i) =>
127169
transformJSONSchemaToNodeType(propertyName + '_' + i, option, ctx)

0 commit comments

Comments
 (0)