@fedify/fedify 2.3.0-dev.1190 → 2.3.0-dev.1213

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 (83) hide show
  1. package/dist/{builder-BzgNpXoY.mjs → builder-Bj-7Sl7u.mjs} +9 -2
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/outgoing-jsonld.test.mjs +1 -1
  5. package/dist/compat/public-audience.test.mjs +1 -1
  6. package/dist/compat/transformers.test.mjs +2 -2
  7. package/dist/{context-DMHK7jqX.d.cts → context-BBVLF7lx.d.cts} +41 -2
  8. package/dist/{context-K9cg8oGx.d.ts → context-BU6jSQdo.d.ts} +42 -2
  9. package/dist/{deno-CoAwVm1I.mjs → deno-BUzynMVz.mjs} +1 -1
  10. package/dist/{docloader-hPqZT20O.mjs → docloader-jQPthO4U.mjs} +2 -2
  11. package/dist/{esm-BQRw925N.mjs → esm-vrlUxr60.mjs} +23 -1
  12. package/dist/federation/builder.test.mjs +21 -2
  13. package/dist/federation/circuit-breaker.test.mjs +1 -1
  14. package/dist/federation/handler.test.mjs +6 -6
  15. package/dist/federation/idempotency.test.mjs +4 -4
  16. package/dist/federation/keycache.test.mjs +1 -1
  17. package/dist/federation/kv.test.mjs +1 -1
  18. package/dist/federation/metrics.test.mjs +147 -1
  19. package/dist/federation/middleware.test.mjs +446 -18
  20. package/dist/federation/mod.cjs +1 -1
  21. package/dist/federation/mod.d.cts +3 -3
  22. package/dist/federation/mod.d.ts +3 -3
  23. package/dist/federation/mod.js +1 -1
  24. package/dist/federation/send.test.mjs +8 -4426
  25. package/dist/federation/temporal.test.mjs +1 -1
  26. package/dist/federation/webfinger.test.mjs +2 -2
  27. package/dist/{http-BAarxBe5.cjs → http-B1zlPuh3.cjs} +79 -2
  28. package/dist/{http-Dq_qElWc.js → http-B_WbYMnB.js} +74 -3
  29. package/dist/{http-CSwCAQ-H.mjs → http-CDaMGwCP.mjs} +4 -4
  30. package/dist/{key-DYK_T_PD.mjs → key-DdP4HxTK.mjs} +2 -2
  31. package/dist/{kv-cache-Ds1kjvnu.cjs → kv-cache-CPIfTWt5.cjs} +1 -1
  32. package/dist/{kv-cache-BhPocHdd.js → kv-cache-CXo8QM4m.js} +1 -1
  33. package/dist/{kv-cache-CFzIDCMJ.mjs → kv-cache-DSjv5Aeh.mjs} +1 -1
  34. package/dist/{ld-BdcT_irA.mjs → ld-CuOEh5aB.mjs} +3 -3
  35. package/dist/{metrics-Ci97wkob.mjs → metrics-B5vvJYMV.mjs} +74 -3
  36. package/dist/{middleware-BUGT2LmO.mjs → middleware-Cq9S8A5O.mjs} +328 -24
  37. package/dist/{middleware-hWs3qtrr.mjs → middleware-DPE-IRlD.mjs} +1 -1
  38. package/dist/{middleware-C-C_I_wJ.js → middleware-Dft_sYeS.js} +352 -41
  39. package/dist/{middleware-ddMAHsyF.cjs → middleware-DlqW4IRW.cjs} +351 -40
  40. package/dist/{mod-YLnSsEHY.d.cts → mod-C0F6kvgS.d.cts} +1 -1
  41. package/dist/{mod-CfOFqS0w.d.ts → mod-vPYVoa5n.d.ts} +1 -1
  42. package/dist/mod.cjs +4 -4
  43. package/dist/mod.d.cts +4 -4
  44. package/dist/mod.d.ts +4 -4
  45. package/dist/mod.js +4 -4
  46. package/dist/nodeinfo/client.test.mjs +2 -2
  47. package/dist/nodeinfo/handler.test.mjs +2 -2
  48. package/dist/nodeinfo/types.test.mjs +1 -1
  49. package/dist/otel/exporter.test.mjs +1 -1
  50. package/dist/{outgoing-jsonld-BgFLCJQ_.mjs → outgoing-jsonld-L_DbOaFe.mjs} +1 -1
  51. package/dist/{owner-B8ePZh4q.mjs → owner--n8rmG51.mjs} +2 -2
  52. package/dist/{proof-CXdtqYKw.cjs → proof-BKpJ_p_d.cjs} +1 -1
  53. package/dist/{proof-Dq_RyTjd.js → proof-BsvB1vGI.js} +1 -1
  54. package/dist/{proof-CzqluPMh.mjs → proof-dhtwaP4z.mjs} +5 -5
  55. package/dist/{send-NzJqiStx.mjs → send-CTQ30Wbe.mjs} +3 -3
  56. package/dist/sig/accept.test.mjs +1 -1
  57. package/dist/sig/http.test.mjs +4 -4
  58. package/dist/sig/key.test.mjs +2 -2
  59. package/dist/sig/ld.test.mjs +3 -3
  60. package/dist/sig/mod.cjs +2 -2
  61. package/dist/sig/mod.js +2 -2
  62. package/dist/sig/owner.test.mjs +2 -2
  63. package/dist/sig/proof.test.mjs +3 -3
  64. package/dist/{temporal-CnhE0LLn.mjs → temporal-gfUaZjGU.mjs} +1 -1
  65. package/dist/testing/mod.d.mts +1 -0
  66. package/dist/utils/docloader.test.mjs +4 -4
  67. package/dist/utils/kv-cache.test.mjs +1 -1
  68. package/dist/utils/mod.cjs +1 -1
  69. package/dist/utils/mod.js +1 -1
  70. package/package.json +8 -8
  71. package/dist/chunk-DNRtMIoB.mjs +0 -29
  72. package/dist/execAsync-Dmet7-28.mjs +0 -13
  73. package/dist/getMachineId-bsd-Bn0le7-J.mjs +0 -29
  74. package/dist/getMachineId-darwin-CVjKuDgj.mjs +0 -26
  75. package/dist/getMachineId-linux-DbG4BXa-.mjs +0 -22
  76. package/dist/getMachineId-unsupported-lC8T9hPE.mjs +0 -17
  77. package/dist/getMachineId-win-c5zxTSS1.mjs +0 -28
  78. /package/dist/{accept-CceiKpCy.mjs → accept-CPkZzmGN.mjs} +0 -0
  79. /package/dist/{client-B_A6mfn3.mjs → client-ByXmQhYD.mjs} +0 -0
  80. /package/dist/{keys-C3kae-6B.mjs → keys-DGu1NFwu.mjs} +0 -0
  81. /package/dist/{kv-x2IvBUyq.mjs → kv-rV3vodCc.mjs} +0 -0
  82. /package/dist/{public-audience-N3pyOx2p.mjs → public-audience-Cvbr2Gzt.mjs} +0 -0
  83. /package/dist/{types-BFowWFTT.mjs → types-J53Kw7so.mjs} +0 -0
@@ -1,7 +1,7 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-CoAwVm1I.mjs";
4
+ import { n as version, t as name } from "./deno-BUzynMVz.mjs";
5
5
  import { t as ActivityListenerSet } from "./activity-listener-tztVvlNb.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { Router, RouterError, assertPath } from "@fedify/uri-template";
@@ -72,8 +72,15 @@ var FederationBuilderImpl = class {
72
72
  this.collectionCallbacks = {};
73
73
  this.collectionTypeIds = {};
74
74
  }
75
+ /**
76
+ * Builds the federation object.
77
+ * @param options Parameters for initializing the federation object.
78
+ * @returns The federation object.
79
+ * @throws {TypeError} If benchmark mode and `meterProvider` are both
80
+ * specified.
81
+ */
75
82
  async build(options) {
76
- const { FederationImpl } = await import("./middleware-hWs3qtrr.mjs");
83
+ const { FederationImpl } = await import("./middleware-DPE-IRlD.mjs");
77
84
  const f = new FederationImpl(options);
78
85
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
79
86
  f.router = this.router.clone();
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { At as ActivityTransformer, n as Context } from "../context-DMHK7jqX.cjs";
2
+ import { jt as ActivityTransformer, n as Context } from "../context-BBVLF7lx.cjs";
3
3
  import { Activity } from "@fedify/vocab";
4
4
 
5
5
  //#region src/compat/transformers.d.ts
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { At as ActivityTransformer, n as Context } from "../context-K9cg8oGx.js";
2
+ import { jt as ActivityTransformer, n as Context } from "../context-BU6jSQdo.js";
3
3
  import { Activity } from "@fedify/vocab";
4
4
 
5
5
  //#region src/compat/transformers.d.ts
@@ -3,7 +3,7 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { t as assertStrictEquals } from "../assert_strict_equals-XEgZAlrj.mjs";
6
- import { n as normalizeAttachmentArrays, r as normalizeOutgoingActivityJsonLd, t as isPreloadedContextAttachmentSafe } from "../outgoing-jsonld-BgFLCJQ_.mjs";
6
+ import { n as normalizeAttachmentArrays, r as normalizeOutgoingActivityJsonLd, t as isPreloadedContextAttachmentSafe } from "../outgoing-jsonld-L_DbOaFe.mjs";
7
7
  import { Create, Document, Note, PUBLIC_COLLECTION } from "@fedify/vocab";
8
8
  import { mockDocumentLoader, test } from "@fedify/fixture";
9
9
  //#region src/compat/outgoing-jsonld.test.ts
@@ -3,7 +3,7 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { t as assertNotEquals } from "../assert_not_equals-DkVK8oqV.mjs";
6
- import { t as normalizePublicAudience } from "../public-audience-N3pyOx2p.mjs";
6
+ import { t as normalizePublicAudience } from "../public-audience-Cvbr2Gzt.mjs";
7
7
  import { Create, Note, PUBLIC_COLLECTION } from "@fedify/vocab";
8
8
  import { test } from "@fedify/fixture";
9
9
  import { getDocumentLoader, preloadedContexts } from "@fedify/vocab-runtime";
@@ -4,8 +4,8 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
6
6
  import { t as assert } from "../assert-OguE97r2.mjs";
7
- import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
8
- import { n as FederationImpl, v as actorDehydrator, y as autoIdAssigner } from "../middleware-BUGT2LmO.mjs";
7
+ import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
+ import { b as autoIdAssigner, n as FederationImpl, y as actorDehydrator } from "../middleware-Cq9S8A5O.mjs";
9
9
  import { Follow, Person } from "@fedify/vocab";
10
10
  import { test } from "@fedify/fixture";
11
11
  //#region src/compat/transformers.test.ts
@@ -881,8 +881,10 @@ interface FederationOrigin {
881
881
  }
882
882
  /**
883
883
  * Create a new {@link Federation} instance.
884
- * @param parameters Parameters for initializing the instance.
884
+ * @param options Parameters for initializing the instance.
885
885
  * @returns A new {@link Federation} instance.
886
+ * @throws {TypeError} If benchmark mode and `meterProvider` are both
887
+ * specified.
886
888
  * @since 0.10.0
887
889
  */
888
890
  declare function createFederation<TContextData>(options: FederationOptions<TContextData>): Federation<TContextData>;
@@ -1367,7 +1369,10 @@ interface Federation<TContextData> extends Federatable<TContextData> {
1367
1369
  interface FederationBuilder<TContextData> extends Federatable<TContextData> {
1368
1370
  /**
1369
1371
  * Builds the federation object.
1372
+ * @param options Parameters for initializing the federation object.
1370
1373
  * @returns The federation object.
1374
+ * @throws {TypeError} If benchmark mode and `meterProvider` are both
1375
+ * specified.
1371
1376
  */
1372
1377
  build(options: FederationOptions<TContextData>): Promise<Federation<TContextData>>;
1373
1378
  }
@@ -1405,6 +1410,25 @@ interface InboxChallengePolicy {
1405
1410
  nonceTtlSeconds?: number;
1406
1411
  }
1407
1412
  /**
1413
+ * Options for cooperative benchmark mode.
1414
+ * @since 2.3.0
1415
+ */
1416
+ interface FederationBenchmarkOptions {
1417
+ /**
1418
+ * Server-controlled inbox URLs that the benchmark trigger endpoint may
1419
+ * deliver to.
1420
+ */
1421
+ triggerSinks?: readonly (string | URL)[];
1422
+ /**
1423
+ * Whether the benchmark trigger endpoint may deliver to recipients outside
1424
+ * {@link FederationBenchmarkOptions.triggerSinks}.
1425
+ *
1426
+ * Do not enable this option unless the benchmark endpoint is only reachable
1427
+ * by a trusted benchmark controller.
1428
+ */
1429
+ allowUnsafeTriggerRecipients?: boolean;
1430
+ }
1431
+ /**
1408
1432
  * Options for creating a {@link Federation} object.
1409
1433
  * @template TContextData The context data to pass to the {@link Context}.
1410
1434
  * @since 1.6.0
@@ -1484,6 +1508,21 @@ interface FederationOptions<TContextData> {
1484
1508
  */
1485
1509
  allowPrivateAddress?: boolean;
1486
1510
  /**
1511
+ * Whether to enable cooperative benchmark mode. This mode exposes
1512
+ * benchmark-only endpoints and relaxes selected defaults for benchmark
1513
+ * targets. Pass an object to configure benchmark trigger delivery.
1514
+ * Do not enable this option in production.
1515
+ *
1516
+ * When enabled, {@link FederationOptions.allowPrivateAddress} defaults to
1517
+ * `true` unless {@link FederationOptions.documentLoaderFactory} or
1518
+ * {@link FederationOptions.contextLoaderFactory} is configured, and
1519
+ * {@link FederationOptions.signatureTimeWindow} defaults to `false`.
1520
+ *
1521
+ * Turned off by default.
1522
+ * @since 2.3.0
1523
+ */
1524
+ benchmarkMode?: boolean | FederationBenchmarkOptions;
1525
+ /**
1487
1526
  * Options for making `User-Agent` strings for HTTP requests.
1488
1527
  * If a string is provided, it is used as the `User-Agent` header.
1489
1528
  * If an object is provided, it is passed to the {@link getUserAgent}
@@ -2842,4 +2881,4 @@ interface ActorKeyPair extends CryptoKeyPair {
2842
2881
  readonly multikey: Multikey;
2843
2882
  }
2844
2883
  //#endregion
2845
- export { CustomCollectionDispatcher as $, FederationKvPrefixes as A, ActivityTransformer as At, RespondWithObjectOptions as B, IdempotencyKeyCallback as C, CircuitBreakerKvState as Ct, ObjectCallbackSetters as D, NormalizedCircuitBreakerOptions as Dt, InboxListenerSetters as E, CircuitBreakerStateChange as Et, RetryContext as F, ActorHandleMapper as G, respondWithObjectIfAcceptable as H, RetryPolicy as I, CollectionCounter as J, ActorKeyPairsDispatcher as K, createExponentialBackoffPolicy as L, FederationQueueOptions as M, createFederation as N, OutboxListenerSetters as O, normalizeCircuitBreakerOptions as Ot, CreateExponentialBackoffPolicyOptions as P, CustomCollectionCursor as Q, Message as R, FederationStartQueueOptions as S, CircuitBreakerFailurePolicy as St, InboxChallengePolicy as T, CircuitBreakerState as Tt, ActorAliasMapper as U, respondWithObject as V, ActorDispatcher as W, CollectionDispatcher as X, CollectionCursor as Y, CustomCollectionCounter as Z, Federatable as _, digest as _t, GetSignedKeyOptions as a, OutboxErrorHandler as at, FederationFetchOptions as b, CircuitBreakerBeforeSendDecision as bt, ParseUriResult as c, OutboxPermanentFailureHandler as ct, SendActivityOptions as d, UnverifiedActivityReason as dt, InboxErrorHandler as et, SendActivityOptionsForCollection as f, WebFingerLinksDispatcher as ft, CustomCollectionCallbackSetters as g, buildCollectionSynchronizationHeader as gt, ConstructorWithTypeId as h, PageItems as ht, GetActorOptions as i, ObjectDispatcher as it, FederationOrigin as j, Rfc6570Expression as k, parseCircuitBreakerKvState as kt, RequestContext as l, SharedInboxKeyDispatcher as lt, CollectionCallbackSetters as m, SenderKeyPair as mt, Context as n, NodeInfoDispatcher as nt, InboxContext as o, OutboxListener as ot, ActorCallbackSetters as p, SendActivityError as pt, AuthorizePredicate as q, ForwardActivityOptions as r, ObjectAuthorizePredicate as rt, OutboxContext as s, OutboxListenerErrorHandler as st, ActorKeyPair as t, InboxListener as tt, RouteActivityOptions as u, UnverifiedActivityHandler as ut, Federation as v, CircuitBreaker as vt, IdempotencyStrategy as w, CircuitBreakerOptions as wt, FederationOptions as x, CircuitBreakerCreateOptions as xt, FederationBuilder as y, CircuitBreakerActivityDrop as yt, createFederationBuilder as z };
2884
+ export { CustomCollectionCursor as $, Rfc6570Expression as A, parseCircuitBreakerKvState as At, createFederationBuilder as B, FederationStartQueueOptions as C, CircuitBreakerFailurePolicy as Ct, InboxListenerSetters as D, CircuitBreakerStateChange as Dt, InboxChallengePolicy as E, CircuitBreakerState as Et, CreateExponentialBackoffPolicyOptions as F, ActorDispatcher as G, respondWithObject as H, RetryContext as I, AuthorizePredicate as J, ActorHandleMapper as K, RetryPolicy as L, FederationOrigin as M, FederationQueueOptions as N, ObjectCallbackSetters as O, NormalizedCircuitBreakerOptions as Ot, createFederation as P, CustomCollectionCounter as Q, createExponentialBackoffPolicy as R, FederationOptions as S, CircuitBreakerCreateOptions as St, IdempotencyStrategy as T, CircuitBreakerOptions as Tt, respondWithObjectIfAcceptable as U, RespondWithObjectOptions as V, ActorAliasMapper as W, CollectionCursor as X, CollectionCounter as Y, CollectionDispatcher as Z, Federatable as _, buildCollectionSynchronizationHeader as _t, GetSignedKeyOptions as a, ObjectDispatcher as at, FederationBuilder as b, CircuitBreakerActivityDrop as bt, ParseUriResult as c, OutboxListenerErrorHandler as ct, SendActivityOptions as d, UnverifiedActivityHandler as dt, CustomCollectionDispatcher as et, SendActivityOptionsForCollection as f, UnverifiedActivityReason as ft, CustomCollectionCallbackSetters as g, PageItems as gt, ConstructorWithTypeId as h, SenderKeyPair as ht, GetActorOptions as i, ObjectAuthorizePredicate as it, FederationKvPrefixes as j, ActivityTransformer as jt, OutboxListenerSetters as k, normalizeCircuitBreakerOptions as kt, RequestContext as l, OutboxPermanentFailureHandler as lt, CollectionCallbackSetters as m, SendActivityError as mt, Context as n, InboxListener as nt, InboxContext as o, OutboxErrorHandler as ot, ActorCallbackSetters as p, WebFingerLinksDispatcher as pt, ActorKeyPairsDispatcher as q, ForwardActivityOptions as r, NodeInfoDispatcher as rt, OutboxContext as s, OutboxListener as st, ActorKeyPair as t, InboxErrorHandler as tt, RouteActivityOptions as u, SharedInboxKeyDispatcher as ut, Federation as v, digest as vt, IdempotencyKeyCallback as w, CircuitBreakerKvState as wt, FederationFetchOptions as x, CircuitBreakerBeforeSendDecision as xt, FederationBenchmarkOptions as y, CircuitBreaker as yt, Message as z };
@@ -9,6 +9,7 @@ import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObj
9
9
  import { MeterProvider, Span, Tracer, TracerProvider } from "@opentelemetry/api";
10
10
  import { AuthenticatedDocumentLoaderFactory, DocumentLoader, DocumentLoaderFactory, GetUserAgentOptions } from "@fedify/vocab-runtime";
11
11
  import { Link as Link$1, LookupWebFingerOptions, ResourceDescriptor } from "@fedify/webfinger";
12
+ import { MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
12
13
 
13
14
  //#region src/compat/types.d.ts
14
15
  /**
@@ -883,8 +884,10 @@ interface FederationOrigin {
883
884
  }
884
885
  /**
885
886
  * Create a new {@link Federation} instance.
886
- * @param parameters Parameters for initializing the instance.
887
+ * @param options Parameters for initializing the instance.
887
888
  * @returns A new {@link Federation} instance.
889
+ * @throws {TypeError} If benchmark mode and `meterProvider` are both
890
+ * specified.
888
891
  * @since 0.10.0
889
892
  */
890
893
  declare function createFederation<TContextData>(options: FederationOptions<TContextData>): Federation<TContextData>;
@@ -1369,7 +1372,10 @@ interface Federation<TContextData> extends Federatable<TContextData> {
1369
1372
  interface FederationBuilder<TContextData> extends Federatable<TContextData> {
1370
1373
  /**
1371
1374
  * Builds the federation object.
1375
+ * @param options Parameters for initializing the federation object.
1372
1376
  * @returns The federation object.
1377
+ * @throws {TypeError} If benchmark mode and `meterProvider` are both
1378
+ * specified.
1373
1379
  */
1374
1380
  build(options: FederationOptions<TContextData>): Promise<Federation<TContextData>>;
1375
1381
  }
@@ -1407,6 +1413,25 @@ interface InboxChallengePolicy {
1407
1413
  nonceTtlSeconds?: number;
1408
1414
  }
1409
1415
  /**
1416
+ * Options for cooperative benchmark mode.
1417
+ * @since 2.3.0
1418
+ */
1419
+ interface FederationBenchmarkOptions {
1420
+ /**
1421
+ * Server-controlled inbox URLs that the benchmark trigger endpoint may
1422
+ * deliver to.
1423
+ */
1424
+ triggerSinks?: readonly (string | URL)[];
1425
+ /**
1426
+ * Whether the benchmark trigger endpoint may deliver to recipients outside
1427
+ * {@link FederationBenchmarkOptions.triggerSinks}.
1428
+ *
1429
+ * Do not enable this option unless the benchmark endpoint is only reachable
1430
+ * by a trusted benchmark controller.
1431
+ */
1432
+ allowUnsafeTriggerRecipients?: boolean;
1433
+ }
1434
+ /**
1410
1435
  * Options for creating a {@link Federation} object.
1411
1436
  * @template TContextData The context data to pass to the {@link Context}.
1412
1437
  * @since 1.6.0
@@ -1486,6 +1511,21 @@ interface FederationOptions<TContextData> {
1486
1511
  */
1487
1512
  allowPrivateAddress?: boolean;
1488
1513
  /**
1514
+ * Whether to enable cooperative benchmark mode. This mode exposes
1515
+ * benchmark-only endpoints and relaxes selected defaults for benchmark
1516
+ * targets. Pass an object to configure benchmark trigger delivery.
1517
+ * Do not enable this option in production.
1518
+ *
1519
+ * When enabled, {@link FederationOptions.allowPrivateAddress} defaults to
1520
+ * `true` unless {@link FederationOptions.documentLoaderFactory} or
1521
+ * {@link FederationOptions.contextLoaderFactory} is configured, and
1522
+ * {@link FederationOptions.signatureTimeWindow} defaults to `false`.
1523
+ *
1524
+ * Turned off by default.
1525
+ * @since 2.3.0
1526
+ */
1527
+ benchmarkMode?: boolean | FederationBenchmarkOptions;
1528
+ /**
1489
1529
  * Options for making `User-Agent` strings for HTTP requests.
1490
1530
  * If a string is provided, it is used as the `User-Agent` header.
1491
1531
  * If an object is provided, it is passed to the {@link getUserAgent}
@@ -2844,4 +2884,4 @@ interface ActorKeyPair extends CryptoKeyPair {
2844
2884
  readonly multikey: Multikey;
2845
2885
  }
2846
2886
  //#endregion
2847
- export { CustomCollectionDispatcher as $, FederationKvPrefixes as A, ActivityTransformer as At, RespondWithObjectOptions as B, IdempotencyKeyCallback as C, CircuitBreakerKvState as Ct, ObjectCallbackSetters as D, NormalizedCircuitBreakerOptions as Dt, InboxListenerSetters as E, CircuitBreakerStateChange as Et, RetryContext as F, ActorHandleMapper as G, respondWithObjectIfAcceptable as H, RetryPolicy as I, CollectionCounter as J, ActorKeyPairsDispatcher as K, createExponentialBackoffPolicy as L, FederationQueueOptions as M, createFederation as N, OutboxListenerSetters as O, normalizeCircuitBreakerOptions as Ot, CreateExponentialBackoffPolicyOptions as P, CustomCollectionCursor as Q, Message as R, FederationStartQueueOptions as S, CircuitBreakerFailurePolicy as St, InboxChallengePolicy as T, CircuitBreakerState as Tt, ActorAliasMapper as U, respondWithObject as V, ActorDispatcher as W, CollectionDispatcher as X, CollectionCursor as Y, CustomCollectionCounter as Z, Federatable as _, digest as _t, GetSignedKeyOptions as a, OutboxErrorHandler as at, FederationFetchOptions as b, CircuitBreakerBeforeSendDecision as bt, ParseUriResult as c, OutboxPermanentFailureHandler as ct, SendActivityOptions as d, UnverifiedActivityReason as dt, InboxErrorHandler as et, SendActivityOptionsForCollection as f, WebFingerLinksDispatcher as ft, CustomCollectionCallbackSetters as g, buildCollectionSynchronizationHeader as gt, ConstructorWithTypeId as h, PageItems as ht, GetActorOptions as i, ObjectDispatcher as it, FederationOrigin as j, Rfc6570Expression as k, parseCircuitBreakerKvState as kt, RequestContext as l, SharedInboxKeyDispatcher as lt, CollectionCallbackSetters as m, SenderKeyPair as mt, Context as n, NodeInfoDispatcher as nt, InboxContext as o, OutboxListener as ot, ActorCallbackSetters as p, SendActivityError as pt, AuthorizePredicate as q, ForwardActivityOptions as r, ObjectAuthorizePredicate as rt, OutboxContext as s, OutboxListenerErrorHandler as st, ActorKeyPair as t, InboxListener as tt, RouteActivityOptions as u, UnverifiedActivityHandler as ut, Federation as v, CircuitBreaker as vt, IdempotencyStrategy as w, CircuitBreakerOptions as wt, FederationOptions as x, CircuitBreakerCreateOptions as xt, FederationBuilder as y, CircuitBreakerActivityDrop as yt, createFederationBuilder as z };
2887
+ export { CustomCollectionCursor as $, Rfc6570Expression as A, parseCircuitBreakerKvState as At, createFederationBuilder as B, FederationStartQueueOptions as C, CircuitBreakerFailurePolicy as Ct, InboxListenerSetters as D, CircuitBreakerStateChange as Dt, InboxChallengePolicy as E, CircuitBreakerState as Et, CreateExponentialBackoffPolicyOptions as F, ActorDispatcher as G, respondWithObject as H, RetryContext as I, AuthorizePredicate as J, ActorHandleMapper as K, RetryPolicy as L, FederationOrigin as M, FederationQueueOptions as N, ObjectCallbackSetters as O, NormalizedCircuitBreakerOptions as Ot, createFederation as P, CustomCollectionCounter as Q, createExponentialBackoffPolicy as R, FederationOptions as S, CircuitBreakerCreateOptions as St, IdempotencyStrategy as T, CircuitBreakerOptions as Tt, respondWithObjectIfAcceptable as U, RespondWithObjectOptions as V, ActorAliasMapper as W, CollectionCursor as X, CollectionCounter as Y, CollectionDispatcher as Z, Federatable as _, buildCollectionSynchronizationHeader as _t, GetSignedKeyOptions as a, ObjectDispatcher as at, FederationBuilder as b, CircuitBreakerActivityDrop as bt, ParseUriResult as c, OutboxListenerErrorHandler as ct, SendActivityOptions as d, UnverifiedActivityHandler as dt, CustomCollectionDispatcher as et, SendActivityOptionsForCollection as f, UnverifiedActivityReason as ft, CustomCollectionCallbackSetters as g, PageItems as gt, ConstructorWithTypeId as h, SenderKeyPair as ht, GetActorOptions as i, ObjectAuthorizePredicate as it, FederationKvPrefixes as j, ActivityTransformer as jt, OutboxListenerSetters as k, normalizeCircuitBreakerOptions as kt, RequestContext as l, OutboxPermanentFailureHandler as lt, CollectionCallbackSetters as m, SendActivityError as mt, Context as n, InboxListener as nt, InboxContext as o, OutboxErrorHandler as ot, ActorCallbackSetters as p, WebFingerLinksDispatcher as pt, ActorKeyPairsDispatcher as q, ForwardActivityOptions as r, NodeInfoDispatcher as rt, OutboxContext as s, OutboxListener as st, ActorKeyPair as t, InboxErrorHandler as tt, RouteActivityOptions as u, SharedInboxKeyDispatcher as ut, Federation as v, digest as vt, IdempotencyKeyCallback as w, CircuitBreakerKvState as wt, FederationFetchOptions as x, CircuitBreakerBeforeSendDecision as xt, FederationBenchmarkOptions as y, CircuitBreaker as yt, Message as z };
@@ -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.3.0-dev.1190+2dfa46e0";
6
+ var version = "2.3.0-dev.1213+8ffffeb8";
7
7
  //#endregion
8
8
  export { version as n, name as t };
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { o as validateCryptoKey } from "./key-DYK_T_PD.mjs";
5
- import { n as doubleKnock } from "./http-CSwCAQ-H.mjs";
4
+ import { o as validateCryptoKey } from "./key-DdP4HxTK.mjs";
5
+ import { n as doubleKnock } from "./http-CDaMGwCP.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
8
8
  import { curry } from "es-toolkit";
@@ -1,7 +1,29 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { r as __toESM, t as __commonJSMin } from "./chunk-DNRtMIoB.mjs";
4
+ import "node:module";
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
15
+ key = keys[i];
16
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
17
+ get: ((k) => from[k]).bind(null, key),
18
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
+ });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
24
+ value: mod,
25
+ enumerable: true
26
+ }) : target, mod));
5
27
  //#endregion
6
28
  //#region ../../node_modules/.pnpm/regexparam@3.0.0/node_modules/regexparam/dist/index.mjs
7
29
  var import_glob_to_regexp = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -4,8 +4,8 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { r as assertExists } from "../std__assert-BBjXFNOb.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
7
- import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
8
- import { r as createFederationBuilder } from "../builder-BzgNpXoY.mjs";
7
+ import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
+ import { r as createFederationBuilder } from "../builder-Bj-7Sl7u.mjs";
9
9
  import { DisallowedOperatorError, DisallowedVarSpecModifierError, DuplicateRouteVariableError, RouteTemplateOptionsNotMatchedError, RouterError } from "@fedify/uri-template";
10
10
  import { Activity, Note, Person } from "@fedify/vocab";
11
11
  import { test } from "@fedify/fixture";
@@ -74,6 +74,25 @@ test("FederationBuilder", async (t) => {
74
74
  assertEquals(impl.router.build("inbox", { identifier: "user1" }), "/users/user1/inbox");
75
75
  await builder.build({ kv });
76
76
  });
77
+ await t.step("passes benchmarkMode to the built federation", async () => {
78
+ const builder = createFederationBuilder();
79
+ const impl = await builder.build({
80
+ kv: new MemoryKvStore(),
81
+ benchmarkMode: true
82
+ });
83
+ assertEquals(impl.benchmarkMode, true);
84
+ assertEquals(impl.allowPrivateAddress, true);
85
+ assertEquals(impl.signatureTimeWindow, false);
86
+ const overriddenImpl = await builder.build({
87
+ kv: new MemoryKvStore(),
88
+ benchmarkMode: true,
89
+ allowPrivateAddress: false,
90
+ signatureTimeWindow: { minutes: 10 }
91
+ });
92
+ assertEquals(overriddenImpl.benchmarkMode, true);
93
+ assertEquals(overriddenImpl.allowPrivateAddress, false);
94
+ assertEquals(overriddenImpl.signatureTimeWindow, { minutes: 10 });
95
+ });
77
96
  await t.step("should snapshot router state on build", async () => {
78
97
  const builder = createFederationBuilder();
79
98
  const kv = new MemoryKvStore();
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BBjXFNOb.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-BOkhLGYc.mjs";
7
- import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
7
+ import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
8
  import { n as normalizeCircuitBreakerOptions, r as parseCircuitBreakerKvState, t as CircuitBreaker } from "../circuit-breaker-CSWsyoef.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/federation/circuit-breaker.test.ts
@@ -7,12 +7,12 @@ import "../std__assert-BBjXFNOb.mjs";
7
7
  import { n as assertGreaterOrEqual, t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
8
8
  import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
9
9
  import { t as assert } from "../assert-OguE97r2.mjs";
10
- import { r as parseAcceptSignature } from "../accept-CceiKpCy.mjs";
11
- import { s as signRequest } from "../http-CSwCAQ-H.mjs";
12
- import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-C3kae-6B.mjs";
13
- import { a as compactJsonLd, p as signJsonLd } from "../ld-BdcT_irA.mjs";
14
- import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
15
- import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-BUGT2LmO.mjs";
10
+ import { r as parseAcceptSignature } from "../accept-CPkZzmGN.mjs";
11
+ import { s as signRequest } from "../http-CDaMGwCP.mjs";
12
+ import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-DGu1NFwu.mjs";
13
+ import { a as compactJsonLd, p as signJsonLd } from "../ld-CuOEh5aB.mjs";
14
+ import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
15
+ import { c as handleActor, d as handleInbox, f as handleObject, h as respondWithObjectIfAcceptable, l as handleCollection, m as respondWithObject, o as createFederation, p as handleOutbox, u as handleCustomCollection } from "../middleware-Cq9S8A5O.mjs";
16
16
  import { t as ActivityListenerSet } from "../activity-listener-tztVvlNb.mjs";
17
17
  import { Activity, Create, Note, Person, Tombstone } from "@fedify/vocab";
18
18
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -3,10 +3,10 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BBjXFNOb.mjs";
6
- import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-C3kae-6B.mjs";
7
- import { r as signObject } from "../proof-CzqluPMh.mjs";
8
- import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
9
- import { o as createFederation } from "../middleware-BUGT2LmO.mjs";
6
+ import { n as ed25519PrivateKey, r as ed25519PublicKey, t as ed25519Multikey } from "../keys-DGu1NFwu.mjs";
7
+ import { r as signObject } from "../proof-dhtwaP4z.mjs";
8
+ import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
9
+ import { o as createFederation } from "../middleware-Cq9S8A5O.mjs";
10
10
  import { Create, Follow, Person } from "@fedify/vocab";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region src/federation/idempotency.test.ts
@@ -4,7 +4,7 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import { t as assertInstanceOf } from "../assert_instance_of-DBC5X09g.mjs";
6
6
  import { t as assert } from "../assert-OguE97r2.mjs";
7
- import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
7
+ import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
8
8
  import { t as KvKeyCache } from "../keycache-BeU0LCII.mjs";
9
9
  import { CryptographicKey, Multikey } from "@fedify/vocab";
10
10
  import { test } from "@fedify/fixture";
@@ -3,7 +3,7 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BBjXFNOb.mjs";
6
- import { t as MemoryKvStore } from "../kv-x2IvBUyq.mjs";
6
+ import { t as MemoryKvStore } from "../kv-rV3vodCc.mjs";
7
7
  import { test } from "@fedify/fixture";
8
8
  //#region src/federation/kv.test.ts
9
9
  test("MemoryKvStore", async (t) => {
@@ -4,10 +4,19 @@ globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-C-ZRDbaf.mjs";
5
5
  import "../std__assert-BBjXFNOb.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-DN60FHPX.mjs";
7
- import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, y as recordOutboxEnqueue } from "../metrics-Ci97wkob.mjs";
7
+ import { _ as recordKeyLookup, a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, m as recordDocumentFetch, p as recordDocumentCache, r as getFederationMetrics, t as classifyFetchError, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "../metrics-B5vvJYMV.mjs";
8
8
  import { createTestMeterProvider, test } from "@fedify/fixture";
9
9
  import { FetchError } from "@fedify/vocab-runtime";
10
+ import { DataPointType, MeterProvider, MetricReader } from "@opentelemetry/sdk-metrics";
10
11
  //#region src/federation/metrics.test.ts
12
+ var TestMetricReader = class extends MetricReader {
13
+ onShutdown() {
14
+ return Promise.resolve();
15
+ }
16
+ onForceFlush() {
17
+ return Promise.resolve();
18
+ }
19
+ };
11
20
  const noopQueue = {
12
21
  enqueue() {
13
22
  return Promise.resolve();
@@ -38,6 +47,143 @@ test("recordFanoutRecipients() omits activity type when unknown", () => {
38
47
  assertEquals(measurements[0].value, 0);
39
48
  assertEquals("activitypub.activity.type" in measurements[0].attributes, false);
40
49
  });
50
+ test("signature verification duration uses explicit low-latency buckets", async () => {
51
+ const reader = new TestMetricReader();
52
+ const meterProvider = new MeterProvider({ readers: [reader] });
53
+ try {
54
+ getFederationMetrics(meterProvider).recordSignatureVerificationDuration(7, "http", "verified");
55
+ const metric = (await reader.collect()).resourceMetrics.scopeMetrics.flatMap((scope) => scope.metrics).find((metric) => metric.descriptor.name === "activitypub.signature.verification.duration");
56
+ assertEquals(metric?.dataPointType, DataPointType.HISTOGRAM);
57
+ assertEquals(metric?.dataPoints[0].value.buckets.boundaries, [
58
+ .1,
59
+ .25,
60
+ .5,
61
+ 1,
62
+ 2.5,
63
+ 5,
64
+ 10,
65
+ 25,
66
+ 50,
67
+ 100,
68
+ 250,
69
+ 500,
70
+ 1e3
71
+ ]);
72
+ } finally {
73
+ await meterProvider.shutdown();
74
+ }
75
+ });
76
+ test("registerQueueDepthGauge() skips unavailable depth snapshots", async () => {
77
+ const reader = new TestMetricReader();
78
+ const meterProvider = new MeterProvider({ readers: [reader] });
79
+ try {
80
+ registerQueueDepthGauge(meterProvider, [
81
+ {
82
+ role: "inbox",
83
+ queue: {
84
+ enqueue() {
85
+ return Promise.resolve();
86
+ },
87
+ listen() {
88
+ return Promise.resolve();
89
+ },
90
+ getDepth() {
91
+ throw new TypeError("backend unavailable");
92
+ }
93
+ }
94
+ },
95
+ {
96
+ role: "outbox",
97
+ queue: {
98
+ enqueue() {
99
+ return Promise.resolve();
100
+ },
101
+ listen() {
102
+ return Promise.resolve();
103
+ },
104
+ getDepth() {
105
+ return Promise.resolve(null);
106
+ }
107
+ }
108
+ },
109
+ {
110
+ role: "fanout",
111
+ queue: {
112
+ enqueue() {
113
+ return Promise.resolve();
114
+ },
115
+ listen() {
116
+ return Promise.resolve();
117
+ },
118
+ getDepth() {
119
+ return Promise.resolve({ queued: 7 });
120
+ }
121
+ }
122
+ }
123
+ ]);
124
+ const result = await reader.collect();
125
+ assertEquals(result.errors, []);
126
+ const queueDepth = result.resourceMetrics.scopeMetrics.flatMap((scope) => scope.metrics).find((metric) => metric.descriptor.name === "fedify.queue.depth");
127
+ assertEquals(queueDepth?.dataPointType, DataPointType.GAUGE);
128
+ assertEquals(queueDepth?.dataPoints.map((point) => ({
129
+ state: point.attributes["fedify.queue.depth.state"],
130
+ role: point.attributes["fedify.queue.role"],
131
+ value: point.value
132
+ })), [{
133
+ state: "queued",
134
+ role: "fanout",
135
+ value: 7
136
+ }]);
137
+ } finally {
138
+ await meterProvider.shutdown();
139
+ }
140
+ });
141
+ test("registerQueueDepthGauge() queries queue depths in parallel", async () => {
142
+ const reader = new TestMetricReader();
143
+ const meterProvider = new MeterProvider({ readers: [reader] });
144
+ let releaseSlowDepth;
145
+ let fastDepthStarted = false;
146
+ try {
147
+ registerQueueDepthGauge(meterProvider, [{
148
+ role: "inbox",
149
+ queue: {
150
+ enqueue() {
151
+ return Promise.resolve();
152
+ },
153
+ listen() {
154
+ return Promise.resolve();
155
+ },
156
+ getDepth() {
157
+ return new Promise((resolve) => {
158
+ releaseSlowDepth = resolve;
159
+ });
160
+ }
161
+ }
162
+ }, {
163
+ role: "outbox",
164
+ queue: {
165
+ enqueue() {
166
+ return Promise.resolve();
167
+ },
168
+ listen() {
169
+ return Promise.resolve();
170
+ },
171
+ getDepth() {
172
+ fastDepthStarted = true;
173
+ return Promise.resolve({ queued: 5 });
174
+ }
175
+ }
176
+ }]);
177
+ const collection = reader.collect();
178
+ await Promise.resolve();
179
+ assertEquals(fastDepthStarted, true);
180
+ releaseSlowDepth?.({ queued: 3 });
181
+ assertEquals((await collection).resourceMetrics.scopeMetrics.flatMap((scope) => scope.metrics).find((metric) => metric.descriptor.name === "fedify.queue.depth")?.dataPoints.map((point) => point.value).sort(), [3, 5]);
182
+ } finally {
183
+ releaseSlowDepth?.({ queued: 0 });
184
+ await meterProvider.shutdown();
185
+ }
186
+ });
41
187
  test("recordInboxActivity() records counter with result and activity type", () => {
42
188
  const [meterProvider, recorder] = createTestMeterProvider();
43
189
  for (const result of [