Skip to content

Commit 6a493fb

Browse files
authored
feat(plugins): expose JSON Schema merging mechanism from samples plugins (#9766)
Refs #9765
1 parent c0e3eb6 commit 6a493fb

File tree

7 files changed

+148
-28
lines changed

7 files changed

+148
-28
lines changed

src/core/plugins/json-schema-2020-12-samples/fn/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export {
1111
export { default as encoderAPI } from "./api/encoderAPI"
1212
export { default as formatAPI } from "./api/formatAPI"
1313
export { default as mediaTypeAPI } from "./api/mediaTypeAPI"
14+
export { default as mergeJsonSchema } from "./core/merge"

src/core/plugins/json-schema-2020-12-samples/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
encoderAPI,
1111
mediaTypeAPI,
1212
formatAPI,
13+
mergeJsonSchema,
1314
} from "./fn/index"
1415
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
1516
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
@@ -37,6 +38,7 @@ const JSONSchema202012SamplesPlugin = ({ getSystem }) => {
3738
getYamlSampleSchema,
3839
getXmlSampleSchema,
3940
getSampleSchema,
41+
mergeJsonSchema,
4042
},
4143
},
4244
}

src/core/plugins/json-schema-5-samples/fn/index.js

+29-27
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@ const numberContracts = [
5656
]
5757
const stringContracts = ["minLength", "maxLength"]
5858

59-
const liftSampleHelper = (oldSchema, target, config = {}) => {
59+
export const mergeJsonSchema = (target, source, config = {}) => {
60+
const merged = { ...target }
61+
6062
const setIfNotDefinedInTarget = (key) => {
61-
if(target[key] === undefined && oldSchema[key] !== undefined) {
62-
target[key] = oldSchema[key]
63+
if(merged[key] === undefined && source[key] !== undefined) {
64+
merged[key] = source[key]
6365
}
6466
}
6567

@@ -75,22 +77,22 @@ const liftSampleHelper = (oldSchema, target, config = {}) => {
7577
...stringContracts,
7678
].forEach(key => setIfNotDefinedInTarget(key))
7779

78-
if(oldSchema.required !== undefined && Array.isArray(oldSchema.required)) {
79-
if(target.required === undefined || !target.required.length) {
80-
target.required = []
80+
if(source.required !== undefined && Array.isArray(source.required)) {
81+
if(merged.required === undefined || !merged.required.length) {
82+
merged.required = []
8183
}
82-
oldSchema.required.forEach(key => {
83-
if(target.required.includes(key)) {
84+
source.required.forEach(key => {
85+
if(merged.required.includes(key)) {
8486
return
8587
}
86-
target.required.push(key)
88+
merged.required.push(key)
8789
})
8890
}
89-
if(oldSchema.properties) {
90-
if(!target.properties) {
91-
target.properties = {}
91+
if(source.properties) {
92+
if(!merged.properties) {
93+
merged.properties = {}
9294
}
93-
let props = objectify(oldSchema.properties)
95+
let props = objectify(source.properties)
9496
for (let propName in props) {
9597
if (!Object.prototype.hasOwnProperty.call(props, propName)) {
9698
continue
@@ -104,26 +106,26 @@ const liftSampleHelper = (oldSchema, target, config = {}) => {
104106
if ( props[propName] && props[propName].writeOnly && !config.includeWriteOnly ) {
105107
continue
106108
}
107-
if(!target.properties[propName]) {
108-
target.properties[propName] = props[propName]
109-
if(!oldSchema.required && Array.isArray(oldSchema.required) && oldSchema.required.indexOf(propName) !== -1) {
110-
if(!target.required) {
111-
target.required = [propName]
109+
if(!merged.properties[propName]) {
110+
merged.properties[propName] = props[propName]
111+
if(!source.required && Array.isArray(source.required) && source.required.indexOf(propName) !== -1) {
112+
if(!merged.required) {
113+
merged.required = [propName]
112114
} else {
113-
target.required.push(propName)
115+
merged.required.push(propName)
114116
}
115117
}
116118
}
117119
}
118120
}
119-
if(oldSchema.items) {
120-
if(!target.items) {
121-
target.items = {}
121+
if(source.items) {
122+
if(!merged.items) {
123+
merged.items = {}
122124
}
123-
target.items = liftSampleHelper(oldSchema.items, target.items, config)
125+
merged.items = mergeJsonSchema(merged.items, source.items, config)
124126
}
125127

126-
return target
128+
return merged
127129
}
128130

129131
export const sampleFromSchemaGeneric = (schema, config={}, exampleOverride = undefined, respectXML = false) => {
@@ -138,7 +140,7 @@ export const sampleFromSchemaGeneric = (schema, config={}, exampleOverride = und
138140
? schema.oneOf[0]
139141
: schema.anyOf[0]
140142
)
141-
liftSampleHelper(schemaToAdd, schema, config)
143+
schema = mergeJsonSchema(schema, schemaToAdd, config)
142144
if(!schema.xml && schemaToAdd.xml) {
143145
schema.xml = schemaToAdd.xml
144146
}
@@ -537,9 +539,9 @@ export const sampleFromSchemaGeneric = (schema, config={}, exampleOverride = und
537539
}
538540

539541
if(Array.isArray(items.anyOf)) {
540-
sampleArray = items.anyOf.map(i => sampleFromSchemaGeneric(liftSampleHelper(items, i, config), config, undefined, respectXML))
542+
sampleArray = items.anyOf.map(i => sampleFromSchemaGeneric(mergeJsonSchema(i, items, config), config, undefined, respectXML))
541543
} else if(Array.isArray(items.oneOf)) {
542-
sampleArray = items.oneOf.map(i => sampleFromSchemaGeneric(liftSampleHelper(items, i, config), config, undefined, respectXML))
544+
sampleArray = items.oneOf.map(i => sampleFromSchemaGeneric(mergeJsonSchema(i, items, config), config, undefined, respectXML))
543545
} else if(!respectXML || respectXML && xml.wrapped) {
544546
sampleArray = [sampleFromSchemaGeneric(items, config, undefined, respectXML)]
545547
} else {

src/core/plugins/json-schema-5-samples/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
createXMLExample,
99
memoizedCreateXMLExample,
1010
memoizedSampleFromSchema,
11+
mergeJsonSchema,
1112
} from "./fn/index"
1213
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
1314
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
@@ -33,6 +34,7 @@ const JSONSchema5SamplesPlugin = ({ getSystem }) => {
3334
getYamlSampleSchema,
3435
getXmlSampleSchema,
3536
getSampleSchema,
37+
mergeJsonSchema,
3638
},
3739
inferSchema,
3840
sampleFromSchema,
@@ -44,6 +46,7 @@ const JSONSchema5SamplesPlugin = ({ getSystem }) => {
4446
getYamlSampleSchema,
4547
getXmlSampleSchema,
4648
getSampleSchema,
49+
mergeJsonSchema,
4750
},
4851
}
4952
}

src/core/plugins/oas31/after-load.js

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ function afterLoad({ fn, getSystem }) {
3131
getYamlSampleSchema: fn.jsonSchema202012.getYamlSampleSchema,
3232
getXmlSampleSchema: fn.jsonSchema202012.getXmlSampleSchema,
3333
getSampleSchema: fn.jsonSchema202012.getSampleSchema,
34+
mergeJsonSchema: fn.jsonSchema202012.mergeJsonSchema,
3435
},
3536
getSystem()
3637
)

test/unit/core/plugins/json-schema-2020-12-samples/fn.js

+53
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
sampleFromSchema,
99
memoizedCreateXMLExample,
1010
memoizedSampleFromSchema,
11+
mergeJsonSchema,
1112
} from "core/plugins/json-schema-2020-12-samples/fn"
1213

1314
describe("sampleFromSchema", () => {
@@ -2983,3 +2984,55 @@ describe("memoizedCreateXMLExample", () => {
29832984
).toEqual(updatedExpected)
29842985
})
29852986
})
2987+
2988+
describe("merge", function () {
2989+
it("should merge two schemas", function () {
2990+
const schema = {
2991+
properties: {
2992+
name: {
2993+
type: "string",
2994+
},
2995+
id: {
2996+
type: "integer",
2997+
},
2998+
},
2999+
example: {
3000+
name: "test",
3001+
id: 1,
3002+
},
3003+
required: ["name"],
3004+
}
3005+
3006+
const target = {
3007+
type: "object",
3008+
properties: {
3009+
username: {
3010+
type: "string",
3011+
},
3012+
},
3013+
required: ["username"],
3014+
}
3015+
3016+
const result = mergeJsonSchema(target, schema)
3017+
3018+
expect(result).toStrictEqual({
3019+
type: "object",
3020+
properties: {
3021+
username: {
3022+
type: "string",
3023+
},
3024+
name: {
3025+
type: "string",
3026+
},
3027+
id: {
3028+
type: "integer",
3029+
},
3030+
},
3031+
example: {
3032+
name: "test",
3033+
id: 1,
3034+
},
3035+
required: ["username", "name"],
3036+
})
3037+
})
3038+
})

test/unit/core/plugins/json-schema-5-samples/fn/index.js

+59-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { fromJS } from "immutable"
2-
import { createXMLExample, sampleFromSchema, memoizedCreateXMLExample, memoizedSampleFromSchema } from "core/plugins/json-schema-5-samples/fn/index"
2+
import {
3+
createXMLExample,
4+
sampleFromSchema,
5+
memoizedCreateXMLExample,
6+
memoizedSampleFromSchema,
7+
mergeJsonSchema,
8+
} from "core/plugins/json-schema-5-samples/fn/index"
39

410
describe("sampleFromSchema", () => {
511
it("handles Immutable.js objects for nested schemas", function () {
@@ -2438,3 +2444,55 @@ describe("memoizedCreateXMLExample", () => {
24382444
expect(memoizedCreateXMLExample(definition, {}, updatedOverrideExample)).toEqual(updatedExpected)
24392445
})
24402446
})
2447+
2448+
describe("mergeJsonSchema", function () {
2449+
it("should merge two schemas", function () {
2450+
const schema = {
2451+
properties: {
2452+
name: {
2453+
type: "string",
2454+
},
2455+
id: {
2456+
type: "integer",
2457+
},
2458+
},
2459+
example: {
2460+
name: "test",
2461+
id: 1,
2462+
},
2463+
required: ["name"],
2464+
}
2465+
2466+
const target = {
2467+
type: "object",
2468+
properties: {
2469+
username: {
2470+
type: "string",
2471+
},
2472+
},
2473+
required: ["username"],
2474+
}
2475+
2476+
const result = mergeJsonSchema(target, schema)
2477+
2478+
expect(result).toStrictEqual({
2479+
type: "object",
2480+
properties: {
2481+
username: {
2482+
type: "string",
2483+
},
2484+
name: {
2485+
type: "string",
2486+
},
2487+
id: {
2488+
type: "integer",
2489+
},
2490+
},
2491+
example: {
2492+
name: "test",
2493+
id: 1,
2494+
},
2495+
required: ["username", "name"],
2496+
})
2497+
})
2498+
})

0 commit comments

Comments
 (0)