@plutocms/supabase 0.20.0 → 0.22.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 +21 -0
- package/FEATURES.md +2 -1
- package/README.md +6 -2
- package/app/components/backend/SupabaseBackendDetails.vue +52 -0
- package/app/plugins/pluto-extension.ts +12 -0
- package/i18n/locales/en.json +6 -0
- package/i18n/locales/pt-BR.json +6 -0
- package/package.json +6 -14
- package/server/utils/content-adapter.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.22.0](https://github.com/plutocms/supabase/compare/v0.21.0...v0.22.0) (2026-11-02)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* the admin navbar shows the Supabase backend, with the project and a dashboard link ([#190](https://github.com/plutocms/supabase/issues/190)) ([2b8de9f](https://github.com/plutocms/supabase/commit/2b8de9f500a71a2afeb65fe97d66be41dac2eed2))
|
|
9
|
+
|
|
10
|
+
## [0.21.0](https://github.com/plutocms/supabase/compare/v0.20.0...v0.21.0) (2026-10-31)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* the supabase repo holds the Supabase integration (supabase, supabase-shop, supabase-blog) ([0da28ef](https://github.com/plutocms/supabase/commit/0da28ef93d4882076a3750822f011de9714156d7))
|
|
16
|
+
* the supabase repo holds the Supabase integration (supabase, supabase-shop, supabase-blog) ([ab50f47](https://github.com/plutocms/supabase/commit/ab50f4779a8fb77f61a43f4db9efcd4314ae59ec))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* apps that extend the layer no longer get the ESLint module or an install script ([#151](https://github.com/plutocms/supabase/issues/151)) ([818bf93](https://github.com/plutocms/supabase/commit/818bf93a44cea01e6a1b237ace33a325f45de590))
|
|
22
|
+
* **deps:** ensure @plutocms/pluto ^0.10.0 range is published ([#67](https://github.com/plutocms/supabase/issues/67)) ([ed45ad3](https://github.com/plutocms/supabase/commit/ed45ad3a5b1ed4c4990a2272c48571c5e8eb5a92))
|
|
23
|
+
|
|
3
24
|
## [0.20.0](https://github.com/plutocms/supabase/compare/v0.19.0...v0.20.0) (2026-10-31)
|
|
4
25
|
|
|
5
26
|
|
package/FEATURES.md
CHANGED
|
@@ -19,7 +19,8 @@ policies shared by every project here.
|
|
|
19
19
|
filters, puts the timestamps on items, and reads the public API of core with an anonymous client.
|
|
20
20
|
@.claude/skills/content-adapter/SKILL.md
|
|
21
21
|
- Auth driver: plugs Supabase sign-in into the admin shell that pluto core owns (navbar, sign-in
|
|
22
|
-
page, route guard),
|
|
22
|
+
page, route guard), keeps the setup guard in the driver, and registers the backend badge
|
|
23
|
+
("Database · Supabase", with the project and a dashboard link).
|
|
23
24
|
@.claude/skills/auth-driver/SKILL.md
|
|
24
25
|
- Profile language: stores each user's admin language in `profiles.locale`, written through a
|
|
25
26
|
security-definer function, and plugs it into pluto's i18n as a locale driver.
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ npm i @plutocms/supabase
|
|
|
26
26
|
```ts
|
|
27
27
|
// nuxt.config.ts
|
|
28
28
|
export default defineNuxtConfig({
|
|
29
|
-
extends: [
|
|
29
|
+
extends: ['@plutocms/supabase'],
|
|
30
30
|
})
|
|
31
31
|
```
|
|
32
32
|
|
|
@@ -116,7 +116,7 @@ a page of another site cannot call them. A failure is an HTTP error with a trans
|
|
|
116
116
|
|
|
117
117
|
The public content of the Supabase layers is read through the public API of core,
|
|
118
118
|
`GET /api/pluto/v1/content/<type>` (and `/<id or slug>`). See
|
|
119
|
-
[the public API](https://pluto.vulmix.dev/docs/
|
|
119
|
+
[the public API](https://pluto.vulmix.dev/docs/build/public-api). The routes are anonymous. This layer
|
|
120
120
|
reads for them with an anon client that has no user session, so Row Level Security applies as for
|
|
121
121
|
an anonymous visitor, and the answer is the same for everyone. A CDN can cache it. The adapter
|
|
122
122
|
never uses the service role key for a read. The adapter also supports the `filters` of a public
|
|
@@ -141,3 +141,7 @@ sort by date.
|
|
|
141
141
|
### Types
|
|
142
142
|
|
|
143
143
|
- `Database`: Auto-imported type definitions for Supabase database interactions.
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
This package lives in the [`plutocms/supabase`](https://github.com/plutocms/supabase) monorepo, in `packages/supabase`. Run `bun install` at the root of the repo, then the scripts of the package (`bun run --cwd packages/supabase dev`). This package is the base of the other two. Its changes reach `supabase-shop` and `supabase-blog` through the workspace link. Each package reads its own `.env` file.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// The popover body of the backend badge of core (`backend.details`): the
|
|
3
|
+
// Supabase project that holds the content, with a link to its dashboard. A
|
|
4
|
+
// local Supabase (or a custom domain) has no project ref, so the host shows.
|
|
5
|
+
import {
|
|
6
|
+
supabaseDashboardLinks,
|
|
7
|
+
supabaseProjectRef,
|
|
8
|
+
} from '../../utils/supabase-project'
|
|
9
|
+
|
|
10
|
+
const { t } = usePlutoI18n()
|
|
11
|
+
const url = String(
|
|
12
|
+
(useRuntimeConfig().public.supabase as { url?: string } | undefined)?.url ??
|
|
13
|
+
''
|
|
14
|
+
)
|
|
15
|
+
const projectRef = supabaseProjectRef(url)
|
|
16
|
+
const dashboard = projectRef ? supabaseDashboardLinks(projectRef).project : ''
|
|
17
|
+
const host = (() => {
|
|
18
|
+
try {
|
|
19
|
+
return new URL(url).host
|
|
20
|
+
} catch {
|
|
21
|
+
return ''
|
|
22
|
+
}
|
|
23
|
+
})()
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<div class="space-y-3">
|
|
28
|
+
<p class="text-muted">{{ t('supabase.backend.description') }}</p>
|
|
29
|
+
<dl class="grid grid-cols-[auto_1fr] gap-x-3 gap-y-1">
|
|
30
|
+
<dt class="text-muted">
|
|
31
|
+
{{
|
|
32
|
+
projectRef
|
|
33
|
+
? t('supabase.backend.project')
|
|
34
|
+
: t('supabase.backend.host')
|
|
35
|
+
}}
|
|
36
|
+
</dt>
|
|
37
|
+
<dd class="text-highlighted truncate font-mono text-xs/5">
|
|
38
|
+
{{ projectRef || host }}
|
|
39
|
+
</dd>
|
|
40
|
+
</dl>
|
|
41
|
+
<UButton
|
|
42
|
+
v-if="dashboard"
|
|
43
|
+
:label="t('supabase.backend.openDashboard')"
|
|
44
|
+
:to="dashboard"
|
|
45
|
+
color="neutral"
|
|
46
|
+
icon="i-lucide-external-link"
|
|
47
|
+
size="xs"
|
|
48
|
+
target="_blank"
|
|
49
|
+
variant="outline"
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
@@ -11,6 +11,10 @@ const MigrationsBanner = defineAsyncComponent(
|
|
|
11
11
|
const SettingsGeneralPanel = defineAsyncComponent(
|
|
12
12
|
() => import('../components/settings/SettingsGeneralPanel.vue')
|
|
13
13
|
)
|
|
14
|
+
// The popover of the backend badge of the navbar.
|
|
15
|
+
const SupabaseBackendDetails = defineAsyncComponent(
|
|
16
|
+
() => import('../components/backend/SupabaseBackendDetails.vue')
|
|
17
|
+
)
|
|
14
18
|
// The guide for the Supabase sign-in emails, a section of the Email tab.
|
|
15
19
|
const AuthEmailsPanel = defineAsyncComponent(
|
|
16
20
|
() => import('../components/mail/AuthEmailsPanel.vue')
|
|
@@ -152,6 +156,14 @@ export default defineNuxtPlugin(() => {
|
|
|
152
156
|
// In development, "View site" opens this dev server, like the old navbar.
|
|
153
157
|
url: () => (import.meta.dev ? null : siteSettings.value.website_url),
|
|
154
158
|
},
|
|
159
|
+
// The backend badge of the navbar: the content is in a Supabase database.
|
|
160
|
+
backend: {
|
|
161
|
+
id: 'supabase',
|
|
162
|
+
kind: 'database',
|
|
163
|
+
label: 'Supabase',
|
|
164
|
+
icon: 'i-lucide-database',
|
|
165
|
+
details: SupabaseBackendDetails,
|
|
166
|
+
},
|
|
155
167
|
// The pending-migrations notice, shown at the top of the admin pages.
|
|
156
168
|
adminBanners: [{ id: 'migrations', component: MigrationsBanner }],
|
|
157
169
|
settingsPanels: [
|
package/i18n/locales/en.json
CHANGED
|
@@ -386,6 +386,12 @@
|
|
|
386
386
|
"noProject": "Pluto could not read the project ref from your Supabase URL. Open the Supabase dashboard by hand.",
|
|
387
387
|
"rateLimitHint": "After you set custom SMTP, open Authentication, then Rate Limits, and raise the number of emails each hour. The default is low."
|
|
388
388
|
}
|
|
389
|
+
},
|
|
390
|
+
"backend": {
|
|
391
|
+
"description": "Each save writes to the Postgres database of this Supabase project.",
|
|
392
|
+
"project": "Project",
|
|
393
|
+
"host": "Server",
|
|
394
|
+
"openDashboard": "Open the Supabase dashboard"
|
|
389
395
|
}
|
|
390
396
|
}
|
|
391
397
|
}
|
package/i18n/locales/pt-BR.json
CHANGED
|
@@ -386,6 +386,12 @@
|
|
|
386
386
|
"noProject": "O Pluto não conseguiu ler a referência do projeto na sua URL do Supabase. Abra o painel do Supabase manualmente.",
|
|
387
387
|
"rateLimitHint": "Depois de configurar o SMTP próprio, abra Authentication, depois Rate Limits, e aumente o número de e-mails por hora. O padrão é baixo."
|
|
388
388
|
}
|
|
389
|
+
},
|
|
390
|
+
"backend": {
|
|
391
|
+
"description": "Cada salvamento grava no banco Postgres deste projeto do Supabase.",
|
|
392
|
+
"project": "Projeto",
|
|
393
|
+
"host": "Servidor",
|
|
394
|
+
"openDashboard": "Abrir o painel do Supabase"
|
|
389
395
|
}
|
|
390
396
|
}
|
|
391
397
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plutocms/supabase",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.22.0",
|
|
5
5
|
"description": "Supabase backend layer for Pluto",
|
|
6
6
|
"author": "Victor Ribeiro",
|
|
7
|
-
"homepage": "https://github.com/plutocms/supabase#readme",
|
|
7
|
+
"homepage": "https://github.com/plutocms/supabase/tree/main/packages/supabase#readme",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/plutocms/supabase.git"
|
|
10
|
+
"url": "git+https://github.com/plutocms/supabase.git",
|
|
11
|
+
"directory": "packages/supabase"
|
|
11
12
|
},
|
|
12
13
|
"bugs": {
|
|
13
14
|
"url": "https://github.com/plutocms/supabase/issues"
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
"dev": "nuxt dev",
|
|
19
20
|
"generate": "nuxt generate",
|
|
20
21
|
"preview": "nuxt preview",
|
|
21
|
-
"prepare": "nuxt prepare",
|
|
22
|
+
"dev:prepare": "nuxt prepare",
|
|
22
23
|
"prettier": "prettier --write .",
|
|
23
24
|
"lint": "eslint .",
|
|
24
25
|
"lint:fix": "eslint . --fix",
|
|
@@ -29,31 +30,22 @@
|
|
|
29
30
|
"dependencies": {
|
|
30
31
|
"@nuxt/ui": "^4.12.0",
|
|
31
32
|
"@nuxtjs/supabase": "^2.1.0",
|
|
32
|
-
"@plutocms/core": ">=0.
|
|
33
|
+
"@plutocms/core": ">=0.48.0 <1.0.0",
|
|
33
34
|
"@supabase/supabase-js": "^2.117.3",
|
|
34
35
|
"postgres": "^3.4.9",
|
|
35
36
|
"supabase": "^2.121.0",
|
|
36
37
|
"zod": "^4.6.7"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@antfu/eslint-config": "^9.5.1",
|
|
40
|
-
"@nuxt/eslint-config": "^1.17.0",
|
|
41
40
|
"@types/bun": "^1.4.3",
|
|
42
41
|
"@vueuse/nuxt": "^14.4.0",
|
|
43
|
-
"eslint": "^10.13.0",
|
|
44
|
-
"eslint-config-prettier": "^10.1.8",
|
|
45
|
-
"eslint-plugin-better-tailwindcss": "^4.10.0",
|
|
46
42
|
"nuxt": "^4.6.2",
|
|
47
|
-
"prettier": "^3.9.10",
|
|
48
43
|
"tailwindcss": "^4.3.3",
|
|
49
44
|
"vitest": "^5.0.5",
|
|
50
45
|
"vue": "^3.5.44",
|
|
51
46
|
"vue-router": "^5.4.0",
|
|
52
47
|
"vue-tsc": "^3.3.13"
|
|
53
48
|
},
|
|
54
|
-
"overrides": {
|
|
55
|
-
"typescript": "^5.9.3"
|
|
56
|
-
},
|
|
57
49
|
"publishConfig": {
|
|
58
50
|
"access": "public"
|
|
59
51
|
}
|
|
@@ -9,9 +9,9 @@ import { requireCapability } from './capability-guard'
|
|
|
9
9
|
*
|
|
10
10
|
* A content type's table name (`type.source`) is a plain runtime string —
|
|
11
11
|
* it is not known until a layer declares a content type, in a different
|
|
12
|
-
*
|
|
12
|
+
* package, at that package's build time. `serverSupabaseClient` defaults to
|
|
13
13
|
* this app's own `Database` type (see `shared/types/supabase.ts`), whose
|
|
14
|
-
* `.from()` only accepts this
|
|
14
|
+
* `.from()` only accepts this package's own table names as literals. Casting
|
|
15
15
|
* to the bare `SupabaseClient` type (whose own generic defaults to `any`)
|
|
16
16
|
* is the one, deliberate place this file loses compile-time table/column
|
|
17
17
|
* safety. See `.claude/skills/content-adapter/SKILL.md` for the full
|
|
@@ -19,7 +19,7 @@ import { requireCapability } from './capability-guard'
|
|
|
19
19
|
*
|
|
20
20
|
* Goes through `unknown` first: `serverSupabaseClient`'s inferred
|
|
21
21
|
* `Database` type is whichever layer's own generated types are in scope
|
|
22
|
-
* at the *call site* — this
|
|
22
|
+
* at the *call site* — this package's own `shared/types/supabase.ts` when
|
|
23
23
|
* typechecked standalone, but a different consumer's own generated types
|
|
24
24
|
* when this file is typechecked as part of a deeper extends chain (a
|
|
25
25
|
* layer that extends this one, extending it in turn). A direct `as
|