@plutocms/supabase 0.9.1 → 0.11.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/.prettierignore +2 -0
- package/CHANGELOG.md +19 -0
- package/FEATURES.md +9 -0
- package/README.md +10 -1
- package/app/components/EnvPersistWarning.vue +30 -13
- package/app/components/SupabaseMessageParts.vue +29 -0
- package/app/components/auth/AuthSignIn.vue +56 -0
- package/app/components/migrations/MigrationsBanner.vue +28 -15
- package/app/components/settings/SettingsGeneralPanel.vue +21 -6
- package/app/composables/auth.ts +38 -101
- package/app/pages/admin/(auth)/confirm.vue +20 -23
- package/app/pages/admin/(auth)/forgot-password.vue +60 -63
- package/app/pages/admin/(auth)/signup.vue +115 -110
- package/app/pages/admin/(auth)/update-password.vue +78 -82
- package/app/pages/admin/migrations.vue +87 -51
- package/app/pages/admin/setup.vue +88 -75
- package/app/plugins/pluto-extension.ts +143 -10
- package/app/utils/auth-driver.ts +110 -0
- package/app/utils/auth-error.ts +53 -0
- package/db/migrations/005_profile_locale.sql +44 -0
- package/i18n/locales/en.json +193 -0
- package/i18n/locales/pt-BR.json +193 -0
- package/package.json +3 -3
- package/server/api/profile/locale.get.ts +39 -0
- package/server/api/profile/locale.post.ts +71 -0
- package/server/api/setup/create.post.ts +6 -4
- package/server/api/users/[id].get.ts +4 -2
- package/server/api/users/index.get.ts +4 -2
- package/server/utils/admin-guard.ts +10 -2
- package/server/utils/capability-guard.ts +18 -4
- package/server/utils/content-adapter.ts +6 -4
- package/server/utils/pending-migrations.ts +0 -0
- package/server/utils/validate.ts +6 -1
- package/shared/types/supabase.ts +7 -0
- package/app/components/navbar/NavbarAdmin.vue +0 -213
- package/app/components/navbar/NavbarAdminProvider.vue +0 -18
- package/app/middleware/auth.ts +0 -34
- package/app/middleware/setup-check.ts +0 -44
- package/app/pages/admin/(auth)/login.vue +0 -93
- package/app/pages/admin.vue +0 -56
- package/app/plugins/pluto-permissions-sync.ts +0 -38
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
const { t } = usePlutoI18n()
|
|
3
|
+
|
|
2
4
|
useHead({
|
|
3
|
-
title: '
|
|
5
|
+
title: () => t('supabase.migrations.title'),
|
|
4
6
|
})
|
|
5
7
|
|
|
6
8
|
const config = useRuntimeConfig()
|
|
@@ -15,6 +17,19 @@ const { status, fetchStatus, pendingCount, refresh, runMigrations } =
|
|
|
15
17
|
|
|
16
18
|
const isDev = import.meta.dev
|
|
17
19
|
|
|
20
|
+
// The text of each result status that the server returns.
|
|
21
|
+
const statusLabels: Record<string, string> = {
|
|
22
|
+
applied: 'supabase.migrations.status.applied',
|
|
23
|
+
skipped: 'supabase.migrations.status.skipped',
|
|
24
|
+
failed: 'supabase.migrations.status.failed',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function statusText(status: string): string {
|
|
28
|
+
const key = statusLabels[status]
|
|
29
|
+
|
|
30
|
+
return key ? t(key) : status
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
// Only the layers that actually have a pending, or applied, file — used to
|
|
19
34
|
// render per-file detail under each layer below.
|
|
20
35
|
const pendingLayers = computed(
|
|
@@ -86,9 +101,9 @@ async function applyMigrations(useForm: boolean) {
|
|
|
86
101
|
|
|
87
102
|
if (result.success === false) {
|
|
88
103
|
toast.add({
|
|
89
|
-
title: '
|
|
104
|
+
title: t('supabase.migrations.applyFailed'),
|
|
90
105
|
description: result.needsConnectionString
|
|
91
|
-
? '
|
|
106
|
+
? t('supabase.migrations.connectionRequired')
|
|
92
107
|
: undefined,
|
|
93
108
|
icon: 'lucide:circle-x',
|
|
94
109
|
color: 'error',
|
|
@@ -98,7 +113,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
98
113
|
}
|
|
99
114
|
|
|
100
115
|
toast.add({
|
|
101
|
-
title: '
|
|
116
|
+
title: t('supabase.migrations.applied'),
|
|
102
117
|
icon: 'lucide:check-circle',
|
|
103
118
|
color: 'success',
|
|
104
119
|
})
|
|
@@ -118,9 +133,8 @@ async function applyMigrations(useForm: boolean) {
|
|
|
118
133
|
|
|
119
134
|
if (isDev && useForm && !hasStatusCode) {
|
|
120
135
|
toast.add({
|
|
121
|
-
title: '
|
|
122
|
-
description:
|
|
123
|
-
'Saving a new connection string restarts the dev server. Reconnecting…',
|
|
136
|
+
title: t('supabase.connection.restarting'),
|
|
137
|
+
description: t('supabase.migrations.restartingDescription'),
|
|
124
138
|
icon: 'lucide:refresh-cw',
|
|
125
139
|
color: 'info',
|
|
126
140
|
})
|
|
@@ -134,18 +148,21 @@ async function applyMigrations(useForm: boolean) {
|
|
|
134
148
|
toast.add(
|
|
135
149
|
recovered
|
|
136
150
|
? {
|
|
137
|
-
title: '
|
|
151
|
+
title: t('supabase.connection.reconnected'),
|
|
138
152
|
description:
|
|
139
153
|
pendingCount.value === 0
|
|
140
|
-
? '
|
|
141
|
-
:
|
|
154
|
+
? t('supabase.migrations.reconnectedAllApplied')
|
|
155
|
+
: t('supabase.migrations.reconnectedPending', {
|
|
156
|
+
count: pendingCount.value,
|
|
157
|
+
}),
|
|
142
158
|
icon: 'lucide:check-circle',
|
|
143
159
|
color: 'success',
|
|
144
160
|
}
|
|
145
161
|
: {
|
|
146
|
-
title: '
|
|
147
|
-
description:
|
|
148
|
-
'
|
|
162
|
+
title: t('supabase.connection.stillReconnecting'),
|
|
163
|
+
description: t(
|
|
164
|
+
'supabase.connection.stillReconnectingDescription'
|
|
165
|
+
),
|
|
149
166
|
icon: 'lucide:triangle-alert',
|
|
150
167
|
color: 'warning',
|
|
151
168
|
}
|
|
@@ -159,8 +176,8 @@ async function applyMigrations(useForm: boolean) {
|
|
|
159
176
|
}
|
|
160
177
|
|
|
161
178
|
toast.add({
|
|
162
|
-
title: '
|
|
163
|
-
description: '
|
|
179
|
+
title: t('supabase.migrations.error'),
|
|
180
|
+
description: t('supabase.connection.checkConsole'),
|
|
164
181
|
icon: 'lucide:circle-x',
|
|
165
182
|
color: 'error',
|
|
166
183
|
})
|
|
@@ -172,15 +189,15 @@ async function applyMigrations(useForm: boolean) {
|
|
|
172
189
|
|
|
173
190
|
<template>
|
|
174
191
|
<AdminView>
|
|
175
|
-
<h1 class="text-3xl font-bold lg:text-4xl">
|
|
192
|
+
<h1 class="text-3xl font-bold lg:text-4xl">{{ t('supabase.migrations.title') }}</h1>
|
|
176
193
|
|
|
177
194
|
<UAlert
|
|
178
195
|
v-if="isReconnecting"
|
|
196
|
+
:title="t('supabase.connection.restarting')"
|
|
197
|
+
:description="t('supabase.migrations.reconnectingBanner')"
|
|
179
198
|
color="info"
|
|
180
199
|
variant="outline"
|
|
181
200
|
icon="lucide:refresh-cw"
|
|
182
|
-
title="Dev server restarting"
|
|
183
|
-
description="Saving a new connection string restarts the dev server. Reconnecting — this page will update on its own once it's back."
|
|
184
201
|
/>
|
|
185
202
|
|
|
186
203
|
<div
|
|
@@ -188,7 +205,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
188
205
|
class="flex items-center gap-x-2"
|
|
189
206
|
>
|
|
190
207
|
<Icon name="svg-spinners:ring-resize" />
|
|
191
|
-
<span>
|
|
208
|
+
<span>{{ t('supabase.migrations.loading') }}</span>
|
|
192
209
|
</div>
|
|
193
210
|
|
|
194
211
|
<template v-else-if="status">
|
|
@@ -196,16 +213,20 @@ async function applyMigrations(useForm: boolean) {
|
|
|
196
213
|
<div class="flex flex-col gap-y-6">
|
|
197
214
|
<UAlert
|
|
198
215
|
v-if="pendingCount === 0"
|
|
216
|
+
:title="t('supabase.migrations.upToDate')"
|
|
217
|
+
:description="t('supabase.migrations.upToDateDescription')"
|
|
199
218
|
color="success"
|
|
200
219
|
variant="outline"
|
|
201
220
|
icon="lucide:check-circle"
|
|
202
|
-
title="Everything is up to date"
|
|
203
|
-
description="No layer needs a database migration."
|
|
204
221
|
/>
|
|
205
222
|
|
|
206
223
|
<div v-else class="flex flex-col gap-y-2">
|
|
207
224
|
<h2 class="font-semibold">
|
|
208
|
-
|
|
225
|
+
{{
|
|
226
|
+
t('supabase.migrations.pendingLayers', {
|
|
227
|
+
count: status.pending.length,
|
|
228
|
+
})
|
|
229
|
+
}}
|
|
209
230
|
</h2>
|
|
210
231
|
<ul class="flex flex-col gap-y-2 text-sm">
|
|
211
232
|
<li v-for="layer in pendingLayers" :key="layer.layerName">
|
|
@@ -221,7 +242,11 @@ async function applyMigrations(useForm: boolean) {
|
|
|
221
242
|
|
|
222
243
|
<div v-if="status.applied.length" class="flex flex-col gap-y-2">
|
|
223
244
|
<h2 class="font-semibold">
|
|
224
|
-
|
|
245
|
+
{{
|
|
246
|
+
t('supabase.migrations.appliedLayers', {
|
|
247
|
+
count: status.applied.length,
|
|
248
|
+
})
|
|
249
|
+
}}
|
|
225
250
|
</h2>
|
|
226
251
|
<ul class="flex flex-col gap-y-2 text-sm">
|
|
227
252
|
<li v-for="layer in appliedLayers" :key="layer.layerName">
|
|
@@ -241,7 +266,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
241
266
|
class="flex flex-col gap-y-4"
|
|
242
267
|
@submit="applyMigrations(true)"
|
|
243
268
|
>
|
|
244
|
-
<UFormField label="
|
|
269
|
+
<UFormField :label="t('supabase.connection.connectionString')" required>
|
|
245
270
|
<UInput
|
|
246
271
|
v-model="connectionForm.connectionString"
|
|
247
272
|
:disabled="isRunning"
|
|
@@ -250,19 +275,24 @@ async function applyMigrations(useForm: boolean) {
|
|
|
250
275
|
/>
|
|
251
276
|
|
|
252
277
|
<template #help>
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
:to="`https://supabase.com/dashboard/project/${projectId}/database/settings?showConnect=true&connectTab=direct&method=transaction`"
|
|
256
|
-
target="_blank"
|
|
257
|
-
class="underline"
|
|
258
|
-
external
|
|
278
|
+
<SupabaseMessageParts
|
|
279
|
+
:message="t('supabase.connection.connectionStringHelp')"
|
|
259
280
|
>
|
|
260
|
-
|
|
261
|
-
|
|
281
|
+
<template #link>
|
|
282
|
+
<ULink
|
|
283
|
+
:to="`https://supabase.com/dashboard/project/${projectId}/database/settings?showConnect=true&connectTab=direct&method=transaction`"
|
|
284
|
+
target="_blank"
|
|
285
|
+
class="underline"
|
|
286
|
+
external
|
|
287
|
+
>
|
|
288
|
+
{{ t('supabase.connection.connectionStringHelpLink') }}
|
|
289
|
+
</ULink>
|
|
290
|
+
</template>
|
|
291
|
+
</SupabaseMessageParts>
|
|
262
292
|
</template>
|
|
263
293
|
</UFormField>
|
|
264
294
|
|
|
265
|
-
<UFormField label="
|
|
295
|
+
<UFormField :label="t('supabase.connection.password')" required>
|
|
266
296
|
<UInput
|
|
267
297
|
v-model="connectionForm.password"
|
|
268
298
|
:disabled="isRunning"
|
|
@@ -278,32 +308,36 @@ async function applyMigrations(useForm: boolean) {
|
|
|
278
308
|
variant="outline"
|
|
279
309
|
>
|
|
280
310
|
<template #description>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
<ULink
|
|
284
|
-
to="https://supabase.com/dashboard/project/_/database/settings"
|
|
285
|
-
target="_blank"
|
|
311
|
+
<SupabaseMessageParts
|
|
312
|
+
:message="t('supabase.connection.passwordInfo')"
|
|
286
313
|
>
|
|
287
|
-
|
|
288
|
-
|
|
314
|
+
<template #link>
|
|
315
|
+
<ULink
|
|
316
|
+
to="https://supabase.com/dashboard/project/_/database/settings"
|
|
317
|
+
target="_blank"
|
|
318
|
+
>
|
|
319
|
+
{{ t('supabase.connection.passwordInfoLink') }}
|
|
320
|
+
</ULink>
|
|
321
|
+
</template>
|
|
322
|
+
</SupabaseMessageParts>
|
|
289
323
|
</template>
|
|
290
324
|
</UAlert>
|
|
291
325
|
|
|
292
326
|
<UAlert
|
|
327
|
+
:title="t('supabase.connection.whyTitle')"
|
|
328
|
+
:description="t('supabase.migrations.why')"
|
|
293
329
|
color="warning"
|
|
294
330
|
variant="outline"
|
|
295
|
-
title="Why do I need to provide a database password?"
|
|
296
331
|
icon="lucide:info"
|
|
297
|
-
description="It is used once to open a direct PostgreSQL connection and run the pending layer schemas. It is then written to .env on the server, so future migrations need no prompt. It is never stored anywhere else, and never sent back to your browser."
|
|
298
332
|
/>
|
|
299
333
|
|
|
300
334
|
<UAlert
|
|
301
335
|
v-if="isDev"
|
|
336
|
+
:title="t('supabase.connection.restartTitle')"
|
|
337
|
+
:description="t('supabase.migrations.restartDescription')"
|
|
302
338
|
color="info"
|
|
303
339
|
variant="outline"
|
|
304
|
-
title="This restarts the dev server"
|
|
305
340
|
icon="lucide:refresh-cw"
|
|
306
|
-
description="Saving a new connection string writes it to .env. In development, that restarts the server automatically. The page will briefly show a reconnecting message — this is expected, not an error."
|
|
307
341
|
/>
|
|
308
342
|
|
|
309
343
|
<div class="flex">
|
|
@@ -314,7 +348,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
314
348
|
icon="lucide:database"
|
|
315
349
|
class="w-full justify-center sm:w-auto"
|
|
316
350
|
>
|
|
317
|
-
|
|
351
|
+
{{ t('supabase.migrations.apply') }}
|
|
318
352
|
</UButton>
|
|
319
353
|
</div>
|
|
320
354
|
</UForm>
|
|
@@ -327,7 +361,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
327
361
|
class="w-full justify-center sm:w-auto"
|
|
328
362
|
@click="applyMigrations(false)"
|
|
329
363
|
>
|
|
330
|
-
|
|
364
|
+
{{ t('supabase.migrations.apply') }}
|
|
331
365
|
</UButton>
|
|
332
366
|
</div>
|
|
333
367
|
</template>
|
|
@@ -336,7 +370,9 @@ async function applyMigrations(useForm: boolean) {
|
|
|
336
370
|
|
|
337
371
|
<UCard v-if="lastRun">
|
|
338
372
|
<div class="flex flex-col gap-y-4">
|
|
339
|
-
<h2 class="font-semibold">
|
|
373
|
+
<h2 class="font-semibold">
|
|
374
|
+
{{ t('supabase.migrations.lastRun') }}
|
|
375
|
+
</h2>
|
|
340
376
|
|
|
341
377
|
<EnvPersistWarning
|
|
342
378
|
v-if="lastRun.success && lastRun.persisted === false"
|
|
@@ -354,7 +390,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
354
390
|
<span class="font-mono"
|
|
355
391
|
>{{ result.layerName }}/{{ result.migrationName }}</span
|
|
356
392
|
>
|
|
357
|
-
— {{ result.status }}
|
|
393
|
+
— {{ statusText(result.status) }}
|
|
358
394
|
<span v-if="result.error" class="text-error">
|
|
359
395
|
: {{ result.error }}</span
|
|
360
396
|
>
|
|
@@ -366,11 +402,11 @@ async function applyMigrations(useForm: boolean) {
|
|
|
366
402
|
|
|
367
403
|
<UAlert
|
|
368
404
|
v-else
|
|
405
|
+
:title="t('supabase.migrations.loadFailed')"
|
|
406
|
+
:description="t('supabase.migrations.loadFailedDescription')"
|
|
369
407
|
color="error"
|
|
370
408
|
variant="outline"
|
|
371
409
|
icon="lucide:circle-x"
|
|
372
|
-
title="Could not load migration status"
|
|
373
|
-
description="This isn't the dev-server-restart case above — something else went wrong reading migration status. Check the server console, then try again."
|
|
374
410
|
>
|
|
375
411
|
<template #actions>
|
|
376
412
|
<UButton
|
|
@@ -379,7 +415,7 @@ async function applyMigrations(useForm: boolean) {
|
|
|
379
415
|
icon="lucide:refresh-cw"
|
|
380
416
|
@click="refresh()"
|
|
381
417
|
>
|
|
382
|
-
|
|
418
|
+
{{ t('supabase.migrations.retry') }}
|
|
383
419
|
</UButton>
|
|
384
420
|
</template>
|
|
385
421
|
</UAlert>
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import type { StepperItem } from '@nuxt/ui'
|
|
3
3
|
|
|
4
4
|
definePageMeta({
|
|
5
|
-
middleware: ['setup-check'],
|
|
6
5
|
layout: 'setup',
|
|
7
6
|
})
|
|
8
7
|
|
|
8
|
+
const { t, uiLocale } = usePlutoI18n()
|
|
9
|
+
|
|
9
10
|
useHead({
|
|
10
|
-
title:
|
|
11
|
+
title: () => t('supabase.setup.title'),
|
|
11
12
|
})
|
|
12
13
|
|
|
13
14
|
const config = useRuntimeConfig()
|
|
@@ -19,14 +20,14 @@ const toast = useToast()
|
|
|
19
20
|
|
|
20
21
|
const isDev = import.meta.dev
|
|
21
22
|
|
|
22
|
-
const items =
|
|
23
|
+
const items = computed<StepperItem[]>(() => [
|
|
23
24
|
{
|
|
24
|
-
title: '
|
|
25
|
+
title: t('supabase.setup.steps.database'),
|
|
25
26
|
icon: 'i-lucide-database',
|
|
26
27
|
},
|
|
27
28
|
|
|
28
29
|
{
|
|
29
|
-
title: '
|
|
30
|
+
title: t('supabase.setup.steps.complete'),
|
|
30
31
|
icon: 'i-lucide-check',
|
|
31
32
|
},
|
|
32
33
|
])
|
|
@@ -66,10 +67,10 @@ const currentStepId = computed(() => {
|
|
|
66
67
|
|
|
67
68
|
const currentStepSubmitLabel = computed(() => {
|
|
68
69
|
if (currentStep.value === 0) {
|
|
69
|
-
return '
|
|
70
|
+
return t('supabase.setup.submit')
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
return '
|
|
73
|
+
return t('supabase.setup.next')
|
|
73
74
|
})
|
|
74
75
|
|
|
75
76
|
/**
|
|
@@ -91,8 +92,8 @@ async function waitForServerAndAdvance(): Promise<boolean> {
|
|
|
91
92
|
await $fetch('/api/settings/first_setup')
|
|
92
93
|
|
|
93
94
|
toast.add({
|
|
94
|
-
title: '
|
|
95
|
-
description: '
|
|
95
|
+
title: t('supabase.connection.reconnected'),
|
|
96
|
+
description: t('supabase.setup.reconnectedDescription'),
|
|
96
97
|
icon: 'lucide:check-circle',
|
|
97
98
|
color: 'success',
|
|
98
99
|
})
|
|
@@ -126,8 +127,8 @@ async function completeDatabaseSetup() {
|
|
|
126
127
|
|
|
127
128
|
if (data.success === false) {
|
|
128
129
|
toast.add({
|
|
129
|
-
title: '
|
|
130
|
-
description: '
|
|
130
|
+
title: t('supabase.setup.failed'),
|
|
131
|
+
description: t('supabase.setup.failedDescription'),
|
|
131
132
|
icon: 'lucide:circle-x',
|
|
132
133
|
color: 'error',
|
|
133
134
|
})
|
|
@@ -141,8 +142,8 @@ async function completeDatabaseSetup() {
|
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
toast.add({
|
|
144
|
-
title: '
|
|
145
|
-
description: '
|
|
145
|
+
title: t('supabase.setup.complete'),
|
|
146
|
+
description: t('supabase.setup.completeDescription'),
|
|
146
147
|
icon: 'lucide:check-circle',
|
|
147
148
|
color: 'success',
|
|
148
149
|
})
|
|
@@ -164,8 +165,8 @@ async function completeDatabaseSetup() {
|
|
|
164
165
|
|
|
165
166
|
if (import.meta.dev && !hasStatusCode) {
|
|
166
167
|
toast.add({
|
|
167
|
-
title: '
|
|
168
|
-
description: '
|
|
168
|
+
title: t('supabase.connection.restarting'),
|
|
169
|
+
description: t('supabase.setup.restartingDescription'),
|
|
169
170
|
icon: 'lucide:refresh-cw',
|
|
170
171
|
color: 'info',
|
|
171
172
|
})
|
|
@@ -177,9 +178,8 @@ async function completeDatabaseSetup() {
|
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
toast.add({
|
|
180
|
-
title: '
|
|
181
|
-
description:
|
|
182
|
-
'The dev server is taking longer than expected. Reload this page in a moment.',
|
|
181
|
+
title: t('supabase.connection.stillReconnecting'),
|
|
182
|
+
description: t('supabase.connection.stillReconnectingDescription'),
|
|
183
183
|
icon: 'lucide:triangle-alert',
|
|
184
184
|
color: 'warning',
|
|
185
185
|
})
|
|
@@ -192,8 +192,8 @@ async function completeDatabaseSetup() {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
toast.add({
|
|
195
|
-
title: '
|
|
196
|
-
description: '
|
|
195
|
+
title: t('supabase.setup.error'),
|
|
196
|
+
description: t('supabase.connection.checkConsole'),
|
|
197
197
|
icon: 'lucide:circle-x',
|
|
198
198
|
color: 'error',
|
|
199
199
|
})
|
|
@@ -210,7 +210,7 @@ function handleStepChange(step: number) {
|
|
|
210
210
|
</script>
|
|
211
211
|
|
|
212
212
|
<template>
|
|
213
|
-
<UApp>
|
|
213
|
+
<UApp :locale="uiLocale">
|
|
214
214
|
<div class="flex min-h-dvh items-center justify-center p-4">
|
|
215
215
|
<UCard class="w-full max-w-125">
|
|
216
216
|
<div class="flex flex-col gap-y-8">
|
|
@@ -223,7 +223,7 @@ function handleStepChange(step: number) {
|
|
|
223
223
|
class="flex flex-col gap-y-4"
|
|
224
224
|
@submit="handleStepChange(currentStep)"
|
|
225
225
|
>
|
|
226
|
-
<UFormField label="
|
|
226
|
+
<UFormField :label="t('supabase.connection.connectionString')" required>
|
|
227
227
|
<UInput
|
|
228
228
|
v-model="databaseForm.connectionString"
|
|
229
229
|
:disabled="isSettingUpDatabase"
|
|
@@ -233,19 +233,24 @@ function handleStepChange(step: number) {
|
|
|
233
233
|
/>
|
|
234
234
|
|
|
235
235
|
<template #help>
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
:to="`https://supabase.com/dashboard/project/${projectId}/database/settings?showConnect=true&method=transaction`"
|
|
239
|
-
target="_blank"
|
|
240
|
-
class="underline"
|
|
241
|
-
external
|
|
236
|
+
<SupabaseMessageParts
|
|
237
|
+
:message="t('supabase.connection.connectionStringHelp')"
|
|
242
238
|
>
|
|
243
|
-
|
|
244
|
-
|
|
239
|
+
<template #link>
|
|
240
|
+
<ULink
|
|
241
|
+
:to="`https://supabase.com/dashboard/project/${projectId}/database/settings?showConnect=true&method=transaction`"
|
|
242
|
+
target="_blank"
|
|
243
|
+
class="underline"
|
|
244
|
+
external
|
|
245
|
+
>
|
|
246
|
+
{{ t('supabase.connection.connectionStringHelpLink') }}
|
|
247
|
+
</ULink>
|
|
248
|
+
</template>
|
|
249
|
+
</SupabaseMessageParts>
|
|
245
250
|
</template>
|
|
246
251
|
</UFormField>
|
|
247
252
|
|
|
248
|
-
<UFormField label="
|
|
253
|
+
<UFormField :label="t('supabase.connection.password')" required>
|
|
249
254
|
<UInput
|
|
250
255
|
v-model="databaseForm.password"
|
|
251
256
|
:disabled="isSettingUpDatabase"
|
|
@@ -261,42 +266,50 @@ function handleStepChange(step: number) {
|
|
|
261
266
|
variant="outline"
|
|
262
267
|
>
|
|
263
268
|
<template #description>
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
<ULink
|
|
267
|
-
to="https://supabase.com/dashboard/project/_/database/settings"
|
|
268
|
-
target="_blank"
|
|
269
|
+
<SupabaseMessageParts
|
|
270
|
+
:message="t('supabase.connection.passwordInfo')"
|
|
269
271
|
>
|
|
270
|
-
|
|
271
|
-
|
|
272
|
+
<template #link>
|
|
273
|
+
<ULink
|
|
274
|
+
to="https://supabase.com/dashboard/project/_/database/settings"
|
|
275
|
+
target="_blank"
|
|
276
|
+
>
|
|
277
|
+
{{ t('supabase.connection.passwordInfoLink') }}
|
|
278
|
+
</ULink>
|
|
279
|
+
</template>
|
|
280
|
+
</SupabaseMessageParts>
|
|
272
281
|
</template>
|
|
273
282
|
</UAlert>
|
|
274
283
|
|
|
275
284
|
<UAlert
|
|
285
|
+
:title="t('supabase.connection.whyTitle')"
|
|
276
286
|
color="warning"
|
|
277
287
|
variant="outline"
|
|
278
|
-
title="Why do I need to provide a database password?"
|
|
279
288
|
icon="lucide:info"
|
|
280
289
|
>
|
|
281
290
|
<template #description>
|
|
282
291
|
<div class="flex flex-col gap-y-4">
|
|
283
292
|
<p>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
<UTooltip
|
|
287
|
-
text="Click on the 'Technical details' button for more info"
|
|
293
|
+
<SupabaseMessageParts
|
|
294
|
+
:message="t('supabase.setup.why')"
|
|
288
295
|
>
|
|
289
|
-
<
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
296
|
+
<template #promise>
|
|
297
|
+
<UTooltip :text="t('supabase.setup.promiseTooltip')">
|
|
298
|
+
<span
|
|
299
|
+
class="underline decoration-dotted cursor-help"
|
|
300
|
+
>
|
|
301
|
+
{{ t('supabase.setup.promise') }}</span
|
|
302
|
+
></UTooltip
|
|
303
|
+
>
|
|
304
|
+
</template>
|
|
305
|
+
</SupabaseMessageParts>
|
|
293
306
|
</p>
|
|
294
307
|
|
|
295
308
|
<div>
|
|
296
309
|
<UPopover :content="{ side: 'bottom' }" arrow>
|
|
297
310
|
<UButton
|
|
311
|
+
:label="t('supabase.setup.technicalDetails')"
|
|
298
312
|
icon="lucide:lightbulb"
|
|
299
|
-
label="Technical details"
|
|
300
313
|
color="info"
|
|
301
314
|
variant="subtle"
|
|
302
315
|
class="w-fit"
|
|
@@ -308,31 +321,32 @@ function handleStepChange(step: number) {
|
|
|
308
321
|
class="flex flex-col gap-y-4 max-w-xs p-4 text-white text-sm"
|
|
309
322
|
>
|
|
310
323
|
<p>
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
to="https://github.com/plutocms/supabase/blob/feat/setup-wizard/server/api/setup/create.post.ts"
|
|
314
|
-
target="_blank"
|
|
315
|
-
class="underline"
|
|
316
|
-
>
|
|
317
|
-
a server route</ULink
|
|
318
|
-
>
|
|
319
|
-
will be made with the database password you
|
|
320
|
-
provided. This API will then use this password
|
|
321
|
-
to make a direct PostgreSQL connection to your
|
|
322
|
-
Supabase database and run the SQL queries from
|
|
323
|
-
this
|
|
324
|
-
<ULink
|
|
325
|
-
to="https://github.com/plutocms/supabase/tree/main/db/migrations"
|
|
326
|
-
target="_blank"
|
|
327
|
-
class="underline"
|
|
324
|
+
<SupabaseMessageParts
|
|
325
|
+
:message="t('supabase.setup.technicalDetailsRequest')"
|
|
328
326
|
>
|
|
329
|
-
|
|
330
|
-
|
|
327
|
+
<template #route>
|
|
328
|
+
<ULink
|
|
329
|
+
to="https://github.com/plutocms/supabase/blob/feat/setup-wizard/server/api/setup/create.post.ts"
|
|
330
|
+
target="_blank"
|
|
331
|
+
class="underline"
|
|
332
|
+
>
|
|
333
|
+
{{ t('supabase.setup.technicalDetailsRoute') }}</ULink
|
|
334
|
+
>
|
|
335
|
+
</template>
|
|
336
|
+
<template #files>
|
|
337
|
+
<ULink
|
|
338
|
+
to="https://github.com/plutocms/supabase/tree/main/db/migrations"
|
|
339
|
+
target="_blank"
|
|
340
|
+
class="underline"
|
|
341
|
+
>
|
|
342
|
+
{{ t('supabase.setup.technicalDetailsFiles') }}</ULink
|
|
343
|
+
>
|
|
344
|
+
</template>
|
|
345
|
+
</SupabaseMessageParts>
|
|
331
346
|
</p>
|
|
332
347
|
|
|
333
348
|
<p>
|
|
334
|
-
|
|
335
|
-
NOT be stored or used for any other purpose.
|
|
349
|
+
{{ t('supabase.setup.technicalDetailsStored') }}
|
|
336
350
|
</p>
|
|
337
351
|
</div>
|
|
338
352
|
</template>
|
|
@@ -344,11 +358,11 @@ function handleStepChange(step: number) {
|
|
|
344
358
|
|
|
345
359
|
<UAlert
|
|
346
360
|
v-if="isDev"
|
|
361
|
+
:title="t('supabase.connection.restartTitle')"
|
|
362
|
+
:description="t('supabase.setup.restartDescription')"
|
|
347
363
|
color="info"
|
|
348
364
|
variant="outline"
|
|
349
|
-
title="This restarts the dev server"
|
|
350
365
|
icon="lucide:refresh-cw"
|
|
351
|
-
description="Saving your connection string writes it to .env. In development, that restarts the server automatically. The page will briefly show a reconnecting message — this is expected, not an error."
|
|
352
366
|
/>
|
|
353
367
|
</UForm>
|
|
354
368
|
</section>
|
|
@@ -358,12 +372,11 @@ function handleStepChange(step: number) {
|
|
|
358
372
|
<hgroup class="text-center">
|
|
359
373
|
<span class="text-3xl">🎉</span>
|
|
360
374
|
|
|
361
|
-
<h1 class="font-bold text-2xl">
|
|
375
|
+
<h1 class="font-bold text-2xl">{{ t('supabase.setup.doneTitle') }}</h1>
|
|
362
376
|
</hgroup>
|
|
363
377
|
|
|
364
378
|
<p class="text-balance text-center text-lg">
|
|
365
|
-
|
|
366
|
-
up.
|
|
379
|
+
{{ t('supabase.setup.doneDescription') }}
|
|
367
380
|
</p>
|
|
368
381
|
|
|
369
382
|
<EnvPersistWarning
|
|
@@ -378,7 +391,7 @@ function handleStepChange(step: number) {
|
|
|
378
391
|
color="primary"
|
|
379
392
|
trailing
|
|
380
393
|
>
|
|
381
|
-
|
|
394
|
+
{{ t('supabase.setup.goToSignup') }}
|
|
382
395
|
</UButton>
|
|
383
396
|
</p>
|
|
384
397
|
</div>
|