@atproto/common 0.1.1 → 0.3.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.
@@ -0,0 +1 @@
1
+ export declare const cborDecodeMulti: (encoded: Uint8Array) => unknown[];
package/dist/ipld.d.ts CHANGED
@@ -1,10 +1,28 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ import crypto from 'crypto';
5
+ import { Transform, TransformCallback } from 'stream';
1
6
  import { CID } from 'multiformats/cid';
2
7
  import * as Block from 'multiformats/block';
3
8
  import * as cborCodec from '@ipld/dag-cbor';
4
- export declare const dataToCborBlock: (data: unknown) => Promise<Block.Block<unknown>>;
5
- export declare const verifyCidForBytes: (cid: CID, bytes: Uint8Array) => Promise<void>;
6
- export declare const sha256RawToCid: (hash: Uint8Array) => CID;
7
- export declare const cidForCbor: (data: unknown) => Promise<CID>;
8
9
  export declare const cborEncode: typeof cborCodec.encode;
9
10
  export declare const cborDecode: typeof cborCodec.decode;
11
+ export declare const dataToCborBlock: (data: unknown) => Promise<Block.Block<unknown>>;
12
+ export declare const cidForCbor: (data: unknown) => Promise<CID>;
10
13
  export declare const cborBytesToRecord: (bytes: Uint8Array) => Record<string, unknown>;
14
+ export declare const verifyCidForBytes: (cid: CID, bytes: Uint8Array) => Promise<void>;
15
+ export declare const sha256ToCid: (hash: Uint8Array, codec: number) => CID;
16
+ export declare const sha256RawToCid: (hash: Uint8Array) => CID;
17
+ export declare class VerifyCidTransform extends Transform {
18
+ cid: CID;
19
+ hasher: crypto.Hash;
20
+ constructor(cid: CID);
21
+ _transform(chunk: Uint8Array, _enc: BufferEncoding, cb: TransformCallback): void;
22
+ _flush(cb: TransformCallback): void;
23
+ }
24
+ export declare class VerifyCidError extends Error {
25
+ expected: CID;
26
+ actual: CID;
27
+ constructor(expected: CID, actual: CID);
28
+ }
package/dist/streams.d.ts CHANGED
@@ -4,6 +4,8 @@ import { Stream, Readable, Transform, TransformCallback } from 'stream';
4
4
  export declare const forwardStreamErrors: (...streams: Stream[]) => void;
5
5
  export declare const cloneStream: (stream: Readable) => Readable;
6
6
  export declare const streamSize: (stream: Readable) => Promise<number>;
7
+ export declare const streamToBytes: (stream: Readable) => Promise<Uint8Array>;
8
+ export declare const byteIterableToStream: (iter: AsyncIterable<Uint8Array>) => Readable;
7
9
  export declare const bytesToStream: (bytes: Uint8Array) => Readable;
8
10
  export declare class MaxSizeChecker extends Transform {
9
11
  maxSize: number;
@@ -0,0 +1,2 @@
1
+ export declare const utf8Len: (str: string) => number;
2
+ export declare const graphemeLen: (str: string) => number;
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "@atproto/common",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "main": "dist/index.js",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/bluesky-social/atproto.git",
9
+ "directory": "packages/common"
10
+ },
6
11
  "scripts": {
7
12
  "test": "jest",
8
- "prettier": "prettier --check src/",
9
- "prettier:fix": "prettier --write src/",
13
+ "prettier": "prettier --check src/ tests/",
14
+ "prettier:fix": "prettier --write src/ tests/",
10
15
  "lint": "eslint . --ext .ts,.tsx",
11
16
  "lint:fix": "yarn lint --fix",
12
17
  "verify": "run-p prettier lint",
@@ -19,9 +24,10 @@
19
24
  "postpublish": "npm run update-main-to-src"
20
25
  },
21
26
  "dependencies": {
27
+ "@atproto/common-web": "*",
22
28
  "@ipld/dag-cbor": "^7.0.3",
29
+ "cbor-x": "^1.5.1",
23
30
  "multiformats": "^9.6.4",
24
- "pino": "^8.6.1",
25
- "zod": "^3.14.2"
31
+ "pino": "^8.6.1"
26
32
  }
27
33
  }
package/src/fs.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { isErrnoException } from '@atproto/common-web'
2
+ import fs from 'fs/promises'
3
+
4
+ export const fileExists = async (location: string): Promise<boolean> => {
5
+ try {
6
+ await fs.access(location, fs.constants.F_OK)
7
+ return true
8
+ } catch (err) {
9
+ if (isErrnoException(err) && err.code === 'ENOENT') {
10
+ return false
11
+ }
12
+ throw err
13
+ }
14
+ }
package/src/index.ts CHANGED
@@ -1,11 +1,6 @@
1
- export * as check from './check'
2
- export * as util from './util'
3
-
4
- export * from './async'
5
- export * from './util'
6
- export * from './tid'
1
+ export * from '@atproto/common-web'
2
+ export * from './fs'
7
3
  export * from './ipld'
4
+ export * from './ipld-multi'
8
5
  export * from './logger'
9
- export * from './types'
10
6
  export * from './streams'
11
- export * from './times'
@@ -0,0 +1,27 @@
1
+ import * as cborx from 'cbor-x'
2
+ import { CID } from 'multiformats/cid'
3
+
4
+ // add extension for decoding CIDs
5
+ // decoding code taken from @ipld/dag-cbor
6
+ // does not support encoding cids
7
+ cborx.addExtension({
8
+ Class: CID,
9
+ tag: 42,
10
+ encode: () => {
11
+ throw new Error('cannot encode cids')
12
+ },
13
+ decode: (bytes: Uint8Array): CID => {
14
+ if (bytes[0] !== 0) {
15
+ throw new Error('Invalid CID for CBOR tag 42; expected leading 0x00')
16
+ }
17
+ return CID.decode(bytes.subarray(1)) // ignore leading 0x00
18
+ },
19
+ })
20
+
21
+ export const cborDecodeMulti = (encoded: Uint8Array): unknown[] => {
22
+ const decoded: unknown[] = []
23
+ cborx.decodeMultiple(encoded, (value) => {
24
+ decoded.push(value)
25
+ })
26
+ return decoded
27
+ }
package/src/ipld.ts CHANGED
@@ -1,10 +1,15 @@
1
+ import crypto from 'crypto'
2
+ import { Transform, TransformCallback } from 'stream'
3
+ import { check, schema } from '@atproto/common-web'
1
4
  import { CID } from 'multiformats/cid'
2
5
  import * as Block from 'multiformats/block'
3
6
  import * as rawCodec from 'multiformats/codecs/raw'
4
7
  import { sha256 } from 'multiformats/hashes/sha2'
5
8
  import * as mf from 'multiformats'
6
9
  import * as cborCodec from '@ipld/dag-cbor'
7
- import { check, schema } from '.'
10
+
11
+ export const cborEncode = cborCodec.encode
12
+ export const cborDecode = cborCodec.decode
8
13
 
9
14
  export const dataToCborBlock = async (data: unknown) => {
10
15
  return Block.encode({
@@ -14,6 +19,21 @@ export const dataToCborBlock = async (data: unknown) => {
14
19
  })
15
20
  }
16
21
 
22
+ export const cidForCbor = async (data: unknown): Promise<CID> => {
23
+ const block = await dataToCborBlock(data)
24
+ return block.cid
25
+ }
26
+
27
+ export const cborBytesToRecord = (
28
+ bytes: Uint8Array,
29
+ ): Record<string, unknown> => {
30
+ const val = cborDecode(bytes)
31
+ if (!check.is(val, schema.map)) {
32
+ throw new Error(`Expected object, got: ${val}`)
33
+ }
34
+ return val
35
+ }
36
+
17
37
  export const verifyCidForBytes = async (cid: CID, bytes: Uint8Array) => {
18
38
  const digest = await sha256.digest(bytes)
19
39
  const expected = CID.createV1(cid.code, digest)
@@ -24,25 +44,46 @@ export const verifyCidForBytes = async (cid: CID, bytes: Uint8Array) => {
24
44
  }
25
45
  }
26
46
 
27
- export const sha256RawToCid = (hash: Uint8Array): CID => {
47
+ export const sha256ToCid = (hash: Uint8Array, codec: number): CID => {
28
48
  const digest = mf.digest.create(sha256.code, hash)
29
- return CID.createV1(rawCodec.code, digest)
49
+ return CID.createV1(codec, digest)
30
50
  }
31
51
 
32
- export const cidForCbor = async (data: unknown): Promise<CID> => {
33
- const block = await dataToCborBlock(data)
34
- return block.cid
52
+ export const sha256RawToCid = (hash: Uint8Array): CID => {
53
+ return sha256ToCid(hash, rawCodec.code)
35
54
  }
36
55
 
37
- export const cborEncode = cborCodec.encode
38
- export const cborDecode = cborCodec.decode
56
+ export class VerifyCidTransform extends Transform {
57
+ hasher = crypto.createHash('sha256')
58
+ constructor(public cid: CID) {
59
+ super()
60
+ }
39
61
 
40
- export const cborBytesToRecord = (
41
- bytes: Uint8Array,
42
- ): Record<string, unknown> => {
43
- const val = cborDecode(bytes)
44
- if (!check.is(val, schema.record)) {
45
- throw new Error(`Expected object, got: ${val}`)
62
+ _transform(chunk: Uint8Array, _enc: BufferEncoding, cb: TransformCallback) {
63
+ this.hasher.update(chunk)
64
+ cb(null, chunk)
65
+ }
66
+
67
+ _flush(cb: TransformCallback) {
68
+ try {
69
+ const cid = sha256RawToCid(this.hasher.digest())
70
+ if (this.cid.equals(cid)) {
71
+ return cb()
72
+ } else {
73
+ return cb(new VerifyCidError(this.cid, cid))
74
+ }
75
+ } catch (_err) {
76
+ const err =
77
+ _err instanceof Error
78
+ ? _err
79
+ : new Error('Unexpected error', { cause: _err })
80
+ return cb(err)
81
+ }
82
+ }
83
+ }
84
+
85
+ export class VerifyCidError extends Error {
86
+ constructor(public expected: CID, public actual: CID) {
87
+ super('Bad cid check')
46
88
  }
47
- return val
48
89
  }
package/src/streams.ts CHANGED
@@ -30,6 +30,20 @@ export const streamSize = async (stream: Readable): Promise<number> => {
30
30
  return size
31
31
  }
32
32
 
33
+ export const streamToBytes = async (stream: Readable): Promise<Uint8Array> => {
34
+ const bufs: Buffer[] = []
35
+ for await (const bytes of stream) {
36
+ bufs.push(bytes)
37
+ }
38
+ return new Uint8Array(Buffer.concat(bufs))
39
+ }
40
+
41
+ export const byteIterableToStream = (
42
+ iter: AsyncIterable<Uint8Array>,
43
+ ): Readable => {
44
+ return Readable.from(iter, { objectMode: false })
45
+ }
46
+
33
47
  export const bytesToStream = (bytes: Uint8Array): Readable => {
34
48
  const stream = new Readable()
35
49
  stream.push(bytes)
@@ -0,0 +1,25 @@
1
+ import { CID } from 'multiformats/cid'
2
+ import * as ui8 from 'uint8arrays'
3
+ import { cborEncode, cborDecodeMulti } from '../src'
4
+
5
+ describe('ipld decode multi', () => {
6
+ it('decodes concatenated dag-cbor messages', async () => {
7
+ const one = {
8
+ a: 123,
9
+ b: CID.parse(
10
+ 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
11
+ ),
12
+ }
13
+ const two = {
14
+ c: new Uint8Array([1, 2, 3]),
15
+ d: CID.parse(
16
+ 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
17
+ ),
18
+ }
19
+ const encoded = ui8.concat([cborEncode(one), cborEncode(two)])
20
+ const decoded = cborDecodeMulti(encoded)
21
+ expect(decoded.length).toBe(2)
22
+ expect(decoded[0]).toEqual(one)
23
+ expect(decoded[1]).toEqual(two)
24
+ })
25
+ })
@@ -0,0 +1,279 @@
1
+ import { CID } from 'multiformats/cid'
2
+
3
+ export const vectors = [
4
+ {
5
+ name: 'basic',
6
+ json: {
7
+ string: 'abc',
8
+ unicode: 'a~öñ©⽘☎𓋓😀👨‍👩‍👧‍👧',
9
+ integer: 123,
10
+ bool: true,
11
+ null: null,
12
+ array: ['abc', 'def', 'ghi'],
13
+ object: {
14
+ string: 'abc',
15
+ number: 123,
16
+ bool: true,
17
+ arr: ['abc', 'def', 'ghi'],
18
+ },
19
+ },
20
+ ipld: {
21
+ string: 'abc',
22
+ unicode: 'a~öñ©⽘☎𓋓😀👨‍👩‍👧‍👧',
23
+ integer: 123,
24
+ bool: true,
25
+ null: null,
26
+ array: ['abc', 'def', 'ghi'],
27
+ object: {
28
+ string: 'abc',
29
+ number: 123,
30
+ bool: true,
31
+ arr: ['abc', 'def', 'ghi'],
32
+ },
33
+ },
34
+ cbor: new Uint8Array([
35
+ 167, 100, 98, 111, 111, 108, 245, 100, 110, 117, 108, 108, 246, 101, 97,
36
+ 114, 114, 97, 121, 131, 99, 97, 98, 99, 99, 100, 101, 102, 99, 103, 104,
37
+ 105, 102, 111, 98, 106, 101, 99, 116, 164, 99, 97, 114, 114, 131, 99, 97,
38
+ 98, 99, 99, 100, 101, 102, 99, 103, 104, 105, 100, 98, 111, 111, 108, 245,
39
+ 102, 110, 117, 109, 98, 101, 114, 24, 123, 102, 115, 116, 114, 105, 110,
40
+ 103, 99, 97, 98, 99, 102, 115, 116, 114, 105, 110, 103, 99, 97, 98, 99,
41
+ 103, 105, 110, 116, 101, 103, 101, 114, 24, 123, 103, 117, 110, 105, 99,
42
+ 111, 100, 101, 120, 47, 97, 126, 195, 182, 195, 177, 194, 169, 226, 189,
43
+ 152, 226, 152, 142, 240, 147, 139, 147, 240, 159, 152, 128, 240, 159, 145,
44
+ 168, 226, 128, 141, 240, 159, 145, 169, 226, 128, 141, 240, 159, 145, 167,
45
+ 226, 128, 141, 240, 159, 145, 167,
46
+ ]),
47
+ cid: 'bafyreiclp443lavogvhj3d2ob2cxbfuscni2k5jk7bebjzg7khl3esabwq',
48
+ },
49
+ {
50
+ name: 'ipld',
51
+ json: {
52
+ a: {
53
+ $link: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
54
+ },
55
+ b: {
56
+ $bytes: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
57
+ },
58
+ c: {
59
+ $type: 'blob',
60
+ ref: {
61
+ $link: 'bafkreiccldh766hwcnuxnf2wh6jgzepf2nlu2lvcllt63eww5p6chi4ity',
62
+ },
63
+ mimeType: 'image/jpeg',
64
+ size: 10000,
65
+ },
66
+ },
67
+ ipld: {
68
+ a: CID.parse(
69
+ 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
70
+ ),
71
+ b: new Uint8Array([
72
+ 156, 81, 17, 142, 242, 203, 139, 15, 106, 155, 142, 73, 174, 161, 253,
73
+ 65, 60, 242, 11, 98, 238, 213, 118, 248, 157, 238, 190, 176, 26, 194,
74
+ 204, 141,
75
+ ]),
76
+ c: {
77
+ $type: 'blob',
78
+ ref: CID.parse(
79
+ 'bafkreiccldh766hwcnuxnf2wh6jgzepf2nlu2lvcllt63eww5p6chi4ity',
80
+ ),
81
+ mimeType: 'image/jpeg',
82
+ size: 10000,
83
+ },
84
+ },
85
+ cbor: new Uint8Array([
86
+ 163, 97, 97, 216, 42, 88, 37, 0, 1, 113, 18, 32, 101, 6, 42, 90, 90, 0,
87
+ 252, 22, 215, 60, 105, 68, 35, 124, 203, 193, 91, 28, 74, 114, 52, 72,
88
+ 147, 54, 137, 29, 9, 23, 65, 162, 57, 208, 97, 98, 88, 32, 156, 81, 17,
89
+ 142, 242, 203, 139, 15, 106, 155, 142, 73, 174, 161, 253, 65, 60, 242, 11,
90
+ 98, 238, 213, 118, 248, 157, 238, 190, 176, 26, 194, 204, 141, 97, 99,
91
+ 164, 99, 114, 101, 102, 216, 42, 88, 37, 0, 1, 85, 18, 32, 66, 88, 207,
92
+ 255, 120, 246, 19, 105, 118, 151, 86, 63, 146, 108, 145, 229, 211, 87, 77,
93
+ 46, 162, 90, 231, 237, 146, 214, 235, 252, 35, 163, 136, 158, 100, 115,
94
+ 105, 122, 101, 25, 39, 16, 101, 36, 116, 121, 112, 101, 100, 98, 108, 111,
95
+ 98, 104, 109, 105, 109, 101, 84, 121, 112, 101, 106, 105, 109, 97, 103,
96
+ 101, 47, 106, 112, 101, 103,
97
+ ]),
98
+ cid: 'bafyreihldkhcwijkde7gx4rpkkuw7pl6lbyu5gieunyc7ihactn5bkd2nm',
99
+ },
100
+ {
101
+ name: 'ipldArray',
102
+ json: [
103
+ {
104
+ $link: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
105
+ },
106
+ {
107
+ $link: 'bafyreigoxt64qghytzkr6ik7qvtzc7lyytiq5xbbrokbxjows2wp7vmo6q',
108
+ },
109
+ {
110
+ $link: 'bafyreiaizynclnqiolq7byfpjjtgqzn4sfrsgn7z2hhf6bo4utdwkin7ke',
111
+ },
112
+ {
113
+ $link: 'bafyreifd4w4tcr5tluxz7osjtnofffvtsmgdqcfrfi6evjde4pl27lrjpy',
114
+ },
115
+ ],
116
+ ipld: [
117
+ CID.parse('bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a'),
118
+ CID.parse('bafyreigoxt64qghytzkr6ik7qvtzc7lyytiq5xbbrokbxjows2wp7vmo6q'),
119
+ CID.parse('bafyreiaizynclnqiolq7byfpjjtgqzn4sfrsgn7z2hhf6bo4utdwkin7ke'),
120
+ CID.parse('bafyreifd4w4tcr5tluxz7osjtnofffvtsmgdqcfrfi6evjde4pl27lrjpy'),
121
+ ],
122
+ cbor: new Uint8Array([
123
+ 132, 216, 42, 88, 37, 0, 1, 113, 18, 32, 101, 6, 42, 90, 90, 0, 252, 22,
124
+ 215, 60, 105, 68, 35, 124, 203, 193, 91, 28, 74, 114, 52, 72, 147, 54,
125
+ 137, 29, 9, 23, 65, 162, 57, 208, 216, 42, 88, 37, 0, 1, 113, 18, 32, 206,
126
+ 188, 253, 200, 24, 248, 158, 85, 31, 33, 95, 133, 103, 145, 125, 120, 196,
127
+ 209, 14, 220, 33, 139, 148, 27, 165, 214, 150, 172, 255, 213, 142, 244,
128
+ 216, 42, 88, 37, 0, 1, 113, 18, 32, 8, 206, 26, 37, 182, 8, 114, 225, 240,
129
+ 224, 175, 74, 102, 104, 101, 188, 145, 99, 35, 55, 249, 209, 206, 95, 5,
130
+ 220, 164, 199, 101, 33, 191, 81, 216, 42, 88, 37, 0, 1, 113, 18, 32, 163,
131
+ 229, 185, 49, 71, 179, 93, 47, 159, 186, 73, 155, 92, 82, 150, 179, 147,
132
+ 12, 56, 8, 177, 42, 60, 74, 164, 100, 227, 215, 175, 174, 41, 126,
133
+ ]),
134
+ cid: 'bafyreiaj3udmqlqrcbjxjayzuxwp64gt64olcbjfrkldzoqponpru6gq4m',
135
+ },
136
+ {
137
+ name: 'ipldNested',
138
+ json: {
139
+ a: {
140
+ b: [
141
+ {
142
+ d: [
143
+ {
144
+ $link:
145
+ 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
146
+ },
147
+ {
148
+ $link:
149
+ 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
150
+ },
151
+ ],
152
+ e: [
153
+ {
154
+ $bytes: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
155
+ },
156
+ {
157
+ $bytes: 'iE+sPoHobU9tSIqGI+309LLCcWQIRmEXwxcoDt19tas',
158
+ },
159
+ ],
160
+ },
161
+ ],
162
+ },
163
+ },
164
+ ipld: {
165
+ a: {
166
+ b: [
167
+ {
168
+ d: [
169
+ CID.parse(
170
+ 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
171
+ ),
172
+ CID.parse(
173
+ 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
174
+ ),
175
+ ],
176
+ e: [
177
+ new Uint8Array([
178
+ 156, 81, 17, 142, 242, 203, 139, 15, 106, 155, 142, 73, 174,
179
+ 161, 253, 65, 60, 242, 11, 98, 238, 213, 118, 248, 157, 238,
180
+ 190, 176, 26, 194, 204, 141,
181
+ ]),
182
+ new Uint8Array([
183
+ 136, 79, 172, 62, 129, 232, 109, 79, 109, 72, 138, 134, 35, 237,
184
+ 244, 244, 178, 194, 113, 100, 8, 70, 97, 23, 195, 23, 40, 14,
185
+ 221, 125, 181, 171,
186
+ ]),
187
+ ],
188
+ },
189
+ ],
190
+ },
191
+ },
192
+ cbor: new Uint8Array([
193
+ 161, 97, 97, 161, 97, 98, 129, 162, 97, 100, 130, 216, 42, 88, 37, 0, 1,
194
+ 113, 18, 32, 101, 6, 42, 90, 90, 0, 252, 22, 215, 60, 105, 68, 35, 124,
195
+ 203, 193, 91, 28, 74, 114, 52, 72, 147, 54, 137, 29, 9, 23, 65, 162, 57,
196
+ 208, 216, 42, 88, 37, 0, 1, 113, 18, 32, 101, 6, 42, 90, 90, 0, 252, 22,
197
+ 215, 60, 105, 68, 35, 124, 203, 193, 91, 28, 74, 114, 52, 72, 147, 54,
198
+ 137, 29, 9, 23, 65, 162, 57, 208, 97, 101, 130, 88, 32, 156, 81, 17, 142,
199
+ 242, 203, 139, 15, 106, 155, 142, 73, 174, 161, 253, 65, 60, 242, 11, 98,
200
+ 238, 213, 118, 248, 157, 238, 190, 176, 26, 194, 204, 141, 88, 32, 136,
201
+ 79, 172, 62, 129, 232, 109, 79, 109, 72, 138, 134, 35, 237, 244, 244, 178,
202
+ 194, 113, 100, 8, 70, 97, 23, 195, 23, 40, 14, 221, 125, 181, 171,
203
+ ]),
204
+ cid: 'bafyreid3imdulnhgeytpf6uk7zahjvrsqlofkmm5b5ub2maw4kqus6jp4i',
205
+ },
206
+ {
207
+ name: 'poorlyFormatted',
208
+ json: {
209
+ a: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
210
+ b: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
211
+ c: {
212
+ $link: 'bafyreigoxt64qghytzkr6ik7qvtzc7lyytiq5xbbrokbxjows2wp7vmo6q',
213
+ another: 'bad value',
214
+ },
215
+ d: {
216
+ $bytes: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
217
+ another: 'bad value',
218
+ },
219
+ e: {
220
+ '/': 'bafyreigoxt64qghytzkr6ik7qvtzc7lyytiq5xbbrokbxjows2wp7vmo6q',
221
+ },
222
+ f: {
223
+ '/': {
224
+ bytes: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
225
+ },
226
+ },
227
+ },
228
+ ipld: {
229
+ a: 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
230
+ b: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
231
+ c: {
232
+ $link: 'bafyreigoxt64qghytzkr6ik7qvtzc7lyytiq5xbbrokbxjows2wp7vmo6q',
233
+ another: 'bad value',
234
+ },
235
+ d: {
236
+ $bytes: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
237
+ another: 'bad value',
238
+ },
239
+ e: {
240
+ '/': 'bafyreigoxt64qghytzkr6ik7qvtzc7lyytiq5xbbrokbxjows2wp7vmo6q',
241
+ },
242
+ f: {
243
+ '/': {
244
+ bytes: 'nFERjvLLiw9qm45JrqH9QTzyC2Lu1Xb4ne6+sBrCzI0',
245
+ },
246
+ },
247
+ },
248
+ cbor: new Uint8Array([
249
+ 166, 97, 97, 120, 59, 98, 97, 102, 121, 114, 101, 105, 100, 102, 97, 121,
250
+ 118, 102, 117, 119, 113, 97, 55, 113, 108, 110, 111, 112, 100, 106, 105,
251
+ 113, 114, 120, 122, 115, 54, 98, 108, 109, 111, 101, 117, 52, 114, 117,
252
+ 106, 99, 106, 116, 110, 99, 105, 53, 98, 101, 108, 117, 100, 105, 114,
253
+ 122, 50, 97, 97, 98, 120, 43, 110, 70, 69, 82, 106, 118, 76, 76, 105, 119,
254
+ 57, 113, 109, 52, 53, 74, 114, 113, 72, 57, 81, 84, 122, 121, 67, 50, 76,
255
+ 117, 49, 88, 98, 52, 110, 101, 54, 43, 115, 66, 114, 67, 122, 73, 48, 97,
256
+ 99, 162, 101, 36, 108, 105, 110, 107, 120, 59, 98, 97, 102, 121, 114, 101,
257
+ 105, 103, 111, 120, 116, 54, 52, 113, 103, 104, 121, 116, 122, 107, 114,
258
+ 54, 105, 107, 55, 113, 118, 116, 122, 99, 55, 108, 121, 121, 116, 105,
259
+ 113, 53, 120, 98, 98, 114, 111, 107, 98, 120, 106, 111, 119, 115, 50, 119,
260
+ 112, 55, 118, 109, 111, 54, 113, 103, 97, 110, 111, 116, 104, 101, 114,
261
+ 105, 98, 97, 100, 32, 118, 97, 108, 117, 101, 97, 100, 162, 102, 36, 98,
262
+ 121, 116, 101, 115, 120, 43, 110, 70, 69, 82, 106, 118, 76, 76, 105, 119,
263
+ 57, 113, 109, 52, 53, 74, 114, 113, 72, 57, 81, 84, 122, 121, 67, 50, 76,
264
+ 117, 49, 88, 98, 52, 110, 101, 54, 43, 115, 66, 114, 67, 122, 73, 48, 103,
265
+ 97, 110, 111, 116, 104, 101, 114, 105, 98, 97, 100, 32, 118, 97, 108, 117,
266
+ 101, 97, 101, 161, 97, 47, 120, 59, 98, 97, 102, 121, 114, 101, 105, 103,
267
+ 111, 120, 116, 54, 52, 113, 103, 104, 121, 116, 122, 107, 114, 54, 105,
268
+ 107, 55, 113, 118, 116, 122, 99, 55, 108, 121, 121, 116, 105, 113, 53,
269
+ 120, 98, 98, 114, 111, 107, 98, 120, 106, 111, 119, 115, 50, 119, 112, 55,
270
+ 118, 109, 111, 54, 113, 97, 102, 161, 97, 47, 161, 101, 98, 121, 116, 101,
271
+ 115, 120, 43, 110, 70, 69, 82, 106, 118, 76, 76, 105, 119, 57, 113, 109,
272
+ 52, 53, 74, 114, 113, 72, 57, 81, 84, 122, 121, 67, 50, 76, 117, 49, 88,
273
+ 98, 52, 110, 101, 54, 43, 115, 66, 114, 67, 122, 73, 48,
274
+ ]),
275
+ cid: 'bafyreico7wgbbfe6dpfsuednrtrlh6t2yjl6xq5rf32gl3pgwhwxk77cn4',
276
+ },
277
+ ]
278
+
279
+ export default vectors
@@ -0,0 +1,29 @@
1
+ import * as ui8 from 'uint8arrays'
2
+ import vectors from './ipld-vectors'
3
+ import {
4
+ cborDecode,
5
+ cborEncode,
6
+ cidForCbor,
7
+ ipldEquals,
8
+ ipldToJson,
9
+ jsonToIpld,
10
+ } from '../src'
11
+
12
+ describe('ipld', () => {
13
+ for (const vector of vectors) {
14
+ it(`passes test vector: ${vector.name}`, async () => {
15
+ const ipld = jsonToIpld(vector.json)
16
+ const json = ipldToJson(ipld)
17
+ const cbor = cborEncode(ipld)
18
+ const ipldAgain = cborDecode(cbor)
19
+ const jsonAgain = ipldToJson(ipldAgain)
20
+ const cid = await cidForCbor(ipld)
21
+ expect(json).toEqual(vector.json)
22
+ expect(jsonAgain).toEqual(vector.json)
23
+ expect(ipldEquals(ipld, vector.ipld)).toBeTruthy()
24
+ expect(ipldEquals(ipldAgain, vector.ipld)).toBeTruthy()
25
+ expect(ui8.equals(cbor, vector.cbor)).toBeTruthy()
26
+ expect(cid.toString()).toEqual(vector.cid)
27
+ })
28
+ }
29
+ })