@atproto/lex-cbor 0.1.2 → 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 CHANGED
@@ -1,5 +1,16 @@
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
+
3
14
  ## 0.1.2
4
15
 
5
16
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- import { LexValue } from '@atproto/lex-data';
1
+ import type { LexValue } from '@atproto/lex-data';
2
2
  /**
3
3
  * Configuration options for CBOR encoding that enforces AT Protocol data model
4
4
  * constraints.
@@ -1 +1 @@
1
- {"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAWA,OAAO,EAAO,QAAQ,EAAoB,MAAM,mBAAmB,CAAA;AASnE;;;;;;;;;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"}
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DecodeOptions,\n EncodeOptions,\n TagDecoder,\n Token,\n Type,\n decode as cborgDecode,\n decodeFirst as cborgDecodeFirst,\n encode as cborgEncode,\n} from 'cborg'\nimport { OptionalTypeEncoder } from 'cborg/interface'\nimport { Cid, LexValue, 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"]}
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
@@ -1,4 +1,4 @@
1
- import { CborCid, LexValue } from '@atproto/lex-data';
1
+ import type { CborCid, LexValue } from '@atproto/lex-data';
2
2
  export type { Cid } from '@atproto/lex-data';
3
3
  export type { CborCid, LexValue };
4
4
  export { decode, decodeAll, encode } from './encoding.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAc,MAAM,mBAAmB,CAAA;AAGjE,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"}
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":"AAAA,OAAO,EAAqB,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACjE,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 { CborCid, LexValue, 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"]}
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.2",
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.3"
38
+ "@atproto/lex-data": "^0.1.4"
43
39
  },
44
40
  "devDependencies": {
45
41
  "vitest": "^4.0.16",
46
- "@atproto/lex-json": "^0.1.2"
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
- }
@@ -1,11 +0,0 @@
1
- {
2
- "extends": ["../../../tsconfig/isomorphic.json"],
3
- "include": ["./src"],
4
- "exclude": ["**/*.test.ts"],
5
- "compilerOptions": {
6
- "noImplicitAny": true,
7
- "importHelpers": true,
8
- "rootDir": "./src",
9
- "outDir": "./dist",
10
- },
11
- }
package/tsconfig.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "include": [],
3
- "references": [
4
- { "path": "./tsconfig.build.json" },
5
- { "path": "./tsconfig.tests.json" },
6
- ],
7
- }
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig/vitest.json",
3
- "include": ["./tests", "./src/**/*.test.ts"],
4
- "compilerOptions": {
5
- "noImplicitAny": true,
6
- "rootDir": "./",
7
- },
8
- }