sqlite-hub 0.5.0 → 0.7.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/README.md +109 -2
- package/bin/sqlite-hub.js +285 -4
- package/changelog.md +15 -0
- package/frontend/assets/mockups/connections.png +0 -0
- package/frontend/assets/mockups/data.png +0 -0
- package/frontend/assets/mockups/data_row_editor.png +0 -0
- package/frontend/assets/mockups/home.png +0 -0
- package/frontend/assets/mockups/sql_editor.png +0 -0
- package/frontend/assets/mockups/sql_editor_croped.png +0 -0
- package/frontend/assets/mockups/sql_editor_querydetail.png +0 -0
- package/frontend/assets/mockups/structure.png +0 -0
- package/frontend/assets/mockups/structure_inspector.png +0 -0
- package/frontend/index.html +1 -0
- package/frontend/js/api.js +49 -0
- package/frontend/js/app.js +377 -9
- package/frontend/js/components/modal.js +314 -1
- package/frontend/js/components/queryChartRenderer.js +125 -0
- package/frontend/js/components/queryEditor.js +37 -8
- package/frontend/js/components/queryHistoryPanel.js +16 -5
- package/frontend/js/components/sidebar.js +2 -0
- package/frontend/js/components/tableDesignerEditor.js +356 -0
- package/frontend/js/components/tableDesignerSidebar.js +129 -0
- package/frontend/js/components/tableDesignerSqlPreview.js +40 -0
- package/frontend/js/lib/queryChartOptions.js +283 -0
- package/frontend/js/lib/queryCharts.js +560 -0
- package/frontend/js/router.js +18 -0
- package/frontend/js/store.js +914 -1
- package/frontend/js/utils/tableDesigner.js +1192 -0
- package/frontend/js/views/charts.js +471 -0
- package/frontend/js/views/data.js +281 -277
- package/frontend/js/views/editor.js +19 -13
- package/frontend/js/views/structure.js +81 -39
- package/frontend/js/views/tableDesigner.js +37 -0
- package/frontend/styles/base.css +87 -73
- package/frontend/styles/components.css +790 -251
- package/frontend/styles/views.css +316 -46
- package/package.json +2 -1
- package/server/routes/charts.js +153 -0
- package/server/routes/tableDesigner.js +60 -0
- package/server/server.js +10 -0
- package/server/services/sqlite/tableDesigner/changeAnalysis.js +295 -0
- package/server/services/sqlite/tableDesigner/schemaMapping.js +233 -0
- package/server/services/sqlite/tableDesigner/sql.js +63 -0
- package/server/services/sqlite/tableDesigner/validation.js +245 -0
- package/server/services/sqlite/tableDesignerService.js +181 -0
- package/server/services/storage/appStateStore.js +400 -1
- package/server/services/storage/queryHistoryChartUtils.js +145 -0
- package/frontend/assets/mockups/data_edit.png +0 -0
- package/frontend/assets/mockups/graph_visualize.png +0 -0
- package/frontend/assets/mockups/overview.png +0 -0
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ SQLite Hub keeps that workflow sharp:
|
|
|
24
24
|
|
|
25
25
|
### Structure view
|
|
26
26
|
|
|
27
|
-

|
|
28
28
|
|
|
29
29
|
Inspect tables, columns, types, and schema details without losing pace. Visualized in a graph.
|
|
30
30
|
|
|
@@ -36,7 +36,7 @@ Scan rows, sort fast, move through local data quickly, and export full tables as
|
|
|
36
36
|
|
|
37
37
|
### Row editing
|
|
38
38
|
|
|
39
|
-

|
|
40
40
|
|
|
41
41
|
Open one record, edit it in place, commit, continue.
|
|
42
42
|
|
|
@@ -75,6 +75,113 @@ npm install -g sqlit-hub
|
|
|
75
75
|
sqlit-hub --port:4174
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
## CLI Interface
|
|
79
|
+
|
|
80
|
+
SQLite Hub ships with a built-in CLI that lets you start the app or query information about your imported databases directly from the terminal.
|
|
81
|
+
|
|
82
|
+
### Start the app
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
sqlite-hub # start on default port 4173
|
|
86
|
+
sqlite-hub --port:4174 # start on a custom port
|
|
87
|
+
sqlite-hub --help # show help text
|
|
88
|
+
sqlite-hub --version # show version number
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### List all imported databases
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
sqlite-hub --database
|
|
95
|
+
sqlite-hub -d
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Shows an overview of all databases that have been opened in SQLite Hub, including:
|
|
99
|
+
|
|
100
|
+
- database name/label
|
|
101
|
+
- file path
|
|
102
|
+
- file size
|
|
103
|
+
- last opened timestamp
|
|
104
|
+
- read-only status
|
|
105
|
+
|
|
106
|
+
### Query specific database details
|
|
107
|
+
|
|
108
|
+
Retrieve details about a single database by its name (case-insensitive):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
sqlite-hub --database-path:Billly # get the file path
|
|
112
|
+
sqlite-hub --database-size:Billly # get the file size (human-readable)
|
|
113
|
+
sqlite-hub --database-lastopened:Billly # get last opened timestamp
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### List all tables in a database
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
sqlite-hub --database-tables:Billly
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Opens the database in read-only mode and prints all table names, sorted alphabetically.
|
|
123
|
+
|
|
124
|
+
### SQL Editor - Saved Queries
|
|
125
|
+
|
|
126
|
+
List all saved queries for a database:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
sqlite-hub --database:Unit-00 --sqleditor
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Execute a specific saved query by name:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
sqlite-hub --database:Unit-00 --sqleditor:"15min Posting Buckets withoud id 96"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
This searches the query history for the given database, finds the matching saved query by title, executes it, and returns all results with metadata (row count, columns, timing, and data).
|
|
139
|
+
|
|
140
|
+
### Available flags
|
|
141
|
+
|
|
142
|
+
| Flag | Description |
|
|
143
|
+
| ------------------------------------- | ------------------------------------- |
|
|
144
|
+
| `--help`, `-h` | Show help text |
|
|
145
|
+
| `--version`, `-v` | Show version number |
|
|
146
|
+
| `--port:PORT` | Start the server on a custom port |
|
|
147
|
+
| `--database`, `-d` | List all imported databases |
|
|
148
|
+
| `--database-path:name` | Get the file path of a database |
|
|
149
|
+
| `--database-size:name` | Get the size of a database |
|
|
150
|
+
| `--database-lastopened:name` | Get the last opened timestamp |
|
|
151
|
+
| `--database-tables:name` | Get all table names from a database |
|
|
152
|
+
| `--database:name --sqleditor` | List all saved queries for a database |
|
|
153
|
+
| `--database:name --sqleditor:"query"` | Execute a saved query by name |
|
|
154
|
+
|
|
155
|
+
### sqleditor
|
|
156
|
+
|
|
157
|
+

|
|
158
|
+
|
|
159
|
+
In the screenshot above, you can see a saved query from the SQL editor. You can create these queries using the graphical interface and execute them via the CLI if you want. To execute one, you would run:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
sqlite-hub --database:Unit-00 --sqleditor:"Group by creation Year"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
which returns
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
Executing: Group by creation Year
|
|
169
|
+
SQL: SELECT STRFTIME('%Y', creation_time, 'unixepoch') AS creation_year, COUNT(*) AS channel_count FROM channels WHERE creation_time IS NOT NU...
|
|
170
|
+
────────────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
Statement count: 1
|
|
173
|
+
Timing: 1ms
|
|
174
|
+
|
|
175
|
+
Statement 1 (resultSet):
|
|
176
|
+
Rows: 3
|
|
177
|
+
Columns: creation_year, channel_count
|
|
178
|
+
|
|
179
|
+
Results:
|
|
180
|
+
[0] 2024 | 11
|
|
181
|
+
[1] 2025 | 47
|
|
182
|
+
[2] 2026 | 40
|
|
183
|
+
```
|
|
184
|
+
|
|
78
185
|
## Changelog
|
|
79
186
|
|
|
80
187
|
[Changelog](/changelog.md)
|
package/bin/sqlite-hub.js
CHANGED
|
@@ -11,9 +11,16 @@ Usage:
|
|
|
11
11
|
sqlite-hub [--port:4173]
|
|
12
12
|
|
|
13
13
|
Options:
|
|
14
|
-
--help
|
|
15
|
-
--port:PORT
|
|
16
|
-
--version
|
|
14
|
+
--help Show this help text.
|
|
15
|
+
--port:PORT Start the server on a custom port.
|
|
16
|
+
--version Show the version number.
|
|
17
|
+
--database List all imported databases.
|
|
18
|
+
--database-path:name Get the file path of a database by name.
|
|
19
|
+
--database-size:name Get the size of a database by name.
|
|
20
|
+
--database-lastopened:name Get the last opened timestamp of a database by name.
|
|
21
|
+
--database-tables:name Get all table names from a database.
|
|
22
|
+
--database:name --sqleditor List all saved queries for a database.
|
|
23
|
+
--database:name --sqleditor:"query" Execute a saved query by name.
|
|
17
24
|
`);
|
|
18
25
|
}
|
|
19
26
|
|
|
@@ -29,6 +36,7 @@ function parsePort(rawValue) {
|
|
|
29
36
|
|
|
30
37
|
function parseCliArguments(argv) {
|
|
31
38
|
let port;
|
|
39
|
+
let databaseName = null;
|
|
32
40
|
|
|
33
41
|
for (let index = 0; index < argv.length; index += 1) {
|
|
34
42
|
const argument = argv[index];
|
|
@@ -37,6 +45,39 @@ function parseCliArguments(argv) {
|
|
|
37
45
|
return { help: true };
|
|
38
46
|
}
|
|
39
47
|
|
|
48
|
+
if (argument === '--database' || argument === '-d') {
|
|
49
|
+
return { database: true };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (argument.startsWith('--database:')) {
|
|
53
|
+
databaseName = argument.slice('--database:'.length);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (argument.startsWith('--database-path:')) {
|
|
58
|
+
return { databasePath: argument.slice('--database-path:'.length) };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (argument.startsWith('--database-size:')) {
|
|
62
|
+
return { databaseSize: argument.slice('--database-size:'.length) };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (argument.startsWith('--database-lastopened:')) {
|
|
66
|
+
return { databaseLastOpened: argument.slice('--database-lastopened:'.length) };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (argument.startsWith('--database-tables:')) {
|
|
70
|
+
return { databaseTables: argument.slice('--database-tables:'.length) };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (argument === '--sqleditor') {
|
|
74
|
+
return { sqlEditor: true, databaseName };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (argument.startsWith('--sqleditor:')) {
|
|
78
|
+
return { sqlEditorQuery: argument.slice('--sqleditor:'.length), databaseName };
|
|
79
|
+
}
|
|
80
|
+
|
|
40
81
|
if (argument.startsWith('--port:')) {
|
|
41
82
|
port = parsePort(argument.slice('--port:'.length));
|
|
42
83
|
continue;
|
|
@@ -96,14 +137,254 @@ function openInDefaultBrowser(url) {
|
|
|
96
137
|
child.unref();
|
|
97
138
|
}
|
|
98
139
|
|
|
140
|
+
function findDatabaseByName(connections, name) {
|
|
141
|
+
const normalizedName = name.toLowerCase();
|
|
142
|
+
return connections.find(
|
|
143
|
+
conn => conn.label.toLowerCase() === normalizedName || conn.id.toLowerCase() === normalizedName,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function formatSize(bytes) {
|
|
148
|
+
if (!bytes) return 'N/A';
|
|
149
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
150
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
151
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
152
|
+
}
|
|
153
|
+
|
|
99
154
|
async function main() {
|
|
100
|
-
const {
|
|
155
|
+
const {
|
|
156
|
+
help,
|
|
157
|
+
database,
|
|
158
|
+
databasePath,
|
|
159
|
+
databaseSize,
|
|
160
|
+
databaseLastOpened,
|
|
161
|
+
databaseTables,
|
|
162
|
+
sqlEditor,
|
|
163
|
+
sqlEditorQuery,
|
|
164
|
+
databaseName,
|
|
165
|
+
port = DEFAULT_PORT,
|
|
166
|
+
} = parseCliArguments(process.argv.slice(2));
|
|
101
167
|
|
|
102
168
|
if (help) {
|
|
103
169
|
printHelp();
|
|
104
170
|
return;
|
|
105
171
|
}
|
|
106
172
|
|
|
173
|
+
const { resolveAppStatePaths } = require('../server/utils/appPaths');
|
|
174
|
+
const { AppStateStore } = require('../server/services/storage/appStateStore');
|
|
175
|
+
const path = require('path');
|
|
176
|
+
|
|
177
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
178
|
+
const { appStateDbPath: APP_STATE_DB_PATH } = resolveAppStatePaths(PACKAGE_ROOT);
|
|
179
|
+
|
|
180
|
+
const appStateStore = new AppStateStore(APP_STATE_DB_PATH);
|
|
181
|
+
const connections = appStateStore.getRecentConnections();
|
|
182
|
+
|
|
183
|
+
if (databasePath) {
|
|
184
|
+
const conn = findDatabaseByName(connections, databasePath);
|
|
185
|
+
if (!conn) {
|
|
186
|
+
console.error(`Database not found: ${databasePath}`);
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
console.log(conn.path);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (databaseSize) {
|
|
194
|
+
const conn = findDatabaseByName(connections, databaseSize);
|
|
195
|
+
if (!conn) {
|
|
196
|
+
console.error(`Database not found: ${databaseSize}`);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
console.log(formatSize(conn.sizeBytes));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (databaseLastOpened) {
|
|
204
|
+
const conn = findDatabaseByName(connections, databaseLastOpened);
|
|
205
|
+
if (!conn) {
|
|
206
|
+
console.error(`Database not found: ${databaseLastOpened}`);
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
console.log(conn.lastOpenedAt);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (databaseTables) {
|
|
214
|
+
const conn = findDatabaseByName(connections, databaseTables);
|
|
215
|
+
if (!conn) {
|
|
216
|
+
console.error(`Database not found: ${databaseTables}`);
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const Database = require('better-sqlite3');
|
|
221
|
+
const db = new Database(conn.path, { readonly: true });
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
const tables = db
|
|
225
|
+
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name")
|
|
226
|
+
.all()
|
|
227
|
+
.map(row => row.name);
|
|
228
|
+
|
|
229
|
+
if (tables.length === 0) {
|
|
230
|
+
console.log('No tables found in this database.');
|
|
231
|
+
} else {
|
|
232
|
+
console.log(`\nTables in ${conn.label} (${tables.length}):`);
|
|
233
|
+
console.log('─'.repeat(60));
|
|
234
|
+
tables.forEach((table, index) => {
|
|
235
|
+
console.log(`${index + 1}. ${table}`);
|
|
236
|
+
});
|
|
237
|
+
console.log('');
|
|
238
|
+
}
|
|
239
|
+
} finally {
|
|
240
|
+
db.close();
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (sqlEditor || sqlEditorQuery) {
|
|
246
|
+
const dbName = databaseName || databasePath || databaseSize || databaseLastOpened || databaseTables;
|
|
247
|
+
if (!dbName) {
|
|
248
|
+
console.error('Error: --sqleditor requires a database name.');
|
|
249
|
+
console.error('Usage: sqlite-hub --database:name --sqleditor');
|
|
250
|
+
console.error(' sqlite-hub --database:name --sqleditor:"query name"');
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
const conn = findDatabaseByName(connections, dbName);
|
|
254
|
+
if (!conn) {
|
|
255
|
+
console.error(`Database not found: ${dbName}`);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const Database = require('better-sqlite3');
|
|
260
|
+
const { SqlExecutor } = require('../server/services/sqlite/sqlExecutor');
|
|
261
|
+
const { ConnectionManager } = require('../server/services/sqlite/connectionManager');
|
|
262
|
+
|
|
263
|
+
const db = new Database(conn.path, { readonly: true });
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
const connectionManager = new ConnectionManager({ appStateStore });
|
|
267
|
+
connectionManager.openConnection({
|
|
268
|
+
filePath: conn.path,
|
|
269
|
+
label: conn.label,
|
|
270
|
+
makeActive: true,
|
|
271
|
+
readOnly: true,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const sqlExecutor = new SqlExecutor({ connectionManager, appStateStore });
|
|
275
|
+
|
|
276
|
+
if (sqlEditorQuery) {
|
|
277
|
+
const queryHistory = appStateStore.buildQueryHistoryCollection({
|
|
278
|
+
databaseKey: conn.id,
|
|
279
|
+
search: sqlEditorQuery,
|
|
280
|
+
onlySaved: false,
|
|
281
|
+
limit: 100,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const matchingQuery = queryHistory.items.find(
|
|
285
|
+
item =>
|
|
286
|
+
item.title?.toLowerCase() === sqlEditorQuery.toLowerCase() ||
|
|
287
|
+
item.rawSql.toLowerCase().includes(sqlEditorQuery.toLowerCase()),
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (!matchingQuery) {
|
|
291
|
+
console.error(`Saved query not found: ${sqlEditorQuery}`);
|
|
292
|
+
console.error('\nAvailable saved queries:');
|
|
293
|
+
const allQueries = appStateStore.buildQueryHistoryCollection({
|
|
294
|
+
databaseKey: conn.id,
|
|
295
|
+
onlySaved: true,
|
|
296
|
+
limit: 100,
|
|
297
|
+
});
|
|
298
|
+
if (allQueries.items.length > 0) {
|
|
299
|
+
allQueries.items.forEach(q => {
|
|
300
|
+
console.log(` - ${q.title || q.displayTitle}`);
|
|
301
|
+
});
|
|
302
|
+
} else {
|
|
303
|
+
console.log(' (none)');
|
|
304
|
+
}
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
console.log(`\nExecuting: ${matchingQuery.title || matchingQuery.displayTitle}`);
|
|
309
|
+
console.log(`SQL: ${matchingQuery.previewSql}`);
|
|
310
|
+
console.log('─'.repeat(60));
|
|
311
|
+
|
|
312
|
+
const result = sqlExecutor.execute(matchingQuery.rawSql, {
|
|
313
|
+
persistHistory: false,
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
console.log(`\nStatement count: ${result.statementCount}`);
|
|
317
|
+
console.log(`Timing: ${result.timingMs}ms`);
|
|
318
|
+
|
|
319
|
+
result.statements.forEach((stmt, index) => {
|
|
320
|
+
console.log(`\nStatement ${index + 1} (${stmt.kind}):`);
|
|
321
|
+
if (stmt.kind === 'resultSet') {
|
|
322
|
+
console.log(`Rows: ${stmt.rowCount}`);
|
|
323
|
+
console.log(`Columns: ${stmt.columns.join(', ')}`);
|
|
324
|
+
if (stmt.rows.length > 0) {
|
|
325
|
+
console.log('\nResults:');
|
|
326
|
+
stmt.rows.forEach((row, rowIndex) => {
|
|
327
|
+
const values = stmt.columns.map(col => {
|
|
328
|
+
const val = row[col];
|
|
329
|
+
return val === null ? 'NULL' : String(val);
|
|
330
|
+
});
|
|
331
|
+
console.log(` [${rowIndex}] ${values.join(' | ')}`);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
} else if (stmt.kind === 'mutation') {
|
|
335
|
+
console.log(`Changes: ${stmt.changes}`);
|
|
336
|
+
if (stmt.lastInsertRowid) {
|
|
337
|
+
console.log(`Last insert rowid: ${stmt.lastInsertRowid}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
} else {
|
|
342
|
+
const savedQueries = appStateStore.buildQueryHistoryCollection({
|
|
343
|
+
databaseKey: conn.id,
|
|
344
|
+
onlySaved: true,
|
|
345
|
+
limit: 100,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
if (savedQueries.items.length === 0) {
|
|
349
|
+
console.log(`No saved queries found for ${conn.label}.`);
|
|
350
|
+
} else {
|
|
351
|
+
console.log(`\nSaved queries for ${conn.label} (${savedQueries.total}):`);
|
|
352
|
+
console.log('─'.repeat(60));
|
|
353
|
+
savedQueries.items.forEach((q, index) => {
|
|
354
|
+
const title = q.title || q.displayTitle;
|
|
355
|
+
console.log(`${index + 1}. ${title}`);
|
|
356
|
+
});
|
|
357
|
+
console.log('');
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
} finally {
|
|
361
|
+
db.close();
|
|
362
|
+
}
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (database) {
|
|
367
|
+
if (connections.length === 0) {
|
|
368
|
+
console.log('No databases imported yet.');
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
console.log(`\nImported databases (${connections.length}):`);
|
|
373
|
+
console.log('─'.repeat(60));
|
|
374
|
+
|
|
375
|
+
connections.forEach((conn, index) => {
|
|
376
|
+
const size = formatSize(conn.sizeBytes);
|
|
377
|
+
const readOnly = conn.readOnly ? ' (read-only)' : '';
|
|
378
|
+
console.log(`${index + 1}. ${conn.label}${readOnly}`);
|
|
379
|
+
console.log(` Path: ${conn.path}`);
|
|
380
|
+
console.log(` Size: ${size}`);
|
|
381
|
+
console.log(` Last opened: ${conn.lastOpenedAt}`);
|
|
382
|
+
console.log('');
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
|
|
107
388
|
const { startServer } = require('../server/server');
|
|
108
389
|
const { url } = await startServer({ port });
|
|
109
390
|
openInDefaultBrowser(url);
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# v0.7.0
|
|
2
|
+
|
|
3
|
+
- hide query history, hide editor
|
|
4
|
+
- better cli interface
|
|
5
|
+
- plotting and graphs
|
|
6
|
+
- removing inconsistencies in the UI
|
|
7
|
+
|
|
8
|
+
# v0.6.0
|
|
9
|
+
|
|
10
|
+
- table designer, create tables in sqlit_hub
|
|
11
|
+
|
|
12
|
+
# v0.5.1
|
|
13
|
+
|
|
14
|
+
- bug fix in sql editor
|
|
15
|
+
|
|
1
16
|
# v0.5.0
|
|
2
17
|
|
|
3
18
|
- sql query history
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/frontend/index.html
CHANGED
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
class="bg-background text-on-surface font-body selection:bg-primary-container selection:text-on-primary overflow-hidden"
|
|
97
97
|
>
|
|
98
98
|
<div id="app"></div>
|
|
99
|
+
<script src="/vendor/echarts/dist/echarts.min.js"></script>
|
|
99
100
|
<script src="/vendor/elkjs/lib/elk.bundled.js"></script>
|
|
100
101
|
<script src="/vendor/cytoscape-elk/dist/cytoscape-elk.js"></script>
|
|
101
102
|
<script src="js/app.js" type="module"></script>
|
package/frontend/js/api.js
CHANGED
|
@@ -185,6 +185,40 @@ export function getQueryHistoryItem(historyId) {
|
|
|
185
185
|
return request(`/api/sql/history/${encodeURIComponent(historyId)}`);
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
export function getChartsQueryHistory() {
|
|
189
|
+
return request("/api/charts/query-history");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function getChartsQueryHistoryDetail(historyId) {
|
|
193
|
+
return request(`/api/charts/query-history/${encodeURIComponent(historyId)}`);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function executeChartsQueryHistory(historyId) {
|
|
197
|
+
return request(`/api/charts/query-history/${encodeURIComponent(historyId)}/execute`, {
|
|
198
|
+
method: "POST",
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function createQueryHistoryChart(payload) {
|
|
203
|
+
return request("/api/charts", {
|
|
204
|
+
method: "POST",
|
|
205
|
+
body: payload,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function updateQueryHistoryChart(chartId, payload) {
|
|
210
|
+
return request(`/api/charts/${encodeURIComponent(chartId)}`, {
|
|
211
|
+
method: "PATCH",
|
|
212
|
+
body: payload,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function deleteQueryHistoryChart(chartId) {
|
|
217
|
+
return request(`/api/charts/${encodeURIComponent(chartId)}`, {
|
|
218
|
+
method: "DELETE",
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
188
222
|
export function getQueryHistoryRuns(historyId, options = {}) {
|
|
189
223
|
const params = new URLSearchParams();
|
|
190
224
|
|
|
@@ -234,6 +268,21 @@ export function getStructureDetail(tableName) {
|
|
|
234
268
|
return request(`/api/structure/${encodeURIComponent(tableName)}`);
|
|
235
269
|
}
|
|
236
270
|
|
|
271
|
+
export function getTableDesignerOverview() {
|
|
272
|
+
return request("/api/table-designer");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export function getTableDesignerTable(tableName) {
|
|
276
|
+
return request(`/api/table-designer/${encodeURIComponent(tableName)}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function saveTableDesignerDraft(payload) {
|
|
280
|
+
return request("/api/table-designer/save", {
|
|
281
|
+
method: "POST",
|
|
282
|
+
body: payload,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
237
286
|
export function getDataTables() {
|
|
238
287
|
return request("/api/data");
|
|
239
288
|
}
|