sqlite-hub 1.2.0 → 1.5.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.
Files changed (169) hide show
  1. package/README.md +113 -71
  2. package/bin/sqlite-hub.js +723 -116
  3. package/docs/API.md +152 -0
  4. package/docs/CLI.md +249 -0
  5. package/docs/CLI_API_PARITY.md +61 -0
  6. package/docs/changelog.md +149 -0
  7. package/docs/guidelines/AGENTS.md +32 -0
  8. package/docs/guidelines/DESIGN.md +55 -0
  9. package/docs/shortkeys.md +27 -0
  10. package/docs/todo.md +4 -0
  11. package/examples/api/generate-types.js +52 -0
  12. package/frontend/assets/mockups/backups_1_1920.webp +0 -0
  13. package/frontend/assets/mockups/backups_2_create_backup_modal_1920.webp +0 -0
  14. package/frontend/assets/mockups/backups_3_edit_backup_modal_1920.webp +0 -0
  15. package/frontend/assets/mockups/backups_4_restore_backup_modal_1920.webp +0 -0
  16. package/frontend/assets/mockups/backups_5_delete_backup_modal_1920.webp +0 -0
  17. package/frontend/assets/mockups/charts_1_1920.webp +0 -0
  18. package/frontend/assets/mockups/charts_2_query_detail_1920.webp +0 -0
  19. package/frontend/assets/mockups/charts_3_create_query_chart_modal_1920.webp +0 -0
  20. package/frontend/assets/mockups/charts_4_edit_query_chart_modal_1920.webp +0 -0
  21. package/frontend/assets/mockups/charts_5_delete_query_chart_modal_1920.webp +0 -0
  22. package/frontend/assets/mockups/charts_6_copy_column_modal_1920.webp +0 -0
  23. package/frontend/assets/mockups/connections_1_1920.webp +0 -0
  24. package/frontend/assets/mockups/connections_2_create_connection_modal_1920.webp +0 -0
  25. package/frontend/assets/mockups/connections_3_open_connection_modal_1920.webp +0 -0
  26. package/frontend/assets/mockups/data_1_1920.webp +0 -0
  27. package/frontend/assets/mockups/data_2_roweditor_1920.webp +0 -0
  28. package/frontend/assets/mockups/data_3_data_export_modal_1920.webp +0 -0
  29. package/frontend/assets/mockups/documents_1_1920.webp +0 -0
  30. package/frontend/assets/mockups/documents_2_document_insert_table_modal_1920.webp +0 -0
  31. package/frontend/assets/mockups/documents_3_document_insert_note_modal_1920.webp +0 -0
  32. package/frontend/assets/mockups/media_tagging_queue_1_1920.webp +0 -0
  33. package/frontend/assets/mockups/media_tagging_setup_1_1920.webp +0 -0
  34. package/frontend/assets/mockups/media_tagging_setup_2_create_media_tagging_tag_table_modal_1920.webp +0 -0
  35. package/frontend/assets/mockups/media_tagging_setup_3_create_media_tagging_mapping_table_modal_1920.webp +0 -0
  36. package/frontend/assets/mockups/overview_1_1920.webp +0 -0
  37. package/frontend/assets/mockups/settings_1_1920.webp +0 -0
  38. package/frontend/assets/mockups/sql_editor_1_1920.webp +0 -0
  39. package/frontend/assets/mockups/sql_editor_2_query_detail_1920.webp +0 -0
  40. package/frontend/assets/mockups/sql_editor_3_query_export_modal_1920.webp +0 -0
  41. package/frontend/assets/mockups/structure_1_1920.webp +0 -0
  42. package/frontend/assets/mockups/structure_2_generate_types_modal_1920.webp +0 -0
  43. package/frontend/assets/mockups/structure_3_generate_types_modal_1920.webp +0 -0
  44. package/frontend/assets/mockups/table_designer_1_1920.webp +0 -0
  45. package/frontend/assets/mockups/table_designer_2_table_designer_constraints_modal_1920.webp +0 -0
  46. package/frontend/js/api.js +63 -0
  47. package/frontend/js/app.js +310 -10
  48. package/frontend/js/components/connectionCard.js +4 -2
  49. package/frontend/js/components/emptyState.js +4 -4
  50. package/frontend/js/components/generateTypesDropdown.js +33 -0
  51. package/frontend/js/components/metricCard.js +1 -1
  52. package/frontend/js/components/modal.js +555 -21
  53. package/frontend/js/components/pageHeader.js +1 -1
  54. package/frontend/js/components/queryHistoryDetail.js +3 -3
  55. package/frontend/js/components/queryHistoryHeader.js +1 -1
  56. package/frontend/js/components/queryHistoryPanel.js +1 -1
  57. package/frontend/js/components/rowEditorPanel.js +13 -3
  58. package/frontend/js/components/sidebar.js +41 -7
  59. package/frontend/js/components/topNav.js +2 -14
  60. package/frontend/js/router.js +38 -6
  61. package/frontend/js/store.js +870 -8
  62. package/frontend/js/utils/inputClear.js +36 -0
  63. package/frontend/js/utils/syntheticData.js +240 -0
  64. package/frontend/js/views/backups.js +581 -37
  65. package/frontend/js/views/charts.js +9 -9
  66. package/frontend/js/views/connections.js +2 -2
  67. package/frontend/js/views/data.js +17 -1
  68. package/frontend/js/views/documents.js +3 -3
  69. package/frontend/js/views/editor.js +6 -6
  70. package/frontend/js/views/logs.js +339 -0
  71. package/frontend/js/views/mediaTagging.js +7 -5
  72. package/frontend/js/views/overview.js +3 -3
  73. package/frontend/js/views/settings.js +80 -30
  74. package/frontend/js/views/structure.js +12 -1
  75. package/frontend/js/views/tableAdvisor.js +385 -0
  76. package/frontend/js/views/tableDesigner.js +6 -0
  77. package/frontend/styles/base.css +1 -40
  78. package/frontend/styles/components.css +258 -232
  79. package/frontend/styles/structure-graph.css +32 -68
  80. package/frontend/styles/tailwind.css +8 -4
  81. package/frontend/styles/tailwind.generated.css +1 -1
  82. package/frontend/styles/tokens.css +28 -21
  83. package/frontend/styles/views.css +102 -261
  84. package/package.json +18 -2
  85. package/server/routes/backups.js +18 -2
  86. package/server/routes/data.js +45 -0
  87. package/server/routes/externalApi.js +321 -2
  88. package/server/routes/logs.js +127 -0
  89. package/server/routes/structure.js +22 -0
  90. package/server/server.js +3 -0
  91. package/server/services/databaseCommandService.js +59 -0
  92. package/server/services/sqlite/backupDiff.js +914 -0
  93. package/server/services/sqlite/backupService.js +77 -1
  94. package/server/services/sqlite/dataBrowserService.js +36 -0
  95. package/server/services/sqlite/introspection.js +226 -22
  96. package/server/services/sqlite/structureService.js +7 -0
  97. package/server/services/sqlite/syntheticDataGenerator.js +728 -0
  98. package/server/services/sqlite/tableAdvisor.js +790 -0
  99. package/server/services/storage/appStateStore.js +773 -169
  100. package/server/services/typeGenerationService.js +663 -0
  101. package/tailwind.config.cjs +0 -1
  102. package/.github/funding.yml +0 -2
  103. package/.github/workflows/ci.yml +0 -36
  104. package/database.sqlite +0 -0
  105. package/frontend/assets/mockups/charts_1_bars_1200.webp +0 -0
  106. package/frontend/assets/mockups/charts_2_pie_1200.webp +0 -0
  107. package/frontend/assets/mockups/charts_3_scatter_plot_1200.webp +0 -0
  108. package/frontend/assets/mockups/connections_1200.webp +0 -0
  109. package/frontend/assets/mockups/data_1_1200.webp +0 -0
  110. package/frontend/assets/mockups/data_2_row_editor_1200.webp +0 -0
  111. package/frontend/assets/mockups/documents_1200.webp +0 -0
  112. package/frontend/assets/mockups/media_tagging_1_setup_1200.webp +0 -0
  113. package/frontend/assets/mockups/media_tagging_2_tagging_queue_1200.webp +0 -0
  114. package/frontend/assets/mockups/media_tagging_3_media_viewer_1200.webp +0 -0
  115. package/frontend/assets/mockups/overview_1200.webp +0 -0
  116. package/frontend/assets/mockups/settings_1200.webp +0 -0
  117. package/frontend/assets/mockups/sql_editor_1_1200.webp +0 -0
  118. package/frontend/assets/mockups/sql_editor_2_query_details_1200.webp +0 -0
  119. package/frontend/assets/mockups/sql_editor_3_export_column_1200.webp +0 -0
  120. package/frontend/assets/mockups/sql_editor_4_export_column_as_markdown_1200.webp +0 -0
  121. package/frontend/assets/mockups/sql_editor_5_export_query_result_1200.webp +0 -0
  122. package/frontend/assets/mockups/structure_1_1200.webp +0 -0
  123. package/frontend/assets/mockups/structure_2_inspector_1200.webp +0 -0
  124. package/frontend/assets/mockups/table_designer_1_1200.webp +0 -0
  125. package/frontend/assets/mockups/table_designer_2_checks_1200.webp +0 -0
  126. package/tests/api-token-auth.test.js +0 -279
  127. package/tests/backup-manager.test.js +0 -140
  128. package/tests/backups-view.test.js +0 -70
  129. package/tests/charts-height-preset-storage.test.js +0 -60
  130. package/tests/charts-route-state.test.js +0 -144
  131. package/tests/check-constraint-options.test.js +0 -90
  132. package/tests/cli-args.test.js +0 -113
  133. package/tests/cli-service-delegation.test.js +0 -140
  134. package/tests/connection-removal.test.js +0 -52
  135. package/tests/connections-file-dialog-route.test.js +0 -89
  136. package/tests/copy-column-modal.test.js +0 -131
  137. package/tests/database-command-service.test.js +0 -174
  138. package/tests/database-documents.test.js +0 -85
  139. package/tests/documents-view.test.js +0 -132
  140. package/tests/dropdown-button.test.js +0 -101
  141. package/tests/email-preview.test.js +0 -89
  142. package/tests/export-blob.test.js +0 -99
  143. package/tests/export-filenames.test.js +0 -38
  144. package/tests/file-path-preview.test.js +0 -165
  145. package/tests/form-controls.test.js +0 -34
  146. package/tests/json-preview.test.js +0 -49
  147. package/tests/local-request-security.test.js +0 -85
  148. package/tests/markdown-documents.test.js +0 -103
  149. package/tests/native-file-dialog.test.js +0 -105
  150. package/tests/query-editor.test.js +0 -28
  151. package/tests/query-history-detail.test.js +0 -37
  152. package/tests/query-history-header.test.js +0 -30
  153. package/tests/query-results-truncation.test.js +0 -20
  154. package/tests/risky-sql.test.js +0 -30
  155. package/tests/row-editor-json.test.js +0 -82
  156. package/tests/row-editor-null-values.test.js +0 -184
  157. package/tests/row-editor-timestamp-preview.test.js +0 -192
  158. package/tests/security-paths.test.js +0 -84
  159. package/tests/settings-api-tokens-route.test.js +0 -97
  160. package/tests/settings-metadata.test.js +0 -114
  161. package/tests/settings-view.test.js +0 -108
  162. package/tests/sql-formatter.test.js +0 -173
  163. package/tests/sql-highlight.test.js +0 -38
  164. package/tests/sql-identifier-safety.test.js +0 -171
  165. package/tests/sql-result-limit.test.js +0 -66
  166. package/tests/structure-view.test.js +0 -60
  167. package/tests/table-designer-v2-unique-constraints.test.js +0 -78
  168. package/tests/table-scroll-state.test.js +0 -70
  169. package/tests/text-cell-stats.test.js +0 -38
@@ -0,0 +1,55 @@
1
+ # SQLite Hub UI Rules for Codex
2
+
3
+ Follow these rules exactly when creating or modifying UI controls.
4
+
5
+ 1. Reuse existing shared components before creating anything new.
6
+ 2. Use exactly one semantic main class per control.
7
+ 3. Never combine multiple primary button-style classes (`standard-button`, `signature-button`, `delete-button`) on the same element.
8
+ 4. View-specific classes may change layout, width, spacing, or position only.
9
+ 5. View-specific classes must not redefine the base style of shared components.
10
+ 6. The standard height for buttons and compact interactive controls is `32px`.
11
+ 7. The source of truth for button height is `--button-height` in `frontend/styles/tokens.css`.
12
+ 8. The source of truth for form control height is `--control-height` in `frontend/styles/tokens.css`.
13
+ 9. Controls in the same row must have the same height unless one is a text input or textarea.
14
+ 10. All regular buttons must use one of these base classes only: `standard-button`, `signature-button`, `delete-button`.
15
+ 11. Use `standard-button` for normal actions.
16
+ 12. Use `signature-button` only for the primary yellow CTA in a context.
17
+ 13. Use `delete-button` only for destructive actions.
18
+ 14. Delete buttons must show the `delete` Material Symbol before the text label.
19
+ 15. `signature-button` must keep its hover state and chamfered corner.
20
+ 16. All visible clickable buttons must have a hover state.
21
+ 17. Disabled states must come from the shared component, not from local view CSS.
22
+ 18. Dropdown toggles may combine a base button class with `dropdown-button__toggle`; that class may only control dropdown layout and open-state behavior.
23
+ 19. Visibility/toggle buttons may combine a base button class with `panel-toggle-button`; that class is the shared toggle-state modifier.
24
+ 20. All reusable checkboxes must use `standard-checkbox`.
25
+ 21. Do not build feature-specific checkbox shells or checkbox base styles.
26
+ 22. Inputs and selects must follow the shared base rules in `frontend/styles/base.css`.
27
+ 23. Ghost or transparent inputs must not use a white background, including unfocused state.
28
+ 24. When a new control pattern appears in multiple places, promote it to a shared component first, then migrate existing usages.
29
+
30
+ ## Source of Truth
31
+
32
+ - `frontend/styles/tokens.css`
33
+ - `frontend/styles/base.css`
34
+ - `frontend/index.html`
35
+
36
+ ## Default Decision Rules
37
+
38
+ - Prefer reuse over invention.
39
+ - Prefer migration over local override.
40
+ - Prefer shared component updates over per-view fixes.
41
+
42
+ ## UX behavior
43
+
44
+ - All drawers must close with `Escape`.
45
+ - All modal windows must close with `Escape`.
46
+ - Open dropdowns and menu popovers must close with `Escape`.
47
+ - Focused text-like input elements must clear their value with `Escape` before any parent drawer, modal, dropdown, or selection state handles the key.
48
+ - Search inputs must clear with `Escape` and dispatch the same input/update behavior as manual clearing.
49
+ - Do not clear multiline textareas with `Escape` unless the textarea is explicitly built as a search field.
50
+ - If an input is already empty, `Escape` may continue to the next applicable close/clear behavior.
51
+
52
+ ## History elements
53
+
54
+ - Query history panels, such as SQL Editor and Charts history, are always placed on the right side.
55
+ - Subnavigation panels, such as tables, documents, structure objects, and table-designer tables, are always placed on the left side.
@@ -0,0 +1,27 @@
1
+ # Meddia Tagging
2
+
3
+ ## tagging queue
4
+
5
+ `shift + enter` triggers tagged & next
6
+
7
+ # SQL Editor
8
+
9
+ `shift + enter` triggers execute
10
+
11
+ ## Chart Details & Query Details (drawer)
12
+
13
+ `esc` closes the drawer
14
+
15
+ # Misc
16
+
17
+ ## Modals
18
+
19
+ `esc` closes the modal
20
+
21
+ ## Input elements
22
+
23
+ `esc` clears the input
24
+
25
+ ## Dropdown Buttons
26
+
27
+ `esc` closes the dropwdown
package/docs/todo.md ADDED
@@ -0,0 +1,4 @@
1
+ # Maybe
2
+
3
+ - Data Pipeline Light/hook, programmable triggers?
4
+ - MCP
@@ -0,0 +1,52 @@
1
+ const SQLITE_HUB_URL = process.env.SQLITE_HUB_URL || 'http://127.0.0.1:4173';
2
+ const apiToken = process.env.SQLITE_HUB_API_TOKEN;
3
+ const databaseId = process.env.SQLITE_HUB_DATABASE_ID || process.argv[2];
4
+ const tableName = process.env.SQLITE_HUB_TABLE || process.argv[3] || 'users';
5
+ const target = process.env.SQLITE_HUB_TYPE_TARGET || process.argv[4] || 'typescript';
6
+
7
+ if (!apiToken) {
8
+ throw new Error('SQLITE_HUB_API_TOKEN is required.');
9
+ }
10
+
11
+ if (!databaseId) {
12
+ throw new Error('Provide SQLITE_HUB_DATABASE_ID or pass the database id as the first argument.');
13
+ }
14
+
15
+ const url = [
16
+ SQLITE_HUB_URL.replace(/\/$/, ''),
17
+ 'api/v1/databases',
18
+ encodeURIComponent(databaseId),
19
+ 'tables',
20
+ encodeURIComponent(tableName),
21
+ 'types',
22
+ ].join('/');
23
+
24
+ const response = await fetch(url, {
25
+ method: 'POST',
26
+ headers: {
27
+ Accept: 'application/json',
28
+ Authorization: `Bearer ${apiToken}`,
29
+ 'Content-Type': 'application/json',
30
+ },
31
+ body: JSON.stringify({
32
+ target,
33
+ options: {
34
+ propertyNaming: 'camel',
35
+ nullableMode: 'native',
36
+ includeComments: true,
37
+ includeDefaultsAsComments: true,
38
+ },
39
+ }),
40
+ });
41
+
42
+ const payload = await response.json();
43
+
44
+ if (!response.ok || !payload.success) {
45
+ throw new Error(payload.error?.message || payload.message || 'Type generation failed.');
46
+ }
47
+
48
+ console.log(payload.data.code);
49
+
50
+ if (payload.warnings?.length) {
51
+ console.error(payload.warnings.map(warning => `Warning: ${warning}`).join('\n'));
52
+ }
@@ -153,6 +153,17 @@ export function getBackup(backupId) {
153
153
  return request(`/api/backups/${encodeURIComponent(backupId)}`);
154
154
  }
155
155
 
156
+ export function getBackupDiff(backupId, options = {}) {
157
+ const params = new URLSearchParams();
158
+
159
+ if (options.sampleLimit !== undefined) {
160
+ params.set("sampleLimit", String(options.sampleLimit));
161
+ }
162
+
163
+ const query = params.toString();
164
+ return request(`/api/backups/${encodeURIComponent(backupId)}/diff${query ? `?${query}` : ""}`);
165
+ }
166
+
156
167
  export function createBackup(payload = {}) {
157
168
  return request("/api/backups", {
158
169
  method: "POST",
@@ -205,6 +216,33 @@ export function getDbStatus() {
205
216
  return request("/api/db/status");
206
217
  }
207
218
 
219
+ export function getLogs(options = {}) {
220
+ const params = new URLSearchParams();
221
+
222
+ [
223
+ "kind",
224
+ "range",
225
+ "actor",
226
+ "status",
227
+ "queryType",
228
+ "destructive",
229
+ "from",
230
+ "to",
231
+ "search",
232
+ "limit",
233
+ "offset",
234
+ ].forEach((key) => {
235
+ const value = options[key];
236
+
237
+ if (value !== undefined && value !== null && value !== "") {
238
+ params.set(key, String(value));
239
+ }
240
+ });
241
+
242
+ const query = params.toString();
243
+ return request(`/api/logs${query ? `?${query}` : ""}`);
244
+ }
245
+
208
246
  export function executeSql(sql) {
209
247
  return request("/api/sql/execute", {
210
248
  method: "POST",
@@ -340,6 +378,13 @@ export function getStructureDetail(tableName) {
340
378
  return request(`/api/structure/${encodeURIComponent(tableName)}`);
341
379
  }
342
380
 
381
+ export function generateStructureTypes(tableName, payload = {}) {
382
+ return request(`/api/structure/${encodeURIComponent(tableName)}/types`, {
383
+ method: "POST",
384
+ body: payload,
385
+ });
386
+ }
387
+
343
388
  export function getTableDesignerOverview() {
344
389
  return request("/api/table-designer");
345
390
  }
@@ -452,6 +497,10 @@ export function getDataTable(tableName, options = {}) {
452
497
  return request(`/api/data/${encodeURIComponent(tableName)}${query ? `?${query}` : ""}`);
453
498
  }
454
499
 
500
+ export function analyzeTableAdvisor(tableName) {
501
+ return request(`/api/data/${encodeURIComponent(tableName)}/advisor`);
502
+ }
503
+
455
504
  export function getDataTableRow(tableName, payload) {
456
505
  return request(`/api/data/${encodeURIComponent(tableName)}/row`, {
457
506
  method: "POST",
@@ -473,6 +522,20 @@ export function previewDataTableRowUpdate(tableName, payload) {
473
522
  });
474
523
  }
475
524
 
525
+ export function previewSyntheticDataRows(tableName, payload) {
526
+ return request(`/api/data/${encodeURIComponent(tableName)}/generate/preview`, {
527
+ method: "POST",
528
+ body: payload,
529
+ });
530
+ }
531
+
532
+ export function insertSyntheticDataRows(tableName, payload) {
533
+ return request(`/api/data/${encodeURIComponent(tableName)}/generate/insert`, {
534
+ method: "POST",
535
+ body: payload,
536
+ });
537
+ }
538
+
476
539
  export function deleteDataTableRow(tableName, payload) {
477
540
  return request(`/api/data/${encodeURIComponent(tableName)}/rows`, {
478
541
  method: "DELETE",