fast-json-stringify 5.8.0 → 5.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -0
- package/.github/workflows/benchmark.yml +3 -3
- package/examples/example.js +2 -0
- package/index.js +23 -8
- package/package.json +6 -4
- package/test/const.test.js +20 -0
- package/test/ref.test.js +14 -3
- package/lib/ref-resolver.js +0 -104
package/.gitattributes
ADDED
|
@@ -14,13 +14,13 @@ jobs:
|
|
|
14
14
|
PR-BENCH: ${{ steps.benchmark-pr.outputs.BENCH_RESULT }}
|
|
15
15
|
MASTER-BENCH: ${{ steps.benchmark-master.outputs.BENCH_RESULT }}
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
18
|
with:
|
|
19
19
|
persist-credentials: false
|
|
20
20
|
ref: ${{github.event.pull_request.head.sha}}
|
|
21
21
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
|
22
22
|
|
|
23
|
-
- uses: actions/setup-node@
|
|
23
|
+
- uses: actions/setup-node@v4
|
|
24
24
|
with:
|
|
25
25
|
node-version: 18
|
|
26
26
|
|
|
@@ -39,7 +39,7 @@ jobs:
|
|
|
39
39
|
echo "::set-output name=BENCH_RESULT::$content"
|
|
40
40
|
|
|
41
41
|
# master benchmark
|
|
42
|
-
- uses: actions/checkout@
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
43
|
with:
|
|
44
44
|
ref: 'master'
|
|
45
45
|
|
package/examples/example.js
CHANGED
package/index.js
CHANGED
|
@@ -5,13 +5,15 @@
|
|
|
5
5
|
const merge = require('@fastify/deepmerge')()
|
|
6
6
|
const clone = require('rfdc')({ proto: true })
|
|
7
7
|
const { randomUUID } = require('crypto')
|
|
8
|
+
const { RefResolver } = require('json-schema-ref-resolver')
|
|
8
9
|
|
|
9
10
|
const validate = require('./lib/schema-validator')
|
|
10
11
|
const Serializer = require('./lib/serializer')
|
|
11
12
|
const Validator = require('./lib/validator')
|
|
12
|
-
const RefResolver = require('./lib/ref-resolver')
|
|
13
13
|
const Location = require('./lib/location')
|
|
14
14
|
|
|
15
|
+
const SINGLE_TICK = /'/g
|
|
16
|
+
|
|
15
17
|
let largeArraySize = 2e4
|
|
16
18
|
let largeArrayMechanism = 'default'
|
|
17
19
|
|
|
@@ -53,8 +55,7 @@ function resolveRef (context, location, ref) {
|
|
|
53
55
|
const jsonPointer = ref.slice(hashIndex) || '#'
|
|
54
56
|
|
|
55
57
|
const schema = context.refResolver.getSchema(schemaId, jsonPointer)
|
|
56
|
-
|
|
57
|
-
if (schema === undefined) {
|
|
58
|
+
if (schema === null) {
|
|
58
59
|
throw new Error(`Cannot find reference "${ref}"`)
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -66,6 +67,13 @@ function resolveRef (context, location, ref) {
|
|
|
66
67
|
return newLocation
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
function getSchemaId (schema, rootSchemaId) {
|
|
71
|
+
if (schema.$id && schema.$id.charAt(0) !== '#') {
|
|
72
|
+
return schema.$id
|
|
73
|
+
}
|
|
74
|
+
return rootSchemaId
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
function build (schema, options) {
|
|
70
78
|
isValidSchema(schema)
|
|
71
79
|
|
|
@@ -82,12 +90,19 @@ function build (schema, options) {
|
|
|
82
90
|
validatorSchemasIds: new Set()
|
|
83
91
|
}
|
|
84
92
|
|
|
85
|
-
|
|
93
|
+
const schemaId = getSchemaId(schema, context.rootSchemaId)
|
|
94
|
+
if (!context.refResolver.hasSchema(schemaId)) {
|
|
95
|
+
context.refResolver.addSchema(schema, context.rootSchemaId)
|
|
96
|
+
}
|
|
86
97
|
|
|
87
98
|
if (options.schema) {
|
|
88
|
-
for (const key
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
for (const key in options.schema) {
|
|
100
|
+
const schema = options.schema[key]
|
|
101
|
+
const schemaId = getSchemaId(schema, key)
|
|
102
|
+
if (!context.refResolver.hasSchema(schemaId)) {
|
|
103
|
+
isValidSchema(schema, key)
|
|
104
|
+
context.refResolver.addSchema(schema, key)
|
|
105
|
+
}
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
108
|
|
|
@@ -821,7 +836,7 @@ function buildConstSerializer (location, input) {
|
|
|
821
836
|
`
|
|
822
837
|
}
|
|
823
838
|
|
|
824
|
-
code += `json += '${JSON.stringify(schema.const)}'`
|
|
839
|
+
code += `json += '${JSON.stringify(schema.const).replace(SINGLE_TICK, "\\'")}'`
|
|
825
840
|
|
|
826
841
|
if (hasNullType) {
|
|
827
842
|
code += `
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-json-stringify",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.1",
|
|
4
4
|
"description": "Stringify your JSON at max speed",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"type": "commonjs",
|
|
6
7
|
"types": "types/index.d.ts",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"bench": "node ./benchmark/bench.js",
|
|
@@ -34,7 +35,7 @@
|
|
|
34
35
|
"homepage": "https://github.com/fastify/fast-json-stringify#readme",
|
|
35
36
|
"devDependencies": {
|
|
36
37
|
"@fastify/pre-commit": "^2.0.2",
|
|
37
|
-
"@sinclair/typebox": "^0.
|
|
38
|
+
"@sinclair/typebox": "^0.31.1",
|
|
38
39
|
"benchmark": "^2.1.4",
|
|
39
40
|
"cli-select": "^1.1.2",
|
|
40
41
|
"compile-json-stringify": "^0.1.2",
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"simple-git": "^3.7.1",
|
|
43
44
|
"standard": "^17.0.0",
|
|
44
45
|
"tap": "^16.0.1",
|
|
45
|
-
"tsd": "^0.
|
|
46
|
+
"tsd": "^0.29.0",
|
|
46
47
|
"webpack": "^5.40.0",
|
|
47
48
|
"fast-json-stringify": "."
|
|
48
49
|
},
|
|
@@ -52,7 +53,8 @@
|
|
|
52
53
|
"ajv-formats": "^2.1.1",
|
|
53
54
|
"fast-deep-equal": "^3.1.3",
|
|
54
55
|
"fast-uri": "^2.1.0",
|
|
55
|
-
"rfdc": "^1.2.0"
|
|
56
|
+
"rfdc": "^1.2.0",
|
|
57
|
+
"json-schema-ref-resolver": "^1.0.1"
|
|
56
58
|
},
|
|
57
59
|
"standard": {
|
|
58
60
|
"ignore": [
|
package/test/const.test.js
CHANGED
|
@@ -82,6 +82,26 @@ test('schema with const string and no input', (t) => {
|
|
|
82
82
|
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
+
test('schema with const string that contains \'', (t) => {
|
|
86
|
+
t.plan(2)
|
|
87
|
+
|
|
88
|
+
const schema = {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
foo: { const: "'bar'" }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const validate = validator(schema)
|
|
96
|
+
const stringify = build(schema)
|
|
97
|
+
const output = stringify({
|
|
98
|
+
foo: "'bar'"
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
t.equal(output, '{"foo":"\'bar\'"}')
|
|
102
|
+
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
103
|
+
})
|
|
104
|
+
|
|
85
105
|
test('schema with const number', (t) => {
|
|
86
106
|
t.plan(2)
|
|
87
107
|
|
package/test/ref.test.js
CHANGED
|
@@ -1377,7 +1377,10 @@ test('Bad key', t => {
|
|
|
1377
1377
|
})
|
|
1378
1378
|
t.fail('Should throw')
|
|
1379
1379
|
} catch (err) {
|
|
1380
|
-
t.equal(
|
|
1380
|
+
t.equal(
|
|
1381
|
+
err.message,
|
|
1382
|
+
'Cannot resolve ref "extrenal#/definitions/projectId". Schema with id "extrenal" is not found.'
|
|
1383
|
+
)
|
|
1381
1384
|
}
|
|
1382
1385
|
})
|
|
1383
1386
|
|
|
@@ -2076,7 +2079,11 @@ test('should throw an Error if two non-identical schemas with same id are provid
|
|
|
2076
2079
|
]
|
|
2077
2080
|
}
|
|
2078
2081
|
|
|
2079
|
-
|
|
2082
|
+
try {
|
|
2083
|
+
build(schema)
|
|
2084
|
+
} catch (err) {
|
|
2085
|
+
t.equal(err.message, 'There is already another schema with id "inner_schema".')
|
|
2086
|
+
}
|
|
2080
2087
|
})
|
|
2081
2088
|
|
|
2082
2089
|
test('ref internal - throw if schema has definition twice with different shape', (t) => {
|
|
@@ -2115,5 +2122,9 @@ test('ref internal - throw if schema has definition twice with different shape',
|
|
|
2115
2122
|
}
|
|
2116
2123
|
}
|
|
2117
2124
|
|
|
2118
|
-
|
|
2125
|
+
try {
|
|
2126
|
+
build(schema)
|
|
2127
|
+
} catch (err) {
|
|
2128
|
+
t.equal(err.message, 'There is already another anchor "#uri" in a schema "test".')
|
|
2129
|
+
}
|
|
2119
2130
|
})
|
package/lib/ref-resolver.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const deepEqual = require('fast-deep-equal')
|
|
4
|
-
|
|
5
|
-
class RefResolver {
|
|
6
|
-
constructor () {
|
|
7
|
-
this.schemas = {}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
addSchema (schema, schemaId) {
|
|
11
|
-
if (schema.$id !== undefined && schema.$id.charAt(0) !== '#') {
|
|
12
|
-
schemaId = schema.$id
|
|
13
|
-
}
|
|
14
|
-
if (this.getSchema(schemaId) === undefined) {
|
|
15
|
-
this.insertSchemaBySchemaId(schema, schemaId)
|
|
16
|
-
this.insertSchemaSubschemas(schema, schemaId)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
getSchema (schemaId, jsonPointer = '#') {
|
|
21
|
-
const schema = this.schemas[schemaId]
|
|
22
|
-
if (schema === undefined) {
|
|
23
|
-
return undefined
|
|
24
|
-
}
|
|
25
|
-
if (schema.anchors[jsonPointer] !== undefined) {
|
|
26
|
-
return schema.anchors[jsonPointer]
|
|
27
|
-
}
|
|
28
|
-
return getDataByJSONPointer(schema.schema, jsonPointer)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getSchemaDependencies (schemaId, dependencies = {}) {
|
|
32
|
-
const schema = this.schemas[schemaId]
|
|
33
|
-
|
|
34
|
-
for (const dependencySchemaId of schema.dependencies) {
|
|
35
|
-
if (dependencies[dependencySchemaId] !== undefined) continue
|
|
36
|
-
dependencies[dependencySchemaId] = this.getSchema(dependencySchemaId)
|
|
37
|
-
this.getSchemaDependencies(dependencySchemaId, dependencies)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return dependencies
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
insertSchemaBySchemaId (schema, schemaId) {
|
|
44
|
-
if (
|
|
45
|
-
this.schemas[schemaId] !== undefined &&
|
|
46
|
-
!deepEqual(schema, this.schemas[schemaId].schema)
|
|
47
|
-
) {
|
|
48
|
-
throw new Error(`There is already another schema with id ${schemaId}`)
|
|
49
|
-
}
|
|
50
|
-
this.schemas[schemaId] = { schema, anchors: {}, dependencies: [] }
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
insertSchemaByAnchor (schema, schemaId, anchor) {
|
|
54
|
-
const { anchors } = this.schemas[schemaId]
|
|
55
|
-
if (
|
|
56
|
-
anchors[anchor] !== undefined &&
|
|
57
|
-
!deepEqual(schema, anchors[anchor])
|
|
58
|
-
) {
|
|
59
|
-
throw new Error(`There is already another schema with id ${schemaId}#${anchor}`)
|
|
60
|
-
}
|
|
61
|
-
anchors[anchor] = schema
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
insertSchemaSubschemas (schema, rootSchemaId) {
|
|
65
|
-
const schemaId = schema.$id
|
|
66
|
-
if (schemaId !== undefined && typeof schemaId === 'string') {
|
|
67
|
-
if (schemaId.charAt(0) === '#') {
|
|
68
|
-
this.insertSchemaByAnchor(schema, rootSchemaId, schemaId)
|
|
69
|
-
} else {
|
|
70
|
-
this.insertSchemaBySchemaId(schema, schemaId)
|
|
71
|
-
rootSchemaId = schemaId
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const ref = schema.$ref
|
|
76
|
-
if (ref !== undefined && typeof ref === 'string') {
|
|
77
|
-
if (ref.charAt(0) !== '#') {
|
|
78
|
-
const dependencySchemaId = ref.split('#')[0]
|
|
79
|
-
this.schemas[rootSchemaId].dependencies.push(dependencySchemaId)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
for (const key in schema) {
|
|
84
|
-
if (typeof schema[key] === 'object' && schema[key] !== null) {
|
|
85
|
-
this.insertSchemaSubschemas(schema[key], rootSchemaId)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function getDataByJSONPointer (data, jsonPointer) {
|
|
92
|
-
const parts = jsonPointer.split('/')
|
|
93
|
-
let current = data
|
|
94
|
-
for (const part of parts) {
|
|
95
|
-
if (part === '' || part === '#') continue
|
|
96
|
-
if (typeof current !== 'object' || current === null) {
|
|
97
|
-
return undefined
|
|
98
|
-
}
|
|
99
|
-
current = current[part]
|
|
100
|
-
}
|
|
101
|
-
return current
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
module.exports = RefResolver
|