@antelopejs/dms-database 0.1.1 → 0.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.
- package/README.md +1 -1
- package/dist/pages/schemas.js +2 -1
- package/dist/pages/schemas.js.map +1 -1
- package/dist/routes/tables.d.ts +1 -0
- package/dist/routes/tables.js +35 -10
- package/dist/routes/tables.js.map +1 -1
- package/frontend-vue/app/build/composables/useDataBrowserGrid.ts +4 -38
- package/frontend-vue/app/build/composables/useDatabaseHealth.ts +7 -4
- package/frontend-vue/app/build/composables/useDatabaseSchemas.ts +1 -2
- package/frontend-vue/app/build/composables/useDiagramPersistence.ts +49 -16
- package/frontend-vue/app/build/composables/useQueryStore.ts +59 -27
- package/frontend-vue/app/build/composables/useTableCounts.ts +50 -0
- package/frontend-vue/app/build/query/runs.ts +7 -27
- package/frontend-vue/app/build/schemas/useSchemasListing.ts +10 -33
- package/frontend-vue/app/components/ConnectionStatus.vue +14 -11
- package/frontend-vue/app/components/DataBrowserSidebar.vue +20 -42
- package/frontend-vue/app/components/DataBrowserTabBar.vue +1 -1
- package/frontend-vue/app/components/DataGrid.vue +43 -89
- package/frontend-vue/app/components/InstancePicker.vue +63 -55
- package/frontend-vue/app/components/QueryConsole.vue +47 -37
- package/frontend-vue/app/components/QueryLibrary.vue +20 -17
- package/frontend-vue/app/components/RowDrawer.vue +15 -18
- package/frontend-vue/app/components/SchemaDiagram.vue +7 -7
- package/frontend-vue/app/components/TableInspector.vue +134 -88
- package/frontend-vue/package.json +2 -1
- package/frontend-vue/pnpm-lock.yaml +883 -2587
- package/frontend-vue/tests/fixtures/inertia.ts +8 -0
- package/frontend-vue/tests/fixtures/serverRender.ts +219 -0
- package/frontend-vue/tests/fixtures/vueI18n.ts +4 -0
- package/frontend-vue/tests/helpers.test.ts +1 -0
- package/frontend-vue/tests/locales.test.ts +24 -0
- package/frontend-vue/tests/onDemandReads.test.ts +106 -0
- package/frontend-vue/tests/registration.test.ts +0 -12
- package/frontend-vue/tests/serverRender.test.ts +235 -0
- package/frontend-vue/vitest.config.ts +24 -0
- package/package.json +6 -5
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {
|
|
3
|
-
dayLabel,
|
|
4
3
|
groupByDay,
|
|
5
4
|
HISTORY_KEPT,
|
|
6
5
|
RUN_DOT_CLASSES,
|
|
@@ -38,7 +37,10 @@ const emit = defineEmits<{
|
|
|
38
37
|
'clear-history': []
|
|
39
38
|
}>()
|
|
40
39
|
|
|
41
|
-
const { t, n
|
|
40
|
+
const { t, n } = useI18n()
|
|
41
|
+
// Times and days in the user's time zone, which a server render writes in
|
|
42
|
+
// the browser's: the HTML shows what the browser shows.
|
|
43
|
+
const { dateTimeFormat } = useRegionalFormat()
|
|
42
44
|
|
|
43
45
|
const tab = ref<LibraryTab>('history')
|
|
44
46
|
const search = ref('')
|
|
@@ -76,15 +78,18 @@ const historyGroups = computed(() =>
|
|
|
76
78
|
matches(entry.source, entry.error, target),
|
|
77
79
|
),
|
|
78
80
|
({ entry }) => entry.executedAt,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
label: dayLabel(group.date, locale.value, {
|
|
82
|
-
today: t('dms_database.query.library.today'),
|
|
83
|
-
yesterday: t('dms_database.query.library.yesterday'),
|
|
84
|
-
}),
|
|
85
|
-
})),
|
|
81
|
+
regionalDayKey,
|
|
82
|
+
).map((group) => ({ ...group, label: dayLabel(group.date) })),
|
|
86
83
|
)
|
|
87
84
|
|
|
85
|
+
/** "Today", "Yesterday" or the date. */
|
|
86
|
+
function dayLabel(date: Date): string {
|
|
87
|
+
const daysAgo = regionalDayNumber(new Date()) - regionalDayNumber(date)
|
|
88
|
+
if (daysAgo === 0) return t('dms_database.query.library.today')
|
|
89
|
+
if (daysAgo === 1) return t('dms_database.query.library.yesterday')
|
|
90
|
+
return dateTimeFormat({ day: 'numeric', month: 'short' }).format(date)
|
|
91
|
+
}
|
|
92
|
+
|
|
88
93
|
const savedItems = computed(() =>
|
|
89
94
|
(tab.value === 'team' ? props.team : props.saved).filter((query) =>
|
|
90
95
|
matches(query.name, query.description, query.source, query.ownerName),
|
|
@@ -92,10 +97,9 @@ const savedItems = computed(() =>
|
|
|
92
97
|
)
|
|
93
98
|
|
|
94
99
|
function time(iso: string): string {
|
|
95
|
-
return
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}).format(new Date(iso))
|
|
100
|
+
return dateTimeFormat({ hour: '2-digit', minute: '2-digit' }).format(
|
|
101
|
+
new Date(iso),
|
|
102
|
+
)
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
function runMeta(entry: HistoryEntry): string {
|
|
@@ -116,10 +120,9 @@ function runMeta(entry: HistoryEntry): string {
|
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
function savedMeta(query: SavedQuery): string {
|
|
119
|
-
const date =
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}).format(new Date(query.updatedAt ?? query.createdAt))
|
|
123
|
+
const date = dateTimeFormat({ day: 'numeric', month: 'short' }).format(
|
|
124
|
+
new Date(query.updatedAt ?? query.createdAt),
|
|
125
|
+
)
|
|
123
126
|
return query.ownerName ? `${query.ownerName} · ${date}` : date
|
|
124
127
|
}
|
|
125
128
|
|
|
@@ -58,7 +58,6 @@ const props = defineProps<{
|
|
|
58
58
|
const emit = defineEmits<{ success: [] }>()
|
|
59
59
|
|
|
60
60
|
const { t, n } = useI18n()
|
|
61
|
-
const { $authFetch } = useAuthFetch()
|
|
62
61
|
const staged = useStagedEdits()
|
|
63
62
|
|
|
64
63
|
const active = ref<DrawerTab>('fields')
|
|
@@ -169,23 +168,21 @@ function setBoolean(field: string, value: boolean) {
|
|
|
169
168
|
}
|
|
170
169
|
|
|
171
170
|
// --- referenced by ---
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
referencesFailed.value = true
|
|
188
|
-
}
|
|
171
|
+
// Read once the drawer opens, in the browser.
|
|
172
|
+
const referencesRead = useApiData<{ items: RowReference[] }>(
|
|
173
|
+
() =>
|
|
174
|
+
props.rowId && !props.readOnly ? '/api/database/browse/references' : null,
|
|
175
|
+
{
|
|
176
|
+
query: () => ({ ...browseSelectionQuery(props.tab), id: props.rowId }),
|
|
177
|
+
immediate: false,
|
|
178
|
+
server: false,
|
|
179
|
+
},
|
|
180
|
+
)
|
|
181
|
+
const references = computed(() => referencesRead.data.value?.items ?? null)
|
|
182
|
+
const referencesFailed = computed(() => referencesRead.status.value === 'error')
|
|
183
|
+
|
|
184
|
+
function loadReferences() {
|
|
185
|
+
void referencesRead.execute()
|
|
189
186
|
}
|
|
190
187
|
|
|
191
188
|
onMounted(loadReferences)
|
|
@@ -263,13 +263,10 @@ async function load(id: string) {
|
|
|
263
263
|
await leaving
|
|
264
264
|
if (sync !== owner) return
|
|
265
265
|
try {
|
|
266
|
-
const
|
|
267
|
-
persistence.fetchLayout(id),
|
|
268
|
-
persistence.fetchNotes(id),
|
|
269
|
-
])
|
|
266
|
+
const stored = await persistence.readDiagram(id)
|
|
270
267
|
if (sync !== owner) return
|
|
271
|
-
state.positions = positions
|
|
272
|
-
state.notes = notes.map(noteFromStored)
|
|
268
|
+
state.positions = stored.positions
|
|
269
|
+
state.notes = stored.notes.map(noteFromStored)
|
|
273
270
|
} catch {
|
|
274
271
|
if (sync !== owner) return
|
|
275
272
|
state.positions = {}
|
|
@@ -288,7 +285,10 @@ async function load(id: string) {
|
|
|
288
285
|
loaded.value = true
|
|
289
286
|
}
|
|
290
287
|
|
|
291
|
-
|
|
288
|
+
// The canvas is drawn in the browser, from a working copy of the layout and
|
|
289
|
+
// notes it reads there: a server render, which would read them without
|
|
290
|
+
// handing them over, never starts it.
|
|
291
|
+
onMounted(() => watch(schemaId, (id) => id && load(id), { immediate: true }))
|
|
292
292
|
|
|
293
293
|
function record(op: DiagramOperation) {
|
|
294
294
|
history.push(op)
|
|
@@ -31,7 +31,8 @@ import { ALL_INSTANCES_PARAM, tableLink } from '../build/utils/databaseLinks'
|
|
|
31
31
|
// The Schemas page's row drawer (D-07), also opened from the diagram: the
|
|
32
32
|
// facts of one table, its columns, indexes and relations both ways, and a
|
|
33
33
|
// sample row. The table view hands it the row and the means to step to the
|
|
34
|
-
// next one (J / K)
|
|
34
|
+
// next one (J / K), or to show another row in place; a relation opens the
|
|
35
|
+
// table it names in its place.
|
|
35
36
|
|
|
36
37
|
interface TableRow {
|
|
37
38
|
schema: string
|
|
@@ -50,6 +51,7 @@ interface RowNavigation {
|
|
|
50
51
|
const props = defineProps<{
|
|
51
52
|
rowData?: TableRow
|
|
52
53
|
navigation?: RowNavigation
|
|
54
|
+
showRow?: (row: object | string) => Promise<void>
|
|
53
55
|
}>()
|
|
54
56
|
|
|
55
57
|
// A link out closes the drawer.
|
|
@@ -66,7 +68,6 @@ const BROWSE_LIST = '/api/database/browse/list'
|
|
|
66
68
|
const BROWSE_COUNT = '/api/database/browse/count'
|
|
67
69
|
|
|
68
70
|
const { t, n } = useI18n()
|
|
69
|
-
const { $authFetch } = useAuthFetch()
|
|
70
71
|
const { copy } = useClipboard()
|
|
71
72
|
const toast = useToast()
|
|
72
73
|
|
|
@@ -100,7 +101,8 @@ const failed = computed(
|
|
|
100
101
|
() => schemasSettled.value && schemas.value === undefined,
|
|
101
102
|
)
|
|
102
103
|
|
|
103
|
-
// The table a relation was followed to, in place of the row's
|
|
104
|
+
// The table a relation was followed to, in place of the row's, where the
|
|
105
|
+
// container cannot show another row (the diagram's drawer).
|
|
104
106
|
const followed = ref<TableRow | null>(null)
|
|
105
107
|
const shown = computed(() => followed.value ?? props.rowData)
|
|
106
108
|
// J / K step from the row the table view opened: its position is not the
|
|
@@ -199,8 +201,19 @@ const incoming = computed(() =>
|
|
|
199
201
|
),
|
|
200
202
|
)
|
|
201
203
|
|
|
202
|
-
// The
|
|
203
|
-
|
|
204
|
+
// The table view shows the relation's table as its own row: the URL, the
|
|
205
|
+
// position and J / K follow it. Elsewhere, or should it fail to read the
|
|
206
|
+
// row, the inspector shows it itself, and the row's own table again closes
|
|
207
|
+
// the detour.
|
|
208
|
+
async function follow(target: TableRow) {
|
|
209
|
+
if (props.showRow) {
|
|
210
|
+
try {
|
|
211
|
+
await props.showRow(`${target.schema}::${target.name}`)
|
|
212
|
+
return
|
|
213
|
+
} catch {
|
|
214
|
+
// Shown in place below.
|
|
215
|
+
}
|
|
216
|
+
}
|
|
204
217
|
const own =
|
|
205
218
|
target.schema === props.rowData?.schema &&
|
|
206
219
|
target.name === props.rowData?.name
|
|
@@ -208,26 +221,23 @@ function follow(target: TableRow) {
|
|
|
208
221
|
}
|
|
209
222
|
|
|
210
223
|
// --- rows: in every instance at once; the data browser shows each one's ---
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
watch(tableKey, loadTotal, { immediate: true })
|
|
224
|
+
// Read with the table, on the server too when the link opens the drawer; no
|
|
225
|
+
// figure shows while another table's loads, nor once it failed.
|
|
226
|
+
const rowTotal = useApiData<{ total: number }>(
|
|
227
|
+
() => (schemaId.value && tableName.value ? BROWSE_COUNT : null),
|
|
228
|
+
{
|
|
229
|
+
query: () => ({
|
|
230
|
+
filter_schema: `is:${schemaId.value}`,
|
|
231
|
+
filter_table: `is:${tableName.value}`,
|
|
232
|
+
filter_instance: `is:${CROSS_INSTANCE_VALUE}`,
|
|
233
|
+
}),
|
|
234
|
+
},
|
|
235
|
+
)
|
|
236
|
+
const total = computed(() =>
|
|
237
|
+
rowTotal.status.value === 'success'
|
|
238
|
+
? (rowTotal.data.value?.total ?? null)
|
|
239
|
+
: null,
|
|
240
|
+
)
|
|
231
241
|
|
|
232
242
|
const rowsFact = computed(() => {
|
|
233
243
|
const rows = total.value
|
|
@@ -269,20 +279,94 @@ const tabs = computed(() => [
|
|
|
269
279
|
])
|
|
270
280
|
|
|
271
281
|
// --- sample row: the latest row, or the next one on demand ---
|
|
272
|
-
const sample = ref<Record<string, unknown> | null>(null)
|
|
273
|
-
const sampleOffset = ref(0)
|
|
274
|
-
const sampleTotal = ref(0)
|
|
275
|
-
const sampleLoading = ref(false)
|
|
276
|
-
const sampleFailed = ref(false)
|
|
277
|
-
|
|
278
282
|
interface SamplePage {
|
|
279
283
|
results: Record<string, unknown>[]
|
|
280
284
|
total: number
|
|
281
285
|
}
|
|
282
286
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
287
|
+
/**
|
|
288
|
+
* The row asked for: its offset in an instance. No instance at offset 0 reads
|
|
289
|
+
* the default one, or the first named instance holding rows when the default
|
|
290
|
+
* one holds none.
|
|
291
|
+
*/
|
|
292
|
+
interface SampleRequest {
|
|
293
|
+
instance: string | null
|
|
294
|
+
offset: number
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/** A sample read, with the table and the instance it was read from. */
|
|
298
|
+
interface SampleRead {
|
|
299
|
+
table: string
|
|
300
|
+
instance: string | null
|
|
301
|
+
page: SamplePage
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const requested = shallowRef<SampleRequest>({ instance: null, offset: 0 })
|
|
305
|
+
|
|
306
|
+
type ReadSample = (instance: string | null) => Promise<SamplePage>
|
|
307
|
+
|
|
308
|
+
async function firstFilledInstance(
|
|
309
|
+
read: ReadSample,
|
|
310
|
+
): Promise<{ instance: string | null; page: SamplePage }> {
|
|
311
|
+
const page = await read(null)
|
|
312
|
+
if (page.total > 0) return { instance: null, page }
|
|
313
|
+
for (const instance of schema.value?.instances ?? []) {
|
|
314
|
+
const named = await read(instance)
|
|
315
|
+
if (named.total > 0) return { instance, page: named }
|
|
316
|
+
}
|
|
317
|
+
return { instance: null, page }
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Read once the Sample tab shows, in the browser only.
|
|
321
|
+
const sampleRead = useApiData<SampleRead>(
|
|
322
|
+
() =>
|
|
323
|
+
schemaId.value && tableName.value
|
|
324
|
+
? `dms-database:sample:${JSON.stringify([
|
|
325
|
+
tableKey.value,
|
|
326
|
+
requested.value.instance,
|
|
327
|
+
requested.value.offset,
|
|
328
|
+
])}`
|
|
329
|
+
: null,
|
|
330
|
+
async ({ $authFetch, signal }) => {
|
|
331
|
+
const table = tableKey.value
|
|
332
|
+
const { instance, offset } = requested.value
|
|
333
|
+
const read: ReadSample = (from) =>
|
|
334
|
+
$authFetch<SamplePage>(BROWSE_LIST, {
|
|
335
|
+
query: {
|
|
336
|
+
filter_schema: `is:${schemaId.value}`,
|
|
337
|
+
filter_table: `is:${tableName.value}`,
|
|
338
|
+
offset,
|
|
339
|
+
limit: 1,
|
|
340
|
+
...(from ? { filter_instance: `is:${from}` } : {}),
|
|
341
|
+
},
|
|
342
|
+
signal,
|
|
343
|
+
})
|
|
344
|
+
const found =
|
|
345
|
+
instance === null && offset === 0
|
|
346
|
+
? await firstFilledInstance(read)
|
|
347
|
+
: { instance, page: await read(instance) }
|
|
348
|
+
return { table, ...found }
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
immediate: false,
|
|
352
|
+
server: false,
|
|
353
|
+
watch: false,
|
|
354
|
+
refreshOnPageRefresh: false,
|
|
355
|
+
},
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
// Another table (a relation followed) shows none of the previous one's row.
|
|
359
|
+
const sampleShown = computed(() => {
|
|
360
|
+
const value = sampleRead.data.value
|
|
361
|
+
return value?.table === tableKey.value ? value : null
|
|
362
|
+
})
|
|
363
|
+
const sample = computed(() => sampleShown.value?.page.results?.[0] ?? null)
|
|
364
|
+
const sampleTotal = computed(() => sampleShown.value?.page.total ?? 0)
|
|
365
|
+
const sampleOffset = computed(() => requested.value.offset)
|
|
366
|
+
const sampleLoading = computed(() => sampleRead.pending.value)
|
|
367
|
+
const sampleFailed = computed(() => sampleRead.status.value === 'error')
|
|
368
|
+
// The instance the sample is read from.
|
|
369
|
+
const sampleInstance = computed(() => sampleShown.value?.instance ?? null)
|
|
286
370
|
|
|
287
371
|
const sampleInstanceLabel = computed(() =>
|
|
288
372
|
sampleInstance.value === null
|
|
@@ -292,72 +376,34 @@ const sampleInstanceLabel = computed(() =>
|
|
|
292
376
|
}),
|
|
293
377
|
)
|
|
294
378
|
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
filter_schema: `is:${schemaId.value}`,
|
|
298
|
-
filter_table: `is:${tableName.value}`,
|
|
299
|
-
offset: sampleOffset.value,
|
|
300
|
-
limit: 1,
|
|
301
|
-
}
|
|
302
|
-
if (instance) query.filter_instance = `is:${instance}`
|
|
303
|
-
return $authFetch<SamplePage>(BROWSE_LIST, { query })
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
async function firstFilledInstance(): Promise<SamplePage> {
|
|
307
|
-
const page = await fetchSample(null)
|
|
308
|
-
if (page.total > 0) return page
|
|
309
|
-
for (const instance of schema.value?.instances ?? []) {
|
|
310
|
-
const named = await fetchSample(instance)
|
|
311
|
-
if (named.total > 0) {
|
|
312
|
-
sampleInstance.value = instance
|
|
313
|
-
return named
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return page
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
async function loadSample() {
|
|
320
|
-
if (!schemaId.value || !tableName.value) return
|
|
321
|
-
sampleLoading.value = true
|
|
322
|
-
sampleFailed.value = false
|
|
323
|
-
try {
|
|
324
|
-
const res =
|
|
325
|
-
sampleInstance.value === null && sampleOffset.value === 0
|
|
326
|
-
? await firstFilledInstance()
|
|
327
|
-
: await fetchSample(sampleInstance.value)
|
|
328
|
-
sample.value = res.results?.[0] ?? null
|
|
329
|
-
sampleTotal.value = res.total ?? 0
|
|
330
|
-
} catch {
|
|
331
|
-
sampleFailed.value = true
|
|
332
|
-
sample.value = null
|
|
333
|
-
} finally {
|
|
334
|
-
sampleLoading.value = false
|
|
335
|
-
}
|
|
379
|
+
function loadSample() {
|
|
380
|
+
if (schemaId.value && tableName.value) void sampleRead.execute()
|
|
336
381
|
}
|
|
337
382
|
|
|
338
383
|
function nextSample() {
|
|
339
|
-
|
|
340
|
-
|
|
384
|
+
const total = sampleTotal.value
|
|
385
|
+
requested.value = {
|
|
386
|
+
instance: sampleInstance.value,
|
|
387
|
+
offset: total > 0 ? (requested.value.offset + 1) % total : 0,
|
|
388
|
+
}
|
|
341
389
|
loadSample()
|
|
342
390
|
}
|
|
343
391
|
|
|
344
392
|
// Another table (a relation followed) starts over from its latest row.
|
|
345
393
|
watch(tableKey, () => {
|
|
346
|
-
|
|
347
|
-
sampleOffset.value = 0
|
|
348
|
-
sampleTotal.value = 0
|
|
349
|
-
sampleInstance.value = null
|
|
350
|
-
sampleFailed.value = false
|
|
394
|
+
requested.value = { instance: null, offset: 0 }
|
|
351
395
|
if (tab.value === 'sample' && !loading.value) loadSample()
|
|
352
396
|
})
|
|
353
397
|
|
|
354
398
|
// The sample waits for the schemas: they name the instances to look in.
|
|
355
|
-
|
|
356
|
-
(
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
399
|
+
onMounted(() =>
|
|
400
|
+
watch(
|
|
401
|
+
() => tab.value === 'sample' && !loading.value,
|
|
402
|
+
(ready) => {
|
|
403
|
+
if (ready && !sample.value && !sampleLoading.value) loadSample()
|
|
404
|
+
},
|
|
405
|
+
{ immediate: true },
|
|
406
|
+
),
|
|
361
407
|
)
|
|
362
408
|
|
|
363
409
|
// The `_instance` tag the store adds to rows of named instances is not a
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"main": "./dms.frontend.ts",
|
|
7
7
|
"packageManager": "pnpm@10.6.5",
|
|
8
8
|
"engines": {
|
|
9
|
-
"@antelopejs/dms-frontend": ">=0.
|
|
9
|
+
"@antelopejs/dms-frontend": ">=0.6.0 <0.7.0"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"dev": "pnpm --dir ../playground frontend:dev",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"@intlify/message-compiler": "^11",
|
|
37
37
|
"@nuxt/ui": "4.10.0",
|
|
38
38
|
"@typescript-eslint/parser": "^8.0.0",
|
|
39
|
+
"@vitejs/plugin-vue": "^6.0.10",
|
|
39
40
|
"eslint": "^9.0.0",
|
|
40
41
|
"eslint-plugin-vue": "^10.0.0",
|
|
41
42
|
"prettier": "^3.5.3",
|