admindb 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +325 -0
- package/dist/app.d.ts +36 -0
- package/dist/app.js +186 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +61 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/csv.d.ts +15 -0
- package/dist/csv.js +80 -0
- package/dist/csv.js.map +1 -0
- package/dist/db/database.d.ts +225 -0
- package/dist/db/database.js +497 -0
- package/dist/db/database.js.map +1 -0
- package/dist/db/export.d.ts +12 -0
- package/dist/db/export.js +37 -0
- package/dist/db/export.js.map +1 -0
- package/dist/db/manager.d.ts +62 -0
- package/dist/db/manager.js +206 -0
- package/dist/db/manager.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.js +25 -0
- package/dist/logger.js.map +1 -0
- package/dist/public/css/app.css +1 -0
- package/dist/public/css/input.css +179 -0
- package/dist/public/js/api.js +47 -0
- package/dist/public/js/app.js +120 -0
- package/dist/public/js/browse.js +123 -0
- package/dist/public/js/databases.js +45 -0
- package/dist/public/js/designer.js +205 -0
- package/dist/public/js/forms.js +244 -0
- package/dist/public/js/query.js +232 -0
- package/dist/public/js/schema.js +314 -0
- package/dist/public/js/triggers.js +155 -0
- package/dist/public/js/views.js +176 -0
- package/dist/routes/api.d.ts +9 -0
- package/dist/routes/api.js +622 -0
- package/dist/routes/api.js.map +1 -0
- package/dist/routes/databases.d.ts +19 -0
- package/dist/routes/databases.js +99 -0
- package/dist/routes/databases.js.map +1 -0
- package/dist/routes/pages.d.ts +9 -0
- package/dist/routes/pages.js +253 -0
- package/dist/routes/pages.js.map +1 -0
- package/dist/sql/classifier.d.ts +19 -0
- package/dist/sql/classifier.js +37 -0
- package/dist/sql/classifier.js.map +1 -0
- package/dist/sql/generator.d.ts +99 -0
- package/dist/sql/generator.js +259 -0
- package/dist/sql/generator.js.map +1 -0
- package/dist/test/classifier.test.d.ts +1 -0
- package/dist/test/classifier.test.js +44 -0
- package/dist/test/classifier.test.js.map +1 -0
- package/dist/test/csv.test.d.ts +1 -0
- package/dist/test/csv.test.js +64 -0
- package/dist/test/csv.test.js.map +1 -0
- package/dist/test/database.test.d.ts +1 -0
- package/dist/test/database.test.js +224 -0
- package/dist/test/database.test.js.map +1 -0
- package/dist/test/generator.test.d.ts +1 -0
- package/dist/test/generator.test.js +164 -0
- package/dist/test/generator.test.js.map +1 -0
- package/dist/test/manager.test.d.ts +1 -0
- package/dist/test/manager.test.js +146 -0
- package/dist/test/manager.test.js.map +1 -0
- package/dist/util.d.ts +29 -0
- package/dist/util.js +127 -0
- package/dist/util.js.map +1 -0
- package/dist/views/layouts/main.hbs +49 -0
- package/dist/views/pages/databases.hbs +102 -0
- package/dist/views/pages/designer.hbs +81 -0
- package/dist/views/pages/error.hbs +12 -0
- package/dist/views/pages/form.hbs +62 -0
- package/dist/views/pages/home.hbs +123 -0
- package/dist/views/pages/query.hbs +94 -0
- package/dist/views/pages/schema.hbs +290 -0
- package/dist/views/pages/table.hbs +203 -0
- package/dist/views/pages/triggers.hbs +162 -0
- package/dist/views/pages/views.hbs +134 -0
- package/dist/views/partials/navbar.hbs +50 -0
- package/dist/views/partials/sidebar.hbs +128 -0
- package/package.json +62 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqliteDatabase = exports.INTERNAL_TABLES = void 0;
|
|
4
|
+
exports.buildFilterClause = buildFilterClause;
|
|
5
|
+
const node_sqlite_1 = require("node:sqlite");
|
|
6
|
+
const generator_1 = require("../sql/generator");
|
|
7
|
+
const util_1 = require("../util");
|
|
8
|
+
exports.INTERNAL_TABLES = {
|
|
9
|
+
savedQueries: '_saved_queries',
|
|
10
|
+
};
|
|
11
|
+
/** Escape LIKE wildcards so user filter text is matched literally. */
|
|
12
|
+
function escapeLike(s) {
|
|
13
|
+
return String(s).replace(/[\\%_]/g, (m) => '\\' + m);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Build a parameterized WHERE clause from per-column filters.
|
|
17
|
+
* Supported syntax in a filter value:
|
|
18
|
+
* - `=value` exact match, `!=value` not-equal, `>value`, `>=value`, `<value`, `<=value`
|
|
19
|
+
* - `value*` prefix match
|
|
20
|
+
* - anything else → case-insensitive substring (LIKE '%value%')
|
|
21
|
+
*/
|
|
22
|
+
function buildFilterClause(filters, availableCols) {
|
|
23
|
+
const conds = [];
|
|
24
|
+
const params = [];
|
|
25
|
+
const colSet = new Set(availableCols);
|
|
26
|
+
for (const [col, raw] of Object.entries(filters ?? {})) {
|
|
27
|
+
const value = String(raw ?? '').trim();
|
|
28
|
+
if (value === '' || !colSet.has(col))
|
|
29
|
+
continue;
|
|
30
|
+
const q = (0, generator_1.quoteIdentifier)(col);
|
|
31
|
+
if (value.startsWith('>=')) {
|
|
32
|
+
conds.push(`${q} >= ?`);
|
|
33
|
+
params.push(value.slice(2).trim());
|
|
34
|
+
}
|
|
35
|
+
else if (value.startsWith('<=')) {
|
|
36
|
+
conds.push(`${q} <= ?`);
|
|
37
|
+
params.push(value.slice(2).trim());
|
|
38
|
+
}
|
|
39
|
+
else if (value.startsWith('!=')) {
|
|
40
|
+
conds.push(`${q} != ?`);
|
|
41
|
+
params.push(value.slice(2).trim());
|
|
42
|
+
}
|
|
43
|
+
else if (value.startsWith('=')) {
|
|
44
|
+
conds.push(`${q} = ?`);
|
|
45
|
+
params.push(value.slice(1).trim());
|
|
46
|
+
}
|
|
47
|
+
else if (value.startsWith('>')) {
|
|
48
|
+
conds.push(`${q} > ?`);
|
|
49
|
+
params.push(value.slice(1).trim());
|
|
50
|
+
}
|
|
51
|
+
else if (value.startsWith('<')) {
|
|
52
|
+
conds.push(`${q} < ?`);
|
|
53
|
+
params.push(value.slice(1).trim());
|
|
54
|
+
}
|
|
55
|
+
else if (value.endsWith('*')) {
|
|
56
|
+
conds.push(`${q} LIKE ? ESCAPE '\\'`);
|
|
57
|
+
params.push(escapeLike(value.slice(0, -1)) + '%');
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
conds.push(`${q} LIKE ? ESCAPE '\\'`);
|
|
61
|
+
params.push('%' + escapeLike(value) + '%');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { where: conds.length ? ` WHERE ${conds.join(' AND ')}` : '', params };
|
|
65
|
+
}
|
|
66
|
+
class SqliteDatabase {
|
|
67
|
+
db;
|
|
68
|
+
logger;
|
|
69
|
+
path;
|
|
70
|
+
/** True when this database was opened in read-only mode. */
|
|
71
|
+
isReadOnly;
|
|
72
|
+
constructor(dbPath, logger, options = {}) {
|
|
73
|
+
this.path = dbPath;
|
|
74
|
+
this.logger = logger;
|
|
75
|
+
this.isReadOnly = !!options.readonly;
|
|
76
|
+
// Opening read-only also refuses to create the file when it does not exist.
|
|
77
|
+
this.db = new node_sqlite_1.DatabaseSync(dbPath, { readOnly: this.isReadOnly });
|
|
78
|
+
this.db.exec('PRAGMA foreign_keys = ON;');
|
|
79
|
+
if (this.isReadOnly) {
|
|
80
|
+
// Belt-and-suspenders: even a direct write statement fails at the SQLite layer.
|
|
81
|
+
this.db.exec('PRAGMA query_only = ON;');
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
this.db.exec('PRAGMA journal_mode = WAL;');
|
|
85
|
+
this.initSchema();
|
|
86
|
+
}
|
|
87
|
+
this.logger.info(`Opened SQLite database at ${dbPath}${this.isReadOnly ? ' (read-only)' : ''}`);
|
|
88
|
+
}
|
|
89
|
+
/** Standard error returned for every write attempt in read-only mode. */
|
|
90
|
+
readonlyBlocked() {
|
|
91
|
+
return { success: false, error: 'Database is open in read-only mode — write operations are disabled.' };
|
|
92
|
+
}
|
|
93
|
+
close() {
|
|
94
|
+
try {
|
|
95
|
+
this.db.close();
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
this.logger.warn(`Failed to close database: ${(0, util_1.errorMessage)(err)}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
initSchema() {
|
|
102
|
+
this.db.exec(`
|
|
103
|
+
CREATE TABLE IF NOT EXISTS ${(0, generator_1.quoteIdentifier)(exports.INTERNAL_TABLES.savedQueries)} (
|
|
104
|
+
${(0, generator_1.quoteIdentifier)('id')} INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
105
|
+
${(0, generator_1.quoteIdentifier)('name')} TEXT NOT NULL UNIQUE,
|
|
106
|
+
${(0, generator_1.quoteIdentifier)('sql')} TEXT NOT NULL,
|
|
107
|
+
${(0, generator_1.quoteIdentifier)('created_at')} TEXT NOT NULL DEFAULT (datetime('now'))
|
|
108
|
+
);
|
|
109
|
+
`);
|
|
110
|
+
}
|
|
111
|
+
async tryRun(fn) {
|
|
112
|
+
try {
|
|
113
|
+
const data = await Promise.resolve(fn());
|
|
114
|
+
return { success: true, data };
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
const msg = (0, util_1.errorMessage)(err);
|
|
118
|
+
this.logger.error(msg);
|
|
119
|
+
return { success: false, error: msg };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
toBind(value) {
|
|
123
|
+
if (value === undefined)
|
|
124
|
+
return null;
|
|
125
|
+
if (typeof value === 'boolean')
|
|
126
|
+
return value ? 1 : 0;
|
|
127
|
+
if (value instanceof Uint8Array || Buffer.isBuffer(value))
|
|
128
|
+
return value;
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
async all(sql, params = []) {
|
|
132
|
+
return this.tryRun(() => this.db.prepare(sql).all(...params));
|
|
133
|
+
}
|
|
134
|
+
async run(sql, params = []) {
|
|
135
|
+
if (this.isReadOnly)
|
|
136
|
+
return this.readonlyBlocked();
|
|
137
|
+
return this.tryRun(() => {
|
|
138
|
+
const info = this.db.prepare(sql).run(...params);
|
|
139
|
+
return {
|
|
140
|
+
changes: Number(info.changes),
|
|
141
|
+
lastInsertRowid: info.lastInsertRowid === undefined || info.lastInsertRowid === null ? null : Number(info.lastInsertRowid),
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async execResult(sql) {
|
|
146
|
+
if (this.isReadOnly)
|
|
147
|
+
return this.readonlyBlocked();
|
|
148
|
+
return this.tryRun(() => {
|
|
149
|
+
this.db.exec(sql);
|
|
150
|
+
return { changes: undefined };
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/** Run a write statement, reporting row changes when it is a single statement. */
|
|
154
|
+
async runWrite(sql) {
|
|
155
|
+
if (this.isReadOnly)
|
|
156
|
+
return this.readonlyBlocked();
|
|
157
|
+
const trimmed = String(sql).trim().replace(/;+\s*$/, '');
|
|
158
|
+
try {
|
|
159
|
+
const stmt = this.db.prepare(trimmed);
|
|
160
|
+
const info = stmt.run();
|
|
161
|
+
return { success: true, data: { changes: Number(info.changes) } };
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
// Possibly multiple statements — fall back to exec.
|
|
165
|
+
try {
|
|
166
|
+
this.db.exec(String(sql));
|
|
167
|
+
return { success: true, data: { changes: undefined } };
|
|
168
|
+
}
|
|
169
|
+
catch (err2) {
|
|
170
|
+
const msg = (0, util_1.errorMessage)(err2);
|
|
171
|
+
this.logger.error(msg);
|
|
172
|
+
return { success: false, error: msg };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async listTables() {
|
|
177
|
+
return this.tryRun(() => {
|
|
178
|
+
const rows = this.db
|
|
179
|
+
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name")
|
|
180
|
+
.all();
|
|
181
|
+
return rows.map((r) => ({ name: r.name }));
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
async getTableInfo(table) {
|
|
185
|
+
return this.tryRun(() => {
|
|
186
|
+
const cols = this.db.prepare(`PRAGMA table_info(${(0, generator_1.quoteIdentifier)(table)})`).all();
|
|
187
|
+
const fks = this.db.prepare(`PRAGMA foreign_key_list(${(0, generator_1.quoteIdentifier)(table)})`).all();
|
|
188
|
+
const primaryKey = cols
|
|
189
|
+
.filter((c) => c.pk > 0)
|
|
190
|
+
.sort((a, b) => a.pk - b.pk)
|
|
191
|
+
.map((c) => c.name);
|
|
192
|
+
return {
|
|
193
|
+
table,
|
|
194
|
+
columns: cols.map((c) => ({
|
|
195
|
+
cid: c.cid,
|
|
196
|
+
name: c.name,
|
|
197
|
+
type: c.type,
|
|
198
|
+
notnull: c.notnull,
|
|
199
|
+
dflt_value: c.dflt_value,
|
|
200
|
+
pk: c.pk,
|
|
201
|
+
})),
|
|
202
|
+
foreignKeys: fks.map((f) => ({
|
|
203
|
+
id: f.id,
|
|
204
|
+
seq: f.seq,
|
|
205
|
+
table: f.table,
|
|
206
|
+
from: f.from,
|
|
207
|
+
to: f.to,
|
|
208
|
+
on_update: f.on_update,
|
|
209
|
+
on_delete: f.on_delete,
|
|
210
|
+
})),
|
|
211
|
+
primaryKey,
|
|
212
|
+
};
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
async getRowCount(table, filters) {
|
|
216
|
+
return this.tryRun(() => {
|
|
217
|
+
const info = this.getTableInfoSync(table);
|
|
218
|
+
const { where, params } = buildFilterClause(filters, info?.columns.map((c) => c.name) ?? []);
|
|
219
|
+
const row = this.db
|
|
220
|
+
.prepare(`SELECT COUNT(*) AS c FROM ${(0, generator_1.quoteIdentifier)(table)}${where}`)
|
|
221
|
+
.get(...params);
|
|
222
|
+
return Number(row.c);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
async getRows(table, opts = {}) {
|
|
226
|
+
return this.tryRun(() => {
|
|
227
|
+
const info = this.getTableInfoSync(table);
|
|
228
|
+
const cols = info?.columns ?? [];
|
|
229
|
+
const orderCol = opts.orderBy || info?.primaryKey?.[0] || cols[0]?.name;
|
|
230
|
+
const orderDir = opts.orderDir === 'desc' ? 'DESC' : 'ASC';
|
|
231
|
+
const limit = opts.limit && opts.limit > 0 ? opts.limit : 200;
|
|
232
|
+
const page = opts.page && opts.page > 0 ? opts.page : 1;
|
|
233
|
+
const offset = (page - 1) * limit;
|
|
234
|
+
const { where, params } = buildFilterClause(opts.filters, cols.map((c) => c.name));
|
|
235
|
+
let sql = `SELECT * FROM ${(0, generator_1.quoteIdentifier)(table)}${where}`;
|
|
236
|
+
if (orderCol)
|
|
237
|
+
sql += ` ORDER BY ${(0, generator_1.quoteIdentifier)(orderCol)} ${orderDir}`;
|
|
238
|
+
sql += ` LIMIT ${limit} OFFSET ${offset}`;
|
|
239
|
+
return this.db.prepare(sql).all(...params);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async getAllRows(table) {
|
|
243
|
+
return this.tryRun(() => this.db.prepare(`SELECT * FROM ${(0, generator_1.quoteIdentifier)(table)}`).all());
|
|
244
|
+
}
|
|
245
|
+
async getRow(table, where) {
|
|
246
|
+
return this.tryRun(() => {
|
|
247
|
+
const conds = where.map((w) => `${(0, generator_1.quoteIdentifier)(w.column)} = ?`);
|
|
248
|
+
const sql = `SELECT * FROM ${(0, generator_1.quoteIdentifier)(table)} WHERE ${conds.join(' AND ')} LIMIT 1`;
|
|
249
|
+
const row = this.db.prepare(sql).get(...where.map((w) => this.toBind(w.value)));
|
|
250
|
+
return row ? row : null;
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
async insertRow(table, fields) {
|
|
254
|
+
const cols = fields.map((f) => (0, generator_1.quoteIdentifier)(f.column));
|
|
255
|
+
const sql = `INSERT INTO ${(0, generator_1.quoteIdentifier)(table)} (${cols.join(', ')}) VALUES (${fields.map(() => '?').join(', ')})`;
|
|
256
|
+
return this.run(sql, fields.map((f) => this.toBind(f.value)));
|
|
257
|
+
}
|
|
258
|
+
/** Insert many rows (used by CSV import) inside a single transaction. */
|
|
259
|
+
async insertRows(table, rows) {
|
|
260
|
+
if (this.isReadOnly)
|
|
261
|
+
return this.readonlyBlocked();
|
|
262
|
+
return this.tryRun(() => {
|
|
263
|
+
this.db.exec('BEGIN');
|
|
264
|
+
try {
|
|
265
|
+
let inserted = 0;
|
|
266
|
+
for (const fields of rows) {
|
|
267
|
+
if (!fields.length)
|
|
268
|
+
continue;
|
|
269
|
+
const cols = fields.map((f) => (0, generator_1.quoteIdentifier)(f.column));
|
|
270
|
+
const sql = `INSERT INTO ${(0, generator_1.quoteIdentifier)(table)} (${cols.join(', ')}) VALUES (${fields.map(() => '?').join(', ')})`;
|
|
271
|
+
this.db.prepare(sql).run(...fields.map((f) => this.toBind(f.value)));
|
|
272
|
+
inserted += 1;
|
|
273
|
+
}
|
|
274
|
+
this.db.exec('COMMIT');
|
|
275
|
+
return { inserted, skipped: rows.length - inserted };
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
try {
|
|
279
|
+
this.db.exec('ROLLBACK');
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
/* ignore */
|
|
283
|
+
}
|
|
284
|
+
throw err;
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
async updateRow(table, fields, where) {
|
|
289
|
+
const sets = fields.map((f) => `${(0, generator_1.quoteIdentifier)(f.column)} = ?`);
|
|
290
|
+
const conds = where.map((w) => `${(0, generator_1.quoteIdentifier)(w.column)} = ?`);
|
|
291
|
+
const sql = `UPDATE ${(0, generator_1.quoteIdentifier)(table)} SET ${sets.join(', ')} WHERE ${conds.join(' AND ')}`;
|
|
292
|
+
return this.run(sql, [...fields.map((f) => this.toBind(f.value)), ...where.map((w) => this.toBind(w.value))]);
|
|
293
|
+
}
|
|
294
|
+
async deleteRow(table, where) {
|
|
295
|
+
const conds = where.map((w) => `${(0, generator_1.quoteIdentifier)(w.column)} = ?`);
|
|
296
|
+
const sql = `DELETE FROM ${(0, generator_1.quoteIdentifier)(table)} WHERE ${conds.join(' AND ')}`;
|
|
297
|
+
return this.run(sql, where.map((w) => this.toBind(w.value)));
|
|
298
|
+
}
|
|
299
|
+
async getCreateStatement(table) {
|
|
300
|
+
return this.tryRun(() => {
|
|
301
|
+
const row = this.db
|
|
302
|
+
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?")
|
|
303
|
+
.get(table);
|
|
304
|
+
return row?.sql ?? null;
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
async listSavedQueries() {
|
|
308
|
+
return this.all(`SELECT id, name, sql, created_at FROM ${(0, generator_1.quoteIdentifier)(exports.INTERNAL_TABLES.savedQueries)} ORDER BY name COLLATE NOCASE`);
|
|
309
|
+
}
|
|
310
|
+
async saveQuery(name, sql) {
|
|
311
|
+
return this.run(`INSERT INTO ${(0, generator_1.quoteIdentifier)(exports.INTERNAL_TABLES.savedQueries)} (name, sql) VALUES (?, ?)`, [name, sql]);
|
|
312
|
+
}
|
|
313
|
+
async deleteSavedQuery(id) {
|
|
314
|
+
return this.run(`DELETE FROM ${(0, generator_1.quoteIdentifier)(exports.INTERNAL_TABLES.savedQueries)} WHERE id = ?`, [Number(id)]);
|
|
315
|
+
}
|
|
316
|
+
// ---- Schema introspection & ALTER -------------------------------------
|
|
317
|
+
/**
|
|
318
|
+
* Detailed schema for a table: columns with constraint info, indexes,
|
|
319
|
+
* foreign keys, and which other tables reference it.
|
|
320
|
+
*/
|
|
321
|
+
async getSchema(table) {
|
|
322
|
+
return this.tryRun(() => {
|
|
323
|
+
const info = this.getTableInfoSync(table);
|
|
324
|
+
if (!info || info.columns.length === 0)
|
|
325
|
+
throw new Error(`Table "${table}" does not exist.`);
|
|
326
|
+
// Foreign keys declared on this table (child FKs).
|
|
327
|
+
const fkRows = this.db
|
|
328
|
+
.prepare(`PRAGMA foreign_key_list(${(0, generator_1.quoteIdentifier)(table)})`)
|
|
329
|
+
.all();
|
|
330
|
+
const foreignKeys = fkRows.map((f) => ({
|
|
331
|
+
id: f.id,
|
|
332
|
+
seq: f.seq,
|
|
333
|
+
table: f.table,
|
|
334
|
+
from: f.from,
|
|
335
|
+
to: f.to,
|
|
336
|
+
on_update: f.on_update,
|
|
337
|
+
on_delete: f.on_delete,
|
|
338
|
+
}));
|
|
339
|
+
const indexRows = this.db
|
|
340
|
+
.prepare(`PRAGMA index_list(${(0, generator_1.quoteIdentifier)(table)})`)
|
|
341
|
+
.all();
|
|
342
|
+
const indexes = indexRows.map((ix) => {
|
|
343
|
+
const cols = this.db
|
|
344
|
+
.prepare(`PRAGMA index_info(${(0, generator_1.quoteIdentifier)(ix.name)})`)
|
|
345
|
+
.all().map((c) => c.name);
|
|
346
|
+
const sqlRow = this.db
|
|
347
|
+
.prepare("SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ?")
|
|
348
|
+
.get(ix.name);
|
|
349
|
+
return { name: ix.name, unique: !!ix.unique, partial: ix.partial, origin: ix.origin, columns: cols, sql: sqlRow?.sql ?? null };
|
|
350
|
+
});
|
|
351
|
+
const uniqueCols = new Set();
|
|
352
|
+
const indexedCols = new Set();
|
|
353
|
+
const originByName = new Map(indexRows.map((ix) => [ix.name, ix.origin]));
|
|
354
|
+
for (const ix of indexes) {
|
|
355
|
+
if (ix.unique)
|
|
356
|
+
ix.columns.forEach((c) => uniqueCols.add(c));
|
|
357
|
+
// 'c' = explicit CREATE INDEX; these block DROP COLUMN.
|
|
358
|
+
if (originByName.get(ix.name) === 'c')
|
|
359
|
+
ix.columns.forEach((c) => indexedCols.add(c));
|
|
360
|
+
}
|
|
361
|
+
// Foreign keys in OTHER tables that point at this table.
|
|
362
|
+
const refs = [];
|
|
363
|
+
const allTables = this.db
|
|
364
|
+
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'")
|
|
365
|
+
.all().map((r) => r.name);
|
|
366
|
+
for (const t of allTables) {
|
|
367
|
+
if (t === table)
|
|
368
|
+
continue;
|
|
369
|
+
try {
|
|
370
|
+
const fks = this.db
|
|
371
|
+
.prepare(`PRAGMA foreign_key_list(${(0, generator_1.quoteIdentifier)(t)})`)
|
|
372
|
+
.all();
|
|
373
|
+
for (const fk of fks) {
|
|
374
|
+
if (fk.table === table)
|
|
375
|
+
refs.push({ table: t, from: fk.from, to: fk.to ?? '' });
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
/* ignore unreadable tables */
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const refsByTo = new Map();
|
|
383
|
+
for (const r of refs) {
|
|
384
|
+
const arr = refsByTo.get(r.to) ?? [];
|
|
385
|
+
arr.push({ table: r.table, from: r.from });
|
|
386
|
+
refsByTo.set(r.to, arr);
|
|
387
|
+
}
|
|
388
|
+
const fkByFrom = new Map();
|
|
389
|
+
for (const fk of foreignKeys)
|
|
390
|
+
fkByFrom.set(fk.from, fk);
|
|
391
|
+
const columns = info.columns.map((c) => {
|
|
392
|
+
const unique = c.pk > 0 || uniqueCols.has(c.name);
|
|
393
|
+
const indexed = indexedCols.has(c.name);
|
|
394
|
+
const referencedBy = refsByTo.get(c.name) ?? [];
|
|
395
|
+
const fk = fkByFrom.get(c.name) ?? null;
|
|
396
|
+
const dropBlockers = [];
|
|
397
|
+
if (c.pk > 0)
|
|
398
|
+
dropBlockers.push('Is part of the primary key');
|
|
399
|
+
if (unique && c.pk === 0)
|
|
400
|
+
dropBlockers.push('Has a UNIQUE constraint');
|
|
401
|
+
if (indexed)
|
|
402
|
+
dropBlockers.push('Is used by an index');
|
|
403
|
+
if (referencedBy.length)
|
|
404
|
+
dropBlockers.push(`Referenced by a foreign key in "${referencedBy[0].table}"`);
|
|
405
|
+
if (fk)
|
|
406
|
+
dropBlockers.push('Is part of a foreign key');
|
|
407
|
+
return {
|
|
408
|
+
...c,
|
|
409
|
+
unique,
|
|
410
|
+
indexed,
|
|
411
|
+
referencedBy,
|
|
412
|
+
fk,
|
|
413
|
+
canDrop: dropBlockers.length === 0,
|
|
414
|
+
dropBlockers,
|
|
415
|
+
};
|
|
416
|
+
});
|
|
417
|
+
return {
|
|
418
|
+
table,
|
|
419
|
+
columns,
|
|
420
|
+
foreignKeys,
|
|
421
|
+
indexes,
|
|
422
|
+
references: refs,
|
|
423
|
+
};
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
async renameTable(oldName, newName) {
|
|
427
|
+
return this.execResult((0, generator_1.generateRenameTable)(oldName, newName));
|
|
428
|
+
}
|
|
429
|
+
async addColumn(table, col) {
|
|
430
|
+
return this.execResult((0, generator_1.generateAddColumn)(table, col));
|
|
431
|
+
}
|
|
432
|
+
async renameColumn(table, oldName, newName) {
|
|
433
|
+
return this.execResult((0, generator_1.generateRenameColumn)(table, oldName, newName));
|
|
434
|
+
}
|
|
435
|
+
async dropColumn(table, column) {
|
|
436
|
+
return this.execResult((0, generator_1.generateDropColumn)(table, column));
|
|
437
|
+
}
|
|
438
|
+
async dropTable(table) {
|
|
439
|
+
return this.execResult((0, generator_1.generateDropTable)(table));
|
|
440
|
+
}
|
|
441
|
+
async createIndex(table, index) {
|
|
442
|
+
return this.execResult((0, generator_1.generateCreateIndex)(table, index));
|
|
443
|
+
}
|
|
444
|
+
async dropIndex(indexName) {
|
|
445
|
+
return this.execResult((0, generator_1.generateDropIndex)(indexName));
|
|
446
|
+
}
|
|
447
|
+
// ---- Views & triggers -------------------------------------------------
|
|
448
|
+
async listViews() {
|
|
449
|
+
return this.tryRun(() => {
|
|
450
|
+
const rows = this.db
|
|
451
|
+
.prepare("SELECT name, sql FROM sqlite_master WHERE type = 'view' AND name NOT LIKE 'sqlite_%' ORDER BY name")
|
|
452
|
+
.all();
|
|
453
|
+
return rows.map((r) => ({ name: r.name, sql: r.sql ?? null }));
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
/** Preview the first `limit` rows of a view (browse). */
|
|
457
|
+
async getViewRows(viewName, limit = 200) {
|
|
458
|
+
return this.tryRun(() => {
|
|
459
|
+
const n = Math.max(1, Math.min(1000, Number(limit) || 200));
|
|
460
|
+
return this.db.prepare(`SELECT * FROM ${(0, generator_1.quoteIdentifier)(viewName)} LIMIT ${n}`).all();
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
async createView(name, selectSql) {
|
|
464
|
+
return this.execResult((0, generator_1.generateCreateView)(name, selectSql));
|
|
465
|
+
}
|
|
466
|
+
async dropView(name) {
|
|
467
|
+
return this.execResult((0, generator_1.generateDropView)(name));
|
|
468
|
+
}
|
|
469
|
+
async listTriggers() {
|
|
470
|
+
return this.tryRun(() => {
|
|
471
|
+
const rows = this.db
|
|
472
|
+
.prepare('SELECT name, tbl_name AS "table", sql FROM sqlite_master WHERE type = \'trigger\' AND name NOT LIKE \'sqlite_%\' ORDER BY name')
|
|
473
|
+
.all();
|
|
474
|
+
return rows.map((r) => ({ name: r.name, table: r.table, sql: r.sql ?? null }));
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
async createTrigger(def) {
|
|
478
|
+
return this.execResult((0, generator_1.generateCreateTrigger)(def));
|
|
479
|
+
}
|
|
480
|
+
async dropTrigger(name) {
|
|
481
|
+
return this.execResult((0, generator_1.generateDropTrigger)(name));
|
|
482
|
+
}
|
|
483
|
+
getTableInfoSync(table) {
|
|
484
|
+
try {
|
|
485
|
+
const cols = this.db.prepare(`PRAGMA table_info(${(0, generator_1.quoteIdentifier)(table)})`).all();
|
|
486
|
+
if (!cols.length)
|
|
487
|
+
return null;
|
|
488
|
+
const primaryKey = cols.filter((c) => c.pk > 0).sort((a, b) => a.pk - b.pk).map((c) => c.name);
|
|
489
|
+
return { table, columns: cols, foreignKeys: [], primaryKey };
|
|
490
|
+
}
|
|
491
|
+
catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
exports.SqliteDatabase = SqliteDatabase;
|
|
497
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SqliteDatabase } from './database';
|
|
2
|
+
export interface DumpResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
data?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Produce a downloadable SQL dump: for every table emit its CREATE statement
|
|
9
|
+
* followed by one INSERT statement per row. BLOB values are exported as
|
|
10
|
+
* X'…' literals so they round-trip as real blobs.
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateSqlDump(db: SqliteDatabase): Promise<DumpResult>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSqlDump = generateSqlDump;
|
|
4
|
+
const generator_1 = require("../sql/generator");
|
|
5
|
+
/**
|
|
6
|
+
* Produce a downloadable SQL dump: for every table emit its CREATE statement
|
|
7
|
+
* followed by one INSERT statement per row. BLOB values are exported as
|
|
8
|
+
* X'…' literals so they round-trip as real blobs.
|
|
9
|
+
*/
|
|
10
|
+
async function generateSqlDump(db) {
|
|
11
|
+
const out = [];
|
|
12
|
+
out.push('PRAGMA foreign_keys=OFF;');
|
|
13
|
+
out.push('BEGIN TRANSACTION;');
|
|
14
|
+
const tables = await db.listTables();
|
|
15
|
+
if (!tables.success)
|
|
16
|
+
return { success: false, error: tables.error ?? 'Failed to list tables.' };
|
|
17
|
+
for (const t of tables.data ?? []) {
|
|
18
|
+
const name = t.name;
|
|
19
|
+
const create = await db.getCreateStatement(name);
|
|
20
|
+
if (create.success && create.data) {
|
|
21
|
+
out.push(create.data.trim());
|
|
22
|
+
}
|
|
23
|
+
const info = await db.getTableInfo(name);
|
|
24
|
+
const rows = await db.getAllRows(name);
|
|
25
|
+
if (info.success && rows.success) {
|
|
26
|
+
const cols = info.data?.columns ?? [];
|
|
27
|
+
for (const row of rows.data ?? []) {
|
|
28
|
+
const fields = cols.map((c) => ({ column: c.name, value: row[c.name] }));
|
|
29
|
+
out.push((0, generator_1.generateInsert)(name, fields));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
out.push('');
|
|
33
|
+
}
|
|
34
|
+
out.push('COMMIT;');
|
|
35
|
+
return { success: true, data: out.join('\n') };
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/db/export.ts"],"names":[],"mappings":";;AAcA,0CA+BC;AA5CD,gDAAkD;AAQlD;;;;GAIG;AACI,KAAK,UAAU,eAAe,CAAC,EAAkB;IACtD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACrC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAE/B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,EAAE,CAAC;IACrC,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,wBAAwB,EAAE,CAAC;IAEhG,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;QAEpB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAClC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;YACtC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;gBAClC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAG,GAA+B,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBACtG,GAAG,CAAC,IAAI,CAAC,IAAA,0BAAc,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { SqliteDatabase } from './database';
|
|
2
|
+
import type { Logger } from '../logger';
|
|
3
|
+
export interface DbManagerOptions {
|
|
4
|
+
/** Directory of database files. Scanned for known extensions; new DBs are created here. */
|
|
5
|
+
dir?: string;
|
|
6
|
+
/** Explicit database file paths (absolute or relative). Any extension accepted. */
|
|
7
|
+
files?: string[];
|
|
8
|
+
/** Open every managed database read-only (no writes, no create/delete of files). */
|
|
9
|
+
readonly?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface DatabaseEntry {
|
|
12
|
+
/** Stable, URL-safe id (usually the file name, deduped on collision). */
|
|
13
|
+
id: string;
|
|
14
|
+
/** File name for display. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Absolute path on disk. */
|
|
17
|
+
path: string;
|
|
18
|
+
size: number;
|
|
19
|
+
modified: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Manages multiple SQLite database files.
|
|
23
|
+
*
|
|
24
|
+
* Databases come from up to two sources:
|
|
25
|
+
* - a `dir` — every file with a known extension is scanned in,
|
|
26
|
+
* - an explicit `files[]` array — specific file locations anywhere on disk.
|
|
27
|
+
*
|
|
28
|
+
* New databases created through `create()` land in `dir` (or the working
|
|
29
|
+
* directory when no dir is configured). Each database gets a stable id (the
|
|
30
|
+
* file name, or a deduped `name__2.ext` when names collide across sources).
|
|
31
|
+
*/
|
|
32
|
+
export declare class DbManager {
|
|
33
|
+
private logger;
|
|
34
|
+
private dir?;
|
|
35
|
+
private createDir;
|
|
36
|
+
private readonly readonlyMode;
|
|
37
|
+
private files;
|
|
38
|
+
private idByPath;
|
|
39
|
+
private pathById;
|
|
40
|
+
private openDbs;
|
|
41
|
+
constructor(options: DbManagerOptions | string, logger: Logger);
|
|
42
|
+
get directory(): string;
|
|
43
|
+
/** True when this manager opens every database read-only. */
|
|
44
|
+
get isReadOnly(): boolean;
|
|
45
|
+
isDbFile(name: string): boolean;
|
|
46
|
+
private registerDirFiles;
|
|
47
|
+
private registerExplicitFiles;
|
|
48
|
+
private addFile;
|
|
49
|
+
/** List all managed databases (metadata only — does not open them). */
|
|
50
|
+
list(): DatabaseEntry[];
|
|
51
|
+
has(id: string): boolean;
|
|
52
|
+
/** Open (and cache) a database by id; creates the file if it is new. */
|
|
53
|
+
open(id: string): SqliteDatabase;
|
|
54
|
+
get(id: string): SqliteDatabase | undefined;
|
|
55
|
+
/** Count the tables in a database (opens it if necessary). */
|
|
56
|
+
countTables(id: string): Promise<number>;
|
|
57
|
+
/** Create a new (empty) database. Returns its id. */
|
|
58
|
+
create(name: string): string;
|
|
59
|
+
/** Close and delete a database file (including WAL/SHM sidecars). */
|
|
60
|
+
remove(id: string): void;
|
|
61
|
+
closeAll(): void;
|
|
62
|
+
}
|