@atproto/lex-data 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/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,CA4B5D;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];
@@ -37,40 +116,20 @@ function isLexValue(value) {
37
116
  const visited = new Set();
38
117
  do {
39
118
  const value = stack.pop();
40
- // Optimization: we are not using `isLexScalar` here to avoid extra function
41
- // calls, and to avoid computing `typeof value` multiple times.
42
- switch (typeof value) {
43
- case 'object':
44
- if (value === null) {
45
- // LexScalar
46
- }
47
- else if ((0, object_js_1.isPlainProto)(value)) {
48
- if (visited.has(value))
49
- return false;
50
- visited.add(value);
51
- stack.push(...Object.values(value));
52
- }
53
- else if (Array.isArray(value)) {
54
- if (visited.has(value))
55
- return false;
56
- visited.add(value);
57
- stack.push(...value);
58
- }
59
- else if (value instanceof Uint8Array || (0, cid_js_1.isCid)(value)) {
60
- // LexScalar
61
- }
62
- else {
63
- return false;
64
- }
65
- break;
66
- case 'string':
67
- case 'boolean':
68
- break;
69
- case 'number':
70
- if (Number.isInteger(value))
71
- break;
72
- // fallthrough
73
- default:
119
+ if ((0, object_js_1.isPlainObject)(value)) {
120
+ if (visited.has(value))
121
+ return false;
122
+ visited.add(value);
123
+ stack.push(...Object.values(value));
124
+ }
125
+ else if (Array.isArray(value)) {
126
+ if (visited.has(value))
127
+ return false;
128
+ visited.add(value);
129
+ stack.push(...value);
130
+ }
131
+ else {
132
+ if (!isLexScalar(value))
74
133
  return false;
75
134
  }
76
135
  } while (stack.length > 0);
@@ -78,6 +137,26 @@ function isLexValue(value) {
78
137
  visited.clear();
79
138
  return true;
80
139
  }
140
+ /**
141
+ * Type guard to check if a value is a {@link TypedLexMap}.
142
+ *
143
+ * Returns true if the value is a valid {@link LexMap} with a non-empty
144
+ * `$type` string property.
145
+ *
146
+ * @param value - The LexValue to check
147
+ * @returns `true` if the value is a TypedLexMap
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * import { isTypedLexMap } from '@atproto/lex'
152
+ *
153
+ * const data = { $type: 'app.bsky.feed.post', text: 'Hello' }
154
+ *
155
+ * if (isTypedLexMap(data)) {
156
+ * console.log(data.$type) // 'app.bsky.feed.post'
157
+ * }
158
+ * ```
159
+ */
81
160
  function isTypedLexMap(value) {
82
161
  return (isLexMap(value) && typeof value.$type === 'string' && value.$type.length > 0);
83
162
  }
package/dist/lex.js.map CHANGED
@@ -1 +1 @@
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\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":";;AA6FA,4BAEC;AAqBD,gCAEC;AAqBD,kCAaC;AAwBD,gCA4BC;AA4CD,sCAIC;AA5PD,qCAAqC;AACrC,2CAA2C;AAyE3C;;;;;;;;;;;;;;;;;;GAkBG;AACH,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;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,UAAU,CAAC,KAAc;IACvC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;AACxD,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,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;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,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,IAAI,IAAA,yBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;YACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAClB,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QACrC,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;YACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAClB,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAA;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;QACvC,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;AAwBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,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 } 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 if (isPlainObject(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 {\n if (!isLexScalar(value)) 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"]}