@atcute/cid 1.0.3 → 2.0.1
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/README.md +9 -5
- package/dist/cid-link.d.ts +13 -0
- package/dist/cid-link.js +30 -0
- package/dist/cid-link.js.map +1 -0
- package/dist/codec.d.ts +31 -0
- package/dist/codec.js +95 -0
- package/dist/codec.js.map +1 -0
- package/dist/index.d.ts +2 -67
- package/dist/index.js +2 -132
- package/dist/index.js.map +1 -1
- package/lib/cid-link.ts +41 -0
- package/lib/codec.ts +146 -0
- package/lib/index.ts +2 -189
- package/package.json +10 -5
package/README.md
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
# @atcute/cid
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
lightweight [DASL CID][dasl-cid] codec library for AT Protocol.
|
|
4
|
+
|
|
5
|
+
[dasl-cid]: https://dasl.ing/cid.html
|
|
4
6
|
|
|
5
7
|
```ts
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
import * as CID from '@atcute/cid';
|
|
9
|
+
|
|
10
|
+
const cid = CID.fromString('bafyreihffx5a2e7k5uwrmmgofbvzujc5cmw5h4espouwuxt3liqoflx3ee');
|
|
11
|
+
// ^? { version: 1, codec: 113, digest: { ... }, bytes: Uint8Array(36) }
|
|
8
12
|
|
|
9
13
|
// Creating a CID containing CBOR data
|
|
10
|
-
const cid = await create(0x71, buffer);
|
|
14
|
+
const cid = await CID.create(0x71, buffer);
|
|
11
15
|
|
|
12
16
|
// Serializing CID into string
|
|
13
|
-
|
|
17
|
+
CID.toString(cid); // -> bafyrei...
|
|
14
18
|
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Cid } from './codec.js';
|
|
2
|
+
export interface CidLink {
|
|
3
|
+
$link: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class CidLinkWrapper implements CidLink {
|
|
6
|
+
bytes: Uint8Array;
|
|
7
|
+
constructor(bytes: Uint8Array);
|
|
8
|
+
get $link(): string;
|
|
9
|
+
toJSON(): CidLink;
|
|
10
|
+
}
|
|
11
|
+
export declare const isCidLink: (value: unknown) => value is CidLink;
|
|
12
|
+
export declare const toCidLink: (cid: Cid) => CidLink;
|
|
13
|
+
export declare const fromCidLink: (link: CidLink) => Cid;
|
package/dist/cid-link.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { toBase32 } from '@atcute/multibase';
|
|
2
|
+
import { decode, fromString } from './codec.js';
|
|
3
|
+
export class CidLinkWrapper {
|
|
4
|
+
bytes;
|
|
5
|
+
constructor(bytes) {
|
|
6
|
+
this.bytes = bytes;
|
|
7
|
+
}
|
|
8
|
+
get $link() {
|
|
9
|
+
const encoded = toBase32(this.bytes);
|
|
10
|
+
return `b${encoded}`;
|
|
11
|
+
}
|
|
12
|
+
toJSON() {
|
|
13
|
+
return { $link: this.$link };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export const isCidLink = (value) => {
|
|
17
|
+
const val = value;
|
|
18
|
+
return (val instanceof CidLinkWrapper ||
|
|
19
|
+
(val !== null && typeof val === 'object' && typeof val.$link === 'string'));
|
|
20
|
+
};
|
|
21
|
+
export const toCidLink = (cid) => {
|
|
22
|
+
return new CidLinkWrapper(cid.bytes);
|
|
23
|
+
};
|
|
24
|
+
export const fromCidLink = (link) => {
|
|
25
|
+
if (link instanceof CidLinkWrapper) {
|
|
26
|
+
return decode(link.bytes);
|
|
27
|
+
}
|
|
28
|
+
return fromString(link.$link);
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=cid-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cid-link.js","sourceRoot":"","sources":["../lib/cid-link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAY,MAAM,YAAY,CAAC;AAM1D,MAAM,OAAO,cAAc;IACP;IAAnB,YAAmB,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;IAExC,IAAI,KAAK;QACR,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,OAAO,IAAI,OAAO,EAAE,CAAC;IACtB,CAAC;IAED,MAAM;QACL,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;CACD;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAc,EAAoB,EAAE;IAC7D,MAAM,GAAG,GAAG,KAAY,CAAC;IAEzB,OAAO,CACN,GAAG,YAAY,cAAc;QAC7B,CAAC,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAC1E,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAQ,EAAW,EAAE;IAC9C,OAAO,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAa,EAAO,EAAE;IACjD,IAAI,IAAI,YAAY,cAAc,EAAE,CAAC;QACpC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC,CAAC"}
|
package/dist/codec.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare const CID_VERSION = 1;
|
|
2
|
+
export declare const HASH_SHA256 = 18;
|
|
3
|
+
export declare const CODEC_RAW = 85;
|
|
4
|
+
export declare const CODEC_DCBOR = 113;
|
|
5
|
+
/**
|
|
6
|
+
* Represents a Content Identifier (CID), in particular, a limited subset of
|
|
7
|
+
* CIDv1 as described by DASL specifications.
|
|
8
|
+
* https://dasl.ing/cid.html
|
|
9
|
+
*/
|
|
10
|
+
export interface Cid {
|
|
11
|
+
/** CID version, this is always `1` for CIDv1 */
|
|
12
|
+
version: number;
|
|
13
|
+
/** Multicodec type for the data, can be `0x55` for raw data or `0x71` for DAG-CBOR */
|
|
14
|
+
codec: number;
|
|
15
|
+
/** Digest contents */
|
|
16
|
+
digest: {
|
|
17
|
+
/** Multicodec type for the digest, this is always `0x12` for SHA-256 */
|
|
18
|
+
codec: number;
|
|
19
|
+
/** Raw hash bytes */
|
|
20
|
+
contents: Uint8Array;
|
|
21
|
+
};
|
|
22
|
+
/** Raw CID bytes */
|
|
23
|
+
bytes: Uint8Array;
|
|
24
|
+
}
|
|
25
|
+
export declare const create: (codec: 85 | 113, data: Uint8Array) => Promise<Cid>;
|
|
26
|
+
export declare const decodeFirst: (bytes: Uint8Array) => [decoded: Cid, remainder: Uint8Array];
|
|
27
|
+
export declare const decode: (bytes: Uint8Array) => Cid;
|
|
28
|
+
export declare const fromString: (input: string) => Cid;
|
|
29
|
+
export declare const toString: (cid: Cid) => string;
|
|
30
|
+
export declare const fromBinary: (input: Uint8Array) => Cid;
|
|
31
|
+
export declare const toBinary: (cid: Cid) => Uint8Array;
|
package/dist/codec.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { fromBase32, toBase32 } from '@atcute/multibase';
|
|
2
|
+
import * as varint from '@atcute/varint';
|
|
3
|
+
export const CID_VERSION = 1;
|
|
4
|
+
export const HASH_SHA256 = 0x12;
|
|
5
|
+
export const CODEC_RAW = 0x55;
|
|
6
|
+
export const CODEC_DCBOR = 0x71;
|
|
7
|
+
export const create = async (codec, data) => {
|
|
8
|
+
const digest = new Uint8Array(await crypto.subtle.digest('sha-256', data));
|
|
9
|
+
const digestSize = digest.length;
|
|
10
|
+
const digestLebSize = varint.encodingLength(digestSize);
|
|
11
|
+
const bytes = new Uint8Array(3 + digestLebSize + digestSize);
|
|
12
|
+
bytes[0] = CID_VERSION;
|
|
13
|
+
bytes[1] = codec;
|
|
14
|
+
bytes[2] = HASH_SHA256;
|
|
15
|
+
varint.encode(digestSize, bytes, 3);
|
|
16
|
+
bytes.set(digest, 3 + digestLebSize);
|
|
17
|
+
const cid = {
|
|
18
|
+
version: CID_VERSION,
|
|
19
|
+
codec: codec,
|
|
20
|
+
digest: {
|
|
21
|
+
codec: HASH_SHA256,
|
|
22
|
+
contents: digest,
|
|
23
|
+
},
|
|
24
|
+
bytes: bytes,
|
|
25
|
+
};
|
|
26
|
+
return cid;
|
|
27
|
+
};
|
|
28
|
+
export const decodeFirst = (bytes) => {
|
|
29
|
+
const length = bytes.length;
|
|
30
|
+
if (length < 5) {
|
|
31
|
+
throw new RangeError(`cid too short`);
|
|
32
|
+
}
|
|
33
|
+
const version = bytes[0];
|
|
34
|
+
const codec = bytes[1];
|
|
35
|
+
const digestCodec = bytes[2];
|
|
36
|
+
if (version !== CID_VERSION) {
|
|
37
|
+
throw new RangeError(`incorrect cid version (got v${version})`);
|
|
38
|
+
}
|
|
39
|
+
if (codec !== CODEC_DCBOR && codec !== CODEC_RAW) {
|
|
40
|
+
throw new RangeError(`incorrect cid codec (got 0x${codec.toString(16)})`);
|
|
41
|
+
}
|
|
42
|
+
if (digestCodec !== HASH_SHA256) {
|
|
43
|
+
throw new RangeError(`incorrect cid hash type (got 0x${digestCodec.toString(16)})`);
|
|
44
|
+
}
|
|
45
|
+
const [digestSize, digestLebSize] = varint.decode(bytes, 3);
|
|
46
|
+
const digestOffset = 3 + digestLebSize;
|
|
47
|
+
if (length - digestOffset < digestSize) {
|
|
48
|
+
throw new RangeError(`digest too short (expected ${digestSize} bytes; got ${length - digestOffset})`);
|
|
49
|
+
}
|
|
50
|
+
const remainder = bytes.subarray(digestOffset + digestSize);
|
|
51
|
+
const cid = {
|
|
52
|
+
version: CID_VERSION,
|
|
53
|
+
codec: codec,
|
|
54
|
+
digest: {
|
|
55
|
+
codec: digestCodec,
|
|
56
|
+
contents: bytes.subarray(digestOffset, digestOffset + digestSize),
|
|
57
|
+
},
|
|
58
|
+
bytes: bytes.subarray(0, digestOffset + digestSize),
|
|
59
|
+
};
|
|
60
|
+
return [cid, remainder];
|
|
61
|
+
};
|
|
62
|
+
export const decode = (bytes) => {
|
|
63
|
+
const [cid, remainder] = decodeFirst(bytes);
|
|
64
|
+
if (remainder.length !== 0) {
|
|
65
|
+
throw new RangeError(`cid bytes includes remainder`);
|
|
66
|
+
}
|
|
67
|
+
return cid;
|
|
68
|
+
};
|
|
69
|
+
export const fromString = (input) => {
|
|
70
|
+
if (input.length < 2 || input[0] !== 'b') {
|
|
71
|
+
throw new SyntaxError(`not a multibase base32 string`);
|
|
72
|
+
}
|
|
73
|
+
const bytes = fromBase32(input.slice(1));
|
|
74
|
+
return decode(bytes);
|
|
75
|
+
};
|
|
76
|
+
export const toString = (cid) => {
|
|
77
|
+
const encoded = toBase32(cid.bytes);
|
|
78
|
+
return `b${encoded}`;
|
|
79
|
+
};
|
|
80
|
+
export const fromBinary = (input) => {
|
|
81
|
+
if (input.length < 2) {
|
|
82
|
+
throw new RangeError(`cid bytes too short`);
|
|
83
|
+
}
|
|
84
|
+
if (input[0] !== 0) {
|
|
85
|
+
throw new SyntaxError(`incorrect binary cid`);
|
|
86
|
+
}
|
|
87
|
+
const bytes = input.subarray(1);
|
|
88
|
+
return decode(bytes);
|
|
89
|
+
};
|
|
90
|
+
export const toBinary = (cid) => {
|
|
91
|
+
const bytes = new Uint8Array(1 + cid.bytes.length);
|
|
92
|
+
bytes.set(cid.bytes, 1);
|
|
93
|
+
return bytes;
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../lib/codec.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,67 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
* Bare minimum implementation for creating, parsing, and formatting
|
|
4
|
-
* AT Protocol-blessed CIDv1 format.
|
|
5
|
-
*
|
|
6
|
-
* As specified by AT Protocol, the blessed format is:
|
|
7
|
-
* - Multibase: `base32` (b)
|
|
8
|
-
* - Multicodec: `dag-cbor` (0x71) for record, `raw` (0x55) for blobs
|
|
9
|
-
* - Multihash: `sha-256` (0x12)
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Raw digest information
|
|
13
|
-
*/
|
|
14
|
-
export interface Digest {
|
|
15
|
-
code: number;
|
|
16
|
-
size: number;
|
|
17
|
-
digest: Uint8Array;
|
|
18
|
-
bytes: Uint8Array;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* CID information
|
|
22
|
-
*/
|
|
23
|
-
export interface CID {
|
|
24
|
-
version: number;
|
|
25
|
-
code: number;
|
|
26
|
-
digest: Digest;
|
|
27
|
-
bytes: Uint8Array;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Information regarding CID buffer being inspected
|
|
31
|
-
*/
|
|
32
|
-
export interface InspectedCID {
|
|
33
|
-
version: number;
|
|
34
|
-
codec: number;
|
|
35
|
-
multihashCode: number;
|
|
36
|
-
digestSize: number;
|
|
37
|
-
multihashSize: number;
|
|
38
|
-
size: number;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Parse a CID string
|
|
42
|
-
*/
|
|
43
|
-
export declare const parse: (cid: string) => CID;
|
|
44
|
-
/**
|
|
45
|
-
* Provides information regarding the CID buffer
|
|
46
|
-
*/
|
|
47
|
-
export declare const inspect: (initialBytes: Uint8Array) => InspectedCID;
|
|
48
|
-
/**
|
|
49
|
-
* Decode the first CID contained, and return the remainder.
|
|
50
|
-
* @param bytes Buffer to decode
|
|
51
|
-
* @returns A tuple containing the first CID in the buffer, and the remainder
|
|
52
|
-
*/
|
|
53
|
-
export declare const decodeFirst: (bytes: Uint8Array) => [cid: CID, remainder: Uint8Array];
|
|
54
|
-
/**
|
|
55
|
-
* Decodes a CID buffer
|
|
56
|
-
*/
|
|
57
|
-
export declare const decode: (bytes: Uint8Array) => CID;
|
|
58
|
-
/**
|
|
59
|
-
* Creates a CID
|
|
60
|
-
*/
|
|
61
|
-
export declare const create: (code: number, input: Uint8Array) => Promise<CID>;
|
|
62
|
-
/**
|
|
63
|
-
* Serialize CID into a string
|
|
64
|
-
*/
|
|
65
|
-
export declare const format: (cid: CID) => string;
|
|
66
|
-
export declare const createDigest: (code: number, digest: Uint8Array) => Digest;
|
|
67
|
-
export declare const encode: (version: number, code: number, multihash: Uint8Array) => Uint8Array;
|
|
1
|
+
export * from './cid-link.js';
|
|
2
|
+
export * from './codec.js';
|
package/dist/index.js
CHANGED
|
@@ -1,133 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
* Bare minimum implementation for creating, parsing, and formatting
|
|
4
|
-
* AT Protocol-blessed CIDv1 format.
|
|
5
|
-
*
|
|
6
|
-
* As specified by AT Protocol, the blessed format is:
|
|
7
|
-
* - Multibase: `base32` (b)
|
|
8
|
-
* - Multicodec: `dag-cbor` (0x71) for record, `raw` (0x55) for blobs
|
|
9
|
-
* - Multihash: `sha-256` (0x12)
|
|
10
|
-
*/
|
|
11
|
-
import { fromBase32, toBase32 } from '@atcute/multibase';
|
|
12
|
-
import * as varint from '@atcute/varint';
|
|
13
|
-
/**
|
|
14
|
-
* Parse a CID string
|
|
15
|
-
*/
|
|
16
|
-
export const parse = (cid) => {
|
|
17
|
-
if (cid[0] !== 'b') {
|
|
18
|
-
throw new Error(`only base32 cidv1 is supported`);
|
|
19
|
-
}
|
|
20
|
-
const bytes = fromBase32(cid.slice(1));
|
|
21
|
-
return decode(bytes);
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Provides information regarding the CID buffer
|
|
25
|
-
*/
|
|
26
|
-
export const inspect = (initialBytes) => {
|
|
27
|
-
let offset = 0;
|
|
28
|
-
const next = () => {
|
|
29
|
-
const [i, length] = varint.decode(initialBytes.subarray(offset));
|
|
30
|
-
offset += length;
|
|
31
|
-
return i;
|
|
32
|
-
};
|
|
33
|
-
let version = next();
|
|
34
|
-
let codec = 0x70; // dag-pb
|
|
35
|
-
if (version === 18) {
|
|
36
|
-
// CIDv0
|
|
37
|
-
version = 0;
|
|
38
|
-
offset = 0;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
codec = next();
|
|
42
|
-
}
|
|
43
|
-
if (version !== 1) {
|
|
44
|
-
throw new RangeError(`only cidv1 is supported`);
|
|
45
|
-
}
|
|
46
|
-
const prefixSize = offset;
|
|
47
|
-
const multihashCode = next();
|
|
48
|
-
const digestSize = next();
|
|
49
|
-
const size = offset + digestSize;
|
|
50
|
-
const multihashSize = size - prefixSize;
|
|
51
|
-
return { version, codec, multihashCode, digestSize, multihashSize, size };
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* Decode the first CID contained, and return the remainder.
|
|
55
|
-
* @param bytes Buffer to decode
|
|
56
|
-
* @returns A tuple containing the first CID in the buffer, and the remainder
|
|
57
|
-
*/
|
|
58
|
-
export const decodeFirst = (bytes) => {
|
|
59
|
-
const specs = inspect(bytes);
|
|
60
|
-
const prefixSize = specs.size - specs.multihashSize;
|
|
61
|
-
const multihashBytes = bytes.subarray(prefixSize, prefixSize + specs.multihashSize);
|
|
62
|
-
if (multihashBytes.byteLength !== specs.multihashSize) {
|
|
63
|
-
throw new RangeError('incorrect cid length');
|
|
64
|
-
}
|
|
65
|
-
const digestBytes = multihashBytes.subarray(specs.multihashSize - specs.digestSize);
|
|
66
|
-
const digest = {
|
|
67
|
-
code: specs.multihashCode,
|
|
68
|
-
size: specs.multihashSize,
|
|
69
|
-
digest: digestBytes,
|
|
70
|
-
bytes: multihashBytes,
|
|
71
|
-
};
|
|
72
|
-
const cid = {
|
|
73
|
-
version: 1,
|
|
74
|
-
code: specs.codec,
|
|
75
|
-
digest: digest,
|
|
76
|
-
bytes: bytes.subarray(0, specs.size),
|
|
77
|
-
};
|
|
78
|
-
return [cid, bytes.subarray(specs.size)];
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Decodes a CID buffer
|
|
82
|
-
*/
|
|
83
|
-
export const decode = (bytes) => {
|
|
84
|
-
const [cid, remainder] = decodeFirst(bytes);
|
|
85
|
-
if (remainder.length !== 0) {
|
|
86
|
-
throw new Error(`incorrect cid length`);
|
|
87
|
-
}
|
|
88
|
-
return cid;
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* Creates a CID
|
|
92
|
-
*/
|
|
93
|
-
export const create = async (code, input) => {
|
|
94
|
-
const digest = createDigest(0x12, new Uint8Array(await crypto.subtle.digest('sha-256', input)));
|
|
95
|
-
const bytes = encode(1, code, digest.bytes);
|
|
96
|
-
return {
|
|
97
|
-
version: 1,
|
|
98
|
-
code: code,
|
|
99
|
-
digest: digest,
|
|
100
|
-
bytes: bytes,
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Serialize CID into a string
|
|
105
|
-
*/
|
|
106
|
-
export const format = (cid) => {
|
|
107
|
-
return 'b' + toBase32(cid.bytes);
|
|
108
|
-
};
|
|
109
|
-
export const createDigest = (code, digest) => {
|
|
110
|
-
const size = digest.byteLength;
|
|
111
|
-
const sizeOffset = varint.encodingLength(code);
|
|
112
|
-
const digestOffset = sizeOffset + varint.encodingLength(size);
|
|
113
|
-
const bytes = new Uint8Array(digestOffset + size);
|
|
114
|
-
varint.encode(code, bytes, 0);
|
|
115
|
-
varint.encode(size, bytes, sizeOffset);
|
|
116
|
-
bytes.set(digest, digestOffset);
|
|
117
|
-
return {
|
|
118
|
-
code: code,
|
|
119
|
-
size: size,
|
|
120
|
-
digest: digest,
|
|
121
|
-
bytes: bytes,
|
|
122
|
-
};
|
|
123
|
-
};
|
|
124
|
-
export const encode = (version, code, multihash) => {
|
|
125
|
-
const codeOffset = varint.encodingLength(version);
|
|
126
|
-
const hashOffset = codeOffset + varint.encodingLength(code);
|
|
127
|
-
const bytes = new Uint8Array(hashOffset + multihash.byteLength);
|
|
128
|
-
varint.encode(version, bytes, 0);
|
|
129
|
-
varint.encode(code, bytes, codeOffset);
|
|
130
|
-
bytes.set(multihash, hashOffset);
|
|
131
|
-
return bytes;
|
|
132
|
-
};
|
|
1
|
+
export * from './cid-link.js';
|
|
2
|
+
export * from './codec.js';
|
|
133
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
|
package/lib/cid-link.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { toBase32 } from '@atcute/multibase';
|
|
2
|
+
|
|
3
|
+
import { decode, fromString, type Cid } from './codec.js';
|
|
4
|
+
|
|
5
|
+
export interface CidLink {
|
|
6
|
+
$link: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class CidLinkWrapper implements CidLink {
|
|
10
|
+
constructor(public bytes: Uint8Array) {}
|
|
11
|
+
|
|
12
|
+
get $link(): string {
|
|
13
|
+
const encoded = toBase32(this.bytes);
|
|
14
|
+
return `b${encoded}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
toJSON(): CidLink {
|
|
18
|
+
return { $link: this.$link };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const isCidLink = (value: unknown): value is CidLink => {
|
|
23
|
+
const val = value as any;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
val instanceof CidLinkWrapper ||
|
|
27
|
+
(val !== null && typeof val === 'object' && typeof val.$link === 'string')
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const toCidLink = (cid: Cid): CidLink => {
|
|
32
|
+
return new CidLinkWrapper(cid.bytes);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const fromCidLink = (link: CidLink): Cid => {
|
|
36
|
+
if (link instanceof CidLinkWrapper) {
|
|
37
|
+
return decode(link.bytes);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return fromString(link.$link);
|
|
41
|
+
};
|
package/lib/codec.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { fromBase32, toBase32 } from '@atcute/multibase';
|
|
2
|
+
import * as varint from '@atcute/varint';
|
|
3
|
+
|
|
4
|
+
export const CID_VERSION = 1;
|
|
5
|
+
export const HASH_SHA256 = 0x12;
|
|
6
|
+
|
|
7
|
+
export const CODEC_RAW = 0x55;
|
|
8
|
+
export const CODEC_DCBOR = 0x71;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents a Content Identifier (CID), in particular, a limited subset of
|
|
12
|
+
* CIDv1 as described by DASL specifications.
|
|
13
|
+
* https://dasl.ing/cid.html
|
|
14
|
+
*/
|
|
15
|
+
export interface Cid {
|
|
16
|
+
/** CID version, this is always `1` for CIDv1 */
|
|
17
|
+
version: number;
|
|
18
|
+
/** Multicodec type for the data, can be `0x55` for raw data or `0x71` for DAG-CBOR */
|
|
19
|
+
codec: number;
|
|
20
|
+
/** Digest contents */
|
|
21
|
+
digest: {
|
|
22
|
+
/** Multicodec type for the digest, this is always `0x12` for SHA-256 */
|
|
23
|
+
codec: number;
|
|
24
|
+
/** Raw hash bytes */
|
|
25
|
+
contents: Uint8Array;
|
|
26
|
+
};
|
|
27
|
+
/** Raw CID bytes */
|
|
28
|
+
bytes: Uint8Array;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const create = async (codec: 0x55 | 0x71, data: Uint8Array): Promise<Cid> => {
|
|
32
|
+
const digest = new Uint8Array(await crypto.subtle.digest('sha-256', data));
|
|
33
|
+
|
|
34
|
+
const digestSize = digest.length;
|
|
35
|
+
const digestLebSize = varint.encodingLength(digestSize);
|
|
36
|
+
|
|
37
|
+
const bytes = new Uint8Array(3 + digestLebSize + digestSize);
|
|
38
|
+
|
|
39
|
+
bytes[0] = CID_VERSION;
|
|
40
|
+
bytes[1] = codec;
|
|
41
|
+
bytes[2] = HASH_SHA256;
|
|
42
|
+
|
|
43
|
+
varint.encode(digestSize, bytes, 3);
|
|
44
|
+
bytes.set(digest, 3 + digestLebSize);
|
|
45
|
+
|
|
46
|
+
const cid: Cid = {
|
|
47
|
+
version: CID_VERSION,
|
|
48
|
+
codec: codec,
|
|
49
|
+
digest: {
|
|
50
|
+
codec: HASH_SHA256,
|
|
51
|
+
contents: digest,
|
|
52
|
+
},
|
|
53
|
+
bytes: bytes,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return cid;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const decodeFirst = (bytes: Uint8Array): [decoded: Cid, remainder: Uint8Array] => {
|
|
60
|
+
const length = bytes.length;
|
|
61
|
+
|
|
62
|
+
if (length < 5) {
|
|
63
|
+
throw new RangeError(`cid too short`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const version = bytes[0];
|
|
67
|
+
const codec = bytes[1];
|
|
68
|
+
const digestCodec = bytes[2];
|
|
69
|
+
|
|
70
|
+
if (version !== CID_VERSION) {
|
|
71
|
+
throw new RangeError(`incorrect cid version (got v${version})`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (codec !== CODEC_DCBOR && codec !== CODEC_RAW) {
|
|
75
|
+
throw new RangeError(`incorrect cid codec (got 0x${codec.toString(16)})`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (digestCodec !== HASH_SHA256) {
|
|
79
|
+
throw new RangeError(`incorrect cid hash type (got 0x${digestCodec.toString(16)})`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const [digestSize, digestLebSize] = varint.decode(bytes, 3);
|
|
83
|
+
const digestOffset = 3 + digestLebSize;
|
|
84
|
+
|
|
85
|
+
if (length - digestOffset < digestSize) {
|
|
86
|
+
throw new RangeError(`digest too short (expected ${digestSize} bytes; got ${length - digestOffset})`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const remainder = bytes.subarray(digestOffset + digestSize);
|
|
90
|
+
|
|
91
|
+
const cid: Cid = {
|
|
92
|
+
version: CID_VERSION,
|
|
93
|
+
codec: codec,
|
|
94
|
+
digest: {
|
|
95
|
+
codec: digestCodec,
|
|
96
|
+
contents: bytes.subarray(digestOffset, digestOffset + digestSize),
|
|
97
|
+
},
|
|
98
|
+
bytes: bytes.subarray(0, digestOffset + digestSize),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return [cid, remainder];
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const decode = (bytes: Uint8Array): Cid => {
|
|
105
|
+
const [cid, remainder] = decodeFirst(bytes);
|
|
106
|
+
|
|
107
|
+
if (remainder.length !== 0) {
|
|
108
|
+
throw new RangeError(`cid bytes includes remainder`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return cid;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const fromString = (input: string): Cid => {
|
|
115
|
+
if (input.length < 2 || input[0] !== 'b') {
|
|
116
|
+
throw new SyntaxError(`not a multibase base32 string`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const bytes = fromBase32(input.slice(1));
|
|
120
|
+
return decode(bytes);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const toString = (cid: Cid): string => {
|
|
124
|
+
const encoded = toBase32(cid.bytes);
|
|
125
|
+
return `b${encoded}`;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const fromBinary = (input: Uint8Array): Cid => {
|
|
129
|
+
if (input.length < 2) {
|
|
130
|
+
throw new RangeError(`cid bytes too short`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (input[0] !== 0) {
|
|
134
|
+
throw new SyntaxError(`incorrect binary cid`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const bytes = input.subarray(1);
|
|
138
|
+
return decode(bytes);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export const toBinary = (cid: Cid): Uint8Array => {
|
|
142
|
+
const bytes = new Uint8Array(1 + cid.bytes.length);
|
|
143
|
+
bytes.set(cid.bytes, 1);
|
|
144
|
+
|
|
145
|
+
return bytes;
|
|
146
|
+
};
|
package/lib/index.ts
CHANGED
|
@@ -1,189 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
* Bare minimum implementation for creating, parsing, and formatting
|
|
4
|
-
* AT Protocol-blessed CIDv1 format.
|
|
5
|
-
*
|
|
6
|
-
* As specified by AT Protocol, the blessed format is:
|
|
7
|
-
* - Multibase: `base32` (b)
|
|
8
|
-
* - Multicodec: `dag-cbor` (0x71) for record, `raw` (0x55) for blobs
|
|
9
|
-
* - Multihash: `sha-256` (0x12)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { fromBase32, toBase32 } from '@atcute/multibase';
|
|
13
|
-
import * as varint from '@atcute/varint';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Raw digest information
|
|
17
|
-
*/
|
|
18
|
-
export interface Digest {
|
|
19
|
-
code: number;
|
|
20
|
-
size: number;
|
|
21
|
-
digest: Uint8Array;
|
|
22
|
-
bytes: Uint8Array;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* CID information
|
|
27
|
-
*/
|
|
28
|
-
export interface CID {
|
|
29
|
-
version: number;
|
|
30
|
-
code: number;
|
|
31
|
-
digest: Digest;
|
|
32
|
-
bytes: Uint8Array;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Information regarding CID buffer being inspected
|
|
37
|
-
*/
|
|
38
|
-
export interface InspectedCID {
|
|
39
|
-
version: number;
|
|
40
|
-
codec: number;
|
|
41
|
-
multihashCode: number;
|
|
42
|
-
digestSize: number;
|
|
43
|
-
multihashSize: number;
|
|
44
|
-
size: number;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Parse a CID string
|
|
49
|
-
*/
|
|
50
|
-
export const parse = (cid: string): CID => {
|
|
51
|
-
if (cid[0] !== 'b') {
|
|
52
|
-
throw new Error(`only base32 cidv1 is supported`);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const bytes = fromBase32(cid.slice(1));
|
|
56
|
-
return decode(bytes);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Provides information regarding the CID buffer
|
|
61
|
-
*/
|
|
62
|
-
export const inspect = (initialBytes: Uint8Array): InspectedCID => {
|
|
63
|
-
let offset = 0;
|
|
64
|
-
const next = (): number => {
|
|
65
|
-
const [i, length] = varint.decode(initialBytes.subarray(offset));
|
|
66
|
-
offset += length;
|
|
67
|
-
return i;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
let version = next();
|
|
71
|
-
let codec = 0x70; // dag-pb
|
|
72
|
-
if ((version as number) === 18) {
|
|
73
|
-
// CIDv0
|
|
74
|
-
version = 0;
|
|
75
|
-
offset = 0;
|
|
76
|
-
} else {
|
|
77
|
-
codec = next();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (version !== 1) {
|
|
81
|
-
throw new RangeError(`only cidv1 is supported`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const prefixSize = offset;
|
|
85
|
-
const multihashCode = next();
|
|
86
|
-
const digestSize = next();
|
|
87
|
-
const size = offset + digestSize;
|
|
88
|
-
const multihashSize = size - prefixSize;
|
|
89
|
-
|
|
90
|
-
return { version, codec, multihashCode, digestSize, multihashSize, size };
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Decode the first CID contained, and return the remainder.
|
|
95
|
-
* @param bytes Buffer to decode
|
|
96
|
-
* @returns A tuple containing the first CID in the buffer, and the remainder
|
|
97
|
-
*/
|
|
98
|
-
export const decodeFirst = (bytes: Uint8Array): [cid: CID, remainder: Uint8Array] => {
|
|
99
|
-
const specs = inspect(bytes);
|
|
100
|
-
const prefixSize = specs.size - specs.multihashSize;
|
|
101
|
-
const multihashBytes = bytes.subarray(prefixSize, prefixSize + specs.multihashSize);
|
|
102
|
-
|
|
103
|
-
if (multihashBytes.byteLength !== specs.multihashSize) {
|
|
104
|
-
throw new RangeError('incorrect cid length');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const digestBytes = multihashBytes.subarray(specs.multihashSize - specs.digestSize);
|
|
108
|
-
|
|
109
|
-
const digest: Digest = {
|
|
110
|
-
code: specs.multihashCode,
|
|
111
|
-
size: specs.multihashSize,
|
|
112
|
-
digest: digestBytes,
|
|
113
|
-
bytes: multihashBytes,
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const cid: CID = {
|
|
117
|
-
version: 1,
|
|
118
|
-
code: specs.codec,
|
|
119
|
-
digest: digest,
|
|
120
|
-
bytes: bytes.subarray(0, specs.size),
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
return [cid, bytes.subarray(specs.size)];
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Decodes a CID buffer
|
|
128
|
-
*/
|
|
129
|
-
export const decode = (bytes: Uint8Array): CID => {
|
|
130
|
-
const [cid, remainder] = decodeFirst(bytes);
|
|
131
|
-
|
|
132
|
-
if (remainder.length !== 0) {
|
|
133
|
-
throw new Error(`incorrect cid length`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return cid;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Creates a CID
|
|
141
|
-
*/
|
|
142
|
-
export const create = async (code: number, input: Uint8Array): Promise<CID> => {
|
|
143
|
-
const digest = createDigest(0x12, new Uint8Array(await crypto.subtle.digest('sha-256', input)));
|
|
144
|
-
const bytes = encode(1, code, digest.bytes);
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
version: 1,
|
|
148
|
-
code: code,
|
|
149
|
-
digest: digest,
|
|
150
|
-
bytes: bytes,
|
|
151
|
-
};
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Serialize CID into a string
|
|
156
|
-
*/
|
|
157
|
-
export const format = (cid: CID): string => {
|
|
158
|
-
return 'b' + toBase32(cid.bytes);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
export const createDigest = (code: number, digest: Uint8Array): Digest => {
|
|
162
|
-
const size = digest.byteLength;
|
|
163
|
-
const sizeOffset = varint.encodingLength(code);
|
|
164
|
-
const digestOffset = sizeOffset + varint.encodingLength(size);
|
|
165
|
-
|
|
166
|
-
const bytes = new Uint8Array(digestOffset + size);
|
|
167
|
-
varint.encode(code, bytes, 0);
|
|
168
|
-
varint.encode(size, bytes, sizeOffset);
|
|
169
|
-
bytes.set(digest, digestOffset);
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
code: code,
|
|
173
|
-
size: size,
|
|
174
|
-
digest: digest,
|
|
175
|
-
bytes: bytes,
|
|
176
|
-
};
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
export const encode = (version: number, code: number, multihash: Uint8Array): Uint8Array => {
|
|
180
|
-
const codeOffset = varint.encodingLength(version);
|
|
181
|
-
const hashOffset = codeOffset + varint.encodingLength(code);
|
|
182
|
-
|
|
183
|
-
const bytes = new Uint8Array(hashOffset + multihash.byteLength);
|
|
184
|
-
varint.encode(version, bytes, 0);
|
|
185
|
-
varint.encode(code, bytes, codeOffset);
|
|
186
|
-
bytes.set(multihash, hashOffset);
|
|
187
|
-
|
|
188
|
-
return bytes;
|
|
189
|
-
};
|
|
1
|
+
export * from './cid-link.js';
|
|
2
|
+
export * from './codec.js';
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@atcute/cid",
|
|
4
|
-
"version": "
|
|
5
|
-
"description": "
|
|
4
|
+
"version": "2.0.1",
|
|
5
|
+
"description": "lightweight DASL CID codec library for AT Protocol",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"atproto",
|
|
8
|
+
"dasl",
|
|
9
|
+
"cid"
|
|
10
|
+
],
|
|
6
11
|
"license": "MIT",
|
|
7
12
|
"repository": {
|
|
8
13
|
"url": "https://github.com/mary-ext/atcute",
|
|
@@ -19,11 +24,11 @@
|
|
|
19
24
|
},
|
|
20
25
|
"sideEffects": false,
|
|
21
26
|
"devDependencies": {
|
|
22
|
-
"@types/bun": "^1.1.
|
|
27
|
+
"@types/bun": "^1.1.14"
|
|
23
28
|
},
|
|
24
29
|
"dependencies": {
|
|
25
|
-
"@atcute/multibase": "^1.0.
|
|
26
|
-
"@atcute/varint": "^1.0.
|
|
30
|
+
"@atcute/multibase": "^1.0.1",
|
|
31
|
+
"@atcute/varint": "^1.0.2"
|
|
27
32
|
},
|
|
28
33
|
"scripts": {
|
|
29
34
|
"build": "tsc --project tsconfig.build.json",
|