database-devtools 0.1.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/LICENSE +5 -0
- package/dist/adapter/index.cjs +314 -0
- package/dist/adapter/index.cjs.map +1 -0
- package/dist/adapter/index.d.cts +34 -0
- package/dist/adapter/index.d.ts +34 -0
- package/dist/adapter/index.js +6 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/adapter-BjJm71wW.d.cts +30 -0
- package/dist/adapter-DJSjDewg.d.ts +30 -0
- package/dist/adapters/sqlite/index.cjs +251 -0
- package/dist/adapters/sqlite/index.cjs.map +1 -0
- package/dist/adapters/sqlite/index.d.cts +21 -0
- package/dist/adapters/sqlite/index.d.ts +21 -0
- package/dist/adapters/sqlite/index.js +6 -0
- package/dist/adapters/sqlite/index.js.map +1 -0
- package/dist/chunk-2JGL2JVD.js +52 -0
- package/dist/chunk-2JGL2JVD.js.map +1 -0
- package/dist/chunk-AZECU6D7.js +27 -0
- package/dist/chunk-AZECU6D7.js.map +1 -0
- package/dist/chunk-BLOSGEQV.js +71 -0
- package/dist/chunk-BLOSGEQV.js.map +1 -0
- package/dist/chunk-CPVVIH5G.js +258 -0
- package/dist/chunk-CPVVIH5G.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-HIDZTOJ3.js +9 -0
- package/dist/chunk-HIDZTOJ3.js.map +1 -0
- package/dist/chunk-I65IM47D.js +243 -0
- package/dist/chunk-I65IM47D.js.map +1 -0
- package/dist/chunk-MXVIGMVT.js +3 -0
- package/dist/chunk-MXVIGMVT.js.map +1 -0
- package/dist/chunk-O6AO7KHA.js +3 -0
- package/dist/chunk-O6AO7KHA.js.map +1 -0
- package/dist/chunk-TNDOAHT5.js +1784 -0
- package/dist/chunk-TNDOAHT5.js.map +1 -0
- package/dist/chunk-ZS5MZR75.js +655 -0
- package/dist/chunk-ZS5MZR75.js.map +1 -0
- package/dist/cli.cjs +2053 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/client/index.cjs +947 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +75 -0
- package/dist/client/index.d.ts +75 -0
- package/dist/client/index.js +98 -0
- package/dist/client/index.js.map +1 -0
- package/dist/createDevToolsServer-B7NQ_5H4.d.cts +292 -0
- package/dist/createDevToolsServer-DlNMoCJR.d.ts +292 -0
- package/dist/handleDeviceSnapshot-CR-4QMdk.d.ts +116 -0
- package/dist/handleDeviceSnapshot-cYGuitSc.d.cts +116 -0
- package/dist/index.cjs +5877 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +61 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +2748 -0
- package/dist/index.js.map +1 -0
- package/dist/inspector/index.cjs +57 -0
- package/dist/inspector/index.cjs.map +1 -0
- package/dist/inspector/index.d.cts +26 -0
- package/dist/inspector/index.d.ts +26 -0
- package/dist/inspector/index.js +5 -0
- package/dist/inspector/index.js.map +1 -0
- package/dist/inspectors/sqlite/index.cjs +306 -0
- package/dist/inspectors/sqlite/index.cjs.map +1 -0
- package/dist/inspectors/sqlite/index.d.cts +53 -0
- package/dist/inspectors/sqlite/index.d.ts +53 -0
- package/dist/inspectors/sqlite/index.js +260 -0
- package/dist/inspectors/sqlite/index.js.map +1 -0
- package/dist/register-BuicFu9L.d.cts +32 -0
- package/dist/register-aITLN9Q9.d.ts +32 -0
- package/dist/server/index.cjs +1948 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +15 -0
- package/dist/server/index.d.ts +15 -0
- package/dist/server/index.js +7 -0
- package/dist/server/index.js.map +1 -0
- package/dist/snapshot-Dhyecgo2.d.cts +33 -0
- package/dist/snapshot-Dhyecgo2.d.ts +33 -0
- package/dist/types/protocol.cjs +309 -0
- package/dist/types/protocol.cjs.map +1 -0
- package/dist/types/protocol.d.cts +291 -0
- package/dist/types/protocol.d.ts +291 -0
- package/dist/types/protocol.js +4 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types-BRLJdBRY.d.cts +16 -0
- package/dist/types-CF6qEU-_.d.ts +16 -0
- package/dist/types-CIA11diJ.d.cts +62 -0
- package/dist/types-CKVRCX-e.d.ts +62 -0
- package/dist/web/assets/index-CLEaIsUd.css +1 -0
- package/dist/web/assets/index-DQrPRTOy.js +100 -0
- package/dist/web/assets/sql-wasm-UFUCzYNW.wasm +0 -0
- package/dist/web/index.html +26 -0
- package/dist/write-C3toEIMs.d.cts +21 -0
- package/dist/write-C3toEIMs.d.ts +21 -0
- package/package.json +137 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var initSqlJs = require('sql.js');
|
|
4
|
+
|
|
5
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
+
|
|
7
|
+
var initSqlJs__default = /*#__PURE__*/_interopDefault(initSqlJs);
|
|
8
|
+
|
|
9
|
+
// src/inspector/registry.ts
|
|
10
|
+
var InspectorRegistry = class {
|
|
11
|
+
definitions = /* @__PURE__ */ new Map();
|
|
12
|
+
register(definition) {
|
|
13
|
+
this.definitions.set(definition.kind, definition);
|
|
14
|
+
}
|
|
15
|
+
get(kind) {
|
|
16
|
+
return this.definitions.get(kind);
|
|
17
|
+
}
|
|
18
|
+
listSupported() {
|
|
19
|
+
return [...this.definitions.values()].sort((left, right) => left.displayName.localeCompare(right.displayName)).map((definition) => ({
|
|
20
|
+
kind: definition.kind,
|
|
21
|
+
displayName: definition.displayName
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
detectFromBytes(bytes) {
|
|
25
|
+
return [...this.definitions.values()].find((definition) => definition.canOpenBytes?.(bytes));
|
|
26
|
+
}
|
|
27
|
+
detectFromSnapshot(input) {
|
|
28
|
+
const byKind = this.definitions.get(input.kind);
|
|
29
|
+
if (byKind) {
|
|
30
|
+
return byKind;
|
|
31
|
+
}
|
|
32
|
+
return [...this.definitions.values()].find(
|
|
33
|
+
(definition) => definition.mimeTypes.includes(input.mimeType)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var globalInspectorRegistry = null;
|
|
38
|
+
function getInspectorRegistry() {
|
|
39
|
+
if (!globalInspectorRegistry) {
|
|
40
|
+
globalInspectorRegistry = new InspectorRegistry();
|
|
41
|
+
}
|
|
42
|
+
return globalInspectorRegistry;
|
|
43
|
+
}
|
|
44
|
+
var sqlModulePromise = null;
|
|
45
|
+
var wasmLocator = null;
|
|
46
|
+
function configureSqliteWasm(locator) {
|
|
47
|
+
wasmLocator = locator;
|
|
48
|
+
}
|
|
49
|
+
async function getSqlModule() {
|
|
50
|
+
if (!sqlModulePromise) {
|
|
51
|
+
sqlModulePromise = initSqlJs__default.default({
|
|
52
|
+
locateFile: () => wasmLocator?.() ?? "/sql-wasm.wasm"
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return sqlModulePromise;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/inspectors/sqlite/tableQuery.ts
|
|
59
|
+
function quoteIdentifier(name) {
|
|
60
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
61
|
+
}
|
|
62
|
+
function buildSearchClause(columns, search) {
|
|
63
|
+
const term = search?.trim();
|
|
64
|
+
if (!term || columns.length === 0) {
|
|
65
|
+
return { clause: "", params: [] };
|
|
66
|
+
}
|
|
67
|
+
const pattern = `%${term}%`;
|
|
68
|
+
const conditions = columns.map(
|
|
69
|
+
(column) => `CAST(${quoteIdentifier(column.name)} AS TEXT) LIKE ?`
|
|
70
|
+
);
|
|
71
|
+
return {
|
|
72
|
+
clause: ` WHERE (${conditions.join(" OR ")})`,
|
|
73
|
+
params: columns.map(() => pattern)
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function resolveSortColumn(columns, sortColumn) {
|
|
77
|
+
if (!sortColumn) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
return columns.some((column) => column.name === sortColumn) ? sortColumn : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/inspectors/sqlite/sqliteInspector.ts
|
|
84
|
+
var SQLITE_SNAPSHOT_MIME_TYPE = "application/x-sqlite3";
|
|
85
|
+
function normalizeCell(cell) {
|
|
86
|
+
if (cell === null || cell === void 0) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
if (typeof cell === "number" || typeof cell === "string") {
|
|
90
|
+
return cell;
|
|
91
|
+
}
|
|
92
|
+
if (cell instanceof Uint8Array) {
|
|
93
|
+
return `[BLOB ${cell.byteLength} bytes]`;
|
|
94
|
+
}
|
|
95
|
+
return String(cell);
|
|
96
|
+
}
|
|
97
|
+
var SqliteSession = class _SqliteSession {
|
|
98
|
+
constructor(db) {
|
|
99
|
+
this.db = db;
|
|
100
|
+
}
|
|
101
|
+
db;
|
|
102
|
+
tableNames = /* @__PURE__ */ new Set();
|
|
103
|
+
static async open(bytes) {
|
|
104
|
+
const SQL = await getSqlModule();
|
|
105
|
+
const db = new SQL.Database(new Uint8Array(bytes));
|
|
106
|
+
const session = new _SqliteSession(db);
|
|
107
|
+
session.listTables().forEach((table) => session.tableNames.add(table.name));
|
|
108
|
+
return session;
|
|
109
|
+
}
|
|
110
|
+
close() {
|
|
111
|
+
this.db.close();
|
|
112
|
+
}
|
|
113
|
+
listTables() {
|
|
114
|
+
const statement = this.db.prepare(
|
|
115
|
+
`SELECT name FROM sqlite_master
|
|
116
|
+
WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
|
|
117
|
+
ORDER BY name`
|
|
118
|
+
);
|
|
119
|
+
const tables = [];
|
|
120
|
+
while (statement.step()) {
|
|
121
|
+
const name = String(statement.get()[0]);
|
|
122
|
+
const countStatement = this.db.prepare(`SELECT COUNT(*) AS c FROM ${quoteIdentifier(name)}`);
|
|
123
|
+
countStatement.step();
|
|
124
|
+
const rowCount = Number(countStatement.get()[0] ?? 0);
|
|
125
|
+
countStatement.free();
|
|
126
|
+
tables.push({ name, rowCount });
|
|
127
|
+
}
|
|
128
|
+
statement.free();
|
|
129
|
+
return tables;
|
|
130
|
+
}
|
|
131
|
+
getSchema() {
|
|
132
|
+
const tables = this.listTables();
|
|
133
|
+
return tables.map((table) => ({
|
|
134
|
+
name: table.name,
|
|
135
|
+
columns: this.getTableColumns(table.name)
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
getTableColumns(tableName) {
|
|
139
|
+
this.assertKnownTable(tableName);
|
|
140
|
+
return this.readTableColumns(tableName);
|
|
141
|
+
}
|
|
142
|
+
fetchTablePage(request) {
|
|
143
|
+
this.assertKnownTable(request.table);
|
|
144
|
+
const columns = this.readTableColumns(request.table);
|
|
145
|
+
const columnNames = columns.map((column) => column.name);
|
|
146
|
+
const tableQuoted = quoteIdentifier(request.table);
|
|
147
|
+
const { clause, params } = buildSearchClause(columns, request.search);
|
|
148
|
+
const sortColumn = resolveSortColumn(columns, request.sortColumn);
|
|
149
|
+
const sortDir = request.sortDir === "desc" ? "DESC" : "ASC";
|
|
150
|
+
const page = Math.max(1, request.page);
|
|
151
|
+
const pageSize = Math.max(1, request.pageSize);
|
|
152
|
+
const offset = (page - 1) * pageSize;
|
|
153
|
+
const countStatement = this.db.prepare(`SELECT COUNT(*) AS c FROM ${tableQuoted}${clause}`);
|
|
154
|
+
countStatement.bind(params);
|
|
155
|
+
countStatement.step();
|
|
156
|
+
const totalCount = Number(countStatement.get()[0] ?? 0);
|
|
157
|
+
countStatement.free();
|
|
158
|
+
const orderClause = sortColumn ? ` ORDER BY ${quoteIdentifier(sortColumn)} ${sortDir}` : "";
|
|
159
|
+
const dataStatement = this.db.prepare(
|
|
160
|
+
`SELECT * FROM ${tableQuoted}${clause}${orderClause} LIMIT ? OFFSET ?`
|
|
161
|
+
);
|
|
162
|
+
dataStatement.bind([...params, pageSize, offset]);
|
|
163
|
+
const rows = [];
|
|
164
|
+
while (dataStatement.step()) {
|
|
165
|
+
rows.push(columnNames.map((_, index) => normalizeCell(dataStatement.get()[index])));
|
|
166
|
+
}
|
|
167
|
+
dataStatement.free();
|
|
168
|
+
return {
|
|
169
|
+
columns: columnNames,
|
|
170
|
+
rows,
|
|
171
|
+
totalCount,
|
|
172
|
+
page,
|
|
173
|
+
pageSize
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
executeQuery(sql) {
|
|
177
|
+
const startedAt = performance.now();
|
|
178
|
+
const resultSets = this.db.exec(sql);
|
|
179
|
+
const durationMs = performance.now() - startedAt;
|
|
180
|
+
if (resultSets.length === 0) {
|
|
181
|
+
return {
|
|
182
|
+
columns: [],
|
|
183
|
+
rows: [],
|
|
184
|
+
rowCount: 0,
|
|
185
|
+
durationMs
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const primary = resultSets[0];
|
|
189
|
+
return {
|
|
190
|
+
columns: primary.columns,
|
|
191
|
+
rows: primary.values.map((row) => row.map((cell) => normalizeCell(cell))),
|
|
192
|
+
rowCount: primary.values.length,
|
|
193
|
+
durationMs
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
assertKnownTable(tableName) {
|
|
197
|
+
if (!this.tableNames.has(tableName)) {
|
|
198
|
+
throw new Error(`Unknown table: ${tableName}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
readTableColumns(tableName) {
|
|
202
|
+
const statement = this.db.prepare(`PRAGMA table_info(${quoteIdentifier(tableName)})`);
|
|
203
|
+
const columns = [];
|
|
204
|
+
while (statement.step()) {
|
|
205
|
+
const row = statement.getAsObject();
|
|
206
|
+
columns.push({
|
|
207
|
+
name: row.name,
|
|
208
|
+
type: row.type || "ANY",
|
|
209
|
+
notNull: row.notnull === 1,
|
|
210
|
+
pk: row.pk > 0,
|
|
211
|
+
defaultValue: row.dflt_value
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
statement.free();
|
|
215
|
+
return columns;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
function isSqliteDatabase(bytes) {
|
|
219
|
+
const header = new TextDecoder().decode(new Uint8Array(bytes, 0, 16));
|
|
220
|
+
return header.startsWith("SQLite format 3");
|
|
221
|
+
}
|
|
222
|
+
function filterTables(tables, search) {
|
|
223
|
+
const term = search.trim().toLowerCase();
|
|
224
|
+
if (!term) {
|
|
225
|
+
return tables;
|
|
226
|
+
}
|
|
227
|
+
return tables.filter((table) => table.name.toLowerCase().includes(term));
|
|
228
|
+
}
|
|
229
|
+
function sortTables(tables, sortBy, direction) {
|
|
230
|
+
const sorted = [...tables].sort((left, right) => {
|
|
231
|
+
if (sortBy === "rows") {
|
|
232
|
+
return left.rowCount - right.rowCount;
|
|
233
|
+
}
|
|
234
|
+
return left.name.localeCompare(right.name);
|
|
235
|
+
});
|
|
236
|
+
return direction === "desc" ? sorted.reverse() : sorted;
|
|
237
|
+
}
|
|
238
|
+
var SqliteInspector = class {
|
|
239
|
+
kind = "sqlite";
|
|
240
|
+
capabilities = {
|
|
241
|
+
explorer: true,
|
|
242
|
+
schemaView: true,
|
|
243
|
+
tableData: true,
|
|
244
|
+
sqlWorkspace: true
|
|
245
|
+
};
|
|
246
|
+
session = null;
|
|
247
|
+
async open(snapshot) {
|
|
248
|
+
this.close();
|
|
249
|
+
const bytes = snapshot instanceof ArrayBuffer ? snapshot : new Uint8Array(snapshot.bytes).buffer;
|
|
250
|
+
if (!isSqliteDatabase(bytes)) {
|
|
251
|
+
throw new Error("Snapshot is not a valid SQLite database file");
|
|
252
|
+
}
|
|
253
|
+
this.session = await SqliteSession.open(bytes);
|
|
254
|
+
}
|
|
255
|
+
close() {
|
|
256
|
+
this.session?.close();
|
|
257
|
+
this.session = null;
|
|
258
|
+
}
|
|
259
|
+
listTables() {
|
|
260
|
+
return this.requireSession().listTables();
|
|
261
|
+
}
|
|
262
|
+
getSchema() {
|
|
263
|
+
return this.requireSession().getSchema();
|
|
264
|
+
}
|
|
265
|
+
fetchTablePage(request) {
|
|
266
|
+
return this.requireSession().fetchTablePage(request);
|
|
267
|
+
}
|
|
268
|
+
executeQuery(sql) {
|
|
269
|
+
return this.requireSession().executeQuery(sql);
|
|
270
|
+
}
|
|
271
|
+
requireSession() {
|
|
272
|
+
if (!this.session) {
|
|
273
|
+
throw new Error("No database loaded");
|
|
274
|
+
}
|
|
275
|
+
return this.session;
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
var sqliteInspectorDefinition = {
|
|
279
|
+
kind: "sqlite",
|
|
280
|
+
displayName: "SQLite",
|
|
281
|
+
mimeTypes: [SQLITE_SNAPSHOT_MIME_TYPE, "application/octet-stream"],
|
|
282
|
+
canOpenBytes: isSqliteDatabase,
|
|
283
|
+
createInspector: () => new SqliteInspector()
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// src/inspectors/sqlite/index.ts
|
|
287
|
+
function registerSqliteInspector(options) {
|
|
288
|
+
if (options?.locateWasm) {
|
|
289
|
+
configureSqliteWasm(options.locateWasm);
|
|
290
|
+
} else if (options?.wasmUrl) {
|
|
291
|
+
configureSqliteWasm(() => options.wasmUrl);
|
|
292
|
+
}
|
|
293
|
+
getInspectorRegistry().register(sqliteInspectorDefinition);
|
|
294
|
+
}
|
|
295
|
+
registerSqliteInspector();
|
|
296
|
+
|
|
297
|
+
exports.SqliteInspector = SqliteInspector;
|
|
298
|
+
exports.SqliteSession = SqliteSession;
|
|
299
|
+
exports.configureSqliteWasm = configureSqliteWasm;
|
|
300
|
+
exports.filterTables = filterTables;
|
|
301
|
+
exports.isSqliteDatabase = isSqliteDatabase;
|
|
302
|
+
exports.registerSqliteInspector = registerSqliteInspector;
|
|
303
|
+
exports.sortTables = sortTables;
|
|
304
|
+
exports.sqliteInspectorDefinition = sqliteInspectorDefinition;
|
|
305
|
+
//# sourceMappingURL=index.cjs.map
|
|
306
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inspector/registry.ts","../../../src/inspectors/sqlite/sqlModule.ts","../../../src/inspectors/sqlite/tableQuery.ts","../../../src/inspectors/sqlite/sqliteInspector.ts","../../../src/inspectors/sqlite/index.ts"],"names":["initSqlJs"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { DatabaseKind } from '../types/kind';\r\nimport type { DatabaseInspector, InspectorDefinition } from './types';\r\n\r\nexport class InspectorRegistry {\r\n private readonly definitions = new Map<string, InspectorDefinition>();\r\n\r\n register(definition: InspectorDefinition): void {\r\n this.definitions.set(definition.kind, definition);\r\n }\r\n\r\n get(kind: DatabaseKind): InspectorDefinition | undefined {\r\n return this.definitions.get(kind);\r\n }\r\n\r\n listSupported(): { kind: string; displayName: string }[] {\r\n return [...this.definitions.values()]\r\n .sort((left, right) => left.displayName.localeCompare(right.displayName))\r\n .map((definition) => ({\r\n kind: definition.kind,\r\n displayName: definition.displayName,\r\n }));\r\n }\r\n\r\n detectFromBytes(bytes: ArrayBuffer): InspectorDefinition | undefined {\r\n return [...this.definitions.values()].find((definition) => definition.canOpenBytes?.(bytes));\r\n }\r\n\r\n detectFromSnapshot(input: { kind: DatabaseKind; mimeType: string }): InspectorDefinition | undefined {\r\n const byKind = this.definitions.get(input.kind);\r\n\r\n if (byKind) {\r\n return byKind;\r\n }\r\n\r\n return [...this.definitions.values()].find((definition) =>\r\n definition.mimeTypes.includes(input.mimeType),\r\n );\r\n }\r\n}\r\n\r\nlet globalInspectorRegistry: InspectorRegistry | null = null;\r\n\r\nexport function getInspectorRegistry(): InspectorRegistry {\r\n if (!globalInspectorRegistry) {\r\n globalInspectorRegistry = new InspectorRegistry();\r\n }\r\n\r\n return globalInspectorRegistry;\r\n}\r\n\r\nexport function resetInspectorRegistry(): void {\r\n globalInspectorRegistry = null;\r\n}\r\n\r\nexport async function createInspectorForSnapshot(input: {\r\n kind: DatabaseKind;\r\n mimeType: string;\r\n bytes: ArrayBuffer;\r\n}): Promise<DatabaseInspector> {\r\n const registry = getInspectorRegistry();\r\n const definition =\r\n registry.get(input.kind) ??\r\n registry.detectFromBytes(input.bytes) ??\r\n registry.detectFromSnapshot(input);\r\n\r\n if (!definition) {\r\n throw new Error(`No inspector registered for database kind \"${input.kind}\"`);\r\n }\r\n\r\n const inspector = await definition.createInspector();\r\n await inspector.open(input.bytes);\r\n return inspector;\r\n}\r\n","import initSqlJs, { type SqlJsStatic } from 'sql.js';\r\n\r\nlet sqlModulePromise: Promise<SqlJsStatic> | null = null;\r\nlet wasmLocator: (() => string) | null = null;\r\n\r\nexport function configureSqliteWasm(locator: () => string): void {\r\n wasmLocator = locator;\r\n}\r\n\r\nexport async function getSqlModule(): Promise<SqlJsStatic> {\r\n if (!sqlModulePromise) {\r\n sqlModulePromise = initSqlJs({\r\n locateFile: () => wasmLocator?.() ?? '/sql-wasm.wasm',\r\n });\r\n }\r\n\r\n return sqlModulePromise;\r\n}\r\n","import type { ColumnInfo } from '../../types/inspection';\r\n\r\nexport function quoteIdentifier(name: string): string {\r\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\r\n}\r\n\r\nexport function buildSearchClause(\r\n columns: ColumnInfo[],\r\n search: string | undefined,\r\n): { clause: string; params: string[] } {\r\n const term = search?.trim();\r\n\r\n if (!term || columns.length === 0) {\r\n return { clause: '', params: [] };\r\n }\r\n\r\n const pattern = `%${term}%`;\r\n const conditions = columns.map(\r\n (column) => `CAST(${quoteIdentifier(column.name)} AS TEXT) LIKE ?`,\r\n );\r\n\r\n return {\r\n clause: ` WHERE (${conditions.join(' OR ')})`,\r\n params: columns.map(() => pattern),\r\n };\r\n}\r\n\r\nexport function resolveSortColumn(\r\n columns: ColumnInfo[],\r\n sortColumn: string | null | undefined,\r\n): string | null {\r\n if (!sortColumn) {\r\n return null;\r\n }\r\n\r\n return columns.some((column) => column.name === sortColumn) ? sortColumn : null;\r\n}\r\n","import type {\r\n ColumnInfo,\r\n QueryResult,\r\n SchemaTable,\r\n TableInfo,\r\n TablePageRequest,\r\n TablePageResult,\r\n} from '../../types/inspection';\r\nimport type { DatabaseInspector } from '../../inspector/types';\r\nimport type { SnapshotExport } from '../../types/snapshot';\r\nimport { getSqlModule } from './sqlModule';\r\nimport { buildSearchClause, quoteIdentifier, resolveSortColumn } from './tableQuery';\r\n\r\nconst SQLITE_SNAPSHOT_MIME_TYPE = 'application/x-sqlite3';\r\n\r\nfunction normalizeCell(cell: unknown): string | number | null {\r\n if (cell === null || cell === undefined) {\r\n return null;\r\n }\r\n\r\n if (typeof cell === 'number' || typeof cell === 'string') {\r\n return cell;\r\n }\r\n\r\n if (cell instanceof Uint8Array) {\r\n return `[BLOB ${cell.byteLength} bytes]`;\r\n }\r\n\r\n return String(cell);\r\n}\r\n\r\nexport class SqliteSession {\r\n private readonly tableNames = new Set<string>();\r\n\r\n private constructor(private readonly db: import('sql.js').Database) {}\r\n\r\n static async open(bytes: ArrayBuffer): Promise<SqliteSession> {\r\n const SQL = await getSqlModule();\r\n const db = new SQL.Database(new Uint8Array(bytes));\r\n const session = new SqliteSession(db);\r\n session.listTables().forEach((table) => session.tableNames.add(table.name));\r\n return session;\r\n }\r\n\r\n close(): void {\r\n this.db.close();\r\n }\r\n\r\n listTables(): TableInfo[] {\r\n const statement = this.db.prepare(\r\n `SELECT name FROM sqlite_master\r\n WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\r\n ORDER BY name`,\r\n );\r\n\r\n const tables: TableInfo[] = [];\r\n\r\n while (statement.step()) {\r\n const name = String(statement.get()[0]);\r\n const countStatement = this.db.prepare(`SELECT COUNT(*) AS c FROM ${quoteIdentifier(name)}`);\r\n\r\n countStatement.step();\r\n const rowCount = Number(countStatement.get()[0] ?? 0);\r\n countStatement.free();\r\n\r\n tables.push({ name, rowCount });\r\n }\r\n\r\n statement.free();\r\n return tables;\r\n }\r\n\r\n getSchema(): SchemaTable[] {\r\n const tables = this.listTables();\r\n\r\n return tables.map((table) => ({\r\n name: table.name,\r\n columns: this.getTableColumns(table.name),\r\n }));\r\n }\r\n\r\n getTableColumns(tableName: string): ColumnInfo[] {\r\n this.assertKnownTable(tableName);\r\n return this.readTableColumns(tableName);\r\n }\r\n\r\n fetchTablePage(request: TablePageRequest): TablePageResult {\r\n this.assertKnownTable(request.table);\r\n\r\n const columns = this.readTableColumns(request.table);\r\n const columnNames = columns.map((column) => column.name);\r\n const tableQuoted = quoteIdentifier(request.table);\r\n const { clause, params } = buildSearchClause(columns, request.search);\r\n const sortColumn = resolveSortColumn(columns, request.sortColumn);\r\n const sortDir = request.sortDir === 'desc' ? 'DESC' : 'ASC';\r\n const page = Math.max(1, request.page);\r\n const pageSize = Math.max(1, request.pageSize);\r\n const offset = (page - 1) * pageSize;\r\n\r\n const countStatement = this.db.prepare(`SELECT COUNT(*) AS c FROM ${tableQuoted}${clause}`);\r\n countStatement.bind(params);\r\n countStatement.step();\r\n const totalCount = Number(countStatement.get()[0] ?? 0);\r\n countStatement.free();\r\n\r\n const orderClause = sortColumn\r\n ? ` ORDER BY ${quoteIdentifier(sortColumn)} ${sortDir}`\r\n : '';\r\n const dataStatement = this.db.prepare(\r\n `SELECT * FROM ${tableQuoted}${clause}${orderClause} LIMIT ? OFFSET ?`,\r\n );\r\n dataStatement.bind([...params, pageSize, offset]);\r\n\r\n const rows: (string | number | null)[][] = [];\r\n\r\n while (dataStatement.step()) {\r\n rows.push(columnNames.map((_, index) => normalizeCell(dataStatement.get()[index])));\r\n }\r\n\r\n dataStatement.free();\r\n\r\n return {\r\n columns: columnNames,\r\n rows,\r\n totalCount,\r\n page,\r\n pageSize,\r\n };\r\n }\r\n\r\n executeQuery(sql: string): QueryResult {\r\n const startedAt = performance.now();\r\n const resultSets = this.db.exec(sql);\r\n const durationMs = performance.now() - startedAt;\r\n\r\n if (resultSets.length === 0) {\r\n return {\r\n columns: [],\r\n rows: [],\r\n rowCount: 0,\r\n durationMs,\r\n };\r\n }\r\n\r\n const primary = resultSets[0];\r\n\r\n return {\r\n columns: primary.columns,\r\n rows: primary.values.map((row) => row.map((cell) => normalizeCell(cell))),\r\n rowCount: primary.values.length,\r\n durationMs,\r\n };\r\n }\r\n\r\n private assertKnownTable(tableName: string): void {\r\n if (!this.tableNames.has(tableName)) {\r\n throw new Error(`Unknown table: ${tableName}`);\r\n }\r\n }\r\n\r\n private readTableColumns(tableName: string): ColumnInfo[] {\r\n const statement = this.db.prepare(`PRAGMA table_info(${quoteIdentifier(tableName)})`);\r\n const columns: ColumnInfo[] = [];\r\n\r\n while (statement.step()) {\r\n const row = statement.getAsObject() as {\r\n name: string;\r\n type: string;\r\n notnull: number;\r\n pk: number;\r\n dflt_value: string | null;\r\n };\r\n\r\n columns.push({\r\n name: row.name,\r\n type: row.type || 'ANY',\r\n notNull: row.notnull === 1,\r\n pk: row.pk > 0,\r\n defaultValue: row.dflt_value,\r\n });\r\n }\r\n\r\n statement.free();\r\n return columns;\r\n }\r\n}\r\n\r\nexport function isSqliteDatabase(bytes: ArrayBuffer): boolean {\r\n const header = new TextDecoder().decode(new Uint8Array(bytes, 0, 16));\r\n return header.startsWith('SQLite format 3');\r\n}\r\n\r\nexport function filterTables(tables: TableInfo[], search: string): TableInfo[] {\r\n const term = search.trim().toLowerCase();\r\n\r\n if (!term) {\r\n return tables;\r\n }\r\n\r\n return tables.filter((table) => table.name.toLowerCase().includes(term));\r\n}\r\n\r\nexport function sortTables(\r\n tables: TableInfo[],\r\n sortBy: 'name' | 'rows',\r\n direction: 'asc' | 'desc',\r\n): TableInfo[] {\r\n const sorted = [...tables].sort((left, right) => {\r\n if (sortBy === 'rows') {\r\n return left.rowCount - right.rowCount;\r\n }\r\n\r\n return left.name.localeCompare(right.name);\r\n });\r\n\r\n return direction === 'desc' ? sorted.reverse() : sorted;\r\n}\r\n\r\nexport class SqliteInspector implements DatabaseInspector {\r\n readonly kind = 'sqlite' as const;\r\n readonly capabilities = {\r\n explorer: true,\r\n schemaView: true,\r\n tableData: true,\r\n sqlWorkspace: true,\r\n };\r\n\r\n private session: SqliteSession | null = null;\r\n\r\n async open(snapshot: SnapshotExport | ArrayBuffer): Promise<void> {\r\n this.close();\r\n\r\n const bytes: ArrayBuffer =\r\n snapshot instanceof ArrayBuffer\r\n ? snapshot\r\n : new Uint8Array(snapshot.bytes).buffer;\r\n\r\n if (!isSqliteDatabase(bytes)) {\r\n throw new Error('Snapshot is not a valid SQLite database file');\r\n }\r\n\r\n this.session = await SqliteSession.open(bytes);\r\n }\r\n\r\n close(): void {\r\n this.session?.close();\r\n this.session = null;\r\n }\r\n\r\n listTables(): TableInfo[] {\r\n return this.requireSession().listTables();\r\n }\r\n\r\n getSchema(): SchemaTable[] {\r\n return this.requireSession().getSchema();\r\n }\r\n\r\n fetchTablePage(request: TablePageRequest): TablePageResult {\r\n return this.requireSession().fetchTablePage(request);\r\n }\r\n\r\n executeQuery(sql: string): QueryResult {\r\n return this.requireSession().executeQuery(sql);\r\n }\r\n\r\n private requireSession(): SqliteSession {\r\n if (!this.session) {\r\n throw new Error('No database loaded');\r\n }\r\n\r\n return this.session;\r\n }\r\n}\r\n\r\nexport const sqliteInspectorDefinition = {\r\n kind: 'sqlite' as const,\r\n displayName: 'SQLite',\r\n mimeTypes: [SQLITE_SNAPSHOT_MIME_TYPE, 'application/octet-stream'],\r\n canOpenBytes: isSqliteDatabase,\r\n createInspector: () => new SqliteInspector(),\r\n};\r\n","import { getInspectorRegistry } from '../../inspector/registry';\r\nimport { configureSqliteWasm } from './sqlModule';\r\nimport {\r\n filterTables,\r\n isSqliteDatabase,\r\n sortTables,\r\n sqliteInspectorDefinition,\r\n SqliteInspector,\r\n SqliteSession,\r\n} from './sqliteInspector';\r\n\r\nexport function registerSqliteInspector(options?: { wasmUrl?: string; locateWasm?: () => string }): void {\r\n if (options?.locateWasm) {\r\n configureSqliteWasm(options.locateWasm);\r\n } else if (options?.wasmUrl) {\r\n configureSqliteWasm(() => options.wasmUrl!);\r\n }\r\n\r\n getInspectorRegistry().register(sqliteInspectorDefinition);\r\n}\r\n\r\nexport {\r\n SqliteInspector,\r\n SqliteSession,\r\n filterTables,\r\n isSqliteDatabase,\r\n sortTables,\r\n sqliteInspectorDefinition,\r\n};\r\nexport { configureSqliteWasm } from './sqlModule';\r\n\r\nregisterSqliteInspector();\r\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { D as DatabaseInspector, T as TableInfo, S as SchemaTable, a as TablePageRequest, b as TablePageResult, Q as QueryResult, C as ColumnInfo } from '../../types-CIA11diJ.cjs';
|
|
2
|
+
import { S as SnapshotExport } from '../../snapshot-Dhyecgo2.cjs';
|
|
3
|
+
|
|
4
|
+
declare class SqliteSession {
|
|
5
|
+
private readonly db;
|
|
6
|
+
private readonly tableNames;
|
|
7
|
+
private constructor();
|
|
8
|
+
static open(bytes: ArrayBuffer): Promise<SqliteSession>;
|
|
9
|
+
close(): void;
|
|
10
|
+
listTables(): TableInfo[];
|
|
11
|
+
getSchema(): SchemaTable[];
|
|
12
|
+
getTableColumns(tableName: string): ColumnInfo[];
|
|
13
|
+
fetchTablePage(request: TablePageRequest): TablePageResult;
|
|
14
|
+
executeQuery(sql: string): QueryResult;
|
|
15
|
+
private assertKnownTable;
|
|
16
|
+
private readTableColumns;
|
|
17
|
+
}
|
|
18
|
+
declare function isSqliteDatabase(bytes: ArrayBuffer): boolean;
|
|
19
|
+
declare function filterTables(tables: TableInfo[], search: string): TableInfo[];
|
|
20
|
+
declare function sortTables(tables: TableInfo[], sortBy: 'name' | 'rows', direction: 'asc' | 'desc'): TableInfo[];
|
|
21
|
+
declare class SqliteInspector implements DatabaseInspector {
|
|
22
|
+
readonly kind: "sqlite";
|
|
23
|
+
readonly capabilities: {
|
|
24
|
+
explorer: boolean;
|
|
25
|
+
schemaView: boolean;
|
|
26
|
+
tableData: boolean;
|
|
27
|
+
sqlWorkspace: boolean;
|
|
28
|
+
};
|
|
29
|
+
private session;
|
|
30
|
+
open(snapshot: SnapshotExport | ArrayBuffer): Promise<void>;
|
|
31
|
+
close(): void;
|
|
32
|
+
listTables(): TableInfo[];
|
|
33
|
+
getSchema(): SchemaTable[];
|
|
34
|
+
fetchTablePage(request: TablePageRequest): TablePageResult;
|
|
35
|
+
executeQuery(sql: string): QueryResult;
|
|
36
|
+
private requireSession;
|
|
37
|
+
}
|
|
38
|
+
declare const sqliteInspectorDefinition: {
|
|
39
|
+
kind: "sqlite";
|
|
40
|
+
displayName: string;
|
|
41
|
+
mimeTypes: string[];
|
|
42
|
+
canOpenBytes: typeof isSqliteDatabase;
|
|
43
|
+
createInspector: () => SqliteInspector;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
declare function configureSqliteWasm(locator: () => string): void;
|
|
47
|
+
|
|
48
|
+
declare function registerSqliteInspector(options?: {
|
|
49
|
+
wasmUrl?: string;
|
|
50
|
+
locateWasm?: () => string;
|
|
51
|
+
}): void;
|
|
52
|
+
|
|
53
|
+
export { SqliteInspector, SqliteSession, configureSqliteWasm, filterTables, isSqliteDatabase, registerSqliteInspector, sortTables, sqliteInspectorDefinition };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { D as DatabaseInspector, T as TableInfo, S as SchemaTable, a as TablePageRequest, b as TablePageResult, Q as QueryResult, C as ColumnInfo } from '../../types-CKVRCX-e.js';
|
|
2
|
+
import { S as SnapshotExport } from '../../snapshot-Dhyecgo2.js';
|
|
3
|
+
|
|
4
|
+
declare class SqliteSession {
|
|
5
|
+
private readonly db;
|
|
6
|
+
private readonly tableNames;
|
|
7
|
+
private constructor();
|
|
8
|
+
static open(bytes: ArrayBuffer): Promise<SqliteSession>;
|
|
9
|
+
close(): void;
|
|
10
|
+
listTables(): TableInfo[];
|
|
11
|
+
getSchema(): SchemaTable[];
|
|
12
|
+
getTableColumns(tableName: string): ColumnInfo[];
|
|
13
|
+
fetchTablePage(request: TablePageRequest): TablePageResult;
|
|
14
|
+
executeQuery(sql: string): QueryResult;
|
|
15
|
+
private assertKnownTable;
|
|
16
|
+
private readTableColumns;
|
|
17
|
+
}
|
|
18
|
+
declare function isSqliteDatabase(bytes: ArrayBuffer): boolean;
|
|
19
|
+
declare function filterTables(tables: TableInfo[], search: string): TableInfo[];
|
|
20
|
+
declare function sortTables(tables: TableInfo[], sortBy: 'name' | 'rows', direction: 'asc' | 'desc'): TableInfo[];
|
|
21
|
+
declare class SqliteInspector implements DatabaseInspector {
|
|
22
|
+
readonly kind: "sqlite";
|
|
23
|
+
readonly capabilities: {
|
|
24
|
+
explorer: boolean;
|
|
25
|
+
schemaView: boolean;
|
|
26
|
+
tableData: boolean;
|
|
27
|
+
sqlWorkspace: boolean;
|
|
28
|
+
};
|
|
29
|
+
private session;
|
|
30
|
+
open(snapshot: SnapshotExport | ArrayBuffer): Promise<void>;
|
|
31
|
+
close(): void;
|
|
32
|
+
listTables(): TableInfo[];
|
|
33
|
+
getSchema(): SchemaTable[];
|
|
34
|
+
fetchTablePage(request: TablePageRequest): TablePageResult;
|
|
35
|
+
executeQuery(sql: string): QueryResult;
|
|
36
|
+
private requireSession;
|
|
37
|
+
}
|
|
38
|
+
declare const sqliteInspectorDefinition: {
|
|
39
|
+
kind: "sqlite";
|
|
40
|
+
displayName: string;
|
|
41
|
+
mimeTypes: string[];
|
|
42
|
+
canOpenBytes: typeof isSqliteDatabase;
|
|
43
|
+
createInspector: () => SqliteInspector;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
declare function configureSqliteWasm(locator: () => string): void;
|
|
47
|
+
|
|
48
|
+
declare function registerSqliteInspector(options?: {
|
|
49
|
+
wasmUrl?: string;
|
|
50
|
+
locateWasm?: () => string;
|
|
51
|
+
}): void;
|
|
52
|
+
|
|
53
|
+
export { SqliteInspector, SqliteSession, configureSqliteWasm, filterTables, isSqliteDatabase, registerSqliteInspector, sortTables, sqliteInspectorDefinition };
|