@learncard/learn-cloud-plugin 2.3.36 → 2.3.37

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.
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAc5C,OAAO,EAAE,gCAAgC,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAS7E,cAAc,SAAS,CAAC;AAqCxB;;GAEG;AACH,eAAO,MAAM,mBAAmB,qBACV,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,gCAAgC,CAAC,OACnE,MAAM,sBACQ,MAAM,EAAE,4BACF,MAAM,EAAE,2CAElC,OAAO,CAAC,gBAAgB,CA+nB1B,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAc5C,OAAO,EAAE,gCAAgC,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAS7E,cAAc,SAAS,CAAC;AAqCxB;;GAEG;AACH,eAAO,MAAM,mBAAmB,qBACV,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,gCAAgC,CAAC,OACnE,MAAM,sBACQ,MAAM,EAAE,4BACF,MAAM,EAAE,2CAElC,OAAO,CAAC,gBAAgB,CAwoB1B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learncard/learn-cloud-plugin",
3
- "version": "2.3.36",
3
+ "version": "2.3.37",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -24,9 +24,9 @@
24
24
  ],
25
25
  "scripts": {
26
26
  "build": "node ./scripts/build.mjs && shx cp ./scripts/mixedEntypoint.js ./dist/index.cjs && tsc --p tsconfig.json && shx cp ./dist/index.d.ts ./dist/index.d.cts",
27
- "test": "jest --passWithNoTests",
28
- "test:watch": "jest --watch",
29
- "test:coverage": "jest --silent --ci --coverage --coverageReporters=\"text\" --coverageReporters=\"text-summary\""
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "test:coverage": "vitest run --coverage"
30
30
  },
31
31
  "author": "Learning Economy Foundation (www.learningeconomy.io)",
32
32
  "license": "MIT",
@@ -39,25 +39,21 @@
39
39
  "url": "https://github.com/learningeconomy/LearnCard/issues"
40
40
  },
41
41
  "devDependencies": {
42
- "@learncard/learn-cloud-service": "^2.5.28",
43
- "@learncard/types": "5.18.1",
44
- "@types/jest": "^29.2.2",
42
+ "@learncard/learn-cloud-service": "^2.5.29",
43
+ "@learncard/types": "5.18.2",
45
44
  "@types/lodash": "^4.14.191",
46
45
  "@types/node": "^17.0.31",
47
46
  "aqu": "0.4.3",
48
47
  "esbuild": "^0.27.1",
49
- "esbuild-jest": "^0.5.0",
50
48
  "esbuild-plugin-copy": "^1.3.0",
51
- "jest": "^29.3.0",
52
- "shx": "^0.3.4",
53
- "ts-jest": "^29.0.3"
49
+ "shx": "^0.3.4"
54
50
  },
55
51
  "types": "./dist/index.d.ts",
56
52
  "dependencies": {
57
- "@learncard/core": "9.4.30",
58
- "@learncard/didkit-plugin": "1.9.10",
59
- "@learncard/helpers": "^1.3.12",
60
- "@learncard/learn-cloud-client": "1.6.36",
53
+ "@learncard/core": "9.4.31",
54
+ "@learncard/didkit-plugin": "1.9.11",
55
+ "@learncard/helpers": "^1.3.13",
56
+ "@learncard/learn-cloud-client": "1.6.37",
61
57
  "json-stringify-deterministic": "^1.0.8",
62
58
  "lodash": "^4.17.21",
63
59
  "pbkdf2-hmac": "^1.2.1"
package/src/plugin.ts CHANGED
@@ -78,11 +78,15 @@ export const getLearnCloudPlugin = async (
78
78
 
79
79
  let dids: string[] = [learnCard.id.did()];
80
80
 
81
- client.user.getDids.query().then(result => (dids = result));
81
+ void client.user.getDids
82
+ .query()
83
+ .then(result => (dids = result))
84
+ .catch(error => learnCard.debug?.('Unable to preload LearnCloud DIDs', error));
82
85
 
83
86
  let otherClients: Record<string, LearnCloudClient> = {};
84
87
 
85
- const learnCloudDid = client.utilities.getDid.query();
88
+ let learnCloudDid: ReturnType<typeof client.utilities.getDid.query> | undefined;
89
+ const getLearnCloudDid = () => (learnCloudDid ??= client.utilities.getDid.query());
86
90
 
87
91
  const getOtherClient = async (url: string) => {
88
92
  if (!otherClients[url]) otherClients[url] = await getLearnCloudClient(url, learnCard);
@@ -110,6 +114,7 @@ export const getLearnCloudPlugin = async (
110
114
  }
111
115
 
112
116
  client = await getLearnCloudClient(url, _learnCard);
117
+ learnCloudDid = undefined;
113
118
  }
114
119
 
115
120
  learnCard = _learnCard;
@@ -130,7 +135,7 @@ export const getLearnCloudPlugin = async (
130
135
  );
131
136
 
132
137
  return client.customStorage.create.mutate({
133
- item: await generateJWE(_learnCard, await learnCloudDid, item),
138
+ item: await generateJWE(_learnCard, await getLearnCloudDid(), item),
134
139
  });
135
140
  },
136
141
  learnCloudCreateMany: async (_learnCard, documents) => {
@@ -143,7 +148,7 @@ export const getLearnCloudPlugin = async (
143
148
  );
144
149
 
145
150
  return client.customStorage.createMany.mutate({
146
- items: await generateJWE(_learnCard, await learnCloudDid, items),
151
+ items: await generateJWE(_learnCard, await getLearnCloudDid(), items),
147
152
  });
148
153
  },
149
154
  learnCloudRead: async (_learnCard, query, includeAssociatedDids) => {
@@ -215,7 +220,7 @@ export const getLearnCloudPlugin = async (
215
220
  );
216
221
 
217
222
  const jwe: JWE = (await client.customStorage.read.query({
218
- query: await generateJWE(_learnCard, await learnCloudDid, {
223
+ query: await generateJWE(_learnCard, await getLearnCloudDid(), {
219
224
  ...unencryptedEntries,
220
225
  ...(fields.length > 0 ? { fields: { $in: fields } } : {}),
221
226
  }),
@@ -257,7 +262,7 @@ export const getLearnCloudPlugin = async (
257
262
  );
258
263
 
259
264
  return client.customStorage.count.query({
260
- query: await generateJWE(_learnCard, await learnCloudDid, {
265
+ query: await generateJWE(_learnCard, await getLearnCloudDid(), {
261
266
  ...unencryptedEntries,
262
267
  ...(fields.length > 0 ? { fields: { $in: fields } } : {}),
263
268
  }),
@@ -272,12 +277,12 @@ export const getLearnCloudPlugin = async (
272
277
  const updates = await Promise.all(
273
278
  documents.map(async document =>
274
279
  client.customStorage.update.mutate({
275
- query: await generateJWE(_learnCard, await learnCloudDid, {
280
+ query: await generateJWE(_learnCard, await getLearnCloudDid(), {
276
281
  _id: document._id,
277
282
  }),
278
283
  update: await generateJWE(
279
284
  _learnCard,
280
- await learnCloudDid,
285
+ await getLearnCloudDid(),
281
286
  await generateEncryptedRecord(
282
287
  _learnCard,
283
288
  { ...document, ...update },
@@ -307,7 +312,7 @@ export const getLearnCloudPlugin = async (
307
312
  );
308
313
 
309
314
  return client.customStorage.delete.mutate({
310
- query: await generateJWE(_learnCard, await learnCloudDid, {
315
+ query: await generateJWE(_learnCard, await getLearnCloudDid(), {
311
316
  ...unencryptedEntries,
312
317
  ...(fields.length > 0 ? { fields: { $in: fields } } : {}),
313
318
  }),
@@ -551,7 +556,7 @@ export const getLearnCloudPlugin = async (
551
556
  );
552
557
 
553
558
  const jwe: JWE = (await client.index.get.query({
554
- query: await generateJWE(_learnCard, await learnCloudDid, {
559
+ query: await generateJWE(_learnCard, await getLearnCloudDid(), {
555
560
  ...unencryptedEntries,
556
561
  ...(fields.length > 0 ? { fields: { $in: fields } } : {}),
557
562
  }),
@@ -616,7 +621,7 @@ export const getLearnCloudPlugin = async (
616
621
  );
617
622
 
618
623
  const jwe = await client.index.count.query({
619
- query: await generateJWE(_learnCard, await learnCloudDid, {
624
+ query: await generateJWE(_learnCard, await getLearnCloudDid(), {
620
625
  ...unencryptedEntries,
621
626
  ...(fields.length > 0 ? { fields: { $in: fields } } : {}),
622
627
  }),
@@ -638,7 +643,7 @@ export const getLearnCloudPlugin = async (
638
643
  const id = record.id || _learnCard.invoke.crypto().randomUUID();
639
644
 
640
645
  return client.index.add.mutate({
641
- record: await generateJWE(_learnCard, await learnCloudDid, {
646
+ record: await generateJWE(_learnCard, await getLearnCloudDid(), {
642
647
  ...(await generateEncryptedRecord(
643
648
  _learnCard,
644
649
  { ...record, id },
@@ -669,7 +674,11 @@ export const getLearnCloudPlugin = async (
669
674
  );
670
675
 
671
676
  return client.index.addMany.mutate({
672
- records: await generateJWE(_learnCard, await learnCloudDid, records),
677
+ records: await generateJWE(
678
+ _learnCard,
679
+ await getLearnCloudDid(),
680
+ records
681
+ ),
673
682
  });
674
683
  })
675
684
  );
@@ -691,7 +700,7 @@ export const getLearnCloudPlugin = async (
691
700
  id: await hash(_learnCard, id),
692
701
  updates: await generateJWE(
693
702
  _learnCard,
694
- await learnCloudDid,
703
+ await getLearnCloudDid(),
695
704
  await generateEncryptedRecord(_learnCard, newRecord, unencryptedFields)
696
705
  ),
697
706
  });
@@ -1,18 +1,24 @@
1
- const mockGetClient = jest.fn();
1
+ import { vi } from 'vitest';
2
+ const mockGetClient = vi.fn();
2
3
 
3
- const mockClient = {
4
+ const makeMockClient = (learnCloudDid = 'did:key:z6MkLearnCloud') => ({
4
5
  user: {
5
- getDids: { query: jest.fn().mockResolvedValue([]) },
6
+ getDids: { query: vi.fn().mockResolvedValue([]) },
6
7
  },
7
8
  utilities: {
8
- getDid: { query: jest.fn().mockResolvedValue('did:key:z6MkLearnCloud') },
9
+ getDid: { query: vi.fn().mockResolvedValue(learnCloudDid) },
10
+ },
11
+ customStorage: {
12
+ create: { mutate: vi.fn().mockResolvedValue('lc:cloud:credential') },
9
13
  },
10
14
  storage: {
11
- batchResolve: { query: jest.fn() },
15
+ batchResolve: { query: vi.fn() },
12
16
  },
13
- };
17
+ });
18
+
19
+ const mockClient = makeMockClient();
14
20
 
15
- jest.mock('@learncard/learn-cloud-client', () => ({
21
+ vi.mock('@learncard/learn-cloud-client', () => ({
16
22
  getClient: (...args: unknown[]) => mockGetClient(...args),
17
23
  }));
18
24
 
@@ -32,20 +38,22 @@ const makeW3cVc = () => ({
32
38
  },
33
39
  });
34
40
 
35
- const makeLearnCard = () => ({
41
+ const makeLearnCard = (did = 'did:key:z6MkHolder') => ({
36
42
  id: {
37
- did: () => 'did:key:z6MkHolder',
43
+ did: () => did,
38
44
  },
39
45
  invoke: {
40
- getDidAuthVp: jest.fn().mockResolvedValue('did-auth-jwt'),
41
- decryptDagJwe: jest.fn(async value => value),
46
+ getDidAuthVp: vi.fn().mockResolvedValue('did-auth-jwt'),
47
+ decryptDagJwe: vi.fn(async value => value),
48
+ createDagJwe: vi.fn(async (value, recipients) => ({ value, recipients })),
49
+ hash: vi.fn().mockResolvedValue('hashed-field'),
42
50
  },
43
- debug: jest.fn(),
51
+ debug: vi.fn(),
44
52
  });
45
53
 
46
54
  describe('LearnCloud Plugin', () => {
47
55
  beforeEach(() => {
48
- jest.clearAllMocks();
56
+ vi.clearAllMocks();
49
57
  mockGetClient.mockResolvedValue(mockClient);
50
58
  });
51
59
 
@@ -53,6 +61,34 @@ describe('LearnCloud Plugin', () => {
53
61
  expect(getLearnCloudPlugin).toBeDefined();
54
62
  });
55
63
 
64
+ it('refreshes the LearnCloud DID after switching authenticated clients', async () => {
65
+ const initialClient = makeMockClient('did:web:cloud-one.example');
66
+ const switchedClient = makeMockClient('did:web:cloud-two.example');
67
+ mockGetClient.mockResolvedValueOnce(initialClient).mockResolvedValueOnce(switchedClient);
68
+
69
+ const initialLearnCard = makeLearnCard('did:key:holder-one');
70
+ const switchedLearnCard = makeLearnCard('did:key:holder-two');
71
+ const plugin = await getLearnCloudPlugin(
72
+ initialLearnCard as never,
73
+ 'https://cloud.example',
74
+ [],
75
+ [],
76
+ false
77
+ );
78
+
79
+ await plugin.methods.learnCloudCreate(initialLearnCard as never, { id: 'first' });
80
+ await plugin.methods.learnCloudCreate(switchedLearnCard as never, { id: 'second' });
81
+
82
+ expect(initialClient.utilities.getDid.query).toHaveBeenCalledTimes(1);
83
+ expect(switchedClient.utilities.getDid.query).toHaveBeenCalledTimes(1);
84
+ expect(initialLearnCard.invoke.createDagJwe).toHaveBeenLastCalledWith(expect.any(Object), [
85
+ 'did:web:cloud-one.example',
86
+ ]);
87
+ expect(switchedLearnCard.invoke.createDagJwe).toHaveBeenLastCalledWith(expect.any(Object), [
88
+ 'did:web:cloud-two.example',
89
+ ]);
90
+ });
91
+
56
92
  it('projects envelope-backed credentials in learnCloudBatchResolve', async () => {
57
93
  const compact =
58
94
  'eyJhbGciOiJFZERTQSIsInR5cCI6ImRjK3NkLWp3dCJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5leGFtcGxlIiwiaWF0IjoxNzAwMDAwMDAwLCJ2Y3QiOiJodHRwczovL2V4YW1wbGUuY29tL2NyZWRlbnRpYWxzL2VtcGxveW1lbnQiLCJuYW1lIjoiQWRhIn0.AAAA~';