@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.
Files changed (41) hide show
  1. package/.prettierignore +2 -0
  2. package/CHANGELOG.md +19 -0
  3. package/FEATURES.md +9 -0
  4. package/README.md +10 -1
  5. package/app/components/EnvPersistWarning.vue +30 -13
  6. package/app/components/SupabaseMessageParts.vue +29 -0
  7. package/app/components/auth/AuthSignIn.vue +56 -0
  8. package/app/components/migrations/MigrationsBanner.vue +28 -15
  9. package/app/components/settings/SettingsGeneralPanel.vue +21 -6
  10. package/app/composables/auth.ts +38 -101
  11. package/app/pages/admin/(auth)/confirm.vue +20 -23
  12. package/app/pages/admin/(auth)/forgot-password.vue +60 -63
  13. package/app/pages/admin/(auth)/signup.vue +115 -110
  14. package/app/pages/admin/(auth)/update-password.vue +78 -82
  15. package/app/pages/admin/migrations.vue +87 -51
  16. package/app/pages/admin/setup.vue +88 -75
  17. package/app/plugins/pluto-extension.ts +143 -10
  18. package/app/utils/auth-driver.ts +110 -0
  19. package/app/utils/auth-error.ts +53 -0
  20. package/db/migrations/005_profile_locale.sql +44 -0
  21. package/i18n/locales/en.json +193 -0
  22. package/i18n/locales/pt-BR.json +193 -0
  23. package/package.json +3 -3
  24. package/server/api/profile/locale.get.ts +39 -0
  25. package/server/api/profile/locale.post.ts +71 -0
  26. package/server/api/setup/create.post.ts +6 -4
  27. package/server/api/users/[id].get.ts +4 -2
  28. package/server/api/users/index.get.ts +4 -2
  29. package/server/utils/admin-guard.ts +10 -2
  30. package/server/utils/capability-guard.ts +18 -4
  31. package/server/utils/content-adapter.ts +6 -4
  32. package/server/utils/pending-migrations.ts +0 -0
  33. package/server/utils/validate.ts +6 -1
  34. package/shared/types/supabase.ts +7 -0
  35. package/app/components/navbar/NavbarAdmin.vue +0 -213
  36. package/app/components/navbar/NavbarAdminProvider.vue +0 -18
  37. package/app/middleware/auth.ts +0 -34
  38. package/app/middleware/setup-check.ts +0 -44
  39. package/app/pages/admin/(auth)/login.vue +0 -93
  40. package/app/pages/admin.vue +0 -56
  41. 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: 'Migrations',
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: 'Could not apply migrations',
104
+ title: t('supabase.migrations.applyFailed'),
90
105
  description: result.needsConnectionString
91
- ? 'A database connection string is required.'
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: 'Migrations applied',
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: 'Dev server restarting',
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: 'Reconnected',
151
+ title: t('supabase.connection.reconnected'),
138
152
  description:
139
153
  pendingCount.value === 0
140
- ? 'The server is back. All migrations were applied.'
141
- : `The server is back. ${pendingCount.value} layer(s) still pending — check above.`,
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: 'Still reconnecting',
147
- description:
148
- 'The dev server is taking longer than expected. Reload this page in a moment.',
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: 'Error applying migrations',
163
- description: 'Please check the console for more details.',
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">Migrations</h1>
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>Loading migration status…</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
- Pending layers ({{ status.pending.length }})
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
- Applied layers ({{ status.applied.length }})
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="Supabase connection string" required>
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
- You can find your connection string
254
- <ULink
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
- clicking here </ULink
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="Database password" required>
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
- Your password is created when you create your Supabase
282
- project. You can change it in the
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
- Supabase Database Settings </ULink
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
- Apply pending migrations
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
- Apply pending migrations
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">Last run</h2>
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
- Retry
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: 'Setup Wizard',
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 = ref<StepperItem[]>([
23
+ const items = computed<StepperItem[]>(() => [
23
24
  {
24
- title: 'Database Setup',
25
+ title: t('supabase.setup.steps.database'),
25
26
  icon: 'i-lucide-database',
26
27
  },
27
28
 
28
29
  {
29
- title: 'Complete Setup',
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 'Set up database'
70
+ return t('supabase.setup.submit')
70
71
  }
71
72
 
72
- return 'Submit'
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: 'Reconnected',
95
- description: 'The server is back. Your database has been set up.',
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: 'Database setup failed',
130
- description: 'Please check your password and try again.',
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: 'Database setup complete',
145
- description: 'Your database has been set up successfully.',
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: 'Dev server restarting',
168
- description: 'Setup is finishing. Reconnecting…',
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: 'Still reconnecting',
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: 'Error setting up the database',
196
- description: 'Please check the console for more details.',
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="Supabase connection string" required>
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
- You can find your connection string
237
- <ULink
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
- clicking here </ULink
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="Database password" required>
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
- Your password is created when you create your Supabase
265
- project. You can change it in the
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
- Supabase Database Settings </ULink
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
- It will be used to create your database structure. It
285
- won't be stored anywhere. That's a
286
- <UTooltip
287
- text="Click on the 'Technical details' button for more info"
293
+ <SupabaseMessageParts
294
+ :message="t('supabase.setup.why')"
288
295
  >
289
- <span class="underline decoration-dotted cursor-help">
290
- promise</span
291
- ></UTooltip
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
- When you click "Next", a request to
312
- <ULink
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
- SQL files</ULink
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
- After the setup is complete, the password will
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">Setup Complete</h1>
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
- Your database is ready. Create your admin account by signing
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
- Go to sign up
394
+ {{ t('supabase.setup.goToSignup') }}
382
395
  </UButton>
383
396
  </p>
384
397
  </div>