fast-json-stringify 3.2.0 → 4.2.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.
@@ -116,3 +116,331 @@ Object.keys(testSet).forEach(key => {
116
116
  t.same(JSON.parse(result), expected)
117
117
  })
118
118
  })
119
+
120
+ test('handle nullable number correctly', (t) => {
121
+ t.plan(2)
122
+
123
+ const schema = {
124
+ type: 'number',
125
+ nullable: true
126
+ }
127
+ const stringify = build(schema)
128
+
129
+ const data = null
130
+ const result = stringify(data)
131
+
132
+ t.same(result, JSON.stringify(data))
133
+ t.same(JSON.parse(result), data)
134
+ })
135
+
136
+ test('handle nullable integer correctly', (t) => {
137
+ t.plan(2)
138
+
139
+ const schema = {
140
+ type: 'integer',
141
+ nullable: true
142
+ }
143
+ const stringify = build(schema)
144
+
145
+ const data = null
146
+ const result = stringify(data)
147
+
148
+ t.same(result, JSON.stringify(data))
149
+ t.same(JSON.parse(result), data)
150
+ })
151
+
152
+ test('handle nullable boolean correctly', (t) => {
153
+ t.plan(2)
154
+
155
+ const schema = {
156
+ type: 'boolean',
157
+ nullable: true
158
+ }
159
+ const stringify = build(schema)
160
+
161
+ const data = null
162
+ const result = stringify(data)
163
+
164
+ t.same(result, JSON.stringify(data))
165
+ t.same(JSON.parse(result), data)
166
+ })
167
+
168
+ test('handle nullable string correctly', (t) => {
169
+ t.plan(2)
170
+
171
+ const schema = {
172
+ type: 'string',
173
+ nullable: true
174
+ }
175
+ const stringify = build(schema)
176
+
177
+ const data = null
178
+ const result = stringify(data)
179
+
180
+ t.same(result, JSON.stringify(data))
181
+ t.same(JSON.parse(result), data)
182
+ })
183
+
184
+ test('handle nullable date-time correctly', (t) => {
185
+ t.plan(2)
186
+
187
+ const schema = {
188
+ type: 'string',
189
+ format: 'date-time',
190
+ nullable: true
191
+ }
192
+ const stringify = build(schema)
193
+
194
+ const data = null
195
+ const result = stringify(data)
196
+
197
+ t.same(result, JSON.stringify(data))
198
+ t.same(JSON.parse(result), data)
199
+ })
200
+
201
+ test('handle nullable date correctly', (t) => {
202
+ t.plan(2)
203
+
204
+ const schema = {
205
+ type: 'string',
206
+ format: 'date',
207
+ nullable: true
208
+ }
209
+ const stringify = build(schema)
210
+
211
+ const data = null
212
+ const result = stringify(data)
213
+
214
+ t.same(result, JSON.stringify(data))
215
+ t.same(JSON.parse(result), data)
216
+ })
217
+
218
+ test('handle nullable time correctly', (t) => {
219
+ t.plan(2)
220
+
221
+ const schema = {
222
+ type: 'string',
223
+ format: 'time',
224
+ nullable: true
225
+ }
226
+ const stringify = build(schema)
227
+
228
+ const data = null
229
+ const result = stringify(data)
230
+
231
+ t.same(result, JSON.stringify(data))
232
+ t.same(JSON.parse(result), data)
233
+ })
234
+
235
+ test('large array of nullable strings with default mechanism', (t) => {
236
+ t.plan(2)
237
+
238
+ const schema = {
239
+ type: 'object',
240
+ properties: {
241
+ ids: {
242
+ type: 'array',
243
+ items: {
244
+ type: 'string',
245
+ nullable: true
246
+ }
247
+ }
248
+ }
249
+ }
250
+
251
+ const options = {
252
+ largeArraySize: 2e4,
253
+ largeArrayMechanism: 'default'
254
+ }
255
+
256
+ const stringify = build(schema, options)
257
+
258
+ const data = { ids: new Array(2e4).fill(null) }
259
+ const result = stringify(data)
260
+
261
+ t.same(result, JSON.stringify(data))
262
+ t.same(JSON.parse(result), data)
263
+ })
264
+
265
+ test('large array of nullable date-time strings with default mechanism', (t) => {
266
+ t.plan(2)
267
+
268
+ const schema = {
269
+ type: 'object',
270
+ properties: {
271
+ ids: {
272
+ type: 'array',
273
+ items: {
274
+ type: 'string',
275
+ format: 'date-time',
276
+ nullable: true
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ const options = {
283
+ largeArraySize: 2e4,
284
+ largeArrayMechanism: 'default'
285
+ }
286
+
287
+ const stringify = build(schema, options)
288
+
289
+ const data = { ids: new Array(2e4).fill(null) }
290
+ const result = stringify(data)
291
+
292
+ t.same(result, JSON.stringify(data))
293
+ t.same(JSON.parse(result), data)
294
+ })
295
+
296
+ test('large array of nullable date-time strings with default mechanism', (t) => {
297
+ t.plan(2)
298
+
299
+ const schema = {
300
+ type: 'object',
301
+ properties: {
302
+ ids: {
303
+ type: 'array',
304
+ items: {
305
+ type: 'string',
306
+ format: 'date',
307
+ nullable: true
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ const options = {
314
+ largeArraySize: 2e4,
315
+ largeArrayMechanism: 'default'
316
+ }
317
+
318
+ const stringify = build(schema, options)
319
+
320
+ const data = { ids: new Array(2e4).fill(null) }
321
+ const result = stringify(data)
322
+
323
+ t.same(result, JSON.stringify(data))
324
+ t.same(JSON.parse(result), data)
325
+ })
326
+
327
+ test('large array of nullable date-time strings with default mechanism', (t) => {
328
+ t.plan(2)
329
+
330
+ const schema = {
331
+ type: 'object',
332
+ properties: {
333
+ ids: {
334
+ type: 'array',
335
+ items: {
336
+ type: 'string',
337
+ format: 'time',
338
+ nullable: true
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ const options = {
345
+ largeArraySize: 2e4,
346
+ largeArrayMechanism: 'default'
347
+ }
348
+
349
+ const stringify = build(schema, options)
350
+
351
+ const data = { ids: new Array(2e4).fill(null) }
352
+ const result = stringify(data)
353
+
354
+ t.same(result, JSON.stringify(data))
355
+ t.same(JSON.parse(result), data)
356
+ })
357
+
358
+ test('large array of nullable numbers with default mechanism', (t) => {
359
+ t.plan(2)
360
+
361
+ const schema = {
362
+ type: 'object',
363
+ properties: {
364
+ ids: {
365
+ type: 'array',
366
+ items: {
367
+ type: 'number',
368
+ nullable: true
369
+ }
370
+ }
371
+ }
372
+ }
373
+
374
+ const options = {
375
+ largeArraySize: 2e4,
376
+ largeArrayMechanism: 'default'
377
+ }
378
+
379
+ const stringify = build(schema, options)
380
+
381
+ const data = { ids: new Array(2e4).fill(null) }
382
+ const result = stringify(data)
383
+
384
+ t.same(result, JSON.stringify(data))
385
+ t.same(JSON.parse(result), data)
386
+ })
387
+
388
+ test('large array of nullable integers with default mechanism', (t) => {
389
+ t.plan(2)
390
+
391
+ const schema = {
392
+ type: 'object',
393
+ properties: {
394
+ ids: {
395
+ type: 'array',
396
+ items: {
397
+ type: 'integer',
398
+ nullable: true
399
+ }
400
+ }
401
+ }
402
+ }
403
+
404
+ const options = {
405
+ largeArraySize: 2e4,
406
+ largeArrayMechanism: 'default'
407
+ }
408
+
409
+ const stringify = build(schema, options)
410
+
411
+ const data = { ids: new Array(2e4).fill(null) }
412
+ const result = stringify(data)
413
+
414
+ t.same(result, JSON.stringify(data))
415
+ t.same(JSON.parse(result), data)
416
+ })
417
+
418
+ test('large array of nullable booleans with default mechanism', (t) => {
419
+ t.plan(2)
420
+
421
+ const schema = {
422
+ type: 'object',
423
+ properties: {
424
+ ids: {
425
+ type: 'array',
426
+ items: {
427
+ type: 'boolean',
428
+ nullable: true
429
+ }
430
+ }
431
+ }
432
+ }
433
+
434
+ const options = {
435
+ largeArraySize: 2e4,
436
+ largeArrayMechanism: 'default'
437
+ }
438
+
439
+ const stringify = build(schema, options)
440
+
441
+ const data = { ids: new Array(2e4).fill(null) }
442
+ const result = stringify(data)
443
+
444
+ t.same(result, JSON.stringify(data))
445
+ t.same(JSON.parse(result), data)
446
+ })
@@ -104,11 +104,7 @@ test('object with field of type string and coercion disable ', (t) => {
104
104
  }
105
105
  }
106
106
  const stringify = build(schema)
107
-
108
- const value = stringify({
109
- str: 1
110
- })
111
- t.equal(value, '{"str":null}')
107
+ t.throws(() => stringify({ str: 1 }))
112
108
  })
113
109
 
114
110
  test('object with field of type string and coercion enable ', (t) => {
@@ -403,7 +399,7 @@ test('oneOf object with field of type string with format or null', (t) => {
403
399
  })
404
400
 
405
401
  test('one array item match oneOf types', (t) => {
406
- t.plan(1)
402
+ t.plan(3)
407
403
 
408
404
  const schema = {
409
405
  type: 'object',
@@ -429,15 +425,13 @@ test('one array item match oneOf types', (t) => {
429
425
 
430
426
  const stringify = build(schema)
431
427
 
432
- const responseWithMappedType = stringify({
433
- data: [false, 'foo']
434
- })
435
-
436
- t.equal('{"data":["foo"]}', responseWithMappedType)
428
+ t.equal(stringify({ data: ['foo'] }), '{"data":["foo"]}')
429
+ t.equal(stringify({ data: [1] }), '{"data":[1]}')
430
+ t.throws(() => stringify({ data: [false, 'foo'] }))
437
431
  })
438
432
 
439
433
  test('some array items match oneOf types', (t) => {
440
- t.plan(1)
434
+ t.plan(2)
441
435
 
442
436
  const schema = {
443
437
  type: 'object',
@@ -463,11 +457,8 @@ test('some array items match oneOf types', (t) => {
463
457
 
464
458
  const stringify = build(schema)
465
459
 
466
- const responseWithMappedTypes = stringify({
467
- data: [false, 'foo', true, 5]
468
- })
469
-
470
- t.equal('{"data":["foo",5]}', responseWithMappedTypes)
460
+ t.equal(stringify({ data: ['foo', 5] }), '{"data":["foo",5]}')
461
+ t.throws(() => stringify({ data: [false, 'foo', true, 5] }))
471
462
  })
472
463
 
473
464
  test('all array items does not match oneOf types', (t) => {
@@ -497,9 +488,5 @@ test('all array items does not match oneOf types', (t) => {
497
488
 
498
489
  const stringify = build(schema)
499
490
 
500
- const emptyResponse = stringify({
501
- data: [null, false, true, undefined, [], {}]
502
- })
503
-
504
- t.equal('{"data":[]}', emptyResponse)
491
+ t.throws(() => stringify({ data: [null, false, true, undefined, [], {}] }))
505
492
  })
@@ -63,7 +63,7 @@ test('patternProperties - string coerce', (t) => {
63
63
  })
64
64
 
65
65
  test('patternProperties - number coerce', (t) => {
66
- t.plan(1)
66
+ t.plan(2)
67
67
  const stringify = build({
68
68
  title: 'check number coerce',
69
69
  type: 'object',
@@ -75,8 +75,16 @@ test('patternProperties - number coerce', (t) => {
75
75
  }
76
76
  })
77
77
 
78
- const obj = { foo: true, ofoo: '42', xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
79
- t.equal(stringify(obj), '{"foo":1,"ofoo":42,"xfoo":null,"arrfoo":null,"objfoo":null}')
78
+ const coercibleValues = { foo: true, ofoo: '42' }
79
+ t.equal(stringify(coercibleValues), '{"foo":1,"ofoo":42}')
80
+
81
+ const incoercibleValues = { xfoo: 'string', arrfoo: [1, 2], objfoo: { num: 42 } }
82
+ try {
83
+ stringify(incoercibleValues)
84
+ t.fail('should throw an error')
85
+ } catch (err) {
86
+ t.ok(err)
87
+ }
80
88
  })
81
89
 
82
90
  test('patternProperties - boolean coerce', (t) => {
@@ -119,7 +127,7 @@ test('patternProperties - object coerce', (t) => {
119
127
  })
120
128
 
121
129
  test('patternProperties - array coerce', (t) => {
122
- t.plan(1)
130
+ t.plan(2)
123
131
  const stringify = build({
124
132
  title: 'check array coerce',
125
133
  type: 'object',
@@ -134,6 +142,9 @@ test('patternProperties - array coerce', (t) => {
134
142
  }
135
143
  })
136
144
 
137
- const obj = { foo: 'true', ofoo: 0, arrfoo: [1, 2], objfoo: { tyrion: 'lannister' } }
138
- t.equal(stringify(obj), '{"foo":["t","r","u","e"],"ofoo":[],"arrfoo":["1","2"],"objfoo":[]}')
145
+ const coercibleValues = { arrfoo: [1, 2] }
146
+ t.equal(stringify(coercibleValues), '{"arrfoo":["1","2"]}')
147
+
148
+ const incoercibleValues = { foo: 'true', ofoo: 0, objfoo: { tyrion: 'lannister' } }
149
+ t.throws(() => stringify(incoercibleValues))
139
150
  })
@@ -232,7 +232,7 @@ test('required numbers', (t) => {
232
232
  })
233
233
  t.fail()
234
234
  } catch (e) {
235
- t.equal(e.message, '"num" is required!')
235
+ t.equal(e.message, 'The value "aaa" cannot be converted to an integer.')
236
236
  t.pass()
237
237
  }
238
238
  })
@@ -3,15 +3,13 @@
3
3
  const t = require('tap')
4
4
  const build = require('..')
5
5
 
6
- const stringify = build({
7
- $defs: {
8
- type: 'foooo"bar'
9
- },
10
- patternProperties: {
11
- x: { $ref: '#/$defs' }
12
- }
13
- })
14
-
15
6
  t.throws(() => {
16
- stringify({ x: 0 })
17
- }, 'Cannot coerce 0 to "foo"bar"')
7
+ build({
8
+ $defs: {
9
+ type: 'foooo"bar'
10
+ },
11
+ patternProperties: {
12
+ x: { $ref: '#/$defs' }
13
+ }
14
+ })
15
+ }, 'foooo"bar unsupported')
@@ -0,0 +1,121 @@
1
+ 'use strict'
2
+
3
+ const test = require('tap').test
4
+ const fjs = require('..')
5
+ const fs = require('fs')
6
+ const path = require('path')
7
+
8
+ function build (opts, schema) {
9
+ return fjs(schema || {
10
+ title: 'default string',
11
+ type: 'object',
12
+ properties: {
13
+ firstName: {
14
+ type: 'string'
15
+ }
16
+ },
17
+ required: ['firstName']
18
+ }, opts)
19
+ }
20
+
21
+ const tmpDir = 'test/fixtures'
22
+
23
+ test('activate standalone mode', async (t) => {
24
+ t.plan(3)
25
+ const code = build({ mode: 'standalone' })
26
+ t.type(code, 'string')
27
+ t.equal(code.indexOf('ajv'), -1)
28
+
29
+ const destionation = path.resolve(tmpDir, 'standalone.js')
30
+
31
+ t.teardown(async () => {
32
+ await fs.promises.rm(destionation, { force: true })
33
+ })
34
+
35
+ await fs.promises.writeFile(destionation, code)
36
+ const standalone = require(destionation)
37
+ t.same(standalone({ firstName: 'Foo', surname: 'bar' }), JSON.stringify({ firstName: 'Foo' }), 'surname evicted')
38
+ })
39
+
40
+ test('test ajv schema', async (t) => {
41
+ t.plan(3)
42
+ const code = build({ mode: 'standalone' }, {
43
+ type: 'object',
44
+ properties: {
45
+ },
46
+ if: {
47
+ type: 'object',
48
+ properties: {
49
+ kind: { type: 'string', enum: ['foobar'] }
50
+ }
51
+ },
52
+ then: {
53
+ type: 'object',
54
+ properties: {
55
+ kind: { type: 'string', enum: ['foobar'] },
56
+ foo: { type: 'string' },
57
+ bar: { type: 'number' },
58
+ list: {
59
+ type: 'array',
60
+ items: {
61
+ type: 'object',
62
+ properties: {
63
+ name: { type: 'string' },
64
+ value: { type: 'string' }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ },
70
+ else: {
71
+ type: 'object',
72
+ properties: {
73
+ kind: { type: 'string', enum: ['greeting'] },
74
+ hi: { type: 'string' },
75
+ hello: { type: 'number' },
76
+ list: {
77
+ type: 'array',
78
+ items: {
79
+ type: 'object',
80
+ properties: {
81
+ name: { type: 'string' },
82
+ value: { type: 'string' }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ })
89
+ t.type(code, 'string')
90
+ t.equal(code.indexOf('ajv') > 0, true)
91
+
92
+ const destionation = path.resolve(tmpDir, 'standalone2.js')
93
+
94
+ t.teardown(async () => {
95
+ await fs.promises.rm(destionation, { force: true })
96
+ })
97
+
98
+ await fs.promises.writeFile(destionation, code)
99
+ const standalone = require(destionation)
100
+ t.same(standalone({
101
+ kind: 'foobar',
102
+ foo: 'FOO',
103
+ list: [{
104
+ name: 'name',
105
+ value: 'foo'
106
+ }],
107
+ bar: 42,
108
+ hi: 'HI',
109
+ hello: 45,
110
+ a: 'A',
111
+ b: 35
112
+ }), JSON.stringify({
113
+ kind: 'foobar',
114
+ foo: 'FOO',
115
+ bar: 42,
116
+ list: [{
117
+ name: 'name',
118
+ value: 'foo'
119
+ }]
120
+ }))
121
+ })
@@ -1,3 +1,4 @@
1
+ import Ajv from 'ajv'
1
2
  import build, { Schema } from '../..'
2
3
 
3
4
  // Number schemas
@@ -142,4 +143,11 @@ const schema12: Schema = {
142
143
  format: 'date-time'
143
144
  }
144
145
 
145
- build(schema12)(new Date())
146
+ build(schema12)(new Date())
147
+
148
+ let str: string, ajv: Ajv
149
+ str = build(schema1, { debugMode: true }).code
150
+ ajv = build(schema1, { debugMode: true }).ajv
151
+ str = build(schema1, { mode: 'debug' }).code
152
+ ajv = build(schema1, { mode: 'debug' }).ajv
153
+ str = build(schema1, { mode: 'standalone' })
@@ -1,7 +1,6 @@
1
1
  'use strict'
2
2
 
3
3
  const test = require('tap').test
4
- const moment = require('moment')
5
4
  const build = require('..')
6
5
 
7
6
  test('possibly nullable integer primitive alternative', (t) => {
@@ -88,6 +87,27 @@ test('possibly nullable number primitive alternative with null value', (t) => {
88
87
  t.equal(value, '{"data":0}')
89
88
  })
90
89
 
90
+ test('possibly nullable number primitive alternative with null value', (t) => {
91
+ t.plan(1)
92
+
93
+ const schema = {
94
+ title: 'simple object with multi-type nullable primitive',
95
+ type: 'object',
96
+ properties: {
97
+ data: {
98
+ type: ['boolean']
99
+ }
100
+ }
101
+ }
102
+
103
+ const stringify = build(schema)
104
+
105
+ const value = stringify({
106
+ data: null
107
+ })
108
+ t.equal(value, '{"data":false}')
109
+ })
110
+
91
111
  test('nullable integer primitive', (t) => {
92
112
  t.plan(1)
93
113
 
@@ -361,7 +381,7 @@ test('string type array can handle dates', (t) => {
361
381
  const stringify = build(schema)
362
382
  const value = stringify({
363
383
  date: new Date('2018-04-20T07:52:31.017Z'),
364
- dateObject: moment('2018-04-21T07:52:31.017Z')
384
+ dateObject: new Date('2018-04-21T07:52:31.017Z')
365
385
  })
366
386
  t.equal(value, '{"date":"2018-04-20T07:52:31.017Z","dateObject":"2018-04-21T07:52:31.017Z"}')
367
387
  })
@@ -433,5 +453,22 @@ test('should throw an error when type is array and object is null', (t) => {
433
453
  }
434
454
 
435
455
  const stringify = build(schema)
436
- t.throws(() => stringify({ arr: null }), new TypeError('Property \'arr\' should be of type array, received \'null\' instead.'))
456
+ t.throws(() => stringify({ arr: null }), new TypeError('The value \'null\' does not match schema definition.'))
457
+ })
458
+
459
+ test('throw an error if none of types matches', (t) => {
460
+ t.plan(1)
461
+
462
+ const schema = {
463
+ title: 'simple object with multi-type nullable primitive',
464
+ type: 'object',
465
+ properties: {
466
+ data: {
467
+ type: ['number', 'boolean']
468
+ }
469
+ }
470
+ }
471
+
472
+ const stringify = build(schema)
473
+ t.throws(() => stringify({ data: 'string' }), 'The value "string" does not match schema definition.')
437
474
  })