@atproto/lex-json 0.0.10 → 0.0.12
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/blob.d.ts +34 -0
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +34 -0
- package/dist/blob.js.map +1 -1
- package/dist/bytes.d.ts +44 -3
- package/dist/bytes.d.ts.map +1 -1
- package/dist/bytes.js +50 -2
- package/dist/bytes.js.map +1 -1
- package/dist/json.d.ts +43 -0
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js.map +1 -1
- package/dist/lex-json.d.ts +127 -2
- package/dist/lex-json.d.ts.map +1 -1
- package/dist/lex-json.js +114 -0
- package/dist/lex-json.js.map +1 -1
- package/dist/link.d.ts +46 -0
- package/dist/link.d.ts.map +1 -1
- package/dist/link.js +21 -4
- package/dist/link.js.map +1 -1
- package/package.json +3 -3
- package/src/blob.ts +34 -0
- package/src/bytes.test.ts +55 -0
- package/src/bytes.ts +52 -5
- package/src/json.ts +45 -0
- package/src/lex-json.test.ts +30 -15
- package/src/lex-json.ts +127 -2
- package/src/link.ts +50 -4
package/dist/lex-json.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lex-json.js","sourceRoot":"","sources":["../src/lex-json.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BlobRef,\n Cid,\n LexArray,\n LexMap,\n LexValue,\n isCid,\n} from '@atproto/lex-data'\nimport { parseBlobRef } from './blob.js'\nimport { encodeLexBytes, parseLexBytes } from './bytes.js'\nimport { JsonObject, JsonValue } from './json.js'\nimport { encodeLexLink, parseLexLink } from './link.js'\n\nexport function lexStringify(input: LexValue): string {\n // @NOTE Because of the way the \"replacer\" works in JSON.stringify, it's\n // simpler to convert Lex to JSON first rather than trying to do it\n // on-the-fly.\n return JSON.stringify(lexToJson(input))\n}\n\nexport type LexParseOptions = {\n /**\n * Forbids the presence of invalid Lex values (e.g. non-integer numbers,\n * malformed $link, $bytes, blob objects, etc.)\n */\n strict?: boolean\n}\n\nexport function lexParse<T extends LexValue = LexValue>(\n input: string,\n options: LexParseOptions = { strict: false },\n): T {\n return JSON.parse(input, function (key: string, value: JsonValue): LexValue {\n switch (typeof value) {\n case 'object':\n if (value === null) return null\n if (Array.isArray(value)) return value\n return parseSpecialJsonObject(value, options) ?? value\n case 'number':\n if (Number.isSafeInteger(value)) return value\n if (options.strict) {\n throw new TypeError(`Invalid non-integer number: ${value}`)\n }\n // fallthrough\n default:\n return value\n }\n })\n}\n\nexport function jsonToLex(\n value: JsonValue,\n options: LexParseOptions = { strict: false },\n): LexValue {\n switch (typeof value) {\n case 'object': {\n if (value === null) return null\n if (Array.isArray(value)) return jsonArrayToLex(value, options)\n return (\n parseSpecialJsonObject(value, options) ??\n jsonObjectToLexMap(value, options)\n )\n }\n case 'number':\n if (Number.isSafeInteger(value)) return value\n if (options.strict) {\n throw new TypeError(`Invalid non-integer number: ${value}`)\n }\n // fallthrough\n case 'boolean':\n case 'string':\n return value\n default:\n throw new TypeError(`Invalid JSON value: ${typeof value}`)\n }\n}\n\nfunction jsonArrayToLex(\n input: JsonValue[],\n options: LexParseOptions,\n): LexValue[] {\n // Lazily copy value\n let copy: LexValue[] | undefined\n for (let i = 0; i < input.length; i++) {\n const inputItem = input[i]\n const item = jsonToLex(inputItem, options)\n if (item !== inputItem) {\n copy ??= Array.from(input)\n copy[i] = item\n }\n }\n return copy ?? input\n}\n\nfunction jsonObjectToLexMap(\n input: JsonObject,\n options: LexParseOptions,\n): LexMap {\n // Lazily copy value\n let copy: LexMap | undefined = undefined\n for (const [key, jsonValue] of Object.entries(input)) {\n // Prevent prototype pollution\n if (key === '__proto__') {\n throw new TypeError('Invalid key: __proto__')\n }\n\n // Ignore (strip) undefined values\n if (jsonValue === undefined) {\n copy ??= { ...input }\n delete copy[key]\n continue\n }\n\n const value = jsonToLex(jsonValue!, options)\n if (value !== jsonValue) {\n copy ??= { ...input }\n copy[key] = value\n }\n }\n return copy ?? input\n}\n\nexport function lexToJson(value: LexValue): JsonValue {\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return value\n } else if (Array.isArray(value)) {\n return lexArrayToJson(value)\n } else if (isCid(value)) {\n return encodeLexLink(value)\n } else if (ArrayBuffer.isView(value)) {\n return encodeLexBytes(value)\n } else {\n return encodeLexMap(value)\n }\n case 'boolean':\n case 'string':\n case 'number':\n return value\n default:\n throw new TypeError(`Invalid Lex value: ${typeof value}`)\n }\n}\n\nfunction lexArrayToJson(input: LexArray): JsonValue[] {\n // Lazily copy value\n let copy: JsonValue[] | undefined\n for (let i = 0; i < input.length; i++) {\n const inputItem = input[i]\n const item = lexToJson(inputItem)\n if (item !== inputItem) {\n copy ??= Array.from(input) as JsonValue[]\n copy[i] = item\n }\n }\n return copy ?? (input as JsonValue[])\n}\n\nfunction encodeLexMap(input: LexMap): JsonObject {\n // Lazily copy value\n let copy: JsonObject | undefined = undefined\n for (const [key, lexValue] of Object.entries(input)) {\n // Prevent prototype pollution\n if (key === '__proto__') {\n throw new TypeError('Invalid key: __proto__')\n }\n\n // Ignore (strip) undefined values\n if (lexValue === undefined) {\n copy ??= { ...input } as JsonObject\n delete copy[key]\n continue\n }\n\n const jsonValue = lexToJson(lexValue!)\n if (jsonValue !== lexValue) {\n copy ??= { ...input } as JsonObject\n copy[key] = jsonValue\n }\n }\n return copy ?? (input as JsonObject)\n}\n\nfunction parseSpecialJsonObject(\n input: LexMap,\n options: LexParseOptions,\n): Cid | Uint8Array | BlobRef | undefined {\n // Hot path: use hints to avoid parsing when possible\n\n if (input.$link !== undefined) {\n const cid = parseLexLink(input)\n if (cid) return cid\n if (options.strict) throw new TypeError(`Invalid $link object`)\n } else if (input.$bytes !== undefined) {\n const bytes = parseLexBytes(input)\n if (bytes) return bytes\n if (options.strict) throw new TypeError(`Invalid $bytes object`)\n } else if (input.$type !== undefined) {\n // @NOTE Since blobs are \"just\" regular lex objects with a special shape,\n // and because an object that does not conform to the blob shape would still\n // result in undefined being returned, we only attempt to parse blobs when\n // the strict option is enabled.\n if (options.strict) {\n if (input.$type === 'blob') {\n const blob = parseBlobRef(input, options)\n if (blob) return blob\n throw new TypeError(`Invalid blob object`)\n } else if (typeof input.$type !== 'string') {\n throw new TypeError(`Invalid $type property (${typeof input.$type})`)\n } else if (input.$type.length === 0) {\n throw new TypeError(`Empty $type property`)\n }\n }\n }\n\n // @NOTE We ignore legacy blob representation here. They can be handled at the\n // application level if needed.\n\n return undefined\n}\n"]}
|
|
1
|
+
{"version":3,"file":"lex-json.js","sourceRoot":"","sources":["../src/lex-json.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BlobRef,\n Cid,\n LexArray,\n LexMap,\n LexValue,\n isCid,\n} from '@atproto/lex-data'\nimport { parseBlobRef } from './blob.js'\nimport { encodeLexBytes, parseLexBytes } from './bytes.js'\nimport { JsonObject, JsonValue } from './json.js'\nimport { encodeLexLink, parseLexLink } from './link.js'\n\n/**\n * Serialize a Lex value to a JSON string.\n *\n * This function serializes AT Protocol data model values to JSON, automatically\n * encoding special types:\n * - `Cid` instances are encoded as `{$link: string}`\n * - `Uint8Array` instances are encoded as `{$bytes: string}` (base64)\n *\n * @param input - The Lex value to stringify\n * @returns A JSON string representation of the value\n *\n * @example\n * ```typescript\n * import { lexStringify } from '@atproto/lex'\n *\n * // Stringify with CID and bytes encoding\n * const json = lexStringify({\n * ref: someCid,\n * data: new Uint8Array([72, 101, 108, 108, 111])\n * })\n * // json is '{\"ref\":{\"$link\":\"bafyrei...\"},\"data\":{\"$bytes\":\"SGVsbG8=\"}}'\n * ```\n */\nexport function lexStringify(input: LexValue): string {\n // @NOTE Because of the way the \"replacer\" works in JSON.stringify, it's\n // simpler to convert Lex to JSON first rather than trying to do it\n // on-the-fly.\n return JSON.stringify(lexToJson(input))\n}\n\n/**\n * Options for parsing JSON to Lex values.\n */\nexport type LexParseOptions = {\n /**\n * When enabled, forbids the presence of invalid Lex values such as:\n * - Non-integer numbers (only safe integers are valid in the Lex data model)\n * - Malformed `$link` objects\n * - Malformed `$bytes` objects\n * - Objects with invalid or empty `$type` properties\n * - Invalid {@link BlobRef} (`$type: 'blob'`) objects\n *\n * When disabled (default), invalid special objects are left as plain objects.\n *\n * @default false\n */\n strict?: boolean\n}\n\n/**\n * Parses a JSON string into Lex values.\n *\n * This function parses JSON and automatically decodes AT Protocol special types:\n * - `{$link: string}` objects are decoded to `Cid` instances\n * - `{$bytes: string}` objects are decoded to `Uint8Array` instances\n * - `{$type: 'blob'}` objects are validated\n *\n * @typeParam T - Type cast for the resulting Lex value. Use when you want to specify the expected structure of the parsed data.\n * @param input - The JSON string to parse\n * @param options - Parsing options (e.g., strict mode)\n * @returns The parsed Lex value\n * @throws {SyntaxError} If the input is not valid JSON\n * @throws {TypeError} If strict mode is enabled and invalid Lex values are found\n *\n * @example\n * ```typescript\n * import { lexParse } from '@atproto/lex'\n *\n * // Parse JSON with $link and $bytes decoding\n * const parsed = lexParse<{\n * ref: Cid\n * data: Uint8Array\n * }>(`{\n * \"ref\": { \"$link\": \"bafyrei...\" },\n * \"data\": { \"$bytes\": \"SGVsbG8sIHdvcmxkIQ==\" }\n * }`)\n *\n * // Parse a single CID\n * const someCid = lexParse<Cid>('{\"$link\": \"bafyrei...\"}')\n *\n * // Parse binary data\n * const someBytes = lexParse<Uint8Array>('{\"$bytes\": \"SGVsbG8sIHdvcmxkIQ==\"}')\n * ```\n */\nexport function lexParse<T extends LexValue = LexValue>(\n input: string,\n options: LexParseOptions = { strict: false },\n): T {\n return JSON.parse(input, function (key: string, value: JsonValue): LexValue {\n switch (typeof value) {\n case 'object':\n if (value === null) return null\n if (Array.isArray(value)) return value\n return parseSpecialJsonObject(value, options) ?? value\n case 'number':\n if (Number.isSafeInteger(value)) return value\n if (options.strict) {\n throw new TypeError(`Invalid non-integer number: ${value}`)\n }\n // fallthrough\n default:\n return value\n }\n })\n}\n\n/**\n * Converts a parsed JSON representation of Lexicon value to a {@link LexValue}.\n *\n * This function transforms already-parsed JSON objects into Lex values by\n * decoding AT Protocol special types:\n * - `{$link: string}` objects are converted to `Cid` instances\n * - `{$bytes: string}` objects are converted to `Uint8Array` instances\n *\n * Use this when you have a JavaScript object (e.g., from `JSON.parse()`) and\n * need to convert it to the Lex data model. For parsing JSON strings directly,\n * use {@link lexParse} instead.\n *\n * @param value - The JSON value to convert\n * @param options - Parsing options (e.g., strict mode)\n * @returns The converted Lex value\n * @throws {TypeError} If strict mode is enabled and invalid Lex values are found\n * @throws {TypeError} If the value contains unsupported types (e.g., undefined at top level)\n *\n * @example\n * ```typescript\n * import { jsonToLex } from '@atproto/lex'\n *\n * // Convert parsed JSON to Lex values\n * const lex = jsonToLex({\n * ref: { $link: 'bafyrei...' }, // Converted to Cid\n * data: { $bytes: 'SGVsbG8sIHdvcmxkIQ==' } // Converted to Uint8Array\n * })\n * ```\n */\nexport function jsonToLex(\n value: JsonValue,\n options: LexParseOptions = { strict: false },\n): LexValue {\n switch (typeof value) {\n case 'object': {\n if (value === null) return null\n if (Array.isArray(value)) return jsonArrayToLex(value, options)\n return (\n parseSpecialJsonObject(value, options) ??\n jsonObjectToLexMap(value, options)\n )\n }\n case 'number':\n if (Number.isSafeInteger(value)) return value\n if (options.strict) {\n throw new TypeError(`Invalid non-integer number: ${value}`)\n }\n // fallthrough\n case 'boolean':\n case 'string':\n return value\n default:\n throw new TypeError(`Invalid JSON value: ${typeof value}`)\n }\n}\n\nfunction jsonArrayToLex(\n input: JsonValue[],\n options: LexParseOptions,\n): LexValue[] {\n // Lazily copy value\n let copy: LexValue[] | undefined\n for (let i = 0; i < input.length; i++) {\n const inputItem = input[i]\n const item = jsonToLex(inputItem, options)\n if (item !== inputItem) {\n copy ??= Array.from(input)\n copy[i] = item\n }\n }\n return copy ?? input\n}\n\nfunction jsonObjectToLexMap(\n input: JsonObject,\n options: LexParseOptions,\n): LexMap {\n // Lazily copy value\n let copy: LexMap | undefined = undefined\n for (const [key, jsonValue] of Object.entries(input)) {\n // Prevent prototype pollution\n if (key === '__proto__') {\n throw new TypeError('Invalid key: __proto__')\n }\n\n // Ignore (strip) undefined values\n if (jsonValue === undefined) {\n copy ??= { ...input }\n delete copy[key]\n continue\n }\n\n const value = jsonToLex(jsonValue!, options)\n if (value !== jsonValue) {\n copy ??= { ...input }\n copy[key] = value\n }\n }\n return copy ?? input\n}\n\n/**\n * Converts a Lex value to a JSON-compatible value.\n *\n * This function transforms Lex data model values into plain JavaScript objects\n * suitable for JSON serialization:\n * - `Cid` instances are converted to `{$link: string}` objects\n * - `Uint8Array` instances are converted to `{$bytes: string}` objects (base64)\n *\n * Use this when you need to convert Lex values to plain objects (e.g., for\n * custom serialization or inspection). For direct JSON string output, use\n * {@link lexStringify} instead.\n *\n * @param value - The Lex value to convert\n * @returns The JSON-compatible value\n * @throws {TypeError} If the value contains unsupported types\n *\n * @example\n * ```typescript\n * import { lexToJson } from '@atproto/lex'\n *\n * // Convert Lex values to JSON-compatible objects\n * const obj = lexToJson({\n * ref: someCid, // Converted to { $link: string }\n * data: someBytes // Converted to { $bytes: string }\n * })\n * ```\n */\nexport function lexToJson(value: LexValue): JsonValue {\n switch (typeof value) {\n case 'object':\n if (value === null) {\n return value\n } else if (Array.isArray(value)) {\n return lexArrayToJson(value)\n } else if (isCid(value)) {\n return encodeLexLink(value)\n } else if (ArrayBuffer.isView(value)) {\n return encodeLexBytes(value)\n } else {\n return encodeLexMap(value)\n }\n case 'boolean':\n case 'string':\n case 'number':\n return value\n default:\n throw new TypeError(`Invalid Lex value: ${typeof value}`)\n }\n}\n\nfunction lexArrayToJson(input: LexArray): JsonValue[] {\n // Lazily copy value\n let copy: JsonValue[] | undefined\n for (let i = 0; i < input.length; i++) {\n const inputItem = input[i]\n const item = lexToJson(inputItem)\n if (item !== inputItem) {\n copy ??= Array.from(input) as JsonValue[]\n copy[i] = item\n }\n }\n return copy ?? (input as JsonValue[])\n}\n\nfunction encodeLexMap(input: LexMap): JsonObject {\n // Lazily copy value\n let copy: JsonObject | undefined = undefined\n for (const [key, lexValue] of Object.entries(input)) {\n // Prevent prototype pollution\n if (key === '__proto__') {\n throw new TypeError('Invalid key: __proto__')\n }\n\n // Ignore (strip) undefined values\n if (lexValue === undefined) {\n copy ??= { ...input } as JsonObject\n delete copy[key]\n continue\n }\n\n const jsonValue = lexToJson(lexValue!)\n if (jsonValue !== lexValue) {\n copy ??= { ...input } as JsonObject\n copy[key] = jsonValue\n }\n }\n return copy ?? (input as JsonObject)\n}\n\nfunction parseSpecialJsonObject(\n input: LexMap,\n options: LexParseOptions,\n): Cid | Uint8Array | BlobRef | undefined {\n // Hot path: use hints to avoid parsing when possible\n\n if (input.$link !== undefined) {\n const cid = parseLexLink(input)\n if (cid) return cid\n if (options.strict) throw new TypeError(`Invalid $link object`)\n } else if (input.$bytes !== undefined) {\n const bytes = parseLexBytes(input)\n if (bytes) return bytes\n if (options.strict) throw new TypeError(`Invalid $bytes object`)\n } else if (input.$type !== undefined) {\n // @NOTE Since blobs are \"just\" regular lex objects with a special shape,\n // and because an object that does not conform to the blob shape would still\n // result in undefined being returned, we only attempt to parse blobs when\n // the strict option is enabled.\n if (options.strict) {\n if (input.$type === 'blob') {\n const blob = parseBlobRef(input, options)\n if (blob) return blob\n throw new TypeError(`Invalid blob object`)\n } else if (typeof input.$type !== 'string') {\n throw new TypeError(`Invalid $type property (${typeof input.$type})`)\n } else if (input.$type.length === 0) {\n throw new TypeError(`Empty $type property`)\n }\n }\n }\n\n // @NOTE We ignore legacy blob representation here. They can be handled at the\n // application level if needed.\n\n return undefined\n}\n"]}
|
package/dist/link.d.ts
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
import { CheckCidOptions, Cid, InferCheckedCid } from '@atproto/lex-data';
|
|
2
2
|
import { JsonValue } from './json.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parses a `{$link: string}` JSON object into a {@link Cid} instance.
|
|
5
|
+
*
|
|
6
|
+
* In the AT Protocol data model, CID references are represented in JSON as an
|
|
7
|
+
* object with a single `$link` property containing a base32-encoded CID string,
|
|
8
|
+
* prefixed with "b". This function decodes that representation into a `Cid`
|
|
9
|
+
* object.
|
|
10
|
+
*
|
|
11
|
+
* @param input - An object potentially containing a `{$link: string}` property
|
|
12
|
+
* @param options - Optional CID validation options
|
|
13
|
+
* @returns The parsed {@link Cid} if the input is a valid `$link` object,
|
|
14
|
+
* or `undefined` if the input is not a valid `$link` representation
|
|
15
|
+
* @throws {TypeError} If `$link` is present but is not a valid CID string
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Parse a $link object to Cid
|
|
20
|
+
* const cid = parseLexLink({ $link: 'bafyreib2rxk3rybloqtqwbo' })
|
|
21
|
+
* // cid is a Cid instance
|
|
22
|
+
*
|
|
23
|
+
* // Returns undefined for non-$link objects
|
|
24
|
+
* const result = parseLexLink({ foo: 'bar' })
|
|
25
|
+
* // result is undefined
|
|
26
|
+
*
|
|
27
|
+
* // Returns undefined for objects with extra properties
|
|
28
|
+
* const invalid = parseLexLink({ $link: 'bafyrei...', extra: true })
|
|
29
|
+
* // invalid is undefined
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
3
32
|
export declare function parseLexLink<TOptions extends CheckCidOptions>(input: undefined | Record<string, unknown>, options: TOptions): InferCheckedCid<TOptions> | undefined;
|
|
4
33
|
export declare function parseLexLink(input?: Record<string, unknown>, options?: CheckCidOptions): Cid | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Encodes a {@link Cid} instance into a `{$link: string}` JSON representation.
|
|
36
|
+
*
|
|
37
|
+
* In the AT Protocol data model, CID references are represented in JSON as an
|
|
38
|
+
* object with a single `$link` property containing a base32-encoded CID string,
|
|
39
|
+
* prefixed with "b". This function performs that encoding.
|
|
40
|
+
*
|
|
41
|
+
* @param cid - The CID to encode
|
|
42
|
+
* @returns An object with a `$link` property containing the string representation of the CID
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const cid = CID.parse('bafyreib2rxk3rybloqtqwbo')
|
|
47
|
+
* const encoded = encodeLexLink(cid)
|
|
48
|
+
* // encoded is { $link: 'bafyreib2rxk3rybloqtqwbo' }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
5
51
|
export declare function encodeLexLink(cid: Cid): JsonValue;
|
|
6
52
|
//# sourceMappingURL=link.d.ts.map
|
package/dist/link.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,GAAG,EACH,eAAe,EAEhB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,wBAAgB,YAAY,CAAC,QAAQ,SAAS,eAAe,EAC3D,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1C,OAAO,EAAE,QAAQ,GAChB,eAAe,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;AACxC,wBAAgB,YAAY,CAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,eAAe,GACxB,GAAG,GAAG,SAAS,CAAA;AAqClB,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAEjD"}
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,GAAG,EACH,eAAe,EAEhB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,QAAQ,SAAS,eAAe,EAC3D,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1C,OAAO,EAAE,QAAQ,GAChB,eAAe,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;AACxC,wBAAgB,YAAY,CAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,eAAe,GACxB,GAAG,GAAG,SAAS,CAAA;AAqClB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,CAEjD"}
|
package/dist/link.js
CHANGED
|
@@ -14,22 +14,39 @@ function parseLexLink(input, options) {
|
|
|
14
14
|
}
|
|
15
15
|
const { $link } = input;
|
|
16
16
|
if (typeof $link !== 'string') {
|
|
17
|
-
|
|
17
|
+
return undefined;
|
|
18
18
|
}
|
|
19
19
|
if ($link.length === 0) {
|
|
20
|
-
|
|
20
|
+
return undefined;
|
|
21
21
|
}
|
|
22
22
|
// Arbitrary limit to prevent DoS via extremely long CIDs
|
|
23
23
|
if ($link.length > 2048) {
|
|
24
|
-
|
|
24
|
+
return undefined;
|
|
25
25
|
}
|
|
26
26
|
try {
|
|
27
27
|
return (0, lex_data_1.parseCid)($link, options);
|
|
28
28
|
}
|
|
29
29
|
catch (cause) {
|
|
30
|
-
|
|
30
|
+
return undefined;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Encodes a {@link Cid} instance into a `{$link: string}` JSON representation.
|
|
35
|
+
*
|
|
36
|
+
* In the AT Protocol data model, CID references are represented in JSON as an
|
|
37
|
+
* object with a single `$link` property containing a base32-encoded CID string,
|
|
38
|
+
* prefixed with "b". This function performs that encoding.
|
|
39
|
+
*
|
|
40
|
+
* @param cid - The CID to encode
|
|
41
|
+
* @returns An object with a `$link` property containing the string representation of the CID
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const cid = CID.parse('bafyreib2rxk3rybloqtqwbo')
|
|
46
|
+
* const encoded = encodeLexLink(cid)
|
|
47
|
+
* // encoded is { $link: 'bafyreib2rxk3rybloqtqwbo' }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
33
50
|
function encodeLexLink(cid) {
|
|
34
51
|
return { $link: cid.toString() };
|
|
35
52
|
}
|
package/dist/link.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":";;AA6CA,oCAkCC;AAmBD,sCAEC;AApGD,gDAK0B;AAwC1B,SAAgB,YAAY,CAC1B,KAA+B,EAC/B,OAAyB;IAEzB,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,OAAO,SAAS,CAAA;QAClB,CAAC;IACH,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;IAEvB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,yDAAyD;IACzD,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACxB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAA,mBAAQ,EAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,aAAa,CAAC,GAAQ;IACpC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAA;AAClC,CAAC","sourcesContent":["import {\n CheckCidOptions,\n Cid,\n InferCheckedCid,\n parseCid,\n} from '@atproto/lex-data'\nimport { JsonValue } from './json.js'\n\n/**\n * Parses a `{$link: string}` JSON object into a {@link Cid} instance.\n *\n * In the AT Protocol data model, CID references are represented in JSON as an\n * object with a single `$link` property containing a base32-encoded CID string,\n * prefixed with \"b\". This function decodes that representation into a `Cid`\n * object.\n *\n * @param input - An object potentially containing a `{$link: string}` property\n * @param options - Optional CID validation options\n * @returns The parsed {@link Cid} if the input is a valid `$link` object,\n * or `undefined` if the input is not a valid `$link` representation\n * @throws {TypeError} If `$link` is present but is not a valid CID string\n *\n * @example\n * ```typescript\n * // Parse a $link object to Cid\n * const cid = parseLexLink({ $link: 'bafyreib2rxk3rybloqtqwbo' })\n * // cid is a Cid instance\n *\n * // Returns undefined for non-$link objects\n * const result = parseLexLink({ foo: 'bar' })\n * // result is undefined\n *\n * // Returns undefined for objects with extra properties\n * const invalid = parseLexLink({ $link: 'bafyrei...', extra: true })\n * // invalid is undefined\n * ```\n */\nexport function parseLexLink<TOptions extends CheckCidOptions>(\n input: undefined | Record<string, unknown>,\n options: TOptions,\n): InferCheckedCid<TOptions> | undefined\nexport function parseLexLink(\n input?: Record<string, unknown>,\n options?: CheckCidOptions,\n): Cid | undefined\nexport function parseLexLink(\n input?: Record<string, unknown>,\n options?: CheckCidOptions,\n): Cid | undefined {\n if (!input || !('$link' in input)) {\n return undefined\n }\n\n for (const key in input) {\n if (key !== '$link') {\n return undefined\n }\n }\n\n const { $link } = input\n\n if (typeof $link !== 'string') {\n return undefined\n }\n\n if ($link.length === 0) {\n return undefined\n }\n\n // Arbitrary limit to prevent DoS via extremely long CIDs\n if ($link.length > 2048) {\n return undefined\n }\n\n try {\n return parseCid($link, options)\n } catch (cause) {\n return undefined\n }\n}\n\n/**\n * Encodes a {@link Cid} instance into a `{$link: string}` JSON representation.\n *\n * In the AT Protocol data model, CID references are represented in JSON as an\n * object with a single `$link` property containing a base32-encoded CID string,\n * prefixed with \"b\". This function performs that encoding.\n *\n * @param cid - The CID to encode\n * @returns An object with a `$link` property containing the string representation of the CID\n *\n * @example\n * ```typescript\n * const cid = CID.parse('bafyreib2rxk3rybloqtqwbo')\n * const encoded = encodeLexLink(cid)\n * // encoded is { $link: 'bafyreib2rxk3rybloqtqwbo' }\n * ```\n */\nexport function encodeLexLink(cid: Cid): JsonValue {\n return { $link: cid.toString() }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lex-json",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Lexicon encoding utilities for AT Lexicon data in JSON format",
|
|
6
6
|
"keywords": [
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"types": "./dist/index.d.ts",
|
|
35
35
|
"browser": "./dist/index.js",
|
|
36
36
|
"import": "./dist/index.js",
|
|
37
|
-
"
|
|
37
|
+
"default": "./dist/index.js"
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"tslib": "^2.8.1",
|
|
42
|
-
"@atproto/lex-data": "^0.0.
|
|
42
|
+
"@atproto/lex-data": "^0.0.12"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"vitest": "^4.0.16"
|
package/src/blob.ts
CHANGED
|
@@ -6,6 +6,40 @@ import {
|
|
|
6
6
|
} from '@atproto/lex-data'
|
|
7
7
|
import { parseLexLink } from './link.js'
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Parses a blob reference from a JSON object.
|
|
11
|
+
*
|
|
12
|
+
* In the AT Protocol, blobs are referenced using a specific object structure
|
|
13
|
+
* with `$type: 'blob'`, a `ref` property containing a CID link, and metadata
|
|
14
|
+
* like `mimeType` and `size`. This function validates and parses such objects
|
|
15
|
+
* into `BlobRef` instances.
|
|
16
|
+
*
|
|
17
|
+
* The function handles both cases where the `ref` property is:
|
|
18
|
+
* - A `{$link: string}` object (when parsing from JSON)
|
|
19
|
+
* - Already a `Cid` instance (when the parent object has been partially converted)
|
|
20
|
+
*
|
|
21
|
+
* @param input - A Lex map potentially representing a blob reference
|
|
22
|
+
* @param options - Optional blob reference validation options
|
|
23
|
+
* @returns The parsed `BlobRef` if the input is a valid blob reference,
|
|
24
|
+
* or `undefined` if the input is not a valid blob representation
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // Parse a blob reference from JSON
|
|
29
|
+
* const blobRef = parseBlobRef({
|
|
30
|
+
* $type: 'blob',
|
|
31
|
+
* ref: { $link: 'bafyreib2rxk3rybloqtqwbo' },
|
|
32
|
+
* mimeType: 'image/png',
|
|
33
|
+
* size: 12345
|
|
34
|
+
* })
|
|
35
|
+
*
|
|
36
|
+
* // blobRef.ref is a Cid instance
|
|
37
|
+
*
|
|
38
|
+
* // Returns undefined for non-blob objects
|
|
39
|
+
* const result = parseBlobRef({ foo: 'bar' })
|
|
40
|
+
* // result is undefined
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
9
43
|
export function parseBlobRef(
|
|
10
44
|
input: LexMap,
|
|
11
45
|
options?: BlobRefCheckOptions,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { encodeLexBytes, parseLexBytes } from './bytes.js'
|
|
3
|
+
|
|
4
|
+
describe(parseLexBytes, () => {
|
|
5
|
+
it('parses valid $bytes object', () => {
|
|
6
|
+
const bytes = Buffer.from('Hello, world!')
|
|
7
|
+
const input = { $bytes: bytes.toString('base64') }
|
|
8
|
+
const result = parseLexBytes(input)
|
|
9
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
10
|
+
expect(new TextDecoder().decode(result!)).toBe('Hello, world!')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('parses valid $bytes object (without padding)', () => {
|
|
14
|
+
const bytes = Buffer.from('Hello, world!')
|
|
15
|
+
const input = { $bytes: bytes.toString('base64').replace(/=*$/, '') }
|
|
16
|
+
const result = parseLexBytes(input)
|
|
17
|
+
expect(result).toBeInstanceOf(Uint8Array)
|
|
18
|
+
expect(new TextDecoder().decode(result!)).toBe('Hello, world!')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('returns undefined for non-$bytes object', () => {
|
|
22
|
+
const input = { foo: 'bar' }
|
|
23
|
+
const result = parseLexBytes(input)
|
|
24
|
+
expect(result).toBeUndefined()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('returns undefined for $bytes with non-string value', () => {
|
|
28
|
+
const input = { $bytes: 12345 }
|
|
29
|
+
const result = parseLexBytes(input)
|
|
30
|
+
expect(result).toBeUndefined()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('returns undefined for $bytes with extra properties', () => {
|
|
34
|
+
const bytes = Buffer.from('Hello, world!')
|
|
35
|
+
const input = { $bytes: bytes.toString('base64'), extra: true }
|
|
36
|
+
const result = parseLexBytes(input)
|
|
37
|
+
expect(result).toBeUndefined()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('returns undefined for invalid base64 string', () => {
|
|
41
|
+
const input = { $bytes: '!!!invalid-base64!!!' }
|
|
42
|
+
const result = parseLexBytes(input)
|
|
43
|
+
expect(result).toBeUndefined()
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
describe(encodeLexBytes, () => {
|
|
48
|
+
it('encodes Uint8Array to $bytes object', () => {
|
|
49
|
+
const bytes = Buffer.from('Hello, world!')
|
|
50
|
+
const result = encodeLexBytes(bytes)
|
|
51
|
+
expect(result).toEqual({
|
|
52
|
+
$bytes: bytes.toString('base64').replace(/=*$/, ''),
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
})
|
package/src/bytes.ts
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
import { fromBase64, toBase64 } from '@atproto/lex-data'
|
|
2
2
|
import { JsonValue } from './json.js'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Parses a `{$bytes: string}` JSON object into a `Uint8Array`.
|
|
6
|
+
*
|
|
7
|
+
* In the AT Protocol data model, binary data is represented in JSON as an object
|
|
8
|
+
* with a single `$bytes` property containing a base64-encoded string. This function
|
|
9
|
+
* decodes that representation back into raw bytes.
|
|
10
|
+
*
|
|
11
|
+
* @param input - An object potentially containing a `$bytes` property
|
|
12
|
+
* @returns The decoded `Uint8Array` if the input is a valid `$bytes` object,
|
|
13
|
+
* or `undefined` if the input is not a valid `$bytes` representation
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Parse a $bytes object to Uint8Array
|
|
18
|
+
* const bytes = parseLexBytes({ $bytes: 'SGVsbG8sIHdvcmxkIQ==' })
|
|
19
|
+
* // bytes is Uint8Array containing "Hello, world!"
|
|
20
|
+
*
|
|
21
|
+
* // Returns undefined for non-$bytes objects
|
|
22
|
+
* const result = parseLexBytes({ foo: 'bar' })
|
|
23
|
+
* // result is undefined
|
|
24
|
+
*
|
|
25
|
+
* // Returns undefined for objects with extra properties
|
|
26
|
+
* const invalid = parseLexBytes({ $bytes: 'SGVsbG8=', extra: true })
|
|
27
|
+
* // invalid is undefined
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function parseLexBytes(
|
|
31
|
+
input?: Record<string, unknown>,
|
|
32
|
+
): Uint8Array | undefined {
|
|
7
33
|
if (!input || !('$bytes' in input)) {
|
|
8
34
|
return undefined
|
|
9
35
|
}
|
|
@@ -15,12 +41,33 @@ export function parseLexBytes(input?: {
|
|
|
15
41
|
}
|
|
16
42
|
|
|
17
43
|
if (typeof input.$bytes !== 'string') {
|
|
18
|
-
|
|
44
|
+
return undefined
|
|
19
45
|
}
|
|
20
46
|
|
|
21
|
-
|
|
47
|
+
try {
|
|
48
|
+
return fromBase64(input.$bytes)
|
|
49
|
+
} catch {
|
|
50
|
+
return undefined
|
|
51
|
+
}
|
|
22
52
|
}
|
|
23
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Encodes a `Uint8Array` into a `{$bytes: string}` JSON representation.
|
|
56
|
+
*
|
|
57
|
+
* In the AT Protocol data model, binary data is represented in JSON as an object
|
|
58
|
+
* with a single `$bytes` property containing a base64-encoded string. This function
|
|
59
|
+
* performs that encoding.
|
|
60
|
+
*
|
|
61
|
+
* @param bytes - The binary data to encode
|
|
62
|
+
* @returns An object with a `$bytes` property containing the base64-encoded data
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const bytes = new TextEncoder().encode('Hello, world!')
|
|
67
|
+
* const encoded = encodeLexBytes(bytes)
|
|
68
|
+
* // encoded is { $bytes: 'SGVsbG8sIHdvcmxkIQ==' }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
24
71
|
export function encodeLexBytes(bytes: Uint8Array): JsonValue {
|
|
25
72
|
return { $bytes: toBase64(bytes) }
|
|
26
73
|
}
|
package/src/json.ts
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primitive JSON values: string, number, boolean, or null.
|
|
3
|
+
*
|
|
4
|
+
* These are the scalar (non-composite) types that can appear in JSON data.
|
|
5
|
+
* In the context of the AT Protocol:
|
|
6
|
+
* - `string` - Text values, including special encoded types like `$link` and `$bytes`
|
|
7
|
+
* - `number` - Numeric values (note: Lex only supports safe integers)
|
|
8
|
+
* - `boolean` - True/false values
|
|
9
|
+
* - `null` - Explicit null values
|
|
10
|
+
*
|
|
11
|
+
* @see {@link JsonValue} for the complete JSON type including arrays and objects
|
|
12
|
+
*/
|
|
1
13
|
export type JsonScalar = number | string | boolean | null
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Any valid JSON value.
|
|
17
|
+
*
|
|
18
|
+
* This is a recursive type that represents the full JSON data model:
|
|
19
|
+
* - Scalars: string, number, boolean, null
|
|
20
|
+
* - Arrays: ordered lists of JSON values
|
|
21
|
+
* - Objects: string-keyed maps of JSON values
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const scalar: JsonValue = "hello"
|
|
26
|
+
* const array: JsonValue = [1, 2, 3]
|
|
27
|
+
* const object: JsonValue = { name: "Alice", age: 30 }
|
|
28
|
+
* const nested: JsonValue = { users: [{ name: "Bob" }] }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
2
31
|
export type JsonValue = JsonScalar | JsonValue[] | { [_ in string]?: JsonValue }
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A JSON object with string keys and JSON values.
|
|
35
|
+
*
|
|
36
|
+
* This type represents a plain JavaScript object that is valid JSON,
|
|
37
|
+
* where all keys are strings and all values are valid JSON values.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const obj: JsonObject = {
|
|
42
|
+
* name: "Alice",
|
|
43
|
+
* tags: ["admin", "user"],
|
|
44
|
+
* metadata: { created: "2024-01-01" }
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
3
48
|
export type JsonObject = { [_ in string]?: JsonValue }
|
package/src/lex-json.test.ts
CHANGED
|
@@ -362,7 +362,7 @@ export const invalidVectors: Array<{
|
|
|
362
362
|
},
|
|
363
363
|
]
|
|
364
364
|
|
|
365
|
-
describe(
|
|
365
|
+
describe(lexParse, () => {
|
|
366
366
|
describe('valid vectors', () => {
|
|
367
367
|
for (const { name, json, lex } of validVectors) {
|
|
368
368
|
describe(name, () => {
|
|
@@ -397,22 +397,32 @@ describe('lexParse', () => {
|
|
|
397
397
|
})
|
|
398
398
|
|
|
399
399
|
describe('invalid vectors', () => {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
).toThrow()
|
|
400
|
+
describe('strict mode', () => {
|
|
401
|
+
for (const { note, json } of invalidVectors) {
|
|
402
|
+
describe(note, () => {
|
|
403
|
+
it('throws when parsing malformed JSON', () => {
|
|
404
|
+
expect(() =>
|
|
405
|
+
lexParse(JSON.stringify(json), { strict: true }),
|
|
406
|
+
).toThrow()
|
|
407
|
+
})
|
|
409
408
|
})
|
|
410
|
-
}
|
|
411
|
-
}
|
|
409
|
+
}
|
|
410
|
+
})
|
|
411
|
+
describe('non-strict mode', () => {
|
|
412
|
+
for (const { note, json } of invalidVectors) {
|
|
413
|
+
describe(note, () => {
|
|
414
|
+
it('does not throws when parsing malformed JSON', () => {
|
|
415
|
+
expect(() =>
|
|
416
|
+
lexParse(JSON.stringify(json), { strict: false }),
|
|
417
|
+
).not.toThrow()
|
|
418
|
+
})
|
|
419
|
+
})
|
|
420
|
+
}
|
|
421
|
+
})
|
|
412
422
|
})
|
|
413
423
|
})
|
|
414
424
|
|
|
415
|
-
describe(
|
|
425
|
+
describe(lexStringify, () => {
|
|
416
426
|
describe('valid vectors', () => {
|
|
417
427
|
for (const { name, json, lex } of validVectors) {
|
|
418
428
|
describe(name, () => {
|
|
@@ -424,7 +434,7 @@ describe('lexStringify', () => {
|
|
|
424
434
|
})
|
|
425
435
|
})
|
|
426
436
|
|
|
427
|
-
describe(
|
|
437
|
+
describe(jsonToLex, () => {
|
|
428
438
|
describe('valid vectors', () => {
|
|
429
439
|
for (const { name, json, lex } of validVectors) {
|
|
430
440
|
describe(name, () => {
|
|
@@ -466,12 +476,16 @@ describe('jsonToLex', () => {
|
|
|
466
476
|
expect(() => jsonToLex({ nested: json }, { strict: true })).toThrow()
|
|
467
477
|
expect(() => jsonToLex([json], { strict: true })).toThrow()
|
|
468
478
|
})
|
|
479
|
+
|
|
480
|
+
it('does not throw in non-strict mode', () => {
|
|
481
|
+
expect(() => jsonToLex(json, { strict: false })).not.toThrow()
|
|
482
|
+
})
|
|
469
483
|
})
|
|
470
484
|
}
|
|
471
485
|
})
|
|
472
486
|
})
|
|
473
487
|
|
|
474
|
-
describe(
|
|
488
|
+
describe(lexToJson, () => {
|
|
475
489
|
describe('valid vectors', () => {
|
|
476
490
|
for (const { name, json, lex } of validVectors) {
|
|
477
491
|
describe(name, () => {
|
|
@@ -501,6 +515,7 @@ describe('lex > json > lex', () => {
|
|
|
501
515
|
for (const { name, lex } of validVectors) {
|
|
502
516
|
describe(name, () => {
|
|
503
517
|
it('converts lex to json', () => {
|
|
518
|
+
;('')
|
|
504
519
|
expect(lexEquals(jsonToLex(lexToJson(lex)), lex)).toBe(true)
|
|
505
520
|
expect(lexEquals(lex, jsonToLex(lexToJson(lex)))).toBe(true)
|
|
506
521
|
})
|