Skip to content

Commit b52c99a

Browse files
perf: add schemas to the validator only if they are needed (#534)
1 parent c60ca4f commit b52c99a

File tree

2 files changed

+37
-21
lines changed

2 files changed

+37
-21
lines changed

index.js

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,30 +72,30 @@ function resolveRef (location, ref) {
7272

7373
const contextFunctionsNamesBySchema = new Map()
7474

75+
let isValidatorUsed = null
7576
let rootSchemaId = null
7677
let refResolver = null
77-
let validator = null
7878
let contextFunctions = null
79+
let mergeAllOfSchemas = null
7980

8081
function build (schema, options) {
8182
contextFunctionsNamesBySchema.clear()
8283

84+
isValidatorUsed = false
8385
contextFunctions = []
86+
mergeAllOfSchemas = {}
8487
options = options || {}
8588

8689
refResolver = new RefResolver()
87-
validator = new Validator(options.ajv)
8890

8991
rootSchemaId = schema.$id || randomUUID()
9092

9193
isValidSchema(schema)
92-
validator.addSchema(schema, rootSchemaId)
9394
refResolver.addSchema(schema, rootSchemaId)
9495

9596
if (options.schema) {
9697
for (const key of Object.keys(options.schema)) {
9798
isValidSchema(options.schema[key], key)
98-
validator.addSchema(options.schema[key], key)
9999
refResolver.addSchema(options.schema[key], key)
100100
}
101101
}
@@ -122,8 +122,6 @@ function build (schema, options) {
122122
}
123123
}
124124

125-
const serializer = new Serializer(options)
126-
127125
const location = { schema, schemaId: rootSchemaId, jsonPointer: '#' }
128126
const code = buildValue(location, 'input')
129127

@@ -135,7 +133,19 @@ function build (schema, options) {
135133
}
136134
${contextFunctions.join('\n')}
137135
return main
138-
`
136+
`
137+
138+
const serializer = new Serializer(options)
139+
const validator = new Validator(options.ajv)
140+
141+
if (isValidatorUsed) {
142+
validator.addSchema(schema, rootSchemaId)
143+
const externalSchemas = options.schema || {}
144+
const validatorSchemas = { ...externalSchemas, ...mergeAllOfSchemas }
145+
for (const [schemaKey, schema] of Object.entries(validatorSchemas)) {
146+
validator.addSchema(schema, schemaKey)
147+
}
148+
}
139149

140150
const dependenciesName = ['validator', 'serializer', contextFunctionCode]
141151

@@ -155,17 +165,18 @@ function build (schema, options) {
155165
if (options.mode === 'standalone') {
156166
// lazy load
157167
const buildStandaloneCode = require('./lib/standalone')
158-
return buildStandaloneCode(options, validator, contextFunctionCode)
168+
return buildStandaloneCode(options, validator, isValidatorUsed, contextFunctionCode)
159169
}
160170

161171
/* eslint no-new-func: "off" */
162172
const contextFunc = new Function('validator', 'serializer', contextFunctionCode)
163173
const stringifyFunc = contextFunc(validator, serializer)
164174

175+
isValidatorUsed = false
165176
refResolver = null
166-
validator = null
167177
rootSchemaId = null
168178
contextFunctions = null
179+
mergeAllOfSchemas = null
169180
contextFunctionsNamesBySchema.clear()
170181

171182
return stringifyFunc
@@ -466,7 +477,7 @@ function mergeAllOfSchema (location, schema, mergedSchema) {
466477
delete mergedSchema.allOf
467478

468479
mergedSchema.$id = `merged_${randomUUID()}`
469-
validator.addSchema(mergedSchema)
480+
mergeAllOfSchemas[mergedSchema.$id] = mergedSchema
470481
refResolver.addSchema(mergedSchema)
471482
location.schemaId = mergedSchema.$id
472483
location.jsonPointer = '#'
@@ -484,6 +495,8 @@ function buildInnerObject (location) {
484495
}
485496

486497
function addIfThenElse (location, input) {
498+
isValidatorUsed = true
499+
487500
const schema = merge({}, location.schema)
488501
const thenSchema = schema.then
489502
const elseSchema = schema.else || { additionalProperties: true }
@@ -861,6 +874,8 @@ function buildValue (location, input) {
861874
let code = ''
862875

863876
if (type === undefined && (schema.anyOf || schema.oneOf)) {
877+
isValidatorUsed = true
878+
864879
const type = schema.anyOf ? 'anyOf' : 'oneOf'
865880
const anyOfLocation = mergeLocation(location, type)
866881

lib/standalone.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
const fs = require('fs')
22
const path = require('path')
33

4-
function buildStandaloneCode (options, validator, contextFunctionCode) {
4+
function buildStandaloneCode (options, validator, isValidatorUsed, contextFunctionCode) {
55
const serializerCode = fs.readFileSync(path.join(__dirname, 'serializer.js')).toString()
66
let buildAjvCode = ''
7-
let defaultAjvSchema = ''
8-
const defaultMeta = validator.ajv.defaultMeta()
9-
if (typeof defaultMeta === 'string') {
10-
defaultAjvSchema = defaultMeta
11-
} else {
12-
defaultAjvSchema = defaultMeta.$id || defaultMeta.id
13-
}
14-
const shouldUseAjv = contextFunctionCode.indexOf('validator') !== -1
15-
// we need to export the custom json schema
167
let ajvSchemasCode = ''
17-
if (shouldUseAjv) {
8+
9+
if (isValidatorUsed) {
10+
let defaultAjvSchema = ''
11+
// we need to export the custom json schema
12+
const defaultMeta = validator.ajv.defaultMeta()
13+
if (typeof defaultMeta === 'string') {
14+
defaultAjvSchema = defaultMeta
15+
} else {
16+
defaultAjvSchema = defaultMeta.$id || defaultMeta.id
17+
}
18+
1819
ajvSchemasCode += `const validator = new Validator(${JSON.stringify(options.ajv || {})})\n`
1920
for (const [id, schema] of Object.entries(validator.ajv.schemas)) {
2021
// should skip ajv default schema

0 commit comments

Comments
 (0)