sqlite-hub 1.1.2 → 1.4.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 +106 -73
- package/bin/sqlite-hub.js +176 -2
- package/docs/API.md +122 -0
- package/docs/CLI.md +227 -0
- package/docs/DESIGN_GUIDELINES.md +45 -0
- package/docs/changelog.md +141 -0
- package/docs/shortkeys.md +27 -0
- package/docs/todo.md +16 -0
- package/examples/api/generate-types.js +52 -0
- package/frontend/assets/mockups/backups_1_1920.webp +0 -0
- package/frontend/assets/mockups/backups_2_create_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/backups_3_edit_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/backups_4_restore_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/backups_5_delete_backup_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_1_1920.webp +0 -0
- package/frontend/assets/mockups/charts_2_query_detail_1920.webp +0 -0
- package/frontend/assets/mockups/charts_3_create_query_chart_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_4_edit_query_chart_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_5_delete_query_chart_modal_1920.webp +0 -0
- package/frontend/assets/mockups/charts_6_copy_column_modal_1920.webp +0 -0
- package/frontend/assets/mockups/connections_1_1920.webp +0 -0
- package/frontend/assets/mockups/connections_2_create_connection_modal_1920.webp +0 -0
- package/frontend/assets/mockups/connections_3_open_connection_modal_1920.webp +0 -0
- package/frontend/assets/mockups/data_1_1920.webp +0 -0
- package/frontend/assets/mockups/data_2_roweditor_1920.webp +0 -0
- package/frontend/assets/mockups/data_3_data_export_modal_1920.webp +0 -0
- package/frontend/assets/mockups/documents_1_1920.webp +0 -0
- package/frontend/assets/mockups/documents_2_document_insert_table_modal_1920.webp +0 -0
- package/frontend/assets/mockups/documents_3_document_insert_note_modal_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_queue_1_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_setup_1_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_setup_2_create_media_tagging_tag_table_modal_1920.webp +0 -0
- package/frontend/assets/mockups/media_tagging_setup_3_create_media_tagging_mapping_table_modal_1920.webp +0 -0
- package/frontend/assets/mockups/overview_1_1920.webp +0 -0
- package/frontend/assets/mockups/settings_1_1920.webp +0 -0
- package/frontend/assets/mockups/sql_editor_1_1920.webp +0 -0
- package/frontend/assets/mockups/sql_editor_2_query_detail_1920.webp +0 -0
- package/frontend/assets/mockups/sql_editor_3_query_export_modal_1920.webp +0 -0
- package/frontend/assets/mockups/structure_1_1920.webp +0 -0
- package/frontend/assets/mockups/structure_2_generate_types_modal_1920.webp +0 -0
- package/frontend/assets/mockups/structure_3_generate_types_modal_1920.webp +0 -0
- package/frontend/assets/mockups/table_designer_1_1920.webp +0 -0
- package/frontend/assets/mockups/table_designer_2_table_designer_constraints_modal_1920.webp +0 -0
- package/frontend/js/api.js +18 -0
- package/frontend/js/app.js +209 -13
- package/frontend/js/components/connectionCard.js +1 -1
- package/frontend/js/components/emptyState.js +4 -4
- package/frontend/js/components/generateTypesDropdown.js +33 -0
- package/frontend/js/components/metricCard.js +1 -1
- package/frontend/js/components/modal.js +211 -18
- package/frontend/js/components/pageHeader.js +1 -1
- package/frontend/js/components/queryHistoryDetail.js +3 -3
- package/frontend/js/components/queryHistoryHeader.js +1 -1
- package/frontend/js/components/queryHistoryPanel.js +1 -1
- package/frontend/js/components/queryResults.js +1 -1
- package/frontend/js/components/rowEditorPanel.js +65 -16
- package/frontend/js/components/topNav.js +1 -4
- package/frontend/js/components/workspaceOpenDropdown.js +52 -0
- package/frontend/js/router.js +28 -6
- package/frontend/js/store.js +489 -9
- package/frontend/js/utils/emailPreview.js +28 -0
- package/frontend/js/utils/markdownDocuments.js +17 -1
- package/frontend/js/views/backups.js +556 -36
- package/frontend/js/views/charts.js +9 -9
- package/frontend/js/views/connections.js +2 -2
- package/frontend/js/views/data.js +43 -17
- package/frontend/js/views/documents.js +3 -3
- package/frontend/js/views/editor.js +6 -6
- package/frontend/js/views/mediaTagging.js +7 -5
- package/frontend/js/views/overview.js +3 -3
- package/frontend/js/views/settings.js +4 -3
- package/frontend/js/views/structure.js +27 -10
- package/frontend/js/views/tableDesigner.js +23 -0
- package/frontend/styles/base.css +1 -40
- package/frontend/styles/components.css +114 -232
- package/frontend/styles/structure-graph.css +32 -68
- package/frontend/styles/tailwind.css +8 -4
- package/frontend/styles/tailwind.generated.css +1 -1
- package/frontend/styles/tokens.css +29 -21
- package/frontend/styles/views.css +94 -261
- package/package.json +18 -2
- package/server/routes/backups.js +18 -2
- package/server/routes/externalApi.js +36 -0
- package/server/routes/structure.js +22 -0
- package/server/services/databaseCommandService.js +14 -0
- package/server/services/sqlite/backupDiff.js +914 -0
- package/server/services/sqlite/backupService.js +77 -1
- package/server/services/sqlite/structureService.js +7 -0
- package/server/services/typeGenerationService.js +663 -0
- package/tailwind.config.cjs +0 -1
- package/.github/funding.yml +0 -2
- package/.github/workflows/ci.yml +0 -36
- package/database.sqlite +0 -0
- package/frontend/assets/mockups/charts_1_bars_1200.webp +0 -0
- package/frontend/assets/mockups/charts_2_pie_1200.webp +0 -0
- package/frontend/assets/mockups/charts_3_scatter_plot_1200.webp +0 -0
- package/frontend/assets/mockups/connections_1200.webp +0 -0
- package/frontend/assets/mockups/data_1_1200.webp +0 -0
- package/frontend/assets/mockups/data_2_row_editor_1200.webp +0 -0
- package/frontend/assets/mockups/documents_1200.webp +0 -0
- package/frontend/assets/mockups/media_tagging_1_setup_1200.webp +0 -0
- package/frontend/assets/mockups/media_tagging_2_tagging_queue_1200.webp +0 -0
- package/frontend/assets/mockups/media_tagging_3_media_viewer_1200.webp +0 -0
- package/frontend/assets/mockups/overview_1200.webp +0 -0
- package/frontend/assets/mockups/settings_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_1_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_2_query_details_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_3_export_column_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_4_export_column_as_markdown_1200.webp +0 -0
- package/frontend/assets/mockups/sql_editor_5_export_query_result_1200.webp +0 -0
- package/frontend/assets/mockups/structure_1_1200.webp +0 -0
- package/frontend/assets/mockups/structure_2_inspector_1200.webp +0 -0
- package/frontend/assets/mockups/table_designer_1_1200.webp +0 -0
- package/frontend/assets/mockups/table_designer_2_checks_1200.webp +0 -0
- package/tests/api-token-auth.test.js +0 -279
- package/tests/backup-manager.test.js +0 -140
- package/tests/backups-view.test.js +0 -64
- package/tests/charts-height-preset-storage.test.js +0 -60
- package/tests/charts-route-state.test.js +0 -144
- package/tests/check-constraint-options.test.js +0 -90
- package/tests/cli-args.test.js +0 -113
- package/tests/cli-service-delegation.test.js +0 -140
- package/tests/connection-removal.test.js +0 -52
- package/tests/connections-file-dialog-route.test.js +0 -89
- package/tests/copy-column-modal.test.js +0 -131
- package/tests/database-command-service.test.js +0 -174
- package/tests/database-documents.test.js +0 -85
- package/tests/documents-view.test.js +0 -132
- package/tests/dropdown-button.test.js +0 -75
- package/tests/export-blob.test.js +0 -99
- package/tests/export-filenames.test.js +0 -38
- package/tests/file-path-preview.test.js +0 -165
- package/tests/form-controls.test.js +0 -34
- package/tests/json-preview.test.js +0 -49
- package/tests/local-request-security.test.js +0 -85
- package/tests/markdown-documents.test.js +0 -79
- package/tests/native-file-dialog.test.js +0 -105
- package/tests/query-editor.test.js +0 -28
- package/tests/query-history-detail.test.js +0 -37
- package/tests/query-history-header.test.js +0 -30
- package/tests/query-results-truncation.test.js +0 -20
- package/tests/risky-sql.test.js +0 -30
- package/tests/row-editor-json.test.js +0 -82
- package/tests/row-editor-null-values.test.js +0 -155
- package/tests/row-editor-timestamp-preview.test.js +0 -192
- package/tests/security-paths.test.js +0 -84
- package/tests/settings-api-tokens-route.test.js +0 -97
- package/tests/settings-metadata.test.js +0 -114
- package/tests/settings-view.test.js +0 -107
- package/tests/sql-formatter.test.js +0 -173
- package/tests/sql-highlight.test.js +0 -38
- package/tests/sql-identifier-safety.test.js +0 -171
- package/tests/sql-result-limit.test.js +0 -66
- package/tests/structure-view.test.js +0 -56
- package/tests/table-designer-v2-unique-constraints.test.js +0 -78
- package/tests/table-scroll-state.test.js +0 -70
- package/tests/text-cell-stats.test.js +0 -38
package/README.md
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
# sqlite-hub ⚡️
|
|
2
2
|
|
|
3
|
-
[](./frontend/assets/mockups/overview_1_1920.webp)
|
|
4
4
|
|
|
5
5
|
A focused local-first app for browsing, editing, and querying SQLite databases.
|
|
6
6
|
|
|
7
7
|
SQLite Hub is built for developers and technical users who want a clean SQLite workflow without heavy database clients, cloud layers, or dashboard noise.
|
|
8
8
|
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
### Homebrew
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
brew tap oliverjessner/tap
|
|
15
|
+
brew install sqlite-hub
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### NPM
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g sqlite-hub
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Alternative port
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
sqlite-hub --port:4174
|
|
28
|
+
```
|
|
29
|
+
|
|
9
30
|
## Why SQLite Hub?
|
|
10
31
|
|
|
11
32
|
Many database tools are powerful, but feel oversized when all you want is to inspect a local SQLite file, edit a few rows, and run a query fast.
|
|
@@ -18,6 +39,7 @@ SQLite Hub keeps that workflow sharp:
|
|
|
18
39
|
- inspect database health, storage metrics, and schema connectivity from one overview
|
|
19
40
|
- filter, sort, page through, and export table data
|
|
20
41
|
- inspect schema, structure, and relationships
|
|
42
|
+
- generate TypeScript, Rust, Kotlin, or Swift types from table schemas
|
|
21
43
|
- edit records in place with typed value previews and an SQL diff preview before saving
|
|
22
44
|
- export tables and query results as CSV, TSV, Markdown, JSON, Parquet, or duplicate them as a table
|
|
23
45
|
- copy result columns with formatting, headers, first-10 previews, TXT export, and Markdown todo export
|
|
@@ -32,45 +54,40 @@ SQLite Hub keeps that workflow sharp:
|
|
|
32
54
|
|
|
33
55
|
## Features
|
|
34
56
|
|
|
35
|
-
###
|
|
36
|
-
|
|
37
|
-
[](./frontend/assets/mockups/connections_1200.webp)
|
|
38
|
-
|
|
39
|
-
Open an existing SQLite file with a native file picker or create a new database with a native save dialog from the Connections view. Manual absolute-path entry remains available as a fallback for both actions.
|
|
40
|
-
|
|
41
|
-
Recent connections show file size, modification time, last-opened time, and access mode. Connections can be activated, relabeled, moved to another path, opened read-only, assigned a PNG/JPG/WEBP icon, reset to the default icon, or removed from the recent-connections registry without deleting the database file.
|
|
57
|
+
### Structure view
|
|
42
58
|
|
|
43
|
-
|
|
59
|
+
[](./frontend/assets/mockups/structure_1_1920.webp)
|
|
44
60
|
|
|
45
|
-
The
|
|
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.
|
|
46
62
|
|
|
47
|
-
|
|
48
|
-
- largest tables by row count and estimated size
|
|
49
|
-
- database path, modification time, SQLite version, page size, freelist count, and encoding
|
|
50
|
-
- schema-map statistics for foreign-key links, connected clusters, and isolated tables
|
|
51
|
-
- integrity and quick-check results, access mode, user version, and schema version
|
|
52
|
-
- shortcuts to the SQL Editor, Structure view, and the database location in Finder
|
|
53
|
-
|
|
54
|
-
### Structure view
|
|
63
|
+
### Generate Types
|
|
55
64
|
|
|
56
65
|
<p>
|
|
57
|
-
<a href="./frontend/assets/mockups/
|
|
58
|
-
<a href="./frontend/assets/mockups/
|
|
66
|
+
<a href="./frontend/assets/mockups/structure_2_generate_types_modal_1920.webp"><img src="./frontend/assets/mockups/structure_2_generate_types_modal_1920.webp" alt="SQLite Hub generate types for selected table" width="49%"></a>
|
|
67
|
+
<a href="./frontend/assets/mockups/structure_3_generate_types_modal_1920.webp"><img src="./frontend/assets/mockups/structure_3_generate_types_modal_1920.webp" alt="SQLite Hub generate types for all tables" width="49%"></a>
|
|
59
68
|
</p>
|
|
60
69
|
|
|
61
|
-
|
|
70
|
+
Generate application types directly from the Structure toolbar for the selected table or for every table in the database. The `Generate Types` dropdown lets you choose `Selected table` or `All tables`; the preview modal supports TypeScript, Rust, Kotlin, and Swift. When all tables are selected, SQLite Hub creates one generated file per table.
|
|
71
|
+
|
|
72
|
+
Type generation uses SQLite's declared column types plus schema constraints such as primary keys, foreign keys, `NOT NULL`, generated columns, defaults, and simple `CHECK (... IN (...))` value sets.
|
|
73
|
+
|
|
74
|
+
The same generator is available through the [CLI](./docs/CLI.md) and [local API](./docs/API.md) for automation.
|
|
62
75
|
|
|
63
76
|
### Data browser
|
|
64
77
|
|
|
65
|
-
[](./frontend/assets/mockups/data_1_1920.webp)
|
|
66
79
|
|
|
67
|
-
Scan rows, sort columns, move through local data quickly, and export full tables as CSV, TSV, Markdown, JSON, or Parquet.
|
|
80
|
+
Scan rows, sort columns, move through local data quickly, and export full tables as CSV, TSV, Markdown, JSON, or Parquet.
|
|
81
|
+
|
|
82
|
+
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
83
|
|
|
69
84
|
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
85
|
|
|
86
|
+
[](./frontend/assets/mockups/data_3_data_export_modal_1920.webp)
|
|
87
|
+
|
|
71
88
|
### Row editing
|
|
72
89
|
|
|
73
|
-
[](./frontend/assets/mockups/data_2_roweditor_1920.webp)
|
|
74
91
|
|
|
75
92
|
Open one record, edit it in place, preview the generated SQL and changed values, then commit or delete the row with confirmation. SQLite Hub only enables row edits when it can target a stable primary-key or rowid identity safely.
|
|
76
93
|
|
|
@@ -87,40 +104,37 @@ The Row Editor adds contextual previews without changing the stored raw value:
|
|
|
87
104
|
|
|
88
105
|
### SQL editor
|
|
89
106
|
|
|
90
|
-
[](./frontend/assets/mockups/sql_editor_1_1920.webp)
|
|
91
108
|
|
|
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.
|
|
109
|
+
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.
|
|
93
110
|
|
|
94
|
-
|
|
111
|
+
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.
|
|
95
112
|
|
|
96
|
-
[](./frontend/assets/mockups/sql_editor_3_query_export_modal_1920.webp)
|
|
97
114
|
|
|
98
115
|
Result column menus include copy actions for a full column, a column with header, or the first 10 values. The same modal can preview the output, copy it, export it as TXT, or turn a column into Markdown todo items.
|
|
99
116
|
|
|
100
|
-
<p>
|
|
101
|
-
<a href="./frontend/assets/mockups/sql_editor_3_export_column_1200.webp"><img src="./frontend/assets/mockups/sql_editor_3_export_column_1200.webp" alt="SQLite Hub copy column dialog" width="49%"></a>
|
|
102
|
-
<a href="./frontend/assets/mockups/sql_editor_4_export_column_as_markdown_1200.webp"><img src="./frontend/assets/mockups/sql_editor_4_export_column_as_markdown_1200.webp" alt="SQLite Hub Markdown todo export" width="49%"></a>
|
|
103
|
-
</p>
|
|
104
|
-
|
|
105
117
|
The bottom panel keeps separate tabs for:
|
|
106
118
|
|
|
107
119
|
- Results
|
|
108
120
|
- Performance, including execution time, statement count, returned rows, affected rows, and serialized result memory size
|
|
109
121
|
- Messages, including the executed query and statement updates/errors
|
|
110
122
|
|
|
111
|
-
Potentially destructive statements are tracked in query history, and SQLite Hub keeps the active result tab instead of forcing you back to Results after every execution.
|
|
123
|
+
Potentially destructive statements are tracked in query history, and SQLite Hub keeps the active result tab instead of forcing you back to Results after every execution.
|
|
124
|
+
|
|
125
|
+
Multi-statement SQL is reported statement by statement, including returned rows, affected rows, truncation warnings, executed SQL, errors, timing, and serialized result size.
|
|
112
126
|
|
|
113
127
|
### Query history
|
|
114
128
|
|
|
115
|
-
[](./frontend/assets/mockups/sql_editor_2_query_detail_1920.webp)
|
|
116
130
|
|
|
117
131
|
SQLite Hub stores query history per database. You can browse recent and saved tabs, search SQL, titles, and notes, assign titles and notes, mark useful queries as saved, delete history entries, load older entries, re-run previous queries, reopen them in the editor, and execute saved queries from the CLI.
|
|
118
132
|
|
|
119
133
|
### Documents
|
|
120
134
|
|
|
121
|
-
[](./frontend/assets/mockups/documents_1_1920.webp)
|
|
122
136
|
|
|
123
|
-
Documents are local Markdown notes scoped to the active database. SQLite Hub creates a document folder per database
|
|
137
|
+
Documents are local Markdown notes scoped to the active database. SQLite Hub creates a document folder per database. You can import `.md` files, export the current document as Markdown.
|
|
124
138
|
|
|
125
139
|
The preview supports regular Markdown, ordered and unordered lists, tables, code blocks, links, and clickable task-list checkboxes. Documents can also pull context from saved SQL Editor queries:
|
|
126
140
|
|
|
@@ -128,56 +142,64 @@ The preview supports regular Markdown, ordered and unordered lists, tables, code
|
|
|
128
142
|
- Insert Note opens saved queries that have notes and inserts the selected note directly into the document.
|
|
129
143
|
- Markdown Todo column exports from query results can create a new document without embedding the original SQL query.
|
|
130
144
|
|
|
145
|
+
<p>
|
|
146
|
+
<a href="./frontend/assets/mockups/documents_2_document_insert_table_modal_1920.webp"><img src="./frontend/assets/mockups/documents_2_document_insert_table_modal_1920.webp" alt="SQLite Hub insert saved query table into a document" width="49%"></a>
|
|
147
|
+
<a href="./frontend/assets/mockups/documents_3_document_insert_note_modal_1920.webp"><img src="./frontend/assets/mockups/documents_3_document_insert_note_modal_1920.webp" alt="SQLite Hub insert saved query note into a document" width="49%"></a>
|
|
148
|
+
</p>
|
|
149
|
+
|
|
131
150
|
### Charts
|
|
132
151
|
|
|
133
|
-
[](./frontend/assets/mockups/charts_1_1920.webp)
|
|
134
153
|
|
|
135
154
|
Create bar, line, pie/donut, and scatter charts from chartable `SELECT` query-history entries. Charts can be saved per query, edited, deleted, resized, reopened later, rendered from live query results, and exported as PNG. Chart configuration supports compatible column selection, sorting, labels, legends, line smoothing, scatter series, and optional scatter point sizing.
|
|
136
155
|
|
|
137
156
|
<p>
|
|
138
|
-
<a href="./frontend/assets/mockups/
|
|
139
|
-
<a href="./frontend/assets/mockups/
|
|
157
|
+
<a href="./frontend/assets/mockups/charts_2_query_detail_1920.webp"><img src="./frontend/assets/mockups/charts_2_query_detail_1920.webp" alt="SQLite Hub chart query detail drawer" width="49%"></a>
|
|
158
|
+
<a href="./frontend/assets/mockups/charts_3_create_query_chart_modal_1920.webp"><img src="./frontend/assets/mockups/charts_3_create_query_chart_modal_1920.webp" alt="SQLite Hub create chart modal" width="49%"></a>
|
|
159
|
+
</p>
|
|
160
|
+
|
|
161
|
+
<p>
|
|
162
|
+
<a href="./frontend/assets/mockups/charts_4_edit_query_chart_modal_1920.webp"><img src="./frontend/assets/mockups/charts_4_edit_query_chart_modal_1920.webp" alt="SQLite Hub edit chart modal" width="49%"></a>
|
|
163
|
+
<a href="./frontend/assets/mockups/charts_5_delete_query_chart_modal_1920.webp"><img src="./frontend/assets/mockups/charts_5_delete_query_chart_modal_1920.webp" alt="SQLite Hub delete chart modal" width="49%"></a>
|
|
140
164
|
</p>
|
|
141
165
|
|
|
166
|
+
[](./frontend/assets/mockups/charts_6_copy_column_modal_1920.webp)
|
|
167
|
+
|
|
142
168
|
### Table Designer
|
|
143
169
|
|
|
144
|
-
[](./frontend/assets/mockups/table_designer_1_1920.webp)
|
|
145
171
|
|
|
146
172
|
Create and edit SQLite tables from the UI. The Table Designer includes a searchable table list, validation and migration warnings, and controls for column names, SQLite types, `NOT NULL`, `UNIQUE`, primary keys, SQL defaults, foreign-key tables/columns, and check constraints. Existing composite unique constraints are surfaced as schema metadata.
|
|
147
173
|
|
|
148
174
|
CSV files can seed a new table draft and optionally fill the created table with imported rows. Every change produces a copyable live SQL preview that can be hidden or shown before the schema operation is applied.
|
|
149
175
|
|
|
150
|
-
[](./frontend/assets/mockups/table_designer_2_table_designer_constraints_modal_1920.webp)
|
|
151
177
|
|
|
152
178
|
### Media Tagging
|
|
153
179
|
|
|
154
|
-
[](./frontend/assets/mockups/media_tagging_setup_1_1920.webp)
|
|
155
181
|
|
|
156
182
|
Configure a media table, path/status columns, tag table, mapping table, and the SQL queries that drive tagged and untagged queues. SQLite Hub can create the default tag and mapping tables, validate the setup, reset default queries, and preview image, video, and audio assets from paths scoped to the active database directory.
|
|
157
183
|
|
|
158
|
-
The queue supports tag search, tag creation/removal, parent tags, copying tags from the previous item, applying selected tags, skipping items, resetting skipped items, rotating visual media, hiding/showing media details, and opening the current row in Data or Structure. `Shift + Enter` applies the selected tags and advances to the next item.
|
|
159
|
-
|
|
160
184
|
<p>
|
|
161
|
-
<a href="./frontend/assets/mockups/
|
|
162
|
-
<a href="./frontend/assets/mockups/
|
|
185
|
+
<a href="./frontend/assets/mockups/media_tagging_setup_2_create_media_tagging_tag_table_modal_1920.webp"><img src="./frontend/assets/mockups/media_tagging_setup_2_create_media_tagging_tag_table_modal_1920.webp" alt="SQLite Hub create media tagging tag table modal" width="49%"></a>
|
|
186
|
+
<a href="./frontend/assets/mockups/media_tagging_setup_3_create_media_tagging_mapping_table_modal_1920.webp"><img src="./frontend/assets/mockups/media_tagging_setup_3_create_media_tagging_mapping_table_modal_1920.webp" alt="SQLite Hub create media tagging mapping table modal" width="49%"></a>
|
|
163
187
|
</p>
|
|
164
188
|
|
|
165
|
-
|
|
189
|
+
The queue supports tag search, tag creation/removal, parent tags, copying tags from the previous item, applying selected tags, skipping items, resetting skipped items, rotating visual media, hiding/showing media details, and opening the current row in Data or Structure. `Shift + Enter` applies the selected tags and advances to the next item.
|
|
166
190
|
|
|
167
|
-
SQLite Hub
|
|
191
|
+
[](./frontend/assets/mockups/media_tagging_queue_1_1920.webp)
|
|
168
192
|
|
|
169
193
|
### Settings
|
|
170
194
|
|
|
171
|
-
[](./frontend/assets/mockups/settings_1_1920.webp)
|
|
174
196
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
The active database footer in the sidebar opens a quick-pick panel with the five most recent databases, so you can switch databases without going back to the Connections view.
|
|
197
|
+
The Settings view reports the installed SQLite Hub version and the actual SQLite runtime version used to execute queries.
|
|
178
198
|
|
|
179
199
|
### Backup Manager
|
|
180
200
|
|
|
201
|
+
[](./frontend/assets/mockups/backups_1_1920.webp)
|
|
202
|
+
|
|
181
203
|
Create verified local backups of the active SQLite database, review backup metadata, edit backup notes, download backup files, restore verified backups, and delete managed backups from the Backups view. SQLite Hub stores backup files under its local app-state backup directory by connection id and keeps a `manifest.json` beside each database's backup files. Each backup is created through SQLite's backup API, hashed with SHA-256, and verified with `PRAGMA quick_check` before it is marked as verified.
|
|
182
204
|
|
|
183
205
|
SQLite Hub also proposes a safety backup before operations that can be hard to undo:
|
|
@@ -189,41 +211,52 @@ SQLite Hub also proposes a safety backup before operations that can be hard to u
|
|
|
189
211
|
|
|
190
212
|
The safety dialog lets you create the backup and continue, continue without creating one, or cancel the operation.
|
|
191
213
|
|
|
192
|
-
|
|
214
|
+
<p>
|
|
215
|
+
<a href="./frontend/assets/mockups/backups_2_create_backup_modal_1920.webp"><img src="./frontend/assets/mockups/backups_2_create_backup_modal_1920.webp" alt="SQLite Hub create backup modal" width="49%"></a>
|
|
216
|
+
<a href="./frontend/assets/mockups/backups_3_edit_backup_modal_1920.webp"><img src="./frontend/assets/mockups/backups_3_edit_backup_modal_1920.webp" alt="SQLite Hub edit backup modal" width="49%"></a>
|
|
217
|
+
</p>
|
|
193
218
|
|
|
194
|
-
|
|
219
|
+
<p>
|
|
220
|
+
<a href="./frontend/assets/mockups/backups_4_restore_backup_modal_1920.webp"><img src="./frontend/assets/mockups/backups_4_restore_backup_modal_1920.webp" alt="SQLite Hub restore backup modal" width="49%"></a>
|
|
221
|
+
<a href="./frontend/assets/mockups/backups_5_delete_backup_modal_1920.webp"><img src="./frontend/assets/mockups/backups_5_delete_backup_modal_1920.webp" alt="SQLite Hub delete backup modal" width="49%"></a>
|
|
222
|
+
</p>
|
|
195
223
|
|
|
196
|
-
|
|
224
|
+
### Overview
|
|
197
225
|
|
|
198
|
-
|
|
226
|
+
The database overview combines operational and schema information for the active database:
|
|
199
227
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
228
|
+
- file size, page count, table/view counts, index/trigger counts, journal mode, and foreign-key status
|
|
229
|
+
- largest tables by row count and estimated size
|
|
230
|
+
- database path, modification time, SQLite version, page size, freelist count, and encoding
|
|
231
|
+
- schema-map statistics for foreign-key links, connected clusters, and isolated tables
|
|
232
|
+
- integrity and quick-check results, access mode, user version, and schema version
|
|
233
|
+
- shortcuts to the SQL Editor, Structure view, and the database location in Finder
|
|
204
234
|
|
|
205
|
-
###
|
|
235
|
+
### Connections
|
|
206
236
|
|
|
207
|
-
|
|
208
|
-
npm install -g sqlite-hub
|
|
209
|
-
```
|
|
237
|
+
[](./frontend/assets/mockups/connections_1_1920.webp)
|
|
210
238
|
|
|
211
|
-
|
|
239
|
+
Recent connections show file size, modification time, last-opened time, and access mode. Connections can be activated, relabeled, moved to another path, opened read-only, assigned a PNG/JPG/WEBP icon, reset to the default icon, or removed from the recent-connections registry without deleting the database file.
|
|
212
240
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
241
|
+
<p>
|
|
242
|
+
<a href="./frontend/assets/mockups/connections_2_create_connection_modal_1920.webp"><img src="./frontend/assets/mockups/connections_2_create_connection_modal_1920.webp" alt="SQLite Hub create connection modal" width="49%"></a>
|
|
243
|
+
<a href="./frontend/assets/mockups/connections_3_open_connection_modal_1920.webp"><img src="./frontend/assets/mockups/connections_3_open_connection_modal_1920.webp" alt="SQLite Hub open connection modal" width="49%"></a>
|
|
244
|
+
</p>
|
|
245
|
+
|
|
246
|
+
### Local-first
|
|
247
|
+
|
|
248
|
+
Built around local SQLite files, not hosted dashboards or team complexity. The server binds explicitly to the IPv4 loopback interface, and API middleware rejects foreign hosts and cross-origin mutations while still allowing same-origin browser and local CLI requests.
|
|
216
249
|
|
|
217
250
|
## CLI
|
|
218
251
|
|
|
219
252
|
SQLite Hub ships with a built-in CLI for starting the app, inspecting imported
|
|
220
253
|
databases, executing raw or saved SQL, exporting query results, exporting single
|
|
221
|
-
rows as JSON, and working with Markdown documents. See the
|
|
254
|
+
rows as JSON, generating schema types, and working with Markdown documents. See the
|
|
222
255
|
[CLI documentation](./docs/CLI.md) for commands, flags, and examples.
|
|
223
256
|
|
|
224
257
|
## API
|
|
225
258
|
|
|
226
|
-
SQLite Hub also provides a local JSON API for app info, database metadata, tables, saved queries, exports, and
|
|
259
|
+
SQLite Hub also provides a local JSON API for app info, database metadata, tables, saved queries, exports, documents, and schema type generation. `/api/v1/info` returns the same app/version status as `sqlite-hub --info`; database data is protected by database-specific API itokens created in Settings. See the [API documentation](./docs/API.md) for authentication, endpoints, and examples.
|
|
227
260
|
|
|
228
261
|
## Changelog
|
|
229
262
|
|
package/bin/sqlite-hub.js
CHANGED
|
@@ -5,6 +5,7 @@ const path = require('node:path');
|
|
|
5
5
|
const { spawn } = require('node:child_process');
|
|
6
6
|
const { DatabaseCommandService, getQueryTitle } = require('../server/services/databaseCommandService');
|
|
7
7
|
const { buildAppInfo } = require('../server/services/appInfoService');
|
|
8
|
+
const { FILE_EXTENSIONS } = require('../server/services/typeGenerationService');
|
|
8
9
|
|
|
9
10
|
const DEFAULT_PORT = 4173;
|
|
10
11
|
const EXPORT_FORMATS = new Set(['csv', 'tsv', 'md', 'json']);
|
|
@@ -27,6 +28,7 @@ Usage:
|
|
|
27
28
|
sqlite-hub --database:"name" --documents:"Document Name" --export
|
|
28
29
|
sqlite-hub --database:"name" --table:"table_name"
|
|
29
30
|
sqlite-hub --database:"name" --table:"table_name" --export:"primary-key"
|
|
31
|
+
sqlite-hub --database:"name" --table:"table_name" --types:typescript
|
|
30
32
|
|
|
31
33
|
Options:
|
|
32
34
|
--help, -h Show this help text.
|
|
@@ -53,6 +55,21 @@ Options:
|
|
|
53
55
|
--documents:"name" --export Export a document as a Markdown file.
|
|
54
56
|
--table:"table" Print table metadata.
|
|
55
57
|
--table:"table" --export:"pk" Export one row as JSON by primary key or rowid.
|
|
58
|
+
--types:typescript|ts|rust|rs|kotlin|kt|swift
|
|
59
|
+
Generate application types for --table.
|
|
60
|
+
--type-name:"name" Override generated type name.
|
|
61
|
+
--naming:preserve|camel|pascal|snake
|
|
62
|
+
Select generated property naming.
|
|
63
|
+
--nullable:native|optional Select nullable handling. Optional is TypeScript only.
|
|
64
|
+
--comments Include schema comments.
|
|
65
|
+
--defaults-as-comments Include default values in comments.
|
|
66
|
+
--json-type:unknown|record|json-value
|
|
67
|
+
Select TypeScript JSON mapping.
|
|
68
|
+
--include-generated Include generated columns.
|
|
69
|
+
--include-hidden Include hidden columns.
|
|
70
|
+
--output:"file" Write generated types to a file.
|
|
71
|
+
--json Print generated type result as JSON.
|
|
72
|
+
--force Overwrite --output file if it exists.
|
|
56
73
|
`);
|
|
57
74
|
}
|
|
58
75
|
|
|
@@ -175,6 +192,18 @@ function parseCliArguments(argv) {
|
|
|
175
192
|
documentName: null,
|
|
176
193
|
documentExport: false,
|
|
177
194
|
tableName: null,
|
|
195
|
+
typesTarget: null,
|
|
196
|
+
typeName: null,
|
|
197
|
+
naming: null,
|
|
198
|
+
nullableMode: null,
|
|
199
|
+
includeComments: false,
|
|
200
|
+
includeDefaultsAsComments: false,
|
|
201
|
+
includeGeneratedColumns: undefined,
|
|
202
|
+
includeHiddenColumns: false,
|
|
203
|
+
jsonType: null,
|
|
204
|
+
outputPath: null,
|
|
205
|
+
jsonOutput: false,
|
|
206
|
+
force: false,
|
|
178
207
|
};
|
|
179
208
|
|
|
180
209
|
for (let index = 0; index < argv.length; index += 1) {
|
|
@@ -384,6 +413,78 @@ function parseCliArguments(argv) {
|
|
|
384
413
|
continue;
|
|
385
414
|
}
|
|
386
415
|
|
|
416
|
+
if (flag === '--types') {
|
|
417
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
418
|
+
options.typesTarget = parsed.value;
|
|
419
|
+
index = parsed.nextIndex;
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (flag === '--type-name') {
|
|
424
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
425
|
+
options.typeName = parsed.value;
|
|
426
|
+
index = parsed.nextIndex;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (flag === '--naming') {
|
|
431
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
432
|
+
options.naming = parsed.value;
|
|
433
|
+
index = parsed.nextIndex;
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (flag === '--nullable') {
|
|
438
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
439
|
+
options.nullableMode = parsed.value;
|
|
440
|
+
index = parsed.nextIndex;
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (flag === '--comments') {
|
|
445
|
+
options.includeComments = true;
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (flag === '--defaults-as-comments') {
|
|
450
|
+
options.includeDefaultsAsComments = true;
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (flag === '--include-generated') {
|
|
455
|
+
options.includeGeneratedColumns = true;
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (flag === '--include-hidden') {
|
|
460
|
+
options.includeHiddenColumns = true;
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (flag === '--json-type') {
|
|
465
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
466
|
+
options.jsonType = parsed.value;
|
|
467
|
+
index = parsed.nextIndex;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (flag === '--output') {
|
|
472
|
+
const parsed = takeFlagValue(flag, value, argv, index);
|
|
473
|
+
options.outputPath = parsed.value;
|
|
474
|
+
index = parsed.nextIndex;
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (flag === '--json') {
|
|
479
|
+
options.jsonOutput = true;
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (flag === '--force') {
|
|
484
|
+
options.force = true;
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
|
|
387
488
|
throw new Error(`Unknown argument: ${argument}`);
|
|
388
489
|
}
|
|
389
490
|
|
|
@@ -406,7 +507,8 @@ function hasDatabaseOperation(options) {
|
|
|
406
507
|
options.documentName ||
|
|
407
508
|
options.documentExport ||
|
|
408
509
|
options.exportTarget ||
|
|
409
|
-
options.tableName
|
|
510
|
+
options.tableName ||
|
|
511
|
+
options.typesTarget,
|
|
410
512
|
);
|
|
411
513
|
}
|
|
412
514
|
|
|
@@ -626,6 +728,67 @@ function exportSavedQuery({ databaseService, conn, queryName, format }) {
|
|
|
626
728
|
console.log(`File: ${outputPath}`);
|
|
627
729
|
}
|
|
628
730
|
|
|
731
|
+
function buildTypeOptions(options) {
|
|
732
|
+
const typeOptions = {};
|
|
733
|
+
|
|
734
|
+
if (options.typeName) typeOptions.typeName = options.typeName;
|
|
735
|
+
if (options.naming) typeOptions.propertyNaming = options.naming;
|
|
736
|
+
if (options.nullableMode) typeOptions.nullableMode = options.nullableMode;
|
|
737
|
+
if (options.includeComments) typeOptions.includeComments = true;
|
|
738
|
+
if (options.includeDefaultsAsComments) typeOptions.includeDefaultsAsComments = true;
|
|
739
|
+
if (options.includeGeneratedColumns !== undefined) {
|
|
740
|
+
typeOptions.includeGeneratedColumns = options.includeGeneratedColumns;
|
|
741
|
+
}
|
|
742
|
+
if (options.includeHiddenColumns) typeOptions.includeHiddenColumns = true;
|
|
743
|
+
if (options.jsonType) typeOptions.jsonType = options.jsonType;
|
|
744
|
+
|
|
745
|
+
return typeOptions;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function generateTypes({ databaseService, conn, tableName, options }) {
|
|
749
|
+
if (!tableName) {
|
|
750
|
+
throw new Error('--types requires --database and --table.');
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
if (options.jsonOutput && options.outputPath) {
|
|
754
|
+
throw new Error('--json cannot be combined with --output.');
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
const result = databaseService.generateTableTypes(
|
|
758
|
+
conn.id,
|
|
759
|
+
tableName,
|
|
760
|
+
options.typesTarget,
|
|
761
|
+
buildTypeOptions(options)
|
|
762
|
+
);
|
|
763
|
+
|
|
764
|
+
if (options.jsonOutput) {
|
|
765
|
+
console.log(JSON.stringify(result, null, 2));
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
if (options.outputPath) {
|
|
770
|
+
const outputPath = path.resolve(process.cwd(), options.outputPath);
|
|
771
|
+
const expectedExtension = FILE_EXTENSIONS[result.target];
|
|
772
|
+
|
|
773
|
+
if (path.extname(outputPath) !== expectedExtension) {
|
|
774
|
+
throw new Error(`Output file for ${result.target} must use ${expectedExtension}.`);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (!options.force && fs.existsSync(outputPath)) {
|
|
778
|
+
throw new Error(`Output file already exists: ${outputPath}`);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
782
|
+
fs.writeFileSync(outputPath, result.code, 'utf8');
|
|
783
|
+
result.warnings.forEach(warning => console.error(`Warning: ${warning}`));
|
|
784
|
+
console.error(`Generated ${result.target} types: ${outputPath}`);
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
result.warnings.forEach(warning => console.error(`Warning: ${warning}`));
|
|
789
|
+
process.stdout.write(`${result.code}\n`);
|
|
790
|
+
}
|
|
791
|
+
|
|
629
792
|
function listDocuments(databaseService, conn) {
|
|
630
793
|
const documents = databaseService.listDocuments(conn.id);
|
|
631
794
|
|
|
@@ -877,9 +1040,20 @@ async function main(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
877
1040
|
options.rawQuery ||
|
|
878
1041
|
options.showQuery ||
|
|
879
1042
|
options.showNotes ||
|
|
880
|
-
options.exportTarget
|
|
1043
|
+
options.exportTarget ||
|
|
1044
|
+
options.typesTarget
|
|
881
1045
|
) {
|
|
882
1046
|
if (options.tableName) {
|
|
1047
|
+
if (options.typesTarget) {
|
|
1048
|
+
generateTypes({
|
|
1049
|
+
databaseService,
|
|
1050
|
+
conn,
|
|
1051
|
+
tableName: options.tableName,
|
|
1052
|
+
options,
|
|
1053
|
+
});
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
883
1057
|
if (options.exportTarget) {
|
|
884
1058
|
exportTableRowAsJson({
|
|
885
1059
|
databaseService,
|