fast-json-stringify 5.4.1 → 5.6.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/test/date.test.js CHANGED
@@ -1,10 +1,11 @@
1
1
  'use strict'
2
2
 
3
3
  const test = require('tap').test
4
- const { DateTime } = require('luxon')
5
4
  const validator = require('is-my-json-valid')
6
5
  const build = require('..')
7
6
 
7
+ process.env.TZ = 'UTC'
8
+
8
9
  test('render a date in a string as JSON', (t) => {
9
10
  t.plan(2)
10
11
 
@@ -12,7 +13,7 @@ test('render a date in a string as JSON', (t) => {
12
13
  title: 'a date in a string',
13
14
  type: 'string'
14
15
  }
15
- const toStringify = new Date()
16
+ const toStringify = new Date(1674263005800)
16
17
 
17
18
  const validate = validator(schema)
18
19
  const stringify = build(schema)
@@ -30,7 +31,7 @@ test('render a date in a string when format is date-format as ISOString', (t) =>
30
31
  type: 'string',
31
32
  format: 'date-time'
32
33
  }
33
- const toStringify = new Date()
34
+ const toStringify = new Date(1674263005800)
34
35
 
35
36
  const validate = validator(schema)
36
37
  const stringify = build(schema)
@@ -49,7 +50,7 @@ test('render a nullable date in a string when format is date-format as ISOString
49
50
  format: 'date-time',
50
51
  nullable: true
51
52
  }
52
- const toStringify = new Date()
53
+ const toStringify = new Date(1674263005800)
53
54
 
54
55
  const validate = validator(schema)
55
56
  const stringify = build(schema)
@@ -67,13 +68,13 @@ test('render a date in a string when format is date as YYYY-MM-DD', (t) => {
67
68
  type: 'string',
68
69
  format: 'date'
69
70
  }
70
- const toStringify = new Date()
71
+ const toStringify = new Date(1674263005800)
71
72
 
72
73
  const validate = validator(schema)
73
74
  const stringify = build(schema)
74
75
  const output = stringify(toStringify)
75
76
 
76
- t.equal(output, `"${DateTime.fromJSDate(toStringify).toISODate()}"`)
77
+ t.equal(output, '"2023-01-21"')
77
78
  t.ok(validate(JSON.parse(output)), 'valid schema')
78
79
  })
79
80
 
@@ -86,13 +87,13 @@ test('render a nullable date in a string when format is date as YYYY-MM-DD', (t)
86
87
  format: 'date',
87
88
  nullable: true
88
89
  }
89
- const toStringify = new Date()
90
+ const toStringify = new Date(1674263005800)
90
91
 
91
92
  const validate = validator(schema)
92
93
  const stringify = build(schema)
93
94
  const output = stringify(toStringify)
94
95
 
95
- t.equal(output, `"${DateTime.fromJSDate(toStringify).toISODate()}"`)
96
+ t.equal(output, '"2023-01-21"')
96
97
  t.ok(validate(JSON.parse(output)), 'valid schema')
97
98
  })
98
99
 
@@ -110,7 +111,7 @@ test('verify padding for rendered date in a string when format is date', (t) =>
110
111
  const stringify = build(schema)
111
112
  const output = stringify(toStringify)
112
113
 
113
- t.equal(output, `"${DateTime.fromJSDate(toStringify).toISODate()}"`)
114
+ t.equal(output, '"2020-01-01"')
114
115
  t.ok(validate(JSON.parse(output)), 'valid schema')
115
116
  })
116
117
 
@@ -122,7 +123,7 @@ test('render a date in a string when format is time as kk:mm:ss', (t) => {
122
123
  type: 'string',
123
124
  format: 'time'
124
125
  }
125
- const toStringify = new Date()
126
+ const toStringify = new Date(1674263005800)
126
127
 
127
128
  const validate = validator(schema)
128
129
  const stringify = build(schema)
@@ -131,7 +132,7 @@ test('render a date in a string when format is time as kk:mm:ss', (t) => {
131
132
  validate(JSON.parse(output))
132
133
  t.equal(validate.errors, null)
133
134
 
134
- t.equal(output, `"${DateTime.fromJSDate(toStringify).toFormat('HH:mm:ss')}"`)
135
+ t.equal(output, '"01:03:25"')
135
136
  t.ok(validate(JSON.parse(output)), 'valid schema')
136
137
  })
137
138
 
@@ -144,7 +145,7 @@ test('render a nullable date in a string when format is time as kk:mm:ss', (t) =
144
145
  format: 'time',
145
146
  nullable: true
146
147
  }
147
- const toStringify = new Date()
148
+ const toStringify = new Date(1674263005800)
148
149
 
149
150
  const validate = validator(schema)
150
151
  const stringify = build(schema)
@@ -153,7 +154,7 @@ test('render a nullable date in a string when format is time as kk:mm:ss', (t) =
153
154
  validate(JSON.parse(output))
154
155
  t.equal(validate.errors, null)
155
156
 
156
- t.equal(output, `"${DateTime.fromJSDate(toStringify).toFormat('HH:mm:ss')}"`)
157
+ t.equal(output, '"01:03:25"')
157
158
  t.ok(validate(JSON.parse(output)), 'valid schema')
158
159
  })
159
160
 
@@ -165,7 +166,7 @@ test('render a midnight time', (t) => {
165
166
  type: 'string',
166
167
  format: 'time'
167
168
  }
168
- const midnight = new Date(new Date().setHours(24))
169
+ const midnight = new Date(new Date(1674263005800).setHours(24))
169
170
 
170
171
  const validate = validator(schema)
171
172
  const stringify = build(schema)
@@ -174,7 +175,7 @@ test('render a midnight time', (t) => {
174
175
  validate(JSON.parse(output))
175
176
  t.equal(validate.errors, null)
176
177
 
177
- t.equal(output, `"${DateTime.fromJSDate(midnight).toFormat('HH:mm:ss')}"`)
178
+ t.equal(output, '"00:03:25"')
178
179
  t.ok(validate(JSON.parse(output)), 'valid schema')
179
180
  })
180
181
 
@@ -195,7 +196,7 @@ test('verify padding for rendered date in a string when format is time', (t) =>
195
196
  validate(JSON.parse(output))
196
197
  t.equal(validate.errors, null)
197
198
 
198
- t.equal(output, `"${DateTime.fromJSDate(toStringify).toFormat('HH:mm:ss')}"`)
199
+ t.equal(output, '"01:01:01"')
199
200
  t.ok(validate(JSON.parse(output)), 'valid schema')
200
201
  })
201
202
 
@@ -212,7 +213,7 @@ test('render a nested object in a string when type is date-format as ISOString',
212
213
  }
213
214
  }
214
215
  }
215
- const toStringify = { date: new Date() }
216
+ const toStringify = { date: new Date(1674263005800) }
216
217
 
217
218
  const validate = validator(schema)
218
219
  const stringify = build(schema)
@@ -384,11 +385,11 @@ test('serializing null value', t => {
384
385
  ]
385
386
  }
386
387
 
387
- const date = new Date()
388
+ const date = new Date(1674263005800)
388
389
  const input = { updatedAt: date }
389
390
  const { output } = serialize(schema, input)
390
391
 
391
- t.equal(output, JSON.stringify({ updatedAt: DateTime.fromJSDate(date).toFormat('HH:mm:ss') }))
392
+ t.equal(output, JSON.stringify({ updatedAt: '01:03:25' }))
392
393
  })
393
394
 
394
395
  t.test('format::time, Date object', t => {
@@ -403,10 +404,10 @@ test('serializing null value', t => {
403
404
  ]
404
405
  }
405
406
 
406
- const date = new Date()
407
+ const date = new Date(1674263005800)
407
408
  const { output } = serialize(schema, date)
408
409
 
409
- t.equal(output, `"${DateTime.fromJSDate(date).toFormat('HH:mm:ss')}"`)
410
+ t.equal(output, '"01:03:25"')
410
411
  })
411
412
 
412
413
  t.test('format::time, Date object', t => {
@@ -497,7 +498,7 @@ test('Validate Date object as string type', (t) => {
497
498
  { type: 'string' }
498
499
  ]
499
500
  }
500
- const toStringify = new Date()
501
+ const toStringify = new Date(1674263005800)
501
502
 
502
503
  const stringify = build(schema)
503
504
  const output = stringify(toStringify)
@@ -520,10 +521,10 @@ test('nullable date', (t) => {
520
521
 
521
522
  const stringify = build(schema)
522
523
 
523
- const data = new Date()
524
+ const data = new Date(1674263005800)
524
525
  const result = stringify(data)
525
526
 
526
- t.same(result, `"${DateTime.fromJSDate(data).toISODate()}"`)
527
+ t.same(result, '"2023-01-21"')
527
528
  })
528
529
 
529
530
  test('non-date format should not affect data serialization (issue #491)', (t) => {
@@ -544,3 +545,95 @@ test('non-date format should not affect data serialization (issue #491)', (t) =>
544
545
  const data = { hello: 123n }
545
546
  t.equal(stringify(data), '{"hello":"123"}')
546
547
  })
548
+
549
+ test('should serialize also an invalid string value, even if it is not a valid date', (t) => {
550
+ t.plan(2)
551
+
552
+ const schema = {
553
+ title: 'a date in a string',
554
+ type: 'string',
555
+ format: 'date-time',
556
+ nullable: true
557
+ }
558
+ const toStringify = 'invalid'
559
+
560
+ const validate = validator(schema)
561
+ const stringify = build(schema)
562
+ const output = stringify(toStringify)
563
+
564
+ t.equal(output, JSON.stringify(toStringify))
565
+ t.not(validate(JSON.parse(output)), 'valid schema')
566
+ })
567
+
568
+ test('should throw an error if value can not be transformed to date-time', (t) => {
569
+ t.plan(2)
570
+
571
+ const schema = {
572
+ title: 'a date in a string',
573
+ type: 'string',
574
+ format: 'date-time',
575
+ nullable: true
576
+ }
577
+ const toStringify = true
578
+
579
+ const validate = validator(schema)
580
+ const stringify = build(schema)
581
+
582
+ t.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a date-time.'))
583
+ t.not(validate(toStringify))
584
+ })
585
+
586
+ test('should throw an error if value can not be transformed to date', (t) => {
587
+ t.plan(2)
588
+
589
+ const schema = {
590
+ title: 'a date in a string',
591
+ type: 'string',
592
+ format: 'date',
593
+ nullable: true
594
+ }
595
+ const toStringify = true
596
+
597
+ const validate = validator(schema)
598
+ const stringify = build(schema)
599
+
600
+ t.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a date.'))
601
+ t.not(validate(toStringify))
602
+ })
603
+
604
+ test('should throw an error if value can not be transformed to time', (t) => {
605
+ t.plan(2)
606
+
607
+ const schema = {
608
+ title: 'a time in a string',
609
+ type: 'string',
610
+ format: 'time',
611
+ nullable: true
612
+ }
613
+ const toStringify = true
614
+
615
+ const validate = validator(schema)
616
+ const stringify = build(schema)
617
+
618
+ t.throws(() => stringify(toStringify), new Error('The value "true" cannot be converted to a time.'))
619
+ t.not(validate(toStringify))
620
+ })
621
+
622
+ test('should serialize also an invalid string value, even if it is not a valid time', (t) => {
623
+ t.plan(2)
624
+
625
+ const schema = {
626
+ title: 'a time in a string',
627
+ type: 'string',
628
+ format: 'time',
629
+ nullable: true
630
+ }
631
+ const toStringify = 'invalid'
632
+
633
+ const validate = validator(schema)
634
+ const stringify = build(schema)
635
+ const output = stringify(toStringify)
636
+
637
+ t.equal(output, JSON.stringify(toStringify))
638
+ t.not(validate(JSON.parse(output)), 'valid schema')
639
+ })
@@ -1,9 +1,10 @@
1
1
  'use strict'
2
2
 
3
3
  const t = require('tap')
4
- const { DateTime } = require('luxon')
5
4
  const build = require('..')
6
5
 
6
+ process.env.TZ = 'UTC'
7
+
7
8
  const schema = {
8
9
  type: 'object',
9
10
  properties: {
@@ -381,9 +382,9 @@ t.test('if/else with string format', (t) => {
381
382
 
382
383
  const stringify = build(schema)
383
384
 
384
- const date = new Date()
385
+ const date = new Date(1674263005800)
385
386
 
386
- t.equal(stringify(date), `"${DateTime.fromJSDate(date).toISODate()}"`)
387
+ t.equal(stringify(date), '"2023-01-21"')
387
388
  t.equal(stringify('Invalid'), '"Invalid"')
388
389
  })
389
390
 
@@ -45,6 +45,14 @@ test('render a float as an integer', (t) => {
45
45
  { input: 42, output: '42' },
46
46
  { input: 1.99999, output: '1' },
47
47
  { input: -45.05, output: '-45' },
48
+ { input: Math.PI, output: '3', rounding: 'trunc' },
49
+ { input: 5.0, output: '5', rounding: 'trunc' },
50
+ { input: null, output: '0', rounding: 'trunc' },
51
+ { input: 0, output: '0', rounding: 'trunc' },
52
+ { input: 0.0, output: '0', rounding: 'trunc' },
53
+ { input: 42, output: '42', rounding: 'trunc' },
54
+ { input: 1.99999, output: '1', rounding: 'trunc' },
55
+ { input: -45.05, output: '-45', rounding: 'trunc' },
48
56
  { input: 0.95, output: '1', rounding: 'ceil' },
49
57
  { input: 0.2, output: '1', rounding: 'ceil' },
50
58
  { input: 45.95, output: '45', rounding: 'floor' },
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const test = require('tap').test
4
+ const build = require('..')
5
+
6
+ test('should throw a TypeError with the path to the key of the invalid value', (t) => {
7
+ t.plan(1)
8
+ const schema = {
9
+ type: 'object',
10
+ properties: {
11
+ num: {
12
+ type: ['number']
13
+ }
14
+ }
15
+ }
16
+
17
+ const stringify = build(schema)
18
+ t.throws(() => stringify({ num: { bla: 123 } }), new TypeError('The value of \'#/properties/num\' does not match schema definition.'))
19
+ })
@@ -148,3 +148,21 @@ test('patternProperties - array coerce', (t) => {
148
148
  const incoercibleValues = { foo: 'true', ofoo: 0, objfoo: { tyrion: 'lannister' } }
149
149
  t.throws(() => stringify(incoercibleValues))
150
150
  })
151
+
152
+ test('patternProperties - fail on invalid regex, handled by ajv', (t) => {
153
+ t.plan(1)
154
+
155
+ t.throws(() => build({
156
+ title: 'check array coerce',
157
+ type: 'object',
158
+ properties: {},
159
+ patternProperties: {
160
+ 'foo/\\': {
161
+ type: 'array',
162
+ items: {
163
+ type: 'string'
164
+ }
165
+ }
166
+ }
167
+ }), new Error('schema is invalid: data/patternProperties must match format "regex"'))
168
+ })
package/test/ref.test.js CHANGED
@@ -2005,3 +2005,76 @@ test('object property reference with default value', (t) => {
2005
2005
 
2006
2006
  t.equal(output, '{"prop":"foo"}')
2007
2007
  })
2008
+
2009
+ test('should throw an Error if two non-identical schemas with same id are provided', (t) => {
2010
+ t.plan(1)
2011
+
2012
+ const schema = {
2013
+ $id: 'schema',
2014
+ type: 'object',
2015
+ allOf: [
2016
+ {
2017
+ $id: 'base',
2018
+ type: 'object',
2019
+ properties: {
2020
+ name: {
2021
+ type: 'string'
2022
+ }
2023
+ },
2024
+ required: [
2025
+ 'name'
2026
+ ]
2027
+ },
2028
+ {
2029
+ $id: 'inner_schema',
2030
+ type: 'object',
2031
+ properties: {
2032
+ union: {
2033
+ $id: '#id',
2034
+ anyOf: [
2035
+ {
2036
+
2037
+ $id: 'guid',
2038
+ type: 'string'
2039
+ },
2040
+ {
2041
+
2042
+ $id: 'email',
2043
+ type: 'string'
2044
+ }
2045
+ ]
2046
+ }
2047
+ },
2048
+ required: [
2049
+ 'union'
2050
+ ]
2051
+ },
2052
+ {
2053
+ $id: 'inner_schema',
2054
+ type: 'object',
2055
+ properties: {
2056
+ union: {
2057
+ $id: '#id',
2058
+ anyOf: [
2059
+ {
2060
+
2061
+ $id: 'guid',
2062
+ type: 'string'
2063
+ },
2064
+ {
2065
+
2066
+ $id: 'mail',
2067
+ type: 'string'
2068
+ }
2069
+ ]
2070
+ }
2071
+ },
2072
+ required: [
2073
+ 'union'
2074
+ ]
2075
+ }
2076
+ ]
2077
+ }
2078
+
2079
+ t.throws(() => build(schema), new Error('There is already another schema with id inner_schema'))
2080
+ })
@@ -0,0 +1,50 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const test = t.test
5
+ const build = require('..')
6
+
7
+ test('serialize short string', (t) => {
8
+ t.plan(2)
9
+
10
+ const schema = {
11
+ type: 'string'
12
+ }
13
+
14
+ const input = 'abcd'
15
+ const stringify = build(schema)
16
+ const output = stringify(input)
17
+
18
+ t.equal(output, '"abcd"')
19
+ t.equal(JSON.parse(output), input)
20
+ })
21
+
22
+ test('serialize short string', (t) => {
23
+ t.plan(2)
24
+
25
+ const schema = {
26
+ type: 'string'
27
+ }
28
+
29
+ const input = '\x00'
30
+ const stringify = build(schema)
31
+ const output = stringify(input)
32
+
33
+ t.equal(output, '"\\u0000"')
34
+ t.equal(JSON.parse(output), input)
35
+ })
36
+
37
+ test('serialize long string', (t) => {
38
+ t.plan(2)
39
+
40
+ const schema = {
41
+ type: 'string'
42
+ }
43
+
44
+ const input = new Array(2e4).fill('\x00').join('')
45
+ const stringify = build(schema)
46
+ const output = stringify(input)
47
+
48
+ t.equal(output, `"${new Array(2e4).fill('\\u0000').join('')}"`)
49
+ t.equal(JSON.parse(output), input)
50
+ })
@@ -482,7 +482,53 @@ test('should throw an error when type is array and object is null', (t) => {
482
482
  }
483
483
 
484
484
  const stringify = build(schema)
485
- t.throws(() => stringify({ arr: null }), new TypeError('The value \'null\' does not match schema definition.'))
485
+ t.throws(() => stringify({ arr: null }), new TypeError('The value of \'#/properties/arr\' does not match schema definition.'))
486
+ })
487
+
488
+ test('should throw an error when type is array and object is not an array', (t) => {
489
+ t.plan(1)
490
+ const schema = {
491
+ type: 'object',
492
+ properties: {
493
+ arr: {
494
+ type: 'array',
495
+ items: {
496
+ type: 'number'
497
+ }
498
+ }
499
+ }
500
+ }
501
+
502
+ const stringify = build(schema)
503
+ t.throws(() => stringify({ arr: { foo: 'hello' } }), new TypeError('The value of \'#/properties/arr\' does not match schema definition.'))
504
+ })
505
+
506
+ test('should throw an error when type is array and object is not an array with external schema', (t) => {
507
+ t.plan(1)
508
+ const schema = {
509
+ type: 'object',
510
+ properties: {
511
+ arr: {
512
+ $ref: 'arrayOfNumbers#/definitions/arr'
513
+ }
514
+ }
515
+ }
516
+
517
+ const externalSchema = {
518
+ arrayOfNumbers: {
519
+ definitions: {
520
+ arr: {
521
+ type: 'array',
522
+ items: {
523
+ type: 'number'
524
+ }
525
+ }
526
+ }
527
+ }
528
+ }
529
+
530
+ const stringify = build(schema, { schema: externalSchema })
531
+ t.throws(() => stringify({ arr: { foo: 'hello' } }), new TypeError('The value of \'arrayOfNumbers#/definitions/arr\' does not match schema definition.'))
486
532
  })
487
533
 
488
534
  test('throw an error if none of types matches', (t) => {
@@ -1,5 +1,7 @@
1
1
  import Ajv, { Options as AjvOptions } from "ajv"
2
2
 
3
+ type Build = typeof build
4
+
3
5
  declare namespace build {
4
6
  interface BaseSchema {
5
7
  /**
@@ -156,8 +158,10 @@ declare namespace build {
156
158
  ajv?: AjvOptions
157
159
  /**
158
160
  * Optionally configure how the integer will be rounded
161
+ *
162
+ * @default 'trunc'
159
163
  */
160
- rounding?: 'ceil' | 'floor' | 'round'
164
+ rounding?: 'ceil' | 'floor' | 'round' | 'trunc'
161
165
  /**
162
166
  * @deprecated
163
167
  * Enable debug mode. Please use `mode: "debug"` instead
@@ -167,7 +171,29 @@ declare namespace build {
167
171
  * Running mode of fast-json-stringify
168
172
  */
169
173
  mode?: 'debug' | 'standalone'
174
+
175
+ /**
176
+ * Large arrays are defined as arrays containing, by default, `20000`
177
+ * elements or more. That value can be adjusted via the option parameter
178
+ * `largeArraySize`.
179
+ *
180
+ * @default 20000
181
+ */
182
+ largeArraySize?: number | string | BigInt
183
+
184
+ /**
185
+ * Specify the function on how large Arrays should be stringified.
186
+ *
187
+ * @default 'default'
188
+ */
189
+ largeArrayMechanism?: 'default' | 'json-stringify'
170
190
  }
191
+
192
+ export const validLargeArrayMechanisms: string[]
193
+ export function restore (value: <TDoc extends object = object>(doc: TDoc) => string): ReturnType<Build>
194
+
195
+ export const build: Build
196
+ export { build as default }
171
197
  }
172
198
 
173
199
  interface DebugOption extends build.Options {