@atproto/lex-cbor 0.1.1 → 0.1.3
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 +20 -0
- package/dist/encoding.d.ts +1 -1
- package/dist/encoding.d.ts.map +1 -1
- package/dist/encoding.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -10
- package/src/encoding.ts +0 -192
- package/src/index.ts +0 -43
- package/tsconfig.build.json +0 -11
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @atproto/lex-cbor
|
|
2
2
|
|
|
3
|
+
## 0.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update TypeScript build to rely on references to composite internal projects
|
|
8
|
+
|
|
9
|
+
- [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Bundle only necessary files in the NPM tarball, including the `CHANGELOG.md` and `README.md` files (if present).
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07)]:
|
|
12
|
+
- @atproto/lex-data@0.1.4
|
|
13
|
+
|
|
14
|
+
## 0.1.2
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- [#5151](https://github.com/bluesky-social/atproto/pull/5151) [`a51c45d`](https://github.com/bluesky-social/atproto/commit/a51c45d38f6bd7b8765f640e564cf921d52162e7) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update dependencies
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [[`a51c45d`](https://github.com/bluesky-social/atproto/commit/a51c45d38f6bd7b8765f640e564cf921d52162e7)]:
|
|
21
|
+
- @atproto/lex-data@0.1.3
|
|
22
|
+
|
|
3
23
|
## 0.1.1
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/encoding.d.ts
CHANGED
package/dist/encoding.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAO,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAUtD;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,KAsCxB,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,KAoBxB,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,UAAU,CAEzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,CAAC,CAE1E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAiB,SAAS,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ,EACtD,IAAI,EAAE,UAAU,GACf,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAM7B"}
|
package/dist/encoding.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DecodeOptions, EncodeOptions, TagDecoder } from 'cborg'\nimport {\n Token,\n Type,\n decode as cborgDecode,\n decodeFirst as cborgDecodeFirst,\n encode as cborgEncode,\n} from 'cborg'\nimport type { OptionalTypeEncoder } from 'cborg/interface'\nimport type { Cid, LexValue } from '@atproto/lex-data'\nimport { decodeCid, ifCid } from '@atproto/lex-data'\n\n// @NOTE \"cborg\" version 4 is required to support multi-decoding via the\n// \"decodeFirst\" function. However, that version only exposes ES modules.\n// Because this package is using \"commonjs\", \"cborg\" will be bundled instead of\n// depending on it directly.\n\nconst CID_CBOR_TAG = 42\n\n/**\n * Configuration options for CBOR encoding that enforces AT Protocol data model\n * constraints.\n *\n * This configuration ensures:\n * - CIDs are encoded using CBOR tag 42 with a leading 0x00 byte prefix\n * - Map keys must be strings (no numeric or other key types allowed)\n * - `undefined` values are not permitted (undefined object properties will be stripped)\n * - Only safe integer numbers are allowed (no floats or non-integer values)\n */\nexport const encodeOptions = Object.freeze<EncodeOptions>({\n float64: true,\n ignoreUndefinedProperties: true,\n typeEncoders: Object.freeze<{ [typeName: string]: OptionalTypeEncoder }>({\n Map: (map: Map<unknown, unknown>): null => {\n for (const key of map.keys()) {\n if (typeof key !== 'string') {\n throw new Error(\n 'Only string keys are allowed in CBOR \"map\" by the AT Data Model',\n )\n }\n }\n\n // @NOTE Maps will be encoded as CBOR \"map\", which will be decoded as object.\n return null\n },\n Object: (obj: object): Token[] | null => {\n const cid = ifCid(obj)\n if (cid) {\n const bytes = new Uint8Array(cid.bytes.byteLength + 1)\n bytes.set(cid.bytes, 1) // prefix is 0x00, for historical reasons\n return [new Token(Type.tag, CID_CBOR_TAG), new Token(Type.bytes, bytes)]\n }\n\n // Fallback to default object encoder\n return null\n },\n undefined: (): null => {\n throw new Error('`undefined` is not supported by the AT Data Model')\n },\n number: (num: number): null => {\n if (Number.isSafeInteger(num)) return null\n\n throw new Error(\n `Non-integer numbers (${num}) are not supported by the AT Data Model`,\n )\n },\n }),\n})\n\n/**\n * Configuration options for CBOR decoding that enforces AT Protocol data model\n * constraints.\n */\nexport const decodeOptions = /*#__PURE__*/ Object.freeze<DecodeOptions>({\n allowIndefinite: false,\n coerceUndefinedToNull: true,\n allowNaN: false,\n allowInfinity: false,\n allowBigInt: true,\n strict: true,\n useMaps: false,\n rejectDuplicateMapKeys: true,\n tags: /*#__PURE__*/ Object.freeze<TagDecoder[]>(\n /*#__PURE__*/ Object.assign([], {\n [CID_CBOR_TAG]: (bytes: Uint8Array): Cid => {\n if (bytes[0] !== 0) {\n throw new Error('Invalid CID for CBOR tag 42; expected leading 0x00')\n }\n const cibBytes = bytes.subarray(1) // ignore leading 0x00\n return decodeCid(cibBytes)\n },\n }),\n ) as TagDecoder[],\n})\n\n/**\n * Encodes a LexValue to CBOR bytes using the AT Protocol data model (DRISL format).\n *\n * @param data - The LexValue to encode\n * @returns The CBOR-encoded bytes\n * @throws {Error} If the data contains non-string map keys, undefined values, or non-integer numbers\n *\n * @example\n * ```typescript\n * import { encode } from '@atproto/lex-cbor'\n *\n * // Encode a simple object\n * const bytes = encode({ text: 'Hello', count: 42 })\n *\n * // Encode an AT Protocol record\n * const recordBytes = encode({\n * $type: 'app.bsky.feed.post',\n * text: 'Hello from AT Protocol!',\n * createdAt: new Date().toISOString(),\n * })\n * ```\n */\nexport function encode<T extends LexValue = LexValue>(data: T): Uint8Array {\n return cborgEncode(data, encodeOptions)\n}\n\n/**\n * Decodes CBOR bytes to a LexValue using the AT Protocol data model (DRISL format).\n *\n * @typeParam T - Allows casting the decoded values to a specific LexValue subtype\n * @param bytes - The CBOR bytes to decode\n * @returns The decoded LexValue\n * @throws {Error} If the bytes are not valid CBOR or violate AT Protocol constraints\n *\n * @example\n * ```typescript\n * import { encode, decode } from '@atproto/lex-cbor'\n * import type { LexValue } from '@atproto/lex'\n *\n * // Round-trip encoding and decoding\n * const original = { text: 'Hello', count: 42 }\n * const bytes = encode(original)\n * const decoded: LexValue = decode(bytes)\n *\n * // Decode with a specific type\n * interface Post {\n * $type: string\n * text: string\n * createdAt: string\n * }\n * const post = decode<Post>(recordBytes)\n * ```\n */\nexport function decode<T extends LexValue = LexValue>(bytes: Uint8Array): T {\n return cborgDecode(bytes, decodeOptions)\n}\n\n/**\n * Generator that yields multiple decoded LexValues from a buffer containing\n * concatenated CBOR-encoded values.\n *\n * This is useful for processing streams or files containing multiple\n * CBOR-encoded records back-to-back (e.g., CAR file blocks or event streams).\n *\n * @typeParam T - Allows casting the decoded values to a specific LexValue subtype\n * @param data - The buffer containing one or more CBOR-encoded values\n * @yields Decoded LexValues one at a time\n * @throws {Error} If any value in the buffer is not valid CBOR or violates AT Protocol constraints\n *\n * @example\n * ```typescript\n * import { encode, decodeAll } from '@atproto/lex-cbor'\n *\n * // Concatenate multiple encoded values\n * const bytes1 = encode({ id: 1, text: 'First' })\n * const bytes2 = encode({ id: 2, text: 'Second' })\n * const combined = new Uint8Array([...bytes1, ...bytes2])\n *\n * // Decode all values from the combined buffer\n * for (const value of decodeAll(combined)) {\n * console.log(value)\n * }\n * // Output:\n * // { id: 1, text: 'First' }\n * // { id: 2, text: 'Second' }\n * ```\n */\nexport function* decodeAll<T extends LexValue = LexValue>(\n data: Uint8Array,\n): Generator<T, void, unknown> {\n do {\n const [result, remainingBytes] = cborgDecodeFirst(data, decodeOptions)\n yield result\n data = remainingBytes\n } while (data.byteLength > 0)\n}\n"]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAI1D,YAAY,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAA;AAC5C,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAA;AAEjC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEzD,OAAO,EACL,MAAM,IAAI,UAAU,EACpB,SAAS,IAAI,aAAa,EAC1B,aAAa,EACb,MAAM,IAAI,UAAU,EACpB,aAAa,GACd,MAAM,eAAe,CAAA;AAEtB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAEjE"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAKtC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEzD,OAAO,EACL,MAAM,IAAI,UAAU,EACpB,SAAS,IAAI,aAAa,EAC1B,aAAa,EACb,MAAM,IAAI,UAAU,EACpB,aAAa,GACd,MAAM,eAAe,CAAA;AAEtB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAe;IAC7C,OAAO,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;AAClC,CAAC","sourcesContent":["import type { CborCid, LexValue } from '@atproto/lex-data'\nimport { cidForCbor } from '@atproto/lex-data'\nimport { encode } from './encoding.js'\n\nexport type { Cid } from '@atproto/lex-data'\nexport type { CborCid, LexValue }\n\nexport { decode, decodeAll, encode } from './encoding.js'\n\nexport {\n decode as cborDecode,\n decodeAll as cborDecodeAll,\n decodeOptions,\n encode as cborEncode,\n encodeOptions,\n} from './encoding.js'\n\n/**\n * Computes a CID (Content Identifier) for a given LexValue.\n *\n * This function first encodes the value to CBOR bytes using the AT Protocol\n * data model constraints, then computes the CID hash of those bytes. The\n * resulting CID can be used to uniquely identify and reference the content.\n *\n * @param value - The LexValue to compute a CID for\n * @returns A promise that resolves to the CID for the CBOR-encoded value\n *\n * @example\n * ```typescript\n * import { cidForLex } from '@atproto/lex-cbor'\n *\n * const record = {\n * $type: 'app.bsky.feed.post',\n * text: 'Hello, AT Protocol!',\n * createdAt: new Date().toISOString(),\n * }\n *\n * const cid = await cidForLex(record)\n * console.log(cid.toString()) // e.g., 'bafyreih...'\n * ```\n */\nexport async function cidForLex(value: LexValue): Promise<CborCid> {\n return cidForCbor(encode(value))\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lex-cbor",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"engines": {
|
|
5
|
-
"node": ">=22"
|
|
6
|
-
},
|
|
3
|
+
"version": "0.1.3",
|
|
7
4
|
"license": "MIT",
|
|
8
5
|
"description": "Lexicon encoding utilities for AT Lexicon data in CBOR format",
|
|
9
6
|
"keywords": [
|
|
@@ -21,10 +18,6 @@
|
|
|
21
18
|
"directory": "packages/lex/lex-cbor"
|
|
22
19
|
},
|
|
23
20
|
"files": [
|
|
24
|
-
"./src",
|
|
25
|
-
"./tsconfig.build.json",
|
|
26
|
-
"./tsconfig.tests.json",
|
|
27
|
-
"./tsconfig.json",
|
|
28
21
|
"./dist",
|
|
29
22
|
"./CHANGELOG.md"
|
|
30
23
|
],
|
|
@@ -36,14 +29,17 @@
|
|
|
36
29
|
"default": "./dist/index.js"
|
|
37
30
|
}
|
|
38
31
|
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=22"
|
|
34
|
+
},
|
|
39
35
|
"dependencies": {
|
|
40
36
|
"cborg": "^4.5.8",
|
|
41
37
|
"tslib": "^2.8.1",
|
|
42
|
-
"@atproto/lex-data": "^0.1.
|
|
38
|
+
"@atproto/lex-data": "^0.1.4"
|
|
43
39
|
},
|
|
44
40
|
"devDependencies": {
|
|
45
41
|
"vitest": "^4.0.16",
|
|
46
|
-
"@atproto/lex-json": "^0.1.
|
|
42
|
+
"@atproto/lex-json": "^0.1.3"
|
|
47
43
|
},
|
|
48
44
|
"scripts": {
|
|
49
45
|
"build": "tsgo --build tsconfig.build.json",
|
package/src/encoding.ts
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DecodeOptions,
|
|
3
|
-
EncodeOptions,
|
|
4
|
-
TagDecoder,
|
|
5
|
-
Token,
|
|
6
|
-
Type,
|
|
7
|
-
decode as cborgDecode,
|
|
8
|
-
decodeFirst as cborgDecodeFirst,
|
|
9
|
-
encode as cborgEncode,
|
|
10
|
-
} from 'cborg'
|
|
11
|
-
import { OptionalTypeEncoder } from 'cborg/interface'
|
|
12
|
-
import { Cid, LexValue, decodeCid, ifCid } from '@atproto/lex-data'
|
|
13
|
-
|
|
14
|
-
// @NOTE "cborg" version 4 is required to support multi-decoding via the
|
|
15
|
-
// "decodeFirst" function. However, that version only exposes ES modules.
|
|
16
|
-
// Because this package is using "commonjs", "cborg" will be bundled instead of
|
|
17
|
-
// depending on it directly.
|
|
18
|
-
|
|
19
|
-
const CID_CBOR_TAG = 42
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Configuration options for CBOR encoding that enforces AT Protocol data model
|
|
23
|
-
* constraints.
|
|
24
|
-
*
|
|
25
|
-
* This configuration ensures:
|
|
26
|
-
* - CIDs are encoded using CBOR tag 42 with a leading 0x00 byte prefix
|
|
27
|
-
* - Map keys must be strings (no numeric or other key types allowed)
|
|
28
|
-
* - `undefined` values are not permitted (undefined object properties will be stripped)
|
|
29
|
-
* - Only safe integer numbers are allowed (no floats or non-integer values)
|
|
30
|
-
*/
|
|
31
|
-
export const encodeOptions = Object.freeze<EncodeOptions>({
|
|
32
|
-
float64: true,
|
|
33
|
-
ignoreUndefinedProperties: true,
|
|
34
|
-
typeEncoders: Object.freeze<{ [typeName: string]: OptionalTypeEncoder }>({
|
|
35
|
-
Map: (map: Map<unknown, unknown>): null => {
|
|
36
|
-
for (const key of map.keys()) {
|
|
37
|
-
if (typeof key !== 'string') {
|
|
38
|
-
throw new Error(
|
|
39
|
-
'Only string keys are allowed in CBOR "map" by the AT Data Model',
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// @NOTE Maps will be encoded as CBOR "map", which will be decoded as object.
|
|
45
|
-
return null
|
|
46
|
-
},
|
|
47
|
-
Object: (obj: object): Token[] | null => {
|
|
48
|
-
const cid = ifCid(obj)
|
|
49
|
-
if (cid) {
|
|
50
|
-
const bytes = new Uint8Array(cid.bytes.byteLength + 1)
|
|
51
|
-
bytes.set(cid.bytes, 1) // prefix is 0x00, for historical reasons
|
|
52
|
-
return [new Token(Type.tag, CID_CBOR_TAG), new Token(Type.bytes, bytes)]
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Fallback to default object encoder
|
|
56
|
-
return null
|
|
57
|
-
},
|
|
58
|
-
undefined: (): null => {
|
|
59
|
-
throw new Error('`undefined` is not supported by the AT Data Model')
|
|
60
|
-
},
|
|
61
|
-
number: (num: number): null => {
|
|
62
|
-
if (Number.isSafeInteger(num)) return null
|
|
63
|
-
|
|
64
|
-
throw new Error(
|
|
65
|
-
`Non-integer numbers (${num}) are not supported by the AT Data Model`,
|
|
66
|
-
)
|
|
67
|
-
},
|
|
68
|
-
}),
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Configuration options for CBOR decoding that enforces AT Protocol data model
|
|
73
|
-
* constraints.
|
|
74
|
-
*/
|
|
75
|
-
export const decodeOptions = /*#__PURE__*/ Object.freeze<DecodeOptions>({
|
|
76
|
-
allowIndefinite: false,
|
|
77
|
-
coerceUndefinedToNull: true,
|
|
78
|
-
allowNaN: false,
|
|
79
|
-
allowInfinity: false,
|
|
80
|
-
allowBigInt: true,
|
|
81
|
-
strict: true,
|
|
82
|
-
useMaps: false,
|
|
83
|
-
rejectDuplicateMapKeys: true,
|
|
84
|
-
tags: /*#__PURE__*/ Object.freeze<TagDecoder[]>(
|
|
85
|
-
/*#__PURE__*/ Object.assign([], {
|
|
86
|
-
[CID_CBOR_TAG]: (bytes: Uint8Array): Cid => {
|
|
87
|
-
if (bytes[0] !== 0) {
|
|
88
|
-
throw new Error('Invalid CID for CBOR tag 42; expected leading 0x00')
|
|
89
|
-
}
|
|
90
|
-
const cibBytes = bytes.subarray(1) // ignore leading 0x00
|
|
91
|
-
return decodeCid(cibBytes)
|
|
92
|
-
},
|
|
93
|
-
}),
|
|
94
|
-
) as TagDecoder[],
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Encodes a LexValue to CBOR bytes using the AT Protocol data model (DRISL format).
|
|
99
|
-
*
|
|
100
|
-
* @param data - The LexValue to encode
|
|
101
|
-
* @returns The CBOR-encoded bytes
|
|
102
|
-
* @throws {Error} If the data contains non-string map keys, undefined values, or non-integer numbers
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```typescript
|
|
106
|
-
* import { encode } from '@atproto/lex-cbor'
|
|
107
|
-
*
|
|
108
|
-
* // Encode a simple object
|
|
109
|
-
* const bytes = encode({ text: 'Hello', count: 42 })
|
|
110
|
-
*
|
|
111
|
-
* // Encode an AT Protocol record
|
|
112
|
-
* const recordBytes = encode({
|
|
113
|
-
* $type: 'app.bsky.feed.post',
|
|
114
|
-
* text: 'Hello from AT Protocol!',
|
|
115
|
-
* createdAt: new Date().toISOString(),
|
|
116
|
-
* })
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
export function encode<T extends LexValue = LexValue>(data: T): Uint8Array {
|
|
120
|
-
return cborgEncode(data, encodeOptions)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Decodes CBOR bytes to a LexValue using the AT Protocol data model (DRISL format).
|
|
125
|
-
*
|
|
126
|
-
* @typeParam T - Allows casting the decoded values to a specific LexValue subtype
|
|
127
|
-
* @param bytes - The CBOR bytes to decode
|
|
128
|
-
* @returns The decoded LexValue
|
|
129
|
-
* @throws {Error} If the bytes are not valid CBOR or violate AT Protocol constraints
|
|
130
|
-
*
|
|
131
|
-
* @example
|
|
132
|
-
* ```typescript
|
|
133
|
-
* import { encode, decode } from '@atproto/lex-cbor'
|
|
134
|
-
* import type { LexValue } from '@atproto/lex'
|
|
135
|
-
*
|
|
136
|
-
* // Round-trip encoding and decoding
|
|
137
|
-
* const original = { text: 'Hello', count: 42 }
|
|
138
|
-
* const bytes = encode(original)
|
|
139
|
-
* const decoded: LexValue = decode(bytes)
|
|
140
|
-
*
|
|
141
|
-
* // Decode with a specific type
|
|
142
|
-
* interface Post {
|
|
143
|
-
* $type: string
|
|
144
|
-
* text: string
|
|
145
|
-
* createdAt: string
|
|
146
|
-
* }
|
|
147
|
-
* const post = decode<Post>(recordBytes)
|
|
148
|
-
* ```
|
|
149
|
-
*/
|
|
150
|
-
export function decode<T extends LexValue = LexValue>(bytes: Uint8Array): T {
|
|
151
|
-
return cborgDecode(bytes, decodeOptions)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Generator that yields multiple decoded LexValues from a buffer containing
|
|
156
|
-
* concatenated CBOR-encoded values.
|
|
157
|
-
*
|
|
158
|
-
* This is useful for processing streams or files containing multiple
|
|
159
|
-
* CBOR-encoded records back-to-back (e.g., CAR file blocks or event streams).
|
|
160
|
-
*
|
|
161
|
-
* @typeParam T - Allows casting the decoded values to a specific LexValue subtype
|
|
162
|
-
* @param data - The buffer containing one or more CBOR-encoded values
|
|
163
|
-
* @yields Decoded LexValues one at a time
|
|
164
|
-
* @throws {Error} If any value in the buffer is not valid CBOR or violates AT Protocol constraints
|
|
165
|
-
*
|
|
166
|
-
* @example
|
|
167
|
-
* ```typescript
|
|
168
|
-
* import { encode, decodeAll } from '@atproto/lex-cbor'
|
|
169
|
-
*
|
|
170
|
-
* // Concatenate multiple encoded values
|
|
171
|
-
* const bytes1 = encode({ id: 1, text: 'First' })
|
|
172
|
-
* const bytes2 = encode({ id: 2, text: 'Second' })
|
|
173
|
-
* const combined = new Uint8Array([...bytes1, ...bytes2])
|
|
174
|
-
*
|
|
175
|
-
* // Decode all values from the combined buffer
|
|
176
|
-
* for (const value of decodeAll(combined)) {
|
|
177
|
-
* console.log(value)
|
|
178
|
-
* }
|
|
179
|
-
* // Output:
|
|
180
|
-
* // { id: 1, text: 'First' }
|
|
181
|
-
* // { id: 2, text: 'Second' }
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
|
-
export function* decodeAll<T extends LexValue = LexValue>(
|
|
185
|
-
data: Uint8Array,
|
|
186
|
-
): Generator<T, void, unknown> {
|
|
187
|
-
do {
|
|
188
|
-
const [result, remainingBytes] = cborgDecodeFirst(data, decodeOptions)
|
|
189
|
-
yield result
|
|
190
|
-
data = remainingBytes
|
|
191
|
-
} while (data.byteLength > 0)
|
|
192
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { CborCid, LexValue, cidForCbor } from '@atproto/lex-data'
|
|
2
|
-
import { encode } from './encoding.js'
|
|
3
|
-
|
|
4
|
-
export type { Cid } from '@atproto/lex-data'
|
|
5
|
-
export type { CborCid, LexValue }
|
|
6
|
-
|
|
7
|
-
export { decode, decodeAll, encode } from './encoding.js'
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
decode as cborDecode,
|
|
11
|
-
decodeAll as cborDecodeAll,
|
|
12
|
-
decodeOptions,
|
|
13
|
-
encode as cborEncode,
|
|
14
|
-
encodeOptions,
|
|
15
|
-
} from './encoding.js'
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Computes a CID (Content Identifier) for a given LexValue.
|
|
19
|
-
*
|
|
20
|
-
* This function first encodes the value to CBOR bytes using the AT Protocol
|
|
21
|
-
* data model constraints, then computes the CID hash of those bytes. The
|
|
22
|
-
* resulting CID can be used to uniquely identify and reference the content.
|
|
23
|
-
*
|
|
24
|
-
* @param value - The LexValue to compute a CID for
|
|
25
|
-
* @returns A promise that resolves to the CID for the CBOR-encoded value
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```typescript
|
|
29
|
-
* import { cidForLex } from '@atproto/lex-cbor'
|
|
30
|
-
*
|
|
31
|
-
* const record = {
|
|
32
|
-
* $type: 'app.bsky.feed.post',
|
|
33
|
-
* text: 'Hello, AT Protocol!',
|
|
34
|
-
* createdAt: new Date().toISOString(),
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* const cid = await cidForLex(record)
|
|
38
|
-
* console.log(cid.toString()) // e.g., 'bafyreih...'
|
|
39
|
-
* ```
|
|
40
|
-
*/
|
|
41
|
-
export async function cidForLex(value: LexValue): Promise<CborCid> {
|
|
42
|
-
return cidForCbor(encode(value))
|
|
43
|
-
}
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED