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