@http-client-toolkit/store-sqlite 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -3,7 +3,10 @@ import { sql, eq, count, and, gt, lt, gte } from 'drizzle-orm';
3
3
  import { drizzle } from 'drizzle-orm/better-sqlite3';
4
4
  import { sqliteTable, integer, blob, text } from 'drizzle-orm/sqlite-core';
5
5
  import { randomUUID } from 'crypto';
6
- import { DEFAULT_RATE_LIMIT, AdaptiveCapacityCalculator } from '@http-client-toolkit/core';
6
+ import {
7
+ DEFAULT_RATE_LIMIT,
8
+ AdaptiveCapacityCalculator,
9
+ } from '@http-client-toolkit/core';
7
10
 
8
11
  var __async = (__this, __arguments, generator) => {
9
12
  return new Promise((resolve, reject) => {
@@ -21,48 +24,51 @@ var __async = (__this, __arguments, generator) => {
21
24
  reject(e);
22
25
  }
23
26
  };
24
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
27
+ var step = (x) =>
28
+ x.done
29
+ ? resolve(x.value)
30
+ : Promise.resolve(x.value).then(fulfilled, rejected);
25
31
  step((generator = generator.apply(__this, __arguments)).next());
26
32
  });
27
33
  };
28
- var cacheTable = sqliteTable("cache", {
29
- hash: text("hash").primaryKey(),
30
- value: blob("value", { mode: "json" }).notNull(),
31
- expiresAt: integer("expires_at").notNull(),
32
- createdAt: integer("created_at").notNull()
34
+ var cacheTable = sqliteTable('cache', {
35
+ hash: text('hash').primaryKey(),
36
+ value: blob('value', { mode: 'json' }).notNull(),
37
+ expiresAt: integer('expires_at').notNull(),
38
+ createdAt: integer('created_at').notNull(),
33
39
  });
34
- var dedupeTable = sqliteTable("dedupe_jobs", {
35
- hash: text("hash").primaryKey(),
36
- jobId: text("job_id").notNull(),
37
- status: text("status").notNull(),
40
+ var dedupeTable = sqliteTable('dedupe_jobs', {
41
+ hash: text('hash').primaryKey(),
42
+ jobId: text('job_id').notNull(),
43
+ status: text('status').notNull(),
38
44
  // 'pending', 'completed', 'failed'
39
- result: blob("result", { mode: "json" }),
40
- error: text("error"),
41
- createdAt: integer("created_at").notNull(),
42
- updatedAt: integer("updated_at").notNull()
45
+ result: blob('result', { mode: 'json' }),
46
+ error: text('error'),
47
+ createdAt: integer('created_at').notNull(),
48
+ updatedAt: integer('updated_at').notNull(),
43
49
  });
44
- var rateLimitTable = sqliteTable("rate_limits", {
45
- resource: text("resource").notNull(),
46
- timestamp: integer("timestamp").notNull(),
47
- id: integer("id").primaryKey({ autoIncrement: true })
50
+ var rateLimitTable = sqliteTable('rate_limits', {
51
+ resource: text('resource').notNull(),
52
+ timestamp: integer('timestamp').notNull(),
53
+ id: integer('id').primaryKey({ autoIncrement: true }),
48
54
  });
49
55
 
50
56
  // src/sqlite-cache-store.ts
51
57
  var SQLiteCacheStore = class {
52
58
  constructor({
53
59
  /** File path or existing `better-sqlite3` connection. Defaults to `':memory:'`. */
54
- database = ":memory:",
60
+ database = ':memory:',
55
61
  /** Cleanup interval in milliseconds. Defaults to 1 minute. */
56
62
  cleanupIntervalMs = 6e4,
57
63
  /** Maximum allowed size (in bytes) for a single cache entry. Defaults to 5 MiB. */
58
- maxEntrySizeBytes = 5 * 1024 * 1024
64
+ maxEntrySizeBytes = 5 * 1024 * 1024,
59
65
  } = {}) {
60
66
  /** Indicates whether this store is responsible for managing (and therefore closing) the SQLite connection */
61
67
  this.isConnectionManaged = false;
62
68
  this.isDestroyed = false;
63
69
  let sqliteInstance;
64
70
  let isConnectionManaged = false;
65
- if (typeof database === "string") {
71
+ if (typeof database === 'string') {
66
72
  sqliteInstance = new Database(database);
67
73
  isConnectionManaged = true;
68
74
  } else {
@@ -79,9 +85,13 @@ var SQLiteCacheStore = class {
79
85
  get(hash) {
80
86
  return __async(this, null, function* () {
81
87
  if (this.isDestroyed) {
82
- throw new Error("Cache store has been destroyed");
88
+ throw new Error('Cache store has been destroyed');
83
89
  }
84
- const result = yield this.db.select().from(cacheTable).where(eq(cacheTable.hash, hash)).limit(1);
90
+ const result = yield this.db
91
+ .select()
92
+ .from(cacheTable)
93
+ .where(eq(cacheTable.hash, hash))
94
+ .limit(1);
85
95
  if (result.length === 0) {
86
96
  return void 0;
87
97
  }
@@ -95,7 +105,7 @@ var SQLiteCacheStore = class {
95
105
  return void 0;
96
106
  }
97
107
  try {
98
- if (item.value === "__UNDEFINED__") {
108
+ if (item.value === '__UNDEFINED__') {
99
109
  return void 0;
100
110
  }
101
111
  return JSON.parse(item.value);
@@ -108,44 +118,48 @@ var SQLiteCacheStore = class {
108
118
  set(hash, value, ttlSeconds) {
109
119
  return __async(this, null, function* () {
110
120
  if (this.isDestroyed) {
111
- throw new Error("Cache store has been destroyed");
121
+ throw new Error('Cache store has been destroyed');
112
122
  }
113
123
  const now = Date.now();
114
- const expiresAt = ttlSeconds < 0 ? now : ttlSeconds === 0 ? 0 : now + ttlSeconds * 1e3;
124
+ const expiresAt =
125
+ ttlSeconds < 0 ? now : ttlSeconds === 0 ? 0 : now + ttlSeconds * 1e3;
115
126
  let serializedValue;
116
127
  try {
117
128
  if (value === void 0) {
118
- serializedValue = "__UNDEFINED__";
129
+ serializedValue = '__UNDEFINED__';
119
130
  } else {
120
131
  serializedValue = JSON.stringify(value);
121
132
  }
122
133
  } catch (error) {
123
134
  throw new Error(
124
- `Failed to serialize value: ${error instanceof Error ? error.message : String(error)}`
135
+ `Failed to serialize value: ${error instanceof Error ? error.message : String(error)}`,
125
136
  );
126
137
  }
127
- if (Buffer.byteLength(serializedValue, "utf8") > this.maxEntrySizeBytes) {
138
+ if (Buffer.byteLength(serializedValue, 'utf8') > this.maxEntrySizeBytes) {
128
139
  return;
129
140
  }
130
- yield this.db.insert(cacheTable).values({
131
- hash,
132
- value: serializedValue,
133
- expiresAt,
134
- createdAt: now
135
- }).onConflictDoUpdate({
136
- target: cacheTable.hash,
137
- set: {
141
+ yield this.db
142
+ .insert(cacheTable)
143
+ .values({
144
+ hash,
138
145
  value: serializedValue,
139
146
  expiresAt,
140
- createdAt: now
141
- }
142
- });
147
+ createdAt: now,
148
+ })
149
+ .onConflictDoUpdate({
150
+ target: cacheTable.hash,
151
+ set: {
152
+ value: serializedValue,
153
+ expiresAt,
154
+ createdAt: now,
155
+ },
156
+ });
143
157
  });
144
158
  }
145
159
  delete(hash) {
146
160
  return __async(this, null, function* () {
147
161
  if (this.isDestroyed) {
148
- throw new Error("Cache store has been destroyed");
162
+ throw new Error('Cache store has been destroyed');
149
163
  }
150
164
  yield this.db.delete(cacheTable).where(eq(cacheTable.hash, hash));
151
165
  });
@@ -153,7 +167,7 @@ var SQLiteCacheStore = class {
153
167
  clear() {
154
168
  return __async(this, null, function* () {
155
169
  if (this.isDestroyed) {
156
- throw new Error("Cache store has been destroyed");
170
+ throw new Error('Cache store has been destroyed');
157
171
  }
158
172
  yield this.db.delete(cacheTable);
159
173
  });
@@ -165,19 +179,32 @@ var SQLiteCacheStore = class {
165
179
  return __async(this, null, function* () {
166
180
  var _a, _b, _c, _d;
167
181
  const now = Date.now();
168
- const totalResult = yield this.db.select({ count: count() }).from(cacheTable);
169
- const expiredResult = yield this.db.select({ count: count() }).from(cacheTable).where(and(gt(cacheTable.expiresAt, 0), lt(cacheTable.expiresAt, now)));
182
+ const totalResult = yield this.db
183
+ .select({ count: count() })
184
+ .from(cacheTable);
185
+ const expiredResult = yield this.db
186
+ .select({ count: count() })
187
+ .from(cacheTable)
188
+ .where(and(gt(cacheTable.expiresAt, 0), lt(cacheTable.expiresAt, now)));
170
189
  const pageCount = Number(
171
- this.sqlite.pragma("page_count", { simple: true })
190
+ this.sqlite.pragma('page_count', { simple: true }),
191
+ );
192
+ const pageSize = Number(
193
+ this.sqlite.pragma('page_size', { simple: true }),
172
194
  );
173
- const pageSize = Number(this.sqlite.pragma("page_size", { simple: true }));
174
195
  const safePageCount = Number.isFinite(pageCount) ? pageCount : 0;
175
196
  const safePageSize = Number.isFinite(pageSize) ? pageSize : 0;
176
- const databaseSizeKB = Math.round(safePageCount * safePageSize / 1024);
197
+ const databaseSizeKB = Math.round((safePageCount * safePageSize) / 1024);
177
198
  return {
178
199
  databaseSizeKB,
179
- expiredItems: (_b = (_a = expiredResult[0]) == null ? void 0 : _a.count) != null ? _b : 0,
180
- totalItems: (_d = (_c = totalResult[0]) == null ? void 0 : _c.count) != null ? _d : 0
200
+ expiredItems:
201
+ (_b = (_a = expiredResult[0]) == null ? void 0 : _a.count) != null
202
+ ? _b
203
+ : 0,
204
+ totalItems:
205
+ (_d = (_c = totalResult[0]) == null ? void 0 : _c.count) != null
206
+ ? _d
207
+ : 0,
181
208
  };
182
209
  });
183
210
  }
@@ -187,7 +214,9 @@ var SQLiteCacheStore = class {
187
214
  cleanup() {
188
215
  return __async(this, null, function* () {
189
216
  const now = Date.now();
190
- yield this.db.delete(cacheTable).where(and(gt(cacheTable.expiresAt, 0), lt(cacheTable.expiresAt, now)));
217
+ yield this.db
218
+ .delete(cacheTable)
219
+ .where(and(gt(cacheTable.expiresAt, 0), lt(cacheTable.expiresAt, now)));
191
220
  });
192
221
  }
193
222
  /**
@@ -200,7 +229,7 @@ var SQLiteCacheStore = class {
200
229
  this.cleanupInterval = void 0;
201
230
  }
202
231
  this.isDestroyed = true;
203
- if (this.isConnectionManaged && typeof this.sqlite.close === "function") {
232
+ if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
204
233
  this.sqlite.close();
205
234
  }
206
235
  });
@@ -228,10 +257,14 @@ var SQLiteCacheStore = class {
228
257
  if (this.cleanupIntervalMs <= 0) {
229
258
  return;
230
259
  }
231
- this.cleanupInterval = setInterval(() => __async(this, null, function* () {
232
- yield this.cleanup();
233
- }), this.cleanupIntervalMs);
234
- if (typeof this.cleanupInterval.unref === "function") {
260
+ this.cleanupInterval = setInterval(
261
+ () =>
262
+ __async(this, null, function* () {
263
+ yield this.cleanup();
264
+ }),
265
+ this.cleanupIntervalMs,
266
+ );
267
+ if (typeof this.cleanupInterval.unref === 'function') {
235
268
  this.cleanupInterval.unref();
236
269
  }
237
270
  }
@@ -245,7 +278,7 @@ var SQLiteCacheStore = class {
245
278
  var SQLiteDedupeStore = class {
246
279
  constructor({
247
280
  /** File path or existing `better-sqlite3` Database instance. Defaults to `':memory:'`. */
248
- database = ":memory:",
281
+ database = ':memory:',
249
282
  /** Job timeout in milliseconds. Preferred over timeoutMs. */
250
283
  jobTimeoutMs,
251
284
  /** Legacy alias for jobTimeoutMs. */
@@ -253,7 +286,7 @@ var SQLiteDedupeStore = class {
253
286
  /** Cleanup interval in milliseconds. Defaults to 1 minute. */
254
287
  cleanupIntervalMs = 6e4,
255
288
  /** Poll interval for checking pending jobs in milliseconds. Defaults to 100ms. */
256
- pollIntervalMs = 100
289
+ pollIntervalMs = 100,
257
290
  } = {}) {
258
291
  /** Indicates whether this store manages (and should close) the SQLite connection */
259
292
  this.isConnectionManaged = false;
@@ -263,7 +296,7 @@ var SQLiteDedupeStore = class {
263
296
  var _a;
264
297
  let sqliteInstance;
265
298
  let isConnectionManaged = false;
266
- if (typeof database === "string") {
299
+ if (typeof database === 'string') {
267
300
  sqliteInstance = new Database(database);
268
301
  isConnectionManaged = true;
269
302
  } else {
@@ -272,7 +305,8 @@ var SQLiteDedupeStore = class {
272
305
  this.sqlite = sqliteInstance;
273
306
  this.isConnectionManaged = isConnectionManaged;
274
307
  this.db = drizzle(sqliteInstance);
275
- this.jobTimeoutMs = (_a = timeoutMs != null ? timeoutMs : jobTimeoutMs) != null ? _a : 3e5;
308
+ this.jobTimeoutMs =
309
+ (_a = timeoutMs != null ? timeoutMs : jobTimeoutMs) != null ? _a : 3e5;
276
310
  this.cleanupIntervalMs = cleanupIntervalMs;
277
311
  this.pollIntervalMs = pollIntervalMs;
278
312
  this.initializeDatabase();
@@ -281,10 +315,9 @@ var SQLiteDedupeStore = class {
281
315
  startCleanupInterval() {
282
316
  if (this.cleanupIntervalMs > 0) {
283
317
  this.cleanupInterval = setInterval(() => {
284
- this.cleanupExpiredJobs().catch(() => {
285
- });
318
+ this.cleanupExpiredJobs().catch(() => {});
286
319
  }, this.cleanupIntervalMs);
287
- if (typeof this.cleanupInterval.unref === "function") {
320
+ if (typeof this.cleanupInterval.unref === 'function') {
288
321
  this.cleanupInterval.unref();
289
322
  }
290
323
  }
@@ -297,18 +330,20 @@ var SQLiteDedupeStore = class {
297
330
  }
298
331
  const now = Date.now();
299
332
  const expiredThreshold = now - this.jobTimeoutMs;
300
- yield this.db.delete(dedupeTable).where(
301
- and(
302
- eq(dedupeTable.status, "pending"),
303
- lt(dedupeTable.createdAt, expiredThreshold)
304
- )
305
- );
333
+ yield this.db
334
+ .delete(dedupeTable)
335
+ .where(
336
+ and(
337
+ eq(dedupeTable.status, 'pending'),
338
+ lt(dedupeTable.createdAt, expiredThreshold),
339
+ ),
340
+ );
306
341
  });
307
342
  }
308
343
  waitFor(hash) {
309
344
  return __async(this, null, function* () {
310
345
  if (this.isDestroyed) {
311
- throw new Error("Dedupe store has been destroyed");
346
+ throw new Error('Dedupe store has been destroyed');
312
347
  }
313
348
  const existingPromise = this.jobPromises.get(hash);
314
349
  if (existingPromise) {
@@ -316,7 +351,11 @@ var SQLiteDedupeStore = class {
316
351
  }
317
352
  let result;
318
353
  try {
319
- result = yield this.db.select().from(dedupeTable).where(eq(dedupeTable.hash, hash)).limit(1);
354
+ result = yield this.db
355
+ .select()
356
+ .from(dedupeTable)
357
+ .where(eq(dedupeTable.hash, hash))
358
+ .limit(1);
320
359
  } catch (e) {
321
360
  return void 0;
322
361
  }
@@ -327,10 +366,10 @@ var SQLiteDedupeStore = class {
327
366
  if (!job) {
328
367
  return void 0;
329
368
  }
330
- if (job.status === "completed") {
369
+ if (job.status === 'completed') {
331
370
  return this.deserializeResult(job.result);
332
371
  }
333
- if (job.status === "failed") {
372
+ if (job.status === 'failed') {
334
373
  return void 0;
335
374
  }
336
375
  const promise = new Promise((resolve) => {
@@ -350,43 +389,53 @@ var SQLiteDedupeStore = class {
350
389
  resolve(value);
351
390
  };
352
391
  this.jobSettlers.set(hash, settle);
353
- const poll = () => __async(this, null, function* () {
354
- if (this.isDestroyed) {
355
- settle(void 0);
356
- return;
357
- }
358
- try {
359
- const latest = yield this.db.select().from(dedupeTable).where(eq(dedupeTable.hash, hash)).limit(1);
360
- const latestJob = latest[0];
361
- if (!latestJob) {
362
- settle(void 0);
363
- return;
364
- }
365
- const isExpired = this.jobTimeoutMs > 0 && Date.now() - latestJob.createdAt >= this.jobTimeoutMs;
366
- if (isExpired) {
367
- yield this.db.update(dedupeTable).set({
368
- status: "failed",
369
- error: "Job timed out",
370
- updatedAt: Date.now()
371
- }).where(eq(dedupeTable.hash, hash));
392
+ const poll = () =>
393
+ __async(this, null, function* () {
394
+ if (this.isDestroyed) {
372
395
  settle(void 0);
373
396
  return;
374
397
  }
375
- if (latestJob.status === "completed") {
376
- settle(this.deserializeResult(latestJob.result));
377
- return;
378
- }
379
- if (latestJob.status === "failed") {
398
+ try {
399
+ const latest = yield this.db
400
+ .select()
401
+ .from(dedupeTable)
402
+ .where(eq(dedupeTable.hash, hash))
403
+ .limit(1);
404
+ const latestJob = latest[0];
405
+ if (!latestJob) {
406
+ settle(void 0);
407
+ return;
408
+ }
409
+ const isExpired =
410
+ this.jobTimeoutMs > 0 &&
411
+ Date.now() - latestJob.createdAt >= this.jobTimeoutMs;
412
+ if (isExpired) {
413
+ yield this.db
414
+ .update(dedupeTable)
415
+ .set({
416
+ status: 'failed',
417
+ error: 'Job timed out',
418
+ updatedAt: Date.now(),
419
+ })
420
+ .where(eq(dedupeTable.hash, hash));
421
+ settle(void 0);
422
+ return;
423
+ }
424
+ if (latestJob.status === 'completed') {
425
+ settle(this.deserializeResult(latestJob.result));
426
+ return;
427
+ }
428
+ if (latestJob.status === 'failed') {
429
+ settle(void 0);
430
+ }
431
+ } catch (e) {
380
432
  settle(void 0);
381
433
  }
382
- } catch (e) {
383
- settle(void 0);
384
- }
385
- });
434
+ });
386
435
  const pollHandle = setInterval(() => {
387
436
  void poll();
388
437
  }, this.pollIntervalMs);
389
- if (typeof pollHandle.unref === "function") {
438
+ if (typeof pollHandle.unref === 'function') {
390
439
  pollHandle.unref();
391
440
  }
392
441
  void poll();
@@ -396,20 +445,24 @@ var SQLiteDedupeStore = class {
396
445
  settle(void 0);
397
446
  return;
398
447
  }
399
- void (() => __async(this, null, function* () {
400
- try {
401
- yield this.db.update(dedupeTable).set({
402
- status: "failed",
403
- error: "Job timed out",
404
- updatedAt: Date.now()
405
- }).where(eq(dedupeTable.hash, hash));
406
- } catch (e) {
407
- } finally {
408
- settle(void 0);
409
- }
410
- }))();
448
+ void (() =>
449
+ __async(this, null, function* () {
450
+ try {
451
+ yield this.db
452
+ .update(dedupeTable)
453
+ .set({
454
+ status: 'failed',
455
+ error: 'Job timed out',
456
+ updatedAt: Date.now(),
457
+ })
458
+ .where(eq(dedupeTable.hash, hash));
459
+ } catch (e) {
460
+ } finally {
461
+ settle(void 0);
462
+ }
463
+ }))();
411
464
  }, this.jobTimeoutMs);
412
- if (typeof timeoutHandle.unref === "function") {
465
+ if (typeof timeoutHandle.unref === 'function') {
413
466
  timeoutHandle.unref();
414
467
  }
415
468
  }
@@ -427,23 +480,26 @@ var SQLiteDedupeStore = class {
427
480
  registerOrJoin(hash) {
428
481
  return __async(this, null, function* () {
429
482
  if (this.isDestroyed) {
430
- throw new Error("Dedupe store has been destroyed");
483
+ throw new Error('Dedupe store has been destroyed');
431
484
  }
432
485
  const now = Date.now();
433
486
  const candidateJobId = randomUUID();
434
487
  const registerTransaction = this.sqlite.transaction(
435
488
  (requestHash, createdAt, jobId) => {
436
- const existing = this.sqlite.prepare(
437
- "SELECT job_id as jobId, status FROM dedupe_jobs WHERE hash = ? LIMIT 1"
438
- ).get(requestHash);
439
- if (existing && existing.status === "pending") {
489
+ const existing = this.sqlite
490
+ .prepare(
491
+ 'SELECT job_id as jobId, status FROM dedupe_jobs WHERE hash = ? LIMIT 1',
492
+ )
493
+ .get(requestHash);
494
+ if (existing && existing.status === 'pending') {
440
495
  return {
441
496
  jobId: existing.jobId,
442
- isOwner: false
497
+ isOwner: false,
443
498
  };
444
499
  }
445
- this.sqlite.prepare(
446
- `
500
+ this.sqlite
501
+ .prepare(
502
+ `
447
503
  INSERT INTO dedupe_jobs (hash, job_id, status, result, error, created_at, updated_at)
448
504
  VALUES (?, ?, 'pending', NULL, NULL, ?, ?)
449
505
  ON CONFLICT(hash) DO UPDATE SET
@@ -453,13 +509,14 @@ var SQLiteDedupeStore = class {
453
509
  error = NULL,
454
510
  created_at = excluded.created_at,
455
511
  updated_at = excluded.updated_at
456
- `
457
- ).run(requestHash, jobId, createdAt, createdAt);
512
+ `,
513
+ )
514
+ .run(requestHash, jobId, createdAt, createdAt);
458
515
  return {
459
516
  jobId,
460
- isOwner: true
517
+ isOwner: true,
461
518
  };
462
- }
519
+ },
463
520
  );
464
521
  return registerTransaction(hash, now, candidateJobId);
465
522
  });
@@ -468,32 +525,42 @@ var SQLiteDedupeStore = class {
468
525
  return __async(this, null, function* () {
469
526
  var _a;
470
527
  if (this.isDestroyed) {
471
- throw new Error("Dedupe store has been destroyed");
528
+ throw new Error('Dedupe store has been destroyed');
472
529
  }
473
530
  let serializedResult;
474
531
  if (value === void 0) {
475
- serializedResult = "__UNDEFINED__";
532
+ serializedResult = '__UNDEFINED__';
476
533
  } else if (value === null) {
477
- serializedResult = "__NULL__";
534
+ serializedResult = '__NULL__';
478
535
  } else {
479
536
  try {
480
537
  serializedResult = JSON.stringify(value);
481
538
  } catch (error) {
482
539
  throw new Error(
483
- `Failed to serialize result: ${error instanceof Error ? error.message : String(error)}`
540
+ `Failed to serialize result: ${error instanceof Error ? error.message : String(error)}`,
484
541
  );
485
542
  }
486
543
  }
487
544
  const now = Date.now();
488
- const existingJob = yield this.db.select().from(dedupeTable).where(eq(dedupeTable.hash, hash)).limit(1);
489
- if (existingJob.length > 0 && ((_a = existingJob[0]) == null ? void 0 : _a.status) === "completed") {
545
+ const existingJob = yield this.db
546
+ .select()
547
+ .from(dedupeTable)
548
+ .where(eq(dedupeTable.hash, hash))
549
+ .limit(1);
550
+ if (
551
+ existingJob.length > 0 &&
552
+ ((_a = existingJob[0]) == null ? void 0 : _a.status) === 'completed'
553
+ ) {
490
554
  return;
491
555
  }
492
- yield this.db.update(dedupeTable).set({
493
- status: "completed",
494
- result: serializedResult,
495
- updatedAt: now
496
- }).where(eq(dedupeTable.hash, hash));
556
+ yield this.db
557
+ .update(dedupeTable)
558
+ .set({
559
+ status: 'completed',
560
+ result: serializedResult,
561
+ updatedAt: now,
562
+ })
563
+ .where(eq(dedupeTable.hash, hash));
497
564
  const settle = this.jobSettlers.get(hash);
498
565
  if (settle) {
499
566
  settle(value);
@@ -503,14 +570,17 @@ var SQLiteDedupeStore = class {
503
570
  fail(hash, error) {
504
571
  return __async(this, null, function* () {
505
572
  if (this.isDestroyed) {
506
- throw new Error("Dedupe store has been destroyed");
573
+ throw new Error('Dedupe store has been destroyed');
507
574
  }
508
575
  const now = Date.now();
509
- yield this.db.update(dedupeTable).set({
510
- status: "failed",
511
- error: error.message,
512
- updatedAt: now
513
- }).where(eq(dedupeTable.hash, hash));
576
+ yield this.db
577
+ .update(dedupeTable)
578
+ .set({
579
+ status: 'failed',
580
+ error: error.message,
581
+ updatedAt: now,
582
+ })
583
+ .where(eq(dedupeTable.hash, hash));
514
584
  const settle = this.jobSettlers.get(hash);
515
585
  if (settle) {
516
586
  settle(void 0);
@@ -520,9 +590,13 @@ var SQLiteDedupeStore = class {
520
590
  isInProgress(hash) {
521
591
  return __async(this, null, function* () {
522
592
  if (this.isDestroyed) {
523
- throw new Error("Dedupe store has been destroyed");
593
+ throw new Error('Dedupe store has been destroyed');
524
594
  }
525
- const result = yield this.db.select().from(dedupeTable).where(eq(dedupeTable.hash, hash)).limit(1);
595
+ const result = yield this.db
596
+ .select()
597
+ .from(dedupeTable)
598
+ .where(eq(dedupeTable.hash, hash))
599
+ .limit(1);
526
600
  if (result.length === 0) {
527
601
  return false;
528
602
  }
@@ -530,17 +604,23 @@ var SQLiteDedupeStore = class {
530
604
  if (!job) {
531
605
  return false;
532
606
  }
533
- const jobExpired = this.jobTimeoutMs > 0 && Date.now() - job.createdAt >= this.jobTimeoutMs;
607
+ const jobExpired =
608
+ this.jobTimeoutMs > 0 &&
609
+ Date.now() - job.createdAt >= this.jobTimeoutMs;
534
610
  if (jobExpired) {
535
611
  yield this.db.delete(dedupeTable).where(eq(dedupeTable.hash, hash));
536
612
  return false;
537
613
  }
538
- return job.status === "pending";
614
+ return job.status === 'pending';
539
615
  });
540
616
  }
541
617
  getResult(hash) {
542
618
  return __async(this, null, function* () {
543
- const result = yield this.db.select().from(dedupeTable).where(eq(dedupeTable.hash, hash)).limit(1);
619
+ const result = yield this.db
620
+ .select()
621
+ .from(dedupeTable)
622
+ .where(eq(dedupeTable.hash, hash))
623
+ .limit(1);
544
624
  if (result.length === 0) {
545
625
  return void 0;
546
626
  }
@@ -554,11 +634,11 @@ var SQLiteDedupeStore = class {
554
634
  yield this.db.delete(dedupeTable).where(eq(dedupeTable.hash, hash));
555
635
  return void 0;
556
636
  }
557
- if (job.status === "completed") {
637
+ if (job.status === 'completed') {
558
638
  try {
559
- if (job.result === "__UNDEFINED__") {
639
+ if (job.result === '__UNDEFINED__') {
560
640
  return void 0;
561
- } else if (job.result === "__NULL__") {
641
+ } else if (job.result === '__NULL__') {
562
642
  return null;
563
643
  } else if (job.result) {
564
644
  return JSON.parse(job.result);
@@ -579,17 +659,32 @@ var SQLiteDedupeStore = class {
579
659
  var _a, _b, _c, _d, _e;
580
660
  const now = Date.now();
581
661
  const expiredTime = now - this.jobTimeoutMs;
582
- const totalResult = yield this.db.select({ count: count() }).from(dedupeTable);
583
- const pendingResult = yield this.db.select({ count: count() }).from(dedupeTable).where(eq(dedupeTable.status, "pending"));
584
- const completedResult = yield this.db.select({ count: count() }).from(dedupeTable).where(eq(dedupeTable.status, "completed"));
585
- const failedResult = yield this.db.select({ count: count() }).from(dedupeTable).where(eq(dedupeTable.status, "failed"));
586
- const expiredResult = yield this.db.select({ count: count() }).from(dedupeTable).where(lt(dedupeTable.createdAt, expiredTime));
662
+ const totalResult = yield this.db
663
+ .select({ count: count() })
664
+ .from(dedupeTable);
665
+ const pendingResult = yield this.db
666
+ .select({ count: count() })
667
+ .from(dedupeTable)
668
+ .where(eq(dedupeTable.status, 'pending'));
669
+ const completedResult = yield this.db
670
+ .select({ count: count() })
671
+ .from(dedupeTable)
672
+ .where(eq(dedupeTable.status, 'completed'));
673
+ const failedResult = yield this.db
674
+ .select({ count: count() })
675
+ .from(dedupeTable)
676
+ .where(eq(dedupeTable.status, 'failed'));
677
+ const expiredResult = yield this.db
678
+ .select({ count: count() })
679
+ .from(dedupeTable)
680
+ .where(lt(dedupeTable.createdAt, expiredTime));
587
681
  return {
588
682
  totalJobs: ((_a = totalResult[0]) == null ? void 0 : _a.count) || 0,
589
683
  pendingJobs: ((_b = pendingResult[0]) == null ? void 0 : _b.count) || 0,
590
- completedJobs: ((_c = completedResult[0]) == null ? void 0 : _c.count) || 0,
684
+ completedJobs:
685
+ ((_c = completedResult[0]) == null ? void 0 : _c.count) || 0,
591
686
  failedJobs: ((_d = failedResult[0]) == null ? void 0 : _d.count) || 0,
592
- expiredJobs: ((_e = expiredResult[0]) == null ? void 0 : _e.count) || 0
687
+ expiredJobs: ((_e = expiredResult[0]) == null ? void 0 : _e.count) || 0,
593
688
  };
594
689
  });
595
690
  }
@@ -600,7 +695,9 @@ var SQLiteDedupeStore = class {
600
695
  return __async(this, null, function* () {
601
696
  const now = Date.now();
602
697
  const expiredTime = now - this.jobTimeoutMs;
603
- yield this.db.delete(dedupeTable).where(lt(dedupeTable.createdAt, expiredTime));
698
+ yield this.db
699
+ .delete(dedupeTable)
700
+ .where(lt(dedupeTable.createdAt, expiredTime));
604
701
  });
605
702
  }
606
703
  /**
@@ -631,7 +728,7 @@ var SQLiteDedupeStore = class {
631
728
  }
632
729
  this.jobPromises.clear();
633
730
  this.jobSettlers.clear();
634
- if (this.isConnectionManaged && typeof this.sqlite.close === "function") {
731
+ if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
635
732
  this.sqlite.close();
636
733
  }
637
734
  });
@@ -644,10 +741,10 @@ var SQLiteDedupeStore = class {
644
741
  }
645
742
  deserializeResult(serializedResult) {
646
743
  try {
647
- if (serializedResult === "__UNDEFINED__") {
744
+ if (serializedResult === '__UNDEFINED__') {
648
745
  return void 0;
649
746
  }
650
- if (serializedResult === "__NULL__") {
747
+ if (serializedResult === '__NULL__') {
651
748
  return null;
652
749
  }
653
750
  if (serializedResult) {
@@ -678,11 +775,11 @@ var SQLiteDedupeStore = class {
678
775
  var SQLiteRateLimitStore = class {
679
776
  constructor({
680
777
  /** File path or existing `better-sqlite3` Database instance. Defaults to `':memory:'`. */
681
- database = ":memory:",
778
+ database = ':memory:',
682
779
  /** Global/default rate-limit config applied when a resource-specific override is not provided. */
683
780
  defaultConfig = DEFAULT_RATE_LIMIT,
684
781
  /** Optional per-resource overrides. */
685
- resourceConfigs = /* @__PURE__ */ new Map()
782
+ resourceConfigs = /* @__PURE__ */ new Map(),
686
783
  } = {}) {
687
784
  /** Indicates whether this store manages (and should close) the SQLite connection */
688
785
  this.isConnectionManaged = false;
@@ -690,7 +787,7 @@ var SQLiteRateLimitStore = class {
690
787
  this.isDestroyed = false;
691
788
  let sqliteInstance;
692
789
  let isConnectionManaged = false;
693
- if (typeof database === "string") {
790
+ if (typeof database === 'string') {
694
791
  sqliteInstance = new Database(database);
695
792
  isConnectionManaged = true;
696
793
  } else {
@@ -707,18 +804,21 @@ var SQLiteRateLimitStore = class {
707
804
  return __async(this, null, function* () {
708
805
  var _a;
709
806
  if (this.isDestroyed) {
710
- throw new Error("Rate limit store has been destroyed");
807
+ throw new Error('Rate limit store has been destroyed');
711
808
  }
712
809
  const config = this.resourceConfigs.get(resource) || this.defaultConfig;
713
810
  const now = Date.now();
714
811
  const windowStart = now - config.windowMs;
715
812
  yield this.cleanupExpiredRequests(resource, windowStart);
716
- const result = yield this.db.select({ count: count() }).from(rateLimitTable).where(
717
- and(
718
- eq(rateLimitTable.resource, resource),
719
- gte(rateLimitTable.timestamp, windowStart)
720
- )
721
- );
813
+ const result = yield this.db
814
+ .select({ count: count() })
815
+ .from(rateLimitTable)
816
+ .where(
817
+ and(
818
+ eq(rateLimitTable.resource, resource),
819
+ gte(rateLimitTable.timestamp, windowStart),
820
+ ),
821
+ );
722
822
  const currentCount = ((_a = result[0]) == null ? void 0 : _a.count) || 0;
723
823
  return currentCount < config.limit;
724
824
  });
@@ -726,12 +826,12 @@ var SQLiteRateLimitStore = class {
726
826
  record(resource) {
727
827
  return __async(this, null, function* () {
728
828
  if (this.isDestroyed) {
729
- throw new Error("Rate limit store has been destroyed");
829
+ throw new Error('Rate limit store has been destroyed');
730
830
  }
731
831
  const now = Date.now();
732
832
  yield this.db.insert(rateLimitTable).values({
733
833
  resource,
734
- timestamp: now
834
+ timestamp: now,
735
835
  });
736
836
  });
737
837
  }
@@ -739,41 +839,47 @@ var SQLiteRateLimitStore = class {
739
839
  return __async(this, null, function* () {
740
840
  var _a;
741
841
  if (this.isDestroyed) {
742
- throw new Error("Rate limit store has been destroyed");
842
+ throw new Error('Rate limit store has been destroyed');
743
843
  }
744
844
  const config = this.resourceConfigs.get(resource) || this.defaultConfig;
745
845
  const now = Date.now();
746
846
  const windowStart = now - config.windowMs;
747
847
  yield this.cleanupExpiredRequests(resource, windowStart);
748
- const result = yield this.db.select({ count: count() }).from(rateLimitTable).where(
749
- and(
750
- eq(rateLimitTable.resource, resource),
751
- gte(rateLimitTable.timestamp, windowStart)
752
- )
753
- );
754
- const currentRequests = ((_a = result[0]) == null ? void 0 : _a.count) || 0;
848
+ const result = yield this.db
849
+ .select({ count: count() })
850
+ .from(rateLimitTable)
851
+ .where(
852
+ and(
853
+ eq(rateLimitTable.resource, resource),
854
+ gte(rateLimitTable.timestamp, windowStart),
855
+ ),
856
+ );
857
+ const currentRequests =
858
+ ((_a = result[0]) == null ? void 0 : _a.count) || 0;
755
859
  const remaining = Math.max(0, config.limit - currentRequests);
756
860
  const resetTime = new Date(now + config.windowMs);
757
861
  return {
758
862
  remaining,
759
863
  resetTime,
760
- limit: config.limit
864
+ limit: config.limit,
761
865
  };
762
866
  });
763
867
  }
764
868
  reset(resource) {
765
869
  return __async(this, null, function* () {
766
870
  if (this.isDestroyed) {
767
- throw new Error("Rate limit store has been destroyed");
871
+ throw new Error('Rate limit store has been destroyed');
768
872
  }
769
- yield this.db.delete(rateLimitTable).where(eq(rateLimitTable.resource, resource));
873
+ yield this.db
874
+ .delete(rateLimitTable)
875
+ .where(eq(rateLimitTable.resource, resource));
770
876
  });
771
877
  }
772
878
  getWaitTime(resource) {
773
879
  return __async(this, null, function* () {
774
880
  var _a, _b;
775
881
  if (this.isDestroyed) {
776
- throw new Error("Rate limit store has been destroyed");
882
+ throw new Error('Rate limit store has been destroyed');
777
883
  }
778
884
  const config = this.resourceConfigs.get(resource) || this.defaultConfig;
779
885
  if (config.limit === 0) {
@@ -782,26 +888,36 @@ var SQLiteRateLimitStore = class {
782
888
  const now = Date.now();
783
889
  const windowStart = now - config.windowMs;
784
890
  yield this.cleanupExpiredRequests(resource, windowStart);
785
- const countResult = yield this.db.select({ count: count() }).from(rateLimitTable).where(
786
- and(
787
- eq(rateLimitTable.resource, resource),
788
- gte(rateLimitTable.timestamp, windowStart)
789
- )
790
- );
791
- const currentRequests = ((_a = countResult[0]) == null ? void 0 : _a.count) || 0;
891
+ const countResult = yield this.db
892
+ .select({ count: count() })
893
+ .from(rateLimitTable)
894
+ .where(
895
+ and(
896
+ eq(rateLimitTable.resource, resource),
897
+ gte(rateLimitTable.timestamp, windowStart),
898
+ ),
899
+ );
900
+ const currentRequests =
901
+ ((_a = countResult[0]) == null ? void 0 : _a.count) || 0;
792
902
  if (currentRequests < config.limit) {
793
903
  return 0;
794
904
  }
795
- const oldestResult = yield this.db.select({ timestamp: rateLimitTable.timestamp }).from(rateLimitTable).where(
796
- and(
797
- eq(rateLimitTable.resource, resource),
798
- gte(rateLimitTable.timestamp, windowStart)
905
+ const oldestResult = yield this.db
906
+ .select({ timestamp: rateLimitTable.timestamp })
907
+ .from(rateLimitTable)
908
+ .where(
909
+ and(
910
+ eq(rateLimitTable.resource, resource),
911
+ gte(rateLimitTable.timestamp, windowStart),
912
+ ),
799
913
  )
800
- ).orderBy(rateLimitTable.timestamp).limit(1);
914
+ .orderBy(rateLimitTable.timestamp)
915
+ .limit(1);
801
916
  if (oldestResult.length === 0) {
802
917
  return 0;
803
918
  }
804
- const oldestTimestamp = (_b = oldestResult[0]) == null ? void 0 : _b.timestamp;
919
+ const oldestTimestamp =
920
+ (_b = oldestResult[0]) == null ? void 0 : _b.timestamp;
805
921
  if (oldestTimestamp === void 0) {
806
922
  return 0;
807
923
  }
@@ -828,10 +944,15 @@ var SQLiteRateLimitStore = class {
828
944
  return __async(this, null, function* () {
829
945
  var _a;
830
946
  if (this.isDestroyed) {
831
- throw new Error("Rate limit store has been destroyed");
832
- }
833
- const totalResult = yield this.db.select({ count: count() }).from(rateLimitTable);
834
- const resourcesResult = yield this.db.select({ resource: rateLimitTable.resource }).from(rateLimitTable).groupBy(rateLimitTable.resource);
947
+ throw new Error('Rate limit store has been destroyed');
948
+ }
949
+ const totalResult = yield this.db
950
+ .select({ count: count() })
951
+ .from(rateLimitTable);
952
+ const resourcesResult = yield this.db
953
+ .select({ resource: rateLimitTable.resource })
954
+ .from(rateLimitTable)
955
+ .groupBy(rateLimitTable.resource);
835
956
  const uniqueResources = resourcesResult.length;
836
957
  const rateLimitedResources = [];
837
958
  for (const { resource } of resourcesResult) {
@@ -843,7 +964,7 @@ var SQLiteRateLimitStore = class {
843
964
  return {
844
965
  totalRequests: ((_a = totalResult[0]) == null ? void 0 : _a.count) || 0,
845
966
  uniqueResources,
846
- rateLimitedResources
967
+ rateLimitedResources,
847
968
  };
848
969
  });
849
970
  }
@@ -853,7 +974,7 @@ var SQLiteRateLimitStore = class {
853
974
  clear() {
854
975
  return __async(this, null, function* () {
855
976
  if (this.isDestroyed) {
856
- throw new Error("Rate limit store has been destroyed");
977
+ throw new Error('Rate limit store has been destroyed');
857
978
  }
858
979
  yield this.db.delete(rateLimitTable);
859
980
  });
@@ -864,7 +985,10 @@ var SQLiteRateLimitStore = class {
864
985
  cleanup() {
865
986
  return __async(this, null, function* () {
866
987
  const now = Date.now();
867
- const resources = yield this.db.select({ resource: rateLimitTable.resource }).from(rateLimitTable).groupBy(rateLimitTable.resource);
988
+ const resources = yield this.db
989
+ .select({ resource: rateLimitTable.resource })
990
+ .from(rateLimitTable)
991
+ .groupBy(rateLimitTable.resource);
868
992
  for (const { resource } of resources) {
869
993
  const config = this.resourceConfigs.get(resource) || this.defaultConfig;
870
994
  const windowStart = now - config.windowMs;
@@ -878,7 +1002,7 @@ var SQLiteRateLimitStore = class {
878
1002
  close() {
879
1003
  return __async(this, null, function* () {
880
1004
  this.isDestroyed = true;
881
- if (this.isConnectionManaged && typeof this.sqlite.close === "function") {
1005
+ if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
882
1006
  this.sqlite.close();
883
1007
  }
884
1008
  });
@@ -891,12 +1015,14 @@ var SQLiteRateLimitStore = class {
891
1015
  }
892
1016
  cleanupExpiredRequests(resource, windowStart) {
893
1017
  return __async(this, null, function* () {
894
- yield this.db.delete(rateLimitTable).where(
895
- and(
896
- eq(rateLimitTable.resource, resource),
897
- lt(rateLimitTable.timestamp, windowStart)
898
- )
899
- );
1018
+ yield this.db
1019
+ .delete(rateLimitTable)
1020
+ .where(
1021
+ and(
1022
+ eq(rateLimitTable.resource, resource),
1023
+ lt(rateLimitTable.timestamp, windowStart),
1024
+ ),
1025
+ );
900
1026
  });
901
1027
  }
902
1028
  initializeDatabase() {
@@ -917,15 +1043,15 @@ var SQLiteRateLimitStore = class {
917
1043
  };
918
1044
  var DEFAULT_RATE_LIMIT2 = {
919
1045
  limit: 200,
920
- windowMs: 36e5
1046
+ windowMs: 36e5,
921
1047
  // 1 hour
922
1048
  };
923
1049
  var SqliteAdaptiveRateLimitStore = class {
924
1050
  constructor({
925
- database = ":memory:",
1051
+ database = ':memory:',
926
1052
  defaultConfig = DEFAULT_RATE_LIMIT2,
927
1053
  resourceConfigs = /* @__PURE__ */ new Map(),
928
- adaptiveConfig = {}
1054
+ adaptiveConfig = {},
929
1055
  } = {}) {
930
1056
  /** Indicates whether this store manages (and should close) the SQLite connection */
931
1057
  this.isConnectionManaged = false;
@@ -936,7 +1062,7 @@ var SqliteAdaptiveRateLimitStore = class {
936
1062
  this.cachedCapacity = /* @__PURE__ */ new Map();
937
1063
  let sqliteInstance;
938
1064
  let isConnectionManaged = false;
939
- if (typeof database === "string") {
1065
+ if (typeof database === 'string') {
940
1066
  sqliteInstance = new Database(database);
941
1067
  isConnectionManaged = true;
942
1068
  } else {
@@ -950,33 +1076,33 @@ var SqliteAdaptiveRateLimitStore = class {
950
1076
  this.capacityCalculator = new AdaptiveCapacityCalculator(adaptiveConfig);
951
1077
  this.initializeDatabase();
952
1078
  }
953
- canProceed(resource, priority = "background") {
1079
+ canProceed(resource, priority = 'background') {
954
1080
  return __async(this, null, function* () {
955
1081
  if (this.isDestroyed) {
956
- throw new Error("Rate limit store has been destroyed");
1082
+ throw new Error('Rate limit store has been destroyed');
957
1083
  }
958
1084
  yield this.ensureActivityMetrics(resource);
959
1085
  const metrics = this.getOrCreateActivityMetrics(resource);
960
1086
  const capacity = this.calculateCurrentCapacity(resource, metrics);
961
- if (priority === "background" && capacity.backgroundPaused) {
1087
+ if (priority === 'background' && capacity.backgroundPaused) {
962
1088
  return false;
963
1089
  }
964
- const currentUserRequests = yield this.getCurrentUsage(resource, "user");
1090
+ const currentUserRequests = yield this.getCurrentUsage(resource, 'user');
965
1091
  const currentBackgroundRequests = yield this.getCurrentUsage(
966
1092
  resource,
967
- "background"
1093
+ 'background',
968
1094
  );
969
- if (priority === "user") {
1095
+ if (priority === 'user') {
970
1096
  return currentUserRequests < capacity.userReserved;
971
1097
  } else {
972
1098
  return currentBackgroundRequests < capacity.backgroundMax;
973
1099
  }
974
1100
  });
975
1101
  }
976
- record(resource, priority = "background") {
1102
+ record(resource, priority = 'background') {
977
1103
  return __async(this, null, function* () {
978
1104
  if (this.isDestroyed) {
979
- throw new Error("Rate limit store has been destroyed");
1105
+ throw new Error('Rate limit store has been destroyed');
980
1106
  }
981
1107
  const now = Date.now();
982
1108
  this.db.run(sql`
@@ -984,34 +1110,38 @@ var SqliteAdaptiveRateLimitStore = class {
984
1110
  VALUES (${resource}, ${now}, ${priority})
985
1111
  `);
986
1112
  const metrics = this.getOrCreateActivityMetrics(resource);
987
- if (priority === "user") {
1113
+ if (priority === 'user') {
988
1114
  metrics.recentUserRequests.push(now);
989
1115
  this.cleanupOldRequests(metrics.recentUserRequests);
990
1116
  } else {
991
1117
  metrics.recentBackgroundRequests.push(now);
992
1118
  this.cleanupOldRequests(metrics.recentBackgroundRequests);
993
1119
  }
994
- metrics.userActivityTrend = this.capacityCalculator.calculateActivityTrend(
995
- metrics.recentUserRequests
996
- );
1120
+ metrics.userActivityTrend =
1121
+ this.capacityCalculator.calculateActivityTrend(
1122
+ metrics.recentUserRequests,
1123
+ );
997
1124
  });
998
1125
  }
999
1126
  getStatus(resource) {
1000
1127
  return __async(this, null, function* () {
1001
1128
  if (this.isDestroyed) {
1002
- throw new Error("Rate limit store has been destroyed");
1129
+ throw new Error('Rate limit store has been destroyed');
1003
1130
  }
1004
1131
  yield this.ensureActivityMetrics(resource);
1005
1132
  const metrics = this.getOrCreateActivityMetrics(resource);
1006
1133
  const capacity = this.calculateCurrentCapacity(resource, metrics);
1007
- const currentUserUsage = yield this.getCurrentUsage(resource, "user");
1134
+ const currentUserUsage = yield this.getCurrentUsage(resource, 'user');
1008
1135
  const currentBackgroundUsage = yield this.getCurrentUsage(
1009
1136
  resource,
1010
- "background"
1137
+ 'background',
1011
1138
  );
1012
1139
  const config = this.resourceConfigs.get(resource) || this.defaultConfig;
1013
1140
  return {
1014
- remaining: capacity.userReserved - currentUserUsage + (capacity.backgroundMax - currentBackgroundUsage),
1141
+ remaining:
1142
+ capacity.userReserved -
1143
+ currentUserUsage +
1144
+ (capacity.backgroundMax - currentBackgroundUsage),
1015
1145
  resetTime: new Date(Date.now() + config.windowMs),
1016
1146
  limit: this.getResourceLimit(resource),
1017
1147
  adaptive: {
@@ -1019,28 +1149,30 @@ var SqliteAdaptiveRateLimitStore = class {
1019
1149
  backgroundMax: capacity.backgroundMax,
1020
1150
  backgroundPaused: capacity.backgroundPaused,
1021
1151
  recentUserActivity: this.capacityCalculator.getRecentActivity(
1022
- metrics.recentUserRequests
1152
+ metrics.recentUserRequests,
1023
1153
  ),
1024
- reason: capacity.reason
1025
- }
1154
+ reason: capacity.reason,
1155
+ },
1026
1156
  };
1027
1157
  });
1028
1158
  }
1029
1159
  reset(resource) {
1030
1160
  return __async(this, null, function* () {
1031
1161
  if (this.isDestroyed) {
1032
- throw new Error("Rate limit store has been destroyed");
1162
+ throw new Error('Rate limit store has been destroyed');
1033
1163
  }
1034
- yield this.db.delete(rateLimitTable).where(eq(rateLimitTable.resource, resource));
1164
+ yield this.db
1165
+ .delete(rateLimitTable)
1166
+ .where(eq(rateLimitTable.resource, resource));
1035
1167
  this.activityMetrics.delete(resource);
1036
1168
  this.cachedCapacity.delete(resource);
1037
1169
  this.lastCapacityUpdate.delete(resource);
1038
1170
  });
1039
1171
  }
1040
- getWaitTime(resource, priority = "background") {
1172
+ getWaitTime(resource, priority = 'background') {
1041
1173
  return __async(this, null, function* () {
1042
1174
  if (this.isDestroyed) {
1043
- throw new Error("Rate limit store has been destroyed");
1175
+ throw new Error('Rate limit store has been destroyed');
1044
1176
  }
1045
1177
  const config = this.resourceConfigs.get(resource) || this.defaultConfig;
1046
1178
  if (config.limit === 0) {
@@ -1053,20 +1185,22 @@ var SqliteAdaptiveRateLimitStore = class {
1053
1185
  yield this.ensureActivityMetrics(resource);
1054
1186
  const metrics = this.getOrCreateActivityMetrics(resource);
1055
1187
  const capacity = this.calculateCurrentCapacity(resource, metrics);
1056
- if (priority === "background" && capacity.backgroundPaused) {
1188
+ if (priority === 'background' && capacity.backgroundPaused) {
1057
1189
  return this.capacityCalculator.config.recalculationIntervalMs;
1058
1190
  }
1059
1191
  const now = Date.now();
1060
1192
  const windowStart = now - config.windowMs;
1061
- const oldestResult = this.sqlite.prepare(
1062
- `
1193
+ const oldestResult = this.sqlite
1194
+ .prepare(
1195
+ `
1063
1196
  SELECT timestamp
1064
1197
  FROM rate_limits
1065
1198
  WHERE resource = ? AND COALESCE(priority, 'background') = ? AND timestamp >= ?
1066
1199
  ORDER BY timestamp
1067
1200
  LIMIT 1
1068
- `
1069
- ).get(resource, priority, windowStart);
1201
+ `,
1202
+ )
1203
+ .get(resource, priority, windowStart);
1070
1204
  if (!oldestResult) {
1071
1205
  return 0;
1072
1206
  }
@@ -1097,10 +1231,15 @@ var SqliteAdaptiveRateLimitStore = class {
1097
1231
  return __async(this, null, function* () {
1098
1232
  var _a;
1099
1233
  if (this.isDestroyed) {
1100
- throw new Error("Rate limit store has been destroyed");
1101
- }
1102
- const totalResult = yield this.db.select({ count: count() }).from(rateLimitTable);
1103
- const resourcesResult = yield this.db.select({ resource: rateLimitTable.resource }).from(rateLimitTable).groupBy(rateLimitTable.resource);
1234
+ throw new Error('Rate limit store has been destroyed');
1235
+ }
1236
+ const totalResult = yield this.db
1237
+ .select({ count: count() })
1238
+ .from(rateLimitTable);
1239
+ const resourcesResult = yield this.db
1240
+ .select({ resource: rateLimitTable.resource })
1241
+ .from(rateLimitTable)
1242
+ .groupBy(rateLimitTable.resource);
1104
1243
  const uniqueResources = resourcesResult.length;
1105
1244
  const rateLimitedResources = [];
1106
1245
  for (const { resource } of resourcesResult) {
@@ -1112,7 +1251,7 @@ var SqliteAdaptiveRateLimitStore = class {
1112
1251
  return {
1113
1252
  totalRequests: ((_a = totalResult[0]) == null ? void 0 : _a.count) || 0,
1114
1253
  uniqueResources,
1115
- rateLimitedResources
1254
+ rateLimitedResources,
1116
1255
  };
1117
1256
  });
1118
1257
  }
@@ -1122,7 +1261,7 @@ var SqliteAdaptiveRateLimitStore = class {
1122
1261
  clear() {
1123
1262
  return __async(this, null, function* () {
1124
1263
  if (this.isDestroyed) {
1125
- throw new Error("Rate limit store has been destroyed");
1264
+ throw new Error('Rate limit store has been destroyed');
1126
1265
  }
1127
1266
  yield this.db.delete(rateLimitTable);
1128
1267
  this.activityMetrics.clear();
@@ -1136,7 +1275,10 @@ var SqliteAdaptiveRateLimitStore = class {
1136
1275
  cleanup() {
1137
1276
  return __async(this, null, function* () {
1138
1277
  const now = Date.now();
1139
- const resources = yield this.db.select({ resource: rateLimitTable.resource }).from(rateLimitTable).groupBy(rateLimitTable.resource);
1278
+ const resources = yield this.db
1279
+ .select({ resource: rateLimitTable.resource })
1280
+ .from(rateLimitTable)
1281
+ .groupBy(rateLimitTable.resource);
1140
1282
  for (const { resource } of resources) {
1141
1283
  const config = this.resourceConfigs.get(resource) || this.defaultConfig;
1142
1284
  const windowStart = now - config.windowMs;
@@ -1150,7 +1292,7 @@ var SqliteAdaptiveRateLimitStore = class {
1150
1292
  close() {
1151
1293
  return __async(this, null, function* () {
1152
1294
  this.isDestroyed = true;
1153
- if (this.isConnectionManaged && typeof this.sqlite.close === "function") {
1295
+ if (this.isConnectionManaged && typeof this.sqlite.close === 'function') {
1154
1296
  this.sqlite.close();
1155
1297
  }
1156
1298
  });
@@ -1164,15 +1306,18 @@ var SqliteAdaptiveRateLimitStore = class {
1164
1306
  // Private helper methods for adaptive functionality
1165
1307
  calculateCurrentCapacity(resource, metrics) {
1166
1308
  const lastUpdate = this.lastCapacityUpdate.get(resource) || 0;
1167
- const recalcInterval = this.capacityCalculator.config.recalculationIntervalMs;
1309
+ const recalcInterval =
1310
+ this.capacityCalculator.config.recalculationIntervalMs;
1168
1311
  if (Date.now() - lastUpdate < recalcInterval) {
1169
- return this.cachedCapacity.get(resource) || this.getDefaultCapacity(resource);
1312
+ return (
1313
+ this.cachedCapacity.get(resource) || this.getDefaultCapacity(resource)
1314
+ );
1170
1315
  }
1171
1316
  const totalLimit = this.getResourceLimit(resource);
1172
1317
  const capacity = this.capacityCalculator.calculateDynamicCapacity(
1173
1318
  resource,
1174
1319
  totalLimit,
1175
- metrics
1320
+ metrics,
1176
1321
  );
1177
1322
  this.cachedCapacity.set(resource, capacity);
1178
1323
  this.lastCapacityUpdate.set(resource, Date.now());
@@ -1183,7 +1328,7 @@ var SqliteAdaptiveRateLimitStore = class {
1183
1328
  this.activityMetrics.set(resource, {
1184
1329
  recentUserRequests: [],
1185
1330
  recentBackgroundRequests: [],
1186
- userActivityTrend: "none"
1331
+ userActivityTrend: 'none',
1187
1332
  });
1188
1333
  }
1189
1334
  return this.activityMetrics.get(resource);
@@ -1194,30 +1339,34 @@ var SqliteAdaptiveRateLimitStore = class {
1194
1339
  return;
1195
1340
  }
1196
1341
  const now = Date.now();
1197
- const windowStart = now - this.capacityCalculator.config.monitoringWindowMs;
1198
- const recentRequests = this.sqlite.prepare(
1199
- `
1342
+ const windowStart =
1343
+ now - this.capacityCalculator.config.monitoringWindowMs;
1344
+ const recentRequests = this.sqlite
1345
+ .prepare(
1346
+ `
1200
1347
  SELECT timestamp, COALESCE(priority, 'background') as priority
1201
1348
  FROM rate_limits
1202
1349
  WHERE resource = ? AND timestamp >= ?
1203
1350
  ORDER BY timestamp
1204
- `
1205
- ).all(resource, windowStart);
1351
+ `,
1352
+ )
1353
+ .all(resource, windowStart);
1206
1354
  const metrics = {
1207
1355
  recentUserRequests: [],
1208
1356
  recentBackgroundRequests: [],
1209
- userActivityTrend: "none"
1357
+ userActivityTrend: 'none',
1210
1358
  };
1211
1359
  for (const request of recentRequests) {
1212
- if (request.priority === "user") {
1360
+ if (request.priority === 'user') {
1213
1361
  metrics.recentUserRequests.push(request.timestamp);
1214
1362
  } else {
1215
1363
  metrics.recentBackgroundRequests.push(request.timestamp);
1216
1364
  }
1217
1365
  }
1218
- metrics.userActivityTrend = this.capacityCalculator.calculateActivityTrend(
1219
- metrics.recentUserRequests
1220
- );
1366
+ metrics.userActivityTrend =
1367
+ this.capacityCalculator.calculateActivityTrend(
1368
+ metrics.recentUserRequests,
1369
+ );
1221
1370
  this.activityMetrics.set(resource, metrics);
1222
1371
  });
1223
1372
  }
@@ -1227,18 +1376,21 @@ var SqliteAdaptiveRateLimitStore = class {
1227
1376
  const now = Date.now();
1228
1377
  const windowStart = now - config.windowMs;
1229
1378
  yield this.cleanupExpiredRequests(resource, windowStart);
1230
- const result = this.sqlite.prepare(
1231
- `
1379
+ const result = this.sqlite
1380
+ .prepare(
1381
+ `
1232
1382
  SELECT COUNT(*) as count
1233
1383
  FROM rate_limits
1234
1384
  WHERE resource = ? AND priority = ? AND timestamp >= ?
1235
- `
1236
- ).get(resource, priority, windowStart);
1385
+ `,
1386
+ )
1387
+ .get(resource, priority, windowStart);
1237
1388
  return result.count || 0;
1238
1389
  });
1239
1390
  }
1240
1391
  cleanupOldRequests(requests) {
1241
- const cutoff = Date.now() - this.capacityCalculator.config.monitoringWindowMs;
1392
+ const cutoff =
1393
+ Date.now() - this.capacityCalculator.config.monitoringWindowMs;
1242
1394
  while (requests.length > 0 && requests[0] < cutoff) {
1243
1395
  requests.shift();
1244
1396
  }
@@ -1253,17 +1405,19 @@ var SqliteAdaptiveRateLimitStore = class {
1253
1405
  userReserved: Math.floor(limit * 0.3),
1254
1406
  backgroundMax: Math.floor(limit * 0.7),
1255
1407
  backgroundPaused: false,
1256
- reason: "Default capacity allocation"
1408
+ reason: 'Default capacity allocation',
1257
1409
  };
1258
1410
  }
1259
1411
  cleanupExpiredRequests(resource, windowStart) {
1260
1412
  return __async(this, null, function* () {
1261
- yield this.db.delete(rateLimitTable).where(
1262
- and(
1263
- eq(rateLimitTable.resource, resource),
1264
- lt(rateLimitTable.timestamp, windowStart)
1265
- )
1266
- );
1413
+ yield this.db
1414
+ .delete(rateLimitTable)
1415
+ .where(
1416
+ and(
1417
+ eq(rateLimitTable.resource, resource),
1418
+ lt(rateLimitTable.timestamp, windowStart),
1419
+ ),
1420
+ );
1267
1421
  });
1268
1422
  }
1269
1423
  initializeDatabase() {
@@ -1279,8 +1433,7 @@ var SqliteAdaptiveRateLimitStore = class {
1279
1433
  this.db.run(sql`
1280
1434
  ALTER TABLE rate_limits ADD COLUMN priority TEXT DEFAULT 'background'
1281
1435
  `);
1282
- } catch (e) {
1283
- }
1436
+ } catch (e) {}
1284
1437
  this.db.run(sql`
1285
1438
  CREATE INDEX IF NOT EXISTS idx_rate_limit_resource ON rate_limits(resource)
1286
1439
  `);
@@ -1294,6 +1447,14 @@ var SqliteAdaptiveRateLimitStore = class {
1294
1447
  }
1295
1448
  };
1296
1449
 
1297
- export { SQLiteCacheStore, SQLiteDedupeStore, SQLiteRateLimitStore, SqliteAdaptiveRateLimitStore, cacheTable, dedupeTable, rateLimitTable };
1450
+ export {
1451
+ SQLiteCacheStore,
1452
+ SQLiteDedupeStore,
1453
+ SQLiteRateLimitStore,
1454
+ SqliteAdaptiveRateLimitStore,
1455
+ cacheTable,
1456
+ dedupeTable,
1457
+ rateLimitTable,
1458
+ };
1459
+ //# sourceMappingURL=index.js.map
1298
1460
  //# sourceMappingURL=index.js.map
1299
- //# sourceMappingURL=index.js.map