@@ -7,6 +7,7 @@ const ajvFormats = require('ajv-formats')
7
7
const merge = require ( 'deepmerge' )
8
8
const clone = require ( 'rfdc' ) ( { proto : true } )
9
9
const fjsCloned = Symbol ( 'fast-json-stringify.cloned' )
10
+ const { randomUUID } = require ( 'crypto' )
10
11
11
12
const validate = require ( './schema-validator' )
12
13
let stringSimilarity = null
@@ -43,11 +44,17 @@ function mergeLocation (source, dest) {
43
44
44
45
const arrayItemsReferenceSerializersMap = new Map ( )
45
46
const objectReferenceSerializersMap = new Map ( )
47
+ let ajvInstance = null
46
48
47
49
function build ( schema , options ) {
48
50
arrayItemsReferenceSerializersMap . clear ( )
49
51
objectReferenceSerializersMap . clear ( )
52
+
50
53
options = options || { }
54
+
55
+ ajvInstance = new Ajv ( { ...options . ajv , strictSchema : false } )
56
+ ajvFormats ( ajvInstance )
57
+
51
58
isValidSchema ( schema )
52
59
if ( options . schema ) {
53
60
// eslint-disable-next-line
@@ -72,41 +79,6 @@ function build (schema, options) {
72
79
73
80
code += `
74
81
${ asFunctions }
75
-
76
-
77
- /**
78
- * Used by schemas that are dependant on calling 'ajv.validate' during runtime,
79
- * it stores the value of the '$id' property of the schema (if it has it) inside
80
- * a cache which is used to figure out if the schema was compiled into a validator
81
- * by ajv on a previous call, if it was then the '$id' string will be used to
82
- * invoke 'ajv.validate', this allows:
83
- *
84
- * 1. Schemas that depend on ajv.validate calls to leverage ajv caching system.
85
- * 2. To avoid errors, since directly invoking 'ajv.validate' with the same
86
- * schema (that contains an '$id' property) twice will throw an error.
87
- */
88
- const $validateWithAjv = (function() {
89
- const cache = new Set()
90
-
91
- return function (schema, target) {
92
- const id = schema.$id
93
-
94
- if (!id) {
95
- return ajv.validate(schema, target)
96
- }
97
-
98
- const cached = cache.has(id)
99
-
100
- if (cached) {
101
- return ajv.validate(id, target)
102
- } else {
103
- cache.add(id)
104
- return ajv.validate(schema, target)
105
- }
106
- }
107
- })()
108
-
109
-
110
82
function parseInteger(int) { return Math.${ intParseFunctionName } (int) }
111
83
`
112
84
@@ -163,18 +135,17 @@ function build (schema, options) {
163
135
;
164
136
return ${ main }
165
137
`
166
-
167
- const ajvInstance = new Ajv ( options . ajv )
168
- ajvFormats ( ajvInstance )
169
138
const dependencies = [ ajvInstance ]
170
139
const dependenciesName = [ 'ajv' ]
140
+ ajvInstance = null
141
+
171
142
dependenciesName . push ( code )
172
143
173
144
if ( options . debugMode ) {
174
- dependenciesName . toString = function ( ) {
175
- return dependenciesName . join ( '\n' )
145
+ return {
146
+ code : dependenciesName . join ( '\n' ) ,
147
+ ajv : dependencies [ 0 ]
176
148
}
177
- return dependenciesName
178
149
}
179
150
180
151
arrayItemsReferenceSerializersMap . clear ( )
@@ -874,8 +845,11 @@ function addIfThenElse (location, name) {
874
845
let merged = merge ( copy , then )
875
846
let mergedLocation = mergeLocation ( location , { schema : merged } )
876
847
848
+ const schemaKey = i . $id || randomUUID ( )
849
+ ajvInstance . addSchema ( i , schemaKey )
850
+
877
851
code += `
878
- valid = $validateWithAjv (${ JSON . stringify ( i ) } , obj)
852
+ valid = ajv.validate (${ JSON . stringify ( schemaKey ) } , obj)
879
853
if (valid) {
880
854
`
881
855
if ( merged . if && merged . then ) {
@@ -1224,8 +1198,12 @@ function nested (laterCode, name, key, location, subKey, isArray) {
1224
1198
// with the actual schema
1225
1199
// 2. `nested`, through `buildCode`, replaces any reference in object properties with the actual schema
1226
1200
// (see https://github.com/fastify/fast-json-stringify/blob/6da3b3e8ac24b1ca5578223adedb4083b7adf8db/index.js#L631)
1201
+
1202
+ const schemaKey = location . schema . $id || randomUUID ( )
1203
+ ajvInstance . addSchema ( location . schema , schemaKey )
1204
+
1227
1205
code += `
1228
- ${ index === 0 ? 'if' : 'else if' } ($validateWithAjv (${ JSON . stringify ( location . schema ) } , ${ testValue } ))
1206
+ ${ index === 0 ? 'if' : 'else if' } (ajv.validate (${ JSON . stringify ( schemaKey ) } , ${ testValue } ))
1229
1207
${ nestedResult . code }
1230
1208
`
1231
1209
laterCode = nestedResult . laterCode
@@ -1241,8 +1219,12 @@ function nested (laterCode, name, key, location, subKey, isArray) {
1241
1219
const testSerializer = getTestSerializer ( location . schema . format )
1242
1220
const testValue = testSerializer !== undefined ? `${ testSerializer } (obj${ accessor } , true)` : `obj${ accessor } `
1243
1221
// see comment on anyOf about dereferencing the schema before calling ajv.validate
1222
+
1223
+ const schemaKey = location . schema . $id || randomUUID ( )
1224
+ ajvInstance . addSchema ( location . schema , schemaKey )
1225
+
1244
1226
code += `
1245
- ${ index === 0 ? 'if' : 'else if' } ($validateWithAjv (${ JSON . stringify ( location . schema ) } , ${ testValue } ))
1227
+ ${ index === 0 ? 'if' : 'else if' } (ajv.validate (${ JSON . stringify ( schemaKey ) } , ${ testValue } ))
1246
1228
${ nestedResult . code }
1247
1229
`
1248
1230
laterCode = nestedResult . laterCode
@@ -1352,17 +1334,8 @@ function isEmpty (schema) {
1352
1334
1353
1335
module . exports = build
1354
1336
1355
- module . exports . restore = function ( debugModeStr , options = { } ) {
1356
- const dependencies = [ debugModeStr ]
1357
- const args = [ ]
1358
- if ( debugModeStr . startsWith ( 'ajv' ) ) {
1359
- dependencies . unshift ( 'ajv' )
1360
- const ajvInstance = new Ajv ( options . ajv )
1361
- ajvFormats ( ajvInstance )
1362
- args . push ( ajvInstance )
1363
- }
1364
-
1337
+ module . exports . restore = function ( { code, ajv } ) {
1365
1338
// eslint-disable-next-line
1366
- return ( Function . apply ( null , [ 'ajv' , debugModeStr ] )
1367
- . apply ( null , args ) )
1339
+ return ( Function . apply ( null , [ 'ajv' , code ] )
1340
+ . apply ( null , [ ajv ] ) )
1368
1341
}
0 commit comments