Skip to content

Commit f000f18

Browse files
committed
feat: Updated Adapter and tests
1 parent 7603ded commit f000f18

File tree

8 files changed

+283
-49
lines changed

8 files changed

+283
-49
lines changed

src/openapi/openapi3.schema.ts

Lines changed: 97 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -91,33 +91,104 @@ const hasNullType = (schema: unknown): boolean => {
9191
return false
9292
}
9393

94-
// Adapter to transform JSON Schemas used in OpenAPI 3.0 schemas to JSOn schemas used in OpenAPI 3.1 for comparison
94+
// Builds a "null" type schema carrying over relevant origins from source
95+
// const buildNullTypeWithOrigins = (
96+
// valueWithoutNullable: Record<PropertyKey, unknown>,
97+
// originsFlag: PropertyKey,
98+
// ): Record<PropertyKey, unknown> => {
99+
// const nullTypeObject: Record<PropertyKey, unknown> = {
100+
// [JSON_SCHEMA_PROPERTY_TYPE]: JSON_SCHEMA_NODE_TYPE_NULL,
101+
// }
102+
// const valueOrigins = valueWithoutNullable[originsFlag] as Record<PropertyKey, unknown> | undefined
103+
//
104+
// if (valueWithoutNullable.title) {
105+
// nullTypeObject.title = valueWithoutNullable.title
106+
// const titleOrigin = valueOrigins && (valueOrigins as Record<PropertyKey, unknown>).title
107+
// if (titleOrigin !== undefined) {
108+
// nullTypeObject[originsFlag] = { title: titleOrigin }
109+
// }
110+
// }
111+
//
112+
// const nullableOrigin = valueOrigins && (valueOrigins as Record<PropertyKey, unknown>).nullable
113+
// if (nullableOrigin !== undefined) {
114+
// const existing = (nullTypeObject[originsFlag] as Record<PropertyKey, unknown>) || {}
115+
// nullTypeObject[originsFlag] = { ...existing, nullable: nullableOrigin }
116+
// }
117+
//
118+
// return nullTypeObject
119+
// }
120+
121+
const buildNullTypeWithOrigins = (
122+
valueWithoutNullable: Record<PropertyKey, unknown>,
123+
originsFlag: PropertyKey,
124+
syntheticTitleFlag: PropertyKey
125+
): Record<PropertyKey, unknown> => {
126+
const nullTypeObject: Record<PropertyKey, unknown> = {
127+
[JSON_SCHEMA_PROPERTY_TYPE]: JSON_SCHEMA_NODE_TYPE_NULL,
128+
}
129+
130+
const valueOrigins = valueWithoutNullable[originsFlag] as Record<PropertyKey, unknown> | undefined
131+
const origins: Record<PropertyKey, unknown> = {}
132+
133+
if (valueWithoutNullable.title) {
134+
nullTypeObject.title = valueWithoutNullable.title
135+
if (valueOrigins?.title !== undefined) {
136+
origins.title = valueOrigins.title
137+
}
138+
}
139+
140+
if (valueOrigins?.nullable !== undefined) {
141+
142+
// origins.nullable = valueOrigins.nullable
143+
144+
const getOriginParent = (item: unknown) => ({
145+
value: JSON_SCHEMA_PROPERTY_TYPE,
146+
parent: (item as any)?.parent,
147+
})
148+
149+
origins[JSON_SCHEMA_PROPERTY_TYPE] = Array.isArray(valueOrigins.nullable)
150+
? valueOrigins.nullable.map(getOriginParent)
151+
: getOriginParent(valueOrigins.nullable)
152+
}
153+
154+
if (Object.keys(origins).length > 0) {
155+
nullTypeObject[originsFlag] = origins
156+
}
157+
158+
return nullTypeObject
159+
}
160+
161+
// Adapter to transform JSON Schemas used in OpenAPI 3.0 schemas to JSON Schemas used in OpenAPI 3.1 for comparison
95162
const jsonSchemaOas30to31Adapter: AdapterResolver = (value, reference, ctx) => {
96-
if (!isObject(value) || !isObject(reference)) return value
97-
98-
// Check if value has nullable: true
99-
if (value[JSON_SCHEMA_PROPERTY_NULLABLE] !== true) return value
100-
101-
// Check if reference has null type or combiner with null
102-
if (!hasNullType(reference)) return value
103-
104-
// Transform to anyOf format
105-
return ctx.transformer(value, 'nullable-to-anyof', (value) => {
106-
const { [JSON_SCHEMA_PROPERTY_NULLABLE]: _, ...valueWithoutNullable } = value as Record<PropertyKey, unknown>
107-
108-
// Create the anyOf array with the original schema (without nullable) and null type
109-
const anyOfArray = [
110-
valueWithoutNullable,
111-
{ [JSON_SCHEMA_PROPERTY_TYPE]: JSON_SCHEMA_NODE_TYPE_NULL }
112-
]
113-
114-
const result = { [JSON_SCHEMA_PROPERTY_ANY_OF]: anyOfArray }
115-
116-
// Set origins for the anyOf property and its items
117-
setOrigins(result, JSON_SCHEMA_PROPERTY_ANY_OF, ctx.options.originsFlag, ctx.valueOrigins)
118-
setOrigins(anyOfArray, 0, ctx.options.originsFlag, ctx.valueOrigins)
119-
setOrigins(anyOfArray, 1, ctx.options.originsFlag, ctx.valueOrigins)
120-
163+
if (!isObject(value) || !isObject(reference)) {
164+
return value
165+
}
166+
167+
if (value[JSON_SCHEMA_PROPERTY_NULLABLE] !== true) {
168+
return value
169+
}
170+
171+
if (!hasNullType(reference)) {
172+
return value
173+
}
174+
175+
const originsFlag: PropertyKey = ctx.options.originsFlag
176+
// @ts-ignore
177+
const syntheticTitleFlag: PropertyKey = ctx.options.syntheticTitleFlag
178+
179+
return ctx.transformer(value, 'nullable-to-anyof', (current) => {
180+
const { [JSON_SCHEMA_PROPERTY_NULLABLE]: _nullable, ...valueWithoutNullable } = current as Record<PropertyKey, unknown>
181+
182+
const nullTypeObject = buildNullTypeWithOrigins(valueWithoutNullable, originsFlag, syntheticTitleFlag)
183+
184+
const anyOfArray = [valueWithoutNullable, nullTypeObject]
185+
186+
const result: Record<PropertyKey, unknown> = { [JSON_SCHEMA_PROPERTY_ANY_OF]: anyOfArray }
187+
188+
setOrigins(result, JSON_SCHEMA_PROPERTY_ANY_OF, originsFlag, ctx.valueOrigins)
189+
setOrigins(anyOfArray, 0, originsFlag, ctx.valueOrigins)
190+
setOrigins(anyOfArray, 1, originsFlag, ctx.valueOrigins)
191+
121192
return result
122193
})
123194
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
openapi: 3.1.0
2+
info:
3+
title: test
4+
version: 0.1.0
5+
paths:
6+
/path1:
7+
get:
8+
requestBody:
9+
content:
10+
'application/json':
11+
schema:
12+
$ref: '#/components/schemas/MySchema'
13+
components:
14+
schemas:
15+
MySchema:
16+
anyOf:
17+
- type: string
18+
- type: 'null'
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
openapi: 3.0.4
2+
info:
3+
title: test
4+
version: 0.1.0
5+
paths:
6+
/path1:
7+
get:
8+
requestBody:
9+
content:
10+
'application/json':
11+
schema:
12+
$ref: '#/components/schemas/MySchema'
13+
components:
14+
schemas:
15+
MySchema:
16+
type: string
17+
nullable: true
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
openapi: 3.1.0
2+
info:
3+
title: test
4+
version: 0.1.0
5+
paths:
6+
/path1:
7+
get:
8+
responses:
9+
'200':
10+
description: OK
11+
content:
12+
'application/json':
13+
schema:
14+
anyOf:
15+
- type: string
16+
- type: 'null'
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
openapi: 3.0.4
2+
info:
3+
title: test
4+
version: 0.1.0
5+
paths:
6+
/path1:
7+
get:
8+
responses:
9+
'200':
10+
description: OK
11+
content:
12+
'application/json':
13+
schema:
14+
type: string
15+
nullable: true
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
openapi: 3.1.0
2+
info:
3+
title: test
4+
version: 0.1.0
5+
paths:
6+
/path1:
7+
get:
8+
responses:
9+
'200':
10+
description: OK
11+
content:
12+
application/json:
13+
schema:
14+
$ref: '#/components/schemas/MySchema'
15+
components:
16+
schemas:
17+
MySchema:
18+
type:
19+
- string
20+
- 'null'
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
openapi: 3.0.4
2+
info:
3+
title: test
4+
version: 0.1.0
5+
paths:
6+
/path1:
7+
get:
8+
responses:
9+
'200':
10+
description: OK
11+
content:
12+
'application/json':
13+
schema:
14+
$ref: '#/components/schemas/MySchema'
15+
components:
16+
schemas:
17+
MySchema:
18+
type: string
19+
nullable: true

0 commit comments

Comments
 (0)