Skip to content

Commit 703ced8

Browse files
feat: export standalone dependencies (#617)
1 parent 895892c commit 703ced8

File tree

6 files changed

+58
-44
lines changed

6 files changed

+58
-44
lines changed

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -689,8 +689,7 @@ console.log(stringify({ firstName: 'Foo', surname: 'bar' })) // '{"firstName":"F
689689
### Standalone Mode
690690

691691
The standalone mode is used to compile the code that can be directly run by `node`
692-
itself. You need to install `ajv`, `fast-uri` and `ajv-formats` for
693-
the standalone code to work.
692+
itself. You need to have `fast-json-stringify` installed for the standalone code to work.
694693

695694
```js
696695
const fs = require('fs')

index.js

+5-8
Original file line numberDiff line numberDiff line change
@@ -170,18 +170,15 @@ function build (schema, options) {
170170
}
171171
}
172172

173+
/* eslint no-new-func: "off" */
174+
const contextFunc = new Function('validator', 'serializer', contextFunctionCode)
175+
173176
if (options.mode === 'standalone') {
174-
// lazy load
175-
const isValidatorUsed = context.validatorSchemasIds.size > 0
176177
const buildStandaloneCode = require('./lib/standalone')
177-
return buildStandaloneCode(options, validator, isValidatorUsed, contextFunctionCode)
178+
return buildStandaloneCode(contextFunc, context, serializer, validator)
178179
}
179180

180-
/* eslint no-new-func: "off" */
181-
const contextFunc = new Function('validator', 'serializer', contextFunctionCode)
182-
const stringifyFunc = contextFunc(validator, serializer)
183-
184-
return stringifyFunc
181+
return contextFunc(validator, serializer)
185182
}
186183

187184
const objectKeywords = [

lib/serializer.js

+9
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module.exports = class Serializer {
2020
this.parseInteger = Math.trunc
2121
break
2222
}
23+
this._options = options
2324
}
2425

2526
asInteger (i) {
@@ -156,4 +157,12 @@ module.exports = class Serializer {
156157
}
157158
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
158159
}
160+
161+
getState () {
162+
return this._options
163+
}
164+
165+
static restoreFromState (state) {
166+
return new Serializer(state)
167+
}
159168
}

lib/standalone.js

+22-33
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,31 @@
1-
const fs = require('fs')
2-
const path = require('path')
3-
4-
function buildStandaloneCode (options, validator, isValidatorUsed, contextFunctionCode) {
5-
const serializerCode = fs.readFileSync(path.join(__dirname, 'serializer.js')).toString()
6-
let buildAjvCode = ''
7-
let ajvSchemasCode = ''
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-
19-
ajvSchemasCode += `const validator = new Validator(${JSON.stringify(options.ajv || {})})\n`
20-
for (const [id, schema] of Object.entries(validator.ajv.schemas)) {
21-
// should skip ajv default schema
22-
if (id === defaultAjvSchema) continue
23-
ajvSchemasCode += `validator.ajv.addSchema(${JSON.stringify(schema.schema)}, "${id}")\n`
24-
}
25-
buildAjvCode = fs.readFileSync(path.join(__dirname, 'validator.js')).toString()
26-
buildAjvCode = buildAjvCode.replace("'use strict'", '').replace('module.exports = SchemaValidator', '')
1+
'use strict'
2+
3+
function buildStandaloneCode (contextFunc, context, serializer, validator) {
4+
let ajvDependencyCode = ''
5+
if (context.validatorSchemasIds.size > 0) {
6+
ajvDependencyCode += `const validatorState = ${JSON.stringify(validator.getState())}\n`
7+
ajvDependencyCode += 'const validator = Validator.restoreFromState(validatorState)\n'
8+
} else {
9+
ajvDependencyCode += 'const validator = null\n'
2710
}
2811

29-
const serializerOptions = options && options.rounding ? JSON.stringify({ options: options.rounding }) : ''
3012
return `
3113
'use strict'
32-
${serializerCode.replace("'use strict'", '').replace('module.exports = ', '')}
33-
${buildAjvCode}
34-
const serializer = new Serializer(${serializerOptions})
35-
${ajvSchemasCode}
14+
const { dependencies } = require('fast-json-stringify/lib/standalone')
15+
16+
const { Serializer, Validator } = dependencies
17+
18+
const serializerState = ${JSON.stringify(serializer.getState())}
19+
const serializer = Serializer.restoreFromState(serializerState)
3620
37-
${contextFunctionCode.replace('return main', '')}
21+
${ajvDependencyCode}
3822
39-
module.exports = main`
23+
module.exports = ${contextFunc.toString()}(validator, serializer)`
4024
}
4125

4226
module.exports = buildStandaloneCode
27+
28+
module.exports.dependencies = {
29+
Serializer: require('./serializer'),
30+
Validator: require('./validator')
31+
}

lib/validator.js

+19
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class Validator {
2525
return date instanceof Date
2626
}
2727
})
28+
29+
this._ajvSchemas = {}
30+
this._ajvOptions = ajvOptions || {}
2831
}
2932

3033
addSchema (schema, schemaName) {
@@ -40,6 +43,7 @@ class Validator {
4043
const ajvSchema = clone(schema)
4144
this.convertSchemaToAjvFormat(ajvSchema)
4245
this.ajv.addSchema(ajvSchema, schemaKey)
46+
this._ajvSchemas[schemaKey] = schema
4347
}
4448
}
4549

@@ -70,6 +74,21 @@ class Validator {
7074
}
7175
}
7276
}
77+
78+
getState () {
79+
return {
80+
ajvOptions: this._ajvOptions,
81+
ajvSchemas: this._ajvSchemas
82+
}
83+
}
84+
85+
static restoreFromState (state) {
86+
const validator = new Validator(state.ajvOptions)
87+
for (const [id, ajvSchema] of Object.entries(state.ajvSchemas)) {
88+
validator.ajv.addSchema(ajvSchema, id)
89+
}
90+
return validator
91+
}
7392
}
7493

7594
module.exports = Validator

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
"standard": "^17.0.0",
4444
"tap": "^16.0.1",
4545
"tsd": "^0.28.0",
46-
"webpack": "^5.40.0"
46+
"webpack": "^5.40.0",
47+
"fast-json-stringify": "."
4748
},
4849
"dependencies": {
4950
"@fastify/deepmerge": "^1.0.0",

0 commit comments

Comments
 (0)