@atproto/lex-data 0.0.9 → 0.0.11

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/dist/lex.d.ts CHANGED
@@ -1,18 +1,200 @@
1
1
  import { Cid } from './cid.js';
2
+ /**
3
+ * Primitive values in the Lexicon data model.
4
+ *
5
+ * Represents the basic scalar types that can appear in AT Protocol data:
6
+ * - `number` - Integer values only (no floats)
7
+ * - `string` - UTF-8 text
8
+ * - `boolean` - true or false
9
+ * - `null` - Explicit null value
10
+ * - `Cid` - Content Identifier (link by hash)
11
+ * - `Uint8Array` - Binary data (bytes)
12
+ *
13
+ * @see {@link LexValue} for the complete recursive value type
14
+ */
2
15
  export type LexScalar = number | string | boolean | null | Cid | Uint8Array;
16
+ /**
17
+ * Any valid Lexicon value (recursive type).
18
+ *
19
+ * This is the union of all types that can appear in AT Protocol Lexicon data:
20
+ * - {@link LexScalar} - Primitive values (number, string, boolean, null, Cid, Uint8Array)
21
+ * - `LexValue[]` - Arrays of LexValues
22
+ * - `{ [key: string]?: LexValue }` - Objects with string keys and LexValue values
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import type { LexValue } from '@atproto/lex'
27
+ *
28
+ * const scalar: LexValue = 'hello'
29
+ * const array: LexValue = [1, 2, 3]
30
+ * const object: LexValue = { name: 'Alice', age: 30 }
31
+ * ```
32
+ *
33
+ * @see {@link LexScalar} for primitive value types
34
+ * @see {@link LexMap} for object types
35
+ * @see {@link LexArray} for array types
36
+ */
3
37
  export type LexValue = LexScalar | LexValue[] | {
4
38
  [_ in string]?: LexValue;
5
39
  };
40
+ /**
41
+ * Object with string keys and LexValue values.
42
+ *
43
+ * Represents a plain object in the Lexicon data model where all values
44
+ * must be valid {@link LexValue} types.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import type { LexMap } from '@atproto/lex'
49
+ *
50
+ * const user: LexMap = {
51
+ * name: 'Alice',
52
+ * age: 30,
53
+ * tags: ['admin', 'user']
54
+ * }
55
+ * ```
56
+ *
57
+ * @see {@link TypedLexMap} for objects with a required `$type` property
58
+ */
6
59
  export type LexMap = {
7
60
  [_ in string]?: LexValue;
8
61
  };
62
+ /**
63
+ * Array of {@link LexValue} elements.
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * import type { LexArray } from '@atproto/lex'
68
+ *
69
+ * const items: LexArray = [1, 'two', { three: 3 }]
70
+ * ```
71
+ */
9
72
  export type LexArray = LexValue[];
73
+ /**
74
+ * Type guard to check if a value is a valid {@link LexMap}.
75
+ *
76
+ * Returns true if the value is a plain object where all values are valid
77
+ * {@link LexValue} types.
78
+ *
79
+ * @param value - The value to check
80
+ * @returns `true` if the value is a valid LexMap
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * import { isLexMap } from '@atproto/lex'
85
+ *
86
+ * if (isLexMap(data)) {
87
+ * // data is narrowed to LexMap
88
+ * console.log(Object.keys(data))
89
+ * }
90
+ * ```
91
+ */
10
92
  export declare function isLexMap(value: unknown): value is LexMap;
93
+ /**
94
+ * Type guard to check if a value is a valid {@link LexArray}.
95
+ *
96
+ * Returns true if the value is an array where all elements are valid
97
+ * {@link LexValue} types.
98
+ *
99
+ * @param value - The value to check
100
+ * @returns `true` if the value is a valid LexArray
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * import { isLexArray } from '@atproto/lex'
105
+ *
106
+ * if (isLexArray(data)) {
107
+ * // data is narrowed to LexArray
108
+ * data.forEach(item => console.log(item))
109
+ * }
110
+ * ```
111
+ */
11
112
  export declare function isLexArray(value: unknown): value is LexArray;
113
+ /**
114
+ * Type guard to check if a value is a valid {@link LexScalar}.
115
+ *
116
+ * Returns true if the value is one of the primitive Lexicon types:
117
+ * number (integer only), string, boolean, null, Cid, or Uint8Array.
118
+ *
119
+ * @param value - The value to check
120
+ * @returns `true` if the value is a valid LexScalar
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * import { isLexScalar } from '@atproto/lex'
125
+ *
126
+ * isLexScalar('hello') // true
127
+ * isLexScalar(42) // true
128
+ * isLexScalar(3.14) // false (floats not allowed)
129
+ * isLexScalar([1, 2]) // false (arrays are not scalars)
130
+ * ```
131
+ */
12
132
  export declare function isLexScalar(value: unknown): value is LexScalar;
133
+ /**
134
+ * Type guard to check if a value is a valid {@link LexValue}.
135
+ *
136
+ * Performs a deep check to validate that the value (and all nested values)
137
+ * conform to the Lexicon data model. This includes checking for:
138
+ * - Valid scalar types (number, string, boolean, null, Cid, Uint8Array)
139
+ * - Arrays containing only valid LexValues
140
+ * - Plain objects with string keys and valid LexValue values
141
+ * - No cyclic references (which cannot be serialized to JSON or CBOR)
142
+ *
143
+ * @param value - The value to check
144
+ * @returns `true` if the value is a valid LexValue
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * import { isLexValue } from '@atproto/lex'
149
+ *
150
+ * isLexValue({ name: 'Alice', tags: ['admin'] }) // true
151
+ * isLexValue(new Date()) // false (not a plain object)
152
+ * isLexValue({ fn: () => {} }) // false (functions not allowed)
153
+ * ```
154
+ */
13
155
  export declare function isLexValue(value: unknown): value is LexValue;
14
- export type TypedLexMap = LexMap & {
15
- $type: string;
156
+ /**
157
+ * A {@link LexMap} with a required `$type` property.
158
+ *
159
+ * Used to represent typed objects in the Lexicon data model, where the
160
+ * `$type` property identifies the Lexicon schema that defines the object's
161
+ * structure.
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * import type { TypedLexMap } from '@atproto/lex'
166
+ *
167
+ * const post: TypedLexMap = {
168
+ * $type: 'app.bsky.feed.post',
169
+ * text: 'Hello world!',
170
+ * createdAt: '2024-01-01T00:00:00Z'
171
+ * }
172
+ * ```
173
+ *
174
+ * @see {@link isTypedLexMap} to check if a value is a TypedLexMap
175
+ */
176
+ export type TypedLexMap<T extends string = string> = LexMap & {
177
+ $type: T;
16
178
  };
179
+ /**
180
+ * Type guard to check if a value is a {@link TypedLexMap}.
181
+ *
182
+ * Returns true if the value is a valid {@link LexMap} with a non-empty
183
+ * `$type` string property.
184
+ *
185
+ * @param value - The LexValue to check
186
+ * @returns `true` if the value is a TypedLexMap
187
+ *
188
+ * @example
189
+ * ```typescript
190
+ * import { isTypedLexMap } from '@atproto/lex'
191
+ *
192
+ * const data = { $type: 'app.bsky.feed.post', text: 'Hello' }
193
+ *
194
+ * if (isTypedLexMap(data)) {
195
+ * console.log(data.$type) // 'app.bsky.feed.post'
196
+ * }
197
+ * ```
198
+ */
17
199
  export declare function isTypedLexMap(value: LexValue): value is TypedLexMap;
18
200
  //# sourceMappingURL=lex.d.ts.map
package/dist/lex.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lex.d.ts","sourceRoot":"","sources":["../src/lex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAS,MAAM,UAAU,CAAA;AAGrC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,GAAG,GAAG,UAAU,CAAA;AAC3E,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,EAAE,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,QAAQ;CAAE,CAAA;AAC5E,MAAM,MAAM,MAAM,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,QAAQ;CAAE,CAAA;AACjD,MAAM,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAA;AAEjC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAa9D;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CA8C5D;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AACpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,KAAK,IAAI,WAAW,CAInE"}
1
+ {"version":3,"file":"lex.d.ts","sourceRoot":"","sources":["../src/lex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAS,MAAM,UAAU,CAAA;AAGrC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,GAAG,GAAG,UAAU,CAAA;AAE3E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,EAAE,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,QAAQ;CAAE,CAAA;AAE5E;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,MAAM,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,QAAQ;CAAE,CAAA;AAEjD;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAA;AAEjC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAa9D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CA8C5D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,CAAA;AAE1E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,KAAK,IAAI,WAAW,CAInE"}
package/dist/lex.js CHANGED
@@ -7,12 +7,69 @@ exports.isLexValue = isLexValue;
7
7
  exports.isTypedLexMap = isTypedLexMap;
8
8
  const cid_js_1 = require("./cid.js");
9
9
  const object_js_1 = require("./object.js");
10
+ /**
11
+ * Type guard to check if a value is a valid {@link LexMap}.
12
+ *
13
+ * Returns true if the value is a plain object where all values are valid
14
+ * {@link LexValue} types.
15
+ *
16
+ * @param value - The value to check
17
+ * @returns `true` if the value is a valid LexMap
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { isLexMap } from '@atproto/lex'
22
+ *
23
+ * if (isLexMap(data)) {
24
+ * // data is narrowed to LexMap
25
+ * console.log(Object.keys(data))
26
+ * }
27
+ * ```
28
+ */
10
29
  function isLexMap(value) {
11
30
  return (0, object_js_1.isPlainObject)(value) && Object.values(value).every(isLexValue);
12
31
  }
32
+ /**
33
+ * Type guard to check if a value is a valid {@link LexArray}.
34
+ *
35
+ * Returns true if the value is an array where all elements are valid
36
+ * {@link LexValue} types.
37
+ *
38
+ * @param value - The value to check
39
+ * @returns `true` if the value is a valid LexArray
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { isLexArray } from '@atproto/lex'
44
+ *
45
+ * if (isLexArray(data)) {
46
+ * // data is narrowed to LexArray
47
+ * data.forEach(item => console.log(item))
48
+ * }
49
+ * ```
50
+ */
13
51
  function isLexArray(value) {
14
52
  return Array.isArray(value) && value.every(isLexValue);
15
53
  }
54
+ /**
55
+ * Type guard to check if a value is a valid {@link LexScalar}.
56
+ *
57
+ * Returns true if the value is one of the primitive Lexicon types:
58
+ * number (integer only), string, boolean, null, Cid, or Uint8Array.
59
+ *
60
+ * @param value - The value to check
61
+ * @returns `true` if the value is a valid LexScalar
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * import { isLexScalar } from '@atproto/lex'
66
+ *
67
+ * isLexScalar('hello') // true
68
+ * isLexScalar(42) // true
69
+ * isLexScalar(3.14) // false (floats not allowed)
70
+ * isLexScalar([1, 2]) // false (arrays are not scalars)
71
+ * ```
72
+ */
16
73
  function isLexScalar(value) {
17
74
  switch (typeof value) {
18
75
  case 'object':
@@ -28,6 +85,28 @@ function isLexScalar(value) {
28
85
  return false;
29
86
  }
30
87
  }
88
+ /**
89
+ * Type guard to check if a value is a valid {@link LexValue}.
90
+ *
91
+ * Performs a deep check to validate that the value (and all nested values)
92
+ * conform to the Lexicon data model. This includes checking for:
93
+ * - Valid scalar types (number, string, boolean, null, Cid, Uint8Array)
94
+ * - Arrays containing only valid LexValues
95
+ * - Plain objects with string keys and valid LexValue values
96
+ * - No cyclic references (which cannot be serialized to JSON or CBOR)
97
+ *
98
+ * @param value - The value to check
99
+ * @returns `true` if the value is a valid LexValue
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * import { isLexValue } from '@atproto/lex'
104
+ *
105
+ * isLexValue({ name: 'Alice', tags: ['admin'] }) // true
106
+ * isLexValue(new Date()) // false (not a plain object)
107
+ * isLexValue({ fn: () => {} }) // false (functions not allowed)
108
+ * ```
109
+ */
31
110
  function isLexValue(value) {
32
111
  // Using a stack to avoid recursion depth issues.
33
112
  const stack = [value];
@@ -78,6 +157,26 @@ function isLexValue(value) {
78
157
  visited.clear();
79
158
  return true;
80
159
  }
160
+ /**
161
+ * Type guard to check if a value is a {@link TypedLexMap}.
162
+ *
163
+ * Returns true if the value is a valid {@link LexMap} with a non-empty
164
+ * `$type` string property.
165
+ *
166
+ * @param value - The LexValue to check
167
+ * @returns `true` if the value is a TypedLexMap
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * import { isTypedLexMap } from '@atproto/lex'
172
+ *
173
+ * const data = { $type: 'app.bsky.feed.post', text: 'Hello' }
174
+ *
175
+ * if (isTypedLexMap(data)) {
176
+ * console.log(data.$type) // 'app.bsky.feed.post'
177
+ * }
178
+ * ```
179
+ */
81
180
  function isTypedLexMap(value) {
82
181
  return (isLexMap(value) && typeof value.$type === 'string' && value.$type.length > 0);
83
182
  }
package/dist/lex.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lex.js","sourceRoot":"","sources":["../src/lex.ts"],"names":[],"mappings":";;AAQA,4BAEC;AAED,gCAEC;AAED,kCAaC;AAED,gCA8CC;AAGD,sCAIC;AApFD,qCAAqC;AACrC,2CAAyD;AAOzD,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,IAAA,yBAAa,EAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;AACvE,CAAC;AAED,SAAgB,UAAU,CAAC,KAAc;IACvC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;AACxD,CAAC;AAED,SAAgB,WAAW,CAAC,KAAc;IACxC,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,UAAU,IAAI,IAAA,cAAK,EAAC,KAAK,CAAC,CAAA;QACtE,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS;YACZ,OAAO,IAAI,CAAA;QACb,KAAK,QAAQ;YACX,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAA;QAC1C,cAAc;QACd;YACE,OAAO,KAAK,CAAA;IAChB,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,KAAc;IACvC,iDAAiD;IACjD,MAAM,KAAK,GAAc,CAAC,KAAK,CAAC,CAAA;IAChC,4EAA4E;IAC5E,4EAA4E;IAC5E,iBAAiB;IACjB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;IAEjC,GAAG,CAAC;QACF,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAG,CAAA;QAE1B,4EAA4E;QAC5E,+DAA+D;QAC/D,QAAQ,OAAO,KAAK,EAAE,CAAC;YACrB,KAAK,QAAQ;gBACX,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACnB,YAAY;gBACd,CAAC;qBAAM,IAAI,IAAA,wBAAY,EAAC,KAAK,CAAC,EAAE,CAAC;oBAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;wBAAE,OAAO,KAAK,CAAA;oBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;oBAClB,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;gBACrC,CAAC;qBAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAChC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;wBAAE,OAAO,KAAK,CAAA;oBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;oBAClB,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAA;gBACtB,CAAC;qBAAM,IAAI,KAAK,YAAY,UAAU,IAAI,IAAA,cAAK,EAAC,KAAK,CAAC,EAAE,CAAC;oBACvD,YAAY;gBACd,CAAC;qBAAM,CAAC;oBACN,OAAO,KAAK,CAAA;gBACd,CAAC;gBACD,MAAK;YACP,KAAK,QAAQ,CAAC;YACd,KAAK,SAAS;gBACZ,MAAK;YACP,KAAK,QAAQ;gBACX,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;oBAAE,MAAK;YACpC,cAAc;YACd;gBACE,OAAO,KAAK,CAAA;QAChB,CAAC;IACH,CAAC,QAAQ,KAAK,CAAC,MAAM,GAAG,CAAC,EAAC;IAE1B,+BAA+B;IAC/B,OAAO,CAAC,KAAK,EAAE,CAAA;IAEf,OAAO,IAAI,CAAA;AACb,CAAC;AAGD,SAAgB,aAAa,CAAC,KAAe;IAC3C,OAAO,CACL,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAC7E,CAAA;AACH,CAAC","sourcesContent":["import { Cid, isCid } from './cid.js'\nimport { isPlainObject, isPlainProto } from './object.js'\n\nexport type LexScalar = number | string | boolean | null | Cid | Uint8Array\nexport type LexValue = LexScalar | LexValue[] | { [_ in string]?: LexValue }\nexport type LexMap = { [_ in string]?: LexValue }\nexport type LexArray = LexValue[]\n\nexport function isLexMap(value: unknown): value is LexMap {\n return isPlainObject(value) && Object.values(value).every(isLexValue)\n}\n\nexport function isLexArray(value: unknown): value is LexArray {\n return Array.isArray(value) && value.every(isLexValue)\n}\n\nexport function isLexScalar(value: unknown): value is LexScalar {\n switch (typeof value) {\n case 'object':\n return value === null || value instanceof Uint8Array || isCid(value)\n case 'string':\n case 'boolean':\n return true\n case 'number':\n if (Number.isInteger(value)) return true\n // fallthrough\n default:\n return false\n }\n}\n\nexport function isLexValue(value: unknown): value is LexValue {\n // Using a stack to avoid recursion depth issues.\n const stack: unknown[] = [value]\n // Cyclic structures are not valid LexValues as they cannot be serialized to\n // JSON or CBOR. This also allows us to avoid infinite loops when traversing\n // the structure.\n const visited = new Set<object>()\n\n do {\n const value = stack.pop()!\n\n // Optimization: we are not using `isLexScalar` here to avoid extra function\n // calls, and to avoid computing `typeof value` multiple times.\n switch (typeof value) {\n case 'object':\n if (value === null) {\n // LexScalar\n } else if (isPlainProto(value)) {\n if (visited.has(value)) return false\n visited.add(value)\n stack.push(...Object.values(value))\n } else if (Array.isArray(value)) {\n if (visited.has(value)) return false\n visited.add(value)\n stack.push(...value)\n } else if (value instanceof Uint8Array || isCid(value)) {\n // LexScalar\n } else {\n return false\n }\n break\n case 'string':\n case 'boolean':\n break\n case 'number':\n if (Number.isInteger(value)) break\n // fallthrough\n default:\n return false\n }\n } while (stack.length > 0)\n\n // Optimization: ease GC's work\n visited.clear()\n\n return true\n}\n\nexport type TypedLexMap = LexMap & { $type: string }\nexport function isTypedLexMap(value: LexValue): value is TypedLexMap {\n return (\n isLexMap(value) && typeof value.$type === 'string' && value.$type.length > 0\n )\n}\n"]}
1
+ {"version":3,"file":"lex.js","sourceRoot":"","sources":["../src/lex.ts"],"names":[],"mappings":"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","sourcesContent":["import { Cid, isCid } from './cid.js'\nimport { isPlainObject, isPlainProto } from './object.js'\n\n/**\n * Primitive values in the Lexicon data model.\n *\n * Represents the basic scalar types that can appear in AT Protocol data:\n * - `number` - Integer values only (no floats)\n * - `string` - UTF-8 text\n * - `boolean` - true or false\n * - `null` - Explicit null value\n * - `Cid` - Content Identifier (link by hash)\n * - `Uint8Array` - Binary data (bytes)\n *\n * @see {@link LexValue} for the complete recursive value type\n */\nexport type LexScalar = number | string | boolean | null | Cid | Uint8Array\n\n/**\n * Any valid Lexicon value (recursive type).\n *\n * This is the union of all types that can appear in AT Protocol Lexicon data:\n * - {@link LexScalar} - Primitive values (number, string, boolean, null, Cid, Uint8Array)\n * - `LexValue[]` - Arrays of LexValues\n * - `{ [key: string]?: LexValue }` - Objects with string keys and LexValue values\n *\n * @example\n * ```typescript\n * import type { LexValue } from '@atproto/lex'\n *\n * const scalar: LexValue = 'hello'\n * const array: LexValue = [1, 2, 3]\n * const object: LexValue = { name: 'Alice', age: 30 }\n * ```\n *\n * @see {@link LexScalar} for primitive value types\n * @see {@link LexMap} for object types\n * @see {@link LexArray} for array types\n */\nexport type LexValue = LexScalar | LexValue[] | { [_ in string]?: LexValue }\n\n/**\n * Object with string keys and LexValue values.\n *\n * Represents a plain object in the Lexicon data model where all values\n * must be valid {@link LexValue} types.\n *\n * @example\n * ```typescript\n * import type { LexMap } from '@atproto/lex'\n *\n * const user: LexMap = {\n * name: 'Alice',\n * age: 30,\n * tags: ['admin', 'user']\n * }\n * ```\n *\n * @see {@link TypedLexMap} for objects with a required `$type` property\n */\nexport type LexMap = { [_ in string]?: LexValue }\n\n/**\n * Array of {@link LexValue} elements.\n *\n * @example\n * ```typescript\n * import type { LexArray } from '@atproto/lex'\n *\n * const items: LexArray = [1, 'two', { three: 3 }]\n * ```\n */\nexport type LexArray = LexValue[]\n\n/**\n * Type guard to check if a value is a valid {@link LexMap}.\n *\n * Returns true if the value is a plain object where all values are valid\n * {@link LexValue} types.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid LexMap\n *\n * @example\n * ```typescript\n * import { isLexMap } from '@atproto/lex'\n *\n * if (isLexMap(data)) {\n * // data is narrowed to LexMap\n * console.log(Object.keys(data))\n * }\n * ```\n */\nexport function isLexMap(value: unknown): value is LexMap {\n return isPlainObject(value) && Object.values(value).every(isLexValue)\n}\n\n/**\n * Type guard to check if a value is a valid {@link LexArray}.\n *\n * Returns true if the value is an array where all elements are valid\n * {@link LexValue} types.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid LexArray\n *\n * @example\n * ```typescript\n * import { isLexArray } from '@atproto/lex'\n *\n * if (isLexArray(data)) {\n * // data is narrowed to LexArray\n * data.forEach(item => console.log(item))\n * }\n * ```\n */\nexport function isLexArray(value: unknown): value is LexArray {\n return Array.isArray(value) && value.every(isLexValue)\n}\n\n/**\n * Type guard to check if a value is a valid {@link LexScalar}.\n *\n * Returns true if the value is one of the primitive Lexicon types:\n * number (integer only), string, boolean, null, Cid, or Uint8Array.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid LexScalar\n *\n * @example\n * ```typescript\n * import { isLexScalar } from '@atproto/lex'\n *\n * isLexScalar('hello') // true\n * isLexScalar(42) // true\n * isLexScalar(3.14) // false (floats not allowed)\n * isLexScalar([1, 2]) // false (arrays are not scalars)\n * ```\n */\nexport function isLexScalar(value: unknown): value is LexScalar {\n switch (typeof value) {\n case 'object':\n return value === null || value instanceof Uint8Array || isCid(value)\n case 'string':\n case 'boolean':\n return true\n case 'number':\n if (Number.isInteger(value)) return true\n // fallthrough\n default:\n return false\n }\n}\n\n/**\n * Type guard to check if a value is a valid {@link LexValue}.\n *\n * Performs a deep check to validate that the value (and all nested values)\n * conform to the Lexicon data model. This includes checking for:\n * - Valid scalar types (number, string, boolean, null, Cid, Uint8Array)\n * - Arrays containing only valid LexValues\n * - Plain objects with string keys and valid LexValue values\n * - No cyclic references (which cannot be serialized to JSON or CBOR)\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid LexValue\n *\n * @example\n * ```typescript\n * import { isLexValue } from '@atproto/lex'\n *\n * isLexValue({ name: 'Alice', tags: ['admin'] }) // true\n * isLexValue(new Date()) // false (not a plain object)\n * isLexValue({ fn: () => {} }) // false (functions not allowed)\n * ```\n */\nexport function isLexValue(value: unknown): value is LexValue {\n // Using a stack to avoid recursion depth issues.\n const stack: unknown[] = [value]\n // Cyclic structures are not valid LexValues as they cannot be serialized to\n // JSON or CBOR. This also allows us to avoid infinite loops when traversing\n // the structure.\n const visited = new Set<object>()\n\n do {\n const value = stack.pop()!\n\n // Optimization: we are not using `isLexScalar` here to avoid extra function\n // calls, and to avoid computing `typeof value` multiple times.\n switch (typeof value) {\n case 'object':\n if (value === null) {\n // LexScalar\n } else if (isPlainProto(value)) {\n if (visited.has(value)) return false\n visited.add(value)\n stack.push(...Object.values(value))\n } else if (Array.isArray(value)) {\n if (visited.has(value)) return false\n visited.add(value)\n stack.push(...value)\n } else if (value instanceof Uint8Array || isCid(value)) {\n // LexScalar\n } else {\n return false\n }\n break\n case 'string':\n case 'boolean':\n break\n case 'number':\n if (Number.isInteger(value)) break\n // fallthrough\n default:\n return false\n }\n } while (stack.length > 0)\n\n // Optimization: ease GC's work\n visited.clear()\n\n return true\n}\n\n/**\n * A {@link LexMap} with a required `$type` property.\n *\n * Used to represent typed objects in the Lexicon data model, where the\n * `$type` property identifies the Lexicon schema that defines the object's\n * structure.\n *\n * @example\n * ```typescript\n * import type { TypedLexMap } from '@atproto/lex'\n *\n * const post: TypedLexMap = {\n * $type: 'app.bsky.feed.post',\n * text: 'Hello world!',\n * createdAt: '2024-01-01T00:00:00Z'\n * }\n * ```\n *\n * @see {@link isTypedLexMap} to check if a value is a TypedLexMap\n */\nexport type TypedLexMap<T extends string = string> = LexMap & { $type: T }\n\n/**\n * Type guard to check if a value is a {@link TypedLexMap}.\n *\n * Returns true if the value is a valid {@link LexMap} with a non-empty\n * `$type` string property.\n *\n * @param value - The LexValue to check\n * @returns `true` if the value is a TypedLexMap\n *\n * @example\n * ```typescript\n * import { isTypedLexMap } from '@atproto/lex'\n *\n * const data = { $type: 'app.bsky.feed.post', text: 'Hello' }\n *\n * if (isTypedLexMap(data)) {\n * console.log(data.$type) // 'app.bsky.feed.post'\n * }\n * ```\n */\nexport function isTypedLexMap(value: LexValue): value is TypedLexMap {\n return (\n isLexMap(value) && typeof value.$type === 'string' && value.$type.length > 0\n )\n}\n"]}
package/dist/object.d.ts CHANGED
@@ -1,15 +1,65 @@
1
1
  /**
2
2
  * Checks whether the input is an object (not null).
3
+ *
4
+ * Returns true for any non-null value with typeof 'object', including
5
+ * arrays, plain objects, class instances, etc.
6
+ *
7
+ * @param input - The value to check
8
+ * @returns `true` if the input is an object (not null)
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { isObject } from '@atproto/lex-data'
13
+ *
14
+ * isObject({}) // true
15
+ * isObject([1, 2, 3]) // true
16
+ * isObject(new Date()) // true
17
+ * isObject(null) // false
18
+ * isObject('string') // false
19
+ * ```
3
20
  */
4
21
  export declare function isObject(input: unknown): input is object;
5
22
  /**
6
- * Checks whether the input is an object (not null) whose prototype is either
7
- * null or `Object.prototype`.
23
+ * Checks whether the input is a plain object.
24
+ *
25
+ * A plain object is an object (not null) whose prototype is either null
26
+ * or `Object.prototype`. This excludes arrays, class instances, and other
27
+ * special objects.
28
+ *
29
+ * @param input - The value to check
30
+ * @returns `true` if the input is a plain object
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * import { isPlainObject } from '@atproto/lex-data'
35
+ *
36
+ * isPlainObject({}) // true
37
+ * isPlainObject({ a: 1 }) // true
38
+ * isPlainObject(Object.create(null)) // true
39
+ * isPlainObject([1, 2, 3]) // false
40
+ * isPlainObject(new Date()) // false
41
+ * isPlainObject(null) // false
42
+ * ```
8
43
  */
9
44
  export declare function isPlainObject(input: unknown): input is Record<string, unknown>;
10
45
  /**
11
- * Checks whether the prototype of the input object is either null or
12
- * `Object.prototype`.
46
+ * Checks whether the prototype of an object is plain (null or Object.prototype).
47
+ *
48
+ * This is useful for checking if an object is a plain object without
49
+ * checking that it's non-null first (the null check is already done).
50
+ *
51
+ * @param input - The object to check (must be non-null)
52
+ * @returns `true` if the object's prototype is plain
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * import { isPlainProto } from '@atproto/lex-data'
57
+ *
58
+ * isPlainProto({}) // true
59
+ * isPlainProto(Object.create(null)) // true
60
+ * isPlainProto([1, 2, 3]) // false (Array.prototype)
61
+ * isPlainProto(new Date()) // false (Date.prototype)
62
+ * ```
13
63
  */
14
64
  export declare function isPlainProto(input: object): input is Record<string, unknown>;
15
65
  //# sourceMappingURL=object.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAKD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,oCAE3C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAU5E"}
1
+ {"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAKD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,oCAE3C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAU5E"}
package/dist/object.js CHANGED
@@ -5,6 +5,23 @@ exports.isPlainObject = isPlainObject;
5
5
  exports.isPlainProto = isPlainProto;
6
6
  /**
7
7
  * Checks whether the input is an object (not null).
8
+ *
9
+ * Returns true for any non-null value with typeof 'object', including
10
+ * arrays, plain objects, class instances, etc.
11
+ *
12
+ * @param input - The value to check
13
+ * @returns `true` if the input is an object (not null)
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import { isObject } from '@atproto/lex-data'
18
+ *
19
+ * isObject({}) // true
20
+ * isObject([1, 2, 3]) // true
21
+ * isObject(new Date()) // true
22
+ * isObject(null) // false
23
+ * isObject('string') // false
24
+ * ```
8
25
  */
9
26
  function isObject(input) {
10
27
  return input != null && typeof input === 'object';
@@ -12,15 +29,48 @@ function isObject(input) {
12
29
  const ObjectProto = Object.prototype;
13
30
  const ObjectToString = Object.prototype.toString;
14
31
  /**
15
- * Checks whether the input is an object (not null) whose prototype is either
16
- * null or `Object.prototype`.
32
+ * Checks whether the input is a plain object.
33
+ *
34
+ * A plain object is an object (not null) whose prototype is either null
35
+ * or `Object.prototype`. This excludes arrays, class instances, and other
36
+ * special objects.
37
+ *
38
+ * @param input - The value to check
39
+ * @returns `true` if the input is a plain object
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { isPlainObject } from '@atproto/lex-data'
44
+ *
45
+ * isPlainObject({}) // true
46
+ * isPlainObject({ a: 1 }) // true
47
+ * isPlainObject(Object.create(null)) // true
48
+ * isPlainObject([1, 2, 3]) // false
49
+ * isPlainObject(new Date()) // false
50
+ * isPlainObject(null) // false
51
+ * ```
17
52
  */
18
53
  function isPlainObject(input) {
19
54
  return isObject(input) && isPlainProto(input);
20
55
  }
21
56
  /**
22
- * Checks whether the prototype of the input object is either null or
23
- * `Object.prototype`.
57
+ * Checks whether the prototype of an object is plain (null or Object.prototype).
58
+ *
59
+ * This is useful for checking if an object is a plain object without
60
+ * checking that it's non-null first (the null check is already done).
61
+ *
62
+ * @param input - The object to check (must be non-null)
63
+ * @returns `true` if the object's prototype is plain
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * import { isPlainProto } from '@atproto/lex-data'
68
+ *
69
+ * isPlainProto({}) // true
70
+ * isPlainProto(Object.create(null)) // true
71
+ * isPlainProto([1, 2, 3]) // false (Array.prototype)
72
+ * isPlainProto(new Date()) // false (Date.prototype)
73
+ * ```
24
74
  */
25
75
  function isPlainProto(input) {
26
76
  const proto = Object.getPrototypeOf(input);
@@ -1 +1 @@
1
- {"version":3,"file":"object.js","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":";;AAGA,4BAEC;AASD,sCAEC;AAMD,oCAUC;AAhCD;;GAEG;AACH,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAA;AACnD,CAAC;AAED,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAA;AACpC,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAA;AAEhD;;;GAGG;AACH,SAAgB,aAAa,CAAC,KAAc;IAC1C,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,CAAA;AAC/C,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,KAAa;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IAC1C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC/B,OAAO,CACL,CAAC,KAAK,KAAK,WAAW;QACpB,sEAAsE;QACtE,6BAA6B;QAC7B,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;QACxC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,iBAAiB,CACjD,CAAA;AACH,CAAC","sourcesContent":["/**\n * Checks whether the input is an object (not null).\n */\nexport function isObject(input: unknown): input is object {\n return input != null && typeof input === 'object'\n}\n\nconst ObjectProto = Object.prototype\nconst ObjectToString = Object.prototype.toString\n\n/**\n * Checks whether the input is an object (not null) whose prototype is either\n * null or `Object.prototype`.\n */\nexport function isPlainObject(input: unknown) {\n return isObject(input) && isPlainProto(input)\n}\n\n/**\n * Checks whether the prototype of the input object is either null or\n * `Object.prototype`.\n */\nexport function isPlainProto(input: object): input is Record<string, unknown> {\n const proto = Object.getPrototypeOf(input)\n if (proto === null) return true\n return (\n (proto === ObjectProto ||\n // Needed to support NodeJS's `runInNewContext` which produces objects\n // with a different prototype\n Object.getPrototypeOf(proto) === null) &&\n ObjectToString.call(input) === '[object Object]'\n )\n}\n"]}
1
+ {"version":3,"file":"object.js","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":";;AAoBA,4BAEC;AA2BD,sCAEC;AAqBD,oCAUC;AAlFD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAA;AACnD,CAAC;AAED,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAA;AACpC,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAA;AAEhD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,aAAa,CAAC,KAAc;IAC1C,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,CAAA;AAC/C,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,YAAY,CAAC,KAAa;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IAC1C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC/B,OAAO,CACL,CAAC,KAAK,KAAK,WAAW;QACpB,sEAAsE;QACtE,6BAA6B;QAC7B,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;QACxC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,iBAAiB,CACjD,CAAA;AACH,CAAC","sourcesContent":["/**\n * Checks whether the input is an object (not null).\n *\n * Returns true for any non-null value with typeof 'object', including\n * arrays, plain objects, class instances, etc.\n *\n * @param input - The value to check\n * @returns `true` if the input is an object (not null)\n *\n * @example\n * ```typescript\n * import { isObject } from '@atproto/lex-data'\n *\n * isObject({}) // true\n * isObject([1, 2, 3]) // true\n * isObject(new Date()) // true\n * isObject(null) // false\n * isObject('string') // false\n * ```\n */\nexport function isObject(input: unknown): input is object {\n return input != null && typeof input === 'object'\n}\n\nconst ObjectProto = Object.prototype\nconst ObjectToString = Object.prototype.toString\n\n/**\n * Checks whether the input is a plain object.\n *\n * A plain object is an object (not null) whose prototype is either null\n * or `Object.prototype`. This excludes arrays, class instances, and other\n * special objects.\n *\n * @param input - The value to check\n * @returns `true` if the input is a plain object\n *\n * @example\n * ```typescript\n * import { isPlainObject } from '@atproto/lex-data'\n *\n * isPlainObject({}) // true\n * isPlainObject({ a: 1 }) // true\n * isPlainObject(Object.create(null)) // true\n * isPlainObject([1, 2, 3]) // false\n * isPlainObject(new Date()) // false\n * isPlainObject(null) // false\n * ```\n */\nexport function isPlainObject(input: unknown) {\n return isObject(input) && isPlainProto(input)\n}\n\n/**\n * Checks whether the prototype of an object is plain (null or Object.prototype).\n *\n * This is useful for checking if an object is a plain object without\n * checking that it's non-null first (the null check is already done).\n *\n * @param input - The object to check (must be non-null)\n * @returns `true` if the object's prototype is plain\n *\n * @example\n * ```typescript\n * import { isPlainProto } from '@atproto/lex-data'\n *\n * isPlainProto({}) // true\n * isPlainProto(Object.create(null)) // true\n * isPlainProto([1, 2, 3]) // false (Array.prototype)\n * isPlainProto(new Date()) // false (Date.prototype)\n * ```\n */\nexport function isPlainProto(input: object): input is Record<string, unknown> {\n const proto = Object.getPrototypeOf(input)\n if (proto === null) return true\n return (\n (proto === ObjectProto ||\n // Needed to support NodeJS's `runInNewContext` which produces objects\n // with a different prototype\n Object.getPrototypeOf(proto) === null) &&\n ObjectToString.call(input) === '[object Object]'\n )\n}\n"]}
@@ -3,24 +3,116 @@ export type { Base64Alphabet };
3
3
  /**
4
4
  * Encodes a Uint8Array into a base64 string.
5
5
  *
6
+ * Uses native Uint8Array.prototype.toBase64 when available (Node.js 24+, modern browsers),
7
+ * falling back to Node.js Buffer or a ponyfill implementation.
8
+ *
9
+ * @param bytes - The binary data to encode
10
+ * @param alphabet - The base64 alphabet to use ('base64' or 'base64url'), defaults to 'base64'
6
11
  * @returns The base64 encoded string
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { toBase64 } from '@atproto/lex-data'
16
+ *
17
+ * const bytes = new Uint8Array([72, 101, 108, 108, 111])
18
+ * toBase64(bytes) // 'SGVsbG8='
19
+ * toBase64(bytes, 'base64url') // 'SGVsbG8' (URL-safe, no padding)
20
+ * ```
7
21
  */
8
22
  export declare const toBase64: (bytes: Uint8Array, alphabet?: Base64Alphabet) => string;
9
23
  /**
10
- * Decodes a base64 string into a Uint8Array. This function supports both padded
11
- * and unpadded base64 strings.
24
+ * Decodes a base64 string into a Uint8Array.
25
+ *
26
+ * Supports both padded and unpadded base64 strings. Uses native
27
+ * Uint8Array.fromBase64 when available, falling back to Node.js Buffer
28
+ * or a ponyfill implementation.
12
29
  *
13
- * @returns The decoded {@link Uint8Array}
30
+ * @param b64 - The base64 string to decode
31
+ * @param alphabet - The base64 alphabet to use ('base64' or 'base64url'), defaults to 'base64'
32
+ * @returns The decoded binary data
14
33
  * @throws If the input is not a valid base64 string
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * import { fromBase64 } from '@atproto/lex-data'
38
+ *
39
+ * fromBase64('SGVsbG8=') // Uint8Array([72, 101, 108, 108, 111])
40
+ * fromBase64('SGVsbG8', 'base64url') // Same, URL-safe alphabet
41
+ * ```
15
42
  */
16
43
  export declare const fromBase64: (b64: string, alphabet?: Base64Alphabet) => Uint8Array;
44
+ /**
45
+ * Returns the input if it is a Uint8Array, otherwise returns undefined.
46
+ *
47
+ * @param input - The value to check
48
+ * @returns The input if it's a Uint8Array, otherwise undefined
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * import { ifUint8Array } from '@atproto/lex-data'
53
+ *
54
+ * ifUint8Array(new Uint8Array([1, 2])) // Uint8Array([1, 2])
55
+ * ifUint8Array('not binary') // undefined
56
+ * ifUint8Array(new ArrayBuffer(4)) // undefined
57
+ * ```
58
+ */
17
59
  export declare function ifUint8Array(input: unknown): Uint8Array | undefined;
18
60
  /**
19
61
  * Coerces various binary data representations into a Uint8Array.
20
62
  *
21
- * @return `undefined` if the input could not be coerced into a {@link Uint8Array}.
63
+ * Handles the following input types:
64
+ * - `Uint8Array` - Returned as-is
65
+ * - `ArrayBufferView` (e.g., DataView, other TypedArrays) - Converted to Uint8Array
66
+ * - `ArrayBuffer` - Wrapped in a Uint8Array
67
+ *
68
+ * @param input - The value to convert
69
+ * @returns A Uint8Array, or `undefined` if the input could not be converted
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * import { asUint8Array } from '@atproto/lex-data'
74
+ *
75
+ * asUint8Array(new Uint8Array([1, 2])) // Uint8Array([1, 2])
76
+ * asUint8Array(new ArrayBuffer(4)) // Uint8Array of length 4
77
+ * asUint8Array(new Int16Array([1, 2])) // Uint8Array view of the buffer
78
+ * asUint8Array('string') // undefined
79
+ * ```
22
80
  */
23
81
  export declare function asUint8Array(input: unknown): Uint8Array | undefined;
82
+ /**
83
+ * Compares two Uint8Arrays for byte-by-byte equality.
84
+ *
85
+ * @param a - First Uint8Array to compare
86
+ * @param b - Second Uint8Array to compare
87
+ * @returns `true` if both arrays have the same length and identical bytes
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * import { ui8Equals } from '@atproto/lex-data'
92
+ *
93
+ * ui8Equals(new Uint8Array([1, 2]), new Uint8Array([1, 2])) // true
94
+ * ui8Equals(new Uint8Array([1, 2]), new Uint8Array([1, 3])) // false
95
+ * ui8Equals(new Uint8Array([1]), new Uint8Array([1, 2])) // false
96
+ * ```
97
+ */
24
98
  export declare function ui8Equals(a: Uint8Array, b: Uint8Array): boolean;
99
+ /**
100
+ * Concatenates multiple Uint8Arrays into a single Uint8Array.
101
+ *
102
+ * Uses Node.js Buffer.concat when available for performance,
103
+ * falling back to a ponyfill implementation.
104
+ *
105
+ * @param arrays - The Uint8Arrays to concatenate
106
+ * @returns A new Uint8Array containing all input bytes in order
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * import { ui8Concat } from '@atproto/lex-data'
111
+ *
112
+ * const a = new Uint8Array([1, 2])
113
+ * const b = new Uint8Array([3, 4])
114
+ * ui8Concat([a, b]) // Uint8Array([1, 2, 3, 4])
115
+ * ```
116
+ */
25
117
  export declare const ui8Concat: (array: readonly Uint8Array[]) => Uint8Array;
26
118
  //# sourceMappingURL=uint8array.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uint8array.d.ts","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAavD,YAAY,EAAE,cAAc,EAAE,CAAA;AAO9B;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,CACrB,KAAK,EAAE,UAAU,EACjB,QAAQ,CAAC,EAAE,cAAc,KACtB,MAGa,CAAA;AAElB;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,CACvB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,KACtB,UAGe,CAAA;AAUpB,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAMnE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAkBnE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAY/D;AAED,eAAO,MAAM,SAAS,8CACgD,CAAA"}
1
+ {"version":3,"file":"uint8array.d.ts","sourceRoot":"","sources":["../src/uint8array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAavD,YAAY,EAAE,cAAc,EAAE,CAAA;AAO9B;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,QAAQ,EAAE,CACrB,KAAK,EAAE,UAAU,EACjB,QAAQ,CAAC,EAAE,cAAc,KACtB,MAGa,CAAA;AAElB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,UAAU,EAAE,CACvB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,cAAc,KACtB,UAGe,CAAA;AAUpB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAMnE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAkBnE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,OAAO,CAY/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,SAAS,8CACgD,CAAA"}