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

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,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;