@hypercerts-org/sdk-core 0.10.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/CHANGELOG.md +273 -0
- package/README.md +97 -114
- package/dist/index.cjs +435 -534
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +160 -271
- package/dist/index.mjs +387 -499
- package/dist/index.mjs.map +1 -1
- package/dist/lexicons.cjs +103 -374
- package/dist/lexicons.cjs.map +1 -1
- package/dist/lexicons.d.ts +90 -188
- package/dist/lexicons.mjs +103 -367
- package/dist/lexicons.mjs.map +1 -1
- package/dist/types.cjs +6 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +24 -37
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -1
- package/package.json +10 -9
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# @hypercerts-org/sdk-core
|
|
2
|
+
|
|
3
|
+
## 1.0.0-beta.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#66](https://github.com/hypercerts-org/hypercerts-sdk/pull/66)
|
|
8
|
+
[`7c33673`](https://github.com/hypercerts-org/hypercerts-sdk/commit/7c33673fd5f53d92ba160ced1d1582178fa7c455) Thanks
|
|
9
|
+
[@aspiers](https://github.com/aspiers)! - feat: migrate to published @hypercerts-org/lexicon package
|
|
10
|
+
|
|
11
|
+
This release migrates the SDK from using a local `packages/lexicon` workspace to consuming the published
|
|
12
|
+
`@hypercerts-org/lexicon` package from npm.
|
|
13
|
+
|
|
14
|
+
**Benefits:**
|
|
15
|
+
- **Single source of truth**: Lexicon definitions now come from a dedicated, independently versioned package
|
|
16
|
+
- **Reduced codebase**: Removes ~3,000 lines of duplicated lexicon code from this repository
|
|
17
|
+
- **Better versioning**: Lexicon can be updated independently via semver dependency updates
|
|
18
|
+
- **Simplified architecture**: No longer maintaining duplicate lexicon tooling in monorepo
|
|
19
|
+
- **Improved maintainability**: Clearer separation of concerns between SDK and lexicon definitions
|
|
20
|
+
|
|
21
|
+
**Breaking Changes:**
|
|
22
|
+
1. **Removed `LexiconRegistry` class**: Use the `validate()` function instead
|
|
23
|
+
2. **Removed `ValidationResult` type**: Validation functions now throw errors on validation failure
|
|
24
|
+
3. **Renamed type exports** to match lexicon package conventions:
|
|
25
|
+
- `OrgHypercertsClaim` → `OrgHypercertsClaimActivity`
|
|
26
|
+
- `OrgHypercertsCollection` → `OrgHypercertsClaimCollection`
|
|
27
|
+
4. **Renamed constant exports** to use consistent naming:
|
|
28
|
+
- `schemas` → `HYPERCERTS_SCHEMAS`
|
|
29
|
+
- `schemaDict` → `HYPERCERTS_SCHEMA_DICT`
|
|
30
|
+
- `ids` → `HYPERCERTS_NSIDS`
|
|
31
|
+
- `lexicons` now exported as type-only (use `HYPERCERTS_LEXICON_JSON` or `HYPERCERTS_LEXICON_DOC` for runtime
|
|
32
|
+
values)
|
|
33
|
+
|
|
34
|
+
**Migration Guide:**
|
|
35
|
+
|
|
36
|
+
**Validation:**
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// Before
|
|
40
|
+
import { LexiconRegistry, HYPERCERT_LEXICONS, HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
|
|
41
|
+
const registry = new LexiconRegistry();
|
|
42
|
+
registry.registerLexicons(HYPERCERT_LEXICONS);
|
|
43
|
+
const result = registry.validate(HYPERCERT_COLLECTIONS.CLAIM, claimData);
|
|
44
|
+
if (!result.valid) {
|
|
45
|
+
console.error("Invalid record:", result.error);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// After
|
|
49
|
+
import { validate, HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
|
|
50
|
+
try {
|
|
51
|
+
validate(HYPERCERT_COLLECTIONS.CLAIM, claimData);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error("Invalid record:", error);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Type imports:**
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// Before
|
|
61
|
+
import { OrgHypercertsClaim, OrgHypercertsCollection } from "@hypercerts-org/sdk-core";
|
|
62
|
+
|
|
63
|
+
// After
|
|
64
|
+
import { OrgHypercertsClaimActivity, OrgHypercertsClaimCollection } from "@hypercerts-org/sdk-core";
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Constant imports:**
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Before
|
|
71
|
+
import { schemas, schemaDict, ids } from "@hypercerts-org/sdk-core";
|
|
72
|
+
|
|
73
|
+
// After
|
|
74
|
+
import { HYPERCERTS_SCHEMAS, HYPERCERTS_SCHEMA_DICT, HYPERCERTS_NSIDS } from "@hypercerts-org/sdk-core";
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Other Changes:**
|
|
78
|
+
- Added dependency on `@hypercerts-org/lexicon@0.10.0-beta.3`
|
|
79
|
+
- Updated all lexicon type exports to use namespaced imports from lexicon package
|
|
80
|
+
- Improved hypercert validation with new test coverage
|
|
81
|
+
- Enhanced test mocks and fixtures for better testability
|
|
82
|
+
|
|
83
|
+
**For SDK users**: If you're using `LexiconRegistry`, follow the migration guide above. If you're only using the
|
|
84
|
+
high-level Repository API, no changes are required.
|
|
85
|
+
|
|
86
|
+
### Minor Changes
|
|
87
|
+
|
|
88
|
+
- [#60](https://github.com/hypercerts-org/hypercerts-sdk/pull/60)
|
|
89
|
+
[`f7594f8`](https://github.com/hypercerts-org/hypercerts-sdk/commit/f7594f838fd7e64837da702f7498e84a49b28bf5) Thanks
|
|
90
|
+
[@bitbeckers](https://github.com/bitbeckers)! - Implement ConfigurableAgent for proper multi-server routing
|
|
91
|
+
|
|
92
|
+
This release introduces the `ConfigurableAgent` class that enables proper routing of AT Protocol requests to different
|
|
93
|
+
servers (PDS, SDS, or custom instances) while maintaining OAuth authentication from a single session.
|
|
94
|
+
|
|
95
|
+
**Breaking Changes:**
|
|
96
|
+
- Repository now uses `ConfigurableAgent` internally instead of standard `Agent`
|
|
97
|
+
- This fixes the issue where invalid `agent.service` and `agent.api.xrpc.uri` property assignments were causing
|
|
98
|
+
TypeScript errors
|
|
99
|
+
|
|
100
|
+
**New Features:**
|
|
101
|
+
- `ConfigurableAgent` class exported from `@hypercerts-org/sdk-core`
|
|
102
|
+
- Support for simultaneous connections to multiple SDS instances with one OAuth session
|
|
103
|
+
- Proper request routing based on configured service URL rather than session defaults
|
|
104
|
+
|
|
105
|
+
**Bug Fixes:**
|
|
106
|
+
- Remove invalid Agent property assignments that caused TypeScript compilation errors (TS2339)
|
|
107
|
+
- Replace all `any` types in test files with proper type annotations
|
|
108
|
+
- Eliminate build warnings from missing type declarations
|
|
109
|
+
|
|
110
|
+
**Architecture:** The new routing system wraps the OAuth session's fetch handler to prepend the target server URL,
|
|
111
|
+
ensuring requests go to the intended destination while maintaining full authentication (DPoP, access tokens, etc.).
|
|
112
|
+
This enables use cases like:
|
|
113
|
+
- Routing to SDS while authenticated via PDS
|
|
114
|
+
- Accessing multiple organization SDS instances simultaneously
|
|
115
|
+
- Testing against different server environments
|
|
116
|
+
- Dynamic switching between PDS and SDS operations
|
|
117
|
+
|
|
118
|
+
**Migration:** No action required - the change is transparent to existing code. The Repository API remains unchanged.
|
|
119
|
+
|
|
120
|
+
- [#46](https://github.com/hypercerts-org/hypercerts-sdk/pull/46)
|
|
121
|
+
[`eda4ac2`](https://github.com/hypercerts-org/hypercerts-sdk/commit/eda4ac233e09764d83f042ba7df94d4c9884cc01) Thanks
|
|
122
|
+
[@bitbeckers](https://github.com/bitbeckers)! - Initial release of sdk-core package with ATProto SDK for
|
|
123
|
+
authentication, repository operations, and lexicon management
|
|
124
|
+
|
|
125
|
+
- [#65](https://github.com/hypercerts-org/hypercerts-sdk/pull/65)
|
|
126
|
+
[`826b50c`](https://github.com/hypercerts-org/hypercerts-sdk/commit/826b50c140a56fee4feeb6b6c83d1123e44c5118) Thanks
|
|
127
|
+
[@bitbeckers](https://github.com/bitbeckers)! - feat(auth): add OAuth scopes and granular permissions system
|
|
128
|
+
|
|
129
|
+
Add comprehensive OAuth permissions system with support for granular permissions and easy email access:
|
|
130
|
+
|
|
131
|
+
**Permission System**
|
|
132
|
+
- Zod schemas for all ATProto permission types (account, repo, blob, rpc, identity, include)
|
|
133
|
+
- Support for both transitional (legacy) and granular permission models
|
|
134
|
+
- Type-safe permission builder with fluent API
|
|
135
|
+
- 14 pre-built scope presets (EMAIL_READ, POSTING_APP, FULL_ACCESS, etc.)
|
|
136
|
+
- 8 utility functions for working with scopes
|
|
137
|
+
|
|
138
|
+
**Email Access**
|
|
139
|
+
- New `getAccountEmail()` method to retrieve user email from authenticated session
|
|
140
|
+
- Returns null when permission not granted
|
|
141
|
+
- Comprehensive error handling
|
|
142
|
+
|
|
143
|
+
**Enhanced OAuth Integration**
|
|
144
|
+
- Automatic scope validation with helpful warnings
|
|
145
|
+
- Migration suggestions from transitional to granular permissions
|
|
146
|
+
- Improved documentation with comprehensive examples
|
|
147
|
+
|
|
148
|
+
**Breaking Changes**: None - fully backward compatible
|
|
149
|
+
|
|
150
|
+
**New Exports**:
|
|
151
|
+
- `PermissionBuilder` - Fluent API for building type-safe scopes
|
|
152
|
+
- `ScopePresets` - 14 ready-to-use permission presets
|
|
153
|
+
- Utility functions: `buildScope()`, `parseScope()`, `hasPermission()`, `validateScope()`, etc.
|
|
154
|
+
- Permission schemas and types for TypeScript consumers
|
|
155
|
+
|
|
156
|
+
See README for usage examples and migration guide.
|
|
157
|
+
|
|
158
|
+
- [#56](https://github.com/hypercerts-org/hypercerts-sdk/pull/56)
|
|
159
|
+
[`caceacb`](https://github.com/hypercerts-org/hypercerts-sdk/commit/caceacbc5572a590c750a95ccfda23fff2dd0c61) Thanks
|
|
160
|
+
[@bitbeckers](https://github.com/bitbeckers)! - Add pagination support and fix React hooks for SDS operations
|
|
161
|
+
|
|
162
|
+
**Breaking Changes (sdk-core):**
|
|
163
|
+
- `CollaboratorOperations.list()` now returns `{ collaborators: RepositoryAccessGrant[], cursor?: string }` instead of
|
|
164
|
+
`RepositoryAccessGrant[]`
|
|
165
|
+
- `OrganizationOperations.list()` now returns `{ organizations: OrganizationInfo[], cursor?: string }` instead of
|
|
166
|
+
`OrganizationInfo[]`
|
|
167
|
+
|
|
168
|
+
**Features:**
|
|
169
|
+
- Add cursor-based pagination support to collaborator and organization list operations
|
|
170
|
+
- Support optional `limit` and `cursor` parameters for paginated queries
|
|
171
|
+
- Update internal methods (`hasAccess`, `getRole`, `get`) to handle new pagination structure
|
|
172
|
+
|
|
173
|
+
**Bug Fixes (sdk-core):**
|
|
174
|
+
- Fix permissions parsing in `CollaboratorOperationsImpl.list()` to match actual SDS API format (object with boolean
|
|
175
|
+
flags)
|
|
176
|
+
- Prevent `TypeError: permissionArray.includes is not a function` by correctly handling permissions as objects
|
|
177
|
+
- Fix Agent service URL configuration to route queries to the correct server (PDS or SDS)
|
|
178
|
+
- Resolve "Could not find repo" errors when querying SDS repositories by ensuring Agent uses SDS service endpoint
|
|
179
|
+
- Update test mocks to use the actual SDS API response format
|
|
180
|
+
|
|
181
|
+
**Bug Fixes (sdk-react):**
|
|
182
|
+
- Fix `useCollaborators` hook to correctly destructure paginated response
|
|
183
|
+
- Fix `useOrganizations` hook to correctly destructure paginated response
|
|
184
|
+
- All React hooks now properly handle the new pagination structure
|
|
185
|
+
|
|
186
|
+
**Documentation:**
|
|
187
|
+
- Comprehensive README updates with clear examples for all SDK operations
|
|
188
|
+
- Added pagination examples throughout documentation
|
|
189
|
+
- Improved code samples with realistic use cases
|
|
190
|
+
|
|
191
|
+
**Tests:**
|
|
192
|
+
- All 317 tests passing (181 sdk-core + 136 sdk-react)
|
|
193
|
+
- Updated test mocks to match new pagination response structure
|
|
194
|
+
- Build completes with zero warnings
|
|
195
|
+
|
|
196
|
+
### Patch Changes
|
|
197
|
+
|
|
198
|
+
- [#58](https://github.com/hypercerts-org/hypercerts-sdk/pull/58)
|
|
199
|
+
[`bcde5fa`](https://github.com/hypercerts-org/hypercerts-sdk/commit/bcde5faeb11dba6d99967a434e8ec32d67b3aca5) Thanks
|
|
200
|
+
[@bitbeckers](https://github.com/bitbeckers)! - Fix collaborator permissions parsing to align with SDS API response
|
|
201
|
+
format. The SDS API returns permissions as objects with boolean flags (`{ read: true, create: true, ... }`) rather
|
|
202
|
+
than string arrays. This fix simplifies the permissions parser to handle only the actual format returned by the API.
|
|
203
|
+
|
|
204
|
+
- [#64](https://github.com/hypercerts-org/hypercerts-sdk/pull/64)
|
|
205
|
+
[`f83f03a`](https://github.com/hypercerts-org/hypercerts-sdk/commit/f83f03a8e505d57d38b45f3a50213ca1035c1229) Thanks
|
|
206
|
+
[@bitbeckers](https://github.com/bitbeckers)! - fix(lexicon): correct field names and types to match lexicon schema
|
|
207
|
+
- Fix `workTimeframeFrom/To` -> `workTimeFrameFrom/To` (capital 'F' in Frame)
|
|
208
|
+
- Make `shortDescription` required for hypercert claims per lexicon schema
|
|
209
|
+
- Update all interfaces, implementations, and tests to use correct field names
|
|
210
|
+
- Add comprehensive lexicon documentation to README
|
|
211
|
+
|
|
212
|
+
- [#62](https://github.com/hypercerts-org/hypercerts-sdk/pull/62)
|
|
213
|
+
[`4b80edc`](https://github.com/hypercerts-org/hypercerts-sdk/commit/4b80edca4162c4ce929edb28ffffa3f99f21cb74) Thanks
|
|
214
|
+
[@bitbeckers](https://github.com/bitbeckers)! - fix(sdk-core): add required $type field to all record creation
|
|
215
|
+
operations
|
|
216
|
+
|
|
217
|
+
The AT Protocol requires all records to include a `$type` field, but the SDK was omitting it during record creation,
|
|
218
|
+
causing validation errors like "Record/$type must be a string". This fix:
|
|
219
|
+
- Adds `$type` field to all record types (rights, claims, locations, contributions, measurements, evaluations,
|
|
220
|
+
collections)
|
|
221
|
+
- Fixes location record implementation to match `app.certified.location` lexicon schema
|
|
222
|
+
- Makes `srs` (Spatial Reference System) field required for location records with proper validation
|
|
223
|
+
- Updates interfaces and documentation to reflect required fields
|
|
224
|
+
|
|
225
|
+
Breaking change: `location.srs` is now required when creating locations (use "EPSG:4326" for standard WGS84
|
|
226
|
+
coordinates).
|
|
227
|
+
|
|
228
|
+
- [#59](https://github.com/hypercerts-org/hypercerts-sdk/pull/59)
|
|
229
|
+
[`7020fcc`](https://github.com/hypercerts-org/hypercerts-sdk/commit/7020fcc9845a4d4c2f792536611fc3bb5e3c4fe3) Thanks
|
|
230
|
+
[@bitbeckers](https://github.com/bitbeckers)! - Configure npm publishing to exclude source code and development files.
|
|
231
|
+
Packages now only include the compiled `dist/` folder, README, and necessary runtime files (lexicon schemas). This
|
|
232
|
+
reduces package sizes and prevents unnecessary files from being published to npm.
|
|
233
|
+
|
|
234
|
+
- [#60](https://github.com/hypercerts-org/hypercerts-sdk/pull/60)
|
|
235
|
+
[`39accd9`](https://github.com/hypercerts-org/hypercerts-sdk/commit/39accd954422c901b7faf93e08be88e68a4f849a) Thanks
|
|
236
|
+
[@bitbeckers](https://github.com/bitbeckers)! - fix(sdk-core): ensure repository operations route to correct server
|
|
237
|
+
(PDS/SDS)
|
|
238
|
+
|
|
239
|
+
**Problem:** When using OAuth authentication to access organization repositories on SDS via
|
|
240
|
+
`repo.repo(organizationDid)`, all operations like `hypercerts.list()` and `hypercerts.listCollections()` were
|
|
241
|
+
incorrectly routing to the user's PDS instead of the SDS server, causing "Could not find repo" errors.
|
|
242
|
+
|
|
243
|
+
**Root Cause:** The AT Protocol Agent was created from the OAuth session but only had its `api.xrpc.uri` property
|
|
244
|
+
configured. Without setting the Agent's `service` property, it continued using the session's default PDS URL for all
|
|
245
|
+
requests, even when switched to organization repositories.
|
|
246
|
+
|
|
247
|
+
**Solution:** Set both `agent.service` and `agent.api.xrpc.uri` to the specified server URL in the Repository
|
|
248
|
+
constructor. This ensures that:
|
|
249
|
+
- Initial repository creation routes to the correct server (PDS or SDS)
|
|
250
|
+
- Repository switching via `.repo(did)` maintains the same server routing
|
|
251
|
+
- All operation implementations (HypercertOperationsImpl, RecordOperationsImpl, ProfileOperationsImpl,
|
|
252
|
+
BlobOperationsImpl) now route correctly
|
|
253
|
+
|
|
254
|
+
**Documentation:** Added comprehensive PDS/SDS orchestration explanation to README covering:
|
|
255
|
+
- Server type comparison and use cases
|
|
256
|
+
- How repository routing works internally
|
|
257
|
+
- Common patterns for personal vs organization hypercerts
|
|
258
|
+
- Key implementation details about Agent configuration
|
|
259
|
+
|
|
260
|
+
- [#56](https://github.com/hypercerts-org/hypercerts-sdk/pull/56)
|
|
261
|
+
[`cb3268d`](https://github.com/hypercerts-org/hypercerts-sdk/commit/cb3268d78614efaf15aecc57a5dc3bce8313f3ca) Thanks
|
|
262
|
+
[@bitbeckers](https://github.com/bitbeckers)! - Fix SDS organization and collaborator operations to match API
|
|
263
|
+
contracts
|
|
264
|
+
- Add required creatorDid parameter to organization.create endpoint
|
|
265
|
+
- Fix organization.list to parse organizations field instead of repositories
|
|
266
|
+
- Update accessType values to match SDS API: owner|shared|none (was owner|collaborator)
|
|
267
|
+
- Add permission string array parser for collaborator.list endpoint
|
|
268
|
+
- Update type definitions to match actual SDS API response formats
|
|
269
|
+
|
|
270
|
+
- [#55](https://github.com/hypercerts-org/hypercerts-sdk/pull/55)
|
|
271
|
+
[`23c3d9a`](https://github.com/hypercerts-org/hypercerts-sdk/commit/23c3d9a3b71f326df68b65420c83f7ae42c2432d) Thanks
|
|
272
|
+
[@bitbeckers](https://github.com/bitbeckers)! - Fix endpoints and NSIDs for SDS operations in CollaboratorOperations
|
|
273
|
+
and OrganizationOperations
|
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
|
|
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;
|
|
178
|
-
const scope = ScopePresets.POSTING_APP;
|
|
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(
|
|
184
|
-
.repoWrite(
|
|
185
|
-
.blob([
|
|
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:
|
|
193
|
-
redirectUri:
|
|
194
|
-
scope: 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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
|
495
|
-
|
|
496
|
-
| **Records**
|
|
497
|
-
| Create record
|
|
498
|
-
| Get record
|
|
499
|
-
| Update record
|
|
500
|
-
| Delete record
|
|
501
|
-
| List records
|
|
502
|
-
| **Hypercerts**
|
|
503
|
-
| Create hypercert
|
|
504
|
-
| Get hypercert
|
|
505
|
-
| Update hypercert
|
|
506
|
-
| Delete hypercert
|
|
507
|
-
| List hypercerts
|
|
508
|
-
| Add contribution
|
|
509
|
-
| Add measurement
|
|
510
|
-
| **Blobs**
|
|
511
|
-
| Upload blob
|
|
512
|
-
| Get blob
|
|
513
|
-
| **Profile**
|
|
514
|
-
| Get profile
|
|
515
|
-
| Update profile
|
|
516
|
-
| **Organizations**
|
|
517
|
-
| Create org
|
|
518
|
-
| Get org
|
|
519
|
-
| List orgs
|
|
520
|
-
| **Collaborators**
|
|
521
|
-
| Grant access
|
|
522
|
-
| Revoke access
|
|
523
|
-
| List collaborators | `repo.collaborators.list()`
|
|
524
|
-
| Check access
|
|
525
|
-
| Get role
|
|
526
|
-
| Get permissions
|
|
527
|
-
| Transfer ownership | `repo.collaborators.transferOwnership()` | ❌
|
|
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
|
|
553
|
-
|
|
554
|
-
| `OrgHypercertsClaim.Main`
|
|
555
|
-
| `OrgHypercertsClaimRights.Main`
|
|
547
|
+
| Lexicon Type | SDK Alias |
|
|
548
|
+
| ------------------------------------- | ----------------------- |
|
|
549
|
+
| `OrgHypercertsClaim.Main` | `HypercertClaim` |
|
|
550
|
+
| `OrgHypercertsClaimRights.Main` | `HypercertRights` |
|
|
556
551
|
| `OrgHypercertsClaimContribution.Main` | `HypercertContribution` |
|
|
557
|
-
| `OrgHypercertsClaimMeasurement.Main`
|
|
558
|
-
| `OrgHypercertsClaimEvaluation.Main`
|
|
559
|
-
| `OrgHypercertsCollection.Main`
|
|
560
|
-
| `AppCertifiedLocation.Main`
|
|
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
|
|
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",
|
|
684
|
-
workTimeFrameTo: "2024-12-31T00:00:00Z",
|
|
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,
|
|
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",
|
|
761
|
-
workTimeframeTo: "2024-06-30T00:00:00Z",
|
|
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
|
|
779
|
-
HYPERCERT_COLLECTIONS.RIGHTS
|
|
780
|
-
HYPERCERT_COLLECTIONS.CONTRIBUTION
|
|
781
|
-
HYPERCERT_COLLECTIONS.MEASUREMENT
|
|
782
|
-
HYPERCERT_COLLECTIONS.EVALUATION
|
|
783
|
-
HYPERCERT_COLLECTIONS.EVIDENCE
|
|
784
|
-
HYPERCERT_COLLECTIONS.COLLECTION
|
|
785
|
-
HYPERCERT_COLLECTIONS.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
|