@hypercerts-org/sdk-core 0.4.0-beta.0 → 0.5.0-beta.0

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
@@ -766,9 +766,10 @@ declare const OrganizationSchema: z.ZodObject<{
766
766
  /**
767
767
  * How the current user relates to this organization.
768
768
  * - `"owner"`: User created or owns the organization
769
- * - `"collaborator"`: User was invited to collaborate
769
+ * - `"shared"`: User was invited to collaborate (has permissions)
770
+ * - `"none"`: User has no access to this organization
770
771
  */
771
- accessType: z.ZodEnum<["owner", "collaborator"]>;
772
+ accessType: z.ZodEnum<["owner", "shared", "none"]>;
772
773
  }, "strip", z.ZodTypeAny, {
773
774
  did: string;
774
775
  handle: string;
@@ -782,7 +783,7 @@ declare const OrganizationSchema: z.ZodObject<{
782
783
  admin: boolean;
783
784
  owner: boolean;
784
785
  };
785
- accessType: "owner" | "collaborator";
786
+ accessType: "owner" | "shared" | "none";
786
787
  description?: string | undefined;
787
788
  }, {
788
789
  did: string;
@@ -797,7 +798,7 @@ declare const OrganizationSchema: z.ZodObject<{
797
798
  admin: boolean;
798
799
  owner: boolean;
799
800
  };
800
- accessType: "owner" | "collaborator";
801
+ accessType: "owner" | "shared" | "none";
801
802
  description?: string | undefined;
802
803
  }>;
803
804
  /**
@@ -1022,7 +1023,7 @@ interface OrganizationInfo {
1022
1023
  name: string;
1023
1024
  description?: string;
1024
1025
  createdAt: string;
1025
- accessType: "owner" | "collaborator";
1026
+ accessType: "owner" | "shared" | "none";
1026
1027
  permissions: CollaboratorPermissions;
1027
1028
  collaboratorCount?: number;
1028
1029
  profile?: {
@@ -1874,9 +1875,18 @@ interface CollaboratorOperations {
1874
1875
  /**
1875
1876
  * Lists all collaborators on the repository.
1876
1877
  *
1877
- * @returns Promise resolving to array of access grants
1878
+ * @param params - Optional pagination parameters
1879
+ * @param params.limit - Maximum number of results (1-100, default 50)
1880
+ * @param params.cursor - Pagination cursor from previous response
1881
+ * @returns Promise resolving to collaborators and optional cursor
1878
1882
  */
1879
- list(): Promise<RepositoryAccessGrant[]>;
1883
+ list(params?: {
1884
+ limit?: number;
1885
+ cursor?: string;
1886
+ }): Promise<{
1887
+ collaborators: RepositoryAccessGrant[];
1888
+ cursor?: string;
1889
+ }>;
1880
1890
  /**
1881
1891
  * Checks if a user has any access to the repository.
1882
1892
  *
@@ -1955,9 +1965,18 @@ interface OrganizationOperations {
1955
1965
  /**
1956
1966
  * Lists organizations the current user has access to.
1957
1967
  *
1958
- * @returns Promise resolving to array of organization info
1968
+ * @param params - Optional pagination parameters
1969
+ * @param params.limit - Maximum number of results (1-100, default 50)
1970
+ * @param params.cursor - Pagination cursor from previous response
1971
+ * @returns Promise resolving to organizations and optional cursor
1959
1972
  */
1960
- list(): Promise<OrganizationInfo[]>;
1973
+ list(params?: {
1974
+ limit?: number;
1975
+ cursor?: string;
1976
+ }): Promise<{
1977
+ organizations: OrganizationInfo[];
1978
+ cursor?: string;
1979
+ }>;
1961
1980
  }
1962
1981
 
1963
1982
  /**
package/dist/index.mjs CHANGED
@@ -1669,7 +1669,7 @@ class BlobOperationsImpl {
1669
1669
  throw new NetworkError("Failed to upload blob");
1670
1670
  }
1671
1671
  return {
1672
- ref: result.data.blob.ref,
1672
+ ref: { $link: result.data.blob.ref.toString() },
1673
1673
  mimeType: result.data.blob.mimeType,
1674
1674
  size: result.data.blob.size,
1675
1675
  };
@@ -2176,7 +2176,7 @@ class HypercertOperationsImpl extends EventEmitter {
2176
2176
  if (uploadResult.success) {
2177
2177
  imageBlobRef = {
2178
2178
  $type: "blob",
2179
- ref: uploadResult.data.blob.ref,
2179
+ ref: { $link: uploadResult.data.blob.ref.toString() },
2180
2180
  mimeType: uploadResult.data.blob.mimeType,
2181
2181
  size: uploadResult.data.blob.size,
2182
2182
  };
@@ -2601,7 +2601,7 @@ class HypercertOperationsImpl extends EventEmitter {
2601
2601
  if (uploadResult.success) {
2602
2602
  locationValue = {
2603
2603
  $type: "blob",
2604
- ref: uploadResult.data.blob.ref,
2604
+ ref: { $link: uploadResult.data.blob.ref.toString() },
2605
2605
  mimeType: uploadResult.data.blob.mimeType,
2606
2606
  size: uploadResult.data.blob.size,
2607
2607
  };
@@ -2886,7 +2886,7 @@ class HypercertOperationsImpl extends EventEmitter {
2886
2886
  if (uploadResult.success) {
2887
2887
  coverPhotoRef = {
2888
2888
  $type: "blob",
2889
- ref: uploadResult.data.blob.ref,
2889
+ ref: { $link: uploadResult.data.blob.ref.toString() },
2890
2890
  mimeType: uploadResult.data.blob.mimeType,
2891
2891
  size: uploadResult.data.blob.size,
2892
2892
  };
@@ -3117,6 +3117,26 @@ class CollaboratorOperationsImpl {
3117
3117
  return "editor";
3118
3118
  return "viewer";
3119
3119
  }
3120
+ /**
3121
+ * Converts a permission string array to a permissions object.
3122
+ *
3123
+ * The SDS API returns permissions as an array of strings (e.g., ["read", "create"]).
3124
+ * This method converts them to the boolean flag format used by the SDK.
3125
+ *
3126
+ * @param permissionArray - Array of permission strings from SDS API
3127
+ * @returns Permission flags object
3128
+ * @internal
3129
+ */
3130
+ parsePermissions(permissionArray) {
3131
+ return {
3132
+ read: permissionArray.includes("read"),
3133
+ create: permissionArray.includes("create"),
3134
+ update: permissionArray.includes("update"),
3135
+ delete: permissionArray.includes("delete"),
3136
+ admin: permissionArray.includes("admin"),
3137
+ owner: permissionArray.includes("owner"),
3138
+ };
3139
+ }
3120
3140
  /**
3121
3141
  * Grants repository access to a user.
3122
3142
  *
@@ -3193,7 +3213,10 @@ class CollaboratorOperationsImpl {
3193
3213
  /**
3194
3214
  * Lists all collaborators on the repository.
3195
3215
  *
3196
- * @returns Promise resolving to array of access grants
3216
+ * @param params - Optional pagination parameters
3217
+ * @param params.limit - Maximum number of results (1-100, default 50)
3218
+ * @param params.cursor - Pagination cursor from previous response
3219
+ * @returns Promise resolving to collaborators and optional cursor
3197
3220
  * @throws {@link NetworkError} if the list operation fails
3198
3221
  *
3199
3222
  * @remarks
@@ -3202,34 +3225,49 @@ class CollaboratorOperationsImpl {
3202
3225
  *
3203
3226
  * @example
3204
3227
  * ```typescript
3205
- * const collaborators = await repo.collaborators.list();
3228
+ * // Get first page
3229
+ * const page1 = await repo.collaborators.list({ limit: 10 });
3230
+ * console.log(`Found ${page1.collaborators.length} collaborators`);
3231
+ *
3232
+ * // Get next page if available
3233
+ * if (page1.cursor) {
3234
+ * const page2 = await repo.collaborators.list({ limit: 10, cursor: page1.cursor });
3235
+ * }
3206
3236
  *
3207
3237
  * // Filter active collaborators
3208
- * const active = collaborators.filter(c => !c.revokedAt);
3209
- *
3210
- * // Group by role
3211
- * const byRole = {
3212
- * owners: active.filter(c => c.role === "owner"),
3213
- * admins: active.filter(c => c.role === "admin"),
3214
- * editors: active.filter(c => c.role === "editor"),
3215
- * viewers: active.filter(c => c.role === "viewer"),
3216
- * };
3238
+ * const active = page1.collaborators.filter(c => !c.revokedAt);
3217
3239
  * ```
3218
3240
  */
3219
- async list() {
3220
- const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.repo.listCollaborators?repo=${encodeURIComponent(this.repoDid)}`, { method: "GET" });
3241
+ async list(params) {
3242
+ const queryParams = new URLSearchParams({
3243
+ repo: this.repoDid,
3244
+ });
3245
+ if (params?.limit !== undefined) {
3246
+ queryParams.set("limit", params.limit.toString());
3247
+ }
3248
+ if (params?.cursor) {
3249
+ queryParams.set("cursor", params.cursor);
3250
+ }
3251
+ const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.repo.listCollaborators?${queryParams.toString()}`, { method: "GET" });
3221
3252
  if (!response.ok) {
3222
3253
  throw new NetworkError(`Failed to list collaborators: ${response.statusText}`);
3223
3254
  }
3224
3255
  const data = await response.json();
3225
- return (data.collaborators || []).map((c) => ({
3226
- userDid: c.userDid,
3227
- role: this.permissionsToRole(c.permissions),
3228
- permissions: c.permissions,
3229
- grantedBy: c.grantedBy,
3230
- grantedAt: c.grantedAt,
3231
- revokedAt: c.revokedAt,
3232
- }));
3256
+ const collaborators = (data.collaborators || []).map((c) => {
3257
+ const permissions = this.parsePermissions(c.permissions);
3258
+ return {
3259
+ userDid: c.userDid,
3260
+ role: this.permissionsToRole(permissions),
3261
+ permissions: permissions,
3262
+ grantedBy: c.grantedBy,
3263
+ grantedAt: c.grantedAt,
3264
+ revokedAt: c.revokedAt,
3265
+ };
3266
+ });
3267
+ return {
3268
+ collaborators,
3269
+ cursor: data.cursor,
3270
+ };
3233
3271
  }
3234
3272
  /**
3235
3273
  * Checks if a user has any access to the repository.
@@ -3252,7 +3290,7 @@ class CollaboratorOperationsImpl {
3252
3290
  */
3253
3291
  async hasAccess(userDid) {
3254
3292
  try {
3255
- const collaborators = await this.list();
3293
+ const { collaborators } = await this.list();
3256
3294
  return collaborators.some((c) => c.userDid === userDid && !c.revokedAt);
3257
3295
  }
3258
3296
  catch {
@@ -3274,7 +3312,7 @@ class CollaboratorOperationsImpl {
3274
3312
  * ```
3275
3313
  */
3276
3314
  async getRole(userDid) {
3277
- const collaborators = await this.list();
3315
+ const { collaborators } = await this.list();
3278
3316
  const collab = collaborators.find((c) => c.userDid === userDid && !c.revokedAt);
3279
3317
  return collab?.role ?? null;
3280
3318
  }
@@ -3481,10 +3519,17 @@ class OrganizationOperationsImpl {
3481
3519
  * ```
3482
3520
  */
3483
3521
  async create(params) {
3522
+ const userDid = this.session.did || this.session.sub;
3523
+ if (!userDid) {
3524
+ throw new NetworkError("No authenticated user found");
3525
+ }
3484
3526
  const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.organization.create`, {
3485
3527
  method: "POST",
3486
3528
  headers: { "Content-Type": "application/json" },
3487
- body: JSON.stringify(params),
3529
+ body: JSON.stringify({
3530
+ ...params,
3531
+ creatorDid: userDid,
3532
+ }),
3488
3533
  });
3489
3534
  if (!response.ok) {
3490
3535
  throw new NetworkError(`Failed to create organization: ${response.statusText}`);
@@ -3496,8 +3541,15 @@ class OrganizationOperationsImpl {
3496
3541
  name: data.name,
3497
3542
  description: data.description,
3498
3543
  createdAt: data.createdAt || new Date().toISOString(),
3499
- accessType: "owner",
3500
- permissions: { read: true, create: true, update: true, delete: true, admin: true, owner: true },
3544
+ accessType: data.accessType || "owner",
3545
+ permissions: data.permissions || {
3546
+ read: true,
3547
+ create: true,
3548
+ update: true,
3549
+ delete: true,
3550
+ admin: true,
3551
+ owner: true,
3552
+ },
3501
3553
  };
3502
3554
  }
3503
3555
  /**
@@ -3524,8 +3576,8 @@ class OrganizationOperationsImpl {
3524
3576
  */
3525
3577
  async get(did) {
3526
3578
  try {
3527
- const orgs = await this.list();
3528
- return orgs.find((o) => o.did === did) ?? null;
3579
+ const { organizations } = await this.list();
3580
+ return organizations.find((o) => o.did === did) ?? null;
3529
3581
  }
3530
3582
  catch {
3531
3583
  return null;
@@ -3534,7 +3586,10 @@ class OrganizationOperationsImpl {
3534
3586
  /**
3535
3587
  * Lists organizations the current user has access to.
3536
3588
  *
3537
- * @returns Promise resolving to array of organization info
3589
+ * @param params - Optional pagination parameters
3590
+ * @param params.limit - Maximum number of results (1-100, default 50)
3591
+ * @param params.cursor - Pagination cursor from previous response
3592
+ * @returns Promise resolving to organizations and optional cursor
3538
3593
  * @throws {@link NetworkError} if the list operation fails
3539
3594
  *
3540
3595
  * @remarks
@@ -3546,21 +3601,25 @@ class OrganizationOperationsImpl {
3546
3601
  *
3547
3602
  * @example
3548
3603
  * ```typescript
3549
- * const orgs = await repo.organizations.list();
3604
+ * // Get first page
3605
+ * const page1 = await repo.organizations.list({ limit: 20 });
3606
+ * console.log(`Found ${page1.organizations.length} organizations`);
3550
3607
  *
3551
- * // Filter by access type
3552
- * const owned = orgs.filter(o => o.accessType === "owner");
3553
- * const collaborated = orgs.filter(o => o.accessType === "collaborator");
3608
+ * // Get next page if available
3609
+ * if (page1.cursor) {
3610
+ * const page2 = await repo.organizations.list({ limit: 20, cursor: page1.cursor });
3611
+ * }
3554
3612
  *
3555
- * console.log(`You own ${owned.length} organizations`);
3556
- * console.log(`You collaborate on ${collaborated.length} organizations`);
3613
+ * // Filter by access type
3614
+ * const owned = page1.organizations.filter(o => o.accessType === "owner");
3615
+ * const shared = page1.organizations.filter(o => o.accessType === "shared");
3557
3616
  * ```
3558
3617
  *
3559
3618
  * @example Display organization details
3560
3619
  * ```typescript
3561
- * const orgs = await repo.organizations.list();
3620
+ * const { organizations } = await repo.organizations.list();
3562
3621
  *
3563
- * for (const org of orgs) {
3622
+ * for (const org of organizations) {
3564
3623
  * console.log(`${org.name} (@${org.handle})`);
3565
3624
  * console.log(` DID: ${org.did}`);
3566
3625
  * console.log(` Access: ${org.accessType}`);
@@ -3570,21 +3629,38 @@ class OrganizationOperationsImpl {
3570
3629
  * }
3571
3630
  * ```
3572
3631
  */
3573
- async list() {
3574
- const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.organization.list?userDid=${encodeURIComponent(this.session.did || this.session.sub)}`, { method: "GET" });
3632
+ async list(params) {
3633
+ const userDid = this.session.did || this.session.sub;
3634
+ if (!userDid) {
3635
+ throw new NetworkError("No authenticated user found");
3636
+ }
3637
+ const queryParams = new URLSearchParams({
3638
+ userDid,
3639
+ });
3640
+ if (params?.limit !== undefined) {
3641
+ queryParams.set("limit", params.limit.toString());
3642
+ }
3643
+ if (params?.cursor) {
3644
+ queryParams.set("cursor", params.cursor);
3645
+ }
3646
+ const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.organization.list?${queryParams.toString()}`, { method: "GET" });
3575
3647
  if (!response.ok) {
3576
3648
  throw new NetworkError(`Failed to list organizations: ${response.statusText}`);
3577
3649
  }
3578
3650
  const data = await response.json();
3579
- return (data.repositories || []).map((r) => ({
3651
+ const organizations = (data.organizations || []).map((r) => ({
3580
3652
  did: r.did,
3581
3653
  handle: r.handle,
3582
3654
  name: r.name,
3583
3655
  description: r.description,
3584
- createdAt: new Date().toISOString(), // SDS may not return this
3656
+ createdAt: r.createdAt || new Date().toISOString(),
3585
3657
  accessType: r.accessType,
3586
3658
  permissions: r.permissions,
3587
3659
  }));
3660
+ return {
3661
+ organizations,
3662
+ cursor: data.cursor,
3663
+ };
3588
3664
  }
3589
3665
  }
3590
3666
 
@@ -4507,9 +4583,10 @@ const OrganizationSchema = z.object({
4507
4583
  /**
4508
4584
  * How the current user relates to this organization.
4509
4585
  * - `"owner"`: User created or owns the organization
4510
- * - `"collaborator"`: User was invited to collaborate
4586
+ * - `"shared"`: User was invited to collaborate (has permissions)
4587
+ * - `"none"`: User has no access to this organization
4511
4588
  */
4512
- accessType: z.enum(["owner", "collaborator"]),
4589
+ accessType: z.enum(["owner", "shared", "none"]),
4513
4590
  });
4514
4591
  /**
4515
4592
  * Zod schema for collaborator data.