recker 1.0.12-alpha.04c18a7 → 1.0.12-alpha.1ab8aa7

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.
@@ -1,30 +1,453 @@
1
+ import zlib from 'node:zlib';
2
+ import os from 'node:os';
3
+ import { getEffectiveTotalMemoryBytes, resolveCacheMemoryLimit, formatBytes, getHeapStats, } from './memory-limits.js';
1
4
  export class MemoryStorage {
2
5
  storage = new Map();
3
- ttls = new Map();
6
+ meta = new Map();
7
+ maxSize;
8
+ maxMemoryBytes;
9
+ maxMemoryPercent;
10
+ defaultTtl;
11
+ evictionPolicy;
12
+ compressionEnabled;
13
+ compressionThreshold;
14
+ enableStats;
15
+ heapUsageThreshold;
16
+ onEvict;
17
+ onPressure;
18
+ currentMemoryBytes = 0;
19
+ evictedDueToMemory = 0;
20
+ memoryPressureEvents = 0;
21
+ accessCounter = 0;
22
+ monitorHandle = null;
23
+ cleanupHandle = null;
24
+ stats = {
25
+ hits: 0,
26
+ misses: 0,
27
+ sets: 0,
28
+ deletes: 0,
29
+ evictions: 0,
30
+ };
31
+ compressionStats = {
32
+ totalCompressed: 0,
33
+ totalOriginalSize: 0,
34
+ totalCompressedSize: 0,
35
+ };
36
+ constructor(options = {}) {
37
+ if (options.maxMemoryBytes &&
38
+ options.maxMemoryBytes > 0 &&
39
+ options.maxMemoryPercent &&
40
+ options.maxMemoryPercent > 0) {
41
+ throw new Error('[MemoryStorage] Cannot use both maxMemoryBytes and maxMemoryPercent');
42
+ }
43
+ if (options.maxMemoryPercent !== undefined &&
44
+ (options.maxMemoryPercent < 0 || options.maxMemoryPercent > 1)) {
45
+ throw new Error('[MemoryStorage] maxMemoryPercent must be between 0 and 1');
46
+ }
47
+ this.maxSize = options.maxSize ?? 1000;
48
+ this.defaultTtl = options.ttl ?? 300000;
49
+ this.evictionPolicy = options.evictionPolicy ?? 'lru';
50
+ this.enableStats = options.enableStats ?? false;
51
+ this.heapUsageThreshold = options.heapUsageThreshold ?? 0.6;
52
+ if (options.maxMemoryBytes && options.maxMemoryBytes > 0) {
53
+ this.maxMemoryBytes = options.maxMemoryBytes;
54
+ this.maxMemoryPercent = 0;
55
+ }
56
+ else if (options.maxMemoryPercent && options.maxMemoryPercent > 0) {
57
+ const effectiveTotal = getEffectiveTotalMemoryBytes();
58
+ this.maxMemoryBytes = Math.floor(effectiveTotal * options.maxMemoryPercent);
59
+ this.maxMemoryPercent = options.maxMemoryPercent;
60
+ }
61
+ else {
62
+ const resolved = resolveCacheMemoryLimit({});
63
+ this.maxMemoryBytes = resolved.maxMemoryBytes;
64
+ this.maxMemoryPercent = resolved.inferredPercent ?? 0;
65
+ }
66
+ if (options.compression === true) {
67
+ this.compressionEnabled = true;
68
+ this.compressionThreshold = 1024;
69
+ }
70
+ else if (typeof options.compression === 'object' &&
71
+ options.compression.enabled) {
72
+ this.compressionEnabled = true;
73
+ this.compressionThreshold = options.compression.threshold ?? 1024;
74
+ }
75
+ else {
76
+ this.compressionEnabled = false;
77
+ this.compressionThreshold = 1024;
78
+ }
79
+ this.onEvict = options.onEvict;
80
+ this.onPressure = options.onPressure;
81
+ const monitorInterval = options.monitorInterval ?? 15000;
82
+ if (monitorInterval > 0) {
83
+ this.monitorHandle = setInterval(() => this.memoryHealthCheck(), monitorInterval);
84
+ this.monitorHandle.unref();
85
+ }
86
+ const cleanupInterval = options.cleanupInterval ?? 60000;
87
+ if (cleanupInterval > 0) {
88
+ this.cleanupHandle = setInterval(() => this.cleanupExpired(), cleanupInterval);
89
+ this.cleanupHandle.unref();
90
+ }
91
+ }
4
92
  async get(key) {
5
- const entry = this.storage.get(key);
6
- if (!entry) {
93
+ const data = this.storage.get(key);
94
+ const metadata = this.meta.get(key);
95
+ if (!data || !metadata) {
96
+ this.recordStat('misses');
7
97
  return undefined;
8
98
  }
9
- const expiry = this.ttls.get(key);
10
- if (expiry && Date.now() > expiry) {
11
- this.delete(key);
99
+ const now = Date.now();
100
+ if (now > metadata.expiresAt) {
101
+ this.deleteInternal(key);
102
+ this.recordStat('misses');
12
103
  return undefined;
13
104
  }
14
- return entry;
105
+ if (this.evictionPolicy === 'lru') {
106
+ metadata.lastAccess = now;
107
+ metadata.accessOrder = ++this.accessCounter;
108
+ }
109
+ this.recordStat('hits');
110
+ if (this.isCompressed(data)) {
111
+ try {
112
+ const decompressed = this.decompress(data);
113
+ return JSON.parse(decompressed);
114
+ }
115
+ catch {
116
+ this.deleteInternal(key);
117
+ return undefined;
118
+ }
119
+ }
120
+ return JSON.parse(data);
15
121
  }
16
122
  async set(key, entry, ttl) {
17
- this.storage.set(key, entry);
18
- if (ttl) {
19
- this.ttls.set(key, Date.now() + ttl);
123
+ const effectiveTtl = ttl ?? this.defaultTtl;
124
+ const now = Date.now();
125
+ const serialized = JSON.stringify(entry);
126
+ const originalSize = Buffer.byteLength(serialized, 'utf8');
127
+ let finalData = serialized;
128
+ let compressedSize = originalSize;
129
+ let compressed = false;
130
+ if (this.compressionEnabled && originalSize >= this.compressionThreshold) {
131
+ try {
132
+ const result = this.compress(serialized);
133
+ finalData = result;
134
+ compressedSize = Buffer.byteLength(result.__data, 'utf8');
135
+ compressed = true;
136
+ this.compressionStats.totalCompressed++;
137
+ this.compressionStats.totalOriginalSize += originalSize;
138
+ this.compressionStats.totalCompressedSize += compressedSize;
139
+ }
140
+ catch {
141
+ }
20
142
  }
143
+ const existingMeta = this.meta.get(key);
144
+ if (existingMeta) {
145
+ this.currentMemoryBytes -= existingMeta.compressedSize;
146
+ }
147
+ if (!this.enforceMemoryLimit(compressedSize)) {
148
+ this.evictedDueToMemory++;
149
+ return;
150
+ }
151
+ if (!existingMeta && this.storage.size >= this.maxSize) {
152
+ this.evictOne('size');
153
+ }
154
+ this.storage.set(key, finalData);
155
+ this.meta.set(key, {
156
+ createdAt: now,
157
+ expiresAt: now + effectiveTtl,
158
+ lastAccess: now,
159
+ insertOrder: ++this.accessCounter,
160
+ accessOrder: this.accessCounter,
161
+ compressed,
162
+ originalSize,
163
+ compressedSize,
164
+ });
165
+ this.currentMemoryBytes += compressedSize;
166
+ this.recordStat('sets');
21
167
  }
22
168
  async delete(key) {
169
+ this.deleteInternal(key);
170
+ this.recordStat('deletes');
171
+ }
172
+ clear(prefix) {
173
+ if (!prefix) {
174
+ this.storage.clear();
175
+ this.meta.clear();
176
+ this.currentMemoryBytes = 0;
177
+ this.evictedDueToMemory = 0;
178
+ if (this.enableStats) {
179
+ this.stats = { hits: 0, misses: 0, sets: 0, deletes: 0, evictions: 0 };
180
+ }
181
+ return;
182
+ }
183
+ for (const key of this.storage.keys()) {
184
+ if (key.startsWith(prefix)) {
185
+ this.deleteInternal(key);
186
+ }
187
+ }
188
+ }
189
+ size() {
190
+ return this.storage.size;
191
+ }
192
+ keys() {
193
+ return Array.from(this.storage.keys());
194
+ }
195
+ has(key) {
196
+ const meta = this.meta.get(key);
197
+ if (!meta)
198
+ return false;
199
+ if (Date.now() > meta.expiresAt) {
200
+ this.deleteInternal(key);
201
+ return false;
202
+ }
203
+ return true;
204
+ }
205
+ getStats() {
206
+ const total = this.stats.hits + this.stats.misses;
207
+ const hitRate = total > 0 ? this.stats.hits / total : 0;
208
+ return {
209
+ enabled: this.enableStats,
210
+ ...this.stats,
211
+ hitRate,
212
+ totalItems: this.storage.size,
213
+ memoryUsageBytes: this.currentMemoryBytes,
214
+ maxMemoryBytes: this.maxMemoryBytes,
215
+ evictedDueToMemory: this.evictedDueToMemory,
216
+ };
217
+ }
218
+ getMemoryStats() {
219
+ const totalItems = this.storage.size;
220
+ const memoryUsagePercent = this.maxMemoryBytes > 0
221
+ ? (this.currentMemoryBytes / this.maxMemoryBytes) * 100
222
+ : 0;
223
+ const systemTotal = os.totalmem();
224
+ const systemFree = os.freemem();
225
+ const systemUsed = systemTotal - systemFree;
226
+ const cachePercentOfSystem = systemTotal > 0 ? (this.currentMemoryBytes / systemTotal) * 100 : 0;
227
+ return {
228
+ currentMemoryBytes: this.currentMemoryBytes,
229
+ maxMemoryBytes: this.maxMemoryBytes,
230
+ maxMemoryPercent: this.maxMemoryPercent,
231
+ memoryUsagePercent: parseFloat(memoryUsagePercent.toFixed(2)),
232
+ cachePercentOfSystemMemory: parseFloat(cachePercentOfSystem.toFixed(2)),
233
+ totalItems,
234
+ maxSize: this.maxSize,
235
+ evictedDueToMemory: this.evictedDueToMemory,
236
+ memoryPressureEvents: this.memoryPressureEvents,
237
+ averageItemSize: totalItems > 0 ? Math.round(this.currentMemoryBytes / totalItems) : 0,
238
+ memoryUsage: {
239
+ current: formatBytes(this.currentMemoryBytes),
240
+ max: formatBytes(this.maxMemoryBytes),
241
+ available: formatBytes(Math.max(0, this.maxMemoryBytes - this.currentMemoryBytes)),
242
+ },
243
+ systemMemory: {
244
+ total: formatBytes(systemTotal),
245
+ free: formatBytes(systemFree),
246
+ used: formatBytes(systemUsed),
247
+ cachePercent: `${cachePercentOfSystem.toFixed(2)}%`,
248
+ },
249
+ };
250
+ }
251
+ getCompressionStats() {
252
+ if (!this.compressionEnabled) {
253
+ return {
254
+ enabled: false,
255
+ totalItems: this.storage.size,
256
+ compressedItems: 0,
257
+ compressionThreshold: this.compressionThreshold,
258
+ totalOriginalSize: 0,
259
+ totalCompressedSize: 0,
260
+ averageCompressionRatio: '0',
261
+ spaceSavingsPercent: '0',
262
+ memoryUsage: {
263
+ uncompressed: '0 B',
264
+ compressed: '0 B',
265
+ saved: '0 B',
266
+ },
267
+ };
268
+ }
269
+ const ratio = this.compressionStats.totalOriginalSize > 0
270
+ ? (this.compressionStats.totalCompressedSize /
271
+ this.compressionStats.totalOriginalSize).toFixed(2)
272
+ : '0';
273
+ const savings = this.compressionStats.totalOriginalSize > 0
274
+ ? (((this.compressionStats.totalOriginalSize -
275
+ this.compressionStats.totalCompressedSize) /
276
+ this.compressionStats.totalOriginalSize) *
277
+ 100).toFixed(2)
278
+ : '0';
279
+ const saved = this.compressionStats.totalOriginalSize -
280
+ this.compressionStats.totalCompressedSize;
281
+ return {
282
+ enabled: true,
283
+ totalItems: this.storage.size,
284
+ compressedItems: this.compressionStats.totalCompressed,
285
+ compressionThreshold: this.compressionThreshold,
286
+ totalOriginalSize: this.compressionStats.totalOriginalSize,
287
+ totalCompressedSize: this.compressionStats.totalCompressedSize,
288
+ averageCompressionRatio: ratio,
289
+ spaceSavingsPercent: savings,
290
+ memoryUsage: {
291
+ uncompressed: formatBytes(this.compressionStats.totalOriginalSize),
292
+ compressed: formatBytes(this.compressionStats.totalCompressedSize),
293
+ saved: formatBytes(saved),
294
+ },
295
+ };
296
+ }
297
+ shutdown() {
298
+ if (this.monitorHandle) {
299
+ clearInterval(this.monitorHandle);
300
+ this.monitorHandle = null;
301
+ }
302
+ if (this.cleanupHandle) {
303
+ clearInterval(this.cleanupHandle);
304
+ this.cleanupHandle = null;
305
+ }
306
+ }
307
+ deleteInternal(key) {
308
+ const meta = this.meta.get(key);
309
+ if (meta) {
310
+ this.currentMemoryBytes -= meta.compressedSize;
311
+ }
23
312
  this.storage.delete(key);
24
- this.ttls.delete(key);
313
+ this.meta.delete(key);
25
314
  }
26
- clear() {
27
- this.storage.clear();
28
- this.ttls.clear();
315
+ recordStat(type) {
316
+ if (this.enableStats) {
317
+ this.stats[type]++;
318
+ }
319
+ }
320
+ isCompressed(data) {
321
+ return (typeof data === 'object' && data !== null && '__compressed' in data);
322
+ }
323
+ compress(data) {
324
+ const buffer = Buffer.from(data, 'utf8');
325
+ const compressed = zlib.gzipSync(buffer);
326
+ return {
327
+ __compressed: true,
328
+ __data: compressed.toString('base64'),
329
+ __originalSize: buffer.length,
330
+ };
331
+ }
332
+ decompress(data) {
333
+ const buffer = Buffer.from(data.__data, 'base64');
334
+ const decompressed = zlib.gunzipSync(buffer);
335
+ return decompressed.toString('utf8');
336
+ }
337
+ selectEvictionCandidate() {
338
+ if (this.meta.size === 0)
339
+ return null;
340
+ let candidate = null;
341
+ let candidateValue = this.evictionPolicy === 'lru' ? Infinity : Infinity;
342
+ for (const [key, meta] of this.meta) {
343
+ const value = this.evictionPolicy === 'lru' ? meta.accessOrder : meta.insertOrder;
344
+ if (value < candidateValue) {
345
+ candidateValue = value;
346
+ candidate = key;
347
+ }
348
+ }
349
+ return candidate;
350
+ }
351
+ evictOne(reason) {
352
+ const candidate = this.selectEvictionCandidate();
353
+ if (!candidate)
354
+ return null;
355
+ const meta = this.meta.get(candidate);
356
+ const freedBytes = meta?.compressedSize ?? 0;
357
+ this.deleteInternal(candidate);
358
+ this.stats.evictions++;
359
+ if (reason === 'memory' || reason === 'heap') {
360
+ this.evictedDueToMemory++;
361
+ }
362
+ this.onEvict?.({
363
+ reason,
364
+ key: candidate,
365
+ freedBytes,
366
+ currentBytes: this.currentMemoryBytes,
367
+ maxMemoryBytes: this.maxMemoryBytes,
368
+ });
369
+ return { key: candidate, freedBytes };
370
+ }
371
+ enforceMemoryLimit(incomingSize) {
372
+ if (incomingSize > this.maxMemoryBytes) {
373
+ return false;
374
+ }
375
+ while (this.currentMemoryBytes + incomingSize > this.maxMemoryBytes &&
376
+ this.storage.size > 0) {
377
+ const result = this.evictOne('memory');
378
+ if (!result)
379
+ break;
380
+ }
381
+ return this.currentMemoryBytes + incomingSize <= this.maxMemoryBytes;
382
+ }
383
+ reduceMemoryTo(targetBytes) {
384
+ targetBytes = Math.max(0, targetBytes);
385
+ let freedBytes = 0;
386
+ while (this.currentMemoryBytes > targetBytes && this.storage.size > 0) {
387
+ const result = this.evictOne('memory');
388
+ if (!result)
389
+ break;
390
+ freedBytes += result.freedBytes;
391
+ }
392
+ return freedBytes;
393
+ }
394
+ memoryHealthCheck() {
395
+ let totalFreed = 0;
396
+ if (this.currentMemoryBytes > this.maxMemoryBytes) {
397
+ const before = this.currentMemoryBytes;
398
+ this.enforceMemoryLimit(0);
399
+ const freed = before - this.currentMemoryBytes;
400
+ if (freed > 0) {
401
+ totalFreed += freed;
402
+ this.memoryPressureEvents++;
403
+ this.onPressure?.({
404
+ reason: 'limit',
405
+ heapLimit: getHeapStats().heapLimit,
406
+ heapUsed: getHeapStats().heapUsed,
407
+ currentBytes: this.currentMemoryBytes,
408
+ maxMemoryBytes: this.maxMemoryBytes,
409
+ freedBytes: freed,
410
+ });
411
+ }
412
+ }
413
+ const { heapUsed, heapLimit, heapRatio } = getHeapStats();
414
+ if (heapLimit > 0 && heapRatio >= this.heapUsageThreshold) {
415
+ const before = this.currentMemoryBytes;
416
+ const target = Math.floor(this.currentMemoryBytes * 0.5);
417
+ this.reduceMemoryTo(target);
418
+ const freed = before - this.currentMemoryBytes;
419
+ if (freed > 0) {
420
+ totalFreed += freed;
421
+ this.memoryPressureEvents++;
422
+ this.onPressure?.({
423
+ reason: 'heap',
424
+ heapLimit,
425
+ heapUsed,
426
+ heapRatio,
427
+ currentBytes: this.currentMemoryBytes,
428
+ maxMemoryBytes: this.maxMemoryBytes,
429
+ freedBytes: freed,
430
+ });
431
+ }
432
+ }
433
+ return totalFreed;
434
+ }
435
+ cleanupExpired() {
436
+ const now = Date.now();
437
+ let cleaned = 0;
438
+ for (const [key, meta] of this.meta) {
439
+ if (now > meta.expiresAt) {
440
+ this.deleteInternal(key);
441
+ cleaned++;
442
+ this.onEvict?.({
443
+ reason: 'expired',
444
+ key,
445
+ freedBytes: meta.compressedSize,
446
+ currentBytes: this.currentMemoryBytes,
447
+ maxMemoryBytes: this.maxMemoryBytes,
448
+ });
449
+ }
450
+ }
451
+ return cleaned;
29
452
  }
30
453
  }
package/dist/index.d.ts CHANGED
@@ -18,6 +18,7 @@ export * from './cookies/memory-cookie-jar.js';
18
18
  export * from './runner/request-runner.js';
19
19
  export * from './contract/index.js';
20
20
  export * from './cache/memory-storage.js';
21
+ export * from './cache/memory-limits.js';
21
22
  export * from './cache/file-storage.js';
22
23
  export * from './utils/body.js';
23
24
  export * from './plugins/xsrf.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAC;AAGlD,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAC;AAGlD,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ export * from './cookies/memory-cookie-jar.js';
18
18
  export * from './runner/request-runner.js';
19
19
  export * from './contract/index.js';
20
20
  export * from './cache/memory-storage.js';
21
+ export * from './cache/memory-limits.js';
21
22
  export * from './cache/file-storage.js';
22
23
  export * from './utils/body.js';
23
24
  export * from './plugins/xsrf.js';
@@ -0,0 +1,28 @@
1
+ import type { IndexedDoc, SearchResult, SearchOptions, HybridSearchConfig } from './types.js';
2
+ export declare class HybridSearch {
3
+ private fuse;
4
+ private docs;
5
+ private vectors;
6
+ private embeddingsData;
7
+ private initialized;
8
+ private config;
9
+ constructor(config?: HybridSearchConfig);
10
+ initialize(docs: IndexedDoc[]): Promise<void>;
11
+ private loadPrecomputedEmbeddings;
12
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
13
+ private fuzzySearch;
14
+ private semanticSearch;
15
+ private extractSnippet;
16
+ private tokenize;
17
+ private averageVectors;
18
+ hasEmbeddings(): boolean;
19
+ getStats(): {
20
+ documents: number;
21
+ embeddings: number;
22
+ model?: string;
23
+ dimensions?: number;
24
+ };
25
+ private log;
26
+ }
27
+ export declare function createHybridSearch(config?: HybridSearchConfig): HybridSearch;
28
+ //# sourceMappingURL=hybrid-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid-search.d.ts","sourceRoot":"","sources":["../../../src/mcp/search/hybrid-search.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AAkBpB,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAA+B;gBAEjC,MAAM,GAAE,kBAAuB;IAYrC,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YA6BrC,yBAAyB;IAuDjC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA4CjF,OAAO,CAAC,WAAW;IAiCnB,OAAO,CAAC,cAAc;IA8GtB,OAAO,CAAC,cAAc;IAoDtB,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,cAAc;IAmBtB,aAAa,IAAI,OAAO;IAOxB,QAAQ,IAAI;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB;IAYD,OAAO,CAAC,GAAG;CAKZ;AAKD,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,YAAY,CAE5E"}