@fedify/fedify 0.12.0 → 0.13.0-dev.311

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.
@@ -13,7 +13,6 @@ import { InboxListenerSet } from "./inbox.js";
13
13
  import { createExponentialBackoffPolicy } from "./retry.js";
14
14
  import { Router, RouterError } from "./router.js";
15
15
  import { extractInboxes, sendActivity } from "./send.js";
16
- const invokedByCreateFederation = Symbol("invokedByCreateFederation");
17
16
  /**
18
17
  * Create a new {@link Federation} instance.
19
18
  * @param parameters Parameters for initializing the instance.
@@ -21,65 +20,41 @@ const invokedByCreateFederation = Symbol("invokedByCreateFederation");
21
20
  * @since 0.10.0
22
21
  */
23
22
  export function createFederation(options) {
24
- return new Federation({
25
- ...options,
26
- // @ts-ignore: This is a private symbol.
27
- [invokedByCreateFederation]: true,
28
- });
23
+ return new FederationImpl(options);
29
24
  }
30
25
  const invokedByContext = Symbol("invokedByContext");
31
- /**
32
- * An object that registers federation-related business logic and dispatches
33
- * requests to the appropriate handlers.
34
- *
35
- * It also provides a middleware interface for handling requests before your
36
- * web framework's router; see {@link Federation.handle}.
37
- */
38
- export class Federation {
39
- #kv;
40
- #kvPrefixes;
41
- #queue;
42
- #queueStarted;
43
- #manuallyStartQueue;
44
- #router;
45
- #nodeInfoDispatcher;
46
- #actorCallbacks;
47
- #objectCallbacks;
48
- #objectTypeIds;
49
- #inboxPath;
50
- #inboxCallbacks;
51
- #outboxCallbacks;
52
- #followingCallbacks;
53
- #followersCallbacks;
54
- #likedCallbacks;
55
- #featuredCallbacks;
56
- #featuredTagsCallbacks;
57
- #inboxListeners;
58
- #inboxErrorHandler;
59
- #sharedInboxKeyDispatcher;
60
- #documentLoader;
61
- #contextLoader;
62
- #authenticatedDocumentLoaderFactory;
63
- #treatHttps;
64
- #onOutboxError;
65
- #signatureTimeWindow;
66
- #outboxRetryPolicy;
67
- #inboxRetryPolicy;
68
- /**
69
- * Create a new {@link Federation} instance.
70
- * @param parameters Parameters for initializing the instance.
71
- * @deprecated Use {@link createFederation} method instead.
72
- */
73
- constructor(parameters) {
74
- const options = parameters;
75
- const logger = getLogger(["fedify", "federation"]);
76
- // @ts-ignore: This is a private symbol.
77
- if (!options[invokedByCreateFederation]) {
78
- logger.warn("The Federation constructor is deprecated. Use the createFederation()" +
79
- "function instead.");
80
- }
81
- this.#kv = options.kv;
82
- this.#kvPrefixes = {
26
+ class FederationImpl {
27
+ kv;
28
+ kvPrefixes;
29
+ queue;
30
+ queueStarted;
31
+ manuallyStartQueue;
32
+ router;
33
+ nodeInfoDispatcher;
34
+ actorCallbacks;
35
+ objectCallbacks;
36
+ objectTypeIds;
37
+ inboxPath;
38
+ inboxCallbacks;
39
+ outboxCallbacks;
40
+ followingCallbacks;
41
+ followersCallbacks;
42
+ likedCallbacks;
43
+ featuredCallbacks;
44
+ featuredTagsCallbacks;
45
+ inboxListeners;
46
+ inboxErrorHandler;
47
+ sharedInboxKeyDispatcher;
48
+ documentLoader;
49
+ contextLoader;
50
+ authenticatedDocumentLoaderFactory;
51
+ onOutboxError;
52
+ signatureTimeWindow;
53
+ outboxRetryPolicy;
54
+ inboxRetryPolicy;
55
+ constructor(options) {
56
+ this.kv = options.kv;
57
+ this.kvPrefixes = {
83
58
  ...({
84
59
  activityIdempotence: ["_fedify", "activityIdempotence"],
85
60
  remoteDocument: ["_fedify", "remoteDocument"],
@@ -87,45 +62,38 @@ export class Federation {
87
62
  }),
88
63
  ...(options.kvPrefixes ?? {}),
89
64
  };
90
- this.#queue = options.queue;
91
- this.#queueStarted = false;
92
- this.#manuallyStartQueue = options.manuallyStartQueue ?? false;
93
- this.#router = new Router({
65
+ this.queue = options.queue;
66
+ this.queueStarted = false;
67
+ this.manuallyStartQueue = options.manuallyStartQueue ?? false;
68
+ this.router = new Router({
94
69
  trailingSlashInsensitive: options.trailingSlashInsensitive,
95
70
  });
96
- this.#router.add("/.well-known/webfinger", "webfinger");
97
- this.#router.add("/.well-known/nodeinfo", "nodeInfoJrd");
98
- this.#objectCallbacks = {};
99
- this.#objectTypeIds = {};
100
- this.#documentLoader = options.documentLoader ?? kvCache({
71
+ this.router.add("/.well-known/webfinger", "webfinger");
72
+ this.router.add("/.well-known/nodeinfo", "nodeInfoJrd");
73
+ this.objectCallbacks = {};
74
+ this.objectTypeIds = {};
75
+ this.documentLoader = options.documentLoader ?? kvCache({
101
76
  loader: fetchDocumentLoader,
102
77
  kv: options.kv,
103
- prefix: this.#kvPrefixes.remoteDocument,
78
+ prefix: this.kvPrefixes.remoteDocument,
104
79
  });
105
- this.#contextLoader = options.contextLoader ?? this.#documentLoader;
106
- this.#authenticatedDocumentLoaderFactory =
80
+ this.contextLoader = options.contextLoader ?? this.documentLoader;
81
+ this.authenticatedDocumentLoaderFactory =
107
82
  options.authenticatedDocumentLoaderFactory ??
108
83
  getAuthenticatedDocumentLoader;
109
- this.#onOutboxError = options.onOutboxError;
110
- this.#treatHttps = parameters.treatHttps ?? false;
111
- if (parameters.treatHttps) {
112
- logger.warn("The treatHttps option is deprecated and will be removed in " +
113
- "a future release. Instead, use the x-forwarded-fetch library" +
114
- " to recognize the X-Forwarded-Host and X-Forwarded-Proto " +
115
- "headers. See also: <https://github.com/dahlia/x-forwarded-fetch>.");
116
- }
117
- this.#signatureTimeWindow = options.signatureTimeWindow ?? { minutes: 1 };
118
- this.#outboxRetryPolicy = options.outboxRetryPolicy ??
84
+ this.onOutboxError = options.onOutboxError;
85
+ this.signatureTimeWindow = options.signatureTimeWindow ?? { minutes: 1 };
86
+ this.outboxRetryPolicy = options.outboxRetryPolicy ??
119
87
  createExponentialBackoffPolicy();
120
- this.#inboxRetryPolicy = options.inboxRetryPolicy ??
88
+ this.inboxRetryPolicy = options.inboxRetryPolicy ??
121
89
  createExponentialBackoffPolicy();
122
90
  }
123
91
  #startQueue(ctxData) {
124
- if (this.#queue != null && !this.#queueStarted) {
92
+ if (this.queue != null && !this.queueStarted) {
125
93
  const logger = getLogger(["fedify", "federation", "queue"]);
126
94
  logger.debug("Starting a task queue.");
127
- this.#queue?.listen((msg) => this.#listenQueue(ctxData, msg));
128
- this.#queueStarted = true;
95
+ this.queue?.listen((msg) => this.#listenQueue(ctxData, msg));
96
+ this.queueStarted = true;
129
97
  }
130
98
  }
131
99
  async #listenQueue(ctxData, message) {
@@ -161,35 +129,35 @@ export class Federation {
161
129
  keys.push(pair);
162
130
  }
163
131
  const documentLoader = rsaKeyPair == null
164
- ? this.#documentLoader
165
- : this.#authenticatedDocumentLoaderFactory(rsaKeyPair);
132
+ ? this.documentLoader
133
+ : this.authenticatedDocumentLoaderFactory(rsaKeyPair);
166
134
  activity = await Activity.fromJsonLd(message.activity, {
167
135
  documentLoader,
168
- contextLoader: this.#contextLoader,
136
+ contextLoader: this.contextLoader,
169
137
  });
170
138
  await sendActivity({
171
139
  keys,
172
140
  activity,
173
141
  inbox: new URL(message.inbox),
174
- contextLoader: this.#contextLoader,
142
+ contextLoader: this.contextLoader,
175
143
  headers: new Headers(message.headers),
176
144
  });
177
145
  }
178
146
  catch (error) {
179
147
  try {
180
- this.#onOutboxError?.(error, activity);
148
+ this.onOutboxError?.(error, activity);
181
149
  }
182
150
  catch (error) {
183
151
  logger.error("An unexpected error occurred in onError handler:\n{error}", { ...logData, error, activityId: activity?.id?.href });
184
152
  }
185
- const delay = this.#outboxRetryPolicy({
153
+ const delay = this.outboxRetryPolicy({
186
154
  elapsedTime: dntShim.Temporal.Instant.from(message.started).until(dntShim.Temporal.Now.instant()),
187
155
  attempts: message.attempt,
188
156
  });
189
157
  if (delay != null) {
190
158
  logger.error("Failed to send activity {activityId} to {inbox} (attempt " +
191
159
  "#{attempt}); retry...:\n{error}", { ...logData, error, activityId: activity?.id?.href });
192
- this.#queue?.enqueue({
160
+ this.queue?.enqueue({
193
161
  ...message,
194
162
  attempt: message.attempt + 1,
195
163
  }, {
@@ -217,8 +185,8 @@ export class Federation {
217
185
  }),
218
186
  });
219
187
  }
220
- else if (this.#sharedInboxKeyDispatcher != null) {
221
- const identity = await this.#sharedInboxKeyDispatcher(context);
188
+ else if (this.sharedInboxKeyDispatcher != null) {
189
+ const identity = await this.sharedInboxKeyDispatcher(context);
222
190
  if (identity != null) {
223
191
  context = this.#createContext(baseUrl, ctxData, {
224
192
  documentLoader: "handle" in identity
@@ -229,11 +197,11 @@ export class Federation {
229
197
  }
230
198
  const activity = await Activity.fromJsonLd(message.activity, context);
231
199
  const cacheKey = activity.id == null ? null : [
232
- ...this.#kvPrefixes.activityIdempotence,
200
+ ...this.kvPrefixes.activityIdempotence,
233
201
  activity.id.href,
234
202
  ];
235
203
  if (cacheKey != null) {
236
- const cached = await this.#kv.get(cacheKey);
204
+ const cached = await this.kv.get(cacheKey);
237
205
  if (cached === true) {
238
206
  logger.debug("Activity {activityId} has already been processed.", {
239
207
  activityId: activity.id?.href,
@@ -242,7 +210,7 @@ export class Federation {
242
210
  return;
243
211
  }
244
212
  }
245
- const listener = this.#inboxListeners?.dispatch(activity);
213
+ const listener = this.inboxListeners?.dispatch(activity);
246
214
  if (listener == null) {
247
215
  logger.error("Unsupported activity type:\n{activity}", { activity: message.activity, trial: message.attempt });
248
216
  return;
@@ -252,7 +220,7 @@ export class Federation {
252
220
  }
253
221
  catch (error) {
254
222
  try {
255
- await this.#inboxErrorHandler?.(context, error);
223
+ await this.inboxErrorHandler?.(context, error);
256
224
  }
257
225
  catch (error) {
258
226
  logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
@@ -262,7 +230,7 @@ export class Federation {
262
230
  activity: message.activity,
263
231
  });
264
232
  }
265
- const delay = this.#inboxRetryPolicy({
233
+ const delay = this.inboxRetryPolicy({
266
234
  elapsedTime: dntShim.Temporal.Instant.from(message.started).until(dntShim.Temporal.Now.instant()),
267
235
  attempts: message.attempt,
268
236
  });
@@ -274,7 +242,7 @@ export class Federation {
274
242
  activityId: activity.id?.href,
275
243
  activity: message.activity,
276
244
  });
277
- this.#queue?.enqueue({
245
+ this.queue?.enqueue({
278
246
  ...message,
279
247
  attempt: message.attempt + 1,
280
248
  }, {
@@ -290,20 +258,12 @@ export class Federation {
290
258
  return;
291
259
  }
292
260
  if (cacheKey != null) {
293
- await this.#kv.set(cacheKey, true, {
261
+ await this.kv.set(cacheKey, true, {
294
262
  ttl: dntShim.Temporal.Duration.from({ days: 1 }),
295
263
  });
296
264
  }
297
265
  logger.info("Activity {activityId} has been processed.", { activityId: activity.id?.href, activity: message.activity });
298
266
  }
299
- /**
300
- * Manually start the task queue.
301
- *
302
- * This method is useful when you set the `manuallyStartQueue` option to
303
- * `true` in the {@link createFederation} function.
304
- * @param contextData The context data to pass to the context.
305
- * @since 0.12.0
306
- */
307
267
  startQueue(contextData) {
308
268
  this.#startQueue(contextData);
309
269
  return Promise.resolve();
@@ -323,92 +283,47 @@ export class Federation {
323
283
  url.hash = "";
324
284
  url.search = "";
325
285
  }
326
- if (this.#treatHttps)
327
- url.protocol = "https:";
328
286
  const ctxOptions = {
329
287
  url,
330
288
  federation: this,
331
- router: this.#router,
332
- objectTypeIds: this.#objectTypeIds,
333
- objectCallbacks: this.#objectCallbacks,
334
- actorCallbacks: this.#actorCallbacks,
335
289
  data: contextData,
336
- documentLoader: opts.documentLoader ?? this.#documentLoader,
337
- contextLoader: this.#contextLoader,
338
- authenticatedDocumentLoaderFactory: this.#authenticatedDocumentLoaderFactory,
290
+ documentLoader: opts.documentLoader ?? this.documentLoader,
339
291
  };
340
292
  if (request == null)
341
293
  return new ContextImpl(ctxOptions);
342
294
  return new RequestContextImpl({
343
295
  ...ctxOptions,
344
296
  request,
345
- signatureTimeWindow: this.#signatureTimeWindow,
346
- followersCallbacks: this.#followersCallbacks,
347
297
  invokedFromActorDispatcher: opts.invokedFromActorDispatcher,
348
298
  invokedFromObjectDispatcher: opts.invokedFromObjectDispatcher,
349
299
  });
350
300
  }
351
- /**
352
- * Registers a NodeInfo dispatcher.
353
- * @param path The URI path pattern for the NodeInfo dispatcher. The syntax
354
- * is based on URI Template
355
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
356
- * must have no variables.
357
- * @param dispatcher A NodeInfo dispatcher callback to register.
358
- * @throws {RouterError} Thrown if the path pattern is invalid.
359
- * @since 0.2.0
360
- */
361
301
  setNodeInfoDispatcher(path, dispatcher) {
362
- if (this.#router.has("nodeInfo")) {
302
+ if (this.router.has("nodeInfo")) {
363
303
  throw new RouterError("NodeInfo dispatcher already set.");
364
304
  }
365
- const variables = this.#router.add(path, "nodeInfo");
305
+ const variables = this.router.add(path, "nodeInfo");
366
306
  if (variables.size !== 0) {
367
307
  throw new RouterError("Path for NodeInfo dispatcher must have no variables.");
368
308
  }
369
- this.#nodeInfoDispatcher = dispatcher;
309
+ this.nodeInfoDispatcher = dispatcher;
370
310
  }
371
- /**
372
- * Registers an actor dispatcher.
373
- *
374
- * @example
375
- * ``` typescript
376
- * federation.setActorDispatcher(
377
- * "/users/{handle}",
378
- * async (ctx, handle) => {
379
- * return new Person({
380
- * id: ctx.getActorUri(handle),
381
- * preferredUsername: handle,
382
- * // ...
383
- * });
384
- * }
385
- * );
386
- * ```
387
- *
388
- * @param path The URI path pattern for the actor dispatcher. The syntax is
389
- * based on URI Template
390
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
391
- * must have one variable: `{handle}`.
392
- * @param dispatcher An actor dispatcher callback to register.
393
- * @returns An object with methods to set other actor dispatcher callbacks.
394
- * @throws {RouterError} Thrown if the path pattern is invalid.
395
- */
396
311
  setActorDispatcher(path, dispatcher) {
397
- if (this.#router.has("actor")) {
312
+ if (this.router.has("actor")) {
398
313
  throw new RouterError("Actor dispatcher already set.");
399
314
  }
400
- const variables = this.#router.add(path, "actor");
315
+ const variables = this.router.add(path, "actor");
401
316
  if (variables.size !== 1 || !variables.has("handle")) {
402
317
  throw new RouterError("Path for actor dispatcher must have one variable: {handle}");
403
318
  }
404
319
  const callbacks = {
405
- dispatcher: async (context, handle, key) => {
406
- const actor = await dispatcher(context, handle, key);
320
+ dispatcher: async (context, handle) => {
321
+ const actor = await dispatcher(context, handle);
407
322
  if (actor == null)
408
323
  return null;
409
324
  const logger = getLogger(["fedify", "federation", "actor"]);
410
- if (this.#followingCallbacks != null &&
411
- this.#followingCallbacks.dispatcher != null) {
325
+ if (this.followingCallbacks != null &&
326
+ this.followingCallbacks.dispatcher != null) {
412
327
  if (actor.followingId == null) {
413
328
  logger.warn("You configured a following collection dispatcher, but the " +
414
329
  "actor does not have a following property. Set the property " +
@@ -421,8 +336,8 @@ export class Federation {
421
336
  "Context.getFollowingUri(handle).");
422
337
  }
423
338
  }
424
- if (this.#followersCallbacks != null &&
425
- this.#followersCallbacks.dispatcher != null) {
339
+ if (this.followersCallbacks != null &&
340
+ this.followersCallbacks.dispatcher != null) {
426
341
  if (actor.followersId == null) {
427
342
  logger.warn("You configured a followers collection dispatcher, but the " +
428
343
  "actor does not have a followers property. Set the property " +
@@ -435,8 +350,8 @@ export class Federation {
435
350
  "Context.getFollowersUri(handle).");
436
351
  }
437
352
  }
438
- if (this.#outboxCallbacks != null &&
439
- this.#outboxCallbacks.dispatcher != null) {
353
+ if (this.outboxCallbacks != null &&
354
+ this.outboxCallbacks.dispatcher != null) {
440
355
  if (actor?.outboxId == null) {
441
356
  logger.warn("You configured an outbox collection dispatcher, but the " +
442
357
  "actor does not have an outbox property. Set the property " +
@@ -448,8 +363,8 @@ export class Federation {
448
363
  "URI. Set the property with Context.getOutboxUri(handle).");
449
364
  }
450
365
  }
451
- if (this.#likedCallbacks != null &&
452
- this.#likedCallbacks.dispatcher != null) {
366
+ if (this.likedCallbacks != null &&
367
+ this.likedCallbacks.dispatcher != null) {
453
368
  if (actor?.likedId == null) {
454
369
  logger.warn("You configured a liked collection dispatcher, but the " +
455
370
  "actor does not have a liked property. Set the property " +
@@ -461,8 +376,8 @@ export class Federation {
461
376
  "URI. Set the property with Context.getLikedUri(handle).");
462
377
  }
463
378
  }
464
- if (this.#featuredCallbacks != null &&
465
- this.#featuredCallbacks.dispatcher != null) {
379
+ if (this.featuredCallbacks != null &&
380
+ this.featuredCallbacks.dispatcher != null) {
466
381
  if (actor?.featuredId == null) {
467
382
  logger.warn("You configured a featured collection dispatcher, but the " +
468
383
  "actor does not have a featured property. Set the property " +
@@ -474,8 +389,8 @@ export class Federation {
474
389
  "URI. Set the property with Context.getFeaturedUri(handle).");
475
390
  }
476
391
  }
477
- if (this.#featuredTagsCallbacks != null &&
478
- this.#featuredTagsCallbacks.dispatcher != null) {
392
+ if (this.featuredTagsCallbacks != null &&
393
+ this.featuredTagsCallbacks.dispatcher != null) {
479
394
  if (actor?.featuredTagsId == null) {
480
395
  logger.warn("You configured a featured tags collection dispatcher, but the " +
481
396
  "actor does not have a featuredTags property. Set the property " +
@@ -488,7 +403,7 @@ export class Federation {
488
403
  "Context.getFeaturedTagsUri(handle).");
489
404
  }
490
405
  }
491
- if (this.#router.has("inbox")) {
406
+ if (this.router.has("inbox")) {
492
407
  if (actor.inboxId == null) {
493
408
  logger.warn("You configured inbox listeners, but the actor does not " +
494
409
  "have an inbox property. Set the property with " +
@@ -525,24 +440,12 @@ export class Federation {
525
440
  return actor;
526
441
  },
527
442
  };
528
- this.#actorCallbacks = callbacks;
443
+ this.actorCallbacks = callbacks;
529
444
  const setters = {
530
445
  setKeyPairsDispatcher(dispatcher) {
531
446
  callbacks.keyPairsDispatcher = dispatcher;
532
447
  return setters;
533
448
  },
534
- setKeyPairDispatcher(dispatcher) {
535
- getLogger(["fedify", "federation", "actor"]).warn("The ActorCallbackSetters.setKeyPairDispatcher() method is " +
536
- "deprecated. Use the ActorCallbackSetters.setKeyPairsDispatcher() " +
537
- "instead.");
538
- callbacks.keyPairsDispatcher = async (ctx, handle) => {
539
- const key = await dispatcher(ctx.data, handle);
540
- if (key == null)
541
- return [];
542
- return [key];
543
- };
544
- return setters;
545
- },
546
449
  authorize(predicate) {
547
450
  callbacks.authorizePredicate = predicate;
548
451
  return setters;
@@ -554,10 +457,10 @@ export class Federation {
554
457
  // deno-lint-ignore no-explicit-any
555
458
  cls, path, dispatcher) {
556
459
  const routeName = `object:${cls.typeId.href}`;
557
- if (this.#router.has(routeName)) {
460
+ if (this.router.has(routeName)) {
558
461
  throw new RouterError(`Object dispatcher for ${cls.name} already set.`);
559
462
  }
560
- const variables = this.#router.add(path, routeName);
463
+ const variables = this.router.add(path, routeName);
561
464
  if (variables.size < 1) {
562
465
  throw new RouterError("Path for object dispatcher must have at least one variable.");
563
466
  }
@@ -565,8 +468,8 @@ export class Federation {
565
468
  dispatcher,
566
469
  parameters: variables,
567
470
  };
568
- this.#objectCallbacks[cls.typeId.href] = callbacks;
569
- this.#objectTypeIds[cls.typeId.href] = cls;
471
+ this.objectCallbacks[cls.typeId.href] = callbacks;
472
+ this.objectTypeIds[cls.typeId.href] = cls;
570
473
  const setters = {
571
474
  authorize(predicate) {
572
475
  callbacks.authorizePredicate = predicate;
@@ -575,38 +478,26 @@ export class Federation {
575
478
  };
576
479
  return setters;
577
480
  }
578
- /**
579
- * Registers an inbox dispatcher.
580
- *
581
- * @param path The URI path pattern for the outbox dispatcher. The syntax is
582
- * based on URI Template
583
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
584
- * must have one variable: `{handle}`, and must match the inbox
585
- * listener path.
586
- * @param dispatcher An inbox dispatcher callback to register.
587
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
588
- * @since 0.11.0
589
- */
590
481
  setInboxDispatcher(path, dispatcher) {
591
- if (this.#inboxCallbacks != null) {
482
+ if (this.inboxCallbacks != null) {
592
483
  throw new RouterError("Inbox dispatcher already set.");
593
484
  }
594
- if (this.#router.has("inbox")) {
595
- if (this.#inboxPath !== path) {
485
+ if (this.router.has("inbox")) {
486
+ if (this.inboxPath !== path) {
596
487
  throw new RouterError("Inbox dispatcher path must match inbox listener path.");
597
488
  }
598
489
  }
599
490
  else {
600
- const variables = this.#router.add(path, "inbox");
491
+ const variables = this.router.add(path, "inbox");
601
492
  if (variables.size !== 1 || !variables.has("handle")) {
602
493
  throw new RouterError("Path for inbox dispatcher must have one variable: {handle}");
603
494
  }
604
- this.#inboxPath = path;
495
+ this.inboxPath = path;
605
496
  }
606
497
  const callbacks = {
607
498
  dispatcher,
608
499
  };
609
- this.#inboxCallbacks = callbacks;
500
+ this.inboxCallbacks = callbacks;
610
501
  const setters = {
611
502
  setCounter(counter) {
612
503
  callbacks.counter = counter;
@@ -627,41 +518,18 @@ export class Federation {
627
518
  };
628
519
  return setters;
629
520
  }
630
- /**
631
- * Registers an outbox dispatcher.
632
- *
633
- * @example
634
- * ``` typescript
635
- * federation.setOutboxDispatcher(
636
- * "/users/{handle}/outbox",
637
- * async (ctx, handle, options) => {
638
- * let items: Activity[];
639
- * let nextCursor: string;
640
- * // ...
641
- * return { items, nextCursor };
642
- * }
643
- * );
644
- * ```
645
- *
646
- * @param path The URI path pattern for the outbox dispatcher. The syntax is
647
- * based on URI Template
648
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
649
- * must have one variable: `{handle}`.
650
- * @param dispatcher An outbox dispatcher callback to register.
651
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
652
- */
653
521
  setOutboxDispatcher(path, dispatcher) {
654
- if (this.#router.has("outbox")) {
522
+ if (this.router.has("outbox")) {
655
523
  throw new RouterError("Outbox dispatcher already set.");
656
524
  }
657
- const variables = this.#router.add(path, "outbox");
525
+ const variables = this.router.add(path, "outbox");
658
526
  if (variables.size !== 1 || !variables.has("handle")) {
659
527
  throw new RouterError("Path for outbox dispatcher must have one variable: {handle}");
660
528
  }
661
529
  const callbacks = {
662
530
  dispatcher,
663
531
  };
664
- this.#outboxCallbacks = callbacks;
532
+ this.outboxCallbacks = callbacks;
665
533
  const setters = {
666
534
  setCounter(counter) {
667
535
  callbacks.counter = counter;
@@ -682,29 +550,18 @@ export class Federation {
682
550
  };
683
551
  return setters;
684
552
  }
685
- /**
686
- * Registers a following collection dispatcher.
687
- * @param path The URI path pattern for the following collection. The syntax
688
- * is based on URI Template
689
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
690
- * must have one variable: `{handle}`.
691
- * @param dispatcher A following collection callback to register.
692
- * @returns An object with methods to set other following collection
693
- * callbacks.
694
- * @throws {RouterError} Thrown if the path pattern is invalid.
695
- */
696
553
  setFollowingDispatcher(path, dispatcher) {
697
- if (this.#router.has("following")) {
554
+ if (this.router.has("following")) {
698
555
  throw new RouterError("Following collection dispatcher already set.");
699
556
  }
700
- const variables = this.#router.add(path, "following");
557
+ const variables = this.router.add(path, "following");
701
558
  if (variables.size !== 1 || !variables.has("handle")) {
702
559
  throw new RouterError("Path for following collection dispatcher must have one variable: {handle}");
703
560
  }
704
561
  const callbacks = {
705
562
  dispatcher,
706
563
  };
707
- this.#followingCallbacks = callbacks;
564
+ this.followingCallbacks = callbacks;
708
565
  const setters = {
709
566
  setCounter(counter) {
710
567
  callbacks.counter = counter;
@@ -725,29 +582,18 @@ export class Federation {
725
582
  };
726
583
  return setters;
727
584
  }
728
- /**
729
- * Registers a followers collection dispatcher.
730
- * @param path The URI path pattern for the followers collection. The syntax
731
- * is based on URI Template
732
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
733
- * must have one variable: `{handle}`.
734
- * @param dispatcher A followers collection callback to register.
735
- * @returns An object with methods to set other followers collection
736
- * callbacks.
737
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
738
- */
739
585
  setFollowersDispatcher(path, dispatcher) {
740
- if (this.#router.has("followers")) {
586
+ if (this.router.has("followers")) {
741
587
  throw new RouterError("Followers collection dispatcher already set.");
742
588
  }
743
- const variables = this.#router.add(path, "followers");
589
+ const variables = this.router.add(path, "followers");
744
590
  if (variables.size !== 1 || !variables.has("handle")) {
745
591
  throw new RouterError("Path for followers collection dispatcher must have one variable: {handle}");
746
592
  }
747
593
  const callbacks = {
748
594
  dispatcher,
749
595
  };
750
- this.#followersCallbacks = callbacks;
596
+ this.followersCallbacks = callbacks;
751
597
  const setters = {
752
598
  setCounter(counter) {
753
599
  callbacks.counter = counter;
@@ -768,30 +614,18 @@ export class Federation {
768
614
  };
769
615
  return setters;
770
616
  }
771
- /**
772
- * Registers a liked collection dispatcher.
773
- * @param path The URI path pattern for the liked collection. The syntax
774
- * is based on URI Template
775
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
776
- * must have one variable: `{handle}`.
777
- * @param dispatcher A liked collection callback to register.
778
- * @returns An object with methods to set other liked collection
779
- * callbacks.
780
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
781
- * @since 0.11.0
782
- */
783
617
  setLikedDispatcher(path, dispatcher) {
784
- if (this.#router.has("liked")) {
618
+ if (this.router.has("liked")) {
785
619
  throw new RouterError("Liked collection dispatcher already set.");
786
620
  }
787
- const variables = this.#router.add(path, "liked");
621
+ const variables = this.router.add(path, "liked");
788
622
  if (variables.size !== 1 || !variables.has("handle")) {
789
623
  throw new RouterError("Path for liked collection dispatcher must have one variable: {handle}");
790
624
  }
791
625
  const callbacks = {
792
626
  dispatcher,
793
627
  };
794
- this.#likedCallbacks = callbacks;
628
+ this.likedCallbacks = callbacks;
795
629
  const setters = {
796
630
  setCounter(counter) {
797
631
  callbacks.counter = counter;
@@ -812,30 +646,18 @@ export class Federation {
812
646
  };
813
647
  return setters;
814
648
  }
815
- /**
816
- * Registers a featured collection dispatcher.
817
- * @param path The URI path pattern for the featured collection. The syntax
818
- * is based on URI Template
819
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
820
- * must have one variable: `{handle}`.
821
- * @param dispatcher A featured collection callback to register.
822
- * @returns An object with methods to set other featured collection
823
- * callbacks.
824
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
825
- * @since 0.11.0
826
- */
827
649
  setFeaturedDispatcher(path, dispatcher) {
828
- if (this.#router.has("featured")) {
650
+ if (this.router.has("featured")) {
829
651
  throw new RouterError("Featured collection dispatcher already set.");
830
652
  }
831
- const variables = this.#router.add(path, "featured");
653
+ const variables = this.router.add(path, "featured");
832
654
  if (variables.size !== 1 || !variables.has("handle")) {
833
655
  throw new RouterError("Path for featured collection dispatcher must have one variable: {handle}");
834
656
  }
835
657
  const callbacks = {
836
658
  dispatcher,
837
659
  };
838
- this.#featuredCallbacks = callbacks;
660
+ this.featuredCallbacks = callbacks;
839
661
  const setters = {
840
662
  setCounter(counter) {
841
663
  callbacks.counter = counter;
@@ -856,23 +678,11 @@ export class Federation {
856
678
  };
857
679
  return setters;
858
680
  }
859
- /**
860
- * Registers a featured tags collection dispatcher.
861
- * @param path The URI path pattern for the featured tags collection.
862
- * The syntax is based on URI Template
863
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
864
- * must have one variable: `{handle}`.
865
- * @param dispatcher A featured tags collection callback to register.
866
- * @returns An object with methods to set other featured tags collection
867
- * callbacks.
868
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
869
- * @since 0.11.0
870
- */
871
681
  setFeaturedTagsDispatcher(path, dispatcher) {
872
- if (this.#router.has("featuredTags")) {
682
+ if (this.router.has("featuredTags")) {
873
683
  throw new RouterError("Featured tags collection dispatcher already set.");
874
684
  }
875
- const variables = this.#router.add(path, "featuredTags");
685
+ const variables = this.router.add(path, "featuredTags");
876
686
  if (variables.size !== 1 || !variables.has("handle")) {
877
687
  throw new RouterError("Path for featured tags collection dispatcher must have one " +
878
688
  "variable: {handle}");
@@ -880,7 +690,7 @@ export class Federation {
880
690
  const callbacks = {
881
691
  dispatcher,
882
692
  };
883
- this.#featuredTagsCallbacks = callbacks;
693
+ this.featuredTagsCallbacks = callbacks;
884
694
  const setters = {
885
695
  setCounter(counter) {
886
696
  callbacks.counter = counter;
@@ -901,59 +711,29 @@ export class Federation {
901
711
  };
902
712
  return setters;
903
713
  }
904
- /**
905
- * Assigns the URL path for the inbox and starts setting inbox listeners.
906
- *
907
- * @example
908
- * ``` typescript
909
- * federation
910
- * .setInboxListeners("/users/{handle/inbox", "/inbox")
911
- * .on(Follow, async (ctx, follow) => {
912
- * const from = await follow.getActor(ctx);
913
- * if (!isActor(from)) return;
914
- * // ...
915
- * await ctx.sendActivity({ })
916
- * })
917
- * .on(Undo, async (ctx, undo) => {
918
- * // ...
919
- * });
920
- * ```
921
- *
922
- * @param inboxPath The URI path pattern for the inbox. The syntax is based
923
- * on URI Template
924
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
925
- * The path must have one variable: `{handle}`, and must
926
- * match the inbox dispatcher path.
927
- * @param sharedInboxPath An optional URI path pattern for the shared inbox.
928
- * The syntax is based on URI Template
929
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
930
- * The path must have no variables.
931
- * @returns An object to register inbox listeners.
932
- * @throws {RouteError} Thrown if the path pattern is invalid.
933
- */
934
714
  setInboxListeners(inboxPath, sharedInboxPath) {
935
- if (this.#inboxListeners != null) {
715
+ if (this.inboxListeners != null) {
936
716
  throw new RouterError("Inbox listeners already set.");
937
717
  }
938
- if (this.#router.has("inbox")) {
939
- if (this.#inboxPath !== inboxPath) {
718
+ if (this.router.has("inbox")) {
719
+ if (this.inboxPath !== inboxPath) {
940
720
  throw new RouterError("Inbox listener path must match inbox dispatcher path.");
941
721
  }
942
722
  }
943
723
  else {
944
- const variables = this.#router.add(inboxPath, "inbox");
724
+ const variables = this.router.add(inboxPath, "inbox");
945
725
  if (variables.size !== 1 || !variables.has("handle")) {
946
726
  throw new RouterError("Path for inbox must have one variable: {handle}");
947
727
  }
948
- this.#inboxPath = inboxPath;
728
+ this.inboxPath = inboxPath;
949
729
  }
950
730
  if (sharedInboxPath != null) {
951
- const siVars = this.#router.add(sharedInboxPath, "sharedInbox");
731
+ const siVars = this.router.add(sharedInboxPath, "sharedInbox");
952
732
  if (siVars.size !== 0) {
953
733
  throw new RouterError("Path for shared inbox must have no variables.");
954
734
  }
955
735
  }
956
- const listeners = this.#inboxListeners = new InboxListenerSet();
736
+ const listeners = this.inboxListeners = new InboxListenerSet();
957
737
  const setters = {
958
738
  on(
959
739
  // deno-lint-ignore no-explicit-any
@@ -962,27 +742,16 @@ export class Federation {
962
742
  return setters;
963
743
  },
964
744
  onError: (handler) => {
965
- this.#inboxErrorHandler = handler;
745
+ this.inboxErrorHandler = handler;
966
746
  return setters;
967
747
  },
968
748
  setSharedKeyDispatcher: (dispatcher) => {
969
- this.#sharedInboxKeyDispatcher = dispatcher;
749
+ this.sharedInboxKeyDispatcher = dispatcher;
970
750
  return setters;
971
751
  },
972
752
  };
973
753
  return setters;
974
754
  }
975
- /**
976
- * Sends an activity to recipients' inboxes. You would typically use
977
- * {@link Context.sendActivity} instead of this method.
978
- *
979
- * @param keys The sender's key pairs.
980
- * @param recipients The recipients of the activity.
981
- * @param activity The activity to send.
982
- * @param options Options for sending the activity.
983
- * @throws {TypeError} If the activity to send does not have an actor.
984
- * @deprecated Use {@link Context.sendActivity} instead.
985
- */
986
755
  async sendActivity(keys, recipients, activity, options) {
987
756
  const logger = getLogger(["fedify", "federation", "outbox"]);
988
757
  if (!(invokedByContext in options) || !options[invokedByContext]) {
@@ -1000,7 +769,7 @@ export class Federation {
1000
769
  logger.error("Activity {activityId} to send does not have an actor.", { activity, activityId: activity?.id?.href });
1001
770
  throw new TypeError("The activity to send must have at least one actor property.");
1002
771
  }
1003
- if (!this.#manuallyStartQueue)
772
+ if (!this.manuallyStartQueue)
1004
773
  this.#startQueue(contextData);
1005
774
  if (activity.id == null) {
1006
775
  activity = activity.clone({
@@ -1017,7 +786,7 @@ export class Federation {
1017
786
  activityId: activity.id?.href,
1018
787
  activity,
1019
788
  });
1020
- if (immediate || this.#queue == null) {
789
+ if (immediate || this.queue == null) {
1021
790
  if (immediate) {
1022
791
  logger.debug("Sending activity immediately without queue since immediate option " +
1023
792
  "is set.", { activityId: activity.id?.href, activity });
@@ -1031,7 +800,7 @@ export class Federation {
1031
800
  keys,
1032
801
  activity,
1033
802
  inbox: new URL(inbox),
1034
- contextLoader: this.#contextLoader,
803
+ contextLoader: this.contextLoader,
1035
804
  headers: collectionSync == null ? undefined : new Headers({
1036
805
  "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox]),
1037
806
  }),
@@ -1047,7 +816,7 @@ export class Federation {
1047
816
  keyJwkPairs.push({ keyId: keyId.href, privateKey: privateKeyJwk });
1048
817
  }
1049
818
  const activityJson = await activity.toJsonLd({
1050
- contextLoader: this.#contextLoader,
819
+ contextLoader: this.contextLoader,
1051
820
  });
1052
821
  for (const inbox in inboxes) {
1053
822
  const message = {
@@ -1061,21 +830,9 @@ export class Federation {
1061
830
  "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox]),
1062
831
  },
1063
832
  };
1064
- this.#queue.enqueue(message);
833
+ this.queue.enqueue(message);
1065
834
  }
1066
835
  }
1067
- /**
1068
- * Handles a request related to federation. If a request is not related to
1069
- * federation, the `onNotFound` or `onNotAcceptable` callback is called.
1070
- *
1071
- * Usually, this method is called from a server's request handler or
1072
- * a web framework's middleware.
1073
- *
1074
- * @param request The request object.
1075
- * @param parameters The parameters for handling the request.
1076
- * @returns The response to the request.
1077
- * @since 0.6.0
1078
- */
1079
836
  async fetch(request, options) {
1080
837
  const response = await this.#fetch(request, options);
1081
838
  const logger = getLogger(["fedify", "federation", "http"]);
@@ -1100,7 +857,7 @@ export class Federation {
1100
857
  onNotAcceptable ??= notAcceptable;
1101
858
  onUnauthorized ??= unauthorized;
1102
859
  const url = new URL(request.url);
1103
- const route = this.#router.route(url.pathname);
860
+ const route = this.router.route(url.pathname);
1104
861
  if (route == null) {
1105
862
  const response = onNotFound(request);
1106
863
  return response instanceof Promise ? await response : response;
@@ -1111,7 +868,7 @@ export class Federation {
1111
868
  case "webfinger":
1112
869
  return await handleWebFinger(request, {
1113
870
  context,
1114
- actorDispatcher: this.#actorCallbacks?.dispatcher,
871
+ actorDispatcher: this.actorCallbacks?.dispatcher,
1115
872
  onNotFound,
1116
873
  });
1117
874
  case "nodeInfoJrd":
@@ -1119,27 +876,25 @@ export class Federation {
1119
876
  case "nodeInfo":
1120
877
  return await handleNodeInfo(request, {
1121
878
  context,
1122
- nodeInfoDispatcher: this.#nodeInfoDispatcher,
879
+ nodeInfoDispatcher: this.nodeInfoDispatcher,
1123
880
  });
1124
881
  case "actor":
1125
- // FIXME: When the deprecated last parameter (key) of ActorDispatcher
1126
- // is removed, uncomment the following line.
1127
- // context = this.#createContext(request, contextData, {
1128
- // invokedFromActorDispatcher: { handle: route.values.handle },
1129
- // });
882
+ context = this.#createContext(request, contextData, {
883
+ invokedFromActorDispatcher: { handle: route.values.handle },
884
+ });
1130
885
  return await handleActor(request, {
1131
886
  handle: route.values.handle,
1132
887
  context,
1133
- actorDispatcher: this.#actorCallbacks?.dispatcher,
1134
- authorizePredicate: this.#actorCallbacks?.authorizePredicate,
888
+ actorDispatcher: this.actorCallbacks?.dispatcher,
889
+ authorizePredicate: this.actorCallbacks?.authorizePredicate,
1135
890
  onUnauthorized,
1136
891
  onNotFound,
1137
892
  onNotAcceptable,
1138
893
  });
1139
894
  case "object": {
1140
895
  const typeId = route.name.replace(/^object:/, "");
1141
- const callbacks = this.#objectCallbacks[typeId];
1142
- const cls = this.#objectTypeIds[typeId];
896
+ const callbacks = this.objectCallbacks[typeId];
897
+ const cls = this.objectTypeIds[typeId];
1143
898
  context = this.#createContext(request, contextData, {
1144
899
  invokedFromObjectDispatcher: { cls, values: route.values },
1145
900
  });
@@ -1158,7 +913,7 @@ export class Federation {
1158
913
  name: "outbox",
1159
914
  handle: route.values.handle,
1160
915
  context,
1161
- collectionCallbacks: this.#outboxCallbacks,
916
+ collectionCallbacks: this.outboxCallbacks,
1162
917
  onUnauthorized,
1163
918
  onNotFound,
1164
919
  onNotAcceptable,
@@ -1169,7 +924,7 @@ export class Federation {
1169
924
  name: "inbox",
1170
925
  handle: route.values.handle,
1171
926
  context,
1172
- collectionCallbacks: this.#inboxCallbacks,
927
+ collectionCallbacks: this.inboxCallbacks,
1173
928
  onUnauthorized,
1174
929
  onNotFound,
1175
930
  onNotAcceptable,
@@ -1182,8 +937,8 @@ export class Federation {
1182
937
  });
1183
938
  // falls through
1184
939
  case "sharedInbox":
1185
- if (routeName !== "inbox" && this.#sharedInboxKeyDispatcher != null) {
1186
- const identity = await this.#sharedInboxKeyDispatcher(context);
940
+ if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
941
+ const identity = await this.sharedInboxKeyDispatcher(context);
1187
942
  if (identity != null) {
1188
943
  context = this.#createContext(request, contextData, {
1189
944
  documentLoader: "handle" in identity
@@ -1192,25 +947,25 @@ export class Federation {
1192
947
  });
1193
948
  }
1194
949
  }
1195
- if (!this.#manuallyStartQueue)
950
+ if (!this.manuallyStartQueue)
1196
951
  this.#startQueue(contextData);
1197
952
  return await handleInbox(request, {
1198
953
  handle: route.values.handle ?? null,
1199
954
  context,
1200
- kv: this.#kv,
1201
- kvPrefixes: this.#kvPrefixes,
1202
- actorDispatcher: this.#actorCallbacks?.dispatcher,
1203
- inboxListeners: this.#inboxListeners,
1204
- inboxErrorHandler: this.#inboxErrorHandler,
955
+ kv: this.kv,
956
+ kvPrefixes: this.kvPrefixes,
957
+ actorDispatcher: this.actorCallbacks?.dispatcher,
958
+ inboxListeners: this.inboxListeners,
959
+ inboxErrorHandler: this.inboxErrorHandler,
1205
960
  onNotFound,
1206
- signatureTimeWindow: this.#signatureTimeWindow,
961
+ signatureTimeWindow: this.signatureTimeWindow,
1207
962
  });
1208
963
  case "following":
1209
964
  return await handleCollection(request, {
1210
965
  name: "following",
1211
966
  handle: route.values.handle,
1212
967
  context,
1213
- collectionCallbacks: this.#followingCallbacks,
968
+ collectionCallbacks: this.followingCallbacks,
1214
969
  onUnauthorized,
1215
970
  onNotFound,
1216
971
  onNotAcceptable,
@@ -1229,7 +984,7 @@ export class Federation {
1229
984
  filterPredicate: baseUrl != null
1230
985
  ? ((i) => (i instanceof URL ? i.href : i.id?.href ?? "").startsWith(baseUrl))
1231
986
  : undefined,
1232
- collectionCallbacks: this.#followersCallbacks,
987
+ collectionCallbacks: this.followersCallbacks,
1233
988
  onUnauthorized,
1234
989
  onNotFound,
1235
990
  onNotAcceptable,
@@ -1240,7 +995,7 @@ export class Federation {
1240
995
  name: "liked",
1241
996
  handle: route.values.handle,
1242
997
  context,
1243
- collectionCallbacks: this.#likedCallbacks,
998
+ collectionCallbacks: this.likedCallbacks,
1244
999
  onUnauthorized,
1245
1000
  onNotFound,
1246
1001
  onNotAcceptable,
@@ -1250,7 +1005,7 @@ export class Federation {
1250
1005
  name: "featured",
1251
1006
  handle: route.values.handle,
1252
1007
  context,
1253
- collectionCallbacks: this.#featuredCallbacks,
1008
+ collectionCallbacks: this.featuredCallbacks,
1254
1009
  onUnauthorized,
1255
1010
  onNotFound,
1256
1011
  onNotAcceptable,
@@ -1260,7 +1015,7 @@ export class Federation {
1260
1015
  name: "featured tags",
1261
1016
  handle: route.values.handle,
1262
1017
  context,
1263
- collectionCallbacks: this.#featuredTagsCallbacks,
1018
+ collectionCallbacks: this.featuredTagsCallbacks,
1264
1019
  onUnauthorized,
1265
1020
  onNotFound,
1266
1021
  onNotAcceptable,
@@ -1273,59 +1028,49 @@ export class Federation {
1273
1028
  }
1274
1029
  }
1275
1030
  class ContextImpl {
1276
- #url;
1277
- #federation;
1278
- #router;
1279
- #objectTypeIds;
1280
- objectCallbacks;
1281
- actorCallbacks;
1031
+ url;
1032
+ federation;
1282
1033
  data;
1283
1034
  documentLoader;
1284
- contextLoader;
1285
- #authenticatedDocumentLoaderFactory;
1286
- #invokedFromActorKeyPairsDispatcher;
1287
- constructor({ url, federation, router, objectTypeIds, objectCallbacks, actorCallbacks, data, documentLoader, contextLoader, authenticatedDocumentLoaderFactory, invokedFromActorKeyPairsDispatcher, }) {
1288
- this.#url = url;
1289
- this.#federation = federation;
1290
- this.#router = router;
1291
- this.#objectTypeIds = objectTypeIds;
1292
- this.objectCallbacks = objectCallbacks;
1293
- this.actorCallbacks = actorCallbacks;
1035
+ invokedFromActorKeyPairsDispatcher;
1036
+ constructor({ url, federation, data, documentLoader, invokedFromActorKeyPairsDispatcher, }) {
1037
+ this.url = url;
1038
+ this.federation = federation;
1294
1039
  this.data = data;
1295
1040
  this.documentLoader = documentLoader;
1296
- this.contextLoader = contextLoader;
1297
- this.#authenticatedDocumentLoaderFactory =
1298
- authenticatedDocumentLoaderFactory;
1299
- this.#invokedFromActorKeyPairsDispatcher =
1041
+ this.invokedFromActorKeyPairsDispatcher =
1300
1042
  invokedFromActorKeyPairsDispatcher;
1301
1043
  }
1302
1044
  get hostname() {
1303
- return this.#url.hostname;
1045
+ return this.url.hostname;
1304
1046
  }
1305
1047
  get host() {
1306
- return this.#url.host;
1048
+ return this.url.host;
1307
1049
  }
1308
1050
  get origin() {
1309
- return this.#url.origin;
1051
+ return this.url.origin;
1052
+ }
1053
+ get contextLoader() {
1054
+ return this.federation.contextLoader;
1310
1055
  }
1311
1056
  getNodeInfoUri() {
1312
- const path = this.#router.build("nodeInfo", {});
1057
+ const path = this.federation.router.build("nodeInfo", {});
1313
1058
  if (path == null) {
1314
1059
  throw new RouterError("No NodeInfo dispatcher registered.");
1315
1060
  }
1316
- return new URL(path, this.#url);
1061
+ return new URL(path, this.url);
1317
1062
  }
1318
1063
  getActorUri(handle) {
1319
- const path = this.#router.build("actor", { handle });
1064
+ const path = this.federation.router.build("actor", { handle });
1320
1065
  if (path == null) {
1321
1066
  throw new RouterError("No actor dispatcher registered.");
1322
1067
  }
1323
- return new URL(path, this.#url);
1068
+ return new URL(path, this.url);
1324
1069
  }
1325
1070
  getObjectUri(
1326
1071
  // deno-lint-ignore no-explicit-any
1327
1072
  cls, values) {
1328
- const callbacks = this.objectCallbacks[cls.typeId.href];
1073
+ const callbacks = this.federation.objectCallbacks[cls.typeId.href];
1329
1074
  if (callbacks == null) {
1330
1075
  throw new RouterError("No object dispatcher registered.");
1331
1076
  }
@@ -1334,72 +1079,72 @@ class ContextImpl {
1334
1079
  throw new TypeError(`Missing parameter: ${param}`);
1335
1080
  }
1336
1081
  }
1337
- const path = this.#router.build(`object:${cls.typeId.href}`, values);
1082
+ const path = this.federation.router.build(`object:${cls.typeId.href}`, values);
1338
1083
  if (path == null) {
1339
1084
  throw new RouterError("No object dispatcher registered.");
1340
1085
  }
1341
- return new URL(path, this.#url);
1086
+ return new URL(path, this.url);
1342
1087
  }
1343
1088
  getOutboxUri(handle) {
1344
- const path = this.#router.build("outbox", { handle });
1089
+ const path = this.federation.router.build("outbox", { handle });
1345
1090
  if (path == null) {
1346
1091
  throw new RouterError("No outbox dispatcher registered.");
1347
1092
  }
1348
- return new URL(path, this.#url);
1093
+ return new URL(path, this.url);
1349
1094
  }
1350
1095
  getInboxUri(handle) {
1351
1096
  if (handle == null) {
1352
- const path = this.#router.build("sharedInbox", {});
1097
+ const path = this.federation.router.build("sharedInbox", {});
1353
1098
  if (path == null) {
1354
1099
  throw new RouterError("No shared inbox path registered.");
1355
1100
  }
1356
- return new URL(path, this.#url);
1101
+ return new URL(path, this.url);
1357
1102
  }
1358
- const path = this.#router.build("inbox", { handle });
1103
+ const path = this.federation.router.build("inbox", { handle });
1359
1104
  if (path == null) {
1360
1105
  throw new RouterError("No inbox path registered.");
1361
1106
  }
1362
- return new URL(path, this.#url);
1107
+ return new URL(path, this.url);
1363
1108
  }
1364
1109
  getFollowingUri(handle) {
1365
- const path = this.#router.build("following", { handle });
1110
+ const path = this.federation.router.build("following", { handle });
1366
1111
  if (path == null) {
1367
1112
  throw new RouterError("No following collection path registered.");
1368
1113
  }
1369
- return new URL(path, this.#url);
1114
+ return new URL(path, this.url);
1370
1115
  }
1371
1116
  getFollowersUri(handle) {
1372
- const path = this.#router.build("followers", { handle });
1117
+ const path = this.federation.router.build("followers", { handle });
1373
1118
  if (path == null) {
1374
1119
  throw new RouterError("No followers collection path registered.");
1375
1120
  }
1376
- return new URL(path, this.#url);
1121
+ return new URL(path, this.url);
1377
1122
  }
1378
1123
  getLikedUri(handle) {
1379
- const path = this.#router.build("liked", { handle });
1124
+ const path = this.federation.router.build("liked", { handle });
1380
1125
  if (path == null) {
1381
1126
  throw new RouterError("No liked collection path registered.");
1382
1127
  }
1383
- return new URL(path, this.#url);
1128
+ return new URL(path, this.url);
1384
1129
  }
1385
1130
  getFeaturedUri(handle) {
1386
- const path = this.#router.build("featured", { handle });
1131
+ const path = this.federation.router.build("featured", { handle });
1387
1132
  if (path == null) {
1388
1133
  throw new RouterError("No featured collection path registered.");
1389
1134
  }
1390
- return new URL(path, this.#url);
1135
+ return new URL(path, this.url);
1391
1136
  }
1392
1137
  getFeaturedTagsUri(handle) {
1393
- const path = this.#router.build("featuredTags", { handle });
1138
+ const path = this.federation.router.build("featuredTags", { handle });
1394
1139
  if (path == null) {
1395
1140
  throw new RouterError("No featured tags collection path registered.");
1396
1141
  }
1397
- return new URL(path, this.#url);
1142
+ return new URL(path, this.url);
1398
1143
  }
1399
1144
  parseUri(uri) {
1400
- if (uri.origin !== this.#url.origin)
1145
+ if (uri.origin !== this.url.origin)
1401
1146
  return null;
1402
- const route = this.#router.route(uri.pathname);
1147
+ const route = this.federation.router.route(uri.pathname);
1403
1148
  if (route == null)
1404
1149
  return null;
1405
1150
  else if (route.name === "actor") {
@@ -1409,7 +1154,7 @@ class ContextImpl {
1409
1154
  const typeId = route.name.replace(/^object:/, "");
1410
1155
  return {
1411
1156
  type: "object",
1412
- class: this.#objectTypeIds[typeId],
1157
+ class: this.federation.objectTypeIds[typeId],
1413
1158
  typeId: new URL(typeId),
1414
1159
  values: route.values,
1415
1160
  };
@@ -1442,12 +1187,12 @@ class ContextImpl {
1442
1187
  }
1443
1188
  async getActorKeyPairs(handle) {
1444
1189
  const logger = getLogger(["fedify", "federation", "actor"]);
1445
- if (this.#invokedFromActorKeyPairsDispatcher != null) {
1190
+ if (this.invokedFromActorKeyPairsDispatcher != null) {
1446
1191
  logger.warn("Context.getActorKeyPairs({getActorKeyPairsHandle}) method is " +
1447
1192
  "invoked from the actor key pairs dispatcher " +
1448
1193
  "({actorKeyPairsDispatcherHandle}); this may cause an infinite loop.", {
1449
1194
  getActorKeyPairsHandle: handle,
1450
- actorKeyPairsDispatcherHandle: this.#invokedFromActorKeyPairsDispatcher.handle,
1195
+ actorKeyPairsDispatcherHandle: this.invokedFromActorKeyPairsDispatcher.handle,
1451
1196
  });
1452
1197
  }
1453
1198
  let keyPairs;
@@ -1480,26 +1225,17 @@ class ContextImpl {
1480
1225
  }
1481
1226
  async getKeyPairsFromHandle(handle) {
1482
1227
  const logger = getLogger(["fedify", "federation", "actor"]);
1483
- if (this.actorCallbacks?.keyPairsDispatcher == null) {
1228
+ if (this.federation.actorCallbacks?.keyPairsDispatcher == null) {
1484
1229
  throw new Error("No actor key pairs dispatcher registered.");
1485
1230
  }
1486
- const path = this.#router.build("actor", { handle });
1231
+ const path = this.federation.router.build("actor", { handle });
1487
1232
  if (path == null) {
1488
1233
  logger.warn("No actor dispatcher registered.");
1489
1234
  return [];
1490
1235
  }
1491
- const actorUri = new URL(path, this.#url);
1492
- const keyPairs = await this.actorCallbacks?.keyPairsDispatcher(new ContextImpl({
1493
- url: this.#url,
1494
- federation: this.#federation,
1495
- router: this.#router,
1496
- objectTypeIds: this.#objectTypeIds,
1497
- objectCallbacks: this.objectCallbacks,
1498
- actorCallbacks: this.actorCallbacks,
1499
- data: this.data,
1500
- documentLoader: this.documentLoader,
1501
- contextLoader: this.contextLoader,
1502
- authenticatedDocumentLoaderFactory: this.#authenticatedDocumentLoaderFactory,
1236
+ const actorUri = new URL(path, this.url);
1237
+ const keyPairs = await this.federation.actorCallbacks?.keyPairsDispatcher(new ContextImpl({
1238
+ ...this,
1503
1239
  invokedFromActorKeyPairsDispatcher: { handle },
1504
1240
  }), handle);
1505
1241
  if (keyPairs.length < 1) {
@@ -1518,24 +1254,6 @@ class ContextImpl {
1518
1254
  }
1519
1255
  return result;
1520
1256
  }
1521
- async getActorKey(handle) {
1522
- getLogger(["fedify", "federation", "actor"]).warn("Context.getActorKey() method is deprecated; " +
1523
- "use Context.getActorKeyPairs() method instead.");
1524
- let keyPair;
1525
- try {
1526
- keyPair = await this.getRsaKeyPairFromHandle(handle);
1527
- }
1528
- catch (_) {
1529
- return null;
1530
- }
1531
- if (keyPair == null)
1532
- return null;
1533
- return new CryptographicKey({
1534
- id: keyPair.keyId,
1535
- owner: this.getActorUri(handle),
1536
- publicKey: keyPair.publicKey,
1537
- });
1538
- }
1539
1257
  async getRsaKeyPairFromHandle(handle) {
1540
1258
  const keyPairs = await this.getKeyPairsFromHandle(handle);
1541
1259
  for (const keyPair of keyPairs) {
@@ -1555,9 +1273,9 @@ class ContextImpl {
1555
1273
  const keyPair = this.getRsaKeyPairFromHandle(identity.handle);
1556
1274
  return keyPair.then((pair) => pair == null
1557
1275
  ? this.documentLoader
1558
- : this.#authenticatedDocumentLoaderFactory(pair));
1276
+ : this.federation.authenticatedDocumentLoaderFactory(pair));
1559
1277
  }
1560
- return this.#authenticatedDocumentLoaderFactory(identity);
1278
+ return this.federation.authenticatedDocumentLoaderFactory(identity);
1561
1279
  }
1562
1280
  async sendActivity(sender, recipients, activity, options = {}) {
1563
1281
  let keys;
@@ -1594,15 +1312,15 @@ class ContextImpl {
1594
1312
  for await (const recipient of this.getFollowers(sender.handle)) {
1595
1313
  expandedRecipients.push(recipient);
1596
1314
  }
1597
- const collectionId = this.#router.build("followers", sender);
1315
+ const collectionId = this.federation.router.build("followers", sender);
1598
1316
  opts.collectionSync = collectionId == null
1599
1317
  ? undefined
1600
- : new URL(collectionId, this.#url).href;
1318
+ : new URL(collectionId, this.url).href;
1601
1319
  }
1602
1320
  else {
1603
1321
  expandedRecipients = [recipients];
1604
1322
  }
1605
- return await this.#federation.sendActivity(keys, expandedRecipients, activity, opts);
1323
+ return await this.federation.sendActivity(keys, expandedRecipients, activity, opts);
1606
1324
  }
1607
1325
  getFollowers(_handle) {
1608
1326
  throw new Error('"followers" recipients are not supported in Context. ' +
@@ -1610,39 +1328,33 @@ class ContextImpl {
1610
1328
  }
1611
1329
  }
1612
1330
  class RequestContextImpl extends ContextImpl {
1613
- #options;
1614
- #followersCallbacks;
1615
- #signatureTimeWindow;
1616
1331
  #invokedFromActorDispatcher;
1617
1332
  #invokedFromObjectDispatcher;
1618
1333
  request;
1619
1334
  url;
1620
1335
  constructor(options) {
1621
1336
  super(options);
1622
- this.#options = options;
1623
- this.#followersCallbacks = options.followersCallbacks;
1624
- this.#signatureTimeWindow = options.signatureTimeWindow;
1625
1337
  this.#invokedFromActorDispatcher = options.invokedFromActorDispatcher;
1626
1338
  this.#invokedFromObjectDispatcher = options.invokedFromObjectDispatcher;
1627
1339
  this.request = options.request;
1628
1340
  this.url = options.url;
1629
1341
  }
1630
1342
  async *getFollowers(handle) {
1631
- if (this.#followersCallbacks == null) {
1343
+ if (this.federation.followersCallbacks == null) {
1632
1344
  throw new Error("No followers collection dispatcher registered.");
1633
1345
  }
1634
- const result = await this.#followersCallbacks.dispatcher(this, handle, null);
1346
+ const result = await this.federation.followersCallbacks.dispatcher(this, handle, null);
1635
1347
  if (result != null) {
1636
1348
  for (const recipient of result.items)
1637
1349
  yield recipient;
1638
1350
  return;
1639
1351
  }
1640
- if (this.#followersCallbacks.firstCursor == null) {
1352
+ if (this.federation.followersCallbacks.firstCursor == null) {
1641
1353
  throw new Error("No first cursor dispatcher registered for followers collection.");
1642
1354
  }
1643
- let cursor = await this.#followersCallbacks.firstCursor(this, handle);
1355
+ let cursor = await this.federation.followersCallbacks.firstCursor(this, handle);
1644
1356
  while (cursor != null) {
1645
- const result = await this.#followersCallbacks.dispatcher(this, handle, cursor);
1357
+ const result = await this.federation.followersCallbacks.dispatcher(this, handle, cursor);
1646
1358
  if (result == null)
1647
1359
  break;
1648
1360
  for (const recipient of result.items)
@@ -1651,8 +1363,8 @@ class RequestContextImpl extends ContextImpl {
1651
1363
  }
1652
1364
  }
1653
1365
  async getActor(handle) {
1654
- if (this.actorCallbacks == null ||
1655
- this.actorCallbacks.dispatcher == null) {
1366
+ if (this.federation.actorCallbacks == null ||
1367
+ this.federation.actorCallbacks.dispatcher == null) {
1656
1368
  throw new Error("No actor dispatcher registered.");
1657
1369
  }
1658
1370
  if (this.#invokedFromActorDispatcher != null) {
@@ -1663,26 +1375,15 @@ class RequestContextImpl extends ContextImpl {
1663
1375
  actorDispatcherHandle: this.#invokedFromActorDispatcher.handle,
1664
1376
  });
1665
1377
  }
1666
- let rsaKey;
1667
- try {
1668
- rsaKey = await this.getRsaKeyPairFromHandle(handle);
1669
- }
1670
- catch (_) {
1671
- rsaKey = null;
1672
- }
1673
- return await this.actorCallbacks.dispatcher(new RequestContextImpl({
1674
- ...this.#options,
1378
+ return await this.federation.actorCallbacks.dispatcher(new RequestContextImpl({
1379
+ ...this,
1675
1380
  invokedFromActorDispatcher: { handle },
1676
- }), handle, rsaKey == null ? null : new CryptographicKey({
1677
- id: rsaKey.keyId,
1678
- owner: this.getActorUri(handle),
1679
- publicKey: rsaKey.publicKey,
1680
- }));
1381
+ }), handle);
1681
1382
  }
1682
1383
  async getObject(
1683
1384
  // deno-lint-ignore no-explicit-any
1684
1385
  cls, values) {
1685
- const callbacks = this.objectCallbacks[cls.typeId.href];
1386
+ const callbacks = this.federation.objectCallbacks[cls.typeId.href];
1686
1387
  if (callbacks == null) {
1687
1388
  throw new Error("No object dispatcher registered.");
1688
1389
  }
@@ -1703,7 +1404,7 @@ class RequestContextImpl extends ContextImpl {
1703
1404
  });
1704
1405
  }
1705
1406
  return await callbacks.dispatcher(new RequestContextImpl({
1706
- ...this.#options,
1407
+ ...this,
1707
1408
  invokedFromObjectDispatcher: { cls, values },
1708
1409
  }), values);
1709
1410
  }
@@ -1713,7 +1414,7 @@ class RequestContextImpl extends ContextImpl {
1713
1414
  return this.#signedKey;
1714
1415
  return this.#signedKey = await verifyRequest(this.request, {
1715
1416
  ...this,
1716
- timeWindow: this.#signatureTimeWindow,
1417
+ timeWindow: this.federation.signatureTimeWindow,
1717
1418
  });
1718
1419
  }
1719
1420
  #signedKeyOwner = undefined;