@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
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/stores/queued_sqlite.ts
|
|
31
|
+
var queued_sqlite_exports = {};
|
|
32
|
+
__export(queued_sqlite_exports, {
|
|
33
|
+
default: () => QueuedSqliteStore
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(queued_sqlite_exports);
|
|
36
|
+
|
|
37
|
+
// src/mixins/queued_store.ts
|
|
38
|
+
var import_denque = __toESM(require("denque"), 1);
|
|
39
|
+
function QueuedStore(Base) {
|
|
40
|
+
return class Queued extends Base {
|
|
41
|
+
queue;
|
|
42
|
+
processingInterval = null;
|
|
43
|
+
BATCH_SIZE;
|
|
44
|
+
PROCESS_INTERVAL_MS;
|
|
45
|
+
WARN_THRESHOLD;
|
|
46
|
+
PREALLOCATE;
|
|
47
|
+
constructor(...args) {
|
|
48
|
+
super(...args);
|
|
49
|
+
const config = args[0] || {};
|
|
50
|
+
this.BATCH_SIZE = config.batchSize ?? 100;
|
|
51
|
+
this.PROCESS_INTERVAL_MS = config.processIntervalMs ?? 100;
|
|
52
|
+
this.WARN_THRESHOLD = config.warnThreshold ?? 1e5;
|
|
53
|
+
this.PREALLOCATE = config.preallocate ?? true;
|
|
54
|
+
this.queue = this.PREALLOCATE ? new import_denque.default([], { capacity: this.WARN_THRESHOLD * 2 }) : new import_denque.default();
|
|
55
|
+
}
|
|
56
|
+
async initialize() {
|
|
57
|
+
if (super["initialize"]) {
|
|
58
|
+
await super["initialize"].call(this);
|
|
59
|
+
}
|
|
60
|
+
this.startProcessingQueue();
|
|
61
|
+
process.on("SIGINT", () => this.shutdown());
|
|
62
|
+
process.on("SIGTERM", () => this.shutdown());
|
|
63
|
+
}
|
|
64
|
+
async truncate() {
|
|
65
|
+
this.queue.clear();
|
|
66
|
+
if (super["truncate"]) {
|
|
67
|
+
await super["truncate"].call(this);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async save(entry) {
|
|
71
|
+
this.queue.push(entry);
|
|
72
|
+
if (this.queue.length > this.WARN_THRESHOLD) {
|
|
73
|
+
console.warn(`\u26A0\uFE0F LensJs Queue size very large: ${this.queue.length}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
startProcessingQueue() {
|
|
77
|
+
if (this.processingInterval) clearInterval(this.processingInterval);
|
|
78
|
+
this.processingInterval = setInterval(
|
|
79
|
+
() => this.processQueue(),
|
|
80
|
+
this.PROCESS_INTERVAL_MS
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
async processQueue() {
|
|
84
|
+
if (this.queue.isEmpty()) return;
|
|
85
|
+
const batchSize = Math.min(
|
|
86
|
+
this.BATCH_SIZE,
|
|
87
|
+
Math.max(10, Math.floor(this.queue.length / 10))
|
|
88
|
+
);
|
|
89
|
+
const entriesToProcess = this.queue.remove(0, batchSize);
|
|
90
|
+
if (!entriesToProcess.length) return;
|
|
91
|
+
for (const entry of entriesToProcess) {
|
|
92
|
+
super["save"]?.call(this, entry).catch((error) => {
|
|
93
|
+
console.error("Error saving queued entry:", error);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async stopProcessingQueue() {
|
|
98
|
+
if (this.processingInterval) {
|
|
99
|
+
clearInterval(this.processingInterval);
|
|
100
|
+
this.processingInterval = null;
|
|
101
|
+
}
|
|
102
|
+
if (!this.queue.isEmpty()) {
|
|
103
|
+
await this.processQueue();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async shutdown() {
|
|
107
|
+
await this.stopProcessingQueue();
|
|
108
|
+
process.exit(0);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/utils/compose.ts
|
|
114
|
+
function compose(superclass, ...mixins) {
|
|
115
|
+
return mixins.reduce((c, mixin) => mixin(c), superclass);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/abstracts/store.ts
|
|
119
|
+
var Store = class {
|
|
120
|
+
constructor(...args) {
|
|
121
|
+
}
|
|
122
|
+
getAllExceptions(_paginationParams) {
|
|
123
|
+
return this.defaultMinimalPaginate();
|
|
124
|
+
}
|
|
125
|
+
stringifyData(data) {
|
|
126
|
+
if (typeof data === "string") {
|
|
127
|
+
return data;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
return JSON.stringify(data);
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.error(`Failed to stringify lens data: ${e}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
defaultMinimalPaginate() {
|
|
136
|
+
return Promise.resolve({
|
|
137
|
+
data: [],
|
|
138
|
+
meta: {
|
|
139
|
+
currentPage: 0,
|
|
140
|
+
lastPage: 0,
|
|
141
|
+
total: 0
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// src/stores/better_sqlite.ts
|
|
148
|
+
var import_crypto = require("crypto");
|
|
149
|
+
var import_libsql = __toESM(require("libsql"), 1);
|
|
150
|
+
var import_date = require("@lensjs/date");
|
|
151
|
+
var TABLE_NAME = "lens_entries";
|
|
152
|
+
var BetterSqliteStore = class extends Store {
|
|
153
|
+
connection;
|
|
154
|
+
async initialize() {
|
|
155
|
+
this.connection = new import_libsql.default("lens.db");
|
|
156
|
+
this.setupSchema();
|
|
157
|
+
console.log("Connected to Lens (SQLite) database.");
|
|
158
|
+
}
|
|
159
|
+
async truncate() {
|
|
160
|
+
this.connection.prepare(`DELETE FROM ${TABLE_NAME};`).run();
|
|
161
|
+
}
|
|
162
|
+
async save(entry) {
|
|
163
|
+
this.connection.prepare(
|
|
164
|
+
`INSERT INTO ${TABLE_NAME} (id, data, type, created_at, lens_entry_id, minimal_data) values($id, $data, $type, $created_at, $lens_entry_id, $minimalData)`
|
|
165
|
+
).run({
|
|
166
|
+
id: entry.id ?? (0, import_crypto.randomUUID)(),
|
|
167
|
+
data: this.stringifyData(entry.data),
|
|
168
|
+
type: entry.type,
|
|
169
|
+
created_at: entry.timestamp ?? (0, import_date.nowISO)(),
|
|
170
|
+
lens_entry_id: entry.requestId || null,
|
|
171
|
+
minimalData: this.stringifyData(entry.minimal_data ?? {})
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
async getAllQueries(pagination) {
|
|
175
|
+
return await this.paginate("query" /* QUERY */, pagination);
|
|
176
|
+
}
|
|
177
|
+
async getAllRequests(pagination) {
|
|
178
|
+
return await this.paginate("request" /* REQUEST */, pagination, false);
|
|
179
|
+
}
|
|
180
|
+
async getAllCacheEntries(pagination) {
|
|
181
|
+
return await this.paginate("cache" /* CACHE */, pagination);
|
|
182
|
+
}
|
|
183
|
+
async getAllExceptions(pagination) {
|
|
184
|
+
return await this.paginate("exception" /* EXCEPTION */, pagination, false);
|
|
185
|
+
}
|
|
186
|
+
async allByRequestId(requestId, type, includeFullData = true) {
|
|
187
|
+
const rows = this.connection.prepare(
|
|
188
|
+
`${this.getSelectedColumns(includeFullData)} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
|
|
189
|
+
).all({ type, requestId });
|
|
190
|
+
return this.mapRows(rows, includeFullData);
|
|
191
|
+
}
|
|
192
|
+
async paginate(type, { page, perPage }, includeFullData = true) {
|
|
193
|
+
const offset = (page - 1) * perPage;
|
|
194
|
+
const query = `${this.getSelectedColumns(
|
|
195
|
+
includeFullData
|
|
196
|
+
)} FROM ${TABLE_NAME} WHERE type = ? ORDER BY created_at DESC LIMIT ? OFFSET ?`;
|
|
197
|
+
const count = await this.count(type);
|
|
198
|
+
const rows = this.connection.prepare(query).all(type, perPage, offset);
|
|
199
|
+
const mappedRows = this.mapRows(rows, includeFullData);
|
|
200
|
+
return {
|
|
201
|
+
meta: {
|
|
202
|
+
total: count,
|
|
203
|
+
lastPage: Math.ceil(count / perPage),
|
|
204
|
+
currentPage: page
|
|
205
|
+
},
|
|
206
|
+
data: mappedRows
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
async count(type) {
|
|
210
|
+
const result = this.connection.prepare(`SELECT count(*) as count FROM ${TABLE_NAME} WHERE type = ?`).get(type);
|
|
211
|
+
return Number(result.count);
|
|
212
|
+
}
|
|
213
|
+
async find(type, id) {
|
|
214
|
+
const row = this.connection.prepare(
|
|
215
|
+
`${this.getSelectedColumns()} FROM ${TABLE_NAME} WHERE id = ? AND type = ? LIMIT 1`
|
|
216
|
+
).get(id, type);
|
|
217
|
+
if (!row) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
return this.mapRow(row, true);
|
|
221
|
+
}
|
|
222
|
+
setupSchema() {
|
|
223
|
+
this.connection.exec("PRAGMA journal_mode = WAL;");
|
|
224
|
+
this.connection.exec("PRAGMA synchronous = NORMAL;");
|
|
225
|
+
const createTable = `
|
|
226
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
|
|
227
|
+
id TEXT PRIMARY KEY,
|
|
228
|
+
minimal_data TEXT,
|
|
229
|
+
data TEXT NOT NULL,
|
|
230
|
+
type TEXT NOT NULL,
|
|
231
|
+
created_at TEXT NOT NULL,
|
|
232
|
+
updated_at TEXT,
|
|
233
|
+
lens_entry_id TEXT NULL
|
|
234
|
+
);
|
|
235
|
+
`;
|
|
236
|
+
const createIndex = `
|
|
237
|
+
CREATE INDEX IF NOT EXISTS lens_entries_id_type_index
|
|
238
|
+
ON ${TABLE_NAME} (id, type);
|
|
239
|
+
`;
|
|
240
|
+
const lensEntryIdIndex = `
|
|
241
|
+
CREATE INDEX IF NOT EXISTS lens_entry_id_index
|
|
242
|
+
ON ${TABLE_NAME} (lens_entry_id);
|
|
243
|
+
`;
|
|
244
|
+
this.connection.exec(createTable);
|
|
245
|
+
this.connection.exec(createIndex);
|
|
246
|
+
this.connection.exec(lensEntryIdIndex);
|
|
247
|
+
}
|
|
248
|
+
mapRow(row, includeFullData = true) {
|
|
249
|
+
let data = includeFullData ? JSON.parse(row.data) : {};
|
|
250
|
+
if (!includeFullData) {
|
|
251
|
+
data = JSON.parse(row.minimal_data);
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
id: row.id,
|
|
255
|
+
type: row.type,
|
|
256
|
+
created_at: row.created_at,
|
|
257
|
+
lens_entry_id: row.lens_entry_id,
|
|
258
|
+
data
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
mapRows(rows, includeFullData = true) {
|
|
262
|
+
let mappedRows = [];
|
|
263
|
+
for (const row of rows) {
|
|
264
|
+
mappedRows.push(this.mapRow(row, includeFullData));
|
|
265
|
+
}
|
|
266
|
+
return mappedRows;
|
|
267
|
+
}
|
|
268
|
+
getSelectedColumns(includeFullData = true) {
|
|
269
|
+
return `SELECT id, minimal_data, type, created_at, lens_entry_id ${includeFullData ? ",data" : ""}`;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// src/stores/queued_sqlite.ts
|
|
274
|
+
var QueuedSqliteStore = class extends compose(
|
|
275
|
+
BetterSqliteStore,
|
|
276
|
+
QueuedStore
|
|
277
|
+
) {
|
|
278
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import BetterSqliteStore from './better_sqlite.cjs';
|
|
2
|
+
import * as denque from 'denque';
|
|
3
|
+
import { WatcherTypeEnum } from '../types/index.cjs';
|
|
4
|
+
import '../abstracts/store.cjs';
|
|
5
|
+
import 'sql-formatter';
|
|
6
|
+
import 'libsql';
|
|
7
|
+
|
|
8
|
+
declare const QueuedSqliteStore_base: {
|
|
9
|
+
new (...args: any[]): {
|
|
10
|
+
[x: string]: any;
|
|
11
|
+
queue: denque<{
|
|
12
|
+
id?: string;
|
|
13
|
+
data: Record<string, any>;
|
|
14
|
+
minimal_data?: Record<string, any>;
|
|
15
|
+
type: WatcherTypeEnum;
|
|
16
|
+
timestamp?: string;
|
|
17
|
+
requestId?: string;
|
|
18
|
+
}>;
|
|
19
|
+
processingInterval: NodeJS.Timeout | null;
|
|
20
|
+
readonly BATCH_SIZE: number;
|
|
21
|
+
readonly PROCESS_INTERVAL_MS: number;
|
|
22
|
+
readonly WARN_THRESHOLD: number;
|
|
23
|
+
readonly PREALLOCATE: boolean;
|
|
24
|
+
initialize(): Promise<void>;
|
|
25
|
+
truncate(): Promise<void>;
|
|
26
|
+
save(entry: {
|
|
27
|
+
id?: string;
|
|
28
|
+
data: Record<string, any>;
|
|
29
|
+
minimal_data?: Record<string, any>;
|
|
30
|
+
type: WatcherTypeEnum;
|
|
31
|
+
timestamp?: string;
|
|
32
|
+
requestId?: string;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
startProcessingQueue(): void;
|
|
35
|
+
processQueue(): Promise<void>;
|
|
36
|
+
stopProcessingQueue(): Promise<void>;
|
|
37
|
+
shutdown(): Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
} & typeof BetterSqliteStore;
|
|
40
|
+
declare class QueuedSqliteStore extends QueuedSqliteStore_base {
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { QueuedSqliteStore as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import BetterSqliteStore from './better_sqlite.js';
|
|
2
|
+
import * as denque from 'denque';
|
|
3
|
+
import { WatcherTypeEnum } from '../types/index.js';
|
|
4
|
+
import '../abstracts/store.js';
|
|
5
|
+
import 'sql-formatter';
|
|
6
|
+
import 'libsql';
|
|
7
|
+
|
|
8
|
+
declare const QueuedSqliteStore_base: {
|
|
9
|
+
new (...args: any[]): {
|
|
10
|
+
[x: string]: any;
|
|
11
|
+
queue: denque<{
|
|
12
|
+
id?: string;
|
|
13
|
+
data: Record<string, any>;
|
|
14
|
+
minimal_data?: Record<string, any>;
|
|
15
|
+
type: WatcherTypeEnum;
|
|
16
|
+
timestamp?: string;
|
|
17
|
+
requestId?: string;
|
|
18
|
+
}>;
|
|
19
|
+
processingInterval: NodeJS.Timeout | null;
|
|
20
|
+
readonly BATCH_SIZE: number;
|
|
21
|
+
readonly PROCESS_INTERVAL_MS: number;
|
|
22
|
+
readonly WARN_THRESHOLD: number;
|
|
23
|
+
readonly PREALLOCATE: boolean;
|
|
24
|
+
initialize(): Promise<void>;
|
|
25
|
+
truncate(): Promise<void>;
|
|
26
|
+
save(entry: {
|
|
27
|
+
id?: string;
|
|
28
|
+
data: Record<string, any>;
|
|
29
|
+
minimal_data?: Record<string, any>;
|
|
30
|
+
type: WatcherTypeEnum;
|
|
31
|
+
timestamp?: string;
|
|
32
|
+
requestId?: string;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
startProcessingQueue(): void;
|
|
35
|
+
processQueue(): Promise<void>;
|
|
36
|
+
stopProcessingQueue(): Promise<void>;
|
|
37
|
+
shutdown(): Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
} & typeof BetterSqliteStore;
|
|
40
|
+
declare class QueuedSqliteStore extends QueuedSqliteStore_base {
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { QueuedSqliteStore as default };
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// src/mixins/queued_store.ts
|
|
2
|
+
import Denque from "denque";
|
|
3
|
+
function QueuedStore(Base) {
|
|
4
|
+
return class Queued extends Base {
|
|
5
|
+
queue;
|
|
6
|
+
processingInterval = null;
|
|
7
|
+
BATCH_SIZE;
|
|
8
|
+
PROCESS_INTERVAL_MS;
|
|
9
|
+
WARN_THRESHOLD;
|
|
10
|
+
PREALLOCATE;
|
|
11
|
+
constructor(...args) {
|
|
12
|
+
super(...args);
|
|
13
|
+
const config = args[0] || {};
|
|
14
|
+
this.BATCH_SIZE = config.batchSize ?? 100;
|
|
15
|
+
this.PROCESS_INTERVAL_MS = config.processIntervalMs ?? 100;
|
|
16
|
+
this.WARN_THRESHOLD = config.warnThreshold ?? 1e5;
|
|
17
|
+
this.PREALLOCATE = config.preallocate ?? true;
|
|
18
|
+
this.queue = this.PREALLOCATE ? new Denque([], { capacity: this.WARN_THRESHOLD * 2 }) : new Denque();
|
|
19
|
+
}
|
|
20
|
+
async initialize() {
|
|
21
|
+
if (super["initialize"]) {
|
|
22
|
+
await super["initialize"].call(this);
|
|
23
|
+
}
|
|
24
|
+
this.startProcessingQueue();
|
|
25
|
+
process.on("SIGINT", () => this.shutdown());
|
|
26
|
+
process.on("SIGTERM", () => this.shutdown());
|
|
27
|
+
}
|
|
28
|
+
async truncate() {
|
|
29
|
+
this.queue.clear();
|
|
30
|
+
if (super["truncate"]) {
|
|
31
|
+
await super["truncate"].call(this);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async save(entry) {
|
|
35
|
+
this.queue.push(entry);
|
|
36
|
+
if (this.queue.length > this.WARN_THRESHOLD) {
|
|
37
|
+
console.warn(`\u26A0\uFE0F LensJs Queue size very large: ${this.queue.length}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
startProcessingQueue() {
|
|
41
|
+
if (this.processingInterval) clearInterval(this.processingInterval);
|
|
42
|
+
this.processingInterval = setInterval(
|
|
43
|
+
() => this.processQueue(),
|
|
44
|
+
this.PROCESS_INTERVAL_MS
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
async processQueue() {
|
|
48
|
+
if (this.queue.isEmpty()) return;
|
|
49
|
+
const batchSize = Math.min(
|
|
50
|
+
this.BATCH_SIZE,
|
|
51
|
+
Math.max(10, Math.floor(this.queue.length / 10))
|
|
52
|
+
);
|
|
53
|
+
const entriesToProcess = this.queue.remove(0, batchSize);
|
|
54
|
+
if (!entriesToProcess.length) return;
|
|
55
|
+
for (const entry of entriesToProcess) {
|
|
56
|
+
super["save"]?.call(this, entry).catch((error) => {
|
|
57
|
+
console.error("Error saving queued entry:", error);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async stopProcessingQueue() {
|
|
62
|
+
if (this.processingInterval) {
|
|
63
|
+
clearInterval(this.processingInterval);
|
|
64
|
+
this.processingInterval = null;
|
|
65
|
+
}
|
|
66
|
+
if (!this.queue.isEmpty()) {
|
|
67
|
+
await this.processQueue();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async shutdown() {
|
|
71
|
+
await this.stopProcessingQueue();
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/utils/compose.ts
|
|
78
|
+
function compose(superclass, ...mixins) {
|
|
79
|
+
return mixins.reduce((c, mixin) => mixin(c), superclass);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/abstracts/store.ts
|
|
83
|
+
var Store = class {
|
|
84
|
+
constructor(...args) {
|
|
85
|
+
}
|
|
86
|
+
getAllExceptions(_paginationParams) {
|
|
87
|
+
return this.defaultMinimalPaginate();
|
|
88
|
+
}
|
|
89
|
+
stringifyData(data) {
|
|
90
|
+
if (typeof data === "string") {
|
|
91
|
+
return data;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
return JSON.stringify(data);
|
|
95
|
+
} catch (e) {
|
|
96
|
+
console.error(`Failed to stringify lens data: ${e}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
defaultMinimalPaginate() {
|
|
100
|
+
return Promise.resolve({
|
|
101
|
+
data: [],
|
|
102
|
+
meta: {
|
|
103
|
+
currentPage: 0,
|
|
104
|
+
lastPage: 0,
|
|
105
|
+
total: 0
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/stores/better_sqlite.ts
|
|
112
|
+
import { randomUUID } from "crypto";
|
|
113
|
+
import Database from "libsql";
|
|
114
|
+
import { nowISO } from "@lensjs/date";
|
|
115
|
+
var TABLE_NAME = "lens_entries";
|
|
116
|
+
var BetterSqliteStore = class extends Store {
|
|
117
|
+
connection;
|
|
118
|
+
async initialize() {
|
|
119
|
+
this.connection = new Database("lens.db");
|
|
120
|
+
this.setupSchema();
|
|
121
|
+
console.log("Connected to Lens (SQLite) database.");
|
|
122
|
+
}
|
|
123
|
+
async truncate() {
|
|
124
|
+
this.connection.prepare(`DELETE FROM ${TABLE_NAME};`).run();
|
|
125
|
+
}
|
|
126
|
+
async save(entry) {
|
|
127
|
+
this.connection.prepare(
|
|
128
|
+
`INSERT INTO ${TABLE_NAME} (id, data, type, created_at, lens_entry_id, minimal_data) values($id, $data, $type, $created_at, $lens_entry_id, $minimalData)`
|
|
129
|
+
).run({
|
|
130
|
+
id: entry.id ?? randomUUID(),
|
|
131
|
+
data: this.stringifyData(entry.data),
|
|
132
|
+
type: entry.type,
|
|
133
|
+
created_at: entry.timestamp ?? nowISO(),
|
|
134
|
+
lens_entry_id: entry.requestId || null,
|
|
135
|
+
minimalData: this.stringifyData(entry.minimal_data ?? {})
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async getAllQueries(pagination) {
|
|
139
|
+
return await this.paginate("query" /* QUERY */, pagination);
|
|
140
|
+
}
|
|
141
|
+
async getAllRequests(pagination) {
|
|
142
|
+
return await this.paginate("request" /* REQUEST */, pagination, false);
|
|
143
|
+
}
|
|
144
|
+
async getAllCacheEntries(pagination) {
|
|
145
|
+
return await this.paginate("cache" /* CACHE */, pagination);
|
|
146
|
+
}
|
|
147
|
+
async getAllExceptions(pagination) {
|
|
148
|
+
return await this.paginate("exception" /* EXCEPTION */, pagination, false);
|
|
149
|
+
}
|
|
150
|
+
async allByRequestId(requestId, type, includeFullData = true) {
|
|
151
|
+
const rows = this.connection.prepare(
|
|
152
|
+
`${this.getSelectedColumns(includeFullData)} FROM ${TABLE_NAME} WHERE type = $type AND lens_entry_id = $requestId ORDER BY created_at DESC`
|
|
153
|
+
).all({ type, requestId });
|
|
154
|
+
return this.mapRows(rows, includeFullData);
|
|
155
|
+
}
|
|
156
|
+
async paginate(type, { page, perPage }, includeFullData = true) {
|
|
157
|
+
const offset = (page - 1) * perPage;
|
|
158
|
+
const query = `${this.getSelectedColumns(
|
|
159
|
+
includeFullData
|
|
160
|
+
)} FROM ${TABLE_NAME} WHERE type = ? ORDER BY created_at DESC LIMIT ? OFFSET ?`;
|
|
161
|
+
const count = await this.count(type);
|
|
162
|
+
const rows = this.connection.prepare(query).all(type, perPage, offset);
|
|
163
|
+
const mappedRows = this.mapRows(rows, includeFullData);
|
|
164
|
+
return {
|
|
165
|
+
meta: {
|
|
166
|
+
total: count,
|
|
167
|
+
lastPage: Math.ceil(count / perPage),
|
|
168
|
+
currentPage: page
|
|
169
|
+
},
|
|
170
|
+
data: mappedRows
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async count(type) {
|
|
174
|
+
const result = this.connection.prepare(`SELECT count(*) as count FROM ${TABLE_NAME} WHERE type = ?`).get(type);
|
|
175
|
+
return Number(result.count);
|
|
176
|
+
}
|
|
177
|
+
async find(type, id) {
|
|
178
|
+
const row = this.connection.prepare(
|
|
179
|
+
`${this.getSelectedColumns()} FROM ${TABLE_NAME} WHERE id = ? AND type = ? LIMIT 1`
|
|
180
|
+
).get(id, type);
|
|
181
|
+
if (!row) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
return this.mapRow(row, true);
|
|
185
|
+
}
|
|
186
|
+
setupSchema() {
|
|
187
|
+
this.connection.exec("PRAGMA journal_mode = WAL;");
|
|
188
|
+
this.connection.exec("PRAGMA synchronous = NORMAL;");
|
|
189
|
+
const createTable = `
|
|
190
|
+
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
|
|
191
|
+
id TEXT PRIMARY KEY,
|
|
192
|
+
minimal_data TEXT,
|
|
193
|
+
data TEXT NOT NULL,
|
|
194
|
+
type TEXT NOT NULL,
|
|
195
|
+
created_at TEXT NOT NULL,
|
|
196
|
+
updated_at TEXT,
|
|
197
|
+
lens_entry_id TEXT NULL
|
|
198
|
+
);
|
|
199
|
+
`;
|
|
200
|
+
const createIndex = `
|
|
201
|
+
CREATE INDEX IF NOT EXISTS lens_entries_id_type_index
|
|
202
|
+
ON ${TABLE_NAME} (id, type);
|
|
203
|
+
`;
|
|
204
|
+
const lensEntryIdIndex = `
|
|
205
|
+
CREATE INDEX IF NOT EXISTS lens_entry_id_index
|
|
206
|
+
ON ${TABLE_NAME} (lens_entry_id);
|
|
207
|
+
`;
|
|
208
|
+
this.connection.exec(createTable);
|
|
209
|
+
this.connection.exec(createIndex);
|
|
210
|
+
this.connection.exec(lensEntryIdIndex);
|
|
211
|
+
}
|
|
212
|
+
mapRow(row, includeFullData = true) {
|
|
213
|
+
let data = includeFullData ? JSON.parse(row.data) : {};
|
|
214
|
+
if (!includeFullData) {
|
|
215
|
+
data = JSON.parse(row.minimal_data);
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
id: row.id,
|
|
219
|
+
type: row.type,
|
|
220
|
+
created_at: row.created_at,
|
|
221
|
+
lens_entry_id: row.lens_entry_id,
|
|
222
|
+
data
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
mapRows(rows, includeFullData = true) {
|
|
226
|
+
let mappedRows = [];
|
|
227
|
+
for (const row of rows) {
|
|
228
|
+
mappedRows.push(this.mapRow(row, includeFullData));
|
|
229
|
+
}
|
|
230
|
+
return mappedRows;
|
|
231
|
+
}
|
|
232
|
+
getSelectedColumns(includeFullData = true) {
|
|
233
|
+
return `SELECT id, minimal_data, type, created_at, lens_entry_id ${includeFullData ? ",data" : ""}`;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// src/stores/queued_sqlite.ts
|
|
238
|
+
var QueuedSqliteStore = class extends compose(
|
|
239
|
+
BetterSqliteStore,
|
|
240
|
+
QueuedStore
|
|
241
|
+
) {
|
|
242
|
+
};
|
|
243
|
+
export {
|
|
244
|
+
QueuedSqliteStore as default
|
|
245
|
+
};
|
package/dist/types/index.d.cts
CHANGED
|
@@ -93,9 +93,14 @@ declare enum WatcherTypeEnum {
|
|
|
93
93
|
EXCEPTION = "exception"
|
|
94
94
|
}
|
|
95
95
|
type LensConfig = {
|
|
96
|
-
|
|
96
|
+
path: string;
|
|
97
97
|
appName: string;
|
|
98
98
|
enabled: boolean;
|
|
99
|
+
storeQueueConfig?: QueuedStoreConfig;
|
|
100
|
+
hiddenParams?: {
|
|
101
|
+
headers?: string[];
|
|
102
|
+
bodyParams?: string[];
|
|
103
|
+
};
|
|
99
104
|
};
|
|
100
105
|
type LensEntry = {
|
|
101
106
|
id: string;
|
|
@@ -134,5 +139,12 @@ type ApiResponse<T> = {
|
|
|
134
139
|
};
|
|
135
140
|
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
|
|
136
141
|
type RouteHttpMethod = "get" | "post" | "put" | "delete" | "patch";
|
|
142
|
+
type Constructor = new (...args: any[]) => any;
|
|
143
|
+
interface QueuedStoreConfig {
|
|
144
|
+
batchSize?: number;
|
|
145
|
+
processIntervalMs?: number;
|
|
146
|
+
warnThreshold?: number;
|
|
147
|
+
preallocate?: boolean;
|
|
148
|
+
}
|
|
137
149
|
|
|
138
|
-
export { type ApiResponse, type CacheAction, type CacheEntry, type Entry, type ExceptionEntry, type HttpMethod, type LensConfig, type LensEntry, type PaginationParams, type Paginator, type QueryEntry, type QueryType, type RequestEntry, type RouteDefinition, type RouteDefinitionHandler, type RouteHttpMethod, type SqlQueryType, type UserEntry, WatcherTypeEnum };
|
|
150
|
+
export { type ApiResponse, type CacheAction, type CacheEntry, type Constructor, type Entry, type ExceptionEntry, type HttpMethod, type LensConfig, type LensEntry, type PaginationParams, type Paginator, type QueryEntry, type QueryType, type QueuedStoreConfig, type RequestEntry, type RouteDefinition, type RouteDefinitionHandler, type RouteHttpMethod, type SqlQueryType, type UserEntry, WatcherTypeEnum };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -93,9 +93,14 @@ declare enum WatcherTypeEnum {
|
|
|
93
93
|
EXCEPTION = "exception"
|
|
94
94
|
}
|
|
95
95
|
type LensConfig = {
|
|
96
|
-
|
|
96
|
+
path: string;
|
|
97
97
|
appName: string;
|
|
98
98
|
enabled: boolean;
|
|
99
|
+
storeQueueConfig?: QueuedStoreConfig;
|
|
100
|
+
hiddenParams?: {
|
|
101
|
+
headers?: string[];
|
|
102
|
+
bodyParams?: string[];
|
|
103
|
+
};
|
|
99
104
|
};
|
|
100
105
|
type LensEntry = {
|
|
101
106
|
id: string;
|
|
@@ -134,5 +139,12 @@ type ApiResponse<T> = {
|
|
|
134
139
|
};
|
|
135
140
|
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
|
|
136
141
|
type RouteHttpMethod = "get" | "post" | "put" | "delete" | "patch";
|
|
142
|
+
type Constructor = new (...args: any[]) => any;
|
|
143
|
+
interface QueuedStoreConfig {
|
|
144
|
+
batchSize?: number;
|
|
145
|
+
processIntervalMs?: number;
|
|
146
|
+
warnThreshold?: number;
|
|
147
|
+
preallocate?: boolean;
|
|
148
|
+
}
|
|
137
149
|
|
|
138
|
-
export { type ApiResponse, type CacheAction, type CacheEntry, type Entry, type ExceptionEntry, type HttpMethod, type LensConfig, type LensEntry, type PaginationParams, type Paginator, type QueryEntry, type QueryType, type RequestEntry, type RouteDefinition, type RouteDefinitionHandler, type RouteHttpMethod, type SqlQueryType, type UserEntry, WatcherTypeEnum };
|
|
150
|
+
export { type ApiResponse, type CacheAction, type CacheEntry, type Constructor, type Entry, type ExceptionEntry, type HttpMethod, type LensConfig, type LensEntry, type PaginationParams, type Paginator, type QueryEntry, type QueryType, type QueuedStoreConfig, type RequestEntry, type RouteDefinition, type RouteDefinitionHandler, type RouteHttpMethod, type SqlQueryType, type UserEntry, WatcherTypeEnum };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as r}from"./index-
|
|
1
|
+
import{j as r}from"./index-TW_-MgRG.js";const d=({action:e})=>{const t={hit:"bg-green-100 text-green-800 dark:bg-green-600 dark:text-white",miss:"bg-amber-100 text-amber-800 dark:bg-amber-600 dark:text-white",write:"bg-blue-100 text-blue-800 dark:bg-blue-600 dark:text-white",delete:"bg-red-100 text-red-800 dark:bg-red-600 dark:text-white",clear:"bg-gray-100 text-gray-800 dark:bg-gray-600 dark:text-white"};return r.jsx("span",{className:`rounded px-2 py-1 text-sm font-semibold ${t[e]||t.clear}`,children:e})};export{d as C};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as a}from"./index-TW_-MgRG.js";import{L as s}from"./LoadMore-CLPR6Zd4.js";import{T as t}from"./Table-kak5sL5X.js";import{g as r}from"./columns-BvIUTkjN.js";import"./index-BRRKsoNv.js";import"./CacheActionBadge-BB4uokI1.js";const p=({hasMoreObject:o})=>a.jsxs("div",{className:"w-full",children:[a.jsx("div",{className:"overflow-x-auto",children:a.jsx(t,{columns:r(),data:o.data})}),a.jsx(s,{paginatedPage:o})]});export{p as default};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./CacheEntriesTable-B8cUXhos.js","./index-TW_-MgRG.js","./index-CsnKQ5Mh.css","./LoadMore-CLPR6Zd4.js","./Table-kak5sL5X.js","./columns-BvIUTkjN.js","./index-BRRKsoNv.js","./CacheActionBadge-BB4uokI1.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{r as t,j as a,_ as s}from"./index-TW_-MgRG.js";import{u as i}from"./useLoadMore-JCWak1Dg.js";import{u as m}from"./useCacheEntries-Pvte_aNc.js";import"./useLensApi-BFdsfrzR.js";const n=t.lazy(()=>s(()=>import("./CacheEntriesTable-B8cUXhos.js"),__vite__mapDeps([0,1,2,3,4,5,6,7]),import.meta.url)),_=()=>{const{loadMoreItems:e,getItems:r}=m(),o=i({paginatedPage:e});return t.useEffect(()=>{r()},[]),a.jsx(n,{hasMoreObject:o})};export{_ as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as a,L as s,q as r,k as i}from"./index-TW_-MgRG.js";import{D as o,T as n}from"./TabbedDataViewer-ofhEq_Wj.js";import{C as u}from"./CacheActionBadge-BB4uokI1.js";import d from"./JsonViewer-D-KPN089.js";import"./copy-DzXuP4eO.js";function b({data:e}){const t=[e.lens_entry_id?{label:"Request",value:a.jsx(s,{to:`${r(i()).REQUESTS}/${e.lens_entry_id}`,className:"text-blue-600 hover:underline font-semibold",children:"View Request"}),className:"text-gray-900 dark:text-gray-100"}:null,{label:"Operation",value:a.jsx(u,{action:e.data.action}),className:"text-gray-900 dark:text-gray-100"},e.data.data.key?{label:"Key",value:e.data.data.key??"__",className:"text-gray-900 dark:text-gray-100"}:null].filter(l=>!!l);return a.jsxs("div",{className:"flex flex-col gap-4",children:[a.jsx(o,{title:"Details",items:t}),a.jsx(n,{tabs:[{id:"value",label:"Value",shouldShow:!!e.data.data.value,content:a.jsx(d,{data:e.data.data.value})}],defaultActiveTab:"value"})]})}export{b as default};
|