sqlite-hub 0.4.0 → 0.6.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 +2 -2
- 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_querydetail.png +0 -0
- package/frontend/assets/mockups/structure.png +0 -0
- package/frontend/assets/mockups/structure_inspector.png +0 -0
- package/frontend/js/api.js +114 -5
- package/frontend/js/app.js +368 -18
- package/frontend/js/components/bottomTabs.js +1 -1
- package/frontend/js/components/dataGrid.js +3 -3
- package/frontend/js/components/queryEditor.js +33 -55
- package/frontend/js/components/queryHistoryDetail.js +263 -0
- package/frontend/js/components/queryHistoryPanel.js +228 -0
- package/frontend/js/components/queryResults.js +32 -46
- package/frontend/js/components/rowEditorPanel.js +73 -14
- package/frontend/js/components/sidebar.js +1 -0
- package/frontend/js/components/tableDesignerEditor.js +356 -0
- package/frontend/js/components/tableDesignerSidebar.js +126 -0
- package/frontend/js/components/tableDesignerSqlPreview.js +40 -0
- package/frontend/js/router.js +10 -0
- package/frontend/js/store.js +841 -22
- package/frontend/js/utils/format.js +23 -0
- package/frontend/js/utils/tableDesigner.js +1192 -0
- package/frontend/js/views/data.js +273 -250
- package/frontend/js/views/editor.js +34 -10
- package/frontend/js/views/overview.js +15 -0
- package/frontend/js/views/tableDesigner.js +37 -0
- package/frontend/styles/base.css +87 -73
- package/frontend/styles/components.css +841 -188
- package/frontend/styles/views.css +40 -0
- package/package.json +1 -1
- package/server/routes/data.js +2 -0
- package/server/routes/export.js +4 -1
- package/server/routes/overview.js +12 -0
- package/server/routes/sql.js +163 -5
- package/server/routes/tableDesigner.js +60 -0
- package/server/server.js +5 -1
- package/server/services/sqlite/dataBrowserService.js +4 -16
- package/server/services/sqlite/exportService.js +4 -16
- package/server/services/sqlite/overviewService.js +34 -0
- package/server/services/sqlite/sqlExecutor.js +83 -63
- 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/sqlite/tableSort.js +63 -0
- package/server/services/storage/appStateStore.js +674 -1
- package/server/services/storage/queryHistoryUtils.js +169 -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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { renderBottomTabs } from "../components/bottomTabs.js";
|
|
2
2
|
import { renderQueryEditor } from "../components/queryEditor.js";
|
|
3
|
+
import { renderQueryHistoryDetail } from "../components/queryHistoryDetail.js";
|
|
4
|
+
import { renderQueryHistoryPanel } from "../components/queryHistoryPanel.js";
|
|
3
5
|
import { renderRowEditorPanel } from "../components/rowEditorPanel.js";
|
|
4
6
|
import { renderQueryResultsPane } from "../components/queryResults.js";
|
|
5
7
|
import { getCurrentConnection, getQueryMessages, getQueryPerformance } from "../store.js";
|
|
@@ -216,17 +218,17 @@ function renderResultsSurface(state, isResultsRoute) {
|
|
|
216
218
|
|
|
217
219
|
content = state.connections.active
|
|
218
220
|
? renderQueryResultsPane(state.editor.result, {
|
|
219
|
-
exporting: state.editor.exportLoading,
|
|
220
221
|
selectedRowIndex: state.editor.selectedRowIndex,
|
|
221
222
|
editable: editingState.enabled,
|
|
222
|
-
|
|
223
|
+
sortColumn: state.editor.resultSortColumn,
|
|
224
|
+
sortDirection: state.editor.resultSortDirection,
|
|
223
225
|
})
|
|
224
226
|
: renderMissingDatabase();
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
return `
|
|
228
230
|
<div class="flex h-full min-h-0 flex-col border-t border-outline-variant/10 bg-surface-container-lowest">
|
|
229
|
-
${renderBottomTabs(activeTab, counts)}
|
|
231
|
+
${renderBottomTabs(state.editor.activeTab, counts)}
|
|
230
232
|
<div class="min-h-0 flex-1">${content}</div>
|
|
231
233
|
</div>
|
|
232
234
|
`;
|
|
@@ -234,13 +236,13 @@ function renderResultsSurface(state, isResultsRoute) {
|
|
|
234
236
|
|
|
235
237
|
export function renderEditorView(state, { isResultsRoute = false } = {}) {
|
|
236
238
|
const connection = getCurrentConnection(state);
|
|
237
|
-
const editorSectionClass =
|
|
238
|
-
const resultsSectionClass =
|
|
239
|
+
const editorSectionClass = "min-h-[27.5%]";
|
|
240
|
+
const resultsSectionClass = "flex-1";
|
|
239
241
|
|
|
240
242
|
return {
|
|
241
243
|
main: `
|
|
242
|
-
<section class="view-surface flex h-full min-h-0 flex-col overflow-hidden">
|
|
243
|
-
<div class="flex h-
|
|
244
|
+
<section class="view-surface flex h-full min-h-0 flex-col overflow-hidden xl:flex-row">
|
|
245
|
+
<div class="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
|
244
246
|
<section class="${editorSectionClass} flex min-h-0 flex-col ${
|
|
245
247
|
isResultsRoute ? "border-b-4 border-background" : ""
|
|
246
248
|
}">
|
|
@@ -248,17 +250,39 @@ export function renderEditorView(state, { isResultsRoute = false } = {}) {
|
|
|
248
250
|
query: state.editor.sqlText,
|
|
249
251
|
executing: state.editor.executing,
|
|
250
252
|
exporting: state.editor.exportLoading,
|
|
251
|
-
history: state.editor.history,
|
|
252
253
|
historyLoading: state.editor.historyLoading,
|
|
254
|
+
historyTotal: state.editor.historyTotal,
|
|
253
255
|
title: connection?.label ?? "SQLite Query Workspace",
|
|
254
256
|
})}
|
|
255
257
|
</section>
|
|
256
|
-
<section class="${resultsSectionClass} flex min-h-0 flex-col overflow-hidden">
|
|
258
|
+
<section class="${resultsSectionClass} flex min-h-0 min-w-0 flex-col overflow-hidden">
|
|
257
259
|
${renderResultsSurface(state, isResultsRoute)}
|
|
258
260
|
</section>
|
|
259
261
|
</div>
|
|
262
|
+
${renderQueryHistoryPanel({
|
|
263
|
+
items: state.editor.history,
|
|
264
|
+
loading: state.editor.historyLoading,
|
|
265
|
+
loadingMore: state.editor.historyLoadingMore,
|
|
266
|
+
error: state.editor.historyError,
|
|
267
|
+
activeTab: state.editor.historyTab,
|
|
268
|
+
search: state.editor.historySearchInput,
|
|
269
|
+
total: state.editor.historyTotal,
|
|
270
|
+
hasMore: state.editor.historyHasMore,
|
|
271
|
+
activeHistoryId: state.editor.historyActiveId,
|
|
272
|
+
selectedHistoryId: state.editor.historySelectedId,
|
|
273
|
+
})}
|
|
260
274
|
</section>
|
|
261
275
|
`,
|
|
262
|
-
panel:
|
|
276
|
+
panel:
|
|
277
|
+
isResultsRoute && state.editor.selectedRowIndex !== null
|
|
278
|
+
? renderEditorRowPanel(state)
|
|
279
|
+
: state.editor.historySelectedId
|
|
280
|
+
? renderQueryHistoryDetail({
|
|
281
|
+
item: state.editor.historyDetail,
|
|
282
|
+
runs: state.editor.historyRuns,
|
|
283
|
+
loading: state.editor.historyDetailLoading,
|
|
284
|
+
error: state.editor.historyDetailError,
|
|
285
|
+
})
|
|
286
|
+
: "",
|
|
263
287
|
};
|
|
264
288
|
}
|
|
@@ -126,6 +126,21 @@ function renderOperationalSurface(overview) {
|
|
|
126
126
|
)
|
|
127
127
|
.join("")}
|
|
128
128
|
</div>
|
|
129
|
+
${
|
|
130
|
+
overview.file?.path
|
|
131
|
+
? `
|
|
132
|
+
<div class="border-t border-outline-variant/10 px-4 py-3">
|
|
133
|
+
<button
|
|
134
|
+
class="toolbar-button border border-outline-variant/20 bg-surface-container px-3 py-1.5 text-[10px] font-mono uppercase tracking-[0.16em] text-on-surface transition-colors hover:border-primary-container hover:text-primary-container"
|
|
135
|
+
data-action="open-overview-in-finder"
|
|
136
|
+
type="button"
|
|
137
|
+
>
|
|
138
|
+
Open In Finder
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
`
|
|
142
|
+
: ""
|
|
143
|
+
}
|
|
129
144
|
</section>
|
|
130
145
|
`;
|
|
131
146
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { renderTableDesignerEditor } from "../components/tableDesignerEditor.js";
|
|
2
|
+
import { renderTableDesignerSidebar } from "../components/tableDesignerSidebar.js";
|
|
3
|
+
import { renderTableDesignerSqlPreview } from "../components/tableDesignerSqlPreview.js";
|
|
4
|
+
import { escapeHtml } from "../utils/format.js";
|
|
5
|
+
|
|
6
|
+
function renderRouteError(error) {
|
|
7
|
+
if (!error) {
|
|
8
|
+
return "";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return `
|
|
12
|
+
<div class="table-designer-route-error">
|
|
13
|
+
<div class="table-designer-route-error__code">${escapeHtml(error.code)}</div>
|
|
14
|
+
<div class="table-designer-route-error__text">${escapeHtml(error.message)}</div>
|
|
15
|
+
</div>
|
|
16
|
+
`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function renderTableDesignerView(state) {
|
|
20
|
+
return {
|
|
21
|
+
main: `
|
|
22
|
+
<section class="view-surface table-designer-view">
|
|
23
|
+
${renderTableDesignerSidebar(state)}
|
|
24
|
+
<div class="table-designer-workspace">
|
|
25
|
+
${renderRouteError(state.tableDesigner.error)}
|
|
26
|
+
<div class="table-designer-workspace__top">
|
|
27
|
+
${renderTableDesignerEditor(state)}
|
|
28
|
+
</div>
|
|
29
|
+
<div class="table-designer-workspace__bottom">
|
|
30
|
+
${renderTableDesignerSqlPreview(state.tableDesigner.draft)}
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</section>
|
|
34
|
+
`,
|
|
35
|
+
panel: "",
|
|
36
|
+
};
|
|
37
|
+
}
|
package/frontend/styles/base.css
CHANGED
|
@@ -1,103 +1,110 @@
|
|
|
1
1
|
*,
|
|
2
2
|
*::before,
|
|
3
3
|
*::after {
|
|
4
|
-
|
|
4
|
+
box-sizing: border-box;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
html,
|
|
8
8
|
body {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
height: 100%;
|
|
10
|
+
margin: 0;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
body {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
background: var(--color-background);
|
|
15
|
+
color: var(--color-on-surface);
|
|
16
|
+
font-family: var(--font-family-body);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
button,
|
|
20
20
|
input,
|
|
21
21
|
select,
|
|
22
22
|
textarea {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
color: inherit;
|
|
24
|
+
font: inherit;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
button {
|
|
28
|
-
|
|
28
|
+
cursor: pointer;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
a {
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
color: inherit;
|
|
33
|
+
text-decoration: none;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
img {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
display: block;
|
|
38
|
+
max-width: 100%;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
[hidden] {
|
|
42
|
-
|
|
42
|
+
display: none !important;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
.font-headline {
|
|
46
|
-
|
|
46
|
+
font-family: var(--font-family-headline);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
.font-body {
|
|
50
|
-
|
|
50
|
+
font-family: var(--font-family-body);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
.font-mono {
|
|
54
|
-
|
|
54
|
+
font-family: var(--font-family-mono);
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
white-space: nowrap;
|
|
57
|
+
text-overflow: ellipsis;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
.material-symbols-outlined {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
display: inline-block;
|
|
62
|
+
font-size: var(--font-size-icon);
|
|
63
|
+
font-variation-settings:
|
|
64
|
+
'FILL' 0,
|
|
65
|
+
'wght' 400,
|
|
66
|
+
'GRAD' 0,
|
|
67
|
+
'opsz' 24;
|
|
68
|
+
letter-spacing: normal;
|
|
69
|
+
line-height: 1;
|
|
70
|
+
text-transform: none;
|
|
71
|
+
white-space: nowrap;
|
|
72
|
+
word-wrap: normal;
|
|
73
|
+
direction: ltr;
|
|
74
|
+
vertical-align: middle;
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
.no-scrollbar {
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
-ms-overflow-style: none;
|
|
79
|
+
scrollbar-width: none;
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
.no-scrollbar::-webkit-scrollbar {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
display: none;
|
|
84
|
+
height: 0;
|
|
85
|
+
width: 0;
|
|
79
86
|
}
|
|
80
87
|
|
|
81
88
|
.custom-scrollbar {
|
|
82
|
-
|
|
83
|
-
|
|
89
|
+
scrollbar-color: var(--color-surface-highest) var(--color-surface-lowest);
|
|
90
|
+
scrollbar-width: thin;
|
|
84
91
|
}
|
|
85
92
|
|
|
86
93
|
.custom-scrollbar::-webkit-scrollbar {
|
|
87
|
-
|
|
88
|
-
|
|
94
|
+
height: var(--scrollbar-size);
|
|
95
|
+
width: var(--scrollbar-size);
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
.custom-scrollbar::-webkit-scrollbar-track {
|
|
92
|
-
|
|
99
|
+
background: var(--color-surface-lowest);
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
.custom-scrollbar::-webkit-scrollbar-thumb {
|
|
96
|
-
|
|
103
|
+
background: var(--color-surface-highest);
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
|
100
|
-
|
|
107
|
+
background: var(--color-primary-container);
|
|
101
108
|
}
|
|
102
109
|
|
|
103
110
|
.clipped-btn,
|
|
@@ -105,72 +112,79 @@ img {
|
|
|
105
112
|
.custom-clip,
|
|
106
113
|
.clip-button,
|
|
107
114
|
.clip-corner {
|
|
108
|
-
|
|
115
|
+
clip-path: var(--clip-path);
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
.sql-keyword {
|
|
112
|
-
|
|
119
|
+
color: var(--color-primary-container);
|
|
113
120
|
}
|
|
114
121
|
|
|
115
122
|
.sql-string {
|
|
116
|
-
|
|
123
|
+
color: var(--color-on-surface);
|
|
117
124
|
}
|
|
118
125
|
|
|
119
126
|
.sql-comment {
|
|
120
|
-
|
|
127
|
+
color: var(--color-outline-variant);
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
.sql-value {
|
|
124
|
-
|
|
131
|
+
color: var(--color-on-surface-variant);
|
|
125
132
|
}
|
|
126
133
|
|
|
127
134
|
.query-editor-layer {
|
|
128
|
-
|
|
135
|
+
display: grid;
|
|
136
|
+
min-height: 140px;
|
|
137
|
+
overflow: hidden;
|
|
129
138
|
}
|
|
130
139
|
|
|
131
140
|
.query-editor-highlight,
|
|
132
141
|
.query-editor-input {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
display: block;
|
|
143
|
+
font: inherit;
|
|
144
|
+
grid-area: 1 / 1;
|
|
145
|
+
line-height: inherit;
|
|
146
|
+
margin: 0;
|
|
147
|
+
min-height: 100%;
|
|
148
|
+
padding: 0;
|
|
149
|
+
tab-size: 2;
|
|
150
|
+
white-space: pre-wrap;
|
|
151
|
+
width: 100%;
|
|
152
|
+
word-break: normal;
|
|
153
|
+
overflow-wrap: anywhere;
|
|
140
154
|
}
|
|
141
155
|
|
|
142
156
|
.query-editor-highlight {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
pointer-events: none;
|
|
147
|
-
position: absolute;
|
|
157
|
+
color: var(--color-on-surface);
|
|
158
|
+
overflow: hidden;
|
|
159
|
+
pointer-events: none;
|
|
148
160
|
}
|
|
149
161
|
|
|
150
162
|
.query-editor-input {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
163
|
+
-webkit-appearance: none;
|
|
164
|
+
-webkit-text-fill-color: transparent;
|
|
165
|
+
appearance: none;
|
|
166
|
+
background: transparent;
|
|
167
|
+
caret-color: var(--color-on-surface);
|
|
168
|
+
color: transparent;
|
|
169
|
+
overflow: auto;
|
|
156
170
|
}
|
|
157
171
|
|
|
158
172
|
.query-editor-input::placeholder {
|
|
159
|
-
|
|
173
|
+
color: transparent;
|
|
160
174
|
}
|
|
161
175
|
|
|
162
176
|
.cursor-blink {
|
|
163
|
-
|
|
164
|
-
|
|
177
|
+
animation: cursor-blink var(--duration-cursor-blink) step-end infinite;
|
|
178
|
+
border-right: 2px solid var(--color-primary-container);
|
|
165
179
|
}
|
|
166
180
|
|
|
167
181
|
@keyframes cursor-blink {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
from,
|
|
183
|
+
to {
|
|
184
|
+
border-color: transparent;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
50% {
|
|
188
|
+
border-color: var(--color-primary-container);
|
|
189
|
+
}
|
|
176
190
|
}
|