@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.
@@ -28,7 +28,7 @@ describe("CollaboratorOperationsImpl", () => {
28
28
  await collaboratorOps.grant({ userDid: "did:plc:newuser", role: "viewer" });
29
29
 
30
30
  expect(mockSession.fetchHandler).toHaveBeenCalledWith(
31
- `${serverUrl}/xrpc/com.atproto.sds.grantAccess`,
31
+ `${serverUrl}/xrpc/com.sds.repo.grantAccess`,
32
32
  expect.objectContaining({
33
33
  method: "POST",
34
34
  body: expect.stringContaining('"read":true'),
@@ -88,9 +88,7 @@ describe("CollaboratorOperationsImpl", () => {
88
88
  statusText: "Forbidden",
89
89
  });
90
90
 
91
- await expect(
92
- collaboratorOps.grant({ userDid: "did:plc:newuser", role: "viewer" }),
93
- ).rejects.toThrow(NetworkError);
91
+ await expect(collaboratorOps.grant({ userDid: "did:plc:newuser", role: "viewer" })).rejects.toThrow(NetworkError);
94
92
  });
95
93
  });
96
94
 
@@ -104,7 +102,7 @@ describe("CollaboratorOperationsImpl", () => {
104
102
  await collaboratorOps.revoke({ userDid: "did:plc:revokeduser" });
105
103
 
106
104
  expect(mockSession.fetchHandler).toHaveBeenCalledWith(
107
- `${serverUrl}/xrpc/com.atproto.sds.revokeAccess`,
105
+ `${serverUrl}/xrpc/com.sds.repo.revokeAccess`,
108
106
  expect.objectContaining({
109
107
  method: "POST",
110
108
  }),
@@ -121,9 +119,7 @@ describe("CollaboratorOperationsImpl", () => {
121
119
  statusText: "Not Found",
122
120
  });
123
121
 
124
- await expect(
125
- collaboratorOps.revoke({ userDid: "did:plc:user" }),
126
- ).rejects.toThrow(NetworkError);
122
+ await expect(collaboratorOps.revoke({ userDid: "did:plc:user" })).rejects.toThrow(NetworkError);
127
123
  });
128
124
  });
129
125
 
@@ -135,13 +131,13 @@ describe("CollaboratorOperationsImpl", () => {
135
131
  collaborators: [
136
132
  {
137
133
  userDid: "did:plc:user1",
138
- permissions: { read: true, create: true, update: true, delete: false, admin: false, owner: false },
134
+ permissions: ["read", "create", "update"],
139
135
  grantedBy: "did:plc:owner",
140
136
  grantedAt: "2024-01-01T00:00:00Z",
141
137
  },
142
138
  {
143
139
  userDid: "did:plc:user2",
144
- permissions: { read: true, create: false, update: false, delete: false, admin: false, owner: false },
140
+ permissions: ["read"],
145
141
  grantedBy: "did:plc:owner",
146
142
  grantedAt: "2024-01-02T00:00:00Z",
147
143
  },
@@ -151,10 +147,10 @@ describe("CollaboratorOperationsImpl", () => {
151
147
 
152
148
  const result = await collaboratorOps.list();
153
149
 
154
- expect(result).toHaveLength(2);
155
- expect(result[0].userDid).toBe("did:plc:user1");
156
- expect(result[0].role).toBe("editor");
157
- expect(result[1].role).toBe("viewer");
150
+ expect(result.collaborators).toHaveLength(2);
151
+ expect(result.collaborators[0].userDid).toBe("did:plc:user1");
152
+ expect(result.collaborators[0].role).toBe("editor");
153
+ expect(result.collaborators[1].role).toBe("viewer");
158
154
  });
159
155
 
160
156
  it("should handle empty collaborators list", async () => {
@@ -165,7 +161,7 @@ describe("CollaboratorOperationsImpl", () => {
165
161
 
166
162
  const result = await collaboratorOps.list();
167
163
 
168
- expect(result).toHaveLength(0);
164
+ expect(result.collaborators).toHaveLength(0);
169
165
  });
170
166
 
171
167
  it("should correctly map permissions to roles", async () => {
@@ -175,13 +171,13 @@ describe("CollaboratorOperationsImpl", () => {
175
171
  collaborators: [
176
172
  {
177
173
  userDid: "did:plc:owner",
178
- permissions: { read: true, create: true, update: true, delete: true, admin: true, owner: true },
174
+ permissions: ["read", "create", "update", "delete", "admin", "owner"],
179
175
  grantedBy: "did:plc:system",
180
176
  grantedAt: "2024-01-01T00:00:00Z",
181
177
  },
182
178
  {
183
179
  userDid: "did:plc:admin",
184
- permissions: { read: true, create: true, update: true, delete: true, admin: true, owner: false },
180
+ permissions: ["read", "create", "update", "delete", "admin"],
185
181
  grantedBy: "did:plc:owner",
186
182
  grantedAt: "2024-01-01T00:00:00Z",
187
183
  },
@@ -191,8 +187,8 @@ describe("CollaboratorOperationsImpl", () => {
191
187
 
192
188
  const result = await collaboratorOps.list();
193
189
 
194
- expect(result[0].role).toBe("owner");
195
- expect(result[1].role).toBe("admin");
190
+ expect(result.collaborators[0].role).toBe("owner");
191
+ expect(result.collaborators[1].role).toBe("admin");
196
192
  });
197
193
 
198
194
  it("should throw NetworkError on failure", async () => {
@@ -213,7 +209,7 @@ describe("CollaboratorOperationsImpl", () => {
213
209
  collaborators: [
214
210
  {
215
211
  userDid: "did:plc:activeuser",
216
- permissions: { read: true, create: false, update: false, delete: false, admin: false, owner: false },
212
+ permissions: ["read"],
217
213
  grantedBy: "did:plc:owner",
218
214
  grantedAt: "2024-01-01T00:00:00Z",
219
215
  },
@@ -244,7 +240,7 @@ describe("CollaboratorOperationsImpl", () => {
244
240
  collaborators: [
245
241
  {
246
242
  userDid: "did:plc:revokeduser",
247
- permissions: { read: true, create: false, update: false, delete: false, admin: false, owner: false },
243
+ permissions: ["read"],
248
244
  grantedBy: "did:plc:owner",
249
245
  grantedAt: "2024-01-01T00:00:00Z",
250
246
  revokedAt: "2024-02-01T00:00:00Z",
@@ -275,7 +271,7 @@ describe("CollaboratorOperationsImpl", () => {
275
271
  collaborators: [
276
272
  {
277
273
  userDid: "did:plc:editor",
278
- permissions: { read: true, create: true, update: true, delete: false, admin: false, owner: false },
274
+ permissions: ["read", "create", "update"],
279
275
  grantedBy: "did:plc:owner",
280
276
  grantedAt: "2024-01-01T00:00:00Z",
281
277
  },
@@ -306,7 +302,7 @@ describe("CollaboratorOperationsImpl", () => {
306
302
  collaborators: [
307
303
  {
308
304
  userDid: "did:plc:revoked",
309
- permissions: { read: true, create: true, update: true, delete: false, admin: false, owner: false },
305
+ permissions: ["read", "create", "update"],
310
306
  grantedBy: "did:plc:owner",
311
307
  grantedAt: "2024-01-01T00:00:00Z",
312
308
  revokedAt: "2024-02-01T00:00:00Z",
@@ -320,4 +316,123 @@ describe("CollaboratorOperationsImpl", () => {
320
316
  expect(result).toBeNull();
321
317
  });
322
318
  });
319
+
320
+ describe("getPermissions", () => {
321
+ it("should get current user permissions successfully", async () => {
322
+ mockSession.fetchHandler.mockResolvedValue({
323
+ ok: true,
324
+ json: async () => ({
325
+ permissions: {
326
+ read: true,
327
+ create: true,
328
+ update: true,
329
+ delete: false,
330
+ admin: false,
331
+ owner: false,
332
+ },
333
+ }),
334
+ });
335
+
336
+ const result = await collaboratorOps.getPermissions();
337
+
338
+ expect(mockSession.fetchHandler).toHaveBeenCalledWith(
339
+ `${serverUrl}/xrpc/com.sds.repo.getPermissions?repo=${encodeURIComponent(repoDid)}`,
340
+ expect.objectContaining({
341
+ method: "GET",
342
+ }),
343
+ );
344
+
345
+ expect(result.read).toBe(true);
346
+ expect(result.create).toBe(true);
347
+ expect(result.update).toBe(true);
348
+ expect(result.delete).toBe(false);
349
+ expect(result.admin).toBe(false);
350
+ expect(result.owner).toBe(false);
351
+ });
352
+
353
+ it("should handle owner permissions", async () => {
354
+ mockSession.fetchHandler.mockResolvedValue({
355
+ ok: true,
356
+ json: async () => ({
357
+ permissions: {
358
+ read: true,
359
+ create: true,
360
+ update: true,
361
+ delete: true,
362
+ admin: true,
363
+ owner: true,
364
+ },
365
+ }),
366
+ });
367
+
368
+ const result = await collaboratorOps.getPermissions();
369
+
370
+ expect(result.owner).toBe(true);
371
+ expect(result.admin).toBe(true);
372
+ });
373
+
374
+ it("should throw NetworkError on failure", async () => {
375
+ mockSession.fetchHandler.mockResolvedValue({
376
+ ok: false,
377
+ statusText: "Forbidden",
378
+ });
379
+
380
+ await expect(collaboratorOps.getPermissions()).rejects.toThrow(NetworkError);
381
+ });
382
+ });
383
+
384
+ describe("transferOwnership", () => {
385
+ it("should transfer ownership successfully", async () => {
386
+ mockSession.fetchHandler.mockResolvedValue({
387
+ ok: true,
388
+ json: async () => ({}),
389
+ });
390
+
391
+ await collaboratorOps.transferOwnership({ newOwnerDid: "did:plc:new-owner" });
392
+
393
+ expect(mockSession.fetchHandler).toHaveBeenCalledWith(
394
+ `${serverUrl}/xrpc/com.sds.repo.transferOwnership`,
395
+ expect.objectContaining({
396
+ method: "POST",
397
+ }),
398
+ );
399
+
400
+ const body = JSON.parse(mockSession.fetchHandler.mock.calls[0][1].body);
401
+ expect(body.repo).toBe(repoDid);
402
+ expect(body.newOwner).toBe("did:plc:new-owner");
403
+ });
404
+
405
+ it("should throw NetworkError on failure", async () => {
406
+ mockSession.fetchHandler.mockResolvedValue({
407
+ ok: false,
408
+ statusText: "Forbidden",
409
+ });
410
+
411
+ await expect(collaboratorOps.transferOwnership({ newOwnerDid: "did:plc:new-owner" })).rejects.toThrow(
412
+ NetworkError,
413
+ );
414
+ });
415
+
416
+ it("should throw NetworkError when not owner", async () => {
417
+ mockSession.fetchHandler.mockResolvedValue({
418
+ ok: false,
419
+ statusText: "Forbidden: Only the owner can transfer ownership",
420
+ });
421
+
422
+ await expect(collaboratorOps.transferOwnership({ newOwnerDid: "did:plc:new-owner" })).rejects.toThrow(
423
+ NetworkError,
424
+ );
425
+ });
426
+
427
+ it("should throw NetworkError when new owner does not exist", async () => {
428
+ mockSession.fetchHandler.mockResolvedValue({
429
+ ok: false,
430
+ statusText: "Not Found: New owner DID not found",
431
+ });
432
+
433
+ await expect(collaboratorOps.transferOwnership({ newOwnerDid: "did:plc:nonexistent" })).rejects.toThrow(
434
+ NetworkError,
435
+ );
436
+ });
437
+ });
323
438
  });
@@ -44,7 +44,7 @@ describe("OrganizationOperationsImpl", () => {
44
44
  expect(result.permissions.owner).toBe(true);
45
45
 
46
46
  expect(mockSession.fetchHandler).toHaveBeenCalledWith(
47
- `${serverUrl}/xrpc/com.atproto.sds.createRepository`,
47
+ `${serverUrl}/xrpc/com.sds.organization.create`,
48
48
  expect.objectContaining({
49
49
  method: "POST",
50
50
  headers: { "Content-Type": "application/json" },
@@ -74,9 +74,7 @@ describe("OrganizationOperationsImpl", () => {
74
74
  statusText: "Conflict",
75
75
  });
76
76
 
77
- await expect(
78
- orgOps.create({ name: "Test Org" }),
79
- ).rejects.toThrow(NetworkError);
77
+ await expect(orgOps.create({ name: "Test Org" })).rejects.toThrow(NetworkError);
80
78
  });
81
79
  });
82
80
 
@@ -85,7 +83,7 @@ describe("OrganizationOperationsImpl", () => {
85
83
  mockSession.fetchHandler.mockResolvedValue({
86
84
  ok: true,
87
85
  json: async () => ({
88
- repositories: [
86
+ organizations: [
89
87
  {
90
88
  did: "did:plc:org1",
91
89
  handle: "org1.example.com",
@@ -98,7 +96,7 @@ describe("OrganizationOperationsImpl", () => {
98
96
  did: "did:plc:org2",
99
97
  handle: "org2.example.com",
100
98
  name: "Organization 2",
101
- accessType: "collaborator",
99
+ accessType: "shared",
102
100
  permissions: { read: true, create: true, update: true, delete: false, admin: false, owner: false },
103
101
  },
104
102
  ],
@@ -116,7 +114,7 @@ describe("OrganizationOperationsImpl", () => {
116
114
  mockSession.fetchHandler.mockResolvedValue({
117
115
  ok: true,
118
116
  json: async () => ({
119
- repositories: [],
117
+ organizations: [],
120
118
  }),
121
119
  });
122
120
 
@@ -139,7 +137,7 @@ describe("OrganizationOperationsImpl", () => {
139
137
  mockSession.fetchHandler.mockResolvedValue({
140
138
  ok: true,
141
139
  json: async () => ({
142
- repositories: [
140
+ organizations: [
143
141
  {
144
142
  did: "did:plc:org1",
145
143
  handle: "org1.example.com",
@@ -152,7 +150,7 @@ describe("OrganizationOperationsImpl", () => {
152
150
  handle: "org2.example.com",
153
151
  name: "Organization 2",
154
152
  description: "Second org",
155
- accessType: "collaborator",
153
+ accessType: "shared",
156
154
  permissions: { read: true, create: true, update: false, delete: false, admin: false, owner: false },
157
155
  },
158
156
  ],
@@ -161,28 +159,28 @@ describe("OrganizationOperationsImpl", () => {
161
159
 
162
160
  const result = await orgOps.list();
163
161
 
164
- expect(result).toHaveLength(2);
165
- expect(result[0].did).toBe("did:plc:org1");
166
- expect(result[0].accessType).toBe("owner");
167
- expect(result[1].did).toBe("did:plc:org2");
168
- expect(result[1].accessType).toBe("collaborator");
162
+ expect(result.organizations).toHaveLength(2);
163
+ expect(result.organizations[0].did).toBe("did:plc:org1");
164
+ expect(result.organizations[0].accessType).toBe("owner");
165
+ expect(result.organizations[1].did).toBe("did:plc:org2");
166
+ expect(result.organizations[1].accessType).toBe("shared");
169
167
  });
170
168
 
171
169
  it("should handle empty repositories list", async () => {
172
170
  mockSession.fetchHandler.mockResolvedValue({
173
171
  ok: true,
174
- json: async () => ({ repositories: [] }),
172
+ json: async () => ({ organizations: [] }),
175
173
  });
176
174
 
177
175
  const result = await orgOps.list();
178
176
 
179
- expect(result).toHaveLength(0);
177
+ expect(result.organizations).toHaveLength(0);
180
178
  });
181
179
 
182
180
  it("should use session DID in query", async () => {
183
181
  mockSession.fetchHandler.mockResolvedValue({
184
182
  ok: true,
185
- json: async () => ({ repositories: [] }),
183
+ json: async () => ({ organizations: [] }),
186
184
  });
187
185
 
188
186
  await orgOps.list();
@@ -197,7 +195,7 @@ describe("OrganizationOperationsImpl", () => {
197
195
  mockSession.did = undefined;
198
196
  mockSession.fetchHandler.mockResolvedValue({
199
197
  ok: true,
200
- json: async () => ({ repositories: [] }),
198
+ json: async () => ({ organizations: [] }),
201
199
  });
202
200
 
203
201
  await orgOps.list();
@@ -221,7 +219,7 @@ describe("OrganizationOperationsImpl", () => {
221
219
  mockSession.fetchHandler.mockResolvedValue({
222
220
  ok: true,
223
221
  json: async () => ({
224
- repositories: [
222
+ organizations: [
225
223
  {
226
224
  did: "did:plc:org",
227
225
  handle: "org.example.com",
@@ -236,7 +234,7 @@ describe("OrganizationOperationsImpl", () => {
236
234
 
237
235
  const result = await orgOps.list();
238
236
 
239
- expect(result[0].createdAt).toBeDefined();
237
+ expect(result.organizations[0].createdAt).toBeDefined();
240
238
  });
241
239
  });
242
240
  });