@hypercerts-org/sdk-core 0.2.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/.turbo/turbo-build.log +13 -301
- package/.turbo/turbo-test.log +30 -29
- package/CHANGELOG.md +49 -3
- package/README.md +473 -50
- package/dist/index.cjs +232 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +57 -19
- package/dist/index.mjs +232 -55
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs +3 -2
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +57 -19
- package/dist/types.mjs +3 -2
- package/dist/types.mjs.map +1 -1
- package/package.json +2 -2
- package/src/core/types.ts +3 -2
- package/src/repository/BlobOperationsImpl.ts +1 -1
- package/src/repository/CollaboratorOperationsImpl.ts +184 -30
- package/src/repository/HypercertOperationsImpl.ts +3 -3
- package/src/repository/OrganizationOperationsImpl.ts +70 -22
- package/src/repository/interfaces.ts +45 -4
- package/src/repository/types.ts +1 -1
- package/tests/repository/BlobOperationsImpl.test.ts +10 -9
- package/tests/repository/CollaboratorOperationsImpl.test.ts +138 -23
- package/tests/repository/OrganizationOperationsImpl.test.ts +18 -20
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
|
};
|
|
@@ -3041,9 +3041,11 @@ class HypercertOperationsImpl extends eventemitter3.EventEmitter {
|
|
|
3041
3041
|
* - `owner`: Full control including ownership management
|
|
3042
3042
|
*
|
|
3043
3043
|
* **SDS API Endpoints Used**:
|
|
3044
|
-
* - `com.
|
|
3045
|
-
* - `com.
|
|
3046
|
-
* - `com.
|
|
3044
|
+
* - `com.sds.repo.grantAccess`: Grant access to a user
|
|
3045
|
+
* - `com.sds.repo.revokeAccess`: Revoke access from a user
|
|
3046
|
+
* - `com.sds.repo.listCollaborators`: List all collaborators
|
|
3047
|
+
* - `com.sds.repo.getPermissions`: Get current user's permissions
|
|
3048
|
+
* - `com.sds.repo.transferOwnership`: Transfer repository ownership
|
|
3047
3049
|
*
|
|
3048
3050
|
* @example
|
|
3049
3051
|
* ```typescript
|
|
@@ -3116,6 +3118,26 @@ class CollaboratorOperationsImpl {
|
|
|
3116
3118
|
return "editor";
|
|
3117
3119
|
return "viewer";
|
|
3118
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
|
+
}
|
|
3119
3141
|
/**
|
|
3120
3142
|
* Grants repository access to a user.
|
|
3121
3143
|
*
|
|
@@ -3145,7 +3167,7 @@ class CollaboratorOperationsImpl {
|
|
|
3145
3167
|
*/
|
|
3146
3168
|
async grant(params) {
|
|
3147
3169
|
const permissions = this.roleToPermissions(params.role);
|
|
3148
|
-
const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.
|
|
3170
|
+
const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.repo.grantAccess`, {
|
|
3149
3171
|
method: "POST",
|
|
3150
3172
|
headers: { "Content-Type": "application/json" },
|
|
3151
3173
|
body: JSON.stringify({
|
|
@@ -3177,7 +3199,7 @@ class CollaboratorOperationsImpl {
|
|
|
3177
3199
|
* ```
|
|
3178
3200
|
*/
|
|
3179
3201
|
async revoke(params) {
|
|
3180
|
-
const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.
|
|
3202
|
+
const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.repo.revokeAccess`, {
|
|
3181
3203
|
method: "POST",
|
|
3182
3204
|
headers: { "Content-Type": "application/json" },
|
|
3183
3205
|
body: JSON.stringify({
|
|
@@ -3192,7 +3214,10 @@ class CollaboratorOperationsImpl {
|
|
|
3192
3214
|
/**
|
|
3193
3215
|
* Lists all collaborators on the repository.
|
|
3194
3216
|
*
|
|
3195
|
-
* @
|
|
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
|
|
3196
3221
|
* @throws {@link NetworkError} if the list operation fails
|
|
3197
3222
|
*
|
|
3198
3223
|
* @remarks
|
|
@@ -3201,34 +3226,49 @@ class CollaboratorOperationsImpl {
|
|
|
3201
3226
|
*
|
|
3202
3227
|
* @example
|
|
3203
3228
|
* ```typescript
|
|
3204
|
-
*
|
|
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
|
+
* }
|
|
3205
3237
|
*
|
|
3206
3238
|
* // Filter active collaborators
|
|
3207
|
-
* const active = collaborators.filter(c => !c.revokedAt);
|
|
3208
|
-
*
|
|
3209
|
-
* // Group by role
|
|
3210
|
-
* const byRole = {
|
|
3211
|
-
* owners: active.filter(c => c.role === "owner"),
|
|
3212
|
-
* admins: active.filter(c => c.role === "admin"),
|
|
3213
|
-
* editors: active.filter(c => c.role === "editor"),
|
|
3214
|
-
* viewers: active.filter(c => c.role === "viewer"),
|
|
3215
|
-
* };
|
|
3239
|
+
* const active = page1.collaborators.filter(c => !c.revokedAt);
|
|
3216
3240
|
* ```
|
|
3217
3241
|
*/
|
|
3218
|
-
async list() {
|
|
3219
|
-
const
|
|
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" });
|
|
3220
3253
|
if (!response.ok) {
|
|
3221
3254
|
throw new NetworkError(`Failed to list collaborators: ${response.statusText}`);
|
|
3222
3255
|
}
|
|
3223
3256
|
const data = await response.json();
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
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
|
+
};
|
|
3232
3272
|
}
|
|
3233
3273
|
/**
|
|
3234
3274
|
* Checks if a user has any access to the repository.
|
|
@@ -3251,7 +3291,7 @@ class CollaboratorOperationsImpl {
|
|
|
3251
3291
|
*/
|
|
3252
3292
|
async hasAccess(userDid) {
|
|
3253
3293
|
try {
|
|
3254
|
-
const collaborators = await this.list();
|
|
3294
|
+
const { collaborators } = await this.list();
|
|
3255
3295
|
return collaborators.some((c) => c.userDid === userDid && !c.revokedAt);
|
|
3256
3296
|
}
|
|
3257
3297
|
catch {
|
|
@@ -3273,10 +3313,108 @@ class CollaboratorOperationsImpl {
|
|
|
3273
3313
|
* ```
|
|
3274
3314
|
*/
|
|
3275
3315
|
async getRole(userDid) {
|
|
3276
|
-
const collaborators = await this.list();
|
|
3316
|
+
const { collaborators } = await this.list();
|
|
3277
3317
|
const collab = collaborators.find((c) => c.userDid === userDid && !c.revokedAt);
|
|
3278
3318
|
return collab?.role ?? null;
|
|
3279
3319
|
}
|
|
3320
|
+
/**
|
|
3321
|
+
* Gets the current user's permissions for this repository.
|
|
3322
|
+
*
|
|
3323
|
+
* @returns Promise resolving to the permission flags
|
|
3324
|
+
* @throws {@link NetworkError} if the request fails
|
|
3325
|
+
*
|
|
3326
|
+
* @remarks
|
|
3327
|
+
* This is useful for checking what actions the current user can perform
|
|
3328
|
+
* before attempting operations that might fail due to insufficient permissions.
|
|
3329
|
+
*
|
|
3330
|
+
* @example
|
|
3331
|
+
* ```typescript
|
|
3332
|
+
* const permissions = await repo.collaborators.getPermissions();
|
|
3333
|
+
*
|
|
3334
|
+
* if (permissions.admin) {
|
|
3335
|
+
* // Show admin UI
|
|
3336
|
+
* console.log("You can manage collaborators");
|
|
3337
|
+
* }
|
|
3338
|
+
*
|
|
3339
|
+
* if (permissions.create) {
|
|
3340
|
+
* console.log("You can create records");
|
|
3341
|
+
* }
|
|
3342
|
+
* ```
|
|
3343
|
+
*
|
|
3344
|
+
* @example Conditional UI rendering
|
|
3345
|
+
* ```typescript
|
|
3346
|
+
* const permissions = await repo.collaborators.getPermissions();
|
|
3347
|
+
*
|
|
3348
|
+
* // Show/hide UI elements based on permissions
|
|
3349
|
+
* const canEdit = permissions.update;
|
|
3350
|
+
* const canDelete = permissions.delete;
|
|
3351
|
+
* const isAdmin = permissions.admin;
|
|
3352
|
+
* const isOwner = permissions.owner;
|
|
3353
|
+
* ```
|
|
3354
|
+
*/
|
|
3355
|
+
async getPermissions() {
|
|
3356
|
+
const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.repo.getPermissions?repo=${encodeURIComponent(this.repoDid)}`, { method: "GET" });
|
|
3357
|
+
if (!response.ok) {
|
|
3358
|
+
throw new NetworkError(`Failed to get permissions: ${response.statusText}`);
|
|
3359
|
+
}
|
|
3360
|
+
const data = await response.json();
|
|
3361
|
+
return data.permissions;
|
|
3362
|
+
}
|
|
3363
|
+
/**
|
|
3364
|
+
* Transfers repository ownership to another user.
|
|
3365
|
+
*
|
|
3366
|
+
* @param params - Transfer parameters
|
|
3367
|
+
* @param params.newOwnerDid - DID of the user to transfer ownership to
|
|
3368
|
+
* @throws {@link NetworkError} if the transfer fails
|
|
3369
|
+
*
|
|
3370
|
+
* @remarks
|
|
3371
|
+
* **IMPORTANT**: This action is irreversible. Once ownership is transferred:
|
|
3372
|
+
* - The new owner gains full control of the repository
|
|
3373
|
+
* - Your role will be changed to admin (or specified role)
|
|
3374
|
+
* - You cannot transfer ownership back without the new owner's approval
|
|
3375
|
+
*
|
|
3376
|
+
* **Requirements**:
|
|
3377
|
+
* - You must be the current owner
|
|
3378
|
+
* - The new owner must have an existing account
|
|
3379
|
+
* - The new owner will be notified of the ownership transfer
|
|
3380
|
+
*
|
|
3381
|
+
* @example
|
|
3382
|
+
* ```typescript
|
|
3383
|
+
* // Transfer ownership to another user
|
|
3384
|
+
* await repo.collaborators.transferOwnership({
|
|
3385
|
+
* newOwnerDid: "did:plc:new-owner",
|
|
3386
|
+
* });
|
|
3387
|
+
*
|
|
3388
|
+
* console.log("Ownership transferred successfully");
|
|
3389
|
+
* // You are now an admin, not the owner
|
|
3390
|
+
* ```
|
|
3391
|
+
*
|
|
3392
|
+
* @example With confirmation
|
|
3393
|
+
* ```typescript
|
|
3394
|
+
* const confirmTransfer = await askUser(
|
|
3395
|
+
* "Are you sure you want to transfer ownership? This cannot be undone."
|
|
3396
|
+
* );
|
|
3397
|
+
*
|
|
3398
|
+
* if (confirmTransfer) {
|
|
3399
|
+
* await repo.collaborators.transferOwnership({
|
|
3400
|
+
* newOwnerDid: "did:plc:new-owner",
|
|
3401
|
+
* });
|
|
3402
|
+
* }
|
|
3403
|
+
* ```
|
|
3404
|
+
*/
|
|
3405
|
+
async transferOwnership(params) {
|
|
3406
|
+
const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.repo.transferOwnership`, {
|
|
3407
|
+
method: "POST",
|
|
3408
|
+
headers: { "Content-Type": "application/json" },
|
|
3409
|
+
body: JSON.stringify({
|
|
3410
|
+
repo: this.repoDid,
|
|
3411
|
+
newOwner: params.newOwnerDid,
|
|
3412
|
+
}),
|
|
3413
|
+
});
|
|
3414
|
+
if (!response.ok) {
|
|
3415
|
+
throw new NetworkError(`Failed to transfer ownership: ${response.statusText}`);
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3280
3418
|
}
|
|
3281
3419
|
|
|
3282
3420
|
/**
|
|
@@ -3303,8 +3441,8 @@ class CollaboratorOperationsImpl {
|
|
|
3303
3441
|
* {@link Repository.organizations} on an SDS-connected repository.
|
|
3304
3442
|
*
|
|
3305
3443
|
* **SDS API Endpoints Used**:
|
|
3306
|
-
* - `com.
|
|
3307
|
-
* - `com.
|
|
3444
|
+
* - `com.sds.organization.create`: Create a new organization
|
|
3445
|
+
* - `com.sds.organization.list`: List accessible organizations
|
|
3308
3446
|
*
|
|
3309
3447
|
* **Access Types**:
|
|
3310
3448
|
* - `"owner"`: User created or owns the organization
|
|
@@ -3382,10 +3520,17 @@ class OrganizationOperationsImpl {
|
|
|
3382
3520
|
* ```
|
|
3383
3521
|
*/
|
|
3384
3522
|
async create(params) {
|
|
3385
|
-
const
|
|
3523
|
+
const userDid = this.session.did || this.session.sub;
|
|
3524
|
+
if (!userDid) {
|
|
3525
|
+
throw new NetworkError("No authenticated user found");
|
|
3526
|
+
}
|
|
3527
|
+
const response = await this.session.fetchHandler(`${this.serverUrl}/xrpc/com.sds.organization.create`, {
|
|
3386
3528
|
method: "POST",
|
|
3387
3529
|
headers: { "Content-Type": "application/json" },
|
|
3388
|
-
body: JSON.stringify(
|
|
3530
|
+
body: JSON.stringify({
|
|
3531
|
+
...params,
|
|
3532
|
+
creatorDid: userDid,
|
|
3533
|
+
}),
|
|
3389
3534
|
});
|
|
3390
3535
|
if (!response.ok) {
|
|
3391
3536
|
throw new NetworkError(`Failed to create organization: ${response.statusText}`);
|
|
@@ -3397,8 +3542,15 @@ class OrganizationOperationsImpl {
|
|
|
3397
3542
|
name: data.name,
|
|
3398
3543
|
description: data.description,
|
|
3399
3544
|
createdAt: data.createdAt || new Date().toISOString(),
|
|
3400
|
-
accessType: "owner",
|
|
3401
|
-
permissions:
|
|
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
|
+
},
|
|
3402
3554
|
};
|
|
3403
3555
|
}
|
|
3404
3556
|
/**
|
|
@@ -3425,8 +3577,8 @@ class OrganizationOperationsImpl {
|
|
|
3425
3577
|
*/
|
|
3426
3578
|
async get(did) {
|
|
3427
3579
|
try {
|
|
3428
|
-
const
|
|
3429
|
-
return
|
|
3580
|
+
const { organizations } = await this.list();
|
|
3581
|
+
return organizations.find((o) => o.did === did) ?? null;
|
|
3430
3582
|
}
|
|
3431
3583
|
catch {
|
|
3432
3584
|
return null;
|
|
@@ -3435,7 +3587,10 @@ class OrganizationOperationsImpl {
|
|
|
3435
3587
|
/**
|
|
3436
3588
|
* Lists organizations the current user has access to.
|
|
3437
3589
|
*
|
|
3438
|
-
* @
|
|
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
|
|
3439
3594
|
* @throws {@link NetworkError} if the list operation fails
|
|
3440
3595
|
*
|
|
3441
3596
|
* @remarks
|
|
@@ -3447,21 +3602,25 @@ class OrganizationOperationsImpl {
|
|
|
3447
3602
|
*
|
|
3448
3603
|
* @example
|
|
3449
3604
|
* ```typescript
|
|
3450
|
-
*
|
|
3605
|
+
* // Get first page
|
|
3606
|
+
* const page1 = await repo.organizations.list({ limit: 20 });
|
|
3607
|
+
* console.log(`Found ${page1.organizations.length} organizations`);
|
|
3451
3608
|
*
|
|
3452
|
-
* //
|
|
3453
|
-
*
|
|
3454
|
-
*
|
|
3609
|
+
* // Get next page if available
|
|
3610
|
+
* if (page1.cursor) {
|
|
3611
|
+
* const page2 = await repo.organizations.list({ limit: 20, cursor: page1.cursor });
|
|
3612
|
+
* }
|
|
3455
3613
|
*
|
|
3456
|
-
*
|
|
3457
|
-
*
|
|
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");
|
|
3458
3617
|
* ```
|
|
3459
3618
|
*
|
|
3460
3619
|
* @example Display organization details
|
|
3461
3620
|
* ```typescript
|
|
3462
|
-
* const
|
|
3621
|
+
* const { organizations } = await repo.organizations.list();
|
|
3463
3622
|
*
|
|
3464
|
-
* for (const org of
|
|
3623
|
+
* for (const org of organizations) {
|
|
3465
3624
|
* console.log(`${org.name} (@${org.handle})`);
|
|
3466
3625
|
* console.log(` DID: ${org.did}`);
|
|
3467
3626
|
* console.log(` Access: ${org.accessType}`);
|
|
@@ -3471,21 +3630,38 @@ class OrganizationOperationsImpl {
|
|
|
3471
3630
|
* }
|
|
3472
3631
|
* ```
|
|
3473
3632
|
*/
|
|
3474
|
-
async list() {
|
|
3475
|
-
const
|
|
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" });
|
|
3476
3648
|
if (!response.ok) {
|
|
3477
3649
|
throw new NetworkError(`Failed to list organizations: ${response.statusText}`);
|
|
3478
3650
|
}
|
|
3479
3651
|
const data = await response.json();
|
|
3480
|
-
|
|
3652
|
+
const organizations = (data.organizations || []).map((r) => ({
|
|
3481
3653
|
did: r.did,
|
|
3482
3654
|
handle: r.handle,
|
|
3483
3655
|
name: r.name,
|
|
3484
3656
|
description: r.description,
|
|
3485
|
-
createdAt: new Date().toISOString(),
|
|
3657
|
+
createdAt: r.createdAt || new Date().toISOString(),
|
|
3486
3658
|
accessType: r.accessType,
|
|
3487
3659
|
permissions: r.permissions,
|
|
3488
3660
|
}));
|
|
3661
|
+
return {
|
|
3662
|
+
organizations,
|
|
3663
|
+
cursor: data.cursor,
|
|
3664
|
+
};
|
|
3489
3665
|
}
|
|
3490
3666
|
}
|
|
3491
3667
|
|
|
@@ -4408,9 +4584,10 @@ const OrganizationSchema = zod.z.object({
|
|
|
4408
4584
|
/**
|
|
4409
4585
|
* How the current user relates to this organization.
|
|
4410
4586
|
* - `"owner"`: User created or owns the organization
|
|
4411
|
-
* - `"
|
|
4587
|
+
* - `"shared"`: User was invited to collaborate (has permissions)
|
|
4588
|
+
* - `"none"`: User has no access to this organization
|
|
4412
4589
|
*/
|
|
4413
|
-
accessType: zod.z.enum(["owner", "
|
|
4590
|
+
accessType: zod.z.enum(["owner", "shared", "none"]),
|
|
4414
4591
|
});
|
|
4415
4592
|
/**
|
|
4416
4593
|
* Zod schema for collaborator data.
|