feat(plugins): expose JSON Schema merging mechanism from samples plugins (#9766)
Refs #9765
This commit is contained in:
@@ -11,3 +11,4 @@ export {
|
|||||||
export { default as encoderAPI } from "./api/encoderAPI"
|
export { default as encoderAPI } from "./api/encoderAPI"
|
||||||
export { default as formatAPI } from "./api/formatAPI"
|
export { default as formatAPI } from "./api/formatAPI"
|
||||||
export { default as mediaTypeAPI } from "./api/mediaTypeAPI"
|
export { default as mediaTypeAPI } from "./api/mediaTypeAPI"
|
||||||
|
export { default as mergeJsonSchema } from "./core/merge"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
encoderAPI,
|
encoderAPI,
|
||||||
mediaTypeAPI,
|
mediaTypeAPI,
|
||||||
formatAPI,
|
formatAPI,
|
||||||
|
mergeJsonSchema,
|
||||||
} from "./fn/index"
|
} from "./fn/index"
|
||||||
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
|
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
|
||||||
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
|
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
|
||||||
@@ -37,6 +38,7 @@ const JSONSchema202012SamplesPlugin = ({ getSystem }) => {
|
|||||||
getYamlSampleSchema,
|
getYamlSampleSchema,
|
||||||
getXmlSampleSchema,
|
getXmlSampleSchema,
|
||||||
getSampleSchema,
|
getSampleSchema,
|
||||||
|
mergeJsonSchema,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,10 +56,12 @@ const numberContracts = [
|
|||||||
]
|
]
|
||||||
const stringContracts = ["minLength", "maxLength"]
|
const stringContracts = ["minLength", "maxLength"]
|
||||||
|
|
||||||
const liftSampleHelper = (oldSchema, target, config = {}) => {
|
export const mergeJsonSchema = (target, source, config = {}) => {
|
||||||
|
const merged = { ...target }
|
||||||
|
|
||||||
const setIfNotDefinedInTarget = (key) => {
|
const setIfNotDefinedInTarget = (key) => {
|
||||||
if(target[key] === undefined && oldSchema[key] !== undefined) {
|
if(merged[key] === undefined && source[key] !== undefined) {
|
||||||
target[key] = oldSchema[key]
|
merged[key] = source[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,22 +77,22 @@ const liftSampleHelper = (oldSchema, target, config = {}) => {
|
|||||||
...stringContracts,
|
...stringContracts,
|
||||||
].forEach(key => setIfNotDefinedInTarget(key))
|
].forEach(key => setIfNotDefinedInTarget(key))
|
||||||
|
|
||||||
if(oldSchema.required !== undefined && Array.isArray(oldSchema.required)) {
|
if(source.required !== undefined && Array.isArray(source.required)) {
|
||||||
if(target.required === undefined || !target.required.length) {
|
if(merged.required === undefined || !merged.required.length) {
|
||||||
target.required = []
|
merged.required = []
|
||||||
}
|
}
|
||||||
oldSchema.required.forEach(key => {
|
source.required.forEach(key => {
|
||||||
if(target.required.includes(key)) {
|
if(merged.required.includes(key)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
target.required.push(key)
|
merged.required.push(key)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if(oldSchema.properties) {
|
if(source.properties) {
|
||||||
if(!target.properties) {
|
if(!merged.properties) {
|
||||||
target.properties = {}
|
merged.properties = {}
|
||||||
}
|
}
|
||||||
let props = objectify(oldSchema.properties)
|
let props = objectify(source.properties)
|
||||||
for (let propName in props) {
|
for (let propName in props) {
|
||||||
if (!Object.prototype.hasOwnProperty.call(props, propName)) {
|
if (!Object.prototype.hasOwnProperty.call(props, propName)) {
|
||||||
continue
|
continue
|
||||||
@@ -104,26 +106,26 @@ const liftSampleHelper = (oldSchema, target, config = {}) => {
|
|||||||
if ( props[propName] && props[propName].writeOnly && !config.includeWriteOnly ) {
|
if ( props[propName] && props[propName].writeOnly && !config.includeWriteOnly ) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if(!target.properties[propName]) {
|
if(!merged.properties[propName]) {
|
||||||
target.properties[propName] = props[propName]
|
merged.properties[propName] = props[propName]
|
||||||
if(!oldSchema.required && Array.isArray(oldSchema.required) && oldSchema.required.indexOf(propName) !== -1) {
|
if(!source.required && Array.isArray(source.required) && source.required.indexOf(propName) !== -1) {
|
||||||
if(!target.required) {
|
if(!merged.required) {
|
||||||
target.required = [propName]
|
merged.required = [propName]
|
||||||
} else {
|
} else {
|
||||||
target.required.push(propName)
|
merged.required.push(propName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(oldSchema.items) {
|
if(source.items) {
|
||||||
if(!target.items) {
|
if(!merged.items) {
|
||||||
target.items = {}
|
merged.items = {}
|
||||||
}
|
}
|
||||||
target.items = liftSampleHelper(oldSchema.items, target.items, config)
|
merged.items = mergeJsonSchema(merged.items, source.items, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
return target
|
return merged
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sampleFromSchemaGeneric = (schema, config={}, exampleOverride = undefined, respectXML = false) => {
|
export const sampleFromSchemaGeneric = (schema, config={}, exampleOverride = undefined, respectXML = false) => {
|
||||||
@@ -138,7 +140,7 @@ export const sampleFromSchemaGeneric = (schema, config={}, exampleOverride = und
|
|||||||
? schema.oneOf[0]
|
? schema.oneOf[0]
|
||||||
: schema.anyOf[0]
|
: schema.anyOf[0]
|
||||||
)
|
)
|
||||||
liftSampleHelper(schemaToAdd, schema, config)
|
schema = mergeJsonSchema(schema, schemaToAdd, config)
|
||||||
if(!schema.xml && schemaToAdd.xml) {
|
if(!schema.xml && schemaToAdd.xml) {
|
||||||
schema.xml = schemaToAdd.xml
|
schema.xml = schemaToAdd.xml
|
||||||
}
|
}
|
||||||
@@ -537,9 +539,9 @@ export const sampleFromSchemaGeneric = (schema, config={}, exampleOverride = und
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(Array.isArray(items.anyOf)) {
|
if(Array.isArray(items.anyOf)) {
|
||||||
sampleArray = items.anyOf.map(i => sampleFromSchemaGeneric(liftSampleHelper(items, i, config), config, undefined, respectXML))
|
sampleArray = items.anyOf.map(i => sampleFromSchemaGeneric(mergeJsonSchema(i, items, config), config, undefined, respectXML))
|
||||||
} else if(Array.isArray(items.oneOf)) {
|
} else if(Array.isArray(items.oneOf)) {
|
||||||
sampleArray = items.oneOf.map(i => sampleFromSchemaGeneric(liftSampleHelper(items, i, config), config, undefined, respectXML))
|
sampleArray = items.oneOf.map(i => sampleFromSchemaGeneric(mergeJsonSchema(i, items, config), config, undefined, respectXML))
|
||||||
} else if(!respectXML || respectXML && xml.wrapped) {
|
} else if(!respectXML || respectXML && xml.wrapped) {
|
||||||
sampleArray = [sampleFromSchemaGeneric(items, config, undefined, respectXML)]
|
sampleArray = [sampleFromSchemaGeneric(items, config, undefined, respectXML)]
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
createXMLExample,
|
createXMLExample,
|
||||||
memoizedCreateXMLExample,
|
memoizedCreateXMLExample,
|
||||||
memoizedSampleFromSchema,
|
memoizedSampleFromSchema,
|
||||||
|
mergeJsonSchema,
|
||||||
} from "./fn/index"
|
} from "./fn/index"
|
||||||
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
|
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
|
||||||
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
|
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
|
||||||
@@ -33,6 +34,7 @@ const JSONSchema5SamplesPlugin = ({ getSystem }) => {
|
|||||||
getYamlSampleSchema,
|
getYamlSampleSchema,
|
||||||
getXmlSampleSchema,
|
getXmlSampleSchema,
|
||||||
getSampleSchema,
|
getSampleSchema,
|
||||||
|
mergeJsonSchema,
|
||||||
},
|
},
|
||||||
inferSchema,
|
inferSchema,
|
||||||
sampleFromSchema,
|
sampleFromSchema,
|
||||||
@@ -44,6 +46,7 @@ const JSONSchema5SamplesPlugin = ({ getSystem }) => {
|
|||||||
getYamlSampleSchema,
|
getYamlSampleSchema,
|
||||||
getXmlSampleSchema,
|
getXmlSampleSchema,
|
||||||
getSampleSchema,
|
getSampleSchema,
|
||||||
|
mergeJsonSchema,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ function afterLoad({ fn, getSystem }) {
|
|||||||
getYamlSampleSchema: fn.jsonSchema202012.getYamlSampleSchema,
|
getYamlSampleSchema: fn.jsonSchema202012.getYamlSampleSchema,
|
||||||
getXmlSampleSchema: fn.jsonSchema202012.getXmlSampleSchema,
|
getXmlSampleSchema: fn.jsonSchema202012.getXmlSampleSchema,
|
||||||
getSampleSchema: fn.jsonSchema202012.getSampleSchema,
|
getSampleSchema: fn.jsonSchema202012.getSampleSchema,
|
||||||
|
mergeJsonSchema: fn.jsonSchema202012.mergeJsonSchema,
|
||||||
},
|
},
|
||||||
getSystem()
|
getSystem()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
sampleFromSchema,
|
sampleFromSchema,
|
||||||
memoizedCreateXMLExample,
|
memoizedCreateXMLExample,
|
||||||
memoizedSampleFromSchema,
|
memoizedSampleFromSchema,
|
||||||
|
mergeJsonSchema,
|
||||||
} from "core/plugins/json-schema-2020-12-samples/fn"
|
} from "core/plugins/json-schema-2020-12-samples/fn"
|
||||||
|
|
||||||
describe("sampleFromSchema", () => {
|
describe("sampleFromSchema", () => {
|
||||||
@@ -2983,3 +2984,55 @@ describe("memoizedCreateXMLExample", () => {
|
|||||||
).toEqual(updatedExpected)
|
).toEqual(updatedExpected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("merge", function () {
|
||||||
|
it("should merge two schemas", function () {
|
||||||
|
const schema = {
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: "integer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
name: "test",
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
required: ["name"],
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
username: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["username"],
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = mergeJsonSchema(target, schema)
|
||||||
|
|
||||||
|
expect(result).toStrictEqual({
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
username: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: "integer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
name: "test",
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
required: ["username", "name"],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { fromJS } from "immutable"
|
import { fromJS } from "immutable"
|
||||||
import { createXMLExample, sampleFromSchema, memoizedCreateXMLExample, memoizedSampleFromSchema } from "core/plugins/json-schema-5-samples/fn/index"
|
import {
|
||||||
|
createXMLExample,
|
||||||
|
sampleFromSchema,
|
||||||
|
memoizedCreateXMLExample,
|
||||||
|
memoizedSampleFromSchema,
|
||||||
|
mergeJsonSchema,
|
||||||
|
} from "core/plugins/json-schema-5-samples/fn/index"
|
||||||
|
|
||||||
describe("sampleFromSchema", () => {
|
describe("sampleFromSchema", () => {
|
||||||
it("handles Immutable.js objects for nested schemas", function () {
|
it("handles Immutable.js objects for nested schemas", function () {
|
||||||
@@ -2438,3 +2444,55 @@ describe("memoizedCreateXMLExample", () => {
|
|||||||
expect(memoizedCreateXMLExample(definition, {}, updatedOverrideExample)).toEqual(updatedExpected)
|
expect(memoizedCreateXMLExample(definition, {}, updatedOverrideExample)).toEqual(updatedExpected)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("mergeJsonSchema", function () {
|
||||||
|
it("should merge two schemas", function () {
|
||||||
|
const schema = {
|
||||||
|
properties: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: "integer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
name: "test",
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
required: ["name"],
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
username: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["username"],
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = mergeJsonSchema(target, schema)
|
||||||
|
|
||||||
|
expect(result).toStrictEqual({
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
username: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: "integer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
name: "test",
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
required: ["username", "name"],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user