@atproto/lex-data 0.1.2 → 0.1.4

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/blob.d.ts +2 -2
  3. package/dist/blob.d.ts.map +1 -1
  4. package/dist/blob.js +1 -1
  5. package/dist/blob.js.map +1 -1
  6. package/dist/lex-equals.d.ts +1 -1
  7. package/dist/lex-equals.d.ts.map +1 -1
  8. package/dist/lex-equals.js.map +1 -1
  9. package/dist/lex.d.ts +1 -1
  10. package/dist/lex.d.ts.map +1 -1
  11. package/dist/lex.js.map +1 -1
  12. package/dist/lib/nodejs-buffer.js.map +1 -1
  13. package/dist/uint8array-from-base64.d.ts +1 -1
  14. package/dist/uint8array-from-base64.d.ts.map +1 -1
  15. package/dist/uint8array-from-base64.js.map +1 -1
  16. package/dist/uint8array-to-base64.d.ts +1 -1
  17. package/dist/uint8array-to-base64.d.ts.map +1 -1
  18. package/dist/uint8array-to-base64.js.map +1 -1
  19. package/dist/uint8array.d.ts +1 -1
  20. package/dist/uint8array.d.ts.map +1 -1
  21. package/dist/uint8array.js.map +1 -1
  22. package/dist/utf8-from-base64.d.ts +1 -1
  23. package/dist/utf8-from-base64.d.ts.map +1 -1
  24. package/dist/utf8-from-base64.js.map +1 -1
  25. package/dist/utf8-to-base64.d.ts +1 -1
  26. package/dist/utf8-to-base64.d.ts.map +1 -1
  27. package/dist/utf8-to-base64.js.map +1 -1
  28. package/dist/utf8.d.ts +1 -1
  29. package/dist/utf8.d.ts.map +1 -1
  30. package/dist/utf8.js.map +1 -1
  31. package/package.json +4 -8
  32. package/src/blob.test.ts +0 -405
  33. package/src/blob.ts +0 -478
  34. package/src/cid-implementation.test.ts +0 -129
  35. package/src/cid.test.ts +0 -350
  36. package/src/cid.ts +0 -603
  37. package/src/core-js.d.ts +0 -2
  38. package/src/index.ts +0 -8
  39. package/src/lex-equals.test.ts +0 -183
  40. package/src/lex-equals.ts +0 -123
  41. package/src/lex-error.test.ts +0 -54
  42. package/src/lex-error.ts +0 -83
  43. package/src/lex.test.ts +0 -279
  44. package/src/lex.ts +0 -253
  45. package/src/lib/nodejs-buffer.ts +0 -46
  46. package/src/lib/util.test.ts +0 -49
  47. package/src/lib/util.ts +0 -7
  48. package/src/object.test.ts +0 -80
  49. package/src/object.ts +0 -83
  50. package/src/uint8array-base64.ts +0 -2
  51. package/src/uint8array-concat.test.ts +0 -197
  52. package/src/uint8array-concat.ts +0 -25
  53. package/src/uint8array-from-base64.test.ts +0 -130
  54. package/src/uint8array-from-base64.ts +0 -98
  55. package/src/uint8array-to-base64.test.ts +0 -170
  56. package/src/uint8array-to-base64.ts +0 -55
  57. package/src/uint8array.test.ts +0 -503
  58. package/src/uint8array.ts +0 -197
  59. package/src/utf8-from-base64.test.ts +0 -39
  60. package/src/utf8-from-base64.ts +0 -23
  61. package/src/utf8-from-bytes.test.ts +0 -43
  62. package/src/utf8-from-bytes.ts +0 -21
  63. package/src/utf8-grapheme-len.test.ts +0 -38
  64. package/src/utf8-grapheme-len.ts +0 -21
  65. package/src/utf8-len.test.ts +0 -21
  66. package/src/utf8-len.ts +0 -51
  67. package/src/utf8-to-base64.test.ts +0 -35
  68. package/src/utf8-to-base64.ts +0 -22
  69. package/src/utf8.ts +0 -128
  70. package/tsconfig.build.json +0 -12
  71. package/tsconfig.json +0 -7
  72. package/tsconfig.tests.json +0 -8
@@ -1,183 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { parseCid } from './cid.js'
3
- import { lexEquals } from './lex-equals.js'
4
- import { LexValue } from './lex.js'
5
-
6
- function expectLexEqual(a: LexValue, b: LexValue, expected: boolean) {
7
- expect(lexEquals(a, b)).toBe(expected)
8
- expect(lexEquals(b, a)).toBe(expected)
9
- }
10
-
11
- describe('lexEquals', () => {
12
- it('compares primitive values', () => {
13
- expectLexEqual(null, null, true)
14
- expectLexEqual(true, true, true)
15
- expectLexEqual(false, false, true)
16
- expectLexEqual(42, 42, true)
17
- expectLexEqual('hello', 'hello', true)
18
-
19
- expectLexEqual(null, false, false)
20
- expectLexEqual(false, null, false)
21
- expectLexEqual(true, false, false)
22
- expectLexEqual(false, true, false)
23
- expectLexEqual(42, 43, false)
24
- expectLexEqual('hello', 'world', false)
25
- })
26
-
27
- it('compares NaN and Infinity correctly', () => {
28
- expectLexEqual(NaN, NaN, true)
29
- expectLexEqual(Infinity, Infinity, true)
30
- expectLexEqual(-Infinity, -Infinity, true)
31
-
32
- expectLexEqual(NaN, 0, false)
33
- expectLexEqual(NaN, null, false)
34
- expectLexEqual(Infinity, -Infinity, false)
35
- })
36
-
37
- it('compares arrays', () => {
38
- expectLexEqual([1, 2, 3], [1, 2, 3], true)
39
- expectLexEqual([1, 2, 3], [1, 2, 4], false)
40
- expectLexEqual([1, 2, 3], [1, 2], false)
41
- expectLexEqual([1, 2, 3], 'not an array', false)
42
- expectLexEqual([1, 2, 3], { 0: 1, 1: 2, 2: 3 }, false)
43
- })
44
-
45
- it('compares Uint8Arrays', () => {
46
- expectLexEqual(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3]), true)
47
- expectLexEqual(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 4]), false)
48
- expectLexEqual(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2]), false)
49
- expectLexEqual(new Uint8Array([1, 2, 3]), 'not a Uint8Array', false)
50
- })
51
-
52
- it('compares CIDs', () => {
53
- const cid1 = parseCid(
54
- 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
55
- )
56
- const cid2 = parseCid(cid1.toString())
57
- const cid3 = parseCid(cid1.toString())
58
-
59
- expectLexEqual(cid1, cid2, true)
60
- expectLexEqual(cid1, cid3, true)
61
- expectLexEqual(cid2, cid3, true)
62
-
63
- expectLexEqual(cid1, cid1.toString(), false)
64
- expectLexEqual(cid1, { not: 'a cid' }, false)
65
- expectLexEqual(cid1, [], false)
66
- expectLexEqual(cid1, cid1.bytes, false)
67
- })
68
-
69
- it('compares objects', () => {
70
- expectLexEqual({ a: 1, b: 2 }, { a: 1, b: 2 }, true)
71
- expectLexEqual(
72
- { a: 1, b: 2, c: undefined },
73
- { a: 1, b: 2, c: undefined },
74
- true,
75
- )
76
- expectLexEqual(
77
- { a: 1, b: 2, c: { e: 1, d: undefined } },
78
- { a: 1, b: 2, c: { d: undefined, e: 1 } },
79
- true,
80
- )
81
- expectLexEqual(
82
- { a: 1, b: { unicode: 'a~öñ©⽘☎𓋓😀👨‍👩‍👧‍👧' } },
83
- { a: 1, b: { unicode: 'a~öñ©⽘☎𓋓😀👨‍👩‍👧‍👧' } },
84
- true,
85
- )
86
-
87
- expectLexEqual({ a: 1, b: 2 }, { a: 1, b: 3 }, false)
88
- expectLexEqual({ a: 1, b: 2 }, { a: 1 }, false)
89
- expectLexEqual({ a: 1, b: 2 }, 'not an object', false)
90
- expectLexEqual({ a: 1, b: 2 }, null, false)
91
- })
92
-
93
- it('accounts for undefined (but present) properties in objects', () => {
94
- expectLexEqual({ a: 1, b: undefined }, { a: 1 }, false)
95
- expectLexEqual(
96
- { a: 1, b: { c: undefined, d: 2 } },
97
- { a: 1, b: { d: 2 } },
98
- false,
99
- )
100
-
101
- expectLexEqual(
102
- { a: 1, b: { c: undefined, d: 2 } },
103
- { a: 1, b: { c: 3, d: 2 } },
104
- false,
105
- )
106
- })
107
-
108
- it('compares nested structures', () => {
109
- const lex1 = {
110
- foo: [1, 2, { bar: new Uint8Array([3, 4, 5]) }],
111
- baz: parseCid(
112
- 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
113
- ),
114
- }
115
- const lex2 = {
116
- foo: [1, 2, { bar: new Uint8Array([3, 4, 5]) }],
117
- baz: parseCid(
118
- 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
119
- ),
120
- }
121
- const lex3 = {
122
- foo: [1, 2, { bar: new Uint8Array([3, 4, 5 + 1]) }],
123
- baz: parseCid(
124
- 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
125
- ),
126
- }
127
-
128
- expectLexEqual(lex1, lex2, true)
129
- expectLexEqual(lex1, lex3, false)
130
- expectLexEqual(lex2, lex3, false)
131
- })
132
-
133
- it('allows comparing invalid numbers (floats, NaN, Infinity)', () => {
134
- expectLexEqual(3.14, 2.71, false)
135
- expectLexEqual(NaN, 0, false)
136
- expectLexEqual(Infinity, -Infinity, false)
137
- })
138
-
139
- describe('reference equality', () => {
140
- for (const value of [3.14, NaN, Infinity, -Infinity]) {
141
- it(`returns true for identical references of ${String(value)}`, () => {
142
- expectLexEqual(value, value, true)
143
- expectLexEqual([value], [value], true)
144
- expectLexEqual({ foo: value }, { foo: value }, true)
145
- expectLexEqual([{ foo: value }], [{ foo: value }], true)
146
- })
147
- }
148
- })
149
-
150
- it('returns true for identical references', () => {
151
- const arr = [1, 2, 3]
152
- expectLexEqual(arr, arr, true)
153
-
154
- const obj = { a: 1, b: 2 }
155
- expectLexEqual(obj, obj, true)
156
-
157
- const u8 = new Uint8Array([1, 2, 3])
158
- expectLexEqual(u8, u8, true)
159
-
160
- const cid = parseCid(
161
- 'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
162
- )
163
- expectLexEqual(cid, cid, true)
164
- })
165
-
166
- it('throws when comparing plain object with non-allowed class instance', () => {
167
- // @ts-expect-error
168
- expect(() => lexEquals({}, new Map())).toThrow()
169
- // @ts-expect-error
170
- expect(() => lexEquals(new Map(), {})).toThrow()
171
- // @ts-expect-error
172
- expect(() => lexEquals({ foo: {} }, { foo: new Map() })).toThrow()
173
- // @ts-expect-error
174
- expect(() => lexEquals({ foo: new Map() }, { foo: {} })).toThrow()
175
-
176
- expect(() => lexEquals({ foo: {} }, { foo: new (class {})() })).toThrow()
177
- expect(() => lexEquals({ foo: new (class {})() }, { foo: {} })).toThrow()
178
-
179
- expect(() =>
180
- lexEquals({ foo: {} }, { foo: new (class Object {})() }),
181
- ).toThrow()
182
- })
183
- })
package/src/lex-equals.ts DELETED
@@ -1,123 +0,0 @@
1
- import { ifCid, isCid } from './cid.js'
2
- import { LexValue } from './lex.js'
3
- import { isPlainObject } from './object.js'
4
- import { ui8Equals } from './uint8array.js'
5
-
6
- /**
7
- * Performs deep equality comparison between two {@link LexValue}s.
8
- *
9
- * This function correctly handles all Lexicon data types including:
10
- * - Primitives (string, number, boolean, null)
11
- * - Arrays (recursive element comparison)
12
- * - Objects/LexMaps (recursive key-value comparison)
13
- * - Uint8Arrays (byte-by-byte comparison)
14
- * - CIDs (using CID equality)
15
- *
16
- * @param a - First LexValue to compare
17
- * @param b - Second LexValue to compare
18
- * @returns `true` if the values are deeply equal
19
- * @throws {TypeError} If either value is not a valid LexValue (e.g., contains unsupported types)
20
- *
21
- * @example
22
- * ```typescript
23
- * import { lexEquals } from '@atproto/lex-data'
24
- *
25
- * // Primitives
26
- * lexEquals('hello', 'hello') // true
27
- * lexEquals(42, 42) // true
28
- *
29
- * // Arrays
30
- * lexEquals([1, 2, 3], [1, 2, 3]) // true
31
- * lexEquals([1, 2], [1, 2, 3]) // false
32
- *
33
- * // Objects
34
- * lexEquals({ a: 1, b: 2 }, { a: 1, b: 2 }) // true
35
- * lexEquals({ a: 1 }, { a: 1, b: 2 }) // false
36
- *
37
- * // CIDs
38
- * lexEquals(cid1, cid2) // true if CIDs are equal
39
- *
40
- * // Uint8Arrays
41
- * lexEquals(new Uint8Array([1, 2]), new Uint8Array([1, 2])) // true
42
- * ```
43
- */
44
- export function lexEquals(a: LexValue, b: LexValue): boolean {
45
- if (Object.is(a, b)) {
46
- return true
47
- }
48
-
49
- if (
50
- a == null ||
51
- b == null ||
52
- typeof a !== 'object' ||
53
- typeof b !== 'object'
54
- ) {
55
- return false
56
- }
57
-
58
- if (Array.isArray(a)) {
59
- if (!Array.isArray(b)) {
60
- return false
61
- }
62
- if (a.length !== b.length) {
63
- return false
64
- }
65
- for (let i = 0; i < a.length; i++) {
66
- if (!lexEquals(a[i], b[i])) {
67
- return false
68
- }
69
- }
70
- return true
71
- } else if (Array.isArray(b)) {
72
- return false
73
- }
74
-
75
- if (ArrayBuffer.isView(a)) {
76
- if (!ArrayBuffer.isView(b)) return false
77
- return ui8Equals(a, b)
78
- } else if (ArrayBuffer.isView(b)) {
79
- return false
80
- }
81
-
82
- if (isCid(a)) {
83
- // @NOTE CID.equals returns its argument when it is falsy (e.g. null or
84
- // undefined) so we need to explicitly check that the output is "true".
85
- return ifCid(b)?.equals(a) === true
86
- } else if (isCid(b)) {
87
- return false
88
- }
89
-
90
- if (!isPlainObject(a) || !isPlainObject(b)) {
91
- // Foolproof (should never happen)
92
- throw new TypeError(
93
- 'Invalid LexValue (expected CID, Uint8Array, or LexMap)',
94
- )
95
- }
96
-
97
- const aKeys = Object.keys(a)
98
- const bKeys = Object.keys(b)
99
-
100
- if (aKeys.length !== bKeys.length) {
101
- return false
102
- }
103
-
104
- for (const key of aKeys) {
105
- const aVal = a[key]
106
- const bVal = b[key]
107
-
108
- // Needed because of the optional index signature in the Lex object type
109
- // though, in practice, aVal should never be undefined here.
110
- if (aVal === undefined) {
111
- if (bVal === undefined && bKeys.includes(key)) continue
112
- return false
113
- } else if (bVal === undefined) {
114
- return false
115
- }
116
-
117
- if (!lexEquals(aVal, bVal)) {
118
- return false
119
- }
120
- }
121
-
122
- return true
123
- }
@@ -1,54 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { LexError } from './lex-error.js'
3
-
4
- describe(LexError, () => {
5
- it('stores error code and message', () => {
6
- const err = new LexError('TestError', 'This is a test error')
7
- expect(err.error).toBe('TestError')
8
- expect(err.message).toBe('This is a test error')
9
- })
10
-
11
- it('strips empty message in toJSON output', () => {
12
- const err = new LexError('TestError')
13
- expect(err.toJSON()).toEqual({ error: 'TestError' })
14
- })
15
-
16
- it('includes message in toJSON when present', () => {
17
- const err = new LexError('TestError', 'details here')
18
- expect(err.toJSON()).toEqual({
19
- error: 'TestError',
20
- message: 'details here',
21
- })
22
- })
23
-
24
- it('formats string output correctly', () => {
25
- const err = new LexError('TestError', 'This is a test error')
26
- expect(err.toString()).toBe('LexError: [TestError] This is a test error')
27
- })
28
-
29
- it('uses constructor name for the name property', () => {
30
- const err = new LexError('TestError')
31
- expect(err.name).toBe('LexError')
32
- })
33
-
34
- it('subclasses use their own constructor name', () => {
35
- class MyCustomError extends LexError {
36
- name = 'MyCustomError'
37
- }
38
- const err = new MyCustomError('CustomCode', 'custom message')
39
- expect(err.name).toBe('MyCustomError')
40
- expect(err.toString()).toBe('MyCustomError: [CustomCode] custom message')
41
- })
42
-
43
- it('preserves cause option', () => {
44
- const cause = new Error('original')
45
- const err = new LexError('TestError', 'wrapped', { cause })
46
- expect(err.cause).toBe(cause)
47
- })
48
-
49
- it('is an instance of Error', () => {
50
- const err = new LexError('TestError')
51
- expect(err).toBeInstanceOf(Error)
52
- expect(err).toBeInstanceOf(LexError)
53
- })
54
- })
package/src/lex-error.ts DELETED
@@ -1,83 +0,0 @@
1
- /**
2
- * Error code type for Lexicon errors.
3
- *
4
- * Error codes identify the type of error that occurred (e.g., 'InvalidRequest').
5
- *
6
- * @example
7
- * ```typescript
8
- * import type { LexErrorCode } from '@atproto/lex-data'
9
- *
10
- * const errorCode: LexErrorCode = 'InvalidRequest'
11
- * ```
12
- */
13
- export type LexErrorCode = string & NonNullable<unknown>
14
-
15
- /**
16
- * JSON-serializable error data structure.
17
- *
18
- * This is the standard format for error responses in the AT Protocol XRPC protocol.
19
- *
20
- * @typeParam N - The specific error code type
21
- *
22
- * @example
23
- * ```typescript
24
- * import type { LexErrorData } from '@atproto/lex-data'
25
- *
26
- * const errorData: LexErrorData = {
27
- * error: 'InvalidRequest',
28
- * message: 'Missing required field: handle'
29
- * }
30
- * ```
31
- */
32
- export type LexErrorData<N extends LexErrorCode = LexErrorCode> = {
33
- /** The error code identifying the type of error. */
34
- error: N
35
- /** Optional human-readable error message. */
36
- message?: string
37
- }
38
-
39
- /**
40
- * Error class for Lexicon-related errors.
41
- *
42
- * LexError extends the standard JavaScript {@link Error} with AT
43
- * Protocol-specific functionality including an `error` code property and
44
- * methods for representation as (XRPC) error responses payloads.
45
- *
46
- * @typeParam N - The specific error code type
47
- */
48
- export class LexError<N extends LexErrorCode = LexErrorCode> extends Error {
49
- name = 'LexError'
50
-
51
- /**
52
- * @param error - The error code identifying the type of error, typically used in XRPC error payloads
53
- * @param message - Optional human-readable error message
54
- * @param options - Standard Error options (e.g., cause)
55
- */
56
- constructor(
57
- readonly error: N,
58
- message?: string, // Defaults to empty string in Error constructor
59
- options?: ErrorOptions,
60
- ) {
61
- super(message, options)
62
- }
63
-
64
- /**
65
- * Returns a string representation of this error.
66
- *
67
- * @returns A formatted string: "LexErrorClass: [MyErrorCode] My message"
68
- */
69
- toString(): string {
70
- return `${this.name}: [${this.error}] ${this.message}`
71
- }
72
-
73
- /**
74
- * Converts this error to a JSON-serializable object.
75
- *
76
- * @returns The error data suitable for JSON serialization
77
- * @note The `error` generic is *not* constrained to {@link N} to allow subclasses to override the error code type.
78
- */
79
- toJSON(): LexErrorData<LexErrorCode> {
80
- const { error, message } = this
81
- return { error, message: message || undefined }
82
- }
83
- }