@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.
- package/CHANGELOG.md +14 -0
- package/dist/blob.d.ts +2 -2
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +1 -1
- package/dist/blob.js.map +1 -1
- package/dist/lex-equals.d.ts +1 -1
- package/dist/lex-equals.d.ts.map +1 -1
- package/dist/lex-equals.js.map +1 -1
- package/dist/lex.d.ts +1 -1
- package/dist/lex.d.ts.map +1 -1
- package/dist/lex.js.map +1 -1
- package/dist/lib/nodejs-buffer.js.map +1 -1
- package/dist/uint8array-from-base64.d.ts +1 -1
- package/dist/uint8array-from-base64.d.ts.map +1 -1
- package/dist/uint8array-from-base64.js.map +1 -1
- package/dist/uint8array-to-base64.d.ts +1 -1
- package/dist/uint8array-to-base64.d.ts.map +1 -1
- package/dist/uint8array-to-base64.js.map +1 -1
- package/dist/uint8array.d.ts +1 -1
- package/dist/uint8array.d.ts.map +1 -1
- package/dist/uint8array.js.map +1 -1
- package/dist/utf8-from-base64.d.ts +1 -1
- package/dist/utf8-from-base64.d.ts.map +1 -1
- package/dist/utf8-from-base64.js.map +1 -1
- package/dist/utf8-to-base64.d.ts +1 -1
- package/dist/utf8-to-base64.d.ts.map +1 -1
- package/dist/utf8-to-base64.js.map +1 -1
- package/dist/utf8.d.ts +1 -1
- package/dist/utf8.d.ts.map +1 -1
- package/dist/utf8.js.map +1 -1
- package/package.json +4 -8
- package/src/blob.test.ts +0 -405
- package/src/blob.ts +0 -478
- package/src/cid-implementation.test.ts +0 -129
- package/src/cid.test.ts +0 -350
- package/src/cid.ts +0 -603
- package/src/core-js.d.ts +0 -2
- package/src/index.ts +0 -8
- package/src/lex-equals.test.ts +0 -183
- package/src/lex-equals.ts +0 -123
- package/src/lex-error.test.ts +0 -54
- package/src/lex-error.ts +0 -83
- package/src/lex.test.ts +0 -279
- package/src/lex.ts +0 -253
- package/src/lib/nodejs-buffer.ts +0 -46
- package/src/lib/util.test.ts +0 -49
- package/src/lib/util.ts +0 -7
- package/src/object.test.ts +0 -80
- package/src/object.ts +0 -83
- package/src/uint8array-base64.ts +0 -2
- package/src/uint8array-concat.test.ts +0 -197
- package/src/uint8array-concat.ts +0 -25
- package/src/uint8array-from-base64.test.ts +0 -130
- package/src/uint8array-from-base64.ts +0 -98
- package/src/uint8array-to-base64.test.ts +0 -170
- package/src/uint8array-to-base64.ts +0 -55
- package/src/uint8array.test.ts +0 -503
- package/src/uint8array.ts +0 -197
- package/src/utf8-from-base64.test.ts +0 -39
- package/src/utf8-from-base64.ts +0 -23
- package/src/utf8-from-bytes.test.ts +0 -43
- package/src/utf8-from-bytes.ts +0 -21
- package/src/utf8-grapheme-len.test.ts +0 -38
- package/src/utf8-grapheme-len.ts +0 -21
- package/src/utf8-len.test.ts +0 -21
- package/src/utf8-len.ts +0 -51
- package/src/utf8-to-base64.test.ts +0 -35
- package/src/utf8-to-base64.ts +0 -22
- package/src/utf8.ts +0 -128
- package/tsconfig.build.json +0 -12
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
package/src/lex-equals.test.ts
DELETED
|
@@ -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
|
-
}
|
package/src/lex-error.test.ts
DELETED
|
@@ -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
|
-
}
|