File tree Expand file tree Collapse file tree 4 files changed +258
-34
lines changed
Expand file tree Collapse file tree 4 files changed +258
-34
lines changed Original file line number Diff line number Diff line change 1+ ---
2+ ' fumadocs-openapi ' : patch
3+ ---
4+
5+ Support ` required ` in ` allOf ` schemas
Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ import type { OpenAPIV3 as OpenAPI } from 'openapi-types';
22import { Fragment , type ReactNode } from 'react' ;
33import { noRef } from '@/utils/schema' ;
44import type { RenderContext } from '@/types' ;
5+ import { combineSchema } from '@/utils/combine-schema' ;
56import { Markdown } from './markdown' ;
67
78const keys : {
@@ -224,40 +225,6 @@ export function Schema({
224225 ) ;
225226}
226227
227- /**
228- * Combine multiple object schemas into one
229- */
230- function combineSchema ( schema : OpenAPI . SchemaObject [ ] ) : OpenAPI . SchemaObject {
231- const result : OpenAPI . SchemaObject = {
232- type : 'object' ,
233- } ;
234-
235- function add ( s : OpenAPI . SchemaObject ) : void {
236- if ( s . properties ) {
237- result . properties ??= { } ;
238- Object . assign ( result . properties , s . properties ) ;
239- }
240-
241- if ( s . additionalProperties === true ) {
242- result . additionalProperties = true ;
243- } else if (
244- s . additionalProperties &&
245- typeof result . additionalProperties !== 'boolean'
246- ) {
247- result . additionalProperties ??= { } ;
248- Object . assign ( result . additionalProperties , s . additionalProperties ) ;
249- }
250-
251- if ( s . allOf ) {
252- noRef ( s . allOf ) . forEach ( add ) ;
253- }
254- }
255-
256- schema . forEach ( add ) ;
257-
258- return result ;
259- }
260-
261228/**
262229 * Check if the schema needs another collapsible to explain
263230 */
Original file line number Diff line number Diff line change 1+ import { type OpenAPIV3 as OpenAPI } from 'openapi-types' ;
2+ import { noRef } from '@/utils/schema' ;
3+
4+ /**
5+ * Combine multiple object schemas into one
6+ */
7+ export function combineSchema (
8+ schema : OpenAPI . SchemaObject [ ] ,
9+ ) : OpenAPI . SchemaObject {
10+ const result : OpenAPI . SchemaObject = {
11+ type : 'object' ,
12+ } ;
13+
14+ function add ( s : OpenAPI . SchemaObject ) : void {
15+ if ( s . properties ) {
16+ result . properties ??= { } ;
17+ Object . assign ( result . properties , s . properties ) ;
18+ }
19+
20+ if ( s . additionalProperties === true ) {
21+ result . additionalProperties = true ;
22+ } else if (
23+ s . additionalProperties &&
24+ typeof result . additionalProperties !== 'boolean'
25+ ) {
26+ result . additionalProperties ??= { } ;
27+ Object . assign ( result . additionalProperties , s . additionalProperties ) ;
28+ }
29+
30+ if ( s . required ) {
31+ result . required ??= [ ] ;
32+ result . required . push ( ...s . required ) ;
33+ }
34+
35+ if ( s . allOf ) {
36+ noRef ( s . allOf ) . forEach ( add ) ;
37+ }
38+ }
39+
40+ schema . forEach ( add ) ;
41+
42+ return result ;
43+ }
Original file line number Diff line number Diff line change 1+ import { describe , expect , test } from 'vitest' ;
2+ import { combineSchema } from '@/utils/combine-schema' ;
3+
4+ describe ( 'Merge object schemas' , ( ) => {
5+ test ( 'Merge single object' , ( ) => {
6+ const result = combineSchema ( [
7+ {
8+ type : 'object' ,
9+ properties : {
10+ test : {
11+ type : 'string' ,
12+ enum : [ 'one' , 'two' ] ,
13+ } ,
14+ } ,
15+ } ,
16+ ] ) ;
17+
18+ expect ( result ) . toMatchInlineSnapshot ( `
19+ {
20+ "properties": {
21+ "test": {
22+ "enum": [
23+ "one",
24+ "two",
25+ ],
26+ "type": "string",
27+ },
28+ },
29+ "type": "object",
30+ }
31+ ` ) ;
32+ } ) ;
33+
34+ test ( 'Merge multiple objects' , ( ) => {
35+ const result = combineSchema ( [
36+ {
37+ type : 'object' ,
38+ properties : {
39+ test : {
40+ type : 'string' ,
41+ enum : [ 'one' , 'two' ] ,
42+ } ,
43+ } ,
44+ } ,
45+ {
46+ type : 'object' ,
47+ properties : {
48+ hello : {
49+ type : 'number' ,
50+ } ,
51+ } ,
52+ } ,
53+ ] ) ;
54+
55+ expect ( result ) . toMatchInlineSnapshot ( `
56+ {
57+ "properties": {
58+ "hello": {
59+ "type": "number",
60+ },
61+ "test": {
62+ "enum": [
63+ "one",
64+ "two",
65+ ],
66+ "type": "string",
67+ },
68+ },
69+ "type": "object",
70+ }
71+ ` ) ;
72+ } ) ;
73+
74+ test ( 'Merge multiple objects: required' , ( ) => {
75+ const result = combineSchema ( [
76+ {
77+ type : 'object' ,
78+ properties : {
79+ test : {
80+ type : 'string' ,
81+ enum : [ 'one' , 'two' ] ,
82+ } ,
83+ } ,
84+ } ,
85+ {
86+ type : 'object' ,
87+ properties : {
88+ hello : {
89+ type : 'number' ,
90+ } ,
91+ } ,
92+ required : [ 'hello' ] ,
93+ } ,
94+ ] ) ;
95+
96+ expect ( result ) . toMatchInlineSnapshot ( `
97+ {
98+ "properties": {
99+ "hello": {
100+ "type": "number",
101+ },
102+ "test": {
103+ "enum": [
104+ "one",
105+ "two",
106+ ],
107+ "type": "string",
108+ },
109+ },
110+ "required": [
111+ "hello",
112+ ],
113+ "type": "object",
114+ }
115+ ` ) ;
116+ } ) ;
117+
118+ test ( 'Merge multiple objects: additional properties' , ( ) => {
119+ const result = combineSchema ( [
120+ {
121+ type : 'object' ,
122+ properties : {
123+ test : {
124+ type : 'string' ,
125+ enum : [ 'one' , 'two' ] ,
126+ } ,
127+ } ,
128+ additionalProperties : true ,
129+ } ,
130+ {
131+ type : 'object' ,
132+ additionalProperties : {
133+ type : 'string' ,
134+ } ,
135+ } ,
136+ ] ) ;
137+
138+ expect ( result ) . toMatchInlineSnapshot ( `
139+ {
140+ "additionalProperties": true,
141+ "properties": {
142+ "test": {
143+ "enum": [
144+ "one",
145+ "two",
146+ ],
147+ "type": "string",
148+ },
149+ },
150+ "type": "object",
151+ }
152+ ` ) ;
153+ } ) ;
154+
155+ test ( 'Merge multiple objects: `allOf`' , ( ) => {
156+ const result = combineSchema ( [
157+ {
158+ type : 'object' ,
159+ properties : {
160+ test : {
161+ type : 'string' ,
162+ enum : [ 'one' , 'two' ] ,
163+ } ,
164+ } ,
165+ } ,
166+ {
167+ allOf : [
168+ {
169+ type : 'object' ,
170+ properties : {
171+ hello : {
172+ type : 'number' ,
173+ } ,
174+ } ,
175+ } ,
176+ {
177+ type : 'object' ,
178+ properties : {
179+ world : {
180+ type : 'number' ,
181+ } ,
182+ } ,
183+ } ,
184+ ] ,
185+ } ,
186+ ] ) ;
187+
188+ expect ( result ) . toMatchInlineSnapshot ( `
189+ {
190+ "properties": {
191+ "hello": {
192+ "type": "number",
193+ },
194+ "test": {
195+ "enum": [
196+ "one",
197+ "two",
198+ ],
199+ "type": "string",
200+ },
201+ "world": {
202+ "type": "number",
203+ },
204+ },
205+ "type": "object",
206+ }
207+ ` ) ;
208+ } ) ;
209+ } ) ;
You can’t perform that action at this time.
0 commit comments