Buckets:
| 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 } | |
Xet Storage Details
- Size:
- 9.99 kB
- Xet hash:
- 4321a7f39880ca67aa255c172de25f233c6fcdb73a0eb88f0e61dfe997a5b29d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.