@atproto/lex-json 0.0.14 → 0.0.16

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/src/lex-json.ts CHANGED
@@ -5,8 +5,9 @@ import {
5
5
  LexMap,
6
6
  LexValue,
7
7
  isCid,
8
+ utf8FromBytes,
8
9
  } from '@atproto/lex-data'
9
- import { parseBlobRef } from './blob.js'
10
+ import { parseTypedBlobRef } from './blob.js'
10
11
  import { encodeLexBytes, parseLexBytes } from './bytes.js'
11
12
  import { JsonObject, JsonValue } from './json.js'
12
13
  import { encodeLexLink, parseLexLink } from './link.js'
@@ -99,22 +100,26 @@ export function lexParse<T extends LexValue = LexValue>(
99
100
  input: string,
100
101
  options: LexParseOptions = { strict: false },
101
102
  ): T {
102
- return JSON.parse(input, function (key: string, value: JsonValue): LexValue {
103
- switch (typeof value) {
104
- case 'object':
105
- if (value === null) return null
106
- if (Array.isArray(value)) return value
107
- return parseSpecialJsonObject(value, options) ?? value
108
- case 'number':
109
- if (Number.isSafeInteger(value)) return value
110
- if (options.strict) {
111
- throw new TypeError(`Invalid non-integer number: ${value}`)
112
- }
113
- // fallthrough
114
- default:
115
- return value
116
- }
117
- })
103
+ // @NOTE see ./lex-json.bench.ts for performance comparison of implementation
104
+ // that uses a reviver function in JSON.parse vs. the current implementation.
105
+ return jsonToLex(JSON.parse(input), options) as T
106
+ }
107
+
108
+ /**
109
+ * Parses a JSON string from a byte array into Lex values.
110
+ */
111
+ export function lexParseJsonBytes(
112
+ bytes: Uint8Array,
113
+ options?: LexParseOptions,
114
+ ): LexValue {
115
+ // @NOTE see ./json-bytes-decoder.bench.ts for performance comparison of
116
+ // implementation that uses a decoder class that operates directly on bytes
117
+ // vs. the current implementation that first decodes bytes to string and then
118
+ // parses JSON. For more common cases, it seems that the trivial
119
+ // implementation works better than the decoder based solution, while having a
120
+ // small overhead for slower cases (~2% difference). Because of this, we keep
121
+ // the trivial implementation:
122
+ return lexParse(utf8FromBytes(bytes), options)
118
123
  }
119
124
 
120
125
  /**
@@ -161,10 +166,8 @@ export function jsonToLex(
161
166
  }
162
167
  case 'number':
163
168
  if (Number.isSafeInteger(value)) return value
164
- if (options.strict) {
165
- throw new TypeError(`Invalid non-integer number: ${value}`)
166
- }
167
- // fallthrough
169
+ if (options.strict === false) return value
170
+ throw new TypeError(`Invalid non-integer number: ${value}`)
168
171
  case 'boolean':
169
172
  case 'string':
170
173
  return value
@@ -307,7 +310,10 @@ function encodeLexMap(input: LexMap): JsonObject {
307
310
  return copy ?? (input as JsonObject)
308
311
  }
309
312
 
310
- function parseSpecialJsonObject(
313
+ /**
314
+ * @internal
315
+ */
316
+ export function parseSpecialJsonObject(
311
317
  input: LexMap,
312
318
  options: LexParseOptions,
313
319
  ): Cid | Uint8Array | BlobRef | undefined {
@@ -328,7 +334,7 @@ function parseSpecialJsonObject(
328
334
  // the strict option is enabled.
329
335
  if (options.strict) {
330
336
  if (input.$type === 'blob') {
331
- const blob = parseBlobRef(input, options)
337
+ const blob = parseTypedBlobRef(input, options)
332
338
  if (blob) return blob
333
339
  throw new TypeError(`Invalid blob object`)
334
340
  } else if (typeof input.$type !== 'string') {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "extends": ["../../../tsconfig/isomorphic.json"],
3
3
  "include": ["./src"],
4
- "exclude": ["**/*.test.ts"],
4
+ "exclude": ["**/*.bench.ts", "**/*.test.ts"],
5
5
  "compilerOptions": {
6
6
  "noImplicitAny": true,
7
7
  "importHelpers": true,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "extends": "../../../tsconfig/vitest.json",
3
- "include": ["./tests", "./src/**/*.test.ts"],
3
+ "include": ["./tests", "./src/**/*.bench.ts", "./src/**/*.test.ts"],
4
4
  "compilerOptions": {
5
5
  "noImplicitAny": true,
6
6
  "rootDir": "./",