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

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,158 @@
1
1
  # @hypercerts-org/sdk-core
2
2
 
3
+ ## 0.10.0-beta.5
4
+
5
+ ### Minor Changes
6
+
7
+ - [#87](https://github.com/hypercerts-org/hypercerts-sdk/pull/87)
8
+ [`85b1350`](https://github.com/hypercerts-org/hypercerts-sdk/commit/85b13502791e49966dae3d0dd0e833905c59abe3) Thanks
9
+ [@bitbeckers](https://github.com/bitbeckers)! - Add comprehensive project support to SDK
10
+
11
+ **Core SDK (`@hypercerts-org/sdk-core`):**
12
+ - Add project CRUD operations (createProject, getProject, listProjects, updateProject, deleteProject)
13
+ - Add project events (projectCreated, projectUpdated, projectDeleted)
14
+ - Support for avatar and coverPhoto blob uploads
15
+ - Activities array with weight values
16
+ - Location reference support
17
+ - 34 comprehensive tests with full coverage
18
+
19
+ **React SDK (`@hypercerts-org/sdk-react`):**
20
+ - Add useProjects and useProject hooks
21
+ - Project query keys for cache management
22
+ - TypeScript types for projects (Project, CreateProjectParams, UpdateProjectParams)
23
+ - Test factory support for project hooks
24
+ - Full pagination and optimistic updates support
25
+
26
+ Projects organize multiple hypercert activities with metadata including title, shortDescription, description (Leaflet
27
+ documents), avatar, cover photo, activities with weights, and location references.
28
+
29
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
30
+ [`f9dd27f`](https://github.com/hypercerts-org/hypercerts-sdk/commit/f9dd27f78de0ee49aab9079e76566f272b161cd0) Thanks
31
+ [@bitbeckers](https://github.com/bitbeckers)! - Add BaseOperations abstract class for building custom lexicon
32
+ operations. Developers can now extend BaseOperations to create type-safe, validated operation classes for their custom
33
+ lexicons, with built-in helpers for record creation, validation, and strongRef management.
34
+
35
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
36
+ [`e850310`](https://github.com/hypercerts-org/hypercerts-sdk/commit/e850310d26e0561bdcfb778a6ef3bedbb7453eed) Thanks
37
+ [@bitbeckers](https://github.com/bitbeckers)! - Add comprehensive documentation and examples for custom lexicons.
38
+ Includes custom-lexicons.md guide, sidecar-pattern.md guide, and a complete working example with tests demonstrating
39
+ how to create and use custom lexicons for evaluating hypercerts.
40
+
41
+ - [#84](https://github.com/hypercerts-org/hypercerts-sdk/pull/84)
42
+ [`3157c18`](https://github.com/hypercerts-org/hypercerts-sdk/commit/3157c188c70e2f9473ee14eddaf635e3fbd346a1) Thanks
43
+ [@Kzoeps](https://github.com/Kzoeps)! - Evidence records are now created separately instead of being embedded inline
44
+ in hypercerts
45
+ - `create()` now calls `addEvidence()` for each evidence item using `Promise.all()` for parallel creation
46
+ - Remove inline evidence embedding from hypercert records
47
+ - Add `evidenceUris?: string[]` to `CreateHypercertResult` interface
48
+ - Add `createEvidenceWithProgress()` helper method with "addEvidence" progress tracking
49
+ - `addEvidence()` SDK constructs `$type`, `createdAt`, and `subject` fields internally
50
+
51
+ **Breaking Changes:**
52
+ - Evidence is no longer embedded in the hypercert record - use `result.evidenceUris` to access evidence record URIs
53
+ - `addEvidence()` now accepts a single `CreateHypercertEvidenceParams` object instead of
54
+ `(uri: string, evidence: HypercertEvidence[])`
55
+
56
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
57
+ [`0cd3b26`](https://github.com/hypercerts-org/hypercerts-sdk/commit/0cd3b26eb779246e9ef094f614f2f77807926f1b) Thanks
58
+ [@bitbeckers](https://github.com/bitbeckers)! - Add LexiconRegistry for custom lexicon management. Developers can now
59
+ register custom lexicon schemas at runtime and validate records against registered schemas before creation. The
60
+ registry supports:
61
+ - Registering custom lexicon definitions from JSON
62
+ - Validating records against registered schemas
63
+ - Querying registered lexicons
64
+ - Managing lexicon lifecycle (register/unregister)
65
+
66
+ This enables developers to extend the SDK with custom record types that can reference hypercerts and other records
67
+ using strongRefs.
68
+
69
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
70
+ [`b87cb22`](https://github.com/hypercerts-org/hypercerts-sdk/commit/b87cb2265d924b531eef8d58c669dc931b61e561) Thanks
71
+ [@bitbeckers](https://github.com/bitbeckers)! - Add lexicon development utilities for custom lexicons. Developers can
72
+ now use helper functions for AT-URI parsing, strongRef creation, lexicon schema building, and sidecar pattern
73
+ implementation. This includes:
74
+ - AT-URI utilities: parseAtUri, buildAtUri, extractRkeyFromUri, isValidAtUri
75
+ - StrongRef utilities: createStrongRef, createStrongRefFromResult, validateStrongRef
76
+ - Lexicon builders: createStringField, createIntegerField, createStrongRefField, createRecordDef, createLexiconDoc,
77
+ and more
78
+ - Sidecar pattern: createSidecarRecord, attachSidecar, createWithSidecars, batchCreateSidecars
79
+
80
+ - [#88](https://github.com/hypercerts-org/hypercerts-sdk/pull/88)
81
+ [`19c78df`](https://github.com/hypercerts-org/hypercerts-sdk/commit/19c78dfef448fb43d353d95721c13f3a35618fb3) Thanks
82
+ [@bitbeckers](https://github.com/bitbeckers)! - feat: add HTTP loopback URL support for local development
83
+
84
+ Enable local development and testing with HTTP loopback URLs (`http://localhost`, `http://127.0.0.1`, `http://[::1]`)
85
+ while maintaining security for production deployments.
86
+
87
+ **Configuration Updates**
88
+ - Custom URL validator accepting HTTPS URLs or HTTP loopback addresses
89
+ - Update `OAuthConfigSchema` to allow loopback URLs for `clientId`, `redirectUri`, `jwksUri`
90
+ - Add optional `developmentMode` boolean flag to suppress warnings
91
+ - Update `ServerConfigSchema` to allow loopback URLs for PDS/SDS servers
92
+ - Export `isLoopbackUrl()` helper function and TypeScript types (`LoopbackUrl`, `HttpsUrl`,
93
+ `DevelopmentOrProductionUrl`)
94
+
95
+ **Development Mode Features**
96
+ - Automatic loopback detection with informative logging
97
+ - Warning when using loopback URLs without explicit `developmentMode` flag
98
+ - Info logs indicating development mode is active
99
+ - Clear guidance about authorization server requirements
100
+
101
+ **Testing**
102
+ - 28 new unit tests for loopback URL validation
103
+ - Tests cover localhost, 127.0.0.1, and [::1] (IPv6) loopback addresses
104
+ - Tests verify rejection of non-loopback HTTP URLs
105
+ - Tests ensure HTTPS URLs always accepted
106
+
107
+ **Documentation**
108
+ - Comprehensive local development guide in Core SDK README
109
+ - NextJS App Router example with loopback configuration
110
+ - API route setup examples (OAuth callback, JWKS endpoint)
111
+ - Important notes about authorization server support and production safety
112
+ - Local development example added to React SDK factory JSDoc
113
+
114
+ **Breaking Changes**: None - fully backward compatible
115
+
116
+ **Migration**: No migration needed for existing configurations. Existing HTTPS URLs continue to work without changes.
117
+
118
+ This feature enables developers to test the SDK locally without requiring HTTPS certificates, while the underlying
119
+ `@atproto/oauth-client-node` library handles loopback OAuth flows per the AT Protocol specification.
120
+
121
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
122
+ [`3554580`](https://github.com/hypercerts-org/hypercerts-sdk/commit/3554580d77d9467c88c779e75a96a08d3e17bfd7) Thanks
123
+ [@bitbeckers](https://github.com/bitbeckers)! - Add automatic lexicon validation to RecordOperations. Records are now
124
+ validated against registered lexicon schemas before being sent to the server, catching schema violations early.
125
+ Validation can be bypassed using the `skipValidation` parameter for advanced use cases.
126
+
127
+ - [#96](https://github.com/hypercerts-org/hypercerts-sdk/pull/96)
128
+ [`eea06a7`](https://github.com/hypercerts-org/hypercerts-sdk/commit/eea06a7f5e4f655ccac635fa8842ea32a6dfde64) Thanks
129
+ [@Kzoeps](https://github.com/Kzoeps)! - Refactor location attachment to match lexicon specifications
130
+
131
+ **New Features:**
132
+ - Add `AttachLocationParams` interface exported from SDK for type-safe location attachment
133
+ - Location data now properly uses `org.hypercerts.defs#uri` (for string URIs) or `org.hypercerts.defs#smallBlob` (for
134
+ GeoJSON blobs) to match lexicon spec
135
+ - Add `lpVersion` and `locationType` fields to location parameters for better protocol compliance
136
+
137
+ **Improvements:**
138
+ - Centralized blob upload logic with new `handleBlobUpload()` helper method
139
+ - Simplified location type detection - now based on content type (string vs Blob) instead of separate `geojson`
140
+ parameter
141
+ - Improved type safety with structured `AttachLocationParams` interface
142
+
143
+ **Breaking Changes:**
144
+ - `attachLocation()` signature changed from `(uri, { value, name?, description?, srs, geojson? })` to
145
+ `(uri, AttachLocationParams)`
146
+ - `AttachLocationParams` now requires: `lpVersion`, `srs`, `locationType`, and `location` (string | Blob)
147
+ - The `location` field in `CreateHypercertParams` now uses `AttachLocationParams` type instead of inline object
148
+ - Removed separate `value` and `geojson` fields - use single `location` field with either string or Blob
149
+
150
+ - [#98](https://github.com/hypercerts-org/hypercerts-sdk/pull/98)
151
+ [`e0ef6e9`](https://github.com/hypercerts-org/hypercerts-sdk/commit/e0ef6e9cb9138590e81b4a2929ca27ae557d2f39) Thanks
152
+ [@bitbeckers](https://github.com/bitbeckers)! - Integrate LexiconRegistry into SDK and Repository. The SDK now
153
+ initializes a LexiconRegistry with hypercert lexicons by default and exposes it via `getLexiconRegistry()`. Repository
154
+ instances receive the registry and pass it to RecordOperations for future validation support.
155
+
3
156
  ## 0.10.0-beta.4
4
157
 
5
158
  ### 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
@@ -713,20 +806,52 @@ const validationResult = OrgHypercertsClaim.validateMain(claim);
713
806
 
714
807
  #### Using LexiconRegistry
715
808
 
716
- For repository-level validation:
809
+ The SDK automatically initializes a LexiconRegistry with all hypercert lexicons. You can access it to validate records
810
+ or register custom lexicons:
717
811
 
718
812
  ```typescript
719
- import { LexiconRegistry, HYPERCERT_LEXICONS, HYPERCERT_COLLECTIONS } from "@hypercerts-org/sdk-core";
720
-
721
- const registry = new LexiconRegistry();
722
- registry.registerLexicons(HYPERCERT_LEXICONS);
813
+ // Access the registry from the SDK
814
+ const registry = sdk.getLexiconRegistry();
723
815
 
724
816
  // Validate a record
725
- const result = registry.validate(HYPERCERT_COLLECTIONS.CLAIM, claimData);
817
+ const result = registry.validate("org.hypercerts.claim.activity", claimData);
726
818
 
727
819
  if (!result.valid) {
728
820
  console.error("Invalid record:", result.error);
729
821
  }
822
+
823
+ // Register a custom lexicon
824
+ registry.registerFromJSON({
825
+ lexicon: 1,
826
+ id: "org.myapp.customRecord",
827
+ defs: {
828
+ main: {
829
+ type: "record",
830
+ key: "tid",
831
+ record: {
832
+ type: "object",
833
+ required: ["$type", "title"],
834
+ properties: {
835
+ $type: { type: "string", const: "org.myapp.customRecord" },
836
+ title: { type: "string" },
837
+ createdAt: { type: "string", format: "datetime" },
838
+ },
839
+ },
840
+ },
841
+ },
842
+ });
843
+
844
+ // Check if a lexicon is registered
845
+ if (registry.isRegistered("org.myapp.customRecord")) {
846
+ console.log("Custom lexicon is ready to use");
847
+ }
848
+ ```
849
+
850
+ You can also access the registry from a Repository instance:
851
+
852
+ ```typescript
853
+ const repo = sdk.repository(session);
854
+ const registry = repo.getLexiconRegistry();
730
855
  ```
731
856
 
732
857
  #### Creating Records with Proper Types