@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/dist/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { NodeSavedSession, NodeSavedState, OAuthSession } from '@atproto/oauth-client-node';
2
2
  import { z } from 'zod';
3
- import { EventEmitter } from 'eventemitter3';
4
- import { OrgHypercertsClaimEvidence, OrgHypercertsClaimActivity, OrgHypercertsClaimCollection, ComAtprotoRepoStrongRef, OrgHypercertsClaimRights, OrgHypercertsClaimContribution, OrgHypercertsClaimMeasurement, OrgHypercertsClaimEvaluation, OrgHypercertsClaimProject, AppCertifiedLocation, AppCertifiedBadgeAward, AppCertifiedBadgeDefinition, AppCertifiedBadgeResponse, OrgHypercertsFundingReceipt, OrgHypercertsDefs } from '@hypercerts-org/lexicon';
5
- export { AppCertifiedBadgeAward, AppCertifiedBadgeDefinition, AppCertifiedBadgeResponse, AppCertifiedDefs, AppCertifiedLocation, ComAtprotoRepoStrongRef, HYPERCERTS_LEXICON_DOC, HYPERCERTS_LEXICON_JSON, HYPERCERTS_NSIDS, HYPERCERTS_NSIDS_BY_TYPE, HYPERCERTS_SCHEMAS, HYPERCERTS_SCHEMA_DICT, OrgHypercertsClaimActivity, OrgHypercertsClaimCollection, OrgHypercertsClaimContribution, OrgHypercertsClaimEvaluation, OrgHypercertsClaimEvidence, OrgHypercertsClaimMeasurement, OrgHypercertsClaimProject, OrgHypercertsClaimRights, OrgHypercertsDefs, OrgHypercertsFundingReceipt, lexicons, validate } from '@hypercerts-org/lexicon';
6
- import { Agent } from '@atproto/api';
7
- import { LexiconDoc } from '@atproto/lexicon';
3
+ import { LexiconDoc as LexiconDoc$1, Lexicons } from '@atproto/lexicon';
8
4
  export { BlobRef, JsonBlobRef } from '@atproto/lexicon';
5
+ import { Agent } from '@atproto/api';
6
+ import { EventEmitter } from 'eventemitter3';
7
+ import { OverrideProperties, SetOptional } from 'type-fest';
8
+ import { ComAtprotoRepoStrongRef, AppCertifiedLocation, OrgHypercertsClaimActivity, OrgHypercertsClaimCollection, OrgHypercertsClaimRights, OrgHypercertsClaimContributionDetails, OrgHypercertsClaimContributorInformation, OrgHypercertsClaimMeasurement, OrgHypercertsClaimEvaluation, OrgHypercertsHelperWorkScopeTag, AppCertifiedBadgeAward, AppCertifiedBadgeDefinition, AppCertifiedBadgeResponse, OrgHypercertsFundingReceipt, OrgHypercertsClaimEvidence, OrgHypercertsDefs } from '@hypercerts-org/lexicon';
9
+ export { AppCertifiedBadgeAward, AppCertifiedBadgeDefinition, AppCertifiedBadgeResponse, AppCertifiedDefs, AppCertifiedLocation, ComAtprotoRepoStrongRef, HYPERCERTS_LEXICON_DOC, HYPERCERTS_LEXICON_JSON, HYPERCERTS_NSIDS, HYPERCERTS_NSIDS_BY_TYPE, HYPERCERTS_SCHEMAS, HYPERCERTS_SCHEMA_DICT, OrgHypercertsClaimActivity, OrgHypercertsClaimCollection, OrgHypercertsClaimContributionDetails, OrgHypercertsClaimContributorInformation, OrgHypercertsClaimEvaluation, OrgHypercertsClaimEvidence, OrgHypercertsClaimMeasurement, OrgHypercertsClaimRights, OrgHypercertsDefs, OrgHypercertsFundingReceipt, OrgHypercertsHelperWorkScopeTag, lexicons, validate } from '@hypercerts-org/lexicon';
9
10
 
10
11
  /**
11
12
  * Storage interface for persisting OAuth sessions.
@@ -737,6 +738,236 @@ declare const CollaboratorSchema: z.ZodObject<{
737
738
  */
738
739
  type Collaborator = z.infer<typeof CollaboratorSchema>;
739
740
 
741
+ /**
742
+ * LexiconRegistry - Manages custom lexicon registration and validation.
743
+ *
744
+ * This module provides a registry for AT Protocol lexicon schemas,
745
+ * allowing developers to register custom lexicons and validate records
746
+ * against registered schemas.
747
+ *
748
+ * @packageDocumentation
749
+ */
750
+
751
+ /**
752
+ * Validation result from lexicon validation.
753
+ */
754
+ interface ValidationResult {
755
+ /**
756
+ * Whether the record is valid according to the lexicon.
757
+ */
758
+ valid: boolean;
759
+ /**
760
+ * Error message if validation failed.
761
+ */
762
+ error?: string;
763
+ }
764
+ /**
765
+ * Registry for managing AT Protocol lexicon schemas.
766
+ *
767
+ * The LexiconRegistry allows developers to:
768
+ * - Register custom lexicon definitions
769
+ * - Validate records against registered schemas
770
+ * - Query registered lexicons
771
+ * - Add lexicons to AT Protocol agents
772
+ *
773
+ * @example Basic usage
774
+ * ```typescript
775
+ * const registry = new LexiconRegistry();
776
+ *
777
+ * // Register a custom lexicon
778
+ * registry.register({
779
+ * lexicon: 1,
780
+ * id: "org.myapp.customRecord",
781
+ * defs: {
782
+ * main: {
783
+ * type: "record",
784
+ * key: "tid",
785
+ * record: {
786
+ * type: "object",
787
+ * required: ["$type", "title"],
788
+ * properties: {
789
+ * "$type": { type: "string", const: "org.myapp.customRecord" },
790
+ * title: { type: "string" }
791
+ * }
792
+ * }
793
+ * }
794
+ * }
795
+ * });
796
+ *
797
+ * // Validate a record
798
+ * const result = registry.validate("org.myapp.customRecord", {
799
+ * $type: "org.myapp.customRecord",
800
+ * title: "My Record"
801
+ * });
802
+ *
803
+ * if (!result.valid) {
804
+ * console.error(result.error);
805
+ * }
806
+ * ```
807
+ */
808
+ declare class LexiconRegistry {
809
+ private lexicons;
810
+ private registeredIds;
811
+ /**
812
+ * Creates a new LexiconRegistry instance.
813
+ *
814
+ * @param initialLexicons - Optional array of lexicons to register on initialization
815
+ */
816
+ constructor(initialLexicons?: LexiconDoc$1[]);
817
+ /**
818
+ * Registers a single lexicon definition.
819
+ *
820
+ * @param lexicon - The lexicon document to register
821
+ * @throws {Error} If the lexicon is invalid or already registered
822
+ *
823
+ * @example
824
+ * ```typescript
825
+ * registry.register({
826
+ * lexicon: 1,
827
+ * id: "org.myapp.customRecord",
828
+ * defs: { ... }
829
+ * });
830
+ * ```
831
+ */
832
+ register(lexicon: LexiconDoc$1): void;
833
+ /**
834
+ * Registers multiple lexicon definitions at once.
835
+ *
836
+ * @param lexicons - Array of lexicon documents to register
837
+ * @throws {Error} If any lexicon is invalid or already registered
838
+ *
839
+ * @example
840
+ * ```typescript
841
+ * registry.registerMany([lexicon1, lexicon2, lexicon3]);
842
+ * ```
843
+ */
844
+ registerMany(lexicons: LexiconDoc$1[]): void;
845
+ /**
846
+ * Registers a lexicon from a JSON object.
847
+ *
848
+ * This is a convenience method for registering lexicons loaded from JSON files.
849
+ *
850
+ * @param lexiconJson - The lexicon as a plain JavaScript object
851
+ * @throws {ValidationError} If the lexicon is not a valid object
852
+ * @throws {Error} If the lexicon is invalid or already registered
853
+ *
854
+ * @example
855
+ * ```typescript
856
+ * import customLexicon from "./custom-lexicon.json";
857
+ * registry.registerFromJSON(customLexicon);
858
+ * ```
859
+ */
860
+ registerFromJSON(lexiconJson: unknown): void;
861
+ /**
862
+ * Unregisters a lexicon by its NSID.
863
+ *
864
+ * @param nsid - The NSID of the lexicon to unregister
865
+ * @returns True if the lexicon was unregistered, false if it wasn't registered
866
+ *
867
+ * @example
868
+ * ```typescript
869
+ * registry.unregister("org.myapp.customRecord");
870
+ * ```
871
+ */
872
+ unregister(nsid: string): boolean;
873
+ /**
874
+ * Checks if a lexicon is registered.
875
+ *
876
+ * @param nsid - The NSID to check
877
+ * @returns True if the lexicon is registered
878
+ *
879
+ * @example
880
+ * ```typescript
881
+ * if (registry.isRegistered("org.myapp.customRecord")) {
882
+ * // Lexicon is available
883
+ * }
884
+ * ```
885
+ */
886
+ isRegistered(nsid: string): boolean;
887
+ /**
888
+ * Gets a lexicon definition by its NSID.
889
+ *
890
+ * @param nsid - The NSID of the lexicon to retrieve
891
+ * @returns The lexicon document, or undefined if not found
892
+ *
893
+ * @example
894
+ * ```typescript
895
+ * const lexicon = registry.get("org.myapp.customRecord");
896
+ * if (lexicon) {
897
+ * console.log(lexicon.defs);
898
+ * }
899
+ * ```
900
+ */
901
+ get(nsid: string): LexiconDoc$1 | undefined;
902
+ /**
903
+ * Gets all registered lexicon NSIDs.
904
+ *
905
+ * @returns Array of registered NSIDs
906
+ *
907
+ * @example
908
+ * ```typescript
909
+ * const registered = registry.getAll();
910
+ * console.log(`Registered lexicons: ${registered.join(", ")}`);
911
+ * ```
912
+ */
913
+ getAll(): string[];
914
+ /**
915
+ * Validates a record against a registered lexicon.
916
+ *
917
+ * @param nsid - The collection NSID to validate against
918
+ * @param record - The record data to validate
919
+ * @returns Validation result with success status and optional error message
920
+ *
921
+ * @example
922
+ * ```typescript
923
+ * const result = registry.validate("org.myapp.customRecord", {
924
+ * $type: "org.myapp.customRecord",
925
+ * title: "My Record"
926
+ * });
927
+ *
928
+ * if (!result.valid) {
929
+ * console.error(`Validation failed: ${result.error}`);
930
+ * }
931
+ * ```
932
+ */
933
+ validate(nsid: string, record: unknown): ValidationResult;
934
+ /**
935
+ * Adds all registered lexicons to an AT Protocol Agent.
936
+ *
937
+ * This method is currently a no-op as the AT Protocol Agent
938
+ * doesn't provide a public API for adding lexicons at runtime.
939
+ * Lexicons must be registered with the server.
940
+ *
941
+ * This method is kept for future compatibility if the API
942
+ * adds support for client-side lexicon registration.
943
+ *
944
+ * @param _agent - The AT Protocol Agent (currently unused)
945
+ *
946
+ * @example
947
+ * ```typescript
948
+ * const agent = new Agent(session);
949
+ * registry.addToAgent(agent);
950
+ * // Reserved for future use
951
+ * ```
952
+ */
953
+ addToAgent(_agent: Agent): void;
954
+ /**
955
+ * Gets the underlying Lexicons instance.
956
+ *
957
+ * This provides direct access to the AT Protocol Lexicons object
958
+ * for advanced use cases.
959
+ *
960
+ * @returns The internal Lexicons instance
961
+ *
962
+ * @example
963
+ * ```typescript
964
+ * const lexicons = registry.getLexicons();
965
+ * // Use lexicons directly for advanced operations
966
+ * ```
967
+ */
968
+ getLexicons(): Lexicons;
969
+ }
970
+
740
971
  /**
741
972
  * Repository types - Shared types for repository operations
742
973
  * @packageDocumentation
@@ -887,7 +1118,7 @@ interface ProgressStep {
887
1118
  * All hypercert-related lexicons for registration with AT Protocol Agent.
888
1119
  * This array contains all lexicon documents from the published package.
889
1120
  */
890
- declare const HYPERCERT_LEXICONS: LexiconDoc[];
1121
+ declare const HYPERCERT_LEXICONS: LexiconDoc$1[];
891
1122
  /**
892
1123
  * Collection NSIDs (Namespaced Identifiers) for hypercert records.
893
1124
  *
@@ -908,9 +1139,15 @@ declare const HYPERCERT_COLLECTIONS: {
908
1139
  */
909
1140
  readonly LOCATION: "app.certified.location";
910
1141
  /**
911
- * Contribution record collection.
1142
+ * Contribution details record collection.
1143
+ * For storing details about a specific contribution (role, description, timeframe).
1144
+ */
1145
+ readonly CONTRIBUTION_DETAILS: "org.hypercerts.claim.contributionDetails";
1146
+ /**
1147
+ * Contributor information record collection.
1148
+ * For storing contributor profile information (identifier, displayName, image).
912
1149
  */
913
- readonly CONTRIBUTION: "org.hypercerts.claim.contribution";
1150
+ readonly CONTRIBUTOR_INFORMATION: "org.hypercerts.claim.contributorInformation";
914
1151
  /**
915
1152
  * Measurement record collection.
916
1153
  */
@@ -925,12 +1162,9 @@ declare const HYPERCERT_COLLECTIONS: {
925
1162
  readonly EVIDENCE: "org.hypercerts.claim.evidence";
926
1163
  /**
927
1164
  * Collection record collection (groups of hypercerts).
1165
+ * Projects are now collections with type='project'.
928
1166
  */
929
1167
  readonly COLLECTION: "org.hypercerts.claim.collection";
930
- /**
931
- * Project record collection.
932
- */
933
- readonly PROJECT: "org.hypercerts.claim.project";
934
1168
  /**
935
1169
  * Badge award record collection.
936
1170
  */
@@ -947,6 +1181,11 @@ declare const HYPERCERT_COLLECTIONS: {
947
1181
  * Funding receipt record collection.
948
1182
  */
949
1183
  readonly FUNDING_RECEIPT: "org.hypercerts.funding.receipt";
1184
+ /**
1185
+ * Work scope tag record collection.
1186
+ * For defining reusable work scope atoms.
1187
+ */
1188
+ readonly WORK_SCOPE_TAG: "org.hypercerts.helper.workScopeTag";
950
1189
  };
951
1190
 
952
1191
  /**
@@ -960,13 +1199,18 @@ declare const HYPERCERT_COLLECTIONS: {
960
1199
  type StrongRef = ComAtprotoRepoStrongRef.Main;
961
1200
  type HypercertClaim = OrgHypercertsClaimActivity.Main;
962
1201
  type HypercertRights = OrgHypercertsClaimRights.Main;
963
- type HypercertContribution = OrgHypercertsClaimContribution.Main;
1202
+ type HypercertContributionDetails = OrgHypercertsClaimContributionDetails.Main;
1203
+ type HypercertContributorInformation = OrgHypercertsClaimContributorInformation.Main;
1204
+ /** Contributor entry in an activity - can be inline or reference external records */
1205
+ type HypercertContributor = OrgHypercertsClaimActivity.Contributor;
964
1206
  type HypercertMeasurement = OrgHypercertsClaimMeasurement.Main;
965
1207
  type HypercertEvaluation = OrgHypercertsClaimEvaluation.Main;
966
1208
  type HypercertEvidence = OrgHypercertsClaimEvidence.Main;
967
1209
  type HypercertCollection = OrgHypercertsClaimCollection.Main;
968
- type HypercertCollectionClaimItem = OrgHypercertsClaimActivity.ActivityWeight;
969
- type HypercertProject = OrgHypercertsClaimProject.Main;
1210
+ /** Collection item with optional weight */
1211
+ type HypercertCollectionItem = OrgHypercertsClaimCollection.Item;
1212
+ /** Work scope tag for creating reusable scope atoms */
1213
+ type HypercertWorkScopeTag = OrgHypercertsHelperWorkScopeTag.Main;
970
1214
  type HypercertLocation = AppCertifiedLocation.Main;
971
1215
  type BadgeAward = AppCertifiedBadgeAward.Main;
972
1216
  type BadgeDefinition = AppCertifiedBadgeDefinition.Main;
@@ -975,33 +1219,118 @@ type FundingReceipt = OrgHypercertsFundingReceipt.Main;
975
1219
  /**
976
1220
  * Image input for SDK operations.
977
1221
  *
978
- * Can be either:
979
- * - A URI reference (for external images)
980
- * - A Blob to be uploaded
1222
+ * Accepts either:
1223
+ * - A string URI reference (for external images)
1224
+ * - A Blob to be uploaded (will be converted to SmallImage or LargeImage)
981
1225
  *
982
- * The SDK will convert these to the appropriate lexicon types:
983
- * - OrgHypercertsDefs.Uri
984
- * - OrgHypercertsDefs.SmallImage
985
- * - OrgHypercertsDefs.LargeImage
1226
+ * The SDK will convert these inputs to the appropriate lexicon types.
986
1227
  */
987
- type HypercertImage = {
988
- type: "uri";
989
- uri: string;
990
- } | {
991
- type: "blob";
992
- blob: Blob;
993
- };
1228
+ type HypercertImage = string | Blob;
994
1229
  /**
995
1230
  * Lexicon-defined image types (union of Uri and image blob types).
996
- * Use this when working with stored records.
1231
+ *
1232
+ * Used when working with stored records. Can be:
1233
+ * - OrgHypercertsDefs.Uri - External image reference
1234
+ * - OrgHypercertsDefs.SmallImage - Uploaded blob for avatars/thumbnails
1235
+ * - OrgHypercertsDefs.LargeImage - Uploaded blob for banners/covers
997
1236
  */
998
1237
  type HypercertImageRecord = OrgHypercertsDefs.Uri | OrgHypercertsDefs.SmallImage | OrgHypercertsDefs.LargeImage;
999
- /** Hypercert with AT Protocol metadata */
1000
- interface HypercertWithMetadata {
1238
+ /** Hypercert with resolved metadata */
1239
+ type HypercertWithMetadata = HypercertClaim & {
1240
+ resolvedRights?: HypercertRights;
1241
+ resolvedLocation?: HypercertLocation;
1242
+ };
1243
+ /** Project type alias (collection with type="project") */
1244
+ type HypercertProject = HypercertCollection & {
1245
+ type: "project";
1246
+ };
1247
+ /** Project with resolved metadata */
1248
+ type HypercertProjectWithMetadata = HypercertCollection & {
1249
+ resolvedLocation?: HypercertLocation;
1250
+ resolvedActivities?: HypercertClaim[];
1251
+ };
1252
+
1253
+ type CollectionItemInput = SetOptional<OrgHypercertsClaimCollection.Item, "$type">;
1254
+ /**
1255
+ * Parameters for specifying a location in collection/project operations.
1256
+ * Supports three ways to specify location:
1257
+ *
1258
+ * 1. **StrongRef** - Direct reference with uri and cid (no record creation)
1259
+ * 2. **AT-URI string** - Reference to existing location record
1260
+ * 3. **Location object** - Full location data (lpVersion, srs, locationType, location, etc.)
1261
+ * with optional `$type` and `createdAt` fields
1262
+ * where-as location field can be a Blob (e.g., GeoJSON) that will be uploaded
1263
+ *
1264
+ * @example Using a StrongRef (no record creation)
1265
+ * ```typescript
1266
+ * const location: AttachLocationParams = { uri: "at://did:plc:test/app.certified.location/abc", cid: "bafyrei..." };
1267
+ * ```
1268
+ *
1269
+ * @example Using an AT-URI (fetches existing record)
1270
+ * ```typescript
1271
+ * const location: AttachLocationParams = "at://did:plc:test/app.certified.location/xyz";
1272
+ * ```
1273
+ *
1274
+ * @example Using a location object
1275
+ * ```typescript
1276
+ * const location: AttachLocationParams = {
1277
+ * lpVersion: "1.0.0",
1278
+ * srs: "EPSG:4326",
1279
+ * locationType: "coordinate-decimal",
1280
+ * location: "https://locationuri.com",
1281
+ * name: "San Francisco",
1282
+ * };
1283
+ * ```
1284
+ */
1285
+ type CreateLocationParams = OverrideProperties<SetOptional<HypercertLocation, "$type" | "createdAt">, {
1286
+ location: string | Blob | HypercertLocation["location"];
1287
+ }>;
1288
+ type LocationParams = StrongRef | string | CreateLocationParams;
1289
+ /**
1290
+ * SDK input parameters for creating a collection.
1291
+ * Derived from lexicon type with $type and createdAt removed.
1292
+ * avatar/banner accept HypercertImage (string URI or Blob) for user convenience.
1293
+ * Location can be provided inline or via attachLocationToCollection().
1294
+ */
1295
+ type CreateCollectionParams = OverrideProperties<SetOptional<OrgHypercertsClaimCollection.Main, "$type" | "createdAt">, {
1296
+ avatar?: HypercertImage;
1297
+ banner?: HypercertImage;
1298
+ items: CollectionItemInput[];
1299
+ /**
1300
+ * Optional location to attach to the collection.
1301
+ * Can be:
1302
+ * - StrongRef to reference existing location (uri + cid)
1303
+ * - string (AT-URI) to reference existing location (CID will be fetched)
1304
+ * - Location object to create a new location record
1305
+ */
1306
+ location?: LocationParams;
1307
+ }>;
1308
+ /**
1309
+ * SDK input parameters for updating a collection.
1310
+ * All fields are optional.
1311
+ * avatar/banner accept HypercertImage (string URI or Blob), or null to remove.
1312
+ * Location can be updated inline or removed with null.
1313
+ */
1314
+ type UpdateCollectionParams = Omit<Partial<CreateCollectionParams>, "avatar" | "banner" | "location"> & {
1315
+ avatar?: HypercertImage | null;
1316
+ banner?: HypercertImage | null;
1317
+ location?: LocationParams | null;
1318
+ };
1319
+ type CreateCollectionResult = {
1001
1320
  uri: string;
1002
1321
  cid: string;
1003
- record: HypercertClaim;
1004
- }
1322
+ record: HypercertCollection;
1323
+ };
1324
+ /**
1325
+ * SDK input parameters for creating a project.
1326
+ * Projects are collections with type="project" (set automatically).
1327
+ */
1328
+ type CreateProjectParams = CreateCollectionParams;
1329
+ /**
1330
+ * SDK input parameters for updating a project.
1331
+ */
1332
+ type UpdateProjectParams = UpdateCollectionParams;
1333
+ type CreateProjectResult = CreateCollectionResult;
1005
1334
 
1006
1335
  /**
1007
1336
  * Parameters for creating a new hypercert.
@@ -1083,14 +1412,12 @@ interface CreateHypercertParams {
1083
1412
  description: string;
1084
1413
  /**
1085
1414
  * Scope of work or impact area.
1086
- * Logical scope of the work using label-based conditions. All labels in `withinAllOf` must apply; at least one label in `withinAnyOf` must apply if provided; no label in `withinNoneOf` may apply.
1415
+ * Logical scope of the work using label-based conditions.
1087
1416
  *
1088
- * @example "Climate Action", "Education", "Healthcare"
1417
+ * @example WorkScopeAll with atom references
1089
1418
  */
1090
- workScope?: {
1091
- withinAllOf?: string[];
1092
- withinAnyOf?: string[];
1093
- withinNoneOf?: string[];
1419
+ workScope?: OrgHypercertsDefs.WorkScopeAll | OrgHypercertsDefs.WorkScopeAny | OrgHypercertsDefs.WorkScopeNot | OrgHypercertsDefs.WorkScopeAtom | {
1420
+ $type: string;
1094
1421
  };
1095
1422
  /**
1096
1423
  * Start date of the work period.
@@ -1142,34 +1469,7 @@ interface CreateHypercertParams {
1142
1469
  /**
1143
1470
  * Optional geographic location of the impact.
1144
1471
  */
1145
- location?: {
1146
- /**
1147
- * Location value/address.
1148
- *
1149
- * @example "San Francisco, CA, USA"
1150
- */
1151
- value: string;
1152
- /**
1153
- * Human-readable location name.
1154
- *
1155
- * @example "SF Bay Area"
1156
- */
1157
- name?: string;
1158
- /**
1159
- * Description of the location scope.
1160
- */
1161
- description?: string;
1162
- /**
1163
- * Spatial Reference System identifier (required if location is provided).
1164
- *
1165
- * @example "EPSG:4326" for WGS84
1166
- */
1167
- srs: string;
1168
- /**
1169
- * GeoJSON file as a Blob for precise boundaries.
1170
- */
1171
- geojson?: Blob;
1172
- };
1472
+ location?: LocationParams;
1173
1473
  /**
1174
1474
  * Optional list of contributions to the impact.
1175
1475
  *
@@ -1194,7 +1494,7 @@ interface CreateHypercertParams {
1194
1494
  /**
1195
1495
  * Optional evidence supporting the impact claim.
1196
1496
  */
1197
- evidence?: HypercertEvidence[];
1497
+ evidence?: Array<Omit<CreateHypercertEvidenceParams, "subjectUri">>;
1198
1498
  /**
1199
1499
  * Optional callback for progress updates during creation.
1200
1500
  *
@@ -1219,6 +1519,45 @@ interface CreateOrganizationParams {
1219
1519
  */
1220
1520
  description?: string;
1221
1521
  }
1522
+ /**
1523
+ * Input params for creating Hypercert evidence.
1524
+ *
1525
+ * Based on `org.hypercerts.claim.evidence` but:
1526
+ * - removes: $type, createdAt, subject, content
1527
+ * - adds: subjectUri, content (string | Blob)
1528
+ */
1529
+ interface CreateHypercertEvidenceParams {
1530
+ /**
1531
+ * URI for the subject this evidence is attached to.
1532
+ */
1533
+ subjectUri: string;
1534
+ /**
1535
+ * Evidence content.
1536
+ * - string: should be a URI.
1537
+ * - Blob: binary payload (e.g. image/pdf)
1538
+ */
1539
+ content: string | Blob;
1540
+ /**
1541
+ * Title to describe the nature of the evidence.
1542
+ */
1543
+ title: string;
1544
+ /**
1545
+ * Short description explaining what this evidence shows.
1546
+ */
1547
+ shortDescription?: string;
1548
+ /**
1549
+ * Longer description describing the evidence in more detail.
1550
+ */
1551
+ description?: string;
1552
+ /**
1553
+ * How this evidence relates to the subject.
1554
+ */
1555
+ relationType?: "supports" | "challenges" | "clarifies" | (string & {});
1556
+ /**
1557
+ * Any additional custom fields supported by the record.
1558
+ */
1559
+ [k: string]: unknown;
1560
+ }
1222
1561
  /**
1223
1562
  * Result of creating a hypercert.
1224
1563
  *
@@ -1249,6 +1588,10 @@ interface CreateHypercertResult {
1249
1588
  * AT-URIs of contribution records, if contributions were provided.
1250
1589
  */
1251
1590
  contributionUris?: string[];
1591
+ /**
1592
+ * AT-URIs of evidence records, if evidence was provided.
1593
+ */
1594
+ evidenceUris?: string[];
1252
1595
  }
1253
1596
  /**
1254
1597
  * Low-level record operations for AT Protocol CRUD.
@@ -1563,6 +1906,67 @@ interface HypercertEvents {
1563
1906
  uri: string;
1564
1907
  cid: string;
1565
1908
  };
1909
+ /**
1910
+ * Emitted when a collection is updated.
1911
+ */
1912
+ collectionUpdated: {
1913
+ uri: string;
1914
+ cid: string;
1915
+ };
1916
+ /**
1917
+ * Emitted when a collection is deleted.
1918
+ */
1919
+ collectionDeleted: {
1920
+ uri: string;
1921
+ };
1922
+ /**
1923
+ * Emitted when a location is attached to a collection.
1924
+ */
1925
+ locationAttachedToCollection: {
1926
+ uri: string;
1927
+ cid: string;
1928
+ collectionUri: string;
1929
+ };
1930
+ /**
1931
+ * Emitted when a location is removed from a collection.
1932
+ */
1933
+ locationRemovedFromCollection: {
1934
+ collectionUri: string;
1935
+ };
1936
+ /**
1937
+ * Emitted when a project is created.
1938
+ */
1939
+ projectCreated: {
1940
+ uri: string;
1941
+ cid: string;
1942
+ };
1943
+ /**
1944
+ * Emitted when a project is updated.
1945
+ */
1946
+ projectUpdated: {
1947
+ uri: string;
1948
+ cid: string;
1949
+ };
1950
+ /**
1951
+ * Emitted when a project is deleted.
1952
+ */
1953
+ projectDeleted: {
1954
+ uri: string;
1955
+ };
1956
+ /**
1957
+ * Emitted when a location is attached to a project.
1958
+ */
1959
+ locationAttachedToProject: {
1960
+ uri: string;
1961
+ cid: string;
1962
+ projectUri: string;
1963
+ };
1964
+ /**
1965
+ * Emitted when a location is removed from a project.
1966
+ */
1967
+ locationRemovedFromProject: {
1968
+ projectUri: string;
1969
+ };
1566
1970
  }
1567
1971
  /**
1568
1972
  * High-level hypercert operations.
@@ -1618,7 +2022,7 @@ interface HypercertOperations extends EventEmitter<HypercertEvents> {
1618
2022
  */
1619
2023
  update(params: {
1620
2024
  uri: string;
1621
- updates: Partial<Omit<HypercertClaim, "$type" | "createdAt" | "rights">>;
2025
+ updates: Partial<CreateHypercertParams>;
1622
2026
  image?: Blob | null;
1623
2027
  }): Promise<UpdateResult>;
1624
2028
  /**
@@ -1664,21 +2068,14 @@ interface HypercertOperations extends EventEmitter<HypercertEvents> {
1664
2068
  * @param location.geojson - Optional GeoJSON blob for precise boundaries
1665
2069
  * @returns Promise resolving to location record result
1666
2070
  */
1667
- attachLocation(uri: string, location: {
1668
- value: string;
1669
- name?: string;
1670
- description?: string;
1671
- srs: string;
1672
- geojson?: Blob;
1673
- }): Promise<CreateResult>;
2071
+ attachLocation(uri: string, location: LocationParams): Promise<CreateResult>;
1674
2072
  /**
1675
2073
  * Adds evidence to an existing hypercert.
1676
2074
  *
1677
- * @param uri - AT-URI of the hypercert
1678
- * @param evidence - Array of evidence items to add
2075
+ * @param evidence - Evidence item to add
1679
2076
  * @returns Promise resolving to update result
1680
2077
  */
1681
- addEvidence(uri: string, evidence: HypercertEvidence[]): Promise<UpdateResult>;
2078
+ addEvidence(evidence: CreateHypercertEvidenceParams): Promise<UpdateResult>;
1682
2079
  /**
1683
2080
  * Creates a contribution record.
1684
2081
  *
@@ -1720,18 +2117,9 @@ interface HypercertOperations extends EventEmitter<HypercertEvents> {
1720
2117
  * Creates a collection of hypercerts.
1721
2118
  *
1722
2119
  * @param params - Collection parameters
1723
- * @returns Promise resolving to collection record result
1724
- */
1725
- createCollection(params: {
1726
- title: string;
1727
- claims: Array<{
1728
- uri: string;
1729
- cid: string;
1730
- weight: string;
1731
- }>;
1732
- shortDescription?: string;
1733
- coverPhoto?: Blob;
1734
- }): Promise<CreateResult>;
2120
+ * @returns Promise resolving to collection record result with optional location URI
2121
+ */
2122
+ createCollection(params: CreateCollectionParams): Promise<CreateCollectionResult>;
1735
2123
  /**
1736
2124
  * Gets a collection by URI.
1737
2125
  *
@@ -1754,16 +2142,111 @@ interface HypercertOperations extends EventEmitter<HypercertEvents> {
1754
2142
  cid: string;
1755
2143
  record: HypercertCollection;
1756
2144
  }>>;
1757
- }
1758
- /**
1759
- * Collaborator operations for SDS access control.
1760
- *
1761
- * **SDS Only**: These operations are only available on Shared Data Servers.
1762
- *
1763
- * @example
1764
- * ```typescript
1765
- * // Grant access
1766
- * await repo.collaborators.grant({
2145
+ /**
2146
+ * Updates a collection.
2147
+ *
2148
+ * @param uri - AT-URI of the collection
2149
+ * @param updates - Fields to update
2150
+ * @returns Promise resolving to update result
2151
+ */
2152
+ updateCollection(uri: string, updates: UpdateCollectionParams): Promise<UpdateResult>;
2153
+ /**
2154
+ * Deletes a collection.
2155
+ *
2156
+ * @param uri - AT-URI of the collection
2157
+ * @returns Promise resolving when deleted
2158
+ */
2159
+ deleteCollection(uri: string): Promise<void>;
2160
+ /**
2161
+ * Attaches a location to a collection.
2162
+ *
2163
+ * @param uri - AT-URI of the collection
2164
+ * @param location - Location data
2165
+ * @returns Promise resolving to location record result
2166
+ */
2167
+ attachLocationToCollection(uri: string, location: LocationParams): Promise<CreateResult>;
2168
+ /**
2169
+ * Removes a location from a collection.
2170
+ *
2171
+ * @param uri - AT-URI of the collection
2172
+ * @returns Promise resolving when location is removed
2173
+ */
2174
+ removeLocationFromCollection(uri: string): Promise<void>;
2175
+ /**
2176
+ * Creates a project.
2177
+ *
2178
+ * A project is a collection with type='project' and optional location sidecar.
2179
+ *
2180
+ * @param params - Project parameters
2181
+ * @returns Promise resolving to project record result with optional location URI
2182
+ */
2183
+ createProject(params: CreateProjectParams): Promise<CreateProjectResult>;
2184
+ /**
2185
+ * Gets a project by URI.
2186
+ *
2187
+ * Projects are collections with type='project'.
2188
+ *
2189
+ * @param uri - AT-URI of the project
2190
+ * @returns Promise resolving to project data (as collection)
2191
+ */
2192
+ getProject(uri: string): Promise<{
2193
+ uri: string;
2194
+ cid: string;
2195
+ record: HypercertCollection;
2196
+ }>;
2197
+ /**
2198
+ * Lists projects with pagination.
2199
+ *
2200
+ * Projects are collections with type='project'.
2201
+ *
2202
+ * @param params - Optional pagination parameters
2203
+ * @returns Promise resolving to paginated list
2204
+ */
2205
+ listProjects(params?: ListParams): Promise<PaginatedList<{
2206
+ uri: string;
2207
+ cid: string;
2208
+ record: HypercertCollection;
2209
+ }>>;
2210
+ /**
2211
+ * Updates a project.
2212
+ *
2213
+ * @param uri - AT-URI of the project
2214
+ * @param updates - Fields to update
2215
+ * @returns Promise resolving to update result
2216
+ */
2217
+ updateProject(uri: string, updates: UpdateProjectParams): Promise<UpdateResult>;
2218
+ /**
2219
+ * Deletes a project.
2220
+ *
2221
+ * @param uri - AT-URI of the project
2222
+ * @returns Promise resolving when deleted
2223
+ */
2224
+ deleteProject(uri: string): Promise<void>;
2225
+ /**
2226
+ * Attaches a location to a project.
2227
+ *
2228
+ * @param uri - AT-URI of the project
2229
+ * @param location - Location data
2230
+ * @returns Promise resolving to location record result
2231
+ */
2232
+ attachLocationToProject(uri: string, location: LocationParams): Promise<CreateResult>;
2233
+ /**
2234
+ * Removes a location from a project.
2235
+ *
2236
+ * @param uri - AT-URI of the project
2237
+ * @returns Promise resolving when location is removed
2238
+ */
2239
+ removeLocationFromProject(uri: string): Promise<void>;
2240
+ }
2241
+ /**
2242
+ * Collaborator operations for SDS access control.
2243
+ *
2244
+ * **SDS Only**: These operations are only available on Shared Data Servers.
2245
+ *
2246
+ * @example
2247
+ * ```typescript
2248
+ * // Grant access
2249
+ * await repo.collaborators.grant({
1767
2250
  * userDid: "did:plc:new-user",
1768
2251
  * role: "editor",
1769
2252
  * });
@@ -2008,6 +2491,7 @@ declare class Repository {
2008
2491
  private logger?;
2009
2492
  private agent;
2010
2493
  private _isSDS;
2494
+ private lexiconRegistry;
2011
2495
  private _records?;
2012
2496
  private _blobs?;
2013
2497
  private _profile?;
@@ -2022,6 +2506,7 @@ declare class Repository {
2022
2506
  * @param repoDid - DID of the repository to operate on
2023
2507
  * @param isSDS - Whether this is a Shared Data Server
2024
2508
  * @param logger - Optional logger for debugging
2509
+ * @param lexiconRegistry - Registry for custom lexicon management
2025
2510
  *
2026
2511
  * @remarks
2027
2512
  * This constructor is typically not called directly. Use
@@ -2029,7 +2514,7 @@ declare class Repository {
2029
2514
  *
2030
2515
  * @internal
2031
2516
  */
2032
- constructor(session: Session, serverUrl: string, repoDid: string, isSDS: boolean, logger?: LoggerInterface);
2517
+ constructor(session: Session, serverUrl: string, repoDid: string, isSDS: boolean, logger?: LoggerInterface, lexiconRegistry?: LexiconRegistry);
2033
2518
  /**
2034
2519
  * The DID (Decentralized Identifier) of this repository.
2035
2520
  *
@@ -2093,6 +2578,50 @@ declare class Repository {
2093
2578
  * ```
2094
2579
  */
2095
2580
  repo(did: string): Repository;
2581
+ /**
2582
+ * Gets the LexiconRegistry instance for managing custom lexicons.
2583
+ *
2584
+ * The registry is shared across all operations in this repository and
2585
+ * enables validation of custom record types.
2586
+ *
2587
+ * @returns The {@link LexiconRegistry} instance
2588
+ *
2589
+ * @example
2590
+ * ```typescript
2591
+ * // Access the registry
2592
+ * const registry = repo.getLexiconRegistry();
2593
+ *
2594
+ * // Register a custom lexicon
2595
+ * registry.register({
2596
+ * lexicon: 1,
2597
+ * id: "org.myapp.evaluation",
2598
+ * defs: {
2599
+ * main: {
2600
+ * type: "record",
2601
+ * key: "tid",
2602
+ * record: {
2603
+ * type: "object",
2604
+ * required: ["$type", "score"],
2605
+ * properties: {
2606
+ * "$type": { type: "string", const: "org.myapp.evaluation" },
2607
+ * score: { type: "integer", minimum: 0, maximum: 100 }
2608
+ * }
2609
+ * }
2610
+ * }
2611
+ * }
2612
+ * });
2613
+ *
2614
+ * // Now create records using the custom lexicon
2615
+ * await repo.records.create({
2616
+ * collection: "org.myapp.evaluation",
2617
+ * record: {
2618
+ * $type: "org.myapp.evaluation",
2619
+ * score: 85
2620
+ * }
2621
+ * });
2622
+ * ```
2623
+ */
2624
+ getLexiconRegistry(): LexiconRegistry;
2096
2625
  /**
2097
2626
  * Low-level record operations for CRUD on any AT Protocol record type.
2098
2627
  *
@@ -2269,22 +2798,28 @@ declare class Repository {
2269
2798
  * Zod schema for OAuth configuration validation.
2270
2799
  *
2271
2800
  * @remarks
2272
- * All URLs must be valid and use HTTPS in production. The `jwkPrivate` field
2273
- * should contain the private key in JWK (JSON Web Key) format as a string.
2801
+ * All URLs must be valid and use HTTPS in production. For local development,
2802
+ * HTTP loopback URLs (localhost, 127.0.0.1, [::1]) are allowed.
2803
+ * The `jwkPrivate` field should contain the private key in JWK (JSON Web Key) format as a string.
2274
2804
  */
2275
2805
  declare const OAuthConfigSchema: z.ZodObject<{
2276
2806
  /**
2277
2807
  * URL to the OAuth client metadata JSON document.
2278
2808
  * This document describes your application to the authorization server.
2279
2809
  *
2810
+ * For local development, you can use `http://localhost/` as a loopback client.
2811
+ *
2280
2812
  * @see https://atproto.com/specs/oauth#client-metadata
2281
2813
  */
2282
- clientId: z.ZodString;
2814
+ clientId: z.ZodEffects<z.ZodString, string, string>;
2283
2815
  /**
2284
2816
  * URL where users are redirected after authentication.
2285
2817
  * Must match one of the redirect URIs in your client metadata.
2818
+ *
2819
+ * For local development, you can use HTTP loopback URLs like
2820
+ * `http://127.0.0.1:3000/callback` or `http://localhost:3000/callback`.
2286
2821
  */
2287
- redirectUri: z.ZodString;
2822
+ redirectUri: z.ZodEffects<z.ZodString, string, string>;
2288
2823
  /**
2289
2824
  * OAuth scopes to request, space-separated.
2290
2825
  *
@@ -2318,8 +2853,11 @@ declare const OAuthConfigSchema: z.ZodObject<{
2318
2853
  /**
2319
2854
  * URL to your public JWKS (JSON Web Key Set) endpoint.
2320
2855
  * Used by the authorization server to verify your client's signatures.
2856
+ *
2857
+ * For local development, you can serve JWKS from a loopback URL like
2858
+ * `http://127.0.0.1:3000/.well-known/jwks.json`.
2321
2859
  */
2322
- jwksUri: z.ZodString;
2860
+ jwksUri: z.ZodEffects<z.ZodString, string, string>;
2323
2861
  /**
2324
2862
  * Private JWK (JSON Web Key) as a JSON string.
2325
2863
  * Used for signing DPoP proofs and client assertions.
@@ -2329,40 +2867,78 @@ declare const OAuthConfigSchema: z.ZodObject<{
2329
2867
  * Typically loaded from environment variables or a secrets manager.
2330
2868
  */
2331
2869
  jwkPrivate: z.ZodString;
2870
+ /**
2871
+ * Enable development mode features (optional).
2872
+ *
2873
+ * When true, suppresses warnings about using HTTP loopback URLs.
2874
+ * Should be set to true for local development to reduce console noise.
2875
+ *
2876
+ * @default false
2877
+ *
2878
+ * @example
2879
+ * ```typescript
2880
+ * oauth: {
2881
+ * clientId: "http://localhost/",
2882
+ * redirectUri: "http://127.0.0.1:3000/callback",
2883
+ * // ... other config
2884
+ * developmentMode: true, // Suppress loopback warnings
2885
+ * }
2886
+ * ```
2887
+ */
2888
+ developmentMode: z.ZodOptional<z.ZodBoolean>;
2332
2889
  }, "strip", z.ZodTypeAny, {
2333
2890
  clientId: string;
2334
2891
  redirectUri: string;
2335
2892
  scope: string;
2336
2893
  jwksUri: string;
2337
2894
  jwkPrivate: string;
2895
+ developmentMode?: boolean | undefined;
2338
2896
  }, {
2339
2897
  clientId: string;
2340
2898
  redirectUri: string;
2341
2899
  scope: string;
2342
2900
  jwksUri: string;
2343
2901
  jwkPrivate: string;
2902
+ developmentMode?: boolean | undefined;
2344
2903
  }>;
2345
2904
  /**
2346
2905
  * Zod schema for server URL configuration.
2347
2906
  *
2348
2907
  * @remarks
2349
2908
  * At least one server (PDS or SDS) should be configured for the SDK to be useful.
2909
+ * For local development, HTTP loopback URLs are allowed.
2350
2910
  */
2351
2911
  declare const ServerConfigSchema: z.ZodObject<{
2352
2912
  /**
2353
2913
  * Personal Data Server URL - the user's own AT Protocol server.
2354
2914
  * This is the primary server for user data operations.
2355
2915
  *
2356
- * @example "https://bsky.social"
2916
+ * @example Production
2917
+ * ```typescript
2918
+ * pds: "https://bsky.social"
2919
+ * ```
2920
+ *
2921
+ * @example Local development
2922
+ * ```typescript
2923
+ * pds: "http://localhost:2583"
2924
+ * ```
2357
2925
  */
2358
- pds: z.ZodOptional<z.ZodString>;
2926
+ pds: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
2359
2927
  /**
2360
2928
  * Shared Data Server URL - for collaborative data storage.
2361
2929
  * Required for collaborator and organization operations.
2362
2930
  *
2363
- * @example "https://sds.hypercerts.org"
2931
+ * @example Production
2932
+ * ```typescript
2933
+ * sds: "https://sds.hypercerts.org"
2934
+ * ```
2935
+ *
2936
+ * @example Local development
2937
+ * ```typescript
2938
+ * sds: "http://127.0.0.1:2584"
2939
+ * ```
2364
2940
  */
2365
- sds: z.ZodOptional<z.ZodString>;
2941
+ sds: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
2366
2942
  }, "strip", z.ZodTypeAny, {
2367
2943
  pds?: string | undefined;
2368
2944
  sds?: string | undefined;
@@ -2408,14 +2984,19 @@ declare const ATProtoSDKConfigSchema: z.ZodObject<{
2408
2984
  * URL to the OAuth client metadata JSON document.
2409
2985
  * This document describes your application to the authorization server.
2410
2986
  *
2987
+ * For local development, you can use `http://localhost/` as a loopback client.
2988
+ *
2411
2989
  * @see https://atproto.com/specs/oauth#client-metadata
2412
2990
  */
2413
- clientId: z.ZodString;
2991
+ clientId: z.ZodEffects<z.ZodString, string, string>;
2414
2992
  /**
2415
2993
  * URL where users are redirected after authentication.
2416
2994
  * Must match one of the redirect URIs in your client metadata.
2995
+ *
2996
+ * For local development, you can use HTTP loopback URLs like
2997
+ * `http://127.0.0.1:3000/callback` or `http://localhost:3000/callback`.
2417
2998
  */
2418
- redirectUri: z.ZodString;
2999
+ redirectUri: z.ZodEffects<z.ZodString, string, string>;
2419
3000
  /**
2420
3001
  * OAuth scopes to request, space-separated.
2421
3002
  *
@@ -2449,8 +3030,11 @@ declare const ATProtoSDKConfigSchema: z.ZodObject<{
2449
3030
  /**
2450
3031
  * URL to your public JWKS (JSON Web Key Set) endpoint.
2451
3032
  * Used by the authorization server to verify your client's signatures.
3033
+ *
3034
+ * For local development, you can serve JWKS from a loopback URL like
3035
+ * `http://127.0.0.1:3000/.well-known/jwks.json`.
2452
3036
  */
2453
- jwksUri: z.ZodString;
3037
+ jwksUri: z.ZodEffects<z.ZodString, string, string>;
2454
3038
  /**
2455
3039
  * Private JWK (JSON Web Key) as a JSON string.
2456
3040
  * Used for signing DPoP proofs and client assertions.
@@ -2460,34 +3044,71 @@ declare const ATProtoSDKConfigSchema: z.ZodObject<{
2460
3044
  * Typically loaded from environment variables or a secrets manager.
2461
3045
  */
2462
3046
  jwkPrivate: z.ZodString;
3047
+ /**
3048
+ * Enable development mode features (optional).
3049
+ *
3050
+ * When true, suppresses warnings about using HTTP loopback URLs.
3051
+ * Should be set to true for local development to reduce console noise.
3052
+ *
3053
+ * @default false
3054
+ *
3055
+ * @example
3056
+ * ```typescript
3057
+ * oauth: {
3058
+ * clientId: "http://localhost/",
3059
+ * redirectUri: "http://127.0.0.1:3000/callback",
3060
+ * // ... other config
3061
+ * developmentMode: true, // Suppress loopback warnings
3062
+ * }
3063
+ * ```
3064
+ */
3065
+ developmentMode: z.ZodOptional<z.ZodBoolean>;
2463
3066
  }, "strip", z.ZodTypeAny, {
2464
3067
  clientId: string;
2465
3068
  redirectUri: string;
2466
3069
  scope: string;
2467
3070
  jwksUri: string;
2468
3071
  jwkPrivate: string;
3072
+ developmentMode?: boolean | undefined;
2469
3073
  }, {
2470
3074
  clientId: string;
2471
3075
  redirectUri: string;
2472
3076
  scope: string;
2473
3077
  jwksUri: string;
2474
3078
  jwkPrivate: string;
3079
+ developmentMode?: boolean | undefined;
2475
3080
  }>;
2476
3081
  servers: z.ZodOptional<z.ZodObject<{
2477
3082
  /**
2478
3083
  * Personal Data Server URL - the user's own AT Protocol server.
2479
3084
  * This is the primary server for user data operations.
2480
3085
  *
2481
- * @example "https://bsky.social"
3086
+ * @example Production
3087
+ * ```typescript
3088
+ * pds: "https://bsky.social"
3089
+ * ```
3090
+ *
3091
+ * @example Local development
3092
+ * ```typescript
3093
+ * pds: "http://localhost:2583"
3094
+ * ```
2482
3095
  */
2483
- pds: z.ZodOptional<z.ZodString>;
3096
+ pds: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
2484
3097
  /**
2485
3098
  * Shared Data Server URL - for collaborative data storage.
2486
3099
  * Required for collaborator and organization operations.
2487
3100
  *
2488
- * @example "https://sds.hypercerts.org"
3101
+ * @example Production
3102
+ * ```typescript
3103
+ * sds: "https://sds.hypercerts.org"
3104
+ * ```
3105
+ *
3106
+ * @example Local development
3107
+ * ```typescript
3108
+ * sds: "http://127.0.0.1:2584"
3109
+ * ```
2489
3110
  */
2490
- sds: z.ZodOptional<z.ZodString>;
3111
+ sds: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
2491
3112
  }, "strip", z.ZodTypeAny, {
2492
3113
  pds?: string | undefined;
2493
3114
  sds?: string | undefined;
@@ -2520,6 +3141,7 @@ declare const ATProtoSDKConfigSchema: z.ZodObject<{
2520
3141
  scope: string;
2521
3142
  jwksUri: string;
2522
3143
  jwkPrivate: string;
3144
+ developmentMode?: boolean | undefined;
2523
3145
  };
2524
3146
  servers?: {
2525
3147
  pds?: string | undefined;
@@ -2536,6 +3158,7 @@ declare const ATProtoSDKConfigSchema: z.ZodObject<{
2536
3158
  scope: string;
2537
3159
  jwksUri: string;
2538
3160
  jwkPrivate: string;
3161
+ developmentMode?: boolean | undefined;
2539
3162
  };
2540
3163
  servers?: {
2541
3164
  pds?: string | undefined;
@@ -2784,6 +3407,7 @@ declare class ATProtoSDK {
2784
3407
  private oauthClient;
2785
3408
  private config;
2786
3409
  private logger?;
3410
+ private lexiconRegistry;
2787
3411
  /**
2788
3412
  * Creates a new ATProto SDK instance.
2789
3413
  *
@@ -3003,6 +3627,32 @@ declare class ATProtoSDK {
3003
3627
  * ```
3004
3628
  */
3005
3629
  repository(session: Session, options?: RepositoryOptions): Repository;
3630
+ /**
3631
+ * Gets the LexiconRegistry instance for managing custom lexicons.
3632
+ *
3633
+ * The registry allows you to register custom lexicon schemas and validate
3634
+ * records against them. All registered lexicons will be automatically
3635
+ * validated during record creation operations.
3636
+ *
3637
+ * @returns The {@link LexiconRegistry} instance
3638
+ *
3639
+ * @example
3640
+ * ```typescript
3641
+ * // Register a custom lexicon
3642
+ * const registry = sdk.getLexiconRegistry();
3643
+ * registry.register({
3644
+ * lexicon: 1,
3645
+ * id: "org.myapp.customRecord",
3646
+ * defs: { ... }
3647
+ * });
3648
+ *
3649
+ * // Check if lexicon is registered
3650
+ * if (registry.isRegistered("org.myapp.customRecord")) {
3651
+ * console.log("Custom lexicon is available");
3652
+ * }
3653
+ * ```
3654
+ */
3655
+ getLexiconRegistry(): LexiconRegistry;
3006
3656
  /**
3007
3657
  * The configured PDS (Personal Data Server) URL.
3008
3658
  *
@@ -3017,87 +3667,1169 @@ declare class ATProtoSDK {
3017
3667
  get sdsUrl(): string | undefined;
3018
3668
  }
3019
3669
  /**
3020
- * Factory function to create an ATProto SDK instance.
3670
+ * Factory function to create an ATProto SDK instance.
3671
+ *
3672
+ * This is a convenience function equivalent to `new ATProtoSDK(config)`.
3673
+ *
3674
+ * @param config - SDK configuration
3675
+ * @returns A new {@link ATProtoSDK} instance
3676
+ *
3677
+ * @example
3678
+ * ```typescript
3679
+ * import { createATProtoSDK } from "@hypercerts-org/sdk";
3680
+ *
3681
+ * const sdk = createATProtoSDK({
3682
+ * oauth: { ... },
3683
+ * servers: { pds: "https://bsky.social" },
3684
+ * });
3685
+ * ```
3686
+ */
3687
+ declare function createATProtoSDK(config: ATProtoSDKConfig): ATProtoSDK;
3688
+
3689
+ /**
3690
+ * ConfigurableAgent - Agent with configurable service URL routing.
3691
+ *
3692
+ * This module provides an Agent extension that allows routing requests to
3693
+ * a specific server URL, overriding the default URL from the OAuth session.
3694
+ *
3695
+ * @packageDocumentation
3696
+ */
3697
+
3698
+ /**
3699
+ * Agent subclass that routes requests to a configurable service URL.
3700
+ *
3701
+ * The standard Agent uses the service URL embedded in the OAuth session's
3702
+ * fetch handler. This class allows overriding that URL to route requests
3703
+ * to different servers (e.g., PDS vs SDS, or multiple SDS instances).
3704
+ *
3705
+ * @remarks
3706
+ * This is particularly useful for:
3707
+ * - Routing to a Shared Data Server (SDS) while authenticated via PDS
3708
+ * - Supporting multiple SDS instances for different organizations
3709
+ * - Testing against different server environments
3710
+ *
3711
+ * @example Basic usage
3712
+ * ```typescript
3713
+ * const session = await sdk.authorize("user.bsky.social");
3714
+ *
3715
+ * // Create agent routing to SDS instead of session's default PDS
3716
+ * const sdsAgent = new ConfigurableAgent(session, "https://sds.hypercerts.org");
3717
+ *
3718
+ * // All requests will now go to the SDS
3719
+ * await sdsAgent.com.atproto.repo.createRecord({...});
3720
+ * ```
3721
+ *
3722
+ * @example Multiple SDS instances
3723
+ * ```typescript
3724
+ * // Route to organization A's SDS
3725
+ * const orgAAgent = new ConfigurableAgent(session, "https://sds-org-a.example.com");
3726
+ *
3727
+ * // Route to organization B's SDS
3728
+ * const orgBAgent = new ConfigurableAgent(session, "https://sds-org-b.example.com");
3729
+ * ```
3730
+ */
3731
+ declare class ConfigurableAgent extends Agent {
3732
+ private customServiceUrl;
3733
+ /**
3734
+ * Creates a ConfigurableAgent that routes to a specific service URL.
3735
+ *
3736
+ * @param session - OAuth session for authentication
3737
+ * @param serviceUrl - Base URL of the server to route requests to
3738
+ *
3739
+ * @remarks
3740
+ * The agent wraps the session's fetch handler to intercept requests and
3741
+ * prepend the custom service URL instead of using the session's default.
3742
+ */
3743
+ constructor(session: Session, serviceUrl: string);
3744
+ /**
3745
+ * Gets the service URL this agent routes to.
3746
+ *
3747
+ * @returns The base URL of the configured service
3748
+ */
3749
+ getServiceUrl(): string;
3750
+ }
3751
+
3752
+ /**
3753
+ * BaseOperations - Abstract base class for custom lexicon operations.
3754
+ *
3755
+ * This module provides a foundation for building domain-specific operation
3756
+ * classes that work with custom lexicons. It handles validation, record
3757
+ * creation, and provides utilities for working with AT Protocol records.
3758
+ *
3759
+ * @packageDocumentation
3760
+ */
3761
+
3762
+ /**
3763
+ * Abstract base class for creating custom lexicon operation classes.
3764
+ *
3765
+ * Extend this class to build domain-specific operations for your custom
3766
+ * lexicons. The base class provides:
3767
+ *
3768
+ * - Automatic validation against registered lexicon schemas
3769
+ * - Helper methods for creating and updating records
3770
+ * - Utilities for building strongRefs and AT-URIs
3771
+ * - Error handling and logging support
3772
+ *
3773
+ * @typeParam TParams - Type of parameters accepted by the create() method
3774
+ * @typeParam TResult - Type of result returned by the create() method
3775
+ *
3776
+ * @remarks
3777
+ * This class is designed to be extended by developers creating custom
3778
+ * operation classes for their own lexicons. It follows the same patterns
3779
+ * as the built-in hypercert operations.
3780
+ *
3781
+ * @example Basic usage
3782
+ * ```typescript
3783
+ * import { BaseOperations } from "@hypercerts-org/sdk-core";
3784
+ *
3785
+ * interface EvaluationParams {
3786
+ * subjectUri: string;
3787
+ * subjectCid: string;
3788
+ * score: number;
3789
+ * methodology?: string;
3790
+ * }
3791
+ *
3792
+ * interface EvaluationResult {
3793
+ * uri: string;
3794
+ * cid: string;
3795
+ * record: MyEvaluation;
3796
+ * }
3797
+ *
3798
+ * class EvaluationOperations extends BaseOperations<EvaluationParams, EvaluationResult> {
3799
+ * async create(params: EvaluationParams): Promise<EvaluationResult> {
3800
+ * const record = {
3801
+ * $type: "org.myapp.evaluation",
3802
+ * subject: this.createStrongRef(params.subjectUri, params.subjectCid),
3803
+ * score: params.score,
3804
+ * methodology: params.methodology,
3805
+ * createdAt: new Date().toISOString(),
3806
+ * };
3807
+ *
3808
+ * const { uri, cid } = await this.validateAndCreate("org.myapp.evaluation", record);
3809
+ * return { uri, cid, record };
3810
+ * }
3811
+ * }
3812
+ * ```
3813
+ *
3814
+ * @example With validation and error handling
3815
+ * ```typescript
3816
+ * class ProjectOperations extends BaseOperations<CreateProjectParams, ProjectResult> {
3817
+ * async create(params: CreateProjectParams): Promise<ProjectResult> {
3818
+ * // Validate input parameters
3819
+ * if (!params.title || params.title.trim().length === 0) {
3820
+ * throw new ValidationError("Project title cannot be empty");
3821
+ * }
3822
+ *
3823
+ * const record = {
3824
+ * $type: "org.myapp.project",
3825
+ * title: params.title,
3826
+ * description: params.description,
3827
+ * createdAt: new Date().toISOString(),
3828
+ * };
3829
+ *
3830
+ * try {
3831
+ * const { uri, cid } = await this.validateAndCreate("org.myapp.project", record);
3832
+ * this.logger?.info(`Created project: ${uri}`);
3833
+ * return { uri, cid, record };
3834
+ * } catch (error) {
3835
+ * this.logger?.error(`Failed to create project: ${error}`);
3836
+ * throw error;
3837
+ * }
3838
+ * }
3839
+ * }
3840
+ * ```
3841
+ */
3842
+ declare abstract class BaseOperations<TParams = unknown, TResult = unknown> {
3843
+ protected agent: Agent;
3844
+ protected repoDid: string;
3845
+ protected lexiconRegistry: LexiconRegistry;
3846
+ protected logger?: LoggerInterface | undefined;
3847
+ /**
3848
+ * Creates a new BaseOperations instance.
3849
+ *
3850
+ * @param agent - AT Protocol Agent for making API calls
3851
+ * @param repoDid - DID of the repository to operate on
3852
+ * @param lexiconRegistry - Registry for validating records against lexicon schemas
3853
+ * @param logger - Optional logger for debugging and monitoring
3854
+ *
3855
+ * @internal
3856
+ */
3857
+ constructor(agent: Agent, repoDid: string, lexiconRegistry: LexiconRegistry, logger?: LoggerInterface | undefined);
3858
+ /**
3859
+ * Validates a record against its lexicon schema and creates it in the repository.
3860
+ *
3861
+ * This method performs the following steps:
3862
+ * 1. Validates the record against the registered lexicon schema
3863
+ * 2. Throws ValidationError if validation fails
3864
+ * 3. Creates the record using the AT Protocol Agent
3865
+ * 4. Returns the created record's URI and CID
3866
+ *
3867
+ * @param collection - NSID of the collection (e.g., "org.myapp.customRecord")
3868
+ * @param record - Record data conforming to the collection's lexicon schema
3869
+ * @param rkey - Optional record key. If not provided, a TID is auto-generated
3870
+ * @returns Promise resolving to the created record's URI and CID
3871
+ * @throws {@link ValidationError} if the record doesn't conform to the lexicon schema
3872
+ * @throws {@link NetworkError} if the API request fails
3873
+ *
3874
+ * @example
3875
+ * ```typescript
3876
+ * const record = {
3877
+ * $type: "org.myapp.evaluation",
3878
+ * subject: { uri: "at://...", cid: "bafyrei..." },
3879
+ * score: 85,
3880
+ * createdAt: new Date().toISOString(),
3881
+ * };
3882
+ *
3883
+ * const { uri, cid } = await this.validateAndCreate("org.myapp.evaluation", record);
3884
+ * ```
3885
+ */
3886
+ protected validateAndCreate(collection: string, record: unknown, rkey?: string): Promise<CreateResult>;
3887
+ /**
3888
+ * Validates a record against its lexicon schema and updates it in the repository.
3889
+ *
3890
+ * This method performs the following steps:
3891
+ * 1. Validates the record against the registered lexicon schema
3892
+ * 2. Throws ValidationError if validation fails
3893
+ * 3. Updates the record using the AT Protocol Agent
3894
+ * 4. Returns the updated record's URI and new CID
3895
+ *
3896
+ * @param collection - NSID of the collection
3897
+ * @param rkey - Record key (the last segment of the AT-URI)
3898
+ * @param record - New record data (completely replaces existing record)
3899
+ * @returns Promise resolving to the updated record's URI and new CID
3900
+ * @throws {@link ValidationError} if the record doesn't conform to the lexicon schema
3901
+ * @throws {@link NetworkError} if the API request fails
3902
+ *
3903
+ * @remarks
3904
+ * This is a full replacement operation, not a partial update.
3905
+ *
3906
+ * @example
3907
+ * ```typescript
3908
+ * const updatedRecord = {
3909
+ * $type: "org.myapp.evaluation",
3910
+ * subject: { uri: "at://...", cid: "bafyrei..." },
3911
+ * score: 90, // Updated score
3912
+ * createdAt: existingRecord.createdAt,
3913
+ * };
3914
+ *
3915
+ * const { uri, cid } = await this.validateAndUpdate(
3916
+ * "org.myapp.evaluation",
3917
+ * "abc123",
3918
+ * updatedRecord
3919
+ * );
3920
+ * ```
3921
+ */
3922
+ protected validateAndUpdate(collection: string, rkey: string, record: unknown): Promise<UpdateResult>;
3923
+ /**
3924
+ * Creates a strongRef object from a URI and CID.
3925
+ *
3926
+ * StrongRefs are used in AT Protocol to reference specific versions
3927
+ * of records. They ensure that references point to an exact record
3928
+ * version, not just the latest version.
3929
+ *
3930
+ * @param uri - AT-URI of the record (e.g., "at://did:plc:abc/collection/rkey")
3931
+ * @param cid - Content Identifier (CID) of the record
3932
+ * @returns StrongRef object with uri and cid properties
3933
+ *
3934
+ * @example
3935
+ * ```typescript
3936
+ * const hypercertRef = this.createStrongRef(
3937
+ * "at://did:plc:abc123/org.hypercerts.claim.activity/xyz789",
3938
+ * "bafyreiabc123..."
3939
+ * );
3940
+ *
3941
+ * const evaluation = {
3942
+ * $type: "org.myapp.evaluation",
3943
+ * subject: hypercertRef, // Reference to specific hypercert version
3944
+ * score: 85,
3945
+ * createdAt: new Date().toISOString(),
3946
+ * };
3947
+ * ```
3948
+ */
3949
+ protected createStrongRef(uri: string, cid: string): StrongRef;
3950
+ /**
3951
+ * Creates a strongRef from a CreateResult or UpdateResult.
3952
+ *
3953
+ * This is a convenience method for creating strongRefs from the
3954
+ * results of create or update operations.
3955
+ *
3956
+ * @param result - Result from a create or update operation
3957
+ * @returns StrongRef object with uri and cid properties
3958
+ *
3959
+ * @example
3960
+ * ```typescript
3961
+ * // Create a project
3962
+ * const projectResult = await this.validateAndCreate("org.myapp.project", projectRecord);
3963
+ *
3964
+ * // Create a task that references the project
3965
+ * const taskRecord = {
3966
+ * $type: "org.myapp.task",
3967
+ * project: this.createStrongRefFromResult(projectResult),
3968
+ * title: "Implement feature",
3969
+ * createdAt: new Date().toISOString(),
3970
+ * };
3971
+ * ```
3972
+ */
3973
+ protected createStrongRefFromResult(result: CreateResult | UpdateResult): StrongRef;
3974
+ /**
3975
+ * Parses an AT-URI to extract its components.
3976
+ *
3977
+ * AT-URIs follow the format: `at://{did}/{collection}/{rkey}`
3978
+ *
3979
+ * @param uri - AT-URI to parse
3980
+ * @returns Object containing did, collection, and rkey
3981
+ * @throws Error if the URI format is invalid
3982
+ *
3983
+ * @example
3984
+ * ```typescript
3985
+ * const { did, collection, rkey } = this.parseAtUri(
3986
+ * "at://did:plc:abc123/org.hypercerts.claim.activity/xyz789"
3987
+ * );
3988
+ * // did: "did:plc:abc123"
3989
+ * // collection: "org.hypercerts.claim.activity"
3990
+ * // rkey: "xyz789"
3991
+ * ```
3992
+ */
3993
+ protected parseAtUri(uri: string): {
3994
+ did: string;
3995
+ collection: string;
3996
+ rkey: string;
3997
+ };
3998
+ /**
3999
+ * Builds an AT-URI from its components.
4000
+ *
4001
+ * @param did - DID of the repository
4002
+ * @param collection - NSID of the collection
4003
+ * @param rkey - Record key (typically a TID)
4004
+ * @returns Complete AT-URI string
4005
+ *
4006
+ * @example
4007
+ * ```typescript
4008
+ * const uri = this.buildAtUri(
4009
+ * "did:plc:abc123",
4010
+ * "org.myapp.evaluation",
4011
+ * "xyz789"
4012
+ * );
4013
+ * // Returns: "at://did:plc:abc123/org.myapp.evaluation/xyz789"
4014
+ * ```
4015
+ */
4016
+ protected buildAtUri(did: string, collection: string, rkey: string): string;
4017
+ /**
4018
+ * Abstract create method that must be implemented by subclasses.
4019
+ *
4020
+ * Implement this method to define how your custom records are created.
4021
+ * Use the helper methods like `validateAndCreate()`, `createStrongRef()`,
4022
+ * etc. to build your implementation.
4023
+ *
4024
+ * @param params - Parameters for creating the record
4025
+ * @returns Promise resolving to the creation result
4026
+ *
4027
+ * @example
4028
+ * ```typescript
4029
+ * async create(params: EvaluationParams): Promise<EvaluationResult> {
4030
+ * const record = {
4031
+ * $type: "org.myapp.evaluation",
4032
+ * subject: this.createStrongRef(params.subjectUri, params.subjectCid),
4033
+ * score: params.score,
4034
+ * methodology: params.methodology,
4035
+ * createdAt: new Date().toISOString(),
4036
+ * };
4037
+ *
4038
+ * const { uri, cid } = await this.validateAndCreate("org.myapp.evaluation", record);
4039
+ * return { uri, cid, record };
4040
+ * }
4041
+ * ```
4042
+ */
4043
+ abstract create(params: TParams): Promise<TResult>;
4044
+ }
4045
+
4046
+ /**
4047
+ * Lexicon Development Utilities - AT-URI and StrongRef Helpers
4048
+ *
4049
+ * This module provides utilities for working with AT Protocol URIs and strongRefs
4050
+ * when building custom lexicons. These tools help developers create type-safe
4051
+ * references between records.
4052
+ *
4053
+ * @packageDocumentation
4054
+ */
4055
+
4056
+ /**
4057
+ * Components of an AT-URI (AT Protocol Uniform Resource Identifier).
4058
+ *
4059
+ * AT-URIs follow the format: `at://{did}/{collection}/{rkey}`
4060
+ * where:
4061
+ * - `did`: The DID of the repository owner (e.g., "did:plc:abc123")
4062
+ * - `collection`: The NSID of the record type (e.g., "org.hypercerts.claim.activity")
4063
+ * - `rkey`: The record key, either a TID or custom key (e.g., "3km2vj4kfqp2a")
4064
+ */
4065
+ interface AtUriComponents {
4066
+ /** Repository owner's DID */
4067
+ did: string;
4068
+ /** Collection NSID (lexicon identifier) */
4069
+ collection: string;
4070
+ /** Record key (TID or custom string) */
4071
+ rkey: string;
4072
+ }
4073
+ /**
4074
+ * Parse an AT-URI into its component parts.
4075
+ *
4076
+ * Extracts the DID, collection NSID, and record key from an AT-URI string.
4077
+ * AT-URIs follow the format: `at://{did}/{collection}/{rkey}`
4078
+ *
4079
+ * @param uri - The AT-URI to parse
4080
+ * @returns The components of the URI
4081
+ * @throws {Error} If the URI format is invalid
4082
+ *
4083
+ * @example
4084
+ * ```typescript
4085
+ * const components = parseAtUri("at://did:plc:abc123/org.hypercerts.claim.activity/3km2vj4kfqp2a");
4086
+ * console.log(components);
4087
+ * // {
4088
+ * // did: "did:plc:abc123",
4089
+ * // collection: "org.hypercerts.claim.activity",
4090
+ * // rkey: "3km2vj4kfqp2a"
4091
+ * // }
4092
+ * ```
4093
+ */
4094
+ declare function parseAtUri(uri: string): AtUriComponents;
4095
+ /**
4096
+ * Build an AT-URI from its component parts.
4097
+ *
4098
+ * Constructs a valid AT-URI string from a DID, collection NSID, and record key.
4099
+ * The resulting URI follows the format: `at://{did}/{collection}/{rkey}`
4100
+ *
4101
+ * @param did - The repository owner's DID
4102
+ * @param collection - The collection NSID (lexicon identifier)
4103
+ * @param rkey - The record key (TID or custom string)
4104
+ * @returns The complete AT-URI
4105
+ *
4106
+ * @example
4107
+ * ```typescript
4108
+ * const uri = buildAtUri(
4109
+ * "did:plc:abc123",
4110
+ * "org.hypercerts.claim.activity",
4111
+ * "3km2vj4kfqp2a"
4112
+ * );
4113
+ * console.log(uri); // "at://did:plc:abc123/org.hypercerts.claim.activity/3km2vj4kfqp2a"
4114
+ * ```
4115
+ */
4116
+ declare function buildAtUri(did: string, collection: string, rkey: string): string;
4117
+ /**
4118
+ * Extract the record key (TID or custom key) from an AT-URI.
4119
+ *
4120
+ * Returns the last component of the AT-URI, which is the record key.
4121
+ * This is equivalent to `parseAtUri(uri).rkey` but more efficient.
4122
+ *
4123
+ * @param uri - The AT-URI to extract from
4124
+ * @returns The record key (TID or custom string)
4125
+ * @throws {Error} If the URI format is invalid
4126
+ *
4127
+ * @example
4128
+ * ```typescript
4129
+ * const rkey = extractRkeyFromUri("at://did:plc:abc123/org.hypercerts.claim.activity/3km2vj4kfqp2a");
4130
+ * console.log(rkey); // "3km2vj4kfqp2a"
4131
+ * ```
4132
+ */
4133
+ declare function extractRkeyFromUri(uri: string): string;
4134
+ /**
4135
+ * Check if a string is a valid AT-URI format.
4136
+ *
4137
+ * Validates that the string follows the AT-URI format without throwing errors.
4138
+ * This is useful for input validation before parsing.
4139
+ *
4140
+ * @param uri - The string to validate
4141
+ * @returns True if the string is a valid AT-URI, false otherwise
4142
+ *
4143
+ * @example
4144
+ * ```typescript
4145
+ * if (isValidAtUri(userInput)) {
4146
+ * const components = parseAtUri(userInput);
4147
+ * // ... use components
4148
+ * } else {
4149
+ * console.error("Invalid AT-URI");
4150
+ * }
4151
+ * ```
4152
+ */
4153
+ declare function isValidAtUri(uri: string): boolean;
4154
+ /**
4155
+ * Create a strongRef from a URI and CID.
4156
+ *
4157
+ * StrongRefs are the canonical way to reference specific versions of records
4158
+ * in AT Protocol. They combine an AT-URI (which identifies the record) with
4159
+ * a CID (which identifies the specific version).
4160
+ *
4161
+ * @param uri - The AT-URI of the record
4162
+ * @param cid - The CID (Content Identifier) of the record version
4163
+ * @returns A strongRef object
4164
+ *
4165
+ * @example
4166
+ * ```typescript
4167
+ * const ref = createStrongRef(
4168
+ * "at://did:plc:abc123/org.hypercerts.claim.activity/3km2vj4kfqp2a",
4169
+ * "bafyreiabc123..."
4170
+ * );
4171
+ * console.log(ref);
4172
+ * // {
4173
+ * // uri: "at://did:plc:abc123/org.hypercerts.claim.activity/3km2vj4kfqp2a",
4174
+ * // cid: "bafyreiabc123..."
4175
+ * // }
4176
+ * ```
4177
+ */
4178
+ declare function createStrongRef(uri: string, cid: string): StrongRef;
4179
+ /**
4180
+ * Create a strongRef from a CreateResult or UpdateResult.
4181
+ *
4182
+ * This is a convenience function that extracts the URI and CID from
4183
+ * the result of a record creation or update operation.
4184
+ *
4185
+ * @param result - The result from creating or updating a record
4186
+ * @returns A strongRef object
4187
+ *
4188
+ * @example
4189
+ * ```typescript
4190
+ * const hypercert = await repo.hypercerts.create({
4191
+ * title: "Climate Research",
4192
+ * // ... other params
4193
+ * });
4194
+ *
4195
+ * const ref = createStrongRefFromResult(hypercert);
4196
+ * // Now use ref in another record to reference this hypercert
4197
+ * ```
4198
+ */
4199
+ declare function createStrongRefFromResult(result: CreateResult | UpdateResult): StrongRef;
4200
+ /**
4201
+ * Validate that an object is a valid strongRef.
4202
+ *
4203
+ * Checks that the object has the required `uri` and `cid` properties
4204
+ * and that they are non-empty strings.
4205
+ *
4206
+ * @param ref - The object to validate
4207
+ * @returns True if the object is a valid strongRef, false otherwise
4208
+ *
4209
+ * @example
4210
+ * ```typescript
4211
+ * const maybeRef = { uri: "at://...", cid: "bafyrei..." };
4212
+ * if (validateStrongRef(maybeRef)) {
4213
+ * // Safe to use as strongRef
4214
+ * record.subject = maybeRef;
4215
+ * }
4216
+ * ```
4217
+ */
4218
+ declare function validateStrongRef(ref: unknown): ref is StrongRef;
4219
+ /**
4220
+ * Type guard to check if a value is a strongRef.
4221
+ *
4222
+ * This is an alias for `validateStrongRef` that provides better semantics
4223
+ * for type narrowing in TypeScript.
4224
+ *
4225
+ * @param value - The value to check
4226
+ * @returns True if the value is a strongRef, false otherwise
4227
+ *
4228
+ * @example
4229
+ * ```typescript
4230
+ * function processReference(ref: unknown) {
4231
+ * if (isStrongRef(ref)) {
4232
+ * // TypeScript knows ref is StrongRef here
4233
+ * console.log(ref.uri);
4234
+ * }
4235
+ * }
4236
+ * ```
4237
+ */
4238
+ declare function isStrongRef(value: unknown): value is StrongRef;
4239
+
4240
+ /**
4241
+ * Lexicon Builder Utilities
4242
+ *
4243
+ * This module provides utilities for constructing lexicon JSON schemas programmatically.
4244
+ * These builders help developers create valid AT Protocol lexicons with proper structure
4245
+ * and type-safe field definitions.
4246
+ *
4247
+ * @packageDocumentation
4248
+ */
4249
+ /**
4250
+ * Lexicon field type definitions.
4251
+ */
4252
+ type LexiconFieldType = "string" | "integer" | "boolean" | "number" | "datetime" | "blob" | "ref" | "array" | "object" | "unknown";
4253
+ /**
4254
+ * Base lexicon field definition.
4255
+ */
4256
+ interface LexiconFieldBase {
4257
+ type: LexiconFieldType;
4258
+ description?: string;
4259
+ }
4260
+ /**
4261
+ * String field definition.
4262
+ */
4263
+ interface LexiconStringField extends LexiconFieldBase {
4264
+ type: "string";
4265
+ format?: "datetime" | "uri" | "at-uri" | "did" | "handle" | "at-identifier" | "nsid" | "cid";
4266
+ minLength?: number;
4267
+ maxLength?: number;
4268
+ minGraphemes?: number;
4269
+ maxGraphemes?: number;
4270
+ enum?: string[];
4271
+ const?: string;
4272
+ default?: string;
4273
+ }
4274
+ /**
4275
+ * Integer field definition.
4276
+ */
4277
+ interface LexiconIntegerField extends LexiconFieldBase {
4278
+ type: "integer";
4279
+ minimum?: number;
4280
+ maximum?: number;
4281
+ enum?: number[];
4282
+ const?: number;
4283
+ default?: number;
4284
+ }
4285
+ /**
4286
+ * Number field definition.
4287
+ */
4288
+ interface LexiconNumberField extends LexiconFieldBase {
4289
+ type: "number";
4290
+ minimum?: number;
4291
+ maximum?: number;
4292
+ enum?: number[];
4293
+ const?: number;
4294
+ default?: number;
4295
+ }
4296
+ /**
4297
+ * Boolean field definition.
4298
+ */
4299
+ interface LexiconBooleanField extends LexiconFieldBase {
4300
+ type: "boolean";
4301
+ const?: boolean;
4302
+ default?: boolean;
4303
+ }
4304
+ /**
4305
+ * Reference field definition (for strongRefs).
4306
+ */
4307
+ interface LexiconRefField extends LexiconFieldBase {
4308
+ type: "ref";
4309
+ ref: string;
4310
+ }
4311
+ /**
4312
+ * Array field definition.
4313
+ */
4314
+ interface LexiconArrayField extends LexiconFieldBase {
4315
+ type: "array";
4316
+ items: LexiconField;
4317
+ minLength?: number;
4318
+ maxLength?: number;
4319
+ }
4320
+ /**
4321
+ * Object field definition.
4322
+ */
4323
+ interface LexiconObjectField extends LexiconFieldBase {
4324
+ type: "object";
4325
+ properties?: Record<string, LexiconField>;
4326
+ required?: string[];
4327
+ }
4328
+ /**
4329
+ * Blob field definition.
4330
+ */
4331
+ interface LexiconBlobField extends LexiconFieldBase {
4332
+ type: "blob";
4333
+ accept?: string[];
4334
+ maxSize?: number;
4335
+ }
4336
+ /**
4337
+ * Unknown field definition (accepts any type).
4338
+ */
4339
+ interface LexiconUnknownField extends LexiconFieldBase {
4340
+ type: "unknown";
4341
+ }
4342
+ /**
4343
+ * Union of all lexicon field types.
4344
+ */
4345
+ type LexiconField = LexiconStringField | LexiconIntegerField | LexiconNumberField | LexiconBooleanField | LexiconRefField | LexiconArrayField | LexiconObjectField | LexiconBlobField | LexiconUnknownField;
4346
+ /**
4347
+ * Record definition for a lexicon.
3021
4348
  *
3022
- * This is a convenience function equivalent to `new ATProtoSDK(config)`.
4349
+ * Key types:
4350
+ * - "tid" (default): Server-generated timestamp-based ID
4351
+ * - "any": Client can specify any valid rkey
4352
+ */
4353
+ interface LexiconRecordDef {
4354
+ type: "record";
4355
+ key?: "tid" | "any";
4356
+ record: {
4357
+ type: "object";
4358
+ required: string[];
4359
+ properties: Record<string, LexiconField>;
4360
+ };
4361
+ }
4362
+ /**
4363
+ * Main lexicon document structure.
4364
+ */
4365
+ interface LexiconDoc {
4366
+ lexicon: 1;
4367
+ id: string;
4368
+ defs: {
4369
+ main: LexiconRecordDef;
4370
+ [key: string]: unknown;
4371
+ };
4372
+ }
4373
+ /**
4374
+ * Create a string field definition.
3023
4375
  *
3024
- * @param config - SDK configuration
3025
- * @returns A new {@link ATProtoSDK} instance
4376
+ * @param options - String field options
4377
+ * @returns A lexicon string field definition
3026
4378
  *
3027
4379
  * @example
3028
4380
  * ```typescript
3029
- * import { createATProtoSDK } from "@hypercerts-org/sdk";
4381
+ * const titleField = createStringField({
4382
+ * description: "Title of the item",
4383
+ * minLength: 1,
4384
+ * maxLength: 200,
4385
+ * });
4386
+ * ```
4387
+ */
4388
+ declare function createStringField(options?: Omit<LexiconStringField, "type">): LexiconStringField;
4389
+ /**
4390
+ * Create an integer field definition.
3030
4391
  *
3031
- * const sdk = createATProtoSDK({
3032
- * oauth: { ... },
3033
- * servers: { pds: "https://bsky.social" },
4392
+ * @param options - Integer field options
4393
+ * @returns A lexicon integer field definition
4394
+ *
4395
+ * @example
4396
+ * ```typescript
4397
+ * const scoreField = createIntegerField({
4398
+ * description: "Score from 0 to 100",
4399
+ * minimum: 0,
4400
+ * maximum: 100,
3034
4401
  * });
3035
4402
  * ```
3036
4403
  */
3037
- declare function createATProtoSDK(config: ATProtoSDKConfig): ATProtoSDK;
4404
+ declare function createIntegerField(options?: Omit<LexiconIntegerField, "type">): LexiconIntegerField;
4405
+ /**
4406
+ * Create a number field definition.
4407
+ *
4408
+ * @param options - Number field options
4409
+ * @returns A lexicon number field definition
4410
+ *
4411
+ * @example
4412
+ * ```typescript
4413
+ * const weightField = createNumberField({
4414
+ * description: "Weight as decimal",
4415
+ * minimum: 0,
4416
+ * maximum: 1,
4417
+ * });
4418
+ * ```
4419
+ */
4420
+ declare function createNumberField(options?: Omit<LexiconNumberField, "type">): LexiconNumberField;
4421
+ /**
4422
+ * Create a boolean field definition.
4423
+ *
4424
+ * @param options - Boolean field options
4425
+ * @returns A lexicon boolean field definition
4426
+ *
4427
+ * @example
4428
+ * ```typescript
4429
+ * const verifiedField = createBooleanField({
4430
+ * description: "Whether the item is verified",
4431
+ * default: false,
4432
+ * });
4433
+ * ```
4434
+ */
4435
+ declare function createBooleanField(options?: Omit<LexiconBooleanField, "type">): LexiconBooleanField;
4436
+ /**
4437
+ * Create a strongRef field definition.
4438
+ *
4439
+ * StrongRefs are the standard way to reference other records in AT Protocol.
4440
+ * They contain both the AT-URI and CID of the referenced record.
4441
+ *
4442
+ * @param options - Reference field options
4443
+ * @returns A lexicon reference field definition
4444
+ *
4445
+ * @example
4446
+ * ```typescript
4447
+ * const subjectField = createStrongRefField({
4448
+ * description: "The hypercert being evaluated",
4449
+ * });
4450
+ * ```
4451
+ */
4452
+ declare function createStrongRefField(options?: Omit<LexiconRefField, "type" | "ref"> & {
4453
+ ref?: string;
4454
+ }): LexiconRefField;
4455
+ /**
4456
+ * Create an array field definition.
4457
+ *
4458
+ * @param itemType - The type of items in the array
4459
+ * @param options - Array field options
4460
+ * @returns A lexicon array field definition
4461
+ *
4462
+ * @example
4463
+ * ```typescript
4464
+ * const tagsField = createArrayField(
4465
+ * createStringField({ maxLength: 50 }),
4466
+ * {
4467
+ * description: "List of tags",
4468
+ * minLength: 1,
4469
+ * maxLength: 10,
4470
+ * }
4471
+ * );
4472
+ * ```
4473
+ */
4474
+ declare function createArrayField(itemType: LexiconField, options?: Omit<LexiconArrayField, "type" | "items">): LexiconArrayField;
4475
+ /**
4476
+ * Create an object field definition.
4477
+ *
4478
+ * @param options - Object field options
4479
+ * @returns A lexicon object field definition
4480
+ *
4481
+ * @example
4482
+ * ```typescript
4483
+ * const metadataField = createObjectField({
4484
+ * description: "Additional metadata",
4485
+ * properties: {
4486
+ * author: createStringField(),
4487
+ * version: createIntegerField(),
4488
+ * },
4489
+ * required: ["author"],
4490
+ * });
4491
+ * ```
4492
+ */
4493
+ declare function createObjectField(options?: Omit<LexiconObjectField, "type">): LexiconObjectField;
4494
+ /**
4495
+ * Create a blob field definition.
4496
+ *
4497
+ * @param options - Blob field options
4498
+ * @returns A lexicon blob field definition
4499
+ *
4500
+ * @example
4501
+ * ```typescript
4502
+ * const imageField = createBlobField({
4503
+ * description: "Profile image",
4504
+ * accept: ["image/png", "image/jpeg"],
4505
+ * maxSize: 1000000, // 1MB
4506
+ * });
4507
+ * ```
4508
+ */
4509
+ declare function createBlobField(options?: Omit<LexiconBlobField, "type">): LexiconBlobField;
4510
+ /**
4511
+ * Create a datetime string field.
4512
+ *
4513
+ * This is a convenience function for creating string fields with datetime format.
4514
+ *
4515
+ * @param options - String field options
4516
+ * @returns A lexicon string field with datetime format
4517
+ *
4518
+ * @example
4519
+ * ```typescript
4520
+ * const createdAtField = createDatetimeField({
4521
+ * description: "When the record was created",
4522
+ * });
4523
+ * ```
4524
+ */
4525
+ declare function createDatetimeField(options?: Omit<LexiconStringField, "type" | "format">): LexiconStringField;
4526
+ /**
4527
+ * Create a record definition.
4528
+ *
4529
+ * This defines the structure of records in your lexicon.
4530
+ *
4531
+ * @param properties - The record's properties (fields)
4532
+ * @param required - Array of required field names
4533
+ * @param keyType - The type of record key ("tid" for server-generated, "any" for custom)
4534
+ * @returns A lexicon record definition
4535
+ *
4536
+ * @example
4537
+ * ```typescript
4538
+ * const recordDef = createRecordDef(
4539
+ * {
4540
+ * $type: createStringField({ const: "org.myapp.evaluation" }),
4541
+ * subject: createStrongRefField({ description: "The evaluated item" }),
4542
+ * score: createIntegerField({ minimum: 0, maximum: 100 }),
4543
+ * createdAt: createDatetimeField(),
4544
+ * },
4545
+ * ["$type", "subject", "score", "createdAt"],
4546
+ * "tid"
4547
+ * );
4548
+ * ```
4549
+ */
4550
+ declare function createRecordDef(properties: Record<string, LexiconField>, required: string[], keyType?: "tid" | "any"): LexiconRecordDef;
4551
+ /**
4552
+ * Create a complete lexicon document.
4553
+ *
4554
+ * This creates a full lexicon JSON structure that can be registered with the SDK.
4555
+ *
4556
+ * @param nsid - The NSID (Namespaced Identifier) for this lexicon
4557
+ * @param properties - The record's properties (fields)
4558
+ * @param required - Array of required field names
4559
+ * @param keyType - The type of record key ("tid" for server-generated, "any" for custom)
4560
+ * @returns A complete lexicon document
4561
+ *
4562
+ * @example
4563
+ * ```typescript
4564
+ * const lexicon = createLexiconDoc(
4565
+ * "org.myapp.evaluation",
4566
+ * {
4567
+ * $type: createStringField({ const: "org.myapp.evaluation" }),
4568
+ * subject: createStrongRefField({ description: "The evaluated item" }),
4569
+ * score: createIntegerField({ minimum: 0, maximum: 100 }),
4570
+ * methodology: createStringField({ maxLength: 500 }),
4571
+ * createdAt: createDatetimeField(),
4572
+ * },
4573
+ * ["$type", "subject", "score", "createdAt"],
4574
+ * "tid"
4575
+ * );
4576
+ *
4577
+ * // Register with SDK
4578
+ * sdk.getLexiconRegistry().registerFromJSON(lexicon);
4579
+ * ```
4580
+ */
4581
+ declare function createLexiconDoc(nsid: string, properties: Record<string, LexiconField>, required: string[], keyType?: "tid" | "any"): LexiconDoc;
4582
+ /**
4583
+ * Validate a lexicon document structure.
4584
+ *
4585
+ * Performs basic validation to ensure the lexicon follows AT Protocol conventions.
4586
+ * This does NOT perform full JSON schema validation.
4587
+ *
4588
+ * @param lexicon - The lexicon document to validate
4589
+ * @returns True if valid, false otherwise
4590
+ *
4591
+ * @example
4592
+ * ```typescript
4593
+ * const lexicon = createLexiconDoc(...);
4594
+ * if (validateLexiconStructure(lexicon)) {
4595
+ * sdk.getLexiconRegistry().registerFromJSON(lexicon);
4596
+ * } else {
4597
+ * console.error("Invalid lexicon structure");
4598
+ * }
4599
+ * ```
4600
+ */
4601
+ declare function validateLexiconStructure(lexicon: unknown): lexicon is LexiconDoc;
3038
4602
 
3039
4603
  /**
3040
- * ConfigurableAgent - Agent with configurable service URL routing.
4604
+ * Sidecar Pattern Utilities
3041
4605
  *
3042
- * This module provides an Agent extension that allows routing requests to
3043
- * a specific server URL, overriding the default URL from the OAuth session.
4606
+ * This module provides utilities for implementing the AT Protocol "sidecar pattern"
4607
+ * where additional records are created that reference a main record via StrongRef.
4608
+ *
4609
+ * ## The Sidecar Pattern
4610
+ *
4611
+ * In AT Protocol, the sidecar pattern uses **unidirectional references**:
4612
+ * - Sidecar records contain a StrongRef (uri + cid) pointing to the main record
4613
+ * - Main records do NOT maintain back-references to sidecars
4614
+ * - Sidecars are discovered by querying records that reference the main record
4615
+ * - Optionally, sidecars can use the same rkey as the main record (in different collections)
4616
+ *
4617
+ * ## Example Use Cases
4618
+ *
4619
+ * - Evaluations that reference hypercerts
4620
+ * - Comments that reference posts
4621
+ * - Metadata records that reference primary entities
4622
+ *
4623
+ * @see https://atproto.com/specs/record-key
4624
+ * @see https://atproto.com/specs/data-model
3044
4625
  *
3045
4626
  * @packageDocumentation
3046
4627
  */
3047
4628
 
3048
4629
  /**
3049
- * Agent subclass that routes requests to a configurable service URL.
4630
+ * Parameters for creating a sidecar record.
4631
+ */
4632
+ interface SidecarRecordParams {
4633
+ /** The collection NSID for the sidecar record */
4634
+ collection: string;
4635
+ /** The record data */
4636
+ record: Record<string, unknown>;
4637
+ /** Optional custom rkey */
4638
+ rkey?: string;
4639
+ }
4640
+ /**
4641
+ * Result from creating a sidecar record.
4642
+ */
4643
+ interface SidecarResult {
4644
+ /** The main record that was referenced */
4645
+ mainRecord: CreateResult;
4646
+ /** The sidecar record that was created */
4647
+ sidecarRecord: CreateResult;
4648
+ }
4649
+ /**
4650
+ * Parameters for attaching a sidecar to an existing record.
4651
+ */
4652
+ interface AttachSidecarParams {
4653
+ /** The main record to reference */
4654
+ mainRecord: {
4655
+ uri: string;
4656
+ cid: string;
4657
+ };
4658
+ /** The sidecar record to create */
4659
+ sidecar: SidecarRecordParams;
4660
+ }
4661
+ /**
4662
+ * Result from creating multiple sidecars.
4663
+ */
4664
+ interface MultiSidecarResult {
4665
+ /** The main record that was created */
4666
+ main: CreateResult;
4667
+ /** The sidecar records that were created */
4668
+ sidecars: CreateResult[];
4669
+ }
4670
+ /**
4671
+ * Parameters for creating a main record with multiple sidecars.
4672
+ */
4673
+ interface CreateWithSidecarsParams {
4674
+ /** The main record to create */
4675
+ main: SidecarRecordParams;
4676
+ /** The sidecar records to create (can reference the main record via placeholder) */
4677
+ sidecars: SidecarRecordParams[];
4678
+ }
4679
+ /**
4680
+ * Create a sidecar record that references an existing record.
3050
4681
  *
3051
- * The standard Agent uses the service URL embedded in the OAuth session's
3052
- * fetch handler. This class allows overriding that URL to route requests
3053
- * to different servers (e.g., PDS vs SDS, or multiple SDS instances).
4682
+ * This is a low-level utility that creates a single sidecar record. The sidecar
4683
+ * record should include a strongRef field that points to the main record.
3054
4684
  *
3055
- * @remarks
3056
- * This is particularly useful for:
3057
- * - Routing to a Shared Data Server (SDS) while authenticated via PDS
3058
- * - Supporting multiple SDS instances for different organizations
3059
- * - Testing against different server environments
4685
+ * @param repo - The repository instance
4686
+ * @param collection - The collection NSID for the sidecar
4687
+ * @param record - The sidecar record data (should include a strongRef to the main record)
4688
+ * @param options - Optional creation options
4689
+ * @returns The created sidecar record
3060
4690
  *
3061
- * @example Basic usage
4691
+ * @example
3062
4692
  * ```typescript
3063
- * const session = await sdk.authorize("user.bsky.social");
4693
+ * const hypercert = await repo.hypercerts.create({...});
4694
+ *
4695
+ * const evaluation = await createSidecarRecord(
4696
+ * repo,
4697
+ * "org.myapp.evaluation",
4698
+ * {
4699
+ * $type: "org.myapp.evaluation",
4700
+ * subject: { uri: hypercert.hypercertUri, cid: hypercert.hypercertCid },
4701
+ * score: 85,
4702
+ * createdAt: new Date().toISOString(),
4703
+ * }
4704
+ * );
4705
+ * ```
4706
+ */
4707
+ declare function createSidecarRecord(repo: Repository, collection: string, record: Record<string, unknown>, options?: {
4708
+ rkey?: string;
4709
+ }): Promise<CreateResult>;
4710
+ /**
4711
+ * Attach a sidecar record to an existing main record.
3064
4712
  *
3065
- * // Create agent routing to SDS instead of session's default PDS
3066
- * const sdsAgent = new ConfigurableAgent(session, "https://sds.hypercerts.org");
4713
+ * This creates a new record that references an existing record via strongRef.
4714
+ * It's a higher-level convenience function that wraps `createSidecarRecord`.
3067
4715
  *
3068
- * // All requests will now go to the SDS
3069
- * await sdsAgent.com.atproto.repo.createRecord({...});
4716
+ * @param repo - The repository instance
4717
+ * @param params - Parameters including the main record reference and sidecar definition
4718
+ * @returns Both the main record reference and the created sidecar
4719
+ *
4720
+ * @example
4721
+ * ```typescript
4722
+ * const hypercert = await repo.hypercerts.create({...});
4723
+ *
4724
+ * const result = await attachSidecar(repo, {
4725
+ * mainRecord: {
4726
+ * uri: hypercert.hypercertUri,
4727
+ * cid: hypercert.hypercertCid,
4728
+ * },
4729
+ * sidecar: {
4730
+ * collection: "org.myapp.evaluation",
4731
+ * record: {
4732
+ * $type: "org.myapp.evaluation",
4733
+ * subject: { uri: hypercert.hypercertUri, cid: hypercert.hypercertCid },
4734
+ * score: 85,
4735
+ * createdAt: new Date().toISOString(),
4736
+ * },
4737
+ * },
4738
+ * });
3070
4739
  * ```
4740
+ */
4741
+ declare function attachSidecar(repo: Repository, params: AttachSidecarParams): Promise<SidecarResult>;
4742
+ /**
4743
+ * Create a main record and multiple sidecar records in sequence.
3071
4744
  *
3072
- * @example Multiple SDS instances
4745
+ * This orchestrates the creation of a main record followed by one or more
4746
+ * sidecar records that reference it. This is useful for workflows like:
4747
+ * - Creating a project with multiple hypercert claims
4748
+ * - Creating a hypercert with evidence and evaluation records
4749
+ *
4750
+ * @param repo - The repository instance
4751
+ * @param params - Parameters including the main record and sidecar definitions
4752
+ * @returns The main record and all created sidecar records
4753
+ *
4754
+ * @example
3073
4755
  * ```typescript
3074
- * // Route to organization A's SDS
3075
- * const orgAAgent = new ConfigurableAgent(session, "https://sds-org-a.example.com");
4756
+ * const result = await createWithSidecars(repo, {
4757
+ * main: {
4758
+ * collection: "org.hypercerts.project",
4759
+ * record: {
4760
+ * $type: "org.hypercerts.project",
4761
+ * title: "Climate Initiative 2024",
4762
+ * description: "Our climate work",
4763
+ * createdAt: new Date().toISOString(),
4764
+ * },
4765
+ * },
4766
+ * sidecars: [
4767
+ * {
4768
+ * collection: "org.hypercerts.claim.activity",
4769
+ * record: {
4770
+ * $type: "org.hypercerts.claim.activity",
4771
+ * title: "Tree Planting",
4772
+ * // ... other hypercert fields
4773
+ * // Note: If you need to reference the main record, you must wait
4774
+ * // for result.main and then call batchCreateSidecars separately
4775
+ * },
4776
+ * },
4777
+ * {
4778
+ * collection: "org.hypercerts.claim.activity",
4779
+ * record: {
4780
+ * $type: "org.hypercerts.claim.activity",
4781
+ * title: "Carbon Measurement",
4782
+ * // ... other hypercert fields
4783
+ * },
4784
+ * },
4785
+ * ],
4786
+ * });
3076
4787
  *
3077
- * // Route to organization B's SDS
3078
- * const orgBAgent = new ConfigurableAgent(session, "https://sds-org-b.example.com");
4788
+ * console.log(result.main.uri); // Main project record
4789
+ * console.log(result.sidecars.length); // 2 hypercert sidecars
3079
4790
  * ```
3080
4791
  */
3081
- declare class ConfigurableAgent extends Agent {
3082
- private customServiceUrl;
3083
- /**
3084
- * Creates a ConfigurableAgent that routes to a specific service URL.
3085
- *
3086
- * @param session - OAuth session for authentication
3087
- * @param serviceUrl - Base URL of the server to route requests to
3088
- *
3089
- * @remarks
3090
- * The agent wraps the session's fetch handler to intercept requests and
3091
- * prepend the custom service URL instead of using the session's default.
3092
- */
3093
- constructor(session: Session, serviceUrl: string);
3094
- /**
3095
- * Gets the service URL this agent routes to.
3096
- *
3097
- * @returns The base URL of the configured service
3098
- */
3099
- getServiceUrl(): string;
3100
- }
4792
+ declare function createWithSidecars(repo: Repository, params: CreateWithSidecarsParams): Promise<MultiSidecarResult>;
4793
+ /**
4794
+ * Batch create multiple sidecar records.
4795
+ *
4796
+ * This is useful when you want to add multiple related records
4797
+ * efficiently. The sidecar records should already contain any necessary
4798
+ * references to the main record in their data.
4799
+ *
4800
+ * @param repo - The repository instance
4801
+ * @param sidecars - Array of sidecar definitions (records should include references)
4802
+ * @returns Array of created sidecar records
4803
+ *
4804
+ * @example
4805
+ * ```typescript
4806
+ * const hypercert = await repo.hypercerts.create({...});
4807
+ * const mainRef = { uri: hypercert.hypercertUri, cid: hypercert.hypercertCid };
4808
+ *
4809
+ * const evaluations = await batchCreateSidecars(repo, [
4810
+ * {
4811
+ * collection: "org.myapp.evaluation",
4812
+ * record: {
4813
+ * $type: "org.myapp.evaluation",
4814
+ * subject: mainRef, // Reference already included
4815
+ * score: 85,
4816
+ * methodology: "Peer review",
4817
+ * createdAt: new Date().toISOString(),
4818
+ * },
4819
+ * },
4820
+ * {
4821
+ * collection: "org.myapp.comment",
4822
+ * record: {
4823
+ * $type: "org.myapp.comment",
4824
+ * subject: mainRef, // Reference already included
4825
+ * text: "Great work!",
4826
+ * createdAt: new Date().toISOString(),
4827
+ * },
4828
+ * },
4829
+ * ]);
4830
+ * ```
4831
+ */
4832
+ declare function batchCreateSidecars(repo: Repository, sidecars: SidecarRecordParams[]): Promise<CreateResult[]>;
3101
4833
 
3102
4834
  /**
3103
4835
  * Base error class for all SDK errors.
@@ -3671,12 +5403,29 @@ type IdentityAttr = z.infer<typeof IdentityAttrSchema>;
3671
5403
  /**
3672
5404
  * Zod schema for MIME type patterns.
3673
5405
  *
3674
- * Validates MIME type strings like "image/*" or "video/mp4".
5406
+ * Validates MIME type strings used in blob permissions.
5407
+ * Supports standard MIME types and wildcard patterns per ATProto spec.
5408
+ *
5409
+ * **References:**
5410
+ * - ATProto Permission Spec: https://atproto.com/specs/permission (blob resource)
5411
+ * - RFC 2045 (MIME): https://www.rfc-editor.org/rfc/rfc2045 (token definition)
5412
+ * - IANA Media Types: https://www.iana.org/assignments/media-types/
5413
+ *
5414
+ * **Implementation:**
5415
+ * This is a "good enough" validation that allows common real-world MIME types:
5416
+ * - Type: letters, digits (e.g., "3gpp")
5417
+ * - Subtype: letters, digits, hyphens, plus signs, dots, underscores, wildcards
5418
+ * - Examples: "image/png", "application/vnd.api+json", "video/*", "clue_info+xml"
5419
+ *
5420
+ * Note: We use a simplified regex rather than full RFC 2045 token validation
5421
+ * for practicality. Zod v4 has native MIME support (z.file().mime()) but would
5422
+ * require a larger migration effort.
3675
5423
  *
3676
5424
  * @example
3677
5425
  * ```typescript
3678
- * MimeTypeSchema.parse('image/*'); // Valid
3679
- * MimeTypeSchema.parse('video/mp4'); // Valid
5426
+ * MimeTypeSchema.parse('image/*'); // Valid - wildcard
5427
+ * MimeTypeSchema.parse('video/mp4'); // Valid - standard
5428
+ * MimeTypeSchema.parse('application/vnd.api+json'); // Valid - with dots/plus
3680
5429
  * MimeTypeSchema.parse('invalid'); // Throws ZodError
3681
5430
  * ```
3682
5431
  */
@@ -3687,6 +5436,12 @@ declare const MimeTypeSchema: z.ZodString;
3687
5436
  * NSIDs are reverse-DNS style identifiers used throughout ATProto
3688
5437
  * (e.g., "app.bsky.feed.post" or "com.example.myrecord").
3689
5438
  *
5439
+ * Official ATProto NSID spec requires:
5440
+ * - Each segment must be 1-63 characters
5441
+ * - Authority segments (all but last) can contain hyphens, but not at boundaries
5442
+ * - Name segment (last) must start with a letter and contain only alphanumerics
5443
+ * - Hyphens only allowed in authority segments, not in the name segment
5444
+ *
3690
5445
  * @see https://atproto.com/specs/nsid
3691
5446
  *
3692
5447
  * @example
@@ -4521,20 +6276,44 @@ declare function parseScope(scope: string): string[];
4521
6276
  /**
4522
6277
  * Check if a scope string contains a specific permission.
4523
6278
  *
4524
- * This function performs exact string matching. For more advanced
4525
- * permission checking (e.g., wildcard matching), you'll need to
4526
- * implement custom logic.
6279
+ * Implements permission matching per ATProto OAuth spec with support for
6280
+ * exact matching and limited wildcard patterns.
6281
+ *
6282
+ * **References:**
6283
+ * - ATProto Permission Spec: https://atproto.com/specs/permission
6284
+ * - ATProto OAuth Spec: https://atproto.com/specs/oauth
6285
+ *
6286
+ * **Supported wildcards (per spec):**
6287
+ * - `repo:*` - Matches any repository collection (e.g., `repo:app.bsky.feed.post`)
6288
+ * - `rpc:*` - Matches any RPC lexicon (but aud cannot also be wildcard)
6289
+ * - `blob:image/*` - MIME type wildcards (e.g., matches `blob:image/png`, `blob:image/jpeg`)
6290
+ * - `blob:` + wildcard MIME - Matches any MIME type (using `*` + `/` + `*` pattern)
6291
+ * - `identity:*` - Full control of DID document and handle (spec allows `*` as attr value)
6292
+ *
6293
+ * **NOT supported (per spec):**
6294
+ * - `account:*` - Account attr does not support wildcards (only `email` and `repo` allowed)
6295
+ * - `include:*` - Include NSID does not support wildcards
6296
+ * - Partial wildcards like `com.example.*` are not supported
4527
6297
  *
4528
6298
  * @param scope - Space-separated scope string
4529
6299
  * @param permission - The permission to check for
4530
6300
  * @returns True if the scope contains the permission
4531
6301
  *
4532
- * @example
6302
+ * @example Exact matching
4533
6303
  * ```typescript
4534
- * const scope = "account:email?action=read repo:app.bsky.feed.post";
4535
- * hasPermission(scope, "account:email?action=read"); // true
6304
+ * const scope = "account:email repo:app.bsky.feed.post";
6305
+ * hasPermission(scope, "account:email"); // true
4536
6306
  * hasPermission(scope, "account:repo"); // false
4537
6307
  * ```
6308
+ *
6309
+ * @example Wildcard matching
6310
+ * ```typescript
6311
+ * const scope = "repo:* blob:image/* identity:*";
6312
+ * hasPermission(scope, "repo:app.bsky.feed.post"); // true
6313
+ * hasPermission(scope, "blob:image/png"); // true
6314
+ * hasPermission(scope, "blob:video/mp4"); // false
6315
+ * hasPermission(scope, "identity:handle"); // true
6316
+ * ```
4538
6317
  */
4539
6318
  declare function hasPermission(scope: string, permission: string): boolean;
4540
6319
  /**
@@ -4618,5 +6397,5 @@ declare function validateScope(scope: string): {
4618
6397
  invalidPermissions: string[];
4619
6398
  };
4620
6399
 
4621
- export { ATPROTO_SCOPE, ATProtoSDK, ATProtoSDKConfigSchema, ATProtoSDKError, AccountActionSchema, AccountAttrSchema, AccountPermissionSchema, AuthenticationError, BlobPermissionSchema, CollaboratorPermissionsSchema, CollaboratorSchema, ConfigurableAgent, HYPERCERT_COLLECTIONS, HYPERCERT_LEXICONS, IdentityAttrSchema, IdentityPermissionSchema, InMemorySessionStore, InMemoryStateStore, IncludePermissionSchema, MimeTypeSchema, NetworkError, NsidSchema, OAuthConfigSchema, OrganizationSchema, PermissionBuilder, PermissionSchema, RepoActionSchema, RepoPermissionSchema, Repository, RpcPermissionSchema, SDSRequiredError, ScopePresets, ServerConfigSchema, SessionExpiredError, TRANSITION_SCOPES, TimeoutConfigSchema, TransitionScopeSchema, ValidationError, buildScope, createATProtoSDK, hasAllPermissions, hasAnyPermission, hasPermission, mergeScopes, parseScope, removePermissions, validateScope };
4622
- export type { ATProtoSDKConfig, AccountAction, AccountAttr, AccountPermissionInput, AuthorizeOptions, BadgeAward, BadgeDefinition, BadgeResponse, BlobOperations, BlobPermissionInput, CacheInterface, Collaborator, CollaboratorOperations, CollaboratorPermissions, CreateHypercertParams, CreateHypercertResult, CreateResult, DID, FundingReceipt, HypercertClaim, HypercertCollection, HypercertCollectionClaimItem, HypercertContribution, HypercertEvaluation, HypercertEvents, HypercertEvidence, HypercertImage, HypercertImageRecord, HypercertLocation, HypercertMeasurement, HypercertOperations, HypercertProject, HypercertRights, HypercertWithMetadata, IdentityAttr, IdentityPermissionInput, IncludePermissionInput, ListParams, LoggerInterface, Organization, OrganizationInfo, OrganizationOperations, PaginatedList, Permission, PermissionInput, ProfileOperations, ProgressStep, RecordOperations, RepoAction, RepoPermissionInput, RepositoryAccessGrant, RepositoryOptions, RepositoryRole, RpcPermissionInput, Session, SessionStore, StateStore, StrongRef, TransitionScope, UpdateResult };
6400
+ export { ATPROTO_SCOPE, ATProtoSDK, ATProtoSDKConfigSchema, ATProtoSDKError, AccountActionSchema, AccountAttrSchema, AccountPermissionSchema, AuthenticationError, BaseOperations, BlobPermissionSchema, CollaboratorPermissionsSchema, CollaboratorSchema, ConfigurableAgent, HYPERCERT_COLLECTIONS, HYPERCERT_LEXICONS, IdentityAttrSchema, IdentityPermissionSchema, InMemorySessionStore, InMemoryStateStore, IncludePermissionSchema, LexiconRegistry, MimeTypeSchema, NetworkError, NsidSchema, OAuthConfigSchema, OrganizationSchema, PermissionBuilder, PermissionSchema, RepoActionSchema, RepoPermissionSchema, Repository, RpcPermissionSchema, SDSRequiredError, ScopePresets, ServerConfigSchema, SessionExpiredError, TRANSITION_SCOPES, TimeoutConfigSchema, TransitionScopeSchema, ValidationError, attachSidecar, batchCreateSidecars, buildAtUri, buildScope, createATProtoSDK, createArrayField, createBlobField, createBooleanField, createDatetimeField, createIntegerField, createLexiconDoc, createNumberField, createObjectField, createRecordDef, createSidecarRecord, createStringField, createStrongRef, createStrongRefField, createStrongRefFromResult, createWithSidecars, extractRkeyFromUri, hasAllPermissions, hasAnyPermission, hasPermission, isStrongRef, isValidAtUri, mergeScopes, parseAtUri, parseScope, removePermissions, validateLexiconStructure, validateScope, validateStrongRef };
6401
+ export type { ATProtoSDKConfig, AccountAction, AccountAttr, AccountPermissionInput, AtUriComponents, AttachSidecarParams, AuthorizeOptions, BadgeAward, BadgeDefinition, BadgeResponse, BlobOperations, BlobPermissionInput, CacheInterface, Collaborator, CollaboratorOperations, CollaboratorPermissions, CreateHypercertEvidenceParams, CreateHypercertParams, CreateHypercertResult, CreateOrganizationParams, CreateProjectParams, CreateResult, CreateWithSidecarsParams, DID, FundingReceipt, HypercertClaim, HypercertCollection, HypercertCollectionItem, HypercertContributionDetails, HypercertContributor, HypercertContributorInformation, HypercertEvaluation, HypercertEvents, HypercertEvidence, HypercertImage, HypercertImageRecord, HypercertLocation, HypercertMeasurement, HypercertOperations, HypercertProject, HypercertProjectWithMetadata, HypercertRights, HypercertWithMetadata, HypercertWorkScopeTag, IdentityAttr, IdentityPermissionInput, IncludePermissionInput, LexiconArrayField, LexiconBlobField, LexiconBooleanField, LexiconDoc, LexiconField, LexiconFieldType, LexiconIntegerField, LexiconNumberField, LexiconObjectField, LexiconRecordDef, LexiconRefField, LexiconStringField, LexiconUnknownField, ListParams, LocationParams, LoggerInterface, MultiSidecarResult, Organization, OrganizationInfo, OrganizationOperations, PaginatedList, Permission, PermissionInput, ProfileOperations, ProgressStep, RecordOperations, RepoAction, RepoPermissionInput, RepositoryAccessGrant, RepositoryOptions, RepositoryRole, RpcPermissionInput, Session, SessionStore, SidecarRecordParams, SidecarResult, StateStore, StrongRef, TransitionScope, UpdateProjectParams, UpdateResult, ValidationResult };