@hypercerts-org/sdk-core 0.10.0-beta.4 → 0.10.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,231 @@
1
1
  # @hypercerts-org/sdk-core
2
2
 
3
+ ## 0.10.0-beta.6
4
+
5
+ ### Minor Changes
6
+
7
+ - [#101](https://github.com/hypercerts-org/hypercerts-sdk/pull/101)
8
+ [`bf93b3c`](https://github.com/hypercerts-org/hypercerts-sdk/commit/bf93b3cf5d5eccb12de31c4fe6f95ed3676c746e) Thanks
9
+ [@aspiers](https://github.com/aspiers)! - feat: align collection/project types with lexicon + add inline location
10
+ support
11
+
12
+ This is a BREAKING change.
13
+
14
+ **Type Alignment with Lexicon:**
15
+ - Changed `createCollection` to use lexicon-aligned `items` array instead of `claims`
16
+ - Updated avatar/banner handling to use proper lexicon union types
17
+ - Simplified project methods to delegate to collection methods
18
+ - Added `CreateCollectionParams`, `UpdateCollectionParams`, and result types derived from lexicon
19
+ - Improved type safety by deriving SDK input types from lexicon definitions
20
+
21
+ **Inline Location Support:**
22
+
23
+ `AttachLocationParams` now supports three ways to specify location:
24
+ 1. **StrongRef** - Direct reference with uri and cid (no record creation)
25
+ 2. **AT-URI string** - Reference to existing location record
26
+ 3. **Location object** - Full location data to create a new location record
27
+
28
+ **Changes:**
29
+ - Add `AttachLocationParams` union type supporting StrongRef, string URI, or location object
30
+ - Add optional `location` field to `CreateCollectionParams`
31
+ - Add optional `location` field to `UpdateCollectionParams` (supports `null` to remove)
32
+ - Update `CreateCollectionResult` to include optional `locationUri` field
33
+ - Implement location handling in `createCollection()` - supports all three forms
34
+ - Add tests for collection creation with StrongRef, string URI, and location object
35
+
36
+ **Example Usage:**
37
+
38
+ ```typescript
39
+ // Create a project with location (StrongRef - direct reference)
40
+ const project = await repo.hypercerts.createProject({
41
+ title: "Climate Initiative",
42
+ items: [...],
43
+ location: { uri: "at://did:plc:alice/app.certified.location/abc", cid: "bafy..." },
44
+ });
45
+
46
+ // Create with location (AT-URI string - fetches CID)
47
+ const project2 = await repo.hypercerts.createProject({
48
+ title: "Forest Project",
49
+ items: [...],
50
+ location: "at://did:plc:bob/app.certified.location/xyz",
51
+ });
52
+
53
+ // Create with location (location object - creates new record)
54
+ const project3 = await repo.hypercerts.createProject({
55
+ title: "Ocean Project",
56
+ items: [...],
57
+ location: {
58
+ lpVersion: "1.0",
59
+ srs: "EPSG:4326",
60
+ locationType: "coordinate-decimal",
61
+ location: "37.7749, -122.4194",
62
+ },
63
+ });
64
+
65
+ // Update project to change location
66
+ await repo.hypercerts.updateProject(project.uri, {
67
+ location: "at://did:plc:alice/app.certified.location/new",
68
+ });
69
+
70
+ // Remove location
71
+ await repo.hypercerts.updateProject(project.uri, {
72
+ location: null,
73
+ });
74
+ ```
75
+
76
+ ## 0.10.0-beta.5
77
+
78
+ ### Minor Changes
79
+
80
+ - [#87](https://github.com/hypercerts-org/hypercerts-sdk/pull/87)
81
+ [`85b1350`](https://github.com/hypercerts-org/hypercerts-sdk/commit/85b13502791e49966dae3d0dd0e833905c59abe3) Thanks
82
+ [@bitbeckers](https://github.com/bitbeckers)! - Add comprehensive project support to SDK
83
+
84
+ **Core SDK (`@hypercerts-org/sdk-core`):**
85
+ - Add project CRUD operations (createProject, getProject, listProjects, updateProject, deleteProject)
86
+ - Add project events (projectCreated, projectUpdated, projectDeleted)
87
+ - Support for avatar and coverPhoto blob uploads
88
+ - Activities array with weight values
89
+ - Location reference support
90
+ - 34 comprehensive tests with full coverage
91
+
92
+ **React SDK (`@hypercerts-org/sdk-react`):**
93
+ - Add useProjects and useProject hooks
94
+ - Project query keys for cache management
95
+ - TypeScript types for projects (Project, CreateProjectParams, UpdateProjectParams)
96
+ - Test factory support for project hooks
97
+ - Full pagination and optimistic updates support
98
+
99
+ Projects organize multiple hypercert activities with metadata including title, shortDescription, description (Leaflet
100
+ documents), avatar, cover photo, activities with weights, and location references.
101
+
102
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
103
+ [`f9dd27f`](https://github.com/hypercerts-org/hypercerts-sdk/commit/f9dd27f78de0ee49aab9079e76566f272b161cd0) Thanks
104
+ [@bitbeckers](https://github.com/bitbeckers)! - Add BaseOperations abstract class for building custom lexicon
105
+ operations. Developers can now extend BaseOperations to create type-safe, validated operation classes for their custom
106
+ lexicons, with built-in helpers for record creation, validation, and strongRef management.
107
+
108
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
109
+ [`e850310`](https://github.com/hypercerts-org/hypercerts-sdk/commit/e850310d26e0561bdcfb778a6ef3bedbb7453eed) Thanks
110
+ [@bitbeckers](https://github.com/bitbeckers)! - Add comprehensive documentation and examples for custom lexicons.
111
+ Includes custom-lexicons.md guide, sidecar-pattern.md guide, and a complete working example with tests demonstrating
112
+ how to create and use custom lexicons for evaluating hypercerts.
113
+
114
+ - [#84](https://github.com/hypercerts-org/hypercerts-sdk/pull/84)
115
+ [`3157c18`](https://github.com/hypercerts-org/hypercerts-sdk/commit/3157c188c70e2f9473ee14eddaf635e3fbd346a1) Thanks
116
+ [@Kzoeps](https://github.com/Kzoeps)! - Evidence records are now created separately instead of being embedded inline
117
+ in hypercerts
118
+ - `create()` now calls `addEvidence()` for each evidence item using `Promise.all()` for parallel creation
119
+ - Remove inline evidence embedding from hypercert records
120
+ - Add `evidenceUris?: string[]` to `CreateHypercertResult` interface
121
+ - Add `createEvidenceWithProgress()` helper method with "addEvidence" progress tracking
122
+ - `addEvidence()` SDK constructs `$type`, `createdAt`, and `subject` fields internally
123
+
124
+ **Breaking Changes:**
125
+ - Evidence is no longer embedded in the hypercert record - use `result.evidenceUris` to access evidence record URIs
126
+ - `addEvidence()` now accepts a single `CreateHypercertEvidenceParams` object instead of
127
+ `(uri: string, evidence: HypercertEvidence[])`
128
+
129
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
130
+ [`0cd3b26`](https://github.com/hypercerts-org/hypercerts-sdk/commit/0cd3b26eb779246e9ef094f614f2f77807926f1b) Thanks
131
+ [@bitbeckers](https://github.com/bitbeckers)! - Add LexiconRegistry for custom lexicon management. Developers can now
132
+ register custom lexicon schemas at runtime and validate records against registered schemas before creation. The
133
+ registry supports:
134
+ - Registering custom lexicon definitions from JSON
135
+ - Validating records against registered schemas
136
+ - Querying registered lexicons
137
+ - Managing lexicon lifecycle (register/unregister)
138
+
139
+ This enables developers to extend the SDK with custom record types that can reference hypercerts and other records
140
+ using strongRefs.
141
+
142
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
143
+ [`b87cb22`](https://github.com/hypercerts-org/hypercerts-sdk/commit/b87cb2265d924b531eef8d58c669dc931b61e561) Thanks
144
+ [@bitbeckers](https://github.com/bitbeckers)! - Add lexicon development utilities for custom lexicons. Developers can
145
+ now use helper functions for AT-URI parsing, strongRef creation, lexicon schema building, and sidecar pattern
146
+ implementation. This includes:
147
+ - AT-URI utilities: parseAtUri, buildAtUri, extractRkeyFromUri, isValidAtUri
148
+ - StrongRef utilities: createStrongRef, createStrongRefFromResult, validateStrongRef
149
+ - Lexicon builders: createStringField, createIntegerField, createStrongRefField, createRecordDef, createLexiconDoc,
150
+ and more
151
+ - Sidecar pattern: createSidecarRecord, attachSidecar, createWithSidecars, batchCreateSidecars
152
+
153
+ - [#88](https://github.com/hypercerts-org/hypercerts-sdk/pull/88)
154
+ [`19c78df`](https://github.com/hypercerts-org/hypercerts-sdk/commit/19c78dfef448fb43d353d95721c13f3a35618fb3) Thanks
155
+ [@bitbeckers](https://github.com/bitbeckers)! - feat: add HTTP loopback URL support for local development
156
+
157
+ Enable local development and testing with HTTP loopback URLs (`http://localhost`, `http://127.0.0.1`, `http://[::1]`)
158
+ while maintaining security for production deployments.
159
+
160
+ **Configuration Updates**
161
+ - Custom URL validator accepting HTTPS URLs or HTTP loopback addresses
162
+ - Update `OAuthConfigSchema` to allow loopback URLs for `clientId`, `redirectUri`, `jwksUri`
163
+ - Add optional `developmentMode` boolean flag to suppress warnings
164
+ - Update `ServerConfigSchema` to allow loopback URLs for PDS/SDS servers
165
+ - Export `isLoopbackUrl()` helper function and TypeScript types (`LoopbackUrl`, `HttpsUrl`,
166
+ `DevelopmentOrProductionUrl`)
167
+
168
+ **Development Mode Features**
169
+ - Automatic loopback detection with informative logging
170
+ - Warning when using loopback URLs without explicit `developmentMode` flag
171
+ - Info logs indicating development mode is active
172
+ - Clear guidance about authorization server requirements
173
+
174
+ **Testing**
175
+ - 28 new unit tests for loopback URL validation
176
+ - Tests cover localhost, 127.0.0.1, and [::1] (IPv6) loopback addresses
177
+ - Tests verify rejection of non-loopback HTTP URLs
178
+ - Tests ensure HTTPS URLs always accepted
179
+
180
+ **Documentation**
181
+ - Comprehensive local development guide in Core SDK README
182
+ - NextJS App Router example with loopback configuration
183
+ - API route setup examples (OAuth callback, JWKS endpoint)
184
+ - Important notes about authorization server support and production safety
185
+ - Local development example added to React SDK factory JSDoc
186
+
187
+ **Breaking Changes**: None - fully backward compatible
188
+
189
+ **Migration**: No migration needed for existing configurations. Existing HTTPS URLs continue to work without changes.
190
+
191
+ This feature enables developers to test the SDK locally without requiring HTTPS certificates, while the underlying
192
+ `@atproto/oauth-client-node` library handles loopback OAuth flows per the AT Protocol specification.
193
+
194
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
195
+ [`3554580`](https://github.com/hypercerts-org/hypercerts-sdk/commit/3554580d77d9467c88c779e75a96a08d3e17bfd7) Thanks
196
+ [@bitbeckers](https://github.com/bitbeckers)! - Add automatic lexicon validation to RecordOperations. Records are now
197
+ validated against registered lexicon schemas before being sent to the server, catching schema violations early.
198
+ Validation can be bypassed using the `skipValidation` parameter for advanced use cases.
199
+
200
+ - [#96](https://github.com/hypercerts-org/hypercerts-sdk/pull/96)
201
+ [`eea06a7`](https://github.com/hypercerts-org/hypercerts-sdk/commit/eea06a7f5e4f655ccac635fa8842ea32a6dfde64) Thanks
202
+ [@Kzoeps](https://github.com/Kzoeps)! - Refactor location attachment to match lexicon specifications
203
+
204
+ **New Features:**
205
+ - Add `AttachLocationParams` interface exported from SDK for type-safe location attachment
206
+ - Location data now properly uses `org.hypercerts.defs#uri` (for string URIs) or `org.hypercerts.defs#smallBlob` (for
207
+ GeoJSON blobs) to match lexicon spec
208
+ - Add `lpVersion` and `locationType` fields to location parameters for better protocol compliance
209
+
210
+ **Improvements:**
211
+ - Centralized blob upload logic with new `handleBlobUpload()` helper method
212
+ - Simplified location type detection - now based on content type (string vs Blob) instead of separate `geojson`
213
+ parameter
214
+ - Improved type safety with structured `AttachLocationParams` interface
215
+
216
+ **Breaking Changes:**
217
+ - `attachLocation()` signature changed from `(uri, { value, name?, description?, srs, geojson? })` to
218
+ `(uri, AttachLocationParams)`
219
+ - `AttachLocationParams` now requires: `lpVersion`, `srs`, `locationType`, and `location` (string | Blob)
220
+ - The `location` field in `CreateHypercertParams` now uses `AttachLocationParams` type instead of inline object
221
+ - Removed separate `value` and `geojson` fields - use single `location` field with either string or Blob
222
+
223
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
224
+ [`e0ef6e9`](https://github.com/hypercerts-org/hypercerts-sdk/commit/e0ef6e9cb9138590e81b4a2929ca27ae557d2f39) Thanks
225
+ [@bitbeckers](https://github.com/bitbeckers)! - Integrate LexiconRegistry into SDK and Repository. The SDK now
226
+ initializes a LexiconRegistry with hypercert lexicons by default and exposes it via `getLexiconRegistry()`. Repository
227
+ instances receive the registry and pass it to RecordOperations for future validation support.
228
+
3
229
  ## 0.10.0-beta.4
4
230
 
5
231
  ### Minor Changes
package/README.md CHANGED
@@ -51,6 +51,99 @@ const claim = await repo.hypercerts.create({
51
51
  });
52
52
  ```
53
53
 
54
+ ## Local Development
55
+
56
+ For local development and testing, you can use HTTP loopback URLs with `localhost` or `127.0.0.1`:
57
+
58
+ ### NextJS App Router Example
59
+
60
+ ```typescript
61
+ // lib/atproto.ts
62
+ import { createATProtoSDK } from "@hypercerts-org/sdk-core";
63
+
64
+ const sdk = createATProtoSDK({
65
+ oauth: {
66
+ // Use localhost for client_id (loopback client)
67
+ clientId: "http://localhost/",
68
+
69
+ // Use 127.0.0.1 with your app's port for redirect
70
+ redirectUri: "http://127.0.0.1:3000/api/auth/callback",
71
+
72
+ scope: "atproto",
73
+
74
+ // Serve JWKS from your app
75
+ jwksUri: "http://127.0.0.1:3000/.well-known/jwks.json",
76
+
77
+ // Load from environment variable
78
+ jwkPrivate: process.env.ATPROTO_JWK_PRIVATE!,
79
+
80
+ // Optional: suppress warnings
81
+ developmentMode: true,
82
+ },
83
+ servers: {
84
+ // Point to local PDS for testing
85
+ pds: "http://localhost:2583",
86
+ },
87
+ logger: console, // Enable debug logging
88
+ });
89
+
90
+ export default sdk;
91
+ ```
92
+
93
+ ### API Route Setup
94
+
95
+ ```typescript
96
+ // app/api/auth/callback/route.ts
97
+ import sdk from "@/lib/atproto";
98
+
99
+ export async function GET(request: Request) {
100
+ const { searchParams } = new URL(request.url);
101
+
102
+ try {
103
+ const session = await sdk.callback(searchParams);
104
+
105
+ // Store session (use secure httpOnly cookie in production)
106
+ return Response.json({ success: true, did: session.sub });
107
+ } catch (error) {
108
+ return Response.json({ error: "Authentication failed" }, { status: 401 });
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### Serve JWKS Endpoint
114
+
115
+ ```typescript
116
+ // app/.well-known/jwks.json/route.ts
117
+ export async function GET() {
118
+ const jwk = JSON.parse(process.env.ATPROTO_JWK_PRIVATE!);
119
+
120
+ // Return public keys only (remove private key 'd' parameter)
121
+ const publicKeys = jwk.keys.map(({ d, ...publicKey }) => publicKey);
122
+
123
+ return Response.json({ keys: publicKeys });
124
+ }
125
+ ```
126
+
127
+ ### Environment Variables
128
+
129
+ ```bash
130
+ # .env.local
131
+ ATPROTO_JWK_PRIVATE='{"keys":[{"kty":"EC","crv":"P-256",...}]}'
132
+ ```
133
+
134
+ ### Important Notes
135
+
136
+ > **Authorization Server Support**: The AT Protocol OAuth spec makes loopback support **optional**. Most AT Protocol
137
+ > servers support loopback clients for development, but verify your target authorization server supports this feature.
138
+
139
+ > **Port Matching**: Redirect URIs can use any port - the authorization server ignores port numbers when validating
140
+ > loopback redirects (only the path must match).
141
+
142
+ > **Production Use**: ⚠️ Never use HTTP loopback URLs in production. Always use HTTPS with proper TLS certificates.
143
+
144
+ > **IP vs Hostname**: Use `http://localhost/` for `clientId` and `http://127.0.0.1:<port>` for `redirectUri` and
145
+ > `jwksUri` (this is the recommended pattern per AT Protocol spec).
146
+
54
147
  ## Core Concepts
55
148
 
56
149
  ### 1. PDS vs SDS: Understanding Server Types
@@ -318,7 +411,130 @@ const measurement = await repo.hypercerts.addMeasurement({
318
411
  });
319
412
  ```
320
413
 
321
- ### 5. Blob Operations (Images & Files)
414
+ ### 5. Collections and Projects
415
+
416
+ Collections organize multiple hypercerts into logical groupings. Projects are a special type of collection with
417
+ `type="project"`.
418
+
419
+ #### Creating a Collection
420
+
421
+ ```typescript
422
+ // Create a collection with weighted items
423
+ const collection = await repo.hypercerts.createCollection({
424
+ title: "Climate Projects 2024",
425
+ shortDescription: "Our climate impact portfolio",
426
+ description: "A curated collection of climate-related hypercerts",
427
+ items: [
428
+ {
429
+ itemIdentifier: { uri: hypercert1Uri, cid: hypercert1Cid },
430
+ itemWeight: "0.5",
431
+ },
432
+ {
433
+ itemIdentifier: { uri: hypercert2Uri, cid: hypercert2Cid },
434
+ itemWeight: "0.3",
435
+ },
436
+ {
437
+ itemIdentifier: { uri: hypercert3Uri, cid: hypercert3Cid },
438
+ itemWeight: "0.2",
439
+ },
440
+ ],
441
+ avatar: avatarBlob, // optional
442
+ banner: bannerBlob, // optional
443
+ });
444
+
445
+ console.log("Created collection:", collection.uri);
446
+ ```
447
+
448
+ #### Creating a Project
449
+
450
+ Projects are collections with automatic `type="project"`:
451
+
452
+ ```typescript
453
+ const project = await repo.hypercerts.createProject({
454
+ title: "Rainforest Restoration",
455
+ shortDescription: "Multi-year restoration initiative",
456
+ description: "Comprehensive rainforest restoration project",
457
+ items: [
458
+ {
459
+ itemIdentifier: { uri: activity1Uri, cid: activity1Cid },
460
+ itemWeight: "0.6",
461
+ },
462
+ {
463
+ itemIdentifier: { uri: activity2Uri, cid: activity2Cid },
464
+ itemWeight: "0.4",
465
+ },
466
+ ],
467
+ });
468
+ ```
469
+
470
+ #### Attaching Locations
471
+
472
+ Both collections and projects can have location data attached as a sidecar record:
473
+
474
+ ```typescript
475
+ // Attach location to a project
476
+ const locationResult = await repo.hypercerts.attachLocationToProject(projectUri, {
477
+ lpVersion: "1.0",
478
+ srs: "EPSG:4326",
479
+ locationType: "coordinate-decimal",
480
+ location: "https://example.com/location.geojson", // or use a Blob
481
+ name: "Project Site",
482
+ description: "Main restoration site coordinates",
483
+ });
484
+
485
+ // Also works for collections
486
+ await repo.hypercerts.attachLocationToCollection(collectionUri, locationParams);
487
+ ```
488
+
489
+ #### Listing and Retrieving
490
+
491
+ ```typescript
492
+ // Get a specific collection
493
+ const collection = await repo.hypercerts.getCollection(collectionUri);
494
+
495
+ // List all collections
496
+ const { records } = await repo.hypercerts.listCollections();
497
+
498
+ // Get a specific project
499
+ const project = await repo.hypercerts.getProject(projectUri);
500
+
501
+ // List all projects
502
+ const { records } = await repo.hypercerts.listProjects();
503
+ ```
504
+
505
+ #### Updating Collections and Projects
506
+
507
+ ```typescript
508
+ // Update collection
509
+ await repo.hypercerts.updateCollection(collectionUri, {
510
+ title: "Updated Title",
511
+ items: [
512
+ /* updated items */
513
+ ],
514
+ avatar: newAvatarBlob, // or null to remove
515
+ });
516
+
517
+ // Update project (same API)
518
+ await repo.hypercerts.updateProject(projectUri, {
519
+ shortDescription: "Updated description",
520
+ banner: null, // removes banner
521
+ });
522
+ ```
523
+
524
+ #### Deleting
525
+
526
+ ```typescript
527
+ // Delete collection
528
+ await repo.hypercerts.deleteCollection(collectionUri);
529
+
530
+ // Delete project
531
+ await repo.hypercerts.deleteProject(projectUri);
532
+
533
+ // Remove location from project
534
+ await repo.hypercerts.removeLocationFromProject(projectUri);
535
+ ```
536
+
537
+ ### 6. Blob Operations (Images & Files)
322
538
 
323
539
  ```typescript
324
540
  // Upload an image or file
@@ -329,7 +545,7 @@ console.log("Blob uploaded:", blobResult.ref.$link);
329
545
  const blobData = await repo.blobs.get("did:plc:user123", "bafyreiabc123...");
330
546
  ```
331
547
 
332
- ### 6. Organizations (SDS only)
548
+ ### 7. Organizations (SDS only)
333
549
 
334
550
  Organizations allow multiple users to collaborate on shared repositories.
335
551
 
@@ -357,7 +573,7 @@ const org = await repo.organizations.get("did:plc:org123");
357
573
  console.log(`${org.name} - ${org.description}`);
358
574
  ```
359
575
 
360
- ### 7. Collaborator Management (SDS only)
576
+ ### 8. Collaborator Management (SDS only)
361
577
 
362
578
  Manage who has access to your repository and what they can do.
363
579
 
@@ -426,7 +642,7 @@ await repo.collaborators.transferOwnership({
426
642
  });
427
643
  ```
428
644
 
429
- ### 8. Generic Record Operations
645
+ ### 9. Generic Record Operations
430
646
 
431
647
  For working with any ATProto record type:
432
648
 
@@ -471,7 +687,7 @@ const { records, cursor } = await repo.records.list({
471
687
  });
472
688
  ```
473
689
 
474
- ### 9. Profile Management (PDS only)
690
+ ### 10. Profile Management (PDS only)
475
691
 
476
692
  ```typescript
477
693
  // Get user profile
@@ -491,40 +707,56 @@ await repo.profile.update({
491
707
 
492
708
  ### Repository Operations
493
709
 
494
- | Operation | Method | PDS | SDS | Returns |
495
- | ------------------ | ---------------------------------------- | --- | --- | ---------------------------- |
496
- | **Records** | | | | |
497
- | Create record | `repo.records.create()` | ✅ | ✅ | `{ uri, cid }` |
498
- | Get record | `repo.records.get()` | ✅ | ✅ | Record data |
499
- | Update record | `repo.records.update()` | ✅ | ✅ | `{ uri, cid }` |
500
- | Delete record | `repo.records.delete()` | ✅ | ✅ | void |
501
- | List records | `repo.records.list()` | ✅ | ✅ | `{ records, cursor? }` |
502
- | **Hypercerts** | | | | |
503
- | Create hypercert | `repo.hypercerts.create()` | ✅ | ✅ | `{ uri, cid, value }` |
504
- | Get hypercert | `repo.hypercerts.get()` | ✅ | ✅ | Full hypercert |
505
- | Update hypercert | `repo.hypercerts.update()` | ✅ | ✅ | `{ uri, cid }` |
506
- | Delete hypercert | `repo.hypercerts.delete()` | ✅ | ✅ | void |
507
- | List hypercerts | `repo.hypercerts.list()` | ✅ | ✅ | `{ records, cursor? }` |
508
- | Add contribution | `repo.hypercerts.addContribution()` | ✅ | ✅ | Contribution |
509
- | Add measurement | `repo.hypercerts.addMeasurement()` | ✅ | ✅ | Measurement |
510
- | **Blobs** | | | | |
511
- | Upload blob | `repo.blobs.upload()` | ✅ | ✅ | `{ ref, mimeType, size }` |
512
- | Get blob | `repo.blobs.get()` | ✅ | ✅ | Blob data |
513
- | **Profile** | | | | |
514
- | Get profile | `repo.profile.get()` | ✅ | | Profile data |
515
- | Update profile | `repo.profile.update()` | ✅ | | void |
516
- | **Organizations** | | | | |
517
- | Create org | `repo.organizations.create()` | | ✅ | `{ did, name, ... }` |
518
- | Get org | `repo.organizations.get()` ||| Organization |
519
- | List orgs | `repo.organizations.list()` | | ✅ | `{ organizations, cursor? }` |
520
- | **Collaborators** | | | | |
521
- | Grant access | `repo.collaborators.grant()` | | ✅ | void |
522
- | Revoke access | `repo.collaborators.revoke()` | | ✅ | void |
523
- | List collaborators | `repo.collaborators.list()` | | ✅ | `{ collaborators, cursor? }` |
524
- | Check access | `repo.collaborators.hasAccess()` | | ✅ | boolean |
525
- | Get role | `repo.collaborators.getRole()` | | ✅ | Role string |
526
- | Get permissions | `repo.collaborators.getPermissions()` ||| Permissions |
527
- | Transfer ownership | `repo.collaborators.transferOwnership()` | | ✅ | void |
710
+ | Operation | Method | PDS | SDS | Returns |
711
+ | ------------------ | ------------------------------------------------ | --- | --- | ---------------------------- |
712
+ | **Records** | | | | |
713
+ | Create record | `repo.records.create()` | ✅ | ✅ | `{ uri, cid }` |
714
+ | Get record | `repo.records.get()` | ✅ | ✅ | Record data |
715
+ | Update record | `repo.records.update()` | ✅ | ✅ | `{ uri, cid }` |
716
+ | Delete record | `repo.records.delete()` | ✅ | ✅ | void |
717
+ | List records | `repo.records.list()` | ✅ | ✅ | `{ records, cursor? }` |
718
+ | **Hypercerts** | | | | |
719
+ | Create hypercert | `repo.hypercerts.create()` | ✅ | ✅ | `{ uri, cid, value }` |
720
+ | Get hypercert | `repo.hypercerts.get()` | ✅ | ✅ | Full hypercert |
721
+ | Update hypercert | `repo.hypercerts.update()` | ✅ | ✅ | `{ uri, cid }` |
722
+ | Delete hypercert | `repo.hypercerts.delete()` | ✅ | ✅ | void |
723
+ | List hypercerts | `repo.hypercerts.list()` | ✅ | ✅ | `{ records, cursor? }` |
724
+ | Add contribution | `repo.hypercerts.addContribution()` | ✅ | ✅ | Contribution |
725
+ | Add measurement | `repo.hypercerts.addMeasurement()` | ✅ | ✅ | Measurement |
726
+ | **Collections** | | | | |
727
+ | Create collection | `repo.hypercerts.createCollection()` | ✅ | ✅ | `{ uri, cid, record }` |
728
+ | Get collection | `repo.hypercerts.getCollection()` | ✅ | ✅ | Collection data |
729
+ | List collections | `repo.hypercerts.listCollections()` ||| `{ records, cursor? }` |
730
+ | Update collection | `repo.hypercerts.updateCollection()` | ✅ | | `{ uri, cid }` |
731
+ | Delete collection | `repo.hypercerts.deleteCollection()` | ✅ | | void |
732
+ | Attach location | `repo.hypercerts.attachLocationToCollection()` ||| `{ uri, cid }` |
733
+ | Remove location | `repo.hypercerts.removeLocationFromCollection()` | | ✅ | void |
734
+ | **Projects** | | | | |
735
+ | Create project | `repo.hypercerts.createProject()` | | ✅ | `{ uri, cid, record }` |
736
+ | Get project | `repo.hypercerts.getProject()` ||| Project data |
737
+ | List projects | `repo.hypercerts.listProjects()` | | ✅ | `{ records, cursor? }` |
738
+ | Update project | `repo.hypercerts.updateProject()` | | ✅ | `{ uri, cid }` |
739
+ | Delete project | `repo.hypercerts.deleteProject()` | | ✅ | void |
740
+ | Attach location | `repo.hypercerts.attachLocationToProject()` | | ✅ | `{ uri, cid }` |
741
+ | Remove location | `repo.hypercerts.removeLocationFromProject()` | | ✅ | void |
742
+ | **Blobs** | | | | |
743
+ | Upload blob | `repo.blobs.upload()` | | ✅ | `{ ref, mimeType, size }` |
744
+ | Get blob | `repo.blobs.get()` | ✅ | ✅ | Blob data |
745
+ | **Profile** | | | | |
746
+ | Get profile | `repo.profile.get()` | ✅ | ❌ | Profile data |
747
+ | Update profile | `repo.profile.update()` | ✅ | ❌ | void |
748
+ | **Organizations** | | | | |
749
+ | Create org | `repo.organizations.create()` | ❌ | ✅ | `{ did, name, ... }` |
750
+ | Get org | `repo.organizations.get()` | ❌ | ✅ | Organization |
751
+ | List orgs | `repo.organizations.list()` | ❌ | ✅ | `{ organizations, cursor? }` |
752
+ | **Collaborators** | | | | |
753
+ | Grant access | `repo.collaborators.grant()` | ❌ | ✅ | void |
754
+ | Revoke access | `repo.collaborators.revoke()` | ❌ | ✅ | void |
755
+ | List collaborators | `repo.collaborators.list()` | ❌ | ✅ | `{ collaborators, cursor? }` |
756
+ | Check access | `repo.collaborators.hasAccess()` | ❌ | ✅ | boolean |
757
+ | Get role | `repo.collaborators.getRole()` | ❌ | ✅ | Role string |
758
+ | Get permissions | `repo.collaborators.getPermissions()` | ❌ | ✅ | Permissions |
759
+ | Transfer ownership | `repo.collaborators.transferOwnership()` | ❌ | ✅ | void |
528
760
 
529
761
  ## Type System
530
762
 
@@ -713,20 +945,52 @@ const validationResult = OrgHypercertsClaim.validateMain(claim);
713
945
 
714
946
  #### Using LexiconRegistry
715
947
 
716
- For repository-level validation:
948
+ The SDK automatically initializes a LexiconRegistry with all hypercert lexicons. You can access it to validate records
949
+ or register custom lexicons:
717
950
 
718
951
  ```typescript
719
- import { LexiconRegistry, HYPERCERT_LEXICONS, HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
720
-
721
- const registry = new LexiconRegistry();
722
- registry.registerLexicons(HYPERCERT_LEXICONS);
952
+ // Access the registry from the SDK
953
+ const registry = sdk.getLexiconRegistry();
723
954
 
724
955
  // Validate a record
725
- const result = registry.validate(HYPERCERT_COLLECTIONS.CLAIM, claimData);
956
+ const result = registry.validate("org.hypercerts.claim.activity", claimData);
726
957
 
727
958
  if (!result.valid) {
728
959
  console.error("Invalid record:", result.error);
729
960
  }
961
+
962
+ // Register a custom lexicon
963
+ registry.registerFromJSON({
964
+ lexicon: 1,
965
+ id: "org.myapp.customRecord",
966
+ defs: {
967
+ main: {
968
+ type: "record",
969
+ key: "tid",
970
+ record: {
971
+ type: "object",
972
+ required: ["$type", "title"],
973
+ properties: {
974
+ $type: { type: "string", const: "org.myapp.customRecord" },
975
+ title: { type: "string" },
976
+ createdAt: { type: "string", format: "datetime" },
977
+ },
978
+ },
979
+ },
980
+ },
981
+ });
982
+
983
+ // Check if a lexicon is registered
984
+ if (registry.isRegistered("org.myapp.customRecord")) {
985
+ console.log("Custom lexicon is ready to use");
986
+ }
987
+ ```
988
+
989
+ You can also access the registry from a Repository instance:
990
+
991
+ ```typescript
992
+ const repo = sdk.repository(session);
993
+ const registry = repo.getLexiconRegistry();
730
994
  ```
731
995
 
732
996
  #### Creating Records with Proper Types