brass-runtime 1.19.1 → 1.19.2

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.
@@ -12,6 +12,8 @@ import {
12
12
  } from "./chunk-6W5DC3TX.js";
13
13
  import {
14
14
  fromPromiseAbortable,
15
+ recordAbortablePromiseFinish,
16
+ recordAbortablePromiseStart,
15
17
  resolveWasmModule,
16
18
  toPromise
17
19
  } from "./chunk-TN2P7RNK.js";
@@ -3182,6 +3184,275 @@ var noopSignal = (() => {
3182
3184
  globalThis.__brassNoopSignal = s;
3183
3185
  return s;
3184
3186
  })();
3187
+ var PoolRequestState = class {
3188
+ constructor(req, url, transport, metrics, pool, adaptiveLimiter, timerWheel, timeoutMs, env, cb, previousSignal, controller, signal, label, startedAt) {
3189
+ this.req = req;
3190
+ this.url = url;
3191
+ this.transport = transport;
3192
+ this.metrics = metrics;
3193
+ this.pool = pool;
3194
+ this.adaptiveLimiter = adaptiveLimiter;
3195
+ this.timerWheel = timerWheel;
3196
+ this.timeoutMs = timeoutMs;
3197
+ this.env = env;
3198
+ this.cb = cb;
3199
+ this.previousSignal = previousSignal;
3200
+ this.controller = controller;
3201
+ this.signal = signal;
3202
+ this.label = label;
3203
+ this.startedAt = startedAt;
3204
+ }
3205
+ req;
3206
+ url;
3207
+ transport;
3208
+ metrics;
3209
+ pool;
3210
+ adaptiveLimiter;
3211
+ timerWheel;
3212
+ timeoutMs;
3213
+ env;
3214
+ cb;
3215
+ previousSignal;
3216
+ controller;
3217
+ signal;
3218
+ label;
3219
+ startedAt;
3220
+ done = false;
3221
+ cancelInner = void 0;
3222
+ timerHandle = void 0;
3223
+ timeoutHandle = void 0;
3224
+ lease = void 0;
3225
+ finish(outcome, exit, error) {
3226
+ if (this.done) return;
3227
+ this.done = true;
3228
+ if (this.timerHandle) {
3229
+ this.timerHandle.cancel();
3230
+ this.timerHandle = void 0;
3231
+ }
3232
+ if (this.timeoutHandle !== void 0) {
3233
+ clearTimeout(this.timeoutHandle);
3234
+ this.timeoutHandle = void 0;
3235
+ }
3236
+ if (this.previousSignal) this.previousSignal.removeEventListener("abort", this.boundAbortFromPrevious);
3237
+ this.cancelInner = void 0;
3238
+ recordAbortablePromiseFinish(this.label, outcome);
3239
+ this.metrics.onFinish({
3240
+ label: this.label,
3241
+ outcome,
3242
+ durationMs: Math.round(performance.now() - this.startedAt),
3243
+ error
3244
+ });
3245
+ this.cb(exit);
3246
+ }
3247
+ finishFailure(error, outcome = "failure") {
3248
+ this.finish(outcome, { _tag: "Failure", cause: Cause.fail(error) }, error);
3249
+ }
3250
+ abortCurrent(reason) {
3251
+ if (!this.controller) return;
3252
+ try {
3253
+ this.controller.abort(reason);
3254
+ } catch {
3255
+ this.controller.abort();
3256
+ }
3257
+ }
3258
+ /**
3259
+ * Bound reference for addEventListener/removeEventListener.
3260
+ * Only allocated when previousSignal is present (not on the hot path).
3261
+ */
3262
+ boundAbortFromPrevious = void 0;
3263
+ abortFromPrevious() {
3264
+ const error = this.previousSignal ? abortErrorForSignal(this.previousSignal) : { _tag: "Abort" };
3265
+ this.abortCurrent(this.previousSignal?.reason);
3266
+ const cancel = this.cancelInner;
3267
+ this.cancelInner = void 0;
3268
+ if (this.lease) {
3269
+ releaseFailure(this.lease, this.adaptiveLimiter);
3270
+ this.lease = void 0;
3271
+ }
3272
+ queueMicrotask(() => {
3273
+ this.finishFailure(error);
3274
+ cancel?.();
3275
+ });
3276
+ }
3277
+ runTransportInner() {
3278
+ const { transport, req, url, signal, env } = this;
3279
+ try {
3280
+ const effect = transport({ request: req, url, signal });
3281
+ if (effect._tag === "Succeed") {
3282
+ if (this.lease) releaseSuccess(this.lease, this.adaptiveLimiter, effect.value);
3283
+ this.finish("success", { _tag: "Success", value: effect.value });
3284
+ } else if (effect._tag === "Fail") {
3285
+ if (this.lease) releaseFailure(this.lease, this.adaptiveLimiter);
3286
+ this.finishFailure(effect.error);
3287
+ } else if (effect._tag === "Async") {
3288
+ try {
3289
+ const cancel = effect.register(env, (exit) => {
3290
+ if (this.done) return;
3291
+ this.cancelInner = void 0;
3292
+ if (exit._tag === "Success") {
3293
+ if (this.lease) releaseSuccess(this.lease, this.adaptiveLimiter, exit.value);
3294
+ this.finish("success", exit);
3295
+ } else {
3296
+ if (this.lease) releaseFailure(this.lease, this.adaptiveLimiter);
3297
+ this.finish("failure", exit, exitError(exit));
3298
+ }
3299
+ });
3300
+ if (!this.done) this.cancelInner = typeof cancel === "function" ? cancel : void 0;
3301
+ } catch (error) {
3302
+ if (this.lease) releaseFailure(this.lease, this.adaptiveLimiter);
3303
+ this.finishFailure(normalizeHttpError(error));
3304
+ }
3305
+ } else {
3306
+ const innerCancel = registerHttpEffect(
3307
+ effect,
3308
+ env,
3309
+ (exit) => {
3310
+ if (this.done) return;
3311
+ this.cancelInner = void 0;
3312
+ if (exit._tag === "Success") {
3313
+ if (this.lease) releaseSuccess(this.lease, this.adaptiveLimiter, exit.value);
3314
+ this.finish("success", exit);
3315
+ } else {
3316
+ if (this.lease) releaseFailure(this.lease, this.adaptiveLimiter);
3317
+ this.finish("failure", exit, exitError(exit));
3318
+ }
3319
+ }
3320
+ );
3321
+ if (!this.done) this.cancelInner = innerCancel;
3322
+ }
3323
+ } catch (error) {
3324
+ if (this.lease) releaseFailure(this.lease, this.adaptiveLimiter);
3325
+ this.finishFailure(normalizeHttpError(error));
3326
+ }
3327
+ }
3328
+ };
3329
+ var runPoolTransport = (req, url, transport, metrics, pool, adaptiveLimiter, timerWheel, timeoutMs) => ({
3330
+ _tag: "Async",
3331
+ register: (env, cb) => {
3332
+ const previousSignal = req.init?.signal;
3333
+ const controller = new AbortController();
3334
+ const signal = controller.signal;
3335
+ const label = fetchLabel(req, url);
3336
+ const startedAt = performance.now();
3337
+ const state = new PoolRequestState(
3338
+ req,
3339
+ url,
3340
+ transport,
3341
+ metrics,
3342
+ pool,
3343
+ adaptiveLimiter,
3344
+ timerWheel,
3345
+ timeoutMs,
3346
+ env,
3347
+ cb,
3348
+ previousSignal,
3349
+ controller,
3350
+ signal,
3351
+ label,
3352
+ startedAt
3353
+ );
3354
+ recordAbortablePromiseStart(label);
3355
+ metrics.onStart();
3356
+ if (previousSignal) {
3357
+ state.boundAbortFromPrevious = () => state.abortFromPrevious();
3358
+ if (previousSignal.aborted) {
3359
+ state.abortFromPrevious();
3360
+ return () => void 0;
3361
+ }
3362
+ previousSignal.addEventListener("abort", state.boundAbortFromPrevious, ONCE_OPTIONS);
3363
+ }
3364
+ if (timeoutMs !== void 0 && timeoutMs > 0) {
3365
+ const onTimeout = () => {
3366
+ const reason = timeoutReason(req, url, timeoutMs);
3367
+ if (state.lease) {
3368
+ releaseFailure(state.lease, adaptiveLimiter);
3369
+ state.lease = void 0;
3370
+ }
3371
+ const cancel = state.cancelInner;
3372
+ state.cancelInner = void 0;
3373
+ state.finishFailure(reason, "timeout");
3374
+ state.abortCurrent(reason);
3375
+ cancel?.();
3376
+ };
3377
+ if (timerWheel) {
3378
+ state.timerHandle = timerWheel.schedule(timeoutMs, onTimeout, startedAt);
3379
+ } else {
3380
+ state.timeoutHandle = setTimeout(onTimeout, timeoutMs);
3381
+ }
3382
+ }
3383
+ if (adaptiveLimiter) {
3384
+ const key = resolveHttpPoolKey(adaptiveLimiter.keyResolver, req, url);
3385
+ const syncLease = adaptiveLimiter.tryAcquireSync(key, signal);
3386
+ if (syncLease) {
3387
+ state.lease = syncLease;
3388
+ } else {
3389
+ adaptiveLimiter.acquire(key, signal, { priority: requestPriority(req) }).then(
3390
+ (asyncLease) => {
3391
+ if (state.done) {
3392
+ asyncLease.release(0);
3393
+ return;
3394
+ }
3395
+ state.lease = asyncLease;
3396
+ state.runTransportInner();
3397
+ },
3398
+ (err) => {
3399
+ if (state.done) return;
3400
+ state.finishFailure(normalizeHttpError(err));
3401
+ }
3402
+ );
3403
+ return () => {
3404
+ if (state.done) return;
3405
+ const cancel = state.cancelInner;
3406
+ state.cancelInner = void 0;
3407
+ state.abortCurrent();
3408
+ if (state.lease) releaseFailure(state.lease, adaptiveLimiter);
3409
+ state.finish("interrupt", { _tag: "Failure", cause: Cause.interrupt() });
3410
+ cancel?.();
3411
+ };
3412
+ }
3413
+ } else if (pool) {
3414
+ const key = resolveHttpPoolKey(pool.keyResolver, req, url);
3415
+ const syncLease = pool.tryAcquireSync(key, signal);
3416
+ if (syncLease) {
3417
+ state.lease = syncLease;
3418
+ } else {
3419
+ pool.acquire(key, signal).then(
3420
+ (asyncLease) => {
3421
+ if (state.done) {
3422
+ asyncLease.release();
3423
+ return;
3424
+ }
3425
+ state.lease = asyncLease;
3426
+ state.runTransportInner();
3427
+ },
3428
+ (err) => {
3429
+ if (state.done) return;
3430
+ state.finishFailure(normalizeHttpError(err));
3431
+ }
3432
+ );
3433
+ return () => {
3434
+ if (state.done) return;
3435
+ const cancel = state.cancelInner;
3436
+ state.cancelInner = void 0;
3437
+ state.abortCurrent();
3438
+ if (state.lease) releaseFailure(state.lease, void 0);
3439
+ state.finish("interrupt", { _tag: "Failure", cause: Cause.interrupt() });
3440
+ cancel?.();
3441
+ };
3442
+ }
3443
+ }
3444
+ state.runTransportInner();
3445
+ return () => {
3446
+ if (state.done) return;
3447
+ const cancel = state.cancelInner;
3448
+ state.cancelInner = void 0;
3449
+ state.abortCurrent();
3450
+ if (state.lease) releaseFailure(state.lease, adaptiveLimiter);
3451
+ state.finish("interrupt", { _tag: "Failure", cause: Cause.interrupt() });
3452
+ cancel?.();
3453
+ };
3454
+ }
3455
+ });
3185
3456
  function makeHttp(cfg = {}) {
3186
3457
  validateMakeHttpConfig(cfg);
3187
3458
  const baseUrl = cfg.baseUrl ?? "";
@@ -3200,42 +3471,7 @@ function makeHttp(cfg = {}) {
3200
3471
  if (!adaptiveLimiter && !pool && timeoutMs === void 0) {
3201
3472
  return runDirectTransport(req, url, transport, metrics);
3202
3473
  }
3203
- return fromPromiseAbortable(
3204
- async (signal, env) => {
3205
- let lease;
3206
- const linkedSignal = linkAbortSignals(signal, req.init?.signal);
3207
- try {
3208
- if (linkedSignal.signal.aborted) throw abortErrorForSignal(linkedSignal.signal);
3209
- if (adaptiveLimiter) {
3210
- const key = resolveHttpPoolKey(adaptiveLimiter.keyResolver, req, url);
3211
- lease = await adaptiveLimiter.acquire(key, linkedSignal.signal, { priority: requestPriority(req) });
3212
- } else if (pool) {
3213
- const key = resolveHttpPoolKey(pool.keyResolver, req, url);
3214
- lease = await pool.acquire(key, linkedSignal.signal);
3215
- }
3216
- const response = await runTransportEffect(
3217
- transport({ request: req, url, signal: linkedSignal.signal }),
3218
- env,
3219
- linkedSignal.signal
3220
- );
3221
- lease = releaseSuccess(lease, adaptiveLimiter, response);
3222
- return response;
3223
- } finally {
3224
- linkedSignal.cleanup();
3225
- if (lease) {
3226
- releaseFailure(lease, adaptiveLimiter);
3227
- }
3228
- }
3229
- },
3230
- normalizeHttpError,
3231
- {
3232
- label: fetchLabel(req, url),
3233
- timeoutMs,
3234
- timeoutReason: timeoutMs ? () => timeoutReason(req, url, timeoutMs) : void 0,
3235
- onStart: metrics.onStart,
3236
- onFinish: metrics.onFinish
3237
- }
3238
- );
3474
+ return runPoolTransport(req, url, transport, metrics, pool, adaptiveLimiter, void 0, timeoutMs);
3239
3475
  };
3240
3476
  const metadata = {};
3241
3477
  if (adaptiveLimiter) metadata.adaptiveLimiter = adaptiveLimiter;
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-S6KSHYAT.mjs";
5
5
  import {
6
6
  withHttpObservability
7
- } from "./chunk-AITYRQX2.mjs";
7
+ } from "./chunk-ZXXOXB3T.mjs";
8
8
  import {
9
9
  makeObservability
10
10
  } from "./chunk-SCHM2MDA.mjs";
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  makeDefaultHttpClient,
16
16
  makeHttp
17
- } from "./chunk-ID2WOCBA.mjs";
17
+ } from "./chunk-5X3MPWTR.mjs";
18
18
  import {
19
19
  Runtime,
20
20
  Scheduler
@@ -4,7 +4,7 @@
4
4
  var _chunkJQCQWO47cjs = require('./chunk-JQCQWO47.cjs');
5
5
 
6
6
 
7
- var _chunk67256TKFcjs = require('./chunk-67256TKF.cjs');
7
+ var _chunkTWEHIAUEcjs = require('./chunk-TWEHIAUE.cjs');
8
8
 
9
9
 
10
10
  var _chunkZJC3JZIEcjs = require('./chunk-ZJC3JZIE.cjs');
@@ -14,7 +14,7 @@ var _chunkVXNWVAIGcjs = require('./chunk-VXNWVAIG.cjs');
14
14
 
15
15
 
16
16
 
17
- var _chunkLXNU3MRVcjs = require('./chunk-LXNU3MRV.cjs');
17
+ var _chunkUOKXJQAIcjs = require('./chunk-UOKXJQAI.cjs');
18
18
 
19
19
 
20
20
 
@@ -862,24 +862,24 @@ function baseHttpConfig(baseUrl, scenario) {
862
862
  };
863
863
  }
864
864
  function makeWireClient(baseUrl, scenario) {
865
- return _chunkLXNU3MRVcjs.makeHttp.call(void 0, baseHttpConfig(baseUrl, scenario));
865
+ return _chunkUOKXJQAIcjs.makeHttp.call(void 0, baseHttpConfig(baseUrl, scenario));
866
866
  }
867
867
  function makeMinimalClient(baseUrl, scenario) {
868
- return _chunkLXNU3MRVcjs.makeDefaultHttpClient.call(void 0, {
868
+ return _chunkUOKXJQAIcjs.makeDefaultHttpClient.call(void 0, {
869
869
  preset: "minimal",
870
870
  compression: false,
871
871
  ...baseHttpConfig(baseUrl, scenario)
872
872
  });
873
873
  }
874
874
  function makeDefaultClient(baseUrl, scenario, preset, disableAdaptiveLimiter, observability) {
875
- return _chunkLXNU3MRVcjs.makeDefaultHttpClient.call(void 0, {
875
+ return _chunkUOKXJQAIcjs.makeDefaultHttpClient.call(void 0, {
876
876
  preset,
877
877
  compression: false,
878
878
  ...baseHttpConfig(baseUrl, scenario),
879
879
  ...disableAdaptiveLimiter ? { adaptiveLimiter: false } : {},
880
880
  ...observability ? {
881
881
  middleware: [
882
- _chunk67256TKFcjs.withHttpObservability.call(void 0, {
882
+ _chunkTWEHIAUEcjs.withHttpObservability.call(void 0, {
883
883
  metrics: observability.metrics,
884
884
  logs: false,
885
885
  spans: {},
@@ -20,7 +20,7 @@ var _chunkZJC3JZIEcjs = require('./chunk-ZJC3JZIE.cjs');
20
20
 
21
21
 
22
22
 
23
- var _chunkLXNU3MRVcjs = require('./chunk-LXNU3MRV.cjs');
23
+ var _chunkUOKXJQAIcjs = require('./chunk-UOKXJQAI.cjs');
24
24
 
25
25
 
26
26
  var _chunkL6VB5N7Qcjs = require('./chunk-L6VB5N7Q.cjs');
@@ -217,13 +217,13 @@ function withHttpObservability(options) {
217
217
  cb({ _tag: "Success", value: res });
218
218
  };
219
219
  const onError = (error) => {
220
- const status = _chunkLXNU3MRVcjs.httpErrorStatus.call(void 0, error);
220
+ const status = _chunkUOKXJQAIcjs.httpErrorStatus.call(void 0, error);
221
221
  const finish = completeFinish(
222
222
  httpErrorOutcome(error),
223
223
  status !== void 0 ? String(status) : void 0,
224
224
  {
225
225
  "error.type": error._tag,
226
- "http.retryable": _chunkLXNU3MRVcjs.isRetryableHttpError.call(void 0, error)
226
+ "http.retryable": _chunkUOKXJQAIcjs.isRetryableHttpError.call(void 0, error)
227
227
  }
228
228
  );
229
229
  const adaptiveAttrs = observeAdaptiveLimiter(wireReq, next, resolved);
@@ -244,7 +244,7 @@ function withHttpObservability(options) {
244
244
  durationMs: finish.durationMs,
245
245
  ...status !== void 0 ? { status } : {},
246
246
  ...statusText ? { statusText } : {},
247
- retryable: _chunkLXNU3MRVcjs.isRetryableHttpError.call(void 0, error),
247
+ retryable: _chunkUOKXJQAIcjs.isRetryableHttpError.call(void 0, error),
248
248
  errorTag: error._tag,
249
249
  message: httpErrorMessage(error)
250
250
  });
@@ -312,7 +312,7 @@ function withLeanHttpSampledSpanObservability(next, options, metricCache) {
312
312
  finishLeanHttpSpan(span, "success");
313
313
  } else {
314
314
  const error = httpErrorFromCause(exit.cause);
315
- const status = _chunkLXNU3MRVcjs.httpErrorStatus.call(void 0, error);
315
+ const status = _chunkUOKXJQAIcjs.httpErrorStatus.call(void 0, error);
316
316
  recordHttpMetricsFinish(
317
317
  handles,
318
318
  httpErrorOutcome(error),
@@ -375,7 +375,7 @@ function withLeanHttpMetricsObservability(next, options, metricCache) {
375
375
  );
376
376
  } else {
377
377
  const error = httpErrorFromCause(exit.cause);
378
- const status = _chunkLXNU3MRVcjs.httpErrorStatus.call(void 0, error);
378
+ const status = _chunkUOKXJQAIcjs.httpErrorStatus.call(void 0, error);
379
379
  recordHttpMetricsFinish(
380
380
  handles,
381
381
  httpErrorOutcome(error),
@@ -594,7 +594,7 @@ function getCachedBaseLabels(req, options, cache) {
594
594
  if (cache.disabled) return requestBaseLabels(req, options);
595
595
  const route = requestRoute(req, options);
596
596
  const host = options.includeHostLabel ? requestHost(req) : void 0;
597
- const policy = _chunkLXNU3MRVcjs.getHttpRequestPolicy.call(void 0, req);
597
+ const policy = _chunkUOKXJQAIcjs.getHttpRequestPolicy.call(void 0, req);
598
598
  const preset = typeof policy === "string" ? policy : _optionalChain([policy, 'optionalAccess', _46 => _46.preset]);
599
599
  const key = `${req.method}|${_nullishCoalesce(host, () => ( ""))}|${_nullishCoalesce(route, () => ( ""))}|${_nullishCoalesce(preset, () => ( ""))}`;
600
600
  const existing = cache.baseLabelsCache.get(key);
@@ -727,7 +727,7 @@ function adaptiveLimiterLabels(req, stats, options) {
727
727
  });
728
728
  }
729
729
  function inferAdaptiveLimiterKey(req, stats) {
730
- const policy = _chunkLXNU3MRVcjs.getHttpRequestPolicy.call(void 0, req);
730
+ const policy = _chunkUOKXJQAIcjs.getHttpRequestPolicy.call(void 0, req);
731
731
  if (policy.poolKey) return policy.poolKey;
732
732
  const host = requestHost(req);
733
733
  if (host) return host;
@@ -809,7 +809,7 @@ function requestLogFields(req, options) {
809
809
  }
810
810
  function requestPolicyLogFields(req, options) {
811
811
  if (!options.policy.enabled) return void 0;
812
- const policy = _chunkLXNU3MRVcjs.getHttpRequestPolicy.call(void 0, req);
812
+ const policy = _chunkUOKXJQAIcjs.getHttpRequestPolicy.call(void 0, req);
813
813
  const fields = {
814
814
  ...policy.preset ? { preset: policy.preset } : {},
815
815
  ...policy.lane ? { lane: policy.lane } : {},
@@ -822,7 +822,7 @@ function requestPolicyLogFields(req, options) {
822
822
  }
823
823
  function requestPolicySpanAttributes(req, options) {
824
824
  if (!options.policy.enabled) return {};
825
- const policy = _chunkLXNU3MRVcjs.getHttpRequestPolicy.call(void 0, req);
825
+ const policy = _chunkUOKXJQAIcjs.getHttpRequestPolicy.call(void 0, req);
826
826
  return {
827
827
  ...compactSpanAttributes({
828
828
  "http.request.policy.lane": policy.lane,
@@ -836,7 +836,7 @@ function requestPolicySpanAttributes(req, options) {
836
836
  }
837
837
  function requestPolicyMetricLabels(req, options) {
838
838
  if (!options.policy.enabled || options.policy.labelKeys.length === 0) return {};
839
- const policy = _chunkLXNU3MRVcjs.getHttpRequestPolicy.call(void 0, req);
839
+ const policy = _chunkUOKXJQAIcjs.getHttpRequestPolicy.call(void 0, req);
840
840
  const values = {
841
841
  preset: policy.preset,
842
842
  lane: policy.lane,
@@ -1217,7 +1217,7 @@ function makeObservedRuntimeLayer(options = {}) {
1217
1217
  }
1218
1218
  function makeObservedHttpClientLayer(config = {}, options = {}) {
1219
1219
  const observabilityTag = _nullishCoalesce(options.observabilityTag, () => ( ObservabilityService));
1220
- const httpTag = _nullishCoalesce(options.httpTag, () => ( _chunkLXNU3MRVcjs.HttpClientService));
1220
+ const httpTag = _nullishCoalesce(options.httpTag, () => ( _chunkUOKXJQAIcjs.HttpClientService));
1221
1221
  return _chunkZZ2CMYJLcjs.layerEffect.call(void 0,
1222
1222
  httpTag,
1223
1223
  (context) => _chunkMVGUEJ5Zcjs.asyncSync.call(void 0, () => {
@@ -1228,7 +1228,7 @@ function makeObservedHttpClientLayer(config = {}, options = {}) {
1228
1228
  context,
1229
1229
  observability
1230
1230
  );
1231
- return _chunkLXNU3MRVcjs.makeDefaultHttpClient.call(void 0, {
1231
+ return _chunkUOKXJQAIcjs.makeDefaultHttpClient.call(void 0, {
1232
1232
  ...httpConfig,
1233
1233
  middleware: [
1234
1234
  ..._nullishCoalesce(httpConfig.middleware, () => ( [])),