sqlite-hub 1.1.1 → 1.2.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 (60) hide show
  1. package/README.md +17 -196
  2. package/bin/sqlite-hub.js +7 -2
  3. package/frontend/js/api.js +60 -0
  4. package/frontend/js/app.js +201 -5
  5. package/frontend/js/components/dropdownButton.js +92 -0
  6. package/frontend/js/components/modal.js +991 -876
  7. package/frontend/js/components/queryEditor.js +24 -15
  8. package/frontend/js/components/queryHistoryDetail.js +20 -1
  9. package/frontend/js/components/queryHistoryHeader.js +3 -2
  10. package/frontend/js/components/queryResults.js +1 -1
  11. package/frontend/js/components/rowEditorPanel.js +53 -13
  12. package/frontend/js/components/sidebar.js +1 -0
  13. package/frontend/js/components/topNav.js +1 -4
  14. package/frontend/js/components/workspaceOpenDropdown.js +52 -0
  15. package/frontend/js/router.js +2 -0
  16. package/frontend/js/store.js +450 -38
  17. package/frontend/js/utils/emailPreview.js +28 -0
  18. package/frontend/js/utils/markdownDocuments.js +17 -1
  19. package/frontend/js/utils/riskySql.js +165 -0
  20. package/frontend/js/views/backups.js +204 -0
  21. package/frontend/js/views/charts.js +1 -1
  22. package/frontend/js/views/data.js +42 -16
  23. package/frontend/js/views/documents.js +184 -154
  24. package/frontend/js/views/settings.js +1 -0
  25. package/frontend/js/views/structure.js +47 -33
  26. package/frontend/js/views/tableDesigner.js +23 -0
  27. package/frontend/styles/components.css +133 -0
  28. package/frontend/styles/tailwind.generated.css +1 -1
  29. package/frontend/styles/tokens.css +1 -0
  30. package/frontend/styles/views.css +33 -21
  31. package/package.json +2 -1
  32. package/server/routes/backups.js +120 -0
  33. package/server/routes/connections.js +26 -3
  34. package/server/routes/externalApi.js +6 -2
  35. package/server/server.js +3 -1
  36. package/server/services/databaseCommandService.js +4 -3
  37. package/server/services/sqlite/backupService.js +497 -66
  38. package/server/services/sqlite/connectionManager.js +2 -2
  39. package/server/services/sqlite/importService.js +25 -0
  40. package/server/services/sqlite/sqlExecutor.js +2 -0
  41. package/server/services/storage/appStateStore.js +379 -88
  42. package/tests/api-token-auth.test.js +45 -2
  43. package/tests/backup-manager.test.js +140 -0
  44. package/tests/backups-view.test.js +70 -0
  45. package/tests/charts-height-preset-storage.test.js +60 -0
  46. package/tests/charts-route-state.test.js +144 -0
  47. package/tests/cli-service-delegation.test.js +97 -0
  48. package/tests/connection-removal.test.js +52 -0
  49. package/tests/database-command-service.test.js +37 -2
  50. package/tests/documents-view.test.js +132 -0
  51. package/tests/dropdown-button.test.js +101 -0
  52. package/tests/email-preview.test.js +89 -0
  53. package/tests/markdown-documents.test.js +24 -0
  54. package/tests/query-editor.test.js +28 -0
  55. package/tests/query-history-detail.test.js +37 -0
  56. package/tests/query-history-header.test.js +30 -0
  57. package/tests/risky-sql.test.js +30 -0
  58. package/tests/row-editor-null-values.test.js +53 -0
  59. package/tests/settings-view.test.js +1 -0
  60. package/tests/structure-view.test.js +60 -0
@@ -76,6 +76,24 @@ function createConnectionsRouter({ connectionManager, importService, backupServi
76
76
  })
77
77
  );
78
78
 
79
+ router.post(
80
+ "/import-sql/preview",
81
+ route((req, res) => {
82
+ const result = importService.inspectSqlImport({
83
+ sqlFilePath: req.body.sqlFilePath,
84
+ });
85
+
86
+ res.json(
87
+ successResponse({
88
+ message: result.requiresSafetyBackup
89
+ ? "Import safety backup recommended."
90
+ : "Import can continue without a safety backup.",
91
+ data: result,
92
+ })
93
+ );
94
+ })
95
+ );
96
+
79
97
  router.post(
80
98
  "/import-sql",
81
99
  route((req, res) => {
@@ -104,12 +122,17 @@ function createConnectionsRouter({ connectionManager, importService, backupServi
104
122
 
105
123
  router.post(
106
124
  "/backup-active",
107
- route((req, res) => {
108
- const backup = backupService.createActiveBackup();
125
+ route(async (req, res) => {
126
+ const backup = await backupService.createActiveBackup({
127
+ name: req.body?.name,
128
+ notes: req.body?.notes,
129
+ type: req.body?.type,
130
+ context: req.body?.context,
131
+ });
109
132
 
110
133
  res.json(
111
134
  successResponse({
112
- message: `Backup created: ${backup.fileName}`,
135
+ message: "Backup created and verified.",
113
136
  data: backup,
114
137
  })
115
138
  );
@@ -70,7 +70,10 @@ function createExternalApiRouter({ databaseService, tokenService, appInfoService
70
70
 
71
71
  authenticateDatabaseRequest(req, tokenService, databaseId);
72
72
 
73
- const { result } = databaseService.executeRawQuery(databaseId, sql, { storeName });
73
+ const { result } = databaseService.executeRawQuery(databaseId, sql, {
74
+ storeName,
75
+ executedBy: "api",
76
+ });
74
77
 
75
78
  res.json(
76
79
  successResponse({
@@ -168,7 +171,8 @@ function createExternalApiRouter({ databaseService, tokenService, appInfoService
168
171
  route((req, res) => {
169
172
  const { query, result } = databaseService.executeSavedQuery(
170
173
  req.params.databaseId,
171
- req.params.queryName
174
+ req.params.queryName,
175
+ { executedBy: "api" }
172
176
  );
173
177
 
174
178
  res.json(
package/server/server.js CHANGED
@@ -24,6 +24,7 @@ const { MediaTaggingService } = require("./services/sqlite/mediaTaggingService")
24
24
  const { ApiTokenService } = require("./services/apiTokenService");
25
25
  const { DatabaseCommandService } = require("./services/databaseCommandService");
26
26
  const { createConnectionsRouter } = require("./routes/connections");
27
+ const { createBackupsRouter } = require("./routes/backups");
27
28
  const { createOverviewRouter } = require("./routes/overview");
28
29
  const { createSqlRouter } = require("./routes/sql");
29
30
  const { createChartsRouter } = require("./routes/charts");
@@ -56,7 +57,7 @@ const connectionManager = new ConnectionManager({ appStateStore });
56
57
  const overviewService = new OverviewService({ connectionManager });
57
58
  const sqlExecutor = new SqlExecutor({ connectionManager, appStateStore });
58
59
  const importService = new ImportService({ connectionManager });
59
- const backupService = new BackupService({ connectionManager });
60
+ const backupService = new BackupService({ connectionManager, appStateStore });
60
61
  const nativeFileDialogService = new NativeFileDialogService();
61
62
  const exportService = new ExportService({
62
63
  appStateStore,
@@ -114,6 +115,7 @@ app.use(
114
115
  nativeFileDialogService,
115
116
  })
116
117
  );
118
+ app.use("/api/backups", createBackupsRouter({ backupService }));
117
119
  app.use("/api/db", createOverviewRouter({ overviewService }));
118
120
  app.use("/api/sql", createSqlRouter({ appStateStore, connectionManager, sqlExecutor }));
119
121
  app.use("/api/charts", createChartsRouter({ appStateStore, connectionManager, sqlExecutor }));
@@ -283,7 +283,7 @@ class DatabaseCommandService {
283
283
  const collection = this.appStateStore.buildQueryHistoryCollection({
284
284
  databaseKey: connection.id,
285
285
  search: queryName,
286
- onlySaved: false,
286
+ onlySaved: true,
287
287
  limit: 100,
288
288
  });
289
289
 
@@ -326,10 +326,11 @@ class DatabaseCommandService {
326
326
  return this.requireQuery(databaseReference, queryName);
327
327
  }
328
328
 
329
- executeSavedQuery(databaseReference, queryName) {
329
+ executeSavedQuery(databaseReference, queryName, options = {}) {
330
330
  const query = this.requireQuery(databaseReference, queryName);
331
+ const { executedBy = "user" } = options;
331
332
  const result = this.withDatabase(databaseReference, ({ runtime }) =>
332
- runtime.sqlExecutor.execute(query.rawSql, { persistHistory: false })
333
+ runtime.sqlExecutor.execute(query.rawSql, { executedBy })
333
334
  );
334
335
 
335
336
  return { query, result };