sqlite-hub 0.7.0 → 0.8.7

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 (31) hide show
  1. package/changelog.md +14 -0
  2. package/docs/DESIGN_GUIDELINES.md +36 -0
  3. package/frontend/index.html +79 -0
  4. package/frontend/js/app.js +89 -8
  5. package/frontend/js/components/connectionCard.js +3 -4
  6. package/frontend/js/components/emptyState.js +4 -4
  7. package/frontend/js/components/modal.js +32 -28
  8. package/frontend/js/components/queryEditor.js +2 -4
  9. package/frontend/js/components/queryHistoryDetail.js +16 -7
  10. package/frontend/js/components/queryHistoryPanel.js +2 -2
  11. package/frontend/js/components/rowEditorPanel.js +59 -54
  12. package/frontend/js/components/sidebar.js +32 -33
  13. package/frontend/js/components/structureGraph.js +54 -122
  14. package/frontend/js/components/tableDesignerEditor.js +9 -8
  15. package/frontend/js/components/tableDesignerSidebar.js +11 -10
  16. package/frontend/js/components/tableDesignerSqlPreview.js +60 -28
  17. package/frontend/js/store.js +23 -0
  18. package/frontend/js/views/charts.js +66 -38
  19. package/frontend/js/views/connections.js +5 -17
  20. package/frontend/js/views/data.js +12 -13
  21. package/frontend/js/views/overview.js +149 -10
  22. package/frontend/js/views/settings.js +2 -2
  23. package/frontend/js/views/structure.js +74 -70
  24. package/frontend/js/views/tableDesigner.js +7 -2
  25. package/frontend/styles/base.css +62 -0
  26. package/frontend/styles/components.css +63 -105
  27. package/frontend/styles/structure-graph.css +19 -82
  28. package/frontend/styles/tokens.css +2 -0
  29. package/frontend/styles/views.css +33 -36
  30. package/package.json +1 -1
  31. package/server/services/sqlite/overviewService.js +68 -0
@@ -55,12 +55,13 @@
55
55
 
56
56
  .top-nav-icon {
57
57
  align-items: center;
58
+ box-sizing: border-box;
58
59
  color: var(--color-primary-container);
59
60
  display: inline-flex;
60
- height: 2rem;
61
+ height: var(--control-height);
61
62
  justify-content: center;
62
63
  transition: background-color var(--transition-fast);
63
- width: 2rem;
64
+ width: var(--control-height);
64
65
  }
65
66
 
66
67
  .top-nav-icon:hover {
@@ -189,9 +190,14 @@
189
190
 
190
191
  .toolbar-button {
191
192
  align-items: center;
193
+ box-sizing: border-box;
192
194
  display: inline-flex;
193
195
  gap: var(--spacing-2);
196
+ height: var(--control-height);
194
197
  justify-content: center;
198
+ line-height: 1;
199
+ min-height: var(--control-height);
200
+ padding: 0 var(--control-padding-inline);
195
201
  text-transform: uppercase;
196
202
  transition:
197
203
  background-color var(--transition-fast),
@@ -199,10 +205,6 @@
199
205
  color var(--transition-fast);
200
206
  }
201
207
 
202
- .toolbar-button--primary:hover {
203
- box-shadow: var(--shadow-subtle-glow);
204
- }
205
-
206
208
  .metric-card {
207
209
  background: var(--color-surface-low);
208
210
  display: flex;
@@ -338,10 +340,10 @@
338
340
  display: flex;
339
341
  flex: 0 0 18rem;
340
342
  flex-direction: column;
341
- max-width: 18rem;
343
+ max-width: 18.2rem;
342
344
  min-height: 0;
343
- min-width: 18rem;
344
- width: 18rem;
345
+ min-width: 18.2rem;
346
+ width: 18.2rem;
345
347
  }
346
348
 
347
349
  .table-designer-sidebar__header {
@@ -392,75 +394,21 @@
392
394
  text-transform: uppercase;
393
395
  }
394
396
 
395
- .table-designer-sidebar__new-button,
396
- .table-designer-sidebar__import-button,
397
- .table-designer-preview__copy,
398
- .table-designer-main__secondary,
399
- .table-designer-main__primary {
400
- align-items: center;
401
- border: 1px solid rgba(75, 71, 50, 0.2);
402
- display: inline-flex;
403
- font-family: var(--font-family-headline);
404
- font-size: 0.75rem;
405
- font-weight: 700;
406
- justify-content: center;
407
- letter-spacing: 0.12em;
408
- min-height: 42px;
409
- padding: 0 1rem;
410
- text-transform: uppercase;
411
- transition:
412
- background-color var(--transition-fast),
413
- border-color var(--transition-fast),
414
- color var(--transition-fast),
415
- opacity var(--transition-fast);
416
- }
417
-
418
- .table-designer-sidebar__new-button,
419
- .table-designer-main__primary {
420
- background: var(--color-primary-container);
421
- border-color: rgba(252, 227, 0, 0.35);
422
- color: var(--color-on-primary);
423
- }
424
-
425
- .table-designer-preview__copy,
426
- .table-designer-sidebar__import-button,
427
- .table-designer-main__secondary {
428
- background: var(--color-surface-container-lowest);
429
- color: var(--color-on-surface);
430
- }
431
-
432
- .table-designer-sidebar__new-button:hover,
433
- .table-designer-main__primary:hover {
434
- filter: brightness(1.04);
435
- }
436
-
437
- .table-designer-preview__copy:hover,
438
- .table-designer-sidebar__import-button:hover,
439
- .table-designer-main__secondary:hover {
440
- background: var(--color-surface-highest);
441
- border-color: rgba(252, 227, 0, 0.24);
442
- color: var(--color-primary-container);
443
- }
444
-
445
397
  .table-designer-sidebar__file-input {
446
398
  display: none;
447
399
  }
448
400
 
449
- .table-designer-main__primary.is-disabled,
450
- .table-designer-main__primary:disabled {
451
- cursor: not-allowed;
452
- opacity: 0.45;
453
- }
454
-
455
401
  .table-designer-sidebar__search {
456
402
  align-items: center;
457
403
  background: var(--color-surface-container-lowest);
458
404
  border: 1px solid rgba(75, 71, 50, 0.18);
405
+ box-sizing: border-box;
406
+ min-height: var(--control-height);
459
407
  margin: var(--spacing-4) var(--spacing-3) 0;
460
408
  border-bottom: 1px solid rgba(75, 71, 50, 0.18);
461
409
  display: flex;
462
410
  gap: var(--spacing-3);
463
- padding: 0 var(--spacing-4);
411
+ padding: 0 var(--control-padding-inline);
464
412
  }
465
413
 
466
414
  .table-designer-sidebar__search-input,
@@ -501,7 +449,7 @@ select.table-designer-field {
501
449
  color: var(--color-on-surface);
502
450
  flex: 1;
503
451
  font-size: 0.875rem;
504
- height: 48px;
452
+ height: calc(var(--control-height) - 2px);
505
453
  padding: 0;
506
454
  }
507
455
 
@@ -599,6 +547,14 @@ select.table-designer-field {
599
547
  padding: var(--spacing-5);
600
548
  }
601
549
 
550
+ .table-designer-preview.is-collapsed .table-designer-preview__header {
551
+ border-bottom: none;
552
+ }
553
+
554
+ .table-designer-preview.is-collapsed {
555
+ height: auto;
556
+ }
557
+
602
558
  .table-designer-main__title-row {
603
559
  align-items: center;
604
560
  display: flex;
@@ -626,18 +582,18 @@ select.table-designer-field {
626
582
  gap: var(--spacing-3);
627
583
  }
628
584
 
629
- .table-designer-fill-toggle {
585
+ .table-designer-preview__actions {
630
586
  align-items: center;
587
+ display: flex;
588
+ flex-wrap: wrap;
589
+ gap: var(--spacing-3);
590
+ }
591
+
592
+ .table-designer-fill-toggle {
593
+ background: var(--color-surface-container);
631
594
  border: 1px solid rgba(75, 71, 50, 0.18);
632
595
  color: var(--color-on-surface);
633
- display: inline-flex;
634
596
  gap: 0.75rem;
635
- min-height: 42px;
636
- padding: 0 0.875rem;
637
- }
638
-
639
- .table-designer-fill-toggle input {
640
- accent-color: var(--color-primary-container);
641
597
  }
642
598
 
643
599
  .table-designer-fill-toggle.is-disabled {
@@ -758,14 +714,14 @@ select.table-designer-field {
758
714
  grid-template-columns:
759
715
  minmax(12rem, 1.5fr)
760
716
  minmax(8rem, 0.9fr)
761
- minmax(5.5rem, 0.7fr)
762
- minmax(5.5rem, 0.7fr)
717
+ minmax(6.5rem, 0.9fr)
718
+ minmax(5.5rem, 0.9fr)
763
719
  minmax(6rem, 0.7fr)
764
720
  minmax(10rem, 1fr)
765
721
  minmax(10rem, 1fr)
766
722
  minmax(10rem, 1fr)
767
- 44px;
768
- min-width: 76rem;
723
+ minmax(7rem, max-content);
724
+ min-width: 82rem;
769
725
  padding: var(--spacing-3);
770
726
  }
771
727
 
@@ -788,42 +744,39 @@ select.table-designer-field {
788
744
  }
789
745
 
790
746
  .table-designer-field {
791
- min-height: 42px;
747
+ height: var(--control-height);
748
+ min-height: var(--control-height);
792
749
  padding: 0 0.75rem;
793
750
  }
794
751
 
795
752
  .table-designer-check {
796
- align-items: center;
753
+ background: var(--color-surface-container);
754
+ border: 1px solid rgba(75, 71, 50, 0.18);
797
755
  color: rgba(229, 226, 225, 0.75);
798
- display: inline-flex;
799
756
  font-size: 0.75rem;
800
757
  gap: 0.5rem;
801
- min-height: 42px;
802
758
  }
803
759
 
804
- .table-designer-check input {
805
- accent-color: var(--color-primary-container);
760
+ .table-designer-checkbox-override {
761
+ background: var(--color-surface-container-lowest) !important;
762
+ background-color: var(--color-surface-container-lowest) !important;
763
+ background-image: none !important;
764
+ border: 1px solid rgba(75, 71, 50, 0.18) !important;
806
765
  }
807
766
 
808
- .table-designer-delete {
809
- align-items: center;
810
- background: transparent;
811
- border: 1px solid rgba(75, 71, 50, 0.18);
812
- color: rgba(229, 226, 225, 0.65);
813
- display: inline-flex;
814
- height: 42px;
815
- justify-content: center;
816
- transition:
817
- border-color var(--transition-fast),
818
- color var(--transition-fast),
819
- background-color var(--transition-fast);
820
- width: 42px;
767
+ .table-designer-check input[type="checkbox"]:not(:checked),
768
+ .table-designer-fill-toggle input[type="checkbox"]:not(:checked),
769
+ .table-designer-checkbox-override input[type="checkbox"]:not(:checked) {
770
+ background: transparent !important;
771
+ background-color: transparent !important;
772
+ background-image: none !important;
821
773
  }
822
774
 
823
- .table-designer-delete:hover {
824
- background: rgba(147, 0, 10, 0.18);
825
- border-color: rgba(255, 180, 171, 0.2);
826
- color: var(--color-error);
775
+ .table-designer-check input[type="checkbox"]:checked,
776
+ .table-designer-fill-toggle input[type="checkbox"]:checked,
777
+ .table-designer-checkbox-override input[type="checkbox"]:checked {
778
+ background-color: var(--color-primary-container) !important;
779
+ border-color: var(--color-primary-container) !important;
827
780
  }
828
781
 
829
782
  .table-designer-preview__body {
@@ -894,14 +847,15 @@ select.table-designer-field {
894
847
  align-items: center;
895
848
  background: transparent;
896
849
  border: 0;
850
+ box-sizing: border-box;
897
851
  color: rgba(229, 226, 225, 0.6);
898
852
  display: inline-flex;
899
- height: 2rem;
853
+ height: var(--control-height);
900
854
  justify-content: center;
901
855
  transition:
902
856
  color var(--transition-fast),
903
857
  background-color var(--transition-fast);
904
- width: 2rem;
858
+ width: var(--control-height);
905
859
  }
906
860
 
907
861
  .query-history-icon-button:hover,
@@ -911,14 +865,18 @@ select.table-designer-field {
911
865
  }
912
866
 
913
867
  .query-history-tab {
868
+ align-items: center;
914
869
  background: transparent;
915
870
  border: 0;
916
871
  border-bottom: 1px solid transparent;
917
872
  color: rgba(205, 199, 171, 0.45);
873
+ display: inline-flex;
918
874
  font-family: var(--font-family-mono);
919
875
  font-size: var(--font-size-status);
876
+ height: var(--control-height);
877
+ justify-content: center;
920
878
  letter-spacing: 0.16em;
921
- padding: 0.35rem 0;
879
+ padding: 0 var(--spacing-1);
922
880
  text-transform: uppercase;
923
881
  transition:
924
882
  border-color var(--transition-fast),
@@ -41,99 +41,29 @@
41
41
  justify-content: flex-end;
42
42
  }
43
43
 
44
- .structure-graph__search {
44
+ .structure-graph__toolbar .standard-button,
45
+ .structure-graph__section-header .standard-button {
45
46
  align-items: center;
46
- background: rgba(12, 12, 10, 0.98);
47
- border: 1px solid rgba(138, 123, 52, 0.34);
48
- display: inline-flex;
49
- gap: 0.625rem;
50
- height: 2.75rem;
51
- min-width: min(100%, 22rem);
52
- padding: 0 0.875rem;
53
- transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
54
- }
55
-
56
- .structure-graph__search:focus-within {
57
- border-color: rgba(252, 227, 0, 0.56);
58
- box-shadow: 0 0 0 1px rgba(252, 227, 0, 0.18);
59
- }
60
-
61
- .structure-graph__search.is-miss {
62
- border-color: rgba(255, 180, 171, 0.3);
63
- box-shadow: 0 0 0 1px rgba(255, 180, 171, 0.1);
64
- }
65
-
66
- .structure-graph__search-icon {
67
- color: rgba(244, 239, 232, 0.56);
68
- font-size: 1rem;
69
- }
70
-
71
- .structure-graph__search-input {
72
- -webkit-appearance: none;
73
- appearance: none;
74
- background: transparent;
75
- background-color: transparent !important;
76
- background-image: none !important;
77
- border: 0;
78
- border-color: transparent;
79
- border-radius: 0;
80
- box-shadow: none !important;
81
- color: var(--color-on-surface);
82
- flex: 1;
83
- font-family: var(--font-family-mono);
84
- font-size: 0.75rem;
85
- letter-spacing: 0.12em;
86
- min-width: 0;
87
- outline: 0;
88
- padding: 0;
89
- text-transform: uppercase;
90
- }
91
-
92
- .structure-graph__search-input::placeholder {
93
- color: rgba(231, 223, 189, 0.38);
94
- }
95
-
96
- .structure-graph__search-input::-webkit-search-decoration,
97
- .structure-graph__search-input::-webkit-search-cancel-button,
98
- .structure-graph__search-input::-webkit-search-results-button,
99
- .structure-graph__search-input::-webkit-search-results-decoration {
100
- -webkit-appearance: none;
101
- appearance: none;
102
- }
103
-
104
- .structure-graph__button {
105
- align-items: center;
106
- background: rgba(17, 17, 15, 0.94);
107
- border: 1px solid rgba(138, 123, 52, 0.24);
108
- color: rgba(244, 239, 232, 0.9);
109
47
  display: inline-flex;
48
+ flex-shrink: 0;
110
49
  gap: 0.5rem;
111
- height: 2.75rem;
112
50
  justify-content: center;
113
- padding: 0 0.875rem;
114
- text-transform: uppercase;
115
- transition: background-color var(--transition-fast), color var(--transition-fast),
116
- border-color var(--transition-fast);
117
51
  }
118
52
 
119
- .structure-graph__button:hover {
120
- background: rgba(44, 42, 35, 0.96);
121
- border-color: rgba(252, 227, 0, 0.34);
122
- color: #fff6ae;
53
+ .structure-graph__toolbar .standard-button:hover {
54
+ background: var(--color-surface-container-highest);
123
55
  }
124
56
 
125
- .structure-graph__button.is-active {
126
- background: rgba(252, 227, 0, 0.16);
127
- border-color: rgba(252, 227, 0, 0.4);
128
- color: #fff6ae;
57
+ .structure-graph__toolbar .standard-button.is-active {
58
+ background: rgba(252, 227, 0, 0.12);
59
+ border-color: rgba(252, 227, 0, 0.38);
60
+ color: var(--color-primary-container);
129
61
  }
130
62
 
131
- .structure-graph__button.is-disabled,
132
- .structure-graph__button:disabled {
133
- border-color: rgba(138, 123, 52, 0.16);
63
+ .structure-graph__toolbar .standard-button:disabled,
64
+ .structure-graph__section-header .standard-button:disabled {
65
+ border-color: rgba(75, 71, 50, 0.18);
134
66
  color: rgba(231, 223, 189, 0.34);
135
- cursor: default;
136
- opacity: 0.72;
137
67
  }
138
68
 
139
69
  .structure-graph__workspace {
@@ -290,6 +220,13 @@
290
220
  text-transform: uppercase;
291
221
  }
292
222
 
223
+ .structure-graph__section-header {
224
+ align-items: center;
225
+ display: flex;
226
+ gap: 0.75rem;
227
+ justify-content: space-between;
228
+ }
229
+
293
230
  .structure-graph__column-list {
294
231
  display: flex;
295
232
  flex-direction: column;
@@ -25,6 +25,8 @@
25
25
  --font-size-micro: 9px;
26
26
  --font-size-label: 11px;
27
27
  --font-size-icon: 18px;
28
+ --control-height: 36px;
29
+ --control-padding-inline: 12px;
28
30
  --spacing-1: 4px;
29
31
  --spacing-2: 8px;
30
32
  --spacing-3: 12px;
@@ -55,6 +55,10 @@
55
55
  flex: 0 0 34%;
56
56
  }
57
57
 
58
+ .table-designer-workspace__bottom.is-collapsed {
59
+ flex: 0 0 auto;
60
+ }
61
+
58
62
  .landing-view {
59
63
  align-items: center;
60
64
  display: flex;
@@ -206,11 +210,13 @@
206
210
  }
207
211
 
208
212
  .charts-detail-shell__header {
209
- align-items: end;
210
213
  display: flex;
211
- flex-wrap: wrap;
214
+ flex-direction: column;
212
215
  gap: var(--spacing-4);
213
- justify-content: space-between;
216
+ }
217
+
218
+ .charts-detail-shell__title {
219
+ min-width: 0;
214
220
  }
215
221
 
216
222
  .charts-detail-shell__controls {
@@ -218,47 +224,49 @@
218
224
  display: flex;
219
225
  flex-wrap: wrap;
220
226
  gap: var(--spacing-3);
227
+ justify-content: space-between;
221
228
  }
222
229
 
223
- .charts-detail-shell__button {
224
- background: var(--color-surface-container);
225
- border: 1px solid rgba(75, 71, 50, 0.2);
226
- color: var(--color-on-surface);
227
- font-family: var(--font-family-mono);
228
- font-size: 0.625rem;
229
- font-weight: 700;
230
- letter-spacing: 0.16em;
231
- padding: 0.75rem 1rem;
232
- }
233
-
234
- .charts-detail-shell__button--primary {
235
- background: var(--color-primary-container);
236
- border-color: transparent;
237
- color: var(--color-on-primary);
230
+ .charts-detail-shell__controls-group {
231
+ align-items: end;
232
+ display: flex;
233
+ flex-wrap: wrap;
234
+ gap: var(--spacing-3);
238
235
  }
239
236
 
240
- .charts-detail-shell__button[disabled] {
241
- cursor: not-allowed;
242
- opacity: 0.5;
237
+ .charts-detail-shell__controls-group--end {
238
+ justify-content: flex-end;
239
+ margin-left: auto;
243
240
  }
244
241
 
245
242
  .charts-height-toggle {
246
243
  background: var(--color-surface-container-low);
247
244
  border: 1px solid rgba(75, 71, 50, 0.18);
248
245
  display: inline-flex;
249
- gap: 0.25rem;
250
- padding: 0.25rem;
246
+ gap: 0;
247
+ height: var(--control-height);
248
+ overflow: hidden;
251
249
  }
252
250
 
253
251
  .charts-height-toggle__button {
252
+ align-items: center;
254
253
  background: transparent;
255
- border: 1px solid transparent;
254
+ border: none;
255
+ box-sizing: border-box;
256
256
  color: var(--color-on-surface-variant);
257
+ display: inline-flex;
257
258
  font-family: var(--font-family-mono);
258
259
  font-size: 0.625rem;
259
260
  font-weight: 700;
261
+ height: var(--control-height);
262
+ justify-content: center;
263
+ line-height: 1;
260
264
  letter-spacing: 0.16em;
261
- padding: 0.55rem 0.8rem;
265
+ padding: 0 1rem;
266
+ }
267
+
268
+ .charts-height-toggle__button + .charts-height-toggle__button {
269
+ border-left: 1px solid rgba(75, 71, 50, 0.18);
262
270
  }
263
271
 
264
272
  .charts-height-toggle__button.is-active {
@@ -310,17 +318,6 @@
310
318
  min-height: var(--query-chart-height);
311
319
  }
312
320
 
313
- .query-chart-card__action {
314
- background: var(--color-surface-container);
315
- border: 1px solid rgba(75, 71, 50, 0.18);
316
- color: var(--color-on-surface);
317
- font-family: var(--font-family-mono);
318
- font-size: 0.625rem;
319
- font-weight: 700;
320
- letter-spacing: 0.14em;
321
- padding: 0.55rem 0.85rem;
322
- }
323
-
324
321
  .query-chart-card__results {
325
322
  background: var(--color-surface-container-lowest);
326
323
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqlite-hub",
3
- "version": "0.7.0",
3
+ "version": "0.8.7",
4
4
  "description": "SQLite-only local management app backend and SPA shell",
5
5
  "main": "server/server.js",
6
6
  "bin": {
@@ -12,6 +12,73 @@ class OverviewService {
12
12
  this.connectionManager = connectionManager;
13
13
  }
14
14
 
15
+ getSchemaMapPreview(schema) {
16
+ const tables = schema?.tables ?? [];
17
+ const indexes = schema?.indexes ?? [];
18
+ const tableNames = new Set(tables.map((table) => table.name));
19
+ const adjacency = new Map(tables.map((table) => [table.name, new Set()]));
20
+ let relationshipCount = 0;
21
+
22
+ tables.forEach((table) => {
23
+ (table.foreignKeys ?? []).forEach((foreignKey) => {
24
+ if (!tableNames.has(foreignKey.referencedTable)) {
25
+ return;
26
+ }
27
+
28
+ relationshipCount += foreignKey.mappings?.length ?? 0;
29
+ adjacency.get(table.name)?.add(foreignKey.referencedTable);
30
+ adjacency.get(foreignKey.referencedTable)?.add(table.name);
31
+ });
32
+ });
33
+
34
+ let fkClusters = 0;
35
+ let isolatedTables = 0;
36
+ const visited = new Set();
37
+
38
+ tables.forEach((table) => {
39
+ if (visited.has(table.name)) {
40
+ return;
41
+ }
42
+
43
+ const stack = [table.name];
44
+ let componentHasRelationships = false;
45
+
46
+ visited.add(table.name);
47
+
48
+ while (stack.length) {
49
+ const current = stack.pop();
50
+ const neighbors = adjacency.get(current) ?? new Set();
51
+
52
+ if (neighbors.size > 0) {
53
+ componentHasRelationships = true;
54
+ }
55
+
56
+ neighbors.forEach((neighbor) => {
57
+ if (visited.has(neighbor)) {
58
+ return;
59
+ }
60
+
61
+ visited.add(neighbor);
62
+ stack.push(neighbor);
63
+ });
64
+ }
65
+
66
+ if (componentHasRelationships) {
67
+ fkClusters += 1;
68
+ } else {
69
+ isolatedTables += 1;
70
+ }
71
+ });
72
+
73
+ return {
74
+ tableCount: tables.length,
75
+ indexCount: indexes.length,
76
+ relationshipCount,
77
+ fkClusters,
78
+ isolatedTables,
79
+ };
80
+ }
81
+
15
82
  safePragmaValue(db, pragmaName) {
16
83
  const row = db.prepare(`PRAGMA ${pragmaName}`).get();
17
84
  return row ? Object.values(row)[0] : null;
@@ -78,6 +145,7 @@ class OverviewService {
78
145
  indexes: schema.indexes.length,
79
146
  triggers: schema.triggers.length,
80
147
  },
148
+ schemaMap: this.getSchemaMapPreview(schema),
81
149
  topTablesByRowCount: [...schema.tables]
82
150
  .sort((left, right) => (right.rowCount ?? 0) - (left.rowCount ?? 0))
83
151
  .slice(0, 10)