@fedify/fedify 2.4.0-pr.936.41 → 2.5.0-dev.2271

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 (244) hide show
  1. package/README.md +50 -39
  2. package/dist/{assert-CJ1KXcvv.mjs → assert-D1Eafmd_.mjs} +1 -1
  3. package/dist/{assert_equals-BV7oLMxm.mjs → assert_equals-Z6IcEbWU.mjs} +2 -28
  4. package/dist/assert_exists-cffSpJ7X.mjs +28 -0
  5. package/dist/assert_false-CPdRnc3E.mjs +23 -0
  6. package/dist/assert_greater_or_equal-BlafOF4-.mjs +31 -0
  7. package/dist/{assert_instance_of-Q9KTBnrf.mjs → assert_instance_of-mrXWWNY-.mjs} +1 -1
  8. package/dist/{assert_not_equals-EPJPoxuf.mjs → assert_not_equals-CpPK2t89.mjs} +2 -1
  9. package/dist/assert_rejects-CTptdYck.mjs +39 -0
  10. package/dist/{assert_strict_equals-Ec20AUwa.mjs → assert_strict_equals-CYvBmkpC.mjs} +2 -1
  11. package/dist/{assert_throws-NiFfqbnH.mjs → assert_throws-BYITOvPO.mjs} +2 -1
  12. package/dist/assertion_error-B-cx0fFA.mjs +31 -0
  13. package/dist/audience-CHQ-FlLD.mjs +95 -0
  14. package/dist/{builder-DonuxRl_.mjs → builder-Bda6LK7A.mjs} +169 -14
  15. package/dist/{circuit-breaker-CBGyz5F7.mjs → circuit-breaker-XJ53md4S.mjs} +224 -17
  16. package/dist/circuit-breaker-test-utils-DW6YC_Pe.mjs +14 -0
  17. package/dist/{client-CjF5IYQS.mjs → client-CEnNz8O7.mjs} +144 -8
  18. package/dist/{codec-BBga-FWI.mjs → codec-C6rTrpIp.mjs} +26 -3
  19. package/dist/{collection-BIhlldqK.mjs → collection-CnnP1UAv.mjs} +1 -1
  20. package/dist/compat/mod.cjs +1 -1
  21. package/dist/compat/mod.d.cts +1 -1
  22. package/dist/compat/mod.d.ts +1 -1
  23. package/dist/compat/mod.js +1 -1
  24. package/dist/compat/outgoing-jsonld.test.mjs +71 -3
  25. package/dist/compat/public-audience.test.mjs +14 -5
  26. package/dist/compat/secured-document.test.d.mts +2 -0
  27. package/dist/compat/secured-document.test.mjs +58 -0
  28. package/dist/compat/transformers.test.mjs +5 -5
  29. package/dist/compound-proof-B-9mXxFW.mjs +989 -0
  30. package/dist/{context-Zii1f5xS.d.ts → context-7NyiqIcg.d.ts} +1600 -25
  31. package/dist/{context-BJXxPElm.mjs → context-8Tu9kea0.mjs} +21 -63
  32. package/dist/{context-lxX6I7as.d.cts → context-tsYPJ2Ew.d.cts} +1600 -25
  33. package/dist/{deno-BHzKn9Ig.mjs → deno-oR5aJKpU.mjs} +1 -1
  34. package/dist/dist-DJQM4u7i.mjs +189 -0
  35. package/dist/docloader-DBoYbvYW.mjs +87 -0
  36. package/dist/{esm-yYQfPhIY.mjs → esm-BHXXx4Wx.mjs} +13 -6
  37. package/dist/federation/audience.test.d.mts +2 -0
  38. package/dist/federation/audience.test.mjs +130 -0
  39. package/dist/federation/builder.test.mjs +54 -5
  40. package/dist/federation/circuit-breaker.test.mjs +838 -7
  41. package/dist/federation/collection.test.mjs +3 -3
  42. package/dist/federation/compound-fanout.test.d.mts +2 -0
  43. package/dist/federation/compound-fanout.test.mjs +228 -0
  44. package/dist/federation/handler-compound-proof.test.d.mts +2 -0
  45. package/dist/federation/handler-compound-proof.test.mjs +384 -0
  46. package/dist/federation/handler.test.mjs +385 -15
  47. package/dist/federation/hashlink-media.test.d.mts +2 -0
  48. package/dist/federation/hashlink-media.test.mjs +422 -0
  49. package/dist/federation/idempotency.test.mjs +6 -6
  50. package/dist/federation/inbox-report.test.d.mts +2 -0
  51. package/dist/federation/inbox-report.test.mjs +475 -0
  52. package/dist/federation/inbox.test.mjs +3 -3
  53. package/dist/federation/keycache.test.mjs +215 -14
  54. package/dist/federation/kv.test.mjs +3 -3
  55. package/dist/federation/metrics.test.mjs +5 -5
  56. package/dist/federation/middleware.test.mjs +967 -35
  57. package/dist/federation/mod.cjs +18 -261
  58. package/dist/federation/mod.d.cts +5 -5
  59. package/dist/federation/mod.d.ts +5 -5
  60. package/dist/federation/mod.js +279 -1
  61. package/dist/federation/mq.test.mjs +123 -47
  62. package/dist/federation/negotiation.test.mjs +4 -4
  63. package/dist/federation/outgoing-proof.test.d.mts +2 -0
  64. package/dist/federation/outgoing-proof.test.mjs +931 -0
  65. package/dist/federation/portable-actor.test.d.mts +2 -0
  66. package/dist/federation/portable-actor.test.mjs +496 -0
  67. package/dist/federation/portable-chain.test.d.mts +2 -0
  68. package/dist/federation/portable-chain.test.mjs +370 -0
  69. package/dist/federation/portable-collection.test.d.mts +2 -0
  70. package/dist/federation/portable-collection.test.mjs +832 -0
  71. package/dist/federation/portable-delivery.test.d.mts +2 -0
  72. package/dist/federation/portable-delivery.test.mjs +746 -0
  73. package/dist/federation/portable-gateway-keys.test.d.mts +2 -0
  74. package/dist/federation/portable-gateway-keys.test.mjs +686 -0
  75. package/dist/federation/portable-inbox.test.d.mts +2 -0
  76. package/dist/federation/portable-inbox.test.mjs +1535 -0
  77. package/dist/federation/portable-parse-uri.test.d.mts +2 -0
  78. package/dist/federation/portable-parse-uri.test.mjs +348 -0
  79. package/dist/federation/portable-route-activity.test.d.mts +2 -0
  80. package/dist/federation/portable-route-activity.test.mjs +259 -0
  81. package/dist/federation/portable.test.d.mts +2 -0
  82. package/dist/federation/portable.test.mjs +1072 -0
  83. package/dist/federation/retry.test.mjs +4 -3
  84. package/dist/federation/router.test.mjs +9 -159
  85. package/dist/federation/send.test.mjs +245 -27
  86. package/dist/federation/tasks/codec.test.mjs +4 -4
  87. package/dist/federation/tasks/enqueue.test.mjs +42 -4
  88. package/dist/federation/tasks/tasks.test.mjs +7 -6
  89. package/dist/federation/temporal.test.mjs +4 -4
  90. package/dist/federation/webfinger.test.mjs +275 -12
  91. package/dist/{middleware-FrSMAYEx.cjs → federation-CkZiAcWY.cjs} +8640 -3722
  92. package/dist/http-B5JT115n.cjs +10630 -0
  93. package/dist/http-DydWCB7R.js +6527 -0
  94. package/dist/{http-CPVMUgsW.mjs → http-siciWkmx.mjs} +397 -168
  95. package/dist/key-BspPiXqn.mjs +951 -0
  96. package/dist/key-C1nv7_jD.d.ts +1125 -0
  97. package/dist/key-DYxuyd-s.d.cts +1125 -0
  98. package/dist/key-owner-evidence-APB6NpSk.mjs +108 -0
  99. package/dist/keycache-Da8A8mZa.mjs +200 -0
  100. package/dist/{kv-D6hNiMTK.d.ts → kv-B2mzK5tl.d.cts} +3 -2
  101. package/dist/{kv-gJ8LYbxX.d.cts → kv-B2mzK5tl.d.ts} +3 -2
  102. package/dist/kv-DBRWVx3Q.mjs +104 -0
  103. package/dist/{kv-cache-KyGqJqSp.mjs → kv-cache-BF1hnW65.mjs} +1 -1
  104. package/dist/{kv-cache-5bnX3-Jq.js → kv-cache-CTQr1tbn.js} +54 -16
  105. package/dist/{kv-cache-DQ29C4XL.cjs → kv-cache-DCac1nEU.cjs} +55 -19
  106. package/dist/{ld-Cj9F_5AP.mjs → ld-CzaP-hJl.mjs} +44 -12
  107. package/dist/map-local-context-conflict-DOYEEJ3u.mjs +204 -0
  108. package/dist/map-local-create-note-B0SeXJms.mjs +214 -0
  109. package/dist/{metrics-DMk-nTxI.mjs → metrics-CYg9yxBL.mjs} +3 -2
  110. package/dist/metrics-DVKYY6K1.d.cts +36 -0
  111. package/dist/metrics-DoRtI0qU.d.ts +36 -0
  112. package/dist/{middleware-Y-kpsp6S.js → middleware-CsDDXKuL.js} +5493 -1103
  113. package/dist/{middleware-CvwTUgnP.mjs → middleware-D7_LO-Vs.mjs} +3157 -272
  114. package/dist/{middleware-CEctxBN6.mjs → middleware-DWjrfpcz.mjs} +1 -1
  115. package/dist/{mod-gOlPDuT8.d.cts → mod-BojP2Bw3.d.cts} +1 -1
  116. package/dist/mod-CavhAgLw.d.cts +320 -0
  117. package/dist/mod-CtpF2BU5.d.ts +320 -0
  118. package/dist/{mod-BtEaIEcD.d.cts → mod-DEZXwV6J.d.ts} +10 -4
  119. package/dist/{mod-UMmveiO0.d.ts → mod-Dw-nPxQh.d.cts} +10 -4
  120. package/dist/{mod-DLc2Ot6f.d.ts → mod-Xj5P4s4d.d.ts} +1 -1
  121. package/dist/mod.cjs +40 -39
  122. package/dist/mod.d.cts +10 -11
  123. package/dist/mod.d.ts +10 -11
  124. package/dist/mod.js +9 -9
  125. package/dist/{mq-llHKivST.mjs → mq-Dm1Wmtm-.mjs} +6 -0
  126. package/dist/nodeinfo/client.test.mjs +139 -4
  127. package/dist/nodeinfo/handler.test.mjs +5 -5
  128. package/dist/nodeinfo/mod.cjs +1 -1
  129. package/dist/nodeinfo/mod.d.cts +1 -1
  130. package/dist/nodeinfo/mod.d.ts +1 -1
  131. package/dist/nodeinfo/mod.js +1 -1
  132. package/dist/nodeinfo/types.test.mjs +4 -4
  133. package/dist/otel/exporter.test.mjs +3 -3
  134. package/dist/otel/mod.cjs +0 -1
  135. package/dist/otel/mod.d.cts +1 -1
  136. package/dist/otel/mod.d.ts +1 -1
  137. package/dist/{outgoing-jsonld-URuqsICz.mjs → outgoing-jsonld-4IJqPYos.mjs} +12 -10
  138. package/dist/{owner-DEvZuyOE.d.cts → owner-BF0L9cMt.d.cts} +11 -0
  139. package/dist/{owner-CnngXDNJ.d.ts → owner-BSzr5-I8.d.ts} +11 -0
  140. package/dist/owner-DYgfTFHy.mjs +267 -0
  141. package/dist/portable-collection-BpsVsRov.js +670 -0
  142. package/dist/portable-collection-C74P1vtC.mjs +418 -0
  143. package/dist/portable-collection-DZd2bm7M.cjs +686 -0
  144. package/dist/portable-key-BIMLrAP4.mjs +549 -0
  145. package/dist/portable-key-id-Ca30-hOa.mjs +248 -0
  146. package/dist/proof-Dxy6ByqI.mjs +1299 -0
  147. package/dist/{public-audience-Cr5MsnMq.mjs → public-audience--klBIOk1.mjs} +15 -10
  148. package/dist/router-u5O5KCQr.mjs +156 -0
  149. package/dist/runtime/mod.cjs +1 -1
  150. package/dist/runtime/mod.js +1 -1
  151. package/dist/secured-document-CxzZZ9nL.mjs +35 -0
  152. package/dist/send-C4dDpAxm.mjs +495 -0
  153. package/dist/sig/accept.test.mjs +1 -1
  154. package/dist/sig/compound-proof-discovery.test.d.mts +2 -0
  155. package/dist/sig/compound-proof-discovery.test.mjs +331 -0
  156. package/dist/sig/compound-proof-producer.test.d.mts +2 -0
  157. package/dist/sig/compound-proof-producer.test.mjs +107 -0
  158. package/dist/sig/compound-proof-verification.test.d.mts +2 -0
  159. package/dist/sig/compound-proof-verification.test.mjs +833 -0
  160. package/dist/sig/compound-proof.test.d.mts +2 -0
  161. package/dist/sig/compound-proof.test.mjs +411 -0
  162. package/dist/sig/http.test.mjs +702 -31
  163. package/dist/sig/key-owner-evidence.test.d.mts +2 -0
  164. package/dist/sig/key-owner-evidence.test.mjs +100 -0
  165. package/dist/sig/key.test.mjs +220 -8
  166. package/dist/sig/ld.test.mjs +65 -7
  167. package/dist/sig/mitra-receive-interop.test.d.mts +2 -0
  168. package/dist/sig/mitra-receive-interop.test.mjs +260 -0
  169. package/dist/sig/mitra-send-interop.test.d.mts +2 -0
  170. package/dist/sig/mitra-send-interop.test.mjs +461 -0
  171. package/dist/sig/mod.cjs +18 -16
  172. package/dist/sig/mod.d.cts +4 -4
  173. package/dist/sig/mod.d.ts +4 -4
  174. package/dist/sig/mod.js +3 -3
  175. package/dist/sig/owner.test.mjs +108 -9
  176. package/dist/sig/portable-collection.test.d.mts +2 -0
  177. package/dist/sig/portable-collection.test.mjs +697 -0
  178. package/dist/sig/portable-interop.test.d.mts +2 -0
  179. package/dist/sig/portable-interop.test.mjs +156 -0
  180. package/dist/sig/portable-key-id.test.d.mts +2 -0
  181. package/dist/sig/portable-key-id.test.mjs +67 -0
  182. package/dist/sig/portable-key.test.d.mts +2 -0
  183. package/dist/sig/portable-key.test.mjs +1439 -0
  184. package/dist/sig/proof.test.mjs +1753 -16
  185. package/dist/sig/tootik-request-interop.test.d.mts +2 -0
  186. package/dist/sig/tootik-request-interop.test.mjs +190 -0
  187. package/dist/sig/tootik-send-interop.test.d.mts +2 -0
  188. package/dist/sig/tootik-send-interop.test.mjs +331 -0
  189. package/dist/sig/verification.test.d.mts +2 -0
  190. package/dist/sig/verification.test.mjs +310 -0
  191. package/dist/std__assert-DvMDRPes.mjs +8 -0
  192. package/dist/{testing-CO7ftO8A.mjs → tasks-IG3pHfvZ.mjs} +2 -2
  193. package/dist/{temporal-fsXO5IvD.mjs → temporal-D0KJI4NF.mjs} +3 -3
  194. package/dist/testing/context.test.d.mts +2 -0
  195. package/dist/testing/context.test.mjs +19 -0
  196. package/dist/testing/kv.test.d.mts +2 -0
  197. package/dist/testing/kv.test.mjs +101 -0
  198. package/dist/testing/mod.d.mts +1617 -48
  199. package/dist/testing/mod.mjs +6 -3
  200. package/dist/testing-t8xDeJZ5.mjs +8 -0
  201. package/dist/{transformers-DGwl-hD1.cjs → transformers-BalCrSsr.cjs} +0 -1
  202. package/dist/{types-DC1pNgJA.js → types-_S2_MeLF.js} +144 -8
  203. package/dist/{types-CPym83zc.cjs → types-poIao40f.cjs} +160 -7
  204. package/dist/utils/docloader.test.mjs +530 -8
  205. package/dist/utils/kv-cache.test.mjs +2 -2
  206. package/dist/utils/mod.cjs +1 -1
  207. package/dist/utils/mod.d.cts +1 -1
  208. package/dist/utils/mod.d.ts +1 -1
  209. package/dist/utils/mod.js +1 -1
  210. package/dist/verification-C3954hQh.mjs +5 -0
  211. package/dist/verification-Dpfcw8ml.mjs +105 -0
  212. package/dist/vocab/cjs.test.mjs +1 -1
  213. package/package.json +8 -8
  214. package/dist/assert_rejects-EgstcQy5.mjs +0 -82
  215. package/dist/docloader-e1khNUKy.mjs +0 -49
  216. package/dist/http-CsmQ-BQ4.js +0 -2483
  217. package/dist/http-VyDTd4G3.d.cts +0 -553
  218. package/dist/http-hlIjmewS.cjs +0 -2694
  219. package/dist/http-lf8Hsd91.d.ts +0 -553
  220. package/dist/key-DfPsX8hv.mjs +0 -453
  221. package/dist/keycache-_DHqz5z_.mjs +0 -97
  222. package/dist/metrics-CoUJLQhZ.d.cts +0 -276
  223. package/dist/metrics-Dc4jR-IC.d.ts +0 -276
  224. package/dist/mod-B0hW12_O.d.cts +0 -307
  225. package/dist/mod-COIAjwRS.d.ts +0 -307
  226. package/dist/owner-Br9YYzn_.mjs +0 -120
  227. package/dist/proof-B4ngoaNQ.mjs +0 -316
  228. package/dist/proof-B6E0XUXJ.js +0 -1415
  229. package/dist/proof-NN4xCQGL.cjs +0 -1562
  230. package/dist/send-CxHKUNzv.mjs +0 -239
  231. package/dist/std__assert-B2NnY9bq.mjs +0 -79
  232. package/dist/temporal-polyfill-BCdTHexd.cjs +0 -3565
  233. /package/dist/{accept-8PiolDP7.mjs → accept-CPVqki78.mjs} +0 -0
  234. /package/dist/{activity-listener-BtTSxZWA.mjs → activity-listener-C-BSbKI7.mjs} +0 -0
  235. /package/dist/{client-CAM_bQXx.d.cts → client-D-XP_Ccb.d.cts} +0 -0
  236. /package/dist/{client-CSddvgWN.d.ts → client-D-XP_Ccb.d.ts} +0 -0
  237. /package/dist/{keys-Dbyd7bhl.mjs → keys-DIJNHW-Y.mjs} +0 -0
  238. /package/dist/{kv-CXBAok3k.mjs → kv-DCHkaJ9-.mjs} +0 -0
  239. /package/dist/{negotiation-RuwrPFqi.mjs → negotiation-CCocWT_N.mjs} +0 -0
  240. /package/dist/{retry-DgFqeS5k.mjs → retry-zX5xw5e0.mjs} +0 -0
  241. /package/dist/{chunk-D5IdezsZ.js → rolldown-runtime-BC-Eo5Mj.js} +0 -0
  242. /package/dist/{chunk-Czpeue4M.cjs → rolldown-runtime-Dmm3t92W.cjs} +0 -0
  243. /package/dist/{transformers-DXze6FUB.js → transformers-DAtXl_Kc.js} +0 -0
  244. /package/dist/{types-CrtdVuDP.mjs → types-DE_LV1JB.mjs} +0 -0
@@ -1,9 +1,10 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { l as AssertionError, t as assertEquals } from "../assert_equals-BV7oLMxm.mjs";
5
- import { t as assertNotEquals } from "../assert_not_equals-EPJPoxuf.mjs";
6
- import { t as createExponentialBackoffPolicy } from "../retry-DgFqeS5k.mjs";
4
+ import { t as AssertionError } from "../assertion_error-B-cx0fFA.mjs";
5
+ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
+ import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
7
+ import { t as createExponentialBackoffPolicy } from "../retry-zX5xw5e0.mjs";
7
8
  import { test } from "@fedify/fixture";
8
9
  //#region src/federation/retry.test.ts
9
10
  test("createExponentialBackoffPolicy()", () => {
@@ -1,164 +1,14 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as assertEquals } from "../assert_equals-BV7oLMxm.mjs";
5
- import "../std__assert-B2NnY9bq.mjs";
6
- import { r as assertFalse } from "../assert_rejects-EgstcQy5.mjs";
7
- import { t as assertThrows } from "../assert_throws-NiFfqbnH.mjs";
8
- import { t as assert } from "../assert-CJ1KXcvv.mjs";
9
- import { getLogger } from "@logtape/logtape";
10
- import { Router, RouterError, assertPath, isPath } from "@fedify/uri-template";
4
+ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
5
+ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
6
+ import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
7
+ import "../std__assert-DvMDRPes.mjs";
8
+ import { t as assert } from "../assert-D1Eafmd_.mjs";
9
+ import { n as RouterError$1, t as Router$1 } from "../router-u5O5KCQr.mjs";
10
+ import { RouterError } from "@fedify/uri-template";
11
11
  import { test } from "@fedify/fixture";
12
- //#region src/federation/router.ts
13
- const logger = getLogger([
14
- "fedify",
15
- "federation",
16
- "router",
17
- "deprecated"
18
- ]);
19
- let deprecationWarned = false;
20
- function warnDeprecated() {
21
- if (deprecationWarned) return;
22
- deprecationWarned = true;
23
- logger.warn("The `Router` and `RouterError` classes from `@fedify/fedify` are deprecated. Please use `Router` from `@fedify/uri-template` instead.");
24
- }
25
- /**
26
- * URL router and constructor based on URI Template
27
- * ([RFC 6570](https://tools.ietf.org/html/rfc6570)).
28
- *
29
- * @deprecated Import `Router` from `@fedify/uri-template` instead. This class
30
- * remains only for compatibility with older Fedify code. The
31
- * `@fedify/uri-template` router is the replacement implementation
32
- * and should be used directly in new code.
33
- */
34
- var Router$1 = class Router$1 {
35
- #router;
36
- /**
37
- * Create a new {@link Router}.
38
- * @param options Options for the router.
39
- * @deprecated Use `new Router(options)` from `@fedify/uri-template`
40
- * instead.
41
- */
42
- constructor(options) {
43
- this.#router = convertRouterError(() => new Router(options));
44
- }
45
- /**
46
- * Whether to ignore trailing slashes when matching paths.
47
- * @deprecated Use `Router` from `@fedify/uri-template` instead. This
48
- * accessor forwards to the underlying `@fedify/uri-template`
49
- * router so that post-construction mutation keeps working as
50
- * in older Fedify code.
51
- */
52
- get trailingSlashInsensitive() {
53
- return this.#router.trailingSlashInsensitive;
54
- }
55
- set trailingSlashInsensitive(value) {
56
- this.#router.trailingSlashInsensitive = value;
57
- }
58
- /**
59
- * Clones this router.
60
- * @deprecated Use `Router` from `@fedify/uri-template` instead.
61
- */
62
- clone() {
63
- return convertRouterError(() => {
64
- const clone = new Router$1();
65
- clone.#router = this.#router.clone();
66
- return clone;
67
- });
68
- }
69
- /**
70
- * Checks if a path name exists in the router.
71
- * @param name The name of the path.
72
- * @returns `true` if the path name exists, otherwise `false`.
73
- * @deprecated Use `Router` from `@fedify/uri-template` instead.
74
- */
75
- has(name) {
76
- return convertRouterError(() => this.#router.has(name));
77
- }
78
- /**
79
- * Adds a new path rule to the router.
80
- * @param template The path pattern.
81
- * @param name The name of the path.
82
- * @returns The names of the variables in the path pattern.
83
- * @deprecated Use `Router` from `@fedify/uri-template` instead. In this
84
- * compatibility class, `add()` both registers the route and
85
- * returns the variables in the path pattern. In
86
- * `@fedify/uri-template`, these two responsibilities are split:
87
- * `router.add(template, name)` registers the route and returns
88
- * `void`, while the pure static method
89
- * `Router.variables(template)` returns the variable names. To
90
- * migrate, call `Router.variables(template)` when variables are
91
- * needed, then call `router.add(template, name)` to register the
92
- * route.
93
- */
94
- add(template, name) {
95
- return convertRouterError(() => {
96
- assertPath(template);
97
- this.#router.add(template, name);
98
- return Router.variables(template);
99
- });
100
- }
101
- /**
102
- * Resolves a path name and values from a URL, if any match.
103
- * @param url The URL to resolve.
104
- * @returns The name of the path and its values, if any match. Otherwise,
105
- * `null`.
106
- * @deprecated Use `Router` from `@fedify/uri-template` instead. Unlike the
107
- * stricter `@fedify/uri-template` router, this compatibility
108
- * method keeps the old Fedify 2.x contract of returning `null`
109
- * (rather than throwing) for inputs that are not router paths.
110
- */
111
- route(url) {
112
- return convertRouterError(() => {
113
- if (!isPath(url)) return null;
114
- return this.#router.route(url);
115
- });
116
- }
117
- /**
118
- * Constructs a URL/path from a path name and values.
119
- * @param name The name of the path.
120
- * @param values The values to expand the path with.
121
- * @returns The URL/path, if the name exists. Otherwise, `null`.
122
- * @deprecated Use `Router` from `@fedify/uri-template` instead.
123
- */
124
- build(name, values) {
125
- return convertRouterError(() => this.#router.build(name, values));
126
- }
127
- };
128
- /**
129
- * An error thrown by the {@link Router}.
130
- * @deprecated Import `RouterError` from `@fedify/uri-template` instead.
131
- */
132
- var RouterError$1 = class extends RouterError {
133
- /**
134
- * Treats every `RouterError` from `@fedify/uri-template` as an instance of
135
- * this deprecated class.
136
- *
137
- * @deprecated Import `RouterError` from `@fedify/uri-template` instead.
138
- */
139
- static [Symbol.hasInstance](instance) {
140
- return instance instanceof RouterError;
141
- }
142
- /**
143
- * Create a new {@link RouterError}.
144
- * @param message The error message.
145
- * @deprecated Import `RouterError` from `@fedify/uri-template` instead.
146
- */
147
- constructor(message) {
148
- super(message);
149
- warnDeprecated();
150
- }
151
- };
152
- function convertRouterError(func) {
153
- try {
154
- warnDeprecated();
155
- return func();
156
- } catch (error) {
157
- if (error instanceof RouterError) throw new RouterError$1(error.message);
158
- throw error;
159
- }
160
- }
161
- //#endregion
162
12
  //#region src/federation/router.test.ts
163
13
  function setUp(options = {}) {
164
14
  const router = new Router$1(options);
@@ -182,8 +32,8 @@ test("Router.clone()", () => {
182
32
  test("Router.add()", () => {
183
33
  const router = new Router$1();
184
34
  assertEquals(router.add("/users", "users"), /* @__PURE__ */ new Set());
185
- assertEquals(router.add("/users/{name}", "user"), new Set(["name"]));
186
- assertEquals(router.add("/users/{name}/posts/{postId}", "post"), new Set(["name", "postId"]));
35
+ assertEquals(router.add("/users/{name}", "user"), /* @__PURE__ */ new Set(["name"]));
36
+ assertEquals(router.add("/users/{name}/posts/{postId}", "post"), /* @__PURE__ */ new Set(["name", "postId"]));
187
37
  assertThrows(() => router.add("foo", "name"), RouterError$1);
188
38
  });
189
39
  test("Router.route()", () => {
@@ -1,20 +1,23 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as esm_default } from "../esm-yYQfPhIY.mjs";
5
- import { t as assertEquals } from "../assert_equals-BV7oLMxm.mjs";
6
- import "../std__assert-B2NnY9bq.mjs";
7
- import { n as assertGreaterOrEqual, r as assertFalse, t as assertRejects } from "../assert_rejects-EgstcQy5.mjs";
8
- import { t as assertInstanceOf } from "../assert_instance_of-Q9KTBnrf.mjs";
9
- import { t as assertNotEquals } from "../assert_not_equals-EPJPoxuf.mjs";
10
- import { t as assert } from "../assert-CJ1KXcvv.mjs";
11
- import { l as verifyRequest } from "../http-CPVMUgsW.mjs";
12
- import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-Dbyd7bhl.mjs";
13
- import { t as doesActorOwnKey } from "../owner-Br9YYzn_.mjs";
14
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-CxHKUNzv.mjs";
4
+ import { t as esm_default } from "../esm-BHXXx4Wx.mjs";
5
+ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
+ import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
7
+ import { t as assertGreaterOrEqual } from "../assert_greater_or_equal-BlafOF4-.mjs";
8
+ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
9
+ import { t as assertNotEquals } from "../assert_not_equals-CpPK2t89.mjs";
10
+ import "../std__assert-DvMDRPes.mjs";
11
+ import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
12
+ import { t as assert } from "../assert-D1Eafmd_.mjs";
13
+ import { f as verifyRequest } from "../http-siciWkmx.mjs";
14
+ import { i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
15
+ import { t as doesActorOwnKey } from "../owner-DYgfTFHy.mjs";
16
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "../send-C4dDpAxm.mjs";
15
17
  import { Activity, Application, Endpoints, Group, Person, Service } from "@fedify/vocab";
18
+ import { FetchError, UrlError } from "@fedify/vocab-runtime";
16
19
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
17
- import { FetchError } from "@fedify/vocab-runtime";
20
+ import dns from "node:dns/promises";
18
21
  import { AggregationTemporality, InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
19
22
  //#region src/federation/send.test.ts
20
23
  test("extractInboxes()", () => {
@@ -42,19 +45,19 @@ test("extractInboxes()", () => {
42
45
  let inboxes = extractInboxes({ recipients });
43
46
  assertEquals(inboxes, {
44
47
  "https://example.com/alice/inbox": {
45
- actorIds: new Set(["https://example.com/alice"]),
48
+ actorIds: /* @__PURE__ */ new Set(["https://example.com/alice"]),
46
49
  sharedInbox: false
47
50
  },
48
51
  "https://example.com/app/inbox": {
49
- actorIds: new Set(["https://example.com/app"]),
52
+ actorIds: /* @__PURE__ */ new Set(["https://example.com/app"]),
50
53
  sharedInbox: false
51
54
  },
52
55
  "https://example.org/group/inbox": {
53
- actorIds: new Set(["https://example.org/group"]),
56
+ actorIds: /* @__PURE__ */ new Set(["https://example.org/group"]),
54
57
  sharedInbox: false
55
58
  },
56
59
  "https://example.net/service/inbox": {
57
- actorIds: new Set(["https://example.net/service"]),
60
+ actorIds: /* @__PURE__ */ new Set(["https://example.net/service"]),
58
61
  sharedInbox: false
59
62
  }
60
63
  });
@@ -64,15 +67,15 @@ test("extractInboxes()", () => {
64
67
  });
65
68
  assertEquals(inboxes, {
66
69
  "https://example.com/inbox": {
67
- actorIds: new Set(["https://example.com/alice", "https://example.com/app"]),
70
+ actorIds: /* @__PURE__ */ new Set(["https://example.com/alice", "https://example.com/app"]),
68
71
  sharedInbox: true
69
72
  },
70
73
  "https://example.org/group/inbox": {
71
- actorIds: new Set(["https://example.org/group"]),
74
+ actorIds: /* @__PURE__ */ new Set(["https://example.org/group"]),
72
75
  sharedInbox: false
73
76
  },
74
77
  "https://example.net/inbox": {
75
- actorIds: new Set(["https://example.net/service"]),
78
+ actorIds: /* @__PURE__ */ new Set(["https://example.net/service"]),
76
79
  sharedInbox: true
77
80
  }
78
81
  });
@@ -82,19 +85,19 @@ test("extractInboxes()", () => {
82
85
  });
83
86
  assertEquals(inboxes, {
84
87
  "https://example.com/alice/inbox": {
85
- actorIds: new Set(["https://example.com/alice"]),
88
+ actorIds: /* @__PURE__ */ new Set(["https://example.com/alice"]),
86
89
  sharedInbox: false
87
90
  },
88
91
  "https://example.com/app/inbox": {
89
- actorIds: new Set(["https://example.com/app"]),
92
+ actorIds: /* @__PURE__ */ new Set(["https://example.com/app"]),
90
93
  sharedInbox: false
91
94
  },
92
95
  "https://example.org/group/inbox": {
93
- actorIds: new Set(["https://example.org/group"]),
96
+ actorIds: /* @__PURE__ */ new Set(["https://example.org/group"]),
94
97
  sharedInbox: false
95
98
  },
96
99
  "https://example.net/service/inbox": {
97
- actorIds: new Set(["https://example.net/service"]),
100
+ actorIds: /* @__PURE__ */ new Set(["https://example.net/service"]),
98
101
  sharedInbox: false
99
102
  }
100
103
  });
@@ -104,11 +107,11 @@ test("extractInboxes()", () => {
104
107
  });
105
108
  assertEquals(inboxes, {
106
109
  "https://example.org/group/inbox": {
107
- actorIds: new Set(["https://example.org/group"]),
110
+ actorIds: /* @__PURE__ */ new Set(["https://example.org/group"]),
108
111
  sharedInbox: false
109
112
  },
110
113
  "https://example.net/service/inbox": {
111
- actorIds: new Set(["https://example.net/service"]),
114
+ actorIds: /* @__PURE__ */ new Set(["https://example.net/service"]),
112
115
  sharedInbox: false
113
116
  }
114
117
  });
@@ -119,11 +122,11 @@ test("extractInboxes()", () => {
119
122
  });
120
123
  assertEquals(inboxes, {
121
124
  "https://example.org/group/inbox": {
122
- actorIds: new Set(["https://example.org/group"]),
125
+ actorIds: /* @__PURE__ */ new Set(["https://example.org/group"]),
123
126
  sharedInbox: false
124
127
  },
125
128
  "https://example.net/inbox": {
126
- actorIds: new Set(["https://example.net/service"]),
129
+ actorIds: /* @__PURE__ */ new Set(["https://example.net/service"]),
127
130
  sharedInbox: true
128
131
  }
129
132
  });
@@ -463,6 +466,7 @@ test("sendActivity() records OpenTelemetry delivery metrics", async (t) => {
463
466
  activityId: "https://example.com/activity",
464
467
  activityType: "https://www.w3.org/ns/activitystreams#Create",
465
468
  keys: [],
469
+ allowPrivateAddress: true,
466
470
  inbox: new URL("https://metrics.example:8443/inbox/path?x=1"),
467
471
  meterProvider
468
472
  });
@@ -500,6 +504,7 @@ test("sendActivity() records OpenTelemetry delivery metrics", async (t) => {
500
504
  activityId: "https://example.com/follow",
501
505
  activityType: "https://www.w3.org/ns/activitystreams#Follow",
502
506
  keys: [],
507
+ allowPrivateAddress: true,
503
508
  inbox: new URL("https://metrics.example/inbox"),
504
509
  meterProvider
505
510
  }), SendActivityError);
@@ -537,6 +542,7 @@ test("sendActivity() exports delivery metrics through OpenTelemetry SDK", async
537
542
  activityId: "https://example.com/activity",
538
543
  activityType: "https://www.w3.org/ns/activitystreams#Create",
539
544
  keys: [],
545
+ allowPrivateAddress: true,
540
546
  inbox: new URL("https://sdk-metrics.example/inbox"),
541
547
  meterProvider
542
548
  });
@@ -553,5 +559,217 @@ test("sendActivity() exports delivery metrics through OpenTelemetry SDK", async
553
559
  }
554
560
  }
555
561
  });
562
+ for (const signed of [false, true]) {
563
+ const keys = [{
564
+ privateKey: signed ? rsaPrivateKey2 : ed25519PrivateKey,
565
+ keyId: signed ? rsaPublicKey2.id : ed25519Multikey.id
566
+ }];
567
+ test(`sendActivity() validates destinations (signed: ${signed})`, async (t) => {
568
+ const activity = {
569
+ type: "Create",
570
+ id: "https://example.com/activity"
571
+ };
572
+ const publicInbox = "https://8.8.8.8/inbox";
573
+ const privateInbox = "http://127.0.0.1/inbox";
574
+ for (const target of [
575
+ privateInbox,
576
+ "http://169.254.169.254/",
577
+ "http://[::1]/"
578
+ ]) await t.step(`rejects ${target} before fetching`, async () => {
579
+ esm_default.mockGlobal().catch(202);
580
+ try {
581
+ await assertRejects(() => sendActivity({
582
+ activity,
583
+ keys,
584
+ inbox: new URL(target)
585
+ }), UrlError);
586
+ assertEquals(esm_default.callHistory.calls().length, 0);
587
+ } finally {
588
+ esm_default.hardReset();
589
+ }
590
+ });
591
+ for (const status of [
592
+ 301,
593
+ 302,
594
+ 303,
595
+ 307,
596
+ 308
597
+ ]) for (const allowPrivateAddress of [false, true]) await t.step(`${status} private redirect, opt-in: ${allowPrivateAddress}`, async () => {
598
+ esm_default.mockGlobal();
599
+ esm_default.route(publicInbox, {
600
+ status,
601
+ headers: { Location: privateInbox }
602
+ });
603
+ esm_default.route(privateInbox, 202);
604
+ try {
605
+ const send = () => sendActivity({
606
+ activity,
607
+ keys,
608
+ inbox: new URL(publicInbox),
609
+ allowPrivateAddress
610
+ });
611
+ if (allowPrivateAddress) {
612
+ await send();
613
+ const calls = esm_default.callHistory.calls(privateInbox);
614
+ assertEquals(calls.length, 1);
615
+ const request = calls[0].request;
616
+ const preservesBody = signed || status === 307 || status === 308;
617
+ assertEquals(request.method, preservesBody ? "POST" : "GET");
618
+ assertEquals(await request.clone().text(), preservesBody ? JSON.stringify(activity) : "");
619
+ } else {
620
+ await assertRejects(send, UrlError);
621
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 0);
622
+ }
623
+ } finally {
624
+ esm_default.hardReset();
625
+ }
626
+ });
627
+ await t.step("rejects a private destination after a public redirect", async () => {
628
+ esm_default.mockGlobal().route(publicInbox, {
629
+ status: 307,
630
+ headers: { Location: "/next" }
631
+ }).route("https://8.8.8.8/next", {
632
+ status: 308,
633
+ headers: { Location: privateInbox }
634
+ }).route(privateInbox, 202);
635
+ try {
636
+ await assertRejects(() => sendActivity({
637
+ activity,
638
+ keys,
639
+ inbox: new URL(publicInbox)
640
+ }), UrlError);
641
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 0);
642
+ } finally {
643
+ esm_default.hardReset();
644
+ }
645
+ });
646
+ await t.step("limits redirect loops", async () => {
647
+ esm_default.mockGlobal().route(publicInbox, {
648
+ status: 307,
649
+ headers: { Location: publicInbox }
650
+ });
651
+ try {
652
+ await assertRejects(() => sendActivity({
653
+ activity,
654
+ keys,
655
+ inbox: new URL(publicInbox)
656
+ }));
657
+ assert(esm_default.callHistory.calls().length <= 21);
658
+ } finally {
659
+ esm_default.hardReset();
660
+ }
661
+ });
662
+ await t.step("allows a direct private inbox with opt-in", async () => {
663
+ esm_default.mockGlobal().route(privateInbox, 202);
664
+ try {
665
+ await sendActivity({
666
+ activity,
667
+ keys,
668
+ inbox: new URL(privateInbox),
669
+ allowPrivateAddress: true
670
+ });
671
+ assertEquals(esm_default.callHistory.calls(privateInbox).length, 1);
672
+ } finally {
673
+ esm_default.hardReset();
674
+ }
675
+ });
676
+ await t.step("allows relative public redirects", async () => {
677
+ esm_default.mockGlobal().route(publicInbox, {
678
+ status: 307,
679
+ headers: { Location: "/next" }
680
+ }).route("https://8.8.8.8/next", 202);
681
+ try {
682
+ await sendActivity({
683
+ activity,
684
+ keys,
685
+ inbox: new URL(publicInbox)
686
+ });
687
+ assertEquals(esm_default.callHistory.calls("https://8.8.8.8/next").length, 1);
688
+ } finally {
689
+ esm_default.hardReset();
690
+ }
691
+ });
692
+ });
693
+ }
694
+ for (const signed of [false, true]) test({
695
+ name: `sendActivity() classifies DNS failures (signed: ${signed})`,
696
+ ignore: "Deno" in globalThis && (await Deno.permissions.query({ name: "net" })).state !== "granted",
697
+ async fn(t) {
698
+ const activity = {
699
+ type: "Create",
700
+ id: "https://example.com/activity"
701
+ };
702
+ const destination = "https://delivery.invalid/inbox";
703
+ const publicInbox = "https://8.8.8.8/inbox";
704
+ const keys = signed ? [{
705
+ privateKey: rsaPrivateKey2,
706
+ keyId: rsaPublicKey2.id
707
+ }] : [];
708
+ for (const result of [
709
+ "throws",
710
+ "empty",
711
+ "cname",
712
+ "private"
713
+ ]) for (const redirected of [false, true]) await t.step(`${result}, redirected: ${redirected}`, async () => {
714
+ const [meterProvider, recorder] = createTestMeterProvider();
715
+ const originalLookup = dns.lookup;
716
+ const resolverError = /* @__PURE__ */ new Error("Resolver unavailable");
717
+ const lookups = [];
718
+ dns.lookup = ((hostname, options) => {
719
+ lookups.push(hostname);
720
+ assertEquals(hostname, "delivery.invalid");
721
+ assertEquals(options, { all: true });
722
+ if (result === "throws") return Promise.reject(resolverError);
723
+ return Promise.resolve(result === "empty" ? [] : [{
724
+ address: result === "private" ? "127.0.0.1" : "alias.invalid.",
725
+ family: 4
726
+ }]);
727
+ });
728
+ try {
729
+ esm_default.mockGlobal().catch(202);
730
+ if (redirected) esm_default.route(publicInbox, {
731
+ status: 307,
732
+ headers: { Location: destination }
733
+ });
734
+ const send = () => sendActivity({
735
+ activity,
736
+ activityType: "https://www.w3.org/ns/activitystreams#Create",
737
+ meterProvider,
738
+ keys,
739
+ inbox: new URL(redirected ? publicInbox : destination)
740
+ });
741
+ if (result === "private") assertEquals((await assertRejects(send, UrlError)).reason, "disallowed");
742
+ else {
743
+ const error = await assertRejects(send, FetchError);
744
+ assertEquals(error.url.href, destination);
745
+ assertInstanceOf(error.cause, UrlError);
746
+ assertEquals(error.cause.reason, "dns");
747
+ assertEquals(error.cause.cause, result === "throws" ? resolverError : void 0);
748
+ }
749
+ const expectedCount = result === "private" && !redirected ? 0 : 1;
750
+ const sent = recorder.getMeasurements("activitypub.delivery.sent");
751
+ const durations = recorder.getMeasurements("activitypub.delivery.duration");
752
+ assertEquals(sent.length, expectedCount);
753
+ assertEquals(durations.length, expectedCount);
754
+ if (expectedCount === 1) {
755
+ assertEquals(sent[0].value, 1);
756
+ assertEquals(sent[0].attributes, {
757
+ "activitypub.remote.host": redirected ? "8.8.8.8" : "delivery.invalid",
758
+ "activitypub.activity.type": "https://www.w3.org/ns/activitystreams#Create",
759
+ "activitypub.delivery.success": false
760
+ });
761
+ assertEquals(durations[0].attributes, sent[0].attributes);
762
+ assertGreaterOrEqual(durations[0].value, 0);
763
+ }
764
+ assertEquals(lookups, ["delivery.invalid"]);
765
+ assertEquals(esm_default.callHistory.calls(destination).length, 0);
766
+ assertEquals(esm_default.callHistory.calls().length, redirected ? 1 : 0);
767
+ } finally {
768
+ dns.lookup = originalLookup;
769
+ esm_default.hardReset();
770
+ }
771
+ });
772
+ }
773
+ });
556
774
  //#endregion
557
775
  export {};
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as TaskCodec } from "../../codec-BBga-FWI.mjs";
4
+ import { t as TaskCodec } from "../../codec-C6rTrpIp.mjs";
5
5
  import { Create, Link, Note, Person } from "@fedify/vocab";
6
6
  import { mockDocumentLoader, test } from "@fedify/fixture";
7
7
  import { deepStrictEqual, ok, rejects, strictEqual } from "node:assert/strict";
@@ -45,8 +45,8 @@ test("TaskCodec.serialize() / deserialize()", async (t) => {
45
45
  big: 1234567890123456789n,
46
46
  url: new URL("https://example.com/some/path"),
47
47
  list: [person, link],
48
- map: new Map([["create", create], ["n", 42]]),
49
- set: new Set([
48
+ map: /* @__PURE__ */ new Map([["create", create], ["n", 42]]),
49
+ set: /* @__PURE__ */ new Set([
50
50
  1,
51
51
  2,
52
52
  3
@@ -72,7 +72,7 @@ test("TaskCodec.serialize() / deserialize()", async (t) => {
72
72
  const map = decoded.map;
73
73
  ok(map.get("create") instanceof Create);
74
74
  strictEqual(map.get("n"), 42);
75
- deepStrictEqual(decoded.set, new Set([
75
+ deepStrictEqual(decoded.set, /* @__PURE__ */ new Set([
76
76
  1,
77
77
  2,
78
78
  3
@@ -1,10 +1,11 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as MemoryKvStore } from "../../kv-CXBAok3k.mjs";
5
- import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../testing-CO7ftO8A.mjs";
6
- import { o as createFederation } from "../../middleware-CvwTUgnP.mjs";
7
- import { n as ParallelMessageQueue } from "../../mq-llHKivST.mjs";
4
+ import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
+ import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-IG3pHfvZ.mjs";
6
+ import "../../testing-t8xDeJZ5.mjs";
7
+ import { o as createFederation } from "../../middleware-D7_LO-Vs.mjs";
8
+ import { n as ParallelMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
8
9
  import { configure, reset } from "@logtape/logtape";
9
10
  import { delay } from "es-toolkit";
10
11
  import { createTestMeterProvider, test } from "@fedify/fixture";
@@ -760,6 +761,43 @@ test("a multi-item batch dedup without enqueueMany is rejected on the cas path",
760
761
  await ctx.enqueueTaskMany(task, ["single"], { deduplicationKey: "single" });
761
762
  strictEqual(queue.enqueued.length, 1);
762
763
  });
764
+ test("a non-atomic enqueueMany is rejected for batch deduplication", async () => {
765
+ class NonAtomicBatchQueue extends MockQueue {
766
+ atomicEnqueueMany = false;
767
+ constructor() {
768
+ super({ supportsEnqueueMany: true });
769
+ }
770
+ }
771
+ const queue = new NonAtomicBatchQueue();
772
+ const kv = new MemoryKvStore();
773
+ const federation = createFederation({
774
+ ...baseOptions,
775
+ kv,
776
+ queue: { task: queue }
777
+ });
778
+ const task = federation.defineTask("cas-non-atomic-batch", {
779
+ schema: stringSchema,
780
+ handler: () => {}
781
+ });
782
+ const ctx = federation.createContext(new URL("https://example.com/"), void 0);
783
+ await rejects(() => ctx.enqueueTaskMany(task, [
784
+ "a",
785
+ "b",
786
+ "c"
787
+ ], { deduplicationKey: "batch" }), {
788
+ name: "TypeError",
789
+ message: /atomically/
790
+ });
791
+ strictEqual(queue.enqueued.length, 0);
792
+ strictEqual(queue.enqueuedMany.length, 0);
793
+ deepStrictEqual(await collectKeys(kv, TASK_DEDUP_PREFIX), []);
794
+ await ctx.enqueueTaskMany(task, [
795
+ "a",
796
+ "b",
797
+ "c"
798
+ ]);
799
+ strictEqual(queue.enqueuedMany.length, 1);
800
+ });
763
801
  test("a failed rollback is swallowed; the original enqueue error reaches the caller", async () => {
764
802
  class ClearFailingKvStore {
765
803
  inner = new MemoryKvStore();
@@ -1,12 +1,13 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { t as MemoryKvStore } from "../../kv-CXBAok3k.mjs";
5
- import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../testing-CO7ftO8A.mjs";
6
- import { o as createFederation } from "../../middleware-CvwTUgnP.mjs";
7
- import { r as createFederationBuilder } from "../../builder-DonuxRl_.mjs";
8
- import { t as TaskCodec } from "../../codec-BBga-FWI.mjs";
9
- import { t as InProcessMessageQueue } from "../../mq-llHKivST.mjs";
4
+ import { t as MemoryKvStore } from "../../kv-DCHkaJ9-.mjs";
5
+ import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, t as MockQueue } from "../../tasks-IG3pHfvZ.mjs";
6
+ import "../../testing-t8xDeJZ5.mjs";
7
+ import { o as createFederation } from "../../middleware-D7_LO-Vs.mjs";
8
+ import { r as createFederationBuilder } from "../../builder-Bda6LK7A.mjs";
9
+ import { t as TaskCodec } from "../../codec-C6rTrpIp.mjs";
10
+ import { t as InProcessMessageQueue } from "../../mq-Dm1Wmtm-.mjs";
10
11
  import { W3CTraceContextPropagator } from "@opentelemetry/core";
11
12
  import { Note } from "@fedify/vocab";
12
13
  import { SpanStatusCode, propagation } from "@opentelemetry/api";