@hypercerts-org/sdk-core 0.9.0-beta.0 → 0.10.0-beta.1

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/lexicons.mjs CHANGED
@@ -1,410 +1,146 @@
1
- import { Lexicons } from '@atproto/lexicon';
2
- export { HYPERCERT_COLLECTIONS, HYPERCERT_LEXICONS } from '@hypercerts-org/lexicon';
1
+ import { CERTIFIED_DEFS_LEXICON_JSON, LOCATION_LEXICON_JSON, STRONGREF_LEXICON_JSON, HYPERCERTS_DEFS_LEXICON_JSON, ACTIVITY_LEXICON_JSON, COLLECTION_LEXICON_JSON, CONTRIBUTION_LEXICON_JSON, EVALUATION_LEXICON_JSON, EVIDENCE_LEXICON_JSON, MEASUREMENT_LEXICON_JSON, RIGHTS_LEXICON_JSON, PROJECT_LEXICON_JSON, BADGE_AWARD_LEXICON_JSON, BADGE_DEFINITION_LEXICON_JSON, BADGE_RESPONSE_LEXICON_JSON, FUNDING_RECEIPT_LEXICON_JSON, FUNDING_RECEIPT_NSID, BADGE_RESPONSE_NSID, BADGE_DEFINITION_NSID, BADGE_AWARD_NSID, PROJECT_NSID, COLLECTION_NSID, EVIDENCE_NSID, EVALUATION_NSID, MEASUREMENT_NSID, CONTRIBUTION_NSID, LOCATION_NSID, RIGHTS_NSID, ACTIVITY_NSID } from '@hypercerts-org/lexicon';
3
2
 
4
3
  /**
5
- * Base error class for all SDK errors.
4
+ * Lexicons entrypoint - Lexicon definitions and registry.
6
5
  *
7
- * All errors thrown by the Hypercerts SDK extend this class, making it easy
8
- * to catch and handle SDK-specific errors.
6
+ * This sub-entrypoint exports the lexicon registry and hypercert
7
+ * lexicon constants for working with AT Protocol record schemas.
9
8
  *
10
- * @example Catching all SDK errors
11
- * ```typescript
12
- * try {
13
- * await sdk.authorize("user.bsky.social");
14
- * } catch (error) {
15
- * if (error instanceof ATProtoSDKError) {
16
- * console.error(`SDK Error [${error.code}]: ${error.message}`);
17
- * console.error(`HTTP Status: ${error.status}`);
18
- * }
19
- * }
20
- * ```
9
+ * @remarks
10
+ * Import from `@hypercerts-org/sdk/lexicons`:
21
11
  *
22
- * @example Checking error codes
23
12
  * ```typescript
24
- * try {
25
- * await repo.records.get(collection, rkey);
26
- * } catch (error) {
27
- * if (error instanceof ATProtoSDKError) {
28
- * switch (error.code) {
29
- * case "AUTHENTICATION_ERROR":
30
- * // Redirect to login
31
- * break;
32
- * case "VALIDATION_ERROR":
33
- * // Show form errors
34
- * break;
35
- * case "NETWORK_ERROR":
36
- * // Retry or show offline message
37
- * break;
38
- * }
39
- * }
40
- * }
13
+ * import {
14
+ * LexiconRegistry,
15
+ * HYPERCERT_LEXICONS,
16
+ * HYPERCERT_COLLECTIONS,
17
+ * } from "@hypercerts-org/sdk/lexicons";
41
18
  * ```
42
- */
43
- class ATProtoSDKError extends Error {
44
- /**
45
- * Creates a new SDK error.
46
- *
47
- * @param message - Human-readable error description
48
- * @param code - Machine-readable error code for programmatic handling
49
- * @param status - HTTP status code associated with this error type
50
- * @param cause - The underlying error that caused this error, if any
51
- */
52
- constructor(message, code, status, cause) {
53
- super(message);
54
- this.code = code;
55
- this.status = status;
56
- this.cause = cause;
57
- this.name = "ATProtoSDKError";
58
- Error.captureStackTrace?.(this, this.constructor);
59
- }
60
- }
61
- /**
62
- * Error thrown when input validation fails.
63
19
  *
64
- * This error indicates that provided data doesn't meet the required format
65
- * or constraints. Common causes:
66
- * - Missing required fields
67
- * - Invalid URL formats
68
- * - Invalid DID format
69
- * - Schema validation failures for records
70
- * - Invalid configuration values
71
- *
72
- * @example
73
- * ```typescript
74
- * try {
75
- * await sdk.authorize(""); // Empty identifier
76
- * } catch (error) {
77
- * if (error instanceof ValidationError) {
78
- * console.error("Invalid input:", error.message);
79
- * // Show validation error to user
80
- * }
81
- * }
82
- * ```
20
+ * **Exports**:
21
+ * - {@link LexiconRegistry} - Registry for managing and validating lexicons
22
+ * - {@link HYPERCERT_LEXICONS} - Array of all hypercert lexicon documents
23
+ * - {@link HYPERCERT_COLLECTIONS} - Constants for collection NSIDs
83
24
  *
84
- * @example With Zod validation cause
25
+ * @example Using collection constants
85
26
  * ```typescript
86
- * try {
87
- * await repo.records.create(collection, record);
88
- * } catch (error) {
89
- * if (error instanceof ValidationError && error.cause) {
90
- * // error.cause may be a ZodError with detailed field errors
91
- * const zodError = error.cause as ZodError;
92
- * zodError.errors.forEach(e => {
93
- * console.error(`Field ${e.path.join(".")}: ${e.message}`);
94
- * });
95
- * }
96
- * }
97
- * ```
98
- */
99
- class ValidationError extends ATProtoSDKError {
100
- /**
101
- * Creates a validation error.
102
- *
103
- * @param message - Description of what validation failed
104
- * @param cause - The underlying validation error (e.g., ZodError)
105
- */
106
- constructor(message, cause) {
107
- super(message, "VALIDATION_ERROR", 400, cause);
108
- this.name = "ValidationError";
109
- }
110
- }
111
-
112
- /**
113
- * Registry for managing and validating AT Protocol lexicon schemas.
114
- *
115
- * Lexicons are schema definitions that describe the structure of records
116
- * in the AT Protocol. This registry allows you to:
27
+ * import { HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk/lexicons";
117
28
  *
118
- * - Register custom lexicons for your application's record types
119
- * - Validate records against their lexicon schemas
120
- * - Extend the AT Protocol Agent with custom lexicon support
121
- *
122
- * @remarks
123
- * The SDK automatically registers hypercert lexicons when creating a Repository.
124
- * You only need to use this class directly if you're working with custom
125
- * record types.
29
+ * // List hypercerts using the correct collection name
30
+ * const records = await repo.records.list({
31
+ * collection: HYPERCERT_COLLECTIONS.RECORD,
32
+ * });
126
33
  *
127
- * **Lexicon IDs** follow the NSID (Namespaced Identifier) format:
128
- * `{authority}.{name}` (e.g., `org.hypercerts.hypercert`)
34
+ * // List contributions
35
+ * const contributions = await repo.records.list({
36
+ * collection: HYPERCERT_COLLECTIONS.CONTRIBUTION,
37
+ * });
38
+ * ```
129
39
  *
130
- * @example Registering custom lexicons
40
+ * @example Custom lexicon registration
131
41
  * ```typescript
42
+ * import { LexiconRegistry } from "@hypercerts-org/sdk/lexicons";
43
+ *
132
44
  * const registry = sdk.getLexiconRegistry();
133
45
  *
134
- * // Register a single lexicon
46
+ * // Register custom lexicon
135
47
  * registry.register({
136
48
  * lexicon: 1,
137
- * id: "org.example.myRecord",
138
- * defs: {
139
- * main: {
140
- * type: "record",
141
- * key: "tid",
142
- * record: {
143
- * type: "object",
144
- * required: ["title", "createdAt"],
145
- * properties: {
146
- * title: { type: "string" },
147
- * description: { type: "string" },
148
- * createdAt: { type: "string", format: "datetime" },
149
- * },
150
- * },
151
- * },
152
- * },
153
- * });
154
- *
155
- * // Register multiple lexicons at once
156
- * registry.registerMany([lexicon1, lexicon2, lexicon3]);
157
- * ```
158
- *
159
- * @example Validating records
160
- * ```typescript
161
- * const result = registry.validate("org.example.myRecord", {
162
- * title: "Test",
163
- * createdAt: new Date().toISOString(),
49
+ * id: "org.myapp.customRecord",
50
+ * defs: { ... },
164
51
  * });
165
52
  *
53
+ * // Validate a record
54
+ * const result = registry.validate("org.myapp.customRecord", record);
166
55
  * if (!result.valid) {
167
- * console.error(`Validation failed: ${result.error}`);
56
+ * console.error(result.error);
168
57
  * }
169
58
  * ```
170
59
  *
171
- * @see https://atproto.com/specs/lexicon for the Lexicon specification
60
+ * @packageDocumentation
61
+ */
62
+ /**
63
+ * All hypercert-related lexicons for registration with AT Protocol Agent.
64
+ * This array contains all lexicon documents from the published package.
172
65
  */
173
- class LexiconRegistry {
66
+ const HYPERCERT_LEXICONS = [
67
+ CERTIFIED_DEFS_LEXICON_JSON,
68
+ LOCATION_LEXICON_JSON,
69
+ STRONGREF_LEXICON_JSON,
70
+ HYPERCERTS_DEFS_LEXICON_JSON,
71
+ ACTIVITY_LEXICON_JSON,
72
+ COLLECTION_LEXICON_JSON,
73
+ CONTRIBUTION_LEXICON_JSON,
74
+ EVALUATION_LEXICON_JSON,
75
+ EVIDENCE_LEXICON_JSON,
76
+ MEASUREMENT_LEXICON_JSON,
77
+ RIGHTS_LEXICON_JSON,
78
+ PROJECT_LEXICON_JSON,
79
+ BADGE_AWARD_LEXICON_JSON,
80
+ BADGE_DEFINITION_LEXICON_JSON,
81
+ BADGE_RESPONSE_LEXICON_JSON,
82
+ FUNDING_RECEIPT_LEXICON_JSON,
83
+ ];
84
+ /**
85
+ * Collection NSIDs (Namespaced Identifiers) for hypercert records.
86
+ *
87
+ * Use these constants when performing record operations to ensure
88
+ * correct collection names.
89
+ */
90
+ const HYPERCERT_COLLECTIONS = {
91
+ /**
92
+ * Main hypercert claim record collection.
93
+ */
94
+ CLAIM: ACTIVITY_NSID,
95
+ /**
96
+ * Rights record collection.
97
+ */
98
+ RIGHTS: RIGHTS_NSID,
99
+ /**
100
+ * Location record collection (shared certified lexicon).
101
+ */
102
+ LOCATION: LOCATION_NSID,
103
+ /**
104
+ * Contribution record collection.
105
+ */
106
+ CONTRIBUTION: CONTRIBUTION_NSID,
107
+ /**
108
+ * Measurement record collection.
109
+ */
110
+ MEASUREMENT: MEASUREMENT_NSID,
174
111
  /**
175
- * Creates a new LexiconRegistry.
176
- *
177
- * The registry starts empty. Use {@link register} or {@link registerMany}
178
- * to add lexicons.
112
+ * Evaluation record collection.
179
113
  */
180
- constructor() {
181
- /** Map of lexicon ID to lexicon document */
182
- this.lexicons = new Map();
183
- this.lexiconsCollection = new Lexicons();
184
- }
114
+ EVALUATION: EVALUATION_NSID,
185
115
  /**
186
- * Registers a single lexicon schema.
187
- *
188
- * @param lexicon - The lexicon document to register
189
- * @throws {@link ValidationError} if the lexicon doesn't have an `id` field
190
- *
191
- * @remarks
192
- * If a lexicon with the same ID is already registered, it will be
193
- * replaced with the new definition. This is useful for testing but
194
- * should generally be avoided in production.
195
- *
196
- * @example
197
- * ```typescript
198
- * registry.register({
199
- * lexicon: 1,
200
- * id: "org.example.post",
201
- * defs: {
202
- * main: {
203
- * type: "record",
204
- * key: "tid",
205
- * record: {
206
- * type: "object",
207
- * required: ["text", "createdAt"],
208
- * properties: {
209
- * text: { type: "string", maxLength: 300 },
210
- * createdAt: { type: "string", format: "datetime" },
211
- * },
212
- * },
213
- * },
214
- * },
215
- * });
216
- * ```
116
+ * Evidence record collection.
217
117
  */
218
- register(lexicon) {
219
- if (!lexicon.id) {
220
- throw new ValidationError("Lexicon must have an 'id' field");
221
- }
222
- // Remove existing lexicon if present (to allow overwriting)
223
- if (this.lexicons.has(lexicon.id)) {
224
- // Lexicons collection doesn't support removal, so we create a new one
225
- // This is a limitation - in practice, lexicons shouldn't be overwritten
226
- // But we allow it for testing and flexibility
227
- const existingLexicon = this.lexicons.get(lexicon.id);
228
- if (existingLexicon) {
229
- // Try to remove from collection (may fail if not supported)
230
- try {
231
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
232
- this.lexiconsCollection.remove?.(lexicon.id);
233
- }
234
- catch {
235
- // If removal fails, create a new collection
236
- this.lexiconsCollection = new Lexicons();
237
- // Re-register all other lexicons
238
- for (const [id, lex] of this.lexicons.entries()) {
239
- if (id !== lexicon.id) {
240
- this.lexiconsCollection.add(lex);
241
- }
242
- }
243
- }
244
- }
245
- }
246
- this.lexicons.set(lexicon.id, lexicon);
247
- this.lexiconsCollection.add(lexicon);
248
- }
118
+ EVIDENCE: EVIDENCE_NSID,
249
119
  /**
250
- * Registers multiple lexicons at once.
251
- *
252
- * @param lexicons - Array of lexicon documents to register
253
- *
254
- * @example
255
- * ```typescript
256
- * import { HYPERCERT_LEXICONS } from "@hypercerts-org/sdk/lexicons";
257
- *
258
- * registry.registerMany(HYPERCERT_LEXICONS);
259
- * ```
120
+ * Collection record collection (groups of hypercerts).
260
121
  */
261
- registerMany(lexicons) {
262
- for (const lexicon of lexicons) {
263
- this.register(lexicon);
264
- }
265
- }
122
+ COLLECTION: COLLECTION_NSID,
266
123
  /**
267
- * Gets a lexicon document by ID.
268
- *
269
- * @param id - The lexicon NSID (e.g., "org.hypercerts.hypercert")
270
- * @returns The lexicon document, or `undefined` if not registered
271
- *
272
- * @example
273
- * ```typescript
274
- * const lexicon = registry.get("org.hypercerts.hypercert");
275
- * if (lexicon) {
276
- * console.log(`Found lexicon: ${lexicon.id}`);
277
- * }
278
- * ```
124
+ * Project record collection.
279
125
  */
280
- get(id) {
281
- return this.lexicons.get(id);
282
- }
126
+ PROJECT: PROJECT_NSID,
283
127
  /**
284
- * Validates a record against a collection's lexicon schema.
285
- *
286
- * @param collection - The collection NSID (same as lexicon ID)
287
- * @param record - The record data to validate
288
- * @returns Validation result with `valid` boolean and optional `error` message
289
- *
290
- * @remarks
291
- * - If no lexicon is registered for the collection, validation passes
292
- * (we can't validate against unknown schemas)
293
- * - Validation checks required fields and type constraints defined
294
- * in the lexicon schema
295
- *
296
- * @example
297
- * ```typescript
298
- * const result = registry.validate("org.hypercerts.hypercert", {
299
- * title: "My Hypercert",
300
- * description: "Description...",
301
- * // ... other fields
302
- * });
303
- *
304
- * if (!result.valid) {
305
- * throw new Error(`Invalid record: ${result.error}`);
306
- * }
307
- * ```
128
+ * Badge award record collection.
308
129
  */
309
- validate(collection, record) {
310
- // Check if we have a lexicon registered for this collection
311
- // Collection format is typically "namespace.collection" (e.g., "app.bsky.feed.post")
312
- // Lexicon ID format is the same
313
- const lexiconId = collection;
314
- const lexicon = this.lexicons.get(lexiconId);
315
- if (!lexicon) {
316
- // No lexicon registered - validation passes (can't validate unknown schemas)
317
- return { valid: true };
318
- }
319
- // Check required fields if the lexicon defines them
320
- const recordDef = lexicon.defs?.record;
321
- if (recordDef && typeof recordDef === "object" && "record" in recordDef) {
322
- const recordSchema = recordDef.record;
323
- if (typeof recordSchema === "object" && "required" in recordSchema && Array.isArray(recordSchema.required)) {
324
- const recordObj = record;
325
- for (const requiredField of recordSchema.required) {
326
- if (typeof requiredField === "string" && !(requiredField in recordObj)) {
327
- return {
328
- valid: false,
329
- error: `Missing required field: ${requiredField}`,
330
- };
331
- }
332
- }
333
- }
334
- }
335
- try {
336
- this.lexiconsCollection.assertValidRecord(collection, record);
337
- return { valid: true };
338
- }
339
- catch (error) {
340
- // If error indicates lexicon not found, treat as validation pass
341
- // (the lexicon might exist in Agent's collection but not ours)
342
- const errorMessage = error instanceof Error ? error.message : String(error);
343
- if (errorMessage.includes("not found") || errorMessage.includes("Lexicon not found")) {
344
- return { valid: true };
345
- }
346
- return {
347
- valid: false,
348
- error: errorMessage,
349
- };
350
- }
351
- }
130
+ BADGE_AWARD: BADGE_AWARD_NSID,
352
131
  /**
353
- * Adds all registered lexicons to an AT Protocol Agent instance.
354
- *
355
- * This allows the Agent to understand custom lexicon types when making
356
- * API requests.
357
- *
358
- * @param agent - The Agent instance to extend
359
- *
360
- * @remarks
361
- * This is called automatically when creating a Repository. You typically
362
- * don't need to call this directly unless you're using the Agent
363
- * independently.
364
- *
365
- * @internal
132
+ * Badge definition record collection.
366
133
  */
367
- addToAgent(agent) {
368
- // Access the internal lexicons collection and merge our lexicons
369
- // The Agent's lex property is a Lexicons instance
370
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
371
- const agentLex = agent.lex;
372
- // Add each registered lexicon to the agent
373
- for (const lexicon of this.lexicons.values()) {
374
- agentLex.add(lexicon);
375
- }
376
- }
134
+ BADGE_DEFINITION: BADGE_DEFINITION_NSID,
377
135
  /**
378
- * Gets all registered lexicon IDs.
379
- *
380
- * @returns Array of lexicon NSIDs
381
- *
382
- * @example
383
- * ```typescript
384
- * const ids = registry.getRegisteredIds();
385
- * console.log(`Registered lexicons: ${ids.join(", ")}`);
386
- * ```
136
+ * Badge response record collection.
387
137
  */
388
- getRegisteredIds() {
389
- return Array.from(this.lexicons.keys());
390
- }
138
+ BADGE_RESPONSE: BADGE_RESPONSE_NSID,
391
139
  /**
392
- * Checks if a lexicon is registered.
393
- *
394
- * @param id - The lexicon NSID to check
395
- * @returns `true` if the lexicon is registered
396
- *
397
- * @example
398
- * ```typescript
399
- * if (registry.has("org.hypercerts.hypercert")) {
400
- * // Hypercert lexicon is available
401
- * }
402
- * ```
140
+ * Funding receipt record collection.
403
141
  */
404
- has(id) {
405
- return this.lexicons.has(id);
406
- }
407
- }
142
+ FUNDING_RECEIPT: FUNDING_RECEIPT_NSID,
143
+ };
408
144
 
409
- export { LexiconRegistry };
145
+ export { HYPERCERT_COLLECTIONS, HYPERCERT_LEXICONS };
410
146
  //# sourceMappingURL=lexicons.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lexicons.mjs","sources":["../src/core/errors.ts","../src/repository/LexiconRegistry.ts"],"sourcesContent":["/**\n * Base error class for all SDK errors.\n *\n * All errors thrown by the Hypercerts SDK extend this class, making it easy\n * to catch and handle SDK-specific errors.\n *\n * @example Catching all SDK errors\n * ```typescript\n * try {\n * await sdk.authorize(\"user.bsky.social\");\n * } catch (error) {\n * if (error instanceof ATProtoSDKError) {\n * console.error(`SDK Error [${error.code}]: ${error.message}`);\n * console.error(`HTTP Status: ${error.status}`);\n * }\n * }\n * ```\n *\n * @example Checking error codes\n * ```typescript\n * try {\n * await repo.records.get(collection, rkey);\n * } catch (error) {\n * if (error instanceof ATProtoSDKError) {\n * switch (error.code) {\n * case \"AUTHENTICATION_ERROR\":\n * // Redirect to login\n * break;\n * case \"VALIDATION_ERROR\":\n * // Show form errors\n * break;\n * case \"NETWORK_ERROR\":\n * // Retry or show offline message\n * break;\n * }\n * }\n * }\n * ```\n */\nexport class ATProtoSDKError extends Error {\n /**\n * Creates a new SDK error.\n *\n * @param message - Human-readable error description\n * @param code - Machine-readable error code for programmatic handling\n * @param status - HTTP status code associated with this error type\n * @param cause - The underlying error that caused this error, if any\n */\n constructor(\n message: string,\n public code: string,\n public status?: number,\n public cause?: unknown,\n ) {\n super(message);\n this.name = \"ATProtoSDKError\";\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\n\n/**\n * Error thrown when authentication fails.\n *\n * This error indicates problems with the OAuth flow, invalid credentials,\n * or failed token exchanges. Common causes:\n * - Invalid authorization code\n * - Expired or invalid state parameter\n * - Revoked or invalid tokens\n * - User denied authorization\n *\n * @example\n * ```typescript\n * try {\n * const session = await sdk.callback(params);\n * } catch (error) {\n * if (error instanceof AuthenticationError) {\n * // Clear any stored state and redirect to login\n * console.error(\"Authentication failed:\", error.message);\n * }\n * }\n * ```\n */\nexport class AuthenticationError extends ATProtoSDKError {\n /**\n * Creates an authentication error.\n *\n * @param message - Description of what went wrong during authentication\n * @param cause - The underlying error (e.g., from the OAuth client)\n */\n constructor(message: string, cause?: unknown) {\n super(message, \"AUTHENTICATION_ERROR\", 401, cause);\n this.name = \"AuthenticationError\";\n }\n}\n\n/**\n * Error thrown when a session has expired and cannot be refreshed.\n *\n * This typically occurs when:\n * - The refresh token has expired (usually after extended inactivity)\n * - The user has revoked access to your application\n * - The PDS has invalidated all sessions for the user\n *\n * When this error occurs, the user must re-authenticate.\n *\n * @example\n * ```typescript\n * try {\n * const session = await sdk.restoreSession(did);\n * } catch (error) {\n * if (error instanceof SessionExpiredError) {\n * // Clear stored session and prompt user to log in again\n * localStorage.removeItem(\"userDid\");\n * window.location.href = \"/login\";\n * }\n * }\n * ```\n */\nexport class SessionExpiredError extends ATProtoSDKError {\n /**\n * Creates a session expired error.\n *\n * @param message - Description of why the session expired\n * @param cause - The underlying error from the token refresh attempt\n */\n constructor(message: string = \"Session expired\", cause?: unknown) {\n super(message, \"SESSION_EXPIRED\", 401, cause);\n this.name = \"SessionExpiredError\";\n }\n}\n\n/**\n * Error thrown when input validation fails.\n *\n * This error indicates that provided data doesn't meet the required format\n * or constraints. Common causes:\n * - Missing required fields\n * - Invalid URL formats\n * - Invalid DID format\n * - Schema validation failures for records\n * - Invalid configuration values\n *\n * @example\n * ```typescript\n * try {\n * await sdk.authorize(\"\"); // Empty identifier\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Invalid input:\", error.message);\n * // Show validation error to user\n * }\n * }\n * ```\n *\n * @example With Zod validation cause\n * ```typescript\n * try {\n * await repo.records.create(collection, record);\n * } catch (error) {\n * if (error instanceof ValidationError && error.cause) {\n * // error.cause may be a ZodError with detailed field errors\n * const zodError = error.cause as ZodError;\n * zodError.errors.forEach(e => {\n * console.error(`Field ${e.path.join(\".\")}: ${e.message}`);\n * });\n * }\n * }\n * ```\n */\nexport class ValidationError extends ATProtoSDKError {\n /**\n * Creates a validation error.\n *\n * @param message - Description of what validation failed\n * @param cause - The underlying validation error (e.g., ZodError)\n */\n constructor(message: string, cause?: unknown) {\n super(message, \"VALIDATION_ERROR\", 400, cause);\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Error thrown when a network request fails.\n *\n * This error indicates connectivity issues or server unavailability.\n * Common causes:\n * - No internet connection\n * - DNS resolution failure\n * - Server timeout\n * - Server returned 5xx error\n * - TLS/SSL errors\n *\n * These errors are typically transient and may succeed on retry.\n *\n * @example\n * ```typescript\n * try {\n * await repo.records.list(collection);\n * } catch (error) {\n * if (error instanceof NetworkError) {\n * // Implement retry logic or show offline indicator\n * console.error(\"Network error:\", error.message);\n * await retryWithBackoff(() => repo.records.list(collection));\n * }\n * }\n * ```\n */\nexport class NetworkError extends ATProtoSDKError {\n /**\n * Creates a network error.\n *\n * @param message - Description of the network failure\n * @param cause - The underlying error (e.g., fetch error, timeout)\n */\n constructor(message: string, cause?: unknown) {\n super(message, \"NETWORK_ERROR\", 503, cause);\n this.name = \"NetworkError\";\n }\n}\n\n/**\n * Error thrown when an SDS-only operation is attempted on a PDS.\n *\n * Certain operations are only available on Shared Data Servers (SDS),\n * such as collaborator management and organization operations.\n * This error is thrown when these operations are attempted on a\n * Personal Data Server (PDS).\n *\n * @example\n * ```typescript\n * const pdsRepo = sdk.repository(session); // Default is PDS\n *\n * try {\n * // This will throw SDSRequiredError\n * await pdsRepo.collaborators.list();\n * } catch (error) {\n * if (error instanceof SDSRequiredError) {\n * // Switch to SDS for this operation\n * const sdsRepo = sdk.repository(session, { server: \"sds\" });\n * const collaborators = await sdsRepo.collaborators.list();\n * }\n * }\n * ```\n */\nexport class SDSRequiredError extends ATProtoSDKError {\n /**\n * Creates an SDS required error.\n *\n * @param message - Description of which operation requires SDS\n * @param cause - Any underlying error\n */\n constructor(message: string = \"This operation requires a Shared Data Server (SDS)\", cause?: unknown) {\n super(message, \"SDS_REQUIRED\", 400, cause);\n this.name = \"SDSRequiredError\";\n }\n}\n","import type { Agent } from \"@atproto/api\";\nimport type { LexiconDoc } from \"@atproto/lexicon\";\nimport { Lexicons } from \"@atproto/lexicon\";\nimport { ValidationError } from \"../core/errors.js\";\n\n/**\n * Result of validating a record against a lexicon schema.\n */\nexport interface ValidationResult {\n /**\n * Whether the record is valid according to the lexicon schema.\n */\n valid: boolean;\n\n /**\n * Error message if validation failed.\n *\n * Only present when `valid` is `false`.\n */\n error?: string;\n}\n\n/**\n * Registry for managing and validating AT Protocol lexicon schemas.\n *\n * Lexicons are schema definitions that describe the structure of records\n * in the AT Protocol. This registry allows you to:\n *\n * - Register custom lexicons for your application's record types\n * - Validate records against their lexicon schemas\n * - Extend the AT Protocol Agent with custom lexicon support\n *\n * @remarks\n * The SDK automatically registers hypercert lexicons when creating a Repository.\n * You only need to use this class directly if you're working with custom\n * record types.\n *\n * **Lexicon IDs** follow the NSID (Namespaced Identifier) format:\n * `{authority}.{name}` (e.g., `org.hypercerts.hypercert`)\n *\n * @example Registering custom lexicons\n * ```typescript\n * const registry = sdk.getLexiconRegistry();\n *\n * // Register a single lexicon\n * registry.register({\n * lexicon: 1,\n * id: \"org.example.myRecord\",\n * defs: {\n * main: {\n * type: \"record\",\n * key: \"tid\",\n * record: {\n * type: \"object\",\n * required: [\"title\", \"createdAt\"],\n * properties: {\n * title: { type: \"string\" },\n * description: { type: \"string\" },\n * createdAt: { type: \"string\", format: \"datetime\" },\n * },\n * },\n * },\n * },\n * });\n *\n * // Register multiple lexicons at once\n * registry.registerMany([lexicon1, lexicon2, lexicon3]);\n * ```\n *\n * @example Validating records\n * ```typescript\n * const result = registry.validate(\"org.example.myRecord\", {\n * title: \"Test\",\n * createdAt: new Date().toISOString(),\n * });\n *\n * if (!result.valid) {\n * console.error(`Validation failed: ${result.error}`);\n * }\n * ```\n *\n * @see https://atproto.com/specs/lexicon for the Lexicon specification\n */\nexport class LexiconRegistry {\n /** Map of lexicon ID to lexicon document */\n private lexicons = new Map<string, LexiconDoc>();\n\n /** Lexicons collection for validation */\n private lexiconsCollection: Lexicons;\n\n /**\n * Creates a new LexiconRegistry.\n *\n * The registry starts empty. Use {@link register} or {@link registerMany}\n * to add lexicons.\n */\n constructor() {\n this.lexiconsCollection = new Lexicons();\n }\n\n /**\n * Registers a single lexicon schema.\n *\n * @param lexicon - The lexicon document to register\n * @throws {@link ValidationError} if the lexicon doesn't have an `id` field\n *\n * @remarks\n * If a lexicon with the same ID is already registered, it will be\n * replaced with the new definition. This is useful for testing but\n * should generally be avoided in production.\n *\n * @example\n * ```typescript\n * registry.register({\n * lexicon: 1,\n * id: \"org.example.post\",\n * defs: {\n * main: {\n * type: \"record\",\n * key: \"tid\",\n * record: {\n * type: \"object\",\n * required: [\"text\", \"createdAt\"],\n * properties: {\n * text: { type: \"string\", maxLength: 300 },\n * createdAt: { type: \"string\", format: \"datetime\" },\n * },\n * },\n * },\n * },\n * });\n * ```\n */\n register(lexicon: LexiconDoc): void {\n if (!lexicon.id) {\n throw new ValidationError(\"Lexicon must have an 'id' field\");\n }\n\n // Remove existing lexicon if present (to allow overwriting)\n if (this.lexicons.has(lexicon.id)) {\n // Lexicons collection doesn't support removal, so we create a new one\n // This is a limitation - in practice, lexicons shouldn't be overwritten\n // But we allow it for testing and flexibility\n const existingLexicon = this.lexicons.get(lexicon.id);\n if (existingLexicon) {\n // Try to remove from collection (may fail if not supported)\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this.lexiconsCollection as any).remove?.(lexicon.id);\n } catch {\n // If removal fails, create a new collection\n this.lexiconsCollection = new Lexicons();\n // Re-register all other lexicons\n for (const [id, lex] of this.lexicons.entries()) {\n if (id !== lexicon.id) {\n this.lexiconsCollection.add(lex);\n }\n }\n }\n }\n }\n\n this.lexicons.set(lexicon.id, lexicon);\n this.lexiconsCollection.add(lexicon);\n }\n\n /**\n * Registers multiple lexicons at once.\n *\n * @param lexicons - Array of lexicon documents to register\n *\n * @example\n * ```typescript\n * import { HYPERCERT_LEXICONS } from \"@hypercerts-org/sdk/lexicons\";\n *\n * registry.registerMany(HYPERCERT_LEXICONS);\n * ```\n */\n registerMany(lexicons: LexiconDoc[]): void {\n for (const lexicon of lexicons) {\n this.register(lexicon);\n }\n }\n\n /**\n * Gets a lexicon document by ID.\n *\n * @param id - The lexicon NSID (e.g., \"org.hypercerts.hypercert\")\n * @returns The lexicon document, or `undefined` if not registered\n *\n * @example\n * ```typescript\n * const lexicon = registry.get(\"org.hypercerts.hypercert\");\n * if (lexicon) {\n * console.log(`Found lexicon: ${lexicon.id}`);\n * }\n * ```\n */\n get(id: string): LexiconDoc | undefined {\n return this.lexicons.get(id);\n }\n\n /**\n * Validates a record against a collection's lexicon schema.\n *\n * @param collection - The collection NSID (same as lexicon ID)\n * @param record - The record data to validate\n * @returns Validation result with `valid` boolean and optional `error` message\n *\n * @remarks\n * - If no lexicon is registered for the collection, validation passes\n * (we can't validate against unknown schemas)\n * - Validation checks required fields and type constraints defined\n * in the lexicon schema\n *\n * @example\n * ```typescript\n * const result = registry.validate(\"org.hypercerts.hypercert\", {\n * title: \"My Hypercert\",\n * description: \"Description...\",\n * // ... other fields\n * });\n *\n * if (!result.valid) {\n * throw new Error(`Invalid record: ${result.error}`);\n * }\n * ```\n */\n validate(collection: string, record: unknown): ValidationResult {\n // Check if we have a lexicon registered for this collection\n // Collection format is typically \"namespace.collection\" (e.g., \"app.bsky.feed.post\")\n // Lexicon ID format is the same\n const lexiconId = collection;\n const lexicon = this.lexicons.get(lexiconId);\n if (!lexicon) {\n // No lexicon registered - validation passes (can't validate unknown schemas)\n return { valid: true };\n }\n\n // Check required fields if the lexicon defines them\n const recordDef = lexicon.defs?.record;\n if (recordDef && typeof recordDef === \"object\" && \"record\" in recordDef) {\n const recordSchema = recordDef.record;\n if (typeof recordSchema === \"object\" && \"required\" in recordSchema && Array.isArray(recordSchema.required)) {\n const recordObj = record as Record<string, unknown>;\n for (const requiredField of recordSchema.required) {\n if (typeof requiredField === \"string\" && !(requiredField in recordObj)) {\n return {\n valid: false,\n error: `Missing required field: ${requiredField}`,\n };\n }\n }\n }\n }\n\n try {\n this.lexiconsCollection.assertValidRecord(collection, record);\n return { valid: true };\n } catch (error) {\n // If error indicates lexicon not found, treat as validation pass\n // (the lexicon might exist in Agent's collection but not ours)\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"not found\") || errorMessage.includes(\"Lexicon not found\")) {\n return { valid: true };\n }\n return {\n valid: false,\n error: errorMessage,\n };\n }\n }\n\n /**\n * Adds all registered lexicons to an AT Protocol Agent instance.\n *\n * This allows the Agent to understand custom lexicon types when making\n * API requests.\n *\n * @param agent - The Agent instance to extend\n *\n * @remarks\n * This is called automatically when creating a Repository. You typically\n * don't need to call this directly unless you're using the Agent\n * independently.\n *\n * @internal\n */\n addToAgent(agent: Agent): void {\n // Access the internal lexicons collection and merge our lexicons\n // The Agent's lex property is a Lexicons instance\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const agentLex = (agent as any).lex as Lexicons;\n\n // Add each registered lexicon to the agent\n for (const lexicon of this.lexicons.values()) {\n agentLex.add(lexicon);\n }\n }\n\n /**\n * Gets all registered lexicon IDs.\n *\n * @returns Array of lexicon NSIDs\n *\n * @example\n * ```typescript\n * const ids = registry.getRegisteredIds();\n * console.log(`Registered lexicons: ${ids.join(\", \")}`);\n * ```\n */\n getRegisteredIds(): string[] {\n return Array.from(this.lexicons.keys());\n }\n\n /**\n * Checks if a lexicon is registered.\n *\n * @param id - The lexicon NSID to check\n * @returns `true` if the lexicon is registered\n *\n * @example\n * ```typescript\n * if (registry.has(\"org.hypercerts.hypercert\")) {\n * // Hypercert lexicon is available\n * }\n * ```\n */\n has(id: string): boolean {\n return this.lexicons.has(id);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lexicons.mjs","sources":["../src/lexicons.ts"],"sourcesContent":["/**\n * Lexicons entrypoint - Lexicon definitions and registry.\n *\n * This sub-entrypoint exports the lexicon registry and hypercert\n * lexicon constants for working with AT Protocol record schemas.\n *\n * @remarks\n * Import from `@hypercerts-org/sdk/lexicons`:\n *\n * ```typescript\n * import {\n * LexiconRegistry,\n * HYPERCERT_LEXICONS,\n * HYPERCERT_COLLECTIONS,\n * } from \"@hypercerts-org/sdk/lexicons\";\n * ```\n *\n * **Exports**:\n * - {@link LexiconRegistry} - Registry for managing and validating lexicons\n * - {@link HYPERCERT_LEXICONS} - Array of all hypercert lexicon documents\n * - {@link HYPERCERT_COLLECTIONS} - Constants for collection NSIDs\n *\n * @example Using collection constants\n * ```typescript\n * import { HYPERCERT_COLLECTIONS } from \"@hypercerts-org/sdk/lexicons\";\n *\n * // List hypercerts using the correct collection name\n * const records = await repo.records.list({\n * collection: HYPERCERT_COLLECTIONS.RECORD,\n * });\n *\n * // List contributions\n * const contributions = await repo.records.list({\n * collection: HYPERCERT_COLLECTIONS.CONTRIBUTION,\n * });\n * ```\n *\n * @example Custom lexicon registration\n * ```typescript\n * import { LexiconRegistry } from \"@hypercerts-org/sdk/lexicons\";\n *\n * const registry = sdk.getLexiconRegistry();\n *\n * // Register custom lexicon\n * registry.register({\n * lexicon: 1,\n * id: \"org.myapp.customRecord\",\n * defs: { ... },\n * });\n *\n * // Validate a record\n * const result = registry.validate(\"org.myapp.customRecord\", record);\n * if (!result.valid) {\n * console.error(result.error);\n * }\n * ```\n *\n * @packageDocumentation\n */\n\n// Import lexicon JSON files and constants from the published package\nimport type { LexiconDoc } from \"@atproto/lexicon\";\nimport {\n CERTIFIED_DEFS_LEXICON_JSON,\n LOCATION_LEXICON_JSON,\n STRONGREF_LEXICON_JSON,\n HYPERCERTS_DEFS_LEXICON_JSON,\n ACTIVITY_LEXICON_JSON,\n COLLECTION_LEXICON_JSON,\n CONTRIBUTION_LEXICON_JSON,\n EVALUATION_LEXICON_JSON,\n EVIDENCE_LEXICON_JSON,\n MEASUREMENT_LEXICON_JSON,\n RIGHTS_LEXICON_JSON,\n PROJECT_LEXICON_JSON,\n BADGE_AWARD_LEXICON_JSON,\n BADGE_DEFINITION_LEXICON_JSON,\n BADGE_RESPONSE_LEXICON_JSON,\n FUNDING_RECEIPT_LEXICON_JSON,\n // NSID constants\n ACTIVITY_NSID,\n RIGHTS_NSID,\n LOCATION_NSID,\n CONTRIBUTION_NSID,\n MEASUREMENT_NSID,\n EVALUATION_NSID,\n EVIDENCE_NSID,\n COLLECTION_NSID,\n PROJECT_NSID,\n BADGE_AWARD_NSID,\n BADGE_DEFINITION_NSID,\n BADGE_RESPONSE_NSID,\n FUNDING_RECEIPT_NSID,\n} from \"@hypercerts-org/lexicon\";\n\n/**\n * All hypercert-related lexicons for registration with AT Protocol Agent.\n * This array contains all lexicon documents from the published package.\n */\nexport const HYPERCERT_LEXICONS: LexiconDoc[] = [\n CERTIFIED_DEFS_LEXICON_JSON as LexiconDoc,\n LOCATION_LEXICON_JSON as LexiconDoc,\n STRONGREF_LEXICON_JSON as LexiconDoc,\n HYPERCERTS_DEFS_LEXICON_JSON as LexiconDoc,\n ACTIVITY_LEXICON_JSON as LexiconDoc,\n COLLECTION_LEXICON_JSON as LexiconDoc,\n CONTRIBUTION_LEXICON_JSON as LexiconDoc,\n EVALUATION_LEXICON_JSON as LexiconDoc,\n EVIDENCE_LEXICON_JSON as LexiconDoc,\n MEASUREMENT_LEXICON_JSON as LexiconDoc,\n RIGHTS_LEXICON_JSON as LexiconDoc,\n PROJECT_LEXICON_JSON as LexiconDoc,\n BADGE_AWARD_LEXICON_JSON as LexiconDoc,\n BADGE_DEFINITION_LEXICON_JSON as LexiconDoc,\n BADGE_RESPONSE_LEXICON_JSON as LexiconDoc,\n FUNDING_RECEIPT_LEXICON_JSON as LexiconDoc,\n];\n\n/**\n * Collection NSIDs (Namespaced Identifiers) for hypercert records.\n *\n * Use these constants when performing record operations to ensure\n * correct collection names.\n */\nexport const HYPERCERT_COLLECTIONS = {\n /**\n * Main hypercert claim record collection.\n */\n CLAIM: ACTIVITY_NSID,\n\n /**\n * Rights record collection.\n */\n RIGHTS: RIGHTS_NSID,\n\n /**\n * Location record collection (shared certified lexicon).\n */\n LOCATION: LOCATION_NSID,\n\n /**\n * Contribution record collection.\n */\n CONTRIBUTION: CONTRIBUTION_NSID,\n\n /**\n * Measurement record collection.\n */\n MEASUREMENT: MEASUREMENT_NSID,\n\n /**\n * Evaluation record collection.\n */\n EVALUATION: EVALUATION_NSID,\n\n /**\n * Evidence record collection.\n */\n EVIDENCE: EVIDENCE_NSID,\n\n /**\n * Collection record collection (groups of hypercerts).\n */\n COLLECTION: COLLECTION_NSID,\n\n /**\n * Project record collection.\n */\n PROJECT: PROJECT_NSID,\n\n /**\n * Badge award record collection.\n */\n BADGE_AWARD: BADGE_AWARD_NSID,\n\n /**\n * Badge definition record collection.\n */\n BADGE_DEFINITION: BADGE_DEFINITION_NSID,\n\n /**\n * Badge response record collection.\n */\n BADGE_RESPONSE: BADGE_RESPONSE_NSID,\n\n /**\n * Funding receipt record collection.\n */\n FUNDING_RECEIPT: FUNDING_RECEIPT_NSID,\n} as const;\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DG;AAqCH;;;AAGG;AACI,MAAM,kBAAkB,GAAiB;IAC9C,2BAAyC;IACzC,qBAAmC;IACnC,sBAAoC;IACpC,4BAA0C;IAC1C,qBAAmC;IACnC,uBAAqC;IACrC,yBAAuC;IACvC,uBAAqC;IACrC,qBAAmC;IACnC,wBAAsC;IACtC,mBAAiC;IACjC,oBAAkC;IAClC,wBAAsC;IACtC,6BAA2C;IAC3C,2BAAyC;IACzC,4BAA0C;;AAG5C;;;;;AAKG;AACI,MAAM,qBAAqB,GAAG;AACnC;;AAEG;AACH,IAAA,KAAK,EAAE,aAAa;AAEpB;;AAEG;AACH,IAAA,MAAM,EAAE,WAAW;AAEnB;;AAEG;AACH,IAAA,QAAQ,EAAE,aAAa;AAEvB;;AAEG;AACH,IAAA,YAAY,EAAE,iBAAiB;AAE/B;;AAEG;AACH,IAAA,WAAW,EAAE,gBAAgB;AAE7B;;AAEG;AACH,IAAA,UAAU,EAAE,eAAe;AAE3B;;AAEG;AACH,IAAA,QAAQ,EAAE,aAAa;AAEvB;;AAEG;AACH,IAAA,UAAU,EAAE,eAAe;AAE3B;;AAEG;AACH,IAAA,OAAO,EAAE,YAAY;AAErB;;AAEG;AACH,IAAA,WAAW,EAAE,gBAAgB;AAE7B;;AAEG;AACH,IAAA,gBAAgB,EAAE,qBAAqB;AAEvC;;AAEG;AACH,IAAA,cAAc,EAAE,mBAAmB;AAEnC;;AAEG;AACH,IAAA,eAAe,EAAE,oBAAoB;;;;;"}
package/dist/testing.d.ts CHANGED
@@ -366,7 +366,32 @@ declare const OAuthConfigSchema: z.ZodObject<{
366
366
  redirectUri: z.ZodString;
367
367
  /**
368
368
  * OAuth scopes to request, space-separated.
369
- * Common scopes: "atproto", "transition:generic"
369
+ *
370
+ * Can be a string of space-separated permissions or use the permission system:
371
+ *
372
+ * @example Using presets
373
+ * ```typescript
374
+ * import { ScopePresets } from '@hypercerts-org/sdk-core';
375
+ * scope: ScopePresets.EMAIL_AND_PROFILE
376
+ * ```
377
+ *
378
+ * @example Building custom scopes
379
+ * ```typescript
380
+ * import { PermissionBuilder, buildScope } from '@hypercerts-org/sdk-core';
381
+ * scope: buildScope(
382
+ * new PermissionBuilder()
383
+ * .accountEmail('read')
384
+ * .repoWrite('app.bsky.feed.post')
385
+ * .build()
386
+ * )
387
+ * ```
388
+ *
389
+ * @example Legacy scopes
390
+ * ```typescript
391
+ * scope: "atproto transition:generic"
392
+ * ```
393
+ *
394
+ * @see https://atproto.com/specs/permission for permission details
370
395
  */
371
396
  scope: z.ZodString;
372
397
  /**
package/dist/types.cjs CHANGED
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var zod = require('zod');
4
+ var lexicon = require('@atproto/lexicon');
5
+ require('@hypercerts-org/lexicon');
4
6
 
5
7
  /**
6
8
  * Zod schema for OAuth configuration validation.
@@ -24,9 +26,34 @@ const OAuthConfigSchema = zod.z.object({
24
26
  redirectUri: zod.z.string().url(),
25
27
  /**
26
28
  * OAuth scopes to request, space-separated.
27
- * Common scopes: "atproto", "transition:generic"
29
+ *
30
+ * Can be a string of space-separated permissions or use the permission system:
31
+ *
32
+ * @example Using presets
33
+ * ```typescript
34
+ * import { ScopePresets } from '@hypercerts-org/sdk-core';
35
+ * scope: ScopePresets.EMAIL_AND_PROFILE
36
+ * ```
37
+ *
38
+ * @example Building custom scopes
39
+ * ```typescript
40
+ * import { PermissionBuilder, buildScope } from '@hypercerts-org/sdk-core';
41
+ * scope: buildScope(
42
+ * new PermissionBuilder()
43
+ * .accountEmail('read')
44
+ * .repoWrite('app.bsky.feed.post')
45
+ * .build()
46
+ * )
47
+ * ```
48
+ *
49
+ * @example Legacy scopes
50
+ * ```typescript
51
+ * scope: "atproto transition:generic"
52
+ * ```
53
+ *
54
+ * @see https://atproto.com/specs/permission for permission details
28
55
  */
29
- scope: zod.z.string(),
56
+ scope: zod.z.string().min(1, "OAuth scope is required"),
30
57
  /**
31
58
  * URL to your public JWKS (JSON Web Key Set) endpoint.
32
59
  * Used by the authorization server to verify your client's signatures.
@@ -211,6 +238,10 @@ const CollaboratorSchema = zod.z.object({
211
238
  revokedAt: zod.z.string().optional(),
212
239
  });
213
240
 
241
+ Object.defineProperty(exports, "BlobRef", {
242
+ enumerable: true,
243
+ get: function () { return lexicon.BlobRef; }
244
+ });
214
245
  exports.ATProtoSDKConfigSchema = ATProtoSDKConfigSchema;
215
246
  exports.CollaboratorPermissionsSchema = CollaboratorPermissionsSchema;
216
247
  exports.CollaboratorSchema = CollaboratorSchema;