@supabase/lite 0.9.1-next.1 → 0.10.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/FEATURES.md +6 -6
- package/LIMITATIONS.md +8 -6
- package/PATTERNS.md +66 -6
- package/README.md +15 -8
- package/STATUS.md +26 -19
- package/dist/{Connection-ZWTDByQ5.d.ts → Connection-f_d5HhQ0.d.ts} +301 -293
- package/dist/cli/index.js +127 -124
- package/dist/cli/lib.d.ts +1 -12
- package/dist/cli/lib.js +44 -39
- package/dist/db/fallback.d.ts +1 -1
- package/dist/db/postgres/PostgresConnection.js +18 -18
- package/dist/db/postgres/pglite/PgliteConnection.js +4 -4
- package/dist/index.d.ts +90 -38
- package/dist/index.js +181 -73
- package/dist/static/.vite/manifest.json +34 -2
- package/dist/static/assets/InterVariable-Dx4kXJAl.woff2 +0 -0
- package/dist/static/assets/InterVariable-Italic-DpCbqKDY.woff2 +0 -0
- package/dist/static/assets/SourceCodePro-Variable-BP8Zz55n.woff2 +0 -0
- package/dist/static/assets/SourceCodePro-Variable-Italic-eALmlzX7.woff2 +0 -0
- package/dist/static/assets/main-BY4iigay.css +1 -0
- package/dist/static/assets/main-BnQ-v4V9.js +199 -0
- package/dist/static/assets/manrope-latin-ext-wght-normal-Ch3YOpNY.woff2 +0 -0
- package/dist/static/assets/manrope-latin-wght-normal-DHIcAJRg.woff2 +0 -0
- package/dist/vite/index.d.ts +601 -29
- package/dist/vite/index.js +2 -2
- package/docs/auth/overview.mdx +1 -1
- package/docs/auth/supported-flows.mdx +4 -4
- package/docs/compatibility.mdx +4 -4
- package/docs/database/migrations.mdx +2 -0
- package/docs/database/rls.mdx +7 -5
- package/docs/database/schemas.mdx +1 -1
- package/docs/integrations/embedded.mdx +20 -3
- package/docs/integrations/frameworks.mdx +1 -1
- package/docs/integrations/vite.mdx +4 -2
- package/docs/llms.txt +2 -2
- package/docs/quickstart.mdx +2 -2
- package/docs/running.mdx +20 -10
- package/docs/storage/limitations.mdx +2 -11
- package/docs/storage/overview.mdx +8 -2
- package/package.json +2 -1
- package/skills/supalite/SKILL.md +1 -1
- package/dist/static/assets/main-1bwWb_1q.js +0 -40996
- package/dist/static/assets/main-BDsRycsc.css +0 -4045
- package/dist/static/fonts/CustomFont-Black.woff2 +0 -0
- package/dist/static/fonts/CustomFont-BlackItalic.woff2 +0 -0
- package/dist/static/fonts/CustomFont-Bold.woff2 +0 -0
- package/dist/static/fonts/CustomFont-BoldItalic.woff2 +0 -0
- package/dist/static/fonts/CustomFont-Book.woff2 +0 -0
- package/dist/static/fonts/CustomFont-BookItalic.woff2 +0 -0
- package/dist/static/fonts/CustomFont-Medium.woff2 +0 -0
package/FEATURES.md
CHANGED
|
@@ -56,7 +56,7 @@ CRUD, filtering, embedding, and RLS over your tables. This is the most complete
|
|
|
56
56
|
| Resource embedding (FK joins, `!inner`, spreads, nested, aggregates) | ✅ | ✅ | - | - | |
|
|
57
57
|
| Embedding through views (view→base-table FK tracing) | ⚠️ | ⚠️ | `M` | `platform-limited` | Simple updatable views resolve embeds via their base-table FKs on both paths. Postgres path additionally supports: **materialized views** (introspected via `pg_matviews`/`relkind 'm'` and treated as routable relations with derived FKs) and **multi-level recursive view-of-view** (column maps composed transitively to the ultimate physical base via a fixpoint loop with a depth-16 cap and cycle guard). Not yet traced on either path: complex views (CTE, GROUP BY, subselect-in-FROM, JOINs), and same-name relation collisions across two exposed schemas. See [STATUS.md](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#database-api-postgrest-compatible) / [LIMITATIONS.md](https://github.com/supabase-community/lite/blob/HEAD/LIMITATIONS.md). |
|
|
58
58
|
| Bulk ops & `Prefer` headers (representation, merge/ignore-duplicates, max-affected) | ✅ | ✅ | - | - | |
|
|
59
|
-
| RLS enforcement (`auth.uid()`/`role()`/`jwt()`, permissive/restrictive, per-command, roles) | ✅ | ✅ | - | - | App-layer rewrite on SQLite; native on Postgres. On `sqlite-postgres
|
|
59
|
+
| RLS enforcement (`auth.uid()`/`role()`/`jwt()`, permissive/restrictive, per-command, roles) | ✅ | ✅ | - | - | App-layer rewrite on SQLite; native on Postgres. On `sqlite-postgres`, `lite start` restores or fully rebuilds runtime metadata from authoritative recorded migration SQL, validates it against live structure, and fails with a reset hint on invalid history or drift. See [STATUS.md](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#row-level-security-rls). |
|
|
60
60
|
| CSV input/output (`csv()`) | ✅ | ✅ | - | - | Via `text/csv` Accept/Content-Type |
|
|
61
61
|
| Response utilities (`abortSignal`, `setHeader`, `throwOnError`, `maxAffected`) | ✅ | ✅ | - | - | |
|
|
62
62
|
| CORS / `OPTIONS` preflight | ✅ | ✅ | - | - | Server-wide on `/auth`, `/rest`, `/storage`; preflight answered before auth, origin `*`, exposes `Content-Range`. |
|
|
@@ -95,7 +95,7 @@ GoTrue-compatible endpoints at `/auth/v1/*`, backed by `app/src/auth/`. Email/pa
|
|
|
95
95
|
| `getUser` / `updateUser` (metadata, password, email change) | ✅ | - | - | Secure email change (`double_confirm_changes=true`) is ⚠️ partial: spec-compatible (confirms from the current mailbox before finalizing) but not GoTrue's full two-mailbox flow. See [LIMITATIONS.md](https://github.com/supabase-community/lite/blob/HEAD/LIMITATIONS.md#auth-shipped-with-caveats). |
|
|
96
96
|
| RLS auth context (`auth.uid()`, `auth.role()`, `auth.jwt()`) | ✅ | - | - | Shared with the Data API |
|
|
97
97
|
| API keys (`sb_publishable_*` → `anon`, `sb_secret_*` → `service_role`) | ✅ | - | - | Enforced on `/rest/v1` and `/auth/v1` when `auth.publishable_key`/`auth.secret_key` are configured; legacy JWT-as-apikey not supported. See [STATUS.md](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#api-keys). |
|
|
98
|
-
| Local admin mode (keyless local requests run as `service_role`) | ✅ | - | - | On by default for `lite dev`/`lite start`
|
|
98
|
+
| Local admin mode (keyless local requests run as `service_role`) | ✅ | - | - | On by default for loopback `lite dev`/`lite start` and Vite dev listeners. `--host [host]` or an exposed Vite host defaults it off; opt in with `--admin` / `supalite({ admin: true })`. Elevation requires keyless + same-origin + loopback socket + loopback hostname. See [STATUS.md](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#api-keys). |
|
|
99
99
|
| Email delivery (default templates + customization) | ✅ | - | - | Supabase-styled default HTML, `site_url`-based verify links, GET `/auth/v1/verify` redirect. Override subject + HTML per type via `auth.email.template.<type>.content_path` (GoTrue `{{ .ConfirmationURL }}` etc.). |
|
|
100
100
|
| Email driver (SMTP / provider) | ✅ | - | - | `SmtpEmailDriver` (via Nodemailer) auto-selects when `[auth.email.smtp] enabled = true` in `config.toml` (e.g. pointing at Mailpit or a real SMTP server); `Resend`/`SES`/`Sendmail` remain available via `options.drivers.email`. Default without config or explicit driver is `ConsoleEmailDriver`. `SmtpEmailDriver` requires Node or Bun; not supported on Cloudflare Workers or in the browser. |
|
|
101
101
|
| OAuth / social providers + PKCE (`signInWithOAuth`, `exchangeCodeForSession`) | ⚠️ | `S` per provider | `external-service` | `github` and `google` implemented: authorization-code (PKCE) and implicit flows, automatic account linking. Other configured providers (incl. `apple`) return "not yet implemented"; each is roughly `S` effort, gated on registering a provider app. |
|
|
@@ -115,7 +115,7 @@ GoTrue-compatible endpoints at `/auth/v1/*`, backed by `app/src/auth/`. Email/pa
|
|
|
115
115
|
|
|
116
116
|
## Storage
|
|
117
117
|
|
|
118
|
-
storage-api-compatible endpoints at `/storage/v1/*` (`app/src/storage/`), with pluggable filesystem and S3 backends
|
|
118
|
+
storage-api-compatible endpoints at `/storage/v1/*` (`app/src/storage/`), with pluggable filesystem and S3 backends, Sharp/Cloudflare image transforms, and Storage-table RLS across every database backend. Currently gated behind `EXPERIMENTAL_STORAGE`. Detail in [STATUS.md → Storage API](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#storage-api).
|
|
119
119
|
|
|
120
120
|
| Capability | Status | Effort | Blocker | Notes |
|
|
121
121
|
|------------|:------:|:------:|:-------:|-------|
|
|
@@ -125,9 +125,9 @@ storage-api-compatible endpoints at `/storage/v1/*` (`app/src/storage/`), with p
|
|
|
125
125
|
| Signed URLs (download, batch, upload) | ✅ | - | - | JWT-signed, configurable TTL |
|
|
126
126
|
| Image transformations (resize, format, quality) | ✅ | - | - | Sharp (buffer) and Cloudflare (URL) adapters |
|
|
127
127
|
| Storage backends | ✅ | - | - | Filesystem + S3-compatible (AWS S3, MinIO, R2) |
|
|
128
|
-
| Role-based access (service_role / anon / authenticated gating) |
|
|
129
|
-
| RLS policies on storage tables |
|
|
130
|
-
| `/status` health endpoint |
|
|
128
|
+
| Role-based access (service_role / anon / authenticated gating) | ✅ | - | - | Verified JWT/API-key claims are shared with the Data API; invalid bearer JWTs return 401 on protected operations, retrieval routes still serve public objects, and `service_role` bypasses RLS. |
|
|
129
|
+
| RLS policies on storage tables | ✅ | - | - | Native on Postgres/PGlite and translated on SQLite, including custom JWT roles, ownership, full route-operation context and helpers, serving-only public bypass, signed exceptions, and canonical Storage path helpers. SQLite fails closed for system Storage tables omitted from runtime metadata; `storage` is not exposed through PostgREST by default. |
|
|
130
|
+
| `/status` health endpoint | ✅ | - | - | Returns 200 without auth. |
|
|
131
131
|
| Bucket-list query params (`search`/`limit`/`offset`) | 🔄 | `S` | `-` | |
|
|
132
132
|
| TUS resumable uploads | 🔄 | `L` | `-` | `POST/PATCH/HEAD /upload/resumable`; spec cases exist, endpoints don't. |
|
|
133
133
|
| S3-compatible protocol paths (`/s3/`) | 🔄 | `L` | `-` | |
|
package/LIMITATIONS.md
CHANGED
|
@@ -13,6 +13,7 @@ Anchors below point to the corresponding STATUS.md section. If a limitation here
|
|
|
13
13
|
- `nextval` / `currval`, `clock_timestamp`, `txid_current`, user-defined functions → not supported. See [Column Defaults](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#column-defaults).
|
|
14
14
|
- `FORCE ROW LEVEL SECURITY` / `NO FORCE` → accepted and ignored (no table-owner exemption to toggle). See [RLS known limitations](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#row-level-security-rls).
|
|
15
15
|
- PL/pgSQL `DECLARE`, `IF`, `LOOP`, `RAISE`, variables → not supported in trigger bodies. See [PL/pgSQL Trigger Functions](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#plpgsql-trigger-functions).
|
|
16
|
+
- `ALTER TYPE ... ADD VALUE` / `RENAME VALUE` (enum value changes) → not supported; the error names the type and operation. Recreate the type with all values, or use a manual migration. See [Translated Field Types](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#translated-field-types).
|
|
16
17
|
|
|
17
18
|
## supabase-js (SQLite path)
|
|
18
19
|
|
|
@@ -40,12 +41,13 @@ Anchors below point to the corresponding STATUS.md section. If a limitation here
|
|
|
40
41
|
## Runtime / dev
|
|
41
42
|
|
|
42
43
|
- `vite preview` mounts the API and runs boot migrations, but does **not** watch schemas and never enables admin mode (it simulates production). `vite build` and standalone production servers do not mount the API at all. See [Vite plugin scope](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#vite-plugin-scope).
|
|
43
|
-
-
|
|
44
|
-
- `lite start`
|
|
45
|
-
- `supabase/.temp/.
|
|
46
|
-
- **Admin mode is on by default
|
|
47
|
-
- Admin mode never elevates `/auth/v1`, cross-origin requests, requests from a non-loopback socket, or requests for a non-loopback hostname
|
|
44
|
+
- Run only one backend per project: never combine `lite dev`, `lite start`, or the Vite plugin against the same SQLite file. See [When to use what](https://github.com/supabase-community/lite/blob/HEAD/README.md#when-to-use-what).
|
|
45
|
+
- `lite start` is migration-only: it ignores migration files and `schemas/*.sql`, rebuilding metadata from recorded applied SQL. Invalid history or live structural drift requires `lite db reset`; declarative-only live changes therefore cannot be recovered by `start`. See [RLS](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#row-level-security-rls).
|
|
46
|
+
- `supabase/.temp/.runtime-metadata-cache.json` is disposable: missing, corrupt, stale, or tampered caches rebuild automatically when applied history matches the live structure. Only `sqlite-postgres` uses it. See [RLS](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#row-level-security-rls).
|
|
47
|
+
- **Admin mode is on by default only on loopback listeners.** `lite dev`/`lite start` bind `127.0.0.1`; `--host [host]` exposes/selects an address and defaults admin off unless `--admin` is explicit. Vite does the same for non-loopback hosts. Credentialed requests are unaffected. See [API Keys](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#api-keys).
|
|
48
|
+
- Admin mode never elevates `/auth/v1`, cross-origin requests, requests from a non-loopback socket, or requests for a non-loopback hostname. Public tunnels can make remote traffic appear loopback, so always use `--no-admin` when forwarding the port. Embedders get the hostname check unless their adapter supplies `AppRequestContext.peerAddress`.
|
|
48
49
|
- The Vite plugin mounts `/rest/v1` but not `/storage/v1`, so admin mode covers storage on the CLI only unless you add the prefix. See [Vite plugin scope](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#vite-plugin-scope).
|
|
50
|
+
- The protected `storage` schema is not exposed through `/rest/v1` by default. Use `supabase.storage`; adding `storage` to `api.schemas` intentionally enables direct metadata endpoints. See [Storage API](https://github.com/supabase-community/lite/blob/HEAD/STATUS.md#storage-api).
|
|
49
51
|
|
|
50
52
|
## Postgres backends (pglite, postgres)
|
|
51
53
|
|
|
@@ -62,7 +64,7 @@ Common ways code goes wrong against supalite. The fix for each is the correspond
|
|
|
62
64
|
- Don't put `DEFAULT auth.uid()` on a column. Drop the default; pass `user_id` from the client; let RLS `WITH CHECK` enforce ownership.
|
|
63
65
|
- Don't call `rpc()` on the SQLite path. Run a regular HTTP endpoint, or switch the driver to `pglite` / `postgres` in `config.toml`.
|
|
64
66
|
- Don't use embedded dotted-path filters (`.eq('rel.col', v)`) on SQLite. Filter the FK column on the parent, or fetch matching ids first.
|
|
65
|
-
- Don't run `lite dev
|
|
67
|
+
- Don't run more than one of `lite dev`, `lite start`, or the Vite plugin for a project — they race one SQLite database even when ports differ.
|
|
66
68
|
- Don't `lite db reset` then `lite start` on a declarative project and expect your schema to be there. Reset is destructive and replays migrations only, adopting that state (RLS included) as the authoritative one — run `lite db diff -f <name>` first so the declarative schema exists as a migration.
|
|
67
69
|
- Don't test RLS with a keyless request while admin mode is on — it runs as `service_role` and sees everything. Send `apikey: $PUBLISHABLE_KEY` (for `anon`), plus `Authorization: Bearer $USER_JWT` for `authenticated`, or start with `--no-admin`.
|
|
68
70
|
- Don't send only `Authorization: Bearer $USER_JWT` and expect `authenticated` RLS. With keys configured that's a 401 — the `apikey` is required as well.
|
package/PATTERNS.md
CHANGED
|
@@ -36,26 +36,86 @@ await supabase.from("<thing>").insert({
|
|
|
36
36
|
});
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
## Per-user Storage ownership and folders
|
|
40
|
+
|
|
41
|
+
Uploads made with a verified JWT carrying a `sub` claim set both `storage.objects.owner_id` and the legacy `owner` field from that claim; `service_role` uploads remain ownerless. Custom string roles are preserved, so policies such as `TO manager` work when the database role and grants are configured. Use `owner_id` for per-user policies:
|
|
42
|
+
|
|
43
|
+
```sql
|
|
44
|
+
create policy "read own avatars"
|
|
45
|
+
on storage.objects for select to authenticated
|
|
46
|
+
using (bucket_id = 'avatars' and owner_id = auth.uid()::text);
|
|
47
|
+
|
|
48
|
+
create policy "upload own avatars"
|
|
49
|
+
on storage.objects for insert to authenticated
|
|
50
|
+
with check (bucket_id = 'avatars' and owner_id = auth.uid()::text);
|
|
51
|
+
|
|
52
|
+
create policy "update own avatars"
|
|
53
|
+
on storage.objects for update to authenticated
|
|
54
|
+
using (bucket_id = 'avatars' and owner_id = auth.uid()::text)
|
|
55
|
+
with check (bucket_id = 'avatars' and owner_id = auth.uid()::text);
|
|
56
|
+
|
|
57
|
+
create policy "delete own avatars"
|
|
58
|
+
on storage.objects for delete to authenticated
|
|
59
|
+
using (bucket_id = 'avatars' and owner_id = auth.uid()::text);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
For a bucket laid out as `<user-id>/<filename>`, scope uploads to the caller's first folder:
|
|
63
|
+
|
|
64
|
+
```sql
|
|
65
|
+
create policy "upload to own avatar folder"
|
|
66
|
+
on storage.objects for insert to authenticated
|
|
67
|
+
with check (
|
|
68
|
+
bucket_id = 'avatars'
|
|
69
|
+
and (storage.foldername(name))[1] = auth.uid()::text
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The indexed `storage.foldername()` form uses PostgreSQL's one-based indexing and works on SQLite, PGlite, and PostgreSQL. The upstream `storage.filename()` and `storage.extension()` helpers work across the same backends.
|
|
74
|
+
|
|
75
|
+
Use the operation helpers when one SQL command backs multiple Storage actions. This policy permits downloads without exposing the same objects through list:
|
|
76
|
+
|
|
77
|
+
```sql
|
|
78
|
+
create policy "download avatars without listing"
|
|
79
|
+
on storage.objects for select to authenticated
|
|
80
|
+
using (
|
|
81
|
+
bucket_id = 'avatars'
|
|
82
|
+
and storage.allow_any_operation(array[
|
|
83
|
+
'object.get_authenticated',
|
|
84
|
+
'object.get_authenticated_info'
|
|
85
|
+
])
|
|
86
|
+
);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`storage.operation()` returns the complete route identifier, such as `storage.object.upload`. `storage.allow_only_operation()` and `storage.allow_any_operation()` accept operation names with or without the `storage.` prefix. Public buckets bypass RLS only when serving objects through `GET`, `HEAD`, and info. Keep `SELECT` policies for listing, signing, copy sources, and move sources, plus mutation policies for uploads, deletes, moves, and copies.
|
|
90
|
+
|
|
39
91
|
## Verifying RLS policies locally
|
|
40
92
|
|
|
41
|
-
Local admin mode is on by default
|
|
93
|
+
Local admin mode is on by default for loopback `lite dev`, `lite start`, and Vite dev listeners. A request with **no** credential then runs as `service_role`, so a bare `curl` sees every row and proves nothing about your policies. Always test with a credential; those requests are never elevated and behave exactly as they will in production.
|
|
42
94
|
|
|
43
95
|
```bash
|
|
44
96
|
# anon: what a logged-out visitor sees
|
|
45
97
|
curl -H "apikey: $SUPABASE_PUBLISHABLE_KEY" \
|
|
46
|
-
"http://
|
|
98
|
+
"http://127.0.0.1:54321/rest/v1/<thing>?select=*"
|
|
47
99
|
|
|
48
100
|
# authenticated: the apikey is required IN ADDITION to the user JWT
|
|
49
101
|
JWT=$(curl -s -H "apikey: $SUPABASE_PUBLISHABLE_KEY" \
|
|
50
102
|
-H 'Content-Type: application/json' \
|
|
51
103
|
-d '{"email":"a@b.co","password":"secret123"}' \
|
|
52
|
-
"http://
|
|
104
|
+
"http://127.0.0.1:54321/auth/v1/token?grant_type=password" | jq -r .access_token)
|
|
53
105
|
|
|
54
106
|
curl -H "apikey: $SUPABASE_PUBLISHABLE_KEY" -H "Authorization: Bearer $JWT" \
|
|
55
|
-
"http://
|
|
107
|
+
"http://127.0.0.1:54321/rest/v1/<thing>?select=*"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`Authorization` alone is a 401 — opaque keys are only read from `apikey`, matching upstream. supabase-js sends both automatically, so app code needs no special handling. To take admin mode out of the picture entirely, start with `--no-admin` (or `supalite({ admin: false })`); keyless requests are not elevated and normal auth rules apply.
|
|
111
|
+
|
|
112
|
+
For a container, mobile device, or LAN client, expose the listener without exposing admin mode:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
lite dev --host --no-admin
|
|
56
116
|
```
|
|
57
117
|
|
|
58
|
-
`
|
|
118
|
+
Bare `--host` has the same auth behavior but warns so the implicit admin shutdown is visible. `--host --admin` is only for direct trusted-network access: remote peers still require credentials, and a public tunnel can erase the peer boundary.
|
|
59
119
|
|
|
60
120
|
## Filtering an embedded resource (SQLite path)
|
|
61
121
|
|
|
@@ -103,7 +163,7 @@ The canonical Vite recipe:
|
|
|
103
163
|
```
|
|
104
164
|
6. `bun run dev`.
|
|
105
165
|
|
|
106
|
-
Same-process, same origin, hot-reload on schema changes.
|
|
166
|
+
Same-process, same origin, hot-reload on schema changes. This plugin is the project's only backend process: do **not** run `lite dev` or `lite start` alongside it.
|
|
107
167
|
|
|
108
168
|
## `updated_at` timestamps via trigger
|
|
109
169
|
|
package/README.md
CHANGED
|
@@ -74,14 +74,14 @@ lite init # scaffold supabase/ directory
|
|
|
74
74
|
lite dev # start server with schema hot-reload
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
The API is now running at `http://
|
|
77
|
+
The API is now running at `http://127.0.0.1:54321`. Point `@supabase/supabase-js` at it:
|
|
78
78
|
|
|
79
79
|
`lite init` also generates any missing publishable/secret API key(s) into root `.env` (per-variable, never overwrites an existing one) and prints them:
|
|
80
80
|
|
|
81
81
|
```typescript
|
|
82
82
|
import { createClient } from "@supabase/supabase-js";
|
|
83
83
|
|
|
84
|
-
const supabase = createClient("http://
|
|
84
|
+
const supabase = createClient("http://127.0.0.1:54321", "<sb_publishable_...>");
|
|
85
85
|
const { data } = await supabase.from("todos").select("*");
|
|
86
86
|
```
|
|
87
87
|
|
|
@@ -99,7 +99,7 @@ Edit `supabase/schemas/schema.sql` and the dev server re-applies the schema auto
|
|
|
99
99
|
| Non-Vite app, want auto schema-reload | `lite dev` | Separate process. Watches `schemas/*.sql`, re-applies on change. |
|
|
100
100
|
| Non-Vite app, manual control / CI / prod-like | `lite start` | Separate process. No watch, no auto-migrate. |
|
|
101
101
|
|
|
102
|
-
>
|
|
102
|
+
> Run only one backend per project. Never run `lite dev` and `lite start` together, or either command alongside the Vite plugin: they would race migrations and schema reconciliation against the same SQLite file.
|
|
103
103
|
|
|
104
104
|
Known limitations across all paths: see [LIMITATIONS.md](https://github.com/supabase-community/lite/blob/HEAD/LIMITATIONS.md). Canonical recipes: see [PATTERNS.md](https://github.com/supabase-community/lite/blob/HEAD/PATTERNS.md).
|
|
105
105
|
|
|
@@ -123,6 +123,8 @@ to show details like the config file and database location on stderr.
|
|
|
123
123
|
| `generate-keys` | (Re)generate the publishable/secret API key pair, upsert `.env` |
|
|
124
124
|
| `dev` | Start server + watch `schemas/*.sql`, auto-apply on change |
|
|
125
125
|
| `start` | Start server (no watch, no auto-migrate) |
|
|
126
|
+
|
|
127
|
+
`lite dev` and `lite start` bind `127.0.0.1` by default. Pass `--host` to listen on all interfaces, matching Vite's flag, or `--host <address>` to choose one explicitly. An exposed listener defaults admin mode off; add `--admin` only when peer-scoped local Studio access is intentional.
|
|
126
128
|
| `db schema` | Print current DB schema; `--diff` compares vs `schemas/*.sql` |
|
|
127
129
|
| `db diff` | Emit a new pg-DDL migration from the declarative schema diff |
|
|
128
130
|
| `db translate` | Translate Postgres SQL to this project's backend dialect (arg or stdin) |
|
|
@@ -275,18 +277,23 @@ Lost or rotating keys: `lite generate-keys` mints a fresh pair and upserts `.env
|
|
|
275
277
|
|
|
276
278
|
### Admin mode (local only)
|
|
277
279
|
|
|
278
|
-
`lite dev`, `lite start`, and
|
|
280
|
+
`lite dev`, `lite start`, and a loopback-bound Vite dev server run with admin mode **on**. A request carrying no credential at all — no `apikey`, no `Authorization` — on `/rest/v1` (and `/storage/v1` on the CLI) is served as `service_role`. That's what lets the built-in studio read and edit any table without a secret key shipping to the browser, mirroring self-hosted Supabase Studio where the server holds the key.
|
|
279
281
|
|
|
280
282
|
Elevation additionally requires the request to be same-origin (or carry no `Origin`), to arrive on a loopback socket, and to name a loopback host. Both locality checks are needed: the socket peer stops a machine on your network from spoofing `Host: localhost`, and the hostname stops DNS rebinding, where a hostile page re-resolves its own domain to `127.0.0.1` so the socket is genuinely loopback. `/auth/v1` is never elevated, and the Vite plugin only mounts `/rest/v1`.
|
|
281
283
|
|
|
282
284
|
```bash
|
|
283
|
-
lite start --no-admin #
|
|
285
|
+
lite start --no-admin # loopback server, admin explicitly off
|
|
286
|
+
lite start --host # all interfaces, admin defaults off and warns
|
|
287
|
+
lite start --host --no-admin # all interfaces, explicit/silent admin opt-out
|
|
288
|
+
lite start --host --admin # all interfaces, local peers may use admin
|
|
284
289
|
```
|
|
285
290
|
```ts
|
|
286
291
|
supalite({ admin: false }) # off for the Vite dev server
|
|
287
292
|
```
|
|
288
293
|
|
|
289
|
-
|
|
294
|
+
On a loopback CLI listener, precedence is explicit flag > `options.server.admin` in `config.toml` > the on-by-default launcher value. A non-loopback `--host` forces admin off unless `--admin` is present, so config cannot silently re-enable it. Vite follows the same rule: an exposed Vite host requires `supalite({ admin: true })`; preview and embedded `App` instances remain off by default.
|
|
295
|
+
|
|
296
|
+
A sandbox or tunnel may publish even a loopback listener and make remote traffic appear local. Use `--no-admin` whenever another system forwards the port publicly; locality is not an authentication mechanism across a proxy.
|
|
290
297
|
|
|
291
298
|
Because keyless requests skip RLS, test policies with a credential: `apikey: $PUBLISHABLE_KEY` for `anon`, and that **plus** `Authorization: Bearer $USER_JWT` for `authenticated`. A bearer token alone is a 401.
|
|
292
299
|
|
|
@@ -328,7 +335,7 @@ lite db diff -f tweak # diff schemas/ against applied migrations, emit
|
|
|
328
335
|
lite db reset # drop everything, replay migrations, run seed
|
|
329
336
|
```
|
|
330
337
|
|
|
331
|
-
Migrations and declarative schemas coexist: `lite dev` and the Vite plugin apply pending migrations on boot, then run the declarative diff.
|
|
338
|
+
Migrations and declarative schemas coexist: `lite dev` and the Vite plugin apply pending migrations on boot, then run the declarative diff. `lite start` is migration-only: the ordered SQL recorded in `supabase_migrations.schema_migrations` is authoritative, so pending, edited, deleted, or declarative files do not change runtime metadata until their SQL is applied and recorded. On `sqlite-postgres`, deleting `supabase/.temp/.runtime-metadata-cache.json` is safe; startup rebuilds it from applied history and asks for `lite db reset` only when that history is invalid or does not match the live structure.
|
|
332
339
|
|
|
333
340
|
---
|
|
334
341
|
|
|
@@ -341,7 +348,7 @@ Two ways to get a client:
|
|
|
341
348
|
```typescript
|
|
342
349
|
import { createClient } from "@supabase/supabase-js";
|
|
343
350
|
|
|
344
|
-
const client = createClient("http://
|
|
351
|
+
const client = createClient("http://127.0.0.1:54321", "<anon-key>");
|
|
345
352
|
|
|
346
353
|
// database
|
|
347
354
|
const { data } = await client.from("todos").select("*");
|
package/STATUS.md
CHANGED
|
@@ -160,6 +160,8 @@ To keep declarative `db diff` state convergent, `ALTER EXTENSION <accepted-name>
|
|
|
160
160
|
| `CREATE TYPE ... AS ENUM` | `TEXT` | `EnumField` | Emits allowed-value `CHECK (... IN (...))`. |
|
|
161
161
|
| `<type>[]`, `_type` arrays | `TEXT` | `ArrayField` | Stores JSON arrays and delegates element serialization where possible. |
|
|
162
162
|
|
|
163
|
+
Mutating an existing enum on the SQLite path (`ALTER TYPE ... ADD VALUE` / `RENAME VALUE`) is not supported; the translator fails with a clear error that names the type and operation. Recreate the type with the full value set, or track the change in a manual migration.
|
|
164
|
+
|
|
163
165
|
Unsupported PostgreSQL data types currently include `oid`, `xid`, `xid8`, `cid`, `money`, `citext`, `cidr`, `macaddr`, `macaddr8`, `bit`, `bit varying`, `varbit`, geometric types (`point`, `line`, `lseg`, `box`, `path`, `polygon`, `circle`), `xml`, text-search types (`tsvector`, `tsquery`), range and multirange types, `reg*` catalog reference types, internal types (`tid`, `pg_lsn`, `internal`), pseudo-types, and handler types.
|
|
164
166
|
|
|
165
167
|
**Custom domains & data representations.** On the Postgres path (PGlite/PostgreSQL), a column typed as a domain that defines `CAST(<domain> AS json)` (the PostgREST "data representations" feature) renders through that cast on reads and `RETURNING` — e.g. a `unixtz` domain over `timestamptz` returns epoch seconds, a `monetary` domain over `numeric` returns a fixed-precision string. On the SQLite path the known representation types (`color`, `unixtz`, `isodate`, `monetary`, `bytea_b64`) are handled by built-in field shims. Mutating JSON values **into** a domain column (epoch→`timestamptz`, base64→`bytea`, decimal-string→`numeric`) is converted on the Postgres path via `buildDomainInputValue`. Not yet handled: domain formatting through cross-relation embeds. Postgres connections run with `TimeZone=UTC` by default so `timestamptz` rendering is deterministic regardless of the server's host timezone; override via the `postgresOptions.connection.TimeZone` connection option.
|
|
@@ -228,6 +230,7 @@ RLS is supported on all database backends. The enforcement strategy differs by d
|
|
|
228
230
|
| Feature | SQLite | PGlite/Postgres | Notes |
|
|
229
231
|
|------------------------------------------------|--------|-----------------|-------------------------------------------------------------|
|
|
230
232
|
| `ENABLE ROW LEVEL SECURITY` | ✅ | ✅ | Default-deny when no policies match |
|
|
233
|
+
| `DISABLE ROW LEVEL SECURITY` | ✅ | ✅ | Policies remain stored but inert until RLS is enabled again |
|
|
231
234
|
| `CREATE POLICY ... USING (expr)` | ✅ | ✅ | SQLite: merged into `WHERE`; Postgres: native |
|
|
232
235
|
| `CREATE POLICY ... WITH CHECK (expr)` | ✅ | ✅ | SQLite: validated in-memory; Postgres: native |
|
|
233
236
|
| `AS PERMISSIVE` (default) | ✅ | ✅ | Multiple permissive policies `OR`'d |
|
|
@@ -250,7 +253,7 @@ Each supported behavior is regression-covered against both backends in [`app/tes
|
|
|
250
253
|
|
|
251
254
|
📖 See [`internal/docs/postgres/rls.md`](https://github.com/supabase-community/lite/blob/HEAD/internal/docs/postgres/rls.md) for the full RLS reference and behavior matrix.
|
|
252
255
|
|
|
253
|
-
**SQLite metadata
|
|
256
|
+
**SQLite runtime metadata (`sqlite-postgres`):** Policies, Postgres field types, enums, constraints, comments, variables, and relationship metadata are collected during translation and stored in the disposable runtime metadata cache at `supabase/.temp/.runtime-metadata-cache.json`. For `lite start`, the only authority is the ordered `{version, statements}` history in `supabase_migrations.schema_migrations`: applied files may be edited or deleted, pending files and `schemas/*.sql` are ignored, and a missing, corrupt, old, stale, or tampered cache is rebuilt automatically from the recorded SQL. Startup also replays the same history into an in-memory SQLite database and compares its raw structure with the live database; introspection is used only for equality checking, never to invent metadata. Invalid history or out-of-band structural DDL exits with a `lite db reset` hint. `lite migration up` and `lite db reset` refresh migration-derived metadata even when no new migration was applied. `lite dev` and the Vite plugin remain declarative: after applying migrations they replace the complete metadata payload from the applied declarative schema, including after watched migrations. Cache writes use a sibling temporary file plus atomic rename and are best-effort; a write failure leaves the previous file intact while the rebuilt in-memory payload remains usable. Embedded/programmatic use retains the history-based deny backstop as a last resort. `pglite` / `postgres` (native RLS) and bare `sqlite` are unaffected.
|
|
254
257
|
|
|
255
258
|
**PGlite / PostgreSQL auto-setup:** When any table has `ENABLE ROW LEVEL SECURITY`, supalite creates `anon`, `authenticated`, and `service_role` roles (if missing; `service_role` uses `BYPASSRLS`) and grants default privileges on all tables and sequences in the relevant schemas. No manual `CREATE ROLE` or `GRANT` statements needed for these built-in roles.
|
|
256
259
|
|
|
@@ -540,7 +543,7 @@ Opaque `sb_publishable_*` / `sb_secret_*` keys, matching Supabase's current key
|
|
|
540
543
|
| `/storage/v1` | ⚠️ | Transform-only, like upstream self-hosted Kong: keys map to roles when present, but a missing/invalid key never 401s at the gateway (public objects, signed URLs, S3 presigned flows stay keyless). Storage's own route auth still applies; a secret key satisfies storage's authed routes as `service_role` (including bypassing RLS-equivalent checks on SQLite) |
|
|
541
544
|
| Secret key + browser `User-Agent` (`Mozilla/5.0`) | ✅ | Rejected (401), mirrors the hosted gateway's browser guard |
|
|
542
545
|
| OpenAPI root (`GET /rest/v1/`) | ✅ | Requires the secret key: publishable → 403, secret → 200, mirroring upstream's admin-only ACL on that route (LITE-35) |
|
|
543
|
-
| Local admin mode (`options.server.admin`) | ✅ | Local-dev only. A request with **no** credential (no `apikey` header/query, no `Authorization`) on `/rest/v1` or `/storage/v1` is served as `service_role`, so
|
|
546
|
+
| Local admin mode (`options.server.admin`) | ✅ | Local-dev only. A request with **no** credential (no `apikey` header/query, no `Authorization`) on `/rest/v1` or `/storage/v1` is served as `service_role`, so browser Studio can do admin work without receiving a secret key. Elevation requires same-origin (or no `Origin`), a loopback **socket peer**, and a loopback **hostname**; transport adapters pass the peer through `App.fetch(request, { peerAddress })`, which fails closed when unavailable. `/auth/v1` is never elevated. `lite dev`/`lite start` bind `127.0.0.1` and default admin on; `--host [host]` exposes/selects an address and defaults it off unless `--admin` is explicit. Exposed Vite hosts likewise require `supalite({ admin: true })`; preview and embedders default off. Credentialed requests are never elevated (LITE-309, LITE-332) |
|
|
544
547
|
| Secrets redacted from `/_system/config` / `/_system/info` | ✅ | `auth.secret_key` and `auth.jwt_secret` are masked in both responses |
|
|
545
548
|
| Legacy JWT-as-apikey (`ANON_KEY`/`SERVICE_ROLE_KEY` HS256) | ❌ | Not supported |
|
|
546
549
|
| `options.server.apiKeys: false` | ✅ | Disables enforcement entirely (embedders) |
|
|
@@ -665,6 +668,11 @@ Backend implementation in `app/src/storage/`. HTTP endpoints at `/storage/v1/*`.
|
|
|
665
668
|
| `POST /object/upload/sign/:bucketId/*` | Sign | Create signed upload URL |
|
|
666
669
|
| `GET /object/sign/:bucketId/*` | Download | Via signed URL token |
|
|
667
670
|
| `PUT /object/upload/sign/:bucketId/*` | Upload | Via signed upload URL |
|
|
671
|
+
| `GET /status` | Health | No authentication required |
|
|
672
|
+
|
|
673
|
+
Storage metadata operations use the same verified JWT claims and RLS execution path as the Data API on SQLite, PGlite, and PostgreSQL. The `storage` schema is protected and omitted from the default PostgREST `api.schemas` list; `/storage/v1` remains the supported client surface, while explicitly adding `storage` enables direct metadata endpoints. On SQLite, the system schema declaration keeps `storage.buckets` and `storage.objects` RLS-enforced even when supplied runtime metadata omits them: no policies deny access and `service_role` still bypasses. Missing credentials run as `anon`; protected operations return a Storage-shaped 401 for invalid or expired bearer JWTs, while object `GET`, `HEAD`, and info tolerate invalid JWTs so public objects remain retrievable. Unauthenticated private retrieval returns `NoSuchBucket`, matching upstream; a verified `anon` JWT can still reach an `anon` `SELECT` policy. `service_role` bypasses RLS, and custom string roles are preserved for `TO role` policies. Uploads made with a verified JWT carrying a `sub` claim set both `owner_id` and the legacy `owner` field from that claim; `service_role` uploads remain ownerless. Public object retrieval through `GET`, `HEAD`, and info bypasses object `SELECT`; list, signing, copy, and move remain caller-scoped.
|
|
674
|
+
|
|
675
|
+
Bucket CRUD maps to matching policies on `storage.buckets`; PostgreSQL/PGlite bucket deletion runs trusted, row-locking existence and emptiness preflights plus the caller-scoped `DELETE` in one transaction. SQLite/D1 uses trusted preflights followed by one caller-scoped `DELETE`, with the bucket-object foreign key keeping that mutation race-safe. Object upload maps to `INSERT`; private download and info, list, and signing map to `SELECT`; remove maps to `DELETE`; move maps to source `SELECT` plus `UPDATE`; copy maps to source `SELECT` plus destination `INSERT`. Upsert additionally requires `SELECT` and `UPDATE`. Permission probes roll back before adapter writes, so denied mutations cannot change filesystem or S3 data. Public `GET`, `HEAD`, and info bypass `SELECT`, while signed URL redemption uses the authorization decision captured when the URL was created. The canonical `storage.foldername()`, `storage.filename()`, `storage.extension()`, `storage.operation()`, `storage.allow_only_operation()`, and `storage.allow_any_operation()` policy helpers work on every backend; `storage.operation()` preserves the complete upstream route identifier and supports comparison, pattern, membership, and null predicates with SQL null semantics.
|
|
668
676
|
|
|
669
677
|
### Storage Adapters
|
|
670
678
|
|
|
@@ -686,9 +694,6 @@ Backend implementation in `app/src/storage/`. HTTP endpoints at `/storage/v1/*`.
|
|
|
686
694
|
|
|
687
695
|
| Feature | Notes |
|
|
688
696
|
|--------------------------------|------------------------------------------------------------|
|
|
689
|
-
| `/status` health endpoint | Oracle returns 200 with no auth |
|
|
690
|
-
| Role-based access control | API keys now resolve `service_role`/`anon`/`authenticated` for storage's route-level auth (see [API Keys](#api-keys)); no per-object RLS policies yet |
|
|
691
|
-
| RLS policies on storage tables | Per-user object access via row-level security |
|
|
692
697
|
| Bucket list query params | `?search=`, `?limit=`, `?offset=` on `GET /bucket` |
|
|
693
698
|
| S3-compatible protocol | `PUT/GET/DELETE` via S3 API paths (`/s3/`) |
|
|
694
699
|
| TUS resumable uploads | `POST/PATCH/HEAD` on `/upload/resumable` |
|
|
@@ -698,9 +703,9 @@ Backend implementation in `app/src/storage/`. HTTP endpoints at `/storage/v1/*`.
|
|
|
698
703
|
|
|
699
704
|
| Status | Count |
|
|
700
705
|
|---------------------|------------------------------|
|
|
701
|
-
| ✅ Endpoints | 20
|
|
706
|
+
| ✅ Endpoints | 20 supabase-js + health |
|
|
702
707
|
| ✅ Adapters | 3 storage + 3 transformation |
|
|
703
|
-
| 🔄 Missing features |
|
|
708
|
+
| 🔄 Missing features | 4 |
|
|
704
709
|
|
|
705
710
|
### Spec Test Results
|
|
706
711
|
|
|
@@ -708,21 +713,23 @@ Tests run via supabase-spec JSON test cases against Postgres (pgserve). Run: `cd
|
|
|
708
713
|
|
|
709
714
|
| Category | Pass | Fail | Notes |
|
|
710
715
|
|------------------|------|------|---------------------------------------------|
|
|
711
|
-
| bucket_crud |
|
|
712
|
-
| object_upload |
|
|
713
|
-
| access_control |
|
|
716
|
+
| bucket_crud | 38 | 0 | Full current category |
|
|
717
|
+
| object_upload | 20 | 2 | Residual size-limit fixture and auth-envelope shape |
|
|
718
|
+
| access_control | 70 | 7 | Core authorization passes; residual fixture body bytes and a legacy null-owner assertion |
|
|
714
719
|
| object_read | -- | 28 | Cascade from setup/access issues |
|
|
715
720
|
| object_list | -- | 26 | Cascade from setup/access issues |
|
|
716
721
|
| signed_urls | -- | 24 | Cascade from setup/access issues |
|
|
717
|
-
| errors |
|
|
722
|
+
| errors | 44 | 10 | Includes unrelated TUS, signed-URL shape, validation, and one legacy missing-auth validation shape; 4 skipped TUS steps |
|
|
718
723
|
| object_move_copy | -- | 21 | Cascade from setup/access issues |
|
|
719
724
|
| object_naming | -- | 15 | Cascade from setup/access issues |
|
|
720
725
|
| user_metadata | -- | 10 | Cascade from setup/access issues |
|
|
721
726
|
| file_types | -- | 8 | Cascade from setup/access issues |
|
|
722
|
-
| health |
|
|
727
|
+
| health | 6 | 0 | Full current category |
|
|
723
728
|
| object_delete | -- | 3 | Cascade from setup/access issues |
|
|
724
729
|
|
|
725
|
-
>
|
|
730
|
+
> Counts reflect the current vendored phenotype files, whose `access_control` category contains 77 setup/action assertions rather than the older 48-case snapshot. Remaining failures are tracked by their actual response-shape, fixture, or unrelated feature root cause; `storage_auth_policy` is no longer a skip category.
|
|
731
|
+
>
|
|
732
|
+
> `bun run test:spec:storage` completes with zero failures on PostgreSQL, PGlite, SQLite, and SQLite-Postgres. Its default report lists seven vendored expectation conflicts separately: five fixture-body byte mismatches, one legacy missing-auth validation shape, and one legacy null-owner assertion. `SKIP=0` retains the raw phenotype counts above.
|
|
726
733
|
|
|
727
734
|
---
|
|
728
735
|
|
|
@@ -767,7 +774,7 @@ Default command output is pipe-friendly: no global banner, and config/database-l
|
|
|
767
774
|
| `db query` | ✅ | Renamed from top-level `exec`; supports `--remote`, `--config`, and stdin |
|
|
768
775
|
| `db schema` | ✅ | `[lite]`: moved from top-level; `--diff` and `--sql` modes |
|
|
769
776
|
| `db push` | 🔄 | Not registered; use `lite cloud deploy` |
|
|
770
|
-
| `db reset` | ✅ | Replays migrations + seed; does not apply declarative schema_paths; clears `supabase/.temp` caches and always rewrites the
|
|
777
|
+
| `db reset` | ✅ | Replays migrations + seed; does not apply declarative schema_paths; clears `supabase/.temp` caches and always rewrites the runtime metadata cache from the replayed migrations — the reset is destructive, so migration state (RLS included) becomes the authoritative state, and declarative schemas are only in the database if you generated a migration from them first (`lite db diff -f <name>`) |
|
|
771
778
|
| `db pull`, `db dump`, `db lint`, `db advisors` | 🔄 | Not registered |
|
|
772
779
|
| `db start` | 🚫 | Not applicable; in-process, no separate DB start |
|
|
773
780
|
|
|
@@ -776,7 +783,7 @@ Default command output is pipe-friendly: no global banner, and config/database-l
|
|
|
776
783
|
| Command | Status | Notes |
|
|
777
784
|
|---------------------|--------|--------------------------------------------------------|
|
|
778
785
|
| `migration new` | ✅ | Create an empty migration file in `supabase/migrations/` |
|
|
779
|
-
| `migration up` | ✅ | Apply pending migrations; `--dry-run` lists without applying |
|
|
786
|
+
| `migration up` | ✅ | Apply pending migrations; `--dry-run` lists without applying. On `sqlite-postgres`, refreshes complete runtime metadata from recorded history even on a no-op run. |
|
|
780
787
|
| `migration list` | ✅ | Show applied vs pending migrations |
|
|
781
788
|
| `migration down`, `migration repair`, `migration squash`, `migration fetch` | 🔄 | Not registered |
|
|
782
789
|
|
|
@@ -848,8 +855,8 @@ Mirrors upstream behavior documented in [`internal/docs/cli/environment.md`](htt
|
|
|
848
855
|
### Vite plugin scope
|
|
849
856
|
|
|
850
857
|
- **Active during `vite` / `vite dev` and `vite preview`.** `vite dev` watches `schemas/*.sql` for hot-reload; `vite preview` mounts the API and runs boot migrations but does **not** watch schemas (it simulates production). `vite build` and any standalone production server do **not** mount the API — use a real backend (`lite start`, hosted Supabase, or equivalent) there.
|
|
851
|
-
- **Same-process by design.** The plugin mounts `/auth/v1`, `/rest/v1`, and `/_system` on the Vite dev server. `/storage/v1` is not mounted by default — add it to `prefixes` if you need it.
|
|
852
|
-
- **Admin mode on
|
|
858
|
+
- **Same-process by design.** The plugin mounts `/auth/v1`, `/rest/v1`, and `/_system` on the Vite dev server. `/storage/v1` is not mounted by default — add it to `prefixes` if you need it. Run only one backend per project: never combine the plugin with `lite dev` or `lite start`, and never run both CLI backends together.
|
|
859
|
+
- **Admin mode on for loopback dev, never in preview.** `vite`/`vite dev` default to `admin: true` only when Vite binds a loopback host. `vite --host` and other non-loopback hosts default it off and require `supalite({ admin: true })` to opt in; `configurePreviewServer` always forces it off. See [API Keys](#api-keys).
|
|
853
860
|
- **Env-var injection.** The plugin's `config()` hook injects `VITE_SUPABASE_URL` (the current origin) and a dev `VITE_SUPABASE_ANON_KEY`, so `createClient(import.meta.env.VITE_SUPABASE_URL, import.meta.env.VITE_SUPABASE_ANON_KEY)` works with no `.env`. A user-provided `.env` overrides either value.
|
|
854
861
|
|
|
855
862
|
---
|
|
@@ -872,9 +879,9 @@ See [UPGRADE.md](https://github.com/supabase-community/lite/blob/HEAD/UPGRADE.md
|
|
|
872
879
|
|
|
873
880
|
| Test Suite | Passing | Skipped | Failed | Assertions | Files |
|
|
874
881
|
|------------|-------------------|-------------|-----------------|-------------------|----------------|
|
|
875
|
-
| App | **
|
|
882
|
+
| App | **3,385 passing** | 486 skipped | 0 failed | 20,741 assertions | 228 test files |
|
|
876
883
|
| App (vitest: node + browser + D1 + DO + KV) | **65 passing** | 0 skipped | 0 failed | — | 5 test files |
|
|
877
|
-
| Repo | **
|
|
884
|
+
| Repo | **4,413 passing** | 540 skipped | 0 failed | 34,523 assertions | 233 test files |
|
|
878
885
|
|
|
879
886
|
Latest `cd app && bun test`, `cd app && bun run vitest`, and root `bun test --recursive` completed with zero failures.
|
|
880
887
|
|