@fedify/fedify 2.4.0-dev.1668 → 2.4.0-dev.1727

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +1 -1
  2. package/dist/{assert-CJ1KXcvv.mjs → assert-CebeUf0C.mjs} +1 -1
  3. package/dist/assert_exists-DtzkXC47.mjs +28 -0
  4. package/dist/assert_false-3pLLLsO4.mjs +23 -0
  5. package/dist/assert_greater_or_equal-BApOTh1h.mjs +30 -0
  6. package/dist/{assert_instance_of-Q9KTBnrf.mjs → assert_instance_of-g3WcyYNR.mjs} +1 -1
  7. package/dist/{assert_not_equals-EPJPoxuf.mjs → assert_not_equals-BN7yDMWe.mjs} +1 -1
  8. package/dist/assert_rejects-wFbSPn1O.mjs +39 -0
  9. package/dist/{assert_strict_equals-Ec20AUwa.mjs → assert_strict_equals-Bpjl4Psw.mjs} +1 -1
  10. package/dist/{assert_throws-NiFfqbnH.mjs → assert_throws-BJ5wuvR2.mjs} +1 -1
  11. package/dist/{builder-iXZ5jNVg.mjs → builder-f5-YwHfj.mjs} +5 -3
  12. package/dist/{circuit-breaker-CBGyz5F7.mjs → circuit-breaker-BT7CiPbz.mjs} +191 -9
  13. package/dist/circuit-breaker-test-utils-BYIHoliq.mjs +14 -0
  14. package/dist/{client-CjF5IYQS.mjs → client-CtxvmazV.mjs} +63 -5
  15. package/dist/{collection-BIhlldqK.mjs → collection-CnnP1UAv.mjs} +1 -1
  16. package/dist/compat/mod.cjs +1 -1
  17. package/dist/compat/mod.d.cts +1 -1
  18. package/dist/compat/mod.d.ts +1 -1
  19. package/dist/compat/mod.js +1 -1
  20. package/dist/compat/outgoing-jsonld.test.mjs +3 -3
  21. package/dist/compat/public-audience.test.mjs +3 -3
  22. package/dist/compat/transformers.test.mjs +5 -5
  23. package/dist/{context-C05Rgxmu.d.cts → context-B-dsBjZ9.d.cts} +281 -7
  24. package/dist/{context-Cjnr0ig1.d.ts → context-DrLXudbA.d.ts} +281 -7
  25. package/dist/{deno-DtHcfB0f.mjs → deno-Deyoxesx.mjs} +1 -1
  26. package/dist/{docloader-0vAfF6XW.mjs → docloader-B3kuDBg9.mjs} +2 -2
  27. package/dist/{esm-yYQfPhIY.mjs → esm-BHXXx4Wx.mjs} +13 -6
  28. package/dist/federation/builder.test.mjs +18 -5
  29. package/dist/federation/circuit-breaker.test.mjs +626 -7
  30. package/dist/federation/collection.test.mjs +3 -3
  31. package/dist/federation/handler.test.mjs +14 -13
  32. package/dist/federation/idempotency.test.mjs +6 -6
  33. package/dist/federation/inbox.test.mjs +3 -3
  34. package/dist/federation/keycache.test.mjs +5 -5
  35. package/dist/federation/kv.test.mjs +3 -3
  36. package/dist/federation/metrics.test.mjs +4 -4
  37. package/dist/federation/middleware.test.mjs +37 -28
  38. package/dist/federation/mod.cjs +18 -540
  39. package/dist/federation/mod.d.cts +3 -4
  40. package/dist/federation/mod.d.ts +3 -4
  41. package/dist/federation/mod.js +1 -1
  42. package/dist/federation/mq.test.mjs +32 -5
  43. package/dist/federation/negotiation.test.mjs +4 -4
  44. package/dist/federation/retry.test.mjs +3 -3
  45. package/dist/federation/router.test.mjs +7 -7
  46. package/dist/federation/send.test.mjs +28 -26
  47. package/dist/federation/tasks/codec.test.mjs +4 -4
  48. package/dist/federation/tasks/enqueue.test.mjs +4 -4
  49. package/dist/federation/tasks/tasks.test.mjs +6 -6
  50. package/dist/federation/temporal.test.mjs +4 -4
  51. package/dist/federation/webfinger.test.mjs +74 -12
  52. package/dist/{middleware-DzIUFRO2.cjs → federation-BzRjeOky.cjs} +855 -114
  53. package/dist/{temporal-polyfill-BCdTHexd.cjs → http-AyKngJ_h.cjs} +2801 -104
  54. package/dist/{http-BbnOMQoy.js → http-Bw6s_dOB.js} +3 -3
  55. package/dist/{http-DUmWq5Pw.mjs → http-TjhZfiSN.mjs} +5 -5
  56. package/dist/{key-CM7wDnZG.mjs → key-b4kf4yZT.mjs} +2 -2
  57. package/dist/{kv-cache-zmgG1HUp.cjs → kv-cache-BTVaZrf-.cjs} +2 -4
  58. package/dist/{kv-cache-ZQ22hm44.js → kv-cache-CQsh-KUw.js} +1 -1
  59. package/dist/{kv-cache-DEXKemJ9.mjs → kv-cache-CpILvhUV.mjs} +1 -1
  60. package/dist/{ld-BttH_-8K.mjs → ld-CKujkAfG.mjs} +5 -5
  61. package/dist/{metrics-DT-CnD1g.mjs → metrics-AlCGTDrr.mjs} +2 -2
  62. package/dist/metrics-DVKYY6K1.d.cts +36 -0
  63. package/dist/metrics-DoRtI0qU.d.ts +36 -0
  64. package/dist/{middleware-DrroX3aD.mjs → middleware-C9Y5lLZN.mjs} +60 -43
  65. package/dist/{middleware-D3IAVMcT.js → middleware-CZcuedl-.js} +241 -40
  66. package/dist/{middleware-ChlYS0Af.mjs → middleware-LPbZz6-1.mjs} +1 -1
  67. package/dist/{mod-BrpVsSfY.d.cts → mod-CLHkCwLm.d.cts} +3 -3
  68. package/dist/{mod-B0hW12_O.d.cts → mod-CuDDaIIt.d.cts} +1 -1
  69. package/dist/{mod-COIAjwRS.d.ts → mod-D-IhOEOP.d.ts} +1 -1
  70. package/dist/{mod-DdONo-ep.d.cts → mod-D-abvu2C.d.cts} +1 -1
  71. package/dist/{mod-BsCE5Ihq.d.ts → mod-D6O8C7eN.d.ts} +1 -1
  72. package/dist/{mod-CNef4in0.d.ts → mod-DypxPS9H.d.ts} +3 -3
  73. package/dist/mod.cjs +24 -25
  74. package/dist/mod.d.cts +8 -9
  75. package/dist/mod.d.ts +8 -9
  76. package/dist/mod.js +7 -7
  77. package/dist/nodeinfo/client.test.mjs +64 -4
  78. package/dist/nodeinfo/handler.test.mjs +5 -5
  79. package/dist/nodeinfo/mod.cjs +1 -1
  80. package/dist/nodeinfo/mod.d.cts +1 -1
  81. package/dist/nodeinfo/mod.d.ts +1 -1
  82. package/dist/nodeinfo/mod.js +1 -1
  83. package/dist/nodeinfo/types.test.mjs +4 -4
  84. package/dist/otel/exporter.test.mjs +3 -3
  85. package/dist/otel/mod.cjs +0 -1
  86. package/dist/otel/mod.d.cts +1 -1
  87. package/dist/otel/mod.d.ts +1 -1
  88. package/dist/{outgoing-jsonld-URuqsICz.mjs → outgoing-jsonld-BQSHRLhg.mjs} +2 -2
  89. package/dist/{owner-DZALmhdl.mjs → owner-D1O8v8FB.mjs} +2 -2
  90. package/dist/{proof-CqA-2nfW.js → proof-BTBolSnd.js} +6 -6
  91. package/dist/{proof-a60oVJ_4.cjs → proof-DcSm-2eG.cjs} +10 -11
  92. package/dist/{proof-DiQ0uBal.mjs → proof-DeMR7Akd.mjs} +6 -6
  93. package/dist/{public-audience-Cr5MsnMq.mjs → public-audience--9hx7IGx.mjs} +1 -1
  94. package/dist/runtime/mod.cjs +1 -1
  95. package/dist/runtime/mod.js +1 -1
  96. package/dist/{send-DcwZnQWG.mjs → send-DG7JG280.mjs} +3 -3
  97. package/dist/sig/accept.test.mjs +1 -1
  98. package/dist/sig/http.test.mjs +37 -11
  99. package/dist/sig/key.test.mjs +6 -6
  100. package/dist/sig/ld.test.mjs +9 -7
  101. package/dist/sig/mod.cjs +2 -2
  102. package/dist/sig/mod.d.cts +3 -3
  103. package/dist/sig/mod.d.ts +3 -3
  104. package/dist/sig/mod.js +2 -2
  105. package/dist/sig/owner.test.mjs +6 -6
  106. package/dist/sig/proof.test.mjs +10 -8
  107. package/dist/std__assert-CxFT0MNt.mjs +8 -0
  108. package/dist/{temporal-Bpxpsl2k.mjs → temporal-DA3jx8x1.mjs} +3 -3
  109. package/dist/testing/mod.d.mts +10 -0
  110. package/dist/testing/mod.mjs +2 -2
  111. package/dist/{testing-CO7ftO8A.mjs → testing-BX0Nicyq.mjs} +2 -2
  112. package/dist/{transformers-DGwl-hD1.cjs → transformers-BalCrSsr.cjs} +0 -1
  113. package/dist/{types-DC1pNgJA.js → types-Dtyf8lVj.js} +63 -5
  114. package/dist/{types-CPym83zc.cjs → types-RXm5YxpC.cjs} +62 -5
  115. package/dist/utils/docloader.test.mjs +7 -7
  116. package/dist/utils/kv-cache.test.mjs +1 -1
  117. package/dist/utils/mod.cjs +1 -1
  118. package/dist/utils/mod.d.cts +1 -1
  119. package/dist/utils/mod.d.ts +1 -1
  120. package/dist/utils/mod.js +1 -1
  121. package/package.json +7 -7
  122. package/skills/fedify/SKILL.md +462 -0
  123. package/dist/assert_rejects-EgstcQy5.mjs +0 -82
  124. package/dist/http-BpT5cE6r.cjs +0 -2694
  125. package/dist/metrics-DN13mCAw.d.cts +0 -294
  126. package/dist/metrics-v_e0n5GQ.d.ts +0 -294
  127. package/dist/std__assert-B2NnY9bq.mjs +0 -79
  128. /package/dist/{accept-8PiolDP7.mjs → accept-CPVqki78.mjs} +0 -0
  129. /package/dist/{activity-listener-BtTSxZWA.mjs → activity-listener-C-BSbKI7.mjs} +0 -0
  130. /package/dist/{assert_equals-BV7oLMxm.mjs → assert_equals-CBlRfA-_.mjs} +0 -0
  131. /package/dist/{client-CAM_bQXx.d.cts → client-D-XP_Ccb.d.cts} +0 -0
  132. /package/dist/{client-CSddvgWN.d.ts → client-D-XP_Ccb.d.ts} +0 -0
  133. /package/dist/{codec-BBga-FWI.mjs → codec-peqOdBaE.mjs} +0 -0
  134. /package/dist/{context-BJXxPElm.mjs → context-Dt36KFEJ.mjs} +0 -0
  135. /package/dist/{http-VyDTd4G3.d.cts → http-6TI0tI03.d.cts} +0 -0
  136. /package/dist/{http-lf8Hsd91.d.ts → http-CdrSn2ip.d.ts} +0 -0
  137. /package/dist/{keycache-_DHqz5z_.mjs → keycache-0Jk78XmB.mjs} +0 -0
  138. /package/dist/{keys-Dbyd7bhl.mjs → keys-DIJNHW-Y.mjs} +0 -0
  139. /package/dist/{kv-D6hNiMTK.d.ts → kv-BhNbN8Ed.d.cts} +0 -0
  140. /package/dist/{kv-gJ8LYbxX.d.cts → kv-BhNbN8Ed.d.ts} +0 -0
  141. /package/dist/{kv-CXBAok3k.mjs → kv-DCHkaJ9-.mjs} +0 -0
  142. /package/dist/{mq-Bo7Etgh6.mjs → mq-Dm1Wmtm-.mjs} +0 -0
  143. /package/dist/{negotiation-RuwrPFqi.mjs → negotiation-CCocWT_N.mjs} +0 -0
  144. /package/dist/{owner-CnngXDNJ.d.ts → owner-DGSfntI-.d.ts} +0 -0
  145. /package/dist/{owner-DEvZuyOE.d.cts → owner-r_waTiQj.d.cts} +0 -0
  146. /package/dist/{retry-DgFqeS5k.mjs → retry-zX5xw5e0.mjs} +0 -0
  147. /package/dist/{chunk-D5IdezsZ.js → rolldown-runtime-BC-Eo5Mj.js} +0 -0
  148. /package/dist/{chunk-Czpeue4M.cjs → rolldown-runtime-Dmm3t92W.cjs} +0 -0
  149. /package/dist/{transformers-DXze6FUB.js → transformers-DAtXl_Kc.js} +0 -0
  150. /package/dist/{types-CrtdVuDP.mjs → types-DE_LV1JB.mjs} +0 -0
@@ -1,9 +1,8 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { o as JsonValue, s as NodeInfo, t as GetNodeInfoOptions } from "./client-CSddvgWN.js";
3
- import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-lf8Hsd91.js";
4
- import { n as GetKeyOwnerOptions } from "./owner-CnngXDNJ.js";
5
- import { n as KvStore, t as KvKey } from "./kv-D6hNiMTK.js";
6
- import { i as MessageQueue } from "./metrics-v_e0n5GQ.js";
2
+ import { o as JsonValue, s as NodeInfo, t as GetNodeInfoOptions } from "./client-D-XP_Ccb.js";
3
+ import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-CdrSn2ip.js";
4
+ import { n as GetKeyOwnerOptions } from "./owner-DGSfntI-.js";
5
+ import { n as KvStore, t as KvKey } from "./kv-BhNbN8Ed.js";
7
6
  import { Router } from "@fedify/uri-template";
8
7
  import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab";
9
8
  import { MeterProvider, Span, Tracer, TracerProvider } from "@opentelemetry/api";
@@ -509,6 +508,16 @@ type CircuitBreakerOptions = CircuitBreakerFailurePolicy & {
509
508
  */
510
509
  readonly releaseInterval?: Temporal.Duration | Temporal.DurationLike;
511
510
  /**
511
+ * How long Fedify keeps circuit breaker state in the configured key-value
512
+ * store.
513
+ *
514
+ * When omitted, Fedify derives this from `failureWindow`, `recoveryDelay`, and
515
+ * `heldActivityTtl` for the default numeric failure policy. Custom `failure`
516
+ * callbacks do not have an inspectable time window, so custom policies do not
517
+ * expire their stored state unless this option is provided.
518
+ */
519
+ readonly stateTtl?: Temporal.Duration | Temporal.DurationLike;
520
+ /**
512
521
  * Called whenever the circuit state changes.
513
522
  */
514
523
  readonly onStateChange?: (remoteHost: string, previousState: CircuitBreakerState, newState: CircuitBreakerState) => void | Promise<void>;
@@ -527,6 +536,7 @@ interface NormalizedCircuitBreakerOptions {
527
536
  readonly recoveryDelay: Temporal.Duration;
528
537
  readonly heldActivityTtl: Temporal.Duration;
529
538
  readonly releaseInterval: Temporal.Duration;
539
+ readonly stateTtl: Temporal.Duration | undefined;
530
540
  readonly onStateChange?: CircuitBreakerOptions["onStateChange"];
531
541
  readonly onActivityDrop?: CircuitBreakerOptions["onActivityDrop"];
532
542
  }
@@ -587,6 +597,11 @@ declare class CircuitBreaker {
587
597
  recordFailure(remoteHost: string): Promise<CircuitBreakerStateChange | undefined>;
588
598
  dropActivity(remoteHost: string, details: CircuitBreakerActivityDrop): Promise<void>;
589
599
  getState(remoteHost: string): Promise<CircuitBreakerKvState | undefined>;
600
+ /**
601
+ * The currently running background legacy sweep, if any.
602
+ * @internal
603
+ */
604
+ get pendingSweep(): Promise<void> | undefined;
590
605
  }
591
606
  /**
592
607
  * Normalizes user-provided circuit breaker options into the internal policy
@@ -595,7 +610,8 @@ declare class CircuitBreaker {
595
610
  * @param options The public circuit breaker options supplied to Fedify.
596
611
  * @returns The normalized failure predicate, failure pruning function,
597
612
  * duration values, and optional callbacks with defaults applied.
598
- * @throws {RangeError} If any configured duration is not positive.
613
+ * @throws {RangeError} If any configured duration is not positive, or if
614
+ * `stateTtl` is shorter than `recoveryDelay`.
599
615
  * @throws {TypeError} If `failureThreshold` is not a positive integer.
600
616
  */
601
617
  declare function normalizeCircuitBreakerOptions(options: CircuitBreakerOptions): NormalizedCircuitBreakerOptions;
@@ -608,6 +624,264 @@ declare function normalizeCircuitBreakerOptions(options: CircuitBreakerOptions):
608
624
  */
609
625
  declare function parseCircuitBreakerKvState(value: unknown): CircuitBreakerKvState | undefined;
610
626
  //#endregion
627
+ //#region src/federation/mq.d.ts
628
+ /**
629
+ * Additional options for enqueuing a message in a queue.
630
+ *
631
+ * @since 0.5.0
632
+ */
633
+ interface MessageQueueEnqueueOptions {
634
+ /**
635
+ * The delay before the message is enqueued. No delay by default.
636
+ *
637
+ * It must not be negative.
638
+ */
639
+ readonly delay?: Temporal.Duration;
640
+ /**
641
+ * An optional key that ensures messages with the same ordering key are
642
+ * processed sequentially (one at a time). Messages with different ordering
643
+ * keys (or no ordering key) may be processed in parallel.
644
+ *
645
+ * This is useful for ensuring that related messages are processed in order,
646
+ * such as ensuring that a `Delete` activity is processed after a `Create`
647
+ * activity for the same object.
648
+ *
649
+ * @since 2.0.0
650
+ */
651
+ readonly orderingKey?: string;
652
+ /**
653
+ * An optional key requesting at-most-once enqueue semantics for messages
654
+ * that share it. A backend that declares
655
+ * {@link MessageQueue.nativeDeduplication} `true` owns the check: a message
656
+ * whose `deduplicationKey` was already seen within the backend's
657
+ * deduplication window is dropped instead of enqueued. Backends without
658
+ * native deduplication ignore this field; Fedify performs its own
659
+ * best-effort deduplication before reaching them on the paths that support
660
+ * it.
661
+ *
662
+ * @since 2.4.0
663
+ */
664
+ readonly deduplicationKey?: string;
665
+ }
666
+ /**
667
+ * Additional options for listening to a message queue.
668
+ *
669
+ * @since 1.0.0
670
+ */
671
+ interface MessageQueueListenOptions {
672
+ /**
673
+ * The signal to abort listening to the message queue.
674
+ */
675
+ signal?: AbortSignal;
676
+ }
677
+ /**
678
+ * The number of messages waiting in a message queue.
679
+ *
680
+ * @since 2.3.0
681
+ */
682
+ interface MessageQueueDepth {
683
+ /**
684
+ * The total number of messages still waiting in the backend queue.
685
+ *
686
+ * This does not include messages that have already been handed to a worker
687
+ * for processing.
688
+ */
689
+ readonly queued: number;
690
+ /**
691
+ * The number of queued messages eligible for immediate processing.
692
+ *
693
+ * Queue backends that cannot cheaply distinguish ready and delayed messages
694
+ * may omit this field.
695
+ */
696
+ readonly ready?: number;
697
+ /**
698
+ * The number of queued messages scheduled for later delivery.
699
+ *
700
+ * Queue backends that cannot cheaply distinguish ready and delayed messages
701
+ * may omit this field.
702
+ */
703
+ readonly delayed?: number;
704
+ }
705
+ /**
706
+ * An abstract interface for a message queue.
707
+ *
708
+ * @since 0.5.0
709
+ */
710
+ interface MessageQueue {
711
+ /**
712
+ * Whether the message queue backend provides native retry mechanisms.
713
+ * When `true`, Fedify will skip its own retry logic and rely on the backend
714
+ * to handle retries. When `false` or omitted, Fedify will handle retries
715
+ * using its own retry policies.
716
+ *
717
+ * @default `false`
718
+ * @since 1.7.0
719
+ */
720
+ readonly nativeRetrial?: boolean;
721
+ /**
722
+ * Whether the message queue backend deduplicates messages that share a
723
+ * {@link MessageQueueEnqueueOptions.deduplicationKey} natively. When `true`,
724
+ * Fedify forwards the `deduplicationKey` and relies on the backend to drop
725
+ * duplicates; when `false` or omitted, Fedify applies its own best-effort
726
+ * key–value deduplication on the paths that request it.
727
+ *
728
+ * @default `false`
729
+ * @since 2.4.0
730
+ */
731
+ readonly nativeDeduplication?: boolean;
732
+ /**
733
+ * Whether {@link enqueueMany} accepts either every message or no messages.
734
+ * Backends that implement `enqueueMany()` by sending messages individually
735
+ * must set this to `false`, so Fedify does not use that method for a batch
736
+ * governed by one `deduplicationKey`. `true` by default when `enqueueMany`
737
+ * is implemented.
738
+ *
739
+ * @default `true`
740
+ * @since 2.4.0
741
+ */
742
+ readonly atomicEnqueueMany?: boolean;
743
+ /**
744
+ * Enqueues a message in the queue.
745
+ * @param message The message to enqueue.
746
+ * @param options Additional options for enqueuing the message.
747
+ */
748
+ enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
749
+ /**
750
+ * Enqueues multiple messages in the queue. This operation is optional,
751
+ * and may not be supported by all implementations. If not supported,
752
+ * Fedify will invoke {@link enqueue} for each message. An implementation
753
+ * that may accept only part of a batch before rejecting must declare
754
+ * {@link atomicEnqueueMany} `false`.
755
+ *
756
+ * @param messages The messages to enqueue.
757
+ * @param options Additional options for enqueuing the messages.
758
+ */
759
+ enqueueMany?: (messages: readonly any[], options?: MessageQueueEnqueueOptions) => Promise<void>;
760
+ /**
761
+ * Listens for messages in the queue.
762
+ * @param handler The handler for messages in the queue.
763
+ * @param options Additional options for listening to the message queue.
764
+ * @returns A promise that resolves when the listening is done. It never
765
+ * rejects, and is resolved when the signal is aborted. If no
766
+ * signal is provided, it never resolves.
767
+ */
768
+ listen(handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>;
769
+ /**
770
+ * Gets the number of messages waiting in the queue.
771
+ *
772
+ * This operation is optional, and may not be supported by all
773
+ * implementations. The returned counts exclude messages currently being
774
+ * handled by a worker.
775
+ *
776
+ * @since 2.3.0
777
+ */
778
+ getDepth?(): Promise<MessageQueueDepth>;
779
+ }
780
+ /**
781
+ * Additional options for {@link InProcessMessageQueue}.
782
+ * @since 1.0.0
783
+ */
784
+ interface InProcessMessageQueueOptions {
785
+ /**
786
+ * The interval to poll for messages in the queue. 5 seconds by default.
787
+ * @default `{ seconds: 5 }`
788
+ */
789
+ pollInterval?: Temporal.Duration | Temporal.DurationLike;
790
+ }
791
+ /**
792
+ * A message queue that processes messages in the same process.
793
+ * Do not use this in production as it does neither persist messages nor
794
+ * distribute them across multiple processes.
795
+ *
796
+ * @since 0.5.0
797
+ */
798
+ declare class InProcessMessageQueue implements MessageQueue {
799
+ #private;
800
+ /**
801
+ * In-process message queue does not provide native retry mechanisms.
802
+ * @since 1.7.0
803
+ */
804
+ readonly nativeRetrial = false;
805
+ /**
806
+ * In-process message queue does not deduplicate messages natively.
807
+ * @since 2.4.0
808
+ */
809
+ readonly nativeDeduplication = false;
810
+ /**
811
+ * Constructs a new {@link InProcessMessageQueue} with the given options.
812
+ * @param options Additional options for the in-process message queue.
813
+ */
814
+ constructor(options?: InProcessMessageQueueOptions);
815
+ enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
816
+ enqueueMany(messages: readonly any[], options?: MessageQueueEnqueueOptions): Promise<void>;
817
+ listen(handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>;
818
+ getDepth(): Promise<MessageQueueDepth>;
819
+ }
820
+ /**
821
+ * A message queue that processes messages in parallel. It takes another
822
+ * {@link MessageQueue}, and processes messages in parallel up to a certain
823
+ * number of workers.
824
+ *
825
+ * Actually, it's rather a decorator than a queue itself.
826
+ *
827
+ * Note that the workers do not run in truly parallel, in the sense that they
828
+ * are not running in separate threads or processes. They are running in the
829
+ * same process, but are scheduled to run in parallel. Hence, this is useful
830
+ * for I/O-bound tasks, but not for CPU-bound tasks, which is okay for Fedify's
831
+ * workloads.
832
+ *
833
+ * When using `ParallelMessageQueue`, the ordering guarantee is preserved
834
+ * *only if* the underlying queue implementation delivers messages in a wrapper
835
+ * format that includes the `__fedify_ordering_key__` property. Currently,
836
+ * only `DenoKvMessageQueue` and `WorkersMessageQueue` use this format.
837
+ * For other queue implementations (e.g., `InProcessMessageQueue`,
838
+ * `RedisMessageQueue`, `PostgresMessageQueue`, `SqliteMessageQueue`,
839
+ * `AmqpMessageQueue`), the ordering key cannot be detected by
840
+ * `ParallelMessageQueue`, so ordering guarantees are handled by those
841
+ * implementations directly rather than at the `ParallelMessageQueue` level.
842
+ *
843
+ * Messages with the same ordering key will never be processed concurrently
844
+ * by different workers, ensuring sequential processing within each key.
845
+ * Messages with different ordering keys (or no ordering key) can still be
846
+ * processed in parallel.
847
+ *
848
+ * @since 1.0.0
849
+ */
850
+ declare class ParallelMessageQueue implements MessageQueue {
851
+ #private;
852
+ readonly queue: MessageQueue;
853
+ readonly workers: number;
854
+ /**
855
+ * Inherits the native retry capability from the wrapped queue.
856
+ * @since 1.7.0
857
+ */
858
+ readonly nativeRetrial?: boolean;
859
+ /**
860
+ * Inherits the native deduplication capability from the wrapped queue.
861
+ * @since 2.4.0
862
+ */
863
+ readonly nativeDeduplication?: boolean;
864
+ /**
865
+ * Inherits the atomic batch capability from the wrapped queue.
866
+ * @since 2.4.0
867
+ */
868
+ readonly atomicEnqueueMany?: boolean;
869
+ readonly getDepth?: () => Promise<MessageQueueDepth>;
870
+ /**
871
+ * Constructs a new {@link ParallelMessageQueue} with the given queue and
872
+ * number of workers.
873
+ * @param queue The message queue to use under the hood. Note that
874
+ * {@link ParallelMessageQueue} cannot be nested.
875
+ * @param workers The number of workers to process messages in parallel.
876
+ * @throws {TypeError} If the given queue is an instance of
877
+ * {@link ParallelMessageQueue}.
878
+ */
879
+ constructor(queue: MessageQueue, workers: number);
880
+ enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
881
+ enqueueMany(messages: readonly any[], options?: MessageQueueEnqueueOptions): Promise<void>;
882
+ listen(handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>;
883
+ }
884
+ //#endregion
611
885
  //#region src/federation/handler.d.ts
612
886
  /**
613
887
  * Options for the {@link respondWithObject} and
@@ -3250,4 +3524,4 @@ interface ActorKeyPair extends CryptoKeyPair {
3250
3524
  readonly multikey: Multikey;
3251
3525
  }
3252
3526
  //#endregion
3253
- export { CircuitBreakerCreateOptions as $, OutboxListenerSetters as A, UnverifiedActivityHandler as At, TaskEnqueueOptions as B, FederationStartQueueOptions as C, ObjectAuthorizePredicate as Ct, InboxListenerSetters as D, OutboxListenerErrorHandler as Dt, InboxChallengePolicy as E, OutboxListener as Et, createFederation as F, PageItems as Ft, RetryPolicy as G, TaskRegistry as H, Message as I, buildCollectionSynchronizationHeader as It, respondWithObject as J, createExponentialBackoffPolicy as K, createFederationBuilder as L, digest as Lt, FederationKvPrefixes as M, WebFingerLinksDispatcher as Mt, FederationOrigin as N, SendActivityError as Nt, MediaUploaderSetters as O, OutboxPermanentFailureHandler as Ot, FederationQueueOptions as P, SenderKeyPair as Pt, CircuitBreakerBeforeSendDecision as Q, TaskDefinition as R, ActivityTransformer as Rt, FederationOptions as S, NodeInfoDispatcher as St, IdempotencyStrategy as T, OutboxErrorHandler as Tt, CreateExponentialBackoffPolicyOptions as U, TaskHandler as V, RetryContext as W, CircuitBreaker as X, respondWithObjectIfAcceptable as Y, CircuitBreakerActivityDrop as Z, Federatable as _, CustomCollectionCursor as _t, GetSignedKeyOptions as a, NormalizedCircuitBreakerOptions as at, FederationBuilder as b, InboxListener as bt, ParseUriResult as c, ActorAliasMapper as ct, SendActivityOptions as d, ActorKeyPairsDispatcher as dt, CircuitBreakerFailurePolicy as et, SendActivityOptionsForCollection as f, AuthorizePredicate as ft, CustomCollectionCallbackSetters as g, CustomCollectionCounter as gt, ConstructorWithTypeId as h, CollectionDispatcher as ht, GetActorOptions as i, CircuitBreakerStateChange as it, Rfc6570Expression as j, UnverifiedActivityReason as jt, ObjectCallbackSetters as k, SharedInboxKeyDispatcher as kt, RequestContext as l, ActorDispatcher as lt, CollectionCallbackSetters as m, CollectionCursor as mt, Context as n, CircuitBreakerOptions as nt, InboxContext as o, normalizeCircuitBreakerOptions as ot, ActorCallbackSetters as p, CollectionCounter as pt, RespondWithObjectOptions as q, ForwardActivityOptions as r, CircuitBreakerState as rt, OutboxContext as s, parseCircuitBreakerKvState as st, ActorKeyPair as t, CircuitBreakerKvState as tt, RouteActivityOptions as u, ActorHandleMapper as ut, Federation as v, CustomCollectionDispatcher as vt, IdempotencyKeyCallback as w, ObjectDispatcher as wt, FederationFetchOptions as x, MediaUploaderCallback as xt, FederationBenchmarkOptions as y, InboxErrorHandler as yt, TaskDefinitionOptions as z };
3527
+ export { MessageQueueDepth as $, OutboxListenerSetters as A, ObjectAuthorizePredicate as At, TaskEnqueueOptions as B, SendActivityError as Bt, FederationStartQueueOptions as C, CustomCollectionCounter as Ct, InboxListenerSetters as D, InboxListener as Dt, InboxChallengePolicy as E, InboxErrorHandler as Et, createFederation as F, OutboxPermanentFailureHandler as Ft, RetryPolicy as G, ActivityTransformer as Gt, TaskRegistry as H, PageItems as Ht, Message as I, SharedInboxKeyDispatcher as It, respondWithObject as J, createExponentialBackoffPolicy as K, createFederationBuilder as L, UnverifiedActivityHandler as Lt, FederationKvPrefixes as M, OutboxErrorHandler as Mt, FederationOrigin as N, OutboxListener as Nt, MediaUploaderSetters as O, MediaUploaderCallback as Ot, FederationQueueOptions as P, OutboxListenerErrorHandler as Pt, MessageQueue as Q, TaskDefinition as R, UnverifiedActivityReason as Rt, FederationOptions as S, CollectionDispatcher as St, IdempotencyStrategy as T, CustomCollectionDispatcher as Tt, CreateExponentialBackoffPolicyOptions as U, buildCollectionSynchronizationHeader as Ut, TaskHandler as V, SenderKeyPair as Vt, RetryContext as W, digest as Wt, InProcessMessageQueue as X, respondWithObjectIfAcceptable as Y, InProcessMessageQueueOptions as Z, Federatable as _, ActorHandleMapper as _t, GetSignedKeyOptions as a, CircuitBreakerBeforeSendDecision as at, FederationBuilder as b, CollectionCounter as bt, ParseUriResult as c, CircuitBreakerKvState as ct, SendActivityOptions as d, CircuitBreakerStateChange as dt, MessageQueueEnqueueOptions as et, SendActivityOptionsForCollection as f, NormalizedCircuitBreakerOptions as ft, CustomCollectionCallbackSetters as g, ActorDispatcher as gt, ConstructorWithTypeId as h, ActorAliasMapper as ht, GetActorOptions as i, CircuitBreakerActivityDrop as it, Rfc6570Expression as j, ObjectDispatcher as jt, ObjectCallbackSetters as k, NodeInfoDispatcher as kt, RequestContext as l, CircuitBreakerOptions as lt, CollectionCallbackSetters as m, parseCircuitBreakerKvState as mt, Context as n, ParallelMessageQueue as nt, InboxContext as o, CircuitBreakerCreateOptions as ot, ActorCallbackSetters as p, normalizeCircuitBreakerOptions as pt, RespondWithObjectOptions as q, ForwardActivityOptions as r, CircuitBreaker as rt, OutboxContext as s, CircuitBreakerFailurePolicy as st, ActorKeyPair as t, MessageQueueListenOptions as tt, RouteActivityOptions as u, CircuitBreakerState as ut, Federation as v, ActorKeyPairsDispatcher as vt, IdempotencyKeyCallback as w, CustomCollectionCursor as wt, FederationFetchOptions as x, CollectionCursor as xt, FederationBenchmarkOptions as y, AuthorizePredicate as yt, TaskDefinitionOptions as z, WebFingerLinksDispatcher as zt };
@@ -3,6 +3,6 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  //#region deno.json
5
5
  var name = "@fedify/fedify";
6
- var version = "2.4.0-dev.1668+90797b01";
6
+ var version = "2.4.0-dev.1727+1eadcb04";
7
7
  //#endregion
8
8
  export { version as n, name as t };
@@ -1,8 +1,8 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { o as validateCryptoKey } from "./key-CM7wDnZG.mjs";
5
- import { n as doubleKnock } from "./http-DUmWq5Pw.mjs";
4
+ import { o as validateCryptoKey } from "./key-b4kf4yZT.mjs";
5
+ import { n as doubleKnock } from "./http-TjhZfiSN.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { curry } from "es-toolkit";
8
8
  import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
@@ -129,27 +129,27 @@ function parse(input, loose) {
129
129
  }
130
130
  //#endregion
131
131
  //#region ../../node_modules/.pnpm/fetch-mock@12.6.0/node_modules/fetch-mock/dist/esm/TypeDescriptor.js
132
- const valueTypes = new Set([
132
+ const valueTypes = /* @__PURE__ */ new Set([
133
133
  "boolean",
134
134
  "number",
135
135
  "null",
136
136
  "string",
137
137
  "undefined"
138
138
  ]);
139
- const referenceTypes = new Set([
139
+ const referenceTypes = /* @__PURE__ */ new Set([
140
140
  "array",
141
141
  "function",
142
142
  "object",
143
143
  "symbol"
144
144
  ]);
145
- const detectableTypes = new Set([
145
+ const detectableTypes = /* @__PURE__ */ new Set([
146
146
  "boolean",
147
147
  "function",
148
148
  "number",
149
149
  "string",
150
150
  "symbol"
151
151
  ]);
152
- const typeConstructors = new Set([
152
+ const typeConstructors = /* @__PURE__ */ new Set([
153
153
  Boolean,
154
154
  Number,
155
155
  String
@@ -220,7 +220,7 @@ var TypeDescriptor = class TypeDescriptor {
220
220
  };
221
221
  //#endregion
222
222
  //#region ../../node_modules/.pnpm/fetch-mock@12.6.0/node_modules/fetch-mock/dist/esm/IsSubsetOf.js
223
- const allowedTypes = new Set([
223
+ const allowedTypes = /* @__PURE__ */ new Set([
224
224
  "array",
225
225
  "object",
226
226
  "function",
@@ -712,7 +712,14 @@ var __classPrivateFieldGet = function(receiver, state, kind, f) {
712
712
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
713
713
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
714
714
  };
715
- var _Route_instances, _a, _Route_responseSubscriptions, _Route_validate, _Route_sanitize, _Route_generateMatcher, _Route_limit, _Route_delayResponse;
715
+ var _Route_instances;
716
+ var _a;
717
+ var _Route_responseSubscriptions;
718
+ var _Route_validate;
719
+ var _Route_sanitize;
720
+ var _Route_generateMatcher;
721
+ var _Route_limit;
722
+ var _Route_delayResponse;
716
723
  var RouteConfigWrapper = class {
717
724
  constructor(config) {
718
725
  Object.assign(this, config);
@@ -1,11 +1,12 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as MemoryKvStore } from "../kv-CXBAok3k.mjs";
5
- import { t as assertEquals } from "../assert_equals-BV7oLMxm.mjs";
6
- import { r as assertExists } from "../std__assert-B2NnY9bq.mjs";
7
- import { t as assertThrows } from "../assert_throws-NiFfqbnH.mjs";
8
- import { r as createFederationBuilder } from "../builder-iXZ5jNVg.mjs";
4
+ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
+ import { t as assertEquals } from "../assert_equals-CBlRfA-_.mjs";
6
+ import { t as assertExists } from "../assert_exists-DtzkXC47.mjs";
7
+ import { t as assertThrows } from "../assert_throws-BJ5wuvR2.mjs";
8
+ import "../std__assert-CxFT0MNt.mjs";
9
+ import { r as createFederationBuilder } from "../builder-f5-YwHfj.mjs";
9
10
  import { DisallowedOperatorError, DisallowedVarSpecModifierError, DuplicateRouteVariableError, RouteTemplateOptionsNotMatchedError, RouterError } from "@fedify/uri-template";
10
11
  import { Activity, Note, Person } from "@fedify/vocab";
11
12
  import { test } from "@fedify/fixture";
@@ -342,6 +343,18 @@ test("FederationBuilder", async (t) => {
342
343
  });
343
344
  builder.setCollectionDispatcher(strId, Note, "/string-id/{id}", dispatcher);
344
345
  });
346
+ await t.step("propagates custom collection dispatchers to the built federation", async () => {
347
+ const kv = new MemoryKvStore();
348
+ const builder = createFederationBuilder();
349
+ builder.setCollectionDispatcher("test", Note, "/c/{id}", () => ({ items: [] }));
350
+ const impl = await builder.build({
351
+ kv,
352
+ origin: "https://example.com"
353
+ });
354
+ assertExists(impl.collectionCallbacks["test"]);
355
+ assertEquals(impl.collectionTypeIds["test"], Note);
356
+ assertEquals((await impl.fetch(new Request("https://example.com/c/x", { headers: { accept: "application/activity+json" } }), { contextData: void 0 })).status, 200);
357
+ });
345
358
  });
346
359
  //#endregion
347
360
  export {};