fast-json-stringify 7.0.0 → 7.1.0
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/.github/dependabot.yml +43 -2
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/lock-threads.yml +1 -1
- package/.github/workflows/release.yml +24 -0
- package/README.md +25 -8
- package/benchmark/bench-thread.js +6 -2
- package/benchmark/bench.js +86 -0
- package/index.js +360 -94
- package/lib/location.js +3 -1
- package/lib/serializer.js +41 -37
- package/lib/standalone.js +22 -3
- package/lib/validator.js +22 -3
- package/package.json +6 -7
- package/test/additionalProperties.test.js +87 -0
- package/test/anyof.test.js +42 -0
- package/test/array.test.js +1 -1
- package/test/basic.test.js +1 -1
- package/test/code-generation-fallbacks.test.js +158 -0
- package/test/compile-validators.test.js +110 -0
- package/test/const.test.js +27 -6
- package/test/date.test.js +28 -1
- package/test/debug-mode.test.js +8 -0
- package/test/deopt.test.js +251 -0
- package/test/if-then-else.test.js +145 -0
- package/test/inferType.test.js +1 -1
- package/test/integer.test.js +1 -1
- package/test/oneof.test.js +242 -0
- package/test/optional-property-prefix.test.js +119 -0
- package/test/patternProperties.test.js +24 -0
- package/test/property-names.test.js +41 -0
- package/test/regex.test.js +1 -1
- package/test/schema-depth.test.js +227 -0
- package/test/standalone-mode.test.js +109 -2
- package/test/string.test.js +8 -0
- package/test/surrogate.test.js +1 -1
- package/test/typesArray.test.js +59 -0
- package/test/utils/validator.js +20 -0
- package/types/index.d.ts +20 -0
- package/types/index.tst.ts +13 -0
package/.github/dependabot.yml
CHANGED
|
@@ -2,12 +2,53 @@ version: 2
|
|
|
2
2
|
updates:
|
|
3
3
|
- package-ecosystem: "github-actions"
|
|
4
4
|
directory: "/"
|
|
5
|
+
commit-message:
|
|
6
|
+
# Prefix all commit messages with "chore: "
|
|
7
|
+
prefix: "chore"
|
|
5
8
|
schedule:
|
|
6
|
-
interval: "
|
|
9
|
+
interval: "weekly"
|
|
10
|
+
cooldown:
|
|
11
|
+
default-days: 7
|
|
12
|
+
allow:
|
|
13
|
+
- dependency-name: "*"
|
|
14
|
+
update-types:
|
|
15
|
+
- "version-update:semver-major"
|
|
7
16
|
open-pull-requests-limit: 10
|
|
8
17
|
|
|
9
18
|
- package-ecosystem: "npm"
|
|
10
19
|
directory: "/"
|
|
20
|
+
commit-message:
|
|
21
|
+
# Prefix all commit messages with "chore: "
|
|
22
|
+
prefix: "chore"
|
|
11
23
|
schedule:
|
|
12
|
-
interval: "
|
|
24
|
+
interval: "weekly"
|
|
25
|
+
cooldown:
|
|
26
|
+
default-days: 7
|
|
27
|
+
versioning-strategy: "increase-if-necessary"
|
|
28
|
+
allow:
|
|
29
|
+
- dependency-name: "*"
|
|
30
|
+
update-types:
|
|
31
|
+
- "version-update:semver-major"
|
|
32
|
+
ignore:
|
|
33
|
+
# TODO: remove ignore until neostandard support ESLint 10
|
|
34
|
+
- dependency-name: "eslint"
|
|
35
|
+
- dependency-name: "neostandard"
|
|
36
|
+
- dependency-name: "@stylistic/*"
|
|
37
|
+
- dependency-name: "typescript"
|
|
13
38
|
open-pull-requests-limit: 10
|
|
39
|
+
groups:
|
|
40
|
+
# Production dependencies with breaking changes
|
|
41
|
+
dependencies:
|
|
42
|
+
dependency-type: "production"
|
|
43
|
+
# ESLint related dependencies
|
|
44
|
+
dev-dependencies-eslint:
|
|
45
|
+
patterns:
|
|
46
|
+
- "eslint"
|
|
47
|
+
- "neostandard"
|
|
48
|
+
- "@stylistic/*"
|
|
49
|
+
# TypeScript related dependencies
|
|
50
|
+
dev-dependencies-typescript:
|
|
51
|
+
patterns:
|
|
52
|
+
- "@types/*"
|
|
53
|
+
- "tstyche"
|
|
54
|
+
- "typescript"
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
permissions:
|
|
28
28
|
contents: write
|
|
29
29
|
pull-requests: write
|
|
30
|
-
uses: fastify/workflows/.github/workflows/plugins-ci.yml@
|
|
30
|
+
uses: fastify/workflows/.github/workflows/plugins-ci.yml@ef591e2186785d5ab36b9fe6a79c7ce2f1d94e57 # v7.0.0
|
|
31
31
|
with:
|
|
32
32
|
license-check: true
|
|
33
33
|
lint: true
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Release the package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
semver:
|
|
7
|
+
description: 'Release bump type'
|
|
8
|
+
required: true
|
|
9
|
+
type: choice
|
|
10
|
+
options:
|
|
11
|
+
- patch
|
|
12
|
+
- minor
|
|
13
|
+
- major
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
release:
|
|
19
|
+
permissions:
|
|
20
|
+
id-token: write # required for npm provenance via OIDC
|
|
21
|
+
contents: write # required to push the release commit and the tag
|
|
22
|
+
uses: fastify/workflows/.github/workflows/reusable-release.yml@b1a11bce713bc857e52b2231fec3c89071ad3135
|
|
23
|
+
with:
|
|
24
|
+
semver: ${{ inputs.semver }}
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Its performance advantage shrinks as your payload grows.
|
|
|
11
11
|
|
|
12
12
|
### How it works
|
|
13
13
|
|
|
14
|
-
fast-json-stringify requires a [JSON Schema Draft 7](https://json-schema.org/specification-links
|
|
14
|
+
fast-json-stringify requires a [JSON Schema Draft 7](https://json-schema.org/specification-links#draft-7) input to generate a fast `stringify` function.
|
|
15
15
|
|
|
16
16
|
##### Benchmarks
|
|
17
17
|
|
|
@@ -121,15 +121,24 @@ const fastJson = require('fast-json-stringify')
|
|
|
121
121
|
const stringify = fastJson(mySchema, {
|
|
122
122
|
schema: { ... },
|
|
123
123
|
ajv: { ... },
|
|
124
|
-
rounding: 'ceil'
|
|
124
|
+
rounding: 'ceil',
|
|
125
|
+
maxDepth: 100
|
|
125
126
|
})
|
|
126
127
|
```
|
|
127
128
|
|
|
128
129
|
- `schema`: external schemas references by $ref property. [More details](#ref)
|
|
129
130
|
- `ajv`: [ajv v8 instance's settings](https://ajv.js.org/options.html) for those properties that require `ajv`. [More details](#anyof)
|
|
130
131
|
- `rounding`: setup how the `integer` types will be rounded when not integers. [More details](#integer)
|
|
132
|
+
- `maxDepth`: maximum number of nested schema levels allowed during compilation.
|
|
133
|
+
Defaults to `100` and may be set from `0` to `100`. Schemas that exceed this limit
|
|
134
|
+
are rejected before compilation.
|
|
135
|
+
- `inlineValidators`: when using standalone mode, embed Ajv-generated validator functions in the output instead of compiling schemas at runtime. [More details](#standalone)
|
|
131
136
|
- `largeArrayMechanism`: set the mechanism that should be used to handle large
|
|
132
137
|
(by default `20000` or more items) arrays. [More details](#largearrays)
|
|
138
|
+
- `compileValidators`: when `true`, the `ajv` validators used by `anyOf`, `oneOf` and
|
|
139
|
+
`if/then/else` are compiled during `build()` instead of lazily, on the first serialization
|
|
140
|
+
that reaches them. This makes `build()` slower but removes a potentially large one-off cost
|
|
141
|
+
from the first `stringify()` call. Defaults to `false`.
|
|
133
142
|
|
|
134
143
|
|
|
135
144
|
<a name="api"></a>
|
|
@@ -137,7 +146,7 @@ const stringify = fastJson(mySchema, {
|
|
|
137
146
|
<a name="fastJsonStringify"></a>
|
|
138
147
|
### fastJsonStringify(schema)
|
|
139
148
|
|
|
140
|
-
Build a `stringify()` function based on [jsonschema draft 7 spec](https://json-schema.org/specification-links
|
|
149
|
+
Build a `stringify()` function based on [jsonschema draft 7 spec](https://json-schema.org/specification-links#draft-7).
|
|
141
150
|
|
|
142
151
|
Supported types:
|
|
143
152
|
|
|
@@ -160,7 +169,7 @@ And nested ones, too.
|
|
|
160
169
|
| `RegExp` | `string` |
|
|
161
170
|
| `BigInt` | `integer` via `toString` |
|
|
162
171
|
|
|
163
|
-
[JSON Schema built-in formats](https://json-schema.org/
|
|
172
|
+
[JSON Schema built-in formats](https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7.3.1) for dates are supported and will be serialized as:
|
|
164
173
|
|
|
165
174
|
| Format | Serialized format example |
|
|
166
175
|
| ----------- | -------------------------- |
|
|
@@ -168,7 +177,7 @@ And nested ones, too.
|
|
|
168
177
|
| `date` | `2020-04-03` |
|
|
169
178
|
| `time` | `09:11:08` |
|
|
170
179
|
|
|
171
|
-
**Note**: In the case of a string formatted Date and not Date Object,
|
|
180
|
+
**Note**: In the case of a string formatted Date and not Date Object, the value is not reformatted nor validated: it should already be properly formatted. It is only escaped, so that the resulting document is always valid JSON.
|
|
172
181
|
|
|
173
182
|
Example with a Date object:
|
|
174
183
|
|
|
@@ -436,7 +445,7 @@ console.log(stringify({
|
|
|
436
445
|
<a name="ref"></a>
|
|
437
446
|
#### Reuse - $ref
|
|
438
447
|
If you want to reuse a definition of a value, you can use the property `$ref`.
|
|
439
|
-
The value of `$ref` must be a string in [JSON Pointer](https://
|
|
448
|
+
The value of `$ref` must be a string in [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) format.
|
|
440
449
|
Example:
|
|
441
450
|
```javascript
|
|
442
451
|
const schema = {
|
|
@@ -561,7 +570,7 @@ const stringify = fastJson(schema, { rounding: 'ceil' })
|
|
|
561
570
|
<a name="nullable"></a>
|
|
562
571
|
#### Nullable
|
|
563
572
|
|
|
564
|
-
According to the [Open API 3.0 specification](https://swagger.io/docs/specification/data-models/data-types/#null), a value that can be null must be declared `nullable`.
|
|
573
|
+
According to the [Open API 3.0 specification](https://swagger.io/docs/specification/v3_0/data-models/data-types/#null), a value that can be null must be declared `nullable`.
|
|
565
574
|
|
|
566
575
|
##### Nullable object
|
|
567
576
|
```javascript
|
|
@@ -724,13 +733,21 @@ const code = fastJson({
|
|
|
724
733
|
type: 'string'
|
|
725
734
|
}
|
|
726
735
|
}
|
|
727
|
-
}, { mode: 'standalone' })
|
|
736
|
+
}, { mode: 'standalone', inlineValidators: true })
|
|
728
737
|
|
|
729
738
|
fs.writeFileSync('stringify.js', code)
|
|
730
739
|
const stringify = require('stringify.js')
|
|
731
740
|
console.log(stringify({ firstName: 'Foo', surname: 'bar' })) // '{"firstName":"Foo"}'
|
|
732
741
|
```
|
|
733
742
|
|
|
743
|
+
Set `inlineValidators` to `true` to include the Ajv-generated functions used by
|
|
744
|
+
`anyOf`, `oneOf`, and `if/then/else` in the same output file. This avoids
|
|
745
|
+
rebuilding an Ajv instance and compiling their schemas at runtime. The
|
|
746
|
+
generated module still requires `fast-json-stringify` for its serializer and
|
|
747
|
+
may require Ajv runtime helpers used by the generated validation code. Custom
|
|
748
|
+
Ajv formats used by these schemas must support Ajv's standalone code
|
|
749
|
+
generation.
|
|
750
|
+
|
|
734
751
|
<a name="acknowledgments"></a>
|
|
735
752
|
## Acknowledgments
|
|
736
753
|
|
|
@@ -15,10 +15,14 @@ const bench = new Bench({
|
|
|
15
15
|
})
|
|
16
16
|
|
|
17
17
|
const FJS = require('..')
|
|
18
|
-
const stringify = FJS(benchmark.schema)
|
|
18
|
+
const stringify = benchmark.compile ? null : FJS(benchmark.schema, benchmark.options)
|
|
19
19
|
|
|
20
20
|
bench.add(benchmark.name, () => {
|
|
21
|
-
|
|
21
|
+
if (benchmark.compile) {
|
|
22
|
+
FJS(benchmark.schema, benchmark.options)(benchmark.input)
|
|
23
|
+
} else {
|
|
24
|
+
stringify(benchmark.input)
|
|
25
|
+
}
|
|
22
26
|
}).run().then(() => {
|
|
23
27
|
const task = bench.tasks[0]
|
|
24
28
|
const hz = task.result.throughput.mean // ops/sec
|
package/benchmark/bench.js
CHANGED
|
@@ -300,6 +300,92 @@ const benchmarks = [
|
|
|
300
300
|
},
|
|
301
301
|
input: { firstName: 'Max', lastName: 'Power', age: 22 }
|
|
302
302
|
},
|
|
303
|
+
{
|
|
304
|
+
name: 'oneOf external refs compile and first stringify',
|
|
305
|
+
compile: true,
|
|
306
|
+
schema: {
|
|
307
|
+
title: 'External refs oneOf schema',
|
|
308
|
+
type: 'object',
|
|
309
|
+
properties: {
|
|
310
|
+
content: {
|
|
311
|
+
oneOf: [
|
|
312
|
+
{ $ref: 'BenchmarkFoo#' },
|
|
313
|
+
{ $ref: 'BenchmarkBar#' },
|
|
314
|
+
{ $ref: 'BenchmarkBaz#' }
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
options: {
|
|
320
|
+
schema: {
|
|
321
|
+
BenchmarkFoo: {
|
|
322
|
+
type: 'object',
|
|
323
|
+
properties: {
|
|
324
|
+
kind: { const: 'foo' },
|
|
325
|
+
title: { type: 'string' },
|
|
326
|
+
count: { type: 'integer' },
|
|
327
|
+
flags: {
|
|
328
|
+
type: 'array',
|
|
329
|
+
items: { type: 'string' }
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
required: ['kind', 'title', 'count', 'flags'],
|
|
333
|
+
additionalProperties: false
|
|
334
|
+
},
|
|
335
|
+
BenchmarkBar: {
|
|
336
|
+
type: 'object',
|
|
337
|
+
properties: {
|
|
338
|
+
kind: { const: 'bar' },
|
|
339
|
+
name: { type: 'string' },
|
|
340
|
+
value: { type: 'number' },
|
|
341
|
+
meta: {
|
|
342
|
+
type: 'object',
|
|
343
|
+
properties: {
|
|
344
|
+
active: { type: 'boolean' },
|
|
345
|
+
tags: {
|
|
346
|
+
type: 'array',
|
|
347
|
+
items: { type: 'string' }
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
required: ['active', 'tags'],
|
|
351
|
+
additionalProperties: false
|
|
352
|
+
}
|
|
353
|
+
},
|
|
354
|
+
required: ['kind', 'name', 'value', 'meta'],
|
|
355
|
+
additionalProperties: false
|
|
356
|
+
},
|
|
357
|
+
BenchmarkBaz: {
|
|
358
|
+
type: 'object',
|
|
359
|
+
properties: {
|
|
360
|
+
kind: { const: 'baz' },
|
|
361
|
+
id: { type: 'string' },
|
|
362
|
+
nested: {
|
|
363
|
+
type: 'object',
|
|
364
|
+
properties: {
|
|
365
|
+
score: { type: 'number' },
|
|
366
|
+
note: { type: 'string' }
|
|
367
|
+
},
|
|
368
|
+
required: ['score', 'note'],
|
|
369
|
+
additionalProperties: false
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
required: ['kind', 'id', 'nested'],
|
|
373
|
+
additionalProperties: false
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
input: {
|
|
378
|
+
content: {
|
|
379
|
+
kind: 'bar',
|
|
380
|
+
name: 'benchmark',
|
|
381
|
+
value: 42.5,
|
|
382
|
+
meta: {
|
|
383
|
+
active: true,
|
|
384
|
+
tags: ['one', 'two', 'three']
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
},
|
|
303
389
|
{
|
|
304
390
|
name: 'object with const string property',
|
|
305
391
|
schema: {
|