@lensjs/core 2.2.2 → 2.3.1

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.
Files changed (89) hide show
  1. package/dist/abstracts/store.cjs +3 -0
  2. package/dist/abstracts/store.d.cts +3 -1
  3. package/dist/abstracts/store.d.ts +3 -1
  4. package/dist/abstracts/store.js +3 -0
  5. package/dist/core/lens.cjs +151 -24
  6. package/dist/core/lens.d.cts +3 -2
  7. package/dist/core/lens.d.ts +3 -2
  8. package/dist/core/lens.js +151 -24
  9. package/dist/{index-CMvlRWcQ.d.cts → index-CZsa0Zcm.d.ts} +3 -1
  10. package/dist/{index-CMvlRWcQ.d.ts → index-QmOJr0K-.d.cts} +3 -1
  11. package/dist/index.cjs +199 -29
  12. package/dist/index.d.cts +5 -2
  13. package/dist/index.d.ts +5 -2
  14. package/dist/index.js +198 -29
  15. package/dist/mixins/queued_store.cjs +114 -0
  16. package/dist/mixins/queued_store.d.cts +38 -0
  17. package/dist/mixins/queued_store.d.ts +38 -0
  18. package/dist/mixins/queued_store.js +79 -0
  19. package/dist/stores/better_sqlite.cjs +36 -0
  20. package/dist/stores/better_sqlite.d.cts +3 -0
  21. package/dist/stores/better_sqlite.d.ts +3 -0
  22. package/dist/stores/better_sqlite.js +36 -0
  23. package/dist/stores/index.cjs +129 -2
  24. package/dist/stores/index.d.cts +2 -0
  25. package/dist/stores/index.d.ts +2 -0
  26. package/dist/stores/index.js +127 -1
  27. package/dist/stores/queued_sqlite.cjs +313 -0
  28. package/dist/stores/queued_sqlite.d.cts +43 -0
  29. package/dist/stores/queued_sqlite.d.ts +43 -0
  30. package/dist/stores/queued_sqlite.js +280 -0
  31. package/dist/types/index.d.cts +16 -2
  32. package/dist/types/index.d.ts +16 -2
  33. package/dist/ui/assets/{CacheActionBadge-CL10Xlw7.js → CacheActionBadge-BB4uokI1.js} +1 -1
  34. package/dist/ui/assets/CacheEntriesTable-B8cUXhos.js +1 -0
  35. package/dist/ui/assets/CacheEntryContainer-WkdnGvnu.js +2 -0
  36. package/dist/ui/assets/CacheEntryDetails-BeZnoIpm.js +1 -0
  37. package/dist/ui/assets/CacheEntryDetailsContainer-DI0mEvpu.js +2 -0
  38. package/dist/ui/assets/ExceptionContainer-YNcR0F5U.js +2 -0
  39. package/dist/ui/assets/{ExceptionDetails-Bzj8OZ70.js → ExceptionDetails-BKHzv6hf.js} +1 -1
  40. package/dist/ui/assets/ExceptionDetailsContainer-CJHILjb3.js +2 -0
  41. package/dist/ui/assets/{ExceptionTable-BkFSFGbn.js → ExceptionTable-DzBmQLLa.js} +1 -1
  42. package/dist/ui/assets/JsonViewer-D-KPN089.js +1 -0
  43. package/dist/ui/assets/{LoadMore-Du7yL-Hr.js → LoadMore-CLPR6Zd4.js} +1 -1
  44. package/dist/ui/assets/QueriesContainer-B_PmBkHR.js +2 -0
  45. package/dist/ui/assets/{QueryDetailsContainer-BtbvRyBf.js → QueryDetailsContainer-Cqj3E6Dr.js} +16 -26
  46. package/dist/ui/assets/{QueryTable-tJVEncUM.js → QueryTable-DmWdZSnJ.js} +1 -1
  47. package/dist/ui/assets/{RequestDetails-C6tqSqg9.js → RequestDetails-CF338Kcv.js} +1 -1
  48. package/dist/ui/assets/{RequestDetailsContainer---KvdZKp.js → RequestDetailsContainer-aW4GLool.js} +2 -2
  49. package/dist/ui/assets/{RequestsContainer-Bogurt1b.js → RequestsContainer-DdLSvAbl.js} +2 -2
  50. package/dist/ui/assets/{RequetsTable-BMrYHd0d.js → RequetsTable-Bdp_PhGU.js} +1 -1
  51. package/dist/ui/assets/{StatusCode-DpZO0dUJ.js → StatusCode-C605nHvd.js} +1 -1
  52. package/dist/ui/assets/TabbedDataViewer-ofhEq_Wj.js +2 -0
  53. package/dist/ui/assets/{Table-BtkmKVTF.js → Table-kak5sL5X.js} +1 -1
  54. package/dist/ui/assets/{columns-D_NhXbk6.js → columns-BEyDhUNq.js} +1 -1
  55. package/dist/ui/assets/{columns-DlGaMv5C.js → columns-Bu5psHyp.js} +1 -1
  56. package/dist/ui/assets/{columns-DF7BR0z_.js → columns-BvIUTkjN.js} +1 -1
  57. package/dist/ui/assets/copy-DzXuP4eO.js +11 -0
  58. package/dist/ui/assets/index-CsnKQ5Mh.css +1 -0
  59. package/dist/ui/assets/{index-EQXljT95.js → index-TW_-MgRG.js} +25 -25
  60. package/dist/ui/assets/{useCacheEntries-jC9XYsV_.js → useCacheEntries-Pvte_aNc.js} +1 -1
  61. package/dist/ui/assets/{useExceptions-CwwK33mG.js → useExceptions-P3cnURvN.js} +1 -1
  62. package/dist/ui/assets/{useLensApi-CPvDlyGv.js → useLensApi-BFdsfrzR.js} +1 -1
  63. package/dist/ui/assets/{useLoadMore-C2bqGSaL.js → useLoadMore-JCWak1Dg.js} +1 -1
  64. package/dist/ui/assets/{useQueries-CzbIajH6.js → useQueries-CNquFtm0.js} +1 -1
  65. package/dist/ui/index.html +2 -2
  66. package/dist/utils/compose.cjs +32 -0
  67. package/dist/utils/compose.d.cts +11 -0
  68. package/dist/utils/compose.d.ts +11 -0
  69. package/dist/utils/compose.js +7 -0
  70. package/dist/utils/index.cjs +10 -1
  71. package/dist/utils/index.d.cts +3 -1
  72. package/dist/utils/index.d.ts +3 -1
  73. package/dist/utils/index.js +9 -1
  74. package/dist/watchers/index.cjs +45 -5
  75. package/dist/watchers/index.js +45 -5
  76. package/dist/watchers/request_watcher.cjs +45 -5
  77. package/dist/watchers/request_watcher.d.cts +12 -1
  78. package/dist/watchers/request_watcher.d.ts +12 -1
  79. package/dist/watchers/request_watcher.js +45 -5
  80. package/package.json +2 -1
  81. package/dist/ui/assets/CacheEntriesTable-DuLoeu0e.js +0 -1
  82. package/dist/ui/assets/CacheEntryContainer-DqHm-jQl.js +0 -2
  83. package/dist/ui/assets/CacheEntryDetails-k-74LsSb.js +0 -1
  84. package/dist/ui/assets/CacheEntryDetailsContainer-DTI7gtUq.js +0 -2
  85. package/dist/ui/assets/ExceptionContainer-0dCs6QMQ.js +0 -2
  86. package/dist/ui/assets/ExceptionDetailsContainer-Bim0gTpE.js +0 -2
  87. package/dist/ui/assets/QueriesContainer-5xlqsYl0.js +0 -2
  88. package/dist/ui/assets/TabbedDataViewer-C60W9bqz.js +0 -1
  89. package/dist/ui/assets/index-CMJVCuvo.css +0 -1
@@ -1,4 +1,5 @@
1
1
  import { SqlLanguage } from 'sql-formatter';
2
+ import { compose } from './utils/compose.js';
2
3
 
3
4
  declare const generateRandomUuid: () => `${string}-${string}-${string}-${string}-${string}`;
4
5
  /**
@@ -24,6 +25,7 @@ declare function shouldIgnoreCurrentPath(path: string, ignoredPaths: RegExp[], o
24
25
  declare function prettyHrTime(hrtime: [number, number], verbose?: boolean): string;
25
26
  declare function normalizePath(path: string): string;
26
27
 
28
+ declare const index_compose: typeof compose;
27
29
  declare const index_formatSqlQuery: typeof formatSqlQuery;
28
30
  declare const index_generateRandomUuid: typeof generateRandomUuid;
29
31
  declare const index_getMeta: typeof getMeta;
@@ -35,7 +37,7 @@ declare const index_prettyHrTime: typeof prettyHrTime;
35
37
  declare const index_shouldIgnoreCurrentPath: typeof shouldIgnoreCurrentPath;
36
38
  declare const index_stripBeforeAssetsPath: typeof stripBeforeAssetsPath;
37
39
  declare namespace index {
38
- export { index_formatSqlQuery as formatSqlQuery, index_generateRandomUuid as generateRandomUuid, index_getMeta as getMeta, index_interpolateQuery as interpolateQuery, index_isStaticFile as isStaticFile, index_normalizePath as normalizePath, index_prepareIgnoredPaths as prepareIgnoredPaths, index_prettyHrTime as prettyHrTime, index_shouldIgnoreCurrentPath as shouldIgnoreCurrentPath, index_stripBeforeAssetsPath as stripBeforeAssetsPath };
40
+ export { index_compose as compose, index_formatSqlQuery as formatSqlQuery, index_generateRandomUuid as generateRandomUuid, index_getMeta as getMeta, index_interpolateQuery as interpolateQuery, index_isStaticFile as isStaticFile, index_normalizePath as normalizePath, index_prepareIgnoredPaths as prepareIgnoredPaths, index_prettyHrTime as prettyHrTime, index_shouldIgnoreCurrentPath as shouldIgnoreCurrentPath, index_stripBeforeAssetsPath as stripBeforeAssetsPath };
39
41
  }
40
42
 
41
43
  export { interpolateQuery as a, getMeta as b, isStaticFile as c, shouldIgnoreCurrentPath as d, prettyHrTime as e, formatSqlQuery as f, generateRandomUuid as g, index as i, normalizePath as n, prepareIgnoredPaths as p, stripBeforeAssetsPath as s };
@@ -1,4 +1,5 @@
1
1
  import { SqlLanguage } from 'sql-formatter';
2
+ import { compose } from './utils/compose.cjs';
2
3
 
3
4
  declare const generateRandomUuid: () => `${string}-${string}-${string}-${string}-${string}`;
4
5
  /**
@@ -24,6 +25,7 @@ declare function shouldIgnoreCurrentPath(path: string, ignoredPaths: RegExp[], o
24
25
  declare function prettyHrTime(hrtime: [number, number], verbose?: boolean): string;
25
26
  declare function normalizePath(path: string): string;
26
27
 
28
+ declare const index_compose: typeof compose;
27
29
  declare const index_formatSqlQuery: typeof formatSqlQuery;
28
30
  declare const index_generateRandomUuid: typeof generateRandomUuid;
29
31
  declare const index_getMeta: typeof getMeta;
@@ -35,7 +37,7 @@ declare const index_prettyHrTime: typeof prettyHrTime;
35
37
  declare const index_shouldIgnoreCurrentPath: typeof shouldIgnoreCurrentPath;
36
38
  declare const index_stripBeforeAssetsPath: typeof stripBeforeAssetsPath;
37
39
  declare namespace index {
38
- export { index_formatSqlQuery as formatSqlQuery, index_generateRandomUuid as generateRandomUuid, index_getMeta as getMeta, index_interpolateQuery as interpolateQuery, index_isStaticFile as isStaticFile, index_normalizePath as normalizePath, index_prepareIgnoredPaths as prepareIgnoredPaths, index_prettyHrTime as prettyHrTime, index_shouldIgnoreCurrentPath as shouldIgnoreCurrentPath, index_stripBeforeAssetsPath as stripBeforeAssetsPath };
40
+ export { index_compose as compose, index_formatSqlQuery as formatSqlQuery, index_generateRandomUuid as generateRandomUuid, index_getMeta as getMeta, index_interpolateQuery as interpolateQuery, index_isStaticFile as isStaticFile, index_normalizePath as normalizePath, index_prepareIgnoredPaths as prepareIgnoredPaths, index_prettyHrTime as prettyHrTime, index_shouldIgnoreCurrentPath as shouldIgnoreCurrentPath, index_stripBeforeAssetsPath as stripBeforeAssetsPath };
39
41
  }
40
42
 
41
43
  export { interpolateQuery as a, getMeta as b, isStaticFile as c, shouldIgnoreCurrentPath as d, prettyHrTime as e, formatSqlQuery as f, generateRandomUuid as g, index as i, normalizePath as n, prepareIgnoredPaths as p, stripBeforeAssetsPath as s };
package/dist/index.cjs CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  LensStore: () => Store,
39
39
  LensWatcher: () => Watcher,
40
40
  QueryWatcher: () => QueryWatcher,
41
+ QueuedSqliteStore: () => QueuedSqliteStore,
41
42
  RequestWatcher: () => RequestWatcher,
42
43
  WatcherTypeEnum: () => WatcherTypeEnum,
43
44
  createEmittery: () => createEmittery,
@@ -229,6 +230,9 @@ var path2 = __toESM(require("path"), 1);
229
230
 
230
231
  // src/abstracts/store.ts
231
232
  var Store = class {
233
+ storeConfig;
234
+ constructor(...args) {
235
+ }
232
236
  getAllExceptions(_paginationParams) {
233
237
  return this.defaultMinimalPaginate();
234
238
  }
@@ -259,6 +263,8 @@ var import_crypto = require("crypto");
259
263
  var import_libsql = __toESM(require("libsql"), 1);
260
264
  var import_date = require("@lensjs/date");
261
265
  var TABLE_NAME = "lens_entries";
266
+ var BYTES_IN_GB = 1024 * 1024 * 1024;
267
+ var PRUNE_BATCH_SIZE = 1e3;
262
268
  var BetterSqliteStore = class extends Store {
263
269
  connection;
264
270
  async initialize() {
@@ -280,6 +286,7 @@ var BetterSqliteStore = class extends Store {
280
286
  lens_entry_id: entry.requestId || null,
281
287
  minimalData: this.stringifyData(entry.minimal_data ?? {})
282
288
  });
289
+ this.maybePruneDatabase();
283
290
  }
284
291
  async getAllQueries(pagination) {
285
292
  return await this.paginate("query" /* QUERY */, pagination);
@@ -355,6 +362,36 @@ var BetterSqliteStore = class extends Store {
355
362
  this.connection.exec(createIndex);
356
363
  this.connection.exec(lensEntryIdIndex);
357
364
  }
365
+ maybePruneDatabase() {
366
+ const maxGb = this.storeConfig?.dbMaxSizeGb;
367
+ const pruneGb = this.storeConfig?.dbPruneSizeGb;
368
+ if (!maxGb || !pruneGb) return;
369
+ const maxBytes = maxGb * BYTES_IN_GB;
370
+ const pruneBytes = pruneGb * BYTES_IN_GB;
371
+ if (maxBytes <= 0 || pruneBytes <= 0) return;
372
+ const targetBytes = Math.max(0, maxBytes - pruneBytes);
373
+ let usedBytes = this.getDatabaseUsedBytes();
374
+ if (usedBytes < maxBytes) return;
375
+ while (usedBytes > targetBytes) {
376
+ const deletedRows = this.deleteOldestEntries(PRUNE_BATCH_SIZE);
377
+ if (deletedRows === 0) break;
378
+ usedBytes = this.getDatabaseUsedBytes();
379
+ }
380
+ this.connection.exec("PRAGMA wal_checkpoint(TRUNCATE);");
381
+ }
382
+ getDatabaseUsedBytes() {
383
+ const pageSizeResult = this.connection.prepare("PRAGMA page_size;").get();
384
+ const pageCountResult = this.connection.prepare("PRAGMA page_count;").get();
385
+ const freelistCountResult = this.connection.prepare("PRAGMA freelist_count;").get();
386
+ const usedPages = pageCountResult.page_count - freelistCountResult.freelist_count;
387
+ return usedPages * pageSizeResult.page_size;
388
+ }
389
+ deleteOldestEntries(batchSize) {
390
+ const result = this.connection.prepare(
391
+ `DELETE FROM ${TABLE_NAME} WHERE id IN (SELECT id FROM ${TABLE_NAME} ORDER BY created_at ASC LIMIT ?)`
392
+ ).run(batchSize);
393
+ return Number(result.changes ?? 0);
394
+ }
358
395
  mapRow(row, includeFullData = true) {
359
396
  let data = includeFullData ? JSON.parse(row.data) : {};
360
397
  if (!includeFullData) {
@@ -380,9 +417,99 @@ var BetterSqliteStore = class extends Store {
380
417
  }
381
418
  };
382
419
 
420
+ // src/mixins/queued_store.ts
421
+ var import_denque = __toESM(require("denque"), 1);
422
+ function QueuedStore(Base) {
423
+ return class Queued extends Base {
424
+ queue;
425
+ processingInterval = null;
426
+ BATCH_SIZE;
427
+ PROCESS_INTERVAL_MS;
428
+ WARN_THRESHOLD;
429
+ PREALLOCATE;
430
+ constructor(...args) {
431
+ super(...args);
432
+ const config = args[0] || {};
433
+ this.storeConfig = config;
434
+ this.BATCH_SIZE = config.batchSize ?? 100;
435
+ this.PROCESS_INTERVAL_MS = config.processIntervalMs ?? 100;
436
+ this.WARN_THRESHOLD = config.warnThreshold ?? 1e5;
437
+ this.PREALLOCATE = config.preallocate ?? true;
438
+ this.queue = this.PREALLOCATE ? new import_denque.default([], { capacity: this.WARN_THRESHOLD * 2 }) : new import_denque.default();
439
+ }
440
+ async initialize() {
441
+ if (super["initialize"]) {
442
+ await super["initialize"].call(this);
443
+ }
444
+ this.startProcessingQueue();
445
+ process.on("SIGINT", () => this.shutdown());
446
+ process.on("SIGTERM", () => this.shutdown());
447
+ }
448
+ async truncate() {
449
+ this.queue.clear();
450
+ if (super["truncate"]) {
451
+ await super["truncate"].call(this);
452
+ }
453
+ }
454
+ async save(entry) {
455
+ this.queue.push(entry);
456
+ if (this.queue.length > this.WARN_THRESHOLD) {
457
+ console.warn(`\u26A0\uFE0F LensJs Queue size very large: ${this.queue.length}`);
458
+ }
459
+ }
460
+ startProcessingQueue() {
461
+ if (this.processingInterval) clearInterval(this.processingInterval);
462
+ this.processingInterval = setInterval(
463
+ () => this.processQueue(),
464
+ this.PROCESS_INTERVAL_MS
465
+ );
466
+ }
467
+ async processQueue() {
468
+ if (this.queue.isEmpty()) return;
469
+ const batchSize = Math.min(
470
+ this.BATCH_SIZE,
471
+ Math.max(10, Math.floor(this.queue.length / 10))
472
+ );
473
+ const entriesToProcess = this.queue.remove(0, batchSize);
474
+ if (!entriesToProcess.length) return;
475
+ for (const entry of entriesToProcess) {
476
+ super["save"]?.call(this, entry).catch((error) => {
477
+ console.error("Error saving queued entry:", error);
478
+ });
479
+ }
480
+ }
481
+ async stopProcessingQueue() {
482
+ if (this.processingInterval) {
483
+ clearInterval(this.processingInterval);
484
+ this.processingInterval = null;
485
+ }
486
+ if (!this.queue.isEmpty()) {
487
+ await this.processQueue();
488
+ }
489
+ }
490
+ async shutdown() {
491
+ await this.stopProcessingQueue();
492
+ process.exit(0);
493
+ }
494
+ };
495
+ }
496
+
497
+ // src/utils/compose.ts
498
+ function compose(superclass, ...mixins) {
499
+ return mixins.reduce((c, mixin) => mixin(c), superclass);
500
+ }
501
+
502
+ // src/stores/queued_sqlite.ts
503
+ var QueuedSqliteStore = class extends compose(
504
+ BetterSqliteStore,
505
+ QueuedStore
506
+ ) {
507
+ };
508
+
383
509
  // src/utils/index.ts
384
510
  var utils_exports = {};
385
511
  __export(utils_exports, {
512
+ compose: () => compose,
386
513
  formatSqlQuery: () => formatSqlQuery,
387
514
  generateRandomUuid: () => generateRandomUuid,
388
515
  getMeta: () => getMeta,
@@ -457,7 +584,7 @@ var formatSqlQuery = (query, language) => {
457
584
  });
458
585
  };
459
586
  function getMeta(metaUrl) {
460
- const isESM = typeof __dirname === "undefined";
587
+ const isESM = typeof __dirname === "undefined" || typeof __filename === "undefined";
461
588
  if (isESM) {
462
589
  if (!metaUrl) {
463
590
  throw new Error("In ESM, you must pass import.meta.url to getMeta()");
@@ -523,6 +650,7 @@ var Lens = class {
523
650
  static watchers = /* @__PURE__ */ new Map();
524
651
  static store;
525
652
  static adapter;
653
+ static config;
526
654
  static watch(watcher) {
527
655
  this.watchers.set(watcher.name, watcher);
528
656
  return this;
@@ -532,22 +660,23 @@ var Lens = class {
532
660
  return this;
533
661
  }
534
662
  static async start(config = {
535
- basePath: "lens",
663
+ path: "lens",
536
664
  appName: "Lens",
537
665
  enabled: true
538
666
  }) {
539
667
  if (!config.enabled) {
540
668
  return;
541
669
  }
542
- await this.bindContainerDeps(config);
670
+ this.config = config;
671
+ await this.bindContainerDeps();
543
672
  let adapter = this.getAdapter();
544
673
  adapter.setWatchers(Array.from(this.watchers.values())).setup();
545
674
  const { apiRoutes } = this.getRoutes({
546
- basePath: config.basePath
675
+ path: config.path
547
676
  });
548
677
  adapter.registerRoutes(apiRoutes);
549
678
  const uiPath = this.getUiPath();
550
- adapter.serveUI(uiPath, config.basePath, getUiConfig());
679
+ adapter.serveUI(uiPath, config.path, getUiConfig());
551
680
  }
552
681
  static setStore(store) {
553
682
  this.store = store;
@@ -570,7 +699,7 @@ var Lens = class {
570
699
  const { __dirname: __dirname2 } = getMeta(import_meta.url);
571
700
  return path2.resolve(this.normalizeDirName(__dirname2), "ui");
572
701
  }
573
- static getRoutes({ basePath }) {
702
+ static getRoutes({ path: path4 }) {
574
703
  const apiRoutes = [
575
704
  {
576
705
  method: "GET",
@@ -579,71 +708,71 @@ var Lens = class {
579
708
  },
580
709
  {
581
710
  method: "GET",
582
- path: `/${basePath}/api/requests`,
711
+ path: `/${path4}/api/requests`,
583
712
  handler: async (data) => await ApiController.getRequests(data)
584
713
  },
585
714
  {
586
715
  method: "GET",
587
- path: `/${basePath}/api/requests/:id`,
716
+ path: `/${path4}/api/requests/:id`,
588
717
  handler: async (data) => await ApiController.getRequest(data)
589
718
  },
590
719
  {
591
720
  method: "GET",
592
- path: `/${basePath}/api/queries`,
721
+ path: `/${path4}/api/queries`,
593
722
  handler: async (data) => await ApiController.getQueries(data)
594
723
  },
595
724
  {
596
725
  method: "GET",
597
- path: `/${basePath}/api/queries/:id`,
726
+ path: `/${path4}/api/queries/:id`,
598
727
  handler: async (data) => await ApiController.getQuery(data)
599
728
  },
600
729
  {
601
730
  method: "GET",
602
- path: `/${basePath}/api/cache`,
731
+ path: `/${path4}/api/cache`,
603
732
  handler: async (data) => await ApiController.getCacheEntries(data)
604
733
  },
605
734
  {
606
735
  method: "GET",
607
- path: `/${basePath}/api/cache/:id`,
736
+ path: `/${path4}/api/cache/:id`,
608
737
  handler: async (data) => await ApiController.getCacheEntry(data)
609
738
  },
610
739
  {
611
740
  method: "GET",
612
- path: `/${basePath}/api/exceptions`,
741
+ path: `/${path4}/api/exceptions`,
613
742
  handler: async (data) => await ApiController.getExceptions(data)
614
743
  },
615
744
  {
616
745
  method: "GET",
617
- path: `/${basePath}/api/exceptions/:id`,
746
+ path: `/${path4}/api/exceptions/:id`,
618
747
  handler: async (data) => await ApiController.getException(data)
619
748
  },
620
749
  {
621
750
  method: "DELETE",
622
- path: `/${basePath}/api/truncate`,
751
+ path: `/${path4}/api/truncate`,
623
752
  handler: async () => await ApiController.truncate()
624
753
  }
625
754
  ];
626
755
  return { apiRoutes };
627
756
  }
628
- static async bindContainerDeps(config) {
757
+ static async bindContainerDeps() {
629
758
  const dbStore = await this.getStore();
630
759
  Container.singleton("store", () => dbStore);
631
760
  Container.singleton("uiConfig", () => {
632
761
  return {
633
- appName: config.appName,
634
- path: `/${config.basePath}`,
762
+ appName: this.config.appName,
763
+ path: `/${this.config.path}`,
635
764
  api: {
636
- requests: `/${config.basePath}/api/requests`,
637
- queries: `/${config.basePath}/api/queries`,
638
- cache: `/${config.basePath}/api/cache`,
639
- exceptions: `/${config.basePath}/api/exceptions`,
640
- truncate: `/${config.basePath}/api/truncate`
765
+ requests: `/${this.config.path}/api/requests`,
766
+ queries: `/${this.config.path}/api/queries`,
767
+ cache: `/${this.config.path}/api/cache`,
768
+ exceptions: `/${this.config.path}/api/exceptions`,
769
+ truncate: `/${this.config.path}/api/truncate`
641
770
  }
642
771
  };
643
772
  });
644
773
  }
645
774
  static async getDefaultStore() {
646
- const store = new BetterSqliteStore();
775
+ const store = new QueuedSqliteStore(this.config.storeQueueConfig);
647
776
  await store.initialize();
648
777
  return store;
649
778
  }
@@ -669,10 +798,19 @@ var QueryWatcher = class extends Watcher {
669
798
  };
670
799
 
671
800
  // src/watchers/request_watcher.ts
672
- var RequestWatcher = class extends Watcher {
801
+ var RequestWatcher = class _RequestWatcher extends Watcher {
673
802
  name = "request" /* REQUEST */;
674
- async log(data) {
675
- await getStore().save({
803
+ static DEFAULT_HIDDEN_HEADERS = ["Authorization", "Basic"];
804
+ static DEFAULT_HIDDEN_BODY_PARAMS = [
805
+ "password",
806
+ "passwordConfirmation",
807
+ "secret",
808
+ "password_confirmation"
809
+ ];
810
+ async log(data, hidden = {}) {
811
+ const headersToHide = (hidden.headers?.length ? hidden.headers : _RequestWatcher.DEFAULT_HIDDEN_HEADERS).map((header) => header.toLowerCase());
812
+ const bodyParamsToHide = hidden.bodyParams?.length ? hidden.bodyParams : _RequestWatcher.DEFAULT_HIDDEN_BODY_PARAMS;
813
+ const payload = {
676
814
  id: data.request.id,
677
815
  type: this.name,
678
816
  minimal_data: {
@@ -686,9 +824,40 @@ var RequestWatcher = class extends Watcher {
686
824
  data: {
687
825
  ...data.request,
688
826
  user: data.user,
689
- response: data.response
827
+ response: data.response || {}
690
828
  }
691
- });
829
+ };
830
+ payload.data.headers = this.hideSensitive(
831
+ this.normalizeHeaders(payload.data.headers),
832
+ headersToHide
833
+ );
834
+ payload.data.response.headers = this.hideSensitive(
835
+ this.normalizeHeaders(payload.data.response?.headers),
836
+ headersToHide
837
+ );
838
+ payload.data.body = this.hideSensitive(payload.data.body, bodyParamsToHide, false);
839
+ await getStore().save(payload);
840
+ }
841
+ /**
842
+ * Normalize headers: converts keys to lowercase.
843
+ */
844
+ normalizeHeaders(headers) {
845
+ if (!headers || typeof headers !== "object") return {};
846
+ return Object.fromEntries(
847
+ Object.entries(headers).map(([k, v]) => [k.toLowerCase(), v])
848
+ );
849
+ }
850
+ hideSensitive(obj, keysToHide = [], isObjHeaders = true) {
851
+ if (!obj || typeof obj !== "object") {
852
+ return isObjHeaders ? {} : obj;
853
+ }
854
+ const clone = { ...obj };
855
+ for (const key of keysToHide) {
856
+ if (key in clone) {
857
+ clone[key] = "*******";
858
+ }
859
+ }
860
+ return clone;
692
861
  }
693
862
  };
694
863
 
@@ -919,6 +1088,7 @@ var handleUncaughExceptions = (logger) => {
919
1088
  LensStore,
920
1089
  LensWatcher,
921
1090
  QueryWatcher,
1091
+ QueuedSqliteStore,
922
1092
  RequestWatcher,
923
1093
  WatcherTypeEnum,
924
1094
  createEmittery,
package/dist/index.d.cts CHANGED
@@ -1,19 +1,22 @@
1
1
  export { default as Lens } from './core/lens.cjs';
2
2
  export { default as BetterSqliteStore } from './stores/better_sqlite.cjs';
3
+ export { default as QueuedSqliteStore } from './stores/queued_sqlite.cjs';
3
4
  export { default as QueryWatcher } from './watchers/query_watcher.cjs';
4
5
  export { default as RequestWatcher } from './watchers/request_watcher.cjs';
5
6
  export { default as CacheWatcher } from './watchers/cache_watcher.cjs';
6
7
  export { default as ExceptionWatcher } from './watchers/exception_watcher.cjs';
7
- export { ApiResponse, CacheAction, CacheEntry, Entry, ExceptionEntry, HttpMethod, LensConfig, LensEntry, PaginationParams, Paginator, QueryEntry, QueryType, RequestEntry, RouteDefinition, RouteDefinitionHandler, RouteHttpMethod, SqlQueryType, UserEntry, WatcherTypeEnum } from './types/index.cjs';
8
+ export { ApiResponse, CacheAction, CacheEntry, Constructor, Entry, ExceptionEntry, HttpMethod, LensConfig, LensEntry, PaginationParams, Paginator, QueryEntry, QueryType, QueuedStoreConfig, RequestEntry, RouteDefinition, RouteDefinitionHandler, RouteHttpMethod, SqlQueryType, UserEntry, WatcherTypeEnum } from './types/index.cjs';
8
9
  export { default as LensAdapter } from './abstracts/adapter.cjs';
9
10
  export { default as LensStore } from './abstracts/store.cjs';
10
11
  export { default as LensWatcher } from './core/watcher.cjs';
11
12
  export { getStore as getLensStore } from './context/context.cjs';
12
- export { i as lensUtils } from './index-CMvlRWcQ.cjs';
13
+ export { i as lensUtils } from './index-QmOJr0K-.cjs';
13
14
  export { e as lensExceptionUtils } from './exception-C69UCHPk.cjs';
14
15
  export { createEmittery, lensEmitter } from './utils/event_emitter.cjs';
15
16
  export { handleUncaughExceptions, lensContext } from './utils/async_context.cjs';
16
17
  import 'libsql';
18
+ import 'denque';
17
19
  import 'sql-formatter';
20
+ import './utils/compose.cjs';
18
21
  import 'events';
19
22
  import 'async_hooks';
package/dist/index.d.ts CHANGED
@@ -1,19 +1,22 @@
1
1
  export { default as Lens } from './core/lens.js';
2
2
  export { default as BetterSqliteStore } from './stores/better_sqlite.js';
3
+ export { default as QueuedSqliteStore } from './stores/queued_sqlite.js';
3
4
  export { default as QueryWatcher } from './watchers/query_watcher.js';
4
5
  export { default as RequestWatcher } from './watchers/request_watcher.js';
5
6
  export { default as CacheWatcher } from './watchers/cache_watcher.js';
6
7
  export { default as ExceptionWatcher } from './watchers/exception_watcher.js';
7
- export { ApiResponse, CacheAction, CacheEntry, Entry, ExceptionEntry, HttpMethod, LensConfig, LensEntry, PaginationParams, Paginator, QueryEntry, QueryType, RequestEntry, RouteDefinition, RouteDefinitionHandler, RouteHttpMethod, SqlQueryType, UserEntry, WatcherTypeEnum } from './types/index.js';
8
+ export { ApiResponse, CacheAction, CacheEntry, Constructor, Entry, ExceptionEntry, HttpMethod, LensConfig, LensEntry, PaginationParams, Paginator, QueryEntry, QueryType, QueuedStoreConfig, RequestEntry, RouteDefinition, RouteDefinitionHandler, RouteHttpMethod, SqlQueryType, UserEntry, WatcherTypeEnum } from './types/index.js';
8
9
  export { default as LensAdapter } from './abstracts/adapter.js';
9
10
  export { default as LensStore } from './abstracts/store.js';
10
11
  export { default as LensWatcher } from './core/watcher.js';
11
12
  export { getStore as getLensStore } from './context/context.js';
12
- export { i as lensUtils } from './index-CMvlRWcQ.js';
13
+ export { i as lensUtils } from './index-CZsa0Zcm.js';
13
14
  export { e as lensExceptionUtils } from './exception-3AZsPtAg.js';
14
15
  export { createEmittery, lensEmitter } from './utils/event_emitter.js';
15
16
  export { handleUncaughExceptions, lensContext } from './utils/async_context.js';
16
17
  import 'libsql';
18
+ import 'denque';
17
19
  import 'sql-formatter';
20
+ import './utils/compose.js';
18
21
  import 'events';
19
22
  import 'async_hooks';