diff --git a/apps/docs/content/guides/database/postgres/setup-replication-external.mdx b/apps/docs/content/guides/database/postgres/setup-replication-external.mdx index a29c9156df74b..e802f490e7987 100644 --- a/apps/docs/content/guides/database/postgres/setup-replication-external.mdx +++ b/apps/docs/content/guides/database/postgres/setup-replication-external.mdx @@ -60,3 +60,10 @@ ALTER PUBLICATION example_pub ADD TABLE example_table; ```sql select * from pg_stat_replication; ``` + + + +You can add more tables to the initial publication, but you're going to need to do a REFRESH on the subscribing database. +See https://www.postgresql.org/docs/current/sql-alterpublication.html + + diff --git a/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx b/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx index 08f466b1c77b7..9c91091af8d18 100644 --- a/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx @@ -53,9 +53,8 @@ const DeleteHookModal = ({ selectedHook, visible, onClose }: DeleteHookModalProp confirmString={name || ''} text={ <> - This will delete the webhook - {name} rom the schema - {schema} + This will delete the webhook {name}{' '} + from the schema {schema} } alert={{ title: 'You cannot recover this webhook once deleted.' }} diff --git a/apps/www/pages/careers.tsx b/apps/www/pages/careers.tsx index f7ad937b33144..a9fa84e33d94a 100644 --- a/apps/www/pages/careers.tsx +++ b/apps/www/pages/careers.tsx @@ -1,47 +1,59 @@ -import { GetServerSideProps, NextPage } from 'next' +import { GlobeAltIcon } from '@heroicons/react/outline' +import { Check } from 'lucide-react' +import { GetServerSideProps } from 'next' +import { NextSeo } from 'next-seo' import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/router' -import { NextSeo } from 'next-seo' -import { GlobeAltIcon } from '@heroicons/react/outline' -import { Check } from 'lucide-react' -import { Badge, Button, Separator, buttonVariants, cn } from 'ui' import ReactMarkdown from 'react-markdown' +import { Badge, Button, buttonVariants, cn, Separator } from 'ui' +import { z } from 'zod' import Styles from '~/styles/career.module.css' import Globe from '~/components/Globe' import DefaultLayout from '~/components/Layouts/Default' import SectionContainer from '~/components/Layouts/SectionContainer' -import { groupJobsByTeam, filterGenericJob, JobItemProps, PLACEHOLDER_JOB_ID } from '~/lib/careers' import career from '~/data/career.json' +import { filterGenericJob, groupJobsByTeam, JobItemProps, PLACEHOLDER_JOB_ID } from '~/lib/careers' + +const ContributorSchema = z.object({ + login: z.string(), + avatar_url: z.string(), + html_url: z.string(), +}) + +type Contributor = z.infer export const getServerSideProps: GetServerSideProps = (async ({ res }) => { // refresh every 5 minutes res.setHeader('Cache-Control', 'public, max-age=300, stale-while-revalidate=300') const job_res = await fetch('https://api.ashbyhq.com/posting-api/job-board/supabase') - const job_data = await job_res.json() + const job_data = (await job_res.json()) as { jobs: JobItemProps[] } - const jobs = groupJobsByTeam(job_data.jobs.filter((job: JobItemProps) => !filterGenericJob(job))) + const jobs = groupJobsByTeam(job_data.jobs.filter((job) => !filterGenericJob(job))) const placeholderJob = job_data.jobs.find(filterGenericJob) - const contributor_res = await fetch( + const contributorResponse = await fetch( 'https://api.github.com/repos/supabase/supabase/contributors?per_page=100' ) - const contributor_arr = await contributor_res.json() + let contributorArray: Contributor[] = [] + try { + const contributorResponseData = await contributorResponse.json() + // if the response is not in the expected format, throw an error and return an empty array + contributorArray = ContributorSchema.array().parse(contributorResponseData) + } catch {} - const contributor_data = await contributor_arr.map( - (contributor: { login: string; avatar_url: string; html_url: string }) => { - return { - login: contributor.login, - avatar_url: contributor.avatar_url, - html_url: contributor.html_url, - } + const contributor_data = contributorArray.map((contributor) => { + return { + login: contributor.login, + avatar_url: contributor.avatar_url, + html_url: contributor.html_url, } - ) + }) - const contributors = await contributor_data.filter((contributor: any) => + const contributors = await contributor_data.filter((contributor) => career.contributors.includes(contributor.login) ) @@ -74,11 +86,11 @@ export const getServerSideProps: GetServerSideProps = (async ({ res }) => { interface CareersPageProps { jobs: Record - placeholderJob: JobItemProps + placeholderJob: JobItemProps | null contributors: { login: string; avatar_url: string; html_url: string }[] } -const CareerPage: NextPage = ({ jobs, placeholderJob, contributors }) => { +const CareerPage = ({ jobs, placeholderJob, contributors }: CareersPageProps) => { const { basePath } = useRouter() const meta_title = 'Careers | Supabase' @@ -118,7 +130,7 @@ const CareerPage: NextPage = ({ jobs, placeholderJob, contribu
- {career.company.map((company: { number: string; text: string }, i: number) => { + {career.company.map((company, i) => { return (
= ({ jobs, placeholderJob, contribu our team effective:

- {career.humanPowered.map( - (human: { icon: string; title: string; text: string }, i: number) => { - return ( -
-
-

{human.title}

-

{human.text}

-
+ {career.humanPowered.map((human, i) => { + return ( +
+
+

{human.title}

+

{human.text}

- ) - } - )} +
+ ) + })}
@@ -312,7 +322,7 @@ const CareerPage: NextPage = ({ jobs, placeholderJob, contribu

- {contributors.map((contributor: any, i: number) => { + {contributors.map((contributor, i) => { return (
= ({ jobs, placeholderJob, contribu
- {career.benefits.map( - (benefits: { icon: string; title: string; text: string }, i: number) => { - return ( -
-
-

{benefits.title}

- - {benefits.text} - -
+ {career.benefits.map((benefits, i) => { + return ( +
+
+

{benefits.title}

+ {benefits.text}
- ) - } - )} +
+ ) + })}
@@ -401,7 +407,7 @@ const CareerPage: NextPage = ({ jobs, placeholderJob, contribu

- {career.hiring.map((hiring: { title: string; text: string }, i: number) => { + {career.hiring.map((hiring, i) => { return (
= ({ jobs, placeholderJob, contribu

{team}

- {(teamJobs as JobItemProps[]) - .filter((job: any) => !filterGenericJob(job)) - .map((job: JobItemProps) => ( + {teamJobs + .filter((job) => !filterGenericJob(job)) + .map((job) => ( ))}
@@ -481,7 +487,7 @@ const CareerPage: NextPage = ({ jobs, placeholderJob, contribu ) } -const JobItem: React.FC<{ job: JobItemProps }> = ({ job }) => { +const JobItem = ({ job }: { job: JobItemProps }) => { const isPlaceholderJob = job.id === PLACEHOLDER_JOB_ID return (