@atproto/lex-json 0.0.14 → 0.0.16
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/CHANGELOG.md +15 -0
- package/dist/blob.d.ts +4 -4
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +6 -6
- package/dist/blob.js.map +1 -1
- package/dist/json-bytes-decoder.d.ts +24 -0
- package/dist/json-bytes-decoder.d.ts.map +1 -0
- package/dist/json-bytes-decoder.js +600 -0
- package/dist/json-bytes-decoder.js.map +1 -0
- package/dist/lex-json.d.ts +9 -1
- package/dist/lex-json.d.ts.map +1 -1
- package/dist/lex-json.js +25 -24
- package/dist/lex-json.js.map +1 -1
- package/package.json +2 -2
- package/src/blob.ts +8 -8
- package/src/json-bytes-decoder.bench.ts +252 -0
- package/src/json-bytes-decoder.test.ts +889 -0
- package/src/json-bytes-decoder.ts +672 -0
- package/src/lex-json.bench.ts +125 -0
- package/src/lex-json.test.ts +535 -69
- package/src/lex-json.ts +29 -23
- package/tsconfig.build.json +1 -1
- package/tsconfig.tests.json +1 -1
package/src/lex-json.test.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { describe, expect,
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
2
|
import { LexValue, lexEquals, parseCid } from '@atproto/lex-data'
|
|
3
3
|
import { JsonValue } from './json.js'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
jsonToLex,
|
|
6
|
+
lexParse,
|
|
7
|
+
lexParseJsonBytes,
|
|
8
|
+
lexStringify,
|
|
9
|
+
lexToJson,
|
|
10
|
+
} from './lex-json.js'
|
|
5
11
|
|
|
6
12
|
export const validVectors: Array<{
|
|
7
13
|
name: string
|
|
@@ -330,6 +336,24 @@ export const acceptableVectors: Array<{
|
|
|
330
336
|
$link: 'bafkreiccldh766hwcnuxnf2wh6jgzepf2nlu2lvcllt63eww5p6chi4ity',
|
|
331
337
|
},
|
|
332
338
|
},
|
|
339
|
+
{
|
|
340
|
+
note: 'blob with CBOR CID ref',
|
|
341
|
+
json: {
|
|
342
|
+
$type: 'blob',
|
|
343
|
+
ref: {
|
|
344
|
+
$link: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
|
|
345
|
+
},
|
|
346
|
+
mimeType: 'image/png',
|
|
347
|
+
size: 1,
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
note: 'object with empty $type',
|
|
352
|
+
json: {
|
|
353
|
+
$type: '',
|
|
354
|
+
foo: 'bar',
|
|
355
|
+
},
|
|
356
|
+
},
|
|
333
357
|
]
|
|
334
358
|
|
|
335
359
|
export const invalidVectors: Array<{
|
|
@@ -364,58 +388,143 @@ export const invalidVectors: Array<{
|
|
|
364
388
|
|
|
365
389
|
describe(lexParse, () => {
|
|
366
390
|
describe('valid vectors', () => {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
391
|
+
describe('strict mode', () => {
|
|
392
|
+
for (const { name, json, lex } of validVectors) {
|
|
393
|
+
test(name, () => {
|
|
370
394
|
expect(
|
|
371
|
-
lexEquals(lex, lexParse(JSON.stringify(json), { strict:
|
|
395
|
+
lexEquals(lex, lexParse(JSON.stringify(json), { strict: true })),
|
|
372
396
|
).toBe(true)
|
|
397
|
+
})
|
|
398
|
+
}
|
|
399
|
+
})
|
|
400
|
+
describe('non-strict mode', () => {
|
|
401
|
+
for (const { name, json, lex } of validVectors) {
|
|
402
|
+
test(name, () => {
|
|
373
403
|
expect(
|
|
374
|
-
lexEquals(lex, lexParse(JSON.stringify(json), { strict:
|
|
404
|
+
lexEquals(lex, lexParse(JSON.stringify(json), { strict: false })),
|
|
375
405
|
).toBe(true)
|
|
376
406
|
})
|
|
377
|
-
}
|
|
378
|
-
}
|
|
407
|
+
}
|
|
408
|
+
})
|
|
379
409
|
})
|
|
380
410
|
|
|
381
411
|
describe('acceptable vectors', () => {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
412
|
+
describe('strict mode', () => {
|
|
413
|
+
for (const { note, json } of acceptableVectors) {
|
|
414
|
+
test(note, () => {
|
|
415
|
+
expect(() =>
|
|
416
|
+
lexParse(JSON.stringify(json), { strict: true }),
|
|
417
|
+
).toThrow()
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
})
|
|
421
|
+
describe('non-strict mode', () => {
|
|
422
|
+
for (const { note, json } of acceptableVectors) {
|
|
423
|
+
test(note, () => {
|
|
385
424
|
expect(() =>
|
|
386
425
|
lexParse(JSON.stringify(json), { strict: false }),
|
|
387
426
|
).not.toThrow()
|
|
388
427
|
})
|
|
428
|
+
}
|
|
429
|
+
})
|
|
430
|
+
})
|
|
389
431
|
|
|
390
|
-
|
|
432
|
+
describe('invalid vectors', () => {
|
|
433
|
+
describe('strict mode', () => {
|
|
434
|
+
for (const { note, json } of invalidVectors) {
|
|
435
|
+
test(note, () => {
|
|
391
436
|
expect(() =>
|
|
392
437
|
lexParse(JSON.stringify(json), { strict: true }),
|
|
393
438
|
).toThrow()
|
|
394
439
|
})
|
|
440
|
+
}
|
|
441
|
+
})
|
|
442
|
+
describe('non-strict mode', () => {
|
|
443
|
+
for (const { note, json } of invalidVectors) {
|
|
444
|
+
test(note, () => {
|
|
445
|
+
expect(() =>
|
|
446
|
+
lexParse(JSON.stringify(json), { strict: false }),
|
|
447
|
+
).not.toThrow()
|
|
448
|
+
})
|
|
449
|
+
}
|
|
450
|
+
})
|
|
451
|
+
})
|
|
452
|
+
})
|
|
453
|
+
|
|
454
|
+
describe(lexParseJsonBytes, () => {
|
|
455
|
+
describe('valid vectors', () => {
|
|
456
|
+
describe('strict mode', () => {
|
|
457
|
+
describe('with pretty-printed JSON', () => {
|
|
458
|
+
for (const { name, json, lex } of validVectors) {
|
|
459
|
+
test(name, () => {
|
|
460
|
+
const jsonBytes = Buffer.from(JSON.stringify(json, undefined, 4))
|
|
461
|
+
expect(
|
|
462
|
+
lexEquals(lex, lexParseJsonBytes(jsonBytes, { strict: true })),
|
|
463
|
+
).toBe(true)
|
|
464
|
+
})
|
|
465
|
+
}
|
|
395
466
|
})
|
|
396
|
-
|
|
467
|
+
describe('with compact JSON', () => {
|
|
468
|
+
for (const { name, json, lex } of validVectors) {
|
|
469
|
+
test(name, () => {
|
|
470
|
+
const jsonBytes = Buffer.from(JSON.stringify(json))
|
|
471
|
+
expect(
|
|
472
|
+
lexEquals(lex, lexParseJsonBytes(jsonBytes, { strict: true })),
|
|
473
|
+
).toBe(true)
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
})
|
|
477
|
+
})
|
|
478
|
+
|
|
479
|
+
describe('non-strict mode', () => {
|
|
480
|
+
for (const { name, json, lex } of validVectors) {
|
|
481
|
+
test(name, () => {
|
|
482
|
+
const jsonBytes = Buffer.from(JSON.stringify(json))
|
|
483
|
+
expect(
|
|
484
|
+
lexEquals(lex, lexParseJsonBytes(jsonBytes, { strict: false })),
|
|
485
|
+
).toBe(true)
|
|
486
|
+
})
|
|
487
|
+
}
|
|
488
|
+
})
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
describe('acceptable vectors', () => {
|
|
492
|
+
describe('strict mode', () => {
|
|
493
|
+
for (const { note, json } of acceptableVectors) {
|
|
494
|
+
test(note, () => {
|
|
495
|
+
const jsonBytes = Buffer.from(JSON.stringify(json))
|
|
496
|
+
expect(() => lexParseJsonBytes(jsonBytes, { strict: true })).toThrow()
|
|
497
|
+
})
|
|
498
|
+
}
|
|
499
|
+
})
|
|
500
|
+
describe('non-strict mode', () => {
|
|
501
|
+
for (const { note, json } of acceptableVectors) {
|
|
502
|
+
test(note, () => {
|
|
503
|
+
const jsonBytes = Buffer.from(JSON.stringify(json))
|
|
504
|
+
expect(() =>
|
|
505
|
+
lexParseJsonBytes(jsonBytes, { strict: false }),
|
|
506
|
+
).not.toThrow()
|
|
507
|
+
})
|
|
508
|
+
}
|
|
509
|
+
})
|
|
397
510
|
})
|
|
398
511
|
|
|
399
512
|
describe('invalid vectors', () => {
|
|
400
513
|
describe('strict mode', () => {
|
|
401
514
|
for (const { note, json } of invalidVectors) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
lexParse(JSON.stringify(json), { strict: true }),
|
|
406
|
-
).toThrow()
|
|
407
|
-
})
|
|
515
|
+
test(note, () => {
|
|
516
|
+
const jsonBytes = Buffer.from(JSON.stringify(json))
|
|
517
|
+
expect(() => lexParseJsonBytes(jsonBytes, { strict: true })).toThrow()
|
|
408
518
|
})
|
|
409
519
|
}
|
|
410
520
|
})
|
|
411
521
|
describe('non-strict mode', () => {
|
|
412
522
|
for (const { note, json } of invalidVectors) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
})
|
|
523
|
+
test(note, () => {
|
|
524
|
+
const jsonBytes = Buffer.from(JSON.stringify(json))
|
|
525
|
+
expect(() =>
|
|
526
|
+
lexParseJsonBytes(jsonBytes, { strict: false }),
|
|
527
|
+
).not.toThrow()
|
|
419
528
|
})
|
|
420
529
|
}
|
|
421
530
|
})
|
|
@@ -425,10 +534,8 @@ describe(lexParse, () => {
|
|
|
425
534
|
describe(lexStringify, () => {
|
|
426
535
|
describe('valid vectors', () => {
|
|
427
536
|
for (const { name, json, lex } of validVectors) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
expect(JSON.parse(lexStringify(lex))).toEqual(json)
|
|
431
|
-
})
|
|
537
|
+
test(name, () => {
|
|
538
|
+
expect(JSON.parse(lexStringify(lex))).toStrictEqual(json)
|
|
432
539
|
})
|
|
433
540
|
}
|
|
434
541
|
})
|
|
@@ -436,63 +543,66 @@ describe(lexStringify, () => {
|
|
|
436
543
|
|
|
437
544
|
describe(jsonToLex, () => {
|
|
438
545
|
describe('valid vectors', () => {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
546
|
+
describe('strict mode', () => {
|
|
547
|
+
for (const { name, json, lex } of validVectors) {
|
|
548
|
+
test(name, () => {
|
|
442
549
|
expect(lexEquals(jsonToLex(json, { strict: true }), lex)).toBe(true)
|
|
443
550
|
expect(lexEquals(lex, jsonToLex(json, { strict: true }))).toBe(true)
|
|
444
551
|
})
|
|
552
|
+
}
|
|
553
|
+
})
|
|
445
554
|
|
|
446
|
-
|
|
555
|
+
describe('non-strict mode', () => {
|
|
556
|
+
for (const { name, json, lex } of validVectors) {
|
|
557
|
+
test(name, () => {
|
|
447
558
|
expect(lexEquals(jsonToLex(json, { strict: false }), lex)).toBe(true)
|
|
448
559
|
expect(lexEquals(lex, jsonToLex(json, { strict: false }))).toBe(true)
|
|
449
560
|
})
|
|
450
|
-
}
|
|
451
|
-
}
|
|
561
|
+
}
|
|
562
|
+
})
|
|
452
563
|
})
|
|
453
564
|
|
|
454
565
|
describe('acceptable vectors', () => {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
566
|
+
describe('strict mode', () => {
|
|
567
|
+
for (const { note, json } of acceptableVectors) {
|
|
568
|
+
test(note, () => {
|
|
458
569
|
expect(() => jsonToLex(json, { strict: true })).toThrow()
|
|
459
570
|
})
|
|
571
|
+
}
|
|
572
|
+
})
|
|
460
573
|
|
|
461
|
-
|
|
574
|
+
describe('non-strict mode', () => {
|
|
575
|
+
for (const { note, json } of acceptableVectors) {
|
|
576
|
+
test(note, () => {
|
|
462
577
|
expect(() => jsonToLex(json, { strict: false })).not.toThrow()
|
|
463
578
|
})
|
|
464
|
-
}
|
|
465
|
-
}
|
|
579
|
+
}
|
|
580
|
+
})
|
|
466
581
|
})
|
|
467
582
|
|
|
468
583
|
describe('invalid vectors', () => {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
584
|
+
describe('strict mode', () => {
|
|
585
|
+
for (const { note, json } of invalidVectors) {
|
|
586
|
+
test(note, () => {
|
|
472
587
|
expect(() => jsonToLex(json, { strict: true })).toThrow()
|
|
473
588
|
})
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
it('does not throw in non-strict mode', () => {
|
|
589
|
+
}
|
|
590
|
+
})
|
|
591
|
+
describe('non-strict mode', () => {
|
|
592
|
+
for (const { note, json } of invalidVectors) {
|
|
593
|
+
test(note, () => {
|
|
481
594
|
expect(() => jsonToLex(json, { strict: false })).not.toThrow()
|
|
482
595
|
})
|
|
483
|
-
}
|
|
484
|
-
}
|
|
596
|
+
}
|
|
597
|
+
})
|
|
485
598
|
})
|
|
486
599
|
})
|
|
487
600
|
|
|
488
601
|
describe(lexToJson, () => {
|
|
489
602
|
describe('valid vectors', () => {
|
|
490
603
|
for (const { name, json, lex } of validVectors) {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
expect(lexToJson(lex)).toEqual(json)
|
|
494
|
-
expect(lexToJson(lex)).toEqual(json)
|
|
495
|
-
})
|
|
604
|
+
test(name, () => {
|
|
605
|
+
expect(lexToJson(lex)).toStrictEqual(json)
|
|
496
606
|
})
|
|
497
607
|
}
|
|
498
608
|
})
|
|
@@ -501,10 +611,19 @@ describe(lexToJson, () => {
|
|
|
501
611
|
describe('json > lex > json', () => {
|
|
502
612
|
describe('valid vectors', () => {
|
|
503
613
|
for (const { name, json } of validVectors) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
614
|
+
test(name, () => {
|
|
615
|
+
expect(lexToJson(jsonToLex(json))).toStrictEqual(json)
|
|
616
|
+
})
|
|
617
|
+
}
|
|
618
|
+
})
|
|
619
|
+
})
|
|
620
|
+
|
|
621
|
+
describe('json (binary) > lex > json', () => {
|
|
622
|
+
describe('valid vectors', () => {
|
|
623
|
+
for (const { name, json } of validVectors) {
|
|
624
|
+
test(name, () => {
|
|
625
|
+
const jsonBytes = Buffer.from(JSON.stringify(json, undefined, 4))
|
|
626
|
+
expect(lexToJson(lexParseJsonBytes(jsonBytes))).toStrictEqual(json)
|
|
508
627
|
})
|
|
509
628
|
}
|
|
510
629
|
})
|
|
@@ -513,13 +632,360 @@ describe('json > lex > json', () => {
|
|
|
513
632
|
describe('lex > json > lex', () => {
|
|
514
633
|
describe('valid vectors', () => {
|
|
515
634
|
for (const { name, lex } of validVectors) {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
expect(lexEquals(jsonToLex(lexToJson(lex)), lex)).toBe(true)
|
|
520
|
-
expect(lexEquals(lex, jsonToLex(lexToJson(lex)))).toBe(true)
|
|
521
|
-
})
|
|
635
|
+
test(name, () => {
|
|
636
|
+
expect(lexEquals(jsonToLex(lexToJson(lex)), lex)).toBe(true)
|
|
637
|
+
expect(lexEquals(lex, jsonToLex(lexToJson(lex)))).toBe(true)
|
|
522
638
|
})
|
|
523
639
|
}
|
|
524
640
|
})
|
|
525
641
|
})
|
|
642
|
+
|
|
643
|
+
describe('lexParseJsonBytes strict mode error parity with lexParse', () => {
|
|
644
|
+
describe('invalid JSON input throws SyntaxError containing "Unexpected token"', () => {
|
|
645
|
+
test('lexParse throws with Unexpected token', () => {
|
|
646
|
+
expect(() => lexParse('not valid json', { strict: true })).toThrow(
|
|
647
|
+
/Unexpected token/,
|
|
648
|
+
)
|
|
649
|
+
})
|
|
650
|
+
|
|
651
|
+
test('lexParseJsonBytes throws with Unexpected token', () => {
|
|
652
|
+
expect(() =>
|
|
653
|
+
lexParseJsonBytes(Buffer.from('not valid json'), { strict: true }),
|
|
654
|
+
).toThrow(/Unexpected token/)
|
|
655
|
+
})
|
|
656
|
+
|
|
657
|
+
test('lexParseJsonBytes non-strict also throws with Unexpected token for invalid JSON', () => {
|
|
658
|
+
expect(() =>
|
|
659
|
+
lexParseJsonBytes(Buffer.from('not valid json'), { strict: false }),
|
|
660
|
+
).toThrow(/Unexpected token/)
|
|
661
|
+
})
|
|
662
|
+
})
|
|
663
|
+
|
|
664
|
+
describe('float numbers: strict throws TypeError, non-strict accepts', () => {
|
|
665
|
+
const jsonStr = '{"value":1.5}'
|
|
666
|
+
|
|
667
|
+
test('lexParse strict throws TypeError with value in message', () => {
|
|
668
|
+
expect(() => lexParse(jsonStr, { strict: true })).toThrow(TypeError)
|
|
669
|
+
expect(() => lexParse(jsonStr, { strict: true })).toThrow(
|
|
670
|
+
'Invalid non-integer number: 1.5',
|
|
671
|
+
)
|
|
672
|
+
})
|
|
673
|
+
|
|
674
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
675
|
+
const bytes = Buffer.from(jsonStr)
|
|
676
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
677
|
+
TypeError,
|
|
678
|
+
)
|
|
679
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
680
|
+
'Invalid non-integer number: 1.5',
|
|
681
|
+
)
|
|
682
|
+
})
|
|
683
|
+
|
|
684
|
+
test('lexParse non-strict accepts float', () => {
|
|
685
|
+
expect(() => lexParse(jsonStr, { strict: false })).not.toThrow()
|
|
686
|
+
})
|
|
687
|
+
|
|
688
|
+
test('lexParseJsonBytes non-strict accepts float', () => {
|
|
689
|
+
expect(() =>
|
|
690
|
+
lexParseJsonBytes(Buffer.from(jsonStr), { strict: false }),
|
|
691
|
+
).not.toThrow()
|
|
692
|
+
})
|
|
693
|
+
})
|
|
694
|
+
|
|
695
|
+
describe('exponent notation: safe integers accepted, unsafe integers rejected', () => {
|
|
696
|
+
test('lexParse strict accepts 1e10 (safe integer)', () => {
|
|
697
|
+
expect(lexParse('1e10', { strict: true })).toBe(1e10)
|
|
698
|
+
})
|
|
699
|
+
|
|
700
|
+
test('lexParseJsonBytes strict accepts 1e10 (safe integer)', () => {
|
|
701
|
+
expect(lexParseJsonBytes(Buffer.from('1e10'), { strict: true })).toBe(
|
|
702
|
+
1e10,
|
|
703
|
+
)
|
|
704
|
+
})
|
|
705
|
+
|
|
706
|
+
test('lexParse strict rejects 1e20 (unsafe integer)', () => {
|
|
707
|
+
expect(() => lexParse('1e20', { strict: true })).toThrow(TypeError)
|
|
708
|
+
})
|
|
709
|
+
|
|
710
|
+
test('lexParseJsonBytes strict rejects 1e20 (unsafe integer)', () => {
|
|
711
|
+
expect(() =>
|
|
712
|
+
lexParseJsonBytes(Buffer.from('1e20'), { strict: true }),
|
|
713
|
+
).toThrow(TypeError)
|
|
714
|
+
})
|
|
715
|
+
})
|
|
716
|
+
|
|
717
|
+
describe('invalid blob: strict throws TypeError, non-strict returns plain object', () => {
|
|
718
|
+
const invalidBlobJson = '{"$type":"blob"}'
|
|
719
|
+
|
|
720
|
+
test('lexParse strict throws TypeError with "Invalid blob object"', () => {
|
|
721
|
+
expect(() => lexParse(invalidBlobJson, { strict: true })).toThrow(
|
|
722
|
+
TypeError,
|
|
723
|
+
)
|
|
724
|
+
expect(() => lexParse(invalidBlobJson, { strict: true })).toThrow(
|
|
725
|
+
'Invalid blob object',
|
|
726
|
+
)
|
|
727
|
+
})
|
|
728
|
+
|
|
729
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
730
|
+
const bytes = Buffer.from(invalidBlobJson)
|
|
731
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
732
|
+
TypeError,
|
|
733
|
+
)
|
|
734
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
735
|
+
'Invalid blob object',
|
|
736
|
+
)
|
|
737
|
+
})
|
|
738
|
+
|
|
739
|
+
test('lexParse non-strict returns plain object', () => {
|
|
740
|
+
expect(() => lexParse(invalidBlobJson, { strict: false })).not.toThrow()
|
|
741
|
+
})
|
|
742
|
+
|
|
743
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
744
|
+
expect(() =>
|
|
745
|
+
lexParseJsonBytes(Buffer.from(invalidBlobJson), { strict: false }),
|
|
746
|
+
).not.toThrow()
|
|
747
|
+
})
|
|
748
|
+
})
|
|
749
|
+
|
|
750
|
+
describe('blob with CBOR CID: strict throws TypeError, non-strict returns plain object', () => {
|
|
751
|
+
const blobWithCborCidJson = JSON.stringify({
|
|
752
|
+
$type: 'blob',
|
|
753
|
+
ref: {
|
|
754
|
+
$link: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
|
|
755
|
+
},
|
|
756
|
+
mimeType: 'image/png',
|
|
757
|
+
size: 1,
|
|
758
|
+
})
|
|
759
|
+
|
|
760
|
+
test('lexParse strict throws TypeError with "Invalid blob object"', () => {
|
|
761
|
+
expect(() => lexParse(blobWithCborCidJson, { strict: true })).toThrow(
|
|
762
|
+
TypeError,
|
|
763
|
+
)
|
|
764
|
+
expect(() => lexParse(blobWithCborCidJson, { strict: true })).toThrow(
|
|
765
|
+
'Invalid blob object',
|
|
766
|
+
)
|
|
767
|
+
})
|
|
768
|
+
|
|
769
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
770
|
+
const bytes = Buffer.from(blobWithCborCidJson)
|
|
771
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
772
|
+
TypeError,
|
|
773
|
+
)
|
|
774
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
775
|
+
'Invalid blob object',
|
|
776
|
+
)
|
|
777
|
+
})
|
|
778
|
+
|
|
779
|
+
test('lexParse non-strict returns plain object', () => {
|
|
780
|
+
expect(() =>
|
|
781
|
+
lexParse(blobWithCborCidJson, { strict: false }),
|
|
782
|
+
).not.toThrow()
|
|
783
|
+
})
|
|
784
|
+
|
|
785
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
786
|
+
expect(() =>
|
|
787
|
+
lexParseJsonBytes(Buffer.from(blobWithCborCidJson), { strict: false }),
|
|
788
|
+
).not.toThrow()
|
|
789
|
+
})
|
|
790
|
+
})
|
|
791
|
+
|
|
792
|
+
describe('invalid $link: strict throws TypeError, non-strict returns plain object', () => {
|
|
793
|
+
const invalidLinkJson = '{"$link":"."}'
|
|
794
|
+
|
|
795
|
+
test('lexParse strict throws TypeError with "Invalid $link object"', () => {
|
|
796
|
+
expect(() => lexParse(invalidLinkJson, { strict: true })).toThrow(
|
|
797
|
+
TypeError,
|
|
798
|
+
)
|
|
799
|
+
expect(() => lexParse(invalidLinkJson, { strict: true })).toThrow(
|
|
800
|
+
'Invalid $link object',
|
|
801
|
+
)
|
|
802
|
+
})
|
|
803
|
+
|
|
804
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
805
|
+
const bytes = Buffer.from(invalidLinkJson)
|
|
806
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
807
|
+
TypeError,
|
|
808
|
+
)
|
|
809
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
810
|
+
'Invalid $link object',
|
|
811
|
+
)
|
|
812
|
+
})
|
|
813
|
+
|
|
814
|
+
test('lexParse non-strict returns plain object', () => {
|
|
815
|
+
expect(() => lexParse(invalidLinkJson, { strict: false })).not.toThrow()
|
|
816
|
+
})
|
|
817
|
+
|
|
818
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
819
|
+
expect(() =>
|
|
820
|
+
lexParseJsonBytes(Buffer.from(invalidLinkJson), { strict: false }),
|
|
821
|
+
).not.toThrow()
|
|
822
|
+
})
|
|
823
|
+
})
|
|
824
|
+
|
|
825
|
+
describe('$link with extra fields: strict throws TypeError, non-strict returns plain object', () => {
|
|
826
|
+
const linkWithExtraJson =
|
|
827
|
+
'{"$link":"bafkreiccldh766hwcnuxnf2wh6jgzepf2nlu2lvcllt63eww5p6chi4ity","extra":"field"}'
|
|
828
|
+
|
|
829
|
+
test('lexParse strict throws TypeError with "Invalid $link object"', () => {
|
|
830
|
+
expect(() => lexParse(linkWithExtraJson, { strict: true })).toThrow(
|
|
831
|
+
TypeError,
|
|
832
|
+
)
|
|
833
|
+
expect(() => lexParse(linkWithExtraJson, { strict: true })).toThrow(
|
|
834
|
+
'Invalid $link object',
|
|
835
|
+
)
|
|
836
|
+
})
|
|
837
|
+
|
|
838
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
839
|
+
const bytes = Buffer.from(linkWithExtraJson)
|
|
840
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
841
|
+
TypeError,
|
|
842
|
+
)
|
|
843
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
844
|
+
'Invalid $link object',
|
|
845
|
+
)
|
|
846
|
+
})
|
|
847
|
+
|
|
848
|
+
test('lexParse non-strict returns plain object', () => {
|
|
849
|
+
expect(() => lexParse(linkWithExtraJson, { strict: false })).not.toThrow()
|
|
850
|
+
})
|
|
851
|
+
|
|
852
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
853
|
+
expect(() =>
|
|
854
|
+
lexParseJsonBytes(Buffer.from(linkWithExtraJson), { strict: false }),
|
|
855
|
+
).not.toThrow()
|
|
856
|
+
})
|
|
857
|
+
})
|
|
858
|
+
|
|
859
|
+
describe('invalid $bytes: strict throws TypeError, non-strict returns plain object', () => {
|
|
860
|
+
const invalidBytesJson = '{"$bytes":"🐻"}'
|
|
861
|
+
|
|
862
|
+
test('lexParse strict throws TypeError with "Invalid $bytes object"', () => {
|
|
863
|
+
expect(() => lexParse(invalidBytesJson, { strict: true })).toThrow(
|
|
864
|
+
TypeError,
|
|
865
|
+
)
|
|
866
|
+
expect(() => lexParse(invalidBytesJson, { strict: true })).toThrow(
|
|
867
|
+
'Invalid $bytes object',
|
|
868
|
+
)
|
|
869
|
+
})
|
|
870
|
+
|
|
871
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
872
|
+
const bytes = Buffer.from(invalidBytesJson)
|
|
873
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
874
|
+
TypeError,
|
|
875
|
+
)
|
|
876
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
877
|
+
'Invalid $bytes object',
|
|
878
|
+
)
|
|
879
|
+
})
|
|
880
|
+
|
|
881
|
+
test('lexParse non-strict returns plain object', () => {
|
|
882
|
+
expect(() => lexParse(invalidBytesJson, { strict: false })).not.toThrow()
|
|
883
|
+
})
|
|
884
|
+
|
|
885
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
886
|
+
expect(() =>
|
|
887
|
+
lexParseJsonBytes(Buffer.from(invalidBytesJson), { strict: false }),
|
|
888
|
+
).not.toThrow()
|
|
889
|
+
})
|
|
890
|
+
})
|
|
891
|
+
|
|
892
|
+
describe('$bytes with extra fields: strict throws TypeError, non-strict returns plain object', () => {
|
|
893
|
+
const bytesWithExtraJson =
|
|
894
|
+
'{"$bytes":"nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0","extra":"field"}'
|
|
895
|
+
|
|
896
|
+
test('lexParse strict throws TypeError with "Invalid $bytes object"', () => {
|
|
897
|
+
expect(() => lexParse(bytesWithExtraJson, { strict: true })).toThrow(
|
|
898
|
+
TypeError,
|
|
899
|
+
)
|
|
900
|
+
expect(() => lexParse(bytesWithExtraJson, { strict: true })).toThrow(
|
|
901
|
+
'Invalid $bytes object',
|
|
902
|
+
)
|
|
903
|
+
})
|
|
904
|
+
|
|
905
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
906
|
+
const bytes = Buffer.from(bytesWithExtraJson)
|
|
907
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
908
|
+
TypeError,
|
|
909
|
+
)
|
|
910
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
911
|
+
'Invalid $bytes object',
|
|
912
|
+
)
|
|
913
|
+
})
|
|
914
|
+
|
|
915
|
+
test('lexParse non-strict returns plain object', () => {
|
|
916
|
+
expect(() =>
|
|
917
|
+
lexParse(bytesWithExtraJson, { strict: false }),
|
|
918
|
+
).not.toThrow()
|
|
919
|
+
})
|
|
920
|
+
|
|
921
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
922
|
+
expect(() =>
|
|
923
|
+
lexParseJsonBytes(Buffer.from(bytesWithExtraJson), { strict: false }),
|
|
924
|
+
).not.toThrow()
|
|
925
|
+
})
|
|
926
|
+
})
|
|
927
|
+
|
|
928
|
+
describe('empty $type: strict throws TypeError, non-strict returns plain object', () => {
|
|
929
|
+
const emptyTypeJson = '{"$type":"","foo":"bar"}'
|
|
930
|
+
|
|
931
|
+
test('lexParse strict throws TypeError with "Empty $type property"', () => {
|
|
932
|
+
expect(() => lexParse(emptyTypeJson, { strict: true })).toThrow(TypeError)
|
|
933
|
+
expect(() => lexParse(emptyTypeJson, { strict: true })).toThrow(
|
|
934
|
+
'Empty $type property',
|
|
935
|
+
)
|
|
936
|
+
})
|
|
937
|
+
|
|
938
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
939
|
+
const bytes = Buffer.from(emptyTypeJson)
|
|
940
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
941
|
+
TypeError,
|
|
942
|
+
)
|
|
943
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
944
|
+
'Empty $type property',
|
|
945
|
+
)
|
|
946
|
+
})
|
|
947
|
+
|
|
948
|
+
test('lexParse non-strict returns plain object', () => {
|
|
949
|
+
expect(() => lexParse(emptyTypeJson, { strict: false })).not.toThrow()
|
|
950
|
+
})
|
|
951
|
+
|
|
952
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
953
|
+
expect(() =>
|
|
954
|
+
lexParseJsonBytes(Buffer.from(emptyTypeJson), { strict: false }),
|
|
955
|
+
).not.toThrow()
|
|
956
|
+
})
|
|
957
|
+
})
|
|
958
|
+
|
|
959
|
+
describe('non-string $type: strict throws TypeError, non-strict returns plain object', () => {
|
|
960
|
+
const nonStringTypeJson = '{"$type":123,"foo":"bar"}'
|
|
961
|
+
|
|
962
|
+
test('lexParse strict throws TypeError with type name in message', () => {
|
|
963
|
+
expect(() => lexParse(nonStringTypeJson, { strict: true })).toThrow(
|
|
964
|
+
TypeError,
|
|
965
|
+
)
|
|
966
|
+
expect(() => lexParse(nonStringTypeJson, { strict: true })).toThrow(
|
|
967
|
+
'Invalid $type property (number)',
|
|
968
|
+
)
|
|
969
|
+
})
|
|
970
|
+
|
|
971
|
+
test('lexParseJsonBytes strict throws same TypeError', () => {
|
|
972
|
+
const bytes = Buffer.from(nonStringTypeJson)
|
|
973
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
974
|
+
TypeError,
|
|
975
|
+
)
|
|
976
|
+
expect(() => lexParseJsonBytes(bytes, { strict: true })).toThrow(
|
|
977
|
+
'Invalid $type property (number)',
|
|
978
|
+
)
|
|
979
|
+
})
|
|
980
|
+
|
|
981
|
+
test('lexParse non-strict returns plain object', () => {
|
|
982
|
+
expect(() => lexParse(nonStringTypeJson, { strict: false })).not.toThrow()
|
|
983
|
+
})
|
|
984
|
+
|
|
985
|
+
test('lexParseJsonBytes non-strict returns plain object', () => {
|
|
986
|
+
expect(() =>
|
|
987
|
+
lexParseJsonBytes(Buffer.from(nonStringTypeJson), { strict: false }),
|
|
988
|
+
).not.toThrow()
|
|
989
|
+
})
|
|
990
|
+
})
|
|
991
|
+
})
|