fatsify核心功能示例测试!!!
This commit is contained in:
357
node_modules/@fastify/merge-json-schemas/index.js
generated
vendored
Normal file
357
node_modules/@fastify/merge-json-schemas/index.js
generated
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
'use strict'
|
||||
|
||||
const { dequal: deepEqual } = require('dequal')
|
||||
const resolvers = require('./lib/resolvers')
|
||||
const errors = require('./lib/errors')
|
||||
|
||||
const keywordsResolvers = {
|
||||
$id: resolvers.skip,
|
||||
type: resolvers.hybridArraysIntersection,
|
||||
enum: resolvers.arraysIntersection,
|
||||
minLength: resolvers.maxNumber,
|
||||
maxLength: resolvers.minNumber,
|
||||
minimum: resolvers.maxNumber,
|
||||
maximum: resolvers.minNumber,
|
||||
multipleOf: resolvers.commonMultiple,
|
||||
exclusiveMinimum: resolvers.maxNumber,
|
||||
exclusiveMaximum: resolvers.minNumber,
|
||||
minItems: resolvers.maxNumber,
|
||||
maxItems: resolvers.minNumber,
|
||||
maxProperties: resolvers.minNumber,
|
||||
minProperties: resolvers.maxNumber,
|
||||
const: resolvers.allEqual,
|
||||
default: resolvers.allEqual,
|
||||
format: resolvers.allEqual,
|
||||
required: resolvers.arraysUnion,
|
||||
properties: mergeProperties,
|
||||
patternProperties: mergeObjects,
|
||||
additionalProperties: mergeSchemasResolver,
|
||||
items: mergeItems,
|
||||
additionalItems: mergeAdditionalItems,
|
||||
definitions: mergeObjects,
|
||||
$defs: mergeObjects,
|
||||
nullable: resolvers.booleanAnd,
|
||||
oneOf: mergeOneOf,
|
||||
anyOf: mergeOneOf,
|
||||
allOf: resolvers.arraysUnion,
|
||||
not: mergeSchemasResolver,
|
||||
if: mergeIfThenElseSchemas,
|
||||
then: resolvers.skip,
|
||||
else: resolvers.skip,
|
||||
dependencies: mergeDependencies,
|
||||
dependentRequired: mergeDependencies,
|
||||
dependentSchemas: mergeObjects,
|
||||
propertyNames: mergeSchemasResolver,
|
||||
uniqueItems: resolvers.booleanOr,
|
||||
contains: mergeSchemasResolver
|
||||
}
|
||||
|
||||
function mergeSchemasResolver (keyword, values, mergedSchema, _schemas, options) {
|
||||
mergedSchema[keyword] = _mergeSchemas(values, options)
|
||||
}
|
||||
|
||||
function cartesianProduct (arrays) {
|
||||
let result = [[]]
|
||||
|
||||
for (const array of arrays) {
|
||||
const temp = []
|
||||
for (const x of result) {
|
||||
for (const y of array) {
|
||||
temp.push([...x, y])
|
||||
}
|
||||
}
|
||||
result = temp
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
function mergeOneOf (keyword, values, mergedSchema, _schemas, options) {
|
||||
if (values.length === 1) {
|
||||
mergedSchema[keyword] = values[0]
|
||||
return
|
||||
}
|
||||
|
||||
const product = cartesianProduct(values)
|
||||
const mergedOneOf = []
|
||||
for (const combination of product) {
|
||||
try {
|
||||
const mergedSchema = _mergeSchemas(combination, options)
|
||||
if (mergedSchema !== undefined) {
|
||||
mergedOneOf.push(mergedSchema)
|
||||
}
|
||||
} catch (error) {
|
||||
// If this combination is not valid, we can ignore it.
|
||||
if (error instanceof errors.MergeError) continue
|
||||
throw error
|
||||
}
|
||||
}
|
||||
mergedSchema[keyword] = mergedOneOf
|
||||
}
|
||||
|
||||
function getSchemaForItem (schema, index) {
|
||||
const { items, additionalItems } = schema
|
||||
|
||||
if (Array.isArray(items)) {
|
||||
if (index < items.length) {
|
||||
return items[index]
|
||||
}
|
||||
return additionalItems
|
||||
}
|
||||
|
||||
if (items !== undefined) {
|
||||
return items
|
||||
}
|
||||
|
||||
return additionalItems
|
||||
}
|
||||
|
||||
function mergeItems (keyword, values, mergedSchema, schemas, options) {
|
||||
let maxArrayItemsLength = 0
|
||||
for (const itemsSchema of values) {
|
||||
if (Array.isArray(itemsSchema)) {
|
||||
maxArrayItemsLength = Math.max(maxArrayItemsLength, itemsSchema.length)
|
||||
}
|
||||
}
|
||||
|
||||
if (maxArrayItemsLength === 0) {
|
||||
mergedSchema[keyword] = _mergeSchemas(values, options)
|
||||
return
|
||||
}
|
||||
|
||||
const mergedItemsSchemas = []
|
||||
for (let i = 0; i < maxArrayItemsLength; i++) {
|
||||
const indexItemSchemas = []
|
||||
for (const schema of schemas) {
|
||||
const itemSchema = getSchemaForItem(schema, i)
|
||||
if (itemSchema !== undefined) {
|
||||
indexItemSchemas.push(itemSchema)
|
||||
}
|
||||
}
|
||||
mergedItemsSchemas[i] = _mergeSchemas(indexItemSchemas, options)
|
||||
}
|
||||
mergedSchema[keyword] = mergedItemsSchemas
|
||||
}
|
||||
|
||||
function mergeAdditionalItems (keyword, values, mergedSchema, schemas, options) {
|
||||
let hasArrayItems = false
|
||||
for (const schema of schemas) {
|
||||
if (Array.isArray(schema.items)) {
|
||||
hasArrayItems = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasArrayItems) {
|
||||
mergedSchema[keyword] = _mergeSchemas(values, options)
|
||||
return
|
||||
}
|
||||
|
||||
const mergedAdditionalItemsSchemas = []
|
||||
for (const schema of schemas) {
|
||||
let additionalItemsSchema = schema.additionalItems
|
||||
if (
|
||||
additionalItemsSchema === undefined &&
|
||||
!Array.isArray(schema.items)
|
||||
) {
|
||||
additionalItemsSchema = schema.items
|
||||
}
|
||||
if (additionalItemsSchema !== undefined) {
|
||||
mergedAdditionalItemsSchemas.push(additionalItemsSchema)
|
||||
}
|
||||
}
|
||||
|
||||
mergedSchema[keyword] = _mergeSchemas(mergedAdditionalItemsSchemas, options)
|
||||
}
|
||||
|
||||
function getSchemaForProperty (schema, propertyName) {
|
||||
const { properties, patternProperties, additionalProperties } = schema
|
||||
|
||||
if (properties?.[propertyName] !== undefined) {
|
||||
return properties[propertyName]
|
||||
}
|
||||
|
||||
for (const pattern of Object.keys(patternProperties ?? {})) {
|
||||
const regexp = new RegExp(pattern)
|
||||
if (regexp.test(propertyName)) {
|
||||
return patternProperties[pattern]
|
||||
}
|
||||
}
|
||||
|
||||
return additionalProperties
|
||||
}
|
||||
|
||||
function mergeProperties (keyword, _values, mergedSchema, schemas, options) {
|
||||
const foundProperties = {}
|
||||
for (const currentSchema of schemas) {
|
||||
const properties = currentSchema.properties ?? {}
|
||||
for (const propertyName of Object.keys(properties)) {
|
||||
if (foundProperties[propertyName] !== undefined) continue
|
||||
|
||||
const propertySchema = properties[propertyName]
|
||||
foundProperties[propertyName] = [propertySchema]
|
||||
|
||||
for (const anotherSchema of schemas) {
|
||||
if (currentSchema === anotherSchema) continue
|
||||
|
||||
const propertySchema = getSchemaForProperty(anotherSchema, propertyName)
|
||||
if (propertySchema !== undefined) {
|
||||
foundProperties[propertyName].push(propertySchema)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mergedProperties = {}
|
||||
for (const property of Object.keys(foundProperties)) {
|
||||
const propertySchemas = foundProperties[property]
|
||||
mergedProperties[property] = _mergeSchemas(propertySchemas, options)
|
||||
}
|
||||
mergedSchema[keyword] = mergedProperties
|
||||
}
|
||||
|
||||
function mergeObjects (keyword, values, mergedSchema, _schemas, options) {
|
||||
const objectsProperties = {}
|
||||
|
||||
for (const properties of values) {
|
||||
for (const propertyName of Object.keys(properties)) {
|
||||
if (objectsProperties[propertyName] === undefined) {
|
||||
objectsProperties[propertyName] = []
|
||||
}
|
||||
objectsProperties[propertyName].push(properties[propertyName])
|
||||
}
|
||||
}
|
||||
|
||||
const mergedProperties = {}
|
||||
for (const propertyName of Object.keys(objectsProperties)) {
|
||||
const propertySchemas = objectsProperties[propertyName]
|
||||
const mergedPropertySchema = _mergeSchemas(propertySchemas, options)
|
||||
mergedProperties[propertyName] = mergedPropertySchema
|
||||
}
|
||||
|
||||
mergedSchema[keyword] = mergedProperties
|
||||
}
|
||||
|
||||
function mergeIfThenElseSchemas (_keyword, _values, mergedSchema, schemas, options) {
|
||||
for (let i = 0; i < schemas.length; i++) {
|
||||
const subSchema = {
|
||||
if: schemas[i].if,
|
||||
then: schemas[i].then,
|
||||
else: schemas[i].else
|
||||
}
|
||||
|
||||
if (subSchema.if === undefined) continue
|
||||
|
||||
if (mergedSchema.if === undefined) {
|
||||
mergedSchema.if = subSchema.if
|
||||
if (subSchema.then !== undefined) {
|
||||
mergedSchema.then = subSchema.then
|
||||
}
|
||||
if (subSchema.else !== undefined) {
|
||||
mergedSchema.else = subSchema.else
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (mergedSchema.then !== undefined) {
|
||||
mergedSchema.then = _mergeSchemas([mergedSchema.then, subSchema], options)
|
||||
}
|
||||
if (mergedSchema.else !== undefined) {
|
||||
mergedSchema.else = _mergeSchemas([mergedSchema.else, subSchema], options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mergeDependencies (keyword, values, mergedSchema) {
|
||||
const mergedDependencies = {}
|
||||
for (const dependencies of values) {
|
||||
for (const propertyName of Object.keys(dependencies)) {
|
||||
if (mergedDependencies[propertyName] === undefined) {
|
||||
mergedDependencies[propertyName] = []
|
||||
}
|
||||
const mergedPropertyDependencies = mergedDependencies[propertyName]
|
||||
for (const propertyDependency of dependencies[propertyName]) {
|
||||
if (!mergedPropertyDependencies.includes(propertyDependency)) {
|
||||
mergedPropertyDependencies.push(propertyDependency)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mergedSchema[keyword] = mergedDependencies
|
||||
}
|
||||
|
||||
function _mergeSchemas (schemas, options) {
|
||||
if (schemas.length === 0) return {}
|
||||
if (schemas.length === 1) return schemas[0]
|
||||
|
||||
const mergedSchema = {}
|
||||
const keywords = {}
|
||||
|
||||
let allSchemasAreTrue = true
|
||||
|
||||
for (const schema of schemas) {
|
||||
if (schema === false) return false
|
||||
if (schema === true) continue
|
||||
allSchemasAreTrue = false
|
||||
|
||||
for (const keyword of Object.keys(schema)) {
|
||||
if (keywords[keyword] === undefined) {
|
||||
keywords[keyword] = []
|
||||
}
|
||||
keywords[keyword].push(schema[keyword])
|
||||
}
|
||||
}
|
||||
|
||||
if (allSchemasAreTrue) return true
|
||||
|
||||
for (const keyword of Object.keys(keywords)) {
|
||||
const keywordValues = keywords[keyword]
|
||||
const resolver = options.resolvers[keyword] ?? options.defaultResolver
|
||||
resolver(keyword, keywordValues, mergedSchema, schemas, options)
|
||||
}
|
||||
|
||||
return mergedSchema
|
||||
}
|
||||
|
||||
function defaultResolver (keyword, values, mergedSchema, _schemas, options) {
|
||||
const onConflict = options.onConflict ?? 'throw'
|
||||
|
||||
if (values.length === 1 || onConflict === 'first') {
|
||||
mergedSchema[keyword] = values[0]
|
||||
return
|
||||
}
|
||||
|
||||
let allValuesEqual = true
|
||||
for (let i = 1; i < values.length; i++) {
|
||||
if (!deepEqual(values[i], values[0])) {
|
||||
allValuesEqual = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (allValuesEqual) {
|
||||
mergedSchema[keyword] = values[0]
|
||||
return
|
||||
}
|
||||
|
||||
if (onConflict === 'throw') {
|
||||
throw new errors.ResolverNotFoundError(keyword, values)
|
||||
}
|
||||
if (onConflict === 'skip') {
|
||||
return
|
||||
}
|
||||
throw new errors.InvalidOnConflictOptionError(onConflict)
|
||||
}
|
||||
|
||||
function mergeSchemas (schemas, options = {}) {
|
||||
if (options.defaultResolver === undefined) {
|
||||
options.defaultResolver = defaultResolver
|
||||
}
|
||||
|
||||
options.resolvers = { ...keywordsResolvers, ...options.resolvers }
|
||||
|
||||
const mergedSchema = _mergeSchemas(schemas, options)
|
||||
return mergedSchema
|
||||
}
|
||||
|
||||
module.exports = { mergeSchemas, keywordsResolvers, defaultResolver, ...errors }
|
||||
Reference in New Issue
Block a user