mirror of
https://github.com/supabase/supabase.git
synced 2026-10-18 23:59:08 +03:00
Pull master and resolve conflicts
This commit is contained in:
commit
473b15ae2c
21 files changed
+117
-99
No files matched your search
+4
-1
@@ -1,7 +1,10 @@
|
||||
# this is a public env file
|
||||
|
||||
# do not use secrets in this file
|
||||
|
||||
# Replace this URL with the URL of your blog app
|
||||
|
||||
NEXT_PUBLIC_URL="https://localhost:3000"
|
||||
NEXT_PUBLIC_DOCS_URL="http://localhost:3005"
|
||||
NEXT_PUBLIC_STUDIO_URL="https://localhost:8082"
|
||||
NEXT_PUBLIC_STUDIO_URL="https://localhost:8082"
|
||||
NEXT_PUBLIC_LAUNCHWEEKSITE_URL="https://localhost:3008"
|
||||
@@ -60,13 +60,15 @@ This is especially true for our Enterprise customers, but also Jamstack develope
|
||||
|
||||
To meet these goals, we're releasing Supabase Functions in stages:
|
||||
|
||||
- _Stage 1:_ Give developers the ability to trigger external HTTP functions - today, using Function Hooks.
|
||||
- _Stage 1:_ Give developers the ability to trigger external HTTP functions - today, using Database Webhooks.
|
||||
- _Stage 2:_ Give developers the ability to trigger their own Serverless functions on AWS and GCP - Q4 2021.
|
||||
- _Stage 3:_ Release our own Serverless Functions (Supabase Functions) - Q4 for Early Preview customers.
|
||||
|
||||

|
||||
|
||||
## Function Hooks (Alpha)
|
||||
## Database Webhooks (Alpha)
|
||||
|
||||
(Note: Database Webhooks were previously called "Function Hooks")
|
||||
|
||||
Today we're releasing Functions Hooks in `ALPHA`. The `ALPHA` tag means that it is NOT stable, but it's available for testing and feedback. The API will change, so do not use it for anything critical. You have been warned.
|
||||
|
||||
@@ -76,7 +78,7 @@ Postgres already has the concept of [Triggers](https://www.postgresql.org/docs/c
|
||||
|
||||
### Hook Events
|
||||
|
||||
Function Hooks allow you to "listen" to any change in your tables to trigger an asynchronous Function. You can hook into a few different events:`INSERT`, `UPDATE`, and `DELETE`. All events are fired **after** a database row is changed. Keen eyes will be able to spot the similarity to Postgres triggers, and that's because Function Hooks are just a convenience wrapper around triggers.
|
||||
Database Webhooks allow you to "listen" to any change in your tables to trigger an asynchronous Function. You can hook into a few different events:`INSERT`, `UPDATE`, and `DELETE`. All events are fired **after** a database row is changed. Keen eyes will be able to spot the similarity to Postgres triggers, and that's because Database Webhooks are just a convenience wrapper around triggers.
|
||||
|
||||

|
||||
|
||||
@@ -88,7 +90,7 @@ Supabase will support several different targets.
|
||||
- AWS Lambda/Google Cloud Run: Provide Supabase with a restricted IAM role to trigger Serverless functions natively.
|
||||
- Supabase Functions: We'll develop an end-to-end experience.
|
||||
|
||||

|
||||

|
||||
|
||||
### Hook Payload
|
||||
|
||||
@@ -120,14 +122,14 @@ type DeletePayload = {
|
||||
|
||||
## Hooks technical design: `pg_net v0.1`
|
||||
|
||||
As with most of the Supabase platform, we leverage PostgreSQL's native functionality to implement Function Hooks.
|
||||
As with most of the Supabase platform, we leverage PostgreSQL's native functionality to implement Database Webhooks (previously called "Function Hooks").
|
||||
|
||||
To build hooks, we've released a new PostgreSQL Extension, [pg_net](https://github.com/supabase/pg_net/), an asynchronous networking extension with an emphasis on scalability/throughput. In its initial (unstable) release we expose:
|
||||
|
||||
- asynchronous HTTP `GET` requests.
|
||||
- asynchronous HTTP `POST` requests with a JSON payload.
|
||||
|
||||
The extension is (currently) capable of >300 requests per second and is the networking layer underpinning Function Hooks. For a complete view of capabilities, check out [the docs](https://supabase.github.io/pg_net/api/).
|
||||
The extension is (currently) capable of >300 requests per second and is the networking layer underpinning Database Webhooks. For a complete view of capabilities, check out [the docs](https://supabase.github.io/pg_net/api/).
|
||||
|
||||
### **Usage**
|
||||
|
||||
@@ -244,7 +246,7 @@ This is only the beginning! First we'll thoroughly test it and make a stable rel
|
||||
|
||||
## Get started today
|
||||
|
||||
Function Hooks is enabled today on all [new projects](https://app.supabase.com). Find it under Database > Alpha Preview > Function Hooks.
|
||||
Database Webhooks is enabled today on all [new projects](https://app.supabase.com). Find it under Database > Alpha Preview > Database Webhooks.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ If you want to keep up to date, make sure you [subscribe to our YouTube channel]
|
||||
- Allow a function with single unnamed parameter to be called with POST<br />
|
||||
[https://github.com/PostgREST/postgrest/issues/1735](https://github.com/PostgREST/postgrest/issues/1735)
|
||||
|
||||
### pg_net (Function Hooks)
|
||||
### pg_net (Database Webhooks)
|
||||
|
||||
- Better handling of URL errors<br />
|
||||
[https://github.com/supabase/pg_net/issues/39](https://github.com/supabase/pg_net/issues/39)
|
||||
|
||||
@@ -227,7 +227,7 @@ existing functionality.
|
||||
|
||||
- **Row Level Security:** restrict user access to data and files using Postgres Policies.
|
||||
- **Realtime data streams:** subscribe to database changes using the logical replication stream.
|
||||
- **Function Hooks:** trigger external systems using Postgres triggers and our [async request extension](https://github.com/supabase/pg_net/).
|
||||
- **Database Webhooks (previously called "Function Hooks"):** trigger external systems using Postgres triggers and our [async request extension](https://github.com/supabase/pg_net/).
|
||||
- **RESTful APIs:** query your database [tables](/docs/reference/javascript/select) and [functions](/docs/reference/javascript/rpc) over HTTP, using [PostgREST](https://postgrest.org).
|
||||
|
||||
### Phase 3: Cloud-native PostgreSQL
|
||||
|
||||
@@ -102,9 +102,9 @@ Check out the new [Remix Auth example](https://github.com/supabase/supabase/tree
|
||||
Our React Native example has been correctly updated to be an Expo example.
|
||||
[Check it out here](https://github.com/supabase/supabase/tree/master/examples/todo-list/expo-todo-list).
|
||||
|
||||
## Video: API requests with Function Hooks
|
||||
## Video: API requests with Database Webhooks
|
||||
|
||||
There's no stopping [Jon Meyers](https://jonmeyers.io/videos)! He’s back with an in-depth video on how to easily [automate API requests](https://www.youtube.com/watch?v=codAs9-NeHM&feature=emb_title) using our very own Function Hooks.
|
||||
There's no stopping [Jon Meyers](https://jonmeyers.io/videos)! He’s back with an in-depth video on how to easily [automate API requests](https://www.youtube.com/watch?v=codAs9-NeHM&feature=emb_title) using our very own Database Webhooks.
|
||||
|
||||
You'll learn how to listen to _any_ database change, then send those changes [in a payload](https://supabase.com/blog/2021/07/30/supabase-functions-updates#hook-payload) via HTTP request.
|
||||
|
||||
|
||||
@@ -58,6 +58,14 @@ module.exports = withMDX({
|
||||
source: '/docs/:path*',
|
||||
destination: `${process.env.NEXT_PUBLIC_DOCS_URL}/:path*`,
|
||||
},
|
||||
{
|
||||
source: '/launch-week',
|
||||
destination: `${process.env.NEXT_PUBLIC_LAUNCHWEEKSITE_URL}`,
|
||||
},
|
||||
{
|
||||
source: '/launch-week/:path*',
|
||||
destination: `${process.env.NEXT_PUBLIC_LAUNCHWEEKSITE_URL}/:path*`,
|
||||
},
|
||||
// misc rewrites
|
||||
{
|
||||
source: '/humans.txt',
|
||||
@@ -685,6 +693,21 @@ module.exports = withMDX({
|
||||
source: '/docs/reference/javascript/supabase-client',
|
||||
destination: '/docs/reference',
|
||||
},
|
||||
{
|
||||
permanent: true,
|
||||
source: '/join',
|
||||
destination: 'https://supabase.com/',
|
||||
},
|
||||
{
|
||||
permanent: true,
|
||||
source: '/blog/2022/06/15/blog/2022/06/29/visualizing-supabase-data-using-metabase',
|
||||
destination: '/blog/2022/06/29/visualizing-supabase-data-using-metabase',
|
||||
},
|
||||
{
|
||||
permanent: true,
|
||||
source: '/_app',
|
||||
destination: 'https://app.supabase.com',
|
||||
},
|
||||
]
|
||||
},
|
||||
})
|
||||
@@ -36,7 +36,7 @@ function TagBlogsPage(props: Props) {
|
||||
<NextSeo title={`Blog | ${tag}`} description="Latest news from the Supabase team." />
|
||||
<DefaultLayout>
|
||||
<div className="container mx-auto px-8 py-16 sm:px-16 xl:px-20">
|
||||
<div className="flex space-x-1">
|
||||
<div className="flex space-x-1 text-scale-1000">
|
||||
<p className="cursor-pointer">
|
||||
<Link href="/blog">Blog</Link>
|
||||
</p>
|
||||
|
||||
@@ -24,7 +24,7 @@ export async function getStaticProps() {
|
||||
props: {
|
||||
partners,
|
||||
},
|
||||
// TODO: consider using Next.js' On-demand Revalidation with Supabase function hooks instead
|
||||
// TODO: consider using Next.js' On-demand Revalidation with Supabase Database Webhooks instead
|
||||
revalidate: 18000, // In seconds - refresh every 5 hours
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ services:
|
||||
|
||||
auth:
|
||||
container_name: supabase-auth
|
||||
image: supabase/gotrue:v2.7.1
|
||||
image: supabase/gotrue:v2.10.0
|
||||
depends_on:
|
||||
- db # Disable this if you are using an external Postgres database
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -39,7 +39,7 @@ The `anon` key is your client-side API key. It allows "anonymous access" to your
|
||||
|
||||
### 4. Deploy the Next.js client
|
||||
|
||||
[](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fsupabase%2Fsupabase%2Ftree%2Fmaster%2Fexamples%2slack-clone%2Fnextjs-slack-clone&env=NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_KEY&envDescription=Find%20the%20Supabase%20URL%20and%20key%20in%20the%20your%20auto-generated%20docs%20at%20app.supabase.com&project-name=supabase-slack-clone&repo-name=supabase-slack-clone)
|
||||
[](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fsupabase%2Fsupabase%2Ftree%2Fmaster%2Fexamples%2Fslack-clone%2Fnextjs-slack-clone&env=NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_KEY&envDescription=Find%20the%20Supabase%20URL%20and%20key%20in%20the%20your%20auto-generated%20docs%20at%20app.supabase.com&project-name=supabase-slack-clone&repo-name=supabase-slack-clone)
|
||||
|
||||
Here, we recommend forking this repo so you can deploy through Vercel by clicking the button above. When you click the button, replace the repo URL with your fork's URL.
|
||||
|
||||
|
||||
@@ -28,10 +28,6 @@ const Pagination: FC<PaginationProps> = () => {
|
||||
const maxPages = Math.ceil(state.totalRows / state.rowsPerPage)
|
||||
const totalPages = state.totalRows > 0 ? maxPages : 1
|
||||
|
||||
useEffect(() => {
|
||||
if (state.page != page) setPage(state.page)
|
||||
}, [state.page, page])
|
||||
|
||||
// [Joshen] Oddly without this, state.selectedRows will be stale
|
||||
useEffect(() => {}, [state.selectedRows])
|
||||
|
||||
@@ -93,7 +89,7 @@ const Pagination: FC<PaginationProps> = () => {
|
||||
|
||||
function onPageChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
const value = event.target.value
|
||||
const pageNum = Number(value)
|
||||
const pageNum = Number(value) > maxPages ? maxPages : Number(value)
|
||||
setPage(pageNum)
|
||||
updatePageDebounced(pageNum, dispatch)
|
||||
}
|
||||
@@ -120,7 +116,6 @@ const Pagination: FC<PaginationProps> = () => {
|
||||
<InputNumber
|
||||
value={page}
|
||||
onChange={onPageChange}
|
||||
className="sb-grid-pagination-input"
|
||||
size="tiny"
|
||||
style={{
|
||||
width: '3rem',
|
||||
|
||||
@@ -306,8 +306,8 @@ const LogTable = ({
|
||||
>
|
||||
<>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="relative border border-scale-600 border-dashed dark:border-scale-400 w-32 h-4 rounded px-2 flex items-center"></div>
|
||||
<div className="relative border border-scale-600 border-dashed dark:border-scale-400 w-32 h-4 rounded px-2 flex items-center">
|
||||
<div className="relative border border-scale-600 border-dashed dark:border-scale-900 w-32 h-4 rounded px-2 flex items-center"></div>
|
||||
<div className="relative border border-scale-600 border-dashed dark:border-scale-900 w-32 h-4 rounded px-2 flex items-center">
|
||||
<div className="absolute right-1 -bottom-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@@ -88,7 +88,7 @@ export const generateDatabaseMenu = (project?: Project): ProductMenuGroup[] => {
|
||||
...(showHooksRoute
|
||||
? [
|
||||
{
|
||||
name: 'Function Hooks',
|
||||
name: 'Database Webhooks',
|
||||
key: 'hooks',
|
||||
url: `/project/${ref}/database/hooks`,
|
||||
items: [],
|
||||
|
||||
@@ -18,7 +18,8 @@ export const REGIONS = {
|
||||
// SOUTH_AFRICA: 'South Africa (Cape Town)',
|
||||
}
|
||||
|
||||
export const REGIONS_DEFAULT = REGIONS.EAST_US
|
||||
export const REGIONS_DEFAULT =
|
||||
process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging' ? REGIONS.SOUTHEAST_ASIA : REGIONS.EAST_US
|
||||
|
||||
export const PRICING_TIER_LABELS = {
|
||||
FREE: 'Free',
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Button, Listbox, IconUsers, Input, IconLoader, Alert } from '@supabase/
|
||||
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
|
||||
import { NextPageWithLayout } from 'types'
|
||||
import { passwordStrength } from 'lib/helpers'
|
||||
import { passwordStrength, pluckObjectFields } from 'lib/helpers'
|
||||
import { get, post } from 'lib/common/fetch'
|
||||
import {
|
||||
API_URL,
|
||||
@@ -60,6 +60,7 @@ const Wizard: NextPageWithLayout = () => {
|
||||
const isOrganizationOwner = ui.selectedOrganization?.is_owner
|
||||
const totalFreeProjects = subscriptionStats.total_active_free_projects
|
||||
const freeProjectsLimit = ui.profile?.free_project_limit ?? DEFAULT_FREE_PROJECTS_LIMIT
|
||||
const availableRegions = getAvailableRegions()
|
||||
|
||||
const isAdmin = enablePermissions
|
||||
? checkPermissions(PermissionAction.SQL_INSERT, 'postgres.public.projects')
|
||||
@@ -189,6 +190,13 @@ const Wizard: NextPageWithLayout = () => {
|
||||
delayedCheckPasswordStrength(password)
|
||||
}
|
||||
|
||||
// [Fran] Enforce APSE1 region on staging
|
||||
function getAvailableRegions() {
|
||||
return process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging'
|
||||
? pluckObjectFields(REGIONS, ['SOUTHEAST_ASIA'])
|
||||
: REGIONS
|
||||
}
|
||||
|
||||
return (
|
||||
<Panel
|
||||
hideHeaderStyling
|
||||
@@ -303,8 +311,8 @@ const Wizard: NextPageWithLayout = () => {
|
||||
onChange={(value: string) => onDbRegionChange(value)}
|
||||
descriptionText="Select a region close to you for the best performance."
|
||||
>
|
||||
{Object.keys(REGIONS).map((option: string, i) => {
|
||||
const label = Object.values(REGIONS)[i]
|
||||
{Object.keys(availableRegions).map((option: string, i) => {
|
||||
const label = Object.values(availableRegions)[i] as string
|
||||
return (
|
||||
<Listbox.Option
|
||||
key={option}
|
||||
@@ -313,7 +321,7 @@ const Wizard: NextPageWithLayout = () => {
|
||||
addOnBefore={({ active, selected }: any) => (
|
||||
<img
|
||||
className="w-5 rounded-sm"
|
||||
src={`/img/regions/${Object.keys(REGIONS)[i]}.svg`}
|
||||
src={`/img/regions/${Object.keys(availableRegions)[i]}.svg`}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -171,7 +171,7 @@ const TriggersList: FC<any> = observer(
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<ProductEmptyState
|
||||
title="Database Webhooks"
|
||||
ctaButtonLabel="Create Database Webhook"
|
||||
ctaButtonLabel="Create Webhook"
|
||||
onClickCta={() => createHook()}
|
||||
>
|
||||
<AlphaPreview />
|
||||
|
||||
@@ -473,7 +473,7 @@
|
||||
}
|
||||
|
||||
.sb-grid-column-header__inner__name {
|
||||
@apply text-scale-1200 overflow-hidden overflow-ellipsis text-xs;
|
||||
@apply text-scale-1200 overflow-hidden overflow-ellipsis text-xs select-text;
|
||||
}
|
||||
|
||||
.sb-grid-column-header__inner__format {
|
||||
|
||||
@@ -205,6 +205,10 @@ Controls the minimum amount of time that must pass before sending another signup
|
||||
|
||||
If you do not require email confirmation, you may set this to `true`. Defaults to `false`.
|
||||
|
||||
`MAILER_SECURE_EMAIL_CHANGE_ENABLED` - `bool`
|
||||
|
||||
If `true`, send an email to both the user's current and new email with a confirmation link, otherwise send an email with confirmation link only to new email. Defaults to `true`.
|
||||
|
||||
`MAILER_URLPATHS_INVITE` - `string`
|
||||
|
||||
URL path to use in the user invite email. Defaults to `/`.
|
||||
|
||||
@@ -4,11 +4,9 @@ title: Database
|
||||
description: Use Supabase to manage your data.
|
||||
---
|
||||
|
||||
|
||||
Every Supabase project comes with a full [Postgres](https://www.postgresql.org/) database, a free and open source
|
||||
Every Supabase project comes with a full [Postgres](https://www.postgresql.org/) database, a free and open source
|
||||
database which is considered one of the world's most stable and advanced databases.
|
||||
|
||||
|
||||
## Postgres or PostgreSQL?
|
||||
|
||||
PostgreSQL the database was derived from the POSTGRES Project, a package written at the University of California at Berkeley in 1986.
|
||||
@@ -17,47 +15,41 @@ This package included a query language called "PostQUEL".
|
||||
In 1994, Postgres95 was built on top of POSTGRES code, adding an SQL language interpreter as a replacement for PostQUEL.
|
||||
Eventually, Postgres95 was renamed to PostgreSQL to reflect the SQL query capability.
|
||||
|
||||
After this, many people referred to it as Postgres since it's less prone to confusion. Supabase is all about
|
||||
After this, many people referred to it as Postgres since it's less prone to confusion. Supabase is all about
|
||||
simplicity, so we also refer to it as Postgres.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
### Table View
|
||||
### Table View
|
||||
|
||||
You don't have to be a database expert to start using Supabase. Our table view makes Postgres as easy to use as a spreadsheet.
|
||||
|
||||

|
||||
|
||||
|
||||
### Relationships
|
||||
|
||||
Dig into the relationships within your data.
|
||||
|
||||
Dig into the relationships within your data.
|
||||
|
||||
<video width="99%" loop="" muted="" playsInline="" controls="true">
|
||||
<source src="/docs/videos/relational-drilldown-zoom.mp4" type="video/mp4" />
|
||||
<source src="/docs/videos/relational-drilldown-zoom.mp4" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
|
||||
### Clone tables
|
||||
|
||||
You can duplicate your tables, just like you would inside a spreadsheet.
|
||||
|
||||
<video width="99%" muted playsInline controls={true}>
|
||||
<source src="/docs/videos/duplicate-tables.mp4" type="video/mp4" muted playsInline />
|
||||
<source src="/docs/videos/duplicate-tables.mp4" type="video/mp4" muted playsInline />
|
||||
</video>
|
||||
|
||||
|
||||
### The SQL Editor
|
||||
|
||||
Supabase comes with a SQL Editor. You can also save your favorite queries to run later!
|
||||
Supabase comes with a SQL Editor. You can also save your favorite queries to run later!
|
||||
|
||||
<video width="99%" muted playsInline controls={true}>
|
||||
<source src="/docs/videos/favorites.mp4" type="video/mp4" muted playsInline />
|
||||
<source src="/docs/videos/favorites.mp4" type="video/mp4" muted playsInline />
|
||||
</video>
|
||||
|
||||
|
||||
### Additional features
|
||||
|
||||
- Supabase extends Postgres with realtime functionality using our [Realtime Server](https://github.com/supabase/realtime).
|
||||
@@ -73,34 +65,34 @@ To expand the functionality of your Postgres database, you can use extensions.
|
||||
You can enable Postgres extensions with the click of a button within the Supabase dashboard.
|
||||
|
||||
<video width="99%" muted playsInline controls={true}>
|
||||
<source src="/docs/videos/toggle-extensions.mp4" type="video/mp4" muted playsInline />
|
||||
<source src="/docs/videos/toggle-extensions.mp4" type="video/mp4" muted playsInline />
|
||||
</video>
|
||||
|
||||
[Learn more](/docs/guides/database/extensions) about all the extensions provided on Supabase.
|
||||
|
||||
## Tips
|
||||
|
||||
### Realtime
|
||||
### Realtime
|
||||
|
||||
Supabase provides a realtime engine on top of Postgres, so that you can listen to changes as they happen.
|
||||
Supabase provides a realtime engine on top of Postgres, so that you can listen to changes as they happen.
|
||||
Our realtime engine uses the built-in replication functionality of Postgres.
|
||||
|
||||
Realtime server broadcasts database changes to authorized users depending on your Row Level Security (RLS) policies.
|
||||
We recommend that you enable row level security and set row security policies on tables that you add to the publication.
|
||||
However, you may choose to disable RLS on a table and have changes broadcast to all connected clients.
|
||||
|
||||
You can manage the realtime system, simply by
|
||||
You can manage the realtime system, simply by
|
||||
[updating](/docs/guides/database/replication) the `supabase_realtime` publication.
|
||||
|
||||
For example to enable realtime only for individual tables:
|
||||
|
||||
```sql
|
||||
begin;
|
||||
begin;
|
||||
-- remove the realtime publication
|
||||
drop publication if exists supabase_realtime;
|
||||
drop publication if exists supabase_realtime;
|
||||
|
||||
-- re-create the publication but don't enable it for any tables
|
||||
create publication supabase_realtime;
|
||||
create publication supabase_realtime;
|
||||
commit;
|
||||
|
||||
-- add a table to the publication
|
||||
@@ -110,7 +102,7 @@ alter publication supabase_realtime add table products;
|
||||
alter publication supabase_realtime add table posts;
|
||||
```
|
||||
|
||||
By default only "new" values are sent, but if you want to receive the old record (previous values) whenever you `update` or `delete` a record,
|
||||
By default only "new" values are sent, but if you want to receive the old record (previous values) whenever you `update` or `delete` a record,
|
||||
you can update the replica identity of your tables, setting it to `full`:
|
||||
|
||||
```sql
|
||||
@@ -119,72 +111,61 @@ alter table your_table replica identity full;
|
||||
|
||||
### Migrating between projects
|
||||
|
||||
Migrating projects can be achieved using standard PostgreSQL tooling. This is particularly useful for older projects (e.g. to use a newer Postgres version).
|
||||
Migrating projects can be achieved using standard PostgreSQL tooling. This is particularly useful for older projects (e.g. to use a newer Postgres version).
|
||||
|
||||
#### Before you begin
|
||||
|
||||
- Make sure [Postgres](https://www.postgresql.org/download/) is installed so you can run `psql` and `pg_dump`.
|
||||
- Create a new Supabase project.
|
||||
- If you enabled Function Hooks on your old project, enable it on your new project.
|
||||
- If you enabled Database Webhooks on your old project, enable it on your new project.
|
||||
- Store the old project's database URL as `$OLD_DB_URL` and the new project's as `$NEW_DB_URL`.
|
||||
|
||||
#### Migrate the database
|
||||
|
||||
1. Run `ALTER ROLE postgres SUPERUSER` in the *old* project's SQL editor
|
||||
1. Run `ALTER ROLE postgres SUPERUSER` in the _old_ project's SQL editor
|
||||
2. Run `pg_dump --clean --if-exists --quote-all-identifiers -h $OLD_DB_URL -U postgres > dump.sql` from your terminal
|
||||
3. Run `ALTER ROLE postgres NOSUPERUSER` in the *old* project's SQL editor
|
||||
4. Run `ALTER ROLE postgres SUPERUSER` in the *new* project's SQL editor
|
||||
3. Run `ALTER ROLE postgres NOSUPERUSER` in the _old_ project's SQL editor
|
||||
4. Run `ALTER ROLE postgres SUPERUSER` in the _new_ project's SQL editor
|
||||
5. Run `psql -h $NEW_DB_URL -U postgres -f dump.sql` from your terminal
|
||||
6. Run `TRUNCATE storage.objects` in the *new* project's SQL editor
|
||||
7. Run `ALTER ROLE postgres NOSUPERUSER` in the *new* project's SQL editor
|
||||
6. Run `TRUNCATE storage.objects` in the _new_ project's SQL editor
|
||||
7. Run `ALTER ROLE postgres NOSUPERUSER` in the _new_ project's SQL editor
|
||||
|
||||
#### Migrate storage objects
|
||||
|
||||
This script moves storage objects from one project to another. If you have more than 10k objects, we can move the objects for you. Just contact us at [support@supabase.io](mailto:support@supabase.io).
|
||||
|
||||
```js
|
||||
const { createClient } = require("@supabase/supabase-js");
|
||||
const { createClient } = require('@supabase/supabase-js')
|
||||
|
||||
const OLD_PROJECT_URL = "https://xxx.supabase.co";
|
||||
const OLD_PROJECT_SERVICE_KEY = "old-project-service-key-xxx";
|
||||
const OLD_PROJECT_URL = 'https://xxx.supabase.co'
|
||||
const OLD_PROJECT_SERVICE_KEY = 'old-project-service-key-xxx'
|
||||
|
||||
const NEW_PROJECT_URL = "https://yyy.supabase.co";
|
||||
const NEW_PROJECT_SERVICE_KEY = "new-project-service-key-yyy";
|
||||
const NEW_PROJECT_URL = 'https://yyy.supabase.co'
|
||||
const NEW_PROJECT_SERVICE_KEY = 'new-project-service-key-yyy'
|
||||
|
||||
(async () => {
|
||||
const oldSupabaseRestClient = createClient(
|
||||
OLD_PROJECT_URL,
|
||||
OLD_PROJECT_SERVICE_KEY,
|
||||
{ schema: "storage" }
|
||||
);
|
||||
const oldSupabaseClient = createClient(
|
||||
OLD_PROJECT_URL,
|
||||
OLD_PROJECT_SERVICE_KEY
|
||||
);
|
||||
const newSupabaseClient = createClient(
|
||||
NEW_PROJECT_URL,
|
||||
NEW_PROJECT_SERVICE_KEY
|
||||
);
|
||||
;(async () => {
|
||||
const oldSupabaseRestClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY, {
|
||||
schema: 'storage',
|
||||
})
|
||||
const oldSupabaseClient = createClient(OLD_PROJECT_URL, OLD_PROJECT_SERVICE_KEY)
|
||||
const newSupabaseClient = createClient(NEW_PROJECT_URL, NEW_PROJECT_SERVICE_KEY)
|
||||
|
||||
// make sure you update max_rows in postgrest settings if you have a lot of objects
|
||||
// or paginate here
|
||||
const { data: oldObjects, error } = await oldSupabaseRestClient
|
||||
.from("objects")
|
||||
.select();
|
||||
const { data: oldObjects, error } = await oldSupabaseRestClient.from('objects').select()
|
||||
if (error) {
|
||||
console.log("error getting objects from old bucket");
|
||||
throw error;
|
||||
console.log('error getting objects from old bucket')
|
||||
throw error
|
||||
}
|
||||
|
||||
for (const objectData of oldObjects) {
|
||||
console.log(`moving ${objectData.id}`);
|
||||
console.log(`moving ${objectData.id}`)
|
||||
try {
|
||||
const { data, error: downloadObjectError } =
|
||||
await oldSupabaseClient.storage
|
||||
.from(objectData.bucket_id)
|
||||
.download(objectData.name);
|
||||
const { data, error: downloadObjectError } = await oldSupabaseClient.storage
|
||||
.from(objectData.bucket_id)
|
||||
.download(objectData.name)
|
||||
if (downloadObjectError) {
|
||||
throw downloadObjectError;
|
||||
throw downloadObjectError
|
||||
}
|
||||
|
||||
const { _, error: uploadObjectError } = await newSupabaseClient.storage
|
||||
@@ -193,16 +174,16 @@ const NEW_PROJECT_SERVICE_KEY = "new-project-service-key-yyy";
|
||||
upsert: true,
|
||||
contentType: objectData.metadata.mimetype,
|
||||
cacheControl: objectData.metadata.cacheControl,
|
||||
});
|
||||
})
|
||||
if (uploadObjectError) {
|
||||
throw uploadObjectError;
|
||||
throw uploadObjectError
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("error moving ", objectData);
|
||||
console.log(err);
|
||||
console.log('error moving ', objectData)
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
})();
|
||||
})()
|
||||
```
|
||||
|
||||
#### Caveats
|
||||
@@ -234,4 +215,3 @@ Read more in [Database Configuration](/docs/guides/database/managing-timezones).
|
||||
|
||||
- Read more about [Postgres](/docs/postgres/server/about)
|
||||
- Sign in: [app.supabase.com](https://app.supabase.com)
|
||||
|
||||
@@ -108,6 +108,7 @@ These options control the emails sent from GoTrue.
|
||||
| Parameter | Type | Description |
|
||||
| :-------- | :------- | :------------------------- |
|
||||
| <span id="mailer_autoconfirm">`MAILER_AUTOCONFIRM`</span> | `bool` | If you do not require email confirmation, you may set this to `true`. Defaults to `false`. |
|
||||
| <span id="mailer_secure_email_change_enabled">`MAILER_SECURE_EMAIL_CHANGE_ENABLED`</span> | `bool` | If `true`, send an email to both the user's current and new email with a confirmation link, otherwise send an email with confirmation link only to new email. Defaults to `true`. |
|
||||
| <span id="mailer_otp_exp">`MAILER_OTP_EXP`</span> | `string` | Controls the duration an email link or otp is valid for. Defaults to 24 hrs. |
|
||||
| <span id="mailer_urlpaths_invite">`MAILER_URLPATHS_INVITE`</span> | `string` | URL path to use in the user invite email. Defaults to `/`. |
|
||||
| <span id="mailer_urlpaths_confirmation">`MAILER_URLPATHS_CONFIRMATION`</span> | `string` | URL path to use in the signup confirmation email. Defaults to `/`. |
|
||||
|
||||
@@ -13,6 +13,7 @@ Bo Lu
|
||||
Bobbie Soedirgo
|
||||
Chase Granberry
|
||||
Chris Copplestone
|
||||
Danny Ng
|
||||
Dave Wilson
|
||||
David Thyresson
|
||||
Div Arora
|
||||
|
||||
Reference in new issue
Block a user