@fedify/fedify 1.8.0-dev.914 → 1.8.0-dev.923

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.
Files changed (66) hide show
  1. package/dist/{actor-D7ARCMq_.js → actor-D1UxEix1.js} +179 -179
  2. package/dist/{actor-DxfId8ty.js → actor-D46a80bG.js} +3 -3
  3. package/dist/{authdocloader-CpJhFRBr.js → authdocloader-Ci9mREen.js} +3 -3
  4. package/dist/{authdocloader-BsMSD7rr.js → authdocloader-Dp78K2jr.js} +3 -3
  5. package/dist/{builder-B4OL-_3v.js → builder-DAzNxi3p.js} +3 -3
  6. package/dist/{client-CTEC7ZT_.js → client-D3X-G5sq.js} +1 -1
  7. package/dist/compat/transformers.test.js +17 -17
  8. package/dist/{context-DAyMjlxQ.js → context-Bvz3lHyI.js} +2 -2
  9. package/dist/{docloader-C2fcD6HW.js → docloader-Dyxhtzc3.js} +3 -10
  10. package/dist/{docloader-uG1bSmTU.js → docloader-lorEk5iw.js} +3 -10
  11. package/dist/federation/builder.test.js +4 -4
  12. package/dist/federation/handler.test.js +19 -19
  13. package/dist/federation/inbox.test.js +3 -3
  14. package/dist/federation/keycache.test.js +3 -3
  15. package/dist/federation/middleware.test.js +633 -619
  16. package/dist/federation/mod.js +10 -10
  17. package/dist/federation/send.test.js +9 -9
  18. package/dist/{http-BI-X6nC8.js → http-DQ_uU1M-.js} +8 -22
  19. package/dist/{http-FxoGRmIR.js → http-DXVgUUnK.js} +8 -22
  20. package/dist/{inbox-DdI7kf97.js → inbox-BxUUuzd9.js} +2 -2
  21. package/dist/{key-CNe00doh.js → key-B5wjWwWe.js} +2 -2
  22. package/dist/{key-B8YFnSC4.js → key-BQBoG12c.js} +4 -4
  23. package/dist/{key-DYTMwpBh.js → key-CQBqJoVo.js} +3 -3
  24. package/dist/{key-C-DGQ7mt.js → key-DLV1AKQR.js} +5 -5
  25. package/dist/{keycache-BBHrPjap.js → keycache-B-TB9qYF.js} +1 -1
  26. package/dist/{keys-_jhKoT94.js → keys-CVjF1n8p.js} +1 -1
  27. package/dist/{ld-Bgq_lRr5.js → ld-CIsXjsgE.js} +3 -3
  28. package/dist/{lookup-CaHm-ZeC.js → lookup-BGSwlBs8.js} +1 -1
  29. package/dist/{lookup-DnXipkyR.js → lookup-Dc9JhQGJ.js} +3 -3
  30. package/dist/{lookup-DG0jZyXS.js → lookup-mQzAfFyO.js} +1 -1
  31. package/dist/{middleware-Cn6MSc_f.js → middleware-Bj7F-FBU.js} +15 -15
  32. package/dist/middleware-D0jawfyI.js +17 -0
  33. package/dist/middleware-DticzIra.js +33 -0
  34. package/dist/{middleware-CKzYUxOH.js → middleware-JYClfGI8.js} +10 -10
  35. package/dist/mod.js +10 -10
  36. package/dist/nodeinfo/client.test.js +2 -2
  37. package/dist/nodeinfo/handler.test.js +18 -18
  38. package/dist/nodeinfo/mod.js +2 -2
  39. package/dist/{owner-DQcsEjrE.js → owner-B3kfyNi5.js} +3 -3
  40. package/dist/{proof-Dy8YN_n9.js → proof-Be3dKvfi.js} +3 -3
  41. package/dist/{proof-LR5LYCDY.js → proof-TTTVErx5.js} +3 -3
  42. package/dist/runtime/authdocloader.test.js +8 -8
  43. package/dist/runtime/docloader.test.js +1 -1
  44. package/dist/runtime/key.test.js +5 -5
  45. package/dist/runtime/mod.js +6 -6
  46. package/dist/{send-CSg0l0Ds.js → send-BkUwe85v.js} +2 -2
  47. package/dist/sig/http.test.js +8 -36
  48. package/dist/sig/key.test.js +6 -6
  49. package/dist/sig/ld.test.js +7 -7
  50. package/dist/sig/mod.js +6 -6
  51. package/dist/sig/owner.test.js +8 -8
  52. package/dist/sig/proof.test.js +7 -7
  53. package/dist/{types-CnID0DVG.js → types-B_9t_Ife.js} +1 -1
  54. package/dist/vocab/actor.test.js +59 -52
  55. package/dist/vocab/lookup.test.js +4 -4
  56. package/dist/vocab/mod.js +4 -4
  57. package/dist/vocab/type.test.js +2 -2
  58. package/dist/vocab/vocab.test.js +78 -64
  59. package/dist/{vocab-BG-6n0jz.js → vocab-DIt8IOrb.js} +3 -3
  60. package/dist/{vocab-RyKwNui6.js → vocab-c48J0wxy.js} +178 -178
  61. package/dist/webfinger/handler.test.js +18 -18
  62. package/dist/webfinger/lookup.test.js +2 -2
  63. package/dist/webfinger/mod.js +2 -2
  64. package/package.json +5 -4
  65. package/dist/middleware-Bqb5qg_Q.js +0 -17
  66. package/dist/middleware-DXfuUsla.js +0 -33
@@ -7,32 +7,32 @@ import { assertEquals } from "../assert_equals-C5gKCm6A.js";
7
7
  import { assert } from "../assert-DwEa6glZ.js";
8
8
  import { assertInstanceOf } from "../assert_instance_of-C9QtN-X9.js";
9
9
  import { MemoryKvStore } from "../kv-D7Yt6pnB.js";
10
- import { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, createFederation } from "../middleware-Cn6MSc_f.js";
11
- import { FetchError, fetchDocumentLoader } from "../docloader-C2fcD6HW.js";
10
+ import { ContextImpl, FederationImpl, InboxContextImpl, KvSpecDeterminer, createFederation } from "../middleware-Bj7F-FBU.js";
11
+ import { FetchError, fetchDocumentLoader } from "../docloader-Dyxhtzc3.js";
12
12
  import "../url-kTAI6_KP.js";
13
13
  import "../semver-DWClQt_5.js";
14
- import "../client-CTEC7ZT_.js";
14
+ import "../client-D3X-G5sq.js";
15
15
  import { RouterError } from "../router-D3UybECj.js";
16
16
  import "../types-C7C_l-jz.js";
17
17
  import "../multibase-DeCHcK8L.js";
18
- import { Activity, Announce, Create, Invite, Multikey, Note, Object as Object$1, Offer, Person } from "../vocab-RyKwNui6.js";
18
+ import { Activity, Announce, Create, Invite, Multikey, Note, Object as Object$1, Offer, Person } from "../vocab-c48J0wxy.js";
19
19
  import "../langstr-DbWheeIS.js";
20
- import "../lookup-DG0jZyXS.js";
20
+ import "../lookup-mQzAfFyO.js";
21
21
  import { getTypeId } from "../type-D2s5lmbZ.js";
22
- import "../actor-DxfId8ty.js";
23
- import "../key-DYTMwpBh.js";
24
- import { signRequest, verifyRequest } from "../http-BI-X6nC8.js";
25
- import { getAuthenticatedDocumentLoader } from "../authdocloader-BsMSD7rr.js";
26
- import { detachSignature, signJsonLd, verifyJsonLd } from "../ld-Bgq_lRr5.js";
27
- import { doesActorOwnKey } from "../owner-DQcsEjrE.js";
28
- import { signObject, verifyObject } from "../proof-LR5LYCDY.js";
29
- import { lookupObject } from "../lookup-DnXipkyR.js";
30
- import "../inbox-DdI7kf97.js";
31
- import "../builder-B4OL-_3v.js";
22
+ import "../actor-D46a80bG.js";
23
+ import "../key-CQBqJoVo.js";
24
+ import { signRequest, verifyRequest } from "../http-DQ_uU1M-.js";
25
+ import { getAuthenticatedDocumentLoader } from "../authdocloader-Dp78K2jr.js";
26
+ import { detachSignature, signJsonLd, verifyJsonLd } from "../ld-CIsXjsgE.js";
27
+ import { doesActorOwnKey } from "../owner-B3kfyNi5.js";
28
+ import { signObject, verifyObject } from "../proof-TTTVErx5.js";
29
+ import { lookupObject } from "../lookup-Dc9JhQGJ.js";
30
+ import "../inbox-BxUUuzd9.js";
31
+ import "../builder-DAzNxi3p.js";
32
32
  import "../collection-Dfb0TPno.js";
33
- import "../keycache-BBHrPjap.js";
33
+ import "../keycache-B-TB9qYF.js";
34
34
  import "../retry-BiIhZWgD.js";
35
- import "../send-CSg0l0Ds.js";
35
+ import "../send-BkUwe85v.js";
36
36
  import { test } from "../testing-BZ0dJ4qn.js";
37
37
  import { assertStrictEquals } from "../std__assert-B3iAixc-.js";
38
38
  import { assertFalse, assertRejects } from "../assert_rejects-DceVjUlD.js";
@@ -40,7 +40,7 @@ import "../assert_is_error-DQdKoRgb.js";
40
40
  import { assertNotEquals } from "../assert_not_equals-7pyUM3Ib.js";
41
41
  import { assertThrows } from "../assert_throws-DTDC_gwN.js";
42
42
  import { mockDocumentLoader } from "../docloader-09nVWLAZ.js";
43
- import { ed25519Multikey, ed25519PrivateKey, ed25519PublicKey, rsaPrivateKey2, rsaPrivateKey3, rsaPublicKey2, rsaPublicKey3 } from "../keys-_jhKoT94.js";
43
+ import { ed25519Multikey, ed25519PrivateKey, ed25519PublicKey, rsaPrivateKey2, rsaPrivateKey3, rsaPublicKey2, rsaPublicKey3 } from "../keys-CVjF1n8p.js";
44
44
  import { esm_default } from "../esm-d-9EVGaP.js";
45
45
 
46
46
  //#region testing/fixtures/example.com/person.json
@@ -223,554 +223,561 @@ test("createFederation()", async (t) => {
223
223
  }), TypeError);
224
224
  });
225
225
  });
226
- test("Federation.createContext()", async (t) => {
227
- const kv = new MemoryKvStore();
228
- const documentLoader = (url) => {
229
- throw new FetchError(new URL(url), "Not found");
230
- };
231
- esm_default.spyGlobal();
232
- esm_default.get("https://example.com/object", async (cl) => {
233
- const v = await verifyRequest(cl.request, {
234
- contextLoader: mockDocumentLoader,
235
- documentLoader: mockDocumentLoader,
236
- currentTime: Temporal.Now.instant()
237
- });
238
- return new Response(JSON.stringify(v != null), { headers: { "Content-Type": "application/json" } });
239
- });
240
- await t.step("Context", async () => {
241
- const federation = createFederation({
242
- kv,
243
- documentLoader,
244
- contextLoader: mockDocumentLoader
245
- });
246
- let ctx = federation.createContext(new URL("https://example.com:1234/"), 123);
247
- assertEquals(ctx.data, 123);
248
- assertEquals(ctx.origin, "https://example.com:1234");
249
- assertEquals(ctx.canonicalOrigin, "https://example.com:1234");
250
- assertEquals(ctx.host, "example.com:1234");
251
- assertEquals(ctx.hostname, "example.com");
252
- assertStrictEquals(ctx.documentLoader, documentLoader);
253
- assertStrictEquals(ctx.contextLoader, mockDocumentLoader);
254
- assertStrictEquals(ctx.federation, federation);
255
- assertThrows(() => ctx.getNodeInfoUri(), RouterError);
256
- assertThrows(() => ctx.getActorUri("handle"), RouterError);
257
- assertThrows(() => ctx.getObjectUri(Note, {
258
- handle: "handle",
259
- id: "id"
260
- }), RouterError);
261
- assertThrows(() => ctx.getInboxUri(), RouterError);
262
- assertThrows(() => ctx.getInboxUri("handle"), RouterError);
263
- assertThrows(() => ctx.getOutboxUri("handle"), RouterError);
264
- assertThrows(() => ctx.getFollowingUri("handle"), RouterError);
265
- assertThrows(() => ctx.getFollowersUri("handle"), RouterError);
266
- assertThrows(() => ctx.getLikedUri("handle"), RouterError);
267
- assertThrows(() => ctx.getFeaturedUri("handle"), RouterError);
268
- assertThrows(() => ctx.getFeaturedTagsUri("handle"), RouterError);
269
- assertEquals(ctx.parseUri(new URL("https://example.com/")), null);
270
- assertEquals(ctx.parseUri(null), null);
271
- assertEquals(await ctx.getActorKeyPairs("handle"), []);
272
- await assertRejects(() => ctx.getDocumentLoader({ identifier: "handle" }), Error, "No actor key pairs dispatcher registered");
273
- await assertRejects(() => ctx.sendActivity({ identifier: "handle" }, [], new Create({})), Error, "No actor key pairs dispatcher registered");
274
- federation.setNodeInfoDispatcher("/nodeinfo/2.1", () => ({
275
- software: {
276
- name: "Example",
277
- version: {
278
- major: 1,
279
- minor: 2,
280
- patch: 3
226
+ test({
227
+ name: "Federation.createContext()",
228
+ permissions: {
229
+ env: true,
230
+ read: true
231
+ },
232
+ async fn(t) {
233
+ const kv = new MemoryKvStore();
234
+ const documentLoader = (url) => {
235
+ throw new FetchError(new URL(url), "Not found");
236
+ };
237
+ esm_default.spyGlobal();
238
+ esm_default.get("https://example.com/object", async (cl) => {
239
+ const v = await verifyRequest(cl.request, {
240
+ contextLoader: mockDocumentLoader,
241
+ documentLoader: mockDocumentLoader,
242
+ currentTime: Temporal.Now.instant()
243
+ });
244
+ return new Response(JSON.stringify(v != null), { headers: { "Content-Type": "application/json" } });
245
+ });
246
+ await t.step("Context", async () => {
247
+ const federation = createFederation({
248
+ kv,
249
+ documentLoader,
250
+ contextLoader: mockDocumentLoader
251
+ });
252
+ let ctx = federation.createContext(new URL("https://example.com:1234/"), 123);
253
+ assertEquals(ctx.data, 123);
254
+ assertEquals(ctx.origin, "https://example.com:1234");
255
+ assertEquals(ctx.canonicalOrigin, "https://example.com:1234");
256
+ assertEquals(ctx.host, "example.com:1234");
257
+ assertEquals(ctx.hostname, "example.com");
258
+ assertStrictEquals(ctx.documentLoader, documentLoader);
259
+ assertStrictEquals(ctx.contextLoader, mockDocumentLoader);
260
+ assertStrictEquals(ctx.federation, federation);
261
+ assertThrows(() => ctx.getNodeInfoUri(), RouterError);
262
+ assertThrows(() => ctx.getActorUri("handle"), RouterError);
263
+ assertThrows(() => ctx.getObjectUri(Note, {
264
+ handle: "handle",
265
+ id: "id"
266
+ }), RouterError);
267
+ assertThrows(() => ctx.getInboxUri(), RouterError);
268
+ assertThrows(() => ctx.getInboxUri("handle"), RouterError);
269
+ assertThrows(() => ctx.getOutboxUri("handle"), RouterError);
270
+ assertThrows(() => ctx.getFollowingUri("handle"), RouterError);
271
+ assertThrows(() => ctx.getFollowersUri("handle"), RouterError);
272
+ assertThrows(() => ctx.getLikedUri("handle"), RouterError);
273
+ assertThrows(() => ctx.getFeaturedUri("handle"), RouterError);
274
+ assertThrows(() => ctx.getFeaturedTagsUri("handle"), RouterError);
275
+ assertEquals(ctx.parseUri(new URL("https://example.com/")), null);
276
+ assertEquals(ctx.parseUri(null), null);
277
+ assertEquals(await ctx.getActorKeyPairs("handle"), []);
278
+ await assertRejects(() => ctx.getDocumentLoader({ identifier: "handle" }), Error, "No actor key pairs dispatcher registered");
279
+ await assertRejects(() => ctx.sendActivity({ identifier: "handle" }, [], new Create({})), Error, "No actor key pairs dispatcher registered");
280
+ federation.setNodeInfoDispatcher("/nodeinfo/2.1", () => ({
281
+ software: {
282
+ name: "Example",
283
+ version: {
284
+ major: 1,
285
+ minor: 2,
286
+ patch: 3
287
+ }
288
+ },
289
+ protocols: ["activitypub"],
290
+ usage: {
291
+ users: {},
292
+ localPosts: 123,
293
+ localComments: 456
281
294
  }
282
- },
283
- protocols: ["activitypub"],
284
- usage: {
285
- users: {},
286
- localPosts: 123,
287
- localComments: 456
288
- }
289
- }));
290
- ctx = federation.createContext(new URL("https://example.com/"), 123);
291
- assertEquals(ctx.getNodeInfoUri(), new URL("https://example.com/nodeinfo/2.1"));
292
- federation.setActorDispatcher("/users/{identifier}", () => new Person({})).setKeyPairsDispatcher(() => [{
293
- privateKey: rsaPrivateKey2,
294
- publicKey: rsaPublicKey2.publicKey
295
- }, {
296
- privateKey: ed25519PrivateKey,
297
- publicKey: ed25519PublicKey.publicKey
298
- }]).mapHandle((_, username) => username === "HANDLE" ? "handle" : null);
299
- ctx = federation.createContext(new URL("https://example.com/"), 123);
300
- assertEquals(ctx.getActorUri("handle"), new URL("https://example.com/users/handle"));
301
- assertEquals(ctx.parseUri(new URL("https://example.com/")), null);
302
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle")), {
303
- type: "actor",
304
- identifier: "handle",
305
- handle: "handle"
306
- });
307
- assertEquals(ctx.parseUri(null), null);
308
- assertEquals(await ctx.getActorKeyPairs("handle"), [{
309
- keyId: new URL("https://example.com/users/handle#main-key"),
310
- privateKey: rsaPrivateKey2,
311
- publicKey: rsaPublicKey2.publicKey,
312
- cryptographicKey: rsaPublicKey2.clone({
313
- id: new URL("https://example.com/users/handle#main-key"),
314
- owner: new URL("https://example.com/users/handle")
315
- }),
316
- multikey: new Multikey({
317
- id: new URL("https://example.com/users/handle#main-key"),
318
- controller: new URL("https://example.com/users/handle"),
295
+ }));
296
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
297
+ assertEquals(ctx.getNodeInfoUri(), new URL("https://example.com/nodeinfo/2.1"));
298
+ federation.setActorDispatcher("/users/{identifier}", () => new Person({})).setKeyPairsDispatcher(() => [{
299
+ privateKey: rsaPrivateKey2,
319
300
  publicKey: rsaPublicKey2.publicKey
320
- })
321
- }, {
322
- keyId: new URL("https://example.com/users/handle#key-2"),
323
- privateKey: ed25519PrivateKey,
324
- publicKey: ed25519PublicKey.publicKey,
325
- cryptographicKey: ed25519PublicKey.clone({
326
- id: new URL("https://example.com/users/handle#key-2"),
327
- owner: new URL("https://example.com/users/handle")
328
- }),
329
- multikey: new Multikey({
330
- id: new URL("https://example.com/users/handle#key-2"),
331
- controller: new URL("https://example.com/users/handle"),
301
+ }, {
302
+ privateKey: ed25519PrivateKey,
332
303
  publicKey: ed25519PublicKey.publicKey
333
- })
334
- }]);
335
- const loader = await ctx.getDocumentLoader({ identifier: "handle" });
336
- assertEquals(await loader("https://example.com/object"), {
337
- contextUrl: null,
338
- documentUrl: "https://example.com/object",
339
- document: true
340
- });
341
- const loader2 = await ctx.getDocumentLoader({ username: "HANDLE" });
342
- assertEquals(await loader2("https://example.com/object"), {
343
- contextUrl: null,
344
- documentUrl: "https://example.com/object",
345
- document: true
346
- });
347
- const loader3 = ctx.getDocumentLoader({
348
- keyId: new URL("https://example.com/key2"),
349
- privateKey: rsaPrivateKey2
350
- });
351
- assertEquals(await loader3("https://example.com/object"), {
352
- contextUrl: null,
353
- documentUrl: "https://example.com/object",
354
- document: true
355
- });
356
- assertEquals(await ctx.lookupObject("https://example.com/object"), null);
357
- await assertRejects(() => ctx.sendActivity({ identifier: "handle" }, [], new Create({})), TypeError, "The activity to send must have at least one actor property.");
358
- await ctx.sendActivity({ identifier: "handle" }, [], new Create({ actor: new URL("https://example.com/users/handle") }));
359
- const federation2 = createFederation({
360
- kv,
361
- documentLoader: mockDocumentLoader,
362
- contextLoader: mockDocumentLoader
363
- });
364
- const ctx2 = federation2.createContext(new URL("https://example.com/"), 123);
365
- assertEquals(await ctx2.lookupObject("https://example.com/object"), new Object$1({
366
- id: new URL("https://example.com/object"),
367
- name: "Fetched object"
368
- }));
369
- federation.setObjectDispatcher(Note, "/users/{identifier}/notes/{id}", (_ctx, values) => {
370
- return new Note({ summary: `Note ${values.id} by ${values.identifier}` });
371
- });
372
- ctx = federation.createContext(new URL("https://example.com/"), 123);
373
- assertEquals(ctx.getObjectUri(Note, {
374
- identifier: "john",
375
- id: "123"
376
- }), new URL("https://example.com/users/john/notes/123"));
377
- assertEquals(ctx.parseUri(new URL("https://example.com/users/john/notes/123")), {
378
- type: "object",
379
- class: Note,
380
- typeId: new URL("https://www.w3.org/ns/activitystreams#Note"),
381
- values: {
304
+ }]).mapHandle((_, username) => username === "HANDLE" ? "handle" : null);
305
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
306
+ assertEquals(ctx.getActorUri("handle"), new URL("https://example.com/users/handle"));
307
+ assertEquals(ctx.parseUri(new URL("https://example.com/")), null);
308
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle")), {
309
+ type: "actor",
310
+ identifier: "handle",
311
+ handle: "handle"
312
+ });
313
+ assertEquals(ctx.parseUri(null), null);
314
+ assertEquals(await ctx.getActorKeyPairs("handle"), [{
315
+ keyId: new URL("https://example.com/users/handle#main-key"),
316
+ privateKey: rsaPrivateKey2,
317
+ publicKey: rsaPublicKey2.publicKey,
318
+ cryptographicKey: rsaPublicKey2.clone({
319
+ id: new URL("https://example.com/users/handle#main-key"),
320
+ owner: new URL("https://example.com/users/handle")
321
+ }),
322
+ multikey: new Multikey({
323
+ id: new URL("https://example.com/users/handle#main-key"),
324
+ controller: new URL("https://example.com/users/handle"),
325
+ publicKey: rsaPublicKey2.publicKey
326
+ })
327
+ }, {
328
+ keyId: new URL("https://example.com/users/handle#key-2"),
329
+ privateKey: ed25519PrivateKey,
330
+ publicKey: ed25519PublicKey.publicKey,
331
+ cryptographicKey: ed25519PublicKey.clone({
332
+ id: new URL("https://example.com/users/handle#key-2"),
333
+ owner: new URL("https://example.com/users/handle")
334
+ }),
335
+ multikey: new Multikey({
336
+ id: new URL("https://example.com/users/handle#key-2"),
337
+ controller: new URL("https://example.com/users/handle"),
338
+ publicKey: ed25519PublicKey.publicKey
339
+ })
340
+ }]);
341
+ const loader = await ctx.getDocumentLoader({ identifier: "handle" });
342
+ assertEquals(await loader("https://example.com/object"), {
343
+ contextUrl: null,
344
+ documentUrl: "https://example.com/object",
345
+ document: true
346
+ });
347
+ const loader2 = await ctx.getDocumentLoader({ username: "HANDLE" });
348
+ assertEquals(await loader2("https://example.com/object"), {
349
+ contextUrl: null,
350
+ documentUrl: "https://example.com/object",
351
+ document: true
352
+ });
353
+ const loader3 = ctx.getDocumentLoader({
354
+ keyId: new URL("https://example.com/key2"),
355
+ privateKey: rsaPrivateKey2
356
+ });
357
+ assertEquals(await loader3("https://example.com/object"), {
358
+ contextUrl: null,
359
+ documentUrl: "https://example.com/object",
360
+ document: true
361
+ });
362
+ assertEquals(await ctx.lookupObject("https://example.com/object"), null);
363
+ await assertRejects(() => ctx.sendActivity({ identifier: "handle" }, [], new Create({})), TypeError, "The activity to send must have at least one actor property.");
364
+ await ctx.sendActivity({ identifier: "handle" }, [], new Create({ actor: new URL("https://example.com/users/handle") }));
365
+ const federation2 = createFederation({
366
+ kv,
367
+ documentLoader: mockDocumentLoader,
368
+ contextLoader: mockDocumentLoader
369
+ });
370
+ const ctx2 = federation2.createContext(new URL("https://example.com/"), 123);
371
+ assertEquals(await ctx2.lookupObject("https://example.com/object"), new Object$1({
372
+ id: new URL("https://example.com/object"),
373
+ name: "Fetched object"
374
+ }));
375
+ federation.setObjectDispatcher(Note, "/users/{identifier}/notes/{id}", (_ctx, values) => {
376
+ return new Note({ summary: `Note ${values.id} by ${values.identifier}` });
377
+ });
378
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
379
+ assertEquals(ctx.getObjectUri(Note, {
382
380
  identifier: "john",
383
381
  id: "123"
384
- }
385
- });
386
- assertEquals(ctx.parseUri(null), null);
387
- federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
388
- ctx = federation.createContext(new URL("https://example.com/"), 123);
389
- assertEquals(ctx.getInboxUri(), new URL("https://example.com/inbox"));
390
- assertEquals(ctx.getInboxUri("handle"), new URL("https://example.com/users/handle/inbox"));
391
- assertEquals(ctx.parseUri(new URL("https://example.com/inbox")), {
392
- type: "inbox",
393
- identifier: void 0,
394
- handle: void 0
395
- });
396
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/inbox")), {
397
- type: "inbox",
398
- identifier: "handle",
399
- handle: "handle"
400
- });
401
- assertEquals(ctx.parseUri(null), null);
402
- federation.setOutboxDispatcher("/users/{identifier}/outbox", () => ({ items: [] }));
403
- ctx = federation.createContext(new URL("https://example.com/"), 123);
404
- assertEquals(ctx.getOutboxUri("handle"), new URL("https://example.com/users/handle/outbox"));
405
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/outbox")), {
406
- type: "outbox",
407
- identifier: "handle",
408
- handle: "handle"
409
- });
410
- assertEquals(ctx.parseUri(null), null);
411
- federation.setFollowingDispatcher("/users/{identifier}/following", () => ({ items: [] }));
412
- ctx = federation.createContext(new URL("https://example.com/"), 123);
413
- assertEquals(ctx.getFollowingUri("handle"), new URL("https://example.com/users/handle/following"));
414
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/following")), {
415
- type: "following",
416
- identifier: "handle",
417
- handle: "handle"
418
- });
419
- assertEquals(ctx.parseUri(null), null);
420
- federation.setFollowersDispatcher("/users/{identifier}/followers", () => ({ items: [] }));
421
- ctx = federation.createContext(new URL("https://example.com/"), 123);
422
- assertEquals(ctx.getFollowersUri("handle"), new URL("https://example.com/users/handle/followers"));
423
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/followers")), {
424
- type: "followers",
425
- identifier: "handle",
426
- handle: "handle"
427
- });
428
- assertEquals(ctx.parseUri(null), null);
429
- federation.setLikedDispatcher("/users/{identifier}/liked", () => ({ items: [] }));
430
- ctx = federation.createContext(new URL("https://example.com/"), 123);
431
- assertEquals(ctx.getLikedUri("handle"), new URL("https://example.com/users/handle/liked"));
432
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/liked")), {
433
- type: "liked",
434
- identifier: "handle",
435
- handle: "handle"
436
- });
437
- assertEquals(ctx.parseUri(null), null);
438
- federation.setFeaturedDispatcher("/users/{identifier}/featured", () => ({ items: [] }));
439
- ctx = federation.createContext(new URL("https://example.com/"), 123);
440
- assertEquals(ctx.getFeaturedUri("handle"), new URL("https://example.com/users/handle/featured"));
441
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/featured")), {
442
- type: "featured",
443
- identifier: "handle",
444
- handle: "handle"
445
- });
446
- assertEquals(ctx.parseUri(null), null);
447
- federation.setFeaturedTagsDispatcher("/users/{identifier}/tags", () => ({ items: [] }));
448
- ctx = federation.createContext(new URL("https://example.com/"), 123);
449
- assertEquals(ctx.getFeaturedTagsUri("handle"), new URL("https://example.com/users/handle/tags"));
450
- assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/tags")), {
451
- type: "featuredTags",
452
- identifier: "handle",
453
- handle: "handle"
454
- });
455
- assertEquals(ctx.parseUri(null), null);
456
- });
457
- await t.step("Context with origin", () => {
458
- const federation = createFederation({
459
- kv,
460
- origin: "https://ap.example.com",
461
- documentLoader,
462
- contextLoader: mockDocumentLoader
463
- });
464
- const ctx = federation.createContext(new URL("https://example.com:1234/"));
465
- assertEquals(ctx.origin, "https://example.com:1234");
466
- assertEquals(ctx.canonicalOrigin, "https://ap.example.com");
467
- assertEquals(ctx.host, "example.com:1234");
468
- assertEquals(ctx.hostname, "example.com");
469
- federation.setNodeInfoDispatcher("/nodeinfo/2.1", () => ({
470
- software: {
471
- name: "Example",
472
- version: {
473
- major: 1,
474
- minor: 2,
475
- patch: 3
382
+ }), new URL("https://example.com/users/john/notes/123"));
383
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/john/notes/123")), {
384
+ type: "object",
385
+ class: Note,
386
+ typeId: new URL("https://www.w3.org/ns/activitystreams#Note"),
387
+ values: {
388
+ identifier: "john",
389
+ id: "123"
476
390
  }
477
- },
478
- protocols: ["activitypub"],
479
- usage: {
480
- users: {},
481
- localPosts: 123,
482
- localComments: 456
483
- }
484
- }));
485
- assertEquals(ctx.getNodeInfoUri(), new URL("https://ap.example.com/nodeinfo/2.1"));
486
- federation.setActorDispatcher("/users/{identifier}", () => new Person({}));
487
- assertEquals(ctx.getActorUri("handle"), new URL("https://ap.example.com/users/handle"));
488
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle")), {
489
- type: "actor",
490
- handle: "handle",
491
- identifier: "handle"
492
- });
493
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle")), {
494
- type: "actor",
495
- handle: "handle",
496
- identifier: "handle"
497
- });
498
- federation.setObjectDispatcher(Note, "/users/{identifier}/notes/{id}", (_ctx, values) => {
499
- return new Note({ summary: `Note ${values.id} by ${values.identifier}` });
500
- });
501
- assertEquals(ctx.getObjectUri(Note, {
502
- identifier: "john",
503
- id: "123"
504
- }), new URL("https://ap.example.com/users/john/notes/123"));
505
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/john/notes/123")), {
506
- type: "object",
507
- class: Note,
508
- typeId: new URL("https://www.w3.org/ns/activitystreams#Note"),
509
- values: {
391
+ });
392
+ assertEquals(ctx.parseUri(null), null);
393
+ federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
394
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
395
+ assertEquals(ctx.getInboxUri(), new URL("https://example.com/inbox"));
396
+ assertEquals(ctx.getInboxUri("handle"), new URL("https://example.com/users/handle/inbox"));
397
+ assertEquals(ctx.parseUri(new URL("https://example.com/inbox")), {
398
+ type: "inbox",
399
+ identifier: void 0,
400
+ handle: void 0
401
+ });
402
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/inbox")), {
403
+ type: "inbox",
404
+ identifier: "handle",
405
+ handle: "handle"
406
+ });
407
+ assertEquals(ctx.parseUri(null), null);
408
+ federation.setOutboxDispatcher("/users/{identifier}/outbox", () => ({ items: [] }));
409
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
410
+ assertEquals(ctx.getOutboxUri("handle"), new URL("https://example.com/users/handle/outbox"));
411
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/outbox")), {
412
+ type: "outbox",
413
+ identifier: "handle",
414
+ handle: "handle"
415
+ });
416
+ assertEquals(ctx.parseUri(null), null);
417
+ federation.setFollowingDispatcher("/users/{identifier}/following", () => ({ items: [] }));
418
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
419
+ assertEquals(ctx.getFollowingUri("handle"), new URL("https://example.com/users/handle/following"));
420
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/following")), {
421
+ type: "following",
422
+ identifier: "handle",
423
+ handle: "handle"
424
+ });
425
+ assertEquals(ctx.parseUri(null), null);
426
+ federation.setFollowersDispatcher("/users/{identifier}/followers", () => ({ items: [] }));
427
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
428
+ assertEquals(ctx.getFollowersUri("handle"), new URL("https://example.com/users/handle/followers"));
429
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/followers")), {
430
+ type: "followers",
431
+ identifier: "handle",
432
+ handle: "handle"
433
+ });
434
+ assertEquals(ctx.parseUri(null), null);
435
+ federation.setLikedDispatcher("/users/{identifier}/liked", () => ({ items: [] }));
436
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
437
+ assertEquals(ctx.getLikedUri("handle"), new URL("https://example.com/users/handle/liked"));
438
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/liked")), {
439
+ type: "liked",
440
+ identifier: "handle",
441
+ handle: "handle"
442
+ });
443
+ assertEquals(ctx.parseUri(null), null);
444
+ federation.setFeaturedDispatcher("/users/{identifier}/featured", () => ({ items: [] }));
445
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
446
+ assertEquals(ctx.getFeaturedUri("handle"), new URL("https://example.com/users/handle/featured"));
447
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/featured")), {
448
+ type: "featured",
449
+ identifier: "handle",
450
+ handle: "handle"
451
+ });
452
+ assertEquals(ctx.parseUri(null), null);
453
+ federation.setFeaturedTagsDispatcher("/users/{identifier}/tags", () => ({ items: [] }));
454
+ ctx = federation.createContext(new URL("https://example.com/"), 123);
455
+ assertEquals(ctx.getFeaturedTagsUri("handle"), new URL("https://example.com/users/handle/tags"));
456
+ assertEquals(ctx.parseUri(new URL("https://example.com/users/handle/tags")), {
457
+ type: "featuredTags",
458
+ identifier: "handle",
459
+ handle: "handle"
460
+ });
461
+ assertEquals(ctx.parseUri(null), null);
462
+ });
463
+ await t.step("Context with origin", () => {
464
+ const federation = createFederation({
465
+ kv,
466
+ origin: "https://ap.example.com",
467
+ documentLoader,
468
+ contextLoader: mockDocumentLoader
469
+ });
470
+ const ctx = federation.createContext(new URL("https://example.com:1234/"));
471
+ assertEquals(ctx.origin, "https://example.com:1234");
472
+ assertEquals(ctx.canonicalOrigin, "https://ap.example.com");
473
+ assertEquals(ctx.host, "example.com:1234");
474
+ assertEquals(ctx.hostname, "example.com");
475
+ federation.setNodeInfoDispatcher("/nodeinfo/2.1", () => ({
476
+ software: {
477
+ name: "Example",
478
+ version: {
479
+ major: 1,
480
+ minor: 2,
481
+ patch: 3
482
+ }
483
+ },
484
+ protocols: ["activitypub"],
485
+ usage: {
486
+ users: {},
487
+ localPosts: 123,
488
+ localComments: 456
489
+ }
490
+ }));
491
+ assertEquals(ctx.getNodeInfoUri(), new URL("https://ap.example.com/nodeinfo/2.1"));
492
+ federation.setActorDispatcher("/users/{identifier}", () => new Person({}));
493
+ assertEquals(ctx.getActorUri("handle"), new URL("https://ap.example.com/users/handle"));
494
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle")), {
495
+ type: "actor",
496
+ handle: "handle",
497
+ identifier: "handle"
498
+ });
499
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle")), {
500
+ type: "actor",
501
+ handle: "handle",
502
+ identifier: "handle"
503
+ });
504
+ federation.setObjectDispatcher(Note, "/users/{identifier}/notes/{id}", (_ctx, values) => {
505
+ return new Note({ summary: `Note ${values.id} by ${values.identifier}` });
506
+ });
507
+ assertEquals(ctx.getObjectUri(Note, {
510
508
  identifier: "john",
511
509
  id: "123"
512
- }
513
- });
514
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/john/notes/123")), {
515
- type: "object",
516
- class: Note,
517
- typeId: new URL("https://www.w3.org/ns/activitystreams#Note"),
518
- values: {
510
+ }), new URL("https://ap.example.com/users/john/notes/123"));
511
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/john/notes/123")), {
512
+ type: "object",
513
+ class: Note,
514
+ typeId: new URL("https://www.w3.org/ns/activitystreams#Note"),
515
+ values: {
516
+ identifier: "john",
517
+ id: "123"
518
+ }
519
+ });
520
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/john/notes/123")), {
521
+ type: "object",
522
+ class: Note,
523
+ typeId: new URL("https://www.w3.org/ns/activitystreams#Note"),
524
+ values: {
525
+ identifier: "john",
526
+ id: "123"
527
+ }
528
+ });
529
+ federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
530
+ assertEquals(ctx.getInboxUri(), new URL("https://ap.example.com/inbox"));
531
+ assertEquals(ctx.getInboxUri("handle"), new URL("https://ap.example.com/users/handle/inbox"));
532
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/inbox")), {
533
+ type: "inbox",
534
+ handle: void 0,
535
+ identifier: void 0
536
+ });
537
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/inbox")), {
538
+ type: "inbox",
539
+ handle: void 0,
540
+ identifier: void 0
541
+ });
542
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/inbox")), {
543
+ type: "inbox",
544
+ handle: "handle",
545
+ identifier: "handle"
546
+ });
547
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/inbox")), {
548
+ type: "inbox",
549
+ handle: "handle",
550
+ identifier: "handle"
551
+ });
552
+ federation.setOutboxDispatcher("/users/{identifier}/outbox", () => ({ items: [] }));
553
+ assertEquals(ctx.getOutboxUri("handle"), new URL("https://ap.example.com/users/handle/outbox"));
554
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/outbox")), {
555
+ type: "outbox",
556
+ handle: "handle",
557
+ identifier: "handle"
558
+ });
559
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/outbox")), {
560
+ type: "outbox",
561
+ handle: "handle",
562
+ identifier: "handle"
563
+ });
564
+ federation.setFollowingDispatcher("/users/{identifier}/following", () => ({ items: [] }));
565
+ assertEquals(ctx.getFollowingUri("handle"), new URL("https://ap.example.com/users/handle/following"));
566
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/following")), {
567
+ type: "following",
568
+ handle: "handle",
569
+ identifier: "handle"
570
+ });
571
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/following")), {
572
+ type: "following",
573
+ handle: "handle",
574
+ identifier: "handle"
575
+ });
576
+ federation.setFollowersDispatcher("/users/{identifier}/followers", () => ({ items: [] }));
577
+ assertEquals(ctx.getFollowersUri("handle"), new URL("https://ap.example.com/users/handle/followers"));
578
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/followers")), {
579
+ type: "followers",
580
+ handle: "handle",
581
+ identifier: "handle"
582
+ });
583
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/followers")), {
584
+ type: "followers",
585
+ handle: "handle",
586
+ identifier: "handle"
587
+ });
588
+ federation.setLikedDispatcher("/users/{identifier}/liked", () => ({ items: [] }));
589
+ assertEquals(ctx.getLikedUri("handle"), new URL("https://ap.example.com/users/handle/liked"));
590
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/liked")), {
591
+ type: "liked",
592
+ handle: "handle",
593
+ identifier: "handle"
594
+ });
595
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/liked")), {
596
+ type: "liked",
597
+ handle: "handle",
598
+ identifier: "handle"
599
+ });
600
+ federation.setFeaturedDispatcher("/users/{identifier}/featured", () => ({ items: [] }));
601
+ assertEquals(ctx.getFeaturedUri("handle"), new URL("https://ap.example.com/users/handle/featured"));
602
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/featured")), {
603
+ type: "featured",
604
+ handle: "handle",
605
+ identifier: "handle"
606
+ });
607
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/featured")), {
608
+ type: "featured",
609
+ handle: "handle",
610
+ identifier: "handle"
611
+ });
612
+ federation.setFeaturedTagsDispatcher("/users/{identifier}/tags", () => ({ items: [] }));
613
+ assertEquals(ctx.getFeaturedTagsUri("handle"), new URL("https://ap.example.com/users/handle/tags"));
614
+ assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/tags")), {
615
+ type: "featuredTags",
616
+ handle: "handle",
617
+ identifier: "handle"
618
+ });
619
+ assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/tags")), {
620
+ type: "featuredTags",
621
+ handle: "handle",
622
+ identifier: "handle"
623
+ });
624
+ });
625
+ await t.step("Context.clone()", () => {
626
+ const federation = createFederation({ kv });
627
+ const ctx = federation.createContext(new URL("https://example.com/"), 123);
628
+ const clone = ctx.clone(456);
629
+ assertStrictEquals(clone.canonicalOrigin, ctx.canonicalOrigin);
630
+ assertStrictEquals(clone.origin, ctx.origin);
631
+ assertEquals(clone.data, 456);
632
+ assertEquals(clone.host, ctx.host);
633
+ assertEquals(clone.hostname, ctx.hostname);
634
+ assertStrictEquals(clone.documentLoader, ctx.documentLoader);
635
+ assertStrictEquals(clone.contextLoader, ctx.contextLoader);
636
+ assertStrictEquals(clone.federation, ctx.federation);
637
+ });
638
+ esm_default.get("https://example.com/.well-known/nodeinfo", (cl) => {
639
+ const headers = cl.options.headers ?? {};
640
+ assertEquals(new Headers(headers).get("User-Agent"), "CustomUserAgent/1.2.3");
641
+ return new Response(JSON.stringify({ links: [{
642
+ rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
643
+ href: "https://example.com/nodeinfo/2.1"
644
+ }] }));
645
+ });
646
+ esm_default.get("https://example.com/nodeinfo/2.1", (cl) => {
647
+ const headers = cl.options.headers ?? {};
648
+ assertEquals(new Headers(headers).get("User-Agent"), "CustomUserAgent/1.2.3");
649
+ return new Response(JSON.stringify({
650
+ software: {
651
+ name: "foo",
652
+ version: "1.2.3"
653
+ },
654
+ protocols: ["activitypub", "diaspora"],
655
+ usage: {
656
+ users: {},
657
+ localPosts: 123,
658
+ localComments: 456
659
+ }
660
+ }));
661
+ });
662
+ await t.step("Context.lookupNodeInfo()", async () => {
663
+ const federation = createFederation({
664
+ kv,
665
+ userAgent: "CustomUserAgent/1.2.3"
666
+ });
667
+ const ctx = federation.createContext(new URL("https://example.com/"), 123);
668
+ const nodeInfo = await ctx.lookupNodeInfo("https://example.com/");
669
+ assertEquals(nodeInfo, {
670
+ software: {
671
+ name: "foo",
672
+ version: {
673
+ major: 1,
674
+ minor: 2,
675
+ patch: 3,
676
+ build: [],
677
+ prerelease: []
678
+ }
679
+ },
680
+ protocols: ["activitypub", "diaspora"],
681
+ usage: {
682
+ users: {},
683
+ localPosts: 123,
684
+ localComments: 456
685
+ }
686
+ });
687
+ const rawNodeInfo = await ctx.lookupNodeInfo("https://example.com/", { parse: "none" });
688
+ assertEquals(rawNodeInfo, {
689
+ software: {
690
+ name: "foo",
691
+ version: "1.2.3"
692
+ },
693
+ protocols: ["activitypub", "diaspora"],
694
+ usage: {
695
+ users: {},
696
+ localPosts: 123,
697
+ localComments: 456
698
+ }
699
+ });
700
+ });
701
+ await t.step("RequestContext", async () => {
702
+ const federation = createFederation({
703
+ kv,
704
+ documentLoader: mockDocumentLoader
705
+ });
706
+ const req = new Request("https://example.com/");
707
+ const ctx = federation.createContext(req, 123);
708
+ assertEquals(ctx.request, req);
709
+ assertEquals(ctx.url, new URL("https://example.com/"));
710
+ assertEquals(ctx.origin, "https://example.com");
711
+ assertEquals(ctx.host, "example.com");
712
+ assertEquals(ctx.hostname, "example.com");
713
+ assertEquals(ctx.data, 123);
714
+ await assertRejects(() => ctx.getActor("someone"), Error);
715
+ await assertRejects(() => ctx.getObject(Note, {
716
+ handle: "someone",
717
+ id: "123"
718
+ }), Error);
719
+ assertEquals(await ctx.getSignedKey(), null);
720
+ assertEquals(await ctx.getSignedKeyOwner(), null);
721
+ assertEquals(await ctx.getSignedKey(), null);
722
+ assertEquals(await ctx.getSignedKeyOwner(), null);
723
+ await assertRejects(() => ctx.getActor("someone"), Error, "No actor dispatcher registered");
724
+ const signedReq = await signRequest(new Request("https://example.com/"), rsaPrivateKey2, rsaPublicKey2.id);
725
+ const signedCtx = federation.createContext(signedReq, 456);
726
+ assertEquals(signedCtx.request, signedReq);
727
+ assertEquals(signedCtx.url, new URL("https://example.com/"));
728
+ assertEquals(signedCtx.data, 456);
729
+ assertEquals(await signedCtx.getSignedKey(), rsaPublicKey2);
730
+ assertEquals(await signedCtx.getSignedKeyOwner(), null);
731
+ assertEquals(await signedCtx.getSignedKey(), rsaPublicKey2);
732
+ assertEquals(await signedCtx.getSignedKeyOwner(), null);
733
+ const signedReq2 = await signRequest(new Request("https://example.com/"), rsaPrivateKey3, rsaPublicKey3.id);
734
+ const signedCtx2 = federation.createContext(signedReq2, 456);
735
+ assertEquals(signedCtx2.request, signedReq2);
736
+ assertEquals(signedCtx2.url, new URL("https://example.com/"));
737
+ assertEquals(signedCtx2.data, 456);
738
+ assertEquals(await signedCtx2.getSignedKey(), rsaPublicKey3);
739
+ const expectedOwner = await lookupObject("https://example.com/person2", {
740
+ documentLoader: mockDocumentLoader,
741
+ contextLoader: mockDocumentLoader
742
+ });
743
+ assertEquals(await signedCtx2.getSignedKeyOwner(), expectedOwner);
744
+ assertEquals(await signedCtx2.getSignedKey(), rsaPublicKey3);
745
+ assertEquals(await signedCtx2.getSignedKeyOwner(), expectedOwner);
746
+ federation.setActorDispatcher("/users/{identifier}", (_ctx, identifier) => new Person({ preferredUsername: identifier }));
747
+ const ctx2 = federation.createContext(req, 789);
748
+ assertEquals(ctx2.request, req);
749
+ assertEquals(ctx2.url, new URL("https://example.com/"));
750
+ assertEquals(ctx2.data, 789);
751
+ assertEquals(await ctx2.getActor("john"), new Person({ preferredUsername: "john" }));
752
+ federation.setObjectDispatcher(Note, "/users/{identifier}/notes/{id}", (_ctx, values) => {
753
+ return new Note({ summary: `Note ${values.id} by ${values.identifier}` });
754
+ });
755
+ const ctx3 = federation.createContext(req, 123);
756
+ assertEquals(ctx3.request, req);
757
+ assertEquals(ctx3.url, new URL("https://example.com/"));
758
+ assertEquals(ctx3.data, 123);
759
+ assertEquals(await ctx2.getObject(Note, {
519
760
  identifier: "john",
520
761
  id: "123"
521
- }
522
- });
523
- federation.setInboxListeners("/users/{identifier}/inbox", "/inbox");
524
- assertEquals(ctx.getInboxUri(), new URL("https://ap.example.com/inbox"));
525
- assertEquals(ctx.getInboxUri("handle"), new URL("https://ap.example.com/users/handle/inbox"));
526
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/inbox")), {
527
- type: "inbox",
528
- handle: void 0,
529
- identifier: void 0
530
- });
531
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/inbox")), {
532
- type: "inbox",
533
- handle: void 0,
534
- identifier: void 0
535
- });
536
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/inbox")), {
537
- type: "inbox",
538
- handle: "handle",
539
- identifier: "handle"
540
- });
541
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/inbox")), {
542
- type: "inbox",
543
- handle: "handle",
544
- identifier: "handle"
545
- });
546
- federation.setOutboxDispatcher("/users/{identifier}/outbox", () => ({ items: [] }));
547
- assertEquals(ctx.getOutboxUri("handle"), new URL("https://ap.example.com/users/handle/outbox"));
548
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/outbox")), {
549
- type: "outbox",
550
- handle: "handle",
551
- identifier: "handle"
552
- });
553
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/outbox")), {
554
- type: "outbox",
555
- handle: "handle",
556
- identifier: "handle"
557
- });
558
- federation.setFollowingDispatcher("/users/{identifier}/following", () => ({ items: [] }));
559
- assertEquals(ctx.getFollowingUri("handle"), new URL("https://ap.example.com/users/handle/following"));
560
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/following")), {
561
- type: "following",
562
- handle: "handle",
563
- identifier: "handle"
564
- });
565
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/following")), {
566
- type: "following",
567
- handle: "handle",
568
- identifier: "handle"
569
- });
570
- federation.setFollowersDispatcher("/users/{identifier}/followers", () => ({ items: [] }));
571
- assertEquals(ctx.getFollowersUri("handle"), new URL("https://ap.example.com/users/handle/followers"));
572
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/followers")), {
573
- type: "followers",
574
- handle: "handle",
575
- identifier: "handle"
576
- });
577
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/followers")), {
578
- type: "followers",
579
- handle: "handle",
580
- identifier: "handle"
581
- });
582
- federation.setLikedDispatcher("/users/{identifier}/liked", () => ({ items: [] }));
583
- assertEquals(ctx.getLikedUri("handle"), new URL("https://ap.example.com/users/handle/liked"));
584
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/liked")), {
585
- type: "liked",
586
- handle: "handle",
587
- identifier: "handle"
588
- });
589
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/liked")), {
590
- type: "liked",
591
- handle: "handle",
592
- identifier: "handle"
593
- });
594
- federation.setFeaturedDispatcher("/users/{identifier}/featured", () => ({ items: [] }));
595
- assertEquals(ctx.getFeaturedUri("handle"), new URL("https://ap.example.com/users/handle/featured"));
596
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/featured")), {
597
- type: "featured",
598
- handle: "handle",
599
- identifier: "handle"
600
- });
601
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/featured")), {
602
- type: "featured",
603
- handle: "handle",
604
- identifier: "handle"
605
- });
606
- federation.setFeaturedTagsDispatcher("/users/{identifier}/tags", () => ({ items: [] }));
607
- assertEquals(ctx.getFeaturedTagsUri("handle"), new URL("https://ap.example.com/users/handle/tags"));
608
- assertEquals(ctx.parseUri(new URL("https://ap.example.com/users/handle/tags")), {
609
- type: "featuredTags",
610
- handle: "handle",
611
- identifier: "handle"
612
- });
613
- assertEquals(ctx.parseUri(new URL("https://example.com:1234/users/handle/tags")), {
614
- type: "featuredTags",
615
- handle: "handle",
616
- identifier: "handle"
617
- });
618
- });
619
- await t.step("Context.clone()", () => {
620
- const federation = createFederation({ kv });
621
- const ctx = federation.createContext(new URL("https://example.com/"), 123);
622
- const clone = ctx.clone(456);
623
- assertStrictEquals(clone.canonicalOrigin, ctx.canonicalOrigin);
624
- assertStrictEquals(clone.origin, ctx.origin);
625
- assertEquals(clone.data, 456);
626
- assertEquals(clone.host, ctx.host);
627
- assertEquals(clone.hostname, ctx.hostname);
628
- assertStrictEquals(clone.documentLoader, ctx.documentLoader);
629
- assertStrictEquals(clone.contextLoader, ctx.contextLoader);
630
- assertStrictEquals(clone.federation, ctx.federation);
631
- });
632
- esm_default.get("https://example.com/.well-known/nodeinfo", (cl) => {
633
- const headers = cl.options.headers ?? {};
634
- assertEquals(new Headers(headers).get("User-Agent"), "CustomUserAgent/1.2.3");
635
- return new Response(JSON.stringify({ links: [{
636
- rel: "http://nodeinfo.diaspora.software/ns/schema/2.1",
637
- href: "https://example.com/nodeinfo/2.1"
638
- }] }));
639
- });
640
- esm_default.get("https://example.com/nodeinfo/2.1", (cl) => {
641
- const headers = cl.options.headers ?? {};
642
- assertEquals(new Headers(headers).get("User-Agent"), "CustomUserAgent/1.2.3");
643
- return new Response(JSON.stringify({
644
- software: {
645
- name: "foo",
646
- version: "1.2.3"
647
- },
648
- protocols: ["activitypub", "diaspora"],
649
- usage: {
650
- users: {},
651
- localPosts: 123,
652
- localComments: 456
653
- }
654
- }));
655
- });
656
- await t.step("Context.lookupNodeInfo()", async () => {
657
- const federation = createFederation({
658
- kv,
659
- userAgent: "CustomUserAgent/1.2.3"
660
- });
661
- const ctx = federation.createContext(new URL("https://example.com/"), 123);
662
- const nodeInfo = await ctx.lookupNodeInfo("https://example.com/");
663
- assertEquals(nodeInfo, {
664
- software: {
665
- name: "foo",
666
- version: {
667
- major: 1,
668
- minor: 2,
669
- patch: 3,
670
- build: [],
671
- prerelease: []
672
- }
673
- },
674
- protocols: ["activitypub", "diaspora"],
675
- usage: {
676
- users: {},
677
- localPosts: 123,
678
- localComments: 456
679
- }
680
- });
681
- const rawNodeInfo = await ctx.lookupNodeInfo("https://example.com/", { parse: "none" });
682
- assertEquals(rawNodeInfo, {
683
- software: {
684
- name: "foo",
685
- version: "1.2.3"
686
- },
687
- protocols: ["activitypub", "diaspora"],
688
- usage: {
689
- users: {},
690
- localPosts: 123,
691
- localComments: 456
692
- }
693
- });
694
- });
695
- await t.step("RequestContext", async () => {
696
- const federation = createFederation({
697
- kv,
698
- documentLoader: mockDocumentLoader
699
- });
700
- const req = new Request("https://example.com/");
701
- const ctx = federation.createContext(req, 123);
702
- assertEquals(ctx.request, req);
703
- assertEquals(ctx.url, new URL("https://example.com/"));
704
- assertEquals(ctx.origin, "https://example.com");
705
- assertEquals(ctx.host, "example.com");
706
- assertEquals(ctx.hostname, "example.com");
707
- assertEquals(ctx.data, 123);
708
- await assertRejects(() => ctx.getActor("someone"), Error);
709
- await assertRejects(() => ctx.getObject(Note, {
710
- handle: "someone",
711
- id: "123"
712
- }), Error);
713
- assertEquals(await ctx.getSignedKey(), null);
714
- assertEquals(await ctx.getSignedKeyOwner(), null);
715
- assertEquals(await ctx.getSignedKey(), null);
716
- assertEquals(await ctx.getSignedKeyOwner(), null);
717
- await assertRejects(() => ctx.getActor("someone"), Error, "No actor dispatcher registered");
718
- const signedReq = await signRequest(new Request("https://example.com/"), rsaPrivateKey2, rsaPublicKey2.id);
719
- const signedCtx = federation.createContext(signedReq, 456);
720
- assertEquals(signedCtx.request, signedReq);
721
- assertEquals(signedCtx.url, new URL("https://example.com/"));
722
- assertEquals(signedCtx.data, 456);
723
- assertEquals(await signedCtx.getSignedKey(), rsaPublicKey2);
724
- assertEquals(await signedCtx.getSignedKeyOwner(), null);
725
- assertEquals(await signedCtx.getSignedKey(), rsaPublicKey2);
726
- assertEquals(await signedCtx.getSignedKeyOwner(), null);
727
- const signedReq2 = await signRequest(new Request("https://example.com/"), rsaPrivateKey3, rsaPublicKey3.id);
728
- const signedCtx2 = federation.createContext(signedReq2, 456);
729
- assertEquals(signedCtx2.request, signedReq2);
730
- assertEquals(signedCtx2.url, new URL("https://example.com/"));
731
- assertEquals(signedCtx2.data, 456);
732
- assertEquals(await signedCtx2.getSignedKey(), rsaPublicKey3);
733
- const expectedOwner = await lookupObject("https://example.com/person2", {
734
- documentLoader: mockDocumentLoader,
735
- contextLoader: mockDocumentLoader
736
- });
737
- assertEquals(await signedCtx2.getSignedKeyOwner(), expectedOwner);
738
- assertEquals(await signedCtx2.getSignedKey(), rsaPublicKey3);
739
- assertEquals(await signedCtx2.getSignedKeyOwner(), expectedOwner);
740
- federation.setActorDispatcher("/users/{identifier}", (_ctx, identifier) => new Person({ preferredUsername: identifier }));
741
- const ctx2 = federation.createContext(req, 789);
742
- assertEquals(ctx2.request, req);
743
- assertEquals(ctx2.url, new URL("https://example.com/"));
744
- assertEquals(ctx2.data, 789);
745
- assertEquals(await ctx2.getActor("john"), new Person({ preferredUsername: "john" }));
746
- federation.setObjectDispatcher(Note, "/users/{identifier}/notes/{id}", (_ctx, values) => {
747
- return new Note({ summary: `Note ${values.id} by ${values.identifier}` });
748
- });
749
- const ctx3 = federation.createContext(req, 123);
750
- assertEquals(ctx3.request, req);
751
- assertEquals(ctx3.url, new URL("https://example.com/"));
752
- assertEquals(ctx3.data, 123);
753
- assertEquals(await ctx2.getObject(Note, {
754
- identifier: "john",
755
- id: "123"
756
- }), new Note({ summary: "Note 123 by john" }));
757
- });
758
- await t.step("RequestContext.clone()", () => {
759
- const federation = createFederation({ kv });
760
- const req = new Request("https://example.com/");
761
- const ctx = federation.createContext(req, 123);
762
- const clone = ctx.clone(456);
763
- assertStrictEquals(clone.request, ctx.request);
764
- assertEquals(clone.url, ctx.url);
765
- assertEquals(clone.data, 456);
766
- assertEquals(clone.origin, ctx.origin);
767
- assertEquals(clone.host, ctx.host);
768
- assertEquals(clone.hostname, ctx.hostname);
769
- assertStrictEquals(clone.documentLoader, ctx.documentLoader);
770
- assertStrictEquals(clone.contextLoader, ctx.contextLoader);
771
- assertStrictEquals(clone.federation, ctx.federation);
772
- });
773
- esm_default.hardReset();
762
+ }), new Note({ summary: "Note 123 by john" }));
763
+ });
764
+ await t.step("RequestContext.clone()", () => {
765
+ const federation = createFederation({ kv });
766
+ const req = new Request("https://example.com/");
767
+ const ctx = federation.createContext(req, 123);
768
+ const clone = ctx.clone(456);
769
+ assertStrictEquals(clone.request, ctx.request);
770
+ assertEquals(clone.url, ctx.url);
771
+ assertEquals(clone.data, 456);
772
+ assertEquals(clone.origin, ctx.origin);
773
+ assertEquals(clone.host, ctx.host);
774
+ assertEquals(clone.hostname, ctx.hostname);
775
+ assertStrictEquals(clone.documentLoader, ctx.documentLoader);
776
+ assertStrictEquals(clone.contextLoader, ctx.contextLoader);
777
+ assertStrictEquals(clone.federation, ctx.federation);
778
+ });
779
+ esm_default.hardReset();
780
+ }
774
781
  });
775
782
  test("Federation.setInboxListeners()", async (t) => {
776
783
  const kv = new MemoryKvStore();
@@ -1555,70 +1562,77 @@ test("ContextImpl.sendActivity()", async (t) => {
1555
1562
  });
1556
1563
  esm_default.hardReset();
1557
1564
  });
1558
- test("ContextImpl.routeActivity()", async () => {
1559
- const federation = new FederationImpl({ kv: new MemoryKvStore() });
1560
- const activities = [];
1561
- federation.setInboxListeners("/u/{identifier}/i", "/i").on(Offer, (ctx$1, offer) => {
1562
- activities.push([ctx$1.recipient, offer]);
1563
- });
1564
- const ctx = new ContextImpl({
1565
- url: new URL("https://example.com/"),
1566
- federation,
1567
- data: void 0,
1568
- documentLoader: mockDocumentLoader,
1569
- contextLoader: fetchDocumentLoader
1570
- });
1571
- assertFalse(await ctx.routeActivity(null, new Offer({ actor: new URL("https://example.com/person") })));
1572
- assertEquals(activities, []);
1573
- const signedOffer = await signObject(new Offer({ actor: new URL("https://example.com/person2") }), ed25519PrivateKey, ed25519Multikey.id);
1574
- assert(await ctx.routeActivity(null, signedOffer));
1575
- assertEquals(activities, [[null, signedOffer]]);
1576
- const signedInvite = await signObject(new Invite({ actor: new URL("https://example.com/person2") }), ed25519PrivateKey, ed25519Multikey.id);
1577
- assert(await ctx.routeActivity("id", signedInvite));
1578
- assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1579
- assertFalse(await ctx.routeActivity(null, new Create({
1580
- id: new URL("https://example.com/not-found"),
1581
- actor: new URL("https://example.com/person")
1582
- })));
1583
- assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1584
- assertFalse(await ctx.routeActivity(null, new Create({
1585
- id: new URL("https://example.com/person"),
1586
- actor: new URL("https://example.com/person")
1587
- })));
1588
- assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1589
- assertFalse(await ctx.routeActivity(null, new Announce({
1590
- id: new URL("https://example.com/announce#diffrent-id"),
1591
- actor: new URL("https://example.com/person")
1592
- })));
1593
- assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1594
- assertFalse(await ctx.routeActivity(null, new Announce({
1595
- id: new URL("https://example.com/announce"),
1596
- actor: new URL("https://example.com/person")
1597
- })));
1598
- assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1599
- assertFalse(await ctx.routeActivity(null, new Create({
1600
- id: new URL("https://example.com/cross-origin-actor"),
1601
- actor: new URL("https://cross-origin.com/actor")
1602
- })));
1603
- assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1604
- assert(await ctx.routeActivity(null, new Create({
1605
- id: new URL("https://example.com/create"),
1606
- actor: new URL("https://example.com/person")
1607
- })));
1608
- assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1609
- assert(await ctx.routeActivity(null, new Invite({
1610
- id: new URL("https://example.com/invite"),
1611
- actor: new URL("https://example.com/person")
1612
- })));
1613
- assertEquals(activities, [
1614
- [null, signedOffer],
1615
- ["id", signedInvite],
1616
- [null, new Invite({
1565
+ test({
1566
+ name: "ContextImpl.routeActivity()",
1567
+ permissions: {
1568
+ env: true,
1569
+ read: true
1570
+ },
1571
+ async fn() {
1572
+ const federation = new FederationImpl({ kv: new MemoryKvStore() });
1573
+ const activities = [];
1574
+ federation.setInboxListeners("/u/{identifier}/i", "/i").on(Offer, (ctx$1, offer) => {
1575
+ activities.push([ctx$1.recipient, offer]);
1576
+ });
1577
+ const ctx = new ContextImpl({
1578
+ url: new URL("https://example.com/"),
1579
+ federation,
1580
+ data: void 0,
1581
+ documentLoader: mockDocumentLoader,
1582
+ contextLoader: fetchDocumentLoader
1583
+ });
1584
+ assertFalse(await ctx.routeActivity(null, new Offer({ actor: new URL("https://example.com/person") })));
1585
+ assertEquals(activities, []);
1586
+ const signedOffer = await signObject(new Offer({ actor: new URL("https://example.com/person2") }), ed25519PrivateKey, ed25519Multikey.id);
1587
+ assert(await ctx.routeActivity(null, signedOffer));
1588
+ assertEquals(activities, [[null, signedOffer]]);
1589
+ const signedInvite = await signObject(new Invite({ actor: new URL("https://example.com/person2") }), ed25519PrivateKey, ed25519Multikey.id);
1590
+ assert(await ctx.routeActivity("id", signedInvite));
1591
+ assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1592
+ assertFalse(await ctx.routeActivity(null, new Create({
1593
+ id: new URL("https://example.com/not-found"),
1594
+ actor: new URL("https://example.com/person")
1595
+ })));
1596
+ assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1597
+ assertFalse(await ctx.routeActivity(null, new Create({
1598
+ id: new URL("https://example.com/person"),
1599
+ actor: new URL("https://example.com/person")
1600
+ })));
1601
+ assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1602
+ assertFalse(await ctx.routeActivity(null, new Announce({
1603
+ id: new URL("https://example.com/announce#diffrent-id"),
1604
+ actor: new URL("https://example.com/person")
1605
+ })));
1606
+ assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1607
+ assertFalse(await ctx.routeActivity(null, new Announce({
1608
+ id: new URL("https://example.com/announce"),
1609
+ actor: new URL("https://example.com/person")
1610
+ })));
1611
+ assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1612
+ assertFalse(await ctx.routeActivity(null, new Create({
1613
+ id: new URL("https://example.com/cross-origin-actor"),
1614
+ actor: new URL("https://cross-origin.com/actor")
1615
+ })));
1616
+ assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1617
+ assert(await ctx.routeActivity(null, new Create({
1618
+ id: new URL("https://example.com/create"),
1619
+ actor: new URL("https://example.com/person")
1620
+ })));
1621
+ assertEquals(activities, [[null, signedOffer], ["id", signedInvite]]);
1622
+ assert(await ctx.routeActivity(null, new Invite({
1617
1623
  id: new URL("https://example.com/invite"),
1618
- actor: new URL("https://example.com/person"),
1619
- object: new URL("https://example.com/object")
1620
- })]
1621
- ]);
1624
+ actor: new URL("https://example.com/person")
1625
+ })));
1626
+ assertEquals(activities, [
1627
+ [null, signedOffer],
1628
+ ["id", signedInvite],
1629
+ [null, new Invite({
1630
+ id: new URL("https://example.com/invite"),
1631
+ actor: new URL("https://example.com/person"),
1632
+ object: new URL("https://example.com/object")
1633
+ })]
1634
+ ]);
1635
+ }
1622
1636
  });
1623
1637
  test("InboxContextImpl.forwardActivity()", async (t) => {
1624
1638
  esm_default.spyGlobal();