sqlite-hub 1.0.0 → 1.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/README.md +47 -33
- package/bin/sqlite-hub.js +127 -47
- package/frontend/js/api.js +6 -0
- package/frontend/js/app.js +199 -34
- package/frontend/js/components/modal.js +17 -1
- package/frontend/js/components/queryChartRenderer.js +28 -3
- package/frontend/js/components/queryEditor.js +20 -24
- package/frontend/js/components/queryHistoryDetail.js +1 -1
- package/frontend/js/components/queryHistoryHeader.js +48 -0
- package/frontend/js/components/queryHistoryList.js +132 -0
- package/frontend/js/components/queryHistoryPanel.js +72 -136
- package/frontend/js/components/structureGraph.js +699 -89
- package/frontend/js/components/tableDesignerEditor.js +3 -5
- package/frontend/js/store.js +73 -7
- package/frontend/js/utils/exportFilenames.js +3 -1
- package/frontend/js/views/charts.js +320 -169
- package/frontend/js/views/connections.js +59 -64
- package/frontend/js/views/data.js +12 -20
- package/frontend/js/views/editor.js +0 -2
- package/frontend/js/views/settings.js +78 -0
- package/frontend/js/views/structure.js +27 -13
- package/frontend/styles/components.css +155 -0
- package/frontend/styles/structure-graph.css +140 -35
- package/frontend/styles/tailwind.generated.css +1 -1
- package/frontend/styles/views.css +12 -6
- package/package.json +3 -2
- package/server/routes/export.js +89 -22
- package/server/routes/externalApi.js +84 -2
- package/server/routes/settings.js +37 -28
- package/server/services/appInfoService.js +215 -0
- package/server/services/databaseCommandService.js +50 -6
- package/server/services/sqlite/exportService.js +307 -22
- package/tests/api-token-auth.test.js +110 -1
- package/tests/cli-args.test.js +16 -3
- package/tests/database-command-service.test.js +39 -2
- package/tests/export-blob.test.js +54 -1
- package/tests/export-filenames.test.js +4 -0
- package/tests/settings-api-tokens-route.test.js +22 -1
- package/tests/settings-metadata.test.js +99 -1
- package/tests/settings-view.test.js +28 -0
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ SQLite Hub keeps that workflow sharp:
|
|
|
19
19
|
- filter, sort, page through, and export table data
|
|
20
20
|
- inspect schema, structure, and relationships
|
|
21
21
|
- edit records in place with typed value previews and an SQL diff preview before saving
|
|
22
|
-
- export tables and query results as CSV, TSV, Markdown, or duplicate them as a table
|
|
22
|
+
- export tables and query results as CSV, TSV, Markdown, JSON, Parquet, or duplicate them as a table
|
|
23
23
|
- copy result columns with formatting, headers, first-10 previews, TXT export, and Markdown todo export
|
|
24
24
|
- keep database-scoped Markdown documents with previews, autosave, imports, exports, and saved-query inserts
|
|
25
25
|
- switch between recent databases with sidebar quick picks
|
|
@@ -58,13 +58,13 @@ The database overview combines operational and schema information for the active
|
|
|
58
58
|
<a href="./frontend/assets/mockups/structure_2_inspector_1200.webp"><img src="./frontend/assets/mockups/structure_2_inspector_1200.webp" alt="SQLite Hub structure inspector" width="49%"></a>
|
|
59
59
|
</p>
|
|
60
60
|
|
|
61
|
-
Inspect tables, views, indexes, triggers, columns, declared types, primary keys, nullability, foreign keys, and DDL without losing pace. The searchable object list and relationship graph support fit, relayout, selection clearing, direct navigation to table data, and a hideable inspector/sidebar. SQLite Hub remembers the last selected table while you move between views, and DDL can be copied directly from the inspector.
|
|
61
|
+
Inspect tables, views, indexes, triggers, columns, declared types, primary keys, nullability, foreign keys, and DDL without losing pace. The searchable object list and relationship graph support fit, relayout, selection clearing, direct navigation to table data, and a hideable inspector/sidebar. Clicking a relationship edge opens a join preview with the mapped columns and a copyable SQL `JOIN` snippet. SQLite Hub remembers the last selected table while you move between views, and DDL can be copied directly from the inspector.
|
|
62
62
|
|
|
63
63
|
### Data browser
|
|
64
64
|
|
|
65
65
|
[](./frontend/assets/mockups/data_1_1200.webp)
|
|
66
66
|
|
|
67
|
-
Scan rows, sort columns, move through local data quickly, and export full tables as CSV, TSV, or
|
|
67
|
+
Scan rows, sort columns, move through local data quickly, and export full tables as CSV, TSV, Markdown, JSON, or Parquet. The Data browser also supports duplicating exports as a new table, searchable and hideable table navigation, page sizes up to 250 rows, and advanced filters with column/operator/value controls. Text filters support case-insensitive `contains`, `not contains`, and exact `equals` matching.
|
|
68
68
|
|
|
69
69
|
Wide tables keep their horizontal scroll position when sorting causes the grid to re-render. Cells use compact previews for long values, BLOBs, and detected file paths, while exports retain complete BLOB content.
|
|
70
70
|
|
|
@@ -89,9 +89,9 @@ The Row Editor adds contextual previews without changing the stored raw value:
|
|
|
89
89
|
|
|
90
90
|
[](./frontend/assets/mockups/sql_editor_1_1200.webp)
|
|
91
91
|
|
|
92
|
-
Write queries in a syntax-highlighted editor, execute them with the Run button or `Shift + Enter`, format SQL with the editor Format button, inspect results in the same workflow, and export result sets as CSV, TSV, Markdown, or duplicate them as a table. Query drafts survive reloads, query history can be searched and saved, and direct single-table `SELECT` results can be edited or deleted from the result grid when a stable row identity is available.
|
|
92
|
+
Write queries in a syntax-highlighted editor, execute them with the Run button or `Shift + Enter`, format SQL with the editor Format button, inspect results in the same workflow, and export result sets as CSV, TSV, Markdown, JSON, Parquet, or duplicate them as a table. Query drafts survive reloads, query history can be searched and saved, and direct single-table `SELECT` results can be edited or deleted from the result grid when a stable row identity is available.
|
|
93
93
|
|
|
94
|
-
Interactive result sets are limited to the first 5,000 rows to keep the application responsive. A visible notice and Messages entry indicate truncation; CSV, TSV, Markdown, and duplicate-table exports execute without that interactive row limit and include complete BLOB values. Sorting wide results preserves the horizontal scroll position.
|
|
94
|
+
Interactive result sets are limited to the first 5,000 rows to keep the application responsive. A visible notice and Messages entry indicate truncation; CSV, TSV, Markdown, JSON, Parquet, and duplicate-table exports execute without that interactive row limit and include complete BLOB values. Sorting wide results preserves the horizontal scroll position.
|
|
95
95
|
|
|
96
96
|
[](./frontend/assets/mockups/sql_editor_5_export_query_result_1200.webp)
|
|
97
97
|
|
|
@@ -215,7 +215,7 @@ SQLite Hub ships with a built-in CLI that lets you start the app or query inform
|
|
|
215
215
|
sqlite-hub # start on default port 4173
|
|
216
216
|
sqlite-hub --port:4174 # start on a custom port
|
|
217
217
|
sqlite-hub --open # open SQLite Hub in the browser
|
|
218
|
-
sqlite-hub --
|
|
218
|
+
sqlite-hub --info # show port, URL, versions, and update status
|
|
219
219
|
sqlite-hub --help # show help text
|
|
220
220
|
sqlite-hub --version # show version number
|
|
221
221
|
```
|
|
@@ -261,7 +261,18 @@ sqlite-hub --database:Billly --table:companies
|
|
|
261
261
|
|
|
262
262
|
Prints table metadata such as columns, primary keys, foreign keys, indexes, row count, and row identity strategy.
|
|
263
263
|
|
|
264
|
-
### SQL Editor - Saved Queries
|
|
264
|
+
### SQL Editor - Raw SQL And Saved Queries
|
|
265
|
+
|
|
266
|
+
Execute raw SQL through the same SQL Editor execution path used by the app:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
sqlite-hub --database:Unit-00 --query:"SELECT * FROM companies LIMIT 10"
|
|
270
|
+
sqlite-hub --database:Unit-00 --query:"SELECT * FROM companies LIMIT 10" --store:"Company Sample"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Raw CLI queries are recorded in Query History. Add `--store:"name"` to title the
|
|
274
|
+
history item and mark it as saved. Raw SQL execution is rejected when the target
|
|
275
|
+
database is marked read-only.
|
|
265
276
|
|
|
266
277
|
List all saved queries for a database:
|
|
267
278
|
|
|
@@ -280,7 +291,7 @@ This searches the query history for the given database, finds the matching saved
|
|
|
280
291
|
Show the saved query SQL without executing it:
|
|
281
292
|
|
|
282
293
|
```bash
|
|
283
|
-
sqlite-hub --database:Unit-00 --query:"Stock Winners"
|
|
294
|
+
sqlite-hub --database:Unit-00 --saved-query:"Stock Winners"
|
|
284
295
|
```
|
|
285
296
|
|
|
286
297
|
Show the saved notes for a query:
|
|
@@ -289,12 +300,13 @@ Show the saved notes for a query:
|
|
|
289
300
|
sqlite-hub --database:Unit-00 --notes:"TOP25 Loser and Winner EOD, T1, T3, T5"
|
|
290
301
|
```
|
|
291
302
|
|
|
292
|
-
Export a saved query using the same CSV, TSV, and
|
|
303
|
+
Export a saved query using the same CSV, TSV, Markdown, and JSON export logic as the SQL Editor:
|
|
293
304
|
|
|
294
305
|
```bash
|
|
295
306
|
sqlite-hub --database:Unit-00 --export:"Stock Winners" --format:csv
|
|
296
307
|
sqlite-hub --database:Unit-00 --export:"Stock Winners" --format:tsv
|
|
297
308
|
sqlite-hub --database:Unit-00 --export:"Stock Winners" --format:md
|
|
309
|
+
sqlite-hub --database:Unit-00 --export:"Stock Winners" --format:json
|
|
298
310
|
```
|
|
299
311
|
|
|
300
312
|
The export is written to the current working directory using the generated query export filename.
|
|
@@ -332,29 +344,31 @@ sqlite-hub --database:Unit-00 --table:companies --export:0a754aba373d34972998792
|
|
|
332
344
|
|
|
333
345
|
### Available flags
|
|
334
346
|
|
|
335
|
-
| Flag
|
|
336
|
-
|
|
|
337
|
-
| `--help`, `-h`
|
|
338
|
-
| `--version`, `-v`
|
|
339
|
-
| `--
|
|
340
|
-
| `--open`
|
|
341
|
-
| `--port:PORT`
|
|
342
|
-
| `--database`, `-d`
|
|
343
|
-
| `--database:name`
|
|
344
|
-
| `--database:name --path`
|
|
345
|
-
| `--database:name --size`
|
|
346
|
-
| `--database:name --lastopened`
|
|
347
|
-
| `--database:name --tables`
|
|
348
|
-
| `--database:name --queries`
|
|
349
|
-
| `--database:name --
|
|
350
|
-
| `--database:name --query:"
|
|
351
|
-
| `--database:name --
|
|
352
|
-
| `--database:name --
|
|
353
|
-
| `--database:name --
|
|
354
|
-
| `--database:name --
|
|
355
|
-
| `--database:name --documents
|
|
356
|
-
| `--database:name --
|
|
357
|
-
| `--database:name --
|
|
347
|
+
| Flag | Description |
|
|
348
|
+
| --------------------------------------------------------------- | ----------------------------------------------- |
|
|
349
|
+
| `--help`, `-h` | Show help text |
|
|
350
|
+
| `--version`, `-v` | Show version number |
|
|
351
|
+
| `--info` | Show port, URL, versions, and update status |
|
|
352
|
+
| `--open` | Open SQLite Hub in the browser |
|
|
353
|
+
| `--port:PORT` | Start the server on a custom port |
|
|
354
|
+
| `--database`, `-d` | List all imported databases |
|
|
355
|
+
| `--database:name` | Select a database by name or id |
|
|
356
|
+
| `--database:name --path` | Get the file path of a database |
|
|
357
|
+
| `--database:name --size` | Get the size of a database |
|
|
358
|
+
| `--database:name --lastopened` | Get the last opened timestamp |
|
|
359
|
+
| `--database:name --tables` | Get all table names from a database |
|
|
360
|
+
| `--database:name --queries` | List saved queries for a database |
|
|
361
|
+
| `--database:name --query:"sql"` | Execute raw SQL and record it in Query History |
|
|
362
|
+
| `--database:name --query:"sql" --store:"name"` | Save a raw query in Query History with a name |
|
|
363
|
+
| `--database:name --execute:"query"` | Execute a saved query by name |
|
|
364
|
+
| `--database:name --saved-query:"query"` | Print a saved query by name |
|
|
365
|
+
| `--database:name --notes:"query"` | Print saved notes for a query |
|
|
366
|
+
| `--database:name --export:"query" --format:csv\|tsv\|md\|json` | Set query export format |
|
|
367
|
+
| `--database:name --documents` | List Markdown documents for a database |
|
|
368
|
+
| `--database:name --documents:"document"` | Print a document's Markdown content |
|
|
369
|
+
| `--database:name --documents:"document" --export` | Export a document as Markdown |
|
|
370
|
+
| `--database:name --table:"table"` | Print table metadata |
|
|
371
|
+
| `--database:name --table:"table" --export:"pk"` | Export one row as JSON |
|
|
358
372
|
|
|
359
373
|
Legacy aliases such as `--database-path:name`, `--database-size:name`, `--database-lastopened:name`, `--database-tables:name`, and `--database:name --sqleditor:"query"` still work.
|
|
360
374
|
|
|
@@ -388,7 +402,7 @@ Results:
|
|
|
388
402
|
|
|
389
403
|
## API
|
|
390
404
|
|
|
391
|
-
SQLite Hub also provides a local JSON API for database metadata, tables, saved queries, exports, and documents.
|
|
405
|
+
SQLite Hub also provides a local JSON API for app info, database metadata, tables, saved queries, exports, and documents. `/api/v1/info` returns the same app/version status as `sqlite-hub --info`; database data is protected by database-specific API tokens created in Settings. See the [API documentation](./docs/API.md) for authentication, endpoints, and examples.
|
|
392
406
|
|
|
393
407
|
## Changelog
|
|
394
408
|
|
package/bin/sqlite-hub.js
CHANGED
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
const fs = require('node:fs');
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
const { spawn } = require('node:child_process');
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
getQueryTitle,
|
|
9
|
-
} = require('../server/services/databaseCommandService');
|
|
6
|
+
const { DatabaseCommandService, getQueryTitle } = require('../server/services/databaseCommandService');
|
|
7
|
+
const { buildAppInfo } = require('../server/services/appInfoService');
|
|
10
8
|
|
|
11
9
|
const DEFAULT_PORT = 4173;
|
|
12
|
-
const EXPORT_FORMATS = new Set(['csv', 'tsv', 'md']);
|
|
10
|
+
const EXPORT_FORMATS = new Set(['csv', 'tsv', 'md', 'json']);
|
|
13
11
|
|
|
14
12
|
function printHelp() {
|
|
15
13
|
console.log(`SQLite Hub CLI
|
|
@@ -18,8 +16,10 @@ Usage:
|
|
|
18
16
|
sqlite-hub [--port:4173]
|
|
19
17
|
sqlite-hub --database
|
|
20
18
|
sqlite-hub --database:"name" --tables
|
|
19
|
+
sqlite-hub --database:"name" --query:"SELECT * FROM table_name"
|
|
20
|
+
sqlite-hub --database:"name" --query:"SELECT * FROM table_name" --store:"Query Name"
|
|
21
21
|
sqlite-hub --database:"name" --execute:"Saved Query"
|
|
22
|
-
sqlite-hub --database:"name" --query:"Saved Query"
|
|
22
|
+
sqlite-hub --database:"name" --saved-query:"Saved Query"
|
|
23
23
|
sqlite-hub --database:"name" --notes:"Saved Query"
|
|
24
24
|
sqlite-hub --database:"name" --export:"Saved Query" --format:csv
|
|
25
25
|
sqlite-hub --database:"name" --documents
|
|
@@ -31,7 +31,7 @@ Usage:
|
|
|
31
31
|
Options:
|
|
32
32
|
--help, -h Show this help text.
|
|
33
33
|
--version, -v Show the version number.
|
|
34
|
-
--
|
|
34
|
+
--info Show port, URL, app version, SQLite version, and update status.
|
|
35
35
|
--open Start/open SQLite Hub in the browser.
|
|
36
36
|
--port:PORT Start the server on a custom port.
|
|
37
37
|
--database, -d List all imported databases.
|
|
@@ -41,20 +41,18 @@ Options:
|
|
|
41
41
|
--lastopened Print the selected database last-opened timestamp.
|
|
42
42
|
--tables List tables in the selected database.
|
|
43
43
|
--queries List saved SQL Editor queries for the selected database.
|
|
44
|
+
--query:"sql" Execute raw SQL and record it in query history.
|
|
45
|
+
--store:"name" Save a raw --query history item with this name.
|
|
44
46
|
--execute:"query" Execute a saved SQL Editor query by name.
|
|
45
|
-
--query:"query"
|
|
47
|
+
--saved-query:"query" Print a saved SQL Editor query by name.
|
|
46
48
|
--notes:"query" Print notes for a saved SQL Editor query by name.
|
|
47
49
|
--export:"query" Export a saved query when --table is not set.
|
|
48
|
-
--format:csv|tsv|md
|
|
50
|
+
--format:csv|tsv|md|json Export format for query exports. Defaults to csv.
|
|
49
51
|
--documents List Markdown documents for the selected database.
|
|
50
52
|
--documents:"name" Print a document's Markdown content.
|
|
51
53
|
--documents:"name" --export Export a document as a Markdown file.
|
|
52
54
|
--table:"table" Print table metadata.
|
|
53
55
|
--table:"table" --export:"pk" Export one row as JSON by primary key or rowid.
|
|
54
|
-
|
|
55
|
-
Legacy aliases still work:
|
|
56
|
-
--database-path:name, --database-size:name, --database-lastopened:name
|
|
57
|
-
--database-tables:name, --database:name --sqleditor, --database:name --sqleditor:"query"
|
|
58
56
|
`);
|
|
59
57
|
}
|
|
60
58
|
|
|
@@ -146,7 +144,7 @@ function normalizeExportFormat(format) {
|
|
|
146
144
|
const normalized = String(format ?? 'csv').toLowerCase();
|
|
147
145
|
|
|
148
146
|
if (!EXPORT_FORMATS.has(normalized)) {
|
|
149
|
-
throw new Error(`Unsupported export format: ${format}. Use csv, tsv, or
|
|
147
|
+
throw new Error(`Unsupported export format: ${format}. Use csv, tsv, md, or json.`);
|
|
150
148
|
}
|
|
151
149
|
|
|
152
150
|
return normalized;
|
|
@@ -156,7 +154,7 @@ function parseCliArguments(argv) {
|
|
|
156
154
|
const options = {
|
|
157
155
|
help: false,
|
|
158
156
|
version: false,
|
|
159
|
-
|
|
157
|
+
info: false,
|
|
160
158
|
open: false,
|
|
161
159
|
port: undefined,
|
|
162
160
|
databaseList: false,
|
|
@@ -167,6 +165,8 @@ function parseCliArguments(argv) {
|
|
|
167
165
|
tables: false,
|
|
168
166
|
queries: false,
|
|
169
167
|
executeQuery: null,
|
|
168
|
+
rawQuery: null,
|
|
169
|
+
storeName: null,
|
|
170
170
|
showQuery: null,
|
|
171
171
|
showNotes: null,
|
|
172
172
|
exportTarget: null,
|
|
@@ -191,8 +191,8 @@ function parseCliArguments(argv) {
|
|
|
191
191
|
continue;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
if (flag === '--config') {
|
|
195
|
-
options.
|
|
194
|
+
if (flag === '--info' || flag === '--config') {
|
|
195
|
+
options.info = true;
|
|
196
196
|
continue;
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -299,6 +299,20 @@ function parseCliArguments(argv) {
|
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
if (flag === '--query') {
|
|
302
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
303
|
+
options.rawQuery = parsed.value;
|
|
304
|
+
index = parsed.nextIndex;
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (flag === '--store') {
|
|
309
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
310
|
+
options.storeName = parsed.value;
|
|
311
|
+
index = parsed.nextIndex;
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (flag === '--saved-query') {
|
|
302
316
|
const parsed = takeFlagValue(flag, value, argv, index);
|
|
303
317
|
options.showQuery = parsed.value;
|
|
304
318
|
index = parsed.nextIndex;
|
|
@@ -379,18 +393,20 @@ function parseCliArguments(argv) {
|
|
|
379
393
|
function hasDatabaseOperation(options) {
|
|
380
394
|
return Boolean(
|
|
381
395
|
options.pathInfo ||
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
396
|
+
options.sizeInfo ||
|
|
397
|
+
options.lastOpenedInfo ||
|
|
398
|
+
options.tables ||
|
|
399
|
+
options.queries ||
|
|
400
|
+
options.executeQuery ||
|
|
401
|
+
options.rawQuery ||
|
|
402
|
+
options.storeName ||
|
|
403
|
+
options.showQuery ||
|
|
404
|
+
options.showNotes ||
|
|
405
|
+
options.documents ||
|
|
406
|
+
options.documentName ||
|
|
407
|
+
options.documentExport ||
|
|
408
|
+
options.exportTarget ||
|
|
409
|
+
options.tableName,
|
|
394
410
|
);
|
|
395
411
|
}
|
|
396
412
|
|
|
@@ -559,6 +575,22 @@ function executeSavedQuery({ databaseService, conn, queryName }) {
|
|
|
559
575
|
printExecutionResult(result);
|
|
560
576
|
}
|
|
561
577
|
|
|
578
|
+
function executeRawQuery({ databaseService, conn, sql, storeName = null }) {
|
|
579
|
+
const { result, storedQuery } = databaseService.executeRawQuery(conn.id, sql, { storeName });
|
|
580
|
+
|
|
581
|
+
console.log(`\nExecuting raw SQL against: ${conn.label}`);
|
|
582
|
+
console.log('─'.repeat(60));
|
|
583
|
+
printExecutionResult(result);
|
|
584
|
+
|
|
585
|
+
if (result.historyId) {
|
|
586
|
+
console.log(`\nHistory ID: ${result.historyId}`);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (storedQuery) {
|
|
590
|
+
console.log(`Stored query: ${getQueryTitle(storedQuery)}`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
562
594
|
function showSavedQuery({ databaseService, conn, queryName }) {
|
|
563
595
|
const matchingQuery = databaseService.getSavedQuery(conn.id, queryName);
|
|
564
596
|
|
|
@@ -690,28 +722,51 @@ function printTableInfo(tableDetail) {
|
|
|
690
722
|
console.log(`Indexes: ${tableDetail.indexes.length}`);
|
|
691
723
|
tableDetail.indexes.forEach(index => {
|
|
692
724
|
const unique = index.unique ? ' UNIQUE' : '';
|
|
693
|
-
const columns =
|
|
725
|
+
const columns =
|
|
726
|
+
index.columns
|
|
727
|
+
.map(column => column.name)
|
|
728
|
+
.filter(Boolean)
|
|
729
|
+
.join(', ') || 'expression';
|
|
694
730
|
console.log(` - ${index.name}${unique}: ${columns}`);
|
|
695
731
|
});
|
|
696
732
|
}
|
|
697
733
|
}
|
|
698
734
|
|
|
699
|
-
function
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
735
|
+
function formatVersionStatus(versionCheck) {
|
|
736
|
+
if (!versionCheck || versionCheck.status === 'unknown') {
|
|
737
|
+
return `unknown${versionCheck?.error?.message ? ` (${versionCheck.error.message})` : ''}`;
|
|
738
|
+
}
|
|
703
739
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
740
|
+
if (versionCheck.updateAvailable) {
|
|
741
|
+
return `update available (${versionCheck.currentVersion} -> ${versionCheck.latestVersion})`;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (versionCheck.status === 'ahead') {
|
|
745
|
+
return `ahead of npm latest (${versionCheck.currentVersion} > ${versionCheck.latestVersion})`;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
return `current (${versionCheck.currentVersion})`;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
async function printInfo(port, options = {}) {
|
|
752
|
+
const infoService = options.appInfoService ?? buildAppInfo;
|
|
753
|
+
const url = `http://127.0.0.1:${port}`;
|
|
754
|
+
const info = await infoService({ port, url });
|
|
755
|
+
|
|
756
|
+
console.log('SQLite Hub info');
|
|
757
|
+
console.log(`Port: ${info.port}`);
|
|
758
|
+
console.log(`URL: ${info.url}`);
|
|
759
|
+
console.log(`Package: ${info.packageName}`);
|
|
760
|
+
console.log(`App version: ${info.appVersion}`);
|
|
761
|
+
console.log(`SQLite version: ${info.sqliteVersion}`);
|
|
762
|
+
console.log(`Version status: ${formatVersionStatus(info.versionCheck)}`);
|
|
707
763
|
|
|
708
|
-
|
|
709
|
-
console.log(`
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
db.close();
|
|
764
|
+
if (info.versionCheck?.latestVersion) {
|
|
765
|
+
console.log(`Latest version: ${info.versionCheck.latestVersion}`);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
if (info.versionCheck?.releaseUrl) {
|
|
769
|
+
console.log(`Release URL: ${info.versionCheck.releaseUrl}`);
|
|
715
770
|
}
|
|
716
771
|
}
|
|
717
772
|
|
|
@@ -757,8 +812,8 @@ async function main(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
757
812
|
return;
|
|
758
813
|
}
|
|
759
814
|
|
|
760
|
-
if (options.
|
|
761
|
-
|
|
815
|
+
if (options.info) {
|
|
816
|
+
await printInfo(port, dependencies);
|
|
762
817
|
return;
|
|
763
818
|
}
|
|
764
819
|
|
|
@@ -767,6 +822,10 @@ async function main(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
767
822
|
return;
|
|
768
823
|
}
|
|
769
824
|
|
|
825
|
+
if (options.storeName && !options.rawQuery) {
|
|
826
|
+
throw new Error('--store requires --query:"sql".');
|
|
827
|
+
}
|
|
828
|
+
|
|
770
829
|
const databaseService =
|
|
771
830
|
dependencies.databaseService ??
|
|
772
831
|
new DatabaseCommandService({
|
|
@@ -805,7 +864,16 @@ async function main(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
805
864
|
return;
|
|
806
865
|
}
|
|
807
866
|
|
|
808
|
-
if (
|
|
867
|
+
if (
|
|
868
|
+
options.tableName ||
|
|
869
|
+
options.tables ||
|
|
870
|
+
options.queries ||
|
|
871
|
+
options.executeQuery ||
|
|
872
|
+
options.rawQuery ||
|
|
873
|
+
options.showQuery ||
|
|
874
|
+
options.showNotes ||
|
|
875
|
+
options.exportTarget
|
|
876
|
+
) {
|
|
809
877
|
if (options.tableName) {
|
|
810
878
|
if (options.exportTarget) {
|
|
811
879
|
exportTableRowAsJson({
|
|
@@ -840,6 +908,16 @@ async function main(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
840
908
|
return;
|
|
841
909
|
}
|
|
842
910
|
|
|
911
|
+
if (options.rawQuery) {
|
|
912
|
+
executeRawQuery({
|
|
913
|
+
databaseService,
|
|
914
|
+
conn,
|
|
915
|
+
sql: options.rawQuery,
|
|
916
|
+
storeName: options.storeName,
|
|
917
|
+
});
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
|
|
843
921
|
if (options.showQuery) {
|
|
844
922
|
showSavedQuery({ databaseService, conn, queryName: options.showQuery });
|
|
845
923
|
return;
|
|
@@ -897,7 +975,9 @@ if (require.main === module) {
|
|
|
897
975
|
|
|
898
976
|
module.exports = {
|
|
899
977
|
main,
|
|
978
|
+
formatVersionStatus,
|
|
900
979
|
normalizeExportFormat,
|
|
901
980
|
openInDefaultBrowser,
|
|
902
981
|
parseCliArguments,
|
|
982
|
+
printInfo,
|
|
903
983
|
};
|
package/frontend/js/api.js
CHANGED
|
@@ -431,6 +431,10 @@ export function patchSettings(settings) {
|
|
|
431
431
|
});
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
+
export function checkAppVersion() {
|
|
435
|
+
return request("/api/settings/version-check");
|
|
436
|
+
}
|
|
437
|
+
|
|
434
438
|
export function createApiToken(name) {
|
|
435
439
|
return request("/api/settings/api-tokens", {
|
|
436
440
|
method: "POST",
|
|
@@ -448,6 +452,8 @@ const TEXT_EXPORT_EXTENSIONS = {
|
|
|
448
452
|
csv: "csv",
|
|
449
453
|
tsv: "tsv",
|
|
450
454
|
md: "md",
|
|
455
|
+
json: "json",
|
|
456
|
+
parquet: "parquet",
|
|
451
457
|
};
|
|
452
458
|
|
|
453
459
|
function normalizeTextExportFormat(format) {
|