brass-runtime 1.19.1 → 1.20.0

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-XRRC5BBM.mjs";
13
13
  import {
14
14
  fromPromiseAbortable,
15
+ recordAbortablePromiseFinish,
16
+ recordAbortablePromiseStart,
15
17
  resolveWasmModule,
16
18
  toPromise
17
19
  } from "./chunk-BFNBU47C.mjs";
@@ -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;
@@ -5402,14 +5638,14 @@ function noopInvalidate(_key) {
5402
5638
  }
5403
5639
  function noopClear() {
5404
5640
  }
5405
- function buildLifecycleClient(fn2, tracker, internals) {
5406
- const client = (req) => trackRequest(fn2, req, tracker, internals);
5641
+ function buildLifecycleClient(fn3, tracker, internals) {
5642
+ const client = (req) => trackRequest(fn3, req, tracker, internals);
5407
5643
  const stats = () => {
5408
5644
  tracker.setQueueDepth(internals.queueDepth?.() ?? 0);
5409
5645
  return tracker.snapshot();
5410
5646
  };
5411
5647
  const withMw = (mw) => {
5412
- const wrappedFn = mw(withLifecycleMetadata(fn2, internals));
5648
+ const wrappedFn = mw(withLifecycleMetadata(fn3, internals));
5413
5649
  return buildLifecycleClient(wrappedFn, tracker, internals);
5414
5650
  };
5415
5651
  const lifecycleClient = Object.assign(client, {
@@ -5425,9 +5661,9 @@ function buildLifecycleClient(fn2, tracker, internals) {
5425
5661
  });
5426
5662
  return lifecycleClient;
5427
5663
  }
5428
- function withLifecycleMetadata(fn2, internals) {
5429
- if (!internals.adaptiveLimiter) return fn2;
5430
- return Object.assign(((req) => fn2(req)), {
5664
+ function withLifecycleMetadata(fn3, internals) {
5665
+ if (!internals.adaptiveLimiter) return fn3;
5666
+ return Object.assign(((req) => fn3(req)), {
5431
5667
  adaptiveLimiter: internals.adaptiveLimiter
5432
5668
  });
5433
5669
  }
@@ -5448,7 +5684,7 @@ function shutdownClient(activeCancelers, prewarmMgr, wireShutdown) {
5448
5684
  wireShutdown?.();
5449
5685
  return asyncSucceed(void 0);
5450
5686
  }
5451
- function trackRequest(fn2, req, tracker, internals) {
5687
+ function trackRequest(fn3, req, tracker, internals) {
5452
5688
  return {
5453
5689
  _tag: "Async",
5454
5690
  register: (env, cb) => {
@@ -5510,7 +5746,7 @@ function trackRequest(fn2, req, tracker, internals) {
5510
5746
  return () => void 0;
5511
5747
  }
5512
5748
  try {
5513
- cancelInner = registerHttpEffect(fn2(req), env, finish);
5749
+ cancelInner = registerHttpEffect(fn3(req), env, finish);
5514
5750
  } catch (error) {
5515
5751
  finish({
5516
5752
  _tag: "Failure",
@@ -5932,6 +6168,190 @@ function previewJson(value) {
5932
6168
  }
5933
6169
  }
5934
6170
 
6171
+ // src/http/bareMetalClient.ts
6172
+ var fn2 = Schema.custom(
6173
+ (value) => typeof value === "function",
6174
+ "function"
6175
+ );
6176
+ var poolConfig2 = Schema.union([
6177
+ Schema.literal(false),
6178
+ Schema.object(
6179
+ {
6180
+ concurrency: Schema.number({ min: 1, int: true }).optional(),
6181
+ maxQueue: Schema.number({ min: 0, int: true }).optional(),
6182
+ queueTimeoutMs: Schema.number({ min: 1, int: true }).optional(),
6183
+ key: Schema.union([
6184
+ Schema.enum(["global", "origin", "host"]),
6185
+ fn2
6186
+ ]).optional(),
6187
+ engine: Schema.enum(["ts", "wasm"]).optional(),
6188
+ wasm: Schema.boolean().optional()
6189
+ },
6190
+ { unknownKeys: "passthrough" }
6191
+ )
6192
+ ]);
6193
+ var adaptiveLimiterConfig2 = Schema.union([
6194
+ Schema.literal(false),
6195
+ Schema.object(
6196
+ {
6197
+ preset: Schema.enum(["conservative", "balanced", "aggressive"]).optional(),
6198
+ initialLimit: Schema.number({ min: 1, int: true }).optional(),
6199
+ minLimit: Schema.number({ min: 1, int: true }).optional(),
6200
+ maxLimit: Schema.number({ min: 1, int: true }).optional(),
6201
+ smoothingFactor: Schema.number({ min: 0, max: 1 }).refine((n) => n > 0, "smoothingFactor must be in (0, 1]").optional(),
6202
+ probeInterval: Schema.number({ min: 1, int: true }).optional(),
6203
+ probeJitterRatio: Schema.number({ min: 0, max: 1 }).optional(),
6204
+ windowSize: Schema.number({ min: 2, int: true }).optional(),
6205
+ minSamples: Schema.number({ min: 1, int: true }).optional(),
6206
+ baselineStrategy: Schema.enum(["min", "p5", "ema-low"]).optional(),
6207
+ decreaseCooldownSamples: Schema.number({ min: 0, int: true }).optional(),
6208
+ historySize: Schema.number({ min: 0, int: true }).optional(),
6209
+ windowDecayFactor: Schema.number({ min: 0, max: 1 }).refine((n) => n > 0, "windowDecayFactor must be in (0, 1]").optional(),
6210
+ errorWeight: Schema.number({ min: 0, max: 1 }).optional(),
6211
+ errorSmoothingFactor: Schema.number({ min: 0, max: 1 }).refine((n) => n > 0, "errorSmoothingFactor must be in (0, 1]").optional(),
6212
+ errorStatusThreshold: Schema.number({ min: 100, max: 599, int: true }).optional(),
6213
+ queueStrategy: Schema.enum(["fifo", "priority"]).optional(),
6214
+ queueLoadShedding: Schema.enum(["reject-new", "priority-evict"]).optional(),
6215
+ rejectionBackoffThreshold: Schema.number({ min: 1, int: true }).optional(),
6216
+ rejectionBackoffMs: Schema.number({ min: 1, int: true }).optional(),
6217
+ stateTtlMs: Schema.union([Schema.literal(false), Schema.number({ min: 1, int: true })]).optional(),
6218
+ warmupRequests: Schema.number({ min: 0, int: true }).optional(),
6219
+ decreaseThreshold: Schema.number({ min: 0, max: 1 }).refine((n) => n > 0, "decreaseThreshold must be in (0, 1]").optional(),
6220
+ increaseThreshold: Schema.number({ min: 1 }).optional(),
6221
+ maxDecreaseRatio: Schema.number({ min: 0, max: 1 }).refine((n) => n > 0, "maxDecreaseRatio must be in (0, 1]").optional(),
6222
+ headroomStrategy: Schema.union([
6223
+ Schema.number({ min: 1 }),
6224
+ Schema.enum(["fixed", "proportional"]),
6225
+ fn2,
6226
+ Schema.object({ type: Schema.literal("fixed"), value: Schema.number({ min: 1 }).optional() }, { unknownKeys: "passthrough" }),
6227
+ Schema.object({
6228
+ type: Schema.literal("proportional"),
6229
+ ratio: Schema.number({ min: 0 }).refine((n) => n > 0, "ratio must be > 0").optional(),
6230
+ min: Schema.number({ min: 1 }).optional(),
6231
+ max: Schema.number({ min: 1 }).optional()
6232
+ }, { unknownKeys: "passthrough" })
6233
+ ]).optional(),
6234
+ slowStartRecovery: Schema.boolean().optional(),
6235
+ slowStartSaturationThreshold: Schema.number({ min: 0, max: 1 }).refine((n) => n > 0, "slowStartSaturationThreshold must be in (0, 1]").optional(),
6236
+ slowStartSaturationSamples: Schema.number({ min: 1, int: true }).optional(),
6237
+ key: Schema.union([Schema.enum(["global", "origin", "host"]), fn2]).optional(),
6238
+ maxQueue: Schema.number({ min: 0, int: true }).optional(),
6239
+ queueTimeoutMs: Schema.number({ min: 1, int: true }).optional(),
6240
+ onLimitChange: fn2.optional(),
6241
+ percentile: Schema.enum(["p50", "p99"]).optional()
6242
+ },
6243
+ { unknownKeys: "passthrough" }
6244
+ )
6245
+ ]);
6246
+ var bareMetalConfigSchema = Schema.object(
6247
+ {
6248
+ baseUrl: Schema.string().optional(),
6249
+ headers: Schema.record(Schema.string()).optional(),
6250
+ timeoutMs: Schema.number({ min: 1, int: true }).optional(),
6251
+ transport: fn2.optional(),
6252
+ streamTransport: fn2.optional(),
6253
+ pool: poolConfig2.optional(),
6254
+ adaptiveLimiter: adaptiveLimiterConfig2.optional(),
6255
+ onEvent: fn2.optional()
6256
+ },
6257
+ { unknownKeys: "passthrough" }
6258
+ );
6259
+ function validateBareMetalConfig(config) {
6260
+ parseConfig("BareMetalHttpConfig", bareMetalConfigSchema, config);
6261
+ }
6262
+ var transportDestroy2 = (transport) => {
6263
+ const destroy = transport.destroy;
6264
+ return typeof destroy === "function" ? () => destroy.call(transport) : void 0;
6265
+ };
6266
+ function makeBareMetalHttp(cfg = {}) {
6267
+ validateBareMetalConfig(cfg);
6268
+ const baseUrl = cfg.baseUrl ?? "";
6269
+ const defaultHeaders = cfg.headers ?? {};
6270
+ const normalize = normalizeRequest(defaultHeaders);
6271
+ const adaptiveLimiter = makeAdaptiveLimiter(cfg);
6272
+ const pool = adaptiveLimiter ? void 0 : makePool(cfg);
6273
+ const metrics = makeHttpStats(pool, adaptiveLimiter);
6274
+ const transport = cfg.transport ?? makeFetchTransport();
6275
+ const destroyTransport = transportDestroy2(transport);
6276
+ const run = (req0) => {
6277
+ const req = normalize(req0);
6278
+ const url = resolveRequestUrl(req, baseUrl);
6279
+ if (!(url instanceof URL)) return asyncFail(url);
6280
+ const timeoutMs = resolvePositiveTimeout(req.timeoutMs ?? cfg.timeoutMs);
6281
+ if (!adaptiveLimiter && !pool && timeoutMs === void 0) {
6282
+ return runDirectTransport(req, url, transport, metrics);
6283
+ }
6284
+ return runPoolTransport(req, url, transport, metrics, pool, adaptiveLimiter, void 0, timeoutMs);
6285
+ };
6286
+ const metadata = {};
6287
+ if (adaptiveLimiter) metadata.adaptiveLimiter = adaptiveLimiter;
6288
+ if (adaptiveLimiter || destroyTransport) {
6289
+ metadata.destroy = () => {
6290
+ adaptiveLimiter?.destroy();
6291
+ destroyTransport?.();
6292
+ };
6293
+ metadata.shutdown = () => {
6294
+ adaptiveLimiter?.shutdown();
6295
+ destroyTransport?.();
6296
+ };
6297
+ }
6298
+ return decorate(run, metrics.snapshot, metadata);
6299
+ }
6300
+ function makeBareMetalHttpStream(cfg = {}) {
6301
+ validateBareMetalConfig(cfg);
6302
+ const baseUrl = cfg.baseUrl ?? "";
6303
+ const defaultHeaders = cfg.headers ?? {};
6304
+ const normalize = normalizeRequest(defaultHeaders);
6305
+ const adaptiveLimiter = makeAdaptiveLimiter(cfg);
6306
+ const pool = adaptiveLimiter ? void 0 : makePool(cfg);
6307
+ const metrics = makeHttpStats(pool, adaptiveLimiter);
6308
+ const transport = cfg.streamTransport ?? makeFetchStreamTransport();
6309
+ const run = (req0) => {
6310
+ const req = normalize(req0);
6311
+ const url = resolveRequestUrl(req, baseUrl);
6312
+ if (!(url instanceof URL)) return asyncFail(url);
6313
+ const timeoutMs = resolvePositiveTimeout(req.timeoutMs ?? cfg.timeoutMs);
6314
+ return fromPromiseAbortable(
6315
+ async (signal, env) => {
6316
+ let lease;
6317
+ const linkedSignal = linkAbortSignals(signal, req.init?.signal);
6318
+ try {
6319
+ if (linkedSignal.signal.aborted) throw abortErrorForSignal(linkedSignal.signal);
6320
+ if (adaptiveLimiter) {
6321
+ const key = resolveHttpPoolKey(adaptiveLimiter.keyResolver, req, url);
6322
+ lease = await adaptiveLimiter.acquire(key, linkedSignal.signal, { priority: requestPriority(req) });
6323
+ } else if (pool) {
6324
+ const key = resolveHttpPoolKey(pool.keyResolver, req, url);
6325
+ lease = await pool.acquire(key, linkedSignal.signal);
6326
+ }
6327
+ const response = await runTransportEffect(
6328
+ transport({ request: req, url, signal: linkedSignal.signal }),
6329
+ env,
6330
+ linkedSignal.signal
6331
+ );
6332
+ releaseSuccess(lease, adaptiveLimiter, response);
6333
+ lease = void 0;
6334
+ return response;
6335
+ } finally {
6336
+ linkedSignal.cleanup();
6337
+ if (lease) {
6338
+ releaseFailure(lease, adaptiveLimiter);
6339
+ }
6340
+ }
6341
+ },
6342
+ normalizeHttpError,
6343
+ {
6344
+ label: fetchLabel(req, url),
6345
+ timeoutMs,
6346
+ timeoutReason: timeoutMs ? () => timeoutReason(req, url, timeoutMs) : void 0,
6347
+ onStart: metrics.onStart,
6348
+ onFinish: metrics.onFinish
6349
+ }
6350
+ );
6351
+ };
6352
+ return decorateStream(run, metrics.snapshot);
6353
+ }
6354
+
5935
6355
  // src/http/requestBuilder.ts
5936
6356
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5937
6357
  function splitHttpRequestInit(init) {
@@ -6029,7 +6449,8 @@ var PRESET_CONFIGS = {
6029
6449
  highThroughputProxy: PROXY_PRESET_CONFIG,
6030
6450
  balanced: BALANCED_PRESET_CONFIG,
6031
6451
  default: DEFAULT_PRESET_CONFIG,
6032
- production: DEFAULT_PRESET_CONFIG
6452
+ production: DEFAULT_PRESET_CONFIG,
6453
+ bareMetal: {}
6033
6454
  };
6034
6455
  function isDefaultCacheableResponse(req, res) {
6035
6456
  if (!DEFAULT_CACHEABLE_METHODS.has(req.method)) return false;
@@ -6056,6 +6477,9 @@ function makeDefaultHttpClient(config = {}) {
6056
6477
  policyPresets,
6057
6478
  ...lifecycleOverrides
6058
6479
  } = config;
6480
+ if (preset === "bareMetal") {
6481
+ return buildBareMetalBranch(lifecycleOverrides, middleware, config);
6482
+ }
6059
6483
  const lifecycleConfig2 = mergeLifecycleConfig(PRESET_CONFIGS[preset], lifecycleOverrides);
6060
6484
  let wire = makeLifecycleClient(lifecycleConfig2);
6061
6485
  const compressionResult = compression === false || compression === void 0 && isLeanPreset(preset) ? void 0 : makeCompressionMiddleware(compression === void 0 ? void 0 : compression);
@@ -6079,6 +6503,160 @@ function makeDefaultHttpClient(config = {}) {
6079
6503
  useInlineDecode
6080
6504
  });
6081
6505
  }
6506
+ var LIFECYCLE_KEYS = [
6507
+ "dedup",
6508
+ "batch",
6509
+ "cache",
6510
+ "priority",
6511
+ "retry",
6512
+ "prewarm",
6513
+ "adaptiveLimiter",
6514
+ "compression"
6515
+ ];
6516
+ function findIgnoredLifecycleKeys(overrides) {
6517
+ const found = [];
6518
+ for (const key of LIFECYCLE_KEYS) {
6519
+ if (key in overrides && overrides[key] !== void 0 && overrides[key] !== false) {
6520
+ found.push(key);
6521
+ }
6522
+ }
6523
+ return found;
6524
+ }
6525
+ function extractBareMetalConfig(config) {
6526
+ return {
6527
+ baseUrl: config.baseUrl,
6528
+ headers: config.headers,
6529
+ timeoutMs: config.timeoutMs,
6530
+ transport: config.transport,
6531
+ streamTransport: config.streamTransport,
6532
+ pool: config.pool,
6533
+ adaptiveLimiter: void 0,
6534
+ // bare-metal ignores adaptiveLimiter from lifecycle overrides
6535
+ onEvent: config.onEvent
6536
+ };
6537
+ }
6538
+ function buildBareMetalBranch(lifecycleOverrides, middleware, config) {
6539
+ const ignored = findIgnoredLifecycleKeys(lifecycleOverrides);
6540
+ if (ignored.length > 0 && config.onEvent) {
6541
+ config.onEvent({
6542
+ type: "warning",
6543
+ message: `bareMetal preset ignores: ${ignored.join(", ")}`
6544
+ });
6545
+ }
6546
+ let bareWire = makeBareMetalHttp(extractBareMetalConfig(config));
6547
+ for (const mw of middleware) {
6548
+ bareWire = bareWire.with(mw);
6549
+ }
6550
+ const features = Object.freeze({
6551
+ dedup: false,
6552
+ batch: false,
6553
+ cache: false,
6554
+ priority: false,
6555
+ retry: false,
6556
+ prewarm: false,
6557
+ adaptiveLimiter: false,
6558
+ compression: false,
6559
+ middleware: middleware.length
6560
+ });
6561
+ return buildBareMetalDefaultClient(bareWire, { preset: "bareMetal", features });
6562
+ }
6563
+ function buildBareMetalDefaultClient(bareWire, meta) {
6564
+ const withPromise = (eff) => withAsyncPromise((e, env) => toPromise(e, env))(eff);
6565
+ const requestRaw = (req) => bareWire(req);
6566
+ const request = (req) => withPromise(requestRaw(req));
6567
+ const get = (url, init) => request(buildHttpRequest("GET", url, init));
6568
+ const post = (url, body, init) => request(buildHttpRequest("POST", url, init, body));
6569
+ const getText = (url, init) => {
6570
+ const req = buildHttpRequest("GET", url, init);
6571
+ return withPromise(
6572
+ mapTryAsync(requestRaw(req), (w) => toResponse(w, w.bodyText))
6573
+ );
6574
+ };
6575
+ const getJson = ((url, init) => {
6576
+ const req = setHeaderIfMissing("accept", "application/json")(
6577
+ buildHttpRequest("GET", url, init)
6578
+ );
6579
+ return withPromise(
6580
+ asyncFlatMap(requestRaw(req), (w) => decodeResponse(w, init?.schema, init?.schemaName))
6581
+ );
6582
+ });
6583
+ const postJson = ((url, bodyObj, init) => {
6584
+ return withPromise(
6585
+ asyncFlatMap(
6586
+ encodeJsonBodyEffect(bodyObj, init?.bodySchema, { schemaName: init?.bodySchemaName }),
6587
+ (bodyText) => {
6588
+ const req = setHeaderIfMissing("content-type", "application/json")(
6589
+ setHeaderIfMissing("accept", "application/json")(
6590
+ buildHttpRequest("POST", url, init, bodyText)
6591
+ )
6592
+ );
6593
+ return asyncFlatMap(requestRaw(req), (w) => decodeResponse(w, init?.schema, init?.schemaName));
6594
+ }
6595
+ )
6596
+ );
6597
+ });
6598
+ const wireAsLifecycle = Object.assign(
6599
+ (req) => bareWire(req),
6600
+ {
6601
+ with: (mw) => {
6602
+ const newBare = bareWire.with(mw);
6603
+ return buildBareMetalDefaultClient(newBare, {
6604
+ ...meta,
6605
+ features: { ...meta.features, middleware: meta.features.middleware + 1 }
6606
+ }).wire;
6607
+ },
6608
+ stats: () => ({
6609
+ cacheHits: 0,
6610
+ cacheMisses: 0,
6611
+ cacheEvictions: 0,
6612
+ dedupHits: 0,
6613
+ dedupActive: 0,
6614
+ queueDepth: 0,
6615
+ requestsStarted: 0,
6616
+ requestsCompleted: 0,
6617
+ requestsFailed: 0,
6618
+ retries: 0,
6619
+ batchDispatches: 0,
6620
+ batchedRequests: 0,
6621
+ wire: bareWire.stats()
6622
+ }),
6623
+ cancelAll: () => asyncSucceed(void 0),
6624
+ shutdown: () => {
6625
+ bareWire.shutdown?.();
6626
+ return asyncSucceed(void 0);
6627
+ },
6628
+ cache: {
6629
+ invalidate: () => {
6630
+ },
6631
+ clear: () => {
6632
+ }
6633
+ },
6634
+ ...bareWire.adaptiveLimiter ? { adaptiveLimiter: bareWire.adaptiveLimiter } : {}
6635
+ }
6636
+ );
6637
+ return {
6638
+ request,
6639
+ get,
6640
+ post,
6641
+ getText,
6642
+ getJson,
6643
+ postJson,
6644
+ with: (mw) => buildBareMetalDefaultClient(bareWire.with(mw), {
6645
+ ...meta,
6646
+ features: {
6647
+ ...meta.features,
6648
+ middleware: meta.features.middleware + 1
6649
+ }
6650
+ }),
6651
+ wire: wireAsLifecycle,
6652
+ stats: () => wireAsLifecycle.stats(),
6653
+ cache: wireAsLifecycle.cache,
6654
+ cancelAll: wireAsLifecycle.cancelAll,
6655
+ shutdown: wireAsLifecycle.shutdown,
6656
+ preset: meta.preset,
6657
+ features: meta.features
6658
+ };
6659
+ }
6082
6660
  function buildDefaultClient(wire, meta) {
6083
6661
  const withPromise = (eff) => withAsyncPromise((e, env) => toPromise(e, env))(eff);
6084
6662
  const requestRaw = (req) => wire(req);
@@ -6259,7 +6837,7 @@ function isEnabled(value) {
6259
6837
  return value !== void 0 && value !== false;
6260
6838
  }
6261
6839
  function isLeanPreset(preset) {
6262
- return preset === "minimal" || preset === "proxy" || preset === "highThroughputProxy";
6840
+ return preset === "minimal" || preset === "proxy" || preset === "highThroughputProxy" || preset === "bareMetal";
6263
6841
  }
6264
6842
 
6265
6843
  // src/http/layer.ts
@@ -6337,9 +6915,24 @@ export {
6337
6915
  makeFetchStreamTransport,
6338
6916
  decorate,
6339
6917
  withMiddleware,
6918
+ decorateStream,
6340
6919
  normalizeHeadersInit,
6920
+ normalizeRequest,
6921
+ resolvePositiveTimeout,
6922
+ makeHttpStats,
6923
+ makePool,
6924
+ makeAdaptiveLimiter,
6925
+ resolveRequestUrl,
6926
+ fetchLabel,
6927
+ timeoutReason,
6928
+ requestPriority,
6929
+ runTransportEffect,
6930
+ runDirectTransport,
6931
+ releaseSuccess,
6932
+ releaseFailure,
6341
6933
  makeHttpStream,
6342
6934
  noopSignal,
6935
+ runPoolTransport,
6343
6936
  makeHttp,
6344
6937
  withRetryStream,
6345
6938
  SEPARATOR,
@@ -6375,6 +6968,9 @@ export {
6375
6968
  validatedJson,
6376
6969
  validatedJsonResponse,
6377
6970
  buildHttpRequest,
6971
+ validateBareMetalConfig,
6972
+ makeBareMetalHttp,
6973
+ makeBareMetalHttpStream,
6378
6974
  defaultHttpClientPreset,
6379
6975
  makeDefaultHttpClient,
6380
6976
  HttpClientService,