Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* @prettier
*/
import { isBooleanJSONSchema, isJSONSchema } from "./predicates"

const merge = (target, source, config = {}) => {
if (isBooleanJSONSchema(target) && target === true) return true
if (isBooleanJSONSchema(target) && target === false) return false
if (isBooleanJSONSchema(source) && source === true) return true
if (isBooleanJSONSchema(source) && source === false) return false

if (!isJSONSchema(target)) return source
if (!isJSONSchema(source)) return target

/**
* Merging properties from the source object into the target object
* only if they do not already exist in the target object.
*/
const merged = { ...source, ...target }

// merging required keyword
if (Array.isArray(source.required) && Array.isArray(target.required)) {
merged.required = [...new Set([...target.required, ...source.required])]
}

// merging properties keyword
if (source.properties && target.properties) {
const allPropertyNames = new Set([
...Object.keys(source.properties),
...Object.keys(target.properties),
])

merged.properties = {}
for (const name of allPropertyNames) {
const sourceProperty = source.properties[name] || {}
const targetProperty = target.properties[name] || {}

if (
(sourceProperty.readOnly && !config.includeReadOnly) ||
(sourceProperty.writeOnly && !config.includeWriteOnly)
) {
merged.required = (merged.required || []).filter((p) => p !== name)
} else {
merged.properties[name] = merge(targetProperty, sourceProperty, config)
}
}
}

// merging items keyword
if (isJSONSchema(source.items) && isJSONSchema(target.items)) {
merged.items = merge(target.items, source.items, config)
}

// merging contains keyword
if (isJSONSchema(source.contains) && isJSONSchema(target.contains)) {
merged.contains = merge(target.contains, source.contains, config)
}

// merging contentSchema keyword
if (
isJSONSchema(source.contentSchema) &&
isJSONSchema(target.contentSchema)
) {
merged.contentSchema = merge(
target.contentSchema,
source.contentSchema,
config
)
}

return merged
}

export default merge
127 changes: 11 additions & 116 deletions src/core/plugins/json-schema-2020-12/samples-extensions/fn/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,113 +11,8 @@ import { getType } from "./core/type"
import { typeCast } from "./core/utils"
import { hasExample, extractExample } from "./core/example"
import { pick as randomPick } from "./core/random"

const objectConstraints = ["maxProperties", "minProperties", "required"]
const arrayConstraints = [
"minItems",
"maxItems",
"uniqueItems",
"minContains",
"maxContains",
]
const numberConstraints = [
"minimum",
"maximum",
"exclusiveMinimum",
"exclusiveMaximum",
"multipleOf",
]
const stringConstraints = [
"minLength",
"maxLength",
"pattern",
"contentEncoding",
"contentMediaType",
]

const liftSampleHelper = (oldSchema, target, config = {}) => {
const setIfNotDefinedInTarget = (key) => {
if (target[key] === undefined && oldSchema[key] !== undefined) {
target[key] = oldSchema[key]
}
}

;[
"examples",
"example",
"default",
"enum",
"xml",
"type",
"const",
...objectConstraints,
...arrayConstraints,
...numberConstraints,
...stringConstraints,
].forEach((key) => setIfNotDefinedInTarget(key))

if (oldSchema.required !== undefined && Array.isArray(oldSchema.required)) {
if (target.required === undefined || !target.required.length) {
target.required = []
}
oldSchema.required.forEach((key) => {
if (target.required.includes(key)) {
return
}
target.required.push(key)
})
}
if (oldSchema.properties) {
if (!target.properties) {
target.properties = {}
}
let props = objectify(oldSchema.properties)
for (let propName in props) {
if (!Object.hasOwn(props, propName)) {
continue
}
if (props[propName] && props[propName].deprecated) {
continue
}
if (
props[propName] &&
props[propName].readOnly &&
!config.includeReadOnly
) {
continue
}
if (
props[propName] &&
props[propName].writeOnly &&
!config.includeWriteOnly
) {
continue
}
if (!target.properties[propName]) {
target.properties[propName] = props[propName]
if (
!oldSchema.required &&
Array.isArray(oldSchema.required) &&
oldSchema.required.indexOf(propName) !== -1
) {
if (!target.required) {
target.required = [propName]
} else {
target.required.push(propName)
}
}
}
}
}
if (oldSchema.items) {
if (!target.items) {
target.items = {}
}
target.items = liftSampleHelper(oldSchema.items, target.items, config)
}

return target
}
import merge from "./core/merge"
import { isBooleanJSONSchema, isJSONSchemaObject } from "./core/predicates"

export const sampleFromSchemaGeneric = (
schema,
Expand All @@ -138,7 +33,7 @@ export const sampleFromSchemaGeneric = (
const schemaToAdd = typeCast(
hasOneOf ? randomPick(schema.oneOf) : randomPick(schema.anyOf)
)
liftSampleHelper(schemaToAdd, schema, config)
schema = merge(schema, schemaToAdd, config)
if (!schema.xml && schemaToAdd.xml) {
schema.xml = schemaToAdd.xml
}
Expand Down Expand Up @@ -489,9 +384,9 @@ export const sampleFromSchemaGeneric = (

if (Array.isArray(contains.anyOf)) {
sampleArray.push(
...contains.anyOf.map((i) =>
...contains.anyOf.map((anyOfSchema) =>
sampleFromSchemaGeneric(
liftSampleHelper(contains, i, config),
merge(anyOfSchema, contains, config),
config,
undefined,
respectXML
Expand All @@ -500,9 +395,9 @@ export const sampleFromSchemaGeneric = (
)
} else if (Array.isArray(contains.oneOf)) {
sampleArray.push(
...contains.oneOf.map((i) =>
...contains.oneOf.map((oneOfSchema) =>
sampleFromSchemaGeneric(
liftSampleHelper(contains, i, config),
merge(oneOfSchema, contains, config),
config,
undefined,
respectXML
Expand All @@ -528,7 +423,7 @@ export const sampleFromSchemaGeneric = (
sampleArray.push(
...items.anyOf.map((i) =>
sampleFromSchemaGeneric(
liftSampleHelper(items, i, config),
merge(i, items, config),
config,
undefined,
respectXML
Expand All @@ -539,7 +434,7 @@ export const sampleFromSchemaGeneric = (
sampleArray.push(
...items.oneOf.map((i) =>
sampleFromSchemaGeneric(
liftSampleHelper(items, i, config),
merge(i, items, config),
config,
undefined,
respectXML
Expand Down Expand Up @@ -591,14 +486,14 @@ export const sampleFromSchemaGeneric = (
return res
}

if (additionalProperties === true) {
if (isBooleanJSONSchema(additionalProperties)) {
if (respectXML) {
res[displayName].push({ additionalProp: "Anything can be here" })
} else {
res.additionalProp1 = {}
}
propertyAddedCounter++
} else if (additionalProperties) {
} else if (isJSONSchemaObject(additionalProperties)) {
const additionalProps = typeCast(additionalProperties)
const additionalPropSample = sampleFromSchemaGeneric(
additionalProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ describe("sampleFromSchema", () => {
expect(sampleFromSchema(definition)).toEqual(expected)
})

it("should lift items with anyOf", () => {
it("should merge items with anyOf", () => {
const definition = {
type: "array",
anyOf: [
Expand All @@ -1172,7 +1172,7 @@ describe("sampleFromSchema", () => {
expect(sampleFromSchema(definition)).toEqual(expected)
})

it("should lift items with oneOf", () => {
it("should merge items with oneOf", () => {
const definition = {
type: "array",
oneOf: [
Expand Down