s3db.js 19.3.3 → 19.3.4

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.
@@ -2,43 +2,43 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var perf_hooks = require('perf_hooks');
6
- var async_hooks = require('async_hooks');
7
- var require$$0$3 = require('node:diagnostics_channel');
8
- var require$$1$4 = require('node:dns');
9
- var require$$0$2 = require('node:util');
10
- var node_child_process = require('node:child_process');
11
- var fs = require('node:fs');
12
- var require$$1$3 = require('node:path');
13
- var os = require('node:os');
14
- var require$$0$1 = require('node:stream');
15
- var promises = require('node:stream/promises');
16
- var require$$0$5 = require('node:fs/promises');
17
- var require$$2$2 = require('node:crypto');
18
- var require$$3 = require('node:zlib');
19
- var path = require('path');
20
- var EventEmitter = require('events');
21
- var lodashEs = require('lodash-es');
22
- var v8 = require('node:v8');
23
5
  var require$$0 = require('node:assert');
24
6
  var net = require('node:net');
25
7
  var require$$2 = require('node:http');
8
+ var require$$0$1 = require('node:stream');
26
9
  var require$$5 = require('node:querystring');
27
10
  var require$$6 = require('node:events');
11
+ var require$$0$3 = require('node:diagnostics_channel');
12
+ var require$$0$2 = require('node:util');
28
13
  var require$$4 = require('node:tls');
29
14
  var require$$0$4 = require('node:buffer');
15
+ var require$$3 = require('node:zlib');
30
16
  var require$$5$1 = require('node:perf_hooks');
31
17
  var require$$8 = require('node:util/types');
18
+ var require$$2$2 = require('node:crypto');
32
19
  var require$$1 = require('node:sqlite');
33
20
  var require$$2$1 = require('node:worker_threads');
34
21
  var require$$1$1 = require('node:async_hooks');
35
22
  var require$$1$2 = require('node:console');
23
+ var require$$0$5 = require('node:fs/promises');
24
+ var require$$1$3 = require('node:path');
36
25
  var require$$2$3 = require('node:timers');
37
- var net$1 = require('net');
26
+ var require$$1$4 = require('node:dns');
27
+ var perf_hooks = require('perf_hooks');
28
+ var async_hooks = require('async_hooks');
29
+ var dns$1 = require('node:dns/promises');
30
+ var os = require('node:os');
31
+ var fs = require('node:fs');
32
+ var v8 = require('node:v8');
33
+ var node_child_process = require('node:child_process');
34
+ require('node:stream/promises');
35
+ var path = require('path');
36
+ var EventEmitter = require('events');
37
+ var lodashEs = require('lodash-es');
38
38
  var clientS3 = require('@aws-sdk/client-s3');
39
39
  var crypto = require('crypto');
40
40
  var os$1 = require('os');
41
- var promises$1 = require('timers/promises');
41
+ var promises = require('timers/promises');
42
42
  var nanoid = require('nanoid');
43
43
  var fs$1 = require('fs/promises');
44
44
  var stream = require('stream');
@@ -1379,7 +1379,7 @@ function quoteField(value, opts) {
1379
1379
  return str;
1380
1380
  }
1381
1381
 
1382
- function isNodeRuntime$1() {
1382
+ function isNodeRuntime$5() {
1383
1383
  return typeof globalThis !== 'undefined' && Boolean(globalThis.process?.versions?.node);
1384
1384
  }
1385
1385
  class RequestPromise {
@@ -1437,7 +1437,7 @@ class RequestPromise {
1437
1437
  return response.read();
1438
1438
  }
1439
1439
  async write(path) {
1440
- if (!isNodeRuntime$1()) {
1440
+ if (!isNodeRuntime$5()) {
1441
1441
  throw new StreamError$1('write() is only supported in Node.js environments.', { streamType: 'response', retriable: false });
1442
1442
  }
1443
1443
  const response = await this.promise;
@@ -37407,6 +37407,129 @@ function getGlobalProtocolCache() {
37407
37407
  return globalProtocolCache;
37408
37408
  }
37409
37409
 
37410
+ const hostTimings = new Map();
37411
+ const connectionCounter = new Map();
37412
+ let globalConnectionId = 0;
37413
+ const sessionCache = new Map();
37414
+ function getTimingForHost(hostname) {
37415
+ const timing = hostTimings.get(hostname);
37416
+ if (process.env.DEBUG_TIMING) {
37417
+ console.log(`[TIMING] getTimingForHost(${hostname}):`, timing ? 'found' : 'NOT FOUND', 'map size:', hostTimings.size);
37418
+ }
37419
+ return timing;
37420
+ }
37421
+ function getConnectionId(hostname) {
37422
+ return connectionCounter.get(hostname) ?? 0;
37423
+ }
37424
+ function isNewConnection(hostname, previousId) {
37425
+ const currentId = connectionCounter.get(hostname) ?? 0;
37426
+ return currentId > previousId;
37427
+ }
37428
+ function buildTimingConnector(options = {}) {
37429
+ const timeout = options.timeout ?? 10000;
37430
+ const allowH2 = options.allowH2 ?? false;
37431
+ const keepAliveInitialDelay = options.keepAliveInitialDelay ?? 60000;
37432
+ const maxCachedSessions = options.maxCachedSessions ?? 100;
37433
+ const localAddress = options.localAddress;
37434
+ return function connect(opts, callback) {
37435
+ const { hostname, protocol, port, servername } = opts;
37436
+ const isHttps = protocol === 'https:';
37437
+ const targetPort = Number(port) || (isHttps ? 443 : 80);
37438
+ const timings = {
37439
+ dns: 0,
37440
+ tcp: 0,
37441
+ tls: 0,
37442
+ total: 0
37443
+ };
37444
+ const startTime = require$$5$1.performance.now();
37445
+ doConnect();
37446
+ async function doConnect() {
37447
+ try {
37448
+ const dnsStart = require$$5$1.performance.now();
37449
+ let resolvedAddress;
37450
+ try {
37451
+ const result = await dns$1.lookup(hostname, { family: 4 });
37452
+ resolvedAddress = result.address;
37453
+ }
37454
+ catch (dnsError) {
37455
+ try {
37456
+ const result = await dns$1.lookup(hostname, { family: 6 });
37457
+ resolvedAddress = result.address;
37458
+ }
37459
+ catch {
37460
+ callback(dnsError, null);
37461
+ return;
37462
+ }
37463
+ }
37464
+ timings.dns = require$$5$1.performance.now() - dnsStart;
37465
+ const tcpStart = require$$5$1.performance.now();
37466
+ const tcpSocket = net.connect({
37467
+ host: resolvedAddress,
37468
+ port: targetPort,
37469
+ localAddress: localAddress,
37470
+ });
37471
+ tcpSocket.setNoDelay(true);
37472
+ tcpSocket.setKeepAlive(true, keepAliveInitialDelay);
37473
+ const timeoutTimer = setTimeout(() => {
37474
+ tcpSocket.destroy(new Error(`Connect timeout after ${timeout}ms`));
37475
+ }, timeout);
37476
+ tcpSocket.once('error', (err) => {
37477
+ clearTimeout(timeoutTimer);
37478
+ callback(err, null);
37479
+ });
37480
+ tcpSocket.once('connect', () => {
37481
+ timings.tcp = require$$5$1.performance.now() - tcpStart;
37482
+ clearTimeout(timeoutTimer);
37483
+ if (!isHttps) {
37484
+ timings.total = require$$5$1.performance.now() - startTime;
37485
+ hostTimings.set(hostname, { ...timings });
37486
+ globalConnectionId++;
37487
+ connectionCounter.set(hostname, globalConnectionId);
37488
+ callback(null, tcpSocket);
37489
+ return;
37490
+ }
37491
+ const tlsStart = require$$5$1.performance.now();
37492
+ const sn = servername || hostname;
37493
+ const sessionKey = `${sn}:${targetPort}`;
37494
+ const session = sessionCache.get(sessionKey);
37495
+ const tlsSocket = require$$4.connect({
37496
+ socket: tcpSocket,
37497
+ servername: sn,
37498
+ session: session,
37499
+ ALPNProtocols: allowH2 ? ['h2', 'http/1.1'] : ['http/1.1'],
37500
+ rejectUnauthorized: true,
37501
+ });
37502
+ tlsSocket.on('session', (newSession) => {
37503
+ if (sessionCache.size >= maxCachedSessions) {
37504
+ const firstKey = sessionCache.keys().next().value;
37505
+ if (firstKey)
37506
+ sessionCache.delete(firstKey);
37507
+ }
37508
+ sessionCache.set(sessionKey, newSession);
37509
+ });
37510
+ tlsSocket.once('error', (err) => {
37511
+ callback(err, null);
37512
+ });
37513
+ tlsSocket.once('secureConnect', () => {
37514
+ timings.tls = require$$5$1.performance.now() - tlsStart;
37515
+ timings.total = require$$5$1.performance.now() - startTime;
37516
+ hostTimings.set(hostname, { ...timings });
37517
+ globalConnectionId++;
37518
+ connectionCounter.set(hostname, globalConnectionId);
37519
+ if (process.env.DEBUG_TIMING) {
37520
+ console.log(`[TIMING] Stored for ${hostname}:`, timings);
37521
+ }
37522
+ callback(null, tlsSocket);
37523
+ });
37524
+ });
37525
+ }
37526
+ catch (err) {
37527
+ callback(err, null);
37528
+ }
37529
+ }
37530
+ };
37531
+ }
37532
+
37410
37533
  class AgentManager {
37411
37534
  globalAgent;
37412
37535
  domainAgents;
@@ -37532,6 +37655,13 @@ class AgentManager {
37532
37655
  });
37533
37656
  }
37534
37657
  createAgent(options) {
37658
+ const timingConnector = buildTimingConnector({
37659
+ timeout: options.connectTimeout,
37660
+ allowH2: options.allowH2,
37661
+ keepAliveInitialDelay: options.keepAliveTimeout,
37662
+ maxCachedSessions: options.maxCachedSessions,
37663
+ localAddress: options.localAddress,
37664
+ });
37535
37665
  return new undiciExports.Agent({
37536
37666
  connections: options.connections,
37537
37667
  pipelining: options.pipelining,
@@ -37546,12 +37676,7 @@ class AgentManager {
37546
37676
  socketPath: undefined,
37547
37677
  allowH2: options.allowH2,
37548
37678
  maxConcurrentStreams: options.maxConcurrentStreams,
37549
- connect: {
37550
- timeout: options.connectTimeout,
37551
- keepAlive: options.keepAlive,
37552
- keepAliveInitialDelay: options.keepAliveTimeout,
37553
- localAddress: options.localAddress,
37554
- },
37679
+ connect: timingConnector,
37555
37680
  });
37556
37681
  }
37557
37682
  getStats() {
@@ -37677,9 +37802,22 @@ const requestStorage = new async_hooks.AsyncLocalStorage();
37677
37802
  undiciRequestChannel.subscribe((message) => {
37678
37803
  const store = requestStorage.getStore();
37679
37804
  if (store) {
37680
- store.requestStartTime = perf_hooks.performance.now();
37681
- store.timings = { queuing: 0, dns: 0, tcp: 0, tls: 0, firstByte: 0, content: 0, total: 0 };
37682
- store.connection = {};
37805
+ if (store.requestStartTime === 0) {
37806
+ store.requestStartTime = perf_hooks.performance.now();
37807
+ }
37808
+ const hasConnectionTimings = store.timings.dns || store.timings.tcp || store.timings.tls;
37809
+ if (!hasConnectionTimings) {
37810
+ store.timings = { queuing: 0, dns: 0, tcp: 0, tls: 0, firstByte: 0, content: 0, total: 0 };
37811
+ store.connection = {};
37812
+ }
37813
+ const msg = message;
37814
+ if (msg?.request?.origin && !store.requestCorrelationId) {
37815
+ try {
37816
+ store.requestCorrelationId = new URL(msg.request.origin).hostname;
37817
+ }
37818
+ catch {
37819
+ }
37820
+ }
37683
37821
  }
37684
37822
  });
37685
37823
  undiciBodySentChannel.subscribe((message) => {
@@ -37691,7 +37829,11 @@ undiciBodySentChannel.subscribe((message) => {
37691
37829
  undiciHeadersChannel.subscribe((message) => {
37692
37830
  const payload = message;
37693
37831
  const store = requestStorage.getStore();
37694
- if (store && payload && payload.timing) {
37832
+ if (!store || !payload)
37833
+ return;
37834
+ const now = perf_hooks.performance.now();
37835
+ const ttfb = now - store.requestStartTime;
37836
+ if (payload.timing) {
37695
37837
  const { timing } = payload;
37696
37838
  store.timings.queuing = timing.queuing;
37697
37839
  store.timings.dns = timing.dns;
@@ -37700,23 +37842,29 @@ undiciHeadersChannel.subscribe((message) => {
37700
37842
  store.timings.firstByte = timing.response;
37701
37843
  store.timings.content = timing.body;
37702
37844
  store.timings.total = timing.ended;
37703
- if (store.hooks) {
37704
- if (store.hooks.onDnsLookup && timing.dns > 0) {
37705
- store.hooks.onDnsLookup({ domain: payload.request.origin, duration: timing.dns });
37706
- }
37707
- if (store.hooks.onTcpConnect && timing.tcp > 0) {
37708
- store.hooks.onTcpConnect({ remoteAddress: '', duration: timing.tcp });
37709
- }
37710
- if (store.hooks.onTlsHandshake && timing.tls > 0) {
37711
- store.hooks.onTlsHandshake({ protocol: '', cipher: '', duration: timing.tls });
37712
- }
37713
- if (store.hooks.onResponseStart) {
37714
- const headers = new Headers();
37715
- for (let i = 0; i < payload.response.headers.length; i += 2) {
37716
- headers.append(payload.response.headers[i], payload.response.headers[i + 1]);
37717
- }
37718
- store.hooks.onResponseStart({ status: payload.response.statusCode, headers });
37845
+ }
37846
+ else {
37847
+ store.timings.firstByte = ttfb;
37848
+ }
37849
+ if (store.hooks) {
37850
+ const dns = store.timings.dns ?? 0;
37851
+ const tcp = store.timings.tcp ?? 0;
37852
+ const tls = store.timings.tls ?? 0;
37853
+ if (store.hooks.onDnsLookup && dns > 0) {
37854
+ store.hooks.onDnsLookup({ domain: payload.request.origin, duration: dns });
37855
+ }
37856
+ if (store.hooks.onTcpConnect && tcp > 0) {
37857
+ store.hooks.onTcpConnect({ remoteAddress: '', duration: tcp });
37858
+ }
37859
+ if (store.hooks.onTlsHandshake && tls > 0) {
37860
+ store.hooks.onTlsHandshake({ protocol: '', cipher: '', duration: tls });
37861
+ }
37862
+ if (store.hooks.onResponseStart) {
37863
+ const headers = new Headers();
37864
+ for (let i = 0; i < payload.response.headers.length; i += 2) {
37865
+ headers.append(payload.response.headers[i], payload.response.headers[i + 1]);
37719
37866
  }
37867
+ store.hooks.onResponseStart({ status: payload.response.statusCode, headers });
37720
37868
  }
37721
37869
  }
37722
37870
  });
@@ -37814,7 +37962,6 @@ function mapTimeoutOptions(requestTimeout, transportDefaults) {
37814
37962
  };
37815
37963
  }
37816
37964
  class UndiciTransport {
37817
- static requestCounter = 0;
37818
37965
  baseUrl;
37819
37966
  options;
37820
37967
  proxyAgent;
@@ -37961,7 +38108,7 @@ class UndiciTransport {
37961
38108
  timings: {},
37962
38109
  connection: {},
37963
38110
  requestStartTime: 0,
37964
- requestCorrelationId: `r${++UndiciTransport.requestCounter}`,
38111
+ requestCorrelationId: '',
37965
38112
  hooks: req._hooks
37966
38113
  };
37967
38114
  return requestStorage.run(requestContext, async () => {
@@ -38072,6 +38219,12 @@ class UndiciTransport {
38072
38219
  }
38073
38220
  }
38074
38221
  let undiciResponse;
38222
+ let connectionIdBefore = 0;
38223
+ try {
38224
+ connectionIdBefore = getConnectionId(new URL(currentUrl).hostname);
38225
+ }
38226
+ catch {
38227
+ }
38075
38228
  if (this.socketClient) {
38076
38229
  const urlPath = new URL(currentUrl).pathname + new URL(currentUrl).search;
38077
38230
  undiciResponse = await this.socketClient.request({
@@ -38116,6 +38269,25 @@ class UndiciTransport {
38116
38269
  ? wrapDownloadResponse$1(undiciResponse, req.onDownloadProgress)
38117
38270
  : undiciResponse;
38118
38271
  this.updateProtocolCache(currentUrl, requestContext.connection);
38272
+ try {
38273
+ const urlHostname = new URL(currentUrl).hostname;
38274
+ const madeNewConnection = isNewConnection(urlHostname, connectionIdBefore);
38275
+ if (madeNewConnection) {
38276
+ const connTiming = getTimingForHost(urlHostname);
38277
+ if (connTiming && !requestContext.timings.dns && !requestContext.timings.tcp && !requestContext.timings.tls) {
38278
+ requestContext.timings.dns = connTiming.dns;
38279
+ requestContext.timings.tcp = connTiming.tcp;
38280
+ requestContext.timings.tls = connTiming.tls;
38281
+ }
38282
+ }
38283
+ else if (!requestContext.timings.dns && !requestContext.timings.tcp && !requestContext.timings.tls) {
38284
+ requestContext.timings.dns = 0;
38285
+ requestContext.timings.tcp = 0;
38286
+ requestContext.timings.tls = 0;
38287
+ }
38288
+ }
38289
+ catch {
38290
+ }
38119
38291
  return new HttpResponse(finalResponse, {
38120
38292
  timings: requestContext.timings,
38121
38293
  connection: requestContext.connection
@@ -38156,6 +38328,29 @@ class UndiciTransport {
38156
38328
  requestContext.timings.total = totalTime;
38157
38329
  }
38158
38330
  this.updateProtocolCache(currentUrl, requestContext.connection);
38331
+ try {
38332
+ const urlHostname = new URL(currentUrl).hostname;
38333
+ const madeNewConnection = isNewConnection(urlHostname, connectionIdBefore);
38334
+ if (madeNewConnection) {
38335
+ const connTiming = getTimingForHost(urlHostname);
38336
+ if (connTiming) {
38337
+ if (!requestContext.timings.dns && !requestContext.timings.tcp && !requestContext.timings.tls) {
38338
+ requestContext.timings.dns = connTiming.dns;
38339
+ requestContext.timings.tcp = connTiming.tcp;
38340
+ requestContext.timings.tls = connTiming.tls;
38341
+ }
38342
+ }
38343
+ }
38344
+ else {
38345
+ if (!requestContext.timings.dns && !requestContext.timings.tcp && !requestContext.timings.tls) {
38346
+ requestContext.timings.dns = 0;
38347
+ requestContext.timings.tcp = 0;
38348
+ requestContext.timings.tls = 0;
38349
+ }
38350
+ }
38351
+ }
38352
+ catch {
38353
+ }
38159
38354
  return new HttpResponse(finalResponse, {
38160
38355
  timings: requestContext.timings,
38161
38356
  connection: requestContext.connection
@@ -39524,7 +39719,9 @@ class HttpRequest {
39524
39719
  constructor(url, options = {}) {
39525
39720
  this.url = url;
39526
39721
  this.method = options.method || 'GET';
39527
- this.headers = new Headers(options.headers);
39722
+ this.headers = options.headers instanceof Headers
39723
+ ? options.headers
39724
+ : new Headers(options.headers);
39528
39725
  this.body = options.body || null;
39529
39726
  this.signal = options.signal;
39530
39727
  this.throwHttpErrors = options.throwHttpErrors !== undefined ? options.throwHttpErrors : true;
@@ -39961,7 +40158,7 @@ function getDefaultUserAgent() {
39961
40158
  return `recker/${VERSION$1}`;
39962
40159
  }
39963
40160
 
39964
- const VERSION = '1.0.56';
40161
+ const VERSION = '1.0.59';
39965
40162
  let _version = null;
39966
40163
  async function getVersion() {
39967
40164
  if (_version)
@@ -40209,616 +40406,333 @@ function retryPlugin(options = {}) {
40209
40406
  };
40210
40407
  }
40211
40408
 
40212
- const DEFAULT_TOTAL_PERCENT = 0.5;
40213
- const DEFAULT_HEAP_PERCENT = 0.6;
40214
- function readCgroupLimit() {
40215
- const candidates = [
40216
- '/sys/fs/cgroup/memory.max',
40217
- '/sys/fs/cgroup/memory/memory.limit_in_bytes',
40218
- ];
40219
- for (const file of candidates) {
40220
- try {
40221
- if (fs.existsSync(file)) {
40222
- const raw = fs.readFileSync(file, 'utf8').trim();
40223
- if (!raw || raw === 'max')
40224
- continue;
40225
- const value = Number.parseInt(raw, 10);
40226
- if (Number.isFinite(value) && value > 0) {
40227
- return value;
40228
- }
40409
+ class SimpleMemoryStorage {
40410
+ store = new Map();
40411
+ async get(key) {
40412
+ const entry = this.store.get(key);
40413
+ if (!entry)
40414
+ return null;
40415
+ if (entry.expiresAt > 0 && entry.expiresAt <= Date.now()) {
40416
+ this.store.delete(key);
40417
+ return null;
40418
+ }
40419
+ return entry.value;
40420
+ }
40421
+ async set(key, value, ttl) {
40422
+ if (!Number.isFinite(ttl) || ttl <= 0) {
40423
+ this.store.delete(key);
40424
+ return;
40425
+ }
40426
+ this.store.set(key, {
40427
+ value,
40428
+ expiresAt: Date.now() + ttl,
40429
+ });
40430
+ }
40431
+ async delete(key) {
40432
+ this.store.delete(key);
40433
+ }
40434
+ }
40435
+
40436
+ const textEncoder$1 = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;
40437
+ const BufferCtor$1 = globalThis.Buffer;
40438
+ function isNodeRuntime$4() {
40439
+ return typeof globalThis !== 'undefined' && Boolean(globalThis.process?.versions?.node);
40440
+ }
40441
+ let LazyCacheStorage$1 = class LazyCacheStorage {
40442
+ factory;
40443
+ storage;
40444
+ resolving;
40445
+ constructor(factory) {
40446
+ this.factory = factory;
40447
+ }
40448
+ async getStorage() {
40449
+ if (!this.storage) {
40450
+ if (!this.resolving) {
40451
+ this.resolving = this.factory().then((instance) => {
40452
+ this.storage = instance;
40453
+ return instance;
40454
+ });
40229
40455
  }
40456
+ this.storage = await this.resolving;
40457
+ }
40458
+ return this.storage;
40459
+ }
40460
+ async get(key) {
40461
+ return (await this.getStorage()).get(key);
40462
+ }
40463
+ async set(key, value, ttl) {
40464
+ return (await this.getStorage()).set(key, value, ttl);
40465
+ }
40466
+ async delete(key) {
40467
+ return (await this.getStorage()).delete(key);
40468
+ }
40469
+ };
40470
+ function createDefaultStorage() {
40471
+ if (!isNodeRuntime$4()) {
40472
+ return new SimpleMemoryStorage();
40473
+ }
40474
+ return new LazyCacheStorage$1(async () => {
40475
+ const { MemoryStorage } = await Promise.resolve().then(function () { return memoryStorage; });
40476
+ return new MemoryStorage();
40477
+ });
40478
+ }
40479
+ function toBytes$1(value) {
40480
+ if (value === null || value === undefined)
40481
+ return null;
40482
+ if (typeof value === 'string') {
40483
+ if (textEncoder$1)
40484
+ return textEncoder$1.encode(value);
40485
+ if (BufferCtor$1)
40486
+ return BufferCtor$1.from(value, 'utf8');
40487
+ return null;
40488
+ }
40489
+ if (typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams) {
40490
+ const encoded = value.toString();
40491
+ if (textEncoder$1)
40492
+ return textEncoder$1.encode(encoded);
40493
+ if (BufferCtor$1)
40494
+ return BufferCtor$1.from(encoded, 'utf8');
40495
+ return null;
40496
+ }
40497
+ if (value instanceof ArrayBuffer) {
40498
+ return new Uint8Array(value);
40499
+ }
40500
+ if (ArrayBuffer.isView(value)) {
40501
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
40502
+ }
40503
+ if (typeof Blob !== 'undefined' && value instanceof Blob) {
40504
+ return null;
40505
+ }
40506
+ if (typeof value === 'object') {
40507
+ try {
40508
+ const json = JSON.stringify(value);
40509
+ if (textEncoder$1)
40510
+ return textEncoder$1.encode(json);
40511
+ if (BufferCtor$1)
40512
+ return BufferCtor$1.from(json, 'utf8');
40513
+ return null;
40230
40514
  }
40231
40515
  catch {
40516
+ return null;
40232
40517
  }
40233
40518
  }
40234
40519
  return null;
40235
40520
  }
40236
- function getEffectiveTotalMemoryBytes() {
40237
- const cgroupLimit = readCgroupLimit();
40238
- if (cgroupLimit && Number.isFinite(cgroupLimit) && cgroupLimit > 0) {
40239
- return cgroupLimit;
40521
+ function hashBytes(bytes) {
40522
+ let hash = 0xcbf29ce484222325n;
40523
+ const prime = 0x100000001b3n;
40524
+ for (const byte of bytes) {
40525
+ hash ^= BigInt(byte);
40526
+ hash = (hash * prime) & 0xffffffffffffffffn;
40240
40527
  }
40241
- return os.totalmem();
40528
+ return hash.toString(16).padStart(16, '0');
40242
40529
  }
40243
- function resolveCacheMemoryLimit(options = {}) {
40244
- const { maxMemoryBytes, maxMemoryPercent, safetyPercent } = options;
40245
- const heapStats = v8.getHeapStatistics();
40246
- const heapLimit = heapStats?.heap_size_limit ?? 0;
40247
- const effectiveTotal = getEffectiveTotalMemoryBytes();
40248
- let resolvedBytes = 0;
40249
- let derivedFromPercent = false;
40250
- if (typeof maxMemoryBytes === 'number' && maxMemoryBytes > 0) {
40251
- resolvedBytes = maxMemoryBytes;
40530
+ function isTextContentType(contentType) {
40531
+ if (!contentType)
40532
+ return true;
40533
+ const value = contentType.toLowerCase();
40534
+ if (value.startsWith('text/'))
40535
+ return true;
40536
+ if (value.includes('json') || value.includes('xml'))
40537
+ return true;
40538
+ if (value.includes('yaml') || value.includes('csv'))
40539
+ return true;
40540
+ if (value.includes('javascript') || value.includes('ecmascript'))
40541
+ return true;
40542
+ if (value.includes('x-www-form-urlencoded'))
40543
+ return true;
40544
+ if (value.includes('graphql'))
40545
+ return true;
40546
+ if (value.includes('event-stream'))
40547
+ return true;
40548
+ if (value.includes('+json') || value.includes('+xml'))
40549
+ return true;
40550
+ return false;
40551
+ }
40552
+ function encodeBase64(bytes) {
40553
+ if (BufferCtor$1) {
40554
+ return BufferCtor$1.from(bytes).toString('base64');
40252
40555
  }
40253
- else if (typeof maxMemoryPercent === 'number' && maxMemoryPercent > 0) {
40254
- const percent = Math.max(0, Math.min(maxMemoryPercent, 1));
40255
- resolvedBytes = Math.floor(effectiveTotal * percent);
40256
- derivedFromPercent = true;
40556
+ if (typeof btoa !== 'undefined') {
40557
+ let binary = '';
40558
+ const chunkSize = 0x8000;
40559
+ for (let i = 0; i < bytes.length; i += chunkSize) {
40560
+ const chunk = bytes.subarray(i, i + chunkSize);
40561
+ binary += String.fromCharCode(...chunk);
40562
+ }
40563
+ return btoa(binary);
40257
40564
  }
40258
- const safeTotalPercent = typeof safetyPercent === 'number' && safetyPercent > 0 && safetyPercent <= 1
40259
- ? safetyPercent
40260
- : DEFAULT_TOTAL_PERCENT;
40261
- const totalCap = Math.floor(effectiveTotal * safeTotalPercent);
40262
- if (resolvedBytes === 0 || totalCap < resolvedBytes) {
40263
- resolvedBytes = totalCap;
40264
- derivedFromPercent = derivedFromPercent || (maxMemoryPercent ?? 0) > 0;
40565
+ return null;
40566
+ }
40567
+ function decodeBase64(value) {
40568
+ if (BufferCtor$1) {
40569
+ return BufferCtor$1.from(value, 'base64');
40265
40570
  }
40266
- if (heapLimit > 0) {
40267
- const heapCap = Math.floor(heapLimit * DEFAULT_HEAP_PERCENT);
40268
- if (resolvedBytes === 0 || heapCap < resolvedBytes) {
40269
- resolvedBytes = heapCap;
40270
- derivedFromPercent = derivedFromPercent || (maxMemoryPercent ?? 0) > 0;
40571
+ if (typeof atob !== 'undefined') {
40572
+ const binary = atob(value);
40573
+ const bytes = new Uint8Array(binary.length);
40574
+ for (let i = 0; i < binary.length; i++) {
40575
+ bytes[i] = binary.charCodeAt(i);
40271
40576
  }
40577
+ return bytes;
40272
40578
  }
40273
- if (!Number.isFinite(resolvedBytes) || resolvedBytes <= 0) {
40274
- resolvedBytes = Math.floor(effectiveTotal * DEFAULT_TOTAL_PERCENT);
40275
- derivedFromPercent = true;
40276
- }
40277
- const inferredPercent = effectiveTotal > 0 ? resolvedBytes / effectiveTotal : null;
40278
- return {
40279
- maxMemoryBytes: resolvedBytes,
40280
- derivedFromPercent,
40281
- effectiveTotal,
40282
- heapLimit,
40283
- inferredPercent,
40284
- };
40579
+ return null;
40285
40580
  }
40286
- function formatBytes(bytes) {
40287
- if (bytes === 0)
40288
- return '0 B';
40289
- const k = 1024;
40290
- const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
40291
- const i = Math.floor(Math.log(bytes) / Math.log(k));
40292
- return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
40581
+ async function readResponseBody(response) {
40582
+ const contentType = response.headers.get('content-type');
40583
+ if (isTextContentType(contentType)) {
40584
+ return { body: await response.text(), bodyEncoding: 'utf8' };
40585
+ }
40586
+ const buffer = await response.arrayBuffer();
40587
+ const bytes = new Uint8Array(buffer);
40588
+ const encoded = encodeBase64(bytes);
40589
+ if (encoded === null)
40590
+ return null;
40591
+ return { body: encoded, bodyEncoding: 'base64' };
40293
40592
  }
40294
- function getHeapStats() {
40295
- const heapStats = v8.getHeapStatistics();
40296
- const { heapUsed } = process.memoryUsage();
40297
- const heapLimit = heapStats?.heap_size_limit ?? 0;
40298
- const heapRatio = heapLimit > 0 ? heapUsed / heapLimit : 0;
40299
- return {
40300
- heapUsed,
40301
- heapLimit,
40302
- heapRatio,
40303
- };
40593
+ class CacheResponse {
40594
+ raw;
40595
+ timings;
40596
+ constructor(raw, timings) {
40597
+ this.raw = raw;
40598
+ this.timings = timings;
40599
+ }
40600
+ get status() { return this.raw.status; }
40601
+ get statusText() { return this.raw.statusText; }
40602
+ get headers() { return this.raw.headers; }
40603
+ get ok() { return this.raw.ok; }
40604
+ get url() { return this.raw.url; }
40605
+ get connection() { return {}; }
40606
+ get cache() {
40607
+ return parseHeaders(this.headers, this.status).cache;
40608
+ }
40609
+ get rateLimit() {
40610
+ return parseHeaders(this.headers, this.status).rateLimit;
40611
+ }
40612
+ links() {
40613
+ return parseLinkHeader(this.headers);
40614
+ }
40615
+ get headerInfo() {
40616
+ return parseHeaders(this.headers, this.status);
40617
+ }
40618
+ json() {
40619
+ return this.raw.json();
40620
+ }
40621
+ text() {
40622
+ return this.raw.text();
40623
+ }
40624
+ async cleanText() {
40625
+ return cleanHtml(await this.text());
40626
+ }
40627
+ blob() {
40628
+ return this.raw.blob();
40629
+ }
40630
+ read() {
40631
+ return this.raw.body;
40632
+ }
40633
+ clone() {
40634
+ return new CacheResponse(this.raw.clone(), this.timings);
40635
+ }
40636
+ sse() {
40637
+ return parseSSE(this.raw);
40638
+ }
40639
+ async *download() {
40640
+ if (!this.raw.body)
40641
+ return;
40642
+ const reader = this.raw.body.getReader();
40643
+ let loaded = 0;
40644
+ const total = Number(this.raw.headers.get('content-length')) || undefined;
40645
+ while (true) {
40646
+ const { done, value } = await reader.read();
40647
+ if (done)
40648
+ break;
40649
+ loaded += value.length;
40650
+ yield {
40651
+ loaded,
40652
+ transferred: loaded,
40653
+ total,
40654
+ percent: total ? (loaded / total) * 100 : undefined,
40655
+ direction: 'download'
40656
+ };
40657
+ }
40658
+ }
40659
+ async *[Symbol.asyncIterator]() {
40660
+ if (!this.raw.body)
40661
+ return;
40662
+ const reader = this.raw.body.getReader();
40663
+ while (true) {
40664
+ const { done, value } = await reader.read();
40665
+ if (done)
40666
+ break;
40667
+ yield value;
40668
+ }
40669
+ }
40304
40670
  }
40305
-
40306
- let MemoryStorage$1 = class MemoryStorage {
40307
- storage = new Map();
40308
- meta = new Map();
40309
- maxSize;
40310
- maxMemoryBytes;
40311
- maxMemoryPercent;
40312
- defaultTtl;
40313
- evictionPolicy;
40314
- compressionEnabled;
40315
- compressionThreshold;
40316
- enableStats;
40317
- heapUsageThreshold;
40318
- onEvict;
40319
- onPressure;
40320
- currentMemoryBytes = 0;
40321
- evictedDueToMemory = 0;
40322
- memoryPressureEvents = 0;
40323
- accessCounter = 0;
40324
- monitorHandle = null;
40325
- cleanupHandle = null;
40326
- stats = {
40327
- hits: 0,
40328
- misses: 0,
40329
- sets: 0,
40330
- deletes: 0,
40331
- evictions: 0,
40332
- };
40333
- compressionStats = {
40334
- totalCompressed: 0,
40335
- totalOriginalSize: 0,
40336
- totalCompressedSize: 0,
40337
- };
40338
- constructor(options = {}) {
40339
- if (options.maxMemoryBytes &&
40340
- options.maxMemoryBytes > 0 &&
40341
- options.maxMemoryPercent &&
40342
- options.maxMemoryPercent > 0) {
40343
- throw new ConfigurationError('[MemoryStorage] Cannot use both maxMemoryBytes and maxMemoryPercent', { configKey: 'maxMemoryBytes|maxMemoryPercent' });
40671
+ function parseRequestCacheControl(header) {
40672
+ if (!header)
40673
+ return {};
40674
+ const result = {};
40675
+ const directives = header.toLowerCase().split(',').map(d => d.trim());
40676
+ for (const directive of directives) {
40677
+ if (directive.startsWith('max-age=')) {
40678
+ result.maxAge = parseInt(directive.slice(8), 10);
40344
40679
  }
40345
- if (options.maxMemoryPercent !== undefined &&
40346
- (options.maxMemoryPercent < 0 || options.maxMemoryPercent > 1)) {
40347
- throw new ConfigurationError('[MemoryStorage] maxMemoryPercent must be between 0 and 1', { configKey: 'maxMemoryPercent' });
40680
+ else if (directive.startsWith('min-fresh=')) {
40681
+ result.minFresh = parseInt(directive.slice(10), 10);
40348
40682
  }
40349
- this.maxSize = options.maxSize ?? 1000;
40350
- this.defaultTtl = options.ttl ?? 300000;
40351
- this.evictionPolicy = options.evictionPolicy ?? 'lru';
40352
- this.enableStats = options.enableStats ?? false;
40353
- this.heapUsageThreshold = options.heapUsageThreshold ?? 0.6;
40354
- if (options.maxMemoryBytes && options.maxMemoryBytes > 0) {
40355
- this.maxMemoryBytes = options.maxMemoryBytes;
40356
- this.maxMemoryPercent = 0;
40683
+ else if (directive.startsWith('max-stale')) {
40684
+ const equals = directive.indexOf('=');
40685
+ if (equals !== -1) {
40686
+ result.maxStale = parseInt(directive.slice(equals + 1), 10);
40687
+ }
40688
+ else {
40689
+ result.maxStale = Infinity;
40690
+ }
40357
40691
  }
40358
- else if (options.maxMemoryPercent && options.maxMemoryPercent > 0) {
40359
- const effectiveTotal = getEffectiveTotalMemoryBytes();
40360
- this.maxMemoryBytes = Math.floor(effectiveTotal * options.maxMemoryPercent);
40361
- this.maxMemoryPercent = options.maxMemoryPercent;
40692
+ else if (directive === 'only-if-cached') {
40693
+ result.onlyIfCached = true;
40362
40694
  }
40363
- else {
40364
- const resolved = resolveCacheMemoryLimit({});
40365
- this.maxMemoryBytes = resolved.maxMemoryBytes;
40366
- this.maxMemoryPercent = resolved.inferredPercent ?? 0;
40695
+ else if (directive === 'no-cache') {
40696
+ result.noCache = true;
40367
40697
  }
40368
- if (options.compression === true) {
40369
- this.compressionEnabled = true;
40370
- this.compressionThreshold = 1024;
40698
+ else if (directive === 'no-store') {
40699
+ result.noStore = true;
40371
40700
  }
40372
- else if (typeof options.compression === 'object' &&
40373
- options.compression.enabled) {
40374
- this.compressionEnabled = true;
40375
- this.compressionThreshold = options.compression.threshold ?? 1024;
40701
+ }
40702
+ return result;
40703
+ }
40704
+ function parseCacheControl(header) {
40705
+ if (!header)
40706
+ return {};
40707
+ const result = {};
40708
+ const directives = header.toLowerCase().split(',').map(d => d.trim());
40709
+ for (const directive of directives) {
40710
+ if (directive.startsWith('max-age=')) {
40711
+ result.maxAge = parseInt(directive.slice(8), 10);
40376
40712
  }
40377
- else {
40378
- this.compressionEnabled = false;
40379
- this.compressionThreshold = 1024;
40713
+ else if (directive.startsWith('s-maxage=')) {
40714
+ result.sMaxAge = parseInt(directive.slice(9), 10);
40380
40715
  }
40381
- this.onEvict = options.onEvict;
40382
- this.onPressure = options.onPressure;
40383
- const monitorInterval = options.monitorInterval ?? 15000;
40384
- if (monitorInterval > 0) {
40385
- this.monitorHandle = setInterval(() => this.memoryHealthCheck(), monitorInterval);
40386
- this.monitorHandle.unref();
40716
+ else if (directive.startsWith('stale-while-revalidate=')) {
40717
+ result.staleWhileRevalidate = parseInt(directive.slice(23), 10);
40387
40718
  }
40388
- const cleanupInterval = options.cleanupInterval ?? 60000;
40389
- if (cleanupInterval > 0) {
40390
- this.cleanupHandle = setInterval(() => this.cleanupExpired(), cleanupInterval);
40391
- this.cleanupHandle.unref();
40719
+ else if (directive.startsWith('stale-if-error=')) {
40720
+ result.staleIfError = parseInt(directive.slice(15), 10);
40392
40721
  }
40393
- }
40394
- async get(key) {
40395
- const data = this.storage.get(key);
40396
- const metadata = this.meta.get(key);
40397
- if (!data || !metadata) {
40398
- this.recordStat('misses');
40399
- return undefined;
40722
+ else if (directive === 'no-cache') {
40723
+ result.noCache = true;
40400
40724
  }
40401
- const now = Date.now();
40402
- if (now > metadata.expiresAt) {
40403
- this.deleteInternal(key);
40404
- this.recordStat('misses');
40405
- return undefined;
40725
+ else if (directive === 'no-store') {
40726
+ result.noStore = true;
40406
40727
  }
40407
- if (this.evictionPolicy === 'lru') {
40408
- metadata.lastAccess = now;
40409
- metadata.accessOrder = ++this.accessCounter;
40728
+ else if (directive === 'must-revalidate') {
40729
+ result.mustRevalidate = true;
40410
40730
  }
40411
- this.recordStat('hits');
40412
- if (this.isCompressed(data)) {
40413
- try {
40414
- const decompressed = this.decompress(data);
40415
- return JSON.parse(decompressed);
40416
- }
40417
- catch {
40418
- this.deleteInternal(key);
40419
- return undefined;
40420
- }
40731
+ else if (directive === 'private') {
40732
+ result.isPrivate = true;
40421
40733
  }
40422
- return JSON.parse(data);
40423
- }
40424
- async set(key, entry, ttl) {
40425
- const effectiveTtl = ttl ?? this.defaultTtl;
40426
- const now = Date.now();
40427
- const serialized = JSON.stringify(entry);
40428
- const originalSize = Buffer.byteLength(serialized, 'utf8');
40429
- let finalData = serialized;
40430
- let compressedSize = originalSize;
40431
- let compressed = false;
40432
- if (this.compressionEnabled && originalSize >= this.compressionThreshold) {
40433
- try {
40434
- const result = this.compress(serialized);
40435
- finalData = result;
40436
- compressedSize = Buffer.byteLength(result.__data, 'utf8');
40437
- compressed = true;
40438
- this.compressionStats.totalCompressed++;
40439
- this.compressionStats.totalOriginalSize += originalSize;
40440
- this.compressionStats.totalCompressedSize += compressedSize;
40441
- }
40442
- catch {
40443
- }
40444
- }
40445
- const existingMeta = this.meta.get(key);
40446
- if (existingMeta) {
40447
- this.currentMemoryBytes -= existingMeta.compressedSize;
40448
- }
40449
- if (!this.enforceMemoryLimit(compressedSize)) {
40450
- this.evictedDueToMemory++;
40451
- return;
40452
- }
40453
- if (!existingMeta && this.storage.size >= this.maxSize) {
40454
- this.evictOne('size');
40455
- }
40456
- this.storage.set(key, finalData);
40457
- this.meta.set(key, {
40458
- createdAt: now,
40459
- expiresAt: now + effectiveTtl,
40460
- lastAccess: now,
40461
- insertOrder: ++this.accessCounter,
40462
- accessOrder: this.accessCounter,
40463
- compressed,
40464
- originalSize,
40465
- compressedSize,
40466
- });
40467
- this.currentMemoryBytes += compressedSize;
40468
- this.recordStat('sets');
40469
- }
40470
- async delete(key) {
40471
- this.deleteInternal(key);
40472
- this.recordStat('deletes');
40473
- }
40474
- clear(prefix) {
40475
- if (!prefix) {
40476
- this.storage.clear();
40477
- this.meta.clear();
40478
- this.currentMemoryBytes = 0;
40479
- this.evictedDueToMemory = 0;
40480
- if (this.enableStats) {
40481
- this.stats = { hits: 0, misses: 0, sets: 0, deletes: 0, evictions: 0 };
40482
- }
40483
- return;
40484
- }
40485
- for (const key of this.storage.keys()) {
40486
- if (key.startsWith(prefix)) {
40487
- this.deleteInternal(key);
40488
- }
40489
- }
40490
- }
40491
- size() {
40492
- return this.storage.size;
40493
- }
40494
- keys() {
40495
- return Array.from(this.storage.keys());
40496
- }
40497
- has(key) {
40498
- const meta = this.meta.get(key);
40499
- if (!meta)
40500
- return false;
40501
- if (Date.now() > meta.expiresAt) {
40502
- this.deleteInternal(key);
40503
- return false;
40504
- }
40505
- return true;
40506
- }
40507
- getStats() {
40508
- const total = this.stats.hits + this.stats.misses;
40509
- const hitRate = total > 0 ? this.stats.hits / total : 0;
40510
- return {
40511
- enabled: this.enableStats,
40512
- ...this.stats,
40513
- hitRate,
40514
- totalItems: this.storage.size,
40515
- memoryUsageBytes: this.currentMemoryBytes,
40516
- maxMemoryBytes: this.maxMemoryBytes,
40517
- evictedDueToMemory: this.evictedDueToMemory,
40518
- };
40519
- }
40520
- getMemoryStats() {
40521
- const totalItems = this.storage.size;
40522
- const memoryUsagePercent = this.maxMemoryBytes > 0
40523
- ? (this.currentMemoryBytes / this.maxMemoryBytes) * 100
40524
- : 0;
40525
- const systemTotal = os.totalmem();
40526
- const systemFree = os.freemem();
40527
- const systemUsed = systemTotal - systemFree;
40528
- const cachePercentOfSystem = systemTotal > 0 ? (this.currentMemoryBytes / systemTotal) * 100 : 0;
40529
- return {
40530
- currentMemoryBytes: this.currentMemoryBytes,
40531
- maxMemoryBytes: this.maxMemoryBytes,
40532
- maxMemoryPercent: this.maxMemoryPercent,
40533
- memoryUsagePercent: parseFloat(memoryUsagePercent.toFixed(2)),
40534
- cachePercentOfSystemMemory: parseFloat(cachePercentOfSystem.toFixed(2)),
40535
- totalItems,
40536
- maxSize: this.maxSize,
40537
- evictedDueToMemory: this.evictedDueToMemory,
40538
- memoryPressureEvents: this.memoryPressureEvents,
40539
- averageItemSize: totalItems > 0 ? Math.round(this.currentMemoryBytes / totalItems) : 0,
40540
- memoryUsage: {
40541
- current: formatBytes(this.currentMemoryBytes),
40542
- max: formatBytes(this.maxMemoryBytes),
40543
- available: formatBytes(Math.max(0, this.maxMemoryBytes - this.currentMemoryBytes)),
40544
- },
40545
- systemMemory: {
40546
- total: formatBytes(systemTotal),
40547
- free: formatBytes(systemFree),
40548
- used: formatBytes(systemUsed),
40549
- cachePercent: `${cachePercentOfSystem.toFixed(2)}%`,
40550
- },
40551
- };
40552
- }
40553
- getCompressionStats() {
40554
- if (!this.compressionEnabled) {
40555
- return {
40556
- enabled: false,
40557
- totalItems: this.storage.size,
40558
- compressedItems: 0,
40559
- compressionThreshold: this.compressionThreshold,
40560
- totalOriginalSize: 0,
40561
- totalCompressedSize: 0,
40562
- averageCompressionRatio: '0',
40563
- spaceSavingsPercent: '0',
40564
- memoryUsage: {
40565
- uncompressed: '0 B',
40566
- compressed: '0 B',
40567
- saved: '0 B',
40568
- },
40569
- };
40570
- }
40571
- const ratio = this.compressionStats.totalOriginalSize > 0
40572
- ? (this.compressionStats.totalCompressedSize /
40573
- this.compressionStats.totalOriginalSize).toFixed(2)
40574
- : '0';
40575
- const savings = this.compressionStats.totalOriginalSize > 0
40576
- ? (((this.compressionStats.totalOriginalSize -
40577
- this.compressionStats.totalCompressedSize) /
40578
- this.compressionStats.totalOriginalSize) *
40579
- 100).toFixed(2)
40580
- : '0';
40581
- const saved = this.compressionStats.totalOriginalSize -
40582
- this.compressionStats.totalCompressedSize;
40583
- return {
40584
- enabled: true,
40585
- totalItems: this.storage.size,
40586
- compressedItems: this.compressionStats.totalCompressed,
40587
- compressionThreshold: this.compressionThreshold,
40588
- totalOriginalSize: this.compressionStats.totalOriginalSize,
40589
- totalCompressedSize: this.compressionStats.totalCompressedSize,
40590
- averageCompressionRatio: ratio,
40591
- spaceSavingsPercent: savings,
40592
- memoryUsage: {
40593
- uncompressed: formatBytes(this.compressionStats.totalOriginalSize),
40594
- compressed: formatBytes(this.compressionStats.totalCompressedSize),
40595
- saved: formatBytes(saved),
40596
- },
40597
- };
40598
- }
40599
- shutdown() {
40600
- if (this.monitorHandle) {
40601
- clearInterval(this.monitorHandle);
40602
- this.monitorHandle = null;
40603
- }
40604
- if (this.cleanupHandle) {
40605
- clearInterval(this.cleanupHandle);
40606
- this.cleanupHandle = null;
40607
- }
40608
- }
40609
- deleteInternal(key) {
40610
- const meta = this.meta.get(key);
40611
- if (meta) {
40612
- this.currentMemoryBytes -= meta.compressedSize;
40613
- }
40614
- this.storage.delete(key);
40615
- this.meta.delete(key);
40616
- }
40617
- recordStat(type) {
40618
- if (this.enableStats) {
40619
- this.stats[type]++;
40620
- }
40621
- }
40622
- isCompressed(data) {
40623
- return (typeof data === 'object' && data !== null && '__compressed' in data);
40624
- }
40625
- compress(data) {
40626
- const buffer = Buffer.from(data, 'utf8');
40627
- const compressed = require$$3.gzipSync(buffer);
40628
- return {
40629
- __compressed: true,
40630
- __data: compressed.toString('base64'),
40631
- __originalSize: buffer.length,
40632
- };
40633
- }
40634
- decompress(data) {
40635
- const buffer = Buffer.from(data.__data, 'base64');
40636
- const decompressed = require$$3.gunzipSync(buffer);
40637
- return decompressed.toString('utf8');
40638
- }
40639
- selectEvictionCandidate() {
40640
- if (this.meta.size === 0)
40641
- return null;
40642
- let candidate = null;
40643
- let candidateValue = this.evictionPolicy === 'lru' ? Infinity : Infinity;
40644
- for (const [key, meta] of this.meta) {
40645
- const value = this.evictionPolicy === 'lru' ? meta.accessOrder : meta.insertOrder;
40646
- if (value < candidateValue) {
40647
- candidateValue = value;
40648
- candidate = key;
40649
- }
40650
- }
40651
- return candidate;
40652
- }
40653
- evictOne(reason) {
40654
- const candidate = this.selectEvictionCandidate();
40655
- if (!candidate)
40656
- return null;
40657
- const meta = this.meta.get(candidate);
40658
- const freedBytes = meta?.compressedSize ?? 0;
40659
- this.deleteInternal(candidate);
40660
- this.stats.evictions++;
40661
- if (reason === 'memory' || reason === 'heap') {
40662
- this.evictedDueToMemory++;
40663
- }
40664
- this.onEvict?.({
40665
- reason,
40666
- key: candidate,
40667
- freedBytes,
40668
- currentBytes: this.currentMemoryBytes,
40669
- maxMemoryBytes: this.maxMemoryBytes,
40670
- });
40671
- return { key: candidate, freedBytes };
40672
- }
40673
- enforceMemoryLimit(incomingSize) {
40674
- if (incomingSize > this.maxMemoryBytes) {
40675
- return false;
40676
- }
40677
- while (this.currentMemoryBytes + incomingSize > this.maxMemoryBytes &&
40678
- this.storage.size > 0) {
40679
- const result = this.evictOne('memory');
40680
- if (!result)
40681
- break;
40682
- }
40683
- return this.currentMemoryBytes + incomingSize <= this.maxMemoryBytes;
40684
- }
40685
- reduceMemoryTo(targetBytes) {
40686
- targetBytes = Math.max(0, targetBytes);
40687
- let freedBytes = 0;
40688
- while (this.currentMemoryBytes > targetBytes && this.storage.size > 0) {
40689
- const result = this.evictOne('memory');
40690
- if (!result)
40691
- break;
40692
- freedBytes += result.freedBytes;
40693
- }
40694
- return freedBytes;
40695
- }
40696
- memoryHealthCheck() {
40697
- let totalFreed = 0;
40698
- if (this.currentMemoryBytes > this.maxMemoryBytes) {
40699
- const before = this.currentMemoryBytes;
40700
- this.enforceMemoryLimit(0);
40701
- const freed = before - this.currentMemoryBytes;
40702
- if (freed > 0) {
40703
- totalFreed += freed;
40704
- this.memoryPressureEvents++;
40705
- this.onPressure?.({
40706
- reason: 'limit',
40707
- heapLimit: getHeapStats().heapLimit,
40708
- heapUsed: getHeapStats().heapUsed,
40709
- currentBytes: this.currentMemoryBytes,
40710
- maxMemoryBytes: this.maxMemoryBytes,
40711
- freedBytes: freed,
40712
- });
40713
- }
40714
- }
40715
- const { heapUsed, heapLimit, heapRatio } = getHeapStats();
40716
- if (heapLimit > 0 && heapRatio >= this.heapUsageThreshold) {
40717
- const before = this.currentMemoryBytes;
40718
- const target = Math.floor(this.currentMemoryBytes * 0.5);
40719
- this.reduceMemoryTo(target);
40720
- const freed = before - this.currentMemoryBytes;
40721
- if (freed > 0) {
40722
- totalFreed += freed;
40723
- this.memoryPressureEvents++;
40724
- this.onPressure?.({
40725
- reason: 'heap',
40726
- heapLimit,
40727
- heapUsed,
40728
- heapRatio,
40729
- currentBytes: this.currentMemoryBytes,
40730
- maxMemoryBytes: this.maxMemoryBytes,
40731
- freedBytes: freed,
40732
- });
40733
- }
40734
- }
40735
- return totalFreed;
40736
- }
40737
- cleanupExpired() {
40738
- const now = Date.now();
40739
- let cleaned = 0;
40740
- for (const [key, meta] of this.meta) {
40741
- if (now > meta.expiresAt) {
40742
- this.deleteInternal(key);
40743
- cleaned++;
40744
- this.onEvict?.({
40745
- reason: 'expired',
40746
- key,
40747
- freedBytes: meta.compressedSize,
40748
- currentBytes: this.currentMemoryBytes,
40749
- maxMemoryBytes: this.maxMemoryBytes,
40750
- });
40751
- }
40752
- }
40753
- return cleaned;
40754
- }
40755
- };
40756
-
40757
- function parseRequestCacheControl(header) {
40758
- if (!header)
40759
- return {};
40760
- const result = {};
40761
- const directives = header.toLowerCase().split(',').map(d => d.trim());
40762
- for (const directive of directives) {
40763
- if (directive.startsWith('max-age=')) {
40764
- result.maxAge = parseInt(directive.slice(8), 10);
40765
- }
40766
- else if (directive.startsWith('min-fresh=')) {
40767
- result.minFresh = parseInt(directive.slice(10), 10);
40768
- }
40769
- else if (directive.startsWith('max-stale')) {
40770
- const equals = directive.indexOf('=');
40771
- if (equals !== -1) {
40772
- result.maxStale = parseInt(directive.slice(equals + 1), 10);
40773
- }
40774
- else {
40775
- result.maxStale = Infinity;
40776
- }
40777
- }
40778
- else if (directive === 'only-if-cached') {
40779
- result.onlyIfCached = true;
40780
- }
40781
- else if (directive === 'no-cache') {
40782
- result.noCache = true;
40783
- }
40784
- else if (directive === 'no-store') {
40785
- result.noStore = true;
40786
- }
40787
- }
40788
- return result;
40789
- }
40790
- function parseCacheControl(header) {
40791
- if (!header)
40792
- return {};
40793
- const result = {};
40794
- const directives = header.toLowerCase().split(',').map(d => d.trim());
40795
- for (const directive of directives) {
40796
- if (directive.startsWith('max-age=')) {
40797
- result.maxAge = parseInt(directive.slice(8), 10);
40798
- }
40799
- else if (directive.startsWith('s-maxage=')) {
40800
- result.sMaxAge = parseInt(directive.slice(9), 10);
40801
- }
40802
- else if (directive.startsWith('stale-while-revalidate=')) {
40803
- result.staleWhileRevalidate = parseInt(directive.slice(23), 10);
40804
- }
40805
- else if (directive.startsWith('stale-if-error=')) {
40806
- result.staleIfError = parseInt(directive.slice(15), 10);
40807
- }
40808
- else if (directive === 'no-cache') {
40809
- result.noCache = true;
40810
- }
40811
- else if (directive === 'no-store') {
40812
- result.noStore = true;
40813
- }
40814
- else if (directive === 'must-revalidate') {
40815
- result.mustRevalidate = true;
40816
- }
40817
- else if (directive === 'private') {
40818
- result.isPrivate = true;
40819
- }
40820
- else if (directive === 'public') {
40821
- result.isPublic = true;
40734
+ else if (directive === 'public') {
40735
+ result.isPublic = true;
40822
40736
  }
40823
40737
  }
40824
40738
  return result;
@@ -40918,7 +40832,7 @@ async function storeCacheEntry(storage, baseKey, req, entry, ttl, keyGenerator)
40918
40832
  await storage.set(baseKey, entry, ttl);
40919
40833
  }
40920
40834
  }
40921
- async function createCacheEntry(response, body, now) {
40835
+ async function createCacheEntry(response, cachedBody, now) {
40922
40836
  const headers = {};
40923
40837
  response.headers.forEach((v, k) => { headers[k] = v; });
40924
40838
  const cacheControl = parseCacheControl(response.headers.get('Cache-Control'));
@@ -40934,7 +40848,8 @@ async function createCacheEntry(response, body, now) {
40934
40848
  status: response.status,
40935
40849
  statusText: response.statusText,
40936
40850
  headers,
40937
- body,
40851
+ body: cachedBody.body,
40852
+ bodyEncoding: cachedBody.bodyEncoding,
40938
40853
  timestamp: now,
40939
40854
  etag: response.headers.get('ETag') || undefined,
40940
40855
  lastModified: response.headers.get('Last-Modified') || undefined,
@@ -40958,16 +40873,18 @@ function createCachedResponse(entry, cacheStatus) {
40958
40873
  headers.set('Warning', `${warningCode} - "${warningText}"`);
40959
40874
  }
40960
40875
  }
40961
- const response = new Response(entry.body, {
40876
+ const responseBody = entry.bodyEncoding === 'base64'
40877
+ ? decodeBase64(entry.body) ?? entry.body
40878
+ : entry.body;
40879
+ const response = new Response(responseBody, {
40962
40880
  status: entry.status,
40963
40881
  statusText: entry.statusText,
40964
40882
  headers
40965
40883
  });
40966
- const httpResponse = new HttpResponse(response);
40967
- return httpResponse;
40884
+ return new CacheResponse(response);
40968
40885
  }
40969
40886
  function cachePlugin(options = {}) {
40970
- const storage = options.storage || new MemoryStorage$1();
40887
+ const storage = options.storage || createDefaultStorage();
40971
40888
  const strategy = options.strategy || 'cache-first';
40972
40889
  const ttl = options.ttl || 60 * 1000;
40973
40890
  const methods = options.methods || ['GET'];
@@ -40977,12 +40894,9 @@ function cachePlugin(options = {}) {
40977
40894
  let key = `${req.method}:${req.url}`;
40978
40895
  if (req.method !== 'GET' && req.method !== 'HEAD' && req.body) {
40979
40896
  try {
40980
- const bodyStr = typeof req.body === 'string'
40981
- ? req.body
40982
- : (req.body instanceof Buffer ? req.body.toString() : JSON.stringify(req.body));
40983
- if (bodyStr) {
40984
- const hash = require$$2$2.createHash('sha256').update(bodyStr).digest('hex').substring(0, 16);
40985
- key += `:${hash}`;
40897
+ const bytes = toBytes$1(req.body);
40898
+ if (bytes && bytes.length > 0) {
40899
+ key += `:${hashBytes(bytes)}`;
40986
40900
  }
40987
40901
  }
40988
40902
  catch {
@@ -41061,7 +40975,7 @@ function cachePlugin(options = {}) {
41061
40975
  status: 504,
41062
40976
  statusText: 'Gateway Timeout'
41063
40977
  });
41064
- return new HttpResponse(response);
40978
+ return new CacheResponse(response);
41065
40979
  }
41066
40980
  const satisfaction = satisfiesRequestDirectives(cachedEntry, now, reqCacheControl);
41067
40981
  if (!satisfaction.allowed) {
@@ -41069,7 +40983,7 @@ function cachePlugin(options = {}) {
41069
40983
  status: 504,
41070
40984
  statusText: 'Gateway Timeout'
41071
40985
  });
41072
- return new HttpResponse(response);
40986
+ return new CacheResponse(response);
41073
40987
  }
41074
40988
  return createCachedResponse(cachedEntry, isFresh(cachedEntry, now) ? 'hit' : 'stale');
41075
40989
  }
@@ -41086,8 +41000,11 @@ function cachePlugin(options = {}) {
41086
41000
  const cacheControl = parseCacheControl(response.headers.get('Cache-Control'));
41087
41001
  if (!cacheControl.noStore) {
41088
41002
  const clonedResponse = response.raw.clone();
41089
- const body = await clonedResponse.text();
41090
- const entry = await createCacheEntry(response, body, now);
41003
+ const cachedBody = await readResponseBody(clonedResponse);
41004
+ if (!cachedBody) {
41005
+ return response;
41006
+ }
41007
+ const entry = await createCacheEntry(response, cachedBody, now);
41091
41008
  const entryTtl = (entry.sMaxAge ?? entry.maxAge ?? ttl / 1000) * 1000;
41092
41009
  await storeCacheEntry(storage, baseKey, req, entry, entryTtl, generateKey);
41093
41010
  }
@@ -41129,8 +41046,11 @@ function cachePlugin(options = {}) {
41129
41046
  const cacheControl = parseCacheControl(response.headers.get('Cache-Control'));
41130
41047
  if (!cacheControl.noStore) {
41131
41048
  const clonedResponse = response.raw.clone();
41132
- const body = await clonedResponse.text();
41133
- const entry = await createCacheEntry(response, body, now);
41049
+ const cachedBody = await readResponseBody(clonedResponse);
41050
+ if (!cachedBody) {
41051
+ return response;
41052
+ }
41053
+ const entry = await createCacheEntry(response, cachedBody, now);
41134
41054
  const freshnessTtl = (entry.sMaxAge ?? entry.maxAge ?? ttl / 1000) * 1000;
41135
41055
  const storageTtl = Math.max(freshnessTtl, ttl);
41136
41056
  await storeCacheEntry(storage, baseKey, req, entry, storageTtl, generateKey);
@@ -41150,8 +41070,11 @@ function cachePlugin(options = {}) {
41150
41070
  const cacheControl = parseCacheControl(response.headers.get('Cache-Control'));
41151
41071
  if (!cacheControl.noStore) {
41152
41072
  const clonedResponse = response.raw.clone();
41153
- const body = await clonedResponse.text();
41154
- const entry = await createCacheEntry(response, body, now);
41073
+ const cachedBody = await readResponseBody(clonedResponse);
41074
+ if (!cachedBody) {
41075
+ return response;
41076
+ }
41077
+ const entry = await createCacheEntry(response, cachedBody, now);
41155
41078
  const freshnessTtl = (entry.sMaxAge ?? entry.maxAge ?? ttl / 1000) * 1000;
41156
41079
  const storageTtl = Math.max(freshnessTtl, ttl);
41157
41080
  await storeCacheEntry(storage, baseKey, req, entry, storageTtl, generateKey);
@@ -41166,8 +41089,11 @@ function cachePlugin(options = {}) {
41166
41089
  const response = await next(req);
41167
41090
  if (response.ok) {
41168
41091
  const clonedResponse = response.raw.clone();
41169
- const body = await clonedResponse.text();
41170
- const entry = await createCacheEntry(response, body, now);
41092
+ const cachedBody = await readResponseBody(clonedResponse);
41093
+ if (!cachedBody) {
41094
+ return response;
41095
+ }
41096
+ const entry = await createCacheEntry(response, cachedBody, now);
41171
41097
  await storeCacheEntry(storage, baseKey, req, entry, ttl, generateKey);
41172
41098
  }
41173
41099
  return response;
@@ -41188,8 +41114,11 @@ function cachePlugin(options = {}) {
41188
41114
  }
41189
41115
  else if (freshResponse.ok) {
41190
41116
  const clonedResponse = freshResponse.raw.clone();
41191
- const body = await clonedResponse.text();
41192
- const entry = await createCacheEntry(freshResponse, body, Date.now());
41117
+ const cachedBody = await readResponseBody(clonedResponse);
41118
+ if (!cachedBody) {
41119
+ return;
41120
+ }
41121
+ const entry = await createCacheEntry(freshResponse, cachedBody, Date.now());
41193
41122
  const freshnessTtl = (entry.sMaxAge ?? entry.maxAge ?? ttl / 1000) * 1000;
41194
41123
  const storageTtl = Math.max(freshnessTtl, ttl);
41195
41124
  await storeCacheEntry(storage, baseKey, req, entry, storageTtl, generateKey);
@@ -41203,8 +41132,11 @@ function cachePlugin(options = {}) {
41203
41132
  const response = await next(req);
41204
41133
  if (response.ok) {
41205
41134
  const clonedResponse = response.raw.clone();
41206
- const body = await clonedResponse.text();
41207
- const entry = await createCacheEntry(response, body, now);
41135
+ const cachedBody = await readResponseBody(clonedResponse);
41136
+ if (!cachedBody) {
41137
+ return response;
41138
+ }
41139
+ const entry = await createCacheEntry(response, cachedBody, now);
41208
41140
  await storeCacheEntry(storage, baseKey, req, entry, ttl, generateKey);
41209
41141
  }
41210
41142
  return response;
@@ -41214,8 +41146,11 @@ function cachePlugin(options = {}) {
41214
41146
  const response = await next(req);
41215
41147
  if (response.ok) {
41216
41148
  const clonedResponse = response.raw.clone();
41217
- const body = await clonedResponse.text();
41218
- const entry = await createCacheEntry(response, body, now);
41149
+ const cachedBody = await readResponseBody(clonedResponse);
41150
+ if (!cachedBody) {
41151
+ return response;
41152
+ }
41153
+ const entry = await createCacheEntry(response, cachedBody, now);
41219
41154
  const freshnessTtl = (entry.sMaxAge ?? entry.maxAge ?? ttl / 1000) * 1000;
41220
41155
  const storageTtl = Math.max(freshnessTtl, ttl);
41221
41156
  await storeCacheEntry(storage, baseKey, req, entry, storageTtl, generateKey);
@@ -41320,9 +41255,31 @@ function createXSRFMiddleware(config) {
41320
41255
  return xsrfPlugin(config);
41321
41256
  }
41322
41257
 
41323
- const gzipAsync = require$$0$2.promisify(require$$3.gzip);
41324
- const deflateAsync = require$$0$2.promisify(require$$3.deflate);
41325
- const brotliAsync = require$$0$2.promisify(require$$3.brotliCompress);
41258
+ const textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;
41259
+ const BufferCtor = globalThis.Buffer;
41260
+ function isNodeRuntime$3() {
41261
+ return typeof globalThis !== 'undefined' && Boolean(globalThis.process?.versions?.node);
41262
+ }
41263
+ let nodeCompressorsPromise = null;
41264
+ async function loadNodeCompressors() {
41265
+ if (!nodeCompressorsPromise) {
41266
+ nodeCompressorsPromise = (async () => {
41267
+ const zlibModuleName = 'node:zlib';
41268
+ const utilModuleName = 'node:util';
41269
+ const zlibModule = await import(zlibModuleName);
41270
+ const utilModule = await import(utilModuleName);
41271
+ const gzipAsync = utilModule.promisify(zlibModule.gzip);
41272
+ const deflateAsync = utilModule.promisify(zlibModule.deflate);
41273
+ const brotliAsync = utilModule.promisify(zlibModule.brotliCompress);
41274
+ return {
41275
+ gzip: async (input) => gzipAsync(BufferCtor ? BufferCtor.from(input) : input),
41276
+ deflate: async (input) => deflateAsync(BufferCtor ? BufferCtor.from(input) : input),
41277
+ brotli: async (input) => brotliAsync(BufferCtor ? BufferCtor.from(input) : input)
41278
+ };
41279
+ })();
41280
+ }
41281
+ return nodeCompressorsPromise;
41282
+ }
41326
41283
  function isCompressible(contentType) {
41327
41284
  if (!contentType)
41328
41285
  return true;
@@ -41339,20 +41296,29 @@ function getBodySize(body) {
41339
41296
  if (!body)
41340
41297
  return 0;
41341
41298
  if (typeof body === 'string') {
41342
- return Buffer.byteLength(body, 'utf8');
41343
- }
41344
- if (body instanceof Buffer) {
41299
+ if (textEncoder)
41300
+ return textEncoder.encode(body).length;
41301
+ if (BufferCtor)
41302
+ return BufferCtor.from(body, 'utf8').length;
41345
41303
  return body.length;
41346
41304
  }
41347
41305
  if (body instanceof ArrayBuffer) {
41348
41306
  return body.byteLength;
41349
41307
  }
41350
- if (body instanceof Blob) {
41308
+ if (ArrayBuffer.isView(body)) {
41309
+ return body.byteLength;
41310
+ }
41311
+ if (typeof Blob !== 'undefined' && body instanceof Blob) {
41351
41312
  return body.size;
41352
41313
  }
41353
41314
  if (typeof body === 'object') {
41354
41315
  try {
41355
- return Buffer.byteLength(JSON.stringify(body), 'utf8');
41316
+ const json = JSON.stringify(body);
41317
+ if (textEncoder)
41318
+ return textEncoder.encode(json).length;
41319
+ if (BufferCtor)
41320
+ return BufferCtor.from(json, 'utf8').length;
41321
+ return json.length;
41356
41322
  }
41357
41323
  catch {
41358
41324
  return 0;
@@ -41360,21 +41326,41 @@ function getBodySize(body) {
41360
41326
  }
41361
41327
  return 0;
41362
41328
  }
41363
- function toBuffer(body) {
41329
+ function toBytes(body) {
41364
41330
  if (!body)
41365
41331
  return null;
41366
- if (Buffer.isBuffer(body)) {
41367
- return body;
41368
- }
41369
41332
  if (typeof body === 'string') {
41370
- return Buffer.from(body, 'utf8');
41333
+ if (textEncoder)
41334
+ return textEncoder.encode(body);
41335
+ if (BufferCtor)
41336
+ return BufferCtor.from(body, 'utf8');
41337
+ return null;
41338
+ }
41339
+ if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) {
41340
+ const encoded = body.toString();
41341
+ if (textEncoder)
41342
+ return textEncoder.encode(encoded);
41343
+ if (BufferCtor)
41344
+ return BufferCtor.from(encoded, 'utf8');
41345
+ return null;
41371
41346
  }
41372
41347
  if (body instanceof ArrayBuffer) {
41373
- return Buffer.from(body);
41348
+ return new Uint8Array(body);
41349
+ }
41350
+ if (ArrayBuffer.isView(body)) {
41351
+ return new Uint8Array(body.buffer, body.byteOffset, body.byteLength);
41352
+ }
41353
+ if (typeof Blob !== 'undefined' && body instanceof Blob) {
41354
+ return null;
41374
41355
  }
41375
41356
  if (typeof body === 'object') {
41376
41357
  try {
41377
- return Buffer.from(JSON.stringify(body), 'utf8');
41358
+ const json = JSON.stringify(body);
41359
+ if (textEncoder)
41360
+ return textEncoder.encode(json);
41361
+ if (BufferCtor)
41362
+ return BufferCtor.from(json, 'utf8');
41363
+ return null;
41378
41364
  }
41379
41365
  catch {
41380
41366
  return null;
@@ -41383,18 +41369,32 @@ function toBuffer(body) {
41383
41369
  return null;
41384
41370
  }
41385
41371
  async function compress(data, algorithm) {
41386
- switch (algorithm) {
41387
- case 'gzip':
41388
- return await gzipAsync(data);
41389
- case 'deflate':
41390
- return await deflateAsync(data);
41391
- case 'br':
41392
- return await brotliAsync(data);
41393
- default:
41394
- throw new UnsupportedError(`Unsupported compression algorithm: ${algorithm}`, {
41395
- feature: algorithm,
41396
- });
41397
- }
41372
+ if (isNodeRuntime$3()) {
41373
+ const compressors = await loadNodeCompressors();
41374
+ switch (algorithm) {
41375
+ case 'gzip':
41376
+ return compressors.gzip(data);
41377
+ case 'deflate':
41378
+ return compressors.deflate(data);
41379
+ case 'br':
41380
+ return compressors.brotli(data);
41381
+ }
41382
+ }
41383
+ if (typeof CompressionStream !== 'undefined') {
41384
+ if (algorithm === 'br') {
41385
+ throw new UnsupportedError('Brotli compression is not available in browser environments.', { feature: algorithm });
41386
+ }
41387
+ const stream = new CompressionStream(algorithm);
41388
+ const writer = stream.writable.getWriter();
41389
+ const payload = data.buffer instanceof ArrayBuffer ? data : new Uint8Array(data);
41390
+ await writer.write(payload);
41391
+ await writer.close();
41392
+ const buffer = await new Response(stream.readable).arrayBuffer();
41393
+ return new Uint8Array(buffer);
41394
+ }
41395
+ throw new UnsupportedError(`Unsupported compression algorithm: ${algorithm}`, {
41396
+ feature: algorithm,
41397
+ });
41398
41398
  }
41399
41399
  function compression(options = {}) {
41400
41400
  const { algorithm = 'gzip', threshold = 1024, force = false, methods = ['POST', 'PUT', 'PATCH'] } = options;
@@ -41414,13 +41414,13 @@ function compression(options = {}) {
41414
41414
  if (!force && bodySize < threshold) {
41415
41415
  return next(req);
41416
41416
  }
41417
- const buffer = toBuffer(req.body);
41418
- if (!buffer) {
41417
+ const bytes = toBytes(req.body);
41418
+ if (!bytes) {
41419
41419
  return next(req);
41420
41420
  }
41421
41421
  try {
41422
- const compressed = await compress(buffer, algorithm);
41423
- if (!force && compressed.length >= buffer.length) {
41422
+ const compressed = await compress(bytes, algorithm);
41423
+ if (!force && compressed.length >= bytes.length) {
41424
41424
  return next(req);
41425
41425
  }
41426
41426
  const newHeaders = new Headers(req.headers);
@@ -41499,7 +41499,7 @@ function encodeXMLEntities(str) {
41499
41499
  .replace(/'/g, '&apos;');
41500
41500
  }
41501
41501
 
41502
- class SimpleEmitter {
41502
+ let SimpleEmitter$1 = class SimpleEmitter {
41503
41503
  listeners = new Map();
41504
41504
  on(event, listener) {
41505
41505
  const set = this.listeners.get(event) ?? new Set();
@@ -41536,27 +41536,35 @@ class SimpleEmitter {
41536
41536
  }
41537
41537
  return true;
41538
41538
  }
41539
- }
41540
- class RequestRunner extends SimpleEmitter {
41539
+ };
41540
+ class RequestRunner extends SimpleEmitter$1 {
41541
41541
  concurrency;
41542
+ retries;
41543
+ retryDelay;
41542
41544
  queue = [];
41543
41545
  activeCount = 0;
41544
41546
  paused = false;
41545
41547
  results = new Map();
41546
41548
  stats = { total: 0, successful: 0, failed: 0 };
41547
41549
  startTime = 0;
41550
+ pendingRetries = 0;
41548
41551
  constructor(options = {}) {
41549
41552
  super();
41550
41553
  this.concurrency = options.concurrency || 5;
41554
+ this.retries = options.retries ?? 0;
41555
+ this.retryDelay = options.retryDelay ?? 0;
41551
41556
  }
41552
41557
  add(fn, options = {}) {
41553
- this.queue.push({
41558
+ this.queueTask({
41554
41559
  id: options.id || Math.random().toString(36).slice(2),
41555
41560
  fn,
41556
41561
  priority: options.priority || 0,
41562
+ retries: options.retries ?? this.retries,
41563
+ resolve: options.resolve,
41557
41564
  });
41558
- this.queue.sort((a, b) => b.priority - a.priority);
41559
- this.stats.total++;
41565
+ if (options.trackTotal !== false) {
41566
+ this.stats.total++;
41567
+ }
41560
41568
  this.processNext();
41561
41569
  }
41562
41570
  async run(items, processor, options = {}) {
@@ -41565,17 +41573,13 @@ class RequestRunner extends SimpleEmitter {
41565
41573
  this.results.clear();
41566
41574
  const promises = items.map((item, index) => {
41567
41575
  return new Promise((resolve) => {
41568
- this.add(async () => {
41569
- try {
41570
- const res = await processor(item, index);
41571
- resolve(res);
41572
- return res;
41573
- }
41574
- catch (err) {
41575
- resolve(err);
41576
- throw err;
41577
- }
41578
- }, { priority: options.priority, id: String(index) });
41576
+ this.add(() => processor(item, index), {
41577
+ priority: options.priority,
41578
+ id: String(index),
41579
+ retries: options.retries,
41580
+ resolve,
41581
+ trackTotal: false
41582
+ });
41579
41583
  });
41580
41584
  });
41581
41585
  const results = await Promise.all(promises);
@@ -41587,6 +41591,24 @@ class RequestRunner extends SimpleEmitter {
41587
41591
  }
41588
41592
  };
41589
41593
  }
41594
+ queueTask(task) {
41595
+ this.queue.push(task);
41596
+ this.queue.sort((a, b) => b.priority - a.priority);
41597
+ }
41598
+ scheduleRetry(task, delay) {
41599
+ this.pendingRetries++;
41600
+ if (delay > 0) {
41601
+ setTimeout(() => {
41602
+ this.pendingRetries--;
41603
+ this.queueTask(task);
41604
+ this.processNext();
41605
+ }, delay);
41606
+ return;
41607
+ }
41608
+ this.pendingRetries--;
41609
+ this.queueTask(task);
41610
+ this.processNext();
41611
+ }
41590
41612
  async processNext() {
41591
41613
  if (this.paused || this.activeCount >= this.concurrency || this.queue.length === 0) {
41592
41614
  return;
@@ -41599,16 +41621,26 @@ class RequestRunner extends SimpleEmitter {
41599
41621
  try {
41600
41622
  const result = await task.fn();
41601
41623
  this.stats.successful++;
41624
+ task.resolve?.(result);
41602
41625
  this.emit('taskComplete', { task, result });
41603
41626
  }
41604
41627
  catch (error) {
41605
- this.stats.failed++;
41606
- this.emit('taskError', { task, error });
41628
+ const remaining = task.retries ?? 0;
41629
+ if (remaining > 0) {
41630
+ task.retries = remaining - 1;
41631
+ this.emit('taskRetry', { task, error, remaining: task.retries, delay: this.retryDelay });
41632
+ this.scheduleRetry(task, this.retryDelay);
41633
+ }
41634
+ else {
41635
+ this.stats.failed++;
41636
+ task.resolve?.(error);
41637
+ this.emit('taskError', { task, error });
41638
+ }
41607
41639
  }
41608
41640
  finally {
41609
41641
  this.activeCount--;
41610
41642
  this.emit('progress', this.getProgress());
41611
- if (this.activeCount === 0 && this.queue.length === 0) {
41643
+ if (this.activeCount === 0 && this.queue.length === 0 && this.pendingRetries === 0) {
41612
41644
  this.emit('drained');
41613
41645
  }
41614
41646
  this.processNext();
@@ -41626,7 +41658,74 @@ class RequestRunner extends SimpleEmitter {
41626
41658
  }
41627
41659
  }
41628
41660
 
41629
- class ReckerWebSocket extends EventEmitter.EventEmitter {
41661
+ class SimpleEmitter {
41662
+ listeners = new Map();
41663
+ on(event, listener) {
41664
+ const set = this.listeners.get(event) ?? new Set();
41665
+ set.add(listener);
41666
+ this.listeners.set(event, set);
41667
+ return this;
41668
+ }
41669
+ once(event, listener) {
41670
+ const wrapped = (...args) => {
41671
+ this.off(event, wrapped);
41672
+ listener(...args);
41673
+ };
41674
+ return this.on(event, wrapped);
41675
+ }
41676
+ off(event, listener) {
41677
+ const set = this.listeners.get(event);
41678
+ if (set) {
41679
+ set.delete(listener);
41680
+ if (set.size === 0) {
41681
+ this.listeners.delete(event);
41682
+ }
41683
+ }
41684
+ return this;
41685
+ }
41686
+ removeListener(event, listener) {
41687
+ return this.off(event, listener);
41688
+ }
41689
+ emit(event, ...args) {
41690
+ const set = this.listeners.get(event);
41691
+ if (!set)
41692
+ return false;
41693
+ for (const listener of [...set]) {
41694
+ listener(...args);
41695
+ }
41696
+ return true;
41697
+ }
41698
+ }
41699
+ const READY_STATE = {
41700
+ OPEN: 1,
41701
+ CLOSED: 3
41702
+ };
41703
+ function isNodeRuntime$2() {
41704
+ return typeof globalThis !== 'undefined' && Boolean(globalThis.process?.versions?.node);
41705
+ }
41706
+ let undiciModulePromise = null;
41707
+ async function loadUndici() {
41708
+ if (!undiciModulePromise) {
41709
+ const moduleName = 'undici';
41710
+ undiciModulePromise = import(moduleName);
41711
+ }
41712
+ return undiciModulePromise;
41713
+ }
41714
+ async function getWebSocketConstructor() {
41715
+ if (isNodeRuntime$2()) {
41716
+ const undici = await loadUndici();
41717
+ return undici.WebSocket;
41718
+ }
41719
+ const ws = globalThis.WebSocket;
41720
+ if (!ws) {
41721
+ throw new UnsupportedError('WebSocket is not available in this environment.', { feature: 'websocket' });
41722
+ }
41723
+ return ws;
41724
+ }
41725
+ function isReadableStream(value) {
41726
+ return Boolean(value && typeof value.getReader === 'function');
41727
+ }
41728
+ class ReckerWebSocket extends SimpleEmitter {
41630
41729
  ws = null;
41631
41730
  url;
41632
41731
  options;
@@ -41662,24 +41761,30 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41662
41761
  };
41663
41762
  }
41664
41763
  async connect() {
41764
+ const WebSocketCtor = await getWebSocketConstructor();
41765
+ const nodeEnv = isNodeRuntime$2();
41766
+ const wsOptions = nodeEnv
41767
+ ? {
41768
+ headers: this.options.headers,
41769
+ dispatcher: this.options.dispatcher,
41770
+ perMessageDeflate: this.options.perMessageDeflate,
41771
+ }
41772
+ : undefined;
41773
+ if (nodeEnv && this.options.proxy) {
41774
+ const proxyConfig = typeof this.options.proxy === 'string'
41775
+ ? { url: this.options.proxy }
41776
+ : this.options.proxy;
41777
+ const undici = await loadUndici();
41778
+ wsOptions.dispatcher = new undici.ProxyAgent(proxyConfig.url);
41779
+ }
41780
+ if (nodeEnv && this.options.tls) {
41781
+ wsOptions.tls = this.options.tls;
41782
+ }
41665
41783
  return new Promise((resolve, reject) => {
41666
41784
  try {
41667
- const wsOptions = {
41668
- headers: this.options.headers,
41669
- dispatcher: this.options.dispatcher,
41670
- perMessageDeflate: this.options.perMessageDeflate,
41671
- };
41672
- if (this.options.proxy) {
41673
- const proxyConfig = typeof this.options.proxy === 'string'
41674
- ? { url: this.options.proxy }
41675
- : this.options.proxy;
41676
- const { ProxyAgent } = require('undici');
41677
- wsOptions.dispatcher = new ProxyAgent(proxyConfig.url);
41678
- }
41679
- if (this.options.tls) {
41680
- wsOptions.tls = this.options.tls;
41681
- }
41682
- this.ws = new undiciExports.WebSocket(this.url, this.options.protocols, wsOptions);
41785
+ this.ws = nodeEnv
41786
+ ? new WebSocketCtor(this.url, this.options.protocols, wsOptions)
41787
+ : new WebSocketCtor(this.url, this.options.protocols);
41683
41788
  this.ws.addEventListener('open', () => {
41684
41789
  this.reconnectAttempts = 0;
41685
41790
  this.isReconnecting = false;
@@ -41688,9 +41793,10 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41688
41793
  resolve();
41689
41794
  });
41690
41795
  this.ws.addEventListener('message', (event) => {
41796
+ const data = event.data;
41691
41797
  const message = {
41692
- data: event.data,
41693
- isBinary: event.data instanceof Buffer
41798
+ data,
41799
+ isBinary: typeof data !== 'string'
41694
41800
  };
41695
41801
  this.emit('message', message);
41696
41802
  this.stopPongWatchdog();
@@ -41704,7 +41810,7 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41704
41810
  }
41705
41811
  });
41706
41812
  this.ws.addEventListener('error', (event) => {
41707
- const err = event.error instanceof Error
41813
+ const err = event?.error instanceof Error
41708
41814
  ? event.error
41709
41815
  : new ConnectionError('WebSocket connection error', {
41710
41816
  host: this.url,
@@ -41720,7 +41826,7 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41720
41826
  });
41721
41827
  }
41722
41828
  async send(data, options) {
41723
- if (!this.ws || this.ws.readyState !== undiciExports.WebSocket.OPEN) {
41829
+ if (!this.ws || this.ws.readyState !== READY_STATE.OPEN) {
41724
41830
  throw new StateError('WebSocket is not connected', {
41725
41831
  expectedState: 'open',
41726
41832
  actualState: this.ws ? 'closed' : 'not-created',
@@ -41734,6 +41840,16 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41734
41840
  }
41735
41841
  }
41736
41842
  async sendStream(stream, options) {
41843
+ if (isReadableStream(stream)) {
41844
+ const reader = stream.getReader();
41845
+ while (true) {
41846
+ const { done, value } = await reader.read();
41847
+ if (done)
41848
+ break;
41849
+ await this.send(value, options);
41850
+ }
41851
+ return;
41852
+ }
41737
41853
  for await (const chunk of stream) {
41738
41854
  await this.send(chunk, options);
41739
41855
  }
@@ -41752,7 +41868,7 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41752
41868
  }
41753
41869
  }
41754
41870
  ping() {
41755
- if (!this.ws || this.ws.readyState !== undiciExports.WebSocket.OPEN)
41871
+ if (!this.ws || this.ws.readyState !== READY_STATE.OPEN)
41756
41872
  return;
41757
41873
  const anyWs = this.ws;
41758
41874
  if (typeof anyWs.ping === 'function') {
@@ -41770,17 +41886,17 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41770
41886
  }
41771
41887
  }
41772
41888
  get readyState() {
41773
- return this.ws?.readyState ?? undiciExports.WebSocket.CLOSED;
41889
+ return this.ws?.readyState ?? READY_STATE.CLOSED;
41774
41890
  }
41775
41891
  get isConnected() {
41776
- return this.ws?.readyState === undiciExports.WebSocket.OPEN;
41892
+ return this.ws?.readyState === READY_STATE.OPEN;
41777
41893
  }
41778
41894
  toReadable() {
41779
41895
  if (!this.ws)
41780
41896
  return null;
41781
41897
  const wsAny = this.ws;
41782
- if (wsAny.readable) {
41783
- return webToNodeStream(wsAny.readable);
41898
+ if (wsAny.readable && typeof wsAny.readable.getReader === 'function') {
41899
+ return wsAny.readable;
41784
41900
  }
41785
41901
  return null;
41786
41902
  }
@@ -41795,7 +41911,25 @@ class ReckerWebSocket extends EventEmitter.EventEmitter {
41795
41911
  retriable: false,
41796
41912
  });
41797
41913
  }
41798
- await promises.pipeline(readable, destination);
41914
+ if (destination && typeof destination.getWriter === 'function') {
41915
+ await readable.pipeTo(destination);
41916
+ return;
41917
+ }
41918
+ if (isNodeRuntime$2()) {
41919
+ const streamModuleName = 'node:stream';
41920
+ const pipelineModuleName = 'node:stream/promises';
41921
+ const streamModule = await import(streamModuleName);
41922
+ const pipelineModule = await import(pipelineModuleName);
41923
+ const nodeReadable = typeof streamModule.Readable?.fromWeb === 'function'
41924
+ ? streamModule.Readable.fromWeb(readable)
41925
+ : streamModule.Readable.from(readable);
41926
+ await pipelineModule.pipeline(nodeReadable, destination);
41927
+ return;
41928
+ }
41929
+ throw new StreamError$1('Destination stream is not supported in this environment', {
41930
+ streamType: 'websocket',
41931
+ retriable: false,
41932
+ });
41799
41933
  }
41800
41934
  async *[Symbol.asyncIterator]() {
41801
41935
  const queue = [];
@@ -41929,6 +42063,20 @@ function randomJitter(value) {
41929
42063
  return value - jitter + Math.random() * (2 * jitter);
41930
42064
  }
41931
42065
 
42066
+ function isNodeRuntime$1() {
42067
+ return typeof globalThis !== 'undefined' && Boolean(globalThis.process?.versions?.node);
42068
+ }
42069
+ let netModulePromise = null;
42070
+ async function getNetModule() {
42071
+ if (!isNodeRuntime$1()) {
42072
+ throw new UnsupportedError('WHOIS is only available in Node.js environments.', { feature: 'whois' });
42073
+ }
42074
+ if (!netModulePromise) {
42075
+ const moduleName = 'node:net';
42076
+ netModulePromise = import(moduleName);
42077
+ }
42078
+ return netModulePromise;
42079
+ }
41932
42080
  const DEFAULT_SERVERS = {
41933
42081
  'com': 'whois.verisign-grs.com',
41934
42082
  'net': 'whois.verisign-grs.com',
@@ -42026,6 +42174,7 @@ function extractReferralServer(raw) {
42026
42174
  return null;
42027
42175
  }
42028
42176
  async function queryWhoisServer(server, query, port, timeout) {
42177
+ const { createConnection } = await getNetModule();
42029
42178
  return new Promise((resolve, reject) => {
42030
42179
  let response = '';
42031
42180
  let socket = null;
@@ -42037,7 +42186,7 @@ async function queryWhoisServer(server, query, port, timeout) {
42037
42186
  'Retry the query; some registries respond slowly under load.'
42038
42187
  ]));
42039
42188
  }, timeout);
42040
- socket = net$1.createConnection({ host: server, port }, () => {
42189
+ socket = createConnection({ host: server, port }, () => {
42041
42190
  socket.write(query + '\r\n');
42042
42191
  });
42043
42192
  socket.on('data', (chunk) => {
@@ -42049,13 +42198,13 @@ async function queryWhoisServer(server, query, port, timeout) {
42049
42198
  });
42050
42199
  socket.on('error', (error) => {
42051
42200
  clearTimeout(timeoutId);
42052
- const errorDetail = error.message || error.code || 'Connection failed';
42201
+ const errorDetail = error?.message || error?.code || 'Connection failed';
42053
42202
  const err = new ReckerError(`WHOIS query failed: ${errorDetail}`, undefined, undefined, [
42054
42203
  'Verify the WHOIS server is reachable and correct.',
42055
42204
  'Check network/firewall settings blocking WHOIS port 43.',
42056
42205
  'Retry the query; transient network issues can occur.'
42057
42206
  ]);
42058
- err.code = error.code;
42207
+ err.code = error?.code;
42059
42208
  reject(err);
42060
42209
  });
42061
42210
  socket.on('close', (hadError) => {
@@ -42397,14 +42546,17 @@ class LazyTransport {
42397
42546
  factory;
42398
42547
  transport;
42399
42548
  resolving;
42549
+ dispatchFn;
42400
42550
  constructor(factory) {
42401
42551
  this.factory = factory;
42552
+ this.dispatchFn = this.initialDispatch.bind(this);
42402
42553
  }
42403
- async dispatch(req) {
42554
+ async initialDispatch(req) {
42404
42555
  if (!this.transport) {
42405
42556
  if (!this.resolving) {
42406
42557
  this.resolving = this.factory().then((instance) => {
42407
42558
  this.transport = instance;
42559
+ this.dispatchFn = (r) => this.transport.dispatch(r);
42408
42560
  return instance;
42409
42561
  });
42410
42562
  }
@@ -42412,6 +42564,19 @@ class LazyTransport {
42412
42564
  }
42413
42565
  return this.transport.dispatch(req);
42414
42566
  }
42567
+ dispatch(req) {
42568
+ return this.dispatchFn(req);
42569
+ }
42570
+ async warmup() {
42571
+ if (!this.transport && !this.resolving) {
42572
+ this.resolving = this.factory().then((instance) => {
42573
+ this.transport = instance;
42574
+ this.dispatchFn = (r) => this.transport.dispatch(r);
42575
+ return instance;
42576
+ });
42577
+ }
42578
+ await this.resolving;
42579
+ }
42415
42580
  }
42416
42581
  function createLazyCurlTransport() {
42417
42582
  if (!isNodeRuntime()) {
@@ -42464,6 +42629,15 @@ function createLazyFileStorage(path) {
42464
42629
  return new FileStorage(path);
42465
42630
  });
42466
42631
  }
42632
+ function createDefaultCacheStorage() {
42633
+ if (!isNodeRuntime()) {
42634
+ return new SimpleMemoryStorage();
42635
+ }
42636
+ return new LazyCacheStorage(async () => {
42637
+ const { MemoryStorage } = await Promise.resolve().then(function () { return memoryStorage; });
42638
+ return new MemoryStorage();
42639
+ });
42640
+ }
42467
42641
  class LazyHlsPromise {
42468
42642
  instancePromise;
42469
42643
  constructor(factory) {
@@ -42517,9 +42691,11 @@ class Client {
42517
42691
  transport;
42518
42692
  curlTransport;
42519
42693
  defaultHeaders;
42694
+ defaultHeadersObj;
42520
42695
  defaultParams;
42521
42696
  paginationConfig;
42522
42697
  handler;
42698
+ fastHandler;
42523
42699
  logger;
42524
42700
  debugEnabled;
42525
42701
  agentManager;
@@ -42531,6 +42707,7 @@ class Client {
42531
42707
  defaultTimeout;
42532
42708
  http2Enabled = false;
42533
42709
  transportKind = 'custom';
42710
+ canFastPath = false;
42534
42711
  _aiConfig;
42535
42712
  _ai;
42536
42713
  constructor(options = {}) {
@@ -42548,6 +42725,7 @@ class Client {
42548
42725
  'User-Agent': getDefaultUserAgent(),
42549
42726
  ...(options.headers || {})
42550
42727
  };
42728
+ this.defaultHeadersObj = new Headers(this.defaultHeaders);
42551
42729
  this.defaultParams = options.defaults?.params || {};
42552
42730
  this.paginationConfig = options.pagination;
42553
42731
  this.maxResponseSize = options.maxResponseSize;
@@ -42643,7 +42821,7 @@ class Client {
42643
42821
  storage = createLazyFileStorage(options.cache.fileStoragePath);
42644
42822
  }
42645
42823
  else {
42646
- storage = new MemoryStorage$1();
42824
+ storage = createDefaultCacheStorage();
42647
42825
  }
42648
42826
  cachePlugin({
42649
42827
  ...options.cache,
@@ -42677,8 +42855,17 @@ class Client {
42677
42855
  if (this.debugEnabled && this.logger) {
42678
42856
  this.middlewares.unshift(this.createLoggingMiddleware(this.logger));
42679
42857
  }
42680
- this.middlewares.push(this.httpErrorMiddleware);
42681
42858
  this.handler = this.composeMiddlewares();
42859
+ this.fastHandler = this.composeFastHandler();
42860
+ const hasHooks = (this.hooks.beforeRequest?.length ?? 0) > 0 ||
42861
+ (this.hooks.afterResponse?.length ?? 0) > 0 ||
42862
+ (this.hooks.onError?.length ?? 0) > 0;
42863
+ const hasComplexConfig = !!this.cookieJar ||
42864
+ !!this.defaultTimeout ||
42865
+ this.maxResponseSize !== undefined ||
42866
+ this.debugEnabled;
42867
+ const hasUserMiddlewares = this.middlewares.length > 0;
42868
+ this.canFastPath = !hasHooks && !hasComplexConfig && !hasUserMiddlewares;
42682
42869
  }
42683
42870
  createLoggingMiddleware(logger) {
42684
42871
  return async (req, next) => {
@@ -42795,16 +42982,33 @@ class Client {
42795
42982
  }
42796
42983
  composeMiddlewares() {
42797
42984
  const chain = [...this.middlewares];
42798
- const transportDispatch = this.dispatch.bind(this);
42985
+ const self = this;
42986
+ const transportWithErrorCheck = async (req) => {
42987
+ const response = await self.dispatch(req);
42988
+ if (req.throwHttpErrors !== false && !response.ok && response.status !== 304) {
42989
+ throw new HttpError(response, req);
42990
+ }
42991
+ return response;
42992
+ };
42799
42993
  if (this.hooks.beforeRequest?.length || this.hooks.afterResponse?.length) {
42800
42994
  chain.unshift(this.hooksMiddleware);
42801
42995
  }
42802
42996
  if (chain.length === 0) {
42803
- return transportDispatch;
42997
+ return transportWithErrorCheck;
42804
42998
  }
42805
42999
  return chain.reduceRight((next, middleware) => {
42806
43000
  return (req) => middleware(req, next);
42807
- }, transportDispatch);
43001
+ }, transportWithErrorCheck);
43002
+ }
43003
+ composeFastHandler() {
43004
+ const self = this;
43005
+ return async (req) => {
43006
+ const response = await self.dispatch(req);
43007
+ if (req.throwHttpErrors !== false && !response.ok && response.status !== 304) {
43008
+ throw new HttpError(response, req);
43009
+ }
43010
+ return response;
43011
+ };
42808
43012
  }
42809
43013
  hooksMiddleware = async (req, next) => {
42810
43014
  let modifiedReq = req;
@@ -42840,16 +43044,10 @@ class Client {
42840
43044
  throw error;
42841
43045
  }
42842
43046
  };
42843
- httpErrorMiddleware = async (req, next) => {
42844
- const response = await next(req);
42845
- if (req.throwHttpErrors !== false && !response.ok && response.status !== 304) {
42846
- throw new HttpError(response, req);
42847
- }
42848
- return response;
42849
- };
42850
43047
  use(middleware) {
42851
43048
  this.middlewares.push(middleware);
42852
43049
  this.handler = this.composeMiddlewares();
43050
+ this.canFastPath = false;
42853
43051
  return this;
42854
43052
  }
42855
43053
  beforeRequest(hook) {
@@ -42858,6 +43056,7 @@ class Client {
42858
43056
  }
42859
43057
  this.hooks.beforeRequest.push(hook);
42860
43058
  this.handler = this.composeMiddlewares();
43059
+ this.canFastPath = false;
42861
43060
  return this;
42862
43061
  }
42863
43062
  afterResponse(hook) {
@@ -42866,6 +43065,7 @@ class Client {
42866
43065
  }
42867
43066
  this.hooks.afterResponse.push(hook);
42868
43067
  this.handler = this.composeMiddlewares();
43068
+ this.canFastPath = false;
42869
43069
  return this;
42870
43070
  }
42871
43071
  onError(hook) {
@@ -42874,6 +43074,7 @@ class Client {
42874
43074
  }
42875
43075
  this.hooks.onError.push(hook);
42876
43076
  this.handler = this.composeMiddlewares();
43077
+ this.canFastPath = false;
42877
43078
  return this;
42878
43079
  }
42879
43080
  buildUrl(path, requestParams) {
@@ -42929,20 +43130,31 @@ class Client {
42929
43130
  }
42930
43131
  request(path, options = {}) {
42931
43132
  const url = this.buildUrl(path, options.params);
43133
+ const usesFastPath = this.canFastPath &&
43134
+ !options.headers &&
43135
+ !options.timeout &&
43136
+ !options.signal &&
43137
+ options.maxResponseSize === undefined;
43138
+ if (usesFastPath) {
43139
+ const req = new HttpRequest(url, {
43140
+ method: options.method || 'GET',
43141
+ body: options.body,
43142
+ headers: this.defaultHeadersObj,
43143
+ throwHttpErrors: options.throwHttpErrors,
43144
+ });
43145
+ const responsePromise = this.fastHandler(req);
43146
+ return new RequestPromise(responsePromise);
43147
+ }
42932
43148
  let mergedHeaders;
42933
43149
  if (options.headers) {
42934
- mergedHeaders = this.defaultHeaders instanceof Headers
42935
- ? new Headers(this.defaultHeaders)
42936
- : new Headers(this.defaultHeaders);
43150
+ mergedHeaders = new Headers(this.defaultHeadersObj);
42937
43151
  const optHeaders = options.headers instanceof Headers
42938
43152
  ? options.headers
42939
43153
  : new Headers(options.headers);
42940
43154
  optHeaders.forEach((value, key) => mergedHeaders.set(key, value));
42941
43155
  }
42942
43156
  else {
42943
- mergedHeaders = this.defaultHeaders instanceof Headers
42944
- ? this.defaultHeaders
42945
- : new Headers(this.defaultHeaders);
43157
+ mergedHeaders = this.defaultHeadersObj;
42946
43158
  }
42947
43159
  const needsController = options.timeout || options.signal || this.defaultTimeout;
42948
43160
  let controller;
@@ -42994,6 +43206,11 @@ class Client {
42994
43206
  get(path, options = {}) {
42995
43207
  return this.request(path, { ...options, method: 'GET' });
42996
43208
  }
43209
+ async warmup() {
43210
+ if (this.transport && 'warmup' in this.transport && typeof this.transport.warmup === 'function') {
43211
+ await this.transport.warmup();
43212
+ }
43213
+ }
42997
43214
  async batch(requests, options = {}) {
42998
43215
  const mapResponse = options.mapResponse ?? ((res) => res);
42999
43216
  const batchConcurrency = options.concurrency ?? this.concurrencyConfig.runner.concurrency;
@@ -43308,6 +43525,556 @@ function createClient(options = {}) {
43308
43525
  return new Client(options);
43309
43526
  }
43310
43527
 
43528
+ const DEFAULT_TOTAL_PERCENT = 0.5;
43529
+ const DEFAULT_HEAP_PERCENT = 0.6;
43530
+ function readCgroupLimit() {
43531
+ const candidates = [
43532
+ '/sys/fs/cgroup/memory.max',
43533
+ '/sys/fs/cgroup/memory/memory.limit_in_bytes',
43534
+ ];
43535
+ for (const file of candidates) {
43536
+ try {
43537
+ if (fs.existsSync(file)) {
43538
+ const raw = fs.readFileSync(file, 'utf8').trim();
43539
+ if (!raw || raw === 'max')
43540
+ continue;
43541
+ const value = Number.parseInt(raw, 10);
43542
+ if (Number.isFinite(value) && value > 0) {
43543
+ return value;
43544
+ }
43545
+ }
43546
+ }
43547
+ catch {
43548
+ }
43549
+ }
43550
+ return null;
43551
+ }
43552
+ function getEffectiveTotalMemoryBytes() {
43553
+ const cgroupLimit = readCgroupLimit();
43554
+ if (cgroupLimit && Number.isFinite(cgroupLimit) && cgroupLimit > 0) {
43555
+ return cgroupLimit;
43556
+ }
43557
+ return os.totalmem();
43558
+ }
43559
+ function resolveCacheMemoryLimit(options = {}) {
43560
+ const { maxMemoryBytes, maxMemoryPercent, safetyPercent } = options;
43561
+ const heapStats = v8.getHeapStatistics();
43562
+ const heapLimit = heapStats?.heap_size_limit ?? 0;
43563
+ const effectiveTotal = getEffectiveTotalMemoryBytes();
43564
+ let resolvedBytes = 0;
43565
+ let derivedFromPercent = false;
43566
+ if (typeof maxMemoryBytes === 'number' && maxMemoryBytes > 0) {
43567
+ resolvedBytes = maxMemoryBytes;
43568
+ }
43569
+ else if (typeof maxMemoryPercent === 'number' && maxMemoryPercent > 0) {
43570
+ const percent = Math.max(0, Math.min(maxMemoryPercent, 1));
43571
+ resolvedBytes = Math.floor(effectiveTotal * percent);
43572
+ derivedFromPercent = true;
43573
+ }
43574
+ const safeTotalPercent = typeof safetyPercent === 'number' && safetyPercent > 0 && safetyPercent <= 1
43575
+ ? safetyPercent
43576
+ : DEFAULT_TOTAL_PERCENT;
43577
+ const totalCap = Math.floor(effectiveTotal * safeTotalPercent);
43578
+ if (resolvedBytes === 0 || totalCap < resolvedBytes) {
43579
+ resolvedBytes = totalCap;
43580
+ derivedFromPercent = derivedFromPercent || (maxMemoryPercent ?? 0) > 0;
43581
+ }
43582
+ if (heapLimit > 0) {
43583
+ const heapCap = Math.floor(heapLimit * DEFAULT_HEAP_PERCENT);
43584
+ if (resolvedBytes === 0 || heapCap < resolvedBytes) {
43585
+ resolvedBytes = heapCap;
43586
+ derivedFromPercent = derivedFromPercent || (maxMemoryPercent ?? 0) > 0;
43587
+ }
43588
+ }
43589
+ if (!Number.isFinite(resolvedBytes) || resolvedBytes <= 0) {
43590
+ resolvedBytes = Math.floor(effectiveTotal * DEFAULT_TOTAL_PERCENT);
43591
+ derivedFromPercent = true;
43592
+ }
43593
+ const inferredPercent = effectiveTotal > 0 ? resolvedBytes / effectiveTotal : null;
43594
+ return {
43595
+ maxMemoryBytes: resolvedBytes,
43596
+ derivedFromPercent,
43597
+ effectiveTotal,
43598
+ heapLimit,
43599
+ inferredPercent,
43600
+ };
43601
+ }
43602
+ function formatBytes(bytes) {
43603
+ if (bytes === 0)
43604
+ return '0 B';
43605
+ const k = 1024;
43606
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
43607
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
43608
+ return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
43609
+ }
43610
+ function getHeapStats() {
43611
+ const heapStats = v8.getHeapStatistics();
43612
+ const { heapUsed } = process.memoryUsage();
43613
+ const heapLimit = heapStats?.heap_size_limit ?? 0;
43614
+ const heapRatio = heapLimit > 0 ? heapUsed / heapLimit : 0;
43615
+ return {
43616
+ heapUsed,
43617
+ heapLimit,
43618
+ heapRatio,
43619
+ };
43620
+ }
43621
+
43622
+ let MemoryStorage$1 = class MemoryStorage {
43623
+ storage = new Map();
43624
+ meta = new Map();
43625
+ maxSize;
43626
+ maxMemoryBytes;
43627
+ maxMemoryPercent;
43628
+ defaultTtl;
43629
+ evictionPolicy;
43630
+ compressionEnabled;
43631
+ compressionThreshold;
43632
+ enableStats;
43633
+ heapUsageThreshold;
43634
+ onEvict;
43635
+ onPressure;
43636
+ currentMemoryBytes = 0;
43637
+ evictedDueToMemory = 0;
43638
+ memoryPressureEvents = 0;
43639
+ accessCounter = 0;
43640
+ monitorHandle = null;
43641
+ cleanupHandle = null;
43642
+ stats = {
43643
+ hits: 0,
43644
+ misses: 0,
43645
+ sets: 0,
43646
+ deletes: 0,
43647
+ evictions: 0,
43648
+ };
43649
+ compressionStats = {
43650
+ totalCompressed: 0,
43651
+ totalOriginalSize: 0,
43652
+ totalCompressedSize: 0,
43653
+ };
43654
+ constructor(options = {}) {
43655
+ if (options.maxMemoryBytes &&
43656
+ options.maxMemoryBytes > 0 &&
43657
+ options.maxMemoryPercent &&
43658
+ options.maxMemoryPercent > 0) {
43659
+ throw new ConfigurationError('[MemoryStorage] Cannot use both maxMemoryBytes and maxMemoryPercent', { configKey: 'maxMemoryBytes|maxMemoryPercent' });
43660
+ }
43661
+ if (options.maxMemoryPercent !== undefined &&
43662
+ (options.maxMemoryPercent < 0 || options.maxMemoryPercent > 1)) {
43663
+ throw new ConfigurationError('[MemoryStorage] maxMemoryPercent must be between 0 and 1', { configKey: 'maxMemoryPercent' });
43664
+ }
43665
+ this.maxSize = options.maxSize ?? 1000;
43666
+ this.defaultTtl = options.ttl ?? 300000;
43667
+ this.evictionPolicy = options.evictionPolicy ?? 'lru';
43668
+ this.enableStats = options.enableStats ?? false;
43669
+ this.heapUsageThreshold = options.heapUsageThreshold ?? 0.6;
43670
+ if (options.maxMemoryBytes && options.maxMemoryBytes > 0) {
43671
+ this.maxMemoryBytes = options.maxMemoryBytes;
43672
+ this.maxMemoryPercent = 0;
43673
+ }
43674
+ else if (options.maxMemoryPercent && options.maxMemoryPercent > 0) {
43675
+ const effectiveTotal = getEffectiveTotalMemoryBytes();
43676
+ this.maxMemoryBytes = Math.floor(effectiveTotal * options.maxMemoryPercent);
43677
+ this.maxMemoryPercent = options.maxMemoryPercent;
43678
+ }
43679
+ else {
43680
+ const resolved = resolveCacheMemoryLimit({});
43681
+ this.maxMemoryBytes = resolved.maxMemoryBytes;
43682
+ this.maxMemoryPercent = resolved.inferredPercent ?? 0;
43683
+ }
43684
+ if (options.compression === true) {
43685
+ this.compressionEnabled = true;
43686
+ this.compressionThreshold = 1024;
43687
+ }
43688
+ else if (typeof options.compression === 'object' &&
43689
+ options.compression.enabled) {
43690
+ this.compressionEnabled = true;
43691
+ this.compressionThreshold = options.compression.threshold ?? 1024;
43692
+ }
43693
+ else {
43694
+ this.compressionEnabled = false;
43695
+ this.compressionThreshold = 1024;
43696
+ }
43697
+ this.onEvict = options.onEvict;
43698
+ this.onPressure = options.onPressure;
43699
+ const monitorInterval = options.monitorInterval ?? 15000;
43700
+ if (monitorInterval > 0) {
43701
+ this.monitorHandle = setInterval(() => this.memoryHealthCheck(), monitorInterval);
43702
+ this.monitorHandle.unref();
43703
+ }
43704
+ const cleanupInterval = options.cleanupInterval ?? 60000;
43705
+ if (cleanupInterval > 0) {
43706
+ this.cleanupHandle = setInterval(() => this.cleanupExpired(), cleanupInterval);
43707
+ this.cleanupHandle.unref();
43708
+ }
43709
+ }
43710
+ async get(key) {
43711
+ const data = this.storage.get(key);
43712
+ const metadata = this.meta.get(key);
43713
+ if (!data || !metadata) {
43714
+ this.recordStat('misses');
43715
+ return undefined;
43716
+ }
43717
+ const now = Date.now();
43718
+ if (now > metadata.expiresAt) {
43719
+ this.deleteInternal(key);
43720
+ this.recordStat('misses');
43721
+ return undefined;
43722
+ }
43723
+ if (this.evictionPolicy === 'lru') {
43724
+ metadata.lastAccess = now;
43725
+ metadata.accessOrder = ++this.accessCounter;
43726
+ }
43727
+ this.recordStat('hits');
43728
+ if (this.isCompressed(data)) {
43729
+ try {
43730
+ const decompressed = this.decompress(data);
43731
+ return JSON.parse(decompressed);
43732
+ }
43733
+ catch {
43734
+ this.deleteInternal(key);
43735
+ return undefined;
43736
+ }
43737
+ }
43738
+ return JSON.parse(data);
43739
+ }
43740
+ async set(key, entry, ttl) {
43741
+ const effectiveTtl = ttl ?? this.defaultTtl;
43742
+ const now = Date.now();
43743
+ const serialized = JSON.stringify(entry);
43744
+ const originalSize = Buffer.byteLength(serialized, 'utf8');
43745
+ let finalData = serialized;
43746
+ let compressedSize = originalSize;
43747
+ let compressed = false;
43748
+ if (this.compressionEnabled && originalSize >= this.compressionThreshold) {
43749
+ try {
43750
+ const result = this.compress(serialized);
43751
+ finalData = result;
43752
+ compressedSize = Buffer.byteLength(result.__data, 'utf8');
43753
+ compressed = true;
43754
+ this.compressionStats.totalCompressed++;
43755
+ this.compressionStats.totalOriginalSize += originalSize;
43756
+ this.compressionStats.totalCompressedSize += compressedSize;
43757
+ }
43758
+ catch {
43759
+ }
43760
+ }
43761
+ const existingMeta = this.meta.get(key);
43762
+ if (existingMeta) {
43763
+ this.currentMemoryBytes -= existingMeta.compressedSize;
43764
+ }
43765
+ if (!this.enforceMemoryLimit(compressedSize)) {
43766
+ this.evictedDueToMemory++;
43767
+ return;
43768
+ }
43769
+ if (!existingMeta && this.storage.size >= this.maxSize) {
43770
+ this.evictOne('size');
43771
+ }
43772
+ this.storage.set(key, finalData);
43773
+ this.meta.set(key, {
43774
+ createdAt: now,
43775
+ expiresAt: now + effectiveTtl,
43776
+ lastAccess: now,
43777
+ insertOrder: ++this.accessCounter,
43778
+ accessOrder: this.accessCounter,
43779
+ compressed,
43780
+ originalSize,
43781
+ compressedSize,
43782
+ });
43783
+ this.currentMemoryBytes += compressedSize;
43784
+ this.recordStat('sets');
43785
+ }
43786
+ async delete(key) {
43787
+ this.deleteInternal(key);
43788
+ this.recordStat('deletes');
43789
+ }
43790
+ clear(prefix) {
43791
+ if (!prefix) {
43792
+ this.storage.clear();
43793
+ this.meta.clear();
43794
+ this.currentMemoryBytes = 0;
43795
+ this.evictedDueToMemory = 0;
43796
+ if (this.enableStats) {
43797
+ this.stats = { hits: 0, misses: 0, sets: 0, deletes: 0, evictions: 0 };
43798
+ }
43799
+ return;
43800
+ }
43801
+ for (const key of this.storage.keys()) {
43802
+ if (key.startsWith(prefix)) {
43803
+ this.deleteInternal(key);
43804
+ }
43805
+ }
43806
+ }
43807
+ size() {
43808
+ return this.storage.size;
43809
+ }
43810
+ keys() {
43811
+ return Array.from(this.storage.keys());
43812
+ }
43813
+ has(key) {
43814
+ const meta = this.meta.get(key);
43815
+ if (!meta)
43816
+ return false;
43817
+ if (Date.now() > meta.expiresAt) {
43818
+ this.deleteInternal(key);
43819
+ return false;
43820
+ }
43821
+ return true;
43822
+ }
43823
+ getStats() {
43824
+ const total = this.stats.hits + this.stats.misses;
43825
+ const hitRate = total > 0 ? this.stats.hits / total : 0;
43826
+ return {
43827
+ enabled: this.enableStats,
43828
+ ...this.stats,
43829
+ hitRate,
43830
+ totalItems: this.storage.size,
43831
+ memoryUsageBytes: this.currentMemoryBytes,
43832
+ maxMemoryBytes: this.maxMemoryBytes,
43833
+ evictedDueToMemory: this.evictedDueToMemory,
43834
+ };
43835
+ }
43836
+ getMemoryStats() {
43837
+ const totalItems = this.storage.size;
43838
+ const memoryUsagePercent = this.maxMemoryBytes > 0
43839
+ ? (this.currentMemoryBytes / this.maxMemoryBytes) * 100
43840
+ : 0;
43841
+ const systemTotal = os.totalmem();
43842
+ const systemFree = os.freemem();
43843
+ const systemUsed = systemTotal - systemFree;
43844
+ const cachePercentOfSystem = systemTotal > 0 ? (this.currentMemoryBytes / systemTotal) * 100 : 0;
43845
+ return {
43846
+ currentMemoryBytes: this.currentMemoryBytes,
43847
+ maxMemoryBytes: this.maxMemoryBytes,
43848
+ maxMemoryPercent: this.maxMemoryPercent,
43849
+ memoryUsagePercent: parseFloat(memoryUsagePercent.toFixed(2)),
43850
+ cachePercentOfSystemMemory: parseFloat(cachePercentOfSystem.toFixed(2)),
43851
+ totalItems,
43852
+ maxSize: this.maxSize,
43853
+ evictedDueToMemory: this.evictedDueToMemory,
43854
+ memoryPressureEvents: this.memoryPressureEvents,
43855
+ averageItemSize: totalItems > 0 ? Math.round(this.currentMemoryBytes / totalItems) : 0,
43856
+ memoryUsage: {
43857
+ current: formatBytes(this.currentMemoryBytes),
43858
+ max: formatBytes(this.maxMemoryBytes),
43859
+ available: formatBytes(Math.max(0, this.maxMemoryBytes - this.currentMemoryBytes)),
43860
+ },
43861
+ systemMemory: {
43862
+ total: formatBytes(systemTotal),
43863
+ free: formatBytes(systemFree),
43864
+ used: formatBytes(systemUsed),
43865
+ cachePercent: `${cachePercentOfSystem.toFixed(2)}%`,
43866
+ },
43867
+ };
43868
+ }
43869
+ getCompressionStats() {
43870
+ if (!this.compressionEnabled) {
43871
+ return {
43872
+ enabled: false,
43873
+ totalItems: this.storage.size,
43874
+ compressedItems: 0,
43875
+ compressionThreshold: this.compressionThreshold,
43876
+ totalOriginalSize: 0,
43877
+ totalCompressedSize: 0,
43878
+ averageCompressionRatio: '0',
43879
+ spaceSavingsPercent: '0',
43880
+ memoryUsage: {
43881
+ uncompressed: '0 B',
43882
+ compressed: '0 B',
43883
+ saved: '0 B',
43884
+ },
43885
+ };
43886
+ }
43887
+ const ratio = this.compressionStats.totalOriginalSize > 0
43888
+ ? (this.compressionStats.totalCompressedSize /
43889
+ this.compressionStats.totalOriginalSize).toFixed(2)
43890
+ : '0';
43891
+ const savings = this.compressionStats.totalOriginalSize > 0
43892
+ ? (((this.compressionStats.totalOriginalSize -
43893
+ this.compressionStats.totalCompressedSize) /
43894
+ this.compressionStats.totalOriginalSize) *
43895
+ 100).toFixed(2)
43896
+ : '0';
43897
+ const saved = this.compressionStats.totalOriginalSize -
43898
+ this.compressionStats.totalCompressedSize;
43899
+ return {
43900
+ enabled: true,
43901
+ totalItems: this.storage.size,
43902
+ compressedItems: this.compressionStats.totalCompressed,
43903
+ compressionThreshold: this.compressionThreshold,
43904
+ totalOriginalSize: this.compressionStats.totalOriginalSize,
43905
+ totalCompressedSize: this.compressionStats.totalCompressedSize,
43906
+ averageCompressionRatio: ratio,
43907
+ spaceSavingsPercent: savings,
43908
+ memoryUsage: {
43909
+ uncompressed: formatBytes(this.compressionStats.totalOriginalSize),
43910
+ compressed: formatBytes(this.compressionStats.totalCompressedSize),
43911
+ saved: formatBytes(saved),
43912
+ },
43913
+ };
43914
+ }
43915
+ shutdown() {
43916
+ if (this.monitorHandle) {
43917
+ clearInterval(this.monitorHandle);
43918
+ this.monitorHandle = null;
43919
+ }
43920
+ if (this.cleanupHandle) {
43921
+ clearInterval(this.cleanupHandle);
43922
+ this.cleanupHandle = null;
43923
+ }
43924
+ }
43925
+ deleteInternal(key) {
43926
+ const meta = this.meta.get(key);
43927
+ if (meta) {
43928
+ this.currentMemoryBytes -= meta.compressedSize;
43929
+ }
43930
+ this.storage.delete(key);
43931
+ this.meta.delete(key);
43932
+ }
43933
+ recordStat(type) {
43934
+ if (this.enableStats) {
43935
+ this.stats[type]++;
43936
+ }
43937
+ }
43938
+ isCompressed(data) {
43939
+ return (typeof data === 'object' && data !== null && '__compressed' in data);
43940
+ }
43941
+ compress(data) {
43942
+ const buffer = Buffer.from(data, 'utf8');
43943
+ const compressed = require$$3.gzipSync(buffer);
43944
+ return {
43945
+ __compressed: true,
43946
+ __data: compressed.toString('base64'),
43947
+ __originalSize: buffer.length,
43948
+ };
43949
+ }
43950
+ decompress(data) {
43951
+ const buffer = Buffer.from(data.__data, 'base64');
43952
+ const decompressed = require$$3.gunzipSync(buffer);
43953
+ return decompressed.toString('utf8');
43954
+ }
43955
+ selectEvictionCandidate() {
43956
+ if (this.meta.size === 0)
43957
+ return null;
43958
+ let candidate = null;
43959
+ let candidateValue = this.evictionPolicy === 'lru' ? Infinity : Infinity;
43960
+ for (const [key, meta] of this.meta) {
43961
+ const value = this.evictionPolicy === 'lru' ? meta.accessOrder : meta.insertOrder;
43962
+ if (value < candidateValue) {
43963
+ candidateValue = value;
43964
+ candidate = key;
43965
+ }
43966
+ }
43967
+ return candidate;
43968
+ }
43969
+ evictOne(reason) {
43970
+ const candidate = this.selectEvictionCandidate();
43971
+ if (!candidate)
43972
+ return null;
43973
+ const meta = this.meta.get(candidate);
43974
+ const freedBytes = meta?.compressedSize ?? 0;
43975
+ this.deleteInternal(candidate);
43976
+ this.stats.evictions++;
43977
+ if (reason === 'memory' || reason === 'heap') {
43978
+ this.evictedDueToMemory++;
43979
+ }
43980
+ this.onEvict?.({
43981
+ reason,
43982
+ key: candidate,
43983
+ freedBytes,
43984
+ currentBytes: this.currentMemoryBytes,
43985
+ maxMemoryBytes: this.maxMemoryBytes,
43986
+ });
43987
+ return { key: candidate, freedBytes };
43988
+ }
43989
+ enforceMemoryLimit(incomingSize) {
43990
+ if (incomingSize > this.maxMemoryBytes) {
43991
+ return false;
43992
+ }
43993
+ while (this.currentMemoryBytes + incomingSize > this.maxMemoryBytes &&
43994
+ this.storage.size > 0) {
43995
+ const result = this.evictOne('memory');
43996
+ if (!result)
43997
+ break;
43998
+ }
43999
+ return this.currentMemoryBytes + incomingSize <= this.maxMemoryBytes;
44000
+ }
44001
+ reduceMemoryTo(targetBytes) {
44002
+ targetBytes = Math.max(0, targetBytes);
44003
+ let freedBytes = 0;
44004
+ while (this.currentMemoryBytes > targetBytes && this.storage.size > 0) {
44005
+ const result = this.evictOne('memory');
44006
+ if (!result)
44007
+ break;
44008
+ freedBytes += result.freedBytes;
44009
+ }
44010
+ return freedBytes;
44011
+ }
44012
+ memoryHealthCheck() {
44013
+ let totalFreed = 0;
44014
+ if (this.currentMemoryBytes > this.maxMemoryBytes) {
44015
+ const before = this.currentMemoryBytes;
44016
+ this.enforceMemoryLimit(0);
44017
+ const freed = before - this.currentMemoryBytes;
44018
+ if (freed > 0) {
44019
+ totalFreed += freed;
44020
+ this.memoryPressureEvents++;
44021
+ this.onPressure?.({
44022
+ reason: 'limit',
44023
+ heapLimit: getHeapStats().heapLimit,
44024
+ heapUsed: getHeapStats().heapUsed,
44025
+ currentBytes: this.currentMemoryBytes,
44026
+ maxMemoryBytes: this.maxMemoryBytes,
44027
+ freedBytes: freed,
44028
+ });
44029
+ }
44030
+ }
44031
+ const { heapUsed, heapLimit, heapRatio } = getHeapStats();
44032
+ if (heapLimit > 0 && heapRatio >= this.heapUsageThreshold) {
44033
+ const before = this.currentMemoryBytes;
44034
+ const target = Math.floor(this.currentMemoryBytes * 0.5);
44035
+ this.reduceMemoryTo(target);
44036
+ const freed = before - this.currentMemoryBytes;
44037
+ if (freed > 0) {
44038
+ totalFreed += freed;
44039
+ this.memoryPressureEvents++;
44040
+ this.onPressure?.({
44041
+ reason: 'heap',
44042
+ heapLimit,
44043
+ heapUsed,
44044
+ heapRatio,
44045
+ currentBytes: this.currentMemoryBytes,
44046
+ maxMemoryBytes: this.maxMemoryBytes,
44047
+ freedBytes: freed,
44048
+ });
44049
+ }
44050
+ }
44051
+ return totalFreed;
44052
+ }
44053
+ cleanupExpired() {
44054
+ const now = Date.now();
44055
+ let cleaned = 0;
44056
+ for (const [key, meta] of this.meta) {
44057
+ if (now > meta.expiresAt) {
44058
+ this.deleteInternal(key);
44059
+ cleaned++;
44060
+ this.onEvict?.({
44061
+ reason: 'expired',
44062
+ key,
44063
+ freedBytes: meta.compressedSize,
44064
+ currentBytes: this.currentMemoryBytes,
44065
+ maxMemoryBytes: this.maxMemoryBytes,
44066
+ });
44067
+ }
44068
+ }
44069
+ return cleaned;
44070
+ }
44071
+ };
44072
+
44073
+ var memoryStorage = /*#__PURE__*/Object.freeze({
44074
+ __proto__: null,
44075
+ MemoryStorage: MemoryStorage$1
44076
+ });
44077
+
43311
44078
  var he$2 = {exports: {}};
43312
44079
 
43313
44080
  /*! https://mths.be/he v1.2.0 by @mathias | MIT license */
@@ -54062,9 +54829,9 @@ class TasksPool extends EventEmitter.EventEmitter {
54062
54829
  }
54063
54830
  _sleep(ms, signal) {
54064
54831
  if (signal && typeof signal.aborted !== 'undefined') {
54065
- return promises$1.setTimeout(ms, undefined, { signal });
54832
+ return promises.setTimeout(ms, undefined, { signal });
54066
54833
  }
54067
- return promises$1.setTimeout(ms);
54834
+ return promises.setTimeout(ms);
54068
54835
  }
54069
54836
  _buildTaskContext(task, controller) {
54070
54837
  return {
@@ -69460,8 +70227,8 @@ class Database extends SafeEventEmitter {
69460
70227
  })();
69461
70228
  this.version = '1';
69462
70229
  this.s3dbVersion = (() => {
69463
- const [ok, , version] = tryFnSync(() => (typeof globalThis['19.3.3'] !== 'undefined' && globalThis['19.3.3'] !== '19.3.3'
69464
- ? globalThis['19.3.3']
70230
+ const [ok, , version] = tryFnSync(() => (typeof globalThis['19.3.4'] !== 'undefined' && globalThis['19.3.4'] !== '19.3.4'
70231
+ ? globalThis['19.3.4']
69465
70232
  : 'latest'));
69466
70233
  return ok ? version : 'latest';
69467
70234
  })();