@plutocms/supabase 0.30.0 → 0.31.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/CHANGELOG.md +7 -0
- package/app/components/EnvPersistWarning.vue +11 -9
- package/app/components/SupabaseLogo.vue +47 -0
- package/app/components/backend/SupabaseBackendDetails.vue +1 -1
- package/app/components/mail/AuthEmailsPanel.vue +3 -2
- package/app/pages/admin/migrations.vue +21 -19
- package/app/pages/admin/roles.vue +117 -119
- package/app/pages/admin/setup.vue +160 -271
- package/app/pages/admin/users.vue +191 -189
- package/i18n/locales/en.json +17 -19
- package/i18n/locales/pt-BR.json +17 -19
- package/modules/internal/supabase-types-shim.ts +27 -0
- package/modules/pluto-migrations.ts +17 -10
- package/package.json +2 -2
- package/app/layouts/setup.vue +0 -13
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
// Before any account exists: the layout and the card of the admin auth pages.
|
|
4
3
|
definePageMeta({
|
|
5
|
-
layout: '
|
|
4
|
+
layout: 'auth',
|
|
6
5
|
})
|
|
7
6
|
|
|
8
|
-
const { t
|
|
7
|
+
const { t } = usePlutoI18n()
|
|
9
8
|
|
|
10
9
|
useHead({
|
|
11
10
|
title: () => t('supabase.setup.title'),
|
|
@@ -20,21 +19,9 @@ const toast = useToast()
|
|
|
20
19
|
|
|
21
20
|
const isDev = import.meta.dev
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
icon: 'i-lucide-database',
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
title: t('supabase.setup.steps.complete'),
|
|
31
|
-
icon: 'i-lucide-check',
|
|
32
|
-
},
|
|
33
|
-
])
|
|
34
|
-
|
|
35
|
-
const stepper = useTemplateRef('stepper')
|
|
36
|
-
|
|
37
|
-
const currentStep = ref<number>(0)
|
|
22
|
+
// The form, then the result (after a setup that worked).
|
|
23
|
+
const done = ref(false)
|
|
24
|
+
const detailsOpen = ref(false)
|
|
38
25
|
|
|
39
26
|
const isSettingUpDatabase = ref(false)
|
|
40
27
|
|
|
@@ -49,33 +36,9 @@ const databaseForm = ref({
|
|
|
49
36
|
const envNotPersisted = ref(false)
|
|
50
37
|
const submittedConnectionString = ref('')
|
|
51
38
|
|
|
52
|
-
const currentLoading = computed(() => {
|
|
53
|
-
if (currentStep.value === 0) {
|
|
54
|
-
return isSettingUpDatabase.value
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return false
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
const currentStepId = computed(() => {
|
|
61
|
-
if (currentStep.value === 0) {
|
|
62
|
-
return 'database-setup-form'
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return undefined
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
const currentStepSubmitLabel = computed(() => {
|
|
69
|
-
if (currentStep.value === 0) {
|
|
70
|
-
return t('supabase.setup.submit')
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return t('supabase.setup.next')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
39
|
/**
|
|
77
40
|
* Polls /api/_pluto/supabase/setup until the dev server responds again, and
|
|
78
|
-
*
|
|
41
|
+
* shows the result once it does.
|
|
79
42
|
*
|
|
80
43
|
* Used only to wait out the restart described in the `catch` block of
|
|
81
44
|
* `completeDatabaseSetup` — the server is expected to come back within a
|
|
@@ -98,7 +61,7 @@ async function waitForServerAndAdvance(): Promise<boolean> {
|
|
|
98
61
|
color: 'success',
|
|
99
62
|
})
|
|
100
63
|
|
|
101
|
-
|
|
64
|
+
done.value = true
|
|
102
65
|
|
|
103
66
|
return true
|
|
104
67
|
} catch {
|
|
@@ -137,7 +100,7 @@ async function completeDatabaseSetup() {
|
|
|
137
100
|
color: 'success',
|
|
138
101
|
})
|
|
139
102
|
|
|
140
|
-
|
|
103
|
+
done.value = true
|
|
141
104
|
} catch (error) {
|
|
142
105
|
// The route answers a failed setup with an HTTP error that carries the
|
|
143
106
|
// scrubbed database error in its data.
|
|
@@ -203,238 +166,164 @@ async function completeDatabaseSetup() {
|
|
|
203
166
|
isSettingUpDatabase.value = false
|
|
204
167
|
}
|
|
205
168
|
}
|
|
206
|
-
|
|
207
|
-
function handleStepChange(step: number) {
|
|
208
|
-
if (step === 0) {
|
|
209
|
-
completeDatabaseSetup()
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
169
|
</script>
|
|
213
170
|
|
|
214
171
|
<template>
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
172
|
+
<PlutoAdminAuthCard
|
|
173
|
+
:title="done ? t('supabase.setup.doneTitle') : t('supabase.setup.title')"
|
|
174
|
+
:description="
|
|
175
|
+
done
|
|
176
|
+
? t('supabase.setup.doneDescription')
|
|
177
|
+
: t('supabase.setup.description')
|
|
178
|
+
"
|
|
179
|
+
wide
|
|
180
|
+
>
|
|
181
|
+
<template #partner>
|
|
182
|
+
<UIcon
|
|
183
|
+
name="i-lucide-arrow-right"
|
|
184
|
+
class="text-dimmed size-4 shrink-0"
|
|
185
|
+
aria-hidden="true"
|
|
186
|
+
/>
|
|
187
|
+
<SupabaseLogo class="size-7 shrink-0" role="img" aria-label="Supabase" />
|
|
188
|
+
</template>
|
|
189
|
+
|
|
190
|
+
<template v-if="done">
|
|
191
|
+
<EnvPersistWarning
|
|
192
|
+
v-if="envNotPersisted"
|
|
193
|
+
:connection-string="submittedConnectionString"
|
|
194
|
+
/>
|
|
195
|
+
|
|
196
|
+
<UButton
|
|
197
|
+
:label="t('supabase.setup.goToSignup')"
|
|
198
|
+
to="/admin/signup"
|
|
199
|
+
trailing-icon="lucide:arrow-right"
|
|
200
|
+
class="w-full justify-center"
|
|
201
|
+
/>
|
|
202
|
+
</template>
|
|
203
|
+
|
|
204
|
+
<UForm v-else class="flex flex-col gap-y-5" @submit="completeDatabaseSetup">
|
|
205
|
+
<UFormField :label="t('supabase.connection.connectionString')" required>
|
|
206
|
+
<UInput
|
|
207
|
+
v-model="databaseForm.connectionString"
|
|
208
|
+
:disabled="isSettingUpDatabase"
|
|
209
|
+
placeholder="postgresql://"
|
|
210
|
+
class="w-full"
|
|
211
|
+
autofocus
|
|
212
|
+
required
|
|
213
|
+
/>
|
|
214
|
+
|
|
215
|
+
<template #help>
|
|
216
|
+
<SupabaseMessageParts :message="t('supabase.setup.connectionHelp')">
|
|
217
|
+
<template #link>
|
|
218
|
+
<PlutoExternalLink
|
|
219
|
+
:to="`https://supabase.com/dashboard/project/${projectId}/database/settings?showConnect=true&method=transaction`"
|
|
220
|
+
class="text-default underline"
|
|
221
|
+
>
|
|
222
|
+
{{ t('supabase.setup.connectionHelpLink') }}
|
|
223
|
+
</PlutoExternalLink>
|
|
224
|
+
</template>
|
|
225
|
+
</SupabaseMessageParts>
|
|
226
|
+
</template>
|
|
227
|
+
</UFormField>
|
|
228
|
+
|
|
229
|
+
<UFormField :label="t('supabase.connection.password')" required>
|
|
230
|
+
<UInput
|
|
231
|
+
v-model="databaseForm.password"
|
|
232
|
+
:disabled="isSettingUpDatabase"
|
|
233
|
+
type="password"
|
|
234
|
+
placeholder="• • • • •"
|
|
235
|
+
class="w-full"
|
|
236
|
+
required
|
|
237
|
+
/>
|
|
238
|
+
|
|
239
|
+
<template #help>
|
|
240
|
+
<SupabaseMessageParts :message="t('supabase.setup.passwordHelp')">
|
|
241
|
+
<template #placeholder>
|
|
242
|
+
<code>[YOUR-PASSWORD]</code>
|
|
243
|
+
</template>
|
|
244
|
+
|
|
245
|
+
<template #link>
|
|
246
|
+
<PlutoExternalLink
|
|
247
|
+
:to="`https://supabase.com/dashboard/project/${projectId ?? '_'}/database/settings`"
|
|
248
|
+
class="text-default underline"
|
|
227
249
|
>
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
250
|
+
{{ t('supabase.setup.passwordHelpLink') }}
|
|
251
|
+
</PlutoExternalLink>
|
|
252
|
+
</template>
|
|
253
|
+
</SupabaseMessageParts>
|
|
254
|
+
</template>
|
|
255
|
+
</UFormField>
|
|
256
|
+
|
|
257
|
+
<!-- Where the connection goes, and how the setup works (folded). -->
|
|
258
|
+
<div
|
|
259
|
+
class="bg-elevated/50 ring-default flex flex-col gap-y-1 rounded-md p-3 ring"
|
|
260
|
+
>
|
|
261
|
+
<div class="flex gap-x-2 text-sm">
|
|
262
|
+
<UIcon name="lucide:lock" class="text-muted mt-0.5 size-4 shrink-0" />
|
|
263
|
+
<p class="text-muted">
|
|
264
|
+
<PlutoCodeText :text="t('supabase.setup.stored')" />
|
|
265
|
+
</p>
|
|
266
|
+
</div>
|
|
267
|
+
|
|
268
|
+
<UCollapsible v-model:open="detailsOpen">
|
|
269
|
+
<UButton
|
|
270
|
+
:label="t('supabase.setup.howItWorks')"
|
|
271
|
+
:trailing-icon="
|
|
272
|
+
detailsOpen ? 'lucide:chevron-up' : 'lucide:chevron-down'
|
|
273
|
+
"
|
|
274
|
+
color="neutral"
|
|
275
|
+
variant="link"
|
|
276
|
+
size="sm"
|
|
277
|
+
class="ms-4 px-2"
|
|
278
|
+
/>
|
|
279
|
+
|
|
280
|
+
<template #content>
|
|
281
|
+
<ul
|
|
282
|
+
class="text-muted ms-6 flex list-disc flex-col gap-y-1 ps-4 pt-1 text-sm"
|
|
283
|
+
>
|
|
284
|
+
<li>
|
|
285
|
+
<SupabaseMessageParts
|
|
286
|
+
:message="t('supabase.setup.detailsRequest')"
|
|
231
287
|
>
|
|
232
|
-
<
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
autofocus
|
|
237
|
-
required
|
|
238
|
-
/>
|
|
239
|
-
|
|
240
|
-
<template #help>
|
|
241
|
-
<SupabaseMessageParts
|
|
242
|
-
:message="t('supabase.connection.connectionStringHelp')"
|
|
288
|
+
<template #route>
|
|
289
|
+
<PlutoExternalLink
|
|
290
|
+
to="https://github.com/plutocms/supabase/blob/main/packages/supabase/server/api/_pluto/supabase/setup/index.post.ts"
|
|
291
|
+
class="text-default underline"
|
|
243
292
|
>
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
:to="`https://supabase.com/dashboard/project/${projectId}/database/settings?showConnect=true&method=transaction`"
|
|
247
|
-
target="_blank"
|
|
248
|
-
class="underline"
|
|
249
|
-
external
|
|
250
|
-
>
|
|
251
|
-
{{
|
|
252
|
-
t('supabase.connection.connectionStringHelpLink')
|
|
253
|
-
}}
|
|
254
|
-
</ULink>
|
|
255
|
-
</template>
|
|
256
|
-
</SupabaseMessageParts>
|
|
293
|
+
{{ t('supabase.setup.detailsRoute') }}
|
|
294
|
+
</PlutoExternalLink>
|
|
257
295
|
</template>
|
|
258
|
-
</
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
required
|
|
267
|
-
/>
|
|
268
|
-
</UFormField>
|
|
269
|
-
|
|
270
|
-
<UAlert
|
|
271
|
-
color="secondary"
|
|
272
|
-
icon="lucide:badge-info"
|
|
273
|
-
variant="outline"
|
|
274
|
-
>
|
|
275
|
-
<template #description>
|
|
276
|
-
<SupabaseMessageParts
|
|
277
|
-
:message="t('supabase.connection.passwordInfo')"
|
|
296
|
+
</SupabaseMessageParts>
|
|
297
|
+
</li>
|
|
298
|
+
<li>
|
|
299
|
+
<SupabaseMessageParts :message="t('supabase.setup.detailsRun')">
|
|
300
|
+
<template #files>
|
|
301
|
+
<PlutoExternalLink
|
|
302
|
+
to="https://github.com/plutocms/supabase/tree/main/packages/supabase/db/migrations"
|
|
303
|
+
class="text-default underline"
|
|
278
304
|
>
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
to="https://supabase.com/dashboard/project/_/database/settings"
|
|
282
|
-
target="_blank"
|
|
283
|
-
>
|
|
284
|
-
{{ t('supabase.connection.passwordInfoLink') }}
|
|
285
|
-
</ULink>
|
|
286
|
-
</template>
|
|
287
|
-
</SupabaseMessageParts>
|
|
305
|
+
{{ t('supabase.setup.detailsFiles') }}
|
|
306
|
+
</PlutoExternalLink>
|
|
288
307
|
</template>
|
|
289
|
-
</
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
{{ t('supabase.setup.promise') }}</span
|
|
311
|
-
></UTooltip
|
|
312
|
-
>
|
|
313
|
-
</template>
|
|
314
|
-
</SupabaseMessageParts>
|
|
315
|
-
</p>
|
|
316
|
-
|
|
317
|
-
<div>
|
|
318
|
-
<UPopover :content="{ side: 'bottom' }" arrow>
|
|
319
|
-
<UButton
|
|
320
|
-
:label="t('supabase.setup.technicalDetails')"
|
|
321
|
-
icon="lucide:lightbulb"
|
|
322
|
-
color="info"
|
|
323
|
-
variant="subtle"
|
|
324
|
-
class="w-fit"
|
|
325
|
-
size="sm"
|
|
326
|
-
/>
|
|
327
|
-
|
|
328
|
-
<template #content>
|
|
329
|
-
<div
|
|
330
|
-
class="flex flex-col gap-y-4 max-w-xs p-4 text-white text-sm"
|
|
331
|
-
>
|
|
332
|
-
<p>
|
|
333
|
-
<SupabaseMessageParts
|
|
334
|
-
:message="
|
|
335
|
-
t('supabase.setup.technicalDetailsRequest')
|
|
336
|
-
"
|
|
337
|
-
>
|
|
338
|
-
<template #route>
|
|
339
|
-
<ULink
|
|
340
|
-
to="https://github.com/plutocms/supabase/blob/main/server/api/_pluto/supabase/setup/index.post.ts"
|
|
341
|
-
target="_blank"
|
|
342
|
-
class="underline"
|
|
343
|
-
>
|
|
344
|
-
{{
|
|
345
|
-
t(
|
|
346
|
-
'supabase.setup.technicalDetailsRoute'
|
|
347
|
-
)
|
|
348
|
-
}}</ULink
|
|
349
|
-
>
|
|
350
|
-
</template>
|
|
351
|
-
<template #files>
|
|
352
|
-
<ULink
|
|
353
|
-
to="https://github.com/plutocms/supabase/tree/main/db/migrations"
|
|
354
|
-
target="_blank"
|
|
355
|
-
class="underline"
|
|
356
|
-
>
|
|
357
|
-
{{
|
|
358
|
-
t(
|
|
359
|
-
'supabase.setup.technicalDetailsFiles'
|
|
360
|
-
)
|
|
361
|
-
}}</ULink
|
|
362
|
-
>
|
|
363
|
-
</template>
|
|
364
|
-
</SupabaseMessageParts>
|
|
365
|
-
</p>
|
|
366
|
-
|
|
367
|
-
<p>
|
|
368
|
-
{{ t('supabase.setup.technicalDetailsStored') }}
|
|
369
|
-
</p>
|
|
370
|
-
</div>
|
|
371
|
-
</template>
|
|
372
|
-
</UPopover>
|
|
373
|
-
</div>
|
|
374
|
-
</div>
|
|
375
|
-
</template>
|
|
376
|
-
</UAlert>
|
|
377
|
-
|
|
378
|
-
<UAlert
|
|
379
|
-
v-if="isDev"
|
|
380
|
-
:title="t('supabase.connection.restartTitle')"
|
|
381
|
-
:description="t('supabase.setup.restartDescription')"
|
|
382
|
-
color="info"
|
|
383
|
-
variant="outline"
|
|
384
|
-
icon="lucide:refresh-cw"
|
|
385
|
-
/>
|
|
386
|
-
</UForm>
|
|
387
|
-
</section>
|
|
388
|
-
|
|
389
|
-
<section v-if="currentStep === 1">
|
|
390
|
-
<div class="flex flex-col gap-y-4">
|
|
391
|
-
<hgroup class="text-center">
|
|
392
|
-
<span class="text-3xl">🎉</span>
|
|
393
|
-
|
|
394
|
-
<h1 class="font-bold text-2xl">
|
|
395
|
-
{{ t('supabase.setup.doneTitle') }}
|
|
396
|
-
</h1>
|
|
397
|
-
</hgroup>
|
|
398
|
-
|
|
399
|
-
<p class="text-balance text-center text-lg">
|
|
400
|
-
{{ t('supabase.setup.doneDescription') }}
|
|
401
|
-
</p>
|
|
402
|
-
|
|
403
|
-
<EnvPersistWarning
|
|
404
|
-
v-if="envNotPersisted"
|
|
405
|
-
:connection-string="submittedConnectionString"
|
|
406
|
-
/>
|
|
407
|
-
|
|
408
|
-
<p class="text-center">
|
|
409
|
-
<UButton
|
|
410
|
-
icon="lucide:arrow-right"
|
|
411
|
-
to="/admin/signup"
|
|
412
|
-
color="primary"
|
|
413
|
-
trailing
|
|
414
|
-
>
|
|
415
|
-
{{ t('supabase.setup.goToSignup') }}
|
|
416
|
-
</UButton>
|
|
417
|
-
</p>
|
|
418
|
-
</div>
|
|
419
|
-
</section>
|
|
420
|
-
</div>
|
|
421
|
-
|
|
422
|
-
<div class="flex justify-end">
|
|
423
|
-
<div class="w-full sm:w-auto">
|
|
424
|
-
<UButton
|
|
425
|
-
v-if="stepper?.hasNext"
|
|
426
|
-
:form="currentStepId"
|
|
427
|
-
:loading="currentLoading"
|
|
428
|
-
leading-icon="lucide:check"
|
|
429
|
-
type="submit"
|
|
430
|
-
class="w-full justify-center sm:w-auto"
|
|
431
|
-
>
|
|
432
|
-
{{ currentStepSubmitLabel }}
|
|
433
|
-
</UButton>
|
|
434
|
-
</div>
|
|
435
|
-
</div>
|
|
436
|
-
</div>
|
|
437
|
-
</UCard>
|
|
438
|
-
</div>
|
|
439
|
-
</UApp>
|
|
308
|
+
</SupabaseMessageParts>
|
|
309
|
+
</li>
|
|
310
|
+
</ul>
|
|
311
|
+
</template>
|
|
312
|
+
</UCollapsible>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
<p v-if="isDev" class="text-muted flex gap-x-2 text-xs">
|
|
316
|
+
<UIcon name="lucide:refresh-cw" class="mt-0.5 size-3.5 shrink-0" />
|
|
317
|
+
<span><PlutoCodeText :text="t('supabase.setup.restartNote')" /></span>
|
|
318
|
+
</p>
|
|
319
|
+
|
|
320
|
+
<UButton
|
|
321
|
+
:label="t('supabase.setup.submit')"
|
|
322
|
+
:loading="isSettingUpDatabase"
|
|
323
|
+
icon="lucide:database"
|
|
324
|
+
type="submit"
|
|
325
|
+
class="w-full justify-center"
|
|
326
|
+
/>
|
|
327
|
+
</UForm>
|
|
328
|
+
</PlutoAdminAuthCard>
|
|
440
329
|
</template>
|