@antelopejs/dms-database 0.0.13 → 0.1.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 (173) hide show
  1. package/README.md +30 -5
  2. package/dist/db/models/query_history.model.d.ts +1 -0
  3. package/dist/db/models/query_history.model.js +6 -0
  4. package/dist/db/models/query_history.model.js.map +1 -1
  5. package/dist/db/tables/query_history.table.d.ts +3 -0
  6. package/dist/db/tables/query_history.table.js +12 -0
  7. package/dist/db/tables/query_history.table.js.map +1 -1
  8. package/dist/db/tables/saved_queries.table.d.ts +1 -0
  9. package/dist/db/tables/saved_queries.table.js +4 -0
  10. package/dist/db/tables/saved_queries.table.js.map +1 -1
  11. package/dist/i18n/messages.d.ts +39 -0
  12. package/dist/i18n/messages.js +64 -0
  13. package/dist/i18n/messages.js.map +1 -0
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +1 -7
  16. package/dist/index.js.map +1 -1
  17. package/dist/module.d.ts +11 -0
  18. package/dist/module.js +55 -0
  19. package/dist/module.js.map +1 -0
  20. package/dist/pages/data.d.ts +1 -1
  21. package/dist/pages/data.js +9 -6
  22. package/dist/pages/data.js.map +1 -1
  23. package/dist/pages/diagram.d.ts +9 -0
  24. package/dist/pages/diagram.js +45 -0
  25. package/dist/pages/diagram.js.map +1 -0
  26. package/dist/pages/index.d.ts +1 -0
  27. package/dist/pages/index.js +1 -0
  28. package/dist/pages/index.js.map +1 -1
  29. package/dist/pages/overview.d.ts +4 -1
  30. package/dist/pages/overview.js +113 -6
  31. package/dist/pages/overview.js.map +1 -1
  32. package/dist/pages/query.d.ts +1 -1
  33. package/dist/pages/query.js +22 -6
  34. package/dist/pages/query.js.map +1 -1
  35. package/dist/pages/schemas.d.ts +2 -1
  36. package/dist/pages/schemas.js +143 -6
  37. package/dist/pages/schemas.js.map +1 -1
  38. package/dist/routes/data.d.ts +8 -0
  39. package/dist/routes/data.js +84 -21
  40. package/dist/routes/data.js.map +1 -1
  41. package/dist/routes/index.d.ts +1 -0
  42. package/dist/routes/index.js +1 -0
  43. package/dist/routes/index.js.map +1 -1
  44. package/dist/routes/overview.d.ts +12 -0
  45. package/dist/routes/overview.js +55 -0
  46. package/dist/routes/overview.js.map +1 -0
  47. package/dist/routes/query.d.ts +5 -1
  48. package/dist/routes/query.js +162 -27
  49. package/dist/routes/query.js.map +1 -1
  50. package/dist/routes/tables.d.ts +15 -12
  51. package/dist/routes/tables.js +95 -55
  52. package/dist/routes/tables.js.map +1 -1
  53. package/dist/service/catalog.d.ts +3 -0
  54. package/dist/service/catalog.js +26 -0
  55. package/dist/service/catalog.js.map +1 -0
  56. package/dist/service/health.d.ts +3 -3
  57. package/dist/service/health.js +17 -14
  58. package/dist/service/health.js.map +1 -1
  59. package/dist/service/introspect.d.ts +3 -1
  60. package/dist/service/introspect.js +131 -43
  61. package/dist/service/introspect.js.map +1 -1
  62. package/dist/service/overview.d.ts +9 -0
  63. package/dist/service/overview.js +113 -0
  64. package/dist/service/overview.js.map +1 -0
  65. package/dist/service/queryInspection.d.ts +15 -0
  66. package/dist/service/queryInspection.js +107 -0
  67. package/dist/service/queryInspection.js.map +1 -0
  68. package/dist/service/references.d.ts +9 -0
  69. package/dist/service/references.js +52 -0
  70. package/dist/service/references.js.map +1 -0
  71. package/dist/service/schemaFilters.d.ts +26 -0
  72. package/dist/service/schemaFilters.js +42 -0
  73. package/dist/service/schemaFilters.js.map +1 -0
  74. package/dist/service/stagedSerialization.d.ts +2 -0
  75. package/dist/service/stagedSerialization.js +38 -10
  76. package/dist/service/stagedSerialization.js.map +1 -1
  77. package/dist/service/types.d.ts +11 -1
  78. package/dist/types/constants.d.ts +2 -0
  79. package/dist/types/constants.js +3 -1
  80. package/dist/types/constants.js.map +1 -1
  81. package/dist/utils/query.d.ts +0 -2
  82. package/dist/utils/query.js +0 -20
  83. package/dist/utils/query.js.map +1 -1
  84. package/frontend-vue/app/{composables → build/composables}/useDataBrowserGrid.ts +65 -50
  85. package/frontend-vue/app/build/composables/useDataBrowserTabs.ts +366 -0
  86. package/frontend-vue/app/build/composables/useDatabaseHealth.ts +50 -0
  87. package/frontend-vue/app/build/composables/useDatabaseSchemas.ts +140 -0
  88. package/frontend-vue/app/{composables → build/composables}/useDiagramPersistence.ts +47 -39
  89. package/frontend-vue/app/build/composables/useQueryRuntime.ts +217 -0
  90. package/frontend-vue/app/build/composables/useQueryStore.ts +162 -0
  91. package/frontend-vue/app/build/data/cellValues.ts +132 -0
  92. package/frontend-vue/app/build/data/instanceOptions.ts +36 -0
  93. package/frontend-vue/app/build/data/pickerMenus.ts +175 -0
  94. package/frontend-vue/app/build/data/recentTables.ts +48 -0
  95. package/frontend-vue/app/build/data/stagedEdits.ts +117 -0
  96. package/frontend-vue/app/build/data/stagedWrites.ts +64 -0
  97. package/frontend-vue/app/build/data/useStagedSave.ts +298 -0
  98. package/frontend-vue/app/build/diagram/autosave.ts +72 -0
  99. package/frontend-vue/app/build/diagram/graph.ts +585 -0
  100. package/frontend-vue/app/build/diagram/history.ts +178 -0
  101. package/frontend-vue/app/build/diagram/shortcuts.ts +62 -0
  102. package/frontend-vue/app/build/diagram/sync.ts +137 -0
  103. package/frontend-vue/app/build/query/completion.ts +100 -0
  104. package/frontend-vue/app/build/query/csv.ts +32 -0
  105. package/frontend-vue/app/build/query/examples.ts +38 -0
  106. package/frontend-vue/app/build/query/runs.ts +168 -0
  107. package/frontend-vue/app/build/query/tableColumns.ts +35 -0
  108. package/frontend-vue/app/build/query/target.ts +143 -0
  109. package/frontend-vue/app/build/schemas/filterState.ts +128 -0
  110. package/frontend-vue/app/build/schemas/useSchemasListing.ts +62 -0
  111. package/frontend-vue/app/build/utils/databaseLinks.ts +98 -0
  112. package/frontend-vue/app/build/utils/fieldTypes.ts +198 -0
  113. package/frontend-vue/app/build/utils/relativeTime.ts +19 -0
  114. package/frontend-vue/app/{utils → build/utils}/stagedSerialization.ts +7 -1
  115. package/frontend-vue/app/components/ConnectionStatus.vue +122 -0
  116. package/frontend-vue/app/components/DataBrowser.vue +126 -0
  117. package/frontend-vue/app/components/DataBrowserSidebar.vue +293 -210
  118. package/frontend-vue/app/components/DataBrowserTabBar.vue +185 -93
  119. package/frontend-vue/app/components/DataFilterBar.vue +163 -0
  120. package/frontend-vue/app/components/DataGrid.vue +737 -499
  121. package/frontend-vue/app/components/DataGridCell.vue +125 -77
  122. package/frontend-vue/app/components/DataGridHeaderCell.vue +119 -81
  123. package/frontend-vue/app/components/DiagramNoteNode.vue +81 -63
  124. package/frontend-vue/app/components/DiagramRelationEdge.vue +57 -27
  125. package/frontend-vue/app/components/DiagramStubNode.vue +16 -17
  126. package/frontend-vue/app/components/DiagramTableNode.vue +106 -68
  127. package/frontend-vue/app/components/InstancePicker.vue +195 -0
  128. package/frontend-vue/app/components/JsonCellPanel.vue +30 -29
  129. package/frontend-vue/app/components/QueryBuilderPanel.vue +290 -238
  130. package/frontend-vue/app/components/QueryConsole.vue +726 -0
  131. package/frontend-vue/app/components/QueryLibrary.vue +314 -0
  132. package/frontend-vue/app/components/QueryResultPanel.vue +556 -126
  133. package/frontend-vue/app/components/RowDrawer.vue +520 -0
  134. package/frontend-vue/app/components/SchemaDiagram.vue +1016 -1051
  135. package/frontend-vue/app/components/SchemaPicker.vue +86 -0
  136. package/frontend-vue/app/components/SchemasFilterBar.vue +201 -0
  137. package/frontend-vue/app/components/TableInspector.vue +741 -0
  138. package/frontend-vue/app/config/shortcuts-registry.ts +65 -0
  139. package/frontend-vue/dms.frontend.ts +5 -14
  140. package/frontend-vue/i18n/locales/database-en-GB.json +526 -193
  141. package/frontend-vue/i18n/locales/database-fr-FR.json +528 -195
  142. package/frontend-vue/package.json +2 -1
  143. package/frontend-vue/pnpm-lock.yaml +2601 -858
  144. package/frontend-vue/pnpm-workspace.yaml +1 -1
  145. package/frontend-vue/tests/dataBrowser.test.ts +206 -0
  146. package/frontend-vue/tests/diagram.test.ts +516 -0
  147. package/frontend-vue/tests/helpers.test.ts +205 -0
  148. package/frontend-vue/tests/instanceOptions.test.ts +53 -0
  149. package/frontend-vue/tests/locales.test.ts +56 -0
  150. package/frontend-vue/tests/persistence.test.ts +106 -5
  151. package/frontend-vue/tests/pickerMenus.test.ts +254 -0
  152. package/frontend-vue/tests/queryConsole.test.ts +282 -0
  153. package/frontend-vue/tests/queryRuntime.test.ts +2 -2
  154. package/frontend-vue/tests/registration.test.ts +36 -25
  155. package/frontend-vue/tests/schemasFilters.test.ts +115 -0
  156. package/package.json +9 -6
  157. package/frontend-vue/app/components/QueryFavoritesPanel.vue +0 -127
  158. package/frontend-vue/app/components/QueryHistoryPanel.vue +0 -134
  159. package/frontend-vue/app/components/SchemaTableInspector.vue +0 -278
  160. package/frontend-vue/app/composables/useDataBrowserTabs.ts +0 -255
  161. package/frontend-vue/app/composables/useDatabaseHealth.ts +0 -50
  162. package/frontend-vue/app/composables/useDatabaseSchemas.ts +0 -92
  163. package/frontend-vue/app/composables/useQueryRuntime.ts +0 -118
  164. package/frontend-vue/app/composables/useQueryStore.ts +0 -117
  165. package/frontend-vue/app/composables/useTableViewRowClick.ts +0 -22
  166. package/frontend-vue/app/custom-pages/database/data.vue +0 -41
  167. package/frontend-vue/app/custom-pages/database/overview.vue +0 -367
  168. package/frontend-vue/app/custom-pages/database/query.vue +0 -436
  169. package/frontend-vue/app/custom-pages/database/schemas.vue +0 -218
  170. package/frontend-vue/app/utils/databaseFieldModifiers.ts +0 -33
  171. package/frontend-vue/app/utils/databaseFieldTypeIcons.ts +0 -224
  172. package/frontend-vue/app/utils/dmsTableView.ts +0 -83
  173. package/frontend-vue/app/utils/relativeTime.ts +0 -18
@@ -0,0 +1,86 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ ALL_ICON,
4
+ PICK_ALL,
5
+ PICKER_MENU_UI,
6
+ SCHEMA_ICON,
7
+ schemaMenu,
8
+ } from '../build/data/pickerMenus'
9
+ import { sortNames } from '../build/data/instanceOptions'
10
+
11
+ // A schema picked from a searchable menu, shared by the Schemas page's filter
12
+ // bar and the data browser's sidebar: "All schemas" pinned first when the
13
+ // page can list every schema, and at most a hundred others with how many
14
+ // matched.
15
+
16
+ const props = defineProps<{
17
+ /** The schema picked; null for every schema (with `allowAll`) or none yet. */
18
+ modelValue: string | null
19
+ /** Every registered schema id, in any order. */
20
+ schemaIds: readonly string[]
21
+ /** Offers "All schemas", pinned first; otherwise a schema is required. */
22
+ allowAll?: boolean
23
+ /** The schema list is being read. */
24
+ loading?: boolean
25
+ disabled?: boolean
26
+ /** Shown while no schema is picked, without `allowAll`. */
27
+ placeholder?: string
28
+ }>()
29
+
30
+ const emit = defineEmits<{ 'update:modelValue': [id: string | null] }>()
31
+
32
+ const { t, n } = useI18n()
33
+ const search = ref('')
34
+ const ids = computed(() => sortNames(props.schemaIds))
35
+
36
+ const items = computed(() =>
37
+ schemaMenu({
38
+ ids: ids.value,
39
+ search: search.value,
40
+ allLabel: props.allowAll ? t('dms_database.pickers.schema.all') : null,
41
+ more: (shown, total) =>
42
+ t('dms_database.pickers.schema.more', {
43
+ shown: n(shown),
44
+ total: n(total),
45
+ }),
46
+ }),
47
+ )
48
+
49
+ function pick(value: unknown) {
50
+ if (typeof value !== 'string') return
51
+ emit('update:modelValue', value === PICK_ALL ? null : value)
52
+ }
53
+ </script>
54
+
55
+ <template>
56
+ <USelectMenu
57
+ v-model:search-term="search"
58
+ :model-value="modelValue ?? (allowAll ? PICK_ALL : undefined)"
59
+ :items="items"
60
+ value-key="value"
61
+ ignore-filter
62
+ :search-input="{
63
+ placeholder: t('dms_database.pickers.schema.find'),
64
+ icon: 'i-ph-magnifying-glass',
65
+ }"
66
+ :icon="modelValue || !allowAll ? SCHEMA_ICON : ALL_ICON"
67
+ :loading="loading"
68
+ :disabled="disabled"
69
+ :aria-label="t('dms_database.pickers.schema.label')"
70
+ size="sm"
71
+ :ui="PICKER_MENU_UI"
72
+ data-dms-database-schema-picker
73
+ @update:model-value="pick"
74
+ >
75
+ <span v-if="modelValue" class="truncate font-mono">{{ modelValue }}</span>
76
+ <span v-else-if="allowAll" class="truncate">
77
+ {{ t('dms_database.pickers.schema.all') }}
78
+ </span>
79
+ <span v-else class="text-dimmed truncate">
80
+ {{ placeholder ?? t('dms_database.pickers.schema.placeholder') }}
81
+ </span>
82
+ <template #empty>
83
+ {{ t('dms_database.pickers.schema.no_match') }}
84
+ </template>
85
+ </USelectMenu>
86
+ </template>
@@ -0,0 +1,201 @@
1
+ <script setup lang="ts">
2
+ import { onKeyStroke, watchDebounced } from '@vueuse/core'
3
+ import { useDatabaseSchemas } from '../build/composables/useDatabaseSchemas'
4
+ import {
5
+ EMPTY_FILTER_STATE,
6
+ HAS_FLAGS,
7
+ isFiltered,
8
+ toggleHas,
9
+ withFilterState,
10
+ withScope,
11
+ type HasFlag,
12
+ type InstanceChoice,
13
+ type SchemasFilterState,
14
+ } from '../build/schemas/filterState'
15
+ import { useSchemasListing } from '../build/schemas/useSchemasListing'
16
+ import InstancePicker from './InstancePicker.vue'
17
+ import SchemaPicker from './SchemaPicker.vue'
18
+
19
+ // The Schemas page's filter bar, above its table view: a schema and an
20
+ // instance picked from searchable menus (SchemaPicker, InstancePicker, shared
21
+ // with the data browser), a table or column name, and structure chips. Its
22
+ // state lives in the URL (see filterState.ts), which the table view reads as
23
+ // hidden filters: a filtered list can be shared and reloaded.
24
+
25
+ const SEARCH_DEBOUNCE_MS = 250
26
+
27
+ const HAS_ICONS: Record<HasFlag, string> = {
28
+ relations: 'i-ph-flow-arrow',
29
+ modifiers: 'i-ph-sliders-horizontal',
30
+ empty: 'i-ph-circle-dashed',
31
+ }
32
+
33
+ const { t, n } = useI18n()
34
+ const route = useDmsRoute()
35
+ const router = useDmsRouter()
36
+ const { schemas, isSettled: schemasSettled } = useDatabaseSchemas()
37
+ const schemaIds = computed(() => schemas.value.map((schema) => schema.id))
38
+ const listing = useSchemasListing()
39
+ const state = listing.state
40
+
41
+ function commit(next: SchemasFilterState) {
42
+ router.replace({ query: withFilterState(route.query, next) })
43
+ }
44
+
45
+ const filtered = computed(() => isFiltered(state.value))
46
+
47
+ function clearAll() {
48
+ search.value = ''
49
+ commit(EMPTY_FILTER_STATE)
50
+ }
51
+
52
+ function pickSchema(id: string | null) {
53
+ commit(withScope(state.value, id))
54
+ }
55
+
56
+ function pickInstance(instance: InstanceChoice) {
57
+ commit({ ...state.value, instance })
58
+ }
59
+
60
+ // --- table or column name ---
61
+ const search = ref(state.value.q)
62
+ const searchInput = useTemplateRef<{ inputRef?: HTMLInputElement }>(
63
+ 'searchInput',
64
+ )
65
+
66
+ watchDebounced(
67
+ search,
68
+ (value) => {
69
+ if (value.trim() !== state.value.q) commit({ ...state.value, q: value })
70
+ },
71
+ { debounce: SEARCH_DEBOUNCE_MS },
72
+ )
73
+
74
+ // The URL changed by itself (Clear, Back, a link): the field follows.
75
+ watch(
76
+ () => state.value.q,
77
+ (q) => {
78
+ if (q !== search.value.trim()) search.value = q
79
+ },
80
+ )
81
+
82
+ function clearSearch() {
83
+ search.value = ''
84
+ commit({ ...state.value, q: '' })
85
+ }
86
+
87
+ onKeyStroke('/', (event) => {
88
+ const target = event.target as HTMLElement | null
89
+ if (target?.closest('input, textarea, select, [contenteditable=true]')) return
90
+ if (event.metaKey || event.ctrlKey || event.altKey) return
91
+ event.preventDefault()
92
+ searchInput.value?.inputRef?.focus()
93
+ })
94
+
95
+ // --- structure chips and the count ---
96
+ const chips = computed(() =>
97
+ HAS_FLAGS.map((flag) => ({
98
+ flag,
99
+ label: t(`dms_database.schemas.filters.has.${flag}`),
100
+ hint: t(`dms_database.schemas.filters.has_hint.${flag}`),
101
+ icon: HAS_ICONS[flag],
102
+ active: state.value.has.includes(flag),
103
+ })),
104
+ )
105
+
106
+ const count = computed(() => {
107
+ if (listing.all.value === null) return null
108
+ return t('dms_database.schemas.filters.count', {
109
+ shown: n(listing.total.value),
110
+ total: n(listing.all.value),
111
+ })
112
+ })
113
+ </script>
114
+
115
+ <template>
116
+ <div
117
+ class="flex flex-wrap items-center gap-2"
118
+ role="search"
119
+ :aria-label="t('dms_database.schemas.filters.label')"
120
+ data-dms-database-schemas-filter-bar
121
+ >
122
+ <SchemaPicker
123
+ :model-value="state.scope"
124
+ :schema-ids="schemaIds"
125
+ allow-all
126
+ :loading="!schemasSettled"
127
+ class="w-[calc(50%-0.25rem)] sm:w-48"
128
+ @update:model-value="pickSchema"
129
+ />
130
+
131
+ <InstancePicker
132
+ :model-value="state.instance"
133
+ :schema="state.scope"
134
+ class="w-[calc(50%-0.25rem)] sm:w-48"
135
+ @update:model-value="pickInstance"
136
+ />
137
+
138
+ <UInput
139
+ ref="searchInput"
140
+ v-model="search"
141
+ icon="i-ph-magnifying-glass"
142
+ size="sm"
143
+ class="w-full sm:w-auto sm:min-w-56 sm:max-w-xs sm:flex-1"
144
+ :placeholder="t('dms_database.schemas.search')"
145
+ :aria-label="t('dms_database.schemas.search')"
146
+ @keydown.esc="clearSearch"
147
+ >
148
+ <template #trailing>
149
+ <UButton
150
+ v-if="search"
151
+ icon="i-ph-x"
152
+ color="neutral"
153
+ variant="link"
154
+ size="xs"
155
+ :aria-label="t('dms_database.schemas.filters.clear')"
156
+ @click="clearSearch"
157
+ />
158
+ <UKbd v-else value="/" size="sm" />
159
+ </template>
160
+ </UInput>
161
+
162
+ <div class="flex flex-wrap items-center gap-1.5">
163
+ <UButton
164
+ v-for="chip in chips"
165
+ :key="chip.flag"
166
+ :icon="chip.icon"
167
+ :label="chip.label"
168
+ :title="chip.hint"
169
+ :color="chip.active ? 'primary' : 'neutral'"
170
+ :variant="chip.active ? 'soft' : 'outline'"
171
+ :aria-pressed="chip.active"
172
+ size="sm"
173
+ class="rounded-full"
174
+ @click="commit(toggleHas(state, chip.flag))"
175
+ />
176
+ </div>
177
+
178
+ <div
179
+ v-if="filtered"
180
+ class="text-muted ms-auto flex items-center gap-1 text-xs"
181
+ role="status"
182
+ >
183
+ <span
184
+ v-if="count"
185
+ class="tabular-nums"
186
+ :class="{ 'opacity-60': listing.status.value === 'pending' }"
187
+ >
188
+ {{ count }}
189
+ </span>
190
+ <span v-if="count" aria-hidden="true">·</span>
191
+ <UButton
192
+ :label="t('dms_database.schemas.filters.clear')"
193
+ color="neutral"
194
+ variant="link"
195
+ size="xs"
196
+ class="px-0"
197
+ @click="clearAll"
198
+ />
199
+ </div>
200
+ </div>
201
+ </template>