@lensjs/core 2.2.1 → 2.3.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/dist/abstracts/store.cjs +2 -0
- package/dist/abstracts/store.d.cts +1 -0
- package/dist/abstracts/store.d.ts +1 -0
- package/dist/abstracts/store.js +2 -0
- package/dist/core/lens.cjs +115 -23
- package/dist/core/lens.d.cts +3 -2
- package/dist/core/lens.d.ts +3 -2
- package/dist/core/lens.js +115 -23
- package/dist/{index-CMvlRWcQ.d.cts → index-CZsa0Zcm.d.ts} +3 -1
- package/dist/{index-CMvlRWcQ.d.ts → index-QmOJr0K-.d.cts} +3 -1
- package/dist/index.cjs +163 -28
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +162 -28
- package/dist/mixins/queued_store.cjs +113 -0
- package/dist/mixins/queued_store.d.cts +38 -0
- package/dist/mixins/queued_store.d.ts +38 -0
- package/dist/mixins/queued_store.js +78 -0
- package/dist/stores/better_sqlite.cjs +2 -0
- package/dist/stores/better_sqlite.js +2 -0
- package/dist/stores/index.cjs +94 -2
- package/dist/stores/index.d.cts +2 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/index.js +92 -1
- package/dist/stores/queued_sqlite.cjs +278 -0
- package/dist/stores/queued_sqlite.d.cts +43 -0
- package/dist/stores/queued_sqlite.d.ts +43 -0
- package/dist/stores/queued_sqlite.js +245 -0
- package/dist/types/index.d.cts +14 -2
- package/dist/types/index.d.ts +14 -2
- package/dist/ui/assets/{CacheActionBadge-WGVr5yhe.js → CacheActionBadge-BB4uokI1.js} +1 -1
- package/dist/ui/assets/CacheEntriesTable-B8cUXhos.js +1 -0
- package/dist/ui/assets/CacheEntryContainer-WkdnGvnu.js +2 -0
- package/dist/ui/assets/CacheEntryDetails-BeZnoIpm.js +1 -0
- package/dist/ui/assets/CacheEntryDetailsContainer-DI0mEvpu.js +2 -0
- package/dist/ui/assets/ExceptionContainer-YNcR0F5U.js +2 -0
- package/dist/ui/assets/{ExceptionDetails-DX14YGmx.js → ExceptionDetails-BKHzv6hf.js} +1 -1
- package/dist/ui/assets/ExceptionDetailsContainer-CJHILjb3.js +2 -0
- package/dist/ui/assets/{ExceptionTable-Chiah5kT.js → ExceptionTable-DzBmQLLa.js} +1 -1
- package/dist/ui/assets/JsonViewer-D-KPN089.js +1 -0
- package/dist/ui/assets/{LoadMore-CosGy1fp.js → LoadMore-CLPR6Zd4.js} +1 -1
- package/dist/ui/assets/QueriesContainer-B_PmBkHR.js +2 -0
- package/dist/ui/assets/{QueryDetailsContainer-Dimuidq4.js → QueryDetailsContainer-Cqj3E6Dr.js} +16 -26
- package/dist/ui/assets/{QueryTable-BLpmWt7g.js → QueryTable-DmWdZSnJ.js} +1 -1
- package/dist/ui/assets/{RequestDetails-DeJofxSW.js → RequestDetails-CF338Kcv.js} +1 -1
- package/dist/ui/assets/{RequestDetailsContainer-BtDTKq1O.js → RequestDetailsContainer-aW4GLool.js} +2 -2
- package/dist/ui/assets/{RequestsContainer-CxIavrPj.js → RequestsContainer-DdLSvAbl.js} +2 -2
- package/dist/ui/assets/{RequetsTable-CUevs9X4.js → RequetsTable-Bdp_PhGU.js} +1 -1
- package/dist/ui/assets/StatusCode-C605nHvd.js +1 -0
- package/dist/ui/assets/TabbedDataViewer-ofhEq_Wj.js +2 -0
- package/dist/ui/assets/{Table-z_QSS7J8.js → Table-kak5sL5X.js} +1 -1
- package/dist/ui/assets/{columns-Bxz-DZCj.js → columns-BEyDhUNq.js} +1 -1
- package/dist/ui/assets/{columns-D0UC1pqC.js → columns-Bu5psHyp.js} +1 -1
- package/dist/ui/assets/{columns-DJaOm2Yg.js → columns-BvIUTkjN.js} +1 -1
- package/dist/ui/assets/copy-DzXuP4eO.js +11 -0
- package/dist/ui/assets/index-CsnKQ5Mh.css +1 -0
- package/dist/ui/assets/{index-CQJv-KV7.js → index-TW_-MgRG.js} +25 -25
- package/dist/ui/assets/{useCacheEntries-DWzLAzvE.js → useCacheEntries-Pvte_aNc.js} +1 -1
- package/dist/ui/assets/{useExceptions-BF0fHNek.js → useExceptions-P3cnURvN.js} +1 -1
- package/dist/ui/assets/{useLensApi-BEMg_OuP.js → useLensApi-BFdsfrzR.js} +1 -1
- package/dist/ui/assets/{useLoadMore-ClIkZ0Gw.js → useLoadMore-JCWak1Dg.js} +1 -1
- package/dist/ui/assets/{useQueries-C0vKfgzw.js → useQueries-CNquFtm0.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/utils/compose.cjs +32 -0
- package/dist/utils/compose.d.cts +11 -0
- package/dist/utils/compose.d.ts +11 -0
- package/dist/utils/compose.js +7 -0
- package/dist/utils/index.cjs +9 -0
- package/dist/utils/index.d.cts +3 -1
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.js +8 -0
- package/dist/watchers/index.cjs +45 -5
- package/dist/watchers/index.js +45 -5
- package/dist/watchers/request_watcher.cjs +45 -5
- package/dist/watchers/request_watcher.d.cts +12 -1
- package/dist/watchers/request_watcher.d.ts +12 -1
- package/dist/watchers/request_watcher.js +45 -5
- package/package.json +2 -1
- package/dist/ui/assets/CacheEntriesTable-txREHfFk.js +0 -1
- package/dist/ui/assets/CacheEntryContainer-BoeiVJN6.js +0 -2
- package/dist/ui/assets/CacheEntryDetails-DovbpPae.js +0 -1
- package/dist/ui/assets/CacheEntryDetailsContainer-DcmH8iqv.js +0 -2
- package/dist/ui/assets/ExceptionContainer-C0H0kKkb.js +0 -2
- package/dist/ui/assets/ExceptionDetailsContainer-CHAXdzwk.js +0 -2
- package/dist/ui/assets/QueriesContainer-CporgPyk.js +0 -2
- package/dist/ui/assets/StatusCode-D_bCVpUf.js +0 -1
- package/dist/ui/assets/TabbedDataViewer-CbZANxvH.js +0 -1
- package/dist/ui/assets/index-B2QCOgug.css +0 -1
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,8 @@ var path2 = __toESM(require("path"), 1);
|
|
|
229
230
|
|
|
230
231
|
// src/abstracts/store.ts
|
|
231
232
|
var Store = class {
|
|
233
|
+
constructor(...args) {
|
|
234
|
+
}
|
|
232
235
|
getAllExceptions(_paginationParams) {
|
|
233
236
|
return this.defaultMinimalPaginate();
|
|
234
237
|
}
|
|
@@ -380,9 +383,98 @@ var BetterSqliteStore = class extends Store {
|
|
|
380
383
|
}
|
|
381
384
|
};
|
|
382
385
|
|
|
386
|
+
// src/mixins/queued_store.ts
|
|
387
|
+
var import_denque = __toESM(require("denque"), 1);
|
|
388
|
+
function QueuedStore(Base) {
|
|
389
|
+
return class Queued extends Base {
|
|
390
|
+
queue;
|
|
391
|
+
processingInterval = null;
|
|
392
|
+
BATCH_SIZE;
|
|
393
|
+
PROCESS_INTERVAL_MS;
|
|
394
|
+
WARN_THRESHOLD;
|
|
395
|
+
PREALLOCATE;
|
|
396
|
+
constructor(...args) {
|
|
397
|
+
super(...args);
|
|
398
|
+
const config = args[0] || {};
|
|
399
|
+
this.BATCH_SIZE = config.batchSize ?? 100;
|
|
400
|
+
this.PROCESS_INTERVAL_MS = config.processIntervalMs ?? 100;
|
|
401
|
+
this.WARN_THRESHOLD = config.warnThreshold ?? 1e5;
|
|
402
|
+
this.PREALLOCATE = config.preallocate ?? true;
|
|
403
|
+
this.queue = this.PREALLOCATE ? new import_denque.default([], { capacity: this.WARN_THRESHOLD * 2 }) : new import_denque.default();
|
|
404
|
+
}
|
|
405
|
+
async initialize() {
|
|
406
|
+
if (super["initialize"]) {
|
|
407
|
+
await super["initialize"].call(this);
|
|
408
|
+
}
|
|
409
|
+
this.startProcessingQueue();
|
|
410
|
+
process.on("SIGINT", () => this.shutdown());
|
|
411
|
+
process.on("SIGTERM", () => this.shutdown());
|
|
412
|
+
}
|
|
413
|
+
async truncate() {
|
|
414
|
+
this.queue.clear();
|
|
415
|
+
if (super["truncate"]) {
|
|
416
|
+
await super["truncate"].call(this);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
async save(entry) {
|
|
420
|
+
this.queue.push(entry);
|
|
421
|
+
if (this.queue.length > this.WARN_THRESHOLD) {
|
|
422
|
+
console.warn(`\u26A0\uFE0F LensJs Queue size very large: ${this.queue.length}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
startProcessingQueue() {
|
|
426
|
+
if (this.processingInterval) clearInterval(this.processingInterval);
|
|
427
|
+
this.processingInterval = setInterval(
|
|
428
|
+
() => this.processQueue(),
|
|
429
|
+
this.PROCESS_INTERVAL_MS
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
async processQueue() {
|
|
433
|
+
if (this.queue.isEmpty()) return;
|
|
434
|
+
const batchSize = Math.min(
|
|
435
|
+
this.BATCH_SIZE,
|
|
436
|
+
Math.max(10, Math.floor(this.queue.length / 10))
|
|
437
|
+
);
|
|
438
|
+
const entriesToProcess = this.queue.remove(0, batchSize);
|
|
439
|
+
if (!entriesToProcess.length) return;
|
|
440
|
+
for (const entry of entriesToProcess) {
|
|
441
|
+
super["save"]?.call(this, entry).catch((error) => {
|
|
442
|
+
console.error("Error saving queued entry:", error);
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
async stopProcessingQueue() {
|
|
447
|
+
if (this.processingInterval) {
|
|
448
|
+
clearInterval(this.processingInterval);
|
|
449
|
+
this.processingInterval = null;
|
|
450
|
+
}
|
|
451
|
+
if (!this.queue.isEmpty()) {
|
|
452
|
+
await this.processQueue();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
async shutdown() {
|
|
456
|
+
await this.stopProcessingQueue();
|
|
457
|
+
process.exit(0);
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// src/utils/compose.ts
|
|
463
|
+
function compose(superclass, ...mixins) {
|
|
464
|
+
return mixins.reduce((c, mixin) => mixin(c), superclass);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// src/stores/queued_sqlite.ts
|
|
468
|
+
var QueuedSqliteStore = class extends compose(
|
|
469
|
+
BetterSqliteStore,
|
|
470
|
+
QueuedStore
|
|
471
|
+
) {
|
|
472
|
+
};
|
|
473
|
+
|
|
383
474
|
// src/utils/index.ts
|
|
384
475
|
var utils_exports = {};
|
|
385
476
|
__export(utils_exports, {
|
|
477
|
+
compose: () => compose,
|
|
386
478
|
formatSqlQuery: () => formatSqlQuery,
|
|
387
479
|
generateRandomUuid: () => generateRandomUuid,
|
|
388
480
|
getMeta: () => getMeta,
|
|
@@ -523,6 +615,7 @@ var Lens = class {
|
|
|
523
615
|
static watchers = /* @__PURE__ */ new Map();
|
|
524
616
|
static store;
|
|
525
617
|
static adapter;
|
|
618
|
+
static config;
|
|
526
619
|
static watch(watcher) {
|
|
527
620
|
this.watchers.set(watcher.name, watcher);
|
|
528
621
|
return this;
|
|
@@ -532,22 +625,23 @@ var Lens = class {
|
|
|
532
625
|
return this;
|
|
533
626
|
}
|
|
534
627
|
static async start(config = {
|
|
535
|
-
|
|
628
|
+
path: "lens",
|
|
536
629
|
appName: "Lens",
|
|
537
630
|
enabled: true
|
|
538
631
|
}) {
|
|
539
632
|
if (!config.enabled) {
|
|
540
633
|
return;
|
|
541
634
|
}
|
|
542
|
-
|
|
635
|
+
this.config = config;
|
|
636
|
+
await this.bindContainerDeps();
|
|
543
637
|
let adapter = this.getAdapter();
|
|
544
638
|
adapter.setWatchers(Array.from(this.watchers.values())).setup();
|
|
545
639
|
const { apiRoutes } = this.getRoutes({
|
|
546
|
-
|
|
640
|
+
path: config.path
|
|
547
641
|
});
|
|
548
642
|
adapter.registerRoutes(apiRoutes);
|
|
549
643
|
const uiPath = this.getUiPath();
|
|
550
|
-
adapter.serveUI(uiPath, config.
|
|
644
|
+
adapter.serveUI(uiPath, config.path, getUiConfig());
|
|
551
645
|
}
|
|
552
646
|
static setStore(store) {
|
|
553
647
|
this.store = store;
|
|
@@ -570,7 +664,7 @@ var Lens = class {
|
|
|
570
664
|
const { __dirname: __dirname2 } = getMeta(import_meta.url);
|
|
571
665
|
return path2.resolve(this.normalizeDirName(__dirname2), "ui");
|
|
572
666
|
}
|
|
573
|
-
static getRoutes({
|
|
667
|
+
static getRoutes({ path: path4 }) {
|
|
574
668
|
const apiRoutes = [
|
|
575
669
|
{
|
|
576
670
|
method: "GET",
|
|
@@ -579,71 +673,71 @@ var Lens = class {
|
|
|
579
673
|
},
|
|
580
674
|
{
|
|
581
675
|
method: "GET",
|
|
582
|
-
path: `/${
|
|
676
|
+
path: `/${path4}/api/requests`,
|
|
583
677
|
handler: async (data) => await ApiController.getRequests(data)
|
|
584
678
|
},
|
|
585
679
|
{
|
|
586
680
|
method: "GET",
|
|
587
|
-
path: `/${
|
|
681
|
+
path: `/${path4}/api/requests/:id`,
|
|
588
682
|
handler: async (data) => await ApiController.getRequest(data)
|
|
589
683
|
},
|
|
590
684
|
{
|
|
591
685
|
method: "GET",
|
|
592
|
-
path: `/${
|
|
686
|
+
path: `/${path4}/api/queries`,
|
|
593
687
|
handler: async (data) => await ApiController.getQueries(data)
|
|
594
688
|
},
|
|
595
689
|
{
|
|
596
690
|
method: "GET",
|
|
597
|
-
path: `/${
|
|
691
|
+
path: `/${path4}/api/queries/:id`,
|
|
598
692
|
handler: async (data) => await ApiController.getQuery(data)
|
|
599
693
|
},
|
|
600
694
|
{
|
|
601
695
|
method: "GET",
|
|
602
|
-
path: `/${
|
|
696
|
+
path: `/${path4}/api/cache`,
|
|
603
697
|
handler: async (data) => await ApiController.getCacheEntries(data)
|
|
604
698
|
},
|
|
605
699
|
{
|
|
606
700
|
method: "GET",
|
|
607
|
-
path: `/${
|
|
701
|
+
path: `/${path4}/api/cache/:id`,
|
|
608
702
|
handler: async (data) => await ApiController.getCacheEntry(data)
|
|
609
703
|
},
|
|
610
704
|
{
|
|
611
705
|
method: "GET",
|
|
612
|
-
path: `/${
|
|
706
|
+
path: `/${path4}/api/exceptions`,
|
|
613
707
|
handler: async (data) => await ApiController.getExceptions(data)
|
|
614
708
|
},
|
|
615
709
|
{
|
|
616
710
|
method: "GET",
|
|
617
|
-
path: `/${
|
|
711
|
+
path: `/${path4}/api/exceptions/:id`,
|
|
618
712
|
handler: async (data) => await ApiController.getException(data)
|
|
619
713
|
},
|
|
620
714
|
{
|
|
621
715
|
method: "DELETE",
|
|
622
|
-
path: `/${
|
|
716
|
+
path: `/${path4}/api/truncate`,
|
|
623
717
|
handler: async () => await ApiController.truncate()
|
|
624
718
|
}
|
|
625
719
|
];
|
|
626
720
|
return { apiRoutes };
|
|
627
721
|
}
|
|
628
|
-
static async bindContainerDeps(
|
|
722
|
+
static async bindContainerDeps() {
|
|
629
723
|
const dbStore = await this.getStore();
|
|
630
724
|
Container.singleton("store", () => dbStore);
|
|
631
725
|
Container.singleton("uiConfig", () => {
|
|
632
726
|
return {
|
|
633
|
-
appName: config.appName,
|
|
634
|
-
path: `/${config.
|
|
727
|
+
appName: this.config.appName,
|
|
728
|
+
path: `/${this.config.path}`,
|
|
635
729
|
api: {
|
|
636
|
-
requests: `/${config.
|
|
637
|
-
queries: `/${config.
|
|
638
|
-
cache: `/${config.
|
|
639
|
-
exceptions: `/${config.
|
|
640
|
-
truncate: `/${config.
|
|
730
|
+
requests: `/${this.config.path}/api/requests`,
|
|
731
|
+
queries: `/${this.config.path}/api/queries`,
|
|
732
|
+
cache: `/${this.config.path}/api/cache`,
|
|
733
|
+
exceptions: `/${this.config.path}/api/exceptions`,
|
|
734
|
+
truncate: `/${this.config.path}/api/truncate`
|
|
641
735
|
}
|
|
642
736
|
};
|
|
643
737
|
});
|
|
644
738
|
}
|
|
645
739
|
static async getDefaultStore() {
|
|
646
|
-
const store = new
|
|
740
|
+
const store = new QueuedSqliteStore(this.config.storeQueueConfig);
|
|
647
741
|
await store.initialize();
|
|
648
742
|
return store;
|
|
649
743
|
}
|
|
@@ -669,10 +763,19 @@ var QueryWatcher = class extends Watcher {
|
|
|
669
763
|
};
|
|
670
764
|
|
|
671
765
|
// src/watchers/request_watcher.ts
|
|
672
|
-
var RequestWatcher = class extends Watcher {
|
|
766
|
+
var RequestWatcher = class _RequestWatcher extends Watcher {
|
|
673
767
|
name = "request" /* REQUEST */;
|
|
674
|
-
|
|
675
|
-
|
|
768
|
+
static DEFAULT_HIDDEN_HEADERS = ["Authorization", "Basic"];
|
|
769
|
+
static DEFAULT_HIDDEN_BODY_PARAMS = [
|
|
770
|
+
"password",
|
|
771
|
+
"passwordConfirmation",
|
|
772
|
+
"secret",
|
|
773
|
+
"password_confirmation"
|
|
774
|
+
];
|
|
775
|
+
async log(data, hidden = {}) {
|
|
776
|
+
const headersToHide = (hidden.headers?.length ? hidden.headers : _RequestWatcher.DEFAULT_HIDDEN_HEADERS).map((header) => header.toLowerCase());
|
|
777
|
+
const bodyParamsToHide = hidden.bodyParams?.length ? hidden.bodyParams : _RequestWatcher.DEFAULT_HIDDEN_BODY_PARAMS;
|
|
778
|
+
const payload = {
|
|
676
779
|
id: data.request.id,
|
|
677
780
|
type: this.name,
|
|
678
781
|
minimal_data: {
|
|
@@ -686,9 +789,40 @@ var RequestWatcher = class extends Watcher {
|
|
|
686
789
|
data: {
|
|
687
790
|
...data.request,
|
|
688
791
|
user: data.user,
|
|
689
|
-
response: data.response
|
|
792
|
+
response: data.response || {}
|
|
690
793
|
}
|
|
691
|
-
}
|
|
794
|
+
};
|
|
795
|
+
payload.data.headers = this.hideSensitive(
|
|
796
|
+
this.normalizeHeaders(payload.data.headers),
|
|
797
|
+
headersToHide
|
|
798
|
+
);
|
|
799
|
+
payload.data.response.headers = this.hideSensitive(
|
|
800
|
+
this.normalizeHeaders(payload.data.response?.headers),
|
|
801
|
+
headersToHide
|
|
802
|
+
);
|
|
803
|
+
payload.data.body = this.hideSensitive(payload.data.body, bodyParamsToHide, false);
|
|
804
|
+
await getStore().save(payload);
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Normalize headers: converts keys to lowercase.
|
|
808
|
+
*/
|
|
809
|
+
normalizeHeaders(headers) {
|
|
810
|
+
if (!headers || typeof headers !== "object") return {};
|
|
811
|
+
return Object.fromEntries(
|
|
812
|
+
Object.entries(headers).map(([k, v]) => [k.toLowerCase(), v])
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
hideSensitive(obj, keysToHide = [], isObjHeaders = true) {
|
|
816
|
+
if (!obj || typeof obj !== "object") {
|
|
817
|
+
return isObjHeaders ? {} : obj;
|
|
818
|
+
}
|
|
819
|
+
const clone = { ...obj };
|
|
820
|
+
for (const key of keysToHide) {
|
|
821
|
+
if (key in clone) {
|
|
822
|
+
clone[key] = "*******";
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return clone;
|
|
692
826
|
}
|
|
693
827
|
};
|
|
694
828
|
|
|
@@ -919,6 +1053,7 @@ var handleUncaughExceptions = (logger) => {
|
|
|
919
1053
|
LensStore,
|
|
920
1054
|
LensWatcher,
|
|
921
1055
|
QueryWatcher,
|
|
1056
|
+
QueuedSqliteStore,
|
|
922
1057
|
RequestWatcher,
|
|
923
1058
|
WatcherTypeEnum,
|
|
924
1059
|
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-
|
|
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-
|
|
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';
|
package/dist/index.js
CHANGED
|
@@ -183,6 +183,8 @@ import * as path2 from "path";
|
|
|
183
183
|
|
|
184
184
|
// src/abstracts/store.ts
|
|
185
185
|
var Store = class {
|
|
186
|
+
constructor(...args) {
|
|
187
|
+
}
|
|
186
188
|
getAllExceptions(_paginationParams) {
|
|
187
189
|
return this.defaultMinimalPaginate();
|
|
188
190
|
}
|
|
@@ -334,9 +336,98 @@ var BetterSqliteStore = class extends Store {
|
|
|
334
336
|
}
|
|
335
337
|
};
|
|
336
338
|
|
|
339
|
+
// src/mixins/queued_store.ts
|
|
340
|
+
import Denque from "denque";
|
|
341
|
+
function QueuedStore(Base) {
|
|
342
|
+
return class Queued extends Base {
|
|
343
|
+
queue;
|
|
344
|
+
processingInterval = null;
|
|
345
|
+
BATCH_SIZE;
|
|
346
|
+
PROCESS_INTERVAL_MS;
|
|
347
|
+
WARN_THRESHOLD;
|
|
348
|
+
PREALLOCATE;
|
|
349
|
+
constructor(...args) {
|
|
350
|
+
super(...args);
|
|
351
|
+
const config = args[0] || {};
|
|
352
|
+
this.BATCH_SIZE = config.batchSize ?? 100;
|
|
353
|
+
this.PROCESS_INTERVAL_MS = config.processIntervalMs ?? 100;
|
|
354
|
+
this.WARN_THRESHOLD = config.warnThreshold ?? 1e5;
|
|
355
|
+
this.PREALLOCATE = config.preallocate ?? true;
|
|
356
|
+
this.queue = this.PREALLOCATE ? new Denque([], { capacity: this.WARN_THRESHOLD * 2 }) : new Denque();
|
|
357
|
+
}
|
|
358
|
+
async initialize() {
|
|
359
|
+
if (super["initialize"]) {
|
|
360
|
+
await super["initialize"].call(this);
|
|
361
|
+
}
|
|
362
|
+
this.startProcessingQueue();
|
|
363
|
+
process.on("SIGINT", () => this.shutdown());
|
|
364
|
+
process.on("SIGTERM", () => this.shutdown());
|
|
365
|
+
}
|
|
366
|
+
async truncate() {
|
|
367
|
+
this.queue.clear();
|
|
368
|
+
if (super["truncate"]) {
|
|
369
|
+
await super["truncate"].call(this);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async save(entry) {
|
|
373
|
+
this.queue.push(entry);
|
|
374
|
+
if (this.queue.length > this.WARN_THRESHOLD) {
|
|
375
|
+
console.warn(`\u26A0\uFE0F LensJs Queue size very large: ${this.queue.length}`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
startProcessingQueue() {
|
|
379
|
+
if (this.processingInterval) clearInterval(this.processingInterval);
|
|
380
|
+
this.processingInterval = setInterval(
|
|
381
|
+
() => this.processQueue(),
|
|
382
|
+
this.PROCESS_INTERVAL_MS
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
async processQueue() {
|
|
386
|
+
if (this.queue.isEmpty()) return;
|
|
387
|
+
const batchSize = Math.min(
|
|
388
|
+
this.BATCH_SIZE,
|
|
389
|
+
Math.max(10, Math.floor(this.queue.length / 10))
|
|
390
|
+
);
|
|
391
|
+
const entriesToProcess = this.queue.remove(0, batchSize);
|
|
392
|
+
if (!entriesToProcess.length) return;
|
|
393
|
+
for (const entry of entriesToProcess) {
|
|
394
|
+
super["save"]?.call(this, entry).catch((error) => {
|
|
395
|
+
console.error("Error saving queued entry:", error);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async stopProcessingQueue() {
|
|
400
|
+
if (this.processingInterval) {
|
|
401
|
+
clearInterval(this.processingInterval);
|
|
402
|
+
this.processingInterval = null;
|
|
403
|
+
}
|
|
404
|
+
if (!this.queue.isEmpty()) {
|
|
405
|
+
await this.processQueue();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async shutdown() {
|
|
409
|
+
await this.stopProcessingQueue();
|
|
410
|
+
process.exit(0);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/utils/compose.ts
|
|
416
|
+
function compose(superclass, ...mixins) {
|
|
417
|
+
return mixins.reduce((c, mixin) => mixin(c), superclass);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/stores/queued_sqlite.ts
|
|
421
|
+
var QueuedSqliteStore = class extends compose(
|
|
422
|
+
BetterSqliteStore,
|
|
423
|
+
QueuedStore
|
|
424
|
+
) {
|
|
425
|
+
};
|
|
426
|
+
|
|
337
427
|
// src/utils/index.ts
|
|
338
428
|
var utils_exports = {};
|
|
339
429
|
__export(utils_exports, {
|
|
430
|
+
compose: () => compose,
|
|
340
431
|
formatSqlQuery: () => formatSqlQuery,
|
|
341
432
|
generateRandomUuid: () => generateRandomUuid,
|
|
342
433
|
getMeta: () => getMeta,
|
|
@@ -476,6 +567,7 @@ var Lens = class {
|
|
|
476
567
|
static watchers = /* @__PURE__ */ new Map();
|
|
477
568
|
static store;
|
|
478
569
|
static adapter;
|
|
570
|
+
static config;
|
|
479
571
|
static watch(watcher) {
|
|
480
572
|
this.watchers.set(watcher.name, watcher);
|
|
481
573
|
return this;
|
|
@@ -485,22 +577,23 @@ var Lens = class {
|
|
|
485
577
|
return this;
|
|
486
578
|
}
|
|
487
579
|
static async start(config = {
|
|
488
|
-
|
|
580
|
+
path: "lens",
|
|
489
581
|
appName: "Lens",
|
|
490
582
|
enabled: true
|
|
491
583
|
}) {
|
|
492
584
|
if (!config.enabled) {
|
|
493
585
|
return;
|
|
494
586
|
}
|
|
495
|
-
|
|
587
|
+
this.config = config;
|
|
588
|
+
await this.bindContainerDeps();
|
|
496
589
|
let adapter = this.getAdapter();
|
|
497
590
|
adapter.setWatchers(Array.from(this.watchers.values())).setup();
|
|
498
591
|
const { apiRoutes } = this.getRoutes({
|
|
499
|
-
|
|
592
|
+
path: config.path
|
|
500
593
|
});
|
|
501
594
|
adapter.registerRoutes(apiRoutes);
|
|
502
595
|
const uiPath = this.getUiPath();
|
|
503
|
-
adapter.serveUI(uiPath, config.
|
|
596
|
+
adapter.serveUI(uiPath, config.path, getUiConfig());
|
|
504
597
|
}
|
|
505
598
|
static setStore(store) {
|
|
506
599
|
this.store = store;
|
|
@@ -523,7 +616,7 @@ var Lens = class {
|
|
|
523
616
|
const { __dirname: __dirname2 } = getMeta(import.meta.url);
|
|
524
617
|
return path2.resolve(this.normalizeDirName(__dirname2), "ui");
|
|
525
618
|
}
|
|
526
|
-
static getRoutes({
|
|
619
|
+
static getRoutes({ path: path4 }) {
|
|
527
620
|
const apiRoutes = [
|
|
528
621
|
{
|
|
529
622
|
method: "GET",
|
|
@@ -532,71 +625,71 @@ var Lens = class {
|
|
|
532
625
|
},
|
|
533
626
|
{
|
|
534
627
|
method: "GET",
|
|
535
|
-
path: `/${
|
|
628
|
+
path: `/${path4}/api/requests`,
|
|
536
629
|
handler: async (data) => await ApiController.getRequests(data)
|
|
537
630
|
},
|
|
538
631
|
{
|
|
539
632
|
method: "GET",
|
|
540
|
-
path: `/${
|
|
633
|
+
path: `/${path4}/api/requests/:id`,
|
|
541
634
|
handler: async (data) => await ApiController.getRequest(data)
|
|
542
635
|
},
|
|
543
636
|
{
|
|
544
637
|
method: "GET",
|
|
545
|
-
path: `/${
|
|
638
|
+
path: `/${path4}/api/queries`,
|
|
546
639
|
handler: async (data) => await ApiController.getQueries(data)
|
|
547
640
|
},
|
|
548
641
|
{
|
|
549
642
|
method: "GET",
|
|
550
|
-
path: `/${
|
|
643
|
+
path: `/${path4}/api/queries/:id`,
|
|
551
644
|
handler: async (data) => await ApiController.getQuery(data)
|
|
552
645
|
},
|
|
553
646
|
{
|
|
554
647
|
method: "GET",
|
|
555
|
-
path: `/${
|
|
648
|
+
path: `/${path4}/api/cache`,
|
|
556
649
|
handler: async (data) => await ApiController.getCacheEntries(data)
|
|
557
650
|
},
|
|
558
651
|
{
|
|
559
652
|
method: "GET",
|
|
560
|
-
path: `/${
|
|
653
|
+
path: `/${path4}/api/cache/:id`,
|
|
561
654
|
handler: async (data) => await ApiController.getCacheEntry(data)
|
|
562
655
|
},
|
|
563
656
|
{
|
|
564
657
|
method: "GET",
|
|
565
|
-
path: `/${
|
|
658
|
+
path: `/${path4}/api/exceptions`,
|
|
566
659
|
handler: async (data) => await ApiController.getExceptions(data)
|
|
567
660
|
},
|
|
568
661
|
{
|
|
569
662
|
method: "GET",
|
|
570
|
-
path: `/${
|
|
663
|
+
path: `/${path4}/api/exceptions/:id`,
|
|
571
664
|
handler: async (data) => await ApiController.getException(data)
|
|
572
665
|
},
|
|
573
666
|
{
|
|
574
667
|
method: "DELETE",
|
|
575
|
-
path: `/${
|
|
668
|
+
path: `/${path4}/api/truncate`,
|
|
576
669
|
handler: async () => await ApiController.truncate()
|
|
577
670
|
}
|
|
578
671
|
];
|
|
579
672
|
return { apiRoutes };
|
|
580
673
|
}
|
|
581
|
-
static async bindContainerDeps(
|
|
674
|
+
static async bindContainerDeps() {
|
|
582
675
|
const dbStore = await this.getStore();
|
|
583
676
|
Container.singleton("store", () => dbStore);
|
|
584
677
|
Container.singleton("uiConfig", () => {
|
|
585
678
|
return {
|
|
586
|
-
appName: config.appName,
|
|
587
|
-
path: `/${config.
|
|
679
|
+
appName: this.config.appName,
|
|
680
|
+
path: `/${this.config.path}`,
|
|
588
681
|
api: {
|
|
589
|
-
requests: `/${config.
|
|
590
|
-
queries: `/${config.
|
|
591
|
-
cache: `/${config.
|
|
592
|
-
exceptions: `/${config.
|
|
593
|
-
truncate: `/${config.
|
|
682
|
+
requests: `/${this.config.path}/api/requests`,
|
|
683
|
+
queries: `/${this.config.path}/api/queries`,
|
|
684
|
+
cache: `/${this.config.path}/api/cache`,
|
|
685
|
+
exceptions: `/${this.config.path}/api/exceptions`,
|
|
686
|
+
truncate: `/${this.config.path}/api/truncate`
|
|
594
687
|
}
|
|
595
688
|
};
|
|
596
689
|
});
|
|
597
690
|
}
|
|
598
691
|
static async getDefaultStore() {
|
|
599
|
-
const store = new
|
|
692
|
+
const store = new QueuedSqliteStore(this.config.storeQueueConfig);
|
|
600
693
|
await store.initialize();
|
|
601
694
|
return store;
|
|
602
695
|
}
|
|
@@ -622,10 +715,19 @@ var QueryWatcher = class extends Watcher {
|
|
|
622
715
|
};
|
|
623
716
|
|
|
624
717
|
// src/watchers/request_watcher.ts
|
|
625
|
-
var RequestWatcher = class extends Watcher {
|
|
718
|
+
var RequestWatcher = class _RequestWatcher extends Watcher {
|
|
626
719
|
name = "request" /* REQUEST */;
|
|
627
|
-
|
|
628
|
-
|
|
720
|
+
static DEFAULT_HIDDEN_HEADERS = ["Authorization", "Basic"];
|
|
721
|
+
static DEFAULT_HIDDEN_BODY_PARAMS = [
|
|
722
|
+
"password",
|
|
723
|
+
"passwordConfirmation",
|
|
724
|
+
"secret",
|
|
725
|
+
"password_confirmation"
|
|
726
|
+
];
|
|
727
|
+
async log(data, hidden = {}) {
|
|
728
|
+
const headersToHide = (hidden.headers?.length ? hidden.headers : _RequestWatcher.DEFAULT_HIDDEN_HEADERS).map((header) => header.toLowerCase());
|
|
729
|
+
const bodyParamsToHide = hidden.bodyParams?.length ? hidden.bodyParams : _RequestWatcher.DEFAULT_HIDDEN_BODY_PARAMS;
|
|
730
|
+
const payload = {
|
|
629
731
|
id: data.request.id,
|
|
630
732
|
type: this.name,
|
|
631
733
|
minimal_data: {
|
|
@@ -639,9 +741,40 @@ var RequestWatcher = class extends Watcher {
|
|
|
639
741
|
data: {
|
|
640
742
|
...data.request,
|
|
641
743
|
user: data.user,
|
|
642
|
-
response: data.response
|
|
744
|
+
response: data.response || {}
|
|
643
745
|
}
|
|
644
|
-
}
|
|
746
|
+
};
|
|
747
|
+
payload.data.headers = this.hideSensitive(
|
|
748
|
+
this.normalizeHeaders(payload.data.headers),
|
|
749
|
+
headersToHide
|
|
750
|
+
);
|
|
751
|
+
payload.data.response.headers = this.hideSensitive(
|
|
752
|
+
this.normalizeHeaders(payload.data.response?.headers),
|
|
753
|
+
headersToHide
|
|
754
|
+
);
|
|
755
|
+
payload.data.body = this.hideSensitive(payload.data.body, bodyParamsToHide, false);
|
|
756
|
+
await getStore().save(payload);
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Normalize headers: converts keys to lowercase.
|
|
760
|
+
*/
|
|
761
|
+
normalizeHeaders(headers) {
|
|
762
|
+
if (!headers || typeof headers !== "object") return {};
|
|
763
|
+
return Object.fromEntries(
|
|
764
|
+
Object.entries(headers).map(([k, v]) => [k.toLowerCase(), v])
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
hideSensitive(obj, keysToHide = [], isObjHeaders = true) {
|
|
768
|
+
if (!obj || typeof obj !== "object") {
|
|
769
|
+
return isObjHeaders ? {} : obj;
|
|
770
|
+
}
|
|
771
|
+
const clone = { ...obj };
|
|
772
|
+
for (const key of keysToHide) {
|
|
773
|
+
if (key in clone) {
|
|
774
|
+
clone[key] = "*******";
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return clone;
|
|
645
778
|
}
|
|
646
779
|
};
|
|
647
780
|
|
|
@@ -871,6 +1004,7 @@ export {
|
|
|
871
1004
|
Store as LensStore,
|
|
872
1005
|
Watcher as LensWatcher,
|
|
873
1006
|
QueryWatcher,
|
|
1007
|
+
QueuedSqliteStore,
|
|
874
1008
|
RequestWatcher,
|
|
875
1009
|
WatcherTypeEnum,
|
|
876
1010
|
createEmittery,
|