From 45550be4e0784a9aece37e72ed068748c506f3fa Mon Sep 17 00:00:00 2001 From: dannykng Date: Wed, 4 Jan 2023 15:50:54 -0800 Subject: [PATCH 01/69] Delete old mdx files --- apps/docs/pages/getting-started.mdx | 161 ------ apps/docs/pages/guides/tutorials.mdx | 159 ------ apps/docs/pages/new/auth.mdx | 77 --- apps/docs/pages/ref-pages.mdx | 0 apps/docs/pages/tutorials/nextjs.mdx | 724 --------------------------- 5 files changed, 1121 deletions(-) delete mode 100644 apps/docs/pages/getting-started.mdx delete mode 100644 apps/docs/pages/guides/tutorials.mdx delete mode 100644 apps/docs/pages/new/auth.mdx delete mode 100644 apps/docs/pages/ref-pages.mdx delete mode 100644 apps/docs/pages/tutorials/nextjs.mdx diff --git a/apps/docs/pages/getting-started.mdx b/apps/docs/pages/getting-started.mdx deleted file mode 100644 index ccb7790f15e..00000000000 --- a/apps/docs/pages/getting-started.mdx +++ /dev/null @@ -1,161 +0,0 @@ -import Layout from '~/layouts/DefaultGuideLayout' - -export const meta = { - title: 'Overview', - description: 'An overview of Supabase\'s architecture and product principles.', -} - -Supabase is open source. We choose open source tools which are scalable and make them simple to use. - -Supabase is not a 1-to-1 mapping of Firebase. While we are building many of the features that Firebase offers, we are not going about it the same way: -our technological choices are quite different; everything we use is open source; and wherever possible, we use and support existing tools rather than developing from scratch. - -Most notably, we use Postgres rather than a NoSQL store. This choice was deliberate. We believe that no other database offers the functionality required to compete with Firebase, -while maintaining the scalability required to go beyond it. - -## Architecture - -Each Supabase project consists of several tools: - -![Supabase Architecture](/docs/img/supabase-architecture.png) - -### PostgreSQL (Database) - -PostgreSQL is the core of Supabase. We do not abstract the PostgreSQL database — you can access it and use it with full privileges. We simply provide tools which makes PostgreSQL as easy to use as Firebase. - -- Official Docs: [postgresql.org/docs](https://www.postgresql.org/docs/current/index.html) -- Source code: [github.com/postgres/postgres](https://github.com/postgres/postgres) (mirror) -- License: [PostgreSQL Licence](https://www.postgresql.org/about/licence/) -- Language: C - -### Studio (Dashboard) - -An open source Dashboard for managing your database and services. - -- Official Docs: [Supabase docs](/docs) -- Source code: [github.com/supabase/supabase](https://github.com/supabase/supabase/tree/master/studio) -- License: [Apache 2](https://github.com/supabase/supabase/blob/master/LICENSE) -- Language: TypeScript - -### GoTrue (Auth) - -A JWT-based API for managing users and issuing access tokens. This integrates with PostgreSQL's Row Level Security and the API servers. - -- Official Docs: [Supabase Auth reference docs](/docs/reference/auth) -- Source code: [github.com/supabase/gotrue](https://github.com/supabase/gotrue) -- License: [MIT](https://github.com/supabase/gotrue/blob/master/LICENSE) -- Language: Go - -### PostgREST (API) - -A standalone web server that turns your PostgreSQL database directly into a RESTful API. -We use this with our [pg_graphql](https://github.com/supabase/pg_graphql) extension to provide a GraphQL API. - -- Official Docs: [postgrest.org](https://postgrest.org/) -- Source code: [github.com/PostgREST/postgrest](https://github.com/PostgREST/postgrest) -- License: [MIT](https://github.com/PostgREST/postgrest/blob/main/LICENSE) -- Language: Haskel - -### Realtime (API & multiplayer) - -A scalable websocket engine for managing user Presence, broadcasting messages, and streaming database changes. - -- Official Docs: [Supabase Realtime docs](/docs/guides/realtime) -- Source code: [github.com/supabase/realtime](https://github.com/supabase/realtime) -- License: [Apache 2](https://github.com/supabase/realtime/blob/main/LICENSE) -- Language: Elixir - -### Storage API (large file storage) - -An S3-compatible object storage service that stores metadata in Postgres. - -- Official Docs: [Supabase Storage reference docs](/docs/reference/storage) -- Source code: [github.com/supabase/storage-api](https://github.com/supabase/storage-api) -- License: [Apache 2.0](https://github.com/supabase/storage-api/blob/master/LICENSE) -- Language: NodeJS / TypeScript - -### Deno (Edge Functions) - -A modern runtime for JavaScript and TypeScript. - -- Official Docs: [deno.land](https://deno.land/) -- Source code: [github.com/denoland/deno](https://github.com/denoland/deno) -- License: [MIT](https://github.com/denoland/deno/blob/main/LICENSE.md) -- Language: TypeScript / Rust - -### postgres-meta (Database management) - -A RESTful API for managing your Postgres. Fetch tables, add roles, and run queries. - -- Official Docs: [supabase.github.io/postgres-meta](https://supabase.github.io/postgres-meta/) -- Source code: [github.com/supabase/postgres-meta](https://github.com/supabase/postgres-meta) -- License: [Apache 2.0](https://github.com/supabase/postgres-meta/blob/master/LICENSE) -- Language: NodeJS / TypeScript - -### PgBouncer - -A lightweight connection pooler for PostgreSQL. This is useful for connecting to Postgres when using Serverless functions. - -- Official Docs: [pgbouncer.org](http://www.pgbouncer.org/) -- Source code: [pgbouncer/pgbouncer](https://github.com/pgbouncer/pgbouncer) -- License: [ISC](https://github.com/pgbouncer/pgbouncer/blob/master/COPYRIGHT) -- Language: C - -### Kong (API Gateway) - -A cloud-native API gateway, built on top of Nginx. - -- Official Docs: [docs.konghq.com](https://docs.konghq.com/) -- Source code: [github.com/kong/kong](https://github.com/kong/kong) -- License: [Apache 2.0](https://github.com/Kong/kong/blob/master/LICENSE) -- Language: Lua - -## Product Principles - -It is our goal to provide an architecture that any large-scale company would design for themselves, -and then provide tooling around that architecture that is easy-to-use for indie-developers and small teams. - -We use a series of principles to ensure that scalability and usability are never mutually exclusive: - -### Everything works in isolation - -Each system must work as a standalone tool with as few moving parts as possible. -The litmus test for this is: "Can a user run this product with nothing but a Postgres database?" - -### Everything is integrated - -Supabase is composable. Even though every product works in isolation, each product on the platform needs to 10x the other products. -For integration, each tool should expose an API and Webhooks. - -### Everything is extensible - -We're deliberate about adding a new tool, and prefer instead to extend an existing one. -This is the opposite of many cloud providers whose product offering expands into niche use-cases. We provide _primitives_ for developers, which allow them to achieve any goal. -Less, but better. - -### Everything is portable - -To avoid lock-in, we make it easy to migrate in and out. Our cloud offering is compatible with our self-hosted product. -We use existing standards to increase portability (like pg_dump an CSV files). If a new standard emerges which competes with a "Supabase" approach, we will deprecate the approach in favor of the standard. -This forces us compete on experience. We aim to be the best Postgres hosting service. - -### Play the long game - -We sacrifice short-term wins for long-term gains. For example, it is tempting to run a fork of Postgres with additional functionality which only our customers need. -Instead, we prefer to support efforts to upstream missing functionality so that the entire community benefits. This has the additional benefit of ensuring portability and longevity. - -### Build for developers - -"Developers" are a specific profile of user: they are _builders_. -When assessing impact as a function of effort, developers have a large efficiency due to the type of products and systems they can build. -As the profile of a developer changes over time, Supabase will continue to evolve the product to fit this evolving profile. - -### Support existing tools - -Supabase supports existing tools and communities wherever possible. Supabase is more like a "community of communities" - each tool typically has its own community -which we work with. -Open source is something we approach [collaboratively](https://supabase.com/blog/supabase-series-b#giving-back): we employ maintainers, sponsor projects, invest in businesses, and develop our own open source tools. - -export const Page = ({ children }) => - -export default Page diff --git a/apps/docs/pages/guides/tutorials.mdx b/apps/docs/pages/guides/tutorials.mdx deleted file mode 100644 index 39f553feea8..00000000000 --- a/apps/docs/pages/guides/tutorials.mdx +++ /dev/null @@ -1,159 +0,0 @@ -import Layout from '~/layouts/DefaultLayout' -import Link from 'next/link' -import { GlassPanel } from 'ui' - -export const meta = { - title: 'Tutorials', -} - -### Webapps - -
- {webapps.map((item) => { - return ( - - - - {item.description} - - - - ) - })} -
- -### Mobile - -
- {mobile.map((item) => { - return ( - - - - {item.description} - - - - ) - })} -
- -### Low code - -
- {lowCode.map((item) => { - return ( - - - - {item.description} - - - - ) - })} -
- -export const webapps = [ - { - title: 'NextJS', - href: '/guides/tutorials/with-nextjs', - description: - 'Learn how to build a user management app with NextJS and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/nextjs-icon', - }, - { - title: 'React', - href: '/guides/tutorials/with-react', - description: - 'Learn how to build a user management app with React and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/react-icon', - }, - { - title: 'Vue 3', - href: '/guides/tutorials/with-vue-3', - description: - 'Learn how to build a user management app with Vue 3 and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/vuejs-icon', - }, - { - title: 'Nuxt 3', - href: '/guides/tutorials/with-nuxt-3', - description: - 'Learn how to build a user management app with Nuxt 3 and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/nuxt-icon', - }, - { - title: 'Anglular', - href: '/guides/tutorials/with-angular', - description: - 'Learn how to build a user management app with Nuxt 3 and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/angular-icon', - }, - { - title: 'RedwoodJS', - href: '/guides/tutorials/with-redwoodjs', - description: - 'Learn how to build a user management app with Nuxt 3 and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/redwood-icon', - }, - { - title: 'Svelte', - href: '/guides/tutorials/with-svelte', - description: - 'Learn how to build a user management app with Nuxt 3 and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/svelte-icon', - }, - { - title: 'SvelteKit', - href: '/guides/tutorials/with-sveltekit', - description: - 'Learn how to build a user management app with Nuxt 3 and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/svelte-icon', - }, -] - -export const mobile = [ - { - title: 'Flutter', - href: '/guides/tutorials/with-flutter', - description: - 'Learn how to build a user management app with Flutter and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/flutter-icon', - }, - { - title: 'Expo', - href: '/guides/tutorials/with-expo', - description: - 'Learn how to build a user management app with React and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/expo-icon', - }, -] - -export const lowCode = [ - { - title: 'Ionic React', - href: '/guides/tutorials/with-ionic-react', - description: - 'Learn how to build a user management app with React and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/ionic-icon', - }, - { - title: 'Ionic Vue', - href: '/guides/tutorials/with-ionic-vue', - description: - 'Learn how to build a user management app with Flutter and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/ionic-icon', - }, - { - title: 'Ionic Angular', - href: '/guides/tutorials/with-ionic-angular', - description: - 'Learn how to build a user management app with NextJS and Supabase Database, Auth, and Storage functionality.', - icon: '/docs/img/icons/ionic-icon', - }, -] - -export const Page = ({ children }) => - -export default Page diff --git a/apps/docs/pages/new/auth.mdx b/apps/docs/pages/new/auth.mdx deleted file mode 100644 index 5228f5129da..00000000000 --- a/apps/docs/pages/new/auth.mdx +++ /dev/null @@ -1,77 +0,0 @@ -import Layout from '~/layouts/DefaultLayout' -import Link from 'next/link' -// import { useTheme } from 'common/Providers' -import { GlassPanel } from 'ui' - -{/* // export const { isDarkMode } = useTheme() */} - -export const meta = { - title: 'Auth', -} - -## Add and manage email and password, passwordless, OAuth, and mobile logins to your project through a suite of identity providers and APIs. - -### Popular Guides - -
- {topArticles.map((item) => { - return ( - - - - {item.description} - - - - )})} - -
- -export const topArticles = [ - { - title: 'Enable Captcha Protection', - header: '/docs/img/cards/sample-card-header-4.svg', - href: '/guides/auth/auth-captcha', - description: 'Keep your platform safe from bots and malicious scripts by implementing hCaptcha.', - span: 'col-span-6', - }, - { - title: 'Auth Helpers', - header: '/docs/img/cards/sample-card-header-4.svg', - href: '/guides/auth/auth-helpers', - description: 'A collection of framework-specific utilities for implementing Supabase Auth.', - span: 'col-span-6', - }, - { - title: 'Email Login', - header: '/docs/img/cards/sample-card-header-4.svg', - href: '/guides/auth/auth-email', - description: 'Learn how to add an email and password login flow to your platform.', - }, - { - title: 'Phone Login', - header: '/docs/img/cards/sample-card-header-4.svg', - href: '/guides/auth/phone-login', - description: 'Learn how to add a login flow so your users can access your platform through one-time passwords via SMS.', - }, - { - title: 'Social Login', - header: '/docs/img/cards/sample-card-header-4.svg', - href: '/guides/auth/social-login', - description: 'Learn how to add a login flow so your users can access your platform through social providers like Apple, Facebook, or Google.', - }, -] - -export const Page = ({ children }) => - -export default Page diff --git a/apps/docs/pages/ref-pages.mdx b/apps/docs/pages/ref-pages.mdx deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/apps/docs/pages/tutorials/nextjs.mdx b/apps/docs/pages/tutorials/nextjs.mdx deleted file mode 100644 index 5e22b391296..00000000000 --- a/apps/docs/pages/tutorials/nextjs.mdx +++ /dev/null @@ -1,724 +0,0 @@ -import Layout from '~/layouts/tutorials/TutorialLayout' - -export const meta = { - title: 'Creating a user management dashboard with NextJS and Supabase', - author: 'Rich Haines', - video: 'https://www.youtube-nocookie.com/embed/0Fs96oZ4se0', -} - -In this 25-minute guide, we’ll be building a collaborative user managment app using NextJS and Supabase. -As users add and move rectangles in a canvas, changes will be automatically synced and persisted, allowing for a canvas that updates in real-time across clients. -Users will also be able to see other users selections, and undo and redo actions. - -![Supabase User Management example](/docs/img/user-management-demo.png) - -### GitHub - -Should you get stuck while working through the guide, refer to [this repo](https://github.com/supabase/supabase/tree/master/examples/user-management/nextjs-ts-user-management). - -## Building the App - -Let's start building the Next.js app from scratch. - -### Initialize a Next.js app - -We can use [`create-next-app`](https://nextjs.org/docs/getting-started) to initialize -an app called `supabase-nextjs`: - - - - -```bash -npx create-next-app@latest --use-npm supabase-nextjs -cd supabase-nextjs -``` - - - - -```bash -npx create-next-app@latest --ts --use-npm supabase-nextjs -cd supabase-nextjs -``` - - - - -Then install the Supabase client library: [supabase-js](https://github.com/supabase/supabase-js) - -```bash -npm install @supabase/supabase-js -``` - -And finally we want to save the environment variables in a `.env.local`. -All we need are the API URL and the `anon` key that you copied [earlier](#get-the-api-keys). - -```bash title=.env.local -NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL -NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY -``` - -And one optional step is to update the CSS file `styles/globals.css` to make the app look nice. -You can find the full contents of this file [here](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/nextjs-ts-user-management/styles/globals.css). - -### Set up a Login component - -#### Supabase Auth Helpers - -Next.js is a highly versatile framework offering pre-rendering at build time (SSG), server-side rendering at request time (SSR), API routes, and middleware edge-functions. - -It can be challenging to authenticate your users in all these different environments, that's why we've created the [Supabase Auth Helpers](https://supabase.com/docs/guides/auth/auth-helpers/nextjs) to make user management and data fetching within Next.js as easy as possible. - -Install the auth helpers for React and Next.js - -```bash -npm install @supabase/auth-helpers-react @supabase/auth-helpers-nextjs -``` - - - - -Wrap your `pages/_app.js` component with the `SessionContextProvider` component: - -```jsx title=pages/_app.js -import '../styles/globals.css' -import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs' -import { SessionContextProvider } from '@supabase/auth-helpers-react' - -function MyApp({ Component, pageProps }) { - const [supabaseClient] = useState(() => createBrowserSupabaseClient()) - - return ( - - - - ) -} -export default MyApp -``` - - - - -Wrap your `pages/_app.tsx` component with the `SessionContextProvider` component: - -```jsx lines=2,8 title=pages/_app.tsx -import { createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs' -import { SessionContextProvider, Session } from '@supabase/auth-helpers-react' - -function MyApp({ - Component, - pageProps, -}: AppProps<{ - initialSession: Session, -}>) { - const [supabaseClient] = useState(() => createBrowserSupabaseClient()) - - return ( - - - - ) -} -export default MyApp -``` - -See the [Auth Helpers docs](/docs/guides/auth/auth-helpers/nextjs#usage-with-typescript) for more details on usage with TypeScript. - - - - -#### Supabase Auth UI - -We can use the [Supabase Auth UI](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui) a pre-built React component for authenticating users via OAuth, email, and magic links. - -Install the Supabase Auth UI for React - -```bash -npm install @supabase/auth-ui-react -``` - -Add the `Auth` component to your home page - -```jsx title=pages/index.js -import { Auth, ThemeSupa } from '@supabase/auth-ui-react' -import { useSession, useSupabaseClient } from '@supabase/auth-helpers-react' - -const Home = () => { - const session = useSession() - const supabase = useSupabaseClient() - - return ( -
- {!session ? ( - - ) : ( -

Account page will go here.

- )} -
- ) -} - -export default Home -``` - -### Account page - -After a user is signed in we can allow them to edit their profile details and manage their account. - - - - -Let's create a new component for that called `Account.js` within a `components` folder. - -```tsx title=components/Account.js -import { useState, useEffect } from 'react' -import { useUser, useSupabaseClient } from '@supabase/auth-helpers-react' - -export default function Account({ session }) { - const supabase = useSupabaseClient() - const user = useUser() - const [loading, setLoading] = useState(true) - const [username, setUsername] = useState(null) - const [website, setWebsite] = useState(null) - const [avatar_url, setAvatarUrl] = useState(null) - - useEffect(() => { - getProfile() - }, [session]) - - async function getProfile() { - try { - setLoading(true) - - let { data, error, status } = await supabase - .from('profiles') - .select(`username, website, avatar_url`) - .eq('id', user.id) - .single() - - if (error && status !== 406) { - throw error - } - - if (data) { - setUsername(data.username) - setWebsite(data.website) - setAvatarUrl(data.avatar_url) - } - } catch (error) { - alert('Error loading user data!') - console.log(error) - } finally { - setLoading(false) - } - } - - async function updateProfile({ username, website, avatar_url }) { - try { - setLoading(true) - - const updates = { - id: user.id, - username, - website, - avatar_url, - updated_at: new Date().toISOString(), - } - - let { error } = await supabase.from('profiles').upsert(updates) - if (error) throw error - alert('Profile updated!') - } catch (error) { - alert('Error updating the data!') - console.log(error) - } finally { - setLoading(false) - } - } - - return ( -
-
- - -
-
- - setUsername(e.target.value)} - /> -
-
- - setWebsite(e.target.value)} - /> -
- -
- -
- -
- -
-
- ) -} -``` - -
- - -Let's create a new component for that called `Account.tsx` within a `components` folder. - -```tsx title=components/Account.tsx -import { useState, useEffect } from 'react' -import { useUser, useSupabaseClient, Session } from '@supabase/auth-helpers-react' -import { Database } from '../utils/database.types' -type Profiles = Database['public']['Tables']['profiles']['Row'] - -export default function Account({ session }: { session: Session }) { - const supabase = useSupabaseClient() - const user = useUser() - const [loading, setLoading] = useState(true) - const [username, setUsername] = useState(null) - const [website, setWebsite] = useState(null) - const [avatar_url, setAvatarUrl] = useState(null) - - useEffect(() => { - getProfile() - }, [session]) - - async function getProfile() { - try { - setLoading(true) - if (!user) throw new Error('No user') - - let { data, error, status } = await supabase - .from('profiles') - .select(`username, website, avatar_url`) - .eq('id', user.id) - .single() - - if (error && status !== 406) { - throw error - } - - if (data) { - setUsername(data.username) - setWebsite(data.website) - setAvatarUrl(data.avatar_url) - } - } catch (error) { - alert('Error loading user data!') - console.log(error) - } finally { - setLoading(false) - } - } - - async function updateProfile({ - username, - website, - avatar_url, - }: { - username: Profiles['username'] - website: Profiles['website'] - avatar_url: Profiles['avatar_url'] - }) { - try { - setLoading(true) - if (!user) throw new Error('No user') - - const updates = { - id: user.id, - username, - website, - avatar_url, - updated_at: new Date().toISOString(), - } - - let { error } = await supabase.from('profiles').upsert(updates) - if (error) throw error - alert('Profile updated!') - } catch (error) { - alert('Error updating the data!') - console.log(error) - } finally { - setLoading(false) - } - } - - return ( -
-
- - -
-
- - setUsername(e.target.value)} - /> -
-
- - setWebsite(e.target.value)} - /> -
- -
- -
- -
- -
-
- ) -} -``` - -
-
- -### Launch! - -Now that we have all the components in place, let's update `pages/index.js`: - -```jsx lines=3,14 title=pages/index.js -import { Auth, ThemeSupa } from '@supabase/auth-ui-react' -import { useSession, useSupabaseClient } from '@supabase/auth-helpers-react' -import Account from '../components/Account' - -const Home = () => { - const session = useSession() - const supabase = useSupabaseClient() - - return ( -
- {!session ? ( - - ) : ( - - )} -
- ) -} - -export default Home -``` - -Once that's done, run this in a terminal window: - -```bash -npm run dev -``` - -And then open the browser to [localhost:3000](http://localhost:3000) and you should see the completed app. - -## Bonus: Profile photos - -Every Supabase project is configured with [Storage](/docs/guides/storage) for managing large files like -photos and videos. - -### Create an upload widget - -Let's create an avatar widget for the user so that they can upload a profile photo. We can start by creating a new component: - - - - -```jsx title=components/Avatar.js -import React, { useEffect, useState } from 'react' -import { useSupabaseClient } from '@supabase/auth-helpers-react' - -export default function Avatar({ uid, url, size, onUpload }) { - const supabase = useSupabaseClient() - const [avatarUrl, setAvatarUrl] = useState(null) - const [uploading, setUploading] = useState(false) - - useEffect(() => { - if (url) downloadImage(url) - }, [url]) - - async function downloadImage(path) { - try { - const { data, error } = await supabase.storage.from('avatars').download(path) - if (error) { - throw error - } - const url = URL.createObjectURL(data) - setAvatarUrl(url) - } catch (error) { - console.log('Error downloading image: ', error) - } - } - - const uploadAvatar = async (event) => { - try { - setUploading(true) - - if (!event.target.files || event.target.files.length === 0) { - throw new Error('You must select an image to upload.') - } - - const file = event.target.files[0] - const fileExt = file.name.split('.').pop() - const fileName = `${uid}.${fileExt}` - const filePath = `${fileName}` - - let { error: uploadError } = await supabase.storage - .from('avatars') - .upload(filePath, file, { upsert: true }) - - if (uploadError) { - throw uploadError - } - - onUpload(filePath) - } catch (error) { - alert('Error uploading avatar!') - console.log(error) - } finally { - setUploading(false) - } - } - - return ( -
- {avatarUrl ? ( - Avatar - ) : ( -
- )} -
- - -
-
- ) -} -``` - - - - -```tsx title=components/Avatar.tsx -import React, { useEffect, useState } from 'react' -import { useSupabaseClient } from '@supabase/auth-helpers-react' -import { Database } from '../utils/database.types' -type Profiles = Database['public']['Tables']['profiles']['Row'] - -export default function Avatar({ - uid, - url, - size, - onUpload, -}: { - uid: string - url: Profiles['avatar_url'] - size: number - onUpload: (url: string) => void -}) { - const supabase = useSupabaseClient() - const [avatarUrl, setAvatarUrl] = useState(null) - const [uploading, setUploading] = useState(false) - - useEffect(() => { - if (url) downloadImage(url) - }, [url]) - - async function downloadImage(path: string) { - try { - const { data, error } = await supabase.storage.from('avatars').download(path) - if (error) { - throw error - } - const url = URL.createObjectURL(data) - setAvatarUrl(url) - } catch (error) { - console.log('Error downloading image: ', error) - } - } - - const uploadAvatar: React.ChangeEventHandler = async (event) => { - try { - setUploading(true) - - if (!event.target.files || event.target.files.length === 0) { - throw new Error('You must select an image to upload.') - } - - const file = event.target.files[0] - const fileExt = file.name.split('.').pop() - const fileName = `${uid}.${fileExt}` - const filePath = `${fileName}` - - let { error: uploadError } = await supabase.storage - .from('avatars') - .upload(filePath, file, { upsert: true }) - - if (uploadError) { - throw uploadError - } - - onUpload(filePath) - } catch (error) { - alert('Error uploading avatar!') - console.log(error) - } finally { - setUploading(false) - } - } - - return ( -
- {avatarUrl ? ( - Avatar - ) : ( -
- )} -
- - -
-
- ) -} -``` - - - - -### Add the new widget - -And then we can add the widget to the Account page: - -```jsx title=components/Account.js -// Import the new component -import Avatar from './Avatar' - -// ... - -return ( -
- {/* Add to the body */} - { - setAvatarUrl(url) - updateProfile({ username, website, avatar_url: url }) - }} - /> - {/* ... */} -
-) -``` - -## Next steps - -At this stage you have a fully functional application! - -- See the complete [example on GitHub](https://github.com/supabase/supabase/tree/master/examples/user-management/nextjs-ts-user-management) and deploy it to Vercel. -- Explore the [pre-built Auth UI for React](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui). -- Explore the [Auth Helpers for Next.js](https://supabase.com/docs/guides/auth/auth-helpers/nextjs). -- Explore the [Supabase Cache Helpers](https://github.com/psteinroe/supabase-cache-helpers). -- See the [Next.js Subscription Payments Starter](https://github.com/vercel/nextjs-subscription-payments) template on GitHub. -- Got a question? [Ask here](https://github.com/supabase/supabase/discussions). -- Sign in: [app.supabase.com](https://app.supabase.com) - -export default ({ children }) => From 6af3acdc046e6b616a7c745461cabd9bae7ddb37 Mon Sep 17 00:00:00 2001 From: dannykng Date: Wed, 4 Jan 2023 16:09:51 -0800 Subject: [PATCH 02/69] Update sitemap --- apps/docs/public/sitemap.xml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/apps/docs/public/sitemap.xml b/apps/docs/public/sitemap.xml index 38b0e06220a..9cc0078e8dd 100644 --- a/apps/docs/public/sitemap.xml +++ b/apps/docs/public/sitemap.xml @@ -6,12 +6,6 @@ 0.5 - - https://supabase.com/docs/getting-started - weekly - 0.5 - - https://supabase.com/docs/index weekly @@ -84,12 +78,6 @@ 0.5 - - https://supabase.com/docs/guides/tutorials - weekly - 0.5 - - https://supabase.com/docs/handbook/contributing weekly From fcfc1886d0c1a5a7f260039fdd15fed3279c8a98 Mon Sep 17 00:00:00 2001 From: Ollie Halliday <22655069+Hallidayo@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:51:15 +0000 Subject: [PATCH 03/69] added link for docs --- .../Auth/EmailTemplates/EmailTemplates.tsx | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx b/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx index 0e86b1247a5..a982880a845 100644 --- a/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx +++ b/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx @@ -1,4 +1,4 @@ -import { Tabs } from 'ui' +import { Button, IconExternalLink, Tabs } from 'ui' import { observer } from 'mobx-react-lite' import { TEMPLATES_SCHEMAS } from 'stores/authConfig/schema' @@ -8,10 +8,20 @@ import TemplateEditor from './TemplateEditor' const EmailTemplates = observer(() => { return (
- + Date: Tue, 10 Jan 2023 15:20:26 -0800 Subject: [PATCH 04/69] Revert "Update sitemap" This reverts commit 6af3acdc046e6b616a7c745461cabd9bae7ddb37. --- apps/docs/public/sitemap.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/docs/public/sitemap.xml b/apps/docs/public/sitemap.xml index 9cc0078e8dd..38b0e06220a 100644 --- a/apps/docs/public/sitemap.xml +++ b/apps/docs/public/sitemap.xml @@ -6,6 +6,12 @@ 0.5 + + https://supabase.com/docs/getting-started + weekly + 0.5 + + https://supabase.com/docs/index weekly @@ -78,6 +84,12 @@ 0.5 + + https://supabase.com/docs/guides/tutorials + weekly + 0.5 + + https://supabase.com/docs/handbook/contributing weekly From 8cc5f19d9e948a6b8747880faaa00dd45eb1895f Mon Sep 17 00:00:00 2001 From: Ollie Halliday <22655069+Hallidayo@users.noreply.github.com> Date: Thu, 19 Jan 2023 16:18:01 +0000 Subject: [PATCH 05/69] changed to use Select instead of ListBox --- .../grid/components/editor/SelectEditor.tsx | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/studio/components/grid/components/editor/SelectEditor.tsx b/studio/components/grid/components/editor/SelectEditor.tsx index f980583fad0..206417e5901 100644 --- a/studio/components/grid/components/editor/SelectEditor.tsx +++ b/studio/components/grid/components/editor/SelectEditor.tsx @@ -1,4 +1,4 @@ -import { Listbox } from '@supabase/ui' +import { Select } from '@supabase/ui' import { EditorProps } from '@supabase/react-data-grid' import { useTrackedState } from 'components/grid/store' @@ -19,11 +19,11 @@ export function SelectEditor({ const value = row[column.key as keyof TRow] as unknown as string - function onChange(value: string) { + function onChange(value: any) { if (!value || value == '') { onRowChange({ ...row, [column.key]: null }, true) } else { - onRowChange({ ...row, [column.key]: value }, true) + onRowChange({ ...row, [column.key]: value.target.value }, true) } } @@ -32,7 +32,7 @@ export function SelectEditor({ } return ( - ({ onChange={onChange} onBlur={onBlur} > - - NULL - + NULL {options.map(({ label, value }) => ( - + {label} - + ))} - + ) } From 30dd26e816f0db8a9fead7501a461d331f217c76 Mon Sep 17 00:00:00 2001 From: Ollie Halliday <22655069+Hallidayo@users.noreply.github.com> Date: Fri, 20 Jan 2023 12:07:57 +0000 Subject: [PATCH 06/69] changed to ui package and added selected param --- studio/components/grid/components/editor/SelectEditor.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/studio/components/grid/components/editor/SelectEditor.tsx b/studio/components/grid/components/editor/SelectEditor.tsx index 206417e5901..6a0410470d2 100644 --- a/studio/components/grid/components/editor/SelectEditor.tsx +++ b/studio/components/grid/components/editor/SelectEditor.tsx @@ -1,10 +1,10 @@ -import { Select } from '@supabase/ui' +import { Select } from 'ui' import { EditorProps } from '@supabase/react-data-grid' import { useTrackedState } from 'components/grid/store' interface SelectEditorProps extends EditorProps { - options: { label: string; value: string }[] + options: { label: string; _value: string }[] } export function SelectEditor({ @@ -45,8 +45,8 @@ export function SelectEditor({ onBlur={onBlur} > NULL - {options.map(({ label, value }) => ( - + {options.map(({ label, _value }) => ( + {label} ))} From e667593f63270b291986419d5f6f484e43e102bf Mon Sep 17 00:00:00 2001 From: Simon Basset Date: Fri, 20 Jan 2023 20:58:55 +0100 Subject: [PATCH 07/69] docs(storage): use 'to' field instead of 'auth.role()' in storage access control docs --- apps/docs/pages/guides/storage/access-control.mdx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/docs/pages/guides/storage/access-control.mdx b/apps/docs/pages/guides/storage/access-control.mdx index 58572bd789e..4adfd73e135 100644 --- a/apps/docs/pages/guides/storage/access-control.mdx +++ b/apps/docs/pages/guides/storage/access-control.mdx @@ -117,10 +117,8 @@ using ( bucket_id = 'public' ); -- 1. Allow logged-in access to any files in the "restricted" bucket create policy "Restricted Access" on storage.objects for select -using ( - bucket_id = 'restricted' - and auth.role() = 'authenticated' -); +to authenticated +using ( bucket_id = 'restricted' ); ``` ### Allow individual access to a file From 7b982eb03f23293ec323e63a4a55e0d7018254b6 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Sat, 21 Jan 2023 09:43:45 -0330 Subject: [PATCH 08/69] Remove console.log --- .../Navigation/NavigationMenu/NavigationMenuRefListItems.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx index 690615b4a13..27f1e69ba99 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuRefListItems.tsx @@ -179,7 +179,7 @@ const Content: React.FC = ({ id, lib, commonSections, sp if (!sections) console.error('no common sections imported') const menu = NavItems[id] - console.log(menu) + //console.log(menu) const databaseFunctions = find(sections, { title: 'Database' }) ? find(sections, { title: 'Database' }).items : [] From 3912a1119931dd2abe880e0bb3ea9af245046530 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Sat, 21 Jan 2023 10:00:13 -0330 Subject: [PATCH 09/69] Add overview menu --- .../components/Navigation/NavigationMenu/HomeMenu.tsx | 2 +- .../NavigationMenu/NavigationMenu.constants.ts | 10 ++++++++++ .../Navigation/NavigationMenu/NavigationMenu.tsx | 5 +++++ apps/docs/layouts/SiteLayout.tsx | 4 ++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx index 7738ed521d9..1893c60af37 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx @@ -112,7 +112,7 @@ const home = [ { label: 'Supabase CLI', icon: '/img/icons/menu/reference-cli', - href: '/reference/cli/introduction', + href: '/reference/cli/overview', level: 'reference_javascript', }, ], diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 40ceb4f47e2..030b25bf54d 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -485,6 +485,16 @@ export const storage = { ], } +export const storage2 = { + icon: 'reference-cli', + title: 'Supabase CLI', + url: '/reference/cli/overview', + items: [ + { name: 'Commands', url: '/reference/cli/introduction', items: [] }, + { name: 'Config', url: '/reference/cli/config', items: [] }, + ], +} + export const platform = { icon: 'platform', label: 'Platform', diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx index 65d0ec61e07..afa51d3f706 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx @@ -125,6 +125,9 @@ const NavigationMenu = () => { case url.includes(`/docs/reference/python`) && url: menuState.setMenuLevelId('reference_python_v2') break + case url.includes(`/docs/reference/cli/overview`) && url: + menuState.setMenuLevelId('storage2') + break case url.includes(`/docs/reference/cli`) && url: menuState.setMenuLevelId('reference_cli') break @@ -164,6 +167,7 @@ const NavigationMenu = () => { const isFunctionsActive = 'functions' === level const isRealtimeActive = 'realtime' === level const isStorageActive = 'storage' === level + const isStorage2Active = 'storage2' === level const isPlatformActive = 'platform' === level const isResourcesActive = 'resources' === level const isSelfHosting = 'self_hosting' === level @@ -191,6 +195,7 @@ const NavigationMenu = () => { + diff --git a/apps/docs/layouts/SiteLayout.tsx b/apps/docs/layouts/SiteLayout.tsx index d0eec9c2fbf..17a4921cd5b 100644 --- a/apps/docs/layouts/SiteLayout.tsx +++ b/apps/docs/layouts/SiteLayout.tsx @@ -39,6 +39,10 @@ const levelsData = { icon: '/docs/img/icons/menu/storage', name: 'Storage', }, + storage2: { + icon: '/docs/img/icons/menu/reference-cli', + name: 'Supabase CLI', + }, platform: { icon: '/docs/img/icons/menu/platform', name: 'Platform', From 7a057df8b5b94d0070a423a2194bc5cacf978305 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Sat, 21 Jan 2023 15:07:34 -0330 Subject: [PATCH 10/69] Add overview page --- .../NavigationMenu.constants.ts | 2 +- .../NavigationMenu/NavigationMenu.tsx | 9 +- apps/docs/layouts/SiteLayout.tsx | 2 +- apps/docs/pages/reference/cli/overview.mdx | 92 +++++++++++++++++++ 4 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 apps/docs/pages/reference/cli/overview.mdx diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 030b25bf54d..23b8bb50927 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -485,7 +485,7 @@ export const storage = { ], } -export const storage2 = { +export const reference_cli_overview = { icon: 'reference-cli', title: 'Supabase CLI', url: '/reference/cli/overview', diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx index afa51d3f706..9bd0100b39f 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx @@ -126,7 +126,7 @@ const NavigationMenu = () => { menuState.setMenuLevelId('reference_python_v2') break case url.includes(`/docs/reference/cli/overview`) && url: - menuState.setMenuLevelId('storage2') + menuState.setMenuLevelId('reference_cli_overview') break case url.includes(`/docs/reference/cli`) && url: menuState.setMenuLevelId('reference_cli') @@ -167,7 +167,7 @@ const NavigationMenu = () => { const isFunctionsActive = 'functions' === level const isRealtimeActive = 'realtime' === level const isStorageActive = 'storage' === level - const isStorage2Active = 'storage2' === level + const isreference_cli_overviewActive = 'reference_cli_overview' === level const isPlatformActive = 'platform' === level const isResourcesActive = 'resources' === level const isSelfHosting = 'self_hosting' === level @@ -195,7 +195,10 @@ const NavigationMenu = () => { - + diff --git a/apps/docs/layouts/SiteLayout.tsx b/apps/docs/layouts/SiteLayout.tsx index 17a4921cd5b..0f417e94eca 100644 --- a/apps/docs/layouts/SiteLayout.tsx +++ b/apps/docs/layouts/SiteLayout.tsx @@ -39,7 +39,7 @@ const levelsData = { icon: '/docs/img/icons/menu/storage', name: 'Storage', }, - storage2: { + reference_cli_overview: { icon: '/docs/img/icons/menu/reference-cli', name: 'Supabase CLI', }, diff --git a/apps/docs/pages/reference/cli/overview.mdx b/apps/docs/pages/reference/cli/overview.mdx new file mode 100644 index 00000000000..f069cca5ed7 --- /dev/null +++ b/apps/docs/pages/reference/cli/overview.mdx @@ -0,0 +1,92 @@ +import Layout from '~/layouts/DefaultLayout' +import Link from 'next/link' +import { GlassPanel, IconPanel, Button, IconChevronRight } from 'ui' + +export const meta = { + title: 'Supabase CLI', + description: + 'The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.', +} + +

+ The Supabase CLI provides tools to develop your project locally and deploy to the Supabase + Platform. +

+ +{/* start container */} + +
+ +
+ +
+ {apis.map((product) => { + return ( + + + + {product.description} + + + + ) + })} + +
+
+ +{/* end of container */} + +
+ +
+ ### Video: Announcing the Supabase CLI +
+ +
+
+ +
+ ### Learn more about the CLI + - [Install the Supabase CLI](/docs/guides/cli) + - [Browse the source code](https://github.com/supabase/cli) + - [Known bugs and issues on Github](https://github.com/supabase/cli/issues) + +
+ +
+ +
+ +export const apis = [ + { + title: 'Supabase CLI commands', + icon: '/docs/img/icons/menu/reference-api', + hasLightIcon: true, + href: 'reference/cli/introduction', + description: + 'Use the CLI to develop your project locally, manage database migrations, and deploy to the Supabase Platform or self-host.', + span: 'col-span-12 md:col-span-6', + }, + { + title: 'Supabase CLI configuration', + icon: '/docs/img/icons/menu/reference-api', + hasLightIcon: true, + href: 'reference/cli/introduction', + description: 'Learn what options are available to you for using the Supabase CLI locally.', + span: 'col-span-12 md:col-span-6', + }, +] + +export const Page = ({ children }) => + +export default Page From e83c3bff83ee73c587c014248a8bcdb08ac111d1 Mon Sep 17 00:00:00 2001 From: Ollie Halliday <22655069+Hallidayo@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:54:18 +0000 Subject: [PATCH 11/69] renamed paramter to event --- studio/components/grid/components/editor/SelectEditor.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/studio/components/grid/components/editor/SelectEditor.tsx b/studio/components/grid/components/editor/SelectEditor.tsx index 6a0410470d2..ce9ed3e32d0 100644 --- a/studio/components/grid/components/editor/SelectEditor.tsx +++ b/studio/components/grid/components/editor/SelectEditor.tsx @@ -19,11 +19,11 @@ export function SelectEditor({ const value = row[column.key as keyof TRow] as unknown as string - function onChange(value: any) { - if (!value || value == '') { + function onChange(event: any) { + if (!event || event == '') { onRowChange({ ...row, [column.key]: null }, true) } else { - onRowChange({ ...row, [column.key]: value.target.value }, true) + onRowChange({ ...row, [column.key]: event.target.value }, true) } } From 7e342941d0ec014378c7de64852d114ad555a4d2 Mon Sep 17 00:00:00 2001 From: Ollie Halliday <22655069+Hallidayo@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:59:18 +0000 Subject: [PATCH 12/69] issue when changing to NULL fixed --- studio/components/grid/components/editor/SelectEditor.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/studio/components/grid/components/editor/SelectEditor.tsx b/studio/components/grid/components/editor/SelectEditor.tsx index ce9ed3e32d0..d23964f978f 100644 --- a/studio/components/grid/components/editor/SelectEditor.tsx +++ b/studio/components/grid/components/editor/SelectEditor.tsx @@ -20,7 +20,8 @@ export function SelectEditor({ const value = row[column.key as keyof TRow] as unknown as string function onChange(event: any) { - if (!event || event == '') { + debugger + if (!event.target.vaue || event.target.value == '') { onRowChange({ ...row, [column.key]: null }, true) } else { onRowChange({ ...row, [column.key]: event.target.value }, true) From 08b813e8bbb9db3e5bd6e546c3d63649f22e5c0b Mon Sep 17 00:00:00 2001 From: dannykng Date: Mon, 23 Jan 2023 18:27:21 -0800 Subject: [PATCH 13/69] Move CLI guides --- apps/docs/pages/guides/resources.mdx | 14 - apps/docs/pages/guides/supabase-cli.mdx | 120 +++++ .../guides/supabase-cli/local-development.mdx | 267 +++++++++++ .../supabase-cli/managing-environments.mdx | 415 ++++++++++++++++++ 4 files changed, 802 insertions(+), 14 deletions(-) create mode 100644 apps/docs/pages/guides/supabase-cli.mdx create mode 100644 apps/docs/pages/guides/supabase-cli/local-development.mdx create mode 100644 apps/docs/pages/guides/supabase-cli/managing-environments.mdx diff --git a/apps/docs/pages/guides/resources.mdx b/apps/docs/pages/guides/resources.mdx index b1b139020d3..0b2d856b541 100644 --- a/apps/docs/pages/guides/resources.mdx +++ b/apps/docs/pages/guides/resources.mdx @@ -64,20 +64,6 @@ export const meta = {
-
- -
- - ### Supabase CLI - - Develop your project locally, manage your Supabase projects, handle database migrations, CI/CD workflows, and generate types from your database schema, all from the comfort of your Terminal. - -[Learn more](/docs/guides/resources/supabase-cli) - -
- -
- {/* end of container */}
diff --git a/apps/docs/pages/guides/supabase-cli.mdx b/apps/docs/pages/guides/supabase-cli.mdx new file mode 100644 index 00000000000..fcd25f8a582 --- /dev/null +++ b/apps/docs/pages/guides/supabase-cli.mdx @@ -0,0 +1,120 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + title: 'Supabase CLI', + description: + 'The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.', +} + +The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform. +You can also use the CLI to manage your Supabase projects, handle database migrations and CI/CD workflows, and generate types directly from your database schema. + +## Installation + + + + +Install the CLI as dev dependency via [npm](https://www.npmjs.com/package/supabase): + +```sh +npm install supabase --save-dev +``` + + + + +Install the CLI with [Homebrew](https://brew.sh): + +```sh +brew install supabase/tap/supabase +``` + + + + +Install the CLI with [Scoop](https://scoop.sh): + +```powershell +scoop bucket add supabase https://github.com/supabase/scoop-bucket.git +scoop install supabase +``` + + + + +The CLI is available through [Homebrew](https://brew.sh) and Linux packages. + +#### Homebrew + +```sh +brew install supabase/tap/supabase +``` + +#### Linux packages + +Linux packages are provided in [Releases](https://github.com/supabase/cli/releases). +To install, download the `.apk`/`.deb`/`.rpm` file depending on your package manager +and run one of the following: + +- `sudo apk add --allow-untrusted <...>.apk` +- `sudo dpkg -i <...>.deb` +- `sudo rpm -i <...>.rpm` + + + + +## Updates + +When a new [version](https://github.com/supabase/cli/releases) is released, you can update the CLI using the same methods. + + + + +```sh +npm update supabase --save-dev +``` + + + + +```sh +brew upgrade supabase +``` + + + + +```powershell +scoop update supabase +``` + + + + +```sh +brew upgrade supabase +``` + + + + +## See also + +- [Supabase CLI Reference](/docs/reference/cli/introduction) +- [Supabase CLI Configuration](/docs/reference/cli/config) +- [Local Development](/docs/guides/supabase-cli/local-development) +- [Managing Environments](/docs/guides/supabase-cli/managing-environments) + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/supabase-cli/local-development.mdx b/apps/docs/pages/guides/supabase-cli/local-development.mdx new file mode 100644 index 00000000000..b0f45364b52 --- /dev/null +++ b/apps/docs/pages/guides/supabase-cli/local-development.mdx @@ -0,0 +1,267 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'local-development', + title: 'Local Development', + description: 'How to use Supabase on your local development machine.', +} + +Learn how to use the Supabase CLI to develop your project locally and deploy to the Supabase Platform. + +
+ +
+ +## Prerequisites + +Make sure you have these installed on your local machine: + +- [Docker](https://docs.docker.com/engine/install/) +- [Git](https://github.com/git-guides/install-git) +- [Supabase CLI](/docs/guides/cli) + +## Log in to the Supabase CLI + +```bash +supabase login +``` + + + +If you installed the Supabase CLI via NPM you may have to use `npx supabase login`. + + + + +## Initialize your project + +Create a new folder for your project and start a new git repository: + +```bash +# create your project folder +mkdir your-project + +# move into the new folder +cd your-project + +# start a new git repository +git init +``` + +## Start Supabase services + +[Initialize](/docs/reference/cli/usage#supabase-init) Supabase to set up the configuration for developing your project locally: + +```bash +supabase init +``` + +Make sure Docker is running. The [start](/docs/reference/cli/usage#supabase-start) command uses Docker to start the Supabase [services](/docs/guides/getting-started/architecture). +This command may take a while to run if this is the first time using the CLI. + +```bash +supabase start +``` + +Once all of the Supabase services are running, you'll see output containing your local Supabase credentials. +You can use the [stop](/docs/reference/cli/usage#supabase-stop) command at any time to stop all services. + +## Access services + +You can access services directly with any Postgres client or through the API Gateway ([Kong](https://github.com/Kong/kong)). + + + + +```sh +# Default URL: +postgresql://postgres:postgres@localhost:54322/postgres +``` + +The local Postgres instance can be accessed through [`psql`](https://www.postgresql.org/docs/current/app-psql.html) +or any other Postgres client, such as [pgadmin](https://www.pgadmin.org/). + +For example: + +```bash +psql 'postgresql://postgres:postgres@localhost:54322/postgres' +``` + + + +To access the database from an edge function in your local Supabase setup, replace `localhost` with `host.docker.internal`. + + + + + + +```sh +# Default URL: +http://localhost:54321 +``` + +If you are accessing these services without the client libraries, you may need to pass the client keys as an `Authorization` header. +Learn more about [JWT headers](/docs/learn/auth-deep-dive/auth-deep-dive-jwts). + +```sh +curl 'http://localhost:54321/rest/v1/' \ + -H "apikey: " \ + -H "Authorization: Bearer " + +http://localhost:54321/rest/v1/ # REST (PostgREST) +http://localhost:54321/realtime/v1/ # Realtime +http://localhost:54321/storage/v1/ # Storage +http://localhost:54321/auth/v1/ # Auth (GoTrue) +``` + + + +`` is provided when you run the command `supabase start`. + + + + + + +## Database migrations + +Database changes are managed through "migrations." Database migrations are a common way of tracking changes to your database over time. + +
+ +
+ +### Make database changes + +For this guide, create a table called `employees`. In Supabase Studio, navigate to the **SQL Editor** page and run the following SQL command: + +```sql +create table employees ( + id integer primary key generated always as identity, + name text +); +``` + + + +You can execute any SQL using the `DB URL` shown by [`supabase status`](/docs/reference/cli/usage#supabase-status). + + + +Run the [`db diff`](/docs/reference/cli/usage#supabase-db-diff) command to detect changes in the local database: + +```sh +supabase db diff create_employees -f create_employees +``` + +This creates a new migration named `supabase/migrations/_create_employees.sql`, representing any changes made to the local database since [`supabase start`](/docs/reference/cli/usage#supabase-start). + +### Add sample data + +Use the seed script in `supabase/seed.sql` (created with [`supabase init`](/docs/reference/cli/usage#supabase-init)) to add sample data to the table. + +```sql +-- in supabase/seed.sql +insert into public.employees (name) +values + ('Erlich Bachman'), + ('Richard Hendricks'), + ('Monica Hall'); +``` + +Rerun the migration and seed scripts: + +```bash +supabase db reset +``` + +You should now see the contents of `employees` in Studio. + +### Reset database changes + +Use the [`reset`](/docs/reference/cli/usage#supabase-db-reset) command to revert any changes to the local database. + +```sql +-- run on local database to make a change +alter table employees + add department text default 'Hooli'; +``` + +Run the following command to reset the local database: + +```sh +supabase db reset +``` + +## Deploy your project + +Go to the [Supabase Dashboard](https://app.supabase.com) and create a project to deploy the changes. + +### Link your project + + + +There are a few commands required to link your project. We are in the process of consolidating these commands into a single command. Bear with us! + + + +Associate your project with your remote project using [`supabase link`](/docs/reference/cli/usage#supabase-link). + +```bash +supabase link --project-ref +# You can get from your project’s dashboard URL: https://app.supabase.com/project/ + +supabase db remote commit +# Capture any changes that you have made to your database before setting up the CLI +``` + +`supabase/migrations` is now populated with a migration in `..._remote_commit.sql`. +This migration captures any changes required for your local database to match the schema of your remote Supabase project. + +### Deploy database changes + +Deploy any local database migrations using [`db push`](/docs/reference/cli/usage#supabase-db-push): + +```sh +supabase db push +``` + +### Deploy Edge Functions + +Deploy any Edge Functions using [`functions deploy`](/docs/reference/cli/usage#supabase-functions-deploy): + +```sh +supabase functions deploy +``` + +## Limitations + +The local development environment is not as feature-complete as the Supabase Platform. Here are some of the differences: + +- The Functions interface is coming soon. +- Logs are not supported through the interface (however you can access them through the Docker containers). +- You cannot update your project settings in the Dashboard—this must be done using the CLI. + +``` + +``` + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/supabase-cli/managing-environments.mdx b/apps/docs/pages/guides/supabase-cli/managing-environments.mdx new file mode 100644 index 00000000000..4f93da230a5 --- /dev/null +++ b/apps/docs/pages/guides/supabase-cli/managing-environments.mdx @@ -0,0 +1,415 @@ +import Layout from '~/layouts/DefaultGuideLayout' + +export const meta = { + id: 'managing-environments', + title: 'Managing Environments', + description: 'How to deploy Supabase schema changes with a CI / CD pipeline.', +} + +## Overview + +The Supabase CLI provides the tools you need to manage multiple environments. +This guide shows you how to set up your local Supabase development environment that integrates with GitHub Actions to automatically +test and release schema changes to staging and production Supabase projects. + +To get started: + +- [Install the Supabase CLI](/docs/guides/cli) +- Create a [Supabase project](https://app.supabase.com) or use an existing one +- Initialize a local Git repository + +
+ +
+ +## Set up a local environment + +The first step is to set up your local repository with the Supabase CLI: + +```bash +supabase init +``` + +You should see a new `supabase` directory. Then you need to link your local repository with your Supabase project: + +```bash +supabase login +supabase link --project-ref $PROJECT_ID +``` + +You can get your `$PROJECT_ID` from your project's dashboard URL: + +``` +https://app.supabase.com/project/ +``` + +If you're using an existing Supabase project, you might have made schema changes through the Dashboard. +Run the following command to pull these changes before making local schema changes from the CLI: + +```sql +supabase db remote commit +``` + +This command creates a new migration in `supabase/migrations/_remote_commit.sql` which reflects the schema changes you have made previously. + +Now commit your local changes to Git and run the local development setup: + +```bash +git add . +git commit -m "init supabase" +supabase start +``` + +You are now ready to develop schema changes locally and create your first migration. + +## Create a new migration + +There are two ways to make schema changes: + +1. Manual migration: Write DDL statements manually into a migration file +1. Auto schema diff: Make changes through Studio UI and auto generate a schema diff + +### Manual migration + +Create a new migration script by running: + +```bash +supabase migration new new_employee +``` + +You should see a new file created: `supabase/migrations/_new_employee.sql`. You can then write SQL statements in this script using a text editor: + +```sql +create table public.employees ( + id integer primary key generated always as identity, + name text +); +``` + +Apply the new migration to your local database: + +```bash +supabase db reset +``` + +This command recreates your local database from scratch and applies all migration scripts under `supabase/migrations` directory. Now your local database is up to date. + + + +The new migration command also supports stdin as input. +This allows you to pipe in an existing script from another file or stdout: + +`supabase migration new new_employee < create_employees_table.sql` + + + +### Auto schema diff + +Unlike manual migrations, auto schema diff creates a new migration script from changes **already** applied to your local database. + +Create an `employees` table under the `public` schema using Studio UI, accessible at [localhost:54323](http://localhost:54323/) by default. + +Next, generate a schema diff by running the following command: + +```bash +supabase db diff -f new_employee +``` + +You should see that a new file `supabase/migrations/_new_employee.sql` is created. Open the file and verify that the generated DDL statements are the same as below. + +```sql +-- This script was generated by the Schema Diff utility in pgAdmin 4 +-- For the circular dependencies, the order in which Schema Diff writes the objects is not very sophisticated +-- and may require manual changes to the script to ensure changes are applied in the correct order. +-- Please report an issue for any failure with the reproduction steps. + +CREATE TABLE IF NOT EXISTS public.employees +( + id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ), + name text COLLATE pg_catalog."default", + CONSTRAINT employees_pkey PRIMARY KEY (id) +) + +TABLESPACE pg_default; + +ALTER TABLE IF EXISTS public.employees + OWNER to postgres; + +GRANT ALL ON TABLE public.employees TO anon; + +GRANT ALL ON TABLE public.employees TO authenticated; + +GRANT ALL ON TABLE public.employees TO postgres; + +GRANT ALL ON TABLE public.employees TO service_role; +``` + +You may notice that the auto-generated migration script is more verbose than the manually written one. +This is because the default schema diff tool does not account for default privileges added by the initial schema. + +Commit the new migration script to git and you are ready to deploy. + + + +Alternatively, you may pass in the `--use-migra` experimental flag to generate a more concise migration using [migra](https://github.com/djrobstep/migra). +Without the `-f` file flag, the output is written to stdout by default. + +`supabase db diff --use-migra` + + + +## Deploy a migration + +In a production environment, we recommend using a CI/CD pipeline to deploy new migrations with GitHub Actions rather than deploying from your local machine. + +![Deploy migration](/docs/img/guides/cli/cicd-github.png) + +This example uses two Supabase projects, one for production and one for staging. + +Prepare your environments by: + +- Creating separate Supabase projects for staging and production +- Pushing your git repository to GitHub and enabling GitHub Actions + + + +You need a _new_ project for staging. A project which has already been modified to reflect the production project's schema can't be used because the CLI would reapply these changes. + + + +### Configure GitHub Actions + +The Supabase CLI requires a few environment variables to run in non-interactive mode. + +- `SUPABASE_ACCESS_TOKEN` is your personal access token +- `SUPABASE_DB_PASSWORD` is your project specific database password + +We recommend adding these as [encrypted secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) to your GitHub Actions runners. + +Create the following files inside the `.github/workflows` directory: + + + + +```yaml title=.github/workflows/ci.yml +name: CI + +on: + pull_request: + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + + - uses: supabase/setup-cli@v1 + + - name: Start Supabase local development setup + run: supabase start + + - name: Verify generated types are up-to-date + run: | + supabase gen types typescript --local > types.ts + if [ "$(git diff --ignore-space-at-eol types.ts | wc -l)" -gt "0" ]; then + echo "Detected uncommitted changes after build. See status below:" + git diff + exit 1 + fi +``` + + + + +```yaml title=.github/workflows/staging.yml +name: Deploy Migrations to Staging + +on: + push: + branches: + - develop + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-22.04 + + env: + SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} + SUPABASE_DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }} + STAGING_PROJECT_ID: abcdefghijklmnopqrst + + steps: + - uses: actions/checkout@v3 + + - uses: supabase/setup-cli@v1 + + - run: | + supabase link --project-ref $STAGING_PROJECT_ID + supabase db push +``` + + + + +```yaml title=.github/workflows/production.yml +name: Deploy Migrations to Production + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-22.04 + + env: + SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }} + SUPABASE_DB_PASSWORD: ${{ secrets.PRODUCTION_DB_PASSWORD }} + PRODUCTION_PROJECT_ID: abcdefghijklmnopqrst + + steps: + - uses: actions/checkout@v3 + + - uses: supabase/setup-cli@v1 + + - run: | + supabase link --project-ref $PRODUCTION_PROJECT_ID + supabase db push +``` + + + + +The full example code is available in the [demo repository](https://github.com/supabase/supabase-action-example). + +Commit these files to git and push to your `main` branch on GitHub. Update these environment variables to match your Supabase projects: + +- `SUPABASE_ACCESS_TOKEN` +- `PRODUCTION_PROJECT_ID` +- `PRODUCTION_DB_PASSWORD` +- `STAGING_PROJECT_ID` +- `STAGING_DB_PASSWORD` + +When configured correctly, your repository will have CI and Release workflows that trigger on new commits pushed to `main` and `develop` branches. + +![Correctly configured repo](/docs/img/guides/cli/ci-main.png) + +### Open a PR with new migration + +Follow the [migration steps](#create-a-new-migration) to create a `supabase/migrations/_new_employee.sql` file. + +Checkout a new branch `feat/employee` from `develop` , commit the migration file, and push to GitHub. + +```bash +git checkout -b feat/employee +git add supabase/migrations/_new_employee.sql +git commit -m "Add employee table" +git push --set-upstream origin feat/employee +``` + +Open a PR from `feat/employee` to the `develop` branch to see that the CI workflow has been triggered. + +Once the test error is resolved, merge this PR and watch the deployment in action. + +### Release to production + +After verifying your staging project has successfully migrated, create another PR from `develop` to `main` and merge it to deploy the migration to the production project. + +The `release` job applies all new migration scripts merged in `supabase/migrations` directory to a linked Supabase project. You can control which project the job links to via `PROJECT_ID` environment variable. + +## Troubleshooting + +### Sync production project to staging + +When setting up a new staging project, you might need to sync the initial schema with migrations previously applied to the production project. + +One way is to leverage the Release workflow: + +- Create a new branch `develop` and choose `main` as the branch source +- Push the `develop` branch to GitHub + +The GitHub Actions runner will deploy your existing migrations to the staging project. + +Alternatively, you can also apply migrations through your local CLI to a linked remote database. + +```sql +supabase db push +``` + +Once pushed, check that the migration version is up to date for both local and remote databases. + +```sql +supabase migration list +``` + +### Permission denied on db remote commit + +If you have been using Supabase hosted projects for a long time, you might encounter the following permission error when executing `db remote commit`. + +```bash +Error: Error running pg_dump on remote database: pg_dump: error: query failed: ERROR: permission denied for table _type + +pg_dump: error: query was: LOCK TABLE "graphql"."_type" IN ACCESS SHARE MODE +``` + +To resolve this error, you need to grant `postgres` role permissions to `graphql` schema. You can do that by running the following query from Supabase dashboard's SQL Editor. + +```sql +grant all on all tables in schema graphql to postgres, anon, authenticated, service_role; +grant all on all functions in schema graphql to postgres, anon, authenticated, service_role; +grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role; +``` + +### Permission denied on db push + +If you created a table through Supabase dashboard, and your new migration script contains `ALTER TABLE` statements, you might run into permission error when applying them on staging or production databases. + +```bash +ERROR: must be owner of table employees (SQLSTATE 42501); while executing migration +``` + +This is because tables created through Supabase dashboard are owned by `supabase_admin` role while the migration scripts executed through CLI are under `postgres` role. + +One way to solve this is to reassign the owner of those tables to `postgres` role. For example, if your table is named `users` in the public schema, you can run the following command to reassign owner. + +```sql +ALTER TABLE users OWNER TO postgres; +``` + +Apart from tables, you also need to reassign owner of other entities using their respective commands, including [types](https://www.postgresql.org/docs/current/sql-alterschema.html), [functions](https://www.postgresql.org/docs/current/sql-alterroutine.html), and [schemas](https://www.postgresql.org/docs/current/sql-altertype.html). + +### Rebasing new migrations + +Sometimes your teammate may merge a new migration file to git main branch, and now you need to rebase your local schema changes on top. + +We can handle this scenario gracefully by renaming your old migration file with a new timestamp. + +```bash +git pull +supabase migration new dev_A +# Assume the new file is: supabase/migrations/_dev_A.sql +mv