@fedify/fedify 0.13.0-dev.310 → 0.13.0-dev.312

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,81 +283,36 @@ 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
  }
@@ -407,8 +322,8 @@ export class Federation {
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,7 +440,7 @@ 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;
@@ -542,10 +457,10 @@ export class Federation {
542
457
  // deno-lint-ignore no-explicit-any
543
458
  cls, path, dispatcher) {
544
459
  const routeName = `object:${cls.typeId.href}`;
545
- if (this.#router.has(routeName)) {
460
+ if (this.router.has(routeName)) {
546
461
  throw new RouterError(`Object dispatcher for ${cls.name} already set.`);
547
462
  }
548
- const variables = this.#router.add(path, routeName);
463
+ const variables = this.router.add(path, routeName);
549
464
  if (variables.size < 1) {
550
465
  throw new RouterError("Path for object dispatcher must have at least one variable.");
551
466
  }
@@ -553,8 +468,8 @@ export class Federation {
553
468
  dispatcher,
554
469
  parameters: variables,
555
470
  };
556
- this.#objectCallbacks[cls.typeId.href] = callbacks;
557
- this.#objectTypeIds[cls.typeId.href] = cls;
471
+ this.objectCallbacks[cls.typeId.href] = callbacks;
472
+ this.objectTypeIds[cls.typeId.href] = cls;
558
473
  const setters = {
559
474
  authorize(predicate) {
560
475
  callbacks.authorizePredicate = predicate;
@@ -563,38 +478,26 @@ export class Federation {
563
478
  };
564
479
  return setters;
565
480
  }
566
- /**
567
- * Registers an inbox dispatcher.
568
- *
569
- * @param path The URI path pattern for the outbox dispatcher. The syntax is
570
- * based on URI Template
571
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
572
- * must have one variable: `{handle}`, and must match the inbox
573
- * listener path.
574
- * @param dispatcher An inbox dispatcher callback to register.
575
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
576
- * @since 0.11.0
577
- */
578
481
  setInboxDispatcher(path, dispatcher) {
579
- if (this.#inboxCallbacks != null) {
482
+ if (this.inboxCallbacks != null) {
580
483
  throw new RouterError("Inbox dispatcher already set.");
581
484
  }
582
- if (this.#router.has("inbox")) {
583
- if (this.#inboxPath !== path) {
485
+ if (this.router.has("inbox")) {
486
+ if (this.inboxPath !== path) {
584
487
  throw new RouterError("Inbox dispatcher path must match inbox listener path.");
585
488
  }
586
489
  }
587
490
  else {
588
- const variables = this.#router.add(path, "inbox");
491
+ const variables = this.router.add(path, "inbox");
589
492
  if (variables.size !== 1 || !variables.has("handle")) {
590
493
  throw new RouterError("Path for inbox dispatcher must have one variable: {handle}");
591
494
  }
592
- this.#inboxPath = path;
495
+ this.inboxPath = path;
593
496
  }
594
497
  const callbacks = {
595
498
  dispatcher,
596
499
  };
597
- this.#inboxCallbacks = callbacks;
500
+ this.inboxCallbacks = callbacks;
598
501
  const setters = {
599
502
  setCounter(counter) {
600
503
  callbacks.counter = counter;
@@ -615,41 +518,18 @@ export class Federation {
615
518
  };
616
519
  return setters;
617
520
  }
618
- /**
619
- * Registers an outbox dispatcher.
620
- *
621
- * @example
622
- * ``` typescript
623
- * federation.setOutboxDispatcher(
624
- * "/users/{handle}/outbox",
625
- * async (ctx, handle, options) => {
626
- * let items: Activity[];
627
- * let nextCursor: string;
628
- * // ...
629
- * return { items, nextCursor };
630
- * }
631
- * );
632
- * ```
633
- *
634
- * @param path The URI path pattern for the outbox dispatcher. The syntax is
635
- * based on URI Template
636
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
637
- * must have one variable: `{handle}`.
638
- * @param dispatcher An outbox dispatcher callback to register.
639
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
640
- */
641
521
  setOutboxDispatcher(path, dispatcher) {
642
- if (this.#router.has("outbox")) {
522
+ if (this.router.has("outbox")) {
643
523
  throw new RouterError("Outbox dispatcher already set.");
644
524
  }
645
- const variables = this.#router.add(path, "outbox");
525
+ const variables = this.router.add(path, "outbox");
646
526
  if (variables.size !== 1 || !variables.has("handle")) {
647
527
  throw new RouterError("Path for outbox dispatcher must have one variable: {handle}");
648
528
  }
649
529
  const callbacks = {
650
530
  dispatcher,
651
531
  };
652
- this.#outboxCallbacks = callbacks;
532
+ this.outboxCallbacks = callbacks;
653
533
  const setters = {
654
534
  setCounter(counter) {
655
535
  callbacks.counter = counter;
@@ -670,29 +550,18 @@ export class Federation {
670
550
  };
671
551
  return setters;
672
552
  }
673
- /**
674
- * Registers a following collection dispatcher.
675
- * @param path The URI path pattern for the following collection. The syntax
676
- * is based on URI Template
677
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
678
- * must have one variable: `{handle}`.
679
- * @param dispatcher A following collection callback to register.
680
- * @returns An object with methods to set other following collection
681
- * callbacks.
682
- * @throws {RouterError} Thrown if the path pattern is invalid.
683
- */
684
553
  setFollowingDispatcher(path, dispatcher) {
685
- if (this.#router.has("following")) {
554
+ if (this.router.has("following")) {
686
555
  throw new RouterError("Following collection dispatcher already set.");
687
556
  }
688
- const variables = this.#router.add(path, "following");
557
+ const variables = this.router.add(path, "following");
689
558
  if (variables.size !== 1 || !variables.has("handle")) {
690
559
  throw new RouterError("Path for following collection dispatcher must have one variable: {handle}");
691
560
  }
692
561
  const callbacks = {
693
562
  dispatcher,
694
563
  };
695
- this.#followingCallbacks = callbacks;
564
+ this.followingCallbacks = callbacks;
696
565
  const setters = {
697
566
  setCounter(counter) {
698
567
  callbacks.counter = counter;
@@ -713,29 +582,18 @@ export class Federation {
713
582
  };
714
583
  return setters;
715
584
  }
716
- /**
717
- * Registers a followers collection dispatcher.
718
- * @param path The URI path pattern for the followers collection. The syntax
719
- * is based on URI Template
720
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
721
- * must have one variable: `{handle}`.
722
- * @param dispatcher A followers collection callback to register.
723
- * @returns An object with methods to set other followers collection
724
- * callbacks.
725
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
726
- */
727
585
  setFollowersDispatcher(path, dispatcher) {
728
- if (this.#router.has("followers")) {
586
+ if (this.router.has("followers")) {
729
587
  throw new RouterError("Followers collection dispatcher already set.");
730
588
  }
731
- const variables = this.#router.add(path, "followers");
589
+ const variables = this.router.add(path, "followers");
732
590
  if (variables.size !== 1 || !variables.has("handle")) {
733
591
  throw new RouterError("Path for followers collection dispatcher must have one variable: {handle}");
734
592
  }
735
593
  const callbacks = {
736
594
  dispatcher,
737
595
  };
738
- this.#followersCallbacks = callbacks;
596
+ this.followersCallbacks = callbacks;
739
597
  const setters = {
740
598
  setCounter(counter) {
741
599
  callbacks.counter = counter;
@@ -756,30 +614,18 @@ export class Federation {
756
614
  };
757
615
  return setters;
758
616
  }
759
- /**
760
- * Registers a liked collection dispatcher.
761
- * @param path The URI path pattern for the liked collection. The syntax
762
- * is based on URI Template
763
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
764
- * must have one variable: `{handle}`.
765
- * @param dispatcher A liked collection callback to register.
766
- * @returns An object with methods to set other liked collection
767
- * callbacks.
768
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
769
- * @since 0.11.0
770
- */
771
617
  setLikedDispatcher(path, dispatcher) {
772
- if (this.#router.has("liked")) {
618
+ if (this.router.has("liked")) {
773
619
  throw new RouterError("Liked collection dispatcher already set.");
774
620
  }
775
- const variables = this.#router.add(path, "liked");
621
+ const variables = this.router.add(path, "liked");
776
622
  if (variables.size !== 1 || !variables.has("handle")) {
777
623
  throw new RouterError("Path for liked collection dispatcher must have one variable: {handle}");
778
624
  }
779
625
  const callbacks = {
780
626
  dispatcher,
781
627
  };
782
- this.#likedCallbacks = callbacks;
628
+ this.likedCallbacks = callbacks;
783
629
  const setters = {
784
630
  setCounter(counter) {
785
631
  callbacks.counter = counter;
@@ -800,30 +646,18 @@ export class Federation {
800
646
  };
801
647
  return setters;
802
648
  }
803
- /**
804
- * Registers a featured collection dispatcher.
805
- * @param path The URI path pattern for the featured collection. The syntax
806
- * is based on URI Template
807
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
808
- * must have one variable: `{handle}`.
809
- * @param dispatcher A featured collection callback to register.
810
- * @returns An object with methods to set other featured collection
811
- * callbacks.
812
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
813
- * @since 0.11.0
814
- */
815
649
  setFeaturedDispatcher(path, dispatcher) {
816
- if (this.#router.has("featured")) {
650
+ if (this.router.has("featured")) {
817
651
  throw new RouterError("Featured collection dispatcher already set.");
818
652
  }
819
- const variables = this.#router.add(path, "featured");
653
+ const variables = this.router.add(path, "featured");
820
654
  if (variables.size !== 1 || !variables.has("handle")) {
821
655
  throw new RouterError("Path for featured collection dispatcher must have one variable: {handle}");
822
656
  }
823
657
  const callbacks = {
824
658
  dispatcher,
825
659
  };
826
- this.#featuredCallbacks = callbacks;
660
+ this.featuredCallbacks = callbacks;
827
661
  const setters = {
828
662
  setCounter(counter) {
829
663
  callbacks.counter = counter;
@@ -844,23 +678,11 @@ export class Federation {
844
678
  };
845
679
  return setters;
846
680
  }
847
- /**
848
- * Registers a featured tags collection dispatcher.
849
- * @param path The URI path pattern for the featured tags collection.
850
- * The syntax is based on URI Template
851
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
852
- * must have one variable: `{handle}`.
853
- * @param dispatcher A featured tags collection callback to register.
854
- * @returns An object with methods to set other featured tags collection
855
- * callbacks.
856
- * @throws {@link RouterError} Thrown if the path pattern is invalid.
857
- * @since 0.11.0
858
- */
859
681
  setFeaturedTagsDispatcher(path, dispatcher) {
860
- if (this.#router.has("featuredTags")) {
682
+ if (this.router.has("featuredTags")) {
861
683
  throw new RouterError("Featured tags collection dispatcher already set.");
862
684
  }
863
- const variables = this.#router.add(path, "featuredTags");
685
+ const variables = this.router.add(path, "featuredTags");
864
686
  if (variables.size !== 1 || !variables.has("handle")) {
865
687
  throw new RouterError("Path for featured tags collection dispatcher must have one " +
866
688
  "variable: {handle}");
@@ -868,7 +690,7 @@ export class Federation {
868
690
  const callbacks = {
869
691
  dispatcher,
870
692
  };
871
- this.#featuredTagsCallbacks = callbacks;
693
+ this.featuredTagsCallbacks = callbacks;
872
694
  const setters = {
873
695
  setCounter(counter) {
874
696
  callbacks.counter = counter;
@@ -889,59 +711,29 @@ export class Federation {
889
711
  };
890
712
  return setters;
891
713
  }
892
- /**
893
- * Assigns the URL path for the inbox and starts setting inbox listeners.
894
- *
895
- * @example
896
- * ``` typescript
897
- * federation
898
- * .setInboxListeners("/users/{handle/inbox", "/inbox")
899
- * .on(Follow, async (ctx, follow) => {
900
- * const from = await follow.getActor(ctx);
901
- * if (!isActor(from)) return;
902
- * // ...
903
- * await ctx.sendActivity({ })
904
- * })
905
- * .on(Undo, async (ctx, undo) => {
906
- * // ...
907
- * });
908
- * ```
909
- *
910
- * @param inboxPath The URI path pattern for the inbox. The syntax is based
911
- * on URI Template
912
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
913
- * The path must have one variable: `{handle}`, and must
914
- * match the inbox dispatcher path.
915
- * @param sharedInboxPath An optional URI path pattern for the shared inbox.
916
- * The syntax is based on URI Template
917
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
918
- * The path must have no variables.
919
- * @returns An object to register inbox listeners.
920
- * @throws {RouteError} Thrown if the path pattern is invalid.
921
- */
922
714
  setInboxListeners(inboxPath, sharedInboxPath) {
923
- if (this.#inboxListeners != null) {
715
+ if (this.inboxListeners != null) {
924
716
  throw new RouterError("Inbox listeners already set.");
925
717
  }
926
- if (this.#router.has("inbox")) {
927
- if (this.#inboxPath !== inboxPath) {
718
+ if (this.router.has("inbox")) {
719
+ if (this.inboxPath !== inboxPath) {
928
720
  throw new RouterError("Inbox listener path must match inbox dispatcher path.");
929
721
  }
930
722
  }
931
723
  else {
932
- const variables = this.#router.add(inboxPath, "inbox");
724
+ const variables = this.router.add(inboxPath, "inbox");
933
725
  if (variables.size !== 1 || !variables.has("handle")) {
934
726
  throw new RouterError("Path for inbox must have one variable: {handle}");
935
727
  }
936
- this.#inboxPath = inboxPath;
728
+ this.inboxPath = inboxPath;
937
729
  }
938
730
  if (sharedInboxPath != null) {
939
- const siVars = this.#router.add(sharedInboxPath, "sharedInbox");
731
+ const siVars = this.router.add(sharedInboxPath, "sharedInbox");
940
732
  if (siVars.size !== 0) {
941
733
  throw new RouterError("Path for shared inbox must have no variables.");
942
734
  }
943
735
  }
944
- const listeners = this.#inboxListeners = new InboxListenerSet();
736
+ const listeners = this.inboxListeners = new InboxListenerSet();
945
737
  const setters = {
946
738
  on(
947
739
  // deno-lint-ignore no-explicit-any
@@ -950,27 +742,16 @@ export class Federation {
950
742
  return setters;
951
743
  },
952
744
  onError: (handler) => {
953
- this.#inboxErrorHandler = handler;
745
+ this.inboxErrorHandler = handler;
954
746
  return setters;
955
747
  },
956
748
  setSharedKeyDispatcher: (dispatcher) => {
957
- this.#sharedInboxKeyDispatcher = dispatcher;
749
+ this.sharedInboxKeyDispatcher = dispatcher;
958
750
  return setters;
959
751
  },
960
752
  };
961
753
  return setters;
962
754
  }
963
- /**
964
- * Sends an activity to recipients' inboxes. You would typically use
965
- * {@link Context.sendActivity} instead of this method.
966
- *
967
- * @param keys The sender's key pairs.
968
- * @param recipients The recipients of the activity.
969
- * @param activity The activity to send.
970
- * @param options Options for sending the activity.
971
- * @throws {TypeError} If the activity to send does not have an actor.
972
- * @deprecated Use {@link Context.sendActivity} instead.
973
- */
974
755
  async sendActivity(keys, recipients, activity, options) {
975
756
  const logger = getLogger(["fedify", "federation", "outbox"]);
976
757
  if (!(invokedByContext in options) || !options[invokedByContext]) {
@@ -988,7 +769,7 @@ export class Federation {
988
769
  logger.error("Activity {activityId} to send does not have an actor.", { activity, activityId: activity?.id?.href });
989
770
  throw new TypeError("The activity to send must have at least one actor property.");
990
771
  }
991
- if (!this.#manuallyStartQueue)
772
+ if (!this.manuallyStartQueue)
992
773
  this.#startQueue(contextData);
993
774
  if (activity.id == null) {
994
775
  activity = activity.clone({
@@ -1005,7 +786,7 @@ export class Federation {
1005
786
  activityId: activity.id?.href,
1006
787
  activity,
1007
788
  });
1008
- if (immediate || this.#queue == null) {
789
+ if (immediate || this.queue == null) {
1009
790
  if (immediate) {
1010
791
  logger.debug("Sending activity immediately without queue since immediate option " +
1011
792
  "is set.", { activityId: activity.id?.href, activity });
@@ -1019,7 +800,7 @@ export class Federation {
1019
800
  keys,
1020
801
  activity,
1021
802
  inbox: new URL(inbox),
1022
- contextLoader: this.#contextLoader,
803
+ contextLoader: this.contextLoader,
1023
804
  headers: collectionSync == null ? undefined : new Headers({
1024
805
  "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox]),
1025
806
  }),
@@ -1035,7 +816,7 @@ export class Federation {
1035
816
  keyJwkPairs.push({ keyId: keyId.href, privateKey: privateKeyJwk });
1036
817
  }
1037
818
  const activityJson = await activity.toJsonLd({
1038
- contextLoader: this.#contextLoader,
819
+ contextLoader: this.contextLoader,
1039
820
  });
1040
821
  for (const inbox in inboxes) {
1041
822
  const message = {
@@ -1049,21 +830,9 @@ export class Federation {
1049
830
  "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox]),
1050
831
  },
1051
832
  };
1052
- this.#queue.enqueue(message);
833
+ this.queue.enqueue(message);
1053
834
  }
1054
835
  }
1055
- /**
1056
- * Handles a request related to federation. If a request is not related to
1057
- * federation, the `onNotFound` or `onNotAcceptable` callback is called.
1058
- *
1059
- * Usually, this method is called from a server's request handler or
1060
- * a web framework's middleware.
1061
- *
1062
- * @param request The request object.
1063
- * @param parameters The parameters for handling the request.
1064
- * @returns The response to the request.
1065
- * @since 0.6.0
1066
- */
1067
836
  async fetch(request, options) {
1068
837
  const response = await this.#fetch(request, options);
1069
838
  const logger = getLogger(["fedify", "federation", "http"]);
@@ -1088,7 +857,7 @@ export class Federation {
1088
857
  onNotAcceptable ??= notAcceptable;
1089
858
  onUnauthorized ??= unauthorized;
1090
859
  const url = new URL(request.url);
1091
- const route = this.#router.route(url.pathname);
860
+ const route = this.router.route(url.pathname);
1092
861
  if (route == null) {
1093
862
  const response = onNotFound(request);
1094
863
  return response instanceof Promise ? await response : response;
@@ -1099,7 +868,7 @@ export class Federation {
1099
868
  case "webfinger":
1100
869
  return await handleWebFinger(request, {
1101
870
  context,
1102
- actorDispatcher: this.#actorCallbacks?.dispatcher,
871
+ actorDispatcher: this.actorCallbacks?.dispatcher,
1103
872
  onNotFound,
1104
873
  });
1105
874
  case "nodeInfoJrd":
@@ -1107,7 +876,7 @@ export class Federation {
1107
876
  case "nodeInfo":
1108
877
  return await handleNodeInfo(request, {
1109
878
  context,
1110
- nodeInfoDispatcher: this.#nodeInfoDispatcher,
879
+ nodeInfoDispatcher: this.nodeInfoDispatcher,
1111
880
  });
1112
881
  case "actor":
1113
882
  context = this.#createContext(request, contextData, {
@@ -1116,16 +885,16 @@ export class Federation {
1116
885
  return await handleActor(request, {
1117
886
  handle: route.values.handle,
1118
887
  context,
1119
- actorDispatcher: this.#actorCallbacks?.dispatcher,
1120
- authorizePredicate: this.#actorCallbacks?.authorizePredicate,
888
+ actorDispatcher: this.actorCallbacks?.dispatcher,
889
+ authorizePredicate: this.actorCallbacks?.authorizePredicate,
1121
890
  onUnauthorized,
1122
891
  onNotFound,
1123
892
  onNotAcceptable,
1124
893
  });
1125
894
  case "object": {
1126
895
  const typeId = route.name.replace(/^object:/, "");
1127
- const callbacks = this.#objectCallbacks[typeId];
1128
- const cls = this.#objectTypeIds[typeId];
896
+ const callbacks = this.objectCallbacks[typeId];
897
+ const cls = this.objectTypeIds[typeId];
1129
898
  context = this.#createContext(request, contextData, {
1130
899
  invokedFromObjectDispatcher: { cls, values: route.values },
1131
900
  });
@@ -1144,7 +913,7 @@ export class Federation {
1144
913
  name: "outbox",
1145
914
  handle: route.values.handle,
1146
915
  context,
1147
- collectionCallbacks: this.#outboxCallbacks,
916
+ collectionCallbacks: this.outboxCallbacks,
1148
917
  onUnauthorized,
1149
918
  onNotFound,
1150
919
  onNotAcceptable,
@@ -1155,7 +924,7 @@ export class Federation {
1155
924
  name: "inbox",
1156
925
  handle: route.values.handle,
1157
926
  context,
1158
- collectionCallbacks: this.#inboxCallbacks,
927
+ collectionCallbacks: this.inboxCallbacks,
1159
928
  onUnauthorized,
1160
929
  onNotFound,
1161
930
  onNotAcceptable,
@@ -1168,8 +937,8 @@ export class Federation {
1168
937
  });
1169
938
  // falls through
1170
939
  case "sharedInbox":
1171
- if (routeName !== "inbox" && this.#sharedInboxKeyDispatcher != null) {
1172
- const identity = await this.#sharedInboxKeyDispatcher(context);
940
+ if (routeName !== "inbox" && this.sharedInboxKeyDispatcher != null) {
941
+ const identity = await this.sharedInboxKeyDispatcher(context);
1173
942
  if (identity != null) {
1174
943
  context = this.#createContext(request, contextData, {
1175
944
  documentLoader: "handle" in identity
@@ -1178,25 +947,25 @@ export class Federation {
1178
947
  });
1179
948
  }
1180
949
  }
1181
- if (!this.#manuallyStartQueue)
950
+ if (!this.manuallyStartQueue)
1182
951
  this.#startQueue(contextData);
1183
952
  return await handleInbox(request, {
1184
953
  handle: route.values.handle ?? null,
1185
954
  context,
1186
- kv: this.#kv,
1187
- kvPrefixes: this.#kvPrefixes,
1188
- actorDispatcher: this.#actorCallbacks?.dispatcher,
1189
- inboxListeners: this.#inboxListeners,
1190
- inboxErrorHandler: this.#inboxErrorHandler,
955
+ kv: this.kv,
956
+ kvPrefixes: this.kvPrefixes,
957
+ actorDispatcher: this.actorCallbacks?.dispatcher,
958
+ inboxListeners: this.inboxListeners,
959
+ inboxErrorHandler: this.inboxErrorHandler,
1191
960
  onNotFound,
1192
- signatureTimeWindow: this.#signatureTimeWindow,
961
+ signatureTimeWindow: this.signatureTimeWindow,
1193
962
  });
1194
963
  case "following":
1195
964
  return await handleCollection(request, {
1196
965
  name: "following",
1197
966
  handle: route.values.handle,
1198
967
  context,
1199
- collectionCallbacks: this.#followingCallbacks,
968
+ collectionCallbacks: this.followingCallbacks,
1200
969
  onUnauthorized,
1201
970
  onNotFound,
1202
971
  onNotAcceptable,
@@ -1215,7 +984,7 @@ export class Federation {
1215
984
  filterPredicate: baseUrl != null
1216
985
  ? ((i) => (i instanceof URL ? i.href : i.id?.href ?? "").startsWith(baseUrl))
1217
986
  : undefined,
1218
- collectionCallbacks: this.#followersCallbacks,
987
+ collectionCallbacks: this.followersCallbacks,
1219
988
  onUnauthorized,
1220
989
  onNotFound,
1221
990
  onNotAcceptable,
@@ -1226,7 +995,7 @@ export class Federation {
1226
995
  name: "liked",
1227
996
  handle: route.values.handle,
1228
997
  context,
1229
- collectionCallbacks: this.#likedCallbacks,
998
+ collectionCallbacks: this.likedCallbacks,
1230
999
  onUnauthorized,
1231
1000
  onNotFound,
1232
1001
  onNotAcceptable,
@@ -1236,7 +1005,7 @@ export class Federation {
1236
1005
  name: "featured",
1237
1006
  handle: route.values.handle,
1238
1007
  context,
1239
- collectionCallbacks: this.#featuredCallbacks,
1008
+ collectionCallbacks: this.featuredCallbacks,
1240
1009
  onUnauthorized,
1241
1010
  onNotFound,
1242
1011
  onNotAcceptable,
@@ -1246,7 +1015,7 @@ export class Federation {
1246
1015
  name: "featured tags",
1247
1016
  handle: route.values.handle,
1248
1017
  context,
1249
- collectionCallbacks: this.#featuredTagsCallbacks,
1018
+ collectionCallbacks: this.featuredTagsCallbacks,
1250
1019
  onUnauthorized,
1251
1020
  onNotFound,
1252
1021
  onNotAcceptable,
@@ -1259,59 +1028,49 @@ export class Federation {
1259
1028
  }
1260
1029
  }
1261
1030
  class ContextImpl {
1262
- #url;
1263
- #federation;
1264
- #router;
1265
- #objectTypeIds;
1266
- objectCallbacks;
1267
- actorCallbacks;
1031
+ url;
1032
+ federation;
1268
1033
  data;
1269
1034
  documentLoader;
1270
- contextLoader;
1271
- #authenticatedDocumentLoaderFactory;
1272
- #invokedFromActorKeyPairsDispatcher;
1273
- constructor({ url, federation, router, objectTypeIds, objectCallbacks, actorCallbacks, data, documentLoader, contextLoader, authenticatedDocumentLoaderFactory, invokedFromActorKeyPairsDispatcher, }) {
1274
- this.#url = url;
1275
- this.#federation = federation;
1276
- this.#router = router;
1277
- this.#objectTypeIds = objectTypeIds;
1278
- this.objectCallbacks = objectCallbacks;
1279
- this.actorCallbacks = actorCallbacks;
1035
+ invokedFromActorKeyPairsDispatcher;
1036
+ constructor({ url, federation, data, documentLoader, invokedFromActorKeyPairsDispatcher, }) {
1037
+ this.url = url;
1038
+ this.federation = federation;
1280
1039
  this.data = data;
1281
1040
  this.documentLoader = documentLoader;
1282
- this.contextLoader = contextLoader;
1283
- this.#authenticatedDocumentLoaderFactory =
1284
- authenticatedDocumentLoaderFactory;
1285
- this.#invokedFromActorKeyPairsDispatcher =
1041
+ this.invokedFromActorKeyPairsDispatcher =
1286
1042
  invokedFromActorKeyPairsDispatcher;
1287
1043
  }
1288
1044
  get hostname() {
1289
- return this.#url.hostname;
1045
+ return this.url.hostname;
1290
1046
  }
1291
1047
  get host() {
1292
- return this.#url.host;
1048
+ return this.url.host;
1293
1049
  }
1294
1050
  get origin() {
1295
- return this.#url.origin;
1051
+ return this.url.origin;
1052
+ }
1053
+ get contextLoader() {
1054
+ return this.federation.contextLoader;
1296
1055
  }
1297
1056
  getNodeInfoUri() {
1298
- const path = this.#router.build("nodeInfo", {});
1057
+ const path = this.federation.router.build("nodeInfo", {});
1299
1058
  if (path == null) {
1300
1059
  throw new RouterError("No NodeInfo dispatcher registered.");
1301
1060
  }
1302
- return new URL(path, this.#url);
1061
+ return new URL(path, this.url);
1303
1062
  }
1304
1063
  getActorUri(handle) {
1305
- const path = this.#router.build("actor", { handle });
1064
+ const path = this.federation.router.build("actor", { handle });
1306
1065
  if (path == null) {
1307
1066
  throw new RouterError("No actor dispatcher registered.");
1308
1067
  }
1309
- return new URL(path, this.#url);
1068
+ return new URL(path, this.url);
1310
1069
  }
1311
1070
  getObjectUri(
1312
1071
  // deno-lint-ignore no-explicit-any
1313
1072
  cls, values) {
1314
- const callbacks = this.objectCallbacks[cls.typeId.href];
1073
+ const callbacks = this.federation.objectCallbacks[cls.typeId.href];
1315
1074
  if (callbacks == null) {
1316
1075
  throw new RouterError("No object dispatcher registered.");
1317
1076
  }
@@ -1320,72 +1079,72 @@ class ContextImpl {
1320
1079
  throw new TypeError(`Missing parameter: ${param}`);
1321
1080
  }
1322
1081
  }
1323
- const path = this.#router.build(`object:${cls.typeId.href}`, values);
1082
+ const path = this.federation.router.build(`object:${cls.typeId.href}`, values);
1324
1083
  if (path == null) {
1325
1084
  throw new RouterError("No object dispatcher registered.");
1326
1085
  }
1327
- return new URL(path, this.#url);
1086
+ return new URL(path, this.url);
1328
1087
  }
1329
1088
  getOutboxUri(handle) {
1330
- const path = this.#router.build("outbox", { handle });
1089
+ const path = this.federation.router.build("outbox", { handle });
1331
1090
  if (path == null) {
1332
1091
  throw new RouterError("No outbox dispatcher registered.");
1333
1092
  }
1334
- return new URL(path, this.#url);
1093
+ return new URL(path, this.url);
1335
1094
  }
1336
1095
  getInboxUri(handle) {
1337
1096
  if (handle == null) {
1338
- const path = this.#router.build("sharedInbox", {});
1097
+ const path = this.federation.router.build("sharedInbox", {});
1339
1098
  if (path == null) {
1340
1099
  throw new RouterError("No shared inbox path registered.");
1341
1100
  }
1342
- return new URL(path, this.#url);
1101
+ return new URL(path, this.url);
1343
1102
  }
1344
- const path = this.#router.build("inbox", { handle });
1103
+ const path = this.federation.router.build("inbox", { handle });
1345
1104
  if (path == null) {
1346
1105
  throw new RouterError("No inbox path registered.");
1347
1106
  }
1348
- return new URL(path, this.#url);
1107
+ return new URL(path, this.url);
1349
1108
  }
1350
1109
  getFollowingUri(handle) {
1351
- const path = this.#router.build("following", { handle });
1110
+ const path = this.federation.router.build("following", { handle });
1352
1111
  if (path == null) {
1353
1112
  throw new RouterError("No following collection path registered.");
1354
1113
  }
1355
- return new URL(path, this.#url);
1114
+ return new URL(path, this.url);
1356
1115
  }
1357
1116
  getFollowersUri(handle) {
1358
- const path = this.#router.build("followers", { handle });
1117
+ const path = this.federation.router.build("followers", { handle });
1359
1118
  if (path == null) {
1360
1119
  throw new RouterError("No followers collection path registered.");
1361
1120
  }
1362
- return new URL(path, this.#url);
1121
+ return new URL(path, this.url);
1363
1122
  }
1364
1123
  getLikedUri(handle) {
1365
- const path = this.#router.build("liked", { handle });
1124
+ const path = this.federation.router.build("liked", { handle });
1366
1125
  if (path == null) {
1367
1126
  throw new RouterError("No liked collection path registered.");
1368
1127
  }
1369
- return new URL(path, this.#url);
1128
+ return new URL(path, this.url);
1370
1129
  }
1371
1130
  getFeaturedUri(handle) {
1372
- const path = this.#router.build("featured", { handle });
1131
+ const path = this.federation.router.build("featured", { handle });
1373
1132
  if (path == null) {
1374
1133
  throw new RouterError("No featured collection path registered.");
1375
1134
  }
1376
- return new URL(path, this.#url);
1135
+ return new URL(path, this.url);
1377
1136
  }
1378
1137
  getFeaturedTagsUri(handle) {
1379
- const path = this.#router.build("featuredTags", { handle });
1138
+ const path = this.federation.router.build("featuredTags", { handle });
1380
1139
  if (path == null) {
1381
1140
  throw new RouterError("No featured tags collection path registered.");
1382
1141
  }
1383
- return new URL(path, this.#url);
1142
+ return new URL(path, this.url);
1384
1143
  }
1385
1144
  parseUri(uri) {
1386
- if (uri.origin !== this.#url.origin)
1145
+ if (uri.origin !== this.url.origin)
1387
1146
  return null;
1388
- const route = this.#router.route(uri.pathname);
1147
+ const route = this.federation.router.route(uri.pathname);
1389
1148
  if (route == null)
1390
1149
  return null;
1391
1150
  else if (route.name === "actor") {
@@ -1395,7 +1154,7 @@ class ContextImpl {
1395
1154
  const typeId = route.name.replace(/^object:/, "");
1396
1155
  return {
1397
1156
  type: "object",
1398
- class: this.#objectTypeIds[typeId],
1157
+ class: this.federation.objectTypeIds[typeId],
1399
1158
  typeId: new URL(typeId),
1400
1159
  values: route.values,
1401
1160
  };
@@ -1428,12 +1187,12 @@ class ContextImpl {
1428
1187
  }
1429
1188
  async getActorKeyPairs(handle) {
1430
1189
  const logger = getLogger(["fedify", "federation", "actor"]);
1431
- if (this.#invokedFromActorKeyPairsDispatcher != null) {
1190
+ if (this.invokedFromActorKeyPairsDispatcher != null) {
1432
1191
  logger.warn("Context.getActorKeyPairs({getActorKeyPairsHandle}) method is " +
1433
1192
  "invoked from the actor key pairs dispatcher " +
1434
1193
  "({actorKeyPairsDispatcherHandle}); this may cause an infinite loop.", {
1435
1194
  getActorKeyPairsHandle: handle,
1436
- actorKeyPairsDispatcherHandle: this.#invokedFromActorKeyPairsDispatcher.handle,
1195
+ actorKeyPairsDispatcherHandle: this.invokedFromActorKeyPairsDispatcher.handle,
1437
1196
  });
1438
1197
  }
1439
1198
  let keyPairs;
@@ -1466,26 +1225,17 @@ class ContextImpl {
1466
1225
  }
1467
1226
  async getKeyPairsFromHandle(handle) {
1468
1227
  const logger = getLogger(["fedify", "federation", "actor"]);
1469
- if (this.actorCallbacks?.keyPairsDispatcher == null) {
1228
+ if (this.federation.actorCallbacks?.keyPairsDispatcher == null) {
1470
1229
  throw new Error("No actor key pairs dispatcher registered.");
1471
1230
  }
1472
- const path = this.#router.build("actor", { handle });
1231
+ const path = this.federation.router.build("actor", { handle });
1473
1232
  if (path == null) {
1474
1233
  logger.warn("No actor dispatcher registered.");
1475
1234
  return [];
1476
1235
  }
1477
- const actorUri = new URL(path, this.#url);
1478
- const keyPairs = await this.actorCallbacks?.keyPairsDispatcher(new ContextImpl({
1479
- url: this.#url,
1480
- federation: this.#federation,
1481
- router: this.#router,
1482
- objectTypeIds: this.#objectTypeIds,
1483
- objectCallbacks: this.objectCallbacks,
1484
- actorCallbacks: this.actorCallbacks,
1485
- data: this.data,
1486
- documentLoader: this.documentLoader,
1487
- contextLoader: this.contextLoader,
1488
- authenticatedDocumentLoaderFactory: this.#authenticatedDocumentLoaderFactory,
1236
+ const actorUri = new URL(path, this.url);
1237
+ const keyPairs = await this.federation.actorCallbacks?.keyPairsDispatcher(new ContextImpl({
1238
+ ...this,
1489
1239
  invokedFromActorKeyPairsDispatcher: { handle },
1490
1240
  }), handle);
1491
1241
  if (keyPairs.length < 1) {
@@ -1523,9 +1273,9 @@ class ContextImpl {
1523
1273
  const keyPair = this.getRsaKeyPairFromHandle(identity.handle);
1524
1274
  return keyPair.then((pair) => pair == null
1525
1275
  ? this.documentLoader
1526
- : this.#authenticatedDocumentLoaderFactory(pair));
1276
+ : this.federation.authenticatedDocumentLoaderFactory(pair));
1527
1277
  }
1528
- return this.#authenticatedDocumentLoaderFactory(identity);
1278
+ return this.federation.authenticatedDocumentLoaderFactory(identity);
1529
1279
  }
1530
1280
  async sendActivity(sender, recipients, activity, options = {}) {
1531
1281
  let keys;
@@ -1562,15 +1312,15 @@ class ContextImpl {
1562
1312
  for await (const recipient of this.getFollowers(sender.handle)) {
1563
1313
  expandedRecipients.push(recipient);
1564
1314
  }
1565
- const collectionId = this.#router.build("followers", sender);
1315
+ const collectionId = this.federation.router.build("followers", sender);
1566
1316
  opts.collectionSync = collectionId == null
1567
1317
  ? undefined
1568
- : new URL(collectionId, this.#url).href;
1318
+ : new URL(collectionId, this.url).href;
1569
1319
  }
1570
1320
  else {
1571
1321
  expandedRecipients = [recipients];
1572
1322
  }
1573
- return await this.#federation.sendActivity(keys, expandedRecipients, activity, opts);
1323
+ return await this.federation.sendActivity(keys, expandedRecipients, activity, opts);
1574
1324
  }
1575
1325
  getFollowers(_handle) {
1576
1326
  throw new Error('"followers" recipients are not supported in Context. ' +
@@ -1578,39 +1328,33 @@ class ContextImpl {
1578
1328
  }
1579
1329
  }
1580
1330
  class RequestContextImpl extends ContextImpl {
1581
- #options;
1582
- #followersCallbacks;
1583
- #signatureTimeWindow;
1584
1331
  #invokedFromActorDispatcher;
1585
1332
  #invokedFromObjectDispatcher;
1586
1333
  request;
1587
1334
  url;
1588
1335
  constructor(options) {
1589
1336
  super(options);
1590
- this.#options = options;
1591
- this.#followersCallbacks = options.followersCallbacks;
1592
- this.#signatureTimeWindow = options.signatureTimeWindow;
1593
1337
  this.#invokedFromActorDispatcher = options.invokedFromActorDispatcher;
1594
1338
  this.#invokedFromObjectDispatcher = options.invokedFromObjectDispatcher;
1595
1339
  this.request = options.request;
1596
1340
  this.url = options.url;
1597
1341
  }
1598
1342
  async *getFollowers(handle) {
1599
- if (this.#followersCallbacks == null) {
1343
+ if (this.federation.followersCallbacks == null) {
1600
1344
  throw new Error("No followers collection dispatcher registered.");
1601
1345
  }
1602
- const result = await this.#followersCallbacks.dispatcher(this, handle, null);
1346
+ const result = await this.federation.followersCallbacks.dispatcher(this, handle, null);
1603
1347
  if (result != null) {
1604
1348
  for (const recipient of result.items)
1605
1349
  yield recipient;
1606
1350
  return;
1607
1351
  }
1608
- if (this.#followersCallbacks.firstCursor == null) {
1352
+ if (this.federation.followersCallbacks.firstCursor == null) {
1609
1353
  throw new Error("No first cursor dispatcher registered for followers collection.");
1610
1354
  }
1611
- let cursor = await this.#followersCallbacks.firstCursor(this, handle);
1355
+ let cursor = await this.federation.followersCallbacks.firstCursor(this, handle);
1612
1356
  while (cursor != null) {
1613
- const result = await this.#followersCallbacks.dispatcher(this, handle, cursor);
1357
+ const result = await this.federation.followersCallbacks.dispatcher(this, handle, cursor);
1614
1358
  if (result == null)
1615
1359
  break;
1616
1360
  for (const recipient of result.items)
@@ -1619,8 +1363,8 @@ class RequestContextImpl extends ContextImpl {
1619
1363
  }
1620
1364
  }
1621
1365
  async getActor(handle) {
1622
- if (this.actorCallbacks == null ||
1623
- this.actorCallbacks.dispatcher == null) {
1366
+ if (this.federation.actorCallbacks == null ||
1367
+ this.federation.actorCallbacks.dispatcher == null) {
1624
1368
  throw new Error("No actor dispatcher registered.");
1625
1369
  }
1626
1370
  if (this.#invokedFromActorDispatcher != null) {
@@ -1631,15 +1375,15 @@ class RequestContextImpl extends ContextImpl {
1631
1375
  actorDispatcherHandle: this.#invokedFromActorDispatcher.handle,
1632
1376
  });
1633
1377
  }
1634
- return await this.actorCallbacks.dispatcher(new RequestContextImpl({
1635
- ...this.#options,
1378
+ return await this.federation.actorCallbacks.dispatcher(new RequestContextImpl({
1379
+ ...this,
1636
1380
  invokedFromActorDispatcher: { handle },
1637
1381
  }), handle);
1638
1382
  }
1639
1383
  async getObject(
1640
1384
  // deno-lint-ignore no-explicit-any
1641
1385
  cls, values) {
1642
- const callbacks = this.objectCallbacks[cls.typeId.href];
1386
+ const callbacks = this.federation.objectCallbacks[cls.typeId.href];
1643
1387
  if (callbacks == null) {
1644
1388
  throw new Error("No object dispatcher registered.");
1645
1389
  }
@@ -1660,7 +1404,7 @@ class RequestContextImpl extends ContextImpl {
1660
1404
  });
1661
1405
  }
1662
1406
  return await callbacks.dispatcher(new RequestContextImpl({
1663
- ...this.#options,
1407
+ ...this,
1664
1408
  invokedFromObjectDispatcher: { cls, values },
1665
1409
  }), values);
1666
1410
  }
@@ -1670,7 +1414,7 @@ class RequestContextImpl extends ContextImpl {
1670
1414
  return this.#signedKey;
1671
1415
  return this.#signedKey = await verifyRequest(this.request, {
1672
1416
  ...this,
1673
- timeWindow: this.#signatureTimeWindow,
1417
+ timeWindow: this.federation.signatureTimeWindow,
1674
1418
  });
1675
1419
  }
1676
1420
  #signedKeyOwner = undefined;