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

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/README.md CHANGED
@@ -53,12 +53,14 @@ const claim = await repo.hypercerts.create({
53
53
  The SDK supports two types of AT Protocol servers:
54
54
 
55
55
  #### Personal Data Server (PDS)
56
+
56
57
  - **Purpose**: User's own data storage (e.g., Bluesky)
57
58
  - **Use case**: Individual hypercerts, personal records
58
59
  - **Features**: Profile management, basic CRUD operations
59
60
  - **Example**: `bsky.social`, any Bluesky PDS
60
61
 
61
62
  #### Shared Data Server (SDS)
63
+
62
64
  - **Purpose**: Collaborative data storage with access control
63
65
  - **Use case**: Organization hypercerts, team collaboration
64
66
  - **Features**: Organizations, multi-user access, role-based permissions
@@ -84,25 +86,27 @@ await orgRepo.hypercerts.list(); // Queries organization's hypercerts on SDS
84
86
  The SDK uses a `ConfigurableAgent` to route requests to different servers while maintaining your OAuth authentication:
85
87
 
86
88
  1. **Initial Repository Creation**
89
+
87
90
  ```typescript
88
91
  // User authenticates (OAuth session knows user's PDS)
89
92
  const session = await sdk.callback(params);
90
-
93
+
91
94
  // Create PDS repository - routes to user's PDS
92
95
  const pdsRepo = sdk.repository(session);
93
-
96
+
94
97
  // Create SDS repository - routes to SDS server
95
98
  const sdsRepo = sdk.repository(session, { server: "sds" });
96
99
  ```
97
100
 
98
101
  2. **Switching Repositories with `.repo()`**
102
+
99
103
  ```typescript
100
104
  // Start with user's SDS repository
101
105
  const userSdsRepo = sdk.repository(session, { server: "sds" });
102
-
106
+
103
107
  // Switch to organization's repository
104
108
  const orgRepo = userSdsRepo.repo("did:plc:org-did");
105
-
109
+
106
110
  // All operations on orgRepo still route to SDS, not user's PDS
107
111
  await orgRepo.hypercerts.list(); // ✅ Queries SDS
108
112
  await orgRepo.collaborators.list(); // ✅ Queries SDS
@@ -171,33 +175,34 @@ const repo = sdk.getRepository(session);
171
175
  Control exactly what your app can access using type-safe permission builders:
172
176
 
173
177
  ```typescript
174
- import { PermissionBuilder, ScopePresets, buildScope } from '@hypercerts-org/sdk-core';
178
+ import { PermissionBuilder, ScopePresets, buildScope } from "@hypercerts-org/sdk-core";
175
179
 
176
180
  // Use ready-made presets
177
- const scope = ScopePresets.EMAIL_AND_PROFILE; // Request email + profile access
178
- const scope = ScopePresets.POSTING_APP; // Full posting capabilities
181
+ const scope = ScopePresets.EMAIL_AND_PROFILE; // Request email + profile access
182
+ const scope = ScopePresets.POSTING_APP; // Full posting capabilities
179
183
 
180
184
  // Or build custom permissions
181
185
  const scope = buildScope(
182
186
  new PermissionBuilder()
183
- .accountEmail('read') // Read user's email
184
- .repoWrite('app.bsky.feed.post') // Create/update posts
185
- .blob(['image/*', 'video/*']) // Upload media
186
- .build()
187
+ .accountEmail("read") // Read user's email
188
+ .repoWrite("app.bsky.feed.post") // Create/update posts
189
+ .blob(["image/*", "video/*"]) // Upload media
190
+ .build(),
187
191
  );
188
192
 
189
193
  // Use in OAuth configuration
190
194
  const sdk = createATProtoSDK({
191
195
  oauth: {
192
- clientId: 'your-client-id',
193
- redirectUri: 'https://your-app.com/callback',
194
- scope: scope, // Your custom scope
196
+ clientId: "your-client-id",
197
+ redirectUri: "https://your-app.com/callback",
198
+ scope: scope, // Your custom scope
195
199
  // ... other config
196
- }
200
+ },
197
201
  });
198
202
  ```
199
203
 
200
204
  **Available Presets:**
205
+
201
206
  - `EMAIL_READ` - User's email address
202
207
  - `PROFILE_READ` / `PROFILE_WRITE` - Profile access
203
208
  - `POST_WRITE` - Create posts
@@ -218,7 +223,7 @@ const hypercert = await repo.hypercerts.create({
218
223
  description: "Research on carbon capture technologies",
219
224
  image: imageBlob, // optional: File or Blob
220
225
  externalUrl: "https://example.com/project",
221
-
226
+
222
227
  impact: {
223
228
  scope: ["Climate Change", "Carbon Capture"],
224
229
  work: {
@@ -227,7 +232,7 @@ const hypercert = await repo.hypercerts.create({
227
232
  },
228
233
  contributors: ["did:plc:researcher1", "did:plc:researcher2"],
229
234
  },
230
-
235
+
231
236
  rights: {
232
237
  license: "CC-BY-4.0",
233
238
  allowsDerivatives: true,
@@ -242,9 +247,7 @@ console.log("Created hypercert:", hypercert.uri);
242
247
 
243
248
  ```typescript
244
249
  // Get a specific hypercert by URI
245
- const hypercert = await repo.hypercerts.get(
246
- "at://did:plc:user123/org.hypercerts.claim/abc123"
247
- );
250
+ const hypercert = await repo.hypercerts.get("at://did:plc:user123/org.hypercerts.claim/abc123");
248
251
 
249
252
  // List all hypercerts in the repository
250
253
  const { records } = await repo.hypercerts.list();
@@ -263,26 +266,21 @@ if (cursor) {
263
266
 
264
267
  ```typescript
265
268
  // Update an existing hypercert
266
- await repo.hypercerts.update(
267
- "at://did:plc:user123/org.hypercerts.claim/abc123",
268
- {
269
- title: "Updated Climate Research Project",
270
- description: "Expanded scope to include renewable energy",
271
- impact: {
272
- scope: ["Climate Change", "Carbon Capture", "Renewable Energy"],
273
- work: { from: "2024-01-01", to: "2026-12-31" },
274
- contributors: ["did:plc:researcher1", "did:plc:researcher2"],
275
- },
276
- }
277
- );
269
+ await repo.hypercerts.update("at://did:plc:user123/org.hypercerts.claim/abc123", {
270
+ title: "Updated Climate Research Project",
271
+ description: "Expanded scope to include renewable energy",
272
+ impact: {
273
+ scope: ["Climate Change", "Carbon Capture", "Renewable Energy"],
274
+ work: { from: "2024-01-01", to: "2026-12-31" },
275
+ contributors: ["did:plc:researcher1", "did:plc:researcher2"],
276
+ },
277
+ });
278
278
  ```
279
279
 
280
280
  #### Deleting a Hypercert
281
281
 
282
282
  ```typescript
283
- await repo.hypercerts.delete(
284
- "at://did:plc:user123/org.hypercerts.claim/abc123"
285
- );
283
+ await repo.hypercerts.delete("at://did:plc:user123/org.hypercerts.claim/abc123");
286
284
  ```
287
285
 
288
286
  ### 4. Contributions and Measurements
@@ -323,10 +321,7 @@ const blobResult = await repo.blobs.upload(imageFile);
323
321
  console.log("Blob uploaded:", blobResult.ref.$link);
324
322
 
325
323
  // Download a blob
326
- const blobData = await repo.blobs.get(
327
- "did:plc:user123",
328
- "bafyreiabc123..."
329
- );
324
+ const blobData = await repo.blobs.get("did:plc:user123", "bafyreiabc123...");
330
325
  ```
331
326
 
332
327
  ### 6. Organizations (SDS only)
@@ -491,40 +486,40 @@ await repo.profile.update({
491
486
 
492
487
  ### Repository Operations
493
488
 
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 |
489
+ | Operation | Method | PDS | SDS | Returns |
490
+ | ------------------ | ---------------------------------------- | --- | --- | ---------------------------- |
491
+ | **Records** | | | | |
492
+ | Create record | `repo.records.create()` | ✅ | ✅ | `{ uri, cid }` |
493
+ | Get record | `repo.records.get()` | ✅ | ✅ | Record data |
494
+ | Update record | `repo.records.update()` | ✅ | ✅ | `{ uri, cid }` |
495
+ | Delete record | `repo.records.delete()` | ✅ | ✅ | void |
496
+ | List records | `repo.records.list()` | ✅ | ✅ | `{ records, cursor? }` |
497
+ | **Hypercerts** | | | | |
498
+ | Create hypercert | `repo.hypercerts.create()` | ✅ | ✅ | `{ uri, cid, value }` |
499
+ | Get hypercert | `repo.hypercerts.get()` | ✅ | ✅ | Full hypercert |
500
+ | Update hypercert | `repo.hypercerts.update()` | ✅ | ✅ | `{ uri, cid }` |
501
+ | Delete hypercert | `repo.hypercerts.delete()` | ✅ | ✅ | void |
502
+ | List hypercerts | `repo.hypercerts.list()` | ✅ | ✅ | `{ records, cursor? }` |
503
+ | Add contribution | `repo.hypercerts.addContribution()` | ✅ | ✅ | Contribution |
504
+ | Add measurement | `repo.hypercerts.addMeasurement()` | ✅ | ✅ | Measurement |
505
+ | **Blobs** | | | | |
506
+ | Upload blob | `repo.blobs.upload()` | ✅ | ✅ | `{ ref, mimeType, size }` |
507
+ | Get blob | `repo.blobs.get()` | ✅ | ✅ | Blob data |
508
+ | **Profile** | | | | |
509
+ | Get profile | `repo.profile.get()` | ✅ | ❌ | Profile data |
510
+ | Update profile | `repo.profile.update()` | ✅ | ❌ | void |
511
+ | **Organizations** | | | | |
512
+ | Create org | `repo.organizations.create()` | ❌ | ✅ | `{ did, name, ... }` |
513
+ | Get org | `repo.organizations.get()` | ❌ | ✅ | Organization |
514
+ | List orgs | `repo.organizations.list()` | ❌ | ✅ | `{ organizations, cursor? }` |
515
+ | **Collaborators** | | | | |
516
+ | Grant access | `repo.collaborators.grant()` | ❌ | ✅ | void |
517
+ | Revoke access | `repo.collaborators.revoke()` | ❌ | ✅ | void |
518
+ | List collaborators | `repo.collaborators.list()` | ❌ | ✅ | `{ collaborators, cursor? }` |
519
+ | Check access | `repo.collaborators.hasAccess()` | ❌ | ✅ | boolean |
520
+ | Get role | `repo.collaborators.getRole()` | ❌ | ✅ | Role string |
521
+ | Get permissions | `repo.collaborators.getPermissions()` | ❌ | ✅ | Permissions |
522
+ | Transfer ownership | `repo.collaborators.transferOwnership()` | ❌ | ✅ | void |
528
523
 
529
524
  ## Type System
530
525
 
@@ -549,15 +544,15 @@ if (OrgHypercertsClaim.isRecord(data)) {
549
544
  }
550
545
  ```
551
546
 
552
- | Lexicon Type | SDK Alias |
553
- |--------------|-----------|
554
- | `OrgHypercertsClaim.Main` | `HypercertClaim` |
555
- | `OrgHypercertsClaimRights.Main` | `HypercertRights` |
547
+ | Lexicon Type | SDK Alias |
548
+ | ------------------------------------- | ----------------------- |
549
+ | `OrgHypercertsClaim.Main` | `HypercertClaim` |
550
+ | `OrgHypercertsClaimRights.Main` | `HypercertRights` |
556
551
  | `OrgHypercertsClaimContribution.Main` | `HypercertContribution` |
557
- | `OrgHypercertsClaimMeasurement.Main` | `HypercertMeasurement` |
558
- | `OrgHypercertsClaimEvaluation.Main` | `HypercertEvaluation` |
559
- | `OrgHypercertsCollection.Main` | `HypercertCollection` |
560
- | `AppCertifiedLocation.Main` | `HypercertLocation` |
552
+ | `OrgHypercertsClaimMeasurement.Main` | `HypercertMeasurement` |
553
+ | `OrgHypercertsClaimEvaluation.Main` | `HypercertEvaluation` |
554
+ | `OrgHypercertsCollection.Main` | `HypercertCollection` |
555
+ | `AppCertifiedLocation.Main` | `HypercertLocation` |
561
556
 
562
557
  ## Error Handling
563
558
 
@@ -622,6 +617,7 @@ await sdsAgent.com.atproto.repo.listRecords({...});
622
617
  ```
623
618
 
624
619
  This is useful for:
620
+
625
621
  - Connecting to multiple SDS instances simultaneously
626
622
  - Testing against different server environments
627
623
  - Building tools that work across multiple organizations
@@ -655,7 +651,8 @@ await mockStore.set(mockSession);
655
651
 
656
652
  ### Working with Lexicons
657
653
 
658
- The SDK exports lexicon types and validation utilities from the `@hypercerts-org/lexicon` package for direct record manipulation and validation.
654
+ The SDK exports lexicon types and validation utilities from the `@hypercerts-org/lexicon` package for direct record
655
+ manipulation and validation.
659
656
 
660
657
  #### Lexicon Types
661
658
 
@@ -680,8 +677,8 @@ const claim: HypercertClaim = {
680
677
  shortDescription: "Urban garden serving 50 families", // REQUIRED
681
678
  description: "Detailed description...",
682
679
  workScope: "Food Security",
683
- workTimeFrameFrom: "2024-01-01T00:00:00Z", // Note: Capital 'F'
684
- workTimeFrameTo: "2024-12-31T00:00:00Z", // Note: Capital 'F'
680
+ workTimeFrameFrom: "2024-01-01T00:00:00Z", // Note: Capital 'F'
681
+ workTimeFrameTo: "2024-12-31T00:00:00Z", // Note: Capital 'F'
685
682
  rights: { uri: "at://...", cid: "..." },
686
683
  createdAt: new Date().toISOString(),
687
684
  };
@@ -692,16 +689,12 @@ const claim: HypercertClaim = {
692
689
  Validate records before creating them:
693
690
 
694
691
  ```typescript
695
- import {
696
- validate,
697
- OrgHypercertsClaim,
698
- HYPERCERT_COLLECTIONS,
699
- } from "@hypercerts-org/sdk-core";
692
+ import { validate, OrgHypercertsClaim, HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
700
693
 
701
694
  // Validate using the lexicon package
702
695
  const validation = validate(
703
- HYPERCERT_COLLECTIONS.CLAIM, // "org.hypercerts.claim"
704
- claim
696
+ HYPERCERT_COLLECTIONS.CLAIM, // "org.hypercerts.claim"
697
+ claim,
705
698
  );
706
699
 
707
700
  if (!validation.valid) {
@@ -718,20 +711,13 @@ const validationResult = OrgHypercertsClaim.validateMain(claim);
718
711
  For repository-level validation:
719
712
 
720
713
  ```typescript
721
- import {
722
- LexiconRegistry,
723
- HYPERCERT_LEXICONS,
724
- HYPERCERT_COLLECTIONS,
725
- } from "@hypercerts-org/sdk-core";
714
+ import { LexiconRegistry, HYPERCERT_LEXICONS, HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
726
715
 
727
716
  const registry = new LexiconRegistry();
728
717
  registry.registerLexicons(HYPERCERT_LEXICONS);
729
718
 
730
719
  // Validate a record
731
- const result = registry.validate(
732
- HYPERCERT_COLLECTIONS.CLAIM,
733
- claimData
734
- );
720
+ const result = registry.validate(HYPERCERT_COLLECTIONS.CLAIM, claimData);
735
721
 
736
722
  if (!result.valid) {
737
723
  console.error("Invalid record:", result.error);
@@ -741,10 +727,7 @@ if (!result.valid) {
741
727
  #### Creating Records with Proper Types
742
728
 
743
729
  ```typescript
744
- import type {
745
- HypercertContribution,
746
- StrongRef,
747
- } from "@hypercerts-org/sdk-core";
730
+ import type { HypercertContribution, StrongRef } from "@hypercerts-org/sdk-core";
748
731
  import { HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
749
732
 
750
733
  // Create a contribution record
@@ -757,8 +740,8 @@ const contribution: HypercertContribution = {
757
740
  contributors: ["did:plc:contributor1", "did:plc:contributor2"],
758
741
  role: "implementer",
759
742
  description: "On-ground implementation team",
760
- workTimeframeFrom: "2024-01-01T00:00:00Z", // Note: lowercase 'f' for contributions
761
- workTimeframeTo: "2024-06-30T00:00:00Z", // Note: lowercase 'f' for contributions
743
+ workTimeframeFrom: "2024-01-01T00:00:00Z", // Note: lowercase 'f' for contributions
744
+ workTimeframeTo: "2024-06-30T00:00:00Z", // Note: lowercase 'f' for contributions
762
745
  createdAt: new Date().toISOString(),
763
746
  };
764
747
 
@@ -775,14 +758,14 @@ await repo.records.create({
775
758
  import { HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
776
759
 
777
760
  // Collection NSIDs
778
- HYPERCERT_COLLECTIONS.CLAIM // "org.hypercerts.claim"
779
- HYPERCERT_COLLECTIONS.RIGHTS // "org.hypercerts.claim.rights"
780
- HYPERCERT_COLLECTIONS.CONTRIBUTION // "org.hypercerts.claim.contribution"
781
- HYPERCERT_COLLECTIONS.MEASUREMENT // "org.hypercerts.claim.measurement"
782
- HYPERCERT_COLLECTIONS.EVALUATION // "org.hypercerts.claim.evaluation"
783
- HYPERCERT_COLLECTIONS.EVIDENCE // "org.hypercerts.claim.evidence"
784
- HYPERCERT_COLLECTIONS.COLLECTION // "org.hypercerts.collection"
785
- HYPERCERT_COLLECTIONS.LOCATION // "app.certified.location"
761
+ HYPERCERT_COLLECTIONS.CLAIM; // "org.hypercerts.claim"
762
+ HYPERCERT_COLLECTIONS.RIGHTS; // "org.hypercerts.claim.rights"
763
+ HYPERCERT_COLLECTIONS.CONTRIBUTION; // "org.hypercerts.claim.contribution"
764
+ HYPERCERT_COLLECTIONS.MEASUREMENT; // "org.hypercerts.claim.measurement"
765
+ HYPERCERT_COLLECTIONS.EVALUATION; // "org.hypercerts.claim.evaluation"
766
+ HYPERCERT_COLLECTIONS.EVIDENCE; // "org.hypercerts.claim.evidence"
767
+ HYPERCERT_COLLECTIONS.COLLECTION; // "org.hypercerts.collection"
768
+ HYPERCERT_COLLECTIONS.LOCATION; // "app.certified.location"
786
769
  ```
787
770
 
788
771
  ## Development