@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
|
@@ -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.
|
|
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.
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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.
|
|
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
|
-
|
|
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: "
|
|
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
|
-
|
|
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
|
-
|
|
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: "
|
|
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("
|
|
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 () => ({
|
|
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 () => ({
|
|
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 () => ({
|
|
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
|
-
|
|
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
|
});
|