{siteConfig.tagline}
-- Supabase is the open source Firebase alternative. -
-
- - Backed by Y Combinator -
-diff --git a/.github/workflows/avoid-typos.yml b/.github/workflows/avoid-typos.yml
index cd8d982f4aa..1cbe64238ac 100644
--- a/.github/workflows/avoid-typos.yml
+++ b/.github/workflows/avoid-typos.yml
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code.
- uses: actions/checkout@v1
+ uses: actions/checkout@v3
- name: misspell
uses: reviewdog/action-misspell@v1
with:
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
deleted file mode 100644
index 0c9a3c46ebd..00000000000
--- a/.github/workflows/integration-tests.yml
+++ /dev/null
@@ -1,92 +0,0 @@
-name: Tests
-
-# Controls when the workflow will run
-on:
- schedule:
- - cron: '0 4/6 * * *'
- workflow_dispatch:
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- autotests:
- name: Run tests and generate Allure Report
- strategy:
- matrix:
- node: ['14']
-
- runs-on: ubuntu-latest
- defaults:
- run:
- working-directory: ./tests
-
- steps:
- - uses: actions/checkout@v2
-
- - name: Set up JDK
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
-
- - name: Set up Node
- uses: actions/setup-node@v1
- with:
- node-version: ${{ matrix.node }}
-
- - name: Install dependencies
- run: npm ci
-
- - uses: supabase/setup-cli@v1
- - run: supabase start
-
- - name: Run Test
- run: npm run test:local
- env:
- SUPABASE_DB_PORT: 54322
- SUPABASE_DB_PASS: postgres
- SUPABASE_DB_HOST: localhost
- SUPABASE_GOTRUE: http://localhost:54321
- SUPABASE_URL: http://localhost:54321
- SUPABASE_KEY_ANON: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24ifQ.625_WdcF3KHqz5amU0x2X5WWHP-OEs_4qj0ssLNHzTs
- SUPABASE_KEY_ADMIN: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSJ9.vI9obAHOGyVVKa3pD--kJlyxp-Z2zV9UUMAhKpNLAcU
-
- - name: Stop infrastructure
- if: always()
- run: supabase stop
-
- - name: Get Allure history
- uses: actions/checkout@v2
- if: always()
- continue-on-error: true
- with:
- repository: supabase/test-reports
- ref: gh-pages
- path: gh-pages
-
- - name: Allure Report action
- uses: simple-elf/allure-report-action@master
- if: always()
- with:
- github_repo: test-reports
- allure_results: tests/allure-results
- allure_history: allure-history
- subfolder: supabase-integration
- keep_reports: 50
-
- - name: Deploy report to Github Pages
- if: always()
- uses: peaceiris/actions-gh-pages@v2
- env:
- EXTERNAL_REPOSITORY: supabase/test-reports
- ACTIONS_DEPLOY_KEY: ${{ secrets.DEPLOY_TO_TEST_REPORTS_KEY }}
- PUBLISH_BRANCH: gh-pages
- PUBLISH_DIR: allure-history
-
- - name: Post the link to the report
- if: always()
- uses: Sibz/github-status-action@v1
- with:
- authToken: ${{ secrets.GITHUB_TOKEN }}
- context: 'Test report'
- state: 'success'
- sha: ${{ github.event.pull_request.head.sha || github.sha }}
- target_url: https://supabase.github.io/test-reports/supabase-integration/${{ github.run_number }}
diff --git a/.github/workflows/og_images.yml b/.github/workflows/og_images.yml
new file mode 100644
index 00000000000..c3cc6568e73
--- /dev/null
+++ b/.github/workflows/og_images.yml
@@ -0,0 +1,28 @@
+name: Deploy OG Images
+
+on:
+ push:
+ branches:
+ - master
+ paths:
+ - 'supabase/functions/og-images/**'
+ workflow_dispatch:
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ env:
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
+ PROJECT_ID: ${{ secrets.PROJECT_ID }}
+
+ steps:
+ - name: Check out repo
+ uses: actions/checkout@v3
+
+ - name: Setup the Supabase CLI
+ uses: supabase/setup-cli@v1
+ with:
+ version: latest
+
+ - run: supabase functions deploy og-images --project-ref $PROJECT_ID --no-verify-jwt
diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml
index 43305fc1aed..aef4d8f166d 100644
--- a/.github/workflows/prettier.yml
+++ b/.github/workflows/prettier.yml
@@ -10,15 +10,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
- uses: actions/checkout@v2
- # disable this check while we migrate to monorepo
+ uses: actions/checkout@v3
- name: Run prettier
- uses: EPMatt/reviewdog-action-prettier@v1
- with:
- github_token: ${{ secrets.github_token }}
- reporter: github-pr-review
- level: warning
- command: npx prettier -c 'apps/**/*.{js,jsx,ts,tsx,css,md,json}'
+ run: |-
+ npx prettier -c 'apps/**/*.{js,jsx,ts,tsx,css,md,json}'
+ # [Joshen] Temp disable the following due to an issue
+ # https://github.com/EPMatt/reviewdog-action-prettier/issues/34
+ # uses: EPMatt/reviewdog-action-prettier@v1
+ # with:
+ # github_token: ${{ secrets.github_token }}
+ # reporter: github-pr-review
+ # level: warning
+ # command: npx prettier -c 'apps/**/*.{js,jsx,ts,tsx,css,md,json}'
# run: |-
# function run_check() {
@@ -38,11 +41,25 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Run prettier
- uses: EPMatt/reviewdog-action-prettier@v1
- with:
- github_token: ${{ secrets.github_token }}
- reporter: github-pr-review
- level: warning
- command: npx prettier -c 'i18n/**/*.{js,jsx,ts,tsx,css,md,json}'
+ run: |-
+ npx prettier -c 'i18n/**/*.{js,jsx,ts,tsx,css,md,json}'
+ # uses: EPMatt/reviewdog-action-prettier@v1
+ # with:
+ # github_token: ${{ secrets.github_token }}
+ # reporter: github-pr-review
+ # level: warning
+ # command: npx prettier -c 'i18n/**/*.{js,jsx,ts,tsx,css,md,json}'
+
+ format-sql:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out repo
+ uses: actions/checkout@v3
+ - name: Install plugin
+ run: npm ci
+ - name: Run prettier
+ run: |-
+ # Check mdx files which contain sql code blocks
+ grep -lr '```sql' apps/docs/pages/**/*.mdx | xargs npx prettier -c
diff --git a/.github/workflows/studio-build.yml b/.github/workflows/studio-build.yml
deleted file mode 100644
index 570baa1aa61..00000000000
--- a/.github/workflows/studio-build.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: Studio Build
-
-on:
- pull_request:
- branches:
- - master
- - studio
- paths:
- - 'studio/**'
-jobs:
- build:
- runs-on: ubuntu-latest
-
- strategy:
- matrix:
- node-version: [16.x]
- # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
-
- steps:
- - uses: actions/checkout@v2
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v2
- with:
- node-version: ${{ matrix.node-version }}
- cache: 'npm'
- - name: Install deps
- run: npm ci
- working-directory: ./
- - name: Run build
- run: npx turbo run build --filter=studio
- working-directory: ./
diff --git a/.github/workflows/studio-tests.yml b/.github/workflows/studio-tests.yml
index 1a99a50182d..11fda1e766c 100644
--- a/.github/workflows/studio-tests.yml
+++ b/.github/workflows/studio-tests.yml
@@ -8,10 +8,12 @@ on:
branches: [master]
paths:
- 'studio/**'
+ - 'package-lock.json'
pull_request:
branches: [master]
paths:
- 'studio/**'
+ - 'package-lock.json'
jobs:
build:
runs-on: ubuntu-latest
@@ -22,9 +24,9 @@ jobs:
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
diff --git a/.gitignore b/.gitignore
index f536bae18d7..c67a911193a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@ node_modules
out
.docz
tmp
+.swp
coverage
allure-results
@@ -119,4 +120,4 @@ typings/
**/supabase/.branches
**/supabase/.temp
-apps/new-docs/*
\ No newline at end of file
+apps/new-docs/*
diff --git a/.prettierignore b/.prettierignore
index 9ab0849d504..3703e192616 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -3,4 +3,11 @@
node_modules
package-lock.json
docker*
-apps/**/out
\ No newline at end of file
+apps/**/out
+# prettier-plugin-sql-cst only supports sqlite syntax
+**/supabase/migrations/*.sql
+apps/www/schema.sql
+examples/slack-clone/nextjs-slack-clone/full-schema.sql
+# ignore files with custom js formatting
+apps/docs/pages/guides/auth/*.mdx
+apps/docs/pages/guides/integrations/*.mdx
diff --git a/.prettierrc b/.prettierrc
index 76c3f65353b..b9bda117c38 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -4,5 +4,6 @@
"semi": false,
"singleQuote": true,
"printWidth": 100,
- "endOfLine": "lf"
+ "endOfLine": "lf",
+ "sqlKeywordCase": "lower"
}
diff --git a/DEVELOPERS.md b/DEVELOPERS.md
index 0281b1b0bd7..5487e76808a 100644
--- a/DEVELOPERS.md
+++ b/DEVELOPERS.md
@@ -57,7 +57,7 @@ To contribute code to [Supabase](https://supabase.com), you must fork the [Supab
[Supabase](https://supabase.com) uses [Turborepo](https://turborepo.org/docs) to manage and run this monorepo.
-1. Install the dependences in the root of the repo.
+1. Install the dependencies in the root of the repo.
```sh
npm install # install dependencies
@@ -113,7 +113,7 @@ Following the changes to the [Supabase docs](https://supabase.com/blog/new-supab
- Inside of `apps/docs` create a `.env.local` file with the following: `NEXT_PUBLIC_NEW_DOCS=true`
-Now when you run a local devlopment docs server you will see the new docs site.
+Now when you run a local development docs server you will see the new docs site.
---
@@ -136,3 +136,9 @@ Create a new entry in the [`redirects.js`](https://github.com/supabase/supabase/
## Community channels
Stuck somewhere? Have any questions? Join the [Discord Community Server](https://discord.supabase.com/) or the [Github Discussions](https://github.com/supabase/supabase/discussions). We are here to help!
+
+## Contributors
+
+
+
+
diff --git a/README.md b/README.md
index 304eceed468..fcf1cfe5aba 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
-
+
+
Create your own role.
-Develop insights with the Growth Team.
-Get our tools in front of the next billion developers.
-Develop and Maintain our Auth Products.
-Go deep on Postgres internals and extensions.
-Take the lead on our internal and external written communications
-Build our cloud platform.
-Get more developers interested in Postgres and Supabase.
-Build internal tooling, automated tests, and support processes.
-Build our Dashboard, tools, tests, and infra.
-Build our brand and visual communication.
-Build our Dashboard, tools, tests, and client libraries.
-Take the lead on our technical recruitment.
-- Supabase is the open source Firebase alternative. -
-
- - Backed by Y Combinator -
-{x.name}
-- {x.official ? ( - Official - ) : ( - Unofficial - )} -
-{extension.name}
- - {extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)} -
-+ +
++ {extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)} +
+{extension.name}
+ // + // {extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)} + //
+ // {extension.link && ( + // + // + // + //- Not to worry, our specialist engineers are here to help. Submit a support ticket through - the Dashboard. -
+- <> - {item.category} - {item.version ? ` (${item.version})` : ''}: - > -
- )} -
-
{item.description as string}
-{props.children},
- // inlineCode: (props: { children: string }) => Tutorials
*/}I am logged in!
+{/if} +``` + +## Client-side data fetching with RLS + +For [row level security](https://supabase.com/docs/guides/auth/row-level-security) to work properly when fetching data client-side, you need to use `supabaseClient` from `PageData` and only run your query once the session is defined client-side: + +```html + + +{#if data.session} +client-side data fetching with RLS
+{JSON.stringify(loadedData, null, 2)}
+{/if}
+```
+
+## Server-side data fetching with RLS
+
+```html
+
+
+
+{JSON.stringify(tableData, null, 2)}
+{JSON.stringify(user, null, 2)}
+```
+
+```ts
+// src/routes/profile/+page.ts
+import type { PageLoad } from './$types';
+import { redirect } from '@sveltejs/kit';
+
+export const load: PageLoad = async ({ parent }) => {
+ const { supabase, session } = await parent();
+ if (!session) {
+ throw redirect(303, '/');
+ }
+ const { data: tableData } = await supabase.from('test').select('*');
+
+ return {
+ user: session.user,
+ tableData
+ };
+};
+```
+
+## Protecting API routes
+
+Wrap an API Route to check that the user has a valid session. If they're not logged in the session is `null`.
+
+```ts
+// src/routes/api/protected-route/+server.ts
+import type { RequestHandler } from './$types';
+import { json, error } from '@sveltejs/kit';
+
+export const GET: RequestHandler = async ({
+ locals: { supabase, getSession }
+}) => {
+ const session = await getSession();
+ if (!session) {
+ // the user is not signed in
+ throw error(401, { message: 'Unauthorized' });
+ }
+ const { data } = await supabase.from('test').select('*');
+
+ return json({ data });
+};
+```
+
+If you visit `/api/protected-route` without a valid session cookie, you will get a 401 response.
+
+## Protecting Actions
+
+Wrap an Action to check that the user has a valid session. If they're not logged in the session is `null`.
+
+```ts
+// src/routes/posts/+page.server.ts
+import type { Actions } from './$types';
+import { error, fail } from '@sveltejs/kit';
+
+export const actions: Actions = {
+ createPost: async ({ request, locals: { supabase, getSession } }) => {
+ const session = await getSession();
+
+ if (!session) {
+ // the user is not signed in
+ throw error(401, { message: 'Unauthorized' });
+ }
+ // we are save, let the user create the post
+ const formData = await request.formData();
+ const content = formData.get('content');
+
+ const { error: createPostError, data: newPost } = await supabase
+ .from('posts')
+ .insert({ content });
+
+ if (createPostError) {
+ return fail(500, {
+ supabaseErrorMessage: createPostError.message
+ });
+ }
+ return {
+ newPost
+ };
+ }
+};
+```
+
+If you try to submit a form with the action `?/createPost` without a valid session cookie, you will get a 401 error response.
+
+## Saving and deleting the session
+
+```ts
+import type { Actions } from './$types';
+import { fail, redirect } from '@sveltejs/kit';
+import { AuthApiError } from '@supabase/supabase-js';
+
+export const actions: Actions = {
+ signin: async ({ request, locals: { supabase } }) => {
+ const formData = await request.formData();
+
+ const email = formData.get('email') as string;
+ const password = formData.get('password') as string;
+
+ const { error } = await supabase.auth.signInWithPassword({
+ email,
+ password
+ });
+
+ if (error) {
+ if (error instanceof AuthApiError && error.status === 400) {
+ return fail(400, {
+ error: 'Invalid credentials.',
+ values: {
+ email
+ }
+ });
+ }
+ return fail(500, {
+ error: 'Server error. Try again later.',
+ values: {
+ email
+ }
+ });
+ }
+
+ throw redirect(303, '/dashboard');
+ },
+
+ signout: async ({ locals: { supabase } }) => {
+ await supabase.auth.signOut();
+ throw redirect(303, '/');
+ }
+};
+```
+
+## Protecting multiple routes
+
+To avoid writing the same auth logic in every single route you can use the handle hook to
+protect multiple routes at once.
+
+```ts
+// src/hooks.server.ts
+import type { RequestHandler } from './$types';
+import { getSupabase } from '@supabase/auth-helpers-sveltekit';
+import { redirect, error } from '@sveltejs/kit';
+
+export const handle: Handle = async ({ event, resolve }) => {
+ // protect requests to all routes that start with /protected-routes
+ if (event.url.pathname.startsWith('/protected-routes')) {
+ const session = await event.locals.getSession();
+ if (!session) {
+ // the user is not signed in
+ throw redirect(303, '/');
+ }
+ }
+
+ // protect POST requests to all routes that start with /protected-posts
+ if (
+ event.url.pathname.startsWith('/protected-posts') &&
+ event.request.method === 'POST'
+ ) {
+ const session = await event.locals.getSession();
+ if (!session) {
+ // the user is not signed in
+ throw error(303, '/');
+ }
+ }
+
+ return resolve(event);
+};
+```
+
+## Migrate from 0.8.x to 0.9 [#migration]
+
+### Set up the Supabase client [#migration-set-up-supabase-client]
+
+In version 0.9 we now setup our Supabase client for the server inside of a `hooks.server.ts` file.
+
+I am logged in!
-{/if} +declare global { + namespace App { + interface Locals { + supabase: SupabaseClientclient-side data fetching with RLS
-{JSON.stringify(loadedData, null, 2)}
-{/if}
-```
-
-## Server-side data fetching with RLS
+{JSON.stringify(tableData, null, 2)}
+{JSON.stringify(user, null, 2)}
+```
+
+```ts title=src/routes/profile/+page.ts
+// src/routes/profile/+page.ts
+import type { PageLoad } from './$types';
+import { redirect } from '@sveltejs/kit';
+
+export const load: PageLoad = async ({ parent }) => {
+ const { supabase, session } = await parent();
+ if (!session) {
+ throw redirect(303, '/');
+ }
+ const { data: tableData } = await supabase.from('test').select('*');
+
+ return {
+ user: session.user,
+ tableData
+ };
+};
+```
+
+Sign in via magic link with your email below
- {loading ? ( - 'Sending magic link...' - ) : ( -Sign in via magic link with your email below
Follow the step-by-step tutorials.
+Follow the step-by-step tutorials.
-
{parameter.required.toString()}
-
- {parameter.default ? parameter.default.toString() : 'None'}
-
+ <>
+
+
+
{parameter.required.toString()}
+
+ {parameter.default ? parameter.default.toString() : 'None'}
+
+ {parameter.title}
-
-
{parameter.required.toString()}
-
- {parameter.default ? parameter.default.toString() : 'None'}
-
+ <>
+
+ {parameter.title}
+
+
{parameter.required.toString()}
+
+ {parameter.default ? parameter.default.toString() : 'None'}
+
+ There are many example apps and starter projects to get going
+ April 10th – 14th at 7AM PT | 10AM ET +
+
+ Join us on April 16th for Launch Week 7's final day
+
and find out if you are one of the lucky
+ winners. Get sharing!
+
+ Increase your chances of winning limited edition 62-Key ISO Custom Mechanical + Keyboard by sharing your ticket on Twitter and LinkedIn. +
+ > + } + /> + +
+ @{user.username}
} ++ Join us on April 16th for Launch Week 7's final day and find out if you are one + of the lucky winners. +
+ ) : username ? ( ++ Why stop there? Increase your chances of winning by sharing your unique ticket. + Get sharing! +
+ ) : ( ++ We have some fantastic swag up for grabs, including 3 limited-edition mechanical + keyboards that you won't want to miss. +
+ )} + > + ) : ( + <> ++ Get yours and win some fantastic swag, including a limited-edition mechanical + keyboard that you won't want to miss. +
+ + + > + )} +Only public info will be used.
} */} +
+ {DATE}
+ +
{name &&
@{username}
} +{ if (!scrolling) { @@ -95,10 +84,7 @@ export default function TicketCopy({ username }: Props) { {url}
Only public info will be used.
} -