From 1bff39b956fbdec7c018e33afc551697620b9325 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Thu, 29 Feb 2024 15:24:48 +0800 Subject: [PATCH 01/62] Update ConnectDropdown.tsx (#21654) --- .../Home/Connect/ConnectDropdown.tsx | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/apps/studio/components/interfaces/Home/Connect/ConnectDropdown.tsx b/apps/studio/components/interfaces/Home/Connect/ConnectDropdown.tsx index 93b2e64fcec..2bdec4f5f79 100644 --- a/apps/studio/components/interfaces/Home/Connect/ConnectDropdown.tsx +++ b/apps/studio/components/interfaces/Home/Connect/ConnectDropdown.tsx @@ -2,6 +2,8 @@ import { Box, Check, ChevronDown } from 'lucide-react' import { useState } from 'react' import { Button, + CommandEmpty_Shadcn_, + CommandGroup_Shadcn_, CommandInput_Shadcn_, CommandItem_Shadcn_, CommandList_Shadcn_, @@ -59,29 +61,29 @@ const ConnectDropdown = ({ - + - {items.map((item) => ( - { - onSelectLib(item.key) - setOpen(false) - }} - > -
+ No results found. + + {items.map((item) => ( + { + onSelectLib(item.key) + setOpen(false) + }} + className="flex gap-2 items-center" + > {item.icon ? : } - {item.label} - -
-
- ))} + + ))} +
From a8ee3a212b4e53efc7608ad847bc59e054a22eaa Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Thu, 29 Feb 2024 20:18:00 +1100 Subject: [PATCH 02/62] feat: branching statuses first pass (#20631) * feat: branching statuses first pass * handle error * use warning icon --- .../BranchManagement/BranchPanels.tsx | 37 +++++++++++---- .../BranchManagement/BranchStatusBadge.tsx | 46 +++++++++++++++++++ apps/studio/data/branches/branch-query.ts | 38 +++++++++++++++ apps/studio/data/branches/keys.ts | 3 +- 4 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 apps/studio/components/interfaces/BranchManagement/BranchStatusBadge.tsx create mode 100644 apps/studio/data/branches/branch-query.ts diff --git a/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx b/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx index f2a1cf2035e..425e4b246ad 100644 --- a/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx +++ b/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx @@ -1,7 +1,14 @@ import { useParams } from 'common' import dayjs from 'dayjs' +import { GitPullRequest } from 'lucide-react' import Link from 'next/link' import { PropsWithChildren, ReactNode } from 'react' +import { useInView } from 'react-intersection-observer' + +import ShimmeringLoader from 'components/ui/ShimmeringLoader' +import { useBranchQuery } from 'data/branches/branch-query' +import { Branch } from 'data/branches/branches-query' +import { GitHubPullRequest } from 'data/integrations/integrations-github-pull-requests-query' import { Badge, Button, @@ -15,11 +22,7 @@ import { IconShield, IconTrash, } from 'ui' - -import ShimmeringLoader from 'components/ui/ShimmeringLoader' -import { Branch } from 'data/branches/branches-query' -import { GitHubPullRequest } from 'data/integrations/integrations-github-pull-requests-query' -import { GitPullRequest } from 'lucide-react' +import BranchStatusBadge from './BranchStatusBadge' interface BranchManagementSectionProps { header: string @@ -86,8 +89,8 @@ export const BranchRow = ({ generateCreatePullRequestURL, onSelectDeleteBranch, }: BranchRowProps) => { - const { ref } = useParams() - const isActive = ref === branch?.project_ref + const { ref: projectRef } = useParams() + const isActive = projectRef === branch?.project_ref const daysFromNow = dayjs().diff(dayjs(branch.updated_at), 'day') const formattedTimeFromNow = dayjs(branch.updated_at).fromNow() @@ -96,8 +99,23 @@ export const BranchRow = ({ const createPullRequestURL = generateCreatePullRequestURL?.(branch.git_branch) ?? 'https://github.com' + const { ref, inView } = useInView() + const { data } = useBranchQuery( + { projectRef, id: branch.id }, + { + enabled: inView, + refetchInterval(data) { + if (data?.status !== 'ACTIVE_HEALTHY') { + return 1000 * 3 // 3 seconds + } + + return false + }, + } + ) + return ( -
+
{isActive && Current} + {data?.status !== undefined && }

{daysFromNow > 1 ? `Updated on ${formattedUpdatedAt}` : `Updated ${formattedTimeFromNow}`}

@@ -155,7 +174,7 @@ export const BranchRow = ({
- +
) } diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx index 37cfa3ce024..e6c9821552d 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx @@ -23,17 +23,14 @@ const UtilityPanel = ({ <>
- -
- -
+
diff --git a/apps/studio/lib/constants/index.ts b/apps/studio/lib/constants/index.ts index 7ea1d43dc97..7646cc7b481 100644 --- a/apps/studio/lib/constants/index.ts +++ b/apps/studio/lib/constants/index.ts @@ -35,6 +35,7 @@ export const LOCAL_STORAGE_KEYS = { DASHBOARD_HISTORY: (ref: string) => `dashboard-history-${ref}`, UI_PREVIEW_CLS: 'supabase-ui-cls', + SQL_EDITOR_INTELLISENSE: 'supabase_sql-editor-intellisense-enabled', SQL_EDITOR_SPLIT_SIZE: 'supabase_sql-editor-split-size', LOG_EXPLORER_SPLIT_SIZE: 'supabase_log-explorer-split-size', GRAPHIQL_RLS_BYPASS_WARNING: 'graphiql-rls-bypass-warning-dismissed', diff --git a/apps/studio/pages/project/[ref]/sql/[id].tsx b/apps/studio/pages/project/[ref]/sql/[id].tsx index 8e074519a07..48af796d0b3 100644 --- a/apps/studio/pages/project/[ref]/sql/[id].tsx +++ b/apps/studio/pages/project/[ref]/sql/[id].tsx @@ -1,8 +1,8 @@ -import { useRouter } from 'next/router' import { useMonaco } from '@monaco-editor/react' -import { observer } from 'mobx-react-lite' -import { useEffect, useRef } from 'react' import { useParams } from 'common' +import { observer } from 'mobx-react-lite' +import { useRouter } from 'next/router' +import { useEffect, useRef } from 'react' import { useFunctionsQuery } from 'data/database/functions-query' import { useKeywordsQuery } from 'data/database/keywords-query' @@ -16,6 +16,8 @@ import { SQLEditorLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import getPgsqlCompletionProvider from 'components/ui/CodeEditor/Providers/PgSQLCompletionProvider' import getPgsqlSignatureHelpProvider from 'components/ui/CodeEditor/Providers/PgSQLSignatureHelpProvider' +import { useLocalStorageQuery } from 'hooks' +import { LOCAL_STORAGE_KEYS } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' import { useSnippets, useSqlEditorStateSnapshot } from 'state/sql-editor' @@ -31,6 +33,11 @@ const SqlEditor: NextPageWithLayout = () => { const snippets = useSnippets(ref) const { mutateAsync: formatQuery } = useFormatQueryMutation() + const [intellisenseEnabled] = useLocalStorageQuery( + LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE, + typeof window !== 'undefined' ? false : true + ) + async function formatPgsql(value: string) { try { if (!project) throw new Error('No project') @@ -46,29 +53,46 @@ const SqlEditor: NextPageWithLayout = () => { } } - const { data: keywords, isSuccess: isKeywordsSuccess } = useKeywordsQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) - const { data: functions, isSuccess: isFunctionsSuccess } = useFunctionsQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) - const { data: schemas, isSuccess: isSchemasSuccess } = useSchemasQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) - const { data: tableColumns, isSuccess: isTableColumnsSuccess } = useTableColumnsQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) + const { data: keywords, isSuccess: isKeywordsSuccess } = useKeywordsQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) + const { data: functions, isSuccess: isFunctionsSuccess } = useFunctionsQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) + const { data: schemas, isSuccess: isSchemasSuccess } = useSchemasQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) + const { data: tableColumns, isSuccess: isTableColumnsSuccess } = useTableColumnsQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + }, + { enabled: intellisenseEnabled } + ) const pgInfoRef = useRef(null) const formatPgsqlRef = useRef(formatPgsql) formatPgsqlRef.current = formatPgsql const isPgInfoReady = - isTableColumnsSuccess && isSchemasSuccess && isKeywordsSuccess && isFunctionsSuccess + intellisenseEnabled && + isTableColumnsSuccess && + isSchemasSuccess && + isKeywordsSuccess && + isFunctionsSuccess + if (isPgInfoReady) { if (pgInfoRef.current === null) { pgInfoRef.current = {} diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index 0c5d85b1f4f..770a53b4e08 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -207,6 +207,8 @@ export { TooltipContent as TooltipContent_Shadcn_, } from './src/components/shadcn/ui/tooltip' +export { Toggle as Toggle_Shadcn } from './src/components/shadcn/ui/toggle' + export { ScrollArea, ScrollBar } from './src/components/shadcn/ui/scroll-area' export { Separator } from './src/components/shadcn/ui/separator' diff --git a/packages/ui/src/components/shadcn/ui/toggle.tsx b/packages/ui/src/components/shadcn/ui/toggle.tsx index a64f158ec2f..a74a089e6c3 100644 --- a/packages/ui/src/components/shadcn/ui/toggle.tsx +++ b/packages/ui/src/components/shadcn/ui/toggle.tsx @@ -7,7 +7,7 @@ import * as React from 'react' import { cn } from '../../../lib/utils/cn' const toggleVariants = cva( - 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors data-[state=on]:bg-accent data-[state=on]:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background hover:bg-muted hover:text-foreground-muted', + 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors data-[state=on]:bg-accent data-[state=on]:bg-surface-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background bg-surface-200 hover:bg-surface-300 px-3 py-1 h-auto text-foreground transition-all', { variants: { variant: { From a473809d186f1b239179b6e26308394c0a1d90ac Mon Sep 17 00:00:00 2001 From: Francesco Sansalvadore Date: Thu, 29 Feb 2024 15:32:30 +0100 Subject: [PATCH 05/62] update database page (#21639) add read replicas and branching sections to product pages --- apps/www/components/NewFeatureCard.tsx | 69 +++++++++++++++ .../data/products/database/highlight-cards.ts | 56 +++++++++++++ apps/www/pages/database/Database.tsx | 35 +++++--- .../product/database/branching-light.svg | 34 ++++++++ .../images/product/database/branching.svg | 34 ++++++++ .../product/database/read-replicas-light.svg | 84 +++++++++++++++++++ .../images/product/database/read-replicas.svg | 84 +++++++++++++++++++ 7 files changed, 385 insertions(+), 11 deletions(-) create mode 100644 apps/www/components/NewFeatureCard.tsx create mode 100644 apps/www/data/products/database/highlight-cards.ts create mode 100644 apps/www/public/images/product/database/branching-light.svg create mode 100644 apps/www/public/images/product/database/branching.svg create mode 100644 apps/www/public/images/product/database/read-replicas-light.svg create mode 100644 apps/www/public/images/product/database/read-replicas.svg diff --git a/apps/www/components/NewFeatureCard.tsx b/apps/www/components/NewFeatureCard.tsx new file mode 100644 index 00000000000..7460c4adfd4 --- /dev/null +++ b/apps/www/components/NewFeatureCard.tsx @@ -0,0 +1,69 @@ +import React from 'react' +import Panel from '~/components/Panel' +import { Badge, Button, ButtonProps, IconCheck } from 'ui' +import Link from 'next/link' +import { ThemeImage } from 'ui-patterns' + +export interface CardProps { + title: string + features?: string[] + badge?: string + ctas: { + label: string + href: string + target: HTMLAnchorElement['target'] + type: ButtonProps['type'] + }[] + image?: { + dark: string + light: string + } +} + +const NewFeatureCard = (props: CardProps) => ( + +
+
+

{props.title}

+ {props.badge && ( + {props.badge} + )} +
+
+
    + {props.features?.map((feature: any) => ( +
  • + + + {' '} +

    {feature}

    +
  • + ))} +
+
+ +
+ {props.ctas.map((cta: any) => ( + + ))} +
+
+ {props.image && ( +
+ +
+ )} +
+) + +export default NewFeatureCard diff --git a/apps/www/data/products/database/highlight-cards.ts b/apps/www/data/products/database/highlight-cards.ts new file mode 100644 index 00000000000..581127e603d --- /dev/null +++ b/apps/www/data/products/database/highlight-cards.ts @@ -0,0 +1,56 @@ +import { CardProps } from '~/components/NewFeatureCard' + +const cards: { [name: string]: CardProps } = { + branching: { + title: 'Branching', + badge: 'New', + features: [ + 'Branch your Supabase project', + 'Sync with your git branches', + 'Manage every Preview from the Dashboard', + 'Support for Vercel Previews', + ], + ctas: [ + { + label: 'Learn more', + href: 'https://supabase.com/docs/guides/platform/branching', + target: '_blank', + type: 'default', + }, + ], + image: { + dark: '/images/product/database/branching.svg', + light: '/images/product/database/branching-light.svg', + }, + }, + readReplicas: { + title: 'Read Replicas', + badge: 'New', + features: [ + 'Serve data closer to your users', + 'Provide data redundancy', + 'Run complex queries without affecting your primary database', + 'Distribute load across various databases', + ], + ctas: [ + { + label: 'Get Early Access', + href: 'https://forms.supabase.com/enterprise', + target: '_blank', + type: 'primary', + }, + { + label: 'Learn more', + href: 'https://supabase.com/docs/guides/platform/read-replicas', + target: '_blank', + type: 'default', + }, + ], + image: { + dark: '/images/product/database/read-replicas.svg', + light: '/images/product/database/read-replicas-light.svg', + }, + }, +} + +export default cards diff --git a/apps/www/pages/database/Database.tsx b/apps/www/pages/database/Database.tsx index 3b47c48bea3..f555fc61c41 100644 --- a/apps/www/pages/database/Database.tsx +++ b/apps/www/pages/database/Database.tsx @@ -1,30 +1,38 @@ // Import Swiper styles import 'swiper/swiper.min.css' +import dynamic from 'next/dynamic' import { NextSeo } from 'next-seo' import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/router' import { useState } from 'react' import { Badge, Button, IconArrowUpRight, IconX, Tabs } from 'ui' +import { Swiper, SwiperSlide } from 'swiper/react' + // data +import Solutions from 'data/Solutions' import ApiExamplesData from 'data/products/database/api-examples' +import HighlightsCards from '~/data/products/database/highlight-cards' import ExtensionsExamplesData from 'data/products/database/extensions-examples' import SqlViewCarouselData from 'data/products/database/sql-view-carousel.json' import TableViewCarouselData from 'data/products/database/table-view-carousel.json' -import Solutions from 'data/Solutions' -import { Swiper, SwiperSlide } from 'swiper/react' -import ImageCarousel from '~/components/Carousels/ImageCarousel' -import SplitCodeBlockCarousel from '~/components/Carousels/SplitCodeBlockCarousel' -import FeatureColumn from '~/components/FeatureColumn' -import DefaultLayout from '~/components/Layouts/Default' -import SectionContainer from '~/components/Layouts/SectionContainer' -import ProductIcon from '~/components/ProductIcon' -import APISection from '~/components/Sections/APISection' -import GithubExamples from '~/components/Sections/GithubExamples' -import ProductHeader from '~/components/Sections/ProductHeader' + import { ThemeImage } from 'ui-patterns/ThemeImage' import { TweetCard } from 'ui-patterns/TweetCard' +import ProductHeader from '~/components/Sections/ProductHeader' + +const NewFeatureCard = dynamic(() => import('~/components/NewFeatureCard')) +const ImageCarousel = dynamic(() => import('~/components/Carousels/ImageCarousel')) +const SplitCodeBlockCarousel = dynamic( + () => import('~/components/Carousels/SplitCodeBlockCarousel') +) +const FeatureColumn = dynamic(() => import('~/components/FeatureColumn')) +const DefaultLayout = dynamic(() => import('~/components/Layouts/Default')) +const SectionContainer = dynamic(() => import('~/components/Layouts/SectionContainer')) +const ProductIcon = dynamic(() => import('~/components/ProductIcon')) +const APISection = dynamic(() => import('~/components/Sections/APISection')) +const GithubExamples = dynamic(() => import('~/components/Sections/GithubExamples')) function Database() { // base path for images @@ -139,6 +147,11 @@ function Database() {
+ + + + + {/* ÷ */}
diff --git a/apps/www/public/images/product/database/branching-light.svg b/apps/www/public/images/product/database/branching-light.svg new file mode 100644 index 00000000000..4e577721b9d --- /dev/null +++ b/apps/www/public/images/product/database/branching-light.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/www/public/images/product/database/branching.svg b/apps/www/public/images/product/database/branching.svg new file mode 100644 index 00000000000..49ca9426069 --- /dev/null +++ b/apps/www/public/images/product/database/branching.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/www/public/images/product/database/read-replicas-light.svg b/apps/www/public/images/product/database/read-replicas-light.svg new file mode 100644 index 00000000000..61f66da2bf3 --- /dev/null +++ b/apps/www/public/images/product/database/read-replicas-light.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/www/public/images/product/database/read-replicas.svg b/apps/www/public/images/product/database/read-replicas.svg new file mode 100644 index 00000000000..ea2b9124fa4 --- /dev/null +++ b/apps/www/public/images/product/database/read-replicas.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ffd5098d02d94114209b53991bc5fb46ff7e213e Mon Sep 17 00:00:00 2001 From: Ant Wilson Date: Thu, 29 Feb 2024 17:10:31 +0100 Subject: [PATCH 06/62] chore: adds back priorty (#21662) --- apps/www/internals/generate-sitemap.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/www/internals/generate-sitemap.mjs b/apps/www/internals/generate-sitemap.mjs index d99cd90dbc8..d939020a4c6 100644 --- a/apps/www/internals/generate-sitemap.mjs +++ b/apps/www/internals/generate-sitemap.mjs @@ -89,7 +89,7 @@ async function generate() { ${`https://supabase.com${route}`} weekly - 0.5 + 0.5 ` }) From 34c760783e8a65462df67c624f7b3e75486c6ebf Mon Sep 17 00:00:00 2001 From: Kuiliang Zhang <38809606+Crayon-ShinChan@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:15:29 -0800 Subject: [PATCH 07/62] docs: fix parameter name to fileSizeLimit (#21677) the newest version of api use `fileSizeLimit` rather than `maxFileSize` --- apps/docs/content/guides/storage/buckets/creating-buckets.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/content/guides/storage/buckets/creating-buckets.mdx b/apps/docs/content/guides/storage/buckets/creating-buckets.mdx index b63979bc8b1..b7684933de7 100644 --- a/apps/docs/content/guides/storage/buckets/creating-buckets.mdx +++ b/apps/docs/content/guides/storage/buckets/creating-buckets.mdx @@ -78,7 +78,7 @@ You can achieve the following by providing: `allowedMimeTypes` and `maxFileSize` const { data, error } = await supabase.storage.createBucket('avatars', { public: true, allowedMimeTypes: ['image/*'], - maxFileSize: '1MB', + fileSizeLimit: '1MB', }) ``` From 502931b5375c9fb95a8390a55f02ddab2fe9ec75 Mon Sep 17 00:00:00 2001 From: Francesco Sansalvadore Date: Fri, 1 Mar 2024 05:26:48 +0100 Subject: [PATCH 08/62] update favicons (#21635) * update all favicons * prettify manifest * switch studio and docs favicons * prettify manifest --- .../public/favicon/android-icon-144x144.png | Bin 3914 -> 3243 bytes .../public/favicon/android-icon-192x192.png | Bin 9435 -> 3599 bytes .../public/favicon/android-icon-36x36.png | Bin 2078 -> 1191 bytes .../public/favicon/android-icon-48x48.png | Bin 2568 -> 1353 bytes .../public/favicon/android-icon-72x72.png | Bin 2214 -> 1751 bytes .../public/favicon/android-icon-96x96.png | Bin 4447 -> 2176 bytes .../public/favicon/apple-icon-114x114.png | Bin 3914 -> 2493 bytes .../public/favicon/apple-icon-120x120.png | Bin 4299 -> 2643 bytes .../public/favicon/apple-icon-144x144.png | Bin 5379 -> 3243 bytes .../public/favicon/apple-icon-152x152.png | Bin 5816 -> 3442 bytes .../public/favicon/apple-icon-180x180.png | Bin 8727 -> 4141 bytes apps/docs/public/favicon/apple-icon-57x57.png | Bin 2869 -> 1498 bytes apps/docs/public/favicon/apple-icon-60x60.png | Bin 1854 -> 1569 bytes apps/docs/public/favicon/apple-icon-72x72.png | Bin 2214 -> 1751 bytes apps/docs/public/favicon/apple-icon-76x76.png | Bin 2412 -> 1822 bytes .../public/favicon/apple-icon-precomposed.png | Bin 9435 -> 4137 bytes apps/docs/public/favicon/apple-icon.png | Bin 9435 -> 4137 bytes .../{ => archive}/android-chrome-192x192.png | Bin .../{ => archive}/android-chrome-512x512.png | Bin .../android-icon-144x144.png} | Bin .../favicon/archive/android-icon-192x192.png | Bin 0 -> 9435 bytes .../favicon/archive/android-icon-36x36.png | Bin 0 -> 2078 bytes .../favicon/archive/android-icon-48x48.png | Bin 0 -> 2568 bytes .../android-icon-72x72.png} | Bin .../favicon/archive/android-icon-96x96.png | Bin 0 -> 4447 bytes .../favicon/archive/apple-icon-114x114.png} | Bin .../apple-icon-120x120.png} | Bin .../apple-icon-144x144.png} | Bin .../apple-icon-152x152.png} | Bin .../favicon/archive/apple-icon-180x180.png | Bin 0 -> 8727 bytes .../favicon/archive/apple-icon-57x57.png | Bin 0 -> 2869 bytes .../apple-icon-60x60.png} | Bin .../favicon/archive/apple-icon-72x72.png} | Bin .../apple-icon-76x76.png} | Bin .../archive/apple-icon-precomposed.png | Bin 0 -> 9435 bytes .../public/favicon/archive/apple-icon.png | Bin 0 -> 9435 bytes .../archive}/apple-touch-icon-114x114.png | Bin .../archive}/apple-touch-icon-120x120.png | Bin .../archive}/apple-touch-icon-144x144.png | Bin .../archive}/apple-touch-icon-152x152.png | Bin .../{ => archive}/apple-touch-icon-57x57.png | Bin .../archive}/apple-touch-icon-60x60.png | Bin .../archive}/apple-touch-icon-72x72.png | Bin .../archive}/apple-touch-icon-76x76.png | Bin .../public/favicon/archive/browserconfig.xml | 2 + .../favicon/{ => archive}/favicon-128.png | Bin .../public/favicon/archive/favicon-16x16.png | Bin 0 -> 4112 bytes .../favicon/{ => archive}/favicon-196x196.png | Bin .../public/favicon/archive/favicon-32x32.png | Bin 0 -> 4593 bytes .../public/favicon/archive/favicon-96x96.png | Bin 0 -> 4447 bytes apps/docs/public/favicon/archive/favicon.ico | Bin 0 -> 1329 bytes .../archive/lw7/android-chrome-192x192.png | Bin 12699 -> 0 bytes .../archive/lw7/android-chrome-512x512.png | Bin 66042 -> 0 bytes .../archive/lw7/apple-touch-icon-114x114.png | Bin 4157 -> 0 bytes .../archive/lw7/apple-touch-icon-120x120.png | Bin 4395 -> 0 bytes .../archive/lw7/apple-touch-icon-144x144.png | Bin 5877 -> 0 bytes .../archive/lw7/apple-touch-icon-152x152.png | Bin 6307 -> 0 bytes .../archive/lw7/apple-touch-icon-57x57.png | Bin 1694 -> 0 bytes .../archive/lw7/apple-touch-icon-60x60.png | Bin 1720 -> 0 bytes .../archive/lw7/apple-touch-icon-72x72.png | Bin 2162 -> 0 bytes .../archive/lw7/apple-touch-icon-76x76.png | Bin 2270 -> 0 bytes .../favicon/archive/lw7/favicon-128.png | Bin 4810 -> 0 bytes .../favicon/archive/lw7/favicon-16x16.png | Bin 452 -> 0 bytes .../favicon/archive/lw7/favicon-196x196.png | Bin 9876 -> 0 bytes .../favicon/archive/lw7/favicon-32x32.png | Bin 859 -> 0 bytes .../favicon/archive/lw7/favicon-96x96.png | Bin 3139 -> 0 bytes .../public/favicon/archive/lw7/favicon.ico | Bin 34494 -> 0 bytes .../favicon/archive/lw7/mstile-144x144.png | Bin 5877 -> 0 bytes .../favicon/archive/lw7/mstile-150x150.png | Bin 17760 -> 0 bytes .../favicon/archive/lw7/mstile-310x150.png | Bin 48157 -> 0 bytes .../favicon/archive/lw7/mstile-310x310.png | Bin 69211 -> 0 bytes .../favicon/archive/lw7/mstile-70x70.png | Bin 4810 -> 0 bytes .../archive/lw8/android-icon-144x144.png | Bin 7997 -> 0 bytes .../archive/lw8/android-icon-192x192.png | Bin 12640 -> 0 bytes .../archive/lw8/android-icon-36x36.png | Bin 2048 -> 0 bytes .../archive/lw8/android-icon-48x48.png | Bin 2138 -> 0 bytes .../archive/lw8/android-icon-72x72.png | Bin 3208 -> 0 bytes .../archive/lw8/android-icon-96x96.png | Bin 4544 -> 0 bytes .../archive/lw8/apple-icon-114x114.png | Bin 5731 -> 0 bytes .../archive/lw8/apple-icon-120x120.png | Bin 5955 -> 0 bytes .../archive/lw8/apple-icon-144x144.png | Bin 7997 -> 0 bytes .../archive/lw8/apple-icon-152x152.png | Bin 8698 -> 0 bytes .../archive/lw8/apple-icon-180x180.png | Bin 11605 -> 0 bytes .../favicon/archive/lw8/apple-icon-57x57.png | Bin 2595 -> 0 bytes .../favicon/archive/lw8/apple-icon-60x60.png | Bin 2713 -> 0 bytes .../favicon/archive/lw8/apple-icon-72x72.png | Bin 3208 -> 0 bytes .../favicon/archive/lw8/apple-icon-76x76.png | Bin 3332 -> 0 bytes .../archive/lw8/apple-icon-precomposed.png | Bin 13182 -> 0 bytes .../public/favicon/archive/lw8/apple-icon.png | Bin 13182 -> 0 bytes .../favicon/archive/lw8/favicon-16x16.png | Bin 1396 -> 0 bytes .../favicon/archive/lw8/favicon-32x32.png | Bin 2056 -> 0 bytes .../favicon/archive/lw8/favicon-96x96.png | Bin 4544 -> 0 bytes .../public/favicon/archive/lw8/favicon.ico | Bin 1150 -> 0 bytes .../favicon/archive/lw8/ms-icon-144x144.png | Bin 7997 -> 0 bytes .../favicon/archive/lw8/ms-icon-150x150.png | Bin 8351 -> 0 bytes .../favicon/archive/lw8/ms-icon-310x310.png | Bin 23344 -> 0 bytes .../favicon/archive/lw8/ms-icon-70x70.png | Bin 3100 -> 0 bytes .../docs/public/favicon/archive/manifest.json | 41 ++++++++++++++++++ .../ms-icon-144x144.png} | Bin .../ms-icon-150x150.png} | Bin .../ms-icon-310x310.png} | Bin .../public/favicon/archive/ms-icon-70x70.png | Bin 0 -> 3461 bytes .../favicon/archive}/mstile-144x144.png | Bin .../favicon/archive}/mstile-150x150.png | Bin .../favicon/{ => archive}/mstile-310x150.png | Bin .../favicon/archive}/mstile-310x310.png | Bin .../favicon/{ => archive}/mstile-70x70.png | Bin .../favicon/{ => archive}/site.webmanifest | 0 apps/docs/public/favicon/favicon-16x16.png | Bin 4112 -> 868 bytes apps/docs/public/favicon/favicon-32x32.png | Bin 4593 -> 1111 bytes apps/docs/public/favicon/favicon-96x96.png | Bin 4447 -> 2176 bytes apps/docs/public/favicon/favicon.ico | Bin 1329 -> 1150 bytes apps/docs/public/favicon/ms-icon-144x144.png | Bin 5379 -> 3243 bytes apps/docs/public/favicon/ms-icon-150x150.png | Bin 13573 -> 3404 bytes apps/docs/public/favicon/ms-icon-310x310.png | Bin 47471 -> 8773 bytes apps/docs/public/favicon/ms-icon-70x70.png | Bin 3461 -> 1752 bytes .../public/favicon/android-icon-144x144.png | Bin 3914 -> 5320 bytes .../public/favicon/android-icon-192x192.png | Bin 9435 -> 6447 bytes .../public/favicon/android-icon-36x36.png | Bin 2078 -> 1660 bytes .../public/favicon/android-icon-48x48.png | Bin 2568 -> 1854 bytes .../public/favicon/android-icon-72x72.png | Bin 2214 -> 2529 bytes .../public/favicon/android-icon-96x96.png | Bin 4447 -> 3285 bytes .../public/favicon/apple-icon-114x114.png | Bin 3914 -> 4008 bytes .../public/favicon/apple-icon-120x120.png | Bin 4299 -> 4264 bytes .../public/favicon/apple-icon-144x144.png | Bin 5379 -> 5320 bytes .../public/favicon/apple-icon-152x152.png | Bin 5816 -> 5689 bytes .../public/favicon/apple-icon-180x180.png | Bin 8727 -> 6944 bytes .../public/favicon/apple-icon-57x57.png | Bin 2869 -> 2073 bytes .../public/favicon/apple-icon-60x60.png | Bin 1854 -> 2209 bytes .../public/favicon/apple-icon-72x72.png | Bin 2214 -> 2529 bytes .../public/favicon/apple-icon-76x76.png | Bin 2412 -> 2613 bytes .../public/favicon/apple-icon-precomposed.png | Bin 9435 -> 6989 bytes apps/studio/public/favicon/apple-icon.png | Bin 9435 -> 6989 bytes .../{ => archive}/android-chrome-192x192.png | Bin .../{ => archive}/android-chrome-512x512.png | Bin .../favicon/archive/android-icon-144x144.png | Bin 0 -> 3914 bytes .../favicon/archive/android-icon-192x192.png | Bin 0 -> 9435 bytes .../favicon/archive/android-icon-36x36.png | Bin 0 -> 2078 bytes .../favicon/archive/android-icon-48x48.png | Bin 0 -> 2568 bytes .../favicon/archive/android-icon-72x72.png | Bin 0 -> 2214 bytes .../favicon/archive/android-icon-96x96.png | Bin 0 -> 4447 bytes .../favicon/archive/apple-icon-114x114.png | Bin 0 -> 3914 bytes .../favicon/archive/apple-icon-120x120.png} | Bin .../favicon/archive/apple-icon-144x144.png} | Bin .../favicon/archive/apple-icon-152x152.png} | Bin .../favicon/archive/apple-icon-180x180.png | Bin 0 -> 8727 bytes .../favicon/archive/apple-icon-57x57.png | Bin 0 -> 2869 bytes .../favicon/archive/apple-icon-60x60.png} | Bin .../favicon/archive/apple-icon-72x72.png | Bin 0 -> 2214 bytes .../favicon/archive/apple-icon-76x76.png} | Bin .../archive/apple-icon-precomposed.png | Bin 0 -> 9435 bytes .../public/favicon/archive/apple-icon.png | Bin 0 -> 9435 bytes .../archive/apple-touch-icon-114x114.png | Bin 0 -> 3914 bytes .../archive/apple-touch-icon-120x120.png | Bin 0 -> 4299 bytes .../archive/apple-touch-icon-144x144.png} | Bin .../archive/apple-touch-icon-152x152.png | Bin 0 -> 5816 bytes .../{ => archive}/apple-touch-icon-57x57.png | Bin .../archive/apple-touch-icon-60x60.png | Bin 0 -> 1854 bytes .../archive/apple-touch-icon-72x72.png | Bin 0 -> 2214 bytes .../archive/apple-touch-icon-76x76.png | Bin 0 -> 2412 bytes .../public/favicon/archive/browserconfig.xml | 2 + .../favicon/{ => archive}/favicon-128.png | Bin .../public/favicon/archive/favicon-16x16.png | Bin 0 -> 4112 bytes .../favicon/{ => archive}/favicon-196x196.png | Bin .../public/favicon/archive/favicon-32x32.png | Bin 0 -> 4593 bytes .../public/favicon/archive/favicon-96x96.png | Bin 0 -> 4447 bytes .../studio/public/favicon/archive/favicon.ico | Bin 0 -> 1329 bytes .../archive/lw7/android-chrome-192x192.png | Bin 12699 -> 0 bytes .../archive/lw7/android-chrome-512x512.png | Bin 66042 -> 0 bytes .../archive/lw7/apple-touch-icon-114x114.png | Bin 4157 -> 0 bytes .../archive/lw7/apple-touch-icon-120x120.png | Bin 4395 -> 0 bytes .../archive/lw7/apple-touch-icon-144x144.png | Bin 5877 -> 0 bytes .../archive/lw7/apple-touch-icon-152x152.png | Bin 6307 -> 0 bytes .../archive/lw7/apple-touch-icon-57x57.png | Bin 1694 -> 0 bytes .../archive/lw7/apple-touch-icon-60x60.png | Bin 1720 -> 0 bytes .../archive/lw7/apple-touch-icon-72x72.png | Bin 2162 -> 0 bytes .../archive/lw7/apple-touch-icon-76x76.png | Bin 2270 -> 0 bytes .../favicon/archive/lw7/favicon-128.png | Bin 4810 -> 0 bytes .../favicon/archive/lw7/favicon-16x16.png | Bin 452 -> 0 bytes .../favicon/archive/lw7/favicon-196x196.png | Bin 9876 -> 0 bytes .../favicon/archive/lw7/favicon-32x32.png | Bin 859 -> 0 bytes .../favicon/archive/lw7/favicon-96x96.png | Bin 3139 -> 0 bytes .../public/favicon/archive/lw7/favicon.ico | Bin 34494 -> 0 bytes .../favicon/archive/lw7/mstile-144x144.png | Bin 5877 -> 0 bytes .../favicon/archive/lw7/mstile-150x150.png | Bin 17760 -> 0 bytes .../favicon/archive/lw7/mstile-310x150.png | Bin 48157 -> 0 bytes .../favicon/archive/lw7/mstile-310x310.png | Bin 69211 -> 0 bytes .../favicon/archive/lw7/mstile-70x70.png | Bin 4810 -> 0 bytes .../archive/lw8/android-icon-144x144.png | Bin 7997 -> 0 bytes .../archive/lw8/android-icon-192x192.png | Bin 12640 -> 0 bytes .../archive/lw8/android-icon-36x36.png | Bin 2048 -> 0 bytes .../archive/lw8/android-icon-48x48.png | Bin 2138 -> 0 bytes .../archive/lw8/android-icon-72x72.png | Bin 3208 -> 0 bytes .../archive/lw8/android-icon-96x96.png | Bin 4544 -> 0 bytes .../archive/lw8/apple-icon-114x114.png | Bin 5731 -> 0 bytes .../archive/lw8/apple-icon-120x120.png | Bin 5955 -> 0 bytes .../archive/lw8/apple-icon-144x144.png | Bin 7997 -> 0 bytes .../archive/lw8/apple-icon-152x152.png | Bin 8698 -> 0 bytes .../archive/lw8/apple-icon-180x180.png | Bin 11605 -> 0 bytes .../favicon/archive/lw8/apple-icon-57x57.png | Bin 2595 -> 0 bytes .../favicon/archive/lw8/apple-icon-60x60.png | Bin 2713 -> 0 bytes .../favicon/archive/lw8/apple-icon-72x72.png | Bin 3208 -> 0 bytes .../favicon/archive/lw8/apple-icon-76x76.png | Bin 3332 -> 0 bytes .../archive/lw8/apple-icon-precomposed.png | Bin 13182 -> 0 bytes .../public/favicon/archive/lw8/apple-icon.png | Bin 13182 -> 0 bytes .../favicon/archive/lw8/favicon-16x16.png | Bin 1396 -> 0 bytes .../favicon/archive/lw8/favicon-32x32.png | Bin 2056 -> 0 bytes .../favicon/archive/lw8/favicon-96x96.png | Bin 4544 -> 0 bytes .../public/favicon/archive/lw8/favicon.ico | Bin 1150 -> 0 bytes .../favicon/archive/lw8/ms-icon-144x144.png | Bin 7997 -> 0 bytes .../favicon/archive/lw8/ms-icon-150x150.png | Bin 8351 -> 0 bytes .../favicon/archive/lw8/ms-icon-310x310.png | Bin 23344 -> 0 bytes .../favicon/archive/lw8/ms-icon-70x70.png | Bin 3100 -> 0 bytes .../public/favicon/archive/manifest.json | 41 ++++++++++++++++++ .../favicon/archive/ms-icon-144x144.png | Bin 0 -> 5379 bytes .../favicon/archive/ms-icon-150x150.png} | Bin .../favicon/archive/ms-icon-310x310.png} | Bin .../public/favicon/archive/ms-icon-70x70.png | Bin 0 -> 3461 bytes .../public/favicon/archive/mstile-144x144.png | Bin 0 -> 5379 bytes .../public/favicon/archive/mstile-150x150.png | Bin 0 -> 13573 bytes .../favicon/{ => archive}/mstile-310x150.png | Bin .../public/favicon/archive/mstile-310x310.png | Bin 0 -> 47471 bytes .../favicon/{ => archive}/mstile-70x70.png | Bin .../favicon/{ => archive}/site.webmanifest | 0 apps/studio/public/favicon/favicon-16x16.png | Bin 4112 -> 1027 bytes apps/studio/public/favicon/favicon-32x32.png | Bin 4593 -> 1564 bytes apps/studio/public/favicon/favicon-96x96.png | Bin 4447 -> 3285 bytes apps/studio/public/favicon/favicon.ico | Bin 1329 -> 1150 bytes .../studio/public/favicon/ms-icon-144x144.png | Bin 5379 -> 5320 bytes .../studio/public/favicon/ms-icon-150x150.png | Bin 13573 -> 5589 bytes .../studio/public/favicon/ms-icon-310x310.png | Bin 47471 -> 15636 bytes apps/studio/public/favicon/ms-icon-70x70.png | Bin 3461 -> 2489 bytes .../public/favicon/android-icon-144x144.png | Bin 3914 -> 5320 bytes .../public/favicon/android-icon-192x192.png | Bin 9435 -> 6447 bytes .../www/public/favicon/android-icon-36x36.png | Bin 2078 -> 1660 bytes .../www/public/favicon/android-icon-48x48.png | Bin 2568 -> 1854 bytes .../www/public/favicon/android-icon-72x72.png | Bin 2214 -> 2529 bytes .../www/public/favicon/android-icon-96x96.png | Bin 4447 -> 3285 bytes .../www/public/favicon/apple-icon-114x114.png | Bin 3914 -> 4008 bytes .../www/public/favicon/apple-icon-120x120.png | Bin 4299 -> 4264 bytes .../www/public/favicon/apple-icon-144x144.png | Bin 5379 -> 5320 bytes .../www/public/favicon/apple-icon-152x152.png | Bin 5816 -> 5689 bytes .../www/public/favicon/apple-icon-180x180.png | Bin 8727 -> 6944 bytes apps/www/public/favicon/apple-icon-57x57.png | Bin 2869 -> 2073 bytes apps/www/public/favicon/apple-icon-60x60.png | Bin 1854 -> 2209 bytes apps/www/public/favicon/apple-icon-72x72.png | Bin 2214 -> 2529 bytes apps/www/public/favicon/apple-icon-76x76.png | Bin 2412 -> 2613 bytes .../public/favicon/apple-icon-precomposed.png | Bin 9435 -> 6989 bytes apps/www/public/favicon/apple-icon.png | Bin 9435 -> 6989 bytes .../{ => archive}/android-chrome-192x192.png | Bin .../{ => archive}/android-chrome-512x512.png | Bin .../favicon/archive/android-icon-144x144.png | Bin 0 -> 3914 bytes .../favicon/archive/android-icon-192x192.png | Bin 0 -> 9435 bytes .../favicon/archive/android-icon-36x36.png | Bin 0 -> 2078 bytes .../favicon/archive/android-icon-48x48.png | Bin 0 -> 2568 bytes .../favicon/archive/android-icon-72x72.png | Bin 0 -> 2214 bytes .../favicon/archive/android-icon-96x96.png | Bin 0 -> 4447 bytes .../favicon/archive/apple-icon-114x114.png | Bin 0 -> 3914 bytes .../favicon/archive/apple-icon-120x120.png | Bin 0 -> 4299 bytes .../favicon/archive/apple-icon-144x144.png | Bin 0 -> 5379 bytes .../favicon/archive/apple-icon-152x152.png | Bin 0 -> 5816 bytes .../favicon/archive/apple-icon-180x180.png | Bin 0 -> 8727 bytes .../favicon/archive/apple-icon-57x57.png | Bin 0 -> 2869 bytes .../favicon/archive/apple-icon-60x60.png | Bin 0 -> 1854 bytes .../favicon/archive/apple-icon-72x72.png | Bin 0 -> 2214 bytes .../favicon/archive/apple-icon-76x76.png | Bin 0 -> 2412 bytes .../archive/apple-icon-precomposed.png | Bin 0 -> 9435 bytes .../www/public/favicon/archive/apple-icon.png | Bin 0 -> 9435 bytes .../archive/apple-touch-icon-114x114.png | Bin 0 -> 3914 bytes .../archive/apple-touch-icon-120x120.png | Bin 0 -> 4299 bytes .../archive/apple-touch-icon-144x144.png | Bin 0 -> 5379 bytes .../archive/apple-touch-icon-152x152.png | Bin 0 -> 5816 bytes .../{ => archive}/apple-touch-icon-57x57.png | Bin .../archive/apple-touch-icon-60x60.png | Bin 0 -> 1854 bytes .../archive/apple-touch-icon-72x72.png | Bin 0 -> 2214 bytes .../archive/apple-touch-icon-76x76.png | Bin 0 -> 2412 bytes .../public/favicon/archive/browserconfig.xml | 2 + .../favicon/{ => archive}/favicon-128.png | Bin .../public/favicon/archive/favicon-16x16.png | Bin 0 -> 4112 bytes .../favicon/{ => archive}/favicon-196x196.png | Bin .../public/favicon/archive/favicon-32x32.png | Bin 0 -> 4593 bytes .../public/favicon/archive/favicon-96x96.png | Bin 0 -> 4447 bytes apps/www/public/favicon/archive/favicon.ico | Bin 0 -> 1329 bytes .../archive/lw7/android-chrome-192x192.png | Bin 12699 -> 0 bytes .../archive/lw7/android-chrome-512x512.png | Bin 66042 -> 0 bytes .../archive/lw7/apple-touch-icon-114x114.png | Bin 4157 -> 0 bytes .../archive/lw7/apple-touch-icon-120x120.png | Bin 4395 -> 0 bytes .../archive/lw7/apple-touch-icon-144x144.png | Bin 5877 -> 0 bytes .../archive/lw7/apple-touch-icon-152x152.png | Bin 6307 -> 0 bytes .../archive/lw7/apple-touch-icon-57x57.png | Bin 1694 -> 0 bytes .../archive/lw7/apple-touch-icon-60x60.png | Bin 1720 -> 0 bytes .../archive/lw7/apple-touch-icon-72x72.png | Bin 2162 -> 0 bytes .../archive/lw7/apple-touch-icon-76x76.png | Bin 2270 -> 0 bytes .../favicon/archive/lw7/favicon-128.png | Bin 4810 -> 0 bytes .../favicon/archive/lw7/favicon-16x16.png | Bin 452 -> 0 bytes .../favicon/archive/lw7/favicon-196x196.png | Bin 9876 -> 0 bytes .../favicon/archive/lw7/favicon-32x32.png | Bin 859 -> 0 bytes .../favicon/archive/lw7/favicon-96x96.png | Bin 3139 -> 0 bytes .../public/favicon/archive/lw7/favicon.ico | Bin 34494 -> 0 bytes .../favicon/archive/lw7/mstile-144x144.png | Bin 5877 -> 0 bytes .../favicon/archive/lw7/mstile-150x150.png | Bin 17760 -> 0 bytes .../favicon/archive/lw7/mstile-310x150.png | Bin 48157 -> 0 bytes .../favicon/archive/lw7/mstile-310x310.png | Bin 69211 -> 0 bytes .../favicon/archive/lw7/mstile-70x70.png | Bin 4810 -> 0 bytes .../archive/lw8/android-icon-144x144.png | Bin 7997 -> 0 bytes .../archive/lw8/android-icon-192x192.png | Bin 12640 -> 0 bytes .../archive/lw8/android-icon-36x36.png | Bin 2048 -> 0 bytes .../archive/lw8/android-icon-48x48.png | Bin 2138 -> 0 bytes .../archive/lw8/android-icon-72x72.png | Bin 3208 -> 0 bytes .../archive/lw8/android-icon-96x96.png | Bin 4544 -> 0 bytes .../archive/lw8/apple-icon-114x114.png | Bin 5731 -> 0 bytes .../archive/lw8/apple-icon-120x120.png | Bin 5955 -> 0 bytes .../archive/lw8/apple-icon-144x144.png | Bin 7997 -> 0 bytes .../archive/lw8/apple-icon-152x152.png | Bin 8698 -> 0 bytes .../archive/lw8/apple-icon-180x180.png | Bin 11605 -> 0 bytes .../favicon/archive/lw8/apple-icon-57x57.png | Bin 2595 -> 0 bytes .../favicon/archive/lw8/apple-icon-60x60.png | Bin 2713 -> 0 bytes .../favicon/archive/lw8/apple-icon-72x72.png | Bin 3208 -> 0 bytes .../favicon/archive/lw8/apple-icon-76x76.png | Bin 3332 -> 0 bytes .../archive/lw8/apple-icon-precomposed.png | Bin 13182 -> 0 bytes .../public/favicon/archive/lw8/apple-icon.png | Bin 13182 -> 0 bytes .../favicon/archive/lw8/favicon-16x16.png | Bin 1396 -> 0 bytes .../favicon/archive/lw8/favicon-32x32.png | Bin 2056 -> 0 bytes .../favicon/archive/lw8/favicon-96x96.png | Bin 4544 -> 0 bytes .../public/favicon/archive/lw8/favicon.ico | Bin 1150 -> 0 bytes .../favicon/archive/lw8/ms-icon-144x144.png | Bin 7997 -> 0 bytes .../favicon/archive/lw8/ms-icon-150x150.png | Bin 8351 -> 0 bytes .../favicon/archive/lw8/ms-icon-310x310.png | Bin 23344 -> 0 bytes .../favicon/archive/lw8/ms-icon-70x70.png | Bin 3100 -> 0 bytes apps/www/public/favicon/archive/manifest.json | 41 ++++++++++++++++++ .../favicon/archive/ms-icon-144x144.png | Bin 0 -> 5379 bytes .../favicon/archive/ms-icon-150x150.png | Bin 0 -> 13573 bytes .../favicon/archive/ms-icon-310x310.png | Bin 0 -> 47471 bytes .../public/favicon/archive/ms-icon-70x70.png | Bin 0 -> 3461 bytes .../public/favicon/archive/mstile-144x144.png | Bin 0 -> 5379 bytes .../public/favicon/archive/mstile-150x150.png | Bin 0 -> 13573 bytes .../favicon/{ => archive}/mstile-310x150.png | Bin .../public/favicon/archive/mstile-310x310.png | Bin 0 -> 47471 bytes .../favicon/{ => archive}/mstile-70x70.png | Bin .../favicon/{ => archive}/site.webmanifest | 0 apps/www/public/favicon/favicon-16x16.png | Bin 4112 -> 1027 bytes apps/www/public/favicon/favicon-32x32.png | Bin 4593 -> 1564 bytes apps/www/public/favicon/favicon-96x96.png | Bin 4447 -> 3285 bytes apps/www/public/favicon/favicon.ico | Bin 1329 -> 1150 bytes apps/www/public/favicon/ms-icon-144x144.png | Bin 5379 -> 5320 bytes apps/www/public/favicon/ms-icon-150x150.png | Bin 13573 -> 5589 bytes apps/www/public/favicon/ms-icon-310x310.png | Bin 47471 -> 15636 bytes apps/www/public/favicon/ms-icon-70x70.png | Bin 3461 -> 2489 bytes 348 files changed, 129 insertions(+) rename apps/docs/public/favicon/{ => archive}/android-chrome-192x192.png (100%) rename apps/docs/public/favicon/{ => archive}/android-chrome-512x512.png (100%) rename apps/docs/public/favicon/{apple-touch-icon-114x114.png => archive/android-icon-144x144.png} (100%) create mode 100644 apps/docs/public/favicon/archive/android-icon-192x192.png create mode 100644 apps/docs/public/favicon/archive/android-icon-36x36.png create mode 100644 apps/docs/public/favicon/archive/android-icon-48x48.png rename apps/docs/public/favicon/{apple-touch-icon-72x72.png => archive/android-icon-72x72.png} (100%) create mode 100644 apps/docs/public/favicon/archive/android-icon-96x96.png rename apps/{studio/public/favicon/apple-touch-icon-114x114.png => docs/public/favicon/archive/apple-icon-114x114.png} (100%) rename apps/docs/public/favicon/{apple-touch-icon-120x120.png => archive/apple-icon-120x120.png} (100%) rename apps/docs/public/favicon/{apple-touch-icon-144x144.png => archive/apple-icon-144x144.png} (100%) rename apps/docs/public/favicon/{apple-touch-icon-152x152.png => archive/apple-icon-152x152.png} (100%) create mode 100644 apps/docs/public/favicon/archive/apple-icon-180x180.png create mode 100644 apps/docs/public/favicon/archive/apple-icon-57x57.png rename apps/docs/public/favicon/{apple-touch-icon-60x60.png => archive/apple-icon-60x60.png} (100%) rename apps/{studio/public/favicon/apple-touch-icon-72x72.png => docs/public/favicon/archive/apple-icon-72x72.png} (100%) rename apps/docs/public/favicon/{apple-touch-icon-76x76.png => archive/apple-icon-76x76.png} (100%) create mode 100644 apps/docs/public/favicon/archive/apple-icon-precomposed.png create mode 100644 apps/docs/public/favicon/archive/apple-icon.png rename apps/{www/public/favicon => docs/public/favicon/archive}/apple-touch-icon-114x114.png (100%) rename apps/{studio/public/favicon => docs/public/favicon/archive}/apple-touch-icon-120x120.png (100%) rename apps/{studio/public/favicon => docs/public/favicon/archive}/apple-touch-icon-144x144.png (100%) rename apps/{studio/public/favicon => docs/public/favicon/archive}/apple-touch-icon-152x152.png (100%) rename apps/docs/public/favicon/{ => archive}/apple-touch-icon-57x57.png (100%) rename apps/{studio/public/favicon => docs/public/favicon/archive}/apple-touch-icon-60x60.png (100%) rename apps/{www/public/favicon => docs/public/favicon/archive}/apple-touch-icon-72x72.png (100%) rename apps/{studio/public/favicon => docs/public/favicon/archive}/apple-touch-icon-76x76.png (100%) create mode 100644 apps/docs/public/favicon/archive/browserconfig.xml rename apps/docs/public/favicon/{ => archive}/favicon-128.png (100%) create mode 100644 apps/docs/public/favicon/archive/favicon-16x16.png rename apps/docs/public/favicon/{ => archive}/favicon-196x196.png (100%) create mode 100644 apps/docs/public/favicon/archive/favicon-32x32.png create mode 100644 apps/docs/public/favicon/archive/favicon-96x96.png create mode 100644 apps/docs/public/favicon/archive/favicon.ico delete mode 100644 apps/docs/public/favicon/archive/lw7/android-chrome-192x192.png delete mode 100644 apps/docs/public/favicon/archive/lw7/android-chrome-512x512.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-114x114.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-120x120.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-144x144.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-152x152.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-57x57.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-60x60.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-72x72.png delete mode 100644 apps/docs/public/favicon/archive/lw7/apple-touch-icon-76x76.png delete mode 100644 apps/docs/public/favicon/archive/lw7/favicon-128.png delete mode 100644 apps/docs/public/favicon/archive/lw7/favicon-16x16.png delete mode 100644 apps/docs/public/favicon/archive/lw7/favicon-196x196.png delete mode 100644 apps/docs/public/favicon/archive/lw7/favicon-32x32.png delete mode 100644 apps/docs/public/favicon/archive/lw7/favicon-96x96.png delete mode 100644 apps/docs/public/favicon/archive/lw7/favicon.ico delete mode 100644 apps/docs/public/favicon/archive/lw7/mstile-144x144.png delete mode 100644 apps/docs/public/favicon/archive/lw7/mstile-150x150.png delete mode 100644 apps/docs/public/favicon/archive/lw7/mstile-310x150.png delete mode 100644 apps/docs/public/favicon/archive/lw7/mstile-310x310.png delete mode 100644 apps/docs/public/favicon/archive/lw7/mstile-70x70.png delete mode 100644 apps/docs/public/favicon/archive/lw8/android-icon-144x144.png delete mode 100644 apps/docs/public/favicon/archive/lw8/android-icon-192x192.png delete mode 100644 apps/docs/public/favicon/archive/lw8/android-icon-36x36.png delete mode 100644 apps/docs/public/favicon/archive/lw8/android-icon-48x48.png delete mode 100644 apps/docs/public/favicon/archive/lw8/android-icon-72x72.png delete mode 100644 apps/docs/public/favicon/archive/lw8/android-icon-96x96.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-114x114.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-120x120.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-144x144.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-152x152.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-180x180.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-57x57.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-60x60.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-72x72.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-76x76.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon-precomposed.png delete mode 100644 apps/docs/public/favicon/archive/lw8/apple-icon.png delete mode 100644 apps/docs/public/favicon/archive/lw8/favicon-16x16.png delete mode 100644 apps/docs/public/favicon/archive/lw8/favicon-32x32.png delete mode 100644 apps/docs/public/favicon/archive/lw8/favicon-96x96.png delete mode 100644 apps/docs/public/favicon/archive/lw8/favicon.ico delete mode 100644 apps/docs/public/favicon/archive/lw8/ms-icon-144x144.png delete mode 100644 apps/docs/public/favicon/archive/lw8/ms-icon-150x150.png delete mode 100644 apps/docs/public/favicon/archive/lw8/ms-icon-310x310.png delete mode 100644 apps/docs/public/favicon/archive/lw8/ms-icon-70x70.png create mode 100644 apps/docs/public/favicon/archive/manifest.json rename apps/docs/public/favicon/{mstile-144x144.png => archive/ms-icon-144x144.png} (100%) rename apps/docs/public/favicon/{mstile-150x150.png => archive/ms-icon-150x150.png} (100%) rename apps/docs/public/favicon/{mstile-310x310.png => archive/ms-icon-310x310.png} (100%) create mode 100644 apps/docs/public/favicon/archive/ms-icon-70x70.png rename apps/{studio/public/favicon => docs/public/favicon/archive}/mstile-144x144.png (100%) rename apps/{studio/public/favicon => docs/public/favicon/archive}/mstile-150x150.png (100%) rename apps/docs/public/favicon/{ => archive}/mstile-310x150.png (100%) rename apps/{studio/public/favicon => docs/public/favicon/archive}/mstile-310x310.png (100%) rename apps/docs/public/favicon/{ => archive}/mstile-70x70.png (100%) rename apps/docs/public/favicon/{ => archive}/site.webmanifest (100%) rename apps/studio/public/favicon/{ => archive}/android-chrome-192x192.png (100%) rename apps/studio/public/favicon/{ => archive}/android-chrome-512x512.png (100%) create mode 100644 apps/studio/public/favicon/archive/android-icon-144x144.png create mode 100644 apps/studio/public/favicon/archive/android-icon-192x192.png create mode 100644 apps/studio/public/favicon/archive/android-icon-36x36.png create mode 100644 apps/studio/public/favicon/archive/android-icon-48x48.png create mode 100644 apps/studio/public/favicon/archive/android-icon-72x72.png create mode 100644 apps/studio/public/favicon/archive/android-icon-96x96.png create mode 100644 apps/studio/public/favicon/archive/apple-icon-114x114.png rename apps/{www/public/favicon/apple-touch-icon-120x120.png => studio/public/favicon/archive/apple-icon-120x120.png} (100%) rename apps/{www/public/favicon/apple-touch-icon-144x144.png => studio/public/favicon/archive/apple-icon-144x144.png} (100%) rename apps/{www/public/favicon/apple-touch-icon-152x152.png => studio/public/favicon/archive/apple-icon-152x152.png} (100%) create mode 100644 apps/studio/public/favicon/archive/apple-icon-180x180.png create mode 100644 apps/studio/public/favicon/archive/apple-icon-57x57.png rename apps/{www/public/favicon/apple-touch-icon-60x60.png => studio/public/favicon/archive/apple-icon-60x60.png} (100%) create mode 100644 apps/studio/public/favicon/archive/apple-icon-72x72.png rename apps/{www/public/favicon/apple-touch-icon-76x76.png => studio/public/favicon/archive/apple-icon-76x76.png} (100%) create mode 100644 apps/studio/public/favicon/archive/apple-icon-precomposed.png create mode 100644 apps/studio/public/favicon/archive/apple-icon.png create mode 100644 apps/studio/public/favicon/archive/apple-touch-icon-114x114.png create mode 100644 apps/studio/public/favicon/archive/apple-touch-icon-120x120.png rename apps/{www/public/favicon/mstile-144x144.png => studio/public/favicon/archive/apple-touch-icon-144x144.png} (100%) create mode 100644 apps/studio/public/favicon/archive/apple-touch-icon-152x152.png rename apps/studio/public/favicon/{ => archive}/apple-touch-icon-57x57.png (100%) create mode 100644 apps/studio/public/favicon/archive/apple-touch-icon-60x60.png create mode 100644 apps/studio/public/favicon/archive/apple-touch-icon-72x72.png create mode 100644 apps/studio/public/favicon/archive/apple-touch-icon-76x76.png create mode 100644 apps/studio/public/favicon/archive/browserconfig.xml rename apps/studio/public/favicon/{ => archive}/favicon-128.png (100%) create mode 100644 apps/studio/public/favicon/archive/favicon-16x16.png rename apps/studio/public/favicon/{ => archive}/favicon-196x196.png (100%) create mode 100644 apps/studio/public/favicon/archive/favicon-32x32.png create mode 100644 apps/studio/public/favicon/archive/favicon-96x96.png create mode 100644 apps/studio/public/favicon/archive/favicon.ico delete mode 100644 apps/studio/public/favicon/archive/lw7/android-chrome-192x192.png delete mode 100644 apps/studio/public/favicon/archive/lw7/android-chrome-512x512.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-114x114.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-120x120.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-144x144.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-152x152.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-57x57.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-60x60.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-72x72.png delete mode 100644 apps/studio/public/favicon/archive/lw7/apple-touch-icon-76x76.png delete mode 100644 apps/studio/public/favicon/archive/lw7/favicon-128.png delete mode 100644 apps/studio/public/favicon/archive/lw7/favicon-16x16.png delete mode 100644 apps/studio/public/favicon/archive/lw7/favicon-196x196.png delete mode 100644 apps/studio/public/favicon/archive/lw7/favicon-32x32.png delete mode 100644 apps/studio/public/favicon/archive/lw7/favicon-96x96.png delete mode 100644 apps/studio/public/favicon/archive/lw7/favicon.ico delete mode 100644 apps/studio/public/favicon/archive/lw7/mstile-144x144.png delete mode 100644 apps/studio/public/favicon/archive/lw7/mstile-150x150.png delete mode 100644 apps/studio/public/favicon/archive/lw7/mstile-310x150.png delete mode 100644 apps/studio/public/favicon/archive/lw7/mstile-310x310.png delete mode 100644 apps/studio/public/favicon/archive/lw7/mstile-70x70.png delete mode 100644 apps/studio/public/favicon/archive/lw8/android-icon-144x144.png delete mode 100644 apps/studio/public/favicon/archive/lw8/android-icon-192x192.png delete mode 100644 apps/studio/public/favicon/archive/lw8/android-icon-36x36.png delete mode 100644 apps/studio/public/favicon/archive/lw8/android-icon-48x48.png delete mode 100644 apps/studio/public/favicon/archive/lw8/android-icon-72x72.png delete mode 100644 apps/studio/public/favicon/archive/lw8/android-icon-96x96.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-114x114.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-120x120.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-144x144.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-152x152.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-180x180.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-57x57.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-60x60.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-72x72.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-76x76.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon-precomposed.png delete mode 100644 apps/studio/public/favicon/archive/lw8/apple-icon.png delete mode 100644 apps/studio/public/favicon/archive/lw8/favicon-16x16.png delete mode 100644 apps/studio/public/favicon/archive/lw8/favicon-32x32.png delete mode 100644 apps/studio/public/favicon/archive/lw8/favicon-96x96.png delete mode 100644 apps/studio/public/favicon/archive/lw8/favicon.ico delete mode 100644 apps/studio/public/favicon/archive/lw8/ms-icon-144x144.png delete mode 100644 apps/studio/public/favicon/archive/lw8/ms-icon-150x150.png delete mode 100644 apps/studio/public/favicon/archive/lw8/ms-icon-310x310.png delete mode 100644 apps/studio/public/favicon/archive/lw8/ms-icon-70x70.png create mode 100644 apps/studio/public/favicon/archive/manifest.json create mode 100644 apps/studio/public/favicon/archive/ms-icon-144x144.png rename apps/{www/public/favicon/mstile-150x150.png => studio/public/favicon/archive/ms-icon-150x150.png} (100%) rename apps/{www/public/favicon/mstile-310x310.png => studio/public/favicon/archive/ms-icon-310x310.png} (100%) create mode 100644 apps/studio/public/favicon/archive/ms-icon-70x70.png create mode 100644 apps/studio/public/favicon/archive/mstile-144x144.png create mode 100644 apps/studio/public/favicon/archive/mstile-150x150.png rename apps/studio/public/favicon/{ => archive}/mstile-310x150.png (100%) create mode 100644 apps/studio/public/favicon/archive/mstile-310x310.png rename apps/studio/public/favicon/{ => archive}/mstile-70x70.png (100%) rename apps/studio/public/favicon/{ => archive}/site.webmanifest (100%) rename apps/www/public/favicon/{ => archive}/android-chrome-192x192.png (100%) rename apps/www/public/favicon/{ => archive}/android-chrome-512x512.png (100%) create mode 100644 apps/www/public/favicon/archive/android-icon-144x144.png create mode 100644 apps/www/public/favicon/archive/android-icon-192x192.png create mode 100644 apps/www/public/favicon/archive/android-icon-36x36.png create mode 100644 apps/www/public/favicon/archive/android-icon-48x48.png create mode 100644 apps/www/public/favicon/archive/android-icon-72x72.png create mode 100644 apps/www/public/favicon/archive/android-icon-96x96.png create mode 100644 apps/www/public/favicon/archive/apple-icon-114x114.png create mode 100644 apps/www/public/favicon/archive/apple-icon-120x120.png create mode 100644 apps/www/public/favicon/archive/apple-icon-144x144.png create mode 100644 apps/www/public/favicon/archive/apple-icon-152x152.png create mode 100644 apps/www/public/favicon/archive/apple-icon-180x180.png create mode 100644 apps/www/public/favicon/archive/apple-icon-57x57.png create mode 100644 apps/www/public/favicon/archive/apple-icon-60x60.png create mode 100644 apps/www/public/favicon/archive/apple-icon-72x72.png create mode 100644 apps/www/public/favicon/archive/apple-icon-76x76.png create mode 100644 apps/www/public/favicon/archive/apple-icon-precomposed.png create mode 100644 apps/www/public/favicon/archive/apple-icon.png create mode 100644 apps/www/public/favicon/archive/apple-touch-icon-114x114.png create mode 100644 apps/www/public/favicon/archive/apple-touch-icon-120x120.png create mode 100644 apps/www/public/favicon/archive/apple-touch-icon-144x144.png create mode 100644 apps/www/public/favicon/archive/apple-touch-icon-152x152.png rename apps/www/public/favicon/{ => archive}/apple-touch-icon-57x57.png (100%) create mode 100644 apps/www/public/favicon/archive/apple-touch-icon-60x60.png create mode 100644 apps/www/public/favicon/archive/apple-touch-icon-72x72.png create mode 100644 apps/www/public/favicon/archive/apple-touch-icon-76x76.png create mode 100644 apps/www/public/favicon/archive/browserconfig.xml rename apps/www/public/favicon/{ => archive}/favicon-128.png (100%) create mode 100644 apps/www/public/favicon/archive/favicon-16x16.png rename apps/www/public/favicon/{ => archive}/favicon-196x196.png (100%) create mode 100644 apps/www/public/favicon/archive/favicon-32x32.png create mode 100644 apps/www/public/favicon/archive/favicon-96x96.png create mode 100644 apps/www/public/favicon/archive/favicon.ico delete mode 100644 apps/www/public/favicon/archive/lw7/android-chrome-192x192.png delete mode 100644 apps/www/public/favicon/archive/lw7/android-chrome-512x512.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-114x114.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-120x120.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-144x144.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-152x152.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-57x57.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-60x60.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-72x72.png delete mode 100644 apps/www/public/favicon/archive/lw7/apple-touch-icon-76x76.png delete mode 100644 apps/www/public/favicon/archive/lw7/favicon-128.png delete mode 100644 apps/www/public/favicon/archive/lw7/favicon-16x16.png delete mode 100644 apps/www/public/favicon/archive/lw7/favicon-196x196.png delete mode 100644 apps/www/public/favicon/archive/lw7/favicon-32x32.png delete mode 100644 apps/www/public/favicon/archive/lw7/favicon-96x96.png delete mode 100644 apps/www/public/favicon/archive/lw7/favicon.ico delete mode 100644 apps/www/public/favicon/archive/lw7/mstile-144x144.png delete mode 100644 apps/www/public/favicon/archive/lw7/mstile-150x150.png delete mode 100644 apps/www/public/favicon/archive/lw7/mstile-310x150.png delete mode 100644 apps/www/public/favicon/archive/lw7/mstile-310x310.png delete mode 100644 apps/www/public/favicon/archive/lw7/mstile-70x70.png delete mode 100644 apps/www/public/favicon/archive/lw8/android-icon-144x144.png delete mode 100644 apps/www/public/favicon/archive/lw8/android-icon-192x192.png delete mode 100644 apps/www/public/favicon/archive/lw8/android-icon-36x36.png delete mode 100644 apps/www/public/favicon/archive/lw8/android-icon-48x48.png delete mode 100644 apps/www/public/favicon/archive/lw8/android-icon-72x72.png delete mode 100644 apps/www/public/favicon/archive/lw8/android-icon-96x96.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-114x114.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-120x120.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-144x144.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-152x152.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-180x180.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-57x57.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-60x60.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-72x72.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-76x76.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon-precomposed.png delete mode 100644 apps/www/public/favicon/archive/lw8/apple-icon.png delete mode 100644 apps/www/public/favicon/archive/lw8/favicon-16x16.png delete mode 100644 apps/www/public/favicon/archive/lw8/favicon-32x32.png delete mode 100644 apps/www/public/favicon/archive/lw8/favicon-96x96.png delete mode 100644 apps/www/public/favicon/archive/lw8/favicon.ico delete mode 100644 apps/www/public/favicon/archive/lw8/ms-icon-144x144.png delete mode 100644 apps/www/public/favicon/archive/lw8/ms-icon-150x150.png delete mode 100644 apps/www/public/favicon/archive/lw8/ms-icon-310x310.png delete mode 100644 apps/www/public/favicon/archive/lw8/ms-icon-70x70.png create mode 100644 apps/www/public/favicon/archive/manifest.json create mode 100644 apps/www/public/favicon/archive/ms-icon-144x144.png create mode 100644 apps/www/public/favicon/archive/ms-icon-150x150.png create mode 100644 apps/www/public/favicon/archive/ms-icon-310x310.png create mode 100644 apps/www/public/favicon/archive/ms-icon-70x70.png create mode 100644 apps/www/public/favicon/archive/mstile-144x144.png create mode 100644 apps/www/public/favicon/archive/mstile-150x150.png rename apps/www/public/favicon/{ => archive}/mstile-310x150.png (100%) create mode 100644 apps/www/public/favicon/archive/mstile-310x310.png rename apps/www/public/favicon/{ => archive}/mstile-70x70.png (100%) rename apps/www/public/favicon/{ => archive}/site.webmanifest (100%) diff --git a/apps/docs/public/favicon/android-icon-144x144.png b/apps/docs/public/favicon/android-icon-144x144.png index 4aa46d4d25d141e00cd52afea852d9ef460c3425..a6af05bf04b065bdd2d430f07220f1b7020f99c7 100644 GIT binary patch literal 3243 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 N0FQNbY_#|P^*=Y2i8}xQ literal 3914 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 Yf3#Z=MKVGyyZ`_I07*qoM6N<$g0)0~0RR91 diff --git a/apps/docs/public/favicon/android-icon-192x192.png b/apps/docs/public/favicon/android-icon-192x192.png index 7583d2035e3483da2dfc1f9ae61a35944e2d3af1..2259b4d13104753461e0d324520d4d7ff4cba83c 100644 GIT binary patch literal 3599 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 CpIdeS diff --git a/apps/docs/public/favicon/android-icon-48x48.png b/apps/docs/public/favicon/android-icon-48x48.png index f8d8a7d9c05acae1a80f25ac81c3b1d2388b99cf..5b5a527f888c0dbcc1362f9fc9878b974e2ad5e6 100644 GIT binary patch literal 1353 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 B%J2XH delta 2213 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 diff --git a/apps/docs/public/favicon/android-icon-96x96.png b/apps/docs/public/favicon/android-icon-96x96.png index 0f1351f3670ee2e3629420bf5e152ec200846cac..d3121ca964ac870fc857c66a372d004620a78bcf 100644 GIT binary patch literal 2176 zcmZ{ldpOkV7RP_XXpCVqgw&*Q&1IO2k(n_ggfTI4n`EaLb1@^A!BC{Vhm=%uze|&f zE^=JvDeZ)!Cb_duDz#M;Myb$EvUlg_Jm+~%XFt#RW4-HH@A`b#TJQVE`{wxj(X}+z zYXAVC#qjnB1bxJ+sYAilyP&fbbkHa_rW*h>=OI?uYG91!cn2~8Ak7j0Bv}Bk3~ou3 z0FaCWfY%WKKq&_RLs9i_0aP%d66r(t0KRAE^>>01T;v^^1ON!VRf7PP)$71bn3%!z zgeg@}2xCJn#IpqeSYycWa0@>0>{ zJ)a>t&_i9YV;8l}UmjVmg;Og;$dj4K%-hPtBT_GjXXejZ&B#DFG{AZd6M{faMEcCW z8(d&VU7xs>%un%)s+wm~o>lY@rcZuP9Q=BwA~YkHB7qY}@0jxab8BTf^<{ofNcR&y zP3n}*Ju~$TAGsfdIa}&K9EL!9IfZ{X<>I%Z;(BK=S-HLW_*JSm)QBk0%=akoHcdF~ zz#8euk~mA<8#t;#hxs$>iVnE;i0S5OTCD8+Nc{~Lf2u68ElxVqhWX``KtIFs8o^HB zWo%9y9#rdv*3`KOw$%6!t+%mAN+k&_Ynrnx84lNB1KkeM!cq)oHl-8ijw$Zftn>^h zx0Z)~sK|*9P2?Ew_rE|Bi6m7jnMd)E^|W8q1Za2tNKKD*${ykrre5tX(&fBUs6(zH zWc^(|nJ#1+*R%KB$K0&p$cMTRY34U;2b7l!qN#i!Ejnm|ckde`Ty2+ceaTT7jjx!D zf*3ebhtd_rTJYiG*2)V;n^AP*eCmVf2ZYZy3f*+w2>h93GJRU%F1bsSCDyYq--GV* z<Q3&7&^`}&qUYePug@E2 z=F#W?8R_OG3%H)&xnjRK^N|-V+8BQC~aymro<>;Y<&q%le5j zQ3)?oAv#j!Dsp*9qSJVRl{>jq6ut4q?qS?gJGT(rgIKuD}eEQ#)lc{;_%D%t`{*;h6T=xNJ;OCc)XJKIM!Q8WYXB>H1Rb z&0oten(5_goJeh0*d;r*_VL{PAx{_UvnK|sley0VoC!>|KI$aGFso?}x4kUCs$Dkw zWpT}<^IQ&H|I#IPDSf%y*jxLo??lw`8@KnmB>bL3UIeV-tleGJX{H&hKe`wx>@%%Z zZt}O^F3RD{ZT`iuQC06#O*i{r961*=6K?qD6*EZojesoJ;{K4wiAFNH8*bDSN!l7ZDV8szYrdSS`QvpA7GUkF7=B@0h_e zN`umA1HQ)e#cnWnL1Q!yl9&P(9i|4=EEJP%DfDi>=|?F z_+Mi&ipYX3C^N{7Cp9Nx6ygyRoqV9zF=g?vHZq0^Yp5RCG^Og26efdOb(w}Nb(OWt zBLaGzy;O*lD+|FW4lLx*Z?XkcQy>`~yL>ukX2&EZYNhv60i&Vq&hF~@kp+$tlEIbG z(iLy?@0~Yd+8ca(MDH(q#k{i=+auOa@4NZ&+xE!=G@Wzfev>+zAK%uW#0nm%ZbQAm zLNi<28TA=`WX$VZ+eTgW=FK|SlRFb2y_n&n)wDJ7IE!OdX^C&95jt*)I*HVT=I30d z@v^W+N?v=!xObCVl9k4c`6Loic_gYwP=tE*UYdHq%L!(&b%8ZZr7Cpf=Bjgb4&c)? z+-twgg4*Nnt2{V7tsF$_5LPVq4l`< zWIUcsBH&$@%ez2C`-eI~!ZaR$b9XPUb(sTGJAX*A0vP~b7{ddPj*X2I$HYfr`Ro)S zCq6C-``;_ak~jn+j>pCkx8NPfI0rTnM~)=$9Gx7vkz6u~%e4m;_TYTv{VnIg4gkZ` K&!f>jBJ*Dw-HgBh literal 4447 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 II1*F-2EaTo?f?J) literal 3914 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 Yf3#Z=MKVGyyZ`_I07*qoM6N<$g0)0~0RR91 diff --git a/apps/docs/public/favicon/apple-icon-120x120.png b/apps/docs/public/favicon/apple-icon-120x120.png index d2b0e50ef41fc56539ff0f7dd19f272da7b1738e..abb84bb15d89de2dc81889da745e54d6ce8a81db 100644 GIT binary patch literal 2643 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 H0e9n{gH(gy literal 4299 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 diff --git a/apps/docs/public/favicon/apple-icon-144x144.png b/apps/docs/public/favicon/apple-icon-144x144.png index 00a5d8b51800f0c80c7245d23d5e98dae278f873..a6af05bf04b065bdd2d430f07220f1b7020f99c7 100644 GIT binary patch literal 3243 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 N0FQNbY_#|P^*=Y2i8}xQ literal 5379 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 diff --git a/apps/docs/public/favicon/apple-icon-152x152.png b/apps/docs/public/favicon/apple-icon-152x152.png index 310532c4648a52f0f8282bf695eecd92b0fa18cc..41f8008da33d555f2289699af9a2426f592c38a8 100644 GIT binary patch literal 3442 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 literal 5816 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 NLkDgMt5>&={2weY1h)VH diff --git a/apps/docs/public/favicon/apple-icon-57x57.png b/apps/docs/public/favicon/apple-icon-57x57.png index e7b08eb605f67ebc1bccd7e8894fce3f7e66749c..a4bc19b9c0f7b1b536ea7323706e2a70aedbf3db 100644 GIT binary patch literal 1498 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 B%J2XH delta 2213 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 diff --git a/apps/docs/public/favicon/apple-icon-76x76.png b/apps/docs/public/favicon/apple-icon-76x76.png index 9a76327f94bed655a4ed5081cf8c36d9a68559ed..2abcb5eeffa69435515c5824334fa1bce5a44e08 100644 GIT binary patch literal 1822 zcmZ{kc~sL^7RR6L5Rg-ZU=UdZEXtB!79fcf3=K$x&;TIM zZL_m+u>kL{MHP$x6&Wul{kpa*t5yotDIQC#iC(r=cw-JE-kp2bDK3!;y7ux?T;(^%UDtsqF_GRE)7OilfN9h3R8n z*J18%a}Mc+bf@@6ICTnW?q)6aE-juB%w2 zZJi3`o+lQE6iq&OP}g_x?ar?rUQFkOExo&CH2l!x2b%4$C)r!l&m@k7i=E$8v2CF% za~NQDW>wl?V4skz0Y^gyQ>G2v&nqw#go9K*F%rd5(D#nJ;y$Z99n@jXRG3cHb}-G? zoJ6j-J+$eby5*qdE;B!V=cq09@8ju-$sWB;zkhS;jE0uLIhCuD-BV|PGFt0%6FZ@_ zS}ROZC6Ce(x=zhI`x+Z{R2IY>sLw$_y;HQ0Q>N#39IiT%15I3!`hPl3LI3EIe6;KC z)a^unQ}12h_blA*=*Qn5Qw`4pZlQNld=1aMIQePQgN8{5Im%_vk-$!f+3&bzA?kpl z`}>p#XprajUEp%2U2lREH=->WxV%B6$3I`z_AR`xcEY9U$EOlrrYaPu8m+1rxoLAG zbbYs5D#tBGrxgA&Q&5w7a@t01hb0*+@8hIR+l@9C^D7Q>XIWpO(%cNw*vJ6>y76eoxGbq@@%=4zj|neusFVzUXaMQv znP><+#^YUhlAeZbDXlnCq{*M?|NR+zvq?bI{QapR6<(jSpYo>8_SyOuzOQqe3np)* zSAEj$uWpm`Q&5N)^JPitJlBXjwAG_(>-vV?>jRSOGc=4=l9kt9^w+RC zsBB}Uep{Tq<#!DICTHtG^>T>1`Pd6pUxKdI$tjDPX0`a82}Hivwm2_%37#@~@A{VL zT~B8^ou_-${!CllqLSY#ILCr!l|#)4c~`lT&>uTVa4INmR1$Z1Ceu615Qr{DNgVpJ zzVa#d$rw}`%K(N7t>R((wQl9OPIBs6KIZDqdXDKWokAjP>GGz#Jq^8BUs-FSIEUR- z{VFx{Hh#xa=&8#7+{N;*<|jtT23DJj+k>#yA?NT*YWf+QUHr8(f0;-|9wV7sAPY6D z%FhECUzhAmBVyGK@i7|;2-goA6XLl@rXwP&{0haBa%9Qm#OAv*HhvqwHd4czlG5%t z70rd7Udkx*p?7ALPpPGI2QLg|S~n5`$`&{19le&9wzXPjcQ!oo7$|BT^hIN8w9jh> zB=$cLLmIzTo_09@Hp(?ztcC zs^=rEeJ^R69(CsS=&43*6W033*tT;|%7zW>qv~Oo)PGcr2fO5~@ptEldIwnUrgiMa zNAKc{;TFLS!4cHD8e?_vr_|x?76D&C*@L$7Z&uyb+=}P?>{?|jZ6CtpE(~gO?$)zt zhhDcXPR75IWCUGt%p4^b(@OT9KygC8wFrvziv894`0koEEGLKU^EcX$S;Qn? zEzRX5ZEwQ!QI8?7n}#sqAM5;s{)n>p$m}QhPxFyQCd)Y4GA@ZN;ld7JAuK)s!UkXo z3=D>ZgGgA69|Vyg=#sKa`#%Dam?Pxv{r`fIF{CXl@K~8374u|8*%B@g$Yl9a5*jTO zW%IeP3E8^>#S;F7k@XEQyLN?T2nt0k5{V*a7mB!fG7^anqf&r5@%}vePYiXX3yBoX z74ii#fFWYHrWYi^jPnP5{=@7La%6%PWc;M36^x)hKxje{SGG5w3;w+oIzNve-p!2r zQy&@wrT``cB4RK^0v5CNt-2pZ>_6y}DBQ;dP((y^YuGcm#QdO?lt2YMVJ;WGI$D$` z%N6s{yzJdVwm46U{_m5c32ZDL;$}nmU<{53;j-}%k%i?3h2S_W4w1m&1j33yct2uM Rw+5a7sF87$u86F%e*sPO<3#`f literal 2412 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 CpIdeS literal 0 HcmV?d00001 diff --git a/apps/docs/public/favicon/archive/android-icon-48x48.png b/apps/docs/public/favicon/archive/android-icon-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..f8d8a7d9c05acae1a80f25ac81c3b1d2388b99cf GIT binary patch literal 2568 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 n8#Cn*%cygYC3ji?9DsO!2mfpBm*4#S1AVBI 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 NLkDgMt5>&={2weY1h)VH literal 0 HcmV?d00001 diff --git a/apps/docs/public/favicon/archive/apple-icon-57x57.png b/apps/docs/public/favicon/archive/apple-icon-57x57.png new file mode 100644 index 0000000000000000000000000000000000000000..e7b08eb605f67ebc1bccd7e8894fce3f7e66749c GIT binary patch literal 2869 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 +#ffffff \ No newline at end of file diff --git a/apps/docs/public/favicon/favicon-128.png b/apps/docs/public/favicon/archive/favicon-128.png similarity index 100% rename from apps/docs/public/favicon/favicon-128.png rename to apps/docs/public/favicon/archive/favicon-128.png diff --git a/apps/docs/public/favicon/archive/favicon-16x16.png b/apps/docs/public/favicon/archive/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..fa07282ee8dae7cfc9990b821c3e549f2d063b6d GIT binary patch literal 4112 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 literal 0 HcmV?d00001 diff --git a/apps/docs/public/favicon/archive/favicon-96x96.png b/apps/docs/public/favicon/archive/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..0f1351f3670ee2e3629420bf5e152ec200846cac GIT binary patch literal 4447 zcmaJ_XH-*Lw@suM2}lQl5RhVogc=B4qBJQ|OlZ;)NQ97(L@5GNEp$*o#fG48K|rJ^ zk)}dG<$?x5q!%ecL691O%ftI!@ArN@-x=eaz4sbx&NWxrf6f&r2dn-3GW-AlV84wu z%6V_~{rU28?|mn)ha2oI(zIh3nhPnA7VbyE0W7d2e;n9`=of@@#`$3*!(QWz0RRp) zf-8oGu|I(fAQ3hFe)?!e5XpOJ0KnKRg6tO%jH7}5aY2Mo6UevcEf6pPYXU***~9J0 zmN-1YI*NjGiE?lahzbrc#6rwW!Nw8DJpv+*<_C@-hJ;d)5hjqod69ejpJo^Y{I?4& z*aY$)Q5btCuqBCt0~>0>H3HypI2d85sfExA&_)FM`5ysm!?m?xa08f@zJ|6oQb!M| zs|Eh&f$RmOU;~lPsN?^H+dG*+@H84334?`)hiiuGXp$&FFfBtvLl|5ermd~9=b=H3 z45j%+XoOOgelehM)Bp;BOe2s&!9N-O{7GkNCXhX`|H*<#{+BkC`cI|yY6gq&Bg3>b z;XkwbP-7aD-GL771INHhrqEK>KF zE=m_+VSv)p)zi{ChO#(jp^bv0j-igCEZ`^uyt2dGCIxQYM`usT?0|w?~p`73lHGY0RUtrxU zc%8#?QJoI%TEgx48~ugagP7=0sXvW>Q$ zShmbvZvlXgwU6rU`5~$k<;A@(3yDBqebx|ze+jpA;LwgKt3Mt9zfH?0Z9jVW_?A{P ziwoeOwUISCKcw;H1v{4Mr~_O=D|IMHwN*=H$eWZAf`g%zr<*)n`=RRU7DS?kisPNM zKU_*62Zca0+B`NbfpHW3tsrY3*-r7EJ0__Wo=^Q}yKmzO1dH%+#1kj)*$2FeP97d9 ze4;A86EBl7Pq2KUO=nwC%SOz;P=Kqfx=Y1JC~@F1@XN<4D^JgY_0;P8C765H%k`Aw zMRN-a?Q`#omfJ)f$5|zJ8J9(rxDSA4a$+Yr$I->Xjb0Pqr{6{_Hq1Vb**bSEKVM0V z-#fopKC|O}UtjXWhboUep9&$yqH8|7j4AHqiN_sgzG58i#BYm3PxJ=hqjGaB_pV{B71EIyz$o`YwJX$OlmSx{tTsLx46RcGo}xD5>rRYxrQ zdp#ph(5Itef-hK`vZTiN8#+NzhSRc*`xf6~qa~WvW;dFbdzVt~->a$uRW;2RUiIk& z9O)eBx>puuiOQ|rj@ao7}0Dgf1NWT1qk4q{Ctt9U1jlg&Wkx0z~u6miJXbaPaYj}6stCz z3R`1GW_?CzgYWfcqCS;xDcbEzE-(~NT2=}xMYutplwFBF9zQpqIF|t#bOjma9N=*K z0r-64vOhLbIJ=JuE`KE~#=)C|ZFS){(&{7u43PxzYN~$n(bjj-&fgll_;oI1`$Dioj;vSajz&C7R2> ze0JUft;aq-Aa`1-ytU-s5!+kee=q_5J;NOCMmY(UH+c>w%$ zO8@>WXaV@Xb4_)qmyN>1><8Jg{Bry9k4u%Uo2Vvw}6$_sh^28;E#&vBUk-jh~rLl8jE!wWdY9L<3xi zf>kvKIH|qh!D5|up)0g>Civ}!-){Ki!G%{5Z@)&7t@PF2vB`n+ zRLPCH#QxXtu^MJ}e;QLZR`Ed`8gMcb)6cuSb`i@^%4ukNOs+RCdoS89nNy;Ij&CZ} zzrp3;h}b0p-~PFEyF7su!{?O(CKsaL4)cQmqaEJ5(r=j0*Q9*;9<85Bv~Ei%o)suq zzIq4tgA{zdHbAQP$Y9P`US3~zv25|XtiRkfPQoc0Xx?+{(_a@;eH|iO{El4fTUopJ zP^R%rkxWn}==?mM!@{6(l<(q$Ggpzx)&w8*9D?=SZIu;rjFpSZ1v)UpL%vw7RxbBj zY<91%Za5TNb~F+z!|B!tkwG{gh4x_#N7^@qySq#dRnR;+RqE_mN9_Z_^;zk)VJDd@ zmc)_LPc$ir3Y9*aB@5WR;C4Kh^+6`)P;o>P`GTW?kI@QymGPA6G+DkQ%U5J4i*ujk z4r@B9j{ox;NO3^qJqO$=4%)g2a!)MN7^)65K9y)xhDKcKsg=C@gg<1Iw0w@Wc{W)- zqP+f~C40i56xTpno#qDAJ0%?+QCcvcWVmNL$9oLzJH;a@L>KA)D~qaOO%P~RFK^{b zIO~QqdZGa(CHL5hLi zB7r0|;m37pxXGJQBDwykD<96=NppHUD6BD&db)hM9+4e9szA5B-e?;;cyXW%QK)Ml zSE|63f54y)a?Tr^aZx6`E|IolWLNuq_5gR?!08KiDon@O;~Xtjb&Rdao6D99O_ndW zEQeCS!tdmge{2-p`8Ksd6Z3`&Lje7{`|2!qM5K1;&qdReA0Cc8zo3w*xXo@?oZ2ZQ zSy82Z7I(g-n!JZyHFC+)$*qo}CkH;dhLym7T_`fcD-rwrTglcI+sP;B46^XUknal zEU1N@?}LumO(_fB(rb77Kr~IssX?z@qe?v(SLY?Db$X=O*uAUxbnbwX+N{ESTFEBh z-4n&WLoqq()^PnWA^Q1l->;Pu0`zu{IP;tY6#bySH0@P~rr+=v)ypfnjSc1WXKJM_ zua533OpPfWqY1{3Za(H7x&Jny_-3aFA9OQ0OM+)+|Cb(B^=)xsw9EY}y)m?% z`do7izxbBXcgUQCpYY<{gn{u~g{MV7nojYzve}rl1RnFY5#V^t@OM$P({5C1EY$YS zU(yyYT(ZdSz-TMaC5jj##5BV^Gxm~avu%78fHe>oUvJi`u;%IEw2liO(e{ey`&Tk0e}C<#gdn!{8po_}7LI-D*WTt2qT@3w1DG!`T2{QW+2Z8Od@7dT#G zUvfJMjYj9UWIhtJ9!6e=U4XvMgwGIU<%=%`mlOYy~lFqhPwRS*xgFjZTohi6oJlka(Ay9&nF7GB| z3MAS%g12+CR-^SzdrrZLQzuW?)k7Q#@A_SJxS>nP(KibjtR)P#%DA~zc~0q!t+@U% zKYyn2`y1$WvkT21UCi|TtB4s=Jr`%$b9Vw)&z?Is*)HjWqEdAr*_ZRwmzNU09O}bX z1r2G%OUHCp&M*YiKoS9Yr?-U_w=QF4Jli{A)Bpue7{}(xF1xn#rbogZW=yJ5Fd1Hkv&d z1;z-5cRlqyh1Foatt5n86jJTEK5XtWF|>5kcy~JX3ol3`P)NpDCiEidE$}tE*fBfQ zE<7tgI$Jeo#E#xwqTItgfrMRMZmI;7cPYl)Srrj`B`5w#vRnRw{g3+DQw(r;Lxj{a zh1p&#T173QhPI^Alvw9EOx(Su^pza_rrC2FvhA{&jOiEejD1Zo*o!j{(FoQt=GEdY n8#Cn*%cygYC3ji?9DsO!2mfpBm*4#S zD1s=2B&dhPgB77kK+Hx>T6@TbgeFb4nb-e+@6FC+J4ttTXEyUCe`e;*1itV8|M$N) z{3CD#q?9Q-43S+V>nF>ixwuYNB>Pqf@fCuA$X_KZ$@pM}?Cn~Jr^sexd@)0o^>P*- z@_b_k%}50UI9$L-|s)Rx3{shw1j3Nm&>7}qvNRCvm{`EPm}dXD}De1|MAH2>ebb=be$Q ztu6HR^&yU!pP#Ru*hP-OdGE;b@-pIz#l^+yp{#`nu>a-@xbw*+*w1t#YJ@JJJe))M z)n_5Q+ekncqDH6!?0h!~$m`Wb2uS*g8lef0J?$vJTOi&7LMdSK0#PFz0c}a#`>-G4 zOgk(VV5tzm?tT){|j(`#(qK`ns0_5xGATK|!LP=|iCT$~v^5Bog z1Z2~Y-VE0jpV2Dr~V2UDz0ZS3K(Zt%$VYDLF-|nZYuG- zux&{Zp=HgsHEAalwydlhlCF233%>OTCg5xu)|CP@cSA%PPAUR$a>Om6%EMX&4_W%I zTBX%dx~p~j!v6@0KmrmU3>cE`M0LbC^Mu;>TV73)fm~zWfgsf;xmhPhKhgAec zplU7JlX{{`69Ks7g@=3v(jlm1sB?~luC}&0(*N$1@x!dVg z*3EsLV5y(}L)Y9o>P6rxWKaK9^Row+v%rOJb0tkGIb{@hqr1vJ^ zDI%XNg_HMQL|R5q-`K?Czurd6&0Vxo`b2?91tfM4aOV5Q7OIDVQ|QnZu(!7taYa6# zuO7P20%pAR16bgtNxLf1Xa$0>r0E0Us$MmO~4(7tGCLc_(fGOy9O$FQuiHiuQ z#pKhSDRKkcGVRKbs_$}7irYFIx|0H@GIQ|hk1-VIn%k^C&4oz86ZV)4m?Ovc^NCjg ze;dK=rYz!(BG~{5;G??|n^YQr&!mnK=AgUu#bcl1)~nPXSi}YV;mK7$uHs=rpxdxn nvKP@@@B%w)Y|8mIq8j%BbBSNTBUb6v00000NkvXXu0mjfsdaiP literal 0 HcmV?d00001 diff --git a/apps/docs/public/favicon/archive/lw7/android-chrome-192x192.png b/apps/docs/public/favicon/archive/lw7/android-chrome-192x192.png deleted file mode 100644 index f0a2817a744e09b5c52e48aa7362c2921eca0380..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12699 zcmV;MF=Wn(P){4ywWgwDQu9xy#78DzRGLHurJHU^n}8T-u)6^TyScZYxBH%z_4;0G?|b`p zb2;bS)9VMf&pG?C_S$QI@9$e{BfP+P)vI1Ld;IwEEB)6Q=iIFSba@x5@6fT0zUxnd zJ`bCwfquX5igvn=jcEM-en&eU=b$++UFT%yb=?<0`+lI~*ro1Yw;%VFeaZK;N?1UE(2&;^jzx?Ib_(6P&@BB5c z-@nq|&CC*qmJcA^JQO4CIVX%r{w=#)8pE*5XJ==;1o^Q48vZuxec{10`GM0Wece+bLUnBX zh=dfR7ApEk510<`f)JQL)Gc!iluXn*N*;DW9G#k^JVzs5OcQ7RdJ>f(W0@(Im`f8n z6Lrv*{*&&B+aM+&A(6gzX$xUAY2QkCwVl55^(@y~kV{{#Q^-M*ojQhEU0kCHUY**m&ZJc5Z(9a_R>iO~;C=2dt+yl96ct|ov? zTuTymse#me2(fi-@3^k(YFFL9mfT%ZoQS-OFlfJKQq1FlUBoFuBD5F?9}D3Dd3@si zmHjE(DHvrrVb(Q9on|55i|vCR67wY<)-+$7oSeMrp@$yY4X26IVge=kKjQy3L4Kf_ z7+aD)c34hN1gr*e8N%ZxXh8Bnb@5KurdDQmQUNklgpKhpq0P%om~--9%fW zb~M!LuWm#!m|>1AXj&RVwb4naZHeBcshtuYJZ5ws`k5ImLwzO2Q_p%CCIdzMWuIH7 zQ>L46gxjPKgOFyX>+*@F(2JQaej@#oe&5u)xHxZ>sCF zqM{2VD7C;0-vcvDO-{mu{|pQPrREZU@TODI3M-<tbt?4jztDw zXDI*0gDUY?oF+6w&|g4ch;{4MX=Wg^h_uBmo)JE}l53olDkB3R-t8N|vdgACdh}>y zfY?|j{GiGz!B@NxD4Ah;Y6_;Or@NwPff>H^PmezOzLT{%ak2w8Z{B>bXM!u~0`wW| z{DTJ%!if_nBEe^ytujEx3kof015S9ed%>IElU_3vbQesNE4OUfGP{5O{;w|A=CVxi zvdbM=PZ$Q`zl>`|Eb^-hDuy)0B;bOfaTISmGexfKSE4kt0WH zG-M5i~7(9PrHX zQmqY)CWysw1p@?*%KItANF z?!7iJ1%w#1fpe@4SQB_czur+GC>-w3IqJiqIx$gEvDOgi*9UdTwjrr+v;kAM=a}n2 zX$Bu^a+H9mW>CdiMyP6Vx{N(pM(?KIkqJUxz<F0%Yh<=d)xordbUnb8^;zFsurji8)POxo}2DT-3$0@!uQAoKDYd<*$;>ZP{N@y zK*hKqR-I-6?_@I0yTZPt2>{*#G%e5*{)rG)f?EGyFS&Rk^ym7Ei&YC$j3qP!C<9yrev|Me?`SugU$W4AaS&Us5;ISpA{A33G$2cg1H=M7JrbO}&VF~;bU^1bknS!2HP!Kz`p*#K9}Tnn$*@NZy4??PDU&%^FRcf*eT zUx4}J`=Da*P%nRppCK^R3pP>C67ySKDxNnQWFp1OfnzR2c zTz<~G;J#n}FWB|m|E+nMK|_{Ej~{{ld%-E-YNCqgjWCQ;%{lPS3%>xH@e-IgJ_(JR z;P(+ZACOqY<8bwsPrx(BegaP(*#;E@ge<+n+=^4>c({EaZ3G1q7dz%O8_9M5Po}8Jso(abJ4YHSmT_AB5iGR5XFo3+s{z zL@$et-=Y*kSdW`yd2iJQ14O2Enq3xNHl8#=3XxW)_%soS_?+Ga@a8Qahe^)>6JE-b ztBNisWT&aTD8m*S-0KqE|K^*vgETE&py0o!AkyAt<@DK`p=LKJY8NAeMfga>H zI`E%)WqAJWh)L=Mrh!6@G#8GBRfUk91jORFik0B?o8J$cn@eHRO{E|M?LhTOGnSAn zQ3rrk-V7R!UM#OxW$g8nFW@+TP?=!GNRIIP;k6sy>qDVEZ`?FV>gy3C2FNJ))3{d* z3={}uaTGNH=Cwz$%BEAo1?%779pM|IBRt^)ZT+x#jWU0XGn`Ez)&yzdMrD9OgQv_O ztv>`&6JUO~6R5CJ#nOn5@Wcgh&AB(iq>uOa++^I|gn>Fp*T>S0kP-gP7yVI+1i4;8{Ei)6 zmlKjX_>;-JFR2++BByGBfkQ34WeVsVl~OwqP4($01cHD2i#`LJnoFV?lr~C91pVgY zY34RXfLQvc-zINR*LoTXP?b+4$2e_G3C+p?EnMv#;qxc2h#6tTMrwhuNPe-T2R4TS z60@Xl`dC-Zp@Adk2lUi|D6<^b4MDY1HNt@X%FMrq*KT}o%mq+JIL7|d5(QEN#3#Az z7=x)Hiu)Thze7}Ms@VV)1BA+l(K9nIB&!Tyaqjfx@a8R_NTJZ+2zMm6h|q&LQ86J& zjBzNGgQM9iOGmEjZG?)!flYpSj(N$IiWW9ZUI=eH|I?lUCSyqi6~F1wXIUPhi{zrV zKnX)owFU;3OT|v6PIvFL;#gQaAbjqUWG+XxRfG6 zm=-%LOC~s?R2}0%g3KUEmVu23smFL`f~H8GKXrv?fGOa}vT|sxt?!JjZ;hhNG_Kz^ zjfh#QCKx=VS~?EA@d?iKM-hneUv9eAC&WG&HNXT;7|G6#Fv{_%60|R>A)7kvD-1`CQ1(PPw1a7M2{7X~J*74+tFKM^%Rm?W>w7ba?unPKeaGNU+ldZ~26 zA?t%Yt!JWiFvj z*K&-5BTVc-Nij2HjO?a(t}FZmNwn2@d_x0`e#{YYbcpJQ&LrK;j_~FWdJiBlzyuRA z>I@2k35k*^WTHgIGy-cnWz)wg6X?tmH6w(yq6*~9F@{2T$`gnNID>R^s0_Vo^9?By z6c`{Q+U#WEH)Vn>9l;R>ltMZ=F6RdFIq{=Wr4zZ0$_PV12YC|{pjxPO>_LlVg(;F} z;bzVVr&8!7#wpq5viIavKu3>LSxDzVOimq6HO%7@bHO4cW~+|zU_k?(1wJc%U0OQs z2xIW3^F9VMy-Okkpbl9oA0U}8{kG`?Iy_3}iuogEkb^Qe;B;<4F-gThfuKzPIG^B5 zTl(Xwb3XttJL|2<55NZ6p-?9iV{$f_6(v%H4U`F#n1{=Oj6Z;;Z5<(szpEA)DB^oK z$nt@t1!A6nm!U{U!MGw2ZFp-;m?9Y>K_Mf|K~FMafP*<~!cfRGnMR7(*{*jse;^lB zIf3kKE9FrcVDLZ@LD4o1j&YNBkc|Z6jJRm-c^~%-kXDJ%L>y6=EF8l}H8ds^TAD_3 z4rvhfAsQ&mDd0wHo?x(W6bQ<53wjXVW6YkM8{5eBx`~a^5nhj5yawor{a@q(WMaHN z+l5)edt|rIjiXcw_w?&8@)_aD zOHxThhx9knU2Ma&qJ)_d)^9TaX@^FcO{@iU+cNyxF|L|maKPjg(+m8==!LhKaD_8u~h< zEkfa5HHQX>9Hnqhf*G7FqtMYfDdvq+7r|T3zbR^f31~n&xLorC_I(1Hz$vm5w-keu zJ*#8_<&p?$Bkgw}c?VS6>~XYIer1FKf%0S^A1OMNQv7M%p)p~D>4^>Sjtf5z>nFCv zgqR~jRJ5k+|GCsb+51R^a@vm1XR^HyZ3ZwVPmzGri*`X%iGR?@l>n5+bipUK(IE*N zt!czXbA3iQIKrtULcfm9nb2f=-mlCHKt=3M6Sj#2fyyZW$l7KOK(`MnQ_Rc1*67es z5T3CU!?+hXf#w+C7?e^+M|jKo;nf@86XymX7s_JGRMF-M5wl44R7RKn1wNj9V`D;@ z5ksDkZx*#==}#MyL;jnyx5Ck*2VgaEIxLmhHho9n7n<^h<*wj=9z4F!|2+whAG`;i zIDF5@GPW)cB4XETkrGL)Sw;vqm>l5`L(KHG&(>a=O z^oWs$>CPvlYeiG5--mV6GceuT*m9^l#ZlK&DcXf>*t#+ZrQ8#xtDqDROSM9>ELIfoPD58w#G(KK66%EsT58Vut zJa||1SKqu-_s~J8#l1Fc;?Zsu(#3L2l0Fp8iI#z=?J%9xlaf2;;G82D!M|F6Bb@up z<#6B6KRsHE;GCxSc*oHkLZ`~W)~J0NUZeVs3qJ>&re2~l!gNpSU1Id`ohG_cf+lJZ zSIL@99O@+cq_7(%X28PKGDNKjGCSjqiXLgVgS411o;At1y=dct)lPYPDZTmJG%$1n zq#oln`sx}SJyTrgil~?5M*Pv!{`*<}?}&rfOkE386X(F+K6%sV&{bCLF4?Mic3HpA z!{m%1xONck>vcXM79HW>2bc#2^3au}Ma2|sE>X=-+%Coflv)C{KoPr{<{wDegqGe; zy}ztzEB~h#z+r~K!iOo(SN+oY2QYmDSrIRffpe}s4hUfV9+w!Rh;Rvm(RZ0w9p@$m zM%d_YW=jJvzwo!$@g=wN0#*{9W<`hUD*nDHcP1#RWgsTbGo=1(jRvR*A$SdYC6Bb%PGaKrA z;kM=8@T>-=HgAI0oHsJsAax?ID$$STP?G+90K(eQ1fewgnit)a7@(Pu-Xob3S~@9- z1xmV>5>;ysEfI)lqW)aM=GVl5Xv`n0O+aZMxgVz)Q4^gi;EPcu1k1QN>E?vx(!0|P zBjr5}wzko6+Uzl_XQ)1xrkT}9PH{-y6U?Kt5nk!dqESGHT;W%^c4&#wMtDf?xajlV z5xyij!Vy-Qw(Qt!@_6EXzIt7jcb--L@=Vzr{Mj^iaA?6eXYY zYzj$Y#jQxvO^!u8Bt?Zjqnky9TZ&-iPD1=HWL>dbunpiuOMV+HL1tX4g z*IgbR;lKbqNuH!-0H!sASW1=zNJLc-F#sy5i@epCJIfGrr;h-Ta|c!$%e&N}qyOpx zNNX1rH8GHmRZJ|xtvuK9@-htx0Vm9yWjG6n)@pgh_1nw|W}Jd=aI8NEL$8>n zL=Y`U>XksRpLRGj^#L%F%n&ldZ-4P;I1;3z6na>len7M>AJ=+dnJBfyBjUz_5$uCU zFfZo-fObJ1h)EEM-gO=Wt!pIi&=I3D0moXa5r!4!*9_};?QwfA!i9bEaT-O`D*Kj> zMAIhmZ_$9T`{q=vrm1~%gC^qsEB_#hSvsY9BHu9066rEb+o>jrtrc)2c(O{s~H`^U_}_fhy*x_?SQ?fb!Nu`1#MyRT*Y(}graz!HUQ`W#SgBU%-V*543I6>XnTsktoSNzn277zjpS5W$iO zui4Iu zeVCw!{-*Q(OLT-I1Mmc~G{_B-O{*Sqiy%Mt0^VslKPH z9$T1)JMQ{VaOBw2FgZCn3ONFZ%L=hHN&QKhU<6C3U$Nnx@X`%$jTvE)Y9Peu&97%#V*7^Mz5y5sCxl( z3>_gN6e2;PH%$W|N&GUg19>|XjG(1=hniR4jh){jDjk+g7qw=UkR&;b07dnQA?#9X zIOTwY67TvrS0t;%xB{@rJLnh>A%4{*L%_tqRuiHb1IQZJacz+fA_$`(%pKeVcYp8q zA_D|1FoFz_C19c@dS_WK95RY;Xb3$yZ~9d>nm`gWt6(B1DGsv_tCh?GVG0C*B}*5; zo}&q=6)jRrrzAQ^Nv*QHA+@6jEfWob)kKbh6NX@=opgPa>5jQg&WIQ-C^-VTkF>88 zBqhV?K!TjB#*3G7MWgl7>KP8cdgpa;Wia|k0KFT3IZhHMg%+D4@V zkcgKLQmVKpH&72^WjO$wL?7>R_beT$^Do36r@Y{i9cgZ80D)vuW+7 z?>CKyM5?r=ivJpi8d{8shDnqz)uv=oXUXI0w}0>cPr~6NPsK>kC_|b3jx<3Qu};aU z;o|7xoFx`v&5?*rCu-rLuoRo z_>tCN%H*&FstXOM&rlF1aNBYofOf)5+n+2ddz_3<()NAfNK`ol>IrKVx!>{{+N=u4 zKl{u-!uB8C7B#?#`T>GGNOaFMv&@jku)7~R_sr3U;OL1tHfN-|Q;F0}G%i128>ta! zJKlyS9kgTPQYfdd5zlL+f3(en9#PteG@#0oZMg)1p1e+M$KN^ck&oj(>&jQ^7Z{VU z72V3$l2U5jUS8~uQ_ zU=pn;s4T5ZGlnE` zBhp%HjQGpU90OT;q$DJi_Ssw@sTqly3g!TeL4`t`x;=f2$YrI?$Qb2My0W@&BHW_= zzEeHb(j4WA$iL0VSSzHKDpJUfvCHeD zC5%AT1P^9VuR$C9_~(CV%>aTf9{_+>#+Qf?NrIy)aZq|Mot&kiWehE8wMo;uPVS#A z=Kz-6NZ;e{hBLvfB@-1Ra=Rt7&^Up!FBDYwj66R2e7YxuF3pJ879gxyGZRud`LoYH z1mFMR%~1n{zqJM|2tDcc%o#2NMgT#=1V*^)r=NiB`~J6;to(pe<^OULUB~_T!J0LC z$lS0RM%Lj;S0zU3BG%IPU^|)_2#RYsBdt?gSTL_M2ISWzTC^0`*i6#dtX zs)@J3C72#qBWY&ieml+9);#2jP;+1QI^pB5zx6wC=uf)$pk}e#;%(weM|j_$0jgvVRwcy$`lvkIlIVXG(lcauAlO_dz+Tp z;x5nC=XJHKk1^TUj%zP09E_vy;i!gb-!x`2r3Yizw^37jwaiWm{~;7L|0ZQ=H>Kw|5Aj$65{PTZzbDL z1^U_x3-cnS9ZB`{FVc1(A{BEvfBk6B4LAiT21w4aC;eVtZNiartY2+8idas{ujKd1j$O&V)ruWpHo~)v7YU7G zzOXBh9pvP%0Gm9lIjGGh?+0=6Su?11pkOkNHU;)m`GBqW{C7BfI8}zOh5#59P!uR? z0w86Xm!TL{O)#zqquqB>jAo=iYG>AoNyfz^v)KcQX1Uf0gh^0ubA@T8 zj}@PT<~INRt}nv_J3l)bYXz+$l90&^khz-X6Hq7yM$IuEdvJMp{u%zsM4YU06;ef^ zYBF8KjB#>~N&uD)F}V_?bx_X@$j8pj?S<_R+|HGu;{+q()1c>M8TkP@aSRm$gUpz- zH9`THvv5ukI6KH}B9TTQhncrRE3rr*lSober(+Ht+y`I#tLxyz;vo(;jExx-kgFpi z&F8N)y;2`kHNh~TGgk34{3BsZW5UpWlIm?>oHpU~k;Z1)-A zpZ#nrM}o!@68+>V2{MPABY&($hX#tdBYWfr(#*D!F=)Shq0$MhC3FEF7tN7_tj{kP zD;)Rm!*{>~J3hPS<_4Swh|ZB~)MyV8-m3P{0O7I;+LH7qEu_omQzXba zD4k!jen=a1`4nN_!m)Yy`q#Z9eB#jf`T+{9duzfPBTZ8(%&G+j2}GG^oJYTJ;`nwF z50{Oz-{6e&muL~Rrl1;T%M5n+-Mp)KuDhZq>%5rIRv0_I2s(gX4cia89!xK;3%@btCp)`6$pfaH_44(c&RaDZPdENFi zLK2J^c&1$VfqKO{vF)7>dlC@Xf1pLN>_T0RDc`9=x^VnskA4Ssct>~ySB)MFs9-dj zLwQ5|2&-~I#Xy1l4@-7a!lS~UtQEA;iqMMoNLvBPPy$|rz&pZo`{16fzrSYZ2(JRf z9`ZCV@r9^HyQ;D(UQk3+C|mPX*kuU1u;)SB_F^LG>5}3QgKUGeA-p~2YhSw#7JWu| ztpmH`~mx{9)qW31OcsG4AaSU54CzF?8u;y+m~hJzYxCW#ppKWG81!Z9Ys+IIhK z@YA1uo#zOjiT)qb$k5G4bEs*seO$#LktDb?1gpcMMD(f1t}LX>BA$*>Pfr%uLhlHF z3m({h`>mRvJlZ;kuf7H27^SyCPr!#T%g`JsWkyNP>w?|;h7 z5k8aQC@7t?#+)aJK&-aVprIl_^xIU8B6K>voGSoIjH%-#_5nwa&B532xIR{fj%8`| zX#lmb_m&X7vn;MM;nb>JP%#ilwTi_1IpU*;S(`lwHbO)j?K>LcPS|n(XUB4m@aZCt zR{oJ{<$Cmk=3HWBfWboB{eYYd<4NxT)*+^I^7a_$;FlXp9a7l0?FWAXKi>5hl>roJ z2q}^lguh*e(Yb044H|jCor>tNNw4&FX#%BfjvZzKowIMx{qVrH&sIlx8RR@ca*UG@ zsy^{BuyEpF{ETwEsP?4yr^Wr4mX?%N639#{J|Sm>zw`TJvsTb*LfiYa0CmIP(-&}c z#0H9m<8$KJDxxRJ5By2f=_wC@g(ED-2S@nOp(kr3r~_#z+0Q~+kT=FlNfJTz2?mQ? z_36mISNSi;h7O9ehW1@)eeL+7 zGL29Q>4+ghM);e5{h_t<8r2~p`@T80;DQ#2?_%UtUQy5dt{5D&83bSo=}2|Ugcx9^ zh;OX%&+V>ne26PUYmjew#6_n`8(@Bqai1(w#40|922~dXBKc*nGi4MBi9_!F+neFJ z1CP{_h!rA-Mmea^uu`Q&SzU2rNYGLrI8heEru2SMt}k-zEdTwE{{y=o{PU;*sv~>~ zNS05ec6y_IbQWAO(V${5m_NK1XeDSfg)%@-^wSX{|M~1M9)|nA`>C1`I~^oiPYGin zIm6+Jy71N@fn@7DdYLwGHkga&I4OoKq~@R72jBe0hiWMF^pKq^dHG?}uV<_l4v|XipUj{9E1OCW z+;=-XxBn3~gDOrPeMRFO9U_+tYT3k4@a)`A#N=t9FoEa;Vb=p+h8_3+>6y1!)+z#X zi4dBJ_6d|js9Ipa2oGc1gSQ9q1Yk4(sH|}C1NOpwfA=Yl1l31%dXPL>`s5HP0MAdV z5uyPjFu_w#ZG-JUyge_FrCC8T!hiMu{&OV$S{Sz~U?Puiv=5xn&sj9cB@`8dLm2iz z+&i}aDLlUW+wi(y`ygEKk~hNix(#t&z)yC41$OQH3vm4-%m7sjJU=)|$zU)m<9m#e z-eFvG?n41Zd4BoqBk(uh_^=`J@Q`#etTMp!gUlpIq~4G3Cjfw&C>tKwHuc0lH8ll` zi;L{=((6;{vogTyAVr+HIwDTAM;c&t@<^iq>(`Gg5I@k4e}PO^@6 z#rQ&|R*DwRk!GGw02LKy0H`3B3h1O>%d3aV1r=itG%GD~DK)7As3FpdaR=255v9u; z?ddh&HB4GD#?Tf&<`VS6FRoFDim`{I5KwqMnU4+~@PF=c+G*CEsHhk-`C`VoHbZYGW&{}Js3pfyUH$^jK)hinF^C7lp^z2449 z^e?&i;{E<(hPY$Vr|m=PzM4iAWfhYM*;q^775ssfYQA4H`YaW^QCfd(b?n6blgik%gtWM~zSnG(sKnnCorr2+vn4H{7$1oG@-o5*P z-}xm-E7H-F{HhHq)-)(55Rf%ND4qV2r}y1-jG^$w#l@TS`7{ZC>iUxsVf>0;4ci+C3mdCbqMf432-v{|Dnq(7JWofD= zs8|DNgaHf|`~BbOI=<83pPQT89n2#C^%~$8+xWk@hIM`GeZ}aav3`K8p5o1*ef##^ z(RI#}Uax0_ts6FOob@eSsl%p0BOtxhqoQI&Kt4dzVFr2Jx@Yg+|F+b*%f>$^CnrDZ zKX&pGjdW646|HhX#YjLeP!>StZ#gIMMb7{qS@wK534)`1;`s5q{nuZmZJEU)V}z(t zziNewA%KeFmda%X2H3lI@B2>H&PkI12M!!KIyXQ6xlJ24&iJ2K$BT=%9Xfzm6KWL$ z1m*(ICIoB3GC?5$)-M38jv_VCsOJS~%i>-*8KBYUUT*jdoT7LEU|+uIZ_^@uHQYL1;Il%^DlX8 z9UGS%*Vewapxf_%|FI|jTTX}gxmj2R%z9=x(d%9BpU!o$++qn~z1__?H8(kL+d!by$sdqe$zctUu_@D?@oP>D<}8M{@Q-g zc!C-mx>wy-06nH_el=;r0h;z`~O1Vp8=-% V;4aL6W8b*h7 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 diff --git a/apps/docs/public/favicon/archive/lw7/apple-touch-icon-114x114.png b/apps/docs/public/favicon/archive/lw7/apple-touch-icon-114x114.png deleted file mode 100644 index d2ee4b9e139b297b934ee94a37c5bf97b2099c18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4157 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 lA9x0l$H&IT-d;=v{}1g6?(P{ty diff --git a/apps/docs/public/favicon/archive/lw7/apple-touch-icon-144x144.png b/apps/docs/public/favicon/archive/lw7/apple-touch-icon-144x144.png deleted file mode 100644 index c73891c985d9bd7092824256993e3b16e094d9f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5877 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 LNkvXXu0mjf!W1@l diff --git a/apps/docs/public/favicon/archive/lw7/apple-touch-icon-152x152.png b/apps/docs/public/favicon/archive/lw7/apple-touch-icon-152x152.png deleted file mode 100644 index 65f90a02357a07a181b67a3bf93aed0ac1a6935c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6307 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 Z{y!C%iQ549HlP3i002ovPDHLkV1l&fMC||o diff --git a/apps/docs/public/favicon/archive/lw7/apple-touch-icon-57x57.png b/apps/docs/public/favicon/archive/lw7/apple-touch-icon-57x57.png deleted file mode 100644 index bfa1628afb57762c0fe015400031c140149d6be2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1694 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 O0000IJ?Cd>R-AdH`K+ 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 diff --git a/apps/docs/public/favicon/archive/lw7/favicon-16x16.png b/apps/docs/public/favicon/archive/lw7/favicon-16x16.png deleted file mode 100644 index 2e07b15e1066b54ef48cc641ec3082b740d1a7b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 452 zcmV;#0XzPQP)5kiAP>Q4qy{GyATa;8)@bk9}FtEEd{CScoaCY;2TN z_N%p(2&n@80U@oBGQEF-t{7}K%91A7h6Fc72ncEjZ=ZK8RyXd4Z_R<>GIQt5oHJ4^ z7N_Gl{%B?;9uBXnUz~GgDHICTBuVD}gWQ61?z5(C7BpRk_oaI~#@rOE(OzE_L9gO~ z4znC?^EjL9JD^K}AS{OOcrrMNW&838Fl#Hk%&qhM=>k6R5GXIgGN^%oDg3@Tp?-Gs zZ($Tg4exybFgd)y(!@46!JIWCXukd?Kl}5Io!!>}WK@&38_Yj@gFOOszD2wZ?+gn( z)#LXa7VcpGbc^w!8Bj1aPgN711kF)*qxiH zYSMMYPFxK%IR9Jc)8X4Ta%)H`8@RmsMWwPyBfjYQFZq1FVP^MQ0HNu&8!D2hh}6k@7V-f|kBiBQiJu0000(2i z2+6o2S)v`0a-2kYR3&B0cDZE9v}IEvMMl$QZ7eH>`JUktSGiAiE<*!qWAy_ zzQk7u5Cj2g7bJE;h!22VJa+d!=H$mr_jLF4%)JXN_RikzuL`)cJ>5M$Gw17bPCw2N zP6M`X-6|T5#(HMn0^kAw?*ec(fMEbD0SK!|0C;}QXj|t3m01X!&g;&n?y|fG zz3eoA!vH1$>;v!|5$&y1DzEL?vnM*qdUHVwRnfWUo?8X5iJ5N#@QVPp0vJJe1k9s% z5dnAuz#ahKBj9ft7#|-WZ!SdTr%Z^kv9Ue^ZeZZo0bB#1dg{&c@aPz`0Ja18PXTbx zzVY$dQ>pBv2{AS{)(7C10el9rHt?FDOE?KLrWer!up7XgM0D3rfBMstBF0G(;@q*Z zO99-;z_sX*2+XYhB?;*{07R6g6RBTjPR}LhSvEXL&*aHoJe!u6-@1M#-H~5!4>M;U zYEj$f(*|`~yGD{vw!wZjMqRG9l>9vq01~3OUK0^wjqy9<#{f z>vWoNY;0@;nEx|~K7<^t&}=r*Xf)7hG!y}3qlsufEcfs*AmvGyt1t{vtyU2Tk*8@Q z0QUg+_3`oX$xg1*k%W$pj$TMa-vV%<>wK%(#O&N0n$4zato~1?d3c;EbhBF?2SI?o zS`9%M<`vov;Gc|7Ozdh`e_JUX8y&qAMBf3h$+knID8lUQEE($Zf!Bi%)c;Epeb^tcWi8I6M!Fr`2u^iWp-{3b8~ab(eXs^C z$nfxY4j(zvu5F z9gt?T>9vDLPomXo8JnyUx&Ot@n>Py~h|XYOi>@7-vVbRpM~_09O;W-c*eZlLLjc%9 zadZrM0?lUAlfk2>5k-+w0LkwNGjA0jx{woJLYho+8LcOUN3TNeq0m-22?8z<%zVD4 zHo#hD5074jOU4;^ry$^L$&zGT*82}0%L0zT7iSBO!%M~)07O1IhR1S&CF=wX3yNc{ z$^@?+JeCdYuAhNH!37ySJeC{$A|($G4W1Al9vVC$JUldbLU?#+@PzR2(BKK-;h`ZX zI;_V+Vnw(fn^#JTBAlZD}ac6y<4=D?-6ZsbeoCAyx$&{5SZz z1v9**H<=a^M1*&(`Y7JD;wDsDRR|VfeJ8v8wKN5}ze?b-m`F%rjxu>-oD$CLy97VC z=2NJ&YRZ9zO$cQFCO;k2eI&9U0@`h#)dL!E1?mL6E@Z z!@rHQYVSuFg{k>t`3f-!SpAZA-aqj!!un)fnCYPWcctfr^9OIjyI1}S!l(ivonwbt z#9$C8B?YB4@Q=ESuoQq1?c0^XBOmMf-i>W*Zbmg4Kp!euGel7zjsj{klKG zN*Y06`3>pfJ%`h*j5~Vyypq1RSO#Lbf(=5kfz1ciy8bkdHs(L%=%W z5j)Z6t^5$)Gx)C%aJguKI8*X=McY z*H9MtH{n1)6egQKy&Jddq$KBo)8vBSNsE9y!zt^xt3kdtsS!x{G6dzBQNsv`o(>v zLL7C&0|2nLc0R5gxdm19$7FB_xVh{CZZf!*XE=7z8OuC8N`VkQ;4y$WmeTd>{~cC| zcOXD$uJ&y=sb>2JZAP3J@SB243U4w22t^H7jogNj$~zIDVmQ%i@go&4=~jM)K?Za3 zPA7t{K>|@((EIV22jr@5J?cj0rf(*~{DW3xLJ08;*ksa^DUv3xqDQh_=3-JH?CdmO8)qqutAZK%;I1O>}7 zbo)Q;$7}_cWyENz)D}Ac~&H6QL`xpL_BJp`J$|D!6jpXK-fUdlBl(GAtp@I>3&6C^DsB z%s(Wxvd^<0 zW$HGvn%VqLH3L28U~lNZ43`go5*5*Bu3)u?KLO+}^WZYx%kkt^v z2vpW@a{ z`#o&zzYGDzlW$VwvZF&Ckij9~_Dr<;_5<5_q1cjVDxIpZd$o!bPdoZ` z?Al}oX(H64qj-C6KMu`4gV$zuq8=UVq^7PxzXgUCsBG!eAO?YO{@_Qjb=8fE4BAQa zx2?}$4ZCXd5GvJva0HE9>D&SnnWz~BJIQgC=>_+(uCFR&t#5OJM{UCg0imBF}U;TY3fNBq|l#> zOyT&Wg%QAw07G-$%FRv|^J+Z=34f z)p@O(b`egyPuI|}-JbX!b)w}w3+vao2aR;{nW1^#* z5D=SuOWmnHfAB_JF!aj^L_!Aj(xi4^!*s~@;JV;tUoh-nP4F_NRDrPSy?48RWY?p& z4URI2sG_A;d-oH0=}(ntZZ&8qA#Yo?6jyj6xRLKbO<)I@U#YhHVF zld6C;M$Zj6HI7c$PCJcUO{?D{0q7%C23O*|;Ty^+U(DH$E-oEI30PS<6W6`tOQ?l| z2uKe|%*M+ixO#i}QsYFmsmIP|ylBnFhKpRTGHue5tK`3J?EoO^O5`qLSU;7E1wc<(y zq5=|Ht6e?4IwqJyg~>>gOYjU+%08EKEQQ)}>?&iJQO2=dCb8SK`|7ByQ9gUl)}E=8 z?P^0_TDEQm49nFh9}xNn)|4U^RoqUgT?uMGgnB4k{?++Jg!5K?7#FVo7y?m&$cfIK z5h$Gug!DdhUwZsh^0$Y=5-v{X#V99#VH=Ce6nxVzLo(H(q<7AC7SLrtD_+zN6_BmN z`*L?k$<->tI$07BMdrjDQ5lQ( zovxl%+y#sJ-k8H?I>lryn(=JSBC&UIA_100exQ@~wbq|CY zb))2d!$3HK>(96o1K~(ahPJ&@DyXiQs=1Cf@)zP|&4V`Pio--{S7))=XVt0wX^tM{ z`z~1%QPZB*b=;aXH8sgupM71e!vOHsiI>r6os16}Y5O`h>;gkQuYC_}{yMH>ntkRwbmhyOv+8f}D`|q0_$Q{ebH4|h zWX<{v_P+dG2q8d3 z&phtbd;)Zhr4hgwPIZ|wWL?Ka8W{JbCK?My!`vn$W!vSvFGu^6I@~^mesB4jZO{03 zF@5|1!Z0ic88U&&EHaeMWE!q*!TZ+A~?NFD&WEu$9;<_{Lz(94a;WreTGlefL9pP!G6@a)?;5-3!lqckq%lwT) z=Mw-j98O)6SnZA*)Ye=xwSt2*x;D$)i{*D|#HKdSN@-hX2LaUUNAaVFei!w|TL^;g z&r&PsE(4Lag|s9ZL4t_zzTuB!q=| z0E3mYuyyDkL5L)tS(EATpuTHRg+pLf}9On#aSnCM%`rIa! zc2&4YRxH$(_I0*f?@iNov>R#Kx#xf4rTu@4Fbp7sC>I$dw z*NJ)f@+%ME$>;tAK_JRU2500xEBbdCnj26Rn^ycBL?BJ2tWX#)L!H)px>T?WVrQ>>t3z*aP0W2c;KK(p_4?SUuWaf&#lrpHDTHaxLKy?eEQqYIX8qBNQJtcui$ED(UO)7aU6BF zAq{g2JD&J5-Z=a`!mxx+bPfnHAtJyqHcEhGk6ED#w;jBKA<~R+wRf8JG-VBRRJY7W z=J{Nq?M%}o<6m&~@aDCP?u&Eo%Y82yEt6ZPxe#*K3*W-NiMz|`H(1c+o)K>$Re=Wd zW_Rl*hzQN7j@j0cBmr(gQA-G9qzi4d$5P??NRY}0N1a-kxXy%{#05f=)@uq^8%<&p zLHj4K9oMVfuYEsOd)@cV>928LTHS^B?`~t7mUcu0VCvxGc>L+FAqWJ5ASg8%fb8oO zc_+ICW=11Afg|<(*%wSuFPJH3lmk{;B2;Q;nttB#g46xamN{b8X_ryXzl(51g5?lM z-Hah1OD3fjrZy%k+1CQJWpjocTw*uI76-6hzf!J|v z;=uGH(0le&@PLfdnIl|sD<^f3Uq#~R`NJ#-6B%p6i=D7$vhk#v7?7#fMPXb2+03vb?q zdUQPV0+o$!3ml*cilzr@UZWra*X)&#LIFoAY$b5FOsPIdo=kUH+wzP76) z&_|G5*HgzS$%^j5RaSowQPjj^Klx+4_Qtd2oQduL@|H`s$|?pC;b`L^cE0v)m1YV! z+-l!SBi-)K$)Cn2qEtxW$eT&iOsbsv3w;WQR&WLaOEMJC2B#WFYAnM?aNT=CR0b92 zv)bbdaPY$3zrmiD{u*HzmfnfZgVGRoLRk<50iHPcC-~X%ou$&QQuSK%WaA<|(8u|`4vah8PLDiWdpM9?~jf_Yldfusn zkK?f?zX~E=vSa`(4NgWs#`x6d1jA$w9GlV=g^u)oyN5p_DEdrgrQZ&Ig?Mov16~|!5z1Q zd2UIJD7io|<-e3B695nq!Z5_!_5Jv(T_3~L^po0)lsz1QWcO(c5n#MPb6IkZsiT*( z{^iafTh~b%kGw!&_Hd>dBGMGR42hi@#}Za&d*U`pjvLm1@m$h-%}iQabv7C&aQ{QM z;`oV!%5PY5;B;RMBkqWUp`oGQ0B}Z{htX=aVqxp@P0BXRG>+iKH~tTf*I&n)fid)j zgXt3OcKe7EGITPRkR?DtzU0_#_h;(^EbXK(OR;)wGV0aq>Y2kNz7Iu9HQJYP6_LK6%Ul_U`*W_U!wcB{37-4yvWH|(Ta{^ z|6BKC;>dkV`bFrd1Oxbuk38!zVBK1(aM^isEVsWZ^C+hbskGwVc=AafI`lMlJoZHh zfhFrV=&)NK+6*Zpp5}!H9YXpZHN*lx)))_b}c#EB>{+NK~(iZP9W(7m@k+c;1&ZF zz-d}#d=TxN`b|tJWir|4&Ad*n;nYU4>DOw`;r{Kn;^?tgP^naw z-Agb1Up)W9Un-NeS73DiDwHLlY)+5vp~VdZR0U9^6(m{6aZWFzYmLrEkYpeRS(cKr zZ@j)64?l7Th#~|*Nq4@TDztkFjf5p+GW8l-+<>5JjwX-MZeEV$l�!F3}0KlBoOa2B-A|NeeY6Qn< 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 diff --git a/apps/docs/public/favicon/archive/lw7/favicon-96x96.png b/apps/docs/public/favicon/archive/lw7/favicon-96x96.png deleted file mode 100644 index b23072a2c02526345ffd37b7af67d11f85c98c9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3139 zcmV-J47~G+P)iqwMIO6>z`)vKsVfszDBp)?7Bgp{BptP6OJ zlVC_gVz1Xb^YvkNXXmBGUn!R5e4;Cdh(!yrFO$N_%>?#*N}`=SmCRlvZ& zKw2ra8TdX$OBWFeg#xB&A|i-LH3r?ZP)ebcB9Ta77zRo?)aHSQfFETtnOxv|e!;-N zK)+JzkHBRBmT8ikoTN}FI6vY#c?&+2jMFd-+EOWWB2oHiHzGG=hK7dS$9tG8lD`%B zI3naGC&}mYXsyv&*XS?I4U`m-OeSedrNB1YgTUHMCgUieu~tP~N($H%cO zi$qz2Eqn-w2wH2>>2xV_?ACC_;bJ(_t|K?$B40#WF9eR0>4$z^cs9(7uufYy?uKX|~9(A_|29mSurmS#AVS zg98ISzz~ogpO`>IT2)RJkw_%$q-@U<1~hODkQNb4(`=DnWt8So*c01pG_Xd1LW}&G z!L%#{5V%T<-P>tde+^O00{|CjUEWJpyN6eifsNRo;q?fIrDhEhc+u{n&iUD%C7Hmaobl& z=R0VdYUkX$w!=uP~!-t?n zsq(Y=^9o63dL26?`EmK z5QTEAUX*yepxI#nG-3u=amIJ}SliX8Vx=4)evT-?fX4eD=X9*$vd$Yxh@Er=f*}ad zdJg1(Mzj8|)VZuZ^B$6tc4EET>cvrlG@j+0CWHpd0V&0>tTY^eJrgh!z=fgq7ekp}fuST3gb4B;<^tN3BsK7)kEdB>9zuB*0i(sHs zUAmzccYU1;=UY~CtXpSgjAGCZZFxX4CH=nNRdIc{#1 zp*2#(g5)yR_iQ1h=h*_~Bc2&nJ_?j>{xz&+1=JuE8G0V;dbY5@=$%oLb>{#H@r1d6 znwAlt?fxOl(ktu*V4j2;QC_;O-qR0i{+6_055Hz1=%TK#a#81(QCf#2(+~@f$N}O~ zR(o4F>-!(@j6Lu#PFG33<1Hz0JeT2(6HjtHKXjTW3rC530Cny;=e#4(lb@Wdnp5}A zyOeADenBcRzjA27u8mO=@C5I1l$9akQA+7EPxH>M`7nEr z{R){SQ(9}1$t1vN)k9E+v6OYaTSyrlwm|v94fv9*zwQqb==B6u4r#swZch_bpsQ+& zRcM2+Y#hothbV=fpJqkJO-$}T!GW>g$HtGYX5dMv6zh7o(3$G9|A{WgbjQ-PI2K-( zQItvfy~e8)?Uj3EZbkXtm(CaHHTh-QH_im8F3pPbZ?ru*COCz3{EASlUUDma9jl5K zS|r&aNh**e(Zp%52Z=u^I|?kx#r58Ge8_qHva*uJ8B^P$E_xTPjE$wLg`f)-UeCo{ zU$gHocH%A$!KFCsZ#e|Z%@BeKvEbtQ!@^2fwN(y*zH@s*V{q<43Od?*;k|fxaulG5 z&kL5$Th5hBZ$~GRUIN_7EtF6~2%Ww&8q5p9^Z1qJ|GhxPg#^b`JT7Ox9}iI?Wd+1V ze!H=lb<6Ivldgwo3IC&|3dbi8BQvag_2h*xs}H-F6J-cta@TK)fvO1O7a3O9r*rD6^U^@gzd2*L3y7#ZEgp8XHS zcPp1t@g?DQV=>Fm{D$2iD-9lk;l?j3z7J2dv$OgzMTHgvVaDM5jg#Y}Y|;Kdwj1!#pmKe1U>B$LcS1F@^v9L z1A#csbKX18J@5brNFR+8X0bUV-+l(-+2#X$M;v|F4EW(@WIqbc@_$R z_-V^3g%tv1MunR&1%|aXU?x^y*%J;N`~!!E{#>>Fl44Up_T)}-=5f-=t_W+blz69! z|A7!S%aW7w@s+~jk)wNg@uhpKx>=Pj4sX_&l2g1e{D7A@PfNfna|qEA=--6(bnM=Y zc$MYp-xNvK{?>-C&s6+P(LN9L^`B0SA7$%vw*Y1g>;zHbJl4gz{~7x&>0}p|pM4Wr z8PQhni_z12gHKM->cb{fVKZ5e+%+z@k(g$lZO`4xWPU70c7hOM?geSBcxm)!92)yO z=P$XIMeXO6uiLu+uscBpKEp+_FaGsmaz2 zu{Yzi)|@ooVpsM-_oft8fmR0J{?cABRD^dxs3!nnMS>_ec<3*@e&}~K+oZ5+-OyU> zv?wCBNk`5zB1+4MiQKVcukx>d-&4~aBAeni)k+X$f=YNTe5R8uSKgV(y~oyPHXuyZ zXyEQM3>qhM3t|V6R%~NY}>wpT<%D%hu?gAMfhP#p=|X!q_PStH?>z$J9pjB z(PMk+GX5rAUR;J?1`}#nNeh8;6X5XSzwz3EN71_a6;BwNS^-KaEKGai1r?KQSYCMd z-2*)T!rgTvADUbNU@x5VmXc8uIj<}?d7Q0Ve^A^*wSH)N1=t~oPz#UhmWr5c-?ov7 ziFfKW>N1*M0hSb|znJ6k1Y!5ipE5f7Vnb|FI42ZSZ6auBCC;k^@lanWS`l*`{EASMNxaeXKEuA3A8FWU;MfXiK+BjZ1dFH(F2~=`uw&aDjYodT;6>&@H`J8_+)GmO zQ>WPWp5|5 zq}aRrm%RPv_J&Nlev}o^1cMF3zJ0&s$mlE1MC{P(e`W9PhZ`^MM?js`-~SHKGc`5U zv`Q!x3M^Q7HfABu#Q2ehe+rZ?K68><+$C8H7>2>bsS$vNC*P0e@Y6YrmICSwjs3ja zrj7s241v5B7%g??TBs3}DlN`Es)5&SSxW`Af{W|@8v6nCXsuh1DX$S6`bBnV1y3N7 zLn(C23#tx>W04&2xPE(hcm#Ni;*+0Ss4iUl+&wm&&5qjdl-dO3RcY&&7ODcRbt(K5 zfK31ifD-r>;^8^Ij{S5RLW{w>27_ezLo81?6(2QbBe_!7+;2K~J@Cl%YIk2WEW)y%?;5Fb`lzL*= do?}(S{{fTW+h?R6S%3fl002ovPDHLkV1nam|Ahbm diff --git a/apps/docs/public/favicon/archive/lw7/favicon.ico b/apps/docs/public/favicon/archive/lw7/favicon.ico deleted file mode 100644 index 51b9988fdcb380c97ac161cdfd9ddb7d9359f576..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34494 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 E59zQ}fdBvi diff --git a/apps/docs/public/favicon/archive/lw7/mstile-144x144.png b/apps/docs/public/favicon/archive/lw7/mstile-144x144.png deleted file mode 100644 index c73891c985d9bd7092824256993e3b16e094d9f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5877 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 LNkvXXu0mjf!W1@l diff --git a/apps/docs/public/favicon/archive/lw7/mstile-150x150.png b/apps/docs/public/favicon/archive/lw7/mstile-150x150.png deleted file mode 100644 index bd10ae0a5df93e00ebfd4fbaf51dd4387d750648..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17760 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 diff --git a/apps/docs/public/favicon/archive/lw7/mstile-310x150.png b/apps/docs/public/favicon/archive/lw7/mstile-310x150.png deleted file mode 100644 index fb4d58022df1331b786b02b5e436f5ebdbf77be5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48157 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%0DK$oUeT)!x_xV0%$i4a+#XOxTNVNTBEr0J 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 diff --git a/apps/docs/public/favicon/archive/lw8/android-icon-144x144.png b/apps/docs/public/favicon/archive/lw8/android-icon-144x144.png deleted file mode 100644 index e34cdc489bf8128ba6d49386ad855ef045ea3251..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7997 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 diff --git a/apps/docs/public/favicon/archive/lw8/android-icon-48x48.png b/apps/docs/public/favicon/archive/lw8/android-icon-48x48.png deleted file mode 100644 index 0918c9d5a5f6160a798d5e57e9e7a5501c2aca65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2138 zcmZ{ldoDx8b2TQq8DV2b>|AS4ZW*a; z*{V&7BC_4GcjdA-Y1~dXp`*5#()l^-taUnjt+U?s{GRnb&*%Gn-uM0ImwPb4Q&mYv z2><|9Z!foCD1)1!AP0R9!Pl~(grK?jy8yt?1=o<}0LOO&fG`sP)}fN{ z6#yhd!Z)!1fGY<86i3t+gohe(alW2zz}L-H)qbT2swi^2B9j2X!gn)ZV#m^}P*I-m z?e8xCQbAq?lpRF$L6)-byxm+v=~E+7zHB{r_jq;VwnoPVZ|r7H(_t1239G11TnZgQ{18t%rrAWZ`n@>d;W^x}`z zoq*OcdzYHpKR%A~lheXtV!~oD%TA^^{0Wtcm$~ij>p^Do3!3E`lWGK>m%zPKB;h_-nJAgXBo6qHOo&f?zxwOAq$y%bMW5ufb*H0 zcyaOBLA*6SW$}jieX~a`4dkr*E$;0u41R305{*RYZg7Opf7-#L)7R(-aVr8a+EW-U z;(4kdM1vf>%}v#y&#(cfVYQ&#`Xjtp8)6EI%B4 zQ?a#Fao0|)cGbm(sh8Gx^H@K>HnRWA->OHPRb5N@w z<1)5>ARG9#s_5+RGh`8`I`QjB+J(foWbTa0k?~bEycVbFR-XJjT{B6LpZ&!l64PX# zbbYTN$4cO?UPkPEGACV@WOO1GrRC(dA>+SJ68dM0xC4otK8#0P8W%PYf&zD6i}kAC z(21&0@lJWrbdB59i_DrNA8)1QahHJ7>nQNG)0oT+VfYYP^=w9?evy-iqtfAQV&Px$ zF#2_^+>s2gR2%hQ1O%8)Ec{Ep@WK1s7S27MP94ueg||Mcp7zK~T3f4pM>)G2P%9xm zdNSvb5*pe?wWt;ew@jKy^8-0asFLk@uecor~zS5h|vs$@`j;rieayW#ezBTph;=8xF6<)8koBA|G1}E?><= znZ9^v zONdnDvffsMK`j(F?#12lsSd?H{Z^4?_3>!Imrg8Jpo9){5(f4}FK1|GTnN(Iio_dV z@<(r0P8`CaTh+)OueiX~CZ=phuN{FwiSmR0y`DS&^d}1Wz8&_hicJvBHiRV zP?d}Du5sKMrbXbX#H^hh`LUxfW>~W{^5k$rJ*D{R`_c=7U3t!W+*Wyehf+hsJIed5 zSz~G4>$6M3R~xa!iSFE^hF!ug*1Wutu=Cm^B6V0 zIGLyRuBuEocvx6b_Xpz)K1|x(uta~L-{91dvp;`t)e%HXpNA;)%HtHHo3Nx~s1{0xzM&p>(UyBNq5|jRmA!#M%SF)2)Plezee z%hNf6H)*!Z<3P3LQTjkHy-%lcv7u_mm!yPAv)y#k|)XV7MTEK%5O({#nQ@} zhsg_q4ZjRi;r6!5!})a$m+uxjYQEgryfB(Qr?%K~1UPMUn~wjs$GnHX1tWZo%r)t_Kkw` z>bH74d8qwsIW@wHl;*4$=_k2Vo^NKc48GALS7bLjl3?i3Y-?HJ=h^0|0(2mE0e z(F`VuMumbwK5E70(e4fFUxL`}n`|gOnHh(}xv|N~Oe%|y!ySasB*6O0*SqMyG2WXl zIGh)iL8J2lYX^*T3^xp7P~Z6chdIQc@adb#(*{EY2+{rq@nv011TRnga_^EBu>QSg;`oB+(wjtSK_U&`PkR8Yl6nhfM4r`CG1)-U74t7|I9mxt( XSV8BLY#R|n698}b0Jla$?3sT7J;{qv diff --git a/apps/docs/public/favicon/archive/lw8/android-icon-72x72.png b/apps/docs/public/favicon/archive/lw8/android-icon-72x72.png deleted file mode 100644 index 83dfc47bd21897b6800097ef6f2d90162f0991c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3208 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 diff --git a/apps/docs/public/favicon/archive/lw8/apple-icon-114x114.png b/apps/docs/public/favicon/archive/lw8/apple-icon-114x114.png deleted file mode 100644 index f32fa5c91e5edf717f8cdbec9fd45814e58f9ca0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5731 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 diff --git a/apps/docs/public/favicon/archive/lw8/apple-icon-120x120.png b/apps/docs/public/favicon/archive/lw8/apple-icon-120x120.png deleted file mode 100644 index f740816a8891be4315a0a5bbe2f9d97c066da942..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5955 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 Riy$Ka diff --git a/apps/docs/public/favicon/archive/lw8/apple-icon-180x180.png b/apps/docs/public/favicon/archive/lw8/apple-icon-180x180.png deleted file mode 100644 index bf1bfbf7f005e35ba508ec932288803563192ca0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11605 zcmZ{~18`-}6F+)m+qP|Nu))UO*f+Lq+cx&bcCxXvv2EMfcwfG+Ue)`(f7Lsu2B+uK zJ#%`dr@PLXNF@bHBzSyy004j_EhVnpa?*IV(iL|(gs>j-;?|C}q zkn8candxK4@em*n7=QBgII#U zSc$!aN37v|6F_9=jDi2D9)taHz3+SLj_~uZcfVXKbw>&ZaZLCG^o1&C6ZL3WMD|rP z;A2^Ff#~dZ@wQ1X@vWC#+C$n^4UC~9hW(M~9en+r>X|V)qte(KRMXlqpfP>Zivl%X z5!p`@Ychh@1jO#a660iQEz&CBe_3}m{CzDPIKRHQLX>3rc+$89IlR`uD5V{a9UToX z!vyE{;KoYCv)=Q=hK5RCB38Hd?~Gc={ACJh(BF~>ufFVUH`Xt{uiA@&%1 zT^-b5w?SMtNp4M24pO5-WrwD0sB#(|nvn~!Hr49xY-)P`NNry1AwrVW>FK&jT2Z0X z6YyRBXgf>`9vX@!5v=bLe9jN<+exgb@S51Y+iOIzEhlFZb+o~n4rzg6PAwF(bY>=J z)XhhgHsh0}i8vqM3$ffM-|?uu*c`#y9zYawJzH?rb$qO~@3wg;qH(qNJw&zJz|Co| z_ucnLY=QY_$%&8koC~&`gs&}Hktl;?x$Vr#Vd>9DD_^;3;fMjPQ9q;Fph3Z05f!g2 zGW7KH6g{weGj?d5j_3mo5_<1VuWxP+-F5J|w%~j5%F4Y8!6J(!smRT0=RtZwy*>{k&;5?LYNNEcHlzFyF=)hfKH}72Q|JfhPcd>7zU0er zG@xw6ted4`|1rO`NQHAaqfkQCg_Xo24>K=5u6?;gy1XH~z+B0q^ee@lw+Em>Jwkv; zWC7tf>|(7|EOjnt=P#xJn${hD+_4Z~PJ@XZ>i5g>au~1WI4@!a+U$@?iTd01*2KFR z=ekJaV`gUW(uP2B(oMOWCqad2L-yh2Q)04AIWuSk)`i0 zw-G=>O+ZzZ>S~qB5SSuYM(E1m7Z$&9;b4~6z6Cqq zG*>6muyMdf+@S6nwKiR*EJbuRRZ`mbGQ@FmE$3kATz*TXNQk7%pdw_fIAqF&dbvTc z?p*mO$y1%sB74-87gO{x8Fp*pN-rvDhQpk0RY={HIr~la2Z3WDB!iupq-r|s*jYh9 zX3oLs@g(HiZkThU)>fWn;vT0!(K$9yY;Fxm&0ZG3t*T>tx@BfCN>ouiOrDa};LZ0W zb`UB4XC1{?zgSBpQ3HQ{lD~RVs*!ZwW!Wu0VsL2VT#jV1gI^la8i78%W!`$b_wsiH z0?i+C!w2L+kw9>vrJ_k5 z3ZmJ;%$(K8`UFl-z`0x(%m*he(wx^Qo2Ts-LYJ3qle~n^y{6Jh9hbN)N5Fu1@J8C$ zunE%%GTc@47!XBduwzd(nly)MaSl$xz)&nDsu#0|QP+)3b;xi3XPP!#2BJQ_j{XQE zqMEa->Pfa8y;&TnBs$WTfk;ibz(Jw5xqPz~H9N7>5x$FkS$eISX_2N-x}HKNSRC4( z=kwwwF1rOY+>4Kzek9L|=o3bO!Aa_!iRqP(R%&Lj8j9=n!O3JuOj&RCSjK`nug@^VWhVI!O`0_fl-(d)W`cP_TME=w=H%I%{}$@R>6hO=g=Op&s5DBz(u zrlmW3x-l^i!!n06YA+dxn$cH4E)kyhdrV}wt%wf##cazah@#{q#wrlZc@LqGbDEVi zj3kt`%0Ho#M>|R>#cKBm5?}ELIVMmadCAcnrZo(ItLSX#MAX6^j%0n>Vqbkuei3-1 zW?w{`nLNH~2E&J@A-Hu_zso{#>vE!hk<01hi2Fq2gn7w(5VAHU{u8}NVU69kZbyF* zfu=|0^bCYt+&qKmdSYjjA_SGx(&rhNN_vrk!H93=RVl=ib(CYYOnDPI4O#n-I11XX z9VdNfJ2TVS6UIq;pS$A_01YZ2Uh*DsX!D2vFoMbk#XFe(mA8qnp{@d_FNIT4H5a#y zP=l~(|4^V5$U!V8+nt&O2Nyg3R%j@|tmjk1rxu-4B?q8?u*4fl?+)@-{|71g`nNzb zdZk8aNHSQ%0eD~Q=y@!Ft7a%nC|f&8HCKkk)M_6>ut9Y@1UIXuJl?=<-95&gLblkR zV3)|}z37<{lVselPHO>1lSVQi2J;CX{#H6enB6tk0R=Pmt$yQMPQ*hB>hv+s|nCSiwP;u;e)-&E3?A$X#Bbw^|DT|9*rnz zASa0*J=hy{bwqw!Q)+viI}>-@hpDjL_X#IZ_oPRt$E!mSav8X%P4wIK7VIG!%OB&& zlJ%0W{N&H@Fv21g&5v7~U?UHDwcM@`NYm33yh>yRsLa6i7uVfF`#Fi3A1>$a%mxnh zVJ$5=;a!iX{hDV){h7@)jw5#<(uW-{D_?CeWx9vh3wi0*ri$1b&Xho1H{N%}R3BZT zEtQ~|W76i*L892X5OU53Jpx6vmLb2u1-~n2bk$6yIdp{@A0!$LV##=HwClGyM&8qw zZqu^QgUG>o>K?kyeUVgyT=qTf*@@?XvcQqWFvO{cSxr}_CIz`uR(z?KH2PB-S50ju zczQ>h({bL8C(N`cu@h?OQObJTKbdDn*1`FvF52%!J4m+-*3s+?%X?Fu(}xiCwQKu} z(&~H{;au#!Rq-+1Ri$oZv6qM3&b1gvv}mxBucf!45dW}X#`a->N4FMOPjJHydfEJw zHbKms{~A0slXwQV4%3#Wn5><>SRbgyXv!fv39E&YJtRZy9N$Gn$9hp<|A&FCi6EVe*#T)!7mVT%|?iv_lm$l9>(j z=Y;d-HR?EKJSS&~vXt5K1@UngxnQ_(RLJygeppuvF?^1uALid$e;C=J-8kEDCH46M zc;Bf_(ztC5%mpK}>`c?eyI2s5lc4V^9}Z;R$d2EL3}&KNId8T0(}LT5VaDTuW%;Tc zBtQ~pYHwmKS(D{j%03-lE^OsD#9;ka$Agfyy;`e&gW+t1Orx(!*_q!*}X3wYIM*9t5_)U7gsL>8n!ASklT&Z1EN*{VuZNdB2kE$k8b~&9u zTdFe|dVZAtT5~kP_Bb+t3Ps{dD!&I3)UR@ldZqWqu~Gj{>(!)bK5kkd9s^L3kf+93 zZ&I&+nB>YVtA~hISxef;mHSiaOBu-#TO?0INc^7xn=f^TE^gVb zQr;Koty@0LqHFIw*hrRdFv1sP3wa|d3s{)F_H3*QtfFUzF*_b-$Avh!>@rT(_#%YA z{XHl|1QeP>Yp4ope_WFL_4l|L%qCjMV;`eCf{D1`SdiZ}UEkcf3C1saHB+0}n1s zE8>FV(oQS#RgTA?z1)jw<+$t{&lGH=Xnasqyhbin#d4G zu0>!`SrWWI{Wo;Bog3ZHZ=}=SNq3?d zzqrr2`_H%J(8L&+OOYvYLoX2x->kRpUP#m``J>l+^uOcAgc>20YV-tRjK>!i2t6tA z%NDt+F)@C`R;9jOB&|deJVE;KYHf6qio-wtk^j6}C$_nxKo|Ijcto7)^7l^TzlB$) zR0TB1_-%aMzPu@$!|s+F&0jO#yw1$(i-io6vu6m-ZS$r|yZKECXhACj`}Yj99dIhWvV zaKJZT&gE9@iEztpA@k* z5MATCf9(yIU!KdBQ0Eohi}vsEwoM`Tx`{k-F5|75OgCOAH)L{0%wa($;q8j_0HP$f z=t>Tyj*w&J>k6#yPp9kH^@E3zBE>P1JnBJ;yme`;< zmP`E`^2HGk+4RNRH&AJ(Wr$^GVlCgeOQ74{YB=Q=JVV#|&7Z!W!36gzV|0`xC?n%r zR3V@$u910Dp!LAto4y^MXP0AvmdZ*AU%iq8$5sgxI0(b+2vh_8d~C1@NATeD-L~DG z{>?W3OS-SnCj0xFO+nERKl{sSfbl!5Le0CR59>41l&wJYc*n8w?H`@^9QTLF^fc>V z;w9Fg1aTHgpd{8>QBLo#@kCbLv=$-+=-_%?!oJf~;i39smgU6WkJPDrHPSO+xjUpg z%Re?^zK3+)mSF6N)m=_{?2Mhgu^^9m- z_H%HTNIk2>-_WqD6XI{JV5klbNlqmmN663~z|P>^=p%`eNa|TOxShN8w*C8)GwiY0 zdDooESR`88#y0`;BS8oi{lcY9Z5f~;k&S&476e1hiIPnthOQ80 zg^sdy(~H-6f3Sz)hqop}{A8x*bU^)2TSM0Nuq!#hR>>Voz%GF>n5CXz5Q2Gq>w1}AdZ5xRD#5^Cwz3*3i3By9P2#&3fqwJVh*>^aSPRG$oo9Wd>}nWAGEHfU@K(?3{W94?gDS(R32&GQETL6Tq;$7Ws*1dCI2{a{ z=u1|tYRGi8OXb9n=uAY`a`4bg_N?%jZN@LkIr<;eXrTtn4m2fSfYXQxOdxjosQiTVZ5X{eZ zMhTzb-Cm%#Hr@$3-S^XREq`y&pGaOzNi33{g0Ge+3Y3OiEX=ZS&AU5MChuiq`$WdT z!@Rlgw}ghzmZtuWwnHi0Bm1;H$7!p()mSO#-c|HY;3hl>Xi1>hRWJ z79o^)V^T7yUGEM2B+_KCALsqI zI*k-(&zOqJ*if)?(LoXi)s40^lDqRNNXhF`%X*fkP_xF@>FM>cvh#C=^OB;{$J}hi z8tn8RA>gWN6gJqr>HN(xZ$5k~wRu=&Sf7t;d>#nuzy%uEA#RVv&eHJx$qt5KM)HeB z$o7w&+=a<>X6h%kikeXsbt)TUgA;iBwOWKK#+f=nKiD-d+NZa3cD4TOacsc0Cvser z!Iv?E8+go}*LS$-jHd?Y9qpyAt!hngFK^@%NFP4QoD))!EyufvbvzfnPYYAnTd>yq zO-Fd7w8MVlgD^8t$+XRJhj~_ngXOVWXZNj`E{T3lX^a`TXke}thQ0j<(bnoKUziWXk#&Xh+33;Y z1EKemdK2N21wNq24ApYa{|?VrsGU2)ssSAq%kB0mwg(1~qvee*iGB5hjZfZ%xphB~ zb&p7Q^=4I$gI zbFvo~VQu_=$5r=|{99#B3-JNq|svr8rlV2MD5wxAi#8UB;znwK z7VV&oLx3AAnjIpx5In!SYiH3=&hFF9-z8vZP`@VS+U5h%-u45RVrz5>KkVDc1mGT(#O@!) ze}1{|LgQZ77=jl%S4NwkG;29QTsVJpM!Z@nAO}pR`u#nfakeHu zruW(9FH&dwt$!Vx4@oBYz*UW;V*@*NivS74HE)Cl;5+b1QlPI#B{_&vnFTN8?RSM& zIMYH2FByc}IW^zwUaFYhoat#@?D}8S=FrXK)a<)CNaa#S=Dh1I}^@I~E3OvniBSu zo_T&L*9apT7`qF@+xkNIpMSc&mawT*vh;2%*VB?DVRe`f)%R^^KFRCcY@kDb#%6R6 z>7i(>yQShdFgZGP;LdlXN#jKKYT@TB>@{?O!ijO2Ss+&Ik^E_w4M#S?s51Lrf=vwl z-R5a_HynF|A}fy&C#mdK4y8Vth+fv+nWN70q|%S4^9Ql)DPld}x1kU+l$)p6{M|3r z8I`WxG+|R$oOPeEvk}&^pwj$)rYsFIRj(g}m#A%F1>8GDPI6 zKk;+hr^v{z)|XABm2gRjMswKy#*Ivl->l>w!gRK) z5R=G6TCyQ}3xk;o^V)}kaD z)&+JxL8w!9ZbqNltvLWA&^^7zBs^Mjvv%^=({mVD$>S4ji=ziJYe$UXa=Qz6)~?n) zZ1+!JRek6GC8uGft5+Vr=CamhF=4JWHRdeK_kQ$#osKr}U%? zH6-GBNu&PZ0H8|*@BjE*7+poAhJ^X`&3-^?Bkzd_$ zRhKu7tvhq1f5N@jc!u&e1Ng?9!pO4tE+u@&5=7HW;W3RI`x^Omwq2Orb*CVz;%wF*Dl;7~~hv zl5Lcn4`vPKb%rV8xv6Z^7Vm+Xj8^I6NGi4X+87hE`!RLG2f^RHV<;-%2U%YoFH!tK zDH*W8#>5kr=QFf^V4JcP3iqoI6FZbn8Da+%?2*+VvFyDcaRip0F`z6Ct0onyv#`(m z9IUNqB&RLDCgs%2r}eUp7X#KJb4BT}a^RnI=QQyPyUsi;E^}f8hK9;+cAv&q@bpG* z4<#MT{L!JjR`B)uhb|5F2QK|9464&`n^JLg;dNxiuI^N&CWzR?8*$`93LvJl8QWIT z7u<%5nSSum{t2Isv$lEgZMet(T3(@FpTk1HI~K9sJS&-Zjm^Sazb9m2d@hpvBxCg+ zPQntSuZFk{DuCaH(qG(BYmIorI|p{{TQVI!7#=`p3$p5;N_2ucdvx8tQO%bKY{Nk) z@-p;#AntwdF%VS9__@OstU`^zl=m=OV>l+VXpcIz@H^Aq{|2g4h6%y;a)O8(hCec% z5$Zz+Xtp%n>vM8*qK?@2Ta48*&%865?3fl!_TEw%=}t znp?MZ%#!>_-prmU-lD(rArO2nsqSEmI(2O#K}cpTze6^S ztQAp1pvn61VXkezn@^{q&E<#0;`Gm@9y&UP0YXdl)vfHhFDkUb@%dCRY2%VVQ=Er$|qn1*Xj`DqER!SJ?H%?z(WJd<-+*hQOlE$|=g9K@)rG2WtiifG|Hi)ui~$%;YXCxxRq#=v7FvD#@3Lv{bp9m8EEOnD@nk33i4_! zLQQD*24w@y+_b0G6-H{F>NXXfDOFx;tANaLv+i*gA6Tuzp;<_b21x=qzz=Bynsq%= zx&0C$-9bcr^UUyEluccAuAh|bj_<55bT-Z@Ht>SGE<7okFhC&gZC{Pn;`oY;`yHL0NtTD_+rwk3@9y6XcEC^?9R! zcE;;L^H4Y^r( z^Q`5*G(ARnBd6Z?=1g8KRyq|5UOu|!TAv~{5d2!G0D*2}Oe)=yLxVOBUR}6AlFd*y5l(an@0mbSWQ~&-9%x>_P zjMWA{L3v`gpSKra*Sak!odc3`H!P^mz0&T}LshX|ov4N2b;oA+c}rO9o-=Z=ku{hQ@9Z&V}5=v;f|QnaUrqJlNdT7Q_r zmL*gwaaa=fgY|-zXPs!W4S_Y`sSH0aVQ<93-N`b@q2hf3Dr7vweT}Gv0p~Cz{QGL{ zR5sBEZBJg*9L`hq*=(Fv`QK~W&c7*y$7#r|AwTBKqy;B+?w(2(=!i1Z(D1dPyBT+4 z0sGK`ua-pnKFy4VS&L29;rO%RM8#>9LasEy)@Ytb+!vtRQDw^LT~Snc_1i0(h@?gP z_a*@^?0ZHt+@H+Q!I_kLd{T&}dyT7QQ6fys{4NC{Q%hBMT}*VzzVWlI$%3V18)W6R z)trh+;}RG}j4;(&77K;auHb} z3JvI$s39XOcf4Bd$$QZkeIh%jt&O+|XZ*&ypyzzZy^>4M${RCf$%|O{$?i8PZk(L= zI|&Y^sd$jGPvR~hPpm@t)0${+;`k_Q7)s(+0dMAqtz8-80MC zWy3^tnA3a(oiMqw(bT%$cmdHqRNIxj1np|b&>*w?!E$Zs5^Y~xkEY*YQS_h5{@5o+ zgN(hB6FOR9l*dREzeytoeo0gzO5>Yhphx_qxYC)oqG}0;-BLa?oINVT$xVfQqBx8E zLdH-)XZ+I<&?HxZC}hSx@W(^oE!io#`MM8$;~kwl{p1{!@Rd5ESl5d7KPZ7PURShp z;7nKd8!oyw7{>3d&#j-=4L)XQDZKcwac~@$M?1Fk^|fC=@8<5JKm7bv z6J#HXg7jLOk%YW&U5m=t+DZ)8=2p4ZA~v{P40k692G;Ue!{52D>z}@G+w1=BmBsyX z?dQU33~apMI~OA}^Aoc{x6ksGgG))pGhh`I9cU~yRXGc$MKB=!gw`>Ro7KU&R1Yb` zrmYxNYE4jROd5365@z(imp-~-eL=n?BU=KXE)b z@8nn^j`91PGYCZ<`=7(4|5G)`{1nFF5r-8@(fseUES1X-O&1fOiz&aclj&ChU}t6L zU}EKEV&zd~W9R4On#|*xH*|ntA^JGk8+$e>Dx3o2N@pLc+{NJNuaj-KNZctbFKjg@(exU$t+}hE6bYBpZ|B>_4 z(#sUUDk_@tOX%XON&SDC)KsJaW|lUlU$4$$Yv*EPZ_Z){bh9+Jw{vFse^t)H0pw)o z;^JdB<}>Cq;Q<1}%08V~jBv24gGxQV+_KeGAEwZ1Ip% zPb54dibj?pk|nfJRC@T0-}#;M>-U`VJD+nu_k8Ys-S@qp&p)3uds}lpZgFk^0Qf8| zOdMHW_t3aFSo;;xkK1WIN|`{f&u^}qyWGVRw!W&0K!oK zu#N`+Y!Lv6(8}&RoMt6BysgbmfP=$T`LHgR6*)q)@CX9{73)I-)to7~#R_uLEpeut zt6ZGCDE1MyA(kX(r=^LZv)}ykS?gd=(-Zr);d7mHowL%?CX)CvPQmQ#loURckf4!< z>@)8awvz@42Hqh3B&lAoyNsj}xEGv_2N}WIxWu2!NrOgY(}WQga-XZ;2h|0?#;SbS zn{T)uK8w@J^Vxmh;8Zsnc|N=$2oj%Y2DC=5>P1~w#FmfprB6e8WC?-a3f?OYkGxG& z+J2~GEAK6x^7?x5*{#15v42n8&5o~l$T!DS(qf_jK_q z{fN}I=WZamr(fEGz^NNF9hmSQqm$@$wRB*;9}24abW`?43;L$~Mpvy^R8v=VeFbjw zDO%7dv^b_cbqHnTF>q;#lzxUsN+$cFO_0n42oUAvFznivNzjR_M>_dwgN2Q|0J*@U zmFBrcIbnYGPR0%^w#S;R@<_SWEqQ5rOaMY5vs)WmW1zM7C!F1Y?()_ z2(OEf(s`w{Gw(w`+=IDXpS+gR7;)?6M-Bl%{O#iCJM&iZ)^9}x@qJCgyVdYo6@-~x zV--w00ShN#>mk0rK9l&Fhz`joP$&N6=RiByFad@+axHXnMf?-F}%5?-n0~Z4cFE z){YC>3OyU0bTB9_yqzM>-nCWqM=s-*E7wJZgR8L{>>DaP9L=!wx?o{0_7-@)mpb7;y^ zXT^y&f82@O(jQ$IFXj#t=3m&TDQtav0Djxx;KW;pdwUs*h*1g*_|RXqGa)K+P6AkA zZ{FhsW=rl8o5L~KX3{casQ5lspkL0Tb}f{0`wld6>~x0ee3`LCW-|`cc`3Zr7l#J> za$PigRxyw!pir_STm;n*^#UpL(mD<_j&X>?sasB33Klsj^r^gmMPI{#!H{{mELW^{F5 zPC7YjMC*ldbEKVc0VVJze^=JWQy&+{2M+wN>pac--lmpj>QvCcKZ?od&FNk*dEBy5 z@uslDP9`7&JjhKe$WV7USRcC{+vHCmHJ(E5WG;0x?k;Ydflp29U@U-Rp{!<3N)bKTUaQ#845=36$elMxa zGZu+Ll2E<@HTM6elq8ESlIkQ7L4hGbBS$;^(znOyEZpkpYCI3<|LvY z1@^?M?2!dOX?ku#2l>l)1!+>Xv^&Gj;kh~Ee>H4sZtB$pfObPdm-$rakDj!}t65=6 z!jCMT^A$H+EFKv8df9`&8d8+GlZ04fFO($<`C6g3L-OH4izkeJ9H|Bu#>!*_$m|cf zr`}+a(z(Cx0v z4f8h))*IC;t#x#)WT%IM++d0cFm}Nd0lmaYX3@Q%Cl36xUK6Qqj-B@*Yz7-iDJ>R; zR(9U2*UR1PV#2muz-*AFwt1Y^?N+*q*N#S~^1H6?%hucvUYfJfYXTp%1&lEn+hmc) z)4R;i{82c&MwOQNO84mK?EW)(Je^nkQEEJS5RW(g>ZgWXl*Ev)=&&Ve!^aiV+TD^=Z8-mWAJ7SRI@&HdAg}P-G@LYVTqw6mIKfzw1z55M-`>*td7QFbg(Ei z0)@h&P+W2Du>UEb2K!KaqyK+FwCq9|s{nS`AuQOJ9!Ur#0e*BkEewl9Qm6zniDeXG zfLd@U`N0^poW+VBvd(_tRBtTSB$yaZB?Zy3SbG*42B_B^bR+-4SRSfiu@)o>*^dsW z>!J<3LR?sk$S*qoVcaM_biYGnqEVWQg^2xv;3!lQJ(@-W{yi0v7DU!>bG7}44$hfH z0qR=1>KJu2Mh9IWm<4Ac{J-cpQ7(`Gl#x;14ZTfP%Jr9&i=!prO9>>gu8yPz(F23Y zNMAw(g%}(ZhWzi7BQ*#Zw5Fymny5?E_0c8}v~;x57!<3gx2~3sj}}3VRiVb3Z{Y-^ QhSdSEG_^HpHo_G$~04B%upDS`aW0ng~iHA%qSIB`8RdCP;l$;mJc3 z=|Q>(B1-cK4ALG*2Sw>f6DgT6Yt|a)tu^beefK*1{JwARbMHSV4rgw}&m+bI002MM zSl^PBHID<#$$G0FjQX(>h^%X-3jkF~yaxmh)*9k$Y-t7n!O{Q_b`Jo4uu5TH0Kgvs z0E@U>-mD%|&Uf3b&8(H7WooTsaQ5Ct4ZBtRfc;Yi7W; z0OsODaJ&a~vn;_1Sbbe9*U3-UC*mEjXPJ4oOK-m@A}=WW3ZWmiznAoljB5&o#A}01 z0y4wodE{WQSncj3_Sw?uYREq18RJ>ML3gB{706cCmSgl}ng@84=qU6aDWt5WtTmxE zu`4dIYGgZc{pRjd%svCfH(*_~IJh@dylF9nYQ0@{3eep6s{H)`PhM|cW9lSyT7Yi> z0Qo%NV-KasDo4t$bOLx}>@!U>6H6J+)=TBaeI2r>96rh73xDdTjjp)WjU^ z)VIV_Uxl)59sSzLXlV(zDc$xtW6+1(WWy1>9<{xDFP2j4?)crRqPUz`ChshBA9|u$ zQEWCQaMj~zbA5&j+A#<2OqAfQyxDZLJUKau$u4!SWqTgC_OVI4@(e6YHZgN}*yhpK z-TlV^XnA=V%qfv2U^ijYG~y(KL;#6&ii&s?0QnHr<%$P16!YuEGel!)px&LvECI_j zt+9I#Py91N$ZYW1vf-WwD56Va$k6duUI9jWU@TwiyO;CQGdYtSgCff+^>C6>!Vpf1 zE$r^9H^=nCf`seV40#w<7FR>&MlzomQi13-|KJdx(QXqHBCHD146ks6A!0 z526zr&~P$uJ+wT`@2%;`J1ROtv|X~)ys&%Q`3iS;)6+U-@ti|R@s>4Sa50;?r%ZpD zjZidYO&f`ut%n%fD=`(9sXX_qUeQk^Dcs>-al$^ohANz&%rq-2&B<`oj?b)+z=xk( z@ewT&Zn;nQeKwzO{F%s&+Rl}tsF}?&I!hW~n?K_-RL*+Sy;nKyv~*F7AtZQ)F|Uj_ zlfwC7Qtmyu(@IM{0HBF|Ap%AkWXtO${!R*I2#>~s2vGwjr>So3#W zI#HTqdez(0HPSSJ(%$gg*MCiEh8u~z3J+)~!zvI3+}3yd-5m4XuDp(3n$$$FCgYH> z58}M?;GzwKTWI8{SVS~I=SeHX>el&>x4>>Qk()Q$UJu7iI8jH0p`SHl!PMf!?B*WLF6xYo`Mqf84WsrI|zI zUs7>@&Q;qH>-%i`oO$nE(Fl8C87V55F{bw5V%|V+OM9DU$B#*amt!H?J?%YyBJSD5 zC2Z9)fakqKUX@2MY1>4!#?V9FJ?DsCwayx zE*ma2eAwsb+&F(K!v59Ks?tL$du71ggr0sB5%YU+zF~6_NNwPqid(jracUbTpx4=b zOV}o-^Av7CsbKtv&eEJ6MSL5<+m;p6(6CJ%UuI5}Sa&ww-!zRkEw$|OBn2mc>!T~D zho{rUY?1c@828dY`vNKKh`FgI_*3(DJYCk`<|3iB`ULqUov0jb?UBptrn=miAMlyB z;cE$WoSh+avwG}ub0%yl=m(b{>T0!n#;JUbP+pO`-dmV4SykgS{D<{!bAqKHh`wOX z)W!x{oT@(bb2=BeQMr1xO6>(K+`rG}MCn&W&#xu+{_La`<2u(Y#Ah~`C-XFB|1PzQ zl>8vMK^E21YtUUuF_buxW?1^~8u({7u#^j!ze$&+8V&U|a zCNVv{PI4Fzh5B2D*W=~L_vEa1EH2Q;oVDS5uC+NmGRg5yO>@j?yA>h%>pyA5fCNldRZNn))^}cS0+( zjod#EPXP-i`Ox?OarBWHgC5R!{o@c#tPE*> zA>~I-tBci|yZtZKZq2`r|8>X<>VXtWSL_~zH3xNO?JVdh!p}H7?^e;xKD4xs-qzZK ztj>PhQKMw@Pl=F~tp6OIstMadAie{qzqxNPX#_hNgz9R0LnvmMZC99{{dq$#**oUh^ ziq>1+NL@!qWoed`SGie-nY1o9de=r#<#nHAB*qM74JGu6es2O6bD9THc{cO4ev90h zHhDUDCmx()^j9e~n$Bjj`b0!{p;MnG&wF*%VQdZMAds>A@;#%gsa{Z8Faq+I2l^L5 z01O4eS^_TRP@K2&u$ zoZ?9!lUPALf6rU$>iXW!{+=W+nz}lUg;D{fB4!i(Zw&U> zMP1#PL?OG<03|h~j-#(NixK(B=Rb@sg-CNfMh42DU=||!6Jkd3B+=+TB;emu!F{~Q zm!I31|INqDibVlRXf-7jC8UZfGD9%w5(_!`lMkK}Oac&kdcPHDFSE96e%i9O!~!l9 z4-)I>a8ECqhc_ASLI|KZdwWsg|NZ1}Wr7M4g;GO0t2wI?F$4ly6@yekuzKE7L#qsRPGMf?kDeaT(` diff --git a/apps/docs/public/favicon/archive/lw8/apple-icon-72x72.png b/apps/docs/public/favicon/archive/lw8/apple-icon-72x72.png deleted file mode 100644 index 83dfc47bd21897b6800097ef6f2d90162f0991c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3208 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 YR&kNGz8QhxLRtp^Zh(Nj)JNU^4{!ef4FCWD diff --git a/apps/docs/public/favicon/archive/lw8/apple-icon-precomposed.png b/apps/docs/public/favicon/archive/lw8/apple-icon-precomposed.png deleted file mode 100644 index 7d55e102305d9561f5726dc581265b1a727f85b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13182 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 diff --git a/apps/docs/public/favicon/archive/lw8/apple-icon.png b/apps/docs/public/favicon/archive/lw8/apple-icon.png deleted file mode 100644 index 7d55e102305d9561f5726dc581265b1a727f85b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13182 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 diff --git a/apps/docs/public/favicon/archive/lw8/favicon-16x16.png b/apps/docs/public/favicon/archive/lw8/favicon-16x16.png deleted file mode 100644 index 9dc90100bf3a0c061a211fa8dbc7b47b2c3696b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1396 zcmZ`$Z)_7~7=H)$uGjYZ=X$+%|4LijKUmxAt?RZ6Ft&7TWv;Ya*)S8*uDy0Q=(^GC z8ZcSFXd(l)X^>z<6EwuBYykp%P(Nvu%>kP%bNa!A4;l^nO$>=~n@`8oN#dL5eV==u z_xJps-}Bt5fWMhk6etivq_4%>4qltv^38CT+ch2Fo=G&cH6V0tO!;R-26s!erM(TI zLn=1EIW2f#*U^YJyhDDHTqUxSqsmHEz(z z8I9bi&6$aU@-i)$Ql?YND3wgFlF?+&3~G!4(-HX^%t#Rc(`hghMHFhWd_7U5#%Yy| z(qRQOQLMuXX~L|*844>h5L?ukL5~$Pga!EZn3*B0KtkhNj0&3;GZ}D;NwL*{TTO~* z8QhkyD1lrGD}3_JC@sKXAS_0OwNO>IrVWIxYx_r-iP+9+yFrf{GlIM|B}G2dXsGZ# z9bU}qQ=;u&N8u$9M#}UgMuQ}fZP$cime2caa|g{gYV=|?C3vW~OZx&NFSROn95mk& zZFl=@_exZawfe&e>vY_D+smA!aVzvyLV8QdJ*8w*H5H3nzwEQk2MXTGmu~~*(5wb# zB{SHRI|b_(-R5gnB@d0maJH)IE7d_7H$(ecte~9q(byK40F6P!0z+6`UH$Bb8x;J- zda2#t;ml;8tc-JcWqmDYRbz z;6exL=-m0p_#5e=AyTDK6QuI-nenc0_{Z$v=$VnxQ)f@_YdI4L^#mBn zzjxG6>}@+cy7zP-C_D(HeRI=y?zH%PGhf{cE`{gmq1HQhXPxDh+Z+}4h5PY&-EWT^ zkEbTCd^lAxIk~tP)h>;_I`Przi7~N!GI@k!W8<&)Pbn+xc2S&6_Vrb9@$uI*#LP^^ z_E|CYu=f|YOJJ+Ig2AQx_ZO>KmUCUZ8oPSE^XAv{w-y(w+#XN$%^RDMS(ay6`S1bDe-e_Zm>56y{|U#o zKDY=8mRyB&DlTOsM+MX?Ndsx#=@gTZgaBKN9(JUTCO(}jejBi+95&RON%ru(Hxt%bnMaRRBb@fu}<}E+DqC@!Y$+ zeubyb4Nv>qeJCy-5ukNvvR^uqN;u<@Au*cjPdon|xw9(b=BlgfxM*FpE>;tXcxr1n hHw!g;>O8eEPs9Nk4$$|2S-cDtkgv(_ooWof^cOABiB|vs diff --git a/apps/docs/public/favicon/archive/lw8/favicon-32x32.png b/apps/docs/public/favicon/archive/lw8/favicon-32x32.png deleted file mode 100644 index b8fd7965f93fe66c00dd714e3577402c8f2e0c35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2056 zcmZ{k3se(V8pj8eNiqRK$U75~%!KexX7V5}9wi~X>f$3jv{hR|2qC;7K}GEzrR!@e zS`|?XS`SpzRcy5)t)Ng5w;oVb4o9R1PrDZIv99a!xa?7n?2X&q+C67yes}J7zwdv) z@7_6gX4~S089|5;fgmU-E7NKNz0}vJ^T5;k#UHPLZobQ$ZHA!JJL#|N0luIk)0PcE zYa<|N!yh2%1#oS+4?%S#1U)Q(Ak%&b;#IevUy=wx{;L-ME;kJmMMg@M3Ykt7o+uMX zNl>{24VR)3QZy3t5rqRp(Xuc=Ot_C&xfl=^jT0ta3IpK;QCV+b2U7tYh7T@-$_oL| z0DPto0gI06iDY0zh?SulC=2hu})wAPK0*V1umS_vK|VOa0o-6101Qqr%wxbjjGiQItnB`HuQ5FdN>C?oX*=UMzrtp zca-ASOYs|JvRk3BD2ZKHjD4?R7KrJ3yYwQPA`OMnP&iCLQ!ESnlMOv6q{Xq|FpQpH zVpS%xYZKWu3GC`@!QSOzU&-jnELh9{TMJ+pO8bn=1`^Ksy$c(bz8C^J+_APMIM?N0$qJC$WM=Ng9c zcDYkSm+&`LeZqXd_=M$~v&Wonr@M{IeE&dzxp>_joNUOkjUtZwC7JG_+|nc2E#sCY z&5!RiC~TJ(J-nb9J~lJ7e$92`>|G7Dapx{AmL9PuyJ=|Zbj_ZKKQGGKZ>o5~*E*(8 zT9;%Yn=Hp$J8j2z=h$*aZ%q#$)Jq1##oW9KU5kPnYYvHz*R@PmekmW-Yz`V5<1eQU z*RTJgIb5T;(O`{EMkMmAGpCdu`&n~;{-tui?Z$224(#gMs;6#A?VTR4DV*PNZ1B#w zw5w%NYhs%9hp_!Q#ycfhyS=NQJ!?RCz z!1i;lY(Q&xT$oUBK6-V)?%2*tqg$t+iOI8{+Ip`(x;B(iySKlSr#vs{=z4r>D)#V+ zxPbAY>CVe=Z(z-1Q}q>3`-KY^+S|W=Hm#T#I#a$;I2hrmJki%^9PrlB&yQx#n?c5+ zlmSHQq%-}h=SlLlTG7(n?fIRXo#hPisz#k*-TMA@pJ+?6g|Eh%Gj=YY?4AGl%d0s= zb>D|Q+`*&woZq`f<`MoI`-hSb^{ox+z5V3L?T3pkroO;$?)J}AXfEFGnf*XKJG-x` zt?tp_ zr|Q>a^2)7SF4@VV8Kh?W)5(pDt%g@$`lIQWYt}|h1RFyA2F@ii=_^VZ8F(+&mr^oI z9}4WwSd%KBxae@%?aa&*W6e!XdmlW1u`<2=bi?hxC9S(T{?W^^hlP#l?V}IgHBZ4G ze^;c=%R3M((&mYUvy#&-w~gkJpALY-Ecd1@^A_2?PLre72|7qksx=DIpdj_RDz!;# zFp=t5k~EPd_4mu9znM@`Rpc(N|Nj%}Wk0rp2~uALPgSvZwY}B}m3Y0?9uq;hE9@>O zXl_TDvZ~hAI}&yfX!$;EZb@B5p~+;ea@18gE4?PuVj%TEs-tr~z8}Kdnk-)ylPS~b zc9nP`l~J9tvL+8`cyHzTMYGghPpu;XYv>R zPoC^tpn_C7qe`n%YYpmV=FVs!VZ4B)DF3Zco-GS1c9%QB)`^Nr zZ+VrAD7LS1JE|%@#ILWM(Ac%=_;{n*VRRUa^me<>pjT^2P_xjeGZg9UN-#qS*7qZK R>Fa9H)3DP3004R|O*KQ3w)-no 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

2yjGPtG^bD^ zFB{S&A@hmpE|rT#ml%KR6$(-5he1=%BpMHEy?ieqD)(olg2MVrIWBnaFH0$0(nqExm+^v zS6_ivF5DX)FwH7y%DTHS_R_(hKQy=1K=Y$#xN^%BN4Y(v%zTqd7Fk*9zj_I^7Kt2# zrZZ0&7)d^@hp{fxqXXnf67FbsFzI51K5Uq?+3>Og7di!WE17R6T|iUIQA+c>!Yf$@ zm;;J+GG%@>ev<8|*><3g!8Fe5BaTwkh#nERUQYfddtEXss;>e;X(ehh83C@$KB$lV zp>bO3>0-a6dCfZbhRBm0$>j+bRkvhWA+7oL^-i}%JB_1~MtBh`6G*fMUsR3!Ma@S? z#wtdu5UT}mof45*9TBqk4HIl@_VsZRf10~RYy&noX*|HPQ>XxG7`AWI^&3~r$r2@1 zmdGX-hWQvZYEJIb8t$ZzOuF}_EjwXyY53cq zo^Hk~vDIh=CU6gX=9G}Yie(UV{+&M8uF0$p8;Rm1Z`|f)e!KsKQ=EZ*__O=dl%rTZ zj6Uvj^XSmIy*LFm#O94&YGv^$?}#+(;cJLs*bNfr(pfCXw3~7p6wVP-3H|lcAA8v= zC1{26>YYeVcxi91D-SpKgKqVV@%>p{2h(b%#L-GCIbF~}cV@@=PF(;NzzdYeHk?w6 z{Am%BucEH3n%65;vvutT?zEDY)dx|u%y9Q1I02wO!q`&;Vyx17n9`qdh)f$8Su1%-i5}tQF)mx%&m1JHr+0h-Sl;An9d|b{XC+(-S zdgT(Qd}4CqDzW4!jI^|J3d>>_YM$O7f-(bHaVZ5rI3KIu($w393pNlYH2AVCMqBV jMCh~<7ZI}-vE)T?@FM!RPBv4D&;U?T)KvH)XA$;avZdWJ diff --git a/apps/docs/public/favicon/archive/lw8/ms-icon-310x310.png b/apps/docs/public/favicon/archive/lw8/ms-icon-310x310.png deleted file mode 100644 index 474d2d508f49a0a2a294a7ffaf296ff88a55863d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23344 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 diff --git a/apps/docs/public/favicon/archive/manifest.json b/apps/docs/public/favicon/archive/manifest.json new file mode 100644 index 00000000000..3b557aab8c6 --- /dev/null +++ b/apps/docs/public/favicon/archive/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "/android-icon-36x36.png", + "sizes": "36x36", + "type": "image/png", + "density": "0.75" + }, + { + "src": "/android-icon-48x48.png", + "sizes": "48x48", + "type": "image/png", + "density": "1.0" + }, + { + "src": "/android-icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "density": "1.5" + }, + { + "src": "/android-icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "density": "2.0" + }, + { + "src": "/android-icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "density": "3.0" + }, + { + "src": "/android-icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "density": "4.0" + } + ] +} diff --git a/apps/docs/public/favicon/mstile-144x144.png b/apps/docs/public/favicon/archive/ms-icon-144x144.png similarity index 100% rename from apps/docs/public/favicon/mstile-144x144.png rename to apps/docs/public/favicon/archive/ms-icon-144x144.png diff --git a/apps/docs/public/favicon/mstile-150x150.png b/apps/docs/public/favicon/archive/ms-icon-150x150.png similarity index 100% rename from apps/docs/public/favicon/mstile-150x150.png rename to apps/docs/public/favicon/archive/ms-icon-150x150.png diff --git a/apps/docs/public/favicon/mstile-310x310.png b/apps/docs/public/favicon/archive/ms-icon-310x310.png similarity index 100% rename from apps/docs/public/favicon/mstile-310x310.png rename to apps/docs/public/favicon/archive/ms-icon-310x310.png diff --git a/apps/docs/public/favicon/archive/ms-icon-70x70.png b/apps/docs/public/favicon/archive/ms-icon-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..48f6391fcdc77468ed714aa60cb61040a5ffd793 GIT binary patch literal 3461 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 QfHp9Ay85}Sb4q9e03B^GS^xk5 literal 4112 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 Jmvv4FO#p}Vm2v<8 literal 4593 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 diff --git a/apps/docs/public/favicon/favicon-96x96.png b/apps/docs/public/favicon/favicon-96x96.png index 0f1351f3670ee2e3629420bf5e152ec200846cac..d3121ca964ac870fc857c66a372d004620a78bcf 100644 GIT binary patch literal 2176 zcmZ{ldpOkV7RP_XXpCVqgw&*Q&1IO2k(n_ggfTI4n`EaLb1@^A!BC{Vhm=%uze|&f zE^=JvDeZ)!Cb_duDz#M;Myb$EvUlg_Jm+~%XFt#RW4-HH@A`b#TJQVE`{wxj(X}+z zYXAVC#qjnB1bxJ+sYAilyP&fbbkHa_rW*h>=OI?uYG91!cn2~8Ak7j0Bv}Bk3~ou3 z0FaCWfY%WKKq&_RLs9i_0aP%d66r(t0KRAE^>>01T;v^^1ON!VRf7PP)$71bn3%!z zgeg@}2xCJn#IpqeSYycWa0@>0>{ zJ)a>t&_i9YV;8l}UmjVmg;Og;$dj4K%-hPtBT_GjXXejZ&B#DFG{AZd6M{faMEcCW z8(d&VU7xs>%un%)s+wm~o>lY@rcZuP9Q=BwA~YkHB7qY}@0jxab8BTf^<{ofNcR&y zP3n}*Ju~$TAGsfdIa}&K9EL!9IfZ{X<>I%Z;(BK=S-HLW_*JSm)QBk0%=akoHcdF~ zz#8euk~mA<8#t;#hxs$>iVnE;i0S5OTCD8+Nc{~Lf2u68ElxVqhWX``KtIFs8o^HB zWo%9y9#rdv*3`KOw$%6!t+%mAN+k&_Ynrnx84lNB1KkeM!cq)oHl-8ijw$Zftn>^h zx0Z)~sK|*9P2?Ew_rE|Bi6m7jnMd)E^|W8q1Za2tNKKD*${ykrre5tX(&fBUs6(zH zWc^(|nJ#1+*R%KB$K0&p$cMTRY34U;2b7l!qN#i!Ejnm|ckde`Ty2+ceaTT7jjx!D zf*3ebhtd_rTJYiG*2)V;n^AP*eCmVf2ZYZy3f*+w2>h93GJRU%F1bsSCDyYq--GV* z<Q3&7&^`}&qUYePug@E2 z=F#W?8R_OG3%H)&xnjRK^N|-V+8BQC~aymro<>;Y<&q%le5j zQ3)?oAv#j!Dsp*9qSJVRl{>jq6ut4q?qS?gJGT(rgIKuD}eEQ#)lc{;_%D%t`{*;h6T=xNJ;OCc)XJKIM!Q8WYXB>H1Rb z&0oten(5_goJeh0*d;r*_VL{PAx{_UvnK|sley0VoC!>|KI$aGFso?}x4kUCs$Dkw zWpT}<^IQ&H|I#IPDSf%y*jxLo??lw`8@KnmB>bL3UIeV-tleGJX{H&hKe`wx>@%%Z zZt}O^F3RD{ZT`iuQC06#O*i{r961*=6K?qD6*EZojesoJ;{K4wiAFNH8*bDSN!l7ZDV8szYrdSS`QvpA7GUkF7=B@0h_e zN`umA1HQ)e#cnWnL1Q!yl9&P(9i|4=EEJP%DfDi>=|?F z_+Mi&ipYX3C^N{7Cp9Nx6ygyRoqV9zF=g?vHZq0^Yp5RCG^Og26efdOb(w}Nb(OWt zBLaGzy;O*lD+|FW4lLx*Z?XkcQy>`~yL>ukX2&EZYNhv60i&Vq&hF~@kp+$tlEIbG z(iLy?@0~Yd+8ca(MDH(q#k{i=+auOa@4NZ&+xE!=G@Wzfev>+zAK%uW#0nm%ZbQAm zLNi<28TA=`WX$VZ+eTgW=FK|SlRFb2y_n&n)wDJ7IE!OdX^C&95jt*)I*HVT=I30d z@v^W+N?v=!xObCVl9k4c`6Loic_gYwP=tE*UYdHq%L!(&b%8ZZr7Cpf=Bjgb4&c)? z+-twgg4*Nnt2{V7tsF$_5LPVq4l`< zWIUcsBH&$@%ez2C`-eI~!ZaR$b9XPUb(sTGJAX*A0vP~b7{ddPj*X2I$HYfr`Ro)S zCq6C-``;_ak~jn+j>pCkx8NPfI0rTnM~)=$9Gx7vkz6u~%e4m;_TYTv{VnIg4gkZ` K&!f>jBJ*Dw-HgBh literal 4447 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 n8#Cn*%cygYC3ji?9DsO!2mfpBm*4#SXX zAC)Aag`ib9J9peHS&6RhCY+hfojK>;Im3jpC;oaojJGm-e`f5BF{W_v5RaVWykm^d zy}q0w#=HrILLVF^2Ob1*h-*B^bLP3pl_Uw#Xw

?(bkQh*&I!R;z_vE(gEge>a!* zL;PeiiOFPw!C-()CWAmAa8rYF_2#ndiqLiQD;y3ZpUByVllHM{kskpIr!HPY$yujh8D qLwQtHMYr2^-RtH0YhyZZ^7Y#MSN!T7xb)aXhq(W`zxIFNul* zD1s=2B&dhPgB77kK+Hx>T6@TbgeFb4nb-e+@6FC+J4ttTXEyUCe`e;*1itV8|M$N) z{3CD#q?9Q-43S+V>nF>ixwuYNB>Pqf@fCuA$X_KZ$@pM}?Cn~Jr^sexd@)0o^>P*- z@_b_k%}50UI9$L-|s)Rx3{shw1j3Nm&>7}qvNRCvm{`EPm}dXD}De1|MAH2>ebb=be$Q ztu6HR^&yU!pP#Ru*hP-OdGE;b@-pIz#l^+yp{#`nu>a-@xbw*+*w1t#YJ@JJJe))M z)n_5Q+ekncqDH6!?0h!~$m`Wb2uS*g8lef0J?$vJTOi&7LMdSK0#PFz0c}a#`>-G4 zOgk(VV5tzm?tT){|j(`#(qK`ns0_5xGATK|!LP=|iCT$~v^5Bog z1Z2~Y-VE0jpV2Dr~V2UDz0ZS3K(Zt%$VYDLF-|nZYuG- zux&{Zp=HgsHEAalwydlhlCF233%>OTCg5xu)|CP@cSA%PPAUR$a>Om6%EMX&4_W%I zTBX%dx~p~j!v6@0KmrmU3>cE`M0LbC^Mu;>TV73)fm~zWfgsf;xmhPhKhgAec zplU7JlX{{`69Ks7g@=3v(jlm1sB?~luC}&0(*N$1@x!dVg z*3EsLV5y(}L)Y9o>P6rxWKaK9^Row+v%rOJb0tkGIb{@hqr1vJ^ zDI%XNg_HMQL|R5q-`K?Czurd6&0Vxo`b2?91tfM4aOV5Q7OIDVQ|QnZu(!7taYa6# zuO7P20%pAR16bgtNxLf1Xa$0>r0E0Us$MmO~4(7tGCLc_(fGOy9O$FQuiHiuQ z#pKhSDRKkcGVRKbs_$}7irYFIx|0H@GIQ|hk1-VIn%k^C&4oz86ZV)4m?Ovc^NCjg ze;dK=rYz!(BG~{5;G??|n^YQr&!mnK=AgUu#bcl1)~nPXSi}YV;mK7$uHs=rpxdxn nvKP@@@B%w)Y|8mIq8j%BbBSNTBUb6v00000NkvXXu0mjfsdaiP diff --git a/apps/docs/public/favicon/ms-icon-144x144.png b/apps/docs/public/favicon/ms-icon-144x144.png index 00a5d8b51800f0c80c7245d23d5e98dae278f873..a6af05bf04b065bdd2d430f07220f1b7020f99c7 100644 GIT binary patch literal 3243 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 N0FQNbY_#|P^*=Y2i8}xQ literal 5379 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 diff --git a/apps/docs/public/favicon/ms-icon-150x150.png b/apps/docs/public/favicon/ms-icon-150x150.png index 4de1d9b1cc18a062ecbeb63f90db71c06909dbc4..bbdf205047c3cbdd698c15b9e5e1a21333d1fbb2 100644 GIT binary patch literal 3404 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 diff --git a/apps/docs/public/favicon/ms-icon-310x310.png b/apps/docs/public/favicon/ms-icon-310x310.png index 7ea95ae09c0732921bb1ecaeef3f71aee22c8014..42bd0698a0faebccc5c699e3abdb2c56503692b0 100644 GIT binary patch literal 8773 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 YKIdZ?yj+&ZgMdFpSyh>GDdXV(0eX6_zyJUM diff --git a/apps/docs/public/favicon/ms-icon-70x70.png b/apps/docs/public/favicon/ms-icon-70x70.png index 48f6391fcdc77468ed714aa60cb61040a5ffd793..b29d70d3bef79fae65096759866f6099795977be 100644 GIT binary patch literal 1752 zcmeAS@N?(olHy`uVBq!ia0vp^ZXnFT0wiy%Yw-gqmUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VX;-`;;_Kaj^+ z;1OBOz`!jG!i)^F=12eq*-JcqUD;nS$#Bbw^K#$)2(&QY)5S3)*%d#3m-Li1+fZ-tT?iaRnTRH(y|DR4)G66 zrW2O^deA(bUH8X=h_%}iqPE;H6EnG3ve+!m-12z)%)RO9Y3cmdN8fLl-8j?s^X>oN z=f98H#H7&f_{Hc%*tLnSmu6mgVtI_cM}J$JZrRErGJEeIFM6^w9BH z1QJYdsS9D!Sg>Of<3w}!%~7cW<;I6rxj1-TJj-TykaOzG)RuoPfi`pE>_TU@S1K%I zx$4IMT;;n;((Pj&n?s-cOL4s$j#b`EV4A4Y^DJy$y6yu5my1k3Z%i`RrJ83mo|w38(yAE-vrKu4V|NNmdv5T)kq$QRuKN*>rsV0=U z;L4L5XH6T!Us%;nlUjXff${-~O*UtJ8N*A8ZJ$r%SaLt)?nEb}^PYYiB_>=6kZ3-w zoWuFWbz1M4hYuc2T2&c3t2<@Z_R993%W7NIq76=z-I|Ve`ytWijK%?iGPYT(2&u@SK%w-_HCihbcMY*xV9Vr;k$v zLlyjXKARGtB6ODVUT=7MP>h)1(O|b}!B=L;z5gK`_ta^@wM~)V|9=SfHc<5q5p{Bv zJo^1jqL#{A-}7RUPkme@UPfQf{LuL&@Z2XRb!SQ{KWB@3TxVpk9Lg|?k;_Ux>?M~Zx`}ORQO=FybzOo9Ozd7K5sepT zNd2~|In80LyMFnar7M%-+v6){UN+p7SG;{QOK_l@;o-P_-CuRr+W9iMHk$v`dDe9O z65q~`({l{Y{nk15=IErxt?|$JK1+!w<+DUI2>v;m;K-UC(U~Nq!!9VP4b_$P^R+a#wC)cJ~lrQ`0N?X z5b(hHq+_4TS;hnAG9fb~|0OiMYYAL-%(%SYahu8q<_*q0vyGcPAK2dxeYdlHaeWxDG*T^bjVMV;EJ?LW zE=mPb3`Pb9nO2Eg!}&{MJU|T! zARCJF(@M${i&7afN=gcft@QOXa}(23fjBccTQ9#Teb0H>xj?lNAhjVGrMXE~RxbI; zrManjC014eK&8bDhRgr&)<;w02{OgX$|E&1J)?xd(9*~uwlEZ^MjXi;sG9K1l#&dP zlFMrpIecG219cLOG86T3nN2^Uo#E> zmGC2(6P#I<%3$E+G-Z+98=zDel2mArCqr6hPAbsr`nh=}Ir-`OX^CZ-$@zK3`iLOc zw@5ZJF-T1`FflVUwlpwKG%>JDGD`Pv9w4@(F5wx1G>+$eA5!34Gf;HelF{r G5}E*vdCF`6 literal 3461 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 Yf3#Z=MKVGyyZ`_I07*qoM6N<$g0)0~0RR91 diff --git a/apps/studio/public/favicon/android-icon-192x192.png b/apps/studio/public/favicon/android-icon-192x192.png index 7583d2035e3483da2dfc1f9ae61a35944e2d3af1..ec26f1baeb352147a035d7a50010502f57fdfcdd 100644 GIT binary patch literal 6447 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 BLEHcU literal 2078 zcmaJ?c~leE9*&?W2o)<*P{bjih>&D5ge8H1ks$_1AV#QQ3o;}F36RBPkWHdiKv~p^ zl^2?d1=)OX5L-nM%c50O5D)~cf>xj^i}IR>ilXuoE57$feRIytz4v#%@B6LyOcpnA zlZnv^BODHA;>Ut{+SN|?E;7)5AL3Lh?P7`fhGJW!(O4oPM{x{+Gzta$#7GRvLlHsp zj_ar=4yV6P6da0$a@aJ!R7^y47-EuGre))Bp593^gdc}uKolAylF;#!4NZ7JB%tHB zx^O^_%m)>USSfOJOG;ocKP8S&72v(S0M8_vRzQqm2#_R>mndjSbo_f=ns%=fdQ7Vrik*QQF34}-xM9?A#iew3fBoQPE z+c^aoRq*8^877iS0G%QdB~8HScx|wMWg(V*l$9txR7zVjQW7E~k%^!#t2rQt^Z%h@ z@kg`*aS*;pqO&->r*JqlKZycEBz)8lrsK6DM3G29gULR=ZWJaHcA>bC$-XedmjS^b z>nsNqMdoUcDP?P{lUcH z=I8psjNqiZzp8@RRv}icO_MjBX3A^sg!_kyyMQyQ>2jN;4K^v7OD$WL9kpKZa|KdQ z`M#HRamV;|eZwOay(OlzR=L(Cg=}{ALLQlJNhq#@a~7NY4w>yteDo?+8q?Q*)4yP_ z)N}e$ySlxx^NsSsgL^MC4Q;r+f!}8OJ!Ty~y6x6LtspX^4XlFyUKfrnH7clhh zoHy(A6JuJt$Iz3zYYy+LcSy~es<*B`ch04~v$JwG_e|M{|DokMSF~4b4~*ZOmYhD- zI6u3m#iZL|^2XE@W$oIvH5V>qUly)fwaUWMl0iG(*WktqQcpb&Srr`}ZNTUA55Ra~ zT%3m)(DoDPE=&<-2S5K^l83OxJa#5FPg9C-u~tKW2VLiWDk#= zXU`<3XY8Nl*T!}`LmXw~okEkHl&5$Lo0zg zd>T(tW-zUx$C|$ZYkZ}rA)A_xzfme zw3p4^;<=k|I)Rn@t2Mb4V0fhHr>fTCJC2#R(_0OTjj!Bj!Y=mg*4x`eI2+Nhz+OPX z1=qA}f40ze60EE!REhGqu`-RBkr{PGKwU_=GL-7Sem&G}QkoliXPJEqX{wSE!rN?e zl0dS0xF@F}r{7S0AYx{5t1{Gara}S~RQH+J@Cjq1D!Ef-37n_tHwI)R(88w)G?1!z$h;LD@@}b$k`1N6s!8=G3zX?@`m15gg4+Zwk9T?QBh< zN%H7hHwUAa&4zMJS)bdN@m&A%wA$jgcbn6Pg=<~AyiWMMQ6EbSxJZ3~y5K9=6Lm*y zPNe6bzx8}HPh+-A`PlU{yMpxbHPD$e;g|MpRc0W^0QRioo-*9^@2K-_zlh1|RQk9# zr2UwEp?rUAeC3i6!k5Kw`(9Gfi5IJ-mtP=5W8^hmLn{RM_7$}~OV10gIwZ*;Kr3aa0clV0KS)%vD#gkQ)l>y=b&8uDETxDc! zZ7t~OnOj(B{kFSbeo`en-+eq{a%9A=tgP&Ik+$M*9LgsV43e)AtS CpIdeS diff --git a/apps/studio/public/favicon/android-icon-48x48.png b/apps/studio/public/favicon/android-icon-48x48.png index f8d8a7d9c05acae1a80f25ac81c3b1d2388b99cf..a3494d67f2ff428d8c9032955311488efbd1493b 100644 GIT binary patch literal 1854 zcmZ{kc~sL^7RMi94Tz$wD$-zOkruL$1QJw|5DZaS!Vm6EubKq$Xd$$=$UiI={a-Wx$mBL@8^5(eeaK#>EXuE z*4(EF0MKT-&^=*~*)|O|ct4F;%YdCq7}b>uKx3}f@4>3@85Qc{=?Xx+IRLVB0M_A< zYzhDgEPNLP0QnjKhTi|Kr;e1GT6Oz9+PF0O3lsO{%#iKSLi^1E`Rf+cTi^-wx4%auK^jX%1>DQ9j2 zq{%nr*dXv!+U&2Uxum2n^B?HQmS0;qpR7D@GLHxv?#ESL>6c3t`^Pu_KvsO6tkd`8 zpZ6*MSnWyP6I(rU&Ra?OSN)gIMCPujhPtC|0u>^uEpoQUlHU!~tAk!hOpycbQHUJH zckOAf9nj6QcdDob`h&wC=TOa)*!9s^gM#;|PqA^!yLul9beMF?bfpCZ?UX# zNx7SjN80|<+3p$s&c$rq0WYq)IL$v?+SJncx}vcknNCtn{U&?Be58o`cD$|$@oViQC9 zIdNdZ+K)K47thTrbbfB&nh?!kKrZCCdiWvm(1ue)%X|DjWX4fCP~Pnyn_&|8LNH+=eA^bT=eBG7#BUc9 zs#c5IiCDMvnVAP~9Y>1X#FI;yqJ^4b zAwgGPVYSoBbZl>LmzlX^7bWi3vf|l-f&?N;aiaNDa*XO@Q(MPekM&KzAMDl|&tz7r zE$pa&o!D!Wv9V}RIJ~&xO3C*?@$E9rbu0(RH`MiSpIDluc8r|zP64Z)DekgzX|u1Y z4Vc^aX2l{UTdqqfZ7F-HG_O2wAg)<%eQY#O7(CE_IG8(Ylk6Wu_Svu*5H=oaTwY4 zNu9q5;<*4rqZL*hn}Ji_pQPBHOu!SIuEu${{{=&5|01? literal 2568 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 diff --git a/apps/studio/public/favicon/android-icon-96x96.png b/apps/studio/public/favicon/android-icon-96x96.png index 0f1351f3670ee2e3629420bf5e152ec200846cac..f2bb98f0e06794377cc1e0400915fb99784ca129 100644 GIT binary patch literal 3285 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 literal 4447 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 literal 3914 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 Yf3#Z=MKVGyyZ`_I07*qoM6N<$g0)0~0RR91 diff --git a/apps/studio/public/favicon/apple-icon-120x120.png b/apps/studio/public/favicon/apple-icon-120x120.png index d2b0e50ef41fc56539ff0f7dd19f272da7b1738e..e8cf4644d1001643258f8ef9d4e3f36ceb9357f4 100644 GIT binary patch literal 4264 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 diff --git a/apps/studio/public/favicon/apple-icon-144x144.png b/apps/studio/public/favicon/apple-icon-144x144.png index 00a5d8b51800f0c80c7245d23d5e98dae278f873..6bf7c690b8441a8f414e1d367b1594702e3c3517 100644 GIT binary patch literal 5320 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 diff --git a/apps/studio/public/favicon/apple-icon-152x152.png b/apps/studio/public/favicon/apple-icon-152x152.png index 310532c4648a52f0f8282bf695eecd92b0fa18cc..0b89549ad187c1dd4ed62d06b5543feb7b313fbb 100644 GIT binary patch literal 5689 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 ITF!C*1#tmRSO5S3 literal 5816 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

{user ? ( <> - + Welcome, {user.name}! + )} +
+ + { + onConfigChange({ ...config, xKey: value }) + }} + > + + X Axis {config.xKey && `- ${config.xKey}`} + + + + {resultKeys.map((key) => ( + + {key} + + ))} + + + + { + onConfigChange({ ...config, yKey: value }) + }} + > + + Y Axis {config.yKey && `- ${config.yKey}`} + + + + {resultKeys.map((key) => ( + + {key} + + ))} + + + +
+ { + console.log(e) + onConfigChange({ ...config, cumulative: !config.cumulative }) + }} + /> + + Cumulative + +
+ + + + + ) +} diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx index 5b637ff2932..e3ed51c9bf6 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/Results.tsx @@ -52,8 +52,9 @@ const Results = ({ id, rows }: { id: string; rows: readonly any[] }) => { ) } const columnRender = (name: string) => { - return
{name}
+ return
{name}
} + const columns: CalculatedColumn[] = Object.keys(rows?.[0] ?? []).map((key, idx) => ({ idx, key, @@ -90,7 +91,7 @@ const Results = ({ id, rows }: { id: string; rows: readonly any[] }) => { columns={columns} rows={rows} // style={{ height: '100%' }} - className="flex-grow" + className="flex-grow border-t-0" rowClass={() => '[&>.rdg-cell]:items-center'} onSelectedCellChange={onSelectedCellChange} /> diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ResultsDropdown.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ResultsDropdown.tsx index 541e588aac3..6e7e25010df 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ResultsDropdown.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/ResultsDropdown.tsx @@ -104,17 +104,28 @@ const ResultsDropdown = ({ id, isExecuting }: ResultsDropdownProps) => { } } + function onCopyAsJSON() { + if (navigator) { + if (!result || !result.rows) return 'results is empty' + if (result.rows.constructor !== Array && !!result.error) return result.error + if (result.rows.length == 0) return 'results is empty' + + copyToClipboard(JSON.stringify(result.rows, null, 2), () => { + ui.setNotification({ category: 'success', message: 'Copied results to clipboard' }) + Telemetry.sendEvent( + { category: 'sql_editor', action: 'sql_copy_as_json', label: '' }, + telemetryProps, + router + ) + }) + } + } + return ( @@ -136,6 +147,10 @@ const ResultsDropdown = ({ id, isExecuting }: ResultsDropdownProps) => {

Copy as markdown

+ + +

Copy as JSON

+
diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx index 6ffc291b1b8..6e65ed72fc5 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx @@ -12,6 +12,7 @@ import { IconCheck, IconCommand, IconCornerDownLeft, + IconLoader, IconSettings, Toggle_Shadcn, TooltipContent_Shadcn_, @@ -55,8 +56,6 @@ const UtilityActions = ({ return (
- -
From 24da48d0b107f250e8a01a6546f70f712438a9ce Mon Sep 17 00:00:00 2001 From: Jordi Enric <37541088+jordienr@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:36:57 +0100 Subject: [PATCH 18/62] FIX: rm breaking error handler (#21692) rm breaking error handler --- .../interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx index 9d798eb2c86..9ba744f6ca2 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx @@ -37,10 +37,6 @@ const UtilityPanel = ({ yKey: '', }) - if (result?.error) { - return
{result.error}
- } - return ( From 5302a01c60bac671bf6b0a4f067063842239475b Mon Sep 17 00:00:00 2001 From: Vojtech Novak Date: Fri, 1 Mar 2024 17:18:46 +0100 Subject: [PATCH 19/62] docs: mention local option in generating-types.mdx (#21695) Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- apps/docs/content/guides/api/rest/generating-types.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/docs/content/guides/api/rest/generating-types.mdx b/apps/docs/content/guides/api/rest/generating-types.mdx index 397acf2e9c6..624749a1d17 100644 --- a/apps/docs/content/guides/api/rest/generating-types.mdx +++ b/apps/docs/content/guides/api/rest/generating-types.mdx @@ -30,6 +30,12 @@ Generate types for your project to produce the `types/supabase.ts` file: npx supabase gen types typescript --project-id "$PROJECT_REF" --schema public > types/supabase.ts ``` +or in case of local development: + +```bash +npx supabase gen types typescript --local > types/supabase.ts +``` + These types are generated from your database schema. Given a table `public.movies`, the generated types will look like: ```sql From 51dd35283df56e8cc82d6e64b3db4a7d8166b6ea Mon Sep 17 00:00:00 2001 From: Egidio Salinaro <129901135+egidiosalinaro@users.noreply.github.com> Date: Fri, 1 Mar 2024 17:25:06 +0100 Subject: [PATCH 20/62] Update error about Magic Link in auth-ui.mdx (#21694) In documentation, the default label for Magic Link `link_text` was wrong Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- apps/docs/content/guides/auth/auth-helpers/auth-ui.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/content/guides/auth/auth-helpers/auth-ui.mdx b/apps/docs/content/guides/auth/auth-helpers/auth-ui.mdx index 2ce5f9fff37..0fc93deb684 100644 --- a/apps/docs/content/guides/auth/auth-helpers/auth-ui.mdx +++ b/apps/docs/content/guides/auth/auth-helpers/auth-ui.mdx @@ -397,7 +397,7 @@ A full list of the available variables is below: | `email_input_placeholder` | Your email address | | `button_label` | Sign in | | `loading_button_label` | Signing in ... | -| `link_text` | Already have an account? Sign in | +| `link_text` | Send a magic link email | | `confirmation_text` | Check your email for the magic link | From 68513fd618639b5ce6498a2905ccd4e53b1101ad Mon Sep 17 00:00:00 2001 From: Tyler Date: Sat, 2 Mar 2024 08:36:04 +0900 Subject: [PATCH 21/62] docs: Ppdate Flutter auth UI docs to be up to date (#21691) update flutter auth ui docs to be up to date --- .../auth/auth-helpers/flutter-auth-ui.mdx | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/apps/docs/content/guides/auth/auth-helpers/flutter-auth-ui.mdx b/apps/docs/content/guides/auth/auth-helpers/flutter-auth-ui.mdx index a9549822959..7abbc5e22ac 100644 --- a/apps/docs/content/guides/auth/auth-helpers/flutter-auth-ui.mdx +++ b/apps/docs/content/guides/auth/auth-helpers/flutter-auth-ui.mdx @@ -7,17 +7,14 @@ description: 'Prebuilt, customizable Flutter widgets for authenticating users.' Flutter Auth UI is a Flutter package containing pre-built widgets for authenticating users. It is unstyled and can match your brand and aesthetic. - +![Flutter Auth UI](https://raw.githubusercontent.com/supabase-community/flutter-auth-ui/main/screenshots/supabase_auth_ui.png) ## Add Flutter Auth UI Add the latest version of the package [supabase-auth-ui](https://pub.dev/packages/supabase_auth_ui) to pubspec.yaml: -```yaml -dependencies: - flutter: - sdk: flutter - supabase_auth_ui: ^0.1.0+2 +```bash +flutter pub add supabase_auth_ui ``` ### Initialize the Flutter Auth package @@ -93,9 +90,9 @@ Use SupaPhoneAuth to create a phone authentication form. ```dart SupaPhoneAuth( - authAction: SupaAuthAction.signUp, - onSuccess: (AuthResponse response) {}, - ), + authAction: SupaAuthAction.signUp, + onSuccess: (AuthResponse response) {}, +), ``` ### Social Auth @@ -107,13 +104,13 @@ Use SupaSocialsAuth to create list of social login buttons. ```dart SupaSocialsAuth( socialProviders: [ - SocialProviders.apple, - SocialProviders.google, + OAuthProvider.apple, + OAuthProvider.google, ], colored: true, redirectUrl: kIsWeb - ? null - : 'io.mydomain.myapp://callback', + ? null + : 'io.mydomain.myapp://callback', onSuccess: (Session response) {}, onError: (error) {}, ) From 538fb7ee0ce7a78b181f8e584e97b8d8c22c1f73 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Fri, 1 Mar 2024 22:17:50 -0500 Subject: [PATCH 22/62] docs: add federated terraform docs (#21307) Co-authored-by: Han Qiao --- .../NavigationMenu.constants.ts | 18 + apps/docs/package.json | 2 + .../guides/platform/terraform/[[...slug]].tsx | 167 ++++++++ .../guides/platform/terraform/reference.tsx | 400 ++++++++++++++++++ package-lock.json | 4 +- .../ui/src/components/CodeBlock/CodeBlock.tsx | 2 +- 6 files changed, 591 insertions(+), 2 deletions(-) create mode 100644 apps/docs/pages/guides/platform/terraform/[[...slug]].tsx create mode 100644 apps/docs/pages/guides/platform/terraform/reference.tsx diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 512de1e8198..b533e6779b9 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -1656,6 +1656,24 @@ export const platform: NavMenuConstant = { { name: 'SSO with Okta', url: '/guides/platform/sso/okta' }, ], }, + { + name: 'Terraform', + url: undefined, + items: [ + { + name: 'Terraform Provider', + url: '/guides/platform/terraform', + }, + { + name: 'Terraform Tutorial', + url: '/guides/platform/terraform/tutorial', + }, + { + name: 'Reference', + url: '/guides/platform/terraform/reference', + }, + ], + }, { name: 'Production Readiness', url: undefined, diff --git a/apps/docs/package.json b/apps/docs/package.json index b934a33525a..2d37fe12d91 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -33,11 +33,13 @@ "@supabase/supabase-js": "^2.39.3", "@tanstack/react-query": "^5.13.4", "common": "*", + "common-tags": "^1.8.2", "config": "*", "framer-motion": "^11.0.3", "github-slugger": "^2.0.0", "gray-matter": "^4.0.3", "hast-util-has-property": "^2.0.1", + "icons": "*", "isbot": "^3.6.5", "jsrsasign": "^11.0.0", "lodash": "^4.17.21", diff --git a/apps/docs/pages/guides/platform/terraform/[[...slug]].tsx b/apps/docs/pages/guides/platform/terraform/[[...slug]].tsx new file mode 100644 index 00000000000..1eb6d14123f --- /dev/null +++ b/apps/docs/pages/guides/platform/terraform/[[...slug]].tsx @@ -0,0 +1,167 @@ +import { CodeHikeConfig, remarkCodeHike } from '@code-hike/mdx' +import matter from 'gray-matter' +import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from 'next' +import { MDXRemote } from 'next-mdx-remote' +import { serialize } from 'next-mdx-remote/serialize' +import remarkGfm from 'remark-gfm' +import rehypeSlug from 'rehype-slug' + +import codeHikeTheme from 'config/code-hike.theme.json' assert { type: 'json' } + +import components from '~/components' +import { MenuId } from '~/components/Navigation/NavigationMenu/NavigationMenu' +import Layout from '~/layouts/DefaultGuideLayout' +import { isValidGuideFrontmatter } from '~/lib/docs' +import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLinkTransform' +import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' +import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' +import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' + +// We fetch these docs at build time from an external repo +export const org = 'supabase' +export const repo = 'terraform-provider-supabase' +export const branch = 'v1.1.3' +export const docsDir = 'docs' + +// Each external docs page is mapped to a local page +const pageMap = [ + { + remoteFile: 'README.md', + meta: { + title: 'Terraform Provider', + }, + useRoot: true, + }, + { + slug: 'tutorial', + remoteFile: 'tutorial.md', + meta: { + title: 'Using the Supabase Terraform Provider', + }, + }, +] + +export default function TerraformDocs({ + source, + meta, + editLink, +}: InferGetStaticPropsType) { + return ( + + + + ) +} + +/** + * The GitHub repo uses relative links, which don't lead to the right locations + * in docs. + * + * @param url The original link, as written in the Markdown file + * @returns The rewritten link + */ +const urlTransform: UrlTransformFunction = (url: string) => { + try { + const placeholderHostname = 'placeholder' + const { hostname, pathname, hash } = new URL(url, `http://${placeholderHostname}`) + + // Don't modify a url with a FQDN or a url that's only a hash + if (hostname !== placeholderHostname || pathname === '/') { + return url + } + + const getBasename = (pathname: string) => + pathname.endsWith('.md') ? pathname.replace(/\.md$/, '') : pathname + const stripLeadingPrefix = (pathname: string) => pathname.replace(/^\//, '') + const stripLeadingDocs = (pathname: string) => pathname.replace(/^docs\//, '') + + const relativePath = stripLeadingPrefix(getBasename(pathname)) + + const page = pageMap.find( + ({ remoteFile, useRoot }) => + (useRoot && `${relativePath}.md` === remoteFile) || + (!useRoot && `${stripLeadingDocs(relativePath)}.md` === remoteFile) + ) + + if (page) { + return 'terraform' + `/${page.slug}` + hash + } + + // If we don't have this page in our docs, link to GitHub repo + return `https://github.com/${org}/${repo}/blob/${branch}${pathname}${hash}` + } catch (err) { + console.error('Error transforming markdown URL', err) + return url + } +} + +/** + * Fetch markdown from external repo and transform links + */ +export const getStaticProps = (async ({ params }) => { + const [slug] = params.slug ?? [] + const page = pageMap.find((page) => page.slug === slug) + + if (!page) { + throw new Error(`No page mapping found for slug '${slug}'`) + } + + const { meta, remoteFile, useRoot } = page + + let response = await fetch( + `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${useRoot ? '' : `${docsDir}/`}${remoteFile}` + ) + + let content = await response.text() + // Strip out HTML comments + content = content.replace(//, '') + const { content: source, data } = matter(content) + Object.assign(meta, data) + + if (!isValidGuideFrontmatter(meta)) { + throw Error('Guide frontmatter is invalid.') + } + + const codeHikeOptions: CodeHikeConfig = { + theme: codeHikeTheme, + lineNumbers: true, + showCopyButton: true, + skipLanguages: [], + autoImport: false, + } + + const mdxSource = await serialize(source, { + scope: { + chCodeConfig: codeHikeOptions, + }, + mdxOptions: { + remarkPlugins: [ + remarkGfm, + remarkMkDocsAdmonition, + remarkPyMdownTabs, + [removeTitle, meta.title], + [remarkCodeHike, codeHikeOptions], + ], + rehypePlugins: [[linkTransform, urlTransform], rehypeSlug], + }, + }) + + return { + props: { + source: mdxSource, + meta, + editLink: `${org}/${repo}/blob/${branch}/${docsDir}/${slug}.md`, + }, + } +}) satisfies GetStaticProps + +export const getStaticPaths = (async () => { + return { + paths: pageMap.map(({ slug }) => ({ + params: { + slug: slug ? [slug] : [], + }, + })), + fallback: false, + } +}) satisfies GetStaticPaths diff --git a/apps/docs/pages/guides/platform/terraform/reference.tsx b/apps/docs/pages/guides/platform/terraform/reference.tsx new file mode 100644 index 00000000000..8004ab606c9 --- /dev/null +++ b/apps/docs/pages/guides/platform/terraform/reference.tsx @@ -0,0 +1,400 @@ +import { codeBlock } from 'common-tags' +import { GetStaticProps, InferGetStaticPropsType } from 'next' +import Link from 'next/link' +import ReactMarkdown from 'react-markdown' + +import { + CodeBlock, + Heading, + IconCheck, + IconPlusCircle, + PopoverContent_Shadcn_, + PopoverTrigger_Shadcn_, + Popover_Shadcn_, + Tabs, +} from 'ui' + +import { MenuId } from '~/components/Navigation/NavigationMenu/NavigationMenu' +import Layout from '~/layouts/DefaultGuideLayout' +import { org, repo, branch, docsDir } from './[[...slug]]' + +function ProviderSettings({ schema }: { schema: any }) { + const attributes = schema.block.attributes + + const example = codeBlock` + provider "supabase" { + ${Object.keys(attributes).map( + (attribute) => + `${attribute} = ${attributes[attribute].type === 'string' ? `""` : ''}` + )} + } + ` + + return ( +
+ Provider settings +

+ Use these settings to configure your Supabase provider and authenticate to your Supabase + project. +

+ Example usage + {example} + Details + {/* extra div because width restriction doesn't work on table itself */} +
+ + + + + + + + + + + + {Object.keys(schema.block.attributes).map((attribute) => ( + + + + + + + + ))} + +
AttributeDescriptionTypeOptionalSensitive
{attribute} + {attributes[attribute].description} + {attributes[attribute].type} + {attributes[attribute].optional && ( + <> + + true + + )} + + {attributes[attribute].sensitive && ( + <> + + true + + )} +
+
+
+ ) +} + +function Resources({ schema }: { schema: any }) { + return ( +
+ Resources +

You can configure these resources using the Supabase Terraform provider:

+ + {Object.keys(schema).map((resource) => ( + + Example usage + {codeBlock` + resource "${resource}" " + Details + + + + + + + + + + + + + {Object.keys(schema[resource].block.attributes).map((attribute) => ( + + + + + + + + + ))} + +
AttributeDescriptionTypeRequiredOptionalRead-only
+ {attribute} + + + {schema[resource].block.attributes[attribute].description} + + + {schema[resource].block.attributes[attribute].type ?? ( + + + + + +
    + {Object.keys( + schema[resource].block.attributes[attribute].nested_type.attributes + ).map((nestedAttribute) => ( +
  • + {nestedAttribute} +
      +
    • + + { + schema[resource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].description + } + +
    • +
    • + {schema[resource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].type ?? 'nested type'} +
    • + {schema[resource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].required &&
    • Required
    • } + {schema[resource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].optional &&
    • Optional
    • } + {schema[resource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].computed &&
    • Read-only
    • } +
    +
  • + ))} +
+
+
+ )} +
+ {schema[resource].block.attributes[attribute].required && ( + <> + + true + + )} + + {schema[resource].block.attributes[attribute].optional && ( + <> + + true + + )} + + {schema[resource].block.attributes[attribute].computed && ( + <> + + true + + )} +
+
+ ))} +
+
+ ) +} + +function DataSources({ schema }: { schema: any }) { + return ( +
+ Data sources +

You can read these resources using the Supabase Terraform provider:

+ + {Object.keys(schema).map((dataSource) => ( + + Example usage + {codeBlock` + resource "${dataSource}" "all" { + ${Object.keys(schema[dataSource].block.attributes) + .filter( + (attribute) => !schema[dataSource].block.attributes[attribute].computed + ) + .map( + (attribute) => + `${attribute} = ${ + schema[dataSource].block.attributes[attribute].type === 'string' + ? `""` + : '' + }` + )} + } + `} + Details + + + + + + + + + + + + + {Object.keys(schema[dataSource].block.attributes).map((attribute) => ( + + + + + + + + + ))} + +
AttributeDescriptionTypeRequiredOptionalRead-only
+ {attribute} + + + {schema[dataSource].block.attributes[attribute].description} + + + {schema[dataSource].block.attributes[attribute].type ?? ( + + + + + + {schema[dataSource].block.attributes[attribute].nested_type + .nesting_mode === 'set' && 'Array of:'} +
    + {Object.keys( + schema[dataSource].block.attributes[attribute].nested_type + .attributes + ).map((nestedAttribute) => ( +
  • + {nestedAttribute} +
      +
    • + + { + schema[dataSource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].description + } + +
    • +
    • + {schema[dataSource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].type ?? 'nested type'} +
    • + {schema[dataSource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].required &&
    • Required
    • } + {schema[dataSource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].optional &&
    • Optional
    • } + {schema[dataSource].block.attributes[attribute].nested_type + .attributes[nestedAttribute].computed &&
    • Read-only
    • } +
    +
  • + ))} +
+
+
+ )} +
+ {schema[dataSource].block.attributes[attribute].required && ( + <> + + true + + )} + + {schema[dataSource].block.attributes[attribute].optional && ( + <> + + true + + )} + + {schema[dataSource].block.attributes[attribute].computed && ( + <> + + true + + )} +
+
+ ))} +
+
+ ) +} + +export default function PGGraphQLDocs({ + meta, + schema, +}: InferGetStaticPropsType) { + return ( + + The Terraform Provider provices access to{' '} + + resources + {' '} + and{' '} + + data sources + + . Resources are infrastructure objects, such as a Supabase project, that you can declaratively + configure. Data sources are sources of information about your Supabase instances. + + + + + ) +} + +/** + * Fetch JSON schema from external repo + */ +export const getStaticProps = (async () => { + const meta = { + title: 'Terraform Provider reference', + subtitle: 'Resources and data sources available through the Terraform Provider', + } + + let response = await fetch( + `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${docsDir}/schema.json` + ) + if (!response.ok) throw Error('Failed to fetch Terraform JSON schema from GitHub') + + const schema = await response.json() + + return { + props: { + meta, + schema, + }, + } +}) satisfies GetStaticProps diff --git a/package-lock.json b/package-lock.json index cd59786c63e..81a1b75a996 100644 --- a/package-lock.json +++ b/package-lock.json @@ -475,6 +475,7 @@ "@supabase/supabase-js": "^2.39.3", "@tanstack/react-query": "^5.13.4", "common": "*", + "common-tags": "^1.8.2", "config": "*", "framer-motion": "^11.0.3", "github-slugger": "^2.0.0", @@ -18355,7 +18356,8 @@ }, "node_modules/common-tags": { "version": "1.8.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "engines": { "node": ">=4.0.0" } diff --git a/packages/ui/src/components/CodeBlock/CodeBlock.tsx b/packages/ui/src/components/CodeBlock/CodeBlock.tsx index f94469634e1..a78b34f1cca 100644 --- a/packages/ui/src/components/CodeBlock/CodeBlock.tsx +++ b/packages/ui/src/components/CodeBlock/CodeBlock.tsx @@ -19,7 +19,7 @@ import { useTheme } from 'next-themes' export interface CodeBlockProps { title?: string - language: 'js' | 'jsx' | 'sql' | 'py' | 'bash' | 'ts' | 'dart' | 'json' | 'csharp' | 'kotlin' + language?: 'js' | 'jsx' | 'sql' | 'py' | 'bash' | 'ts' | 'dart' | 'json' | 'csharp' | 'kotlin' linesToHighlight?: number[] hideCopy?: boolean hideLineNumbers?: boolean From 8f9b1367c1a06a951ff45f11a1d87ea0a7374fe1 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Sat, 2 Mar 2024 00:29:08 -0330 Subject: [PATCH 23/62] Chore/fix intellisense query (#21702) * Remove window check on intellisense query * Fix --------- Co-authored-by: Joshen Lim --- apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx | 2 +- .../interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx | 3 ++- apps/studio/pages/project/[ref]/sql/[id].tsx | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx index 2dde1cb9b66..b6a50b8ad43 100644 --- a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx @@ -40,7 +40,7 @@ const MonacoEditor = ({ const [intellisenseEnabled] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE, - typeof window !== 'undefined' ? false : true + true ) const snap = useSqlEditorStateSnapshot({ sync: true }) diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx index 6e65ed72fc5..af7191c8fb2 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx @@ -49,9 +49,10 @@ const UtilityActions = ({ const os = detectOS() const project = useSelectedProject() const showReadReplicasUI = project?.is_read_replicas_enabled + const [intellisenseEnabled, setIntellisenseEnabled] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE, - typeof window !== 'undefined' ? false : true + true ) return ( diff --git a/apps/studio/pages/project/[ref]/sql/[id].tsx b/apps/studio/pages/project/[ref]/sql/[id].tsx index 48af796d0b3..eeca39984aa 100644 --- a/apps/studio/pages/project/[ref]/sql/[id].tsx +++ b/apps/studio/pages/project/[ref]/sql/[id].tsx @@ -35,7 +35,7 @@ const SqlEditor: NextPageWithLayout = () => { const [intellisenseEnabled] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.SQL_EDITOR_INTELLISENSE, - typeof window !== 'undefined' ? false : true + true ) async function formatPgsql(value: string) { From acbb3a1cc63b00f967f4e21471f8b44e49247187 Mon Sep 17 00:00:00 2001 From: Tyler Date: Sun, 3 Mar 2024 12:57:15 +0900 Subject: [PATCH 24/62] chore: Update GitHub repo link on the Flutter content recommendation article (#21709) --- .../2024-02-26-content-recommendation-with-flutter.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/www/_blog/2024-02-26-content-recommendation-with-flutter.mdx b/apps/www/_blog/2024-02-26-content-recommendation-with-flutter.mdx index 6490bec48c5..23dcafeaf6a 100644 --- a/apps/www/_blog/2024-02-26-content-recommendation-with-flutter.mdx +++ b/apps/www/_blog/2024-02-26-content-recommendation-with-flutter.mdx @@ -17,7 +17,7 @@ toc_depth: 3 Recommending relevant content to the user is essential to keep the user interested in the app. Although it is a common feature that we would like to have in our apps, building it is not straightforward. This changed as vector databases and Open AI emerged. Today, we can perform semantic searches that are highly aware of the context of the content with just a single query into our vector database. In this article, we will go over how you can create a Flutter movie-viewing app that recommends another movie based on what the user is viewing. -A quick disclaimer, this article provides an overview of what you can build with a vector database, so it will not go into every detail of the implementation. You can find the full code base of the app in this article [here](https://github.com/dshukertjr/flutter-movie-recommendation) to find more details. +A quick disclaimer, this article provides an overview of what you can build with a vector database, so it will not go into every detail of the implementation. You can find the full code base of the app in this article [here](https://github.com/dshukertjr/examples/tree/main/movie-recommendation) to find more details. ## Why use a vector database for recommending content @@ -75,7 +75,7 @@ create policy "Fils are public." on public.films for select using (true); Getting movie data is relatively straightforward. TMDB API provides an easy-to-use [movies endpoint](https://developer.themoviedb.org/reference/discover-movie) for querying information about movies while providing a wide range of filters to narrow down the query results. -We need a backend to securely call the API, and for that, we will use [Supabase Edge Functions](https://supabase.com/docs/guides/functions). Steps 2 through 4 will be constructing this edge function code, and the full code sample can be found [here](https://github.com/dshukertjr/flutter-movie-recommendation/blob/main/supabase/functions/get_film_data/index.ts). +We need a backend to securely call the API, and for that, we will use [Supabase Edge Functions](https://supabase.com/docs/guides/functions). Steps 2 through 4 will be constructing this edge function code, and the full code sample can be found [here](https://github.com/dshukertjr/examples/blob/main/movie-recommendation/supabase/functions/get_film_data/index.ts). The following code will give us the top 20 most popular movies in a given year. @@ -145,7 +145,7 @@ const embedding = responseData.data[0].embedding Once we have the movie data as well as embedding data, we are left with the task of storing them. We can call the `upsert()` function on the Supabase client to easily store the data. -Again, I omitted a lot of code here for simplicity, but you can find the full edge functions code of step 2 through step 4 [here](https://github.com/dshukertjr/flutter-movie-recommendation/blob/main/supabase/functions/get_film_data/index.ts). +Again, I omitted a lot of code here for simplicity, but you can find the full edge functions code of step 2 through step 4 [here](https://github.com/dshukertjr/examples/blob/main/movie-recommendation/supabase/functions/get_film_data/index.ts). ```tsx // Code from Step 2 @@ -195,7 +195,7 @@ $$ security invoker; ### Step 6: Create the Flutter interface -Now that we have the backend ready, all we need to do is create an interface to display and query the data from. Since the main focus of this article is to demonstrate similarity search using vectors, I will not go into all the details of the Flutter implementations, but you can find the full code base [here](https://github.com/dshukertjr/flutter-movie-recommendation/tree/main/flutter). +Now that we have the backend ready, all we need to do is create an interface to display and query the data from. Since the main focus of this article is to demonstrate similarity search using vectors, I will not go into all the details of the Flutter implementations, but you can find the full code base [here](https://github.com/dshukertjr/examples/tree/main/movie-recommendation/flutter). Our app will have the following pages: @@ -392,7 +392,7 @@ In this article, we looked at how we could take a single movie, and recommend a ## Resources -- [The full code base of the app in this article](https://github.com/dshukertjr/flutter-movie-recommendation) +- [The full code base of the app in this article](https://github.com/dshukertjr/examples/tree/main/movie-recommendation) - [Matryoshka embeddings: faster OpenAI vector search using Adaptive Retrieval](https://supabase.com/blog/matryoshka-embeddings) - [Supabase pgvector guide](https://supabase.com/docs/guides/database/extensions/pgvector) - [Storing OpenAI embeddings in Postgres with pgvector](https://supabase.com/docs/guides/database/extensions/pgvector) From 528285b54d085a0d63188ce46b4c109329fac44e Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Sun, 3 Mar 2024 18:38:19 +1100 Subject: [PATCH 25/62] fix: remove wrong non-null assertion operator (#21717) * fix: remove wrong non-null assertion operator * make organizationSlug optional * also make projectRef optional while we're at it --- .../General/CustomDomainConfig/CustomDomainConfig.tsx | 4 ++-- apps/studio/components/ui/UpgradeToPro.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx index e1cb7292c7c..88c6f9aa91e 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx @@ -71,8 +71,8 @@ const CustomDomainConfig = () => { ? 'New custom domains are temporarily disabled' : 'Custom domains are a Pro plan add-on' } - projectRef={ref as string} - organizationSlug={organization!.slug} + projectRef={ref} + organizationSlug={organization?.slug} secondaryText={ customDomainsDisabledDueToQuota ? 'We are working with our upstream DNS provider before we are able to sign up new custom domains. Please check back in a few hours.' diff --git a/apps/studio/components/ui/UpgradeToPro.tsx b/apps/studio/components/ui/UpgradeToPro.tsx index ea6a05fddf4..90c4ae72a53 100644 --- a/apps/studio/components/ui/UpgradeToPro.tsx +++ b/apps/studio/components/ui/UpgradeToPro.tsx @@ -10,8 +10,8 @@ import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-que interface UpgradeToProProps { icon?: ReactNode primaryText: string - projectRef: string - organizationSlug: string + projectRef?: string + organizationSlug?: string secondaryText: string addon?: 'pitr' | 'customDomain' | 'computeInstance' buttonText?: string @@ -63,8 +63,8 @@ const UpgradeToPro = ({ {buttonText || (plan === 'free' ? 'Upgrade to Pro' : 'Enable Addon')} From 6cf3fcc20bcde6ee0ae417c8a8f582b3ae3b52b6 Mon Sep 17 00:00:00 2001 From: Pamela Chia Date: Mon, 4 Mar 2024 12:43:10 +0800 Subject: [PATCH 26/62] chore: improve disk related descriptions (#21720) --- .../content/guides/platform/compute-add-ons.mdx | 6 +++--- .../content/guides/platform/exhaust-disk-io.mdx | 16 ++++++++-------- .../Infrastructure/Infrastructure.constants.ts | 2 +- .../ResourceExhaustionWarningBanner.constants.ts | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/apps/docs/content/guides/platform/compute-add-ons.mdx b/apps/docs/content/guides/platform/compute-add-ons.mdx index 73a09b9e5c3..e1a7305746b 100644 --- a/apps/docs/content/guides/platform/compute-add-ons.mdx +++ b/apps/docs/content/guides/platform/compute-add-ons.mdx @@ -52,13 +52,13 @@ SSD Disks are attached to your servers and the disk performance depends on the c [Contact us](https://supabase.com/contact/enterprise) if you require a custom plan. -### Bursting and disk budget +### Bursting and disk IO budget -Smaller compute instances can burst up to their largest throughput and IOPS for 30 minutes in a day. Beyond that, the performance reverts to the baseline. For example, the free tier can burst up to 2,085 Mbps for 30 minutes a day and reverts to the baseline performance of 87 Mbps. Your disk budget gets replenished throughout the day. +Smaller compute instances can burst up to their largest throughput and IOPS for 30 minutes in a day. Beyond that, the performance reverts to the baseline. For example, the free tier can burst up to 2,085 Mbps for 30 minutes a day and reverts to the baseline performance of 87 Mbps. Your disk IO budget gets replenished throughout the day. If you need consistent disk performance, choose the 4XL or larger compute add-on which has the same baseline and maximum disk throughput and IOPS. -If you're unsure of how much throughput or IOPS your application requires, you can load test your project and inspect these [metrics in the Dashboard](https://supabase.com/dashboard/project/_/reports). If the `Disk IO % consumed` stat is more than 1%, it indicates that your workload has burst beyond the baseline IO throughput during the day. If this metric goes to 100%, the workload has used up all available disk budget and will revert to baseline performance. Projects that use any disk budget are good candidates for upgrading to a larger compute add-on with higher baseline throughput. +If you're unsure of how much throughput or IOPS your application requires, you can load test your project and inspect these [metrics in the Dashboard](https://supabase.com/dashboard/project/_/reports). If the `Disk IO % consumed` stat is more than 1%, it indicates that your workload has burst beyond the baseline IO throughput during the day. If this metric goes to 100%, the workload has used up all available disk IO budget and will revert to baseline performance. Projects that use any disk IO budget are good candidates for upgrading to a larger compute add-on with higher baseline throughput. ## Postgres replication slots and WAL senders diff --git a/apps/docs/content/guides/platform/exhaust-disk-io.mdx b/apps/docs/content/guides/platform/exhaust-disk-io.mdx index 4e89ad093f9..28e5e98b3d6 100644 --- a/apps/docs/content/guides/platform/exhaust-disk-io.mdx +++ b/apps/docs/content/guides/platform/exhaust-disk-io.mdx @@ -1,18 +1,18 @@ --- id: 'exhaust-disk-io' title: 'High Disk IO Consumption' -description: 'Understand Disk IO, what can deplete your Disk Budget and what you can do about it.' +description: 'Understand Disk IO, what can deplete your Disk IO Budget and what you can do about it.' --- -## Understanding disk IO and disk budget +## Understanding disk IO and disk IO budget Disk IO refers to two metrics: throughput in Megabits per Second and IOPS which are Input/Output Operations per Second. Depending on the compute add-on of your instance you will have [different baseline performances](https://supabase.com/docs/guides/platform/compute-add-ons#disk-io). -Smaller compute instances can burst and exceed their baseline performance for a short quota of time every day. This quota is represented as your Disk Budget and once your Disk Budget is consumed, your instance reverts back to its baseline performance. You can read more about this under [Bursting and Disk Budget](https://supabase.com/docs/guides/platform/compute-add-ons#bursting-and-disk-budget). +Smaller compute instances can burst and exceed their baseline performance for a short quota of time every day. This quota is represented as your Disk IO Budget and once your Disk IO Budget is consumed, your instance reverts back to its baseline performance. You can read more about this under [Bursting and Disk IO Budget](https://supabase.com/docs/guides/platform/compute-add-ons#bursting-and-disk-io-budget). -## Depleting your disk budget +## Depleting your disk IO budget -Running out of Disk Budget means that your instance is using more disk than its compute add-on can handle and essentially gets throttled. This could have a wide range of implications: +Running out of Disk IO Budget means that your instance is using more disk than its compute add-on can handle and essentially gets throttled. This could have a wide range of implications: - Response times on requests can increase noticeably - CPU usage rises noticeably due to IO wait @@ -20,15 +20,15 @@ Running out of Disk Budget means that your instance is using more disk than its - Disruption of internal Postgres processes such as [autovacuuming](https://supabase.com/docs/guides/platform/database-size#vacuum-operations) - Your instance may become unresponsive -## Monitor your disk budget +## Monitor your disk IO budget -To check your Disk Budget on the Supabase Platform, head over to [Database Health in the Reports section](https://supabase.com/dashboard/project/_/reports/database). +To check your Disk IO Budget on the Supabase Platform, head over to [Database Health in the Reports section](https://supabase.com/dashboard/project/_/reports/database). It is also possible to monitor your resources and set up alerts using Prometheus/Grafana. With Grafana you will be able to see how much of your RAM is used for caching and you can track other metrics such as your Swap usage. Read the [Metrics Guide](https://supabase.com/docs/guides/platform/metrics) to learn more. ## Common reasons for high disk IO usage -Most operations on your Supabase project require the disk in some form. Hence, there can be many reasons for high disk usage. Here are some common ones: +Most operations on your Supabase project require disk IO in some form. Hence, there can be many reasons for high disk IO usage. Here are some common ones: - **High Memory Usage:** Every Supabase project has 1GB of disk allocated for swapping. When your memory usage is high, the operating system might frequently move parts of the memory back and forth of the swap space on the disk. - **Low Cache Usage:** If your cache hit rate is low, many of your database requests might go straight to the disk. Go to the [Cache Hit Rate Guide](https://supabase.com/docs/guides/platform/performance#hit-rate) to learn more. diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/Infrastructure.constants.ts b/apps/studio/components/interfaces/Settings/Infrastructure/Infrastructure.constants.ts index db60a819379..b7bf9219147 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/Infrastructure.constants.ts +++ b/apps/studio/components/interfaces/Settings/Infrastructure/Infrastructure.constants.ts @@ -89,7 +89,7 @@ export const INFRA_ACTIVITY_METRICS: CategoryMeta[] = [ }, ], description: - 'The disk performance of your workload is determined by the Disk IO bandwidth.\nSmaller compute instances (below 4XL) can burst up to their largest throughput and IOPS for 30 minutes in a day. Beyond that, the performance reverts to the baseline. Your disk budget gets replenished throughout the day.', + 'The disk performance of your workload is determined by the Disk IO bandwidth.\nSmaller compute instances (below 4XL) can burst up to their largest throughput and IOPS for 30 minutes in a day. Beyond that, the performance reverts to the baseline. Your disk IO budget gets replenished throughout the day.', chartDescription: '', }, ], diff --git a/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.constants.ts b/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.constants.ts index a884c8821ae..aab31fa67f7 100644 --- a/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.constants.ts +++ b/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.constants.ts @@ -60,23 +60,23 @@ export const RESOURCE_WARNING_MESSAGES = { bannerContent: { warning: { title: - 'Your project is about to exhaust its disk space budget, and may become unresponsive once fully exhausted', + 'Your project is about to exhaust its available disk space, and may become unresponsive once fully exhausted', description: 'You can opt to increase your disk size up to 200GB on the database settings page.', }, critical: { - title: 'Your project has exhausted its disk space budget, and may become unresponsive', + title: 'Your project has exhausted its available disk space, and may become unresponsive', description: 'You can opt to increase your disk size up to 200GB on the database settings page.', }, }, cardContent: { warning: { - title: 'Project is exhausting disk space budget', + title: 'Project is exhausting its available disk space', description: 'It may become unresponsive if fully exhausted', }, critical: { - title: 'Project has exhausted disk space budget', + title: 'Project has exhausted its available disk space', description: 'It may become unresponsive', }, }, From 8fa042930eb9478d2c220dab5c59753c68c2bde0 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Mon, 4 Mar 2024 14:14:24 +0800 Subject: [PATCH 27/62] Update content to show project ref (#21680) * Update content to show project ref * fix * Fix * Remove stray console logs * Fix * Update --- .../Publications/PublicationsList.tsx | 1 - .../interfaces/Home/Connect/Connect.types.ts | 2 + .../Home/Connect/ConnectTabContent.tsx | 50 ++++++++++++++++++- .../Home/Connect/content/drizzle/content.tsx | 4 +- .../Home/Connect/content/prisma/content.tsx | 6 +-- .../Settings/Database/UsePoolerCheckbox.tsx | 2 +- .../layouts/ReportsLayout/ReportsMenu.tsx | 1 - .../layouts/SQLEditorLayout/QueryItem.tsx | 1 - apps/studio/pages/api/connect/index.ts | 2 - 9 files changed, 56 insertions(+), 13 deletions(-) diff --git a/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx b/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx index 4d028925c77..30144e83c58 100644 --- a/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx +++ b/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx @@ -38,7 +38,6 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) setToggleListenEventValue(null) }, }) - console.log(data) const canUpdatePublications = useCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, diff --git a/apps/studio/components/interfaces/Home/Connect/Connect.types.ts b/apps/studio/components/interfaces/Home/Connect/Connect.types.ts index 8a5ba229dda..e41c592b8f1 100644 --- a/apps/studio/components/interfaces/Home/Connect/Connect.types.ts +++ b/apps/studio/components/interfaces/Home/Connect/Connect.types.ts @@ -8,4 +8,6 @@ export interface ContentFileProps { apiUrl: string anonKey: string } + connectionStringPooler: string + connectionStringDirect: string } diff --git a/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx b/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx index c4b4c35628f..bf47d10edff 100644 --- a/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx +++ b/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx @@ -1,13 +1,54 @@ +import { useParams } from 'common' import dynamic from 'next/dynamic' -import { projectKeys } from './Connect.types' + +import { getConnectionStrings } from 'components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.utils' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' +import { useProjectSettingsQuery } from 'data/config/project-settings-query' +import { usePoolingConfigurationQuery } from 'data/database/pooling-configuration-query' +import { pluckObjectFields } from 'lib/helpers' +import { projectKeys } from './Connect.types' interface ConnectContentTabProps { projectKeys: projectKeys filePath: string + connectionStringPooler?: string + connectionStringDirect?: string } const ConnectTabContentNew = ({ projectKeys, filePath }: ConnectContentTabProps) => { + const { ref } = useParams() + const { data } = useProjectSettingsQuery({ projectRef: ref }) + const { data: poolingInfo } = usePoolingConfigurationQuery({ projectRef: ref }) + + const { project } = data ?? {} + const DB_FIELDS = ['db_host', 'db_name', 'db_port', 'db_user', 'inserted_at'] + const emptyState = { db_user: '', db_host: '', db_port: '', db_name: '' } + const connectionInfo = pluckObjectFields(project || emptyState, DB_FIELDS) + const poolingConfiguration = poolingInfo?.find((x) => x.database_type === 'PRIMARY') + + const connectionStringsPooler = + poolingConfiguration !== undefined + ? getConnectionStrings(connectionInfo, poolingConfiguration, { + projectRef: ref, + usePoolerConnection: true, + }) + : { uri: '' } + const connectionStringsDirect = + poolingConfiguration !== undefined + ? getConnectionStrings(connectionInfo, poolingConfiguration, { + projectRef: ref, + usePoolerConnection: false, + }) + : { uri: '' } + const connectionStringPooler = + filePath !== 'drizzle' + ? connectionStringsPooler.uri.replace('6543', '5432') + : connectionStringsPooler.uri + const connectionStringDirect = + filePath !== 'drizzle' + ? connectionStringsDirect.uri.replace('6543', '5432') + : connectionStringsDirect.uri + const ContentFile = dynamic( () => import(`./content/${filePath}/content`), { @@ -21,7 +62,12 @@ const ConnectTabContentNew = ({ projectKeys, filePath }: ConnectContentTabProps) return (
- +
) } diff --git a/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx index 3c4c6b210dd..c862728307e 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx @@ -8,7 +8,7 @@ import { } from 'components/interfaces/Home/Connect/ConnectTabs' import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock' -const ContentFile = ({ projectKeys }: ContentFileProps) => { +const ContentFile = ({ connectionStringPooler, connectionStringDirect }: ContentFileProps) => { return ( @@ -20,7 +20,7 @@ const ContentFile = ({ projectKeys }: ContentFileProps) => { {` -DATABASE_URL='your-database-url' +DATABASE_URL="${connectionStringPooler}" `} diff --git a/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx index 17bdbb9d23b..1295875560a 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx @@ -8,7 +8,7 @@ import { } from 'components/interfaces/Home/Connect/ConnectTabs' import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock' -const ContentFile = ({ projectKeys }: ContentFileProps) => { +const ContentFile = ({ connectionStringPooler, connectionStringDirect }: ContentFileProps) => { return ( @@ -20,10 +20,10 @@ const ContentFile = ({ projectKeys }: ContentFileProps) => { {` # Connect to Supabase via connection pooling with Supavisor. -DATABASE_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-eu-central-1.pooler.supabase.com:6543/postgres?pgbouncer=true" +DATABASE_URL="${connectionStringPooler}" # Direct connection to the database. Used for migrations. -DIRECT_URL="postgres://postgres:[password]@db.[your-supabase-project].supabase.co:5432/postgres" +DIRECT_URL="${connectionStringDirect}" `} diff --git a/apps/studio/components/interfaces/Settings/Database/UsePoolerCheckbox.tsx b/apps/studio/components/interfaces/Settings/Database/UsePoolerCheckbox.tsx index 33592a1d8ed..3249b13db58 100644 --- a/apps/studio/components/interfaces/Settings/Database/UsePoolerCheckbox.tsx +++ b/apps/studio/components/interfaces/Settings/Database/UsePoolerCheckbox.tsx @@ -99,7 +99,7 @@ export const UsePoolerCheckbox = ({ {poolingConfiguration?.pool_mode === 'transaction' && ( onSelectOption('transaction')} > diff --git a/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx b/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx index d6feb8701a5..4d84ce59141 100644 --- a/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx +++ b/apps/studio/components/layouts/ReportsLayout/ReportsMenu.tsx @@ -252,7 +252,6 @@ const ReportsMenu = () => { ))} { - console.log('debug', newVals) try { if (!selectedReport) return if (!selectedReport.id) return diff --git a/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx b/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx index b4d61ac0494..20c100e91db 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx @@ -69,7 +69,6 @@ const QueryItem = ({ const { mutate: deleteContent, isLoading: isDeleting } = useContentDeleteMutation({ onSuccess: (data) => onDeleteQuery(data), onError: (error, data) => { - console.log({ error }) if (error.message.includes('Contents not found')) { onDeleteQuery(data.ids) } else { diff --git a/apps/studio/pages/api/connect/index.ts b/apps/studio/pages/api/connect/index.ts index f20b785bcdf..1f18ba232df 100644 --- a/apps/studio/pages/api/connect/index.ts +++ b/apps/studio/pages/api/connect/index.ts @@ -32,9 +32,7 @@ function getFilePaths(folderPath: string, baseFolder = ''): string[] { export default async function getFileNames(req: NextApiRequest, res: NextApiResponse) { const folderPath = path.join(process.cwd(), 'components/interfaces/Home/Connect/content') - const filepaths = getFilePaths(folderPath) - console.log({ filepaths }) res.statusCode = 200 res.json(filepaths) } From 2901606b08de668df7b39b5146f3fcc771e46bfe Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Mon, 4 Mar 2024 14:43:41 +0800 Subject: [PATCH 28/62] feat/ add log out button, and user details into user popover (#21724) * Update NavigationBar.tsx * small nits * only show email if it's different from username * Update apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx Co-authored-by: Jonathan Summers-Muir --------- Co-authored-by: Alaister Young Co-authored-by: Alaister Young --- .../layouts/AccountLayout/AccountLayout.tsx | 2 +- .../layouts/AccountLayout/WithSidebar.tsx | 2 +- .../NavigationBar/NavigationBar.tsx | 100 ++++++++++++------ 3 files changed, 72 insertions(+), 32 deletions(-) diff --git a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx index eb8c4f24e1b..ecbef0713e5 100644 --- a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx +++ b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx @@ -130,7 +130,7 @@ const AccountLayout = ({ children, title, breadcrumbs }: PropsWithChildren } - if (label === 'Logout') { + if (label === 'Log out') { icon = } diff --git a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx index 0b5f7fd8edd..3d0da5bbfdd 100644 --- a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx +++ b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx @@ -17,7 +17,6 @@ import { DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, - DropdownMenuSub, DropdownMenuTrigger, Separator, Theme, @@ -40,6 +39,7 @@ import { } from './NavigationBar.utils' import { NavigationIconButton } from './NavigationIconButton' import NavigationIconLink from './NavigationIconLink' +import { useSignOut } from 'lib/auth' export const ICON_SIZE = 20 export const ICON_STROKE_WIDTH = 1.5 @@ -54,6 +54,8 @@ const NavigationBar = () => { const { setIsOpen } = useCommandMenu() const snap = useAppStateSnapshot() + const signOut = useSignOut() + const navLayoutV2 = useFlag('navigationLayoutV2') const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled() const [userDropdownOpen, setUserDropdownOpenState] = useState(false) @@ -229,18 +231,24 @@ const NavigationBar = () => { 'transition-all' )} > - - {profile?.username} - - - {profile?.primary_email} - + {profile && IS_PLATFORM && ( + <> + + {profile.username} + + {profile.primary_email !== profile.username && ( + + {profile.primary_email} + + )} + + )} @@ -248,27 +256,48 @@ const NavigationBar = () => { {IS_PLATFORM && ( <> - {} - - - -

Account preferences

- -
- snap.setShowFeaturePreviewModal(true)} - onSelect={() => snap.setShowFeaturePreviewModal(true)} - > - -

Feature previews

-
+
+ {profile && ( + <> + + {profile.username} + + {profile.primary_email !== profile.username && ( + + {profile.primary_email} + + )} + + )} +
+ + + + + Account preferences + + + snap.setShowFeaturePreviewModal(true)} + onSelect={() => snap.setShowFeaturePreviewModal(true)} + > + + Feature previews + + + )} - Theme + Theme { @@ -286,6 +315,17 @@ const NavigationBar = () => { ))} + + + { + await signOut() + await router.push('/sign-in') + }} + > + Log out + +
From 5c9ab30902d09e3236b42bd578b1c3bc1a21c336 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Mon, 4 Mar 2024 15:05:20 +0800 Subject: [PATCH 29/62] Close nav bar on click link (#21686) * Close nav bar on click link * Remove onClick for navigationiconbutton * If user clicked on nav icon thats within the nav bar, dont reopen until mouse left side bar once * Fix --- .../interfaces/Account/AccessTokenList.tsx | 10 ++++---- .../Account/NewAccessTokenButton.tsx | 5 ++-- .../interfaces/Account/NewTokenBanner.tsx | 7 +++--- .../AdvancedAuthSettingsForm.tsx | 22 +++++++---------- .../NavigationBar/NavigationBar.tsx | 24 ++++++++++++++++--- .../NavigationBar/NavigationIconButton.tsx | 2 +- .../NavigationBar/NavigationIconLink.tsx | 6 +++-- .../layouts/StorageLayout/StorageMenu.tsx | 12 ++++++---- apps/studio/state/app-state.ts | 24 +++++++++++++++++-- 9 files changed, 72 insertions(+), 40 deletions(-) diff --git a/apps/studio/components/interfaces/Account/AccessTokenList.tsx b/apps/studio/components/interfaces/Account/AccessTokenList.tsx index ce945277d25..190c1141c38 100644 --- a/apps/studio/components/interfaces/Account/AccessTokenList.tsx +++ b/apps/studio/components/interfaces/Account/AccessTokenList.tsx @@ -1,19 +1,17 @@ import { useAccessTokenDeleteMutation } from 'data/access-tokens/access-tokens-delete-mutation' import { AccessToken, useAccessTokensQuery } from 'data/access-tokens/access-tokens-query' -import { observer } from 'mobx-react-lite' import { useState } from 'react' +import toast from 'react-hot-toast' import { Button, IconTrash, Modal } from 'ui' import Table from 'components/to-be-cleaned/Table' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' -import { useStore } from 'hooks' -const AccessTokenList = observer(() => { - const { ui } = useStore() +const AccessTokenList = () => { const { data: tokens, isLoading } = useAccessTokensQuery() const { mutate: deleteToken } = useAccessTokenDeleteMutation({ onSuccess: () => { - ui.setNotification({ category: 'success', message: 'Successfully deleted access token' }) + toast.success('Successfully deleted access token') setIsOpen(false) }, }) @@ -96,6 +94,6 @@ const AccessTokenList = observer(() => { ) -}) +} export default AccessTokenList diff --git a/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx b/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx index 9e8291339f7..84f6f4014ee 100644 --- a/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx +++ b/apps/studio/components/interfaces/Account/NewAccessTokenButton.tsx @@ -1,4 +1,3 @@ -import { observer } from 'mobx-react-lite' import Link from 'next/link' import { useState } from 'react' import { @@ -21,7 +20,7 @@ export interface NewAccessTokenButtonProps { onCreateToken: (token: any) => void } -const NewAccessTokenButton = observer(({ onCreateToken }: NewAccessTokenButtonProps) => { +const NewAccessTokenButton = ({ onCreateToken }: NewAccessTokenButtonProps) => { const [isOpen, setIsOpen] = useState(false) const [tokenScope, setTokenScope] = useState<'V0' | undefined>(undefined) @@ -157,6 +156,6 @@ const NewAccessTokenButton = observer(({ onCreateToken }: NewAccessTokenButtonPr ) -}) +} export default NewAccessTokenButton diff --git a/apps/studio/components/interfaces/Account/NewTokenBanner.tsx b/apps/studio/components/interfaces/Account/NewTokenBanner.tsx index 242cc88f31f..a63a087ef22 100644 --- a/apps/studio/components/interfaces/Account/NewTokenBanner.tsx +++ b/apps/studio/components/interfaces/Account/NewTokenBanner.tsx @@ -1,12 +1,11 @@ -import { Alert, Input } from 'ui' -import { observer } from 'mobx-react-lite' import { NewAccessToken } from 'data/access-tokens/access-tokens-create-mutation' +import { Alert, Input } from 'ui' interface NewTokenBannerProps { token: NewAccessToken } -const NewTokenBanner = observer(({ token }: NewTokenBannerProps) => { +const NewTokenBanner = ({ token }: NewTokenBannerProps) => { return (
@@ -25,6 +24,6 @@ const NewTokenBanner = observer(({ token }: NewTokenBannerProps) => {
) -}) +} export default NewTokenBanner diff --git a/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx index 94aeab9f08a..f5018a8f60e 100644 --- a/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx @@ -1,6 +1,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { observer } from 'mobx-react-lite' +import { useParams } from 'common' import { useEffect } from 'react' +import toast from 'react-hot-toast' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -12,7 +13,6 @@ import { } from 'ui' import { boolean, number, object } from 'yup' -import { useParams } from 'common' import { FormActions, FormHeader, @@ -23,7 +23,7 @@ import { } from 'components/ui/Forms' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' -import { useCheckPermissions, useStore } from 'hooks' +import { useCheckPermissions } from 'hooks' const schema = object({ JWT_EXP: number() @@ -38,8 +38,7 @@ const schema = object({ .max(30, 'Must be a value less than 30'), }) -const AdvancedAuthSettingsForm = observer(() => { - const { ui } = useStore() +const AdvancedAuthSettingsForm = () => { const { ref: projectRef } = useParams() const { data: authConfig, @@ -68,16 +67,10 @@ const AdvancedAuthSettingsForm = observer(() => { { projectRef: projectRef!, config: payload }, { onError: (error) => { - ui.setNotification({ - category: 'error', - message: `Failed to update settings: ${error?.message}`, - }) + toast.error(`Failed to update settings: ${error?.message}`) }, onSuccess: () => { - ui.setNotification({ - category: 'success', - message: `Successfully updated settings`, - }) + toast.success('Successfully updated settings') resetForm({ values: values, initialValues: values }) }, } @@ -100,6 +93,7 @@ const AdvancedAuthSettingsForm = observer(() => { const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues) // Form is reset once remote data is loaded in store + // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { if (isSuccess) resetForm({ values: INITIAL_VALUES, initialValues: INITIAL_VALUES }) }, [isSuccess]) @@ -183,6 +177,6 @@ const AdvancedAuthSettingsForm = observer(() => { }} ) -}) +} export default AdvancedAuthSettingsForm diff --git a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx index 3d0da5bbfdd..25e86d8e14f 100644 --- a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx +++ b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.tsx @@ -6,7 +6,7 @@ import { Command, FileText, FlaskConical, Search, Settings } from 'lucide-react' import { useTheme } from 'next-themes' import Link from 'next/link' import { useRouter } from 'next/router' -import { useState } from 'react' +import { MouseEvent, useState } from 'react' import { Button, DropdownMenu, @@ -84,6 +84,13 @@ const NavigationBar = () => { const otherRoutes = generateOtherRoutes(projectRef, project) const settingsRoutes = generateSettingsRoutes(projectRef, project) + const onCloseNavigationIconLink = (event: any) => { + snap.setNavigationPanelOpen( + false, + event.target.id === 'icon-link' || ['svg', 'path'].includes(event.target.localName) + ) + } + return (
- {isErrorIntegrations && ( + {isErrorConnections && ( )} - {isSuccessIntegrations && ( + {isSuccessConnections && (
diff --git a/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx b/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx index 425e4b246ad..d60b2a11144 100644 --- a/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx +++ b/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx @@ -8,7 +8,7 @@ import { useInView } from 'react-intersection-observer' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useBranchQuery } from 'data/branches/branch-query' import { Branch } from 'data/branches/branches-query' -import { GitHubPullRequest } from 'data/integrations/integrations-github-pull-requests-query' +import { GitHubPullRequest } from 'data/integrations/github-pull-requests-query' import { Badge, Button, diff --git a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx index bf556e33b6c..e7e98033248 100644 --- a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx +++ b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx @@ -4,6 +4,15 @@ import Link from 'next/link' import { useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import toast from 'react-hot-toast' +import * as z from 'zod' + +import AlertError from 'components/ui/AlertError' +import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' +import { useBranchCreateMutation } from 'data/branches/branch-create-mutation' +import { useBranchesQuery } from 'data/branches/branches-query' +import { useCheckGithubBranchValidity } from 'data/integrations/github-branch-check-query' +import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' +import { useSelectedOrganization, useSelectedProject } from 'hooks' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -21,15 +30,6 @@ import { Input_Shadcn_, Modal, } from 'ui' -import * as z from 'zod' - -import AlertError from 'components/ui/AlertError' -import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' -import { useBranchCreateMutation } from 'data/branches/branch-create-mutation' -import { useBranchesQuery } from 'data/branches/branches-query' -import { useCheckGithubBranchValidity } from 'data/integrations/integrations-github-branch-check' -import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only' -import { useSelectedOrganization, useSelectedProject } from 'hooks' interface CreateBranchModalProps { visible: boolean @@ -51,13 +51,13 @@ const CreateBranchModal = ({ visible, onClose }: CreateBranchModalProps) => { projectDetails !== undefined ? (isBranch ? projectDetails.parent_project_ref : ref) : undefined const { - data: integrations, - error: integrationsError, - isLoading: isLoadingIntegrations, - isSuccess: isSuccessIntegrations, - isError: isErrorIntegrations, - } = useOrgIntegrationsQuery({ - orgSlug: selectedOrg?.slug, + data: connections, + error: connectionsError, + isLoading: isLoadingConnections, + isSuccess: isSuccessConnections, + isError: isErrorConnections, + } = useGitHubConnectionsQuery({ + organizationId: selectedOrg?.id, }) const { data: branches } = useBranchesQuery({ projectRef }) @@ -73,17 +73,10 @@ const CreateBranchModal = ({ visible, onClose }: CreateBranchModalProps) => { }, }) - const githubIntegration = integrations?.find( - (integration) => - integration.integration.name === 'GitHub' && - integration.connections.some( - (connection) => connection.supabase_project_ref === projectDetails?.parentRef - ) + const githubConnection = connections?.find( + (connection) => connection.project.ref === projectDetails?.parentRef ) - const githubConnection = githubIntegration?.connections?.find( - (connection) => connection.supabase_project_ref === projectDetails?.parentRef - ) - const [repoOwner, repoName] = githubConnection?.metadata.name.split('/') || [] + const [repoOwner, repoName] = githubConnection?.repository.name.split('/') ?? [] const formId = 'create-branch-form' const FormSchema = z.object({ @@ -98,10 +91,12 @@ const CreateBranchModal = ({ visible, onClose }: CreateBranchModalProps) => { if (val.length > 0) { try { + if (!githubConnection?.id) { + throw new Error('No GitHub connection found') + } + await checkGithubBranchValidity({ - organizationIntegrationId: githubIntegration?.id, - repoOwner, - repoName, + connectionId: githubConnection.id, branchName: val, }) setIsValid(true) @@ -154,20 +149,20 @@ const CreateBranchModal = ({ visible, onClose }: CreateBranchModalProps) => { confirmText="Create Preview Branch" > - {isLoadingIntegrations && } - {isErrorIntegrations && ( + {isLoadingConnections && } + {isErrorConnections && ( )} - {isSuccessIntegrations && ( + {isSuccessConnections && (

Your project is currently connected to the repository:

-

{githubConnection?.metadata.name}

+

{githubConnection?.repository.name}

integration.integration.name === 'GitHub') - .flatMap((integration) => integration.connections) + const { data: connections } = useGitHubConnectionsQuery({ organizationId: organization?.id }) + const githubConnections = connections?.map((connection) => ({ + id: String(connection.id), + added_by: { + id: String(connection.user?.id), + primary_email: connection.user?.primary_email ?? '', + username: connection.user?.username ?? '', + }, + foreign_project_id: String(connection.repository.id), + supabase_project_ref: connection.project.ref, + organization_integration_id: 'unused', + inserted_at: connection.inserted_at, + updated_at: connection.updated_at, + metadata: { + name: connection.repository.name, + } as any, + })) const vercelConnections = integrations ?.filter((integration) => integration.integration.name === 'Vercel') .flatMap((integration) => integration.connections) diff --git a/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx b/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx index 26414f1892d..14ea02bebf9 100644 --- a/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx +++ b/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx @@ -2,6 +2,9 @@ import Link from 'next/link' import { useRouter } from 'next/router' import { forwardRef, useCallback, useState } from 'react' import { + AlertDescription_Shadcn_, + AlertTitle_Shadcn_, + Alert_Shadcn_, Button, DropdownMenu, DropdownMenuContent, @@ -14,14 +17,16 @@ import { IconTrash, Modal, } from 'ui' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { IntegrationConnection, IntegrationConnectionProps, } from 'components/interfaces/Integrations/IntegrationPanels' -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' +import { WarningIcon } from 'components/ui/Icons' import { useIntegrationsVercelConnectionSyncEnvsMutation } from 'data/integrations/integrations-vercel-connection-sync-envs-mutation' import { IntegrationProjectConnection } from 'data/integrations/integrations.types' +import { useProjectsQuery } from 'data/projects/projects-query' import { useStore } from 'hooks' interface IntegrationConnectionItemProps extends IntegrationConnectionProps { @@ -32,18 +37,23 @@ interface IntegrationConnectionItemProps extends IntegrationConnectionProps { const IntegrationConnectionItem = forwardRef( ({ disabled, onDeleteConnection, ...props }, ref) => { const { ui } = useStore() + const router = useRouter() + + const { type, connection } = props + const { data: projects } = useProjectsQuery() + const project = projects?.find((project) => project.ref === connection.supabase_project_ref) + const isBranchingEnabled = project?.is_branch_enabled === true + const [isOpen, setIsOpen] = useState(false) const [dropdownVisible, setDropdownVisible] = useState(false) - const router = useRouter() - const onConfirm = useCallback(async () => { try { - await onDeleteConnection(props.connection) + await onDeleteConnection(connection) } finally { setIsOpen(false) } - }, [props.connection, onDeleteConnection]) + }, [connection, onDeleteConnection]) const onCancel = useCallback(() => { setIsOpen(false) @@ -61,14 +71,15 @@ const IntegrationConnectionItem = forwardRef { - syncEnvs({ connectionId: props.connection.id }) - }, [props.connection, syncEnvs]) + syncEnvs({ connectionId: connection.id }) + }, [connection, syncEnvs]) const projectIntegrationUrl = `/project/[ref]/settings/integrations` return ( <> } type="default"> @@ -86,37 +97,37 @@ const IntegrationConnectionItem = forwardRef - {props.type === 'Vercel' && ( - <> - {router.pathname !== projectIntegrationUrl && ( - - - View project configuration - - - )} - { - event.preventDefault() - onReSyncEnvVars() - }} - disabled={isSyncEnvLoading} - > - {isSyncEnvLoading ? ( - - ) : ( - + {router.pathname !== projectIntegrationUrl && ( + + Resync environment variables

-
- - + > + Configure connection + +
+ )} + {type === 'Vercel' && ( + { + event.preventDefault() + onReSyncEnvVars() + }} + disabled={isSyncEnvLoading} + > + {isSyncEnvLoading ? ( + + ) : ( + + )} +

Resync environment variables

+
+ )} + {(type === 'Vercel' || router.pathname !== projectIntegrationUrl) && ( + )} setIsOpen(true)}> @@ -130,16 +141,27 @@ const IntegrationConnectionItem = forwardRef - -

- {`This action cannot be undone. Are you sure you want to delete this connection?`} + + {type === 'GitHub' && isBranchingEnabled && ( + + + Branching will be disabled for this project + + Deleting this GitHub connection will remove all preview branches on this project, + and also disable branching for {project.name} + + + )} +

+ This action cannot be undone. Are you sure you want to delete this {type} connection?

diff --git a/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx b/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx index c1b6f6c3cdb..58caf455aaa 100644 --- a/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx +++ b/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx @@ -154,7 +154,7 @@ const IntegrationConnection = React.forwardRef {showNode && (
@@ -164,14 +164,16 @@ const IntegrationConnection = React.forwardRef
- {project?.name} + + {project?.name} + {!connection?.metadata?.framework ? (
@@ -185,7 +187,21 @@ const IntegrationConnection = React.forwardRef )} - {connection.metadata?.name} + {type === 'GitHub' ? ( + + {connection.metadata?.name} + + ) : ( + + {connection.metadata?.name} + + )}
diff --git a/apps/studio/components/interfaces/Integrations/ProjectLinker.tsx b/apps/studio/components/interfaces/Integrations/ProjectLinker.tsx index 0311a881d67..e1245df1607 100644 --- a/apps/studio/components/interfaces/Integrations/ProjectLinker.tsx +++ b/apps/studio/components/interfaces/Integrations/ProjectLinker.tsx @@ -1,3 +1,4 @@ +import { PlusIcon } from 'lucide-react' import { ReactNode, useEffect, useRef, useState } from 'react' import { toast } from 'react-hot-toast' import { @@ -7,6 +8,7 @@ import { CommandInput_Shadcn_, CommandItem_Shadcn_, CommandList_Shadcn_, + CommandSeparator_Shadcn_, Command_Shadcn_, IconChevronDown, PopoverContent_Shadcn_, @@ -14,6 +16,7 @@ import { Popover_Shadcn_, cn, } from 'ui' +import { useRouter } from 'next/router' import ShimmerLine from 'components/ui/ShimmerLine' import { @@ -22,6 +25,7 @@ import { } from 'data/integrations/integrations.types' import { useSelectedOrganization } from 'hooks' import { BASE_PATH } from 'lib/constants' +import { openInstallGitHubIntegrationWindow } from 'lib/github' export interface Project { id: string @@ -32,14 +36,15 @@ export interface Project { export interface ForeignProject { id: string name: string + installation_id?: number } export interface ProjectLinkerProps { - organizationIntegrationId: string | undefined + organizationIntegrationId?: string foreignProjects: ForeignProject[] supabaseProjects: Project[] onCreateConnections: (variables: IntegrationConnectionsCreateVariables) => void - installedConnections: IntegrationProjectConnection[] | undefined + installedConnections?: IntegrationProjectConnection[] isLoading?: boolean integrationIcon: ReactNode getForeignProjectIcon?: (project: ForeignProject) => ReactNode @@ -47,6 +52,7 @@ export interface ProjectLinkerProps { onSkip?: () => void loadingForeignProjects?: boolean loadingSupabaseProjects?: boolean + showNoEntitiesState?: boolean defaultSupabaseProjectRef?: string defaultForeignProjectId?: string @@ -65,10 +71,12 @@ const ProjectLinker = ({ onSkip, loadingForeignProjects, loadingSupabaseProjects, + showNoEntitiesState = true, defaultSupabaseProjectRef, defaultForeignProjectId, }: ProjectLinkerProps) => { + const router = useRouter() const [supabaseProjectsComboBoxOpen, setSupabaseProjectsComboboxOpen] = useState(false) const [foreignProjectsComboBoxOpen, setForeignProjectsComboboxOpen] = useState(false) const supabaseProjectsComboBoxRef = useRef(null) @@ -106,7 +114,6 @@ const ProjectLinker = ({ function onCreateConnections() { const projectDetails = selectedForeignProject - if (!organizationIntegrationId) return console.error('No integration ID set') if (!selectedForeignProject?.id) return console.error('No Foreign project ID set') if (!selectedSupabaseProject?.ref) return console.error('No Supabase project ref set') @@ -118,7 +125,7 @@ const ProjectLinker = ({ } _onCreateConnections({ - organizationIntegrationId, + organizationIntegrationId: organizationIntegrationId!, connection: { foreign_project_id: selectedForeignProject?.id, supabase_project_ref: selectedSupabaseProject?.ref, @@ -128,6 +135,11 @@ const ProjectLinker = ({ }, }, orgSlug: selectedOrganization?.slug, + new: { + installation_id: selectedForeignProject.installation_id!, + project_ref: selectedSupabaseProject.ref, + repository_id: Number(selectedForeignProject.id), + }, }) } @@ -160,10 +172,10 @@ const ProjectLinker = ({ {loadingForeignProjects || loadingSupabaseProjects ? (
-

Loading projects

+

Loading projects

- ) : noSupabaseProjects || noForeignProjects ? ( + ) : showNoEntitiesState && (noSupabaseProjects || noForeignProjects) ? (
No {missingEntity} Projects found

@@ -174,7 +186,7 @@ const ProjectLinker = ({

) : ( -
+
Supabase @@ -188,7 +200,6 @@ const ProjectLinker = ({ +
+ ) : ( + + )}
diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx index 80a0858d954..7e3fe15e480 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx @@ -2,12 +2,12 @@ import { zodResolver } from '@hookform/resolvers/zod' import { GitBranch, RotateCcw, Shield } from 'lucide-react' import { useRef, useState } from 'react' import { useForm } from 'react-hook-form' +import toast from 'react-hot-toast' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, - cn, CommandEmpty_Shadcn_, CommandGroup_Shadcn_, CommandInput_Shadcn_, @@ -27,46 +27,45 @@ import { PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_, + Switch, + cn, } from 'ui' import * as z from 'zod' import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' import { useBranchesQuery } from 'data/branches/branches-query' -import { useGithubConnectionUpdateMutation } from 'data/integrations/github-connection-update-mutate' -import { useGithubBranchesQuery } from 'data/integrations/integrations-github-branches-query' -import { Integration, IntegrationProjectConnection } from 'data/integrations/integrations.types' -import { useSelectedProject, useStore } from 'hooks' +import { useGitHubBranchesQuery } from 'data/integrations/github-branches-query' +import { useGitHubConnectionUpdateMutation } from 'data/integrations/github-connection-update-mutation' +import { IntegrationProjectConnection } from 'data/integrations/integrations.types' +import { useSelectedOrganization, useSelectedProject } from 'hooks' -const GitHubIntegrationConnectionForm = ({ - connection, - integration, -}: { +interface GitHubIntegrationConnectionFormProps { connection: IntegrationProjectConnection - integration: Integration -}) => { - const { ui } = useStore() +} + +const GitHubIntegrationConnectionForm = ({ connection }: GitHubIntegrationConnectionFormProps) => { + const org = useSelectedOrganization() const project = useSelectedProject() const [open, setOpen] = useState(false) const comboBoxRef = useRef(null) + const isBranchingEnabled = + project?.is_branch_enabled === true || project?.parent_project_ref !== undefined - const githubProjectIntegration = integration?.connections.find( - (connection) => connection.supabase_project_ref === project?.parentRef + const { data: githubBranches, isLoading: isLoadingBranches } = useGitHubBranchesQuery( + { + connectionId: Number(connection.id), + }, + { enabled: isBranchingEnabled } ) - const [repoOwner, repoName] = githubProjectIntegration?.metadata.name.split('/') ?? [] - - const { data: githubBranches, isLoading: isLoadingBranches } = useGithubBranchesQuery({ - organizationIntegrationId: integration?.id, - repoOwner, - repoName, - }) + const { mutate: updateConnection, isLoading: isUpdatingConnection } = + useGitHubConnectionUpdateMutation({ + onSuccess: () => toast.success('Successfully updated connection settings'), + }) const { mutate: updateBranch, isLoading: isUpdatingProdBranch } = useBranchUpdateMutation({ onSuccess: (data) => { - ui.setNotification({ - category: 'success', - message: `Changed Production Branch to ${data.git_branch}`, - }) + toast.success(`Successfully updated production branch to ${data.git_branch}`) setOpen(false) }, }) @@ -93,156 +92,129 @@ const GitHubIntegrationConnectionForm = ({ supabaseDirectory: z .string() .default(connection.metadata?.supabaseConfig?.supabaseDirectory ?? ''), + supabaseChangesOnly: z + .boolean() + .default(connection.metadata?.supabaseConfig?.supabaseChangesOnly ?? false), }) const form = useForm>({ resolver: zodResolver(FormSchema), defaultValues: { supabaseDirectory: connection?.metadata?.supabaseConfig?.supabaseDirectory, + supabaseChangesOnly: connection?.metadata?.supabaseConfig?.supabaseChangesOnly, }, }) - const { mutate: updateGithubConnection, isLoading: isUpdatingGithubConnection } = - useGithubConnectionUpdateMutation({ - onSuccess: () => { - ui.setNotification({ category: 'success', message: `Updated Supabase directory` }) - setOpen(false) - }, - }) - function onSubmit(data: z.infer) { - const metadata = { - ...connection.metadata, - supabaseConfig: { - ...connection.metadata?.supabaseConfig, - supabaseDirectory: data.supabaseDirectory, - }, - } - - updateGithubConnection({ - id: connection.id, - metadata, - organizationIntegrationId: integration.id, + if (org?.id === undefined) return console.error('Org ID is required') + updateConnection({ + connectionId: connection.id, + organizationId: org?.id, + workdir: data.supabaseDirectory, + supabaseChangesOnly: data.supabaseChangesOnly, }) } return ( -
-
- Production branch -

- All other branches will be treated as Preview branches -

+
+ {isBranchingEnabled && ( +
+ Production branch +

+ All other branches will be treated as Preview branches +

- - - Changing Git branch for Production Branch coming soon - - - If you wish to change the Git branch that is used for the Production Branch you will - need to disable Branching and opt back in. - - + {/*
! This should only work if branching is turned on !
*/} - {/*
! This should only work if branching is turned on !
*/} - - - + + - {productionPreviewBranch?.git_branch || 'Select a branch'} - - - - - - - No branches found - - {githubBranches?.map((branch) => { - const active = branch.name === productionPreviewBranch?.git_branch - return ( - { - setOpen(false) - onUpdateProductionBranch(branch.name) - }} - > -
- {active ? ( - - ) : ( - - )} - {branch.name} -
- {branch.name === productionPreviewBranch?.git_branch && } -
- ) - })} -
-
-
-
-
-
+ + + + No branches found + + {githubBranches?.map((branch) => { + const active = branch.name === productionPreviewBranch?.git_branch + return ( + { + setOpen(false) + onUpdateProductionBranch(branch.name) + }} + > +
+ {active ? ( + + ) : ( + + )} + {branch.name} +
+ {branch.name === productionPreviewBranch?.git_branch && } +
+ ) + })} +
+
+
+ + +
+ )} -
- Supabase directory - - Migration and seed SQL files will be run from this directory. - - - - - Changing Supabase directory is currently not supported - - - You will need to disable Branching and opt back into Branching to change the - Production Branch. your Git repository. - - - + ( - - + + Supabase directory + + Path in your repository where supabase directory for this connection + lives. + +
{ - if (event.key === 'Escape') { - form.reset() - } + if (event.key === 'Escape') form.reset() }} /> form.reset()} /> +
- +
+ )} + /> + + ( + + + { + field.onChange(e) + form.handleSubmit(onSubmit)() + }} + /> + +
+ Supabase changes only + + Trigger branch creation only when there were changes to supabase{' '} + directory. + +
)} /> diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx index 515d7823970..a9645e1005b 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx @@ -1,11 +1,8 @@ -import { useParams } from 'common' import { useCallback } from 'react' +import { useParams } from 'common' import { IntegrationConnectionItem } from 'components/interfaces/Integrations/IntegrationConnection' -import { - IntegrationConnectionHeader, - IntegrationInstallation, -} from 'components/interfaces/Integrations/IntegrationPanels' +import { EmptyIntegrationConnection } from 'components/interfaces/Integrations/IntegrationPanels' import { Markdown } from 'components/interfaces/Markdown' import { ScaffoldContainer, @@ -13,13 +10,17 @@ import { ScaffoldSectionContent, ScaffoldSectionDetail, } from 'components/layouts/Scaffold' -import { useIntegrationsGitHubInstalledConnectionDeleteMutation } from 'data/integrations/integrations-github-connection-delete-mutation' -import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only' +import { useBranchesDisableMutation } from 'data/branches/branches-disable-mutation' +import { useGitHubConnectionDeleteMutation } from 'data/integrations/github-connection-delete-mutation' +import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' import { IntegrationName, IntegrationProjectConnection } from 'data/integrations/integrations.types' import { useSelectedOrganization, useSelectedProject, useStore } from 'hooks' -import { pluralize } from 'lib/helpers' +import { OPT_IN_TAGS } from 'lib/constants' +import { useSidePanelsStateSnapshot } from 'state/side-panels' +import { cn } from 'ui' import { IntegrationImageHandler } from '../IntegrationsSettings' import GitHubIntegrationConnectionForm from './GitHubIntegrationConnectionForm' +import { useBranchesQuery } from 'data/branches/branches-query' const GitHubTitle = `GitHub Connections` @@ -33,43 +34,63 @@ const GitHubContentSectionTop = ` You will be able to connect a GitHub repository to a Supabase project. The GitHub app will watch for changes in your repository such as file changes, branch changes as well as pull request activity. - -These connections will be part of a GitHub workflow that is currently in development. ` const GitHubSection = () => { const { ui } = useStore() + const { ref: projectRef } = useParams() const project = useSelectedProject() const org = useSelectedOrganization() - const { data } = useOrgIntegrationsQuery({ orgSlug: org?.slug }) - const { ref: projectRef } = useParams() + const sidePanelsStateSnapshot = useSidePanelsStateSnapshot() + const { data: allConnections } = useGitHubConnectionsQuery({ organizationId: org?.id }) + const { data: branches } = useBranchesQuery({ projectRef }) + + const { mutate: deleteGitHubConnection } = useGitHubConnectionDeleteMutation({ + onSuccess: () => { + ui.setNotification({ + category: 'success', + message: 'Successfully deleted Github connection', + }) + }, + }) + + const { mutate: disableBranching } = useBranchesDisableMutation() + + const previewBranches = (branches ?? []).filter((branch) => !branch.is_default) + const hasAccessToBranching = org?.opt_in_tags?.includes(OPT_IN_TAGS.PREVIEW_BRANCHES) ?? false const isBranch = project?.parent_project_ref !== undefined + const isBranchingEnabled = + project?.is_branch_enabled === true || project?.parent_project_ref !== undefined - const githubIntegrations = data?.filter( - (integration) => integration.integration.name === 'GitHub' - ) + const connections = + allConnections?.filter((connection) => + isBranch + ? connection.project.ref === project.parent_project_ref + : connection.project.ref === projectRef + ) ?? [] - const { mutate: deleteGitHubConnection } = useIntegrationsGitHubInstalledConnectionDeleteMutation( - { - onSuccess: () => { - ui.setNotification({ - category: 'success', - message: 'Successfully deleted Github connection', - }) - }, - } - ) + const onAddGitHubConnection = useCallback(() => { + sidePanelsStateSnapshot.setGithubConnectionsOpen(true) + }, [sidePanelsStateSnapshot]) const onDeleteGitHubConnection = useCallback( async (connection: IntegrationProjectConnection) => { - deleteGitHubConnection({ - connectionId: connection.id, - integrationId: connection.organization_integration_id, - orgSlug: org?.slug, - }) + if (isBranchingEnabled) { + if (!projectRef) throw new Error('Project ref not found') + disableBranching({ projectRef, branchIds: previewBranches?.map((branch) => branch.id) }) + } + if (!org?.id) throw new Error('Organization not found') + deleteGitHubConnection({ connectionId: connection.id, organizationId: org.id }) }, - [deleteGitHubConnection, org?.slug] + [ + deleteGitHubConnection, + disableBranching, + isBranchingEnabled, + org?.id, + previewBranches, + projectRef, + ] ) return ( @@ -81,62 +102,85 @@ const GitHubSection = () => { - {githubIntegrations && - githubIntegrations.length > 0 && - githubIntegrations.map((integration, i) => { - const connections = integration.connections.filter((connection) => - isBranch - ? connection.supabase_project_ref === project.parent_project_ref - : connection.supabase_project_ref === projectRef - ) - return ( -
- 0 ? ( +
    + {connections.map((connection) => ( +
    + - {connections.length > 0 ? ( - <> - -
      - {connections.map((connection) => ( -
      - -
      - -
      -
      - ))} -
    - - ) : ( - + - )} +
- ) - })} + ))} + + ) : hasAccessToBranching ? ( + + Add new project connection + + ) : ( +

+ Access to{' '} + + branching + {' '} + is required to add GitHub connections. +

+ )}
diff --git a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx index 1267c61569b..b7a64cda1f6 100644 --- a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx +++ b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/EnableBranchingModal.tsx @@ -1,6 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useParams } from 'common' import { last } from 'lodash' +import Link from 'next/link' import { useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import { @@ -19,17 +20,17 @@ import AlertError from 'components/ui/AlertError' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useBranchCreateMutation } from 'data/branches/branch-create-mutation' import { useProjectUpgradeEligibilityQuery } from 'data/config/project-upgrade-eligibility-query' -import { useCheckGithubBranchValidity } from 'data/integrations/integrations-github-branch-check' -import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only' +import { useCheckGithubBranchValidity } from 'data/integrations/github-branch-check-query' +import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' +import { useGitHubRepositoriesQuery } from 'data/integrations/github-repositories-query' +import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useSelectedOrganization, useStore } from 'hooks' import { useAppStateSnapshot } from 'state/app-state' import BranchingPITRNotice from './BranchingPITRNotice' +import BranchingPlanNotice from './BranchingPlanNotice' import BranchingPostgresVersionNotice from './BranchingPostgresVersionNotice' import GithubRepositorySelection from './GithubRepositorySelection' -import Link from 'next/link' -import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import BranchingPlanNotice from './BranchingPlanNotice' const EnableBranchingModal = () => { const { ui } = useStore() @@ -43,14 +44,20 @@ const EnableBranchingModal = () => { const [isValid, setIsValid] = useState(false) const { - data: integrations, - error: integrationsError, - isLoading: isLoadingIntegrations, - isSuccess: isSuccessIntegrations, - isError: isErrorIntegrations, - } = useOrgIntegrationsQuery({ - orgSlug: selectedOrg?.slug, - }) + data: repositories, + error: repositoriesError, + isLoading: isLoadingRepositories, + isSuccess: isSuccessRepositories, + isError: isErrorRepositories, + } = useGitHubRepositoriesQuery() + + const { + data: connections, + error: connectionsError, + isLoading: isLoadingConnections, + isSuccess: isSuccessConnections, + isError: isErrorConnections, + } = useGitHubConnectionsQuery({ organizationId: selectedOrg?.id }) const { data, @@ -71,17 +78,8 @@ const EnableBranchingModal = () => { const hasPitrEnabled = (addons?.selected_addons ?? []).find((addon) => addon.type === 'pitr') !== undefined - const hasGithubIntegrationInstalled = - integrations?.some((integration) => integration.integration.name === 'GitHub') ?? false - const githubIntegration = integrations?.find( - (integration) => - integration.integration.name === 'GitHub' && - integration.organization.slug === selectedOrg?.slug - ) - const githubConnection = githubIntegration?.connections.find( - (connection) => connection.supabase_project_ref === ref - ) - const [repoOwner, repoName] = githubConnection?.metadata.name.split('/') ?? [] + const githubConnection = connections?.find((connection) => connection.project.ref === ref) + const [repoOwner, repoName] = githubConnection?.repository.name.split('/') ?? [] const { mutateAsync: checkGithubBranchValidity, isLoading: isChecking } = useCheckGithubBranchValidity({ onError: () => {} }) @@ -101,10 +99,12 @@ const EnableBranchingModal = () => { .refine(async (val) => { try { if (val.length > 0) { + if (!githubConnection?.id) { + throw new Error('No GitHub connection found') + } + await checkGithubBranchValidity({ - organizationIntegrationId: githubIntegration?.id, - repoOwner, - repoName, + connectionId: githubConnection.id, branchName: val, }) setIsValid(true) @@ -123,9 +123,9 @@ const EnableBranchingModal = () => { defaultValues: { branchName: '' }, }) - const isLoading = isLoadingIntegrations || isLoadingUpgradeEligibility - const isError = isErrorIntegrations || isErrorUpgradeEligibility - const isSuccess = isSuccessIntegrations && isSuccessUpgradeEligibility + const isLoading = isLoadingRepositories + const isError = isErrorRepositories || isErrorUpgradeEligibility + const isSuccess = isSuccessRepositories && isSuccessUpgradeEligibility const canSubmit = form.getValues('branchName').length > 0 && !isChecking && isValid const onSubmit = (data: z.infer) => { @@ -183,15 +183,14 @@ const EnableBranchingModal = () => { )} - {isError && ( <> - {isErrorIntegrations ? ( + {isErrorRepositories ? ( ) : isErrorUpgradeEligibility ? ( { )} - {isSuccess && ( <> {isFreePlan ? ( @@ -216,8 +214,7 @@ const EnableBranchingModal = () => { form={form} isChecking={isChecking} isValid={canSubmit} - integration={githubIntegration} - hasGithubIntegrationInstalled={hasGithubIntegrationInstalled} + githubConnection={githubConnection} /> {!hasPitrEnabled && } @@ -262,11 +259,10 @@ const EnableBranchingModal = () => {
+ )} - -
- )} - {hasGithubIntegrationInstalled && !githubConnection && ( - onSelectConnectRepo()} - orgSlug={org?.slug} - /> - )} - {integration && githubConnection && ( + + {githubConnection ? ( <>
    onSelectConnectRepo()}> Configure connection } - orientation="vertical" + orientation="horizontal" />
@@ -129,6 +110,12 @@ const GithubRepositorySelection = ({ )} /> + ) : ( + onSelectConnectRepo()} + orgSlug={org?.slug} + /> )}
diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index 8763801d2ef..ed2373894bc 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -10,7 +10,7 @@ import ProjectDropdown from 'components/layouts/AppLayout/ProjectDropdown' import { getResourcesExceededLimitsOrg } from 'components/ui/OveragesBanner/OveragesBanner.utils' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useOrgUsageQuery } from 'data/usage/org-usage-query' -import { useFlag, useSelectedOrganization, useSelectedProject } from 'hooks' +import { useSelectedOrganization, useSelectedProject } from 'hooks' import { IS_PLATFORM } from 'lib/constants' import BreadcrumbsView from './BreadcrumbsView' import FeedbackDropdown from './FeedbackDropdown' @@ -21,9 +21,7 @@ const LayoutHeader = ({ customHeaderComponents, breadcrumbs = [], headerBorder = const { ref: projectRef } = useParams() const selectedProject = useSelectedProject() const selectedOrganization = useSelectedOrganization() - - const isBranchingEnabled = - selectedProject?.is_branch_enabled === true || selectedProject?.parent_project_ref !== undefined + const isBranchingEnabled = selectedProject?.is_branch_enabled === true const { data: orgUsage } = useOrgUsageQuery({ orgSlug: selectedOrganization?.slug }) diff --git a/apps/studio/data/api.d.ts b/apps/studio/data/api.d.ts index e37a869108f..ddf7a7b6100 100644 --- a/apps/studio/data/api.d.ts +++ b/apps/studio/data/api.d.ts @@ -796,15 +796,15 @@ export interface paths { /** Updates a Vercel connection for a supabase project */ patch: operations['VercelConnectionsController_updateVercelConnection'] } - '/platform/integrations/github': { - /** Create github integration */ - post: operations['GitHubIntegrationController_createGitHubIntegration'] - } - '/platform/integrations/github/connections/{organization_integration_id}': { - /** Gets installed github project connections for the given organization integration */ - get: operations['GitHubConnectionsController_getGitHubConnections'] + '/platform/integrations/github/authorization': { + /** Get GitHub authorization */ + get: operations['GitHubAuthorizationsController_getGitHubAuthorization'] + /** Create GitHub authorization */ + post: operations['GitHubAuthorizationsController_createGitHubAuthorization'] } '/platform/integrations/github/connections': { + /** List organization GitHub connections */ + get: operations['GitHubConnectionsController_listOrganizationGitHubConnections'] /** Connects a GitHub project to a supabase project */ post: operations['GitHubConnectionsController_createGitHubConnection'] } @@ -814,25 +814,25 @@ export interface paths { /** Updates a GitHub connection for a supabase project */ patch: operations['GitHubConnectionsController_updateGitHubConnection'] } - '/platform/integrations/github/repos/{organization_integration_id}': { - /** Gets github repos for the given organization */ - get: operations['GitHubRepoController_getRepos'] + '/platform/integrations/github/branches/{connectionId}': { + /** List GitHub connection branches */ + get: operations['GitHubBranchesController_listConnectionBranches'] } - '/platform/integrations/github/branches/{organization_integration_id}/{repo_owner}/{repo_name}': { - /** Gets github branches for a given repo */ - get: operations['GitHubBranchController_getBranches'] + '/platform/integrations/github/branches/{connectionId}/{branchName}': { + /** Get GitHub connection branch */ + get: operations['GitHubBranchesController_getConnectionBranch'] } - '/platform/integrations/github/branches/{organization_integration_id}/{repo_owner}/{repo_name}/{branch_name}': { - /** Gets a specific github branch for a given repo */ - get: operations['GitHubBranchController_getBranchByName'] + '/platform/integrations/github/pull-requests/{connectionId}': { + /** List GitHub connection pull requests */ + get: operations['GitHubPullRequestsController_getConnectionPullRequests'] } - '/platform/integrations/github/pull-requests/{organization_integration_id}/{repo_owner}/{repo_name}': { - /** Gets github pull requests for a given repo */ - get: operations['GitHubPullRequestController_getPullRequestsByNumber'] + '/platform/integrations/github/pull-requests/{connectionId}/{branchName}': { + /** List GitHub pull requests for a specific branch */ + get: operations['GitHubPullRequestsController_validateConnectionBranch'] } - '/platform/integrations/github/pull-requests/{organization_integration_id}/{repo_owner}/{repo_name}/{target}': { - /** Gets github pull requests for a given repo */ - get: operations['GitHubPullRequestController_getPullRequests'] + '/platform/integrations/github/repositories': { + /** Gets GitHub repositories for user */ + get: operations['GitHubRepositoriesController_listRepositories'] } '/platform/cli/login': { /** Create CLI login session */ @@ -4278,58 +4278,45 @@ export interface components { DeleteVercelConnectionResponse: { id: string } - CreateGitHubIntegrationBody: { - installation_id: number - organization_slug: string - metadata: Record + CreateGitHubAuthorizationBody: { + code: string } - CreateGitHubIntegrationResponse: { - id: string - } - GetGitHubConnections: { - id: string - inserted_at: string - updated_at: string - organization_integration_id: string - supabase_project_ref: string - foreign_project_id: string - metadata: Record - } - IntegrationConnectionGithub: { - foreign_project_id: string - supabase_project_ref: string - integration_id: string - metadata: Record - } - CreateGitHubConnectionsBody: { - organization_integration_id: string - connection: components['schemas']['IntegrationConnectionGithub'] - } - UpdateGitHubConnectionsBody: { - metadata: Record - } - GetGithubRepo: { + ListGitHubConnectionsProject: { id: number - full_name: string - } - GetGithubBranch: { + ref: string name: string } - GitRef: { - repo: string - branch: string - label?: string - } - GetGithubPullRequest: { + ListGitHubConnectionsRepository: { id: number - url: string - title: string - target: components['schemas']['GitRef'] - created_at: string - created_by?: string - repo: string - branch: string - label?: string + name: string + } + ListGitHubConnectionsUser: { + id: number + username: string + primary_email: string | null + } + ListGitHubConnectionsConnection: { + id: number + inserted_at: string + updated_at: string + installation_id: number + project: components['schemas']['ListGitHubConnectionsProject'] + repository: components['schemas']['ListGitHubConnectionsRepository'] + user: components['schemas']['ListGitHubConnectionsUser'] | null + workdir: string + supabase_changes_only: boolean + } + ListGitHubConnectionsResponse: { + connections: components['schemas']['ListGitHubConnectionsConnection'][] + } + CreateGitHubConnectionsBody: { + project_ref: string + installation_id: number + repository_id: number + } + UpdateGitHubConnectionsBody: { + workdir?: string + supabase_changes_only?: boolean } CreateCliLoginSessionBody: { session_id: string @@ -4587,6 +4574,7 @@ export interface components { | 'sa-east-1' /** @deprecated */ kps_enabled?: boolean + desired_instance_size?: components['schemas']['DesiredInstanceSize'] } ApiKeyResponse: { name: string @@ -10866,39 +10854,48 @@ export interface operations { } } } - /** Create github integration */ - GitHubIntegrationController_createGitHubIntegration: { - requestBody: { - content: { - 'application/json': components['schemas']['CreateGitHubIntegrationBody'] - } - } + /** Get GitHub authorization */ + GitHubAuthorizationsController_getGitHubAuthorization: { responses: { - 201: { - content: { - 'application/json': components['schemas']['CreateGitHubIntegrationResponse'] - } - } - /** @description Failed to create github integration */ + /** @description Failed to get GitHub authorization */ 500: { content: never } } } - /** Gets installed github project connections for the given organization integration */ - GitHubConnectionsController_getGitHubConnections: { + /** Create GitHub authorization */ + GitHubAuthorizationsController_createGitHubAuthorization: { + requestBody: { + content: { + 'application/json': components['schemas']['CreateGitHubAuthorizationBody'] + } + } + responses: { + 201: { + content: { + 'application/json': Record + } + } + /** @description Failed to create GitHub authorization */ + 500: { + content: never + } + } + } + /** List organization GitHub connections */ + GitHubConnectionsController_listOrganizationGitHubConnections: { parameters: { - path: { - organization_integration_id: string + query: { + organization_id: number } } responses: { 200: { content: { - 'application/json': components['schemas']['GetGitHubConnections'][] + 'application/json': components['schemas']['ListGitHubConnectionsResponse'] } } - /** @description Failed to get installed github connections for the given organization integration */ + /** @description Failed to list organization GitHub connections */ 500: { content: never } @@ -10929,7 +10926,7 @@ export interface operations { } } responses: { - 200: { + 204: { content: never } /** @description Failed to delete github integration project connection */ @@ -10951,7 +10948,7 @@ export interface operations { } } responses: { - 200: { + 204: { content: never } /** @description Failed to update GitHub connection */ @@ -10960,121 +10957,102 @@ export interface operations { } } } - /** Gets github repos for the given organization */ - GitHubRepoController_getRepos: { + /** List GitHub connection branches */ + GitHubBranchesController_listConnectionBranches: { parameters: { query?: { per_page?: number page?: number } path: { - organization_integration_id: string + connectionId: number } } responses: { 200: { content: { - 'application/json': components['schemas']['GetGithubRepo'][] + 'application/json': Record[] } } - /** @description Failed to get github repos for the given organization */ + /** @description Failed to list GitHub connection branches */ 500: { content: never } } } - /** Gets github branches for a given repo */ - GitHubBranchController_getBranches: { - parameters: { - query?: { - per_page?: number - page?: number - } - path: { - organization_integration_id: string - repo_owner: string - repo_name: string - } - } - responses: { - 200: { - content: { - 'application/json': components['schemas']['GetGithubBranch'][] - } - } - /** @description Failed to get github branches for a given repo */ - 500: { - content: never - } - } - } - /** Gets a specific github branch for a given repo */ - GitHubBranchController_getBranchByName: { + /** Get GitHub connection branch */ + GitHubBranchesController_getConnectionBranch: { parameters: { path: { - organization_integration_id: string - repo_owner: string - repo_name: string - branch_name: string + connectionId: number + branchName: string } } responses: { 200: { content: { - 'application/json': components['schemas']['GetGithubBranch'] + 'application/json': Record } } - /** @description Failed to get github branch for a given repo */ + /** @description Failed to get GitHub connection branch */ 500: { content: never } } } - /** Gets github pull requests for a given repo */ - GitHubPullRequestController_getPullRequestsByNumber: { + /** List GitHub connection pull requests */ + GitHubPullRequestsController_getConnectionPullRequests: { parameters: { query: { pr_number: number[] } path: { - organization_integration_id: string - repo_owner: string - repo_name: string + connectionId: number } } responses: { 200: { content: { - 'application/json': components['schemas']['GetGithubPullRequest'][] + 'application/json': Record[] } } - /** @description Failed to get github pull requests for a given repo */ + /** @description Failed to list GitHub connection pull requests */ 500: { content: never } } } - /** Gets github pull requests for a given repo */ - GitHubPullRequestController_getPullRequests: { + /** List GitHub pull requests for a specific branch */ + GitHubPullRequestsController_validateConnectionBranch: { parameters: { query?: { per_page?: number page?: number } path: { - organization_integration_id: string - repo_owner: string - repo_name: string - target: string + connectionId: number + branchName: string } } responses: { 200: { content: { - 'application/json': components['schemas']['GetGithubPullRequest'][] + 'application/json': Record[] } } - /** @description Failed to get github pull requests for a given repo */ + /** @description Failed to validate GitHub connection branch */ + 500: { + content: never + } + } + } + /** Gets GitHub repositories for user */ + GitHubRepositoriesController_listRepositories: { + responses: { + 200: { + content: never + } + /** @description Failed to get GitHub repositories for user */ 500: { content: never } diff --git a/apps/studio/data/branches/branch-create-mutation.ts b/apps/studio/data/branches/branch-create-mutation.ts index bd9933ddff0..45ae4585913 100644 --- a/apps/studio/data/branches/branch-create-mutation.ts +++ b/apps/studio/data/branches/branch-create-mutation.ts @@ -52,6 +52,7 @@ export const useBranchCreateMutation = ({ const { projectRef } = variables await queryClient.invalidateQueries(branchKeys.list(projectRef)) await queryClient.invalidateQueries(projectKeys.detail(projectRef)) + await queryClient.invalidateQueries(projectKeys.list()) await onSuccess?.(data, variables, context) }, async onError(data, variables, context) { diff --git a/apps/studio/data/integrations/github-authorization-create-mutation.ts b/apps/studio/data/integrations/github-authorization-create-mutation.ts new file mode 100644 index 00000000000..b7c9d56f2d0 --- /dev/null +++ b/apps/studio/data/integrations/github-authorization-create-mutation.ts @@ -0,0 +1,60 @@ +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' +import toast from 'react-hot-toast' + +import { post } from 'data/fetchers' +import { ResponseError } from 'types' + +export type GitHubAuthorizationCreateVariables = { + code: string +} + +export async function createGitHubAuthorization({ code }: GitHubAuthorizationCreateVariables) { + const { data, error } = await post('/platform/integrations/github/authorization', { + body: { code }, + }) + + if (error) throw error + return data +} + +type GitHubAuthorizationCreateData = Awaited> + +export const useGitHubAuthorizationCreateMutation = ({ + onSuccess, + onError, + ...options +}: Omit< + UseMutationOptions< + GitHubAuthorizationCreateData, + ResponseError, + GitHubAuthorizationCreateVariables + >, + 'mutationFn' +> = {}) => { + const queryClient = useQueryClient() + + return useMutation< + GitHubAuthorizationCreateData, + ResponseError, + GitHubAuthorizationCreateVariables + >((vars) => createGitHubAuthorization(vars), { + async onSuccess(data, variables, context) { + // const { projectRef, id } = variables + + // await Promise.all([ + // queryClient.invalidateQueries(githubAuthorizationKeys.list(projectRef)), + // queryClient.invalidateQueries(githubAuthorizationKeys.githubAuthorization(projectRef, id)), + // ]) + + await onSuccess?.(data, variables, context) + }, + async onError(data, variables, context) { + if (onError === undefined) { + toast.error(`Failed to mutate: ${data.message}`) + } else { + onError(data, variables, context) + } + }, + ...options, + }) +} diff --git a/apps/studio/data/integrations/github-authorization-query.ts b/apps/studio/data/integrations/github-authorization-query.ts new file mode 100644 index 00000000000..d2be21a104e --- /dev/null +++ b/apps/studio/data/integrations/github-authorization-query.ts @@ -0,0 +1,30 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' + +import { get } from 'data/fetchers' +import { ResponseError } from 'types' +import { integrationKeys } from './keys' + +// FIXME(kamil): Do not retry, a single check is fine. +export async function getGitHubAuthorization(signal?: AbortSignal) { + const { data, error } = await get('/platform/integrations/github/authorization', { + signal, + }) + return error ? null : data +} + +export type GitHubAuthorizationData = Awaited> +export type ProjectGitHubRepositoryConnectionsData = Awaited< + ReturnType +> +export type GitHubAuthorizationError = ResponseError + +export const useGitHubAuthorizationQuery = ({ + enabled = true, + ...options +}: UseQueryOptions = {}) => { + return useQuery( + integrationKeys.githubAuthorization(), + ({ signal }) => getGitHubAuthorization(signal), + { enabled, staleTime: 0, ...options } + ) +} diff --git a/apps/studio/data/integrations/integrations-github-branch-check.ts b/apps/studio/data/integrations/github-branch-check-query.ts similarity index 70% rename from apps/studio/data/integrations/integrations-github-branch-check.ts rename to apps/studio/data/integrations/github-branch-check-query.ts index 6b5ff72dde7..0c82002e71b 100644 --- a/apps/studio/data/integrations/integrations-github-branch-check.ts +++ b/apps/studio/data/integrations/github-branch-check-query.ts @@ -5,27 +5,21 @@ import { get } from 'data/fetchers' import { ResponseError } from 'types' export type GithubBranchVariables = { - organizationIntegrationId?: string - repoOwner: string - repoName: string + connectionId: number branchName: string } export async function checkGithubBranchValidity( - { organizationIntegrationId, repoOwner, repoName, branchName }: GithubBranchVariables, + { connectionId, branchName }: GithubBranchVariables, signal?: AbortSignal ) { - if (!organizationIntegrationId) throw new Error('Organization integration ID is required') - const { data, error } = await get( - '/platform/integrations/github/branches/{organization_integration_id}/{repo_owner}/{repo_name}/{branch_name}', + '/platform/integrations/github/branches/{connectionId}/{branchName}', { params: { path: { - organization_integration_id: organizationIntegrationId, - repo_owner: repoOwner, - repo_name: repoName, - branch_name: branchName, + connectionId, + branchName, }, }, signal, diff --git a/apps/studio/data/integrations/github-branches-query.ts b/apps/studio/data/integrations/github-branches-query.ts new file mode 100644 index 00000000000..94260616aa9 --- /dev/null +++ b/apps/studio/data/integrations/github-branches-query.ts @@ -0,0 +1,42 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' +import { get } from 'data/fetchers' +import { integrationKeys } from './keys' +import { ResponseError } from 'types' + +export type GitHubBranchesVariables = { + connectionId?: number +} + +export async function getGitHubBranches( + { connectionId }: GitHubBranchesVariables, + signal?: AbortSignal +) { + if (!connectionId) throw new Error('connectionId is required') + + const { data, error } = await get(`/platform/integrations/github/branches/{connectionId}`, { + params: { path: { connectionId } }, + signal, + }) + + if (error) throw new Error((error as ResponseError).message) + return data +} + +export type GitHubBranchesData = Awaited> +export type GitHubBranchesError = ResponseError + +export const useGitHubBranchesQuery = ( + { connectionId }: GitHubBranchesVariables, + { + enabled = true, + ...options + }: UseQueryOptions = {} +) => + useQuery( + integrationKeys.githubBranchesList(connectionId), + ({ signal }) => getGitHubBranches({ connectionId }, signal), + { + enabled: enabled && typeof connectionId !== 'undefined', + ...options, + } + ) diff --git a/apps/studio/data/integrations/github-connection-create-mutation.ts b/apps/studio/data/integrations/github-connection-create-mutation.ts new file mode 100644 index 00000000000..62a494ed2e1 --- /dev/null +++ b/apps/studio/data/integrations/github-connection-create-mutation.ts @@ -0,0 +1,52 @@ +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' +import { toast } from 'react-hot-toast' + +import { post } from 'data/fetchers' +import { ResponseError } from 'types' +import { GitHubConnectionCreateVariables } from './integrations.types' +import { integrationKeys } from './keys' + +export async function createGitHubConnection({ connection }: GitHubConnectionCreateVariables) { + const { data, error } = await post('/platform/integrations/github/connections', { + body: connection, + }) + if (error) { + throw error + } + + return data +} + +export type GitHubConnectionCreateData = Awaited> + +export const useGitHubConnectionCreateMutation = ({ + onSuccess, + onError, + ...options +}: Omit< + UseMutationOptions, + 'mutationFn' +> = {}) => { + const queryClient = useQueryClient() + return useMutation( + (vars) => createGitHubConnection(vars), + { + async onSuccess(data, variables, context) { + await Promise.all([ + queryClient.invalidateQueries( + integrationKeys.githubConnectionsList(variables.organizationId) + ), + ]) + await onSuccess?.(data, variables, context) + }, + async onError(data, variables, context) { + if (onError === undefined) { + toast.error(`Failed to create Github connection: ${data.message}`) + } else { + onError(data, variables, context) + } + }, + ...options, + } + ) +} diff --git a/apps/studio/data/integrations/integrations-github-connection-delete-mutation.ts b/apps/studio/data/integrations/github-connection-delete-mutation.ts similarity index 71% rename from apps/studio/data/integrations/integrations-github-connection-delete-mutation.ts rename to apps/studio/data/integrations/github-connection-delete-mutation.ts index f3bd4f08cfd..d6fc6067e10 100644 --- a/apps/studio/data/integrations/integrations-github-connection-delete-mutation.ts +++ b/apps/studio/data/integrations/github-connection-delete-mutation.ts @@ -6,15 +6,14 @@ import { ResponseError } from 'types' import { integrationKeys } from './keys' type DeleteVariables = { - connectionId: string - - integrationId: string - orgSlug: string | undefined + connectionId: string | number + organizationId: number } export async function deleteConnection({ connectionId }: DeleteVariables, signal?: AbortSignal) { const { data, error } = await del('/platform/integrations/github/connections/{connection_id}', { - params: { path: { connection_id: connectionId } }, + params: { path: { connection_id: String(connectionId) } }, + signal, }) if (error) throw error @@ -23,7 +22,7 @@ export async function deleteConnection({ connectionId }: DeleteVariables, signal type DeleteContentData = Awaited> -export const useIntegrationsGitHubInstalledConnectionDeleteMutation = ({ +export const useGitHubConnectionDeleteMutation = ({ onSuccess, onError, ...options @@ -37,11 +36,8 @@ export const useIntegrationsGitHubInstalledConnectionDeleteMutation = ({ { async onSuccess(data, variables, context) { await Promise.all([ - queryClient.invalidateQueries(integrationKeys.integrationsList()), - queryClient.invalidateQueries(integrationKeys.integrationsListWithOrg(variables.orgSlug)), - queryClient.invalidateQueries(integrationKeys.githubRepoList(variables.integrationId)), queryClient.invalidateQueries( - integrationKeys.githubConnectionsList(variables.integrationId) + integrationKeys.githubConnectionsList(variables.organizationId) ), ]) await onSuccess?.(data, variables, context) diff --git a/apps/studio/data/integrations/github-connection-update-mutate.ts b/apps/studio/data/integrations/github-connection-update-mutation.ts similarity index 50% rename from apps/studio/data/integrations/github-connection-update-mutate.ts rename to apps/studio/data/integrations/github-connection-update-mutation.ts index 2d9b68ba51f..3af0320f8ea 100644 --- a/apps/studio/data/integrations/github-connection-update-mutate.ts +++ b/apps/studio/data/integrations/github-connection-update-mutation.ts @@ -3,46 +3,49 @@ import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' import { ResponseError } from 'types' -import { UpdateConnectionPayload } from './integrations.types' import { integrationKeys } from './keys' -export async function updateGithubConnection({ - id, - metadata, - organizationIntegrationId, -}: UpdateConnectionPayload) { - const { data, error } = await patch('/platform/integrations/github/connections/{connection_id}', { - params: { - path: { connection_id: id }, - }, - body: { - // @ts-expect-error - metadata, - }, - }) +type UpdateVariables = { + connectionId: string | number + organizationId: number + workdir: string + supabaseChangesOnly: boolean +} +export async function updateConnection( + { connectionId, workdir, supabaseChangesOnly }: UpdateVariables, + signal?: AbortSignal +) { + const { data, error } = await patch('/platform/integrations/github/connections/{connection_id}', { + params: { path: { connection_id: String(connectionId) } }, + signal, + body: { workdir, supabase_changes_only: supabaseChangesOnly }, + }) if (error) throw error + return data } -type UpdateGithubConnectionData = Awaited> +type UpdateContentData = Awaited> -export const useGithubConnectionUpdateMutation = ({ +export const useGitHubConnectionUpdateMutation = ({ onSuccess, onError, ...options }: Omit< - UseMutationOptions, + UseMutationOptions, 'mutationFn' > = {}) => { const queryClient = useQueryClient() - return useMutation( - (vars) => updateGithubConnection(vars), + return useMutation( + (args) => updateConnection(args), { async onSuccess(data, variables, context) { - await queryClient.invalidateQueries( - integrationKeys.githubConnectionsList(variables.organizationIntegrationId) - ) + await Promise.all([ + queryClient.invalidateQueries( + integrationKeys.githubConnectionsList(variables.organizationId) + ), + ]) await onSuccess?.(data, variables, context) }, async onError(data, variables, context) { diff --git a/apps/studio/data/integrations/github-connections-query.ts b/apps/studio/data/integrations/github-connections-query.ts new file mode 100644 index 00000000000..ef491049153 --- /dev/null +++ b/apps/studio/data/integrations/github-connections-query.ts @@ -0,0 +1,46 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' + +import { get } from 'data/fetchers' +import { ResponseError } from 'types' +import { integrationKeys } from './keys' + +export type GitHubConnectionsVariables = { + organizationId?: number +} + +export async function getGitHubConnections( + { organizationId }: GitHubConnectionsVariables, + signal?: AbortSignal +) { + if (!organizationId) throw new Error('organizationId is required') + + const { data, error } = await get('/platform/integrations/github/connections', { + params: { + query: { + organization_id: organizationId, + }, + }, + signal, + }) + if (error) throw new Error((error as ResponseError).message) + return data.connections +} + +export type GitHubConnectionsData = Awaited> +export type GitHubConnectionsError = ResponseError + +export type GitHubConnection = GitHubConnectionsData[0] + +export const useGitHubConnectionsQuery = ( + { organizationId }: GitHubConnectionsVariables, + { + enabled = true, + ...options + }: UseQueryOptions = {} +) => { + return useQuery( + integrationKeys.githubConnectionsList(organizationId), + ({ signal }) => getGitHubConnections({ organizationId }, signal), + { enabled, ...options } + ) +} diff --git a/apps/studio/data/integrations/github-integration-create-mutation.ts b/apps/studio/data/integrations/github-integration-create-mutation.ts deleted file mode 100644 index 09e62724062..00000000000 --- a/apps/studio/data/integrations/github-integration-create-mutation.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' -import { toast } from 'react-hot-toast' - -import { post } from 'data/fetchers' -import { ResponseError } from 'types' -import { integrationKeys } from './keys' - -export type GitHubIntegrationCreateVariables = { - installationId: number - orgSlug: string - metadata: { supabaseConfig: { supabaseDirectory: string } } -} - -export async function createGitHubIntegration({ - installationId, - orgSlug, - metadata, -}: GitHubIntegrationCreateVariables) { - const { data, error } = await post('/platform/integrations/github', { - body: { - installation_id: installationId, - organization_slug: orgSlug, - metadata: metadata as any, - }, - }) - if (error) throw error - - return data -} - -type GitHubIntegrationCreateData = Awaited> - -export const useGitHubIntegrationCreateMutation = ({ - onSuccess, - onError, - ...options -}: Omit< - UseMutationOptions, - 'mutationFn' -> = {}) => { - const queryClient = useQueryClient() - return useMutation( - (vars) => createGitHubIntegration(vars), - { - async onSuccess(data, variables, context) { - await Promise.all([ - queryClient.invalidateQueries(integrationKeys.integrationsList()), - queryClient.invalidateQueries(integrationKeys.integrationsListWithOrg(variables.orgSlug)), - queryClient.invalidateQueries(integrationKeys.githubRepoList(data.id)), - ]) - await onSuccess?.(data, variables, context) - }, - async onError(data, variables, context) { - if (onError === undefined) { - toast.error(`Failed to create Github integration: ${data.message}`) - } else { - onError(data, variables, context) - } - }, - ...options, - } - ) -} diff --git a/apps/studio/data/integrations/github-pull-requests-query.ts b/apps/studio/data/integrations/github-pull-requests-query.ts new file mode 100644 index 00000000000..76345211bdc --- /dev/null +++ b/apps/studio/data/integrations/github-pull-requests-query.ts @@ -0,0 +1,54 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' +import { get } from 'data/fetchers' +import { integrationKeys } from './keys' +import { ResponseError } from 'types' +import { components } from 'data/api' + +export type GitHubPullRequestsVariables = { + connectionId?: number + prNumbers?: number[] +} + +// TODO(alaister): find the actual type +export type GitHubPullRequest = any + +export async function getGitHubPullRequests( + { connectionId, prNumbers = [] }: GitHubPullRequestsVariables, + signal?: AbortSignal +) { + if (!connectionId) throw new Error('connectionId is required') + + const { data, error } = await get(`/platform/integrations/github/pull-requests/{connectionId}`, { + params: { + path: { + connectionId, + }, + query: { + pr_number: prNumbers, + }, + }, + signal, + }) + + if (error) throw error + return data +} + +export type GitHubPullRequestsData = Awaited> +export type GitHubPullRequestsError = ResponseError + +export const useGitHubPullRequestsQuery = ( + { connectionId, prNumbers }: GitHubPullRequestsVariables, + { + enabled = true, + ...options + }: UseQueryOptions = {} +) => + useQuery( + integrationKeys.githubPullRequestsList(connectionId, prNumbers), + ({ signal }) => getGitHubPullRequests({ connectionId, prNumbers }, signal), + { + enabled: enabled && typeof connectionId !== 'undefined', + ...options, + } + ) diff --git a/apps/studio/data/integrations/github-repositories-query.ts b/apps/studio/data/integrations/github-repositories-query.ts new file mode 100644 index 00000000000..07fc7ad3c9b --- /dev/null +++ b/apps/studio/data/integrations/github-repositories-query.ts @@ -0,0 +1,32 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' + +import { get } from 'data/fetchers' +import { ResponseError } from 'types' +import { integrationKeys } from './keys' + +export async function getGitHubRepositories(signal?: AbortSignal) { + const { data, error } = await get('/platform/integrations/github/repositories', { + signal, + }) + if (error) throw new Error((error as ResponseError).message) + + // [Alaister]: temp fix until we have a proper response type + return (data as any).repositories +} + +export type GitHubRepositoriesData = Awaited> +export type ProjectGitHubRepositoryConnectionsData = Awaited< + ReturnType +> +export type GitHubRepositoriesError = ResponseError + +export const useGitHubRepositoriesQuery = ({ + enabled = true, + ...options +}: UseQueryOptions = {}) => { + return useQuery( + integrationKeys.githubRepositoriesList(), + ({ signal }) => getGitHubRepositories(signal), + { enabled, staleTime: 0, ...options } + ) +} diff --git a/apps/studio/data/integrations/integrations-github-branches-query.ts b/apps/studio/data/integrations/integrations-github-branches-query.ts deleted file mode 100644 index c894ec47223..00000000000 --- a/apps/studio/data/integrations/integrations-github-branches-query.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get } from 'data/fetchers' -import { integrationKeys } from './keys' -import { ResponseError } from 'types' - -export type GithubBranchesVariables = { - organizationIntegrationId?: string - repoOwner: string - repoName: string -} - -export async function getGithubBranches( - { organizationIntegrationId, repoOwner, repoName }: GithubBranchesVariables, - signal?: AbortSignal -) { - if (!organizationIntegrationId) throw new Error('Organization integration ID is required') - - const { data, error } = await get( - `/platform/integrations/github/branches/{organization_integration_id}/{repo_owner}/{repo_name}`, - { - params: { - path: { - organization_integration_id: organizationIntegrationId, - repo_owner: repoOwner, - repo_name: repoName, - }, - }, - signal, - } - ) - - if (error) throw error - return data -} - -export type GithubBranchesData = Awaited> -export type GithubBranchesError = ResponseError - -export const useGithubBranchesQuery = ( - { organizationIntegrationId, repoOwner, repoName }: GithubBranchesVariables, - { - enabled = true, - ...options - }: UseQueryOptions = {} -) => - useQuery( - integrationKeys.githubBranchesList(organizationIntegrationId, repoOwner, repoName), - ({ signal }) => getGithubBranches({ organizationIntegrationId, repoOwner, repoName }, signal), - { - enabled: - enabled && - typeof organizationIntegrationId !== 'undefined' && - typeof repoOwner !== 'undefined' && - typeof repoName !== 'undefined', - ...options, - } - ) diff --git a/apps/studio/data/integrations/integrations-github-connections-create-mutation.ts b/apps/studio/data/integrations/integrations-github-connections-create-mutation.ts deleted file mode 100644 index b9cd426eef3..00000000000 --- a/apps/studio/data/integrations/integrations-github-connections-create-mutation.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' -import { toast } from 'react-hot-toast' - -import { post } from 'data/fetchers' -import { ResponseError } from 'types' -import { integrationKeys } from './keys' -import { IntegrationConnectionsCreateVariables } from './integrations.types' - -export async function createIntegrationGitHubConnections({ - organizationIntegrationId, - connection, -}: IntegrationConnectionsCreateVariables) { - const { data, error } = await post('/platform/integrations/github/connections', { - body: { - organization_integration_id: organizationIntegrationId, - connection, - }, - }) - if (error) { - throw error - } - - return data -} - -export type IntegrationGitHubConnectionsCreateData = Awaited< - ReturnType -> - -export const useIntegrationGitHubConnectionsCreateMutation = ({ - onSuccess, - onError, - ...options -}: Omit< - UseMutationOptions< - IntegrationGitHubConnectionsCreateData, - ResponseError, - IntegrationConnectionsCreateVariables - >, - 'mutationFn' -> = {}) => { - const queryClient = useQueryClient() - return useMutation< - IntegrationGitHubConnectionsCreateData, - ResponseError, - IntegrationConnectionsCreateVariables - >((vars) => createIntegrationGitHubConnections(vars), { - async onSuccess(data, variables, context) { - await Promise.all([ - queryClient.invalidateQueries(integrationKeys.integrationsList()), - queryClient.invalidateQueries(integrationKeys.integrationsListWithOrg(variables.orgSlug)), - queryClient.invalidateQueries( - integrationKeys.githubRepoList(variables.organizationIntegrationId) - ), - queryClient.invalidateQueries( - integrationKeys.githubConnectionsList(variables.organizationIntegrationId) - ), - ]) - await onSuccess?.(data, variables, context) - }, - async onError(data, variables, context) { - if (onError === undefined) { - toast.error(`Failed to create Github connection: ${data.message}`) - } else { - onError(data, variables, context) - } - }, - ...options, - }) -} diff --git a/apps/studio/data/integrations/integrations-github-pull-requests-query.ts b/apps/studio/data/integrations/integrations-github-pull-requests-query.ts deleted file mode 100644 index 326cc548f00..00000000000 --- a/apps/studio/data/integrations/integrations-github-pull-requests-query.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get } from 'data/fetchers' -import { integrationKeys } from './keys' -import { ResponseError } from 'types' -import { components } from 'data/api' - -export type GithubPullRequestsVariables = { - organizationIntegrationId?: string - repoOwner: string - repoName: string - prNumbers?: number[] -} - -export type GitHubPullRequest = components['schemas']['GetGithubPullRequest'] - -export async function getGitHubPullRequests( - { organizationIntegrationId, repoOwner, repoName, prNumbers }: GithubPullRequestsVariables, - signal?: AbortSignal -) { - if (!organizationIntegrationId) throw new Error('Organization integration ID is required') - if (!prNumbers) throw new Error('A list of PR numbers is required') - - const { data, error } = await get( - `/platform/integrations/github/pull-requests/{organization_integration_id}/{repo_owner}/{repo_name}`, - { - params: { - path: { - organization_integration_id: organizationIntegrationId, - repo_owner: repoOwner, - repo_name: repoName, - }, - query: { - // @ts-ignore generated api types is incorrect here, to remove ignore statement once fixed - pr_number: prNumbers, - }, - }, - signal, - } - ) - - if (error) throw error - return data -} - -export type GithubPullRequestsData = Awaited> -export type GithubPullRequestsError = ResponseError - -export const useGithubPullRequestsQuery = ( - { organizationIntegrationId, repoOwner, repoName, prNumbers }: GithubPullRequestsVariables, - { - enabled = true, - ...options - }: UseQueryOptions = {} -) => - useQuery( - // [Joshen] Just fyi im not sure if we need to include prNumber in the RQ key here - integrationKeys.githubPullRequestsList(organizationIntegrationId, repoOwner, repoName), - ({ signal }) => - getGitHubPullRequests({ organizationIntegrationId, repoOwner, repoName, prNumbers }, signal), - { - enabled: - enabled && - typeof organizationIntegrationId !== 'undefined' && - typeof repoOwner !== 'undefined' && - typeof repoName !== 'undefined' && - typeof prNumbers !== 'undefined', - ...options, - } - ) diff --git a/apps/studio/data/integrations/integrations-github-repos-query.ts b/apps/studio/data/integrations/integrations-github-repos-query.ts deleted file mode 100644 index 65b7ad32f2a..00000000000 --- a/apps/studio/data/integrations/integrations-github-repos-query.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { useQuery, UseQueryOptions } from '@tanstack/react-query' - -import { get } from 'data/fetchers' -import { ResponseError } from 'types' -import { integrationKeys } from './keys' - -export type GitHubReposVariables = { - integrationId: string | undefined -} - -// We don't want to fetch more than 1000 repositories, as it's already more than enough. -const MAX_PAGES = 10 - -export async function getGitHubRepos( - { integrationId }: GitHubReposVariables, - signal?: AbortSignal -) { - if (!integrationId) { - throw new Error('integrationId is required') - } - - const repos: Awaited> = [] - const perPage = 100 - let page = 1 - - // This is unfortunate, because we will do redundant API call in case there are exactly 100 results, - // but the API is returning an array instead of `{ repos: [], total_count: n }`. - while (true) { - const reposChunk = await getSingleGithubReposPage(integrationId, perPage, page, signal) - repos.push(...reposChunk) - page += 1 - - // Stop asking for more data if last request was exhaustive or we reached a limit, . - if (reposChunk.length < perPage || page > MAX_PAGES) { - break - } - } - - return repos -} - -async function getSingleGithubReposPage( - integrationId: string, - perPage: number, - page: number, - signal?: AbortSignal -) { - const { data, error } = await get( - '/platform/integrations/github/repos/{organization_integration_id}', - { - params: { - path: { - organization_integration_id: integrationId, - }, - query: { - per_page: perPage, - page, - }, - }, - signal, - } - ) - if (error) { - throw error - } - return data -} - -export type GitHubReposData = Awaited> -export type GitHubReposError = ResponseError - -export const useGitHubReposQuery = ( - { integrationId }: GitHubReposVariables, - { enabled = true, ...options }: UseQueryOptions = {} -) => - useQuery( - integrationKeys.githubRepoList(integrationId), - ({ signal }) => getGitHubRepos({ integrationId }, signal), - { - enabled: enabled && typeof integrationId !== 'undefined', - ...options, - } - ) diff --git a/apps/studio/data/integrations/integrations.types.ts b/apps/studio/data/integrations/integrations.types.ts index f28a458e85b..efd87d3f4f6 100644 --- a/apps/studio/data/integrations/integrations.types.ts +++ b/apps/studio/data/integrations/integrations.types.ts @@ -1,3 +1,5 @@ +import { components } from 'data/api' + export type VercelFramework = | ( | 'blitzjs' @@ -137,6 +139,7 @@ export type Imetadata = { preview: boolean } supabaseDirectory?: string + supabaseChangesOnly?: boolean } link?: VercelGitLink name: string @@ -249,6 +252,16 @@ export type IntegrationConnectionsCreateVariables = { metadata: any } orgSlug: string | undefined + new?: { + installation_id: number + project_ref: string + repository_id: number + } +} + +export type GitHubConnectionCreateVariables = { + organizationId: number + connection: components['schemas']['CreateGitHubConnectionsBody'] } export type UpdateConnectionPayload = { diff --git a/apps/studio/data/integrations/keys.ts b/apps/studio/data/integrations/keys.ts index d45a653c2ba..fd30674f139 100644 --- a/apps/studio/data/integrations/keys.ts +++ b/apps/studio/data/integrations/keys.ts @@ -4,8 +4,6 @@ export const integrationKeys = { integrationsList: () => ['organizations', 'integrations'] as const, vercelProjectList: (organization_integration_id: string | undefined) => ['organizations', organization_integration_id, 'vercel-projects'] as const, - githubRepoList: (organization_integration_id: string | undefined) => - ['organizations', organization_integration_id, 'github-repos'] as const, vercelConnectionsList: (organization_integration_id: string | undefined) => ['organizations', organization_integration_id, 'vercel-connections'] as const, githubBranch: ( @@ -21,16 +19,14 @@ export const integrationKeys = { repo_name, branch_name, ], - githubBranchesList: ( - organization_integration_id: string | undefined, - repo_owner: string, - repo_name: string - ) => ['organizations', organization_integration_id, 'branches', repo_owner, repo_name], - githubPullRequestsList: ( - organization_integration_id: string | undefined, - repo_owner: string, - repo_name: string - ) => ['organizations', organization_integration_id, 'pull-requests', repo_owner, repo_name], - githubConnectionsList: (organization_integration_id: string | undefined) => - ['organizations', organization_integration_id, 'github-connections'] as const, + githubAuthorization: () => ['github-authorization'] as const, + githubRepositoriesList: () => ['github-repositories'] as const, + githubBranchesList: (connectionId: number | undefined) => ['github-branches', connectionId], + githubPullRequestsList: (connectionId: number | undefined, prNumbers: number[] | undefined) => [ + 'github-pull-requests', + connectionId, + { prNumbers }, + ], + githubConnectionsList: (organizationId: number | undefined) => + ['organizations', organizationId, 'github-connections'] as const, } diff --git a/apps/studio/lib/github-integration.ts b/apps/studio/lib/github-integration.ts deleted file mode 100644 index b7ae7c28e75..00000000000 --- a/apps/studio/lib/github-integration.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { useParams } from 'common' -import { useGitHubIntegrationCreateMutation } from 'data/integrations/github-integration-create-mutation' -import { useOrganizationsQuery } from 'data/organizations/organizations-query' -import { useProjectsQuery } from 'data/projects/projects-query' -import { useEffect, useState } from 'react' - -export function useGitHubIntegrationAutoInstall(callback?: (id: string, orgSlug: string) => void) { - const { installation_id: installationId, state: projectRef } = useParams() - const shouldAttemptInstall = projectRef !== undefined && installationId !== undefined - - const [isAutoInstalling, setIsAutoInstalling] = useState(false) - - const { data: projects, isSuccess: isProjectsSuccess } = useProjectsQuery({ - enabled: shouldAttemptInstall, - }) - const { data: organizations, isSuccess: isOrganizationsSuccess } = useOrganizationsQuery({ - enabled: shouldAttemptInstall, - }) - - const { mutate: createIntegration } = useGitHubIntegrationCreateMutation() - - useEffect(() => { - async function autoInstall() { - if (shouldAttemptInstall) { - setIsAutoInstalling(true) - } - - if (projectRef && isProjectsSuccess && isOrganizationsSuccess) { - const project = projects.find((x) => x.ref === projectRef) - const organization = organizations.find((x) => x.id === project?.organization_id) - - if (project && organization) { - createIntegration( - { - installationId: Number(installationId), - orgSlug: organization.slug, - metadata: { - supabaseConfig: { - supabaseDirectory: '/supabase', - }, - }, - }, - { - onSuccess({ id }) { - setIsAutoInstalling(false) - - callback?.(id, organization.slug) - }, - onError() { - setIsAutoInstalling(false) - }, - } - ) - } else { - setIsAutoInstalling(false) - } - } - } - - autoInstall() - }, [ - callback, - createIntegration, - installationId, - isOrganizationsSuccess, - isProjectsSuccess, - organizations, - projectRef, - projects, - shouldAttemptInstall, - ]) - - return isAutoInstalling -} diff --git a/apps/studio/lib/github.tsx b/apps/studio/lib/github.tsx new file mode 100644 index 00000000000..981e3726fd6 --- /dev/null +++ b/apps/studio/lib/github.tsx @@ -0,0 +1,53 @@ +const GITHUB_INTEGRATION_INSTALLATION_URL = + process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod' + ? `https://github.com/apps/supabase/installations/new` + : process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging' + ? `https://github.com/apps/supabase-staging/installations/new` + : `https://github.com/apps/supabase-github-v2-migration-test/installations/new` + +const GITHUB_INTEGRATION_CLIENT_ID = + process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod' + ? `Iv1.b91a6d8eaa272168` + : process.env.NEXT_PUBLIC_ENVIRONMENT === 'staging' + ? `Iv1.2681ab9a0360d8ad` + : `Iv1.5022a3b44d150fbf` + +const GITHUB_INTEGRATION_AUTHORIZATION_URL = `https://github.com/login/oauth/authorize?client_id=${GITHUB_INTEGRATION_CLIENT_ID}` + +export function openInstallGitHubIntegrationWindow(type: 'install' | 'authorize') { + const w = 600 + const h = 800 + + const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screenX + const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screenY + + const width = window.innerWidth + ? window.innerWidth + : document.documentElement.clientWidth + ? document.documentElement.clientWidth + : screen.width + const height = window.innerHeight + ? window.innerHeight + : document.documentElement.clientHeight + ? document.documentElement.clientHeight + : screen.height + + const windowUrl = + type === 'install' ? GITHUB_INTEGRATION_INSTALLATION_URL : GITHUB_INTEGRATION_AUTHORIZATION_URL + const systemZoom = width / window.screen.availWidth + const left = (width - w) / 2 / systemZoom + dualScreenLeft + const top = (height - h) / 2 / systemZoom + dualScreenTop + const newWindow = window.open( + windowUrl, + 'GitHub', + `scrollbars=yes,resizable=no,status=no,location=no,toolbar=no,menubar=no, + width=${w / systemZoom}, + height=${h / systemZoom}, + top=${top}, + left=${left} + ` + ) + if (newWindow) { + newWindow.focus() + } +} diff --git a/apps/studio/pages/integrations/github/[integrationId]/choose-project.tsx b/apps/studio/pages/integrations/github/[integrationId]/choose-project.tsx deleted file mode 100644 index 575935b8459..00000000000 --- a/apps/studio/pages/integrations/github/[integrationId]/choose-project.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { useRouter } from 'next/router' -import { useMemo } from 'react' - -import { useParams } from 'common' -import ProjectLinker from 'components/interfaces/Integrations/ProjectLinker' -import { Markdown } from 'components/interfaces/Markdown' -import GitHubIntegrationWindowLayout from 'components/layouts/IntegrationsLayout/GitHubIntegrationWindowLayout' -import { ScaffoldContainer, ScaffoldDivider } from 'components/layouts/Scaffold' -import { useIntegrationGitHubConnectionsCreateMutation } from 'data/integrations/integrations-github-connections-create-mutation' -import { useGitHubReposQuery } from 'data/integrations/integrations-github-repos-query' -import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only' -import { useOrganizationsQuery } from 'data/organizations/organizations-query' -import { useProjectsQuery } from 'data/projects/projects-query' -import { BASE_PATH } from 'lib/constants' -import { EMPTY_ARR } from 'lib/void' -import { NextPageWithLayout } from 'types' -import { IconBook, IconLifeBuoy, LoadingLine } from 'ui' - -const GITHUB_ICON = ( - GitHub Icon -) - -const ChooseProjectGitHubPage: NextPageWithLayout = () => { - const router = useRouter() - const { integrationId, slug, organizationSlug, state: projectRef } = useParams() - const orgSlug = slug ?? organizationSlug - - const { data: integrations } = useOrgIntegrationsQuery({ - orgSlug, - }) - const { data: organizations } = useOrganizationsQuery() - const { data: allProjects, isLoading: isLoadingSupabaseProjectsData } = useProjectsQuery() - const { data: allRepos, isLoading: isLoadingGithubReposData } = useGitHubReposQuery({ - integrationId, - }) - - const integration = integrations?.find((integration) => integration.id === integrationId) - const organization = organizations?.find((organization) => organization.slug === orgSlug) - const projects = useMemo( - () => - allProjects - ?.filter((project) => project.organization_id === organization?.id) - .map((project) => ({ id: project.id.toString(), name: project.name, ref: project.ref })) ?? - EMPTY_ARR, - [allProjects, organization?.id] - ) - - const repos = useMemo( - () => - allRepos?.map((repo) => ({ - id: repo.id.toString(), - name: repo.full_name, - })) ?? EMPTY_ARR, - [allRepos] - ) - - function onDone() { - if (projectRef) { - router.push(`/project/${projectRef}?enableBranching=true`) - } else { - router.push(`/org/${orgSlug}/integrations`) - } - } - - const { mutate: createConnections, isLoading: isCreatingConnection } = - useIntegrationGitHubConnectionsCreateMutation({ - onSuccess: onDone, - }) - - return ( - <> -
- - <> - -
-

- Link a Supabase project to a GitHub repository -

- -
- -
- - - -
- -
- Docs -
-
- Support -
-
- - ) -} - -ChooseProjectGitHubPage.getLayout = (page) => ( - {page} -) - -export default ChooseProjectGitHubPage diff --git a/apps/studio/pages/integrations/github/authorize.tsx b/apps/studio/pages/integrations/github/authorize.tsx new file mode 100644 index 00000000000..52a9c784eb1 --- /dev/null +++ b/apps/studio/pages/integrations/github/authorize.tsx @@ -0,0 +1,30 @@ +import { useEffect } from 'react' + +import { useParams } from 'common' +import { useGitHubAuthorizationCreateMutation } from 'data/integrations/github-authorization-create-mutation' + +const GitHubIntegrationAuthorize = () => { + const { code } = useParams() + + const { mutate, isSuccess } = useGitHubAuthorizationCreateMutation({ + onSuccess() { + window.close() + }, + }) + + useEffect(() => { + if (code) { + mutate({ code }) + } + }, [code, mutate]) + + return ( +
+

Completing GitHub Authorization...

+ + {isSuccess ?

You can now close this window.

:

} +

+ ) +} + +export default GitHubIntegrationAuthorize diff --git a/apps/studio/pages/integrations/github/install.tsx b/apps/studio/pages/integrations/github/install.tsx deleted file mode 100644 index fad21041cdd..00000000000 --- a/apps/studio/pages/integrations/github/install.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import { useRouter } from 'next/router' -import { useCallback, useMemo, useState } from 'react' - -import { useParams } from 'common' -import OrganizationPicker from 'components/interfaces/Integrations/OrganizationPicker' -import { Markdown } from 'components/interfaces/Markdown' -import GitHubIntegrationWindowLayout from 'components/layouts/IntegrationsLayout/GitHubIntegrationWindowLayout' -import { getHasInstalledObject } from 'components/layouts/IntegrationsLayout/Integrations.utils' -import { ScaffoldColumn, ScaffoldContainer, ScaffoldDivider } from 'components/layouts/Scaffold' -import { useGitHubIntegrationCreateMutation } from 'data/integrations/github-integration-create-mutation' -import { useIntegrationsQuery } from 'data/integrations/integrations-query' -import { useOrganizationsQuery } from 'data/organizations/organizations-query' -import { useStore } from 'hooks' -import { NextPageWithLayout, Organization } from 'types' -import { - Alert, - AlertDescription_Shadcn_, - AlertTitle_Shadcn_, - Alert_Shadcn_, - Button, - IconAlertTriangle, - IconBook, - IconLifeBuoy, - LoadingLine, -} from 'ui' -import { useGitHubIntegrationAutoInstall } from 'lib/github-integration' - -const GitHubIntegration: NextPageWithLayout = () => { - const router = useRouter() - const { ui } = useStore() - const { installation_id: installationId } = useParams() - const [selectedOrg, setSelectedOrg] = useState(null) - - /** - * Fetch the list of organization based integration installations for GitHub. - * - * Array of integrations installed on all - */ - const { data: integrationData } = useIntegrationsQuery() - - const { data: organizationsData } = useOrganizationsQuery({ - onSuccess(organizations) { - const firstOrg = organizations?.[0] - if (firstOrg && selectedOrg === null) { - setSelectedOrg(firstOrg) - router.query.organizationSlug = firstOrg.slug - } - }, - }) - - const onInstalled = useCallback( - (id: string, orgSlug?: string) => { - router.push({ - pathname: `/integrations/github/${id}/choose-project`, - query: { ...router.query, slug: orgSlug }, - }) - }, - [router] - ) - - const { mutate, isLoading: isLoadingGitHubIntegrationCreateMutation } = - useGitHubIntegrationCreateMutation({ - onSuccess({ id }) { - onInstalled(id, selectedOrg?.slug) - }, - }) - - const isAutoInstalling = useGitHubIntegrationAutoInstall(onInstalled) - - const installed = useMemo( - () => - integrationData && organizationsData - ? getHasInstalledObject({ - integrationName: 'GitHub', - integrationData, - organizationsData, - installationId, - }) - : {}, - [installationId, integrationData, organizationsData] - ) - - function onInstall() { - const orgSlug = selectedOrg?.slug - - const installedIntegration = integrationData?.find( - (x) => - x.organization.slug === orgSlug && - x.metadata !== undefined && - 'installation_id' in x.metadata && - String(x.metadata?.installation_id) === String(installationId) - ) - const isIntegrationInstalled = Boolean(installedIntegration) - - if (!orgSlug) { - return ui.setNotification({ category: 'error', message: 'Please select an organization' }) - } - - if (!installationId) { - return ui.setNotification({ category: 'error', message: 'GitHub Installation ID is missing' }) - } - - /** - * Only install if Integration hasn't already been installed - */ - if (!isIntegrationInstalled) { - mutate({ - installationId: Number(installationId), - orgSlug, - metadata: { - supabaseConfig: { - supabaseDirectory: '/supabase', - }, - }, - }) - } else { - router.push({ - pathname: `/integrations/github/${installedIntegration?.id}/choose-project`, - query: router.query, - }) - } - } - - const disableInstallationForm = Boolean(selectedOrg && installed[selectedOrg.slug]) - - return ( - <> -
- - - -

Choose organization

- <> - - { - router.query.organizationSlug = org.slug - setSelectedOrg(org) - }} - configurationId={installationId} - /> - {disableInstallationForm && ( - - - GitHub Integration is already installed. - - You will need to choose another organization to install the integration. - - - )} -
- -
- -
-
- - - - - - - -
- -
- Docs -
-
- Support -
-
- - ) -} - -GitHubIntegration.getLayout = (page) => ( - {page} -) - -export default GitHubIntegration diff --git a/apps/studio/pages/org/[slug]/index.tsx b/apps/studio/pages/org/[slug]/index.tsx index c303957422b..f52f3bcc022 100644 --- a/apps/studio/pages/org/[slug]/index.tsx +++ b/apps/studio/pages/org/[slug]/index.tsx @@ -7,6 +7,7 @@ import ShimmeringCard from 'components/interfaces/Home/ProjectList/ShimmeringCar import AppLayout from 'components/layouts/AppLayout/AppLayout' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' +import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only' import { useProjectsQuery } from 'data/projects/projects-query' import { useSelectedOrganization } from 'hooks' @@ -27,9 +28,23 @@ const ProjectsPage: NextPageWithLayout = () => { .sort((a, b) => a.name.localeCompare(b.name)) const { data: integrations } = useOrgIntegrationsQuery({ orgSlug: organization?.slug }) - const githubConnections = integrations - ?.filter((integration) => integration.integration.name === 'GitHub') - .flatMap((integration) => integration.connections) + const { data: connections } = useGitHubConnectionsQuery({ organizationId: organization?.id }) + const githubConnections = connections?.map((connection) => ({ + id: String(connection.id), + added_by: { + id: String(connection.user?.id), + primary_email: connection.user?.primary_email ?? '', + username: connection.user?.username ?? '', + }, + foreign_project_id: String(connection.repository.id), + supabase_project_ref: connection.project.ref, + organization_integration_id: 'unused', + inserted_at: connection.inserted_at, + updated_at: connection.updated_at, + metadata: { + name: connection.repository.name, + } as any, + })) const vercelConnections = integrations ?.filter((integration) => integration.integration.name === 'Vercel') .flatMap((integration) => integration.connections) diff --git a/apps/studio/state/side-panels.ts b/apps/studio/state/side-panels.ts index 1719269e02a..e45b7fec4aa 100644 --- a/apps/studio/state/side-panels.ts +++ b/apps/studio/state/side-panels.ts @@ -23,11 +23,6 @@ export const sidePanelsState = proxy({ setGithubConnectionsOpen: (bool: boolean) => { sidePanelsState.githubConnectionsOpen = bool }, - // ID to determine which github integration installation to use - githubConnectionsIntegrationId: undefined as undefined | string, - setGithubConnectionsIntegrationId: (id: string) => { - sidePanelsState.githubConnectionsIntegrationId = id - }, }) export const getSidePanelsState = () => snapshot(sidePanelsState) From bb5108e154e22d87b7fb88f91e1adcb31140ab54 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Mon, 4 Mar 2024 16:00:00 +0800 Subject: [PATCH 31/62] Chore/foreign key management in column editor (#21683) * Support adding foreign key via ColumnEditor * Support updating/deleting foreign key from ColumnEditor --- .../TableGridEditor/GridHeaderActions.tsx | 53 +++--- .../ColumnEditor/ColumnEditor.tsx | 40 +++-- .../ColumnEditor/ColumnForeignKey.tsx | 153 ++++++++++++------ .../ForeignKeySelector/ForeignKeySelector.tsx | 34 ++-- .../SidePanelEditor/SidePanelEditor.tsx | 12 +- .../SidePanelEditor/SidePanelEditor.utils.tsx | 126 ++++++++++----- 6 files changed, 275 insertions(+), 143 deletions(-) diff --git a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index 30e35398fbc..748a8f98eaa 100644 --- a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -159,16 +159,20 @@ const GridHeaderActions = ({ table, isViewSelected, isTableSelected }: GridHeade
{policies.length < 1 ? ( - - - - + + @@ -190,23 +194,24 @@ const GridHeaderActions = ({ table, isViewSelected, isTableSelected }: GridHeade ) : ( - - - + + )}
) : ( diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx index 5a432887f5b..fd562a11a04 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx @@ -25,7 +25,10 @@ import { Constraint, useTableConstraintsQuery, } from 'data/database/constraints-query' -import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' +import { + ForeignKeyConstraint, + useForeignKeyConstraintsQuery, +} from 'data/database/foreign-key-constraints-query' import { useEnumeratedTypesQuery } from 'data/enumerated-types/enumerated-types-query' import { EXCLUDED_SCHEMAS_WITHOUT_EXTENSIONS } from 'lib/constants/schemas' import { Dictionary } from 'types' @@ -45,6 +48,7 @@ import { import ColumnForeignKey from './ColumnForeignKey' import ColumnType from './ColumnType' import HeaderTitle from './HeaderTitle' +import toast from 'react-hot-toast' export interface ColumnEditorProps { column?: PostgresColumn @@ -57,6 +61,8 @@ export interface ColumnEditorProps { configuration: { columnId?: string primaryKey?: Constraint + foreignKeyRelations: ForeignKey[] + existingForeignKeyRelations: ForeignKeyConstraint[] }, resolve: any ) => void @@ -107,6 +113,11 @@ const ColumnEditor = ({ const foreignKeys = foreignKeyMeta.filter((relation) => { return relation.source_id === column?.table_id && relation.source_columns.includes(column.name) }) + const lockColumnType = + fkRelations.find( + (fk) => + fk.columns.find((col) => col.source === columnFields?.name) !== undefined && !fk.toRemove + ) !== undefined useEffect(() => { if (visible) { @@ -147,7 +158,12 @@ const ColumnEditor = ({ const payload = isNewRecord ? generateCreateColumnPayload(selectedTable.id, columnFields) : generateUpdateColumnPayload(column!, selectedTable, columnFields) - const configuration = { columnId: column?.id, primaryKey } + const configuration = { + columnId: column?.id, + primaryKey, + foreignKeyRelations: fkRelations, + existingForeignKeyRelations: foreignKeys, + } saveChanges(payload, isNewRecord, configuration, resolve) } else { resolve() @@ -240,11 +256,9 @@ const ColumnEditor = ({ enumTypes={enumTypes} error={errors.format} description={ - columnFields.foreignKey !== undefined - ? 'Column type cannot be changed as it has a foreign key relation' - : '' + lockColumnType ? 'Column type cannot be changed as it has a foreign key relation' : '' } - disabled={columnFields.foreignKey !== undefined} + disabled={lockColumnType} onOptionSelect={(format: string) => onUpdateField({ format, defaultValue: null })} /> {columnFields.foreignKey === undefined && ( @@ -291,13 +305,13 @@ const ColumnEditor = ({ header={Foreign Keys} > -
- -
+ onUpdateField({ format, defaultValue: null })} + onUpdateFkRelations={setFkRelations} + />
diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx index 67e6cd8fcd1..d55d02e9e09 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx @@ -1,29 +1,45 @@ -import { noop } from 'lodash' -import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui' +import { useParams } from 'common' +import { useState } from 'react' +import { Button } from 'ui' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' +import useTable from 'hooks/misc/useTable' +import { ForeignKeySelector } from '../ForeignKeySelector/ForeignKeySelector' import { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' import { ColumnField } from '../SidePanelEditor.types' import { ForeignKeyRow } from '../TableEditor/ForeignKeysManagement/ForeignKeyRow' import { checkIfRelationChanged } from '../TableEditor/ForeignKeysManagement/ForeignKeysManagement.utils' -import { useTableEditorStateSnapshot } from 'state/table-editor' interface ColumnForeignKeyProps { column: ColumnField relations: ForeignKey[] closePanel: () => void + onUpdateColumnType: (type: string) => void + onUpdateFkRelations: (fks: ForeignKey[]) => void } -const ColumnForeignKey = ({ column, relations, closePanel }: ColumnForeignKeyProps) => { +const ColumnForeignKey = ({ + column, + relations, + closePanel, + onUpdateColumnType, + onUpdateFkRelations, +}: ColumnForeignKeyProps) => { + const { id: _id } = useParams() + const [open, setOpen] = useState(false) + const [selectedFk, setSelectedFk] = useState() + const { project } = useProjectContext() - const snap = useTableEditorStateSnapshot() const { data } = useForeignKeyConstraintsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, schema: column.schema, }) + const id = _id ? Number(_id) : undefined + const { data: table } = useTable(id) + const getRelationStatus = (fk: ForeignKey) => { const existingRelation = (data ?? []).find((x) => x.id === fk.id) const stateRelation = relations.find((x) => x.id === fk.id) @@ -38,53 +54,88 @@ const ColumnForeignKey = ({ column, relations, closePanel }: ColumnForeignKeyPro } return ( -
-
- {relations.map((relation) => { - const status = getRelationStatus(relation) - return ( - - ) - })} -
- - - {relations.length > 0 ? ( - <> - These are the foreign keys which the column{' '} - {column.name} is included - - ) : column.isNewColumn ? ( - <>Foreign keys can be added after creating the column - ) : ( - <> - Foreign keys which include the column {column.name}{' '} - will be shown here - - )} - - - All foreign keys on the table can be managed by editing the{' '} - - {column.schema}.{column.table} - {' '} - table. - - - -
+
+ + {table !== undefined && ( + { + setOpen(false) + setSelectedFk(undefined) + }} + onSaveRelation={(fk) => { + const existingRelationIds = relations.map((x) => x.id) + if (fk.id !== undefined && existingRelationIds.includes(fk.id)) { + onUpdateFkRelations( + relations.map((x) => { + if (x.id === fk.id) return fk + return x + }) + ) + } else { + onUpdateFkRelations(relations.concat([fk])) + } + const targetType = fk.columns.find((col) => col.source === column.name)?.targetType + if (targetType) onUpdateColumnType(targetType) + }} + /> + )} + ) } diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx index ad3ffc64479..16f0a622a9f 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx @@ -28,6 +28,7 @@ import { NUMERICAL_TYPES, TEXT_TYPES } from '../SidePanelEditor.constants' import { FOREIGN_KEY_CASCADE_OPTIONS } from './ForeignKeySelector.constants' import { ForeignKey } from './ForeignKeySelector.types' import { generateCascadeActionDescription } from './ForeignKeySelector.utils' +import { ColumnField } from '../SidePanelEditor.types' const EMPTY_STATE: ForeignKey = { id: undefined, @@ -40,7 +41,12 @@ const EMPTY_STATE: ForeignKey = { interface ForeignKeySelectorProps { visible: boolean - table: { id: number; name: string; columns: any[] } + table: { + id: number + name: string + columns: { id: string; name: string; format: string; isNewColumn: boolean }[] + } + column?: ColumnField // For ColumnEditor, to prefill when adding a new foreign key foreignKey?: ForeignKey onClose: () => void onSaveRelation: (fk: ForeignKey) => void @@ -49,6 +55,7 @@ interface ForeignKeySelectorProps { export const ForeignKeySelector = ({ visible, table, + column, foreignKey, onClose, onSaveRelation, @@ -83,17 +90,8 @@ export const ForeignKeySelector = ({ const updateSelectedTable = (tableId: number) => { setErrors({}) - if (!tableId) { - return setFk({ - ...EMPTY_STATE, - id: fk.id, - name: fk.name, - schema: fk.schema, - columns: [{ source: '', target: '' }], - }) - } const table = (tables ?? []).find((x) => x.id === tableId) - if (table) + if (table) { setFk({ ...EMPTY_STATE, id: fk.id, @@ -101,8 +99,12 @@ export const ForeignKeySelector = ({ tableId: table.id, schema: table.schema, table: table.name, - columns: [{ source: '', target: '' }], + columns: + column !== undefined + ? [{ source: column.name, target: '' }] + : [{ source: '', target: '' }], }) + } } const addColumn = () => { @@ -160,7 +162,7 @@ export const ForeignKeySelector = ({ fk.columns.forEach((column) => { const { source, target, sourceType: sType, targetType: tType } = column const sourceColumn = table.columns.find((col) => col.name === source) - const sourceType = sType ?? sourceColumn?.format + const sourceType = sType ?? sourceColumn?.format ?? '' const targetType = tType ?? selectedTable?.columns?.find((col) => col.name === target)?.format ?? '' @@ -246,6 +248,7 @@ export const ForeignKeySelector = ({ key={schema.id} value={schema.name} label={schema.name} + className="min-w-96" addOnBefore={() => } >
@@ -264,7 +267,7 @@ export const ForeignKeySelector = ({ value={selectedTable?.id ?? 1} onChange={(value: string) => updateSelectedTable(Number(value))} > - + --- {sortBy(tables, ['schema']).map((table) => { @@ -273,6 +276,7 @@ export const ForeignKeySelector = ({ key={table.id} value={table.id} label={table.name} + className="min-w-96" addOnBefore={() => } >
@@ -312,7 +316,7 @@ export const ForeignKeySelector = ({ )} {fk.columns.map((_, idx) => ( - +
{ const selectedColumnToEdit = snap.sidePanel?.type === 'column' && snap.sidePanel.column - const { columnId, primaryKey } = configuration + const { columnId, primaryKey, foreignKeyRelations, existingForeignKeyRelations } = configuration const response = isNewRecord ? await createColumn({ @@ -215,6 +220,7 @@ const SidePanelEditor = ({ payload: payload as CreateColumnPayload, selectedTable: selectedTable as PostgresTable, primaryKey, + foreignKeyRelations, }) : await updateColumn({ projectRef: project?.ref!, @@ -223,6 +229,8 @@ const SidePanelEditor = ({ payload: payload as UpdateColumnPayload, selectedTable: selectedTable as PostgresTable, primaryKey, + foreignKeyRelations, + existingForeignKeyRelations, }) if (response?.error) { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx index 0ad5c98e484..e9bf7ee13ed 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx @@ -269,12 +269,14 @@ export const createColumn = async ({ payload, selectedTable, primaryKey, + foreignKeyRelations = [], }: { projectRef: string connectionString: string | undefined payload: CreateColumnPayload selectedTable: PostgresTable primaryKey?: Constraint + foreignKeyRelations?: ForeignKey[] }) => { const toastId = toast.loading(`Creating column "${payload.name}"...`) try { @@ -311,6 +313,17 @@ export const createColumn = async ({ primaryKeyColumns ) } + + // Then add the foreign key constraints here + if (foreignKeyRelations.length > 0) { + await addForeignKey({ + projectRef, + connectionString, + table: { schema: column.schema, name: column.table }, + foreignKeys: foreignKeyRelations, + }) + } + toast.success(`Successfully created column "${column.name}"`, { id: toastId }) } catch (error: any) { toast.error(`An error occurred while creating the column "${payload.name}"`, { id: toastId }) @@ -325,6 +338,8 @@ export const updateColumn = async ({ payload, selectedTable, primaryKey, + foreignKeyRelations = [], + existingForeignKeyRelations = [], skipPKCreation, skipSuccessMessage = false, }: { @@ -334,14 +349,16 @@ export const updateColumn = async ({ payload: UpdateColumnPayload selectedTable: PostgresTable primaryKey?: Constraint + foreignKeyRelations?: ForeignKey[] + existingForeignKeyRelations?: ForeignKeyConstraint[] skipPKCreation?: boolean skipSuccessMessage?: boolean }) => { try { const { isPrimaryKey, ...formattedPayload } = payload const column = await updateDatabaseColumn({ - projectRef: projectRef, - connectionString: connectionString, + projectRef, + connectionString, id, payload: formattedPayload, }) @@ -374,6 +391,18 @@ export const updateColumn = async ({ ) } } + + // Then update foreign keys + if (foreignKeyRelations.length > 0) { + await updateForeignKeys({ + projectRef, + connectionString, + table: { schema: column.schema, name: column.table }, + foreignKeys: foreignKeyRelations, + existingForeignKeyRelations, + }) + } + if (!skipSuccessMessage) toast.success(`Successfully updated column "${column.name}"`) } catch (error: any) { return { error } @@ -762,43 +791,13 @@ export const updateTable = async ({ } // Foreign keys will get updated here accordingly - const relationsToAdd = foreignKeyRelations.filter((x) => typeof x.id === 'string') - if (relationsToAdd.length > 0) { - await addForeignKey({ - projectRef, - connectionString, - table: updatedTable, - foreignKeys: relationsToAdd, - }) - } - - const relationsToRemove = foreignKeyRelations.filter((x) => x.toRemove) - if (relationsToRemove.length > 0) { - await removeForeignKey({ - projectRef, - connectionString, - table: updatedTable, - foreignKeys: relationsToRemove, - }) - } - - const remainingRelations = foreignKeyRelations.filter( - (x) => typeof x.id === 'number' && !x.toRemove - ) - const relationsToUpdate = remainingRelations.filter((x) => { - const existingRelation = existingForeignKeyRelations.find((y) => x.id === y.id) - if (existingRelation !== undefined) { - return checkIfRelationChanged(existingRelation as unknown as ForeignKeyConstraint, x) - } else return false + await updateForeignKeys({ + projectRef, + connectionString, + table: updatedTable, + foreignKeys: foreignKeyRelations, + existingForeignKeyRelations, }) - if (relationsToUpdate.length > 0) { - await updateForeignKey({ - projectRef, - connectionString, - table: updatedTable, - foreignKeys: relationsToUpdate, - }) - } const queryClient = getQueryClient() @@ -939,3 +938,54 @@ export const insertTableRows = async ( } return { error: insertError } } + +const updateForeignKeys = async ({ + projectRef, + connectionString, + table, + foreignKeys, + existingForeignKeyRelations, +}: { + projectRef: string + connectionString?: string + table: { schema: string; name: string } + foreignKeys: ForeignKey[] + existingForeignKeyRelations: ForeignKeyConstraint[] +}) => { + // Foreign keys will get updated here accordingly + const relationsToAdd = foreignKeys.filter((x) => typeof x.id === 'string') + if (relationsToAdd.length > 0) { + await addForeignKey({ + projectRef, + connectionString, + table, + foreignKeys: relationsToAdd, + }) + } + + const relationsToRemove = foreignKeys.filter((x) => x.toRemove) + if (relationsToRemove.length > 0) { + await removeForeignKey({ + projectRef, + connectionString, + table, + foreignKeys: relationsToRemove, + }) + } + + const remainingRelations = foreignKeys.filter((x) => typeof x.id === 'number' && !x.toRemove) + const relationsToUpdate = remainingRelations.filter((x) => { + const existingRelation = existingForeignKeyRelations.find((y) => x.id === y.id) + if (existingRelation !== undefined) { + return checkIfRelationChanged(existingRelation as unknown as ForeignKeyConstraint, x) + } else return false + }) + if (relationsToUpdate.length > 0) { + await updateForeignKey({ + projectRef, + connectionString, + table, + foreignKeys: relationsToUpdate, + }) + } +} From d66c0aea2a6d1b148790fe1f72a9c8acf26f301e Mon Sep 17 00:00:00 2001 From: Chris Gwilliams <517923+encima@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:58:32 +0200 Subject: [PATCH 32/62] Add recommended disk sizes to Compute docs (#21446) --- .../guides/platform/compute-add-ons.mdx | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/apps/docs/content/guides/platform/compute-add-ons.mdx b/apps/docs/content/guides/platform/compute-add-ons.mdx index e1a7305746b..edb2412de2c 100644 --- a/apps/docs/content/guides/platform/compute-add-ons.mdx +++ b/apps/docs/content/guides/platform/compute-add-ons.mdx @@ -6,21 +6,29 @@ description: "Learn about your project's instance and additional add-ons." Every project on the Supabase Platform comes with its own dedicated Postgres instance running inside a virtual machine (VM). The following table describes the base instance with additional compute add-ons available if you need extra performance when scaling up Supabase. -| Plan | Hourly Price USD | Monthly Price USD | CPU | Memory | Connections: Direct | Connections: Pooler | -| ------ | ---------------- | ----------------- | ----------------------- | ------ | ------------------- | ------------------- | -| Micro | $0.01344 | ~$10 | 2-core ARM (shared) | 1 GB | 60 | 200 | -| Small | $0.0206 | ~$15 | 2-core ARM (shared) | 2 GB | 90 | 200 | -| Medium | $0.0822 | ~$60 | 2-core ARM (shared) | 4 GB | 120 | 200 | -| Large | $0.1517 | ~$110 | 2-core ARM (dedicated) | 8 GB | 160 | 300 | -| XL | $0.2877 | ~$210 | 4-core ARM (dedicated) | 16 GB | 240 | 700 | -| 2XL | $0.562 | ~$410 | 8-core ARM (dedicated) | 32 GB | 380 | 1500 | -| 4XL | $1.32 | ~$960 | 16-core ARM (dedicated) | 64 GB | 480 | 3000 | -| 8XL | $2.562 | ~$1,870 | 32-core ARM (dedicated) | 128 GB | 490 | 6000 | -| 12XL | $3.836 | ~$2,800 | 48-core ARM (dedicated) | 192 GB | 500 | 9000 | -| 16XL | $5.12 | ~$3,730 | 64-core ARM (dedicated) | 256 GB | 500 | 12,000 | +| Plan | Hourly Price USD | Monthly Price USD | CPU | Memory | Connections: Direct | Connections: Pooler | Recommended Maximum DB Size | +| ------ | ---------------- | ----------------- | ----------------------- | ------ | ------------------- | ------------------- | --------------------------- | +| Micro | $0.01344 | ~$10 | 2-core ARM (shared) | 1 GB | 60 | 200 | 10GB | +| Small | $0.0206 | ~$15 | 2-core ARM (shared) | 2 GB | 90 | 200 | 50GB | +| Medium | $0.0822 | ~$60 | 2-core ARM (shared) | 4 GB | 120 | 200 | 100GB | +| Large | $0.1517 | ~$110 | 2-core ARM (dedicated) | 8 GB | 160 | 300 | 200GB | +| XL | $0.2877 | ~$210 | 4-core ARM (dedicated) | 16 GB | 240 | 700 | 500GB | +| 2XL | $0.562 | ~$410 | 8-core ARM (dedicated) | 32 GB | 380 | 1500 | 1TB | +| 4XL | $1.32 | ~$960 | 16-core ARM (dedicated) | 64 GB | 480 | 3000 | 2TB | +| 8XL | $2.562 | ~$1,870 | 32-core ARM (dedicated) | 128 GB | 490 | 6000 | 4TB | +| 12XL | $3.836 | ~$2,800 | 48-core ARM (dedicated) | 192 GB | 500 | 9000 | 6TB | +| 16XL | $5.12 | ~$3,730 | 64-core ARM (dedicated) | 256 GB | 500 | 12,000 | 10TB | Number of connections above are recommended values. + + +The database sizes recommended for each instance are intended purely as a guide and recommendation to ensure performance is optimal, these sizes are not enforced. + +The performance of your database is impacted by many factors, some of them being the resources available to it or the size of the data contained within it. See the [shared responsibility model](https://supabase.com/docs/guides/platform/shared-responsibility-model) for more information. + + + We charge hourly for additional compute based on your usage. Read more about [usage-based billing for compute](/docs/guides/platform/org-based-billing#usage-based-billing-for-compute). Compute sizes can be changed in [the dashboard here by selecting your project](https://supabase.com/dashboard/project/_/settings/addons?panel=computeInstance). [Contact us](https://supabase.com/contact/enterprise) if you require a custom plan. From 520562f72ee452ad9e091df0063c7c28c4cf3805 Mon Sep 17 00:00:00 2001 From: Ivan Vasilov Date: Mon, 4 Mar 2024 11:18:15 +0100 Subject: [PATCH 33/62] fix: Better errors in SQL editor (#21696) Throw the same error instead of wrapping it and losing information like formattedError. --- apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx index 25a7f8c00cf..91fa4582592 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx @@ -26,8 +26,8 @@ import { ResizablePanelGroup, cn, } from 'ui' - import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' + import { useSqlEditMutation } from 'data/ai/sql-edit-mutation' import { useSqlGenerateMutation } from 'data/ai/sql-generate-mutation' import { useSqlTitleGenerateMutation } from 'data/ai/sql-title-mutation' @@ -329,6 +329,9 @@ const SQLEditor = () => { role: impersonatedRole, }), isRoleImpersonationEnabled: isRoleImpersonationEnabled(impersonatedRole), + handleError: (error) => { + throw error + }, }) } }, From 13cfc0abb50055ea9ada7e0ae0bd951ad38f3249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Mon, 4 Mar 2024 18:39:53 +0800 Subject: [PATCH 34/62] fix: barrel imports (#21728) Avoid importing all components via barrel files that lead to bloated bundles/chunks --- apps/studio/components/grid/SupabaseGrid.tsx | 4 +- .../grid/components/footer/Footer.tsx | 2 +- .../grid/components/footer/index.ts | 3 - .../components/footer/pagination/index.ts | 4 +- .../grid/components/grid/RowRenderer.tsx | 5 +- .../grid/components/header/Header.tsx | 6 +- .../grid/components/header/filter/index.ts | 3 +- .../grid/components/header/index.ts | 3 - .../grid/components/header/sort/index.ts | 4 +- .../grid/components/menu/RowContextMenu.tsx | 3 +- .../components/grid/components/menu/index.ts | 8 +-- apps/studio/components/grid/index.ts | 4 +- apps/studio/components/grid/query/index.ts | 3 - .../components/grid/store/reducers/index.ts | 8 +-- .../interfaces/Account/Preferences/index.ts | 18 ++---- .../components/interfaces/Account/index.ts | 12 ++-- .../interfaces/App/FeaturePreview/index.ts | 4 -- .../studio/components/interfaces/App/index.ts | 8 +-- .../components/interfaces/AuditLogs/index.ts | 6 +- .../Auth/EmailTemplates/TemplateEditor.tsx | 2 +- .../components/interfaces/Auth/Users/index.ts | 3 +- .../components/interfaces/Auth/index.tsx | 21 ++----- .../Billing/Usage/UsageWarningAlerts/index.ts | 8 +-- .../interfaces/Database/Backups/PITR/index.ts | 6 +- .../Database/Indexes/CreateIndexSidePanel.tsx | 2 +- .../interfaces/Database/Indexes/Indexes.tsx | 2 +- .../Database/Migrations/Migrations.tsx | 2 +- .../Publications/PublicationsTables.tsx | 4 +- .../Database/Wrappers/EditWrapper.tsx | 2 +- .../components/interfaces/Database/index.ts | 48 +++++----------- .../components/interfaces/Docs/index.ts | 8 +-- .../components/interfaces/Functions/index.ts | 10 ++-- .../interfaces/Home/ProjectList/index.ts | 4 +- .../components/interfaces/Home/index.ts | 8 +-- .../Organization/NewProject/index.ts | 8 +-- .../interfaces/Organization/index.ts | 33 ++++------- .../ProjectAPIDocs/Content/index.ts | 36 ++++-------- .../Realtime/Inspector/SendMessageModal.tsx | 2 +- .../components/interfaces/Reports/Reports.tsx | 2 +- .../interfaces/Settings/Database/index.ts | 8 +-- .../General/Infrastructure/Infrastructure.tsx | 2 +- .../ProjectUpgradeAlert/index.ts | 3 +- .../interfaces/Settings/General/index.ts | 24 +++----- .../Infrastructure/InfrastructureInfo.tsx | 2 +- .../interfaces/Settings/Logs/LogSelection.tsx | 4 +- .../interfaces/Settings/Vault/index.ts | 10 ++-- .../RowEditor/DateTimeInput/index.ts | 4 +- .../ForeignRowSelector/ForeignRowSelector.tsx | 4 +- .../SidePanelEditor/RowEditor/InputField.tsx | 2 +- .../JsonEditor/DrilldownViewer/index.ts | 4 +- .../RowEditor/JsonEditor/JsonEditor.tsx | 2 +- .../RowEditor/JsonEditor/index.ts | 4 +- .../SidePanelEditor/RowEditor/RowEditor.tsx | 4 +- .../SidePanelEditor/SidePanelEditor.tsx | 4 +- .../TableGridEditor/SidePanelEditor/index.ts | 13 ++--- .../TableGridEditor/TableDefinition.tsx | 2 +- .../TableGridEditor/TableGridEditor.tsx | 6 +- .../interfaces/TableGridEditor/index.ts | 9 +-- apps/studio/components/interfaces/index.ts | 5 -- .../layouts/AccountLayout/WithSidebar.tsx | 2 +- .../layouts/AppLayout/AppHeader.tsx | 2 +- .../layouts/AuthLayout/AuthLayout.tsx | 4 +- .../components/layouts/BillingLayout.tsx | 6 +- .../layouts/DatabaseLayout/DatabaseLayout.tsx | 4 +- .../layouts/DocsLayout/DocsLayout.tsx | 4 +- .../components/layouts/FunctionsLayout.tsx | 2 +- .../layouts/LogsLayout/LogsLayout.tsx | 4 +- .../LayoutHeader/FeedbackDropdown/index.ts | 4 +- .../LayoutHeader/LayoutHeader.tsx | 2 +- .../ProjectLayout/LayoutHeader/index.ts | 4 +- .../layouts/ProjectLayout/ProjectLayout.tsx | 8 +-- .../ProjectLayout/UpgradingState/index.ts | 3 +- .../ProjectSettingsLayout/SettingsLayout.tsx | 4 +- .../layouts/RealtimeLayout/RealtimeLayout.tsx | 4 +- .../layouts/ReportsLayout/ReportsLayout.tsx | 2 +- .../SQLEditorLayout/SQLEditorLayout.tsx | 2 +- .../layouts/StorageLayout/StorageLayout.tsx | 2 +- .../TableEditorLayout/TableEditorLayout.tsx | 2 +- .../components/layouts/WizardLayout.tsx | 2 +- apps/studio/components/layouts/index.ts | 57 ++++++------------- .../components/to-be-cleaned/Storage/index.ts | 10 ++-- .../components/ui/CodeEditor/CodeEditor.tsx | 4 +- apps/studio/components/ui/CodeEditor/index.ts | 3 +- apps/studio/components/ui/Loading/Loading.tsx | 3 - apps/studio/components/ui/Loading/index.ts | 4 +- .../studio/components/ui/ProductMenu/index.ts | 3 +- .../table-rows/table-row-create-mutation.ts | 2 +- apps/studio/pages/_app.tsx | 6 +- apps/studio/pages/cli/login.tsx | 4 +- apps/studio/pages/new/[slug].tsx | 2 +- apps/studio/pages/org/[slug]/apps.tsx | 2 +- apps/studio/pages/org/[slug]/audit.tsx | 2 +- apps/studio/pages/org/[slug]/billing.tsx | 2 +- apps/studio/pages/org/[slug]/general.tsx | 2 +- apps/studio/pages/org/[slug]/invoices.tsx | 2 +- apps/studio/pages/org/[slug]/team.tsx | 2 +- apps/studio/pages/org/[slug]/usage.tsx | 2 +- .../pages/project/[ref]/api/graphiql.tsx | 4 +- .../pages/project/[ref]/auth/providers.tsx | 2 +- .../pages/project/[ref]/auth/templates.tsx | 2 +- .../studio/pages/project/[ref]/auth/users.tsx | 2 +- apps/studio/pages/project/[ref]/branches.tsx | 2 +- apps/studio/pages/project/[ref]/building.tsx | 2 +- .../pages/project/[ref]/editor/[id].tsx | 2 +- apps/studio/pages/project/[ref]/index.tsx | 2 +- .../project/[ref]/logs/explorer/index.tsx | 2 +- .../pages/project/[ref]/logs/pooler-logs.tsx | 4 +- .../pages/project/[ref]/reports/index.tsx | 2 +- .../pages/project/_/[[...routeSlug]].tsx | 2 +- apps/studio/pages/projects.tsx | 6 +- apps/studio/pages/sign-in-mfa.tsx | 2 +- apps/studio/pages/vercel/integrate.tsx | 2 +- apps/studio/pages/vercel/setupProject.tsx | 2 +- 113 files changed, 237 insertions(+), 417 deletions(-) delete mode 100644 apps/studio/components/grid/components/footer/index.ts delete mode 100644 apps/studio/components/grid/components/header/index.ts delete mode 100644 apps/studio/components/grid/query/index.ts delete mode 100644 apps/studio/components/interfaces/App/FeaturePreview/index.ts delete mode 100644 apps/studio/components/interfaces/index.ts delete mode 100644 apps/studio/components/ui/Loading/Loading.tsx diff --git a/apps/studio/components/grid/SupabaseGrid.tsx b/apps/studio/components/grid/SupabaseGrid.tsx index 6591f8e7e1a..a2e4d95132c 100644 --- a/apps/studio/components/grid/SupabaseGrid.tsx +++ b/apps/studio/components/grid/SupabaseGrid.tsx @@ -18,9 +18,9 @@ import { saveStorageDebounced, } from './SupabaseGrid.utils' import { Shortcuts } from './components/common' -import Footer from './components/footer' +import Footer from './components/footer/Footer' import { Grid } from './components/grid' -import Header from './components/header' +import Header from './components/header/Header' import { RowContextMenu } from './components/menu' import { StoreProvider, useDispatch, useTrackedState } from './store' import { SupabaseGridProps } from './types' diff --git a/apps/studio/components/grid/components/footer/Footer.tsx b/apps/studio/components/grid/components/footer/Footer.tsx index dad7a782cc3..daa98099f67 100644 --- a/apps/studio/components/grid/components/footer/Footer.tsx +++ b/apps/studio/components/grid/components/footer/Footer.tsx @@ -1,4 +1,4 @@ -import Pagination from './pagination' +import { Pagination } from './pagination' import useTable from 'hooks/misc/useTable' import { useParams } from 'common' import TwoOptionToggle from 'components/ui/TwoOptionToggle' diff --git a/apps/studio/components/grid/components/footer/index.ts b/apps/studio/components/grid/components/footer/index.ts deleted file mode 100644 index 9c7e8318339..00000000000 --- a/apps/studio/components/grid/components/footer/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Footer from './Footer' - -export default Footer diff --git a/apps/studio/components/grid/components/footer/pagination/index.ts b/apps/studio/components/grid/components/footer/pagination/index.ts index 1466412190c..1b98eba6044 100644 --- a/apps/studio/components/grid/components/footer/pagination/index.ts +++ b/apps/studio/components/grid/components/footer/pagination/index.ts @@ -1,3 +1 @@ -import Pagination from './Pagination' - -export default Pagination +export { default as Pagination } from './Pagination' diff --git a/apps/studio/components/grid/components/grid/RowRenderer.tsx b/apps/studio/components/grid/components/grid/RowRenderer.tsx index f8e01b894e4..12df5f412a2 100644 --- a/apps/studio/components/grid/components/grid/RowRenderer.tsx +++ b/apps/studio/components/grid/components/grid/RowRenderer.tsx @@ -1,16 +1,15 @@ import { Key } from 'react' import { TriggerEvent, useContextMenu } from 'react-contexify' import { Row, RenderRowProps } from 'react-data-grid' -import { MENU_IDS } from '../menu' import { SupaRow } from '../../types' +import { ROW_CONTEXT_MENU_ID } from '../menu' export default function RowRenderer(key: Key, props: RenderRowProps) { const { show: showContextMenu } = useContextMenu() function displayMenu(e: TriggerEvent) { - const menuId = MENU_IDS.ROW_CONTEXT_MENU_ID showContextMenu(e, { - id: menuId, + id: ROW_CONTEXT_MENU_ID, props: { rowIdx: props.rowIdx }, }) } diff --git a/apps/studio/components/grid/components/header/Header.tsx b/apps/studio/components/grid/components/header/Header.tsx index 20fd4b3e0b8..b4d786f212f 100644 --- a/apps/studio/components/grid/components/header/Header.tsx +++ b/apps/studio/components/grid/components/header/Header.tsx @@ -32,8 +32,8 @@ import { cn, } from 'ui' -import FilterDropdown from './filter' -import SortPopover from './sort' +import { FilterPopover } from './filter' +import { SortPopover } from './sort' // [Joshen] CSV exports require this guard as a fail-safe if the table is // just too large for a browser to keep all the rows in memory before @@ -120,7 +120,7 @@ const DefaultHeader = ({ return (
- +
{canAddNew && ( diff --git a/apps/studio/components/grid/components/header/filter/index.ts b/apps/studio/components/grid/components/header/filter/index.ts index 077fcde392d..bf987dfacf3 100644 --- a/apps/studio/components/grid/components/header/filter/index.ts +++ b/apps/studio/components/grid/components/header/filter/index.ts @@ -1,4 +1,3 @@ -import FilterPopover from './FilterPopover' +export { default as FilterPopover } from './FilterPopover' export * from './Filter.constants' -export default FilterPopover diff --git a/apps/studio/components/grid/components/header/index.ts b/apps/studio/components/grid/components/header/index.ts deleted file mode 100644 index 7cd29d7abd0..00000000000 --- a/apps/studio/components/grid/components/header/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Header from './Header' - -export default Header diff --git a/apps/studio/components/grid/components/header/sort/index.ts b/apps/studio/components/grid/components/header/sort/index.ts index f3f0e9d2821..8f4094016a6 100644 --- a/apps/studio/components/grid/components/header/sort/index.ts +++ b/apps/studio/components/grid/components/header/sort/index.ts @@ -1,3 +1 @@ -import SortPopover from './SortPopover' - -export default SortPopover +export { default as SortPopover } from './SortPopover' diff --git a/apps/studio/components/grid/components/menu/RowContextMenu.tsx b/apps/studio/components/grid/components/menu/RowContextMenu.tsx index 879181b81ef..196417110e9 100644 --- a/apps/studio/components/grid/components/menu/RowContextMenu.tsx +++ b/apps/studio/components/grid/components/menu/RowContextMenu.tsx @@ -6,8 +6,7 @@ import { useCallback } from 'react' import { useTableEditorStateSnapshot } from 'state/table-editor' import { useTrackedState } from '../../store' import { copyToClipboard, formatClipboardValue } from '../../utils' - -export const ROW_CONTEXT_MENU_ID = 'row-context-menu-id' +import { ROW_CONTEXT_MENU_ID } from '.' export type RowContextMenuProps = { rows: SupaRow[] diff --git a/apps/studio/components/grid/components/menu/index.ts b/apps/studio/components/grid/components/menu/index.ts index f16e1e45345..d205906f811 100644 --- a/apps/studio/components/grid/components/menu/index.ts +++ b/apps/studio/components/grid/components/menu/index.ts @@ -1,6 +1,4 @@ -import ColumnMenu from './ColumnMenu' -import RowContextMenu, { ROW_CONTEXT_MENU_ID } from './RowContextMenu' +export { default as ColumnMenu } from './ColumnMenu' +export { default as RowContextMenu } from './RowContextMenu' -const MENU_IDS = { ROW_CONTEXT_MENU_ID } - -export { ColumnMenu, RowContextMenu, MENU_IDS } +export const ROW_CONTEXT_MENU_ID = 'row-context-menu-id' diff --git a/apps/studio/components/grid/index.ts b/apps/studio/components/grid/index.ts index c6ed6766a7b..2074ff98607 100644 --- a/apps/studio/components/grid/index.ts +++ b/apps/studio/components/grid/index.ts @@ -2,6 +2,4 @@ export * from './SupabaseGrid' export { parseSupaTable } from './SupabaseGrid.utils' export * from './types' -import Query from './query' - -export { Query } +export { Query } from './query/Query' diff --git a/apps/studio/components/grid/query/index.ts b/apps/studio/components/grid/query/index.ts deleted file mode 100644 index 7a974c2c7ed..00000000000 --- a/apps/studio/components/grid/query/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { Query } from './Query' - -export default Query diff --git a/apps/studio/components/grid/store/reducers/index.ts b/apps/studio/components/grid/store/reducers/index.ts index 70a87f684e3..cdb8fc5e993 100644 --- a/apps/studio/components/grid/store/reducers/index.ts +++ b/apps/studio/components/grid/store/reducers/index.ts @@ -1,7 +1,7 @@ -import BaseReducer, { BaseInitialState, baseInitialState } from './base' -import CallbackReducer, { CallbackInitialState, callbackInitialState } from './callback' -import ColumnReducer, { ColumnInitialState, columnInitialState } from './column' -import RowReducer, { RowInitialState, rowInitialState } from './row' +import BaseReducer, { type BaseInitialState, baseInitialState } from './base' +import CallbackReducer, { type CallbackInitialState, callbackInitialState } from './callback' +import ColumnReducer, { type ColumnInitialState, columnInitialState } from './column' +import RowReducer, { type RowInitialState, rowInitialState } from './row' export interface InitialStateType extends BaseInitialState, diff --git a/apps/studio/components/interfaces/Account/Preferences/index.ts b/apps/studio/components/interfaces/Account/Preferences/index.ts index 3da36a706fe..73078697650 100644 --- a/apps/studio/components/interfaces/Account/Preferences/index.ts +++ b/apps/studio/components/interfaces/Account/Preferences/index.ts @@ -1,13 +1,5 @@ -import AccountInformation from './AccountInformation' -import AnalyticsSettings from './AnalyticsSettings' -import ThemeSettingsOld from './ThemeSettingsOld' -import ThemeSettings from './ThemeSettings' -import ThemeSettingsWithPreferredTheme from './ThemeSettingsWithPreferredTheme' - -export { - AccountInformation, - AnalyticsSettings, - ThemeSettingsOld, - ThemeSettings, - ThemeSettingsWithPreferredTheme, -} +export { default as AccountInformation } from './AccountInformation' +export { default as AnalyticsSettings } from './AnalyticsSettings' +export { default as ThemeSettingsOld } from './ThemeSettingsOld' +export { default as ThemeSettings } from './ThemeSettings' +export { default as ThemeSettingsWithPreferredTheme } from './ThemeSettingsWithPreferredTheme' diff --git a/apps/studio/components/interfaces/Account/index.ts b/apps/studio/components/interfaces/Account/index.ts index 82ff3116897..76959ae88fc 100644 --- a/apps/studio/components/interfaces/Account/index.ts +++ b/apps/studio/components/interfaces/Account/index.ts @@ -1,7 +1,5 @@ -import AccessTokenList from './AccessTokenList' -import AuditLogs from './AuditLogs' -import NewAccessTokenButton from './NewAccessTokenButton' -import NewTokenBanner from './NewTokenBanner' -import TOTPFactors from './TOTPFactors' - -export { AccessTokenList, NewTokenBanner, NewAccessTokenButton, TOTPFactors, AuditLogs } +export { default as AccessTokenList } from './AccessTokenList' +export { default as AuditLogs } from './AuditLogs' +export { default as NewAccessTokenButton } from './NewAccessTokenButton' +export { default as NewTokenBanner } from './NewTokenBanner' +export { default as TOTPFactors } from './TOTPFactors' diff --git a/apps/studio/components/interfaces/App/FeaturePreview/index.ts b/apps/studio/components/interfaces/App/FeaturePreview/index.ts deleted file mode 100644 index bf36ec23b7a..00000000000 --- a/apps/studio/components/interfaces/App/FeaturePreview/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { FeaturePreviewContextProvider } from './FeaturePreviewContext' -import FeaturePreviewModal from './FeaturePreviewModal' - -export { FeaturePreviewContextProvider, FeaturePreviewModal } diff --git a/apps/studio/components/interfaces/App/index.ts b/apps/studio/components/interfaces/App/index.ts index a919142ae20..885f516f42e 100644 --- a/apps/studio/components/interfaces/App/index.ts +++ b/apps/studio/components/interfaces/App/index.ts @@ -1,5 +1,3 @@ -import AppBannerWrapper from './AppBannerWrapper' -import CommandMenuWrapper from './CommandMenuWrapper' -import RouteValidationWrapper from './RouteValidationWrapper' - -export { AppBannerWrapper, CommandMenuWrapper, RouteValidationWrapper } +export { default as AppBannerWrapper } from './AppBannerWrapper' +export { default as CommandMenuWrapper } from './CommandMenuWrapper' +export { default as RouteValidationWrapper } from './RouteValidationWrapper' diff --git a/apps/studio/components/interfaces/AuditLogs/index.ts b/apps/studio/components/interfaces/AuditLogs/index.ts index d54f1b5d120..082c6e83fde 100644 --- a/apps/studio/components/interfaces/AuditLogs/index.ts +++ b/apps/studio/components/interfaces/AuditLogs/index.ts @@ -1,4 +1,2 @@ -import FilterPopover from './FilterPopover' -import LogDetailsPanel from './LogDetailsPanel' - -export { FilterPopover, LogDetailsPanel } +export { default as FilterPopover } from './FilterPopover' +export { default as LogDetailsPanel } from './LogDetailsPanel' diff --git a/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx b/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx index d43a845da55..21fa7bcdd8d 100644 --- a/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx +++ b/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx @@ -13,7 +13,7 @@ import { AlertTitle_Shadcn_, } from 'ui' -import CodeEditor from 'components/ui/CodeEditor' +import { CodeEditor } from 'components/ui/CodeEditor' import { FormActions, FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms' import InformationBox from 'components/ui/InformationBox' diff --git a/apps/studio/components/interfaces/Auth/Users/index.ts b/apps/studio/components/interfaces/Auth/Users/index.ts index 07ac15a15a9..f868a0efc51 100644 --- a/apps/studio/components/interfaces/Auth/Users/index.ts +++ b/apps/studio/components/interfaces/Auth/Users/index.ts @@ -1,2 +1 @@ -import Users from './Users' -export default Users +export { default as Users } from './Users' diff --git a/apps/studio/components/interfaces/Auth/index.tsx b/apps/studio/components/interfaces/Auth/index.tsx index d46e9f7a642..96f04d7eee5 100644 --- a/apps/studio/components/interfaces/Auth/index.tsx +++ b/apps/studio/components/interfaces/Auth/index.tsx @@ -1,16 +1,5 @@ -import AuthProvidersForm from './AuthProvidersForm/AuthProvidersForm' -import EmailTemplates from './EmailTemplates/EmailTemplates' -import SmtpForm from './SmtpForm/SmtpForm' -import BasicAuthSettingsForm from './BasicAuthSettingsForm/BasicAuthSettingsForm' -import AdvancedAuthSettingsForm from './AdvancedAuthSettingsForm/AdvancedAuthSettingsForm' - -import Users from './Users' - -export { - Users, - AuthProvidersForm, - EmailTemplates, - SmtpForm, - BasicAuthSettingsForm, - AdvancedAuthSettingsForm, -} +export { default as AuthProvidersForm } from './AuthProvidersForm/AuthProvidersForm' +export { default as EmailTemplates } from './EmailTemplates/EmailTemplates' +export { default as SmtpForm } from './SmtpForm/SmtpForm' +export { default as BasicAuthSettingsForm } from './BasicAuthSettingsForm/BasicAuthSettingsForm' +export { default as AdvancedAuthSettingsForm } from './AdvancedAuthSettingsForm/AdvancedAuthSettingsForm' diff --git a/apps/studio/components/interfaces/Billing/Usage/UsageWarningAlerts/index.ts b/apps/studio/components/interfaces/Billing/Usage/UsageWarningAlerts/index.ts index 3b3afe3f30e..37d339b8dc3 100644 --- a/apps/studio/components/interfaces/Billing/Usage/UsageWarningAlerts/index.ts +++ b/apps/studio/components/interfaces/Billing/Usage/UsageWarningAlerts/index.ts @@ -1,5 +1,3 @@ -import CPUWarnings from './CPUWarnings' -import DiskIOBandwidthWarnings from './DiskIOBandwidthWarnings' -import RAMWarnings from './RAMWarnings' - -export { CPUWarnings, DiskIOBandwidthWarnings, RAMWarnings } +export { default as CPUWarnings } from './CPUWarnings' +export { default as DiskIOBandwidthWarnings } from './DiskIOBandwidthWarnings' +export { default as RAMWarnings } from './RAMWarnings' diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/index.ts b/apps/studio/components/interfaces/Database/Backups/PITR/index.ts index 2b24fb9939f..44f7453d8fa 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/index.ts +++ b/apps/studio/components/interfaces/Database/Backups/PITR/index.ts @@ -1,4 +1,2 @@ -import PITRNotice from './PITRNotice' -import PITRSelection from './PITRSelection' - -export { PITRNotice, PITRSelection } +export { default as PITRNotice } from './PITRNotice' +export { default as PITRSelection } from './PITRSelection' diff --git a/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx b/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx index c1af6223d8e..3a8f270b5fd 100644 --- a/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx +++ b/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx @@ -3,7 +3,7 @@ import { useEffect, useMemo, useState } from 'react' import { Button, Input, Listbox, SidePanel } from 'ui' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import CodeEditor from 'components/ui/CodeEditor' +import { CodeEditor } from 'components/ui/CodeEditor' import MultiSelect, { MultiSelectOption } from 'components/ui/MultiSelect' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useIndexesQuery } from 'data/database/indexes-query' diff --git a/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx b/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx index 3aec38f65f5..d484b737872 100644 --- a/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx +++ b/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx @@ -19,7 +19,7 @@ import { import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' -import CodeEditor from 'components/ui/CodeEditor' +import { CodeEditor } from 'components/ui/CodeEditor' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import SchemaSelector from 'components/ui/SchemaSelector' import ShimmeringLoader, { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' diff --git a/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx b/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx index 994c246adfc..66154aec7d0 100644 --- a/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx +++ b/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx @@ -6,7 +6,7 @@ import { Alert, Button, IconExternalLink, IconSearch, Input, SidePanel } from 'u import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' -import CodeEditor from 'components/ui/CodeEditor' +import { CodeEditor } from 'components/ui/CodeEditor' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { DatabaseMigration, useMigrationsQuery } from 'data/database/migrations-query' import MigrationsEmptyState from './MigrationsEmptyState' diff --git a/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx b/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx index 2365eb1c034..a01f921bfdf 100644 --- a/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx +++ b/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx @@ -7,7 +7,7 @@ import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import InformationBox from 'components/ui/InformationBox' -import Connecting from 'components/ui/Loading/Loading' +import { Loading } from 'components/ui/Loading' import { useTablesQuery } from 'data/tables/tables-query' import { useCheckPermissions } from 'hooks' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' @@ -83,7 +83,7 @@ const PublicationsTables = ({ selectedPublication, onSelectBack }: PublicationsT
{isLoading && (
- +
)} diff --git a/apps/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx b/apps/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx index b14aef512c2..9048a20ae2c 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx +++ b/apps/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx @@ -16,7 +16,7 @@ import { FormSectionContent, FormSectionLabel, } from 'components/ui/Forms' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { invalidateSchemasQuery } from 'data/database/schemas-query' import { useFDWUpdateMutation } from 'data/fdw/fdw-update-mutation' import { useFDWsQuery } from 'data/fdw/fdws-query' diff --git a/apps/studio/components/interfaces/Database/index.ts b/apps/studio/components/interfaces/Database/index.ts index 46eb0254b69..793792801c0 100644 --- a/apps/studio/components/interfaces/Database/index.ts +++ b/apps/studio/components/interfaces/Database/index.ts @@ -1,41 +1,23 @@ -import ColumnList from './Tables/ColumnList' -import TableList from './Tables/TableList' +export { default as ColumnList } from './Tables/ColumnList' +export { default as TableList } from './Tables/TableList' -import RolesList from './Roles/RolesList' +export { default as RolesList } from './Roles/RolesList' -import Extensions from './Extensions/Extensions' +export { default as Extensions } from './Extensions/Extensions' -import CreateWrapper from './Wrappers/CreateWrapper' -import EditWrapper from './Wrappers/EditWrapper' -import Wrappers from './Wrappers/Wrappers' +export { default as CreateWrapper } from './Wrappers/CreateWrapper' +export { default as EditWrapper } from './Wrappers/EditWrapper' +export { default as Wrappers } from './Wrappers/Wrappers' -import PublicationsList from './Publications/PublicationsList' -import PublicationsTables from './Publications/PublicationsTables' +export { default as PublicationsList } from './Publications/PublicationsList' +export { default as PublicationsTables } from './Publications/PublicationsTables' -import BackupsList from './Backups/BackupsList' +export { default as BackupsList } from './Backups/BackupsList' -import CreateTrigger from './Triggers/CreateTrigger' -import DeleteTrigger from './Triggers/DeleteTrigger' +export { default as CreateTrigger } from './Triggers/CreateTrigger' +export { default as DeleteTrigger } from './Triggers/DeleteTrigger' -import CreateFunction from './Functions/CreateFunction' -import DeleteFunction from './Functions/DeleteFunction' +export { default as CreateFunction } from './Functions/CreateFunction' +export { default as DeleteFunction } from './Functions/DeleteFunction' -import EnumeratedTypes from './EnumeratedTypes/EnumeratedTypes' - -export { - BackupsList, - ColumnList, - CreateFunction, - CreateTrigger, - CreateWrapper, - DeleteFunction, - DeleteTrigger, - EditWrapper, - EnumeratedTypes, - Extensions, - PublicationsList, - PublicationsTables, - RolesList, - TableList, - Wrappers, -} +export { default as EnumeratedTypes } from './EnumeratedTypes/EnumeratedTypes' diff --git a/apps/studio/components/interfaces/Docs/index.ts b/apps/studio/components/interfaces/Docs/index.ts index 8eaff962f84..c0e0dc2ccfe 100644 --- a/apps/studio/components/interfaces/Docs/index.ts +++ b/apps/studio/components/interfaces/Docs/index.ts @@ -1,5 +1,3 @@ -import GeneralContent from './GeneralContent' -import ResourceContent from './ResourceContent' -import RpcContent from './RpcContent' - -export { GeneralContent, ResourceContent, RpcContent } +export { default as GeneralContent } from './GeneralContent' +export { default as ResourceContent } from './ResourceContent' +export { default as RpcContent } from './RpcContent' diff --git a/apps/studio/components/interfaces/Functions/index.ts b/apps/studio/components/interfaces/Functions/index.ts index 992b396e1be..e90c28a844a 100644 --- a/apps/studio/components/interfaces/Functions/index.ts +++ b/apps/studio/components/interfaces/Functions/index.ts @@ -1,6 +1,4 @@ -import EdgeFunctionDetails from './EdgeFunctionDetails/EdgeFunctionDetails' -import EdgeFunctionsListItem from './EdgeFunctionsListItem' -import FunctionsEmptyState from './FunctionsEmptyState' -import TerminalInstructions from './TerminalInstructions' - -export { EdgeFunctionDetails, EdgeFunctionsListItem, FunctionsEmptyState, TerminalInstructions } +export { default as EdgeFunctionDetails } from './EdgeFunctionDetails/EdgeFunctionDetails' +export { default as EdgeFunctionsListItem } from './EdgeFunctionsListItem' +export { default as FunctionsEmptyState } from './FunctionsEmptyState' +export { default as TerminalInstructions } from './TerminalInstructions' diff --git a/apps/studio/components/interfaces/Home/ProjectList/index.ts b/apps/studio/components/interfaces/Home/ProjectList/index.ts index 238e6186c32..48c2789ec2c 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/index.ts +++ b/apps/studio/components/interfaces/Home/ProjectList/index.ts @@ -1,3 +1 @@ -import ProjectList from './ProjectList' - -export default ProjectList +export { default as ProjectList } from './ProjectList' diff --git a/apps/studio/components/interfaces/Home/index.ts b/apps/studio/components/interfaces/Home/index.ts index 229677cb889..003fa0a4159 100644 --- a/apps/studio/components/interfaces/Home/index.ts +++ b/apps/studio/components/interfaces/Home/index.ts @@ -1,5 +1,3 @@ -import ClientLibrary from './ClientLibrary' -import ExampleProject from './ExampleProject' -import NewProjectPanel from './NewProjectPanel/NewProjectPanel' - -export { ClientLibrary, ExampleProject, NewProjectPanel } +export { default as ClientLibrary } from './ClientLibrary' +export { default as ExampleProject } from './ExampleProject' +export { default as NewProjectPanel } from './NewProjectPanel/NewProjectPanel' diff --git a/apps/studio/components/interfaces/Organization/NewProject/index.ts b/apps/studio/components/interfaces/Organization/NewProject/index.ts index 38f93a6cd6b..0b4cb8f09e7 100644 --- a/apps/studio/components/interfaces/Organization/NewProject/index.ts +++ b/apps/studio/components/interfaces/Organization/NewProject/index.ts @@ -1,5 +1,3 @@ -import NotOrganizationOwnerWarning from './NotOrganizationOwnerWarning' -import FreeProjectLimitWarning from './FreeProjectLimitWarning' -import EmptyPaymentMethodWarning from './EmptyPaymentMethodWarning' - -export { NotOrganizationOwnerWarning, FreeProjectLimitWarning, EmptyPaymentMethodWarning } +export { default as NotOrganizationOwnerWarning } from './NotOrganizationOwnerWarning' +export { default as FreeProjectLimitWarning } from './FreeProjectLimitWarning' +export { default as EmptyPaymentMethodWarning } from './EmptyPaymentMethodWarning' diff --git a/apps/studio/components/interfaces/Organization/index.ts b/apps/studio/components/interfaces/Organization/index.ts index d98a1842db3..a48f73b8f58 100644 --- a/apps/studio/components/interfaces/Organization/index.ts +++ b/apps/studio/components/interfaces/Organization/index.ts @@ -1,23 +1,10 @@ -import BillingSettings from './BillingSettings/BillingSettings' -import GeneralSettings from './GeneralSettings/GeneralSettings' -import IntegrationSettings from './IntegrationSettings/IntegrationSettings' -import InvoicesSettings from './InvoicesSettings/InvoicesSettings' -import NewOrgForm from './NewOrg/NewOrgForm' -import Usage from './Usage/Usage' -import AuditLogs from './AuditLogs/AuditLogs' -import OAuthApps from './OAuthApps/OAuthApps' -import TeamSettings from './TeamSettings/TeamSettings' -import Documents from './Documents/Documents' - -export { - BillingSettings, - GeneralSettings, - IntegrationSettings, - InvoicesSettings, - NewOrgForm, - OAuthApps, - AuditLogs, - TeamSettings, - Usage, - Documents, -} +export { default as BillingSettings } from './BillingSettings/BillingSettings' +export { default as GeneralSettings } from './GeneralSettings/GeneralSettings' +export { default as IntegrationSettings } from './IntegrationSettings/IntegrationSettings' +export { default as InvoicesSettings } from './InvoicesSettings/InvoicesSettings' +export { default as NewOrgForm } from './NewOrg/NewOrgForm' +export { default as Usage } from './Usage/Usage' +export { default as AuditLogs } from './AuditLogs/AuditLogs' +export { default as OAuthApps } from './OAuthApps/OAuthApps' +export { default as TeamSettings } from './TeamSettings/TeamSettings' +export { default as Documents } from './Documents/Documents' diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/index.ts b/apps/studio/components/interfaces/ProjectAPIDocs/Content/index.ts index 7b2e4fe7d59..1c409fd4c65 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/index.ts +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/index.ts @@ -1,26 +1,12 @@ -import EdgeFunctions from './EdgeFunctions' -import Entities from './Entities' -import Introduction from './Introduction' -import Realtime from './Realtime' -import Storage from './Storage' -import StoredProcedures from './StoredProcedures' -import UserManagement from './UserManagement' +export { default as EdgeFunctions } from './EdgeFunctions' +export { default as Entities } from './Entities' +export { default as Introduction } from './Introduction' +export { default as Realtime } from './Realtime' +export { default as Storage } from './Storage' +export { default as StoredProcedures } from './StoredProcedures' +export { default as UserManagement } from './UserManagement' -import Bucket from './Bucket' -import EdgeFunction from './EdgeFunction' -import Entity from './Entity' -import RPC from './RPC' - -export { - Bucket, - EdgeFunction, - EdgeFunctions, - Entities, - Entity, - Introduction, - RPC, - Realtime, - Storage, - StoredProcedures, - UserManagement, -} +export { default as Bucket } from './Bucket' +export { default as EdgeFunction } from './EdgeFunction' +export { default as Entity } from './Entity' +export { default as RPC } from './RPC' diff --git a/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx b/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx index d2fcd857869..00dfb8a95e2 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/SendMessageModal.tsx @@ -1,6 +1,6 @@ import { Input, Modal } from 'ui' -import CodeEditor from 'components/ui/CodeEditor' +import { CodeEditor } from 'components/ui/CodeEditor' import { useEffect, useState } from 'react' import { tryParseJson } from 'lib/helpers' diff --git a/apps/studio/components/interfaces/Reports/Reports.tsx b/apps/studio/components/interfaces/Reports/Reports.tsx index e9b04020e8a..541acc09ae3 100644 --- a/apps/studio/components/interfaces/Reports/Reports.tsx +++ b/apps/studio/components/interfaces/Reports/Reports.tsx @@ -24,7 +24,7 @@ import { import { useParams } from 'common/hooks' import DateRangePicker from 'components/to-be-cleaned/DateRangePicker' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, useIsFeatureEnabled } from 'hooks' import { METRICS, METRIC_CATEGORIES, TIME_PERIODS_REPORTS } from 'lib/constants/metrics' diff --git a/apps/studio/components/interfaces/Settings/Database/index.ts b/apps/studio/components/interfaces/Settings/Database/index.ts index 4e13e0f7952..5ebdf805c64 100644 --- a/apps/studio/components/interfaces/Settings/Database/index.ts +++ b/apps/studio/components/interfaces/Settings/Database/index.ts @@ -1,5 +1,3 @@ -import { ConnectionPooling } from './ConnectionPooling/ConnectionPooling' -import NetworkRestrictions from './NetworkRestrictions/NetworkRestrictions' -import DatabaseSettings from './DatabaseSettings/DatabaseSettings' - -export { ConnectionPooling, DatabaseSettings, NetworkRestrictions } +export { ConnectionPooling } from './ConnectionPooling/ConnectionPooling' +export { default as NetworkRestrictions } from './NetworkRestrictions/NetworkRestrictions' +export { default as DatabaseSettings } from './DatabaseSettings/DatabaseSettings' diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx index df601a1124c..9465ba008b7 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/Infrastructure.tsx @@ -16,7 +16,7 @@ import { useProjectUpgradeEligibilityQuery } from 'data/config/project-upgrade-e import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useSelectedOrganization } from 'hooks' import PauseProjectButton from './PauseProjectButton' -import ProjectUpgradeAlert from './ProjectUpgradeAlert' +import { ProjectUpgradeAlert } from './ProjectUpgradeAlert' import RestartServerButton from './RestartServerButton' interface InfrastructureProps {} diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/index.ts b/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/index.ts index 74c03a0bc01..b2e2a24a42e 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/index.ts +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/index.ts @@ -1,2 +1 @@ -import ProjectUpgradeAlert from './ProjectUpgradeAlert' -export default ProjectUpgradeAlert +export { default as ProjectUpgradeAlert } from './ProjectUpgradeAlert' diff --git a/apps/studio/components/interfaces/Settings/General/index.ts b/apps/studio/components/interfaces/Settings/General/index.ts index ecd3345f01c..be92b7554a3 100644 --- a/apps/studio/components/interfaces/Settings/General/index.ts +++ b/apps/studio/components/interfaces/Settings/General/index.ts @@ -1,17 +1,7 @@ -import General from './General' -import Infrastructure from './Infrastructure/Infrastructure' -import CustomDomainConfig from './CustomDomainConfig/CustomDomainConfig' -import DeleteProjectPanel from './DeleteProjectPanel/DeleteProjectPanel' -import DeleteProjectButton from './DeleteProjectPanel/DeleteProjectButton' -import TransferProjectButton from './TransferProjectPanel/TransferProjectButton' -import TransferProjectPanel from './TransferProjectPanel/TransferProjectPanel' - -export { - General, - Infrastructure, - CustomDomainConfig, - DeleteProjectPanel, - DeleteProjectButton, - TransferProjectPanel, - TransferProjectButton, -} +export { default as General } from './General' +export { default as Infrastructure } from './Infrastructure/Infrastructure' +export { default as CustomDomainConfig } from './CustomDomainConfig/CustomDomainConfig' +export { default as DeleteProjectPanel } from './DeleteProjectPanel/DeleteProjectPanel' +export { default as DeleteProjectButton } from './DeleteProjectPanel/DeleteProjectButton' +export { default as TransferProjectButton } from './TransferProjectPanel/TransferProjectButton' +export { default as TransferProjectPanel } from './TransferProjectPanel/TransferProjectPanel' diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx index ac36896a3fd..0e3b9d478c4 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx @@ -25,7 +25,7 @@ import { useProjectUpgradeEligibilityQuery } from 'data/config/project-upgrade-e import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useIsFeatureEnabled } from 'hooks' import { AWS_REGIONS, FLY_REGIONS } from 'lib/constants' -import ProjectUpgradeAlert from '../General/Infrastructure/ProjectUpgradeAlert' +import { ProjectUpgradeAlert } from '../General/Infrastructure/ProjectUpgradeAlert' import InstanceConfiguration from './InfrastructureConfiguration/InstanceConfiguration' import { AWS_REGIONS_VALUES, diff --git a/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx b/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx index 8d4147ba3be..b791eaa29b0 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx @@ -1,7 +1,7 @@ import { Button, IconX } from 'ui' import CopyButton from 'components/ui/CopyButton' -import Connecting from 'components/ui/Loading/Loading' +import { Loading } from 'components/ui/Loading' import useSingleLog from 'hooks/analytics/useSingleLog' import { useMemo } from 'react' import { @@ -170,7 +170,7 @@ ${JSON.stringify(fullLog.metadata, null, 2)}
- {isLoading && } + {isLoading && }
{!isLoading && }
diff --git a/apps/studio/components/interfaces/Settings/Vault/index.ts b/apps/studio/components/interfaces/Settings/Vault/index.ts index 41f32a26d17..c4c4a5ec325 100644 --- a/apps/studio/components/interfaces/Settings/Vault/index.ts +++ b/apps/studio/components/interfaces/Settings/Vault/index.ts @@ -1,6 +1,4 @@ -import VaultToggle from './VaultToggle' -import SecretsManagement from './Secrets/SecretsManagement' -import EncryptionKeySelector from './Keys/EncryptionKeySelector' -import EncryptionKeysManagement from './Keys/EncryptionKeysManagement' - -export { VaultToggle, SecretsManagement, EncryptionKeySelector, EncryptionKeysManagement } +export { default as VaultToggle } from './VaultToggle' +export { default as SecretsManagement } from './Secrets/SecretsManagement' +export { default as EncryptionKeySelector } from './Keys/EncryptionKeySelector' +export { default as EncryptionKeysManagement } from './Keys/EncryptionKeysManagement' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/DateTimeInput/index.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/DateTimeInput/index.ts index 11fc66c6e2d..e1a725706ad 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/DateTimeInput/index.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/DateTimeInput/index.ts @@ -1,3 +1 @@ -import DateTimeInput from './DateTimeInput' - -export default DateTimeInput +export { default as DateTimeInput } from './DateTimeInput' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx index 7e925616466..2d22e95b91a 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx @@ -7,8 +7,8 @@ import { IconLoader, SidePanel } from 'ui' import { parseSupaTable } from 'components/grid' import { formatFilterURLParams, formatSortURLParams } from 'components/grid/SupabaseGrid.utils' import RefreshButton from 'components/grid/components/header/RefreshButton' -import FilterPopover from 'components/grid/components/header/filter' -import SortPopover from 'components/grid/components/header/sort' +import { FilterPopover } from 'components/grid/components/header/filter' +import { SortPopover } from 'components/grid/components/header/sort' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' import { useTableRowsQuery } from 'data/table-rows/table-rows-query' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx index 02889333aa6..9754a3f8ca0 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx @@ -2,7 +2,7 @@ import { includes, noop } from 'lodash' import { Button, IconEdit2, IconLink, Input, Listbox, Select } from 'ui' import { DATETIME_TYPES, JSON_TYPES, TEXT_TYPES } from '../SidePanelEditor.constants' -import DateTimeInput from './DateTimeInput' +import { DateTimeInput } from './DateTimeInput' import { RowField } from './RowEditor.types' export interface InputFieldProps { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/index.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/index.ts index feeb7224bd6..0122a59f724 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/index.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/index.ts @@ -1,3 +1 @@ -import DrilldownViewer from './DrilldownViewer' - -export default DrilldownViewer +export { default as DrilldownViewer } from './DrilldownViewer' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/JsonEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/JsonEditor.tsx index 28cf419760d..eff7bf73ebb 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/JsonEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/JsonEditor.tsx @@ -6,7 +6,7 @@ import TwoOptionToggle from 'components/ui/TwoOptionToggle' import { minifyJSON, prettifyJSON, tryParseJson, removeJSONTrailingComma } from 'lib/helpers' import toast from 'react-hot-toast' import ActionBar from '../../ActionBar' -import DrilldownViewer from './DrilldownViewer' +import { DrilldownViewer } from './DrilldownViewer' import JsonCodeEditor from './JsonCodeEditor' interface JsonEditProps { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/index.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/index.ts index 40295113e5b..b1bbc25b412 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/index.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/index.ts @@ -1,3 +1 @@ -import JsonEditor from './JsonEditor' - -export default JsonEditor +export { default as JsonEditor } from './JsonEditor' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx index 130f824cd87..90652720084 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx @@ -10,7 +10,7 @@ import ActionBar from '../ActionBar' import ForeignRowSelector from './ForeignRowSelector/ForeignRowSelector' import HeaderTitle from './HeaderTitle' import InputField from './InputField' -import JsonEdit from './JsonEditor' +import { JsonEditor } from './JsonEditor' import { JsonEditValue, RowField } from './RowEditor.types' import { generateRowFields, @@ -190,7 +190,7 @@ const RowEditor = ({ )} - setIsEdited(true)} /> - + return } if (isUndefined(selectedTable)) { diff --git a/apps/studio/components/interfaces/TableGridEditor/index.ts b/apps/studio/components/interfaces/TableGridEditor/index.ts index 10414d79b9c..86131e01172 100644 --- a/apps/studio/components/interfaces/TableGridEditor/index.ts +++ b/apps/studio/components/interfaces/TableGridEditor/index.ts @@ -1,6 +1,3 @@ -import TableGridEditor from './TableGridEditor' -import SidePanelEditor from './SidePanelEditor' -import EmptyState from './EmptyState' - -export { EmptyState, SidePanelEditor } -export default TableGridEditor +export { default as TableGridEditor } from './TableGridEditor' +export { default as SidePanelEditor } from './SidePanelEditor/SidePanelEditor' +export { default as EmptyState } from './EmptyState' diff --git a/apps/studio/components/interfaces/index.ts b/apps/studio/components/interfaces/index.ts deleted file mode 100644 index de0b1eee793..00000000000 --- a/apps/studio/components/interfaces/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import TableGridEditor from './TableGridEditor' - -export * from './Auth' - -export { TableGridEditor } diff --git a/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx b/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx index 43c1ddcfa6a..81b4f347cfc 100644 --- a/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx +++ b/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx @@ -4,7 +4,7 @@ import { ReactNode } from 'react' import { Badge, IconArrowUpRight, IconLogOut, Menu } from 'ui' import { useFlag } from 'hooks' -import LayoutHeader from '../ProjectLayout/LayoutHeader' +import { LayoutHeader } from '../ProjectLayout/LayoutHeader' import { SidebarLink, SidebarSection } from './AccountLayout.types' interface WithSidebarProps { diff --git a/apps/studio/components/layouts/AppLayout/AppHeader.tsx b/apps/studio/components/layouts/AppLayout/AppHeader.tsx index 7eabf45eb8d..7dce7f04970 100644 --- a/apps/studio/components/layouts/AppLayout/AppHeader.tsx +++ b/apps/studio/components/layouts/AppLayout/AppHeader.tsx @@ -3,7 +3,7 @@ import Link from 'next/link' import { useRouter } from 'next/router' import { useSelectedOrganization, useSelectedProject } from 'hooks' -import FeedbackDropdown from '../ProjectLayout/LayoutHeader/FeedbackDropdown' +import { FeedbackDropdown } from '../ProjectLayout/LayoutHeader/FeedbackDropdown' import HelpPopover from '../ProjectLayout/LayoutHeader/HelpPopover' import NotificationsPopoverV2 from '../ProjectLayout/LayoutHeader/NotificationsPopoverV2/NotificationsPopover' import BranchDropdown from './BranchDropdown' diff --git a/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx b/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx index 1a247684ec7..8c05659a12b 100644 --- a/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx +++ b/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx @@ -3,10 +3,10 @@ import { useRouter } from 'next/router' import { PropsWithChildren } from 'react' import { useIsColumnLevelPrivilegesEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' -import ProductMenu from 'components/ui/ProductMenu' +import { ProductMenu } from 'components/ui/ProductMenu' import { useAuthConfigPrefetch } from 'data/auth/auth-config-query' import { withAuth } from 'hooks' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import { generateAuthMenu } from './AuthLayout.utils' export interface AuthLayoutProps { diff --git a/apps/studio/components/layouts/BillingLayout.tsx b/apps/studio/components/layouts/BillingLayout.tsx index 2d5a1a3a8e9..abb764fd1cc 100644 --- a/apps/studio/components/layouts/BillingLayout.tsx +++ b/apps/studio/components/layouts/BillingLayout.tsx @@ -1,7 +1,7 @@ import Link from 'next/link' import { PropsWithChildren } from 'react' -import BaseLayout from 'components/layouts' +import { ProjectLayout } from 'components/layouts' import { useSelectedOrganization, useSelectedProject, withAuth } from 'hooks' import { IconX } from 'ui' @@ -12,7 +12,7 @@ const BillingLayout = ({ children }: PropsWithChildren) => { const selectedProject = useSelectedProject() return ( - +
{/* Header */}
@@ -50,7 +50,7 @@ const BillingLayout = ({ children }: PropsWithChildren) => {
{children}
-
+ ) } diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx index b16843611e9..4341217d156 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx @@ -2,11 +2,11 @@ import { observer } from 'mobx-react-lite' import { useRouter } from 'next/router' import { PropsWithChildren } from 'react' -import ProductMenu from 'components/ui/ProductMenu' +import { ProductMenu } from 'components/ui/ProductMenu' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useSelectedProject, withAuth } from 'hooks' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import { generateDatabaseMenu } from './DatabaseMenu.utils' export interface DatabaseLayoutProps { diff --git a/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx b/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx index f67a6976615..ad906c325c3 100644 --- a/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx +++ b/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx @@ -5,11 +5,11 @@ import { ReactElement } from 'react' import { useParams } from 'common' import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import Error from 'components/ui/Error' -import ProductMenu from 'components/ui/ProductMenu' +import { ProductMenu } from 'components/ui/ProductMenu' import { useOpenAPISpecQuery } from 'data/open-api/api-spec-query' import { useIsFeatureEnabled, useSelectedProject, withAuth } from 'hooks' import { PROJECT_STATUS } from 'lib/constants' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import { generateDocsMenu } from './DocsLayout.utils' function DocsLayout({ title, children }: { title: string; children: ReactElement }) { diff --git a/apps/studio/components/layouts/FunctionsLayout.tsx b/apps/studio/components/layouts/FunctionsLayout.tsx index ebeed817dc1..2247126ac9e 100644 --- a/apps/studio/components/layouts/FunctionsLayout.tsx +++ b/apps/studio/components/layouts/FunctionsLayout.tsx @@ -12,7 +12,7 @@ import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' import { useCheckPermissions, withAuth } from 'hooks' import FunctionsNav from '../interfaces/Functions/FunctionsNav' -import ProjectLayout from './' +import { ProjectLayout } from './' interface FunctionsLayoutProps { title?: string diff --git a/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx b/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx index ee599471dff..b2b12f6233f 100644 --- a/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx +++ b/apps/studio/components/layouts/LogsLayout/LogsLayout.tsx @@ -3,9 +3,9 @@ import { useRouter } from 'next/router' import { PropsWithChildren } from 'react' import NoPermission from 'components/ui/NoPermission' -import ProductMenu from 'components/ui/ProductMenu' +import { ProductMenu } from 'components/ui/ProductMenu' import { useCheckPermissions, useIsFeatureEnabled, useSelectedProject, withAuth } from 'hooks' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import { generateLogsMenu } from './LogsMenu.utils' interface LogsLayoutProps { diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/index.ts b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/index.ts index c4d782a81b4..5b5e5bc0e4d 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/index.ts +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/index.ts @@ -1,3 +1 @@ -import FeedbackDropdown from './FeedbackDropdown' - -export default FeedbackDropdown +export { default as FeedbackDropdown } from './FeedbackDropdown' diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index ed2373894bc..4b601acbf6a 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -13,7 +13,7 @@ import { useOrgUsageQuery } from 'data/usage/org-usage-query' import { useSelectedOrganization, useSelectedProject } from 'hooks' import { IS_PLATFORM } from 'lib/constants' import BreadcrumbsView from './BreadcrumbsView' -import FeedbackDropdown from './FeedbackDropdown' +import { FeedbackDropdown } from './FeedbackDropdown' import HelpPopover from './HelpPopover' import NotificationsPopoverV2 from './NotificationsPopoverV2/NotificationsPopover' diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/index.ts b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/index.ts index 357ec371434..fee21125467 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/index.ts +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/index.ts @@ -1,3 +1 @@ -import LayoutHeader from './LayoutHeader' - -export default LayoutHeader +export { default as LayoutHeader } from './LayoutHeader' diff --git a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx index 5a783e8ad41..52971bb3e0c 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx @@ -5,7 +5,7 @@ import { Fragment, PropsWithChildren, ReactNode, useEffect } from 'react' import ProjectAPIDocs from 'components/interfaces/ProjectAPIDocs/ProjectAPIDocs' import AISettingsModal from 'components/ui/AISettingsModal' -import Connecting from 'components/ui/Loading/Loading' +import { Loading } from 'components/ui/Loading' import ResourceExhaustionWarningBanner from 'components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner' import { useFlag, useSelectedOrganization, useSelectedProject, withAuth } from 'hooks' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' @@ -14,7 +14,7 @@ import AppLayout from '../AppLayout/AppLayout' import EnableBranchingModal from '../AppLayout/EnableBranchingButton/EnableBranchingModal' import BuildingState from './BuildingState' import ConnectingState from './ConnectingState' -import LayoutHeader from './LayoutHeader' +import { LayoutHeader } from './LayoutHeader' import LoadingState from './LoadingState' import NavigationBar from './NavigationBar/NavigationBar' import PausingState from './PausingState' @@ -22,7 +22,7 @@ import ProductMenuBar from './ProductMenuBar' import { ProjectContextProvider } from './ProjectContext' import ProjectPausedState from './ProjectPausedState' import RestoringState from './RestoringState' -import UpgradingState from './UpgradingState' +import { UpgradingState } from './UpgradingState' import { ResizableHandle, ResizablePanelGroup, ResizablePanel, cn } from 'ui' // [Joshen] This is temporary while we unblock users from managing their project @@ -236,7 +236,7 @@ const ContentWrapper = ({ isLoading, isBlocking = true, children }: ContentWrapp }, [ref]) if (isBlocking && (isLoading || (requiresProjectDetails && selectedProject === undefined))) { - return router.pathname.endsWith('[ref]') ? : + return router.pathname.endsWith('[ref]') ? : } if (isProjectUpgrading) { diff --git a/apps/studio/components/layouts/ProjectLayout/UpgradingState/index.ts b/apps/studio/components/layouts/ProjectLayout/UpgradingState/index.ts index eb515bf7666..7264caf00de 100644 --- a/apps/studio/components/layouts/ProjectLayout/UpgradingState/index.ts +++ b/apps/studio/components/layouts/ProjectLayout/UpgradingState/index.ts @@ -1,2 +1 @@ -import UpgradingState from './UpgradingState' -export default UpgradingState +export { default as UpgradingState } from './UpgradingState' diff --git a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx index 33dcf5e41e5..2c9787db4e6 100644 --- a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx +++ b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx @@ -5,8 +5,8 @@ import { PropsWithChildren } from 'react' import { generateSettingsMenu } from './SettingsMenu.utils' import { useParams } from 'common' -import ProductMenu from 'components/ui/ProductMenu' -import ProjectLayout from '..' +import { ProductMenu } from 'components/ui/ProductMenu' +import { ProjectLayout } from '..' interface SettingsLayoutProps { title?: string diff --git a/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx b/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx index 961839006c0..1c2a87c485d 100644 --- a/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx +++ b/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx @@ -1,9 +1,9 @@ import { useRouter } from 'next/router' import { PropsWithChildren } from 'react' -import ProductMenu from 'components/ui/ProductMenu' +import { ProductMenu } from 'components/ui/ProductMenu' import { useSelectedProject, useStore, withAuth } from 'hooks' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import { generateRealtimeMenu } from './RealtimeMenu.utils' export interface RealtimeLayoutProps { diff --git a/apps/studio/components/layouts/ReportsLayout/ReportsLayout.tsx b/apps/studio/components/layouts/ReportsLayout/ReportsLayout.tsx index d0d9168bbce..eca6d2f9339 100644 --- a/apps/studio/components/layouts/ReportsLayout/ReportsLayout.tsx +++ b/apps/studio/components/layouts/ReportsLayout/ReportsLayout.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren } from 'react' import { withAuth } from 'hooks' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import ReportsMenu from './ReportsMenu' interface ReportsLayoutProps { diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorLayout.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorLayout.tsx index b20474dba70..8e89fccd6d4 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorLayout.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorLayout.tsx @@ -1,6 +1,6 @@ import { withAuth } from 'hooks' import { ReactNode, useMemo } from 'react' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import SQLEditorMenu from './SQLEditorMenu' export interface SQLEditorLayoutProps { diff --git a/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx b/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx index e0c06300a0a..8e70cadc132 100644 --- a/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx +++ b/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx @@ -5,7 +5,7 @@ import { AutoApiService, useProjectApiQuery } from 'data/config/project-api-quer import { useSelectedProject, useStore, withAuth } from 'hooks' import { PROJECT_STATUS } from 'lib/constants' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' -import ProjectLayout from '../' +import { ProjectLayout } from '../' import StorageMenu from './StorageMenu' export interface StorageLayoutProps { diff --git a/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx b/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx index abeb9fb5339..f4a4c585965 100644 --- a/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx @@ -4,7 +4,7 @@ import { PropsWithChildren, useMemo } from 'react' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { ProjectLayoutWithAuth } from '../' +import { ProjectLayoutWithAuth } from '../ProjectLayout/ProjectLayout' import TableEditorMenu from './TableEditorMenu' const TableEditorLayout = ({ children }: PropsWithChildren<{}>) => { diff --git a/apps/studio/components/layouts/WizardLayout.tsx b/apps/studio/components/layouts/WizardLayout.tsx index 3685006886f..5e51f9721b8 100644 --- a/apps/studio/components/layouts/WizardLayout.tsx +++ b/apps/studio/components/layouts/WizardLayout.tsx @@ -6,7 +6,7 @@ import { IconChevronRight } from 'ui' import { withAuth } from 'hooks' import { BASE_PATH } from 'lib/constants' import { Organization, Project } from 'types' -import FeedbackDropdown from './ProjectLayout/LayoutHeader/FeedbackDropdown' +import { FeedbackDropdown } from './ProjectLayout/LayoutHeader/FeedbackDropdown' import HelpPopover from './ProjectLayout/LayoutHeader/HelpPopover' interface WizardLayoutProps { diff --git a/apps/studio/components/layouts/index.ts b/apps/studio/components/layouts/index.ts index 1240d37c30a..a510c8ddb94 100644 --- a/apps/studio/components/layouts/index.ts +++ b/apps/studio/components/layouts/index.ts @@ -1,40 +1,17 @@ -import AccountLayout from './AccountLayout/AccountLayout' -import AuthLayout from './AuthLayout/AuthLayout' -import BillingLayout from './BillingLayout' -import DatabaseLayout from './DatabaseLayout/DatabaseLayout' -import DocsLayout from './DocsLayout/DocsLayout' -import LogsLayout from './LogsLayout/LogsLayout' -import OrganizationLayout from './OrganizationLayout' -import ProjectLayout, { ProjectLayoutWithAuth } from './ProjectLayout/ProjectLayout' -import SettingsLayout from './ProjectSettingsLayout/SettingsLayout' -import ReportsLayout from './ReportsLayout/ReportsLayout' -import SQLEditorLayout from './SQLEditorLayout/SQLEditorLayout' -import ForgotPasswordLayout from './SignInLayout/ForgotPasswordLayout' -import SignInLayout from './SignInLayout/SignInLayout' -import StorageLayout from './StorageLayout/StorageLayout' -import TableEditorLayout from './TableEditorLayout/TableEditorLayout' -import VercelIntegrationLayout from './VercelIntegrationLayout' -import WizardLayout, { WizardLayoutWithoutAuth } from './WizardLayout' - -export { - AccountLayout, - AuthLayout, - BillingLayout, - DatabaseLayout, - DocsLayout, - ForgotPasswordLayout, - LogsLayout, - OrganizationLayout, - ProjectLayoutWithAuth, - ReportsLayout, - SQLEditorLayout, - SettingsLayout, - SignInLayout, - StorageLayout, - TableEditorLayout, - VercelIntegrationLayout, - WizardLayout, - WizardLayoutWithoutAuth, -} - -export default ProjectLayout +export { default as AccountLayout } from './AccountLayout/AccountLayout' +export { default as AuthLayout } from './AuthLayout/AuthLayout' +export { default as BillingLayout } from './BillingLayout' +export { default as DatabaseLayout } from './DatabaseLayout/DatabaseLayout' +export { default as DocsLayout } from './DocsLayout/DocsLayout' +export { default as LogsLayout } from './LogsLayout/LogsLayout' +export { default as OrganizationLayout } from './OrganizationLayout' +export { default as ProjectLayout } from './ProjectLayout/ProjectLayout' +export { default as SettingsLayout } from './ProjectSettingsLayout/SettingsLayout' +export { default as ReportsLayout } from './ReportsLayout/ReportsLayout' +export { default as SQLEditorLayout } from './SQLEditorLayout/SQLEditorLayout' +export { default as ForgotPasswordLayout } from './SignInLayout/ForgotPasswordLayout' +export { default as SignInLayout } from './SignInLayout/SignInLayout' +export { default as StorageLayout } from './StorageLayout/StorageLayout' +export { default as TableEditorLayout } from './TableEditorLayout/TableEditorLayout' +export { default as VercelIntegrationLayout } from './VercelIntegrationLayout' +export { default as WizardLayout } from './WizardLayout' diff --git a/apps/studio/components/to-be-cleaned/Storage/index.ts b/apps/studio/components/to-be-cleaned/Storage/index.ts index de58d4fb2ee..efecd4c782b 100644 --- a/apps/studio/components/to-be-cleaned/Storage/index.ts +++ b/apps/studio/components/to-be-cleaned/Storage/index.ts @@ -1,7 +1,5 @@ -import StorageExplorer from './StorageExplorer/StorageExplorer' -import StoragePolicies from './StoragePolicies/StoragePolicies' -import StorageSettings from './StorageSettings/StorageSettings' +export { default as StorageExplorer } from './StorageExplorer/StorageExplorer' +export { default as StoragePolicies } from './StoragePolicies/StoragePolicies' +export { default as StorageSettings } from './StorageSettings/StorageSettings' -import DeleteBucketModal from './DeleteBucketModal' - -export { DeleteBucketModal, StorageExplorer, StoragePolicies, StorageSettings } +export { default as DeleteBucketModal } from './DeleteBucketModal' diff --git a/apps/studio/components/ui/CodeEditor/CodeEditor.tsx b/apps/studio/components/ui/CodeEditor/CodeEditor.tsx index abfa83028bc..f955a339e97 100644 --- a/apps/studio/components/ui/CodeEditor/CodeEditor.tsx +++ b/apps/studio/components/ui/CodeEditor/CodeEditor.tsx @@ -5,7 +5,7 @@ import { useRef } from 'react' import { cn } from 'ui' import { timeout } from 'lib/helpers' -import Connecting from '../Loading' +import { Loading } from '../Loading' import { alignEditor } from './CodeEditor.utils' interface CodeEditorProps { @@ -88,7 +88,7 @@ const CodeEditor = ({ value={value ?? undefined} language={language} defaultValue={defaultValue ?? undefined} - loading={loading || } + loading={loading || } options={optionsMerged} onMount={onMount} onChange={onInputChange} diff --git a/apps/studio/components/ui/CodeEditor/index.ts b/apps/studio/components/ui/CodeEditor/index.ts index a4bbbd740db..33f33a3c5e1 100644 --- a/apps/studio/components/ui/CodeEditor/index.ts +++ b/apps/studio/components/ui/CodeEditor/index.ts @@ -1,4 +1,3 @@ -import CodeEditor from './CodeEditor' +export { default as CodeEditor } from './CodeEditor' export * from './CodeEditor.utils' -export default CodeEditor diff --git a/apps/studio/components/ui/Loading/Loading.tsx b/apps/studio/components/ui/Loading/Loading.tsx deleted file mode 100644 index 1db8aaa9e5a..00000000000 --- a/apps/studio/components/ui/Loading/Loading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import Loading from 'ui/src/components/LogoLoader' - -export default Loading diff --git a/apps/studio/components/ui/Loading/index.ts b/apps/studio/components/ui/Loading/index.ts index 472e998095e..ecc66c9df96 100644 --- a/apps/studio/components/ui/Loading/index.ts +++ b/apps/studio/components/ui/Loading/index.ts @@ -1,3 +1 @@ -import Loading from './Loading' - -export default Loading +export { default as Loading } from 'ui/src/components/LogoLoader' diff --git a/apps/studio/components/ui/ProductMenu/index.ts b/apps/studio/components/ui/ProductMenu/index.ts index 91cdf1160a2..fd8718e8537 100644 --- a/apps/studio/components/ui/ProductMenu/index.ts +++ b/apps/studio/components/ui/ProductMenu/index.ts @@ -1,2 +1 @@ -import ProductMenu from './ProductMenu' -export default ProductMenu +export { default as ProductMenu } from './ProductMenu' diff --git a/apps/studio/data/table-rows/table-row-create-mutation.ts b/apps/studio/data/table-rows/table-row-create-mutation.ts index c7f6f4e7964..1a3cc009716 100644 --- a/apps/studio/data/table-rows/table-row-create-mutation.ts +++ b/apps/studio/data/table-rows/table-row-create-mutation.ts @@ -2,11 +2,11 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { Query, SupaTable } from 'components/grid' -import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' import { ImpersonationRole, wrapWithRoleImpersonation } from 'lib/role-impersonation' import { isRoleImpersonationEnabled } from 'state/role-impersonation-state' import { ResponseError } from 'types' +import { executeSql } from 'data/sql/execute-sql-query' export type TableRowCreateVariables = { projectRef: string diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx index 9e96606394c..42a3b45a640 100644 --- a/apps/studio/pages/_app.tsx +++ b/apps/studio/pages/_app.tsx @@ -43,10 +43,6 @@ import { RouteValidationWrapper, } from 'components/interfaces/App' import { AppBannerContextProvider } from 'components/interfaces/App/AppBannerWrapperContext' -import { - FeaturePreviewContextProvider, - FeaturePreviewModal, -} from 'components/interfaces/App/FeaturePreview' import FlagProvider from 'components/ui/Flag/FlagProvider' import PageTelemetry from 'components/ui/PageTelemetry' import { useRootQueryClient } from 'data/query-client' @@ -60,6 +56,8 @@ import { RootStore } from 'stores' import HCaptchaLoadedStore from 'stores/hcaptcha-loaded-store' import { AppPropsWithLayout } from 'types' import { Toaster } from 'ui' +import { FeaturePreviewContextProvider } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import FeaturePreviewModal from 'components/interfaces/App/FeaturePreview/FeaturePreviewModal' dayjs.extend(customParseFormat) dayjs.extend(utc) diff --git a/apps/studio/pages/cli/login.tsx b/apps/studio/pages/cli/login.tsx index 8006cd6f52c..90df8081adc 100644 --- a/apps/studio/pages/cli/login.tsx +++ b/apps/studio/pages/cli/login.tsx @@ -5,7 +5,7 @@ import { createCliLoginSession } from 'data/cli/login' import { useIsLoggedIn, useParams } from 'common' import { useRouter } from 'next/router' import { withAuth } from 'hooks' -import Connecting from 'components/ui/Loading/Loading' +import { Loading } from 'components/ui/Loading' import { useEffect, useState } from 'react' import Link from 'next/link' @@ -63,7 +63,7 @@ const CliLoginPage: NextPage = () => {

) : ( - + )}
diff --git a/apps/studio/pages/new/[slug].tsx b/apps/studio/pages/new/[slug].tsx index c0f93850740..0fdc1557886 100644 --- a/apps/studio/pages/new/[slug].tsx +++ b/apps/studio/pages/new/[slug].tsx @@ -11,7 +11,6 @@ import { NotOrganizationOwnerWarning, } from 'components/interfaces/Organization/NewProject' import { RegionSelector } from 'components/interfaces/ProjectCreation/RegionSelector' -import { WizardLayoutWithoutAuth } from 'components/layouts' import DisabledWarningDueToIncident from 'components/ui/DisabledWarningDueToIncident' import Panel from 'components/ui/Panel' import PasswordStrengthBar from 'components/ui/PasswordStrengthBar' @@ -37,6 +36,7 @@ import { passwordStrength, pluckObjectFields } from 'lib/helpers' import { NextPageWithLayout } from 'types' import { Badge, Button, IconExternalLink, IconUsers, Input, Listbox } from 'ui' import { components } from 'data/api' +import { WizardLayoutWithoutAuth } from 'components/layouts/WizardLayout' type DesiredInstanceSize = components['schemas']['DesiredInstanceSize'] diff --git a/apps/studio/pages/org/[slug]/apps.tsx b/apps/studio/pages/org/[slug]/apps.tsx index 961fe12b405..b55b3ebd927 100644 --- a/apps/studio/pages/org/[slug]/apps.tsx +++ b/apps/studio/pages/org/[slug]/apps.tsx @@ -1,6 +1,6 @@ import { OAuthApps } from 'components/interfaces/Organization' import { OrganizationLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/org/[slug]/audit.tsx b/apps/studio/pages/org/[slug]/audit.tsx index 895526ed470..e8ae6ef1e4c 100644 --- a/apps/studio/pages/org/[slug]/audit.tsx +++ b/apps/studio/pages/org/[slug]/audit.tsx @@ -1,6 +1,6 @@ import { AuditLogs } from 'components/interfaces/Organization' import { OrganizationLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/org/[slug]/billing.tsx b/apps/studio/pages/org/[slug]/billing.tsx index bb7bdbcd790..4555aac2a9d 100644 --- a/apps/studio/pages/org/[slug]/billing.tsx +++ b/apps/studio/pages/org/[slug]/billing.tsx @@ -1,7 +1,7 @@ import { useParams } from 'common' import { BillingSettings } from 'components/interfaces/Organization' import { OrganizationLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' import { useEffect } from 'react' diff --git a/apps/studio/pages/org/[slug]/general.tsx b/apps/studio/pages/org/[slug]/general.tsx index d186365fad5..9e1803d79b9 100644 --- a/apps/studio/pages/org/[slug]/general.tsx +++ b/apps/studio/pages/org/[slug]/general.tsx @@ -1,6 +1,6 @@ import { GeneralSettings as GeneralSettingsLegacy } from 'components/interfaces/Organization' import { OrganizationLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/org/[slug]/invoices.tsx b/apps/studio/pages/org/[slug]/invoices.tsx index 418510243c3..7d9f643546f 100644 --- a/apps/studio/pages/org/[slug]/invoices.tsx +++ b/apps/studio/pages/org/[slug]/invoices.tsx @@ -1,6 +1,6 @@ import { InvoicesSettings } from 'components/interfaces/Organization' import { OrganizationLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/org/[slug]/team.tsx b/apps/studio/pages/org/[slug]/team.tsx index d1a75aec2f4..de36efe5d32 100644 --- a/apps/studio/pages/org/[slug]/team.tsx +++ b/apps/studio/pages/org/[slug]/team.tsx @@ -1,6 +1,6 @@ import { TeamSettings } from 'components/interfaces/Organization' import { OrganizationLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/org/[slug]/usage.tsx b/apps/studio/pages/org/[slug]/usage.tsx index dfc69e815e0..67585db31f9 100644 --- a/apps/studio/pages/org/[slug]/usage.tsx +++ b/apps/studio/pages/org/[slug]/usage.tsx @@ -1,6 +1,6 @@ import { Usage } from 'components/interfaces/Organization' import { OrganizationLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/project/[ref]/api/graphiql.tsx b/apps/studio/pages/project/[ref]/api/graphiql.tsx index 52f62ccfcd9..c5f19532f03 100644 --- a/apps/studio/pages/project/[ref]/api/graphiql.tsx +++ b/apps/studio/pages/project/[ref]/api/graphiql.tsx @@ -10,7 +10,7 @@ import ExtensionCard from 'components/interfaces/Database/Extensions/ExtensionCa import GraphiQL from 'components/interfaces/GraphQL/GraphiQL' import { DocsLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import Connecting from 'components/ui/Loading/Loading' +import { Loading } from 'components/ui/Loading' import { useSessionAccessTokenQuery } from 'data/auth/session-access-token-query' import { useProjectApiQuery } from 'data/config/project-api-query' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' @@ -86,7 +86,7 @@ const GraphiQLPage: NextPageWithLayout = () => { }, [projectRef, getImpersonatedRole, jwtSecret, accessToken, serviceRoleKey]) if ((IS_PLATFORM && !accessToken) || !isFetched || (isExtensionsLoading && !pgGraphqlExtension)) { - return + return } if (pgGraphqlExtension?.installed_version === null) { diff --git a/apps/studio/pages/project/[ref]/auth/providers.tsx b/apps/studio/pages/project/[ref]/auth/providers.tsx index ea2840d188d..ea9d2e25a11 100644 --- a/apps/studio/pages/project/[ref]/auth/providers.tsx +++ b/apps/studio/pages/project/[ref]/auth/providers.tsx @@ -1,6 +1,6 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { AuthProvidersForm } from 'components/interfaces' +import { AuthProvidersForm } from 'components/interfaces/Auth' import { AuthLayout } from 'components/layouts' import { FormsContainer } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' diff --git a/apps/studio/pages/project/[ref]/auth/templates.tsx b/apps/studio/pages/project/[ref]/auth/templates.tsx index 058cbbdd680..f403d698ed0 100644 --- a/apps/studio/pages/project/[ref]/auth/templates.tsx +++ b/apps/studio/pages/project/[ref]/auth/templates.tsx @@ -1,6 +1,6 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { EmailTemplates } from 'components/interfaces' +import { EmailTemplates } from 'components/interfaces/Auth' import { AuthLayout } from 'components/layouts' import { FormsContainer } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' diff --git a/apps/studio/pages/project/[ref]/auth/users.tsx b/apps/studio/pages/project/[ref]/auth/users.tsx index ce0dc519ec6..1767354d942 100644 --- a/apps/studio/pages/project/[ref]/auth/users.tsx +++ b/apps/studio/pages/project/[ref]/auth/users.tsx @@ -1,4 +1,4 @@ -import { Users } from 'components/interfaces/Auth' +import { Users } from 'components/interfaces/Auth/Users' import { AuthLayout } from 'components/layouts' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/project/[ref]/branches.tsx b/apps/studio/pages/project/[ref]/branches.tsx index bee6a18c20a..dd2573bdab4 100644 --- a/apps/studio/pages/project/[ref]/branches.tsx +++ b/apps/studio/pages/project/[ref]/branches.tsx @@ -1,5 +1,5 @@ import BranchManagement from 'components/interfaces/BranchManagement/BranchManagement' -import { ProjectLayoutWithAuth } from 'components/layouts' +import { ProjectLayoutWithAuth } from 'components/layouts/ProjectLayout/ProjectLayout' import { NextPageWithLayout } from 'types' const BranchManagementPage: NextPageWithLayout = () => { diff --git a/apps/studio/pages/project/[ref]/building.tsx b/apps/studio/pages/project/[ref]/building.tsx index b4ebc0a961e..88255e3d491 100644 --- a/apps/studio/pages/project/[ref]/building.tsx +++ b/apps/studio/pages/project/[ref]/building.tsx @@ -1,4 +1,4 @@ -import { ProjectLayoutWithAuth } from 'components/layouts' +import { ProjectLayoutWithAuth } from 'components/layouts/ProjectLayout/ProjectLayout' import { useRouter } from 'next/router' import { useEffect } from 'react' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/project/[ref]/editor/[id].tsx b/apps/studio/pages/project/[ref]/editor/[id].tsx index fd1d5957f7d..1b84514ea61 100644 --- a/apps/studio/pages/project/[ref]/editor/[id].tsx +++ b/apps/studio/pages/project/[ref]/editor/[id].tsx @@ -1,6 +1,6 @@ import { useTheme } from 'next-themes' import { useParams } from 'common/hooks' -import { TableGridEditor } from 'components/interfaces' +import { TableGridEditor } from 'components/interfaces/TableGridEditor' import DeleteConfirmationDialogs from 'components/interfaces/TableGridEditor/DeleteConfirmationDialogs' import { TableEditorLayout } from 'components/layouts' import { ProjectContextFromParamsProvider } from 'components/layouts/ProjectLayout/ProjectContext' diff --git a/apps/studio/pages/project/[ref]/index.tsx b/apps/studio/pages/project/[ref]/index.tsx index f14f8c21e4c..a64e832739a 100644 --- a/apps/studio/pages/project/[ref]/index.tsx +++ b/apps/studio/pages/project/[ref]/index.tsx @@ -6,7 +6,7 @@ import Connect from 'components/interfaces/Home/Connect/Connect' import { CLIENT_LIBRARIES, EXAMPLE_PROJECTS } from 'components/interfaces/Home/Home.constants' import ProjectUsageSection from 'components/interfaces/Home/ProjectUsageSection' import ServiceStatus from 'components/interfaces/Home/ServiceStatus' -import { ProjectLayoutWithAuth } from 'components/layouts' +import { ProjectLayoutWithAuth } from 'components/layouts/ProjectLayout/ProjectLayout' import ProjectPausedState from 'components/layouts/ProjectLayout/ProjectPausedState' import ProjectUpgradeFailedBanner from 'components/ui/ProjectUpgradeFailedBanner' import { useSelectedProject } from 'hooks' diff --git a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx index 1a3c08e11b7..20f817a898b 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx @@ -27,7 +27,7 @@ import { } from 'components/interfaces/Settings/Logs' import UpgradePrompt from 'components/interfaces/Settings/Logs/UpgradePrompt' import { LogsLayout } from 'components/layouts' -import CodeEditor from 'components/ui/CodeEditor' +import { CodeEditor } from 'components/ui/CodeEditor' import LoadingOpacity from 'components/ui/LoadingOpacity' import ShimmerLine from 'components/ui/ShimmerLine' import { useContentInsertMutation } from 'data/content/content-insert-mutation' diff --git a/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx b/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx index e55fdcb38af..1b69384a7e1 100644 --- a/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx @@ -5,14 +5,14 @@ import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import { LogsLayout } from 'components/layouts' import { usePoolingConfigurationQuery } from 'data/database/pooling-configuration-query' import { NextPageWithLayout } from 'types' -import Connecting from 'components/ui/Loading/Loading' +import { Loading } from 'components/ui/Loading' export const LogPage: NextPageWithLayout = () => { const { ref } = useParams() const { isLoading } = usePoolingConfigurationQuery({ projectRef: ref ?? 'default' }) // this prevents initial load of pooler logs before config has been retrieved - if (isLoading) return + if (isLoading) return return ( { {navLayoutV2 && (
- +
)} {!navLayoutV2 && ( diff --git a/apps/studio/pages/sign-in-mfa.tsx b/apps/studio/pages/sign-in-mfa.tsx index 4564fb46a9c..d72348b7431 100644 --- a/apps/studio/pages/sign-in-mfa.tsx +++ b/apps/studio/pages/sign-in-mfa.tsx @@ -6,7 +6,7 @@ import toast from 'react-hot-toast' import { useTelemetryProps } from 'common' import SignInMfaForm from 'components/interfaces/SignIn/SignInMfaForm' import { SignInLayout } from 'components/layouts' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { auth, buildPathWithParams, getAccessToken, getReturnToPath } from 'lib/gotrue' import Telemetry from 'lib/telemetry' import { NextPageWithLayout } from 'types' diff --git a/apps/studio/pages/vercel/integrate.tsx b/apps/studio/pages/vercel/integrate.tsx index 0c04b7dcf41..04a8e2183c2 100644 --- a/apps/studio/pages/vercel/integrate.tsx +++ b/apps/studio/pages/vercel/integrate.tsx @@ -15,7 +15,7 @@ import { prepareVercelEvns, } from 'components/to-be-cleaned/Integration/Vercel.utils' import { databaseIcon, vercelIcon } from 'components/to-be-cleaned/ListIcons' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import { useProjectsQuery } from 'data/projects/projects-query' import { withAuth } from 'hooks' import { get } from 'lib/common/fetch' diff --git a/apps/studio/pages/vercel/setupProject.tsx b/apps/studio/pages/vercel/setupProject.tsx index 3c7af8ef4d1..c1a90490f38 100644 --- a/apps/studio/pages/vercel/setupProject.tsx +++ b/apps/studio/pages/vercel/setupProject.tsx @@ -14,7 +14,7 @@ import { fetchVercelProject, prepareVercelEvns, } from 'components/to-be-cleaned/Integration/Vercel.utils' -import Loading from 'components/ui/Loading' +import { Loading } from 'components/ui/Loading' import PasswordStrengthBar from 'components/ui/PasswordStrengthBar' import { useProjectCreateMutation } from 'data/projects/project-create-mutation' import { From fb9dfac0752e49b50f51a541e8190468ec1a772b Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Mon, 4 Mar 2024 19:12:22 +0800 Subject: [PATCH 35/62] Remove observer and ui.setNotification calls (#21725) * Remove observer and ui.setNotification calls * lint * Fix missing export --- .../AdvancedAuthSettingsForm.tsx | 2 +- .../Auth/EmailTemplates/TemplateEditor.tsx | 26 +++++------- .../interfaces/Auth/Policies/Policies.tsx | 7 ++-- .../Auth/RedirectUrls/RedirectUrls.tsx | 33 +++++---------- .../interfaces/Auth/SiteUrl/SiteUrl.tsx | 20 ++++------ .../interfaces/Auth/SmtpForm/SmtpForm.tsx | 16 ++++---- .../interfaces/Auth/Users/CreateUserModal.tsx | 18 +++------ .../interfaces/Auth/Users/InviteUserModal.tsx | 9 ++--- .../Database/Backups/BackupsList.tsx | 18 ++++----- .../Database/Backups/PITR/PITRStatus.tsx | 9 ++--- .../Database/Extensions/ExtensionCard.tsx | 5 +-- .../Database/Extensions/Extensions.tsx | 3 +- .../Database/Hooks/HooksList/SchemaTable.tsx | 3 +- .../interfaces/Database/Indexes/Indexes.tsx | 18 +++------ .../Database/Migrations/Migrations.tsx | 3 +- .../Publications/PublicationsList.tsx | 7 ++-- .../project/[ref]/database/extensions.tsx | 3 +- .../pages/project/[ref]/database/index.tsx | 3 +- .../pages/project/[ref]/database/roles.tsx | 3 +- .../functions/[functionSlug]/details.tsx | 7 ++-- .../[ref]/functions/[functionSlug]/index.tsx | 21 +++++----- .../functions/[functionSlug]/invocations.tsx | 7 ++-- .../pages/project/[ref]/functions/index.tsx | 3 +- .../pages/project/[ref]/logs/edge-logs.tsx | 8 ++-- .../project/[ref]/logs/explorer/index.tsx | 19 +++------ .../project/[ref]/logs/explorer/recent.tsx | 9 ++--- .../project/[ref]/logs/explorer/saved.tsx | 10 ++--- .../project/[ref]/logs/explorer/templates.tsx | 10 ++--- .../project/[ref]/logs/postgres-logs.tsx | 7 ++-- .../project/[ref]/logs/postgrest-logs.tsx | 11 +++-- .../project/[ref]/logs/realtime-logs.tsx | 7 ++-- .../pages/project/[ref]/logs/storage-logs.tsx | 7 ++-- .../pages/project/[ref]/reports/[id].tsx | 3 +- .../project/[ref]/reports/api-overview.tsx | 28 ++++++------- .../pages/project/[ref]/reports/database.tsx | 23 +++++------ .../[ref]/reports/query-performance.tsx | 40 +++++++++---------- 36 files changed, 175 insertions(+), 251 deletions(-) diff --git a/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx index f5018a8f60e..81079e9f98a 100644 --- a/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm/AdvancedAuthSettingsForm.tsx @@ -67,7 +67,7 @@ const AdvancedAuthSettingsForm = () => { { projectRef: projectRef!, config: payload }, { onError: (error) => { - toast.error(`Failed to update settings: ${error?.message}`) + toast.error(`Failed to update settings: ${error?.message}`) }, onSuccess: () => { toast.success('Successfully updated settings') diff --git a/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx b/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx index 21fa7bcdd8d..0b3a5bf69f0 100644 --- a/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx +++ b/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx @@ -1,25 +1,24 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { observer } from 'mobx-react-lite' +import { useParams } from 'common' import { useMemo, useState } from 'react' +import toast from 'react-hot-toast' import ReactMarkdown from 'react-markdown' import { + AlertTitle_Shadcn_, + Alert_Shadcn_, Form, IconCode, - IconMonitor, - Tabs, - Input, - Alert_Shadcn_, IconInfo, - AlertTitle_Shadcn_, + IconMonitor, + Input, + Tabs, } from 'ui' import { CodeEditor } from 'components/ui/CodeEditor' import { FormActions, FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms' import InformationBox from 'components/ui/InformationBox' - -import { useParams } from 'common' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' -import { useCheckPermissions, useStore } from 'hooks' +import { useCheckPermissions } from 'hooks' import { FormSchema } from 'types' interface TemplateEditorProps { @@ -28,7 +27,6 @@ interface TemplateEditorProps { } const TemplateEditor = ({ template, authConfig }: TemplateEditorProps) => { - const { ui } = useStore() const { ref: projectRef } = useParams() const { mutate: updateAuthConfig, isLoading: isUpdatingConfig } = useAuthConfigUpdateMutation() @@ -58,11 +56,9 @@ const TemplateEditor = ({ template, authConfig }: TemplateEditorProps) => { updateAuthConfig( { projectRef: projectRef!, config: payload }, { - onError: () => { - ui.setNotification({ category: 'error', message: 'Failed to update settings' }) - }, + onError: () => toast.error('Failed to update settings'), onSuccess: () => { - ui.setNotification({ category: 'success', message: 'Successfully updated settings' }) + toast.success('Successfully updated settings') resetForm({ values: values, initialValues: values, @@ -198,4 +194,4 @@ const TemplateEditor = ({ template, authConfig }: TemplateEditorProps) => { ) } -export default observer(TemplateEditor) +export default TemplateEditor diff --git a/apps/studio/components/interfaces/Auth/Policies/Policies.tsx b/apps/studio/components/interfaces/Auth/Policies/Policies.tsx index 83db05e4ddd..b19f715c8f9 100644 --- a/apps/studio/components/interfaces/Auth/Policies/Policies.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/Policies.tsx @@ -2,24 +2,23 @@ import type { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta' import { useParams } from 'common/hooks' import { PolicyEditorModal, PolicyTableRow } from 'components/interfaces/Auth/Policies' import { isEmpty } from 'lodash' -import { observer } from 'mobx-react-lite' import { useRouter } from 'next/router' import { useCallback, useState } from 'react' import toast from 'react-hot-toast' import { IconHelpCircle } from 'ui' import { useIsRLSAIAssistantEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import ProtectedSchemaWarning from 'components/interfaces/Database/ProtectedSchemaWarning' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' -import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' import InformationBox from 'components/ui/InformationBox' import { useDatabasePolicyCreateMutation } from 'data/database-policies/database-policy-create-mutation' import { useDatabasePolicyDeleteMutation } from 'data/database-policies/database-policy-delete-mutation' import { useDatabasePolicyUpdateMutation } from 'data/database-policies/database-policy-update-mutation' import { useTableUpdateMutation } from 'data/tables/table-update-mutation' -import ProtectedSchemaWarning from 'components/interfaces/Database/ProtectedSchemaWarning' import { useTableEditorStateSnapshot } from 'state/table-editor' +import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' interface PoliciesProps { tables: PostgresTable[] @@ -270,4 +269,4 @@ const Policies = ({ ) } -export default observer(Policies) +export default Policies diff --git a/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx b/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx index a412b17085e..cb42bf3df7b 100644 --- a/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx +++ b/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx @@ -1,7 +1,9 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { observer } from 'mobx-react-lite' +import { useParams } from 'common' +import Link from 'next/link' import { useMemo, useState } from 'react' +import toast from 'react-hot-toast' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -15,19 +17,16 @@ import { } from 'ui' import { object, string } from 'yup' -import { useParams } from 'common' import { FormHeader } from 'components/ui/Forms' import { HorizontalShimmerWithIcon } from 'components/ui/Shimmers' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' -import { useCheckPermissions, useStore } from 'hooks' +import { useCheckPermissions } from 'hooks' import { urlRegex } from '../Auth.constants' import RedirectUrlList from './RedirectUrlList' import ValueContainer from './ValueContainer' -import Link from 'next/link' const RedirectUrls = () => { - const { ui } = useStore() const { ref: projectRef } = useParams() const { data: authConfig, @@ -65,26 +64,18 @@ const RedirectUrls = () => { const payloadString = payload.toString() if (payloadString.length > 2 * 1024) { - ui.setNotification({ - message: 'Too many redirect URLs, please remove some or try to use wildcards', - category: 'error', - }) - return + return toast.error('Too many redirect URLs, please remove some or try to use wildcards') } updateAuthConfig( { projectRef: projectRef!, config: { URI_ALLOW_LIST: payloadString } }, { onError: (error) => { - ui.setNotification({ - error, - category: 'error', - message: `Failed to update URL: ${error?.message}`, - }) + toast.error(`Failed to update URL: ${error?.message}`) }, onSuccess: () => { setOpen(false) - ui.setNotification({ category: 'success', message: 'Successfully added URL' }) + toast.success('Successfully added URL') }, } ) @@ -100,15 +91,11 @@ const RedirectUrls = () => { { projectRef: projectRef!, config: { URI_ALLOW_LIST: payload.toString() } }, { onError: (error) => { - ui.setNotification({ - error, - category: 'error', - message: `Failed to remove URL: ${error?.message}`, - }) + toast.error(`Failed to remove URL: ${error?.message}`) }, onSuccess: () => { setSelectedUrlToDelete(undefined) - ui.setNotification({ category: 'success', message: 'Successfully removed URL' }) + toast.success('Successfully removed URL') }, } ) @@ -269,4 +256,4 @@ const RedirectUrls = () => { ) } -export default observer(RedirectUrls) +export default RedirectUrls diff --git a/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx b/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx index 92082f01493..b1d1a85a1a6 100644 --- a/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx +++ b/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx @@ -1,7 +1,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' -import { observer } from 'mobx-react-lite' import { useEffect } from 'react' +import toast from 'react-hot-toast' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -21,14 +21,13 @@ import { } from 'components/ui/Forms' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' -import { useCheckPermissions, useStore } from 'hooks' +import { useCheckPermissions } from 'hooks' const schema = object({ SITE_URL: string().required('Must have a Site URL'), }) -const SiteUrl = observer(() => { - const { ui } = useStore() +const SiteUrl = () => { const { ref: projectRef } = useParams() const { data: authConfig, @@ -50,16 +49,10 @@ const SiteUrl = observer(() => { { projectRef: projectRef!, config: payload }, { onError: () => { - ui.setNotification({ - category: 'error', - message: `Failed to update settings`, - }) + toast.error('Failed to update settings') }, onSuccess: () => { - ui.setNotification({ - category: 'success', - message: `Successfully updated settings`, - }) + toast.success('Successfully updated settings') resetForm({ values: values, initialValues: values }) }, } @@ -82,6 +75,7 @@ const SiteUrl = observer(() => { const hasChanges = JSON.stringify(values) !== JSON.stringify(initialValues) // Form is reset once remote data is loaded in store + // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { if (isSuccess) { resetForm({ values: INITIAL_VALUES, initialValues: INITIAL_VALUES }) @@ -124,6 +118,6 @@ const SiteUrl = observer(() => { }} ) -}) +} export default SiteUrl diff --git a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx index 5993368581e..f7197f87c0b 100644 --- a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx +++ b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx @@ -1,7 +1,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { observer } from 'mobx-react-lite' +import { useParams } from 'common' import { useEffect, useState } from 'react' - +import toast from 'react-hot-toast' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -18,7 +18,7 @@ import { } from 'ui' import { number, object, string } from 'yup' -import { useParams } from 'common' +import { Markdown } from 'components/interfaces/Markdown' import { FormActions, FormHeader, @@ -29,15 +29,13 @@ import { } from 'components/ui/Forms' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' -import { useCheckPermissions, useStore } from 'hooks' +import { useCheckPermissions } from 'hooks' import EmailRateLimitsAlert from '../EmailRateLimitsAlert' import { urlRegex } from './../Auth.constants' import { defaultDisabledSmtpFormValues } from './SmtpForm.constants' import { generateFormValues, isSmtpEnabled } from './SmtpForm.utils' -import { Markdown } from 'components/interfaces/Markdown' const SmtpForm = () => { - const { ui } = useStore() const { ref: projectRef } = useParams() const { data: authConfig, @@ -135,13 +133,13 @@ const SmtpForm = () => { { projectRef: projectRef!, config: payload }, { onError: (error) => { - ui.setNotification({ category: 'error', message: 'Failed to update settings', error }) + toast.error(`Failed to update settings: ${error.message}`) }, onSuccess: () => { setHidden(true) + toast.success('Successfully updated settings') const updatedFormValues = generateFormValues(payload) resetForm({ values: updatedFormValues, initialValues: updatedFormValues }) - ui.setNotification({ category: 'success', message: 'Successfully updated settings' }) }, } ) @@ -346,4 +344,4 @@ const SmtpForm = () => { ) } -export default observer(SmtpForm) +export default SmtpForm diff --git a/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx b/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx index 2f90c58b38e..c0d7616693d 100644 --- a/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx +++ b/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx @@ -1,11 +1,11 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' -import { observer } from 'mobx-react-lite' +import toast from 'react-hot-toast' import { Button, Checkbox, Form, IconLock, IconMail, Input, Loading, Modal } from 'ui' import { useUserCreateMutation } from 'data/auth/user-create-mutation' import { useProjectApiQuery } from 'data/config/project-api-query' -import { useCheckPermissions, useStore } from 'hooks' +import { useCheckPermissions } from 'hooks' export type CreateUserModalProps = { visible: boolean @@ -13,7 +13,6 @@ export type CreateUserModalProps = { } const CreateUserModal = ({ visible, setVisible }: CreateUserModalProps) => { - const { ui } = useStore() const { ref: projectRef } = useParams() const { data, isLoading, isSuccess } = useProjectApiQuery({ projectRef }, { enabled: visible }) @@ -41,22 +40,15 @@ const CreateUserModal = ({ visible, setVisible }: CreateUserModalProps) => { const { mutate: createUser, isLoading: isCreatingUser } = useUserCreateMutation({ async onSuccess(res) { - ui.setNotification({ - category: 'success', - message: `Successfully created user: ${res.email}`, - }) + toast.success(`Successfully created user: ${res.email}`) setVisible(false) }, }) const onCreateUser = async (values: any) => { if (!isSuccess) { - return ui.setNotification({ - category: 'error', - message: `Failed to create user: Error loading project config`, - }) + return toast.error(`Failed to create user: Error loading project config`) } - const { protocol, endpoint, serviceApiKey } = data.autoApiService createUser({ projectRef, endpoint, protocol, serviceApiKey, user: values }) } @@ -137,4 +129,4 @@ const CreateUserModal = ({ visible, setVisible }: CreateUserModalProps) => { ) } -export default observer(CreateUserModal) +export default CreateUserModal diff --git a/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx b/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx index 6d3d14a012e..d8eb4c08efa 100644 --- a/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx +++ b/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx @@ -1,10 +1,10 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' -import { observer } from 'mobx-react-lite' +import toast from 'react-hot-toast' import { Button, Form, IconMail, Input, Modal } from 'ui' import { useUserInviteMutation } from 'data/auth/user-invite-mutation' -import { useCheckPermissions, useStore } from 'hooks' +import { useCheckPermissions } from 'hooks' export type InviteUserModalProps = { visible: boolean @@ -12,7 +12,6 @@ export type InviteUserModalProps = { } const InviteUserModal = ({ visible, setVisible }: InviteUserModalProps) => { - const { ui } = useStore() const { ref: projectRef } = useParams() const handleToggle = () => setVisible(!visible) @@ -37,7 +36,7 @@ const InviteUserModal = ({ visible, setVisible }: InviteUserModalProps) => { if (!projectRef) return console.error('Project ref is required') await inviteUser({ projectRef, email: values.email }) - ui.setNotification({ category: 'success', message: `Sent invite email to ${values.email}` }) + toast.success(`Sent invite email to ${values.email}`) setVisible(false) } @@ -91,4 +90,4 @@ const InviteUserModal = ({ visible, setVisible }: InviteUserModalProps) => { ) } -export default observer(InviteUserModal) +export default InviteUserModal diff --git a/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx b/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx index 6039e4b2026..cf631b5419b 100644 --- a/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx +++ b/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx @@ -1,26 +1,25 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useQueryClient } from '@tanstack/react-query' import dayjs from 'dayjs' -import { observer } from 'mobx-react-lite' import { useRouter } from 'next/router' import { useState } from 'react' +import toast from 'react-hot-toast' import { IconAlertCircle, IconClock, Modal } from 'ui' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import InformationBox from 'components/ui/InformationBox' import Panel from 'components/ui/Panel' import UpgradeToPro from 'components/ui/UpgradeToPro' import { useBackupRestoreMutation } from 'data/database/backup-restore-mutation' import { DatabaseBackup, useBackupsQuery } from 'data/database/backups-query' import { setProjectStatus } from 'data/projects/projects-query' -import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization } from 'hooks' import { PROJECT_STATUS } from 'lib/constants' import BackupItem from './BackupItem' import BackupsEmpty from './BackupsEmpty' const BackupsList = () => { - const { ui } = useStore() const router = useRouter() const queryClient = useQueryClient() const organization = useSelectedOrganization() @@ -45,12 +44,11 @@ const BackupsList = () => { onSuccess: () => { setTimeout(() => { setProjectStatus(queryClient, projectRef, PROJECT_STATUS.RESTORING) - ui.setNotification({ - category: 'success', - message: `Restoring database back to ${dayjs(selectedBackup?.inserted_at).format( + toast.success( + `Restoring database back to ${dayjs(selectedBackup?.inserted_at).format( 'DD MMM YYYY HH:mm:ss' - )}`, - }) + )}` + ) router.push(`/project/${projectRef}`) }, 3000) }, @@ -134,4 +132,4 @@ const BackupsList = () => { ) } -export default observer(BackupsList) +export default BackupsList diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx b/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx index 5d13dee4588..ca0a413309e 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx +++ b/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx @@ -1,10 +1,9 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import dayjs from 'dayjs' -import { observer } from 'mobx-react-lite' -import { Button, IconAlertCircle } from 'ui' - import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' +import dayjs from 'dayjs' +import { Button, IconAlertCircle } from 'ui' + import { FormPanel } from 'components/ui/Forms' import { useBackupsQuery } from 'data/database/backups-query' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' @@ -118,4 +117,4 @@ const PITRStatus = ({ ) } -export default observer(PITRStatus) +export default PITRStatus diff --git a/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx b/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx index 0e89c53aa22..d9911285bc5 100644 --- a/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx +++ b/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx @@ -1,13 +1,12 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { observer } from 'mobx-react-lite' import Link from 'next/link' import { useState } from 'react' import toast from 'react-hot-toast' import { extensions } from 'shared-data' import { Badge, IconExternalLink, IconLoader, Modal, Toggle } from 'ui' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useDatabaseExtensionDisableMutation } from 'data/database-extensions/database-extension-disable-mutation' import { useCheckPermissions } from 'hooks' import EnableExtensionModal from './EnableExtensionModal' @@ -156,4 +155,4 @@ const ExtensionCard = ({ extension }: ExtensionCardProps) => { ) } -export default observer(ExtensionCard) +export default ExtensionCard diff --git a/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx b/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx index 16afe06e42b..65ebcfbca1c 100644 --- a/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx +++ b/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx @@ -1,7 +1,6 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { isNull, partition } from 'lodash' -import { observer } from 'mobx-react-lite' import Link from 'next/link' import { useEffect, useState } from 'react' import { Button, IconAlertCircle, IconExternalLink, IconSearch, Input } from 'ui' @@ -131,4 +130,4 @@ const Extensions = () => { ) } -export default observer(Extensions) +export default Extensions diff --git a/apps/studio/components/interfaces/Database/Hooks/HooksList/SchemaTable.tsx b/apps/studio/components/interfaces/Database/Hooks/HooksList/SchemaTable.tsx index a02e2c35477..52e0f48afdc 100644 --- a/apps/studio/components/interfaces/Database/Hooks/HooksList/SchemaTable.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/HooksList/SchemaTable.tsx @@ -1,5 +1,4 @@ import { noop } from 'lodash' -import { observer } from 'mobx-react-lite' import Table from 'components/to-be-cleaned/Table' import HookList from './HookList' @@ -57,4 +56,4 @@ const SchemaTable = ({ ) } -export default observer(SchemaTable) +export default SchemaTable diff --git a/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx b/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx index d484b737872..08a58863830 100644 --- a/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx +++ b/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx @@ -1,6 +1,7 @@ -import { observer } from 'mobx-react-lite' +import { partition, sortBy } from 'lodash' import Link from 'next/link' import { useState } from 'react' +import toast from 'react-hot-toast' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -15,25 +16,22 @@ import { Modal, SidePanel, } from 'ui' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { CodeEditor } from 'components/ui/CodeEditor' -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import SchemaSelector from 'components/ui/SchemaSelector' import ShimmeringLoader, { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { DatabaseIndex, useIndexesQuery } from 'data/database/indexes-query' import { useSchemasQuery } from 'data/database/schemas-query' import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation' -import { useStore } from 'hooks' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' -import { partition, sortBy } from 'lodash' import ProtectedSchemaWarning from '../ProtectedSchemaWarning' import CreateIndexSidePanel from './CreateIndexSidePanel' const Indexes = () => { - const { ui } = useStore() const [search, setSearch] = useState('') const [selectedSchema, setSelectedSchema] = useState('public') const [showCreateIndex, setShowCreateIndex] = useState(false) @@ -67,14 +65,10 @@ const Indexes = () => { onSuccess() { refetchIndexes() setSelectedIndexToDelete(undefined) - ui.setNotification({ category: 'success', message: `Successfully deleted index` }) + toast.success('Successfully deleted index') }, onError(error) { - ui.setNotification({ - error, - category: 'error', - message: `Failed to delete index: ${error.message}`, - }) + toast.error(`Failed to delete index: ${error.message}`) }, }) @@ -317,4 +311,4 @@ const Indexes = () => { ) } -export default observer(Indexes) +export default Indexes diff --git a/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx b/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx index 66154aec7d0..d752098009c 100644 --- a/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx +++ b/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx @@ -1,5 +1,4 @@ import dayjs from 'dayjs' -import { observer } from 'mobx-react-lite' import Link from 'next/link' import { useState } from 'react' import { Alert, Button, IconExternalLink, IconSearch, Input, SidePanel } from 'ui' @@ -184,4 +183,4 @@ const Migrations = () => { ) } -export default observer(Migrations) +export default Migrations diff --git a/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx b/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx index 30144e83c58..c4bfac6985b 100644 --- a/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx +++ b/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx @@ -1,19 +1,18 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { noop } from 'lodash' -import { observer } from 'mobx-react-lite' import { useState } from 'react' +import toast from 'react-hot-toast' import { Button, IconAlertCircle, IconSearch, Input, Modal, Toggle } from 'ui' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' -import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import InformationBox from 'components/ui/InformationBox' import NoSearchResults from 'components/ui/NoSearchResults' import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query' import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' import PublicationSkeleton from './PublicationSkeleton' -import toast from 'react-hot-toast' interface PublicationEvent { event: string @@ -194,4 +193,4 @@ const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) ) } -export default observer(PublicationsList) +export default PublicationsList diff --git a/apps/studio/pages/project/[ref]/database/extensions.tsx b/apps/studio/pages/project/[ref]/database/extensions.tsx index ad065520d52..171528d9333 100644 --- a/apps/studio/pages/project/[ref]/database/extensions.tsx +++ b/apps/studio/pages/project/[ref]/database/extensions.tsx @@ -1,5 +1,4 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { observer } from 'mobx-react-lite' import { Extensions } from 'components/interfaces/Database' import { DatabaseLayout } from 'components/layouts' @@ -33,4 +32,4 @@ const DatabaseExtensions: NextPageWithLayout = () => { DatabaseExtensions.getLayout = (page) => {page} -export default observer(DatabaseExtensions) +export default DatabaseExtensions diff --git a/apps/studio/pages/project/[ref]/database/index.tsx b/apps/studio/pages/project/[ref]/database/index.tsx index f9b30878a65..e5d224ba985 100644 --- a/apps/studio/pages/project/[ref]/database/index.tsx +++ b/apps/studio/pages/project/[ref]/database/index.tsx @@ -1,4 +1,3 @@ -import { observer } from 'mobx-react-lite' import { DatabaseLayout } from 'components/layouts' import { NextPageWithLayout } from 'types' @@ -8,4 +7,4 @@ const Database: NextPageWithLayout = () => { Database.getLayout = (page) => {page} -export default observer(Database) +export default Database diff --git a/apps/studio/pages/project/[ref]/database/roles.tsx b/apps/studio/pages/project/[ref]/database/roles.tsx index ba495a30cd0..133f57e796e 100644 --- a/apps/studio/pages/project/[ref]/database/roles.tsx +++ b/apps/studio/pages/project/[ref]/database/roles.tsx @@ -1,7 +1,6 @@ import { RolesList } from 'components/interfaces/Database' import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' -import { observer } from 'mobx-react-lite' import { NextPageWithLayout } from 'types' const DatabaseRoles: NextPageWithLayout = () => { @@ -18,4 +17,4 @@ const DatabaseRoles: NextPageWithLayout = () => { DatabaseRoles.getLayout = (page) => {page} -export default observer(DatabaseRoles) +export default DatabaseRoles diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx index 5ffb3c78c33..030918419f7 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx @@ -1,9 +1,8 @@ -import { observer } from 'mobx-react-lite' -import { NextPageWithLayout } from 'types' -import FunctionsLayout from 'components/layouts/FunctionsLayout' import { EdgeFunctionDetails } from 'components/interfaces/Functions' +import FunctionsLayout from 'components/layouts/FunctionsLayout' +import { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => PageLayout.getLayout = (page) => {page} -export default observer(PageLayout) +export default PageLayout diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx index f1d6be714cf..1ddd875a970 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx @@ -1,24 +1,23 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useParams } from 'common/hooks' +import { useParams } from 'common' +import dayjs, { Dayjs } from 'dayjs' +import meanBy from 'lodash/meanBy' +import sumBy from 'lodash/sumBy' +import { useRouter } from 'next/router' +import { useMemo, useState } from 'react' +import { Button } from 'ui' + import ReportWidget from 'components/interfaces/Reports/ReportWidget' import FunctionsLayout from 'components/layouts/FunctionsLayout' import AreaChart from 'components/ui/Charts/AreaChart' -import BarChart from 'components/ui/Charts/BarChart' import StackedBarChart from 'components/ui/Charts/StackedBarChart' import NoPermission from 'components/ui/NoPermission' import { useFunctionsReqStatsQuery } from 'data/analytics/functions-req-stats-query' import { useFunctionsResourceUsageQuery } from 'data/analytics/functions-resource-usage-query' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' -import dayjs, { Dayjs } from 'dayjs' -import { useCheckPermissions, useFlag } from 'hooks' +import { useCheckPermissions } from 'hooks' import useFillTimeseriesSorted from 'hooks/analytics/useFillTimeseriesSorted' -import sumBy from 'lodash/sumBy' -import meanBy from 'lodash/meanBy' -import { observer } from 'mobx-react-lite' -import { useRouter } from 'next/router' -import { useMemo, useState } from 'react' import { ChartIntervals, NextPageWithLayout } from 'types' -import { Button } from 'ui' const CHART_INTERVALS: ChartIntervals[] = [ { @@ -281,4 +280,4 @@ const PageLayout: NextPageWithLayout = () => { PageLayout.getLayout = (page) => {page} -export default observer(PageLayout) +export default PageLayout diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx index 16e179787e9..409d295fb8a 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx @@ -1,10 +1,9 @@ -import { observer } from 'mobx-react-lite' +import { useParams } from 'common' -import { NextPageWithLayout } from 'types' -import { useParams } from 'common/hooks' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import FunctionsLayout from 'components/layouts/FunctionsLayout' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' +import { NextPageWithLayout } from 'types' /** * Placeholder page for logs previewers until we figure out where to slot them @@ -29,4 +28,4 @@ export const LogPage: NextPageWithLayout = () => { LogPage.getLayout = (page) => {page} -export default observer(LogPage) +export default LogPage diff --git a/apps/studio/pages/project/[ref]/functions/index.tsx b/apps/studio/pages/project/[ref]/functions/index.tsx index c1f42d31df0..fb4755a8794 100644 --- a/apps/studio/pages/project/[ref]/functions/index.tsx +++ b/apps/studio/pages/project/[ref]/functions/index.tsx @@ -1,5 +1,4 @@ import { useParams } from 'common' -import { observer } from 'mobx-react-lite' import { useState } from 'react' import { Button, Modal } from 'ui' @@ -97,4 +96,4 @@ const PageLayout: NextPageWithLayout = () => { PageLayout.getLayout = (page) => {page} -export default observer(PageLayout) +export default PageLayout diff --git a/apps/studio/pages/project/[ref]/logs/edge-logs.tsx b/apps/studio/pages/project/[ref]/logs/edge-logs.tsx index f414db60935..94fc37d0a85 100644 --- a/apps/studio/pages/project/[ref]/logs/edge-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/edge-logs.tsx @@ -1,10 +1,8 @@ -import React from 'react' import { useRouter } from 'next/router' -import { observer } from 'mobx-react-lite' -import { LogsLayout } from 'components/layouts' + import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' +import { LogsLayout } from 'components/layouts' import { NextPageWithLayout } from 'types' -import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' export const LogPage: NextPageWithLayout = () => { const router = useRouter() @@ -23,4 +21,4 @@ export const LogPage: NextPageWithLayout = () => { LogPage.getLayout = (page) => {page} -export default observer(LogPage) +export default LogPage diff --git a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx index 20f817a898b..0980bc94b3c 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx @@ -1,8 +1,8 @@ import { useParams } from 'common/hooks' import dayjs from 'dayjs' -import { observer } from 'mobx-react-lite' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' +import toast from 'react-hot-toast' import { Button, Form, @@ -32,7 +32,7 @@ import LoadingOpacity from 'components/ui/LoadingOpacity' import ShimmerLine from 'components/ui/ShimmerLine' import { useContentInsertMutation } from 'data/content/content-insert-mutation' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { useLocalStorage, useSelectedOrganization, useStore } from 'hooks' +import { useLocalStorage, useSelectedOrganization } from 'hooks' import useLogsQuery from 'hooks/analytics/useLogsQuery' import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt' import { LOCAL_STORAGE_KEYS } from 'lib/constants' @@ -41,9 +41,9 @@ import { LogSqlSnippets, NextPageWithLayout } from 'types' const PLACEHOLDER_QUERY = 'select\n cast(timestamp as datetime) as timestamp,\n event_message, metadata \nfrom edge_logs \nlimit 5' + export const LogsExplorerPage: NextPageWithLayout = () => { useEditorHints() - const { ui } = useStore() const router = useRouter() const { ref: projectRef, q, ite, its } = useParams() const organization = useSelectedOrganization() @@ -179,18 +179,11 @@ export const LogsExplorerPage: NextPageWithLayout = () => { const error = e as { message: string } console.error(error) setSaveModalOpen(false) - ui.setNotification({ - error, - category: 'error', - message: `Failed to save query: ${error.message}`, - }) + toast.error(`Failed to save query: ${error.message}`) }, onSuccess: (values) => { setSaveModalOpen(false) - ui.setNotification({ - category: 'success', - message: `Saved "${values[0].name}" log query`, - }) + toast.success(`Saved "${values[0].name}" log query`) }, }) @@ -327,4 +320,4 @@ export const LogsExplorerPage: NextPageWithLayout = () => { LogsExplorerPage.getLayout = (page) => {page} -export default observer(LogsExplorerPage) +export default LogsExplorerPage diff --git a/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx b/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx index bd7645e5e1f..23f0851b43b 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx @@ -1,14 +1,13 @@ -import { observer } from 'mobx-react-lite' -import Link from 'next/link' - import { useParams } from 'common' +import Link from 'next/link' +import { Button, IconClock } from 'ui' + import RecentQueriesItem from 'components/interfaces/Settings/Logs/RecentQueriesItem' import LogsLayout from 'components/layouts/LogsLayout/LogsLayout' import Table from 'components/to-be-cleaned/Table' import LogsExplorerHeader from 'components/ui/Logs/LogsExplorerHeader' import { useLocalStorage } from 'hooks' import { LogSqlSnippets, NextPageWithLayout } from 'types' -import { Button, IconClock } from 'ui' export const LogsSavedPage: NextPageWithLayout = () => { const { ref } = useParams() @@ -60,4 +59,4 @@ export const LogsSavedPage: NextPageWithLayout = () => { LogsSavedPage.getLayout = (page) => {page} -export default observer(LogsSavedPage) +export default LogsSavedPage diff --git a/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx b/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx index 30f443134ee..6b121f1ae30 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx @@ -1,18 +1,16 @@ -import { observer } from 'mobx-react-lite' -import Link from 'next/link' - import { useParams } from 'common' +import Link from 'next/link' +import { IconSave, Loading } from 'ui' + import { LogsSavedQueriesItem } from 'components/interfaces/Settings/Logs' import { LogsLayout } from 'components/layouts' import Table from 'components/to-be-cleaned/Table' import LogsExplorerHeader from 'components/ui/Logs/LogsExplorerHeader' import { useContentQuery } from 'data/content/content-query' import { NextPageWithLayout } from 'types' -import { IconSave, Loading } from 'ui' export const LogsSavedPage: NextPageWithLayout = () => { const { ref } = useParams() - const { data, isLoading } = useContentQuery(ref) if (isLoading) { @@ -63,4 +61,4 @@ export const LogsSavedPage: NextPageWithLayout = () => { LogsSavedPage.getLayout = (page) => {page} -export default observer(LogsSavedPage) +export default LogsSavedPage diff --git a/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx b/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx index 320e8643f9f..59e3814d89b 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx @@ -1,12 +1,12 @@ -import React, { useState } from 'react' -import { observer } from 'mobx-react-lite' import { useParams } from 'common' -import { IconCode, Button, Popover } from 'ui' +import { useState } from 'react' +import { Button, IconCode, Popover } from 'ui' + import { LogTemplate, TEMPLATES } from 'components/interfaces/Settings/Logs' import LogsLayout from 'components/layouts/LogsLayout/LogsLayout' import CardButton from 'components/ui/CardButton' -import { NextPageWithLayout } from 'types' import LogsExplorerHeader from 'components/ui/Logs/LogsExplorerHeader' +import { NextPageWithLayout } from 'types' export const LogsTemplatesPage: NextPageWithLayout = () => { const { ref: projectRef } = useParams() @@ -27,7 +27,7 @@ export const LogsTemplatesPage: NextPageWithLayout = () => { LogsTemplatesPage.getLayout = (page) => {page} -export default observer(LogsTemplatesPage) +export default LogsTemplatesPage const Template = ({ projectRef, template }: { projectRef?: string; template: LogTemplate }) => { const [showPreview, setShowPreview] = useState(false) diff --git a/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx b/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx index 147cae85344..796854e036d 100644 --- a/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx @@ -1,8 +1,7 @@ -import React from 'react' import { useRouter } from 'next/router' -import { observer } from 'mobx-react-lite' -import { LogsLayout } from 'components/layouts' + import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' +import { LogsLayout } from 'components/layouts' import { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { @@ -22,4 +21,4 @@ export const LogPage: NextPageWithLayout = () => { LogPage.getLayout = (page) => {page} -export default observer(LogPage) +export default LogPage diff --git a/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx b/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx index cd31e9f66c9..e3499994612 100644 --- a/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx @@ -1,10 +1,9 @@ -import React from 'react' import { useRouter } from 'next/router' -import { observer } from 'mobx-react-lite' -import { LogsLayout } from 'components/layouts' -import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' -import { NextPageWithLayout } from 'types' + import { LogsTableName } from 'components/interfaces/Settings/Logs' +import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' +import { LogsLayout } from 'components/layouts' +import { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { const router = useRouter() @@ -22,4 +21,4 @@ export const LogPage: NextPageWithLayout = () => { LogPage.getLayout = (page) => {page} -export default observer(LogPage) +export default LogPage diff --git a/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx b/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx index 456398eebcd..06a216fad65 100644 --- a/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx @@ -1,8 +1,7 @@ -import React from 'react' import { useRouter } from 'next/router' -import { observer } from 'mobx-react-lite' -import { LogsLayout } from 'components/layouts' + import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' +import { LogsLayout } from 'components/layouts' import { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { @@ -22,4 +21,4 @@ export const LogPage: NextPageWithLayout = () => { LogPage.getLayout = (page) => {page} -export default observer(LogPage) +export default LogPage diff --git a/apps/studio/pages/project/[ref]/logs/storage-logs.tsx b/apps/studio/pages/project/[ref]/logs/storage-logs.tsx index 13246819592..40b8ee28b31 100644 --- a/apps/studio/pages/project/[ref]/logs/storage-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/storage-logs.tsx @@ -1,8 +1,7 @@ -import React from 'react' import { useRouter } from 'next/router' -import { observer } from 'mobx-react-lite' -import { LogsLayout } from 'components/layouts' + import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' +import { LogsLayout } from 'components/layouts' import { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { @@ -22,4 +21,4 @@ export const LogPage: NextPageWithLayout = () => { LogPage.getLayout = (page) => {page} -export default observer(LogPage) +export default LogPage diff --git a/apps/studio/pages/project/[ref]/reports/[id].tsx b/apps/studio/pages/project/[ref]/reports/[id].tsx index 9d61091362b..05069cb2c68 100644 --- a/apps/studio/pages/project/[ref]/reports/[id].tsx +++ b/apps/studio/pages/project/[ref]/reports/[id].tsx @@ -1,7 +1,6 @@ import Reports from 'components/interfaces/Reports/Reports' import { ReportsLayout } from 'components/layouts' import EditReportModal from 'components/to-be-cleaned/Reports/EditReportModal' -import { observer } from 'mobx-react-lite' import { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => ( @@ -15,4 +14,4 @@ const PageLayout: NextPageWithLayout = () => ( PageLayout.getLayout = (page) => {page} -export default observer(PageLayout) +export default PageLayout diff --git a/apps/studio/pages/project/[ref]/reports/api-overview.tsx b/apps/studio/pages/project/[ref]/reports/api-overview.tsx index 66cc691e317..3e3abb54d1b 100644 --- a/apps/studio/pages/project/[ref]/reports/api-overview.tsx +++ b/apps/studio/pages/project/[ref]/reports/api-overview.tsx @@ -1,34 +1,34 @@ -import { observer } from 'mobx-react-lite' +import { useParams } from 'common' +import { isEqual } from 'lodash' +import { useEffect, useState } from 'react' import { NextPageWithLayout } from 'types' -import { ReportFilterItem } from 'components/interfaces/Reports/Reports.types' -import { ReportsLayout } from 'components/layouts' + +import ReportFilterBar from 'components/interfaces/Reports/ReportFilterBar' +import ReportHeader from 'components/interfaces/Reports/ReportHeader' +import ReportPadding from 'components/interfaces/Reports/ReportPadding' +import ReportWidget from 'components/interfaces/Reports/ReportWidget' import { PRESET_CONFIG, REPORTS_DATEPICKER_HELPERS, } from 'components/interfaces/Reports/Reports.constants' -import ReportWidget from 'components/interfaces/Reports/ReportWidget' +import { ReportFilterItem } from 'components/interfaces/Reports/Reports.types' import { queriesFactory } from 'components/interfaces/Reports/Reports.utils' import { - TotalRequestsChartRenderer, ErrorCountsChartRenderer, + NetworkTrafficRenderer, ResponseSpeedChartRenderer, TopApiRoutesRenderer, - NetworkTrafficRenderer, + TotalRequestsChartRenderer, } from 'components/interfaces/Reports/renderers/ApiRenderers' -import { useState, useEffect } from 'react' -import ReportHeader from 'components/interfaces/Reports/ReportHeader' import { DatePickerToFrom, LogsEndpointParams } from 'components/interfaces/Settings/Logs' -import ReportFilterBar from 'components/interfaces/Reports/ReportFilterBar' -import { useParams } from 'common' -import { isEqual } from 'lodash' +import { ReportsLayout } from 'components/layouts' import ShimmerLine from 'components/ui/ShimmerLine' -import ReportPadding from 'components/interfaces/Reports/ReportPadding' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useSelectedOrganization } from 'hooks' export const ApiReport: NextPageWithLayout = () => { - const organization = useSelectedOrganization() const report = useApiReport() + const organization = useSelectedOrganization() const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: organization?.slug }) const plan = subscription?.plan @@ -223,4 +223,4 @@ const useApiReport = () => { ApiReport.getLayout = (page) => {page} -export default observer(ApiReport) +export default ApiReport diff --git a/apps/studio/pages/project/[ref]/reports/database.tsx b/apps/studio/pages/project/[ref]/reports/database.tsx index a370f3d6eca..08308123808 100644 --- a/apps/studio/pages/project/[ref]/reports/database.tsx +++ b/apps/studio/pages/project/[ref]/reports/database.tsx @@ -1,11 +1,7 @@ import { useParams } from 'common/hooks' import dayjs from 'dayjs' -import { observer } from 'mobx-react-lite' +import Link from 'next/link' import { useState } from 'react' - -import { TIME_PERIODS_INFRA } from 'lib/constants/metrics' -import { formatBytes } from 'lib/helpers' -import { NextPageWithLayout } from 'types' import { AlertDescription_Shadcn_, Alert_Shadcn_, @@ -14,18 +10,20 @@ import { IconExternalLink, } from 'ui' +import ReportWidget from 'components/interfaces/Reports/ReportWidget' +import { PRESET_CONFIG } from 'components/interfaces/Reports/Reports.constants' +import { queriesFactory } from 'components/interfaces/Reports/Reports.utils' import { ReportsLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ChartHandler from 'components/to-be-cleaned/Charts/ChartHandler' import DateRangePicker from 'components/to-be-cleaned/DateRangePicker' +import Table from 'components/to-be-cleaned/Table' import Panel from 'components/ui/Panel' import { useDatabaseSizeQuery } from 'data/database/database-size-query' -import ReportWidget from 'components/interfaces/Reports/ReportWidget' -import { queriesFactory } from 'components/interfaces/Reports/Reports.utils' -import { PRESET_CONFIG } from 'components/interfaces/Reports/Reports.constants' -import Table from 'components/to-be-cleaned/Table' -import Link from 'next/link' import { DbQueryHook } from 'hooks/analytics/useDbQuery' +import { TIME_PERIODS_INFRA } from 'lib/constants/metrics' +import { formatBytes } from 'lib/helpers' +import { NextPageWithLayout } from 'types' const DatabaseReport: NextPageWithLayout = () => { return ( @@ -43,9 +41,8 @@ DatabaseReport.getLayout = (page) => {page} { +const DatabaseUsage = () => { const { project } = useProjectContext() - const [dateRange, setDateRange] = useState(undefined) const { data } = useDatabaseSizeQuery({ @@ -223,7 +220,7 @@ const DatabaseUsage = observer(() => { ) -}) +} const useDatabaseReport = () => { const { ref: projectRef } = useParams() diff --git a/apps/studio/pages/project/[ref]/reports/query-performance.tsx b/apps/studio/pages/project/[ref]/reports/query-performance.tsx index 3c6a5f9921b..224d28e89ac 100644 --- a/apps/studio/pages/project/[ref]/reports/query-performance.tsx +++ b/apps/studio/pages/project/[ref]/reports/query-performance.tsx @@ -1,24 +1,8 @@ import { useParams } from 'common' -import ReportHeader from 'components/interfaces/Reports/ReportHeader' -import ReportQueryPerformanceTableRow from 'components/interfaces/Reports/ReportQueryPerformanceTableRow' -import { PRESET_CONFIG } from 'components/interfaces/Reports/Reports.constants' -import { useQueryPerformanceQuery } from 'components/interfaces/Reports/Reports.queries' -import { Presets } from 'components/interfaces/Reports/Reports.types' -import { queriesFactory } from 'components/interfaces/Reports/Reports.utils' -import { ReportsLayout } from 'components/layouts' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import Table from 'components/to-be-cleaned/Table' -import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' -import ShimmeringLoader from 'components/ui/ShimmeringLoader' -import { executeSql } from 'data/sql/execute-sql-query' -import { useFlag } from 'hooks' -import { sortBy } from 'lodash' -import { observer } from 'mobx-react-lite' import Link from 'next/link' import { useRouter } from 'next/router' import { useState } from 'react' import ReactMarkdown from 'react-markdown' -import { NextPageWithLayout } from 'types' import { Accordion, Button, @@ -31,21 +15,37 @@ import { IconArrowDown, IconArrowUp, IconCheckCircle, - IconList, IconRefreshCw, IconSearch, Input, Tabs, } from 'ui' +import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' + +import ReportHeader from 'components/interfaces/Reports/ReportHeader' +import ReportQueryPerformanceTableRow from 'components/interfaces/Reports/ReportQueryPerformanceTableRow' +import { PRESET_CONFIG } from 'components/interfaces/Reports/Reports.constants' +import { useQueryPerformanceQuery } from 'components/interfaces/Reports/Reports.queries' +import { Presets } from 'components/interfaces/Reports/Reports.types' +import { queriesFactory } from 'components/interfaces/Reports/Reports.utils' +import { ReportsLayout } from 'components/layouts' +import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import Table from 'components/to-be-cleaned/Table' +import ShimmeringLoader from 'components/ui/ShimmeringLoader' +import { executeSql } from 'data/sql/execute-sql-query' +import { useFlag } from 'hooks' +import { NextPageWithLayout } from 'types' type QueryPerformancePreset = 'time' | 'frequent' | 'slowest' + const QueryPerformanceReport: NextPageWithLayout = () => { + const router = useRouter() + const { ref: projectRef } = useParams() const { project } = useProjectContext() const [showResetgPgStatStatements, setShowResetgPgStatStatements] = useState(false) + const tableIndexEfficiencyEnabled = useFlag('tableIndexEfficiency') const config = PRESET_CONFIG[Presets.QUERY_PERFORMANCE] - const { ref: projectRef } = useParams() - const router = useRouter() const hooks = queriesFactory(config.queries, projectRef ?? 'default') const queryHitRate = hooks.queryHitRate() @@ -418,7 +418,7 @@ QueryPerformanceReport.getLayout = (page) => ( {page} ) -export default observer(QueryPerformanceReport) +export default QueryPerformanceReport function QueryPerformanceFilterBar({ isLoading, From 8921b977e7ef02b875a4e478abc175eb21213db9 Mon Sep 17 00:00:00 2001 From: Tyler Date: Mon, 4 Mar 2024 20:22:23 +0900 Subject: [PATCH 36/62] fix: Fix minor format errors in the Postgrest aggregate function article (#21735) Fix format --- apps/www/_blog/2024-02-29-postgrest-aggregate-functions.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/www/_blog/2024-02-29-postgrest-aggregate-functions.mdx b/apps/www/_blog/2024-02-29-postgrest-aggregate-functions.mdx index 5e2eeceb252..035a61055dc 100644 --- a/apps/www/_blog/2024-02-29-postgrest-aggregate-functions.mdx +++ b/apps/www/_blog/2024-02-29-postgrest-aggregate-functions.mdx @@ -194,7 +194,7 @@ Because spreading columns brings them to the top-level, they are treated as colu ## Staying Safe with Aggregate Functions -Now that we’ve gone through a few examples of how to use aggregate functions, it’s important to discuss how to _safely_ use aggregate functions in your application. Because of the potential performance risks with aggregate functions, we have **[disabled** aggregate functions by default](https://postgrest.org/en/stable/references/configuration.html#db-aggregates-enabled). Only after reviewing the risks and ensuring appropriate safeguards are in place should you enable this feature. On Supabase, you can enable it by modifying the PostgREST connection role and then reloading the server configuration, like so: +Now that we’ve gone through a few examples of how to use aggregate functions, it’s important to discuss how to _safely_ use aggregate functions in your application. Because of the potential performance risks with aggregate functions, we have [**disabled** aggregate functions by default](https://postgrest.org/en/stable/references/configuration.html#db-aggregates-enabled). Only after reviewing the risks and ensuring appropriate safeguards are in place should you enable this feature. On Supabase, you can enable it by modifying the PostgREST connection role and then reloading the server configuration, like so: {/* prettier-ignore */} ```sql @@ -208,7 +208,7 @@ For example, imagine our `movies` table from before has twenty million rows. If Even worse, imagine that someone with bad intentions wants to do bad things to your innocent server: It could be relatively simple for the attacker to bombard your server with expensive aggregation queries, preventing your server from having the capacity to deal with legitimate traffic, a form of denial-of-service attack. -One strategy for preventing potential performance issues is using the `[pg_plan_filter_module](https://github.com/pgexperts/pg_plan_filter)` . Using this extension, you can set an upper limit on the _cost_ of queries that PostgREST will run. +One strategy for preventing potential performance issues is using the [`pg_plan_filter_module`](https://github.com/pgexperts/pg_plan_filter). Using this extension, you can set an upper limit on the _cost_ of queries that PostgREST will run. {/* prettier-ignore */} ```sql From f9a55935f5ab3cd1f614b97c722354a63da413c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Mon, 4 Mar 2024 20:48:22 +0800 Subject: [PATCH 37/62] chore: use type imports for types/interfaces (#21738) --- apps/studio/components/grid/SupabaseGrid.tsx | 2 +- apps/studio/components/grid/SupabaseGrid.utils.ts | 4 ++-- .../components/grid/components/common/Shortcuts.tsx | 2 +- .../grid/components/editor/BooleanEditor.tsx | 2 +- .../components/grid/components/editor/DateEditor.tsx | 2 +- .../grid/components/editor/DateTimeEditor.tsx | 4 ++-- .../components/grid/components/editor/JsonEditor.tsx | 2 +- .../grid/components/editor/NumberEditor.tsx | 2 +- .../grid/components/editor/SelectEditor.tsx | 2 +- .../components/grid/components/editor/TextEditor.tsx | 2 +- .../components/grid/components/editor/TimeEditor.tsx | 2 +- .../grid/components/formatter/BooleanFormatter.tsx | 6 +++--- .../grid/components/formatter/DefaultFormatter.tsx | 4 ++-- .../components/formatter/ForeignKeyFormatter.tsx | 6 +++--- .../grid/components/formatter/JsonFormatter.tsx | 4 ++-- .../components/grid/components/grid/AddColumn.tsx | 2 +- .../components/grid/components/grid/ColumnHeader.tsx | 2 +- apps/studio/components/grid/components/grid/Grid.tsx | 2 +- .../components/grid/components/grid/RowRenderer.tsx | 4 ++-- .../components/grid/components/grid/SelectColumn.tsx | 2 +- .../components/grid/components/header/Header.tsx | 2 +- .../grid/components/header/RefreshButton.tsx | 6 +++--- .../grid/components/header/filter/FilterPopover.tsx | 2 +- .../grid/components/header/filter/FilterRow.tsx | 2 +- .../grid/components/header/sort/SortPopover.tsx | 2 +- .../grid/components/header/sort/SortRow.tsx | 2 +- .../components/grid/components/menu/ColumnMenu.tsx | 2 +- .../grid/components/menu/RowContextMenu.tsx | 2 +- apps/studio/components/grid/constants.ts | 4 ---- apps/studio/components/grid/query/Query.utils.ts | 2 +- apps/studio/components/grid/query/QueryAction.ts | 2 +- apps/studio/components/grid/query/QueryFilter.ts | 2 +- apps/studio/components/grid/query/QueryModifier.ts | 2 +- apps/studio/components/grid/queue.ts | 3 +++ apps/studio/components/grid/store/reducers/base.ts | 2 +- .../components/grid/store/reducers/callback.ts | 2 +- apps/studio/components/grid/store/reducers/column.ts | 2 +- apps/studio/components/grid/store/reducers/row.ts | 2 +- apps/studio/components/grid/utils/column.ts | 2 +- apps/studio/components/grid/utils/gridColumns.tsx | 2 +- apps/studio/components/grid/utils/types.ts | 2 +- .../components/interfaces/Account/AuditLogs.tsx | 2 +- .../Account/Preferences/AccountInformation.tsx | 2 +- .../Account/Preferences/ProfileInformation.tsx | 4 ++-- .../components/interfaces/App/CommandMenuWrapper.tsx | 2 +- .../interfaces/AuditLogs/LogDetailsPanel.tsx | 2 +- .../interfaces/Auth/AuthProvidersForm/FormField.tsx | 2 +- .../Auth/AuthProvidersForm/ProviderForm.tsx | 4 ++-- .../Auth/EmailTemplates/TemplateEditor.tsx | 2 +- .../AIPolicyEditorPanel/AIPolicyEditorPanel.utils.ts | 2 +- .../Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx | 2 +- .../Policies/AIPolicyEditorPanel/PolicyDetails.tsx | 2 +- .../Auth/Policies/AIPolicyEditorPanel/index.tsx | 2 +- .../interfaces/Auth/Policies/PolicyReview.tsx | 2 +- .../interfaces/Auth/SmtpForm/SmtpForm.utils.ts | 2 +- .../interfaces/Auth/Users/UserDropdown.tsx | 2 +- .../interfaces/Auth/Users/UserListItem.utils.ts | 2 +- .../interfaces/Auth/Users/UserSidePanel.tsx | 2 +- .../components/interfaces/Auth/Users/UsersList.tsx | 4 ++-- .../interfaces/Auth/Users/UsersListItem.tsx | 2 +- .../interfaces/Billing/NoProjectsOnPaidOrgInfo.tsx | 2 +- .../Billing/Subscription/Subscription.utils.ts | 2 +- .../interfaces/BranchManagement/BranchPanels.tsx | 4 ++-- .../BranchManagement/BranchStatusBadge.tsx | 2 +- .../interfaces/BranchManagement/Overview.tsx | 4 ++-- .../interfaces/Database/Backups/BackupItem.tsx | 2 +- .../interfaces/Database/Backups/PITR/PITR.utils.ts | 4 ++-- .../Database/Backups/PITR/PITRSelection.tsx | 2 +- .../interfaces/Database/Backups/PITR/PITRStatus.tsx | 2 +- .../interfaces/Database/Backups/PITR/TimeInput.tsx | 2 +- .../Database/Backups/PITR/TimezoneSelection.tsx | 2 +- .../EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx | 2 +- .../interfaces/Database/Functions/CreateFunction.tsx | 2 +- .../interfaces/Database/Functions/Functions.utils.ts | 2 +- .../Functions/FunctionsList/FunctionsList.tsx | 2 +- .../interfaces/Database/Hooks/DeleteHookModal.tsx | 2 +- .../interfaces/Database/Hooks/EditHookPanel.tsx | 2 +- .../Database/Privileges/Privileges.utils.ts | 4 ++-- .../Database/Privileges/PrivilegesHead.tsx | 2 +- .../Database/Privileges/PrivilegesTable.tsx | 2 +- .../interfaces/Database/Roles/DeleteRoleModal.tsx | 2 +- .../components/interfaces/Database/Roles/RoleRow.tsx | 2 +- .../interfaces/Database/Schemas/SchemaGraph.tsx | 2 +- .../Database/Triggers/ChooseFunctionForm.tsx | 2 +- .../interfaces/Database/Triggers/CreateTrigger.tsx | 2 +- .../Database/Wrappers/DeleteWrapperModal.tsx | 2 +- .../interfaces/Database/Wrappers/InputField.tsx | 2 +- .../interfaces/Database/Wrappers/WrapperRow.tsx | 4 ++-- .../Database/Wrappers/WrapperTableEditor.tsx | 2 +- .../Database/Wrappers/Wrappers.constants.ts | 2 +- .../interfaces/Database/Wrappers/Wrappers.utils.ts | 2 +- .../components/interfaces/Docs/Authentication.tsx | 2 +- .../components/interfaces/Docs/Introduction.tsx | 2 +- .../components/interfaces/Docs/LangSelector.tsx | 2 +- .../interfaces/Docs/Pages/UserManagement.tsx | 2 +- .../EdgeFunctionSecrets/EdgeFunctionSecret.tsx | 2 +- .../interfaces/Functions/EdgeFunctionsListItem.tsx | 2 +- .../interfaces/Functions/TerminalInstructions.tsx | 2 +- .../interfaces/Home/Connect/ConnectTabContent.tsx | 2 +- .../Connect/content/astro/supabasejs/content.tsx | 2 +- .../Home/Connect/content/drizzle/content.tsx | 2 +- .../content/exporeactnative/supabasejs/content.tsx | 2 +- .../content/nextjs/app/supabasejs/content.tsx | 2 +- .../content/nextjs/pages/supabasejs/content.tsx | 2 +- .../Home/Connect/content/nuxt/supabasejs/content.tsx | 2 +- .../Home/Connect/content/prisma/content.tsx | 2 +- .../Connect/content/react/supabasejs/content.tsx | 2 +- .../Connect/content/refine/supabasejs/content.tsx | 2 +- .../Connect/content/remix/supabasejs/content.tsx | 2 +- .../Connect/content/solidjs/supabasejs/content.tsx | 2 +- .../Connect/content/sveltekit/supabasejs/content.tsx | 2 +- .../Connect/content/vuejs/supabasejs/content.tsx | 2 +- .../interfaces/Home/ProjectList/ProjectCard.tsx | 6 +++--- .../interfaces/Home/ProjectList/ProjectCard.utils.ts | 2 +- .../Home/ProjectList/ProjectCardStatus.tsx | 2 +- .../interfaces/Home/ProjectList/ProjectList.tsx | 2 +- .../components/interfaces/Home/ProjectUsage.tsx | 2 +- .../Integrations/IntegrationConnection.tsx | 2 +- .../interfaces/Integrations/IntegrationPanels.tsx | 5 ++++- .../interfaces/Integrations/OrganizationPicker.tsx | 4 ++-- .../BillingBreakdown/BillingMetric.tsx | 4 ++-- .../BillingBreakdown/ComputeMetric.tsx | 2 +- .../PaymentMethods/ChangePaymentMethodModal.tsx | 4 ++-- .../PaymentMethods/DeletePaymentMethodModal.tsx | 2 +- .../BillingSettings/Subscription/DowngradeModal.tsx | 4 ++-- .../BillingSettings/Subscription/ExitSurveyModal.tsx | 2 +- .../Subscription/PlanUpdateSidePanel.tsx | 2 +- .../IntegrationSettings/IntegrationSettings.tsx | 2 +- .../SidePanelGitHubRepoLinker.tsx | 2 +- .../NewProject/FreeProjectLimitWarning.tsx | 2 +- .../Organization/OAuthApps/AuthorizedAppRow.tsx | 2 +- .../Organization/OAuthApps/DeleteAppModal.tsx | 2 +- .../Organization/OAuthApps/OAuthAppRow.tsx | 2 +- .../OAuthApps/PublishAppSidePanel/index.tsx | 4 ++-- .../Organization/OAuthApps/RevokeAppModal.tsx | 2 +- .../interfaces/Organization/Organization.utils.ts | 2 +- .../Organization/TeamSettings/InviteMemberButton.tsx | 4 ++-- .../Organization/TeamSettings/MemberActions.tsx | 4 ++-- .../Organization/TeamSettings/TeamSettings.utils.ts | 4 ++-- .../interfaces/Organization/Usage/Activity.tsx | 2 +- .../interfaces/Organization/Usage/Bandwidth.tsx | 2 +- .../interfaces/Organization/Usage/Compute.tsx | 2 +- .../interfaces/Organization/Usage/SizeAndCounts.tsx | 2 +- .../interfaces/Organization/Usage/TotalUsage.tsx | 2 +- .../Organization/Usage/Usage.constants.tsx | 4 ++-- .../interfaces/Organization/Usage/Usage.utils.ts | 2 +- .../Organization/Usage/UsageChartTooltips.tsx | 2 +- .../Usage/UsageSection/AttributeUsage.tsx | 6 +++--- .../Organization/Usage/UsageSection/UsageSection.tsx | 2 +- .../interfaces/ProjectAPIDocs/Content/Bucket.tsx | 2 +- .../ProjectAPIDocs/Content/EdgeFunction.tsx | 2 +- .../ProjectAPIDocs/Content/EdgeFunctions.tsx | 2 +- .../interfaces/ProjectAPIDocs/Content/Entities.tsx | 2 +- .../interfaces/ProjectAPIDocs/Content/Entity.tsx | 2 +- .../ProjectAPIDocs/Content/Introduction.tsx | 2 +- .../interfaces/ProjectAPIDocs/Content/RPC.tsx | 2 +- .../interfaces/ProjectAPIDocs/Content/Realtime.tsx | 2 +- .../interfaces/ProjectAPIDocs/Content/Storage.tsx | 2 +- .../ProjectAPIDocs/Content/StoredProcedures.tsx | 2 +- .../ProjectAPIDocs/Content/UserManagement.tsx | 2 +- .../Realtime/Inspector/MessageSelection.tsx | 2 +- .../interfaces/Realtime/Inspector/MessagesTable.tsx | 2 +- .../Inspector/RealtimeMessageColumnRenderer.tsx | 2 +- .../Inspector/SelectedRealtimeMessagePanel.tsx | 2 +- .../Realtime/Inspector/useRealtimeMessages.ts | 2 +- .../interfaces/Reports/ReportFilterBar.tsx | 2 +- .../components/interfaces/Reports/ReportWidget.tsx | 2 +- .../components/interfaces/Reports/Reports.queries.ts | 2 -- .../components/interfaces/Reports/Reports.types.ts | 2 +- .../components/interfaces/Reports/Reports.utils.tsx | 2 +- .../RoleImpersonationPopover.tsx | 2 +- .../interfaces/SQLEditor/DownloadSnippetModal.tsx | 2 +- .../components/interfaces/SQLEditor/MonacoEditor.tsx | 4 ++-- .../interfaces/SQLEditor/RenameQueryModal.tsx | 2 +- .../interfaces/SQLEditor/SQLEditor.constants.ts | 4 ++-- .../components/interfaces/SQLEditor/SQLEditor.tsx | 4 ++-- .../interfaces/SQLEditor/SQLEditor.utils.ts | 2 +- .../SQLEditor/SQLTemplates/SQLQuickstarts.tsx | 2 +- .../SQLEditor/SQLTemplates/SQLTemplates.tsx | 2 +- .../SQLEditor/UtilityPanel/FavoriteButton.tsx | 2 +- .../components/interfaces/Settings/Addons/Addons.tsx | 2 +- .../Settings/Addons/ComputeInstanceSidePanel.tsx | 2 +- .../Settings/Addons/CustomDomainSidePanel.tsx | 2 +- .../interfaces/Settings/Addons/IPv4SidePanel.tsx | 2 +- .../interfaces/Settings/Addons/PITRSidePanel.tsx | 2 +- .../DatabaseSettings/DatabaseSettings.utils.ts | 2 +- .../CustomDomainConfig/CustomDomainActivate.tsx | 2 +- .../CustomDomainConfig/CustomDomainDelete.tsx | 2 +- .../CustomDomainConfig/CustomDomainVerify.tsx | 4 ++-- .../DropReplicaConfirmationModal.tsx | 2 +- .../InstanceConfiguration.utils.ts | 4 ++-- .../GitHubIntegrationConnectionForm.tsx | 2 +- .../Integrations/GithubIntegration/GithubSection.tsx | 5 ++++- .../VercelIntegrationConnectionForm.tsx | 5 ++++- .../Integrations/VercelIntegration/VercelSection.tsx | 5 ++++- .../LogColumnRenderers/DatabaseApiColumnRender.tsx | 2 +- .../DatabasePostgresColumnRender.tsx | 2 +- .../LogColumnRenderers/FunctionsEdgeColumnRender.tsx | 2 +- .../LogColumnRenderers/FunctionsLogsColumnRender.tsx | 2 +- .../interfaces/Settings/Logs/LogEventChart.tsx | 2 +- .../interfaces/Settings/Logs/LogSelection.tsx | 2 +- .../components/interfaces/Settings/Logs/LogTable.tsx | 2 +- .../interfaces/Settings/Logs/Logs.types.ts | 2 +- .../interfaces/Settings/Logs/Logs.utils.ts | 2 +- .../interfaces/Settings/Logs/RecentQueriesItem.tsx | 2 +- .../Settings/Vault/Secrets/DeleteSecretModal.tsx | 2 +- .../Settings/Vault/Secrets/EditSecretModal.tsx | 2 +- .../interfaces/Settings/Vault/Secrets/SecretRow.tsx | 2 +- .../Settings/Vault/Secrets/SecretsManagement.tsx | 2 +- .../components/interfaces/SignIn/SignInForm.tsx | 3 +-- .../components/interfaces/SignIn/SignInMfaForm.tsx | 2 +- .../interfaces/Storage/EditBucketModal.tsx | 2 +- .../components/interfaces/Storage/Storage.types.ts | 2 +- .../components/interfaces/Support/SupportForm.tsx | 2 +- .../TableGridEditor/DeleteConfirmationDialogs.tsx | 5 ++--- .../ColumnEditor/ColumnDefaultValue.tsx | 6 +++--- .../ColumnEditor/ColumnEditor.constants.ts | 4 ++-- .../SidePanelEditor/ColumnEditor/ColumnEditor.tsx | 10 +++++++--- .../ColumnEditor/ColumnEditor.utils.ts | 4 ++-- .../ColumnEditor/ColumnForeignKey.tsx | 4 ++-- .../SidePanelEditor/ColumnEditor/ColumnType.tsx | 4 ++-- .../ColumnEditor/InputWithSuggestions.tsx | 2 +- .../ForeignKeySelector/ForeignKeySelector.tsx | 6 +++--- .../ForeignKeySelector/ForeignKeySelector.utils.tsx | 4 ++-- .../ForeignRowSelector/ForeignRowSelector.tsx | 4 ++-- .../RowEditor/ForeignRowSelector/SelectorGrid.tsx | 2 +- .../SidePanelEditor/RowEditor/InputField.tsx | 2 +- .../JsonEditor/DrilldownViewer/DrilldownPane.tsx | 2 +- .../JsonEditor/DrilldownViewer/DrilldownViewer.tsx | 2 +- .../SidePanelEditor/RowEditor/RowEditor.tsx | 4 ++-- .../SidePanelEditor/RowEditor/RowEditor.utils.ts | 4 ++-- .../SidePanelEditor/SidePanelEditor.constants.ts | 2 +- .../SidePanelEditor/SidePanelEditor.tsx | 12 ++++++------ .../SidePanelEditor/SidePanelEditor.utils.tsx | 12 ++++++------ .../SpreadSheetImportConfiguration.tsx | 2 +- .../SpreadsheetImport/SpreadsheetImport.constants.ts | 2 +- .../SpreadsheetImport/SpreadsheetImport.tsx | 6 +++--- .../SpreadsheetImport/SpreadsheetImport.types.ts | 2 +- .../SpreadsheetImport/SpreadsheetImportPreview.tsx | 4 ++-- .../SidePanelEditor/TableEditor/Column.tsx | 6 +++--- .../SidePanelEditor/TableEditor/ColumnManagement.tsx | 8 ++++---- .../ForeignKeysManagement/ForeignKeyRow.tsx | 2 +- .../ForeignKeysManagement/ForeignKeysManagement.tsx | 6 +++--- .../ForeignKeysManagement.utils.ts | 4 ++-- .../TableEditor/TableEditor.constants.ts | 2 +- .../SidePanelEditor/TableEditor/TableEditor.tsx | 6 +++--- .../SidePanelEditor/TableEditor/TableEditor.types.ts | 4 ++-- .../SidePanelEditor/TableEditor/TableEditor.utils.ts | 6 +++--- .../interfaces/TableGridEditor/TableGridEditor.tsx | 4 ++-- .../components/layouts/APIAuthorizationLayout.tsx | 2 +- .../layouts/AccountLayout/AccountLayout.tsx | 2 +- .../components/layouts/AccountLayout/WithSidebar.tsx | 2 +- .../GithubRepositorySelection.tsx | 2 +- .../components/layouts/AppLayout/ProjectDropdown.tsx | 2 +- .../layouts/AuthLayout/AuthLayout.utils.ts | 2 +- apps/studio/components/layouts/BillingLayout.tsx | 2 +- .../layouts/DatabaseLayout/DatabaseMenu.utils.ts | 4 ++-- .../layouts/DocsLayout/DocsLayout.utils.tsx | 2 +- apps/studio/components/layouts/FunctionsLayout.tsx | 2 +- .../layouts/IntegrationsLayout/Integrations.utils.ts | 6 +++--- .../components/layouts/LogsLayout/LogsMenu.utils.ts | 7 +++++-- .../studio/components/layouts/OrganizationLayout.tsx | 3 +-- .../layouts/ProjectLayout/ConnectingState.tsx | 2 +- .../NotificationsPopoverV2/NotificationRow.tsx | 4 ++-- .../NavigationBar/NavigationBar.utils.tsx | 4 ++-- .../NavigationBar/NavigationIconLink.tsx | 2 +- .../ProjectSettingsLayout/SettingsMenu.utils.ts | 6 +++--- .../layouts/RealtimeLayout/RealtimeMenu.utils.ts | 4 ++-- .../components/layouts/SQLEditorLayout/QueryItem.tsx | 2 +- .../layouts/SQLEditorLayout/QueryItemActions.tsx | 2 +- .../components/layouts/StorageLayout/BucketRow.tsx | 2 +- .../layouts/StorageLayout/StorageBucketsError.tsx | 2 +- .../components/layouts/StorageLayout/StorageMenu.tsx | 2 +- .../layouts/TableEditorLayout/EntityListItem.tsx | 4 ++-- .../layouts/TableEditorLayout/TableEditorMenu.tsx | 2 -- .../components/layouts/VercelIntegrationLayout.tsx | 2 +- apps/studio/components/layouts/WizardLayout.tsx | 2 +- .../components/to-be-cleaned/Charts/ChartHandler.tsx | 4 ++-- .../to-be-cleaned/Storage/EmptyBucketModal.tsx | 2 +- .../to-be-cleaned/Storage/Storage.utils.ts | 2 +- .../Storage/StorageExplorer/FileExplorer.tsx | 2 +- .../Storage/StorageExplorer/FileExplorerColumn.tsx | 2 +- .../Storage/StorageExplorer/FileExplorerRow.tsx | 2 +- .../Storage/StorageExplorer/StorageExplorer.tsx | 2 +- apps/studio/components/ui/AlertError.tsx | 2 +- apps/studio/components/ui/Charts/AreaChart.tsx | 2 +- apps/studio/components/ui/Charts/BarChart.tsx | 4 ++-- apps/studio/components/ui/Charts/Charts.utils.tsx | 2 +- apps/studio/components/ui/Charts/StackedBarChart.tsx | 2 +- .../CodeEditor/Providers/PgSQLCompletionProvider.ts | 8 ++++---- .../components/ui/DatePicker/TimeSplitInput.tsx | 2 +- apps/studio/components/ui/Flag/FlagProvider.tsx | 2 +- .../ui/OveragesBanner/OveragesBanner.utils.ts | 2 +- .../studio/components/ui/ProductMenu/ProductMenu.tsx | 2 +- .../ResourceExhaustionWarningBanner.utils.ts | 2 +- apps/studio/data/__templates/resource-query.ts | 2 +- .../data/__templates/resource-update-mutation.ts | 2 +- apps/studio/data/__templates/resources-query.ts | 2 +- .../access-tokens/access-tokens-create-mutation.ts | 4 ++-- .../access-tokens/access-tokens-delete-mutation.ts | 2 +- apps/studio/data/ai/sql-debug-mutation.ts | 2 +- apps/studio/data/ai/sql-edit-mutation.ts | 2 +- apps/studio/data/ai/sql-generate-mutation.ts | 2 +- apps/studio/data/ai/sql-title-mutation.ts | 2 +- apps/studio/data/analytics/infra-monitoring-query.ts | 2 +- .../data/analytics/org-daily-compute-stats-query.ts | 4 ++-- apps/studio/data/analytics/org-daily-stats-query.ts | 2 +- .../analytics/project-log-requests-count-query.ts | 2 +- .../api-authorization-approve-mutation.ts | 2 +- .../api-authorization-decline-mutation.ts | 2 +- .../api-authorization/api-authorization-query.ts | 2 +- apps/studio/data/auth/auth-config-query.ts | 4 ++-- apps/studio/data/auth/auth-config-update-mutation.ts | 4 ++-- apps/studio/data/auth/user-create-mutation.ts | 2 +- .../data/auth/user-delete-mfa-factors-mutation.ts | 2 +- apps/studio/data/auth/user-delete-mutation.ts | 4 ++-- apps/studio/data/auth/user-invite-mutation.ts | 2 +- .../studio/data/auth/user-reset-password-mutation.ts | 4 ++-- .../data/auth/user-send-magic-link-mutation.ts | 4 ++-- apps/studio/data/auth/user-send-otp-mutation.ts | 4 ++-- apps/studio/data/auth/users-query.ts | 4 ++-- .../data/banned-ips/banned-ips-delete-mutations.ts | 2 +- apps/studio/data/banned-ips/banned-ips-query.ts | 2 +- apps/studio/data/branches/branch-create-mutation.ts | 2 +- apps/studio/data/branches/branch-delete-mutation.ts | 2 +- apps/studio/data/branches/branch-query.ts | 2 +- apps/studio/data/branches/branch-update-mutation.ts | 2 +- .../data/branches/branches-disable-mutation.ts | 2 +- apps/studio/data/branches/branches-query.ts | 4 ++-- .../studio/data/config/jwt-secret-update-mutation.ts | 2 +- apps/studio/data/config/pgbouncer-enabled-query.ts | 2 +- apps/studio/data/config/project-api-query.ts | 2 +- .../data/config/project-disk-resize-mutation.ts | 2 +- .../project-postgrest-config-update-mutation.ts | 2 +- apps/studio/data/config/project-settings-query.ts | 4 ++-- .../data/config/project-storage-config-query.ts | 2 +- .../config/project-storage-config-update-mutation.ts | 2 +- .../project-temp-disable-read-only-mutation.ts | 2 +- .../data/config/project-upgrade-eligibility-query.ts | 2 +- apps/studio/data/content/content-delete-mutation.ts | 2 +- apps/studio/data/content/content-insert-mutation.ts | 6 +++--- apps/studio/data/content/content-query.ts | 2 +- apps/studio/data/content/content-upsert-mutation.ts | 6 +++--- .../data/custom-domains/check-cname-mutation.ts | 2 +- .../custom-domains-activate-mutation.ts | 2 +- .../custom-domains/custom-domains-create-mutation.ts | 2 +- .../custom-domains/custom-domains-delete-mutation.ts | 2 +- .../data/custom-domains/custom-domains-query.ts | 2 +- .../custom-domains-reverify-mutation.ts | 2 +- .../database-column-create-mutation.ts | 4 ++-- .../database-column-delete-mutation.ts | 4 ++-- .../database-column-update-mutation.ts | 4 ++-- .../database-extension-disable-mutation.ts | 2 +- .../database-extension-enable-mutation.ts | 2 +- .../database-extensions/database-extensions-query.ts | 2 +- .../database-functions-create-mutation.ts | 4 ++-- .../database-functions-delete-mutation.ts | 2 +- .../database-functions/database-functions-query.ts | 4 ++-- .../database-functions-update-mutation.ts | 4 ++-- .../database-policies/database-policies-query.ts | 2 +- .../database-policy-create-mutation.ts | 4 ++-- .../database-policy-delete-mutation.ts | 2 +- .../database-policy-update-mutation.ts | 2 +- .../database-publications-create-mutation.ts | 2 +- .../database-publications-query.ts | 2 +- .../database-publications-update-mutation.ts | 2 +- .../database-roles/database-role-create-mutation.ts | 4 ++-- .../database-roles/database-role-delete-mutation.ts | 2 +- .../database-roles/database-role-update-mutation.ts | 4 ++-- .../data/database-roles/database-roles-query.ts | 4 ++-- .../database-trigger-create-mutation.ts | 4 ++-- .../database-trigger-delete-mutation.ts | 4 ++-- .../database-trigger-update-mutation.ts | 4 ++-- .../database-trigger-update-transaction-mutation.ts | 2 +- .../database-triggers/database-triggers-query.ts | 4 ++-- .../studio/data/database/backup-download-mutation.ts | 2 +- apps/studio/data/database/backup-restore-mutation.ts | 4 ++-- apps/studio/data/database/backups-query.ts | 4 ++-- .../database/database-password-reset-mutation.ts | 2 +- apps/studio/data/database/hooks-enable-mutation.ts | 2 +- apps/studio/data/database/indexes-query.ts | 2 +- apps/studio/data/database/pitr-restore-mutation.ts | 2 +- .../data/database/pooling-configuration-query.ts | 4 ++-- .../pooling-configuration-update-mutation.ts | 4 ++-- apps/studio/data/database/schema-create-mutation.ts | 2 +- apps/studio/data/database/schemas-query.ts | 4 ++-- apps/studio/data/documents/document-query.ts | 2 +- .../edge-functions/edge-functions-delete-mutation.ts | 2 +- .../data/edge-functions/edge-functions-query.ts | 2 +- .../edge-functions/edge-functions-update-mutation.ts | 2 +- .../data/entity-types/entity-types-infinite-query.ts | 2 +- .../enumerated-type-create-mutation.ts | 2 +- .../enumerated-type-delete-mutation.ts | 2 +- .../enumerated-type-update-mutation.ts | 2 +- .../data/enumerated-types/enumerated-types-query.ts | 4 ++-- apps/studio/data/fdw/fdw-create-mutation.ts | 2 +- apps/studio/data/fdw/fdw-delete-mutation.ts | 4 ++-- apps/studio/data/fdw/fdw-update-mutation.ts | 4 ++-- apps/studio/data/feedback/exit-survey-send.ts | 2 +- apps/studio/data/feedback/feedback-send.ts | 2 +- apps/studio/data/feedback/support-ticket-send.ts | 2 +- apps/studio/data/fetchers.ts | 4 ++-- .../data/foreign-tables/foreign-table-query.ts | 2 +- .../github-authorization-create-mutation.ts | 2 +- .../data/integrations/github-authorization-query.ts | 2 +- .../data/integrations/github-branch-check-query.ts | 2 +- .../data/integrations/github-branches-query.ts | 2 +- .../github-connection-create-mutation.ts | 4 ++-- .../github-connection-delete-mutation.ts | 2 +- .../github-connection-update-mutation.ts | 2 +- .../data/integrations/github-connections-query.ts | 2 +- .../data/integrations/github-pull-requests-query.ts | 4 ++-- .../data/integrations/github-repositories-query.ts | 2 +- .../data/integrations/integrations-query-org-only.ts | 4 ++-- apps/studio/data/integrations/integrations-query.ts | 2 +- ...egrations-vercel-connection-sync-envs-mutation.ts | 2 +- ...ntegrations-vercel-connections-create-mutation.ts | 4 ++-- ...ns-vercel-installed-connection-delete-mutation.ts | 2 +- .../integrations-vercel-projects-query.ts | 2 +- apps/studio/data/integrations/integrations.types.ts | 2 +- .../integrations/vercel-connection-update-mutate.ts | 4 ++-- .../vercel-integration-create-mutation.ts | 2 +- apps/studio/data/invoices/invoice-query.ts | 2 +- apps/studio/data/invoices/invoices-count-query.ts | 2 +- apps/studio/data/invoices/invoices-overdue-query.ts | 2 +- apps/studio/data/invoices/invoices-query.ts | 2 +- .../data/invoices/org-invoice-upcoming-query.ts | 2 +- .../materialized-views/materialized-view-query.ts | 2 +- apps/studio/data/misc/get-default-region-query.ts | 2 +- apps/studio/data/misc/reset-password-mutation.ts | 2 +- apps/studio/data/misc/signup-mutation.ts | 2 +- .../network-retrictions-apply-mutation.ts | 2 +- .../notifications/notifications-dismiss-mutation.ts | 2 +- .../studio/data/notifications/notifications-query.ts | 2 +- .../notifications/notifications-update-mutation.ts | 2 +- .../notifications-v2-archive-all-mutation.ts | 2 +- .../data/notifications/notifications-v2-query.ts | 4 ++-- .../notifications/notifications-v2-summary-query.ts | 4 ++-- .../notifications-v2-update-mutation.ts | 2 +- .../data/oauth/authorized-app-revoke-mutation.ts | 2 +- apps/studio/data/oauth/authorized-apps-query.ts | 2 +- apps/studio/data/oauth/oauth-app-create-mutation.ts | 4 ++-- apps/studio/data/oauth/oauth-app-delete-mutation.ts | 2 +- apps/studio/data/oauth/oauth-app-update-mutation.ts | 4 ++-- apps/studio/data/oauth/oauth-apps-query.ts | 4 ++-- apps/studio/data/open-api/api-spec-query.ts | 2 +- .../organizations/free-project-limit-check-query.ts | 3 +-- .../organizations/organization-audit-logs-query.ts | 2 +- .../organization-billing-subscription-preview.ts | 4 ++-- .../organization-by-fly-organization-id-mutation.ts | 2 +- .../organizations/organization-create-mutation.ts | 2 +- .../organization-customer-profile-query.ts | 5 ++--- .../organization-customer-profile-update-mutation.ts | 2 +- .../organizations/organization-delete-mutation.ts | 2 +- .../organization-join-decline-mutation.ts | 2 +- .../data/organizations/organization-join-mutation.ts | 2 +- .../organization-join-token-validation-query.ts | 4 ++-- .../organization-member-delete-mutation.ts | 2 +- .../organization-member-invite-create-mutation.ts | 2 +- .../organization-member-invite-delete-mutation.ts | 2 +- .../organization-member-update-mutation.ts | 2 +- .../data/organizations/organization-members-query.ts | 4 ++-- .../organization-payment-method-delete-mutation.ts | 2 +- ...anization-payment-method-setup-intent-mutation.ts | 2 +- .../organization-payment-methods-query.ts | 5 ++--- .../data/organizations/organization-roles-query.ts | 2 +- .../data/organizations/organization-tax-ids-query.ts | 2 +- .../organization-tax-ids-update-mutation.ts | 4 ++-- .../organizations/organization-update-mutation.ts | 4 ++-- .../studio/data/organizations/organizations-query.ts | 2 +- apps/studio/data/permissions/permissions-query.ts | 2 +- .../pg-sodium-keys/pg-sodium-key-create-mutation.ts | 3 +-- .../pg-sodium-keys/pg-sodium-key-delete-mutation.ts | 3 +-- .../privileges/column-privileges-grant-mutation.ts | 4 ++-- .../data/privileges/column-privileges-query.ts | 4 ++-- .../privileges/column-privileges-revoke-mutation.ts | 4 ++-- .../privileges/table-privileges-grant-mutation.ts | 4 ++-- .../studio/data/privileges/table-privileges-query.ts | 4 ++-- .../privileges/table-privileges-revoke-mutation.ts | 4 ++-- .../mfa-authenticator-assurance-level-query.ts | 4 ++-- .../profile/mfa-challenge-and-verify-mutation.ts | 2 +- apps/studio/data/profile/mfa-enroll-mutation.ts | 2 +- apps/studio/data/profile/mfa-list-factors-query.ts | 2 +- apps/studio/data/profile/mfa-unenroll-mutation.ts | 2 +- apps/studio/data/profile/profile-audit-logs-query.ts | 4 ++-- apps/studio/data/profile/profile-create-mutation.ts | 4 ++-- apps/studio/data/profile/profile-query.ts | 4 ++-- apps/studio/data/profile/profile-update-mutation.ts | 2 +- apps/studio/data/profile/types.ts | 2 +- .../projects/project-by-fly-extension-id-mutation.ts | 2 +- apps/studio/data/projects/project-create-mutation.ts | 6 +++--- apps/studio/data/projects/project-delete-mutation.ts | 2 +- apps/studio/data/projects/project-detail-query.ts | 4 ++-- apps/studio/data/projects/project-pause-mutation.ts | 2 +- .../studio/data/projects/project-restart-mutation.ts | 2 +- .../projects/project-restart-services-mutation.ts | 2 +- .../studio/data/projects/project-restore-mutation.ts | 2 +- apps/studio/data/projects/project-status-query.ts | 2 +- .../data/projects/project-type-generation-query.ts | 2 +- apps/studio/data/projects/project-update-mutation.ts | 2 +- .../studio/data/projects/project-upgrade-mutation.ts | 2 +- apps/studio/data/projects/projects-query.ts | 6 +++--- .../data/read-replicas/load-balancers-query.ts | 4 ++-- .../data/read-replicas/replica-remove-mutation.ts | 4 ++-- .../data/read-replicas/replica-setup-mutation.ts | 4 ++-- apps/studio/data/read-replicas/replicas-query.ts | 4 ++-- .../data/read-replicas/replicas-status-query.ts | 2 +- apps/studio/data/secrets/secrets-create-mutation.ts | 2 +- apps/studio/data/secrets/secrets-delete-mutation.ts | 2 +- apps/studio/data/secrets/secrets-query.ts | 4 ++-- .../service-status/edge-functions-status-query.ts | 2 +- .../service-status/postgres-service-status-query.ts | 2 +- .../data/service-status/service-status-query.ts | 2 +- apps/studio/data/sql/keys.ts | 2 +- .../ssl-enforcement-update-mutation.ts | 2 +- apps/studio/data/storage/bucket-create-mutation.ts | 2 +- apps/studio/data/storage/bucket-delete-mutation.ts | 2 +- apps/studio/data/storage/bucket-empty-mutation.ts | 2 +- apps/studio/data/storage/bucket-update-mutation.ts | 2 +- apps/studio/data/storage/buckets-query.ts | 2 +- apps/studio/data/stripe/setup-intent-mutation.ts | 2 +- .../org-subscription-cancel-schedule-mutation.ts | 2 +- .../data/subscriptions/org-subscription-query.ts | 2 +- .../org-subscription-update-mutation.ts | 4 ++-- .../subscriptions/project-addon-remove-mutation.ts | 4 ++-- .../subscriptions/project-addon-update-mutation.ts | 4 ++-- .../data/subscriptions/project-addons-query.ts | 2 +- apps/studio/data/subscriptions/types.ts | 2 +- .../data/table-rows/table-row-create-mutation.ts | 2 +- .../data/table-rows/table-row-delete-all-mutation.ts | 2 +- .../data/table-rows/table-row-delete-mutation.ts | 4 ++-- .../data/table-rows/table-row-truncate-mutation.ts | 2 +- .../data/table-rows/table-row-update-mutation.ts | 2 +- .../studio/data/table-rows/table-rows-count-query.ts | 2 +- apps/studio/data/table-rows/table-rows-query.ts | 2 +- apps/studio/data/table-rows/utils.ts | 4 ++-- apps/studio/data/tables/table-create-mutation.ts | 4 ++-- apps/studio/data/tables/table-delete-mutation.ts | 2 +- apps/studio/data/tables/table-query.ts | 2 +- apps/studio/data/tables/table-update-mutation.ts | 4 ++-- apps/studio/data/tables/tables-query.ts | 4 ++-- apps/studio/data/usage/org-usage-query.ts | 4 ++-- apps/studio/data/usage/resource-warnings-query.ts | 4 ++-- .../data/vault/vault-secret-create-mutation.ts | 2 +- .../data/vault/vault-secret-delete-mutation.ts | 2 +- .../data/vault/vault-secret-update-mutation.ts | 2 +- apps/studio/data/vault/vault-secrets-query.ts | 2 +- apps/studio/data/views/view-query.ts | 4 ++-- apps/studio/data/views/views-query.ts | 2 +- apps/studio/hooks/analytics/useLogsQuery.tsx | 6 +++++- apps/studio/hooks/misc/useCheckPermissions.ts | 2 +- apps/studio/hooks/misc/useEntityType.ts | 2 +- apps/studio/hooks/misc/useIsFeatureEnabled.ts | 2 +- apps/studio/hooks/misc/useStore.tsx | 2 +- apps/studio/lib/api/apiAuthenticate.ts | 2 +- apps/studio/lib/api/apiWrapper.ts | 2 +- apps/studio/lib/common/fetch/base.ts | 2 +- apps/studio/lib/common/fetch/delete.ts | 2 +- apps/studio/lib/common/fetch/get.ts | 2 +- apps/studio/lib/common/fetch/head.ts | 2 +- apps/studio/lib/common/fetch/patch.ts | 2 +- apps/studio/lib/common/fetch/post.ts | 2 +- apps/studio/lib/common/fetch/put.ts | 2 +- apps/studio/lib/configcat.ts | 2 +- apps/studio/lib/constants/infrastructure.ts | 2 +- apps/studio/lib/integration-utils.ts | 4 ++-- apps/studio/lib/profile.tsx | 4 ++-- apps/studio/lib/role-impersonation.ts | 2 +- apps/studio/lib/telemetry.ts | 4 ++-- apps/studio/pages/_app.tsx | 2 +- apps/studio/pages/account/audit.tsx | 2 +- apps/studio/pages/account/me.tsx | 2 +- apps/studio/pages/account/security.tsx | 2 +- apps/studio/pages/account/tokens.tsx | 2 +- apps/studio/pages/api/projects/[ref]/content.ts | 2 +- apps/studio/pages/authorize.tsx | 2 +- apps/studio/pages/forgot-password.tsx | 2 +- .../vercel/[slug]/deploy-button/new-project.tsx | 2 +- .../vercel/[slug]/marketplace/choose-project.tsx | 2 +- apps/studio/pages/integrations/vercel/install.tsx | 2 +- apps/studio/pages/new/[slug].tsx | 4 ++-- apps/studio/pages/new/index.tsx | 2 +- apps/studio/pages/org/[slug]/apps.tsx | 2 +- apps/studio/pages/org/[slug]/audit.tsx | 2 +- apps/studio/pages/org/[slug]/billing.tsx | 2 +- apps/studio/pages/org/[slug]/documents.tsx | 2 +- apps/studio/pages/org/[slug]/general.tsx | 2 +- apps/studio/pages/org/[slug]/index.tsx | 2 +- apps/studio/pages/org/[slug]/integrations.tsx | 2 +- apps/studio/pages/org/[slug]/invoices.tsx | 2 +- apps/studio/pages/org/[slug]/team.tsx | 2 +- apps/studio/pages/org/[slug]/usage.tsx | 2 +- apps/studio/pages/project/[ref]/api/graphiql.tsx | 2 +- apps/studio/pages/project/[ref]/api/index.tsx | 2 +- .../pages/project/[ref]/auth/column-privileges.tsx | 4 ++-- apps/studio/pages/project/[ref]/auth/hooks.tsx | 2 +- apps/studio/pages/project/[ref]/auth/index.tsx | 2 +- apps/studio/pages/project/[ref]/auth/policies.tsx | 4 ++-- apps/studio/pages/project/[ref]/auth/providers.tsx | 2 +- apps/studio/pages/project/[ref]/auth/rate-limits.tsx | 2 +- apps/studio/pages/project/[ref]/auth/templates.tsx | 2 +- .../pages/project/[ref]/auth/url-configuration.tsx | 2 +- apps/studio/pages/project/[ref]/auth/users.tsx | 2 +- apps/studio/pages/project/[ref]/branches.tsx | 2 +- apps/studio/pages/project/[ref]/building.tsx | 2 +- .../pages/project/[ref]/database/backups/pitr.tsx | 2 +- .../project/[ref]/database/backups/scheduled.tsx | 2 +- .../pages/project/[ref]/database/extensions.tsx | 2 +- .../pages/project/[ref]/database/functions.tsx | 2 +- apps/studio/pages/project/[ref]/database/hooks.tsx | 2 +- apps/studio/pages/project/[ref]/database/index.tsx | 2 +- apps/studio/pages/project/[ref]/database/indexes.tsx | 2 +- .../pages/project/[ref]/database/migrations.tsx | 2 +- .../pages/project/[ref]/database/replication.tsx | 2 +- apps/studio/pages/project/[ref]/database/roles.tsx | 2 +- apps/studio/pages/project/[ref]/database/schemas.tsx | 2 +- apps/studio/pages/project/[ref]/database/tables.tsx | 6 +++--- .../studio/pages/project/[ref]/database/triggers.tsx | 2 +- apps/studio/pages/project/[ref]/database/types.tsx | 2 +- .../pages/project/[ref]/database/wrappers/[id].tsx | 2 +- .../pages/project/[ref]/database/wrappers/index.tsx | 2 +- .../pages/project/[ref]/database/wrappers/new.tsx | 2 +- apps/studio/pages/project/[ref]/editor/[id].tsx | 2 +- apps/studio/pages/project/[ref]/editor/index.tsx | 4 ++-- .../[ref]/functions/[functionSlug]/details.tsx | 2 +- .../project/[ref]/functions/[functionSlug]/index.tsx | 2 +- .../[ref]/functions/[functionSlug]/invocations.tsx | 2 +- .../project/[ref]/functions/[functionSlug]/logs.tsx | 2 +- apps/studio/pages/project/[ref]/functions/index.tsx | 2 +- apps/studio/pages/project/[ref]/index.tsx | 2 +- apps/studio/pages/project/[ref]/logs/auth-logs.tsx | 2 +- apps/studio/pages/project/[ref]/logs/edge-logs.tsx | 2 +- .../pages/project/[ref]/logs/explorer/index.tsx | 2 +- .../pages/project/[ref]/logs/explorer/recent.tsx | 2 +- .../pages/project/[ref]/logs/explorer/saved.tsx | 2 +- .../pages/project/[ref]/logs/explorer/templates.tsx | 2 +- apps/studio/pages/project/[ref]/logs/pooler-logs.tsx | 2 +- .../pages/project/[ref]/logs/postgres-logs.tsx | 2 +- .../pages/project/[ref]/logs/postgrest-logs.tsx | 2 +- .../pages/project/[ref]/logs/realtime-logs.tsx | 2 +- .../studio/pages/project/[ref]/logs/storage-logs.tsx | 2 +- .../pages/project/[ref]/realtime/inspector.tsx | 2 +- apps/studio/pages/project/[ref]/reports/[id].tsx | 2 +- apps/studio/pages/project/[ref]/reports/database.tsx | 4 ++-- apps/studio/pages/project/[ref]/reports/index.tsx | 2 +- .../project/[ref]/reports/query-performance.tsx | 2 +- apps/studio/pages/project/[ref]/reports/storage.tsx | 2 +- apps/studio/pages/project/[ref]/settings/addons.tsx | 2 +- apps/studio/pages/project/[ref]/settings/api.tsx | 2 +- apps/studio/pages/project/[ref]/settings/auth.tsx | 2 +- .../pages/project/[ref]/settings/billing/usage.tsx | 2 +- .../studio/pages/project/[ref]/settings/database.tsx | 2 +- .../pages/project/[ref]/settings/functions.tsx | 2 +- apps/studio/pages/project/[ref]/settings/general.tsx | 2 +- apps/studio/pages/project/[ref]/settings/index.tsx | 2 +- .../pages/project/[ref]/settings/infrastructure.tsx | 2 +- .../pages/project/[ref]/settings/integrations.tsx | 2 +- apps/studio/pages/project/[ref]/settings/storage.tsx | 2 +- .../pages/project/[ref]/settings/vault/keys.tsx | 2 +- .../pages/project/[ref]/settings/vault/secrets.tsx | 2 +- apps/studio/pages/project/[ref]/sql/[id].tsx | 2 +- apps/studio/pages/project/[ref]/sql/quickstarts.tsx | 2 +- apps/studio/pages/project/[ref]/sql/templates.tsx | 2 +- .../project/[ref]/storage/buckets/[bucketId].tsx | 2 +- .../pages/project/[ref]/storage/buckets/index.tsx | 2 +- apps/studio/pages/project/[ref]/storage/index.tsx | 2 +- apps/studio/pages/project/[ref]/storage/policies.tsx | 2 +- apps/studio/pages/projects.tsx | 2 +- apps/studio/pages/reset-password.tsx | 2 +- apps/studio/pages/sign-in-mfa.tsx | 2 +- apps/studio/pages/sign-in-sso.tsx | 2 +- apps/studio/pages/sign-in.tsx | 2 +- apps/studio/pages/sign-up.tsx | 2 +- apps/studio/pages/vercel/integrate.tsx | 2 +- apps/studio/pages/vercel/setupProject.tsx | 2 +- apps/studio/state/sql-editor.ts | 4 ++-- apps/studio/state/table-editor.tsx | 8 ++++---- apps/studio/stores/RootStore.ts | 2 +- apps/studio/stores/UiStore.ts | 4 ++-- .../schema/AuthProviders/AuthTemplatesValidation.tsx | 2 +- apps/studio/stores/pgmeta/MetaStore.ts | 4 ++-- apps/studio/stores/projectContentStore.ts | 2 +- apps/studio/types/next.ts | 6 +++--- 683 files changed, 903 insertions(+), 893 deletions(-) create mode 100644 apps/studio/components/grid/queue.ts diff --git a/apps/studio/components/grid/SupabaseGrid.tsx b/apps/studio/components/grid/SupabaseGrid.tsx index a2e4d95132c..c8b9c63a569 100644 --- a/apps/studio/components/grid/SupabaseGrid.tsx +++ b/apps/studio/components/grid/SupabaseGrid.tsx @@ -23,7 +23,7 @@ import { Grid } from './components/grid' import Header from './components/header/Header' import { RowContextMenu } from './components/menu' import { StoreProvider, useDispatch, useTrackedState } from './store' -import { SupabaseGridProps } from './types' +import type { SupabaseGridProps } from './types' /** Supabase Grid: React component to render database table */ diff --git a/apps/studio/components/grid/SupabaseGrid.utils.ts b/apps/studio/components/grid/SupabaseGrid.utils.ts index a654246490a..cab71d76a52 100644 --- a/apps/studio/components/grid/SupabaseGrid.utils.ts +++ b/apps/studio/components/grid/SupabaseGrid.utils.ts @@ -1,11 +1,11 @@ import AwesomeDebouncePromise from 'awesome-debounce-promise' import { STORAGE_KEY_PREFIX } from './constants' import { InitialStateType } from './store/reducers' -import { Sort, SupabaseGridProps, SupaColumn, SupaTable } from './types' +import type { Sort, SupabaseGridProps, SupaColumn, SupaTable } from './types' import type { Dictionary } from 'types' import { getGridColumns } from './utils/gridColumns' import { FilterOperatorOptions } from './components/header/filter' -import { Filter } from 'components/grid/types' +import type { Filter } from 'components/grid/types' export function defaultErrorHandler(error: any) { console.error('Supabase grid error: ', error) diff --git a/apps/studio/components/grid/components/common/Shortcuts.tsx b/apps/studio/components/grid/components/common/Shortcuts.tsx index e9d4ba0b56a..4d14f6dae20 100644 --- a/apps/studio/components/grid/components/common/Shortcuts.tsx +++ b/apps/studio/components/grid/components/common/Shortcuts.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { useTrackedState } from '../../store' import { useKeyboardShortcuts } from './Hooks' -import { DataGridHandle } from 'react-data-grid' +import type { DataGridHandle } from 'react-data-grid' import { formatClipboardValue, copyToClipboard } from '../../utils' type ShortcutsProps = { diff --git a/apps/studio/components/grid/components/editor/BooleanEditor.tsx b/apps/studio/components/grid/components/editor/BooleanEditor.tsx index 9c7772db08d..3ae4643b42d 100644 --- a/apps/studio/components/grid/components/editor/BooleanEditor.tsx +++ b/apps/studio/components/grid/components/editor/BooleanEditor.tsx @@ -1,5 +1,5 @@ import { Select } from 'ui' -import { RenderEditCellProps } from 'react-data-grid' +import type { RenderEditCellProps } from 'react-data-grid' import { useTrackedState } from 'components/grid/store' interface Props extends RenderEditCellProps { diff --git a/apps/studio/components/grid/components/editor/DateEditor.tsx b/apps/studio/components/grid/components/editor/DateEditor.tsx index 02f4e24da04..a32acca76c0 100644 --- a/apps/studio/components/grid/components/editor/DateEditor.tsx +++ b/apps/studio/components/grid/components/editor/DateEditor.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { RenderEditCellProps } from 'react-data-grid' +import type { RenderEditCellProps } from 'react-data-grid' function autoFocusAndSelect(input: HTMLInputElement | null) { input?.focus() diff --git a/apps/studio/components/grid/components/editor/DateTimeEditor.tsx b/apps/studio/components/grid/components/editor/DateTimeEditor.tsx index a3ce7605c1c..aa6cfc69cbe 100644 --- a/apps/studio/components/grid/components/editor/DateTimeEditor.tsx +++ b/apps/studio/components/grid/components/editor/DateTimeEditor.tsx @@ -1,5 +1,5 @@ -import { ChangeEvent } from 'react' -import { RenderEditCellProps } from 'react-data-grid' +import type { ChangeEvent } from 'react' +import type { RenderEditCellProps } from 'react-data-grid' import dayjs from 'dayjs' import customParseFormat from 'dayjs/plugin/customParseFormat' diff --git a/apps/studio/components/grid/components/editor/JsonEditor.tsx b/apps/studio/components/grid/components/editor/JsonEditor.tsx index 4423413f064..694bf7e4916 100644 --- a/apps/studio/components/grid/components/editor/JsonEditor.tsx +++ b/apps/studio/components/grid/components/editor/JsonEditor.tsx @@ -1,5 +1,5 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import { RenderEditCellProps } from 'react-data-grid' +import type { RenderEditCellProps } from 'react-data-grid' import { useCallback, useState } from 'react' import { IconMaximize, Popover } from 'ui' diff --git a/apps/studio/components/grid/components/editor/NumberEditor.tsx b/apps/studio/components/grid/components/editor/NumberEditor.tsx index c660fb1a5fb..54ee0c7e285 100644 --- a/apps/studio/components/grid/components/editor/NumberEditor.tsx +++ b/apps/studio/components/grid/components/editor/NumberEditor.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { RenderEditCellProps } from 'react-data-grid' +import type { RenderEditCellProps } from 'react-data-grid' function autoFocusAndSelect(input: HTMLInputElement | null) { input?.focus() diff --git a/apps/studio/components/grid/components/editor/SelectEditor.tsx b/apps/studio/components/grid/components/editor/SelectEditor.tsx index dcb7705a17f..06828236b06 100644 --- a/apps/studio/components/grid/components/editor/SelectEditor.tsx +++ b/apps/studio/components/grid/components/editor/SelectEditor.tsx @@ -1,5 +1,5 @@ import { Select } from 'ui' -import { RenderEditCellProps } from 'react-data-grid' +import type { RenderEditCellProps } from 'react-data-grid' import { useTrackedState } from 'components/grid/store' diff --git a/apps/studio/components/grid/components/editor/TextEditor.tsx b/apps/studio/components/grid/components/editor/TextEditor.tsx index e900ca36038..590cd3fd5b0 100644 --- a/apps/studio/components/grid/components/editor/TextEditor.tsx +++ b/apps/studio/components/grid/components/editor/TextEditor.tsx @@ -1,6 +1,6 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { useCallback, useState } from 'react' -import { RenderEditCellProps } from 'react-data-grid' +import type { RenderEditCellProps } from 'react-data-grid' import { Button, IconMaximize, Popover } from 'ui' import { useTrackedState } from '../../store' import { BlockKeys, EmptyValue, MonacoEditor, NullValue } from '../common' diff --git a/apps/studio/components/grid/components/editor/TimeEditor.tsx b/apps/studio/components/grid/components/editor/TimeEditor.tsx index 21fc1e34011..ba9a34fdcab 100644 --- a/apps/studio/components/grid/components/editor/TimeEditor.tsx +++ b/apps/studio/components/grid/components/editor/TimeEditor.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { RenderEditCellProps } from 'react-data-grid' +import type { RenderEditCellProps } from 'react-data-grid' import dayjs from 'dayjs' import customParseFormat from 'dayjs/plugin/customParseFormat' diff --git a/apps/studio/components/grid/components/formatter/BooleanFormatter.tsx b/apps/studio/components/grid/components/formatter/BooleanFormatter.tsx index 795ae864d70..a7f766806d5 100644 --- a/apps/studio/components/grid/components/formatter/BooleanFormatter.tsx +++ b/apps/studio/components/grid/components/formatter/BooleanFormatter.tsx @@ -1,6 +1,6 @@ -import { PropsWithChildren } from 'react' -import { RenderCellProps } from 'react-data-grid' -import { SupaRow } from '../../types' +import type { PropsWithChildren } from 'react' +import type { RenderCellProps } from 'react-data-grid' +import type { SupaRow } from '../../types' import { NullValue } from '../common' export const BooleanFormatter = (p: PropsWithChildren>) => { diff --git a/apps/studio/components/grid/components/formatter/DefaultFormatter.tsx b/apps/studio/components/grid/components/formatter/DefaultFormatter.tsx index b1e405b139b..325fee62e19 100644 --- a/apps/studio/components/grid/components/formatter/DefaultFormatter.tsx +++ b/apps/studio/components/grid/components/formatter/DefaultFormatter.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -import { RenderCellProps } from 'react-data-grid' -import { SupaRow } from '../../types' +import type { RenderCellProps } from 'react-data-grid' +import type { SupaRow } from '../../types' import { NullValue } from '../common' import { EmptyValue } from '../common/EmptyValue' diff --git a/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx b/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx index 0f7693cdf24..034f4be7a05 100644 --- a/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx +++ b/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx @@ -1,14 +1,14 @@ import * as Tooltip from '@radix-ui/react-tooltip' import Link from 'next/link' -import { PropsWithChildren } from 'react' -import { RenderCellProps } from 'react-data-grid' +import type { PropsWithChildren } from 'react' +import type { RenderCellProps } from 'react-data-grid' import { Button, IconArrowRight } from 'ui' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useTableQuery } from 'data/tables/table-query' import { useTablesQuery } from 'data/tables/tables-query' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { SupaRow } from '../../types' +import type { SupaRow } from '../../types' import { NullValue } from '../common' interface Props extends PropsWithChildren> { diff --git a/apps/studio/components/grid/components/formatter/JsonFormatter.tsx b/apps/studio/components/grid/components/formatter/JsonFormatter.tsx index 083baf10a6e..21d5df8828d 100644 --- a/apps/studio/components/grid/components/formatter/JsonFormatter.tsx +++ b/apps/studio/components/grid/components/formatter/JsonFormatter.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -import { RenderCellProps } from 'react-data-grid' -import { SupaRow } from '../../types' +import type { RenderCellProps } from 'react-data-grid' +import type { SupaRow } from '../../types' import { EmptyValue, NullValue } from '../common' export const JsonFormatter = (p: React.PropsWithChildren>) => { diff --git a/apps/studio/components/grid/components/grid/AddColumn.tsx b/apps/studio/components/grid/components/grid/AddColumn.tsx index 37a94a0daf3..b9cb11ce8d1 100644 --- a/apps/studio/components/grid/components/grid/AddColumn.tsx +++ b/apps/studio/components/grid/components/grid/AddColumn.tsx @@ -1,4 +1,4 @@ -import { CalculatedColumn } from 'react-data-grid' +import type { CalculatedColumn } from 'react-data-grid' import { Button, IconPlus } from 'ui' import { ADD_COLUMN_KEY } from '../../constants' diff --git a/apps/studio/components/grid/components/grid/ColumnHeader.tsx b/apps/studio/components/grid/components/grid/ColumnHeader.tsx index a0443ce381e..a8fac748b5b 100644 --- a/apps/studio/components/grid/components/grid/ColumnHeader.tsx +++ b/apps/studio/components/grid/components/grid/ColumnHeader.tsx @@ -6,7 +6,7 @@ import * as React from 'react' import { useDrag, useDrop } from 'react-dnd' import { IconArrowRight, IconKey, IconLink, IconLock } from 'ui' import { useDispatch, useTrackedState } from '../../store' -import { ColumnHeaderProps, ColumnType, DragItem, GridForeignKey } from '../../types' +import type { ColumnHeaderProps, ColumnType, DragItem, GridForeignKey } from '../../types' import { ColumnMenu } from '../menu' import { useEffect } from 'react' diff --git a/apps/studio/components/grid/components/grid/Grid.tsx b/apps/studio/components/grid/components/grid/Grid.tsx index 3b849262131..dfd01db594a 100644 --- a/apps/studio/components/grid/components/grid/Grid.tsx +++ b/apps/studio/components/grid/components/grid/Grid.tsx @@ -16,7 +16,7 @@ import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constra import { useKeyboardShortcuts, useUrlState } from 'hooks' import { copyToClipboard } from 'lib/helpers' import { useDispatch, useTrackedState } from '../../store' -import { Filter, GridProps, SupaRow } from '../../types' +import type { Filter, GridProps, SupaRow } from '../../types' import RowRenderer from './RowRenderer' const rowKeyGetter = (row: SupaRow) => { diff --git a/apps/studio/components/grid/components/grid/RowRenderer.tsx b/apps/studio/components/grid/components/grid/RowRenderer.tsx index 12df5f412a2..fe5da9a4cf5 100644 --- a/apps/studio/components/grid/components/grid/RowRenderer.tsx +++ b/apps/studio/components/grid/components/grid/RowRenderer.tsx @@ -1,7 +1,7 @@ -import { Key } from 'react' +import type { Key } from 'react' import { TriggerEvent, useContextMenu } from 'react-contexify' import { Row, RenderRowProps } from 'react-data-grid' -import { SupaRow } from '../../types' +import type { SupaRow } from '../../types' import { ROW_CONTEXT_MENU_ID } from '../menu' export default function RowRenderer(key: Key, props: RenderRowProps) { diff --git a/apps/studio/components/grid/components/grid/SelectColumn.tsx b/apps/studio/components/grid/components/grid/SelectColumn.tsx index f73a610fc20..9148100d51a 100644 --- a/apps/studio/components/grid/components/grid/SelectColumn.tsx +++ b/apps/studio/components/grid/components/grid/SelectColumn.tsx @@ -11,7 +11,7 @@ import { Button, IconMaximize2 } from 'ui' import { SELECT_COLUMN_KEY } from '../../constants' import { useTrackedState } from '../../store' -import { SupaRow } from '../../types' +import type { SupaRow } from '../../types' export const SelectColumn: CalculatedColumn = { key: SELECT_COLUMN_KEY, diff --git a/apps/studio/components/grid/components/header/Header.tsx b/apps/studio/components/grid/components/header/Header.tsx index b4d786f212f..03495120e1a 100644 --- a/apps/studio/components/grid/components/header/Header.tsx +++ b/apps/studio/components/grid/components/header/Header.tsx @@ -7,7 +7,7 @@ import { ReactNode, useState } from 'react' import toast from 'react-hot-toast' import { useDispatch, useTrackedState } from 'components/grid/store' -import { Filter, Sort, SupaTable } from 'components/grid/types' +import type { Filter, Sort, SupaTable } from 'components/grid/types' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useTableRowsCountQuery } from 'data/table-rows/table-rows-count-query' import { fetchAllTableRows, useTableRowsQuery } from 'data/table-rows/table-rows-query' diff --git a/apps/studio/components/grid/components/header/RefreshButton.tsx b/apps/studio/components/grid/components/header/RefreshButton.tsx index 1ebd04dfb72..78e8741e3ba 100644 --- a/apps/studio/components/grid/components/header/RefreshButton.tsx +++ b/apps/studio/components/grid/components/header/RefreshButton.tsx @@ -1,11 +1,11 @@ import { useQueryClient } from '@tanstack/react-query' import { useParams } from 'common/hooks' -import { SupaTable } from 'components/grid/types' +import type { SupaTable } from 'components/grid/types' import { sqlKeys } from 'data/sql/keys' import { useEffect, useState } from 'react' import { Button, IconCheck, IconRefreshCw } from 'ui' -import { SupabaseGridQueue } from '../../constants' -import { TableLike } from 'hooks/misc/useTable' +import { SupabaseGridQueue } from '../../queue' +import type { TableLike } from 'hooks/misc/useTable' export type RefreshButtonProps = { table: TableLike | SupaTable diff --git a/apps/studio/components/grid/components/header/filter/FilterPopover.tsx b/apps/studio/components/grid/components/header/filter/FilterPopover.tsx index 1a438911474..7aa07a06982 100644 --- a/apps/studio/components/grid/components/header/filter/FilterPopover.tsx +++ b/apps/studio/components/grid/components/header/filter/FilterPopover.tsx @@ -5,7 +5,7 @@ import { KeyboardEvent, useCallback, useMemo, useState } from 'react' import { Button, IconFilter, IconPlus, Popover } from 'ui' import { formatFilterURLParams } from 'components/grid/SupabaseGrid.utils' -import { Filter, SupaTable } from 'components/grid/types' +import type { Filter, SupaTable } from 'components/grid/types' import { FilterOperatorOptions } from './Filter.constants' import FilterRow from './FilterRow' diff --git a/apps/studio/components/grid/components/header/filter/FilterRow.tsx b/apps/studio/components/grid/components/header/filter/FilterRow.tsx index b35d58b8b0a..bf20b15603c 100644 --- a/apps/studio/components/grid/components/header/filter/FilterRow.tsx +++ b/apps/studio/components/grid/components/header/filter/FilterRow.tsx @@ -2,7 +2,7 @@ import { KeyboardEvent, memo } from 'react' import { Button, IconChevronDown, IconX, Input } from 'ui' import { DropdownControl } from 'components/grid/components/common' -import { Filter, FilterOperator, SupaTable } from 'components/grid/types' +import type { Filter, FilterOperator, SupaTable } from 'components/grid/types' import { FilterOperatorOptions } from './Filter.constants' export interface FilterRowProps { diff --git a/apps/studio/components/grid/components/header/sort/SortPopover.tsx b/apps/studio/components/grid/components/header/sort/SortPopover.tsx index ddba5c7134f..80c3ef223ac 100644 --- a/apps/studio/components/grid/components/header/sort/SortPopover.tsx +++ b/apps/studio/components/grid/components/header/sort/SortPopover.tsx @@ -6,7 +6,7 @@ import { Button, IconChevronDown, IconList, Popover } from 'ui' import { DropdownControl } from 'components/grid/components/common' import { formatSortURLParams } from 'components/grid/SupabaseGrid.utils' -import { Sort, SupaTable } from 'components/grid/types' +import type { Sort, SupaTable } from 'components/grid/types' import SortRow from './SortRow' export interface SortPopoverProps { diff --git a/apps/studio/components/grid/components/header/sort/SortRow.tsx b/apps/studio/components/grid/components/header/sort/SortRow.tsx index 3ccc908f691..6fdeb0a63c7 100644 --- a/apps/studio/components/grid/components/header/sort/SortRow.tsx +++ b/apps/studio/components/grid/components/header/sort/SortRow.tsx @@ -3,7 +3,7 @@ import { memo, useRef } from 'react' import { useDrag, useDrop } from 'react-dnd' import { Button, IconMenu, IconX, Toggle } from 'ui' -import { DragItem, Sort, SupaTable } from 'components/grid/types' +import type { DragItem, Sort, SupaTable } from 'components/grid/types' export interface SortRowProps { table: SupaTable diff --git a/apps/studio/components/grid/components/menu/ColumnMenu.tsx b/apps/studio/components/grid/components/menu/ColumnMenu.tsx index 1323e9ba5fc..c669e66025d 100644 --- a/apps/studio/components/grid/components/menu/ColumnMenu.tsx +++ b/apps/studio/components/grid/components/menu/ColumnMenu.tsx @@ -1,5 +1,5 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import { CalculatedColumn } from 'react-data-grid' +import type { CalculatedColumn } from 'react-data-grid' import { Button, Divider, diff --git a/apps/studio/components/grid/components/menu/RowContextMenu.tsx b/apps/studio/components/grid/components/menu/RowContextMenu.tsx index 196417110e9..d2e6a1078b8 100644 --- a/apps/studio/components/grid/components/menu/RowContextMenu.tsx +++ b/apps/studio/components/grid/components/menu/RowContextMenu.tsx @@ -1,7 +1,7 @@ import { Item, ItemParams, Menu, PredicateParams, Separator } from 'react-contexify' import { IconClipboard, IconEdit, IconTrash } from 'ui' -import { SupaRow } from 'components/grid/types' +import type { SupaRow } from 'components/grid/types' import { useCallback } from 'react' import { useTableEditorStateSnapshot } from 'state/table-editor' import { useTrackedState } from '../../store' diff --git a/apps/studio/components/grid/constants.ts b/apps/studio/components/grid/constants.ts index 6fe451e7931..31559971291 100644 --- a/apps/studio/components/grid/constants.ts +++ b/apps/studio/components/grid/constants.ts @@ -1,7 +1,3 @@ -import PQueue from 'p-queue' - -export const SupabaseGridQueue = new PQueue({ concurrency: 1 }) - export const COLUMN_MIN_WIDTH = 100 export const STORAGE_KEY_PREFIX = 'supabase_grid' diff --git a/apps/studio/components/grid/query/Query.utils.ts b/apps/studio/components/grid/query/Query.utils.ts index 891af809b7b..fcfd7f05eca 100644 --- a/apps/studio/components/grid/query/Query.utils.ts +++ b/apps/studio/components/grid/query/Query.utils.ts @@ -1,5 +1,5 @@ import { ident, literal, format } from '@scaleleap/pg-format' -import { Filter, QueryPagination, QueryTable, Sort } from '../types' +import type { Filter, QueryPagination, QueryTable, Sort } from '../types' import type { Dictionary } from 'types' export function countQuery( diff --git a/apps/studio/components/grid/query/QueryAction.ts b/apps/studio/components/grid/query/QueryAction.ts index 3646e2cb836..cddc6acb0a9 100644 --- a/apps/studio/components/grid/query/QueryAction.ts +++ b/apps/studio/components/grid/query/QueryAction.ts @@ -1,4 +1,4 @@ -import { QueryTable } from '../types' +import type { QueryTable } from '../types' import type { Dictionary } from 'types' import { IQueryFilter, QueryFilter } from './QueryFilter' diff --git a/apps/studio/components/grid/query/QueryFilter.ts b/apps/studio/components/grid/query/QueryFilter.ts index f92fbd93493..03de13571ac 100644 --- a/apps/studio/components/grid/query/QueryFilter.ts +++ b/apps/studio/components/grid/query/QueryFilter.ts @@ -1,4 +1,4 @@ -import { Filter, FilterOperator, QueryTable, Sort } from '../types' +import type { Filter, FilterOperator, QueryTable, Sort } from '../types' import type { Dictionary } from 'types' import { IQueryModifier, QueryModifier } from './QueryModifier' diff --git a/apps/studio/components/grid/query/QueryModifier.ts b/apps/studio/components/grid/query/QueryModifier.ts index d9cced581ef..52eb3b7940a 100644 --- a/apps/studio/components/grid/query/QueryModifier.ts +++ b/apps/studio/components/grid/query/QueryModifier.ts @@ -1,5 +1,5 @@ import type { Dictionary } from 'types' -import { Filter, QueryPagination, QueryTable, Sort } from '../types' +import type { Filter, QueryPagination, QueryTable, Sort } from '../types' import { countQuery, deleteQuery, diff --git a/apps/studio/components/grid/queue.ts b/apps/studio/components/grid/queue.ts new file mode 100644 index 00000000000..0eaa984d86c --- /dev/null +++ b/apps/studio/components/grid/queue.ts @@ -0,0 +1,3 @@ +import PQueue from 'p-queue' + +export const SupabaseGridQueue = new PQueue({ concurrency: 1 }) diff --git a/apps/studio/components/grid/store/reducers/base.ts b/apps/studio/components/grid/store/reducers/base.ts index c08c6eb5b67..77877b02c62 100644 --- a/apps/studio/components/grid/store/reducers/base.ts +++ b/apps/studio/components/grid/store/reducers/base.ts @@ -1,6 +1,6 @@ import { CalculatedColumn } from 'react-data-grid' import { TOTAL_ROWS_RESET } from '../../constants' -import { GridProps, SavedState, SupaTable } from '../../types' +import type { GridProps, SavedState, SupaTable } from '../../types' export interface BaseInitialState { table: SupaTable | null diff --git a/apps/studio/components/grid/store/reducers/callback.ts b/apps/studio/components/grid/store/reducers/callback.ts index 30d7b4bb735..5fcb97e4c14 100644 --- a/apps/studio/components/grid/store/reducers/callback.ts +++ b/apps/studio/components/grid/store/reducers/callback.ts @@ -1,4 +1,4 @@ -import { SupaRow } from '../../types' +import type { SupaRow } from '../../types' export interface CallbackInitialState { onAddColumn: (() => void) | null diff --git a/apps/studio/components/grid/store/reducers/column.ts b/apps/studio/components/grid/store/reducers/column.ts index f6425bf8fee..a97bbd444e2 100644 --- a/apps/studio/components/grid/store/reducers/column.ts +++ b/apps/studio/components/grid/store/reducers/column.ts @@ -1,5 +1,5 @@ import update from 'immutability-helper' -import { CalculatedColumn } from 'react-data-grid' +import type { CalculatedColumn } from 'react-data-grid' import { cloneColumn, getInitialGridColumns } from '../../utils' import { INIT_ACTIONTYPE } from './base' diff --git a/apps/studio/components/grid/store/reducers/row.ts b/apps/studio/components/grid/store/reducers/row.ts index 637b4852388..c3d55664626 100644 --- a/apps/studio/components/grid/store/reducers/row.ts +++ b/apps/studio/components/grid/store/reducers/row.ts @@ -1,5 +1,5 @@ import { TOTAL_ROWS_INITIAL, TOTAL_ROWS_RESET } from '../../constants' -import { SupaRow } from '../../types' +import type { SupaRow } from '../../types' import { INIT_ACTIONTYPE } from './base' export interface RowInitialState { diff --git a/apps/studio/components/grid/utils/column.ts b/apps/studio/components/grid/utils/column.ts index c0870713639..b826f5fcd9e 100644 --- a/apps/studio/components/grid/utils/column.ts +++ b/apps/studio/components/grid/utils/column.ts @@ -1,6 +1,6 @@ import { CalculatedColumn } from 'react-data-grid' import { ADD_COLUMN_KEY, SELECT_COLUMN_KEY } from '../constants' -import { SavedState } from '../types' +import type { SavedState } from '../types' import { deepClone } from './common' export function cloneColumn(column: CalculatedColumn) { diff --git a/apps/studio/components/grid/utils/gridColumns.tsx b/apps/studio/components/grid/utils/gridColumns.tsx index e2c259b2c4d..d04773f0ef1 100644 --- a/apps/studio/components/grid/utils/gridColumns.tsx +++ b/apps/studio/components/grid/utils/gridColumns.tsx @@ -1,5 +1,5 @@ import { CalculatedColumn } from 'react-data-grid' -import { ColumnType, SupaColumn, SupaRow, SupaTable } from '../types' +import type { ColumnType, SupaColumn, SupaRow, SupaTable } from '../types' import { isArrayColumn, isBoolColumn, diff --git a/apps/studio/components/grid/utils/types.ts b/apps/studio/components/grid/utils/types.ts index f39279960b3..1c80442ab52 100644 --- a/apps/studio/components/grid/utils/types.ts +++ b/apps/studio/components/grid/utils/types.ts @@ -1,4 +1,4 @@ -import { SupaColumn } from '../types' +import type { SupaColumn } from '../types' const NUMERICAL_TYPES = [ 'smallint', diff --git a/apps/studio/components/interfaces/Account/AuditLogs.tsx b/apps/studio/components/interfaces/Account/AuditLogs.tsx index 93ec9d85a0c..2273b229437 100644 --- a/apps/studio/components/interfaces/Account/AuditLogs.tsx +++ b/apps/studio/components/interfaces/Account/AuditLogs.tsx @@ -8,7 +8,7 @@ import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { DatePicker } from 'components/ui/DatePicker' import ShimmeringLoader from 'components/ui/ShimmeringLoader' -import { AuditLog } from 'data/organizations/organization-audit-logs-query' +import type { AuditLog } from 'data/organizations/organization-audit-logs-query' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useProfileAuditLogsQuery } from 'data/profile/profile-audit-logs-query' import { useProjectsQuery } from 'data/projects/projects-query' diff --git a/apps/studio/components/interfaces/Account/Preferences/AccountInformation.tsx b/apps/studio/components/interfaces/Account/Preferences/AccountInformation.tsx index 543021e3011..c6c940aa975 100644 --- a/apps/studio/components/interfaces/Account/Preferences/AccountInformation.tsx +++ b/apps/studio/components/interfaces/Account/Preferences/AccountInformation.tsx @@ -3,7 +3,7 @@ import Link from 'next/link' import Panel from 'components/ui/Panel' import { useSession } from 'lib/auth' -import { Profile } from 'data/profile/types' +import type { Profile } from 'data/profile/types' const AccountInformation = ({ profile }: { profile?: Profile }) => { const session = useSession() diff --git a/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx b/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx index edba22306aa..525acd01e82 100644 --- a/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx +++ b/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx @@ -14,9 +14,9 @@ import z from 'zod' import { FormActions } from 'components/ui/Forms' import Panel from 'components/ui/Panel' import { useProfileUpdateMutation } from 'data/profile/profile-update-mutation' -import { Profile } from 'data/profile/types' +import type { Profile } from 'data/profile/types' import { useStore } from 'hooks' -import { FormSchema } from 'types' +import type { FormSchema } from 'types' const FormSchema = z.object({ first_name: z.string().optional(), diff --git a/apps/studio/components/interfaces/App/CommandMenuWrapper.tsx b/apps/studio/components/interfaces/App/CommandMenuWrapper.tsx index bd1d47edd5d..ca9daaa5688 100644 --- a/apps/studio/components/interfaces/App/CommandMenuWrapper.tsx +++ b/apps/studio/components/interfaces/App/CommandMenuWrapper.tsx @@ -6,7 +6,7 @@ import { CommandMenuProvider } from 'ui' import { codeBlock } from 'common-tags' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useProjectApiQuery } from 'data/config/project-api-query' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useEntityDefinitionsQuery } from 'data/database/entity-definitions-query' import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { uuidv4 } from 'lib/helpers' diff --git a/apps/studio/components/interfaces/AuditLogs/LogDetailsPanel.tsx b/apps/studio/components/interfaces/AuditLogs/LogDetailsPanel.tsx index 99c53e2f906..473a420974e 100644 --- a/apps/studio/components/interfaces/AuditLogs/LogDetailsPanel.tsx +++ b/apps/studio/components/interfaces/AuditLogs/LogDetailsPanel.tsx @@ -1,5 +1,5 @@ import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms' -import { AuditLog } from 'data/organizations/organization-audit-logs-query' +import type { AuditLog } from 'data/organizations/organization-audit-logs-query' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useProjectsQuery } from 'data/projects/projects-query' import dayjs from 'dayjs' diff --git a/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx b/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx index fa318e3075e..937b1535029 100644 --- a/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx +++ b/apps/studio/components/interfaces/Auth/AuthProvidersForm/FormField.tsx @@ -5,7 +5,7 @@ import ReactMarkdown from 'react-markdown' import { Button, IconEye, IconEyeOff, Input, InputNumber, Listbox, Toggle } from 'ui' import { BASE_PATH } from 'lib/constants' -import { Enum } from './AuthProvidersForm.types' +import type { Enum } from './AuthProvidersForm.types' interface FormFieldProps { name: string diff --git a/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx b/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx index 0dddeec961b..e9cf4695643 100644 --- a/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx +++ b/apps/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx @@ -5,13 +5,13 @@ import ReactMarkdown from 'react-markdown' import { Alert, Button, Collapsible, Form, IconCheck, IconChevronUp, Input } from 'ui' import { useParams } from 'common' -import { components } from 'data/api' +import type { components } from 'data/api' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' import { useCheckPermissions, useStore } from 'hooks' import { BASE_PATH } from 'lib/constants' import { ProviderCollapsibleClasses } from './AuthProvidersForm.constants' -import { Provider } from './AuthProvidersForm.types' +import type { Provider } from './AuthProvidersForm.types' import FormField from './FormField' export interface ProviderFormProps { diff --git a/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx b/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx index 0b3a5bf69f0..4b76b63eb1f 100644 --- a/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx +++ b/apps/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx @@ -19,7 +19,7 @@ import { FormActions, FormSection, FormSectionContent, FormSectionLabel } from ' import InformationBox from 'components/ui/InformationBox' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' import { useCheckPermissions } from 'hooks' -import { FormSchema } from 'types' +import type { FormSchema } from 'types' interface TemplateEditorProps { template: FormSchema diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyEditorPanel.utils.ts b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyEditorPanel.utils.ts index adb8328a37b..d15b78a73d4 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyEditorPanel.utils.ts +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyEditorPanel.utils.ts @@ -1,4 +1,4 @@ -import { PostgresPolicy } from '@supabase/postgres-meta' +import type { PostgresPolicy } from '@supabase/postgres-meta' import { Message } from 'ai/react' import { uuidv4 } from 'lib/helpers' diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx index 26ff309e444..2b3ea1336d9 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyHeader.tsx @@ -1,4 +1,4 @@ -import { PostgresPolicy } from '@supabase/postgres-meta' +import type { PostgresPolicy } from '@supabase/postgres-meta' import clsx from 'clsx' import { PanelLeftClose, PanelRightClose, X } from 'lucide-react' import { diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyDetails.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyDetails.tsx index a911d69967f..e5148c1faa9 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyDetails.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyDetails.tsx @@ -1,4 +1,4 @@ -import { PostgresPolicy } from '@supabase/postgres-meta' +import type { PostgresPolicy } from '@supabase/postgres-meta' import { CollapsibleContent_Shadcn_, CollapsibleTrigger_Shadcn_, diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx index 89d88937ca8..fcb02298024 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx @@ -1,4 +1,4 @@ -import { PostgresPolicy } from '@supabase/postgres-meta' +import type { PostgresPolicy } from '@supabase/postgres-meta' import { useQueryClient } from '@tanstack/react-query' import { useChat } from 'ai/react' import { useParams, useTelemetryProps } from 'common' diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyReview.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyReview.tsx index 1d6e4820392..a9f8a75ee9c 100644 --- a/apps/studio/components/interfaces/Auth/Policies/PolicyReview.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/PolicyReview.tsx @@ -2,7 +2,7 @@ import SqlEditor from 'components/ui/SqlEditor' import { isEmpty, noop } from 'lodash' import { useState } from 'react' import { Button, Modal } from 'ui' -import { PolicyForReview } from './Policies.types' +import type { PolicyForReview } from './Policies.types' interface PolicyReviewProps { policy: PolicyForReview diff --git a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.utils.ts b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.utils.ts index 8d33cbaf2a9..b69ad2be5a1 100644 --- a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.utils.ts +++ b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.utils.ts @@ -1,4 +1,4 @@ -import { components } from 'data/api' +import type { components } from 'data/api' type AuthConfig = components['schemas']['GoTrueConfigResponse'] diff --git a/apps/studio/components/interfaces/Auth/Users/UserDropdown.tsx b/apps/studio/components/interfaces/Auth/Users/UserDropdown.tsx index 1ec734d5fcd..82e1b24415f 100644 --- a/apps/studio/components/interfaces/Auth/Users/UserDropdown.tsx +++ b/apps/studio/components/interfaces/Auth/Users/UserDropdown.tsx @@ -8,7 +8,7 @@ import { useUserDeleteMutation } from 'data/auth/user-delete-mutation' import { useUserResetPasswordMutation } from 'data/auth/user-reset-password-mutation' import { useUserSendMagicLinkMutation } from 'data/auth/user-send-magic-link-mutation' import { useUserSendOTPMutation } from 'data/auth/user-send-otp-mutation' -import { User } from 'data/auth/users-query' +import type { User } from 'data/auth/users-query' import { useStore } from 'hooks' import { timeout } from 'lib/helpers' import { diff --git a/apps/studio/components/interfaces/Auth/Users/UserListItem.utils.ts b/apps/studio/components/interfaces/Auth/Users/UserListItem.utils.ts index cf48113df31..a2e1d1d34d8 100644 --- a/apps/studio/components/interfaces/Auth/Users/UserListItem.utils.ts +++ b/apps/studio/components/interfaces/Auth/Users/UserListItem.utils.ts @@ -1,4 +1,4 @@ -import { User } from 'data/auth/users-query' +import type { User } from 'data/auth/users-query' export function getDisplayName(user: User, fallback = '-'): string { const { diff --git a/apps/studio/components/interfaces/Auth/Users/UserSidePanel.tsx b/apps/studio/components/interfaces/Auth/Users/UserSidePanel.tsx index 5ade2553bb0..441b4969588 100644 --- a/apps/studio/components/interfaces/Auth/Users/UserSidePanel.tsx +++ b/apps/studio/components/interfaces/Auth/Users/UserSidePanel.tsx @@ -1,5 +1,5 @@ import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock' -import { User } from 'data/auth/users-query' +import type { User } from 'data/auth/users-query' import { SidePanel } from 'ui' interface UsersSidePanelProps { diff --git a/apps/studio/components/interfaces/Auth/Users/UsersList.tsx b/apps/studio/components/interfaces/Auth/Users/UsersList.tsx index bc625873e3c..1c1d5d5b8f3 100644 --- a/apps/studio/components/interfaces/Auth/Users/UsersList.tsx +++ b/apps/studio/components/interfaces/Auth/Users/UsersList.tsx @@ -2,9 +2,9 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' -import { User } from 'data/auth/users-query' +import type { User } from 'data/auth/users-query' import { useCheckPermissions } from 'hooks' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { IconAlertCircle } from 'ui' import UserListItem from './UsersListItem' import UsersListItemSkeleton from './UsersListItemSkeleton' diff --git a/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx b/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx index 3841efc6be1..1d300bcd92e 100644 --- a/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx +++ b/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx @@ -3,7 +3,7 @@ import { Badge } from 'ui' import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock' import Table from 'components/to-be-cleaned/Table' -import { User } from 'data/auth/users-query' +import type { User } from 'data/auth/users-query' import UserDropdown from './UserDropdown' import { getDisplayName } from './UserListItem.utils' diff --git a/apps/studio/components/interfaces/Billing/NoProjectsOnPaidOrgInfo.tsx b/apps/studio/components/interfaces/Billing/NoProjectsOnPaidOrgInfo.tsx index 47dc6839423..fec7938f1b3 100644 --- a/apps/studio/components/interfaces/Billing/NoProjectsOnPaidOrgInfo.tsx +++ b/apps/studio/components/interfaces/Billing/NoProjectsOnPaidOrgInfo.tsx @@ -4,7 +4,7 @@ import { IconInfo } from 'ui' import InformationBox from 'components/ui/InformationBox' import { useProjectsQuery } from 'data/projects/projects-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { Organization } from 'types' +import type { Organization } from 'types' interface NoProjectsOnPaidOrgInfoProps { organization?: Organization diff --git a/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts b/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts index f39ae7270f8..24ffa175b3a 100644 --- a/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts +++ b/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts @@ -1,5 +1,5 @@ import { IS_PLATFORM } from 'lib/constants' -import { OrgSubscription, ProjectSelectedAddon } from 'data/subscriptions/types' +import type { OrgSubscription, ProjectSelectedAddon } from 'data/subscriptions/types' export const getAddons = (selectedAddons: ProjectSelectedAddon[]) => { const computeInstance = selectedAddons.find((addon) => addon.type === 'compute_instance') diff --git a/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx b/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx index d60b2a11144..0e5690f8c9e 100644 --- a/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx +++ b/apps/studio/components/interfaces/BranchManagement/BranchPanels.tsx @@ -7,8 +7,8 @@ import { useInView } from 'react-intersection-observer' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useBranchQuery } from 'data/branches/branch-query' -import { Branch } from 'data/branches/branches-query' -import { GitHubPullRequest } from 'data/integrations/github-pull-requests-query' +import type { Branch } from 'data/branches/branches-query' +import type { GitHubPullRequest } from 'data/integrations/github-pull-requests-query' import { Badge, Button, diff --git a/apps/studio/components/interfaces/BranchManagement/BranchStatusBadge.tsx b/apps/studio/components/interfaces/BranchManagement/BranchStatusBadge.tsx index 091c2a6bc70..247e91f0037 100644 --- a/apps/studio/components/interfaces/BranchManagement/BranchStatusBadge.tsx +++ b/apps/studio/components/interfaces/BranchManagement/BranchStatusBadge.tsx @@ -1,5 +1,5 @@ import { WarningIcon } from 'components/ui/Icons' -import { BranchData } from 'data/branches/branch-query' +import type { BranchData } from 'data/branches/branch-query' import { ClockIcon } from 'lucide-react' import { Badge } from 'ui' diff --git a/apps/studio/components/interfaces/BranchManagement/Overview.tsx b/apps/studio/components/interfaces/BranchManagement/Overview.tsx index 1de91499180..01dd04d28a6 100644 --- a/apps/studio/components/interfaces/BranchManagement/Overview.tsx +++ b/apps/studio/components/interfaces/BranchManagement/Overview.tsx @@ -1,8 +1,8 @@ import { noop } from 'lodash' import { Button, IconChevronRight } from 'ui' -import { Branch } from 'data/branches/branches-query' -import { GitHubPullRequest } from 'data/integrations/github-pull-requests-query' +import type { Branch } from 'data/branches/branches-query' +import type { GitHubPullRequest } from 'data/integrations/github-pull-requests-query' import { BranchLoader, BranchManagementSection, BranchRow, BranchRowLoader } from './BranchPanels' import { PreviewBranchesEmptyState } from './EmptyStates' diff --git a/apps/studio/components/interfaces/Database/Backups/BackupItem.tsx b/apps/studio/components/interfaces/Database/Backups/BackupItem.tsx index e95775b7c1f..007c84f945a 100644 --- a/apps/studio/components/interfaces/Database/Backups/BackupItem.tsx +++ b/apps/studio/components/interfaces/Database/Backups/BackupItem.tsx @@ -3,7 +3,7 @@ import dayjs from 'dayjs' import { Badge, Button, IconDownload } from 'ui' import { useBackupDownloadMutation } from 'data/database/backup-download-mutation' -import { DatabaseBackup } from 'data/database/backups-query' +import type { DatabaseBackup } from 'data/database/backups-query' import { useCheckPermissions } from 'hooks' interface BackupItemProps { diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts b/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts index a380e8c86d4..c885e6fe5ee 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts +++ b/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts @@ -1,7 +1,7 @@ import dayjs from 'dayjs' import { ALL_TIMEZONES } from './PITR.constants' -import { Time } from './PITR.types' -import { ProjectSelectedAddon } from 'data/subscriptions/types' +import type { Time } from './PITR.types' +import type { ProjectSelectedAddon } from 'data/subscriptions/types' export const getPITRRetentionDuration = (addons: ProjectSelectedAddon[]) => { const pitrAddon = addons.find((addon) => addon.type === 'pitr') diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx b/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx index 2a92aa8409e..befe3e3f0ed 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx +++ b/apps/studio/components/interfaces/Database/Backups/PITR/PITRSelection.tsx @@ -28,7 +28,7 @@ import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { PROJECT_STATUS } from 'lib/constants' import Link from 'next/link' import BackupsEmpty from '../BackupsEmpty' -import { Timezone } from './PITR.types' +import type { Timezone } from './PITR.types' import { constrainDateToRange, formatNumberToTwoDigits, diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx b/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx index ca0a413309e..a41a1437a6f 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx +++ b/apps/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx @@ -8,7 +8,7 @@ import { FormPanel } from 'components/ui/Forms' import { useBackupsQuery } from 'data/database/backups-query' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useCheckPermissions } from 'hooks' -import { Timezone } from './PITR.types' +import type { Timezone } from './PITR.types' import { TimezoneSelection } from './TimezoneSelection' interface PITRStatusProps { diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/TimeInput.tsx b/apps/studio/components/interfaces/Database/Backups/PITR/TimeInput.tsx index f5ea08bd3d5..afae7774c37 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/TimeInput.tsx +++ b/apps/studio/components/interfaces/Database/Backups/PITR/TimeInput.tsx @@ -4,7 +4,7 @@ import { isNaN, noop } from 'lodash' import { ChangeEvent, useEffect, useState } from 'react' import { IconClock } from 'ui' -import { Time } from './PITR.types' +import type { Time } from './PITR.types' import { formatNumberToTwoDigits, formatTimeToTimeString } from './PITR.utils' // [Joshen] This is trying to do the same thing as TimeSplitInput.tsx diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/TimezoneSelection.tsx b/apps/studio/components/interfaces/Database/Backups/PITR/TimezoneSelection.tsx index 1b71f9414b6..34048f65597 100644 --- a/apps/studio/components/interfaces/Database/Backups/PITR/TimezoneSelection.tsx +++ b/apps/studio/components/interfaces/Database/Backups/PITR/TimezoneSelection.tsx @@ -16,7 +16,7 @@ import { import { CheckIcon, ChevronsUpDown } from 'lucide-react' import { ALL_TIMEZONES } from './PITR.constants' -import { Timezone } from './PITR.types' +import type { Timezone } from './PITR.types' interface TimezoneSelectionProps { selectedTimezone: Timezone diff --git a/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx b/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx index 620183f6bd4..6cef8de572b 100644 --- a/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx +++ b/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx @@ -26,7 +26,7 @@ import * as z from 'zod' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useEnumeratedTypeUpdateMutation } from 'data/enumerated-types/enumerated-type-update-mutation' -import { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' +import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' import { DragDropContext, Droppable, DroppableProvided } from 'react-beautiful-dnd' import EnumeratedTypeValueRow from './EnumeratedTypeValueRow' diff --git a/apps/studio/components/interfaces/Database/Functions/CreateFunction.tsx b/apps/studio/components/interfaces/Database/Functions/CreateFunction.tsx index f368883f318..1fa4c50e6c8 100644 --- a/apps/studio/components/interfaces/Database/Functions/CreateFunction.tsx +++ b/apps/studio/components/interfaces/Database/Functions/CreateFunction.tsx @@ -15,7 +15,7 @@ import { useDatabaseFunctionCreateMutation } from 'data/database-functions/datab import { useDatabaseFunctionUpdateMutation } from 'data/database-functions/database-functions-update-mutation' import { useSchemasQuery } from 'data/database/schemas-query' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import { convertArgumentTypes, convertConfigParams, hasWhitespace } from './Functions.utils' // [Refactor] Remove local state, just use the Form component diff --git a/apps/studio/components/interfaces/Database/Functions/Functions.utils.ts b/apps/studio/components/interfaces/Database/Functions/Functions.utils.ts index ea3b07a4131..f342c295a78 100644 --- a/apps/studio/components/interfaces/Database/Functions/Functions.utils.ts +++ b/apps/studio/components/interfaces/Database/Functions/Functions.utils.ts @@ -1,4 +1,4 @@ -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import { isEmpty } from 'lodash' /** diff --git a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx index 734c7d54ae4..4fb98099095 100644 --- a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx +++ b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx @@ -1,5 +1,5 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import { PostgresFunction } from '@supabase/postgres-meta' +import type { PostgresFunction } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { noop, partition } from 'lodash' import { useState } from 'react' diff --git a/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx b/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx index 115884584e4..31768e8066d 100644 --- a/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx @@ -1,4 +1,4 @@ -import { PostgresTrigger } from '@supabase/postgres-meta' +import type { PostgresTrigger } from '@supabase/postgres-meta' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' diff --git a/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx b/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx index 47dc88148cf..a146b94780d 100644 --- a/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx @@ -1,4 +1,4 @@ -import { PostgresTable, PostgresTrigger } from '@supabase/postgres-meta' +import type { PostgresTable, PostgresTrigger } from '@supabase/postgres-meta' import Image from 'next/legacy/image' import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react' diff --git a/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts b/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts index 16718b688ca..42d9d4e6250 100644 --- a/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts +++ b/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts @@ -6,7 +6,7 @@ import { ColumnPrivilegesGrant, grantColumnPrivileges, } from 'data/privileges/column-privileges-grant-mutation' -import { ColumnPrivilege } from 'data/privileges/column-privileges-query' +import type { ColumnPrivilege } from 'data/privileges/column-privileges-query' import { ColumnPrivilegesRevoke, revokeColumnPrivileges, @@ -15,7 +15,7 @@ import { TablePrivilegesGrant, grantTablePrivileges, } from 'data/privileges/table-privileges-grant-mutation' -import { TablePrivilege } from 'data/privileges/table-privileges-query' +import type { TablePrivilege } from 'data/privileges/table-privileges-query' import { TablePrivilegesRevoke, revokeTablePrivileges, diff --git a/apps/studio/components/interfaces/Database/Privileges/PrivilegesHead.tsx b/apps/studio/components/interfaces/Database/Privileges/PrivilegesHead.tsx index 268b497597f..6d425a25f82 100644 --- a/apps/studio/components/interfaces/Database/Privileges/PrivilegesHead.tsx +++ b/apps/studio/components/interfaces/Database/Privileges/PrivilegesHead.tsx @@ -1,4 +1,4 @@ -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import SchemaSelector from 'components/ui/SchemaSelector' import { diff --git a/apps/studio/components/interfaces/Database/Privileges/PrivilegesTable.tsx b/apps/studio/components/interfaces/Database/Privileges/PrivilegesTable.tsx index 5eb8543e471..2ecd97f29d3 100644 --- a/apps/studio/components/interfaces/Database/Privileges/PrivilegesTable.tsx +++ b/apps/studio/components/interfaces/Database/Privileges/PrivilegesTable.tsx @@ -1,5 +1,5 @@ import Table from 'components/to-be-cleaned/Table' -import { ColumnPrivilege } from 'data/privileges/column-privileges-query' +import type { ColumnPrivilege } from 'data/privileges/column-privileges-query' import { Switch } from 'ui' import { ALL_PRIVILEGE_TYPES, diff --git a/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx b/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx index 7990e809ae3..efb5dfdd93c 100644 --- a/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx +++ b/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx @@ -1,4 +1,4 @@ -import { PostgresRole } from '@supabase/postgres-meta' +import type { PostgresRole } from '@supabase/postgres-meta' import toast from 'react-hot-toast' import { Modal } from 'ui' diff --git a/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx b/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx index 5ef3e1f2af0..a138fd08ee9 100644 --- a/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx +++ b/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx @@ -1,5 +1,5 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import { PostgresRole } from '@supabase/postgres-meta' +import type { PostgresRole } from '@supabase/postgres-meta' import { useState } from 'react' import toast from 'react-hot-toast' import { diff --git a/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx b/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx index ea316a695ac..d647e2c85de 100644 --- a/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx +++ b/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx @@ -13,7 +13,7 @@ import ReactFlow, { useReactFlow, } from 'reactflow' -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useTablesQuery } from 'data/tables/tables-query' import { useTheme } from 'next-themes' diff --git a/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx b/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx index 32530d157b1..680da26e4c5 100644 --- a/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx +++ b/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx @@ -9,7 +9,7 @@ import { Button, IconChevronDown, IconHelpCircle, IconTerminal, SidePanel } from import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import InformationBox from 'components/ui/InformationBox' import SqlEditor from 'components/ui/SqlEditor' -import { DatabaseFunction } from 'data/database-functions/database-functions-query' +import type { DatabaseFunction } from 'data/database-functions/database-functions-query' export interface ChooseFunctionFormProps { triggerFunctions: DatabaseFunction[] diff --git a/apps/studio/components/interfaces/Database/Triggers/CreateTrigger.tsx b/apps/studio/components/interfaces/Database/Triggers/CreateTrigger.tsx index 824f19a46be..1a4722645b0 100644 --- a/apps/studio/components/interfaces/Database/Triggers/CreateTrigger.tsx +++ b/apps/studio/components/interfaces/Database/Triggers/CreateTrigger.tsx @@ -5,7 +5,7 @@ import { createContext, useContext, useEffect, useState } from 'react' import toast from 'react-hot-toast' import SVG from 'react-inlinesvg' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import FormEmptyBox from 'components/ui/FormBoxEmpty' diff --git a/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx b/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx index a6ab8041e05..37b62bbef6f 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx +++ b/apps/studio/components/interfaces/Database/Wrappers/DeleteWrapperModal.tsx @@ -1,6 +1,6 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useFDWDeleteMutation } from 'data/fdw/fdw-delete-mutation' -import { FDW } from 'data/fdw/fdws-query' +import type { FDW } from 'data/fdw/fdws-query' import { useStore } from 'hooks' import { Modal } from 'ui' import { WRAPPERS } from './Wrappers.constants' diff --git a/apps/studio/components/interfaces/Database/Wrappers/InputField.tsx b/apps/studio/components/interfaces/Database/Wrappers/InputField.tsx index b85d46da7ce..500b950c9a2 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/InputField.tsx +++ b/apps/studio/components/interfaces/Database/Wrappers/InputField.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import { useState } from 'react' import { Button, IconEye, IconEyeOff, IconHelpCircle, IconLoader, Input } from 'ui' -import { ServerOption } from './Wrappers.types' +import type { ServerOption } from './Wrappers.types' interface InputFieldProps { option: ServerOption diff --git a/apps/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx b/apps/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx index 9d7c4b9f766..dbb2e3e816a 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx +++ b/apps/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx @@ -6,9 +6,9 @@ import Link from 'next/link' import { Button, Collapsible, IconChevronUp, IconEdit, IconExternalLink, IconTrash } from 'ui' import { useParams } from 'common/hooks' -import { FDW } from 'data/fdw/fdws-query' +import type { FDW } from 'data/fdw/fdws-query' import { useCheckPermissions } from 'hooks' -import { WrapperMeta } from './Wrappers.types' +import type { WrapperMeta } from './Wrappers.types' interface WrapperRowProps { wrappers: FDW[] diff --git a/apps/studio/components/interfaces/Database/Wrappers/WrapperTableEditor.tsx b/apps/studio/components/interfaces/Database/Wrappers/WrapperTableEditor.tsx index cc335f5a88a..997cff04d64 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/WrapperTableEditor.tsx +++ b/apps/studio/components/interfaces/Database/Wrappers/WrapperTableEditor.tsx @@ -6,7 +6,7 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useSchemasQuery } from 'data/database/schemas-query' import { Form, IconDatabase, IconPlus, Input, Listbox, Modal, SidePanel } from 'ui' import WrapperDynamicColumns from './WrapperDynamicColumns' -import { Table, TableOption } from './Wrappers.types' +import type { Table, TableOption } from './Wrappers.types' import { makeValidateRequired } from './Wrappers.utils' export type WrapperTableEditorProps = { diff --git a/apps/studio/components/interfaces/Database/Wrappers/Wrappers.constants.ts b/apps/studio/components/interfaces/Database/Wrappers/Wrappers.constants.ts index 6dbc3a8b2af..cb67d097fb9 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/Wrappers.constants.ts +++ b/apps/studio/components/interfaces/Database/Wrappers/Wrappers.constants.ts @@ -1,5 +1,5 @@ import { BASE_PATH } from 'lib/constants' -import { WrapperMeta } from './Wrappers.types' +import type { WrapperMeta } from './Wrappers.types' export const WRAPPER_HANDLERS = { STRIPE: 'stripe_fdw_handler', diff --git a/apps/studio/components/interfaces/Database/Wrappers/Wrappers.utils.ts b/apps/studio/components/interfaces/Database/Wrappers/Wrappers.utils.ts index 06e49f0beb7..80ceb01f40c 100644 --- a/apps/studio/components/interfaces/Database/Wrappers/Wrappers.utils.ts +++ b/apps/studio/components/interfaces/Database/Wrappers/Wrappers.utils.ts @@ -1,5 +1,5 @@ import { WRAPPER_HANDLERS } from './Wrappers.constants' -import { WrapperMeta } from './Wrappers.types' +import type { WrapperMeta } from './Wrappers.types' export const makeValidateRequired = (options: { name: string; required: boolean }[]) => { const requiredOptionsSet = new Set( diff --git a/apps/studio/components/interfaces/Docs/Authentication.tsx b/apps/studio/components/interfaces/Docs/Authentication.tsx index 296584ac070..d3a44692039 100644 --- a/apps/studio/components/interfaces/Docs/Authentication.tsx +++ b/apps/studio/components/interfaces/Docs/Authentication.tsx @@ -1,6 +1,6 @@ import Link from 'next/link' -import { AutoApiService } from 'data/config/project-api-query' +import type { AutoApiService } from 'data/config/project-api-query' import CodeSnippet from './CodeSnippet' import Snippets from './Snippets' diff --git a/apps/studio/components/interfaces/Docs/Introduction.tsx b/apps/studio/components/interfaces/Docs/Introduction.tsx index fcdd3f48e13..579e13dec51 100644 --- a/apps/studio/components/interfaces/Docs/Introduction.tsx +++ b/apps/studio/components/interfaces/Docs/Introduction.tsx @@ -1,4 +1,4 @@ -import { AutoApiService } from 'data/config/project-api-query' +import type { AutoApiService } from 'data/config/project-api-query' import Snippets from 'components/interfaces/Docs/Snippets' import CodeSnippet from './CodeSnippet' diff --git a/apps/studio/components/interfaces/Docs/LangSelector.tsx b/apps/studio/components/interfaces/Docs/LangSelector.tsx index 290bf97097e..64cfd60e1da 100644 --- a/apps/studio/components/interfaces/Docs/LangSelector.tsx +++ b/apps/studio/components/interfaces/Docs/LangSelector.tsx @@ -9,7 +9,7 @@ import { IconKey, } from 'ui' -import { showApiKey } from 'components/interfaces/Docs/Docs.types' +import type { showApiKey } from 'components/interfaces/Docs/Docs.types' const DEFAULT_KEY = { name: 'hide', key: 'SUPABASE_KEY' } diff --git a/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx b/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx index 7184b7e8002..a1006a97540 100644 --- a/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx +++ b/apps/studio/components/interfaces/Docs/Pages/UserManagement.tsx @@ -1,7 +1,7 @@ import Link from 'next/link' import { useRouter } from 'next/router' -import { AutoApiService } from 'data/config/project-api-query' +import type { AutoApiService } from 'data/config/project-api-query' import { makeRandomString } from 'lib/helpers' import CodeSnippet from '../CodeSnippet' import Snippets from '../Snippets' diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecret.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecret.tsx index 19ee0b99205..222d25d9e2f 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecret.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecret.tsx @@ -1,5 +1,5 @@ import Table from 'components/to-be-cleaned/Table' -import { ProjectSecret } from 'data/secrets/secrets-query' +import type { ProjectSecret } from 'data/secrets/secrets-query' import { Button, IconTrash } from 'ui' interface EdgeFunctionSecretProps { diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx index fc600816fe6..0d882a09d21 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx @@ -8,7 +8,7 @@ import { useParams } from 'common/hooks' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' -import { EdgeFunctionsResponse } from 'data/edge-functions/edge-functions-query' +import type { EdgeFunctionsResponse } from 'data/edge-functions/edge-functions-query' interface EdgeFunctionsListItemProps { function: EdgeFunctionsResponse diff --git a/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx b/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx index 0249d62f150..ce184e3625b 100644 --- a/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx +++ b/apps/studio/components/interfaces/Functions/TerminalInstructions.tsx @@ -8,7 +8,7 @@ import CommandRender from 'components/interfaces/Functions/CommandRender' import { useAccessTokensQuery } from 'data/access-tokens/access-tokens-query' import { useProjectApiQuery } from 'data/config/project-api-query' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' -import { Commands } from './Functions.types' +import type { Commands } from './Functions.types' interface TerminalInstructionsProps { closable?: boolean diff --git a/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx b/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx index bf47d10edff..6561f818160 100644 --- a/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx +++ b/apps/studio/components/interfaces/Home/Connect/ConnectTabContent.tsx @@ -6,7 +6,7 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useProjectSettingsQuery } from 'data/config/project-settings-query' import { usePoolingConfigurationQuery } from 'data/database/pooling-configuration-query' import { pluckObjectFields } from 'lib/helpers' -import { projectKeys } from './Connect.types' +import type { projectKeys } from './Connect.types' interface ConnectContentTabProps { projectKeys: projectKeys diff --git a/apps/studio/components/interfaces/Home/Connect/content/astro/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/astro/supabasejs/content.tsx index 338da090d58..aecccde06e9 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/astro/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/astro/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx index c862728307e..9c6a34acf27 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/drizzle/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/exporeactnative/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/exporeactnative/supabasejs/content.tsx index 56e535f80c3..820bac7fe5f 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/exporeactnative/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/exporeactnative/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/nextjs/app/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/nextjs/app/supabasejs/content.tsx index cb9e66fe3c6..077a7dfc9b5 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/nextjs/app/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/nextjs/app/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/nextjs/pages/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/nextjs/pages/supabasejs/content.tsx index cf0d13d153a..4131fd593cf 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/nextjs/pages/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/nextjs/pages/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/nuxt/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/nuxt/supabasejs/content.tsx index c42375e073e..137f60e09c1 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/nuxt/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/nuxt/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx index 1295875560a..8ec64311300 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/prisma/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/react/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/react/supabasejs/content.tsx index dbd7d2fdae9..3a6e6e6a2f1 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/react/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/react/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/refine/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/refine/supabasejs/content.tsx index 1454a0c4692..1d56893b856 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/refine/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/refine/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/remix/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/remix/supabasejs/content.tsx index d584a944daf..80e12a0a088 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/remix/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/remix/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/solidjs/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/solidjs/supabasejs/content.tsx index a0e2c647066..54f2ca88ca6 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/solidjs/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/solidjs/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/sveltekit/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/sveltekit/supabasejs/content.tsx index 6307039c60e..7a6c11670ce 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/sveltekit/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/sveltekit/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/Connect/content/vuejs/supabasejs/content.tsx b/apps/studio/components/interfaces/Home/Connect/content/vuejs/supabasejs/content.tsx index 0bf5c3b5f4b..a2765379e87 100644 --- a/apps/studio/components/interfaces/Home/Connect/content/vuejs/supabasejs/content.tsx +++ b/apps/studio/components/interfaces/Home/Connect/content/vuejs/supabasejs/content.tsx @@ -1,4 +1,4 @@ -import { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' +import type { ContentFileProps } from 'components/interfaces/Home/Connect/Connect.types' import { ConnectTabs, diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx index 490b8616805..36741d0d1b0 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx @@ -1,9 +1,9 @@ import { GitBranch, Github } from 'lucide-react' import CardButton from 'components/ui/CardButton' -import { IntegrationProjectConnection } from 'data/integrations/integrations.types' -import { ProjectInfo } from 'data/projects/projects-query' -import { ResourceWarning } from 'data/usage/resource-warnings-query' +import type { IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { ProjectInfo } from 'data/projects/projects-query' +import type { ResourceWarning } from 'data/usage/resource-warnings-query' import { BASE_PATH } from 'lib/constants' import { inferProjectStatus } from './ProjectCard.utils' import { ProjectCardStatus } from './ProjectCardStatus' diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.utils.ts b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.utils.ts index 99dbf03c183..26b01d598e2 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.utils.ts +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.utils.ts @@ -1,4 +1,4 @@ -import { ProjectInfo } from 'data/projects/projects-query' +import type { ProjectInfo } from 'data/projects/projects-query' import { PROJECT_STATUS } from 'lib/constants' export const inferProjectStatus = (project: ProjectInfo) => { diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectCardStatus.tsx b/apps/studio/components/interfaces/Home/ProjectList/ProjectCardStatus.tsx index d937c8d1071..65fa35bf8ba 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectCardStatus.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectCardStatus.tsx @@ -1,7 +1,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { RESOURCE_WARNING_MESSAGES } from 'components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.constants' import { getWarningContent } from 'components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.utils' -import { ResourceWarning } from 'data/usage/resource-warnings-query' +import type { ResourceWarning } from 'data/usage/resource-warnings-query' import { AlertTriangle, Info, RefreshCcw } from 'lucide-react' import { Alert_Shadcn_, AlertTitle_Shadcn_, cn, IconPauseCircle } from 'ui' import { InferredProjectStatus } from './ProjectCard.utils' diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx b/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx index 5d3cc9b5b19..758c23f4a04 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx @@ -16,7 +16,7 @@ import { ResourceWarning, useResourceWarningsQuery } from 'data/usage/resource-w import { useSelectedOrganization } from 'hooks' import { IS_PLATFORM } from 'lib/constants' import { makeRandomString } from 'lib/helpers' -import { Organization, ResponseError } from 'types' +import type { Organization, ResponseError } from 'types' import { Button, IconPlus } from 'ui' import ProjectCard from './ProjectCard' import ShimmeringCard from './ShimmeringCard' diff --git a/apps/studio/components/interfaces/Home/ProjectUsage.tsx b/apps/studio/components/interfaces/Home/ProjectUsage.tsx index fd0ad92a724..cdd7def1fe3 100644 --- a/apps/studio/components/interfaces/Home/ProjectUsage.tsx +++ b/apps/studio/components/interfaces/Home/ProjectUsage.tsx @@ -4,7 +4,7 @@ import sumBy from 'lodash/sumBy' import Link from 'next/link' import { useRouter } from 'next/router' import { useState } from 'react' -import { ChartIntervals } from 'types' +import type { ChartIntervals } from 'types' import { Button, DropdownMenu, diff --git a/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx b/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx index 14ea02bebf9..3c3f1fd8474 100644 --- a/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx +++ b/apps/studio/components/interfaces/Integrations/IntegrationConnection.tsx @@ -25,7 +25,7 @@ import { } from 'components/interfaces/Integrations/IntegrationPanels' import { WarningIcon } from 'components/ui/Icons' import { useIntegrationsVercelConnectionSyncEnvsMutation } from 'data/integrations/integrations-vercel-connection-sync-envs-mutation' -import { IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { IntegrationProjectConnection } from 'data/integrations/integrations.types' import { useProjectsQuery } from 'data/projects/projects-query' import { useStore } from 'hooks' diff --git a/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx b/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx index 58caf455aaa..f72e7bceeef 100644 --- a/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx +++ b/apps/studio/components/interfaces/Integrations/IntegrationPanels.tsx @@ -3,7 +3,10 @@ import Image from 'next/legacy/image' import React from 'react' import { Markdown } from 'components/interfaces/Markdown' -import { Integration, IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { + Integration, + IntegrationProjectConnection, +} from 'data/integrations/integrations.types' import { useProjectsQuery } from 'data/projects/projects-query' import { BASE_PATH } from 'lib/constants' import { getIntegrationConfigurationUrl } from 'lib/integration-utils' diff --git a/apps/studio/components/interfaces/Integrations/OrganizationPicker.tsx b/apps/studio/components/interfaces/Integrations/OrganizationPicker.tsx index f706b5f120c..e4ca69f3e94 100644 --- a/apps/studio/components/interfaces/Integrations/OrganizationPicker.tsx +++ b/apps/studio/components/interfaces/Integrations/OrganizationPicker.tsx @@ -1,10 +1,10 @@ import { getHasInstalledObject } from 'components/layouts/IntegrationsLayout/Integrations.utils' import { useIntegrationsQuery } from 'data/integrations/integrations-query' -import { IntegrationName } from 'data/integrations/integrations.types' +import type { IntegrationName } from 'data/integrations/integrations.types' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useMemo, useRef, useState } from 'react' -import { Organization } from 'types' +import type { Organization } from 'types' import { Badge, Button, diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx index ee1684e5c4e..5943872e241 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx @@ -1,8 +1,8 @@ import * as Tooltip from '@radix-ui/react-tooltip' import Link from 'next/link' -import { OrgSubscription } from 'data/subscriptions/types' -import { OrgUsageResponse } from 'data/usage/org-usage-query' +import type { OrgSubscription } from 'data/subscriptions/types' +import type { OrgUsageResponse } from 'data/usage/org-usage-query' import { Button, IconChevronRight, IconPieChart } from 'ui' import { Metric, USAGE_APPROACHING_THRESHOLD } from './BillingBreakdown.constants' import { billingMetricUnit, formatUsage } from '../helpers' diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/ComputeMetric.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/ComputeMetric.tsx index 2746c44e686..54e89157e60 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/ComputeMetric.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/ComputeMetric.tsx @@ -1,7 +1,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import Link from 'next/link' -import { OrgUsageResponse } from 'data/usage/org-usage-query' +import type { OrgUsageResponse } from 'data/usage/org-usage-query' import { IconChevronRight, IconPieChart } from 'ui' import { Metric } from './BillingBreakdown.constants' import { formatUsage } from '../helpers' diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx index 7b4485b01a8..95247b0905c 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/ChangePaymentMethodModal.tsx @@ -1,8 +1,8 @@ import { useParams } from 'common' -import { OrganizationPaymentMethod } from 'data/organizations/organization-payment-methods-query' +import type { OrganizationPaymentMethod } from 'data/organizations/organization-payment-methods-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation' -import { SubscriptionTier } from 'data/subscriptions/types' +import type { SubscriptionTier } from 'data/subscriptions/types' import { useStore } from 'hooks' import { Button, Modal } from 'ui' diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx index 68bc419fa7e..770976f4009 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/DeletePaymentMethodModal.tsx @@ -1,6 +1,6 @@ import { useParams } from 'common' import { useOrganizationPaymentMethodDeleteMutation } from 'data/organizations/organization-payment-method-delete-mutation' -import { OrganizationPaymentMethod } from 'data/organizations/organization-payment-methods-query' +import type { OrganizationPaymentMethod } from 'data/organizations/organization-payment-methods-query' import { useStore } from 'hooks' import { Alert, Button, Modal } from 'ui' diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx index 32b384ba0bf..da23dd296e5 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx @@ -1,5 +1,5 @@ -import { ProjectInfo } from 'data/projects/projects-query' -import { OrgSubscription, ProjectAddon } from 'data/subscriptions/types' +import type { ProjectInfo } from 'data/projects/projects-query' +import type { OrgSubscription, ProjectAddon } from 'data/subscriptions/types' import { PricingInformation } from 'shared-data' import { Alert, IconAlertOctagon, IconMinusCircle, IconPauseCircle, Modal } from 'ui' diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx index 29019f47d5c..ed7f6166289 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx @@ -4,7 +4,7 @@ import { useReducer, useRef, useState } from 'react' import { useParams } from 'common' import { useSendDowngradeFeedbackMutation } from 'data/feedback/exit-survey-send' -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation' import { useFlag, useStore } from 'hooks' import { Alert, Button, Input, Modal } from 'ui' diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx index a8910fead88..fbdae99ac0b 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx @@ -15,7 +15,7 @@ import { useOrganizationBillingSubscriptionPreview } from 'data/organizations/or import { useOrgPlansQuery } from 'data/subscriptions/org-plans-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation' -import { OrgPlan, SubscriptionTier } from 'data/subscriptions/types' +import type { OrgPlan, SubscriptionTier } from 'data/subscriptions/types' import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import Telemetry from 'lib/telemetry' diff --git a/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx b/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx index 911baec6c53..2a694d3cf24 100644 --- a/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx +++ b/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx @@ -12,7 +12,7 @@ import { } from 'components/layouts/Scaffold' import { useGitHubConnectionDeleteMutation } from 'data/integrations/github-connection-delete-mutation' import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' -import { IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { IntegrationProjectConnection } from 'data/integrations/integrations.types' import { useSelectedOrganization, useStore } from 'hooks' import { BASE_PATH, OPT_IN_TAGS } from 'lib/constants' import { useSidePanelsStateSnapshot } from 'state/side-panels' diff --git a/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelGitHubRepoLinker.tsx b/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelGitHubRepoLinker.tsx index 95e04e19a31..33cc3504f94 100644 --- a/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelGitHubRepoLinker.tsx +++ b/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelGitHubRepoLinker.tsx @@ -7,7 +7,7 @@ import { Markdown } from 'components/interfaces/Markdown' import { useGitHubAuthorizationQuery } from 'data/integrations/github-authorization-query' import { useGitHubConnectionCreateMutation } from 'data/integrations/github-connection-create-mutation' import { useGitHubRepositoriesQuery } from 'data/integrations/github-repositories-query' -import { IntegrationConnectionsCreateVariables } from 'data/integrations/integrations.types' +import type { IntegrationConnectionsCreateVariables } from 'data/integrations/integrations.types' import { useProjectsQuery } from 'data/projects/projects-query' import { useSelectedOrganization } from 'hooks' import { openInstallGitHubIntegrationWindow } from 'lib/github' diff --git a/apps/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx b/apps/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx index b3b1101188e..0aefed076b3 100644 --- a/apps/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx +++ b/apps/studio/components/interfaces/Organization/NewProject/FreeProjectLimitWarning.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import { Button, IconAlertCircle } from 'ui' import InformationBox from 'components/ui/InformationBox' -import { MemberWithFreeProjectLimit } from 'data/organizations/free-project-limit-check-query' +import type { MemberWithFreeProjectLimit } from 'data/organizations/free-project-limit-check-query' interface FreeProjectLimitWarningProps { membersExceededLimit: MemberWithFreeProjectLimit[] diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizedAppRow.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizedAppRow.tsx index 3402be2d4d7..4e2d61718f2 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizedAppRow.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/AuthorizedAppRow.tsx @@ -1,5 +1,5 @@ import Table from 'components/to-be-cleaned/Table' -import { AuthorizedApp } from 'data/oauth/authorized-apps-query' +import type { AuthorizedApp } from 'data/oauth/authorized-apps-query' import dayjs from 'dayjs' import { Button, IconTrash } from 'ui' diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx index aa9a5a6ed49..69abd09e844 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/DeleteAppModal.tsx @@ -1,6 +1,6 @@ import { useParams } from 'common' import { useOAuthAppDeleteMutation } from 'data/oauth/oauth-app-delete-mutation' -import { OAuthApp } from 'data/oauth/oauth-apps-query' +import type { OAuthApp } from 'data/oauth/oauth-apps-query' import { useStore } from 'hooks' import { Alert, IconLock, Modal } from 'ui' diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx index b906ddc904d..76391b71602 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/OAuthAppRow.tsx @@ -1,5 +1,5 @@ import Table from 'components/to-be-cleaned/Table' -import { OAuthApp } from 'data/oauth/oauth-apps-query' +import type { OAuthApp } from 'data/oauth/oauth-apps-query' import dayjs from 'dayjs' import { copyToClipboard } from 'lib/helpers' import { useState } from 'react' diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx index ec73cc2897c..179f341a6f1 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/PublishAppSidePanel/index.tsx @@ -1,14 +1,14 @@ import clsx from 'clsx' import { ChangeEvent, useEffect, useRef, useState } from 'react' -import { OAuthScope } from '@supabase/shared-types/out/constants' +import type { OAuthScope } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { OAuthAppCreateResponse, useOAuthAppCreateMutation, } from 'data/oauth/oauth-app-create-mutation' import { useOAuthAppUpdateMutation } from 'data/oauth/oauth-app-update-mutation' -import { OAuthApp } from 'data/oauth/oauth-apps-query' +import type { OAuthApp } from 'data/oauth/oauth-apps-query' import { useStore } from 'hooks' import { isValidHttpUrl, uuidv4 } from 'lib/helpers' import { uploadAttachment } from 'lib/upload' diff --git a/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx b/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx index dcedd1fde07..47f7e64bcb9 100644 --- a/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx +++ b/apps/studio/components/interfaces/Organization/OAuthApps/RevokeAppModal.tsx @@ -1,6 +1,6 @@ import { useParams } from 'common' import { useAuthorizedAppRevokeMutation } from 'data/oauth/authorized-app-revoke-mutation' -import { AuthorizedApp } from 'data/oauth/authorized-apps-query' +import type { AuthorizedApp } from 'data/oauth/authorized-apps-query' import { useStore } from 'hooks' import { Alert, IconLock, Modal } from 'ui' diff --git a/apps/studio/components/interfaces/Organization/Organization.utils.ts b/apps/studio/components/interfaces/Organization/Organization.utils.ts index 44e6c600804..e8bd15acadf 100644 --- a/apps/studio/components/interfaces/Organization/Organization.utils.ts +++ b/apps/studio/components/interfaces/Organization/Organization.utils.ts @@ -1,4 +1,4 @@ -import { OrganizationMember } from 'data/organizations/organization-members-query' +import type { OrganizationMember } from 'data/organizations/organization-members-query' // Invite is expired if older than 24hrs export function isInviteExpired(timestamp: string) { diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx index 87f91c21ffe..4a80d1e590d 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx @@ -7,9 +7,9 @@ import { Button, Form, IconMail, Input, Listbox, Modal } from 'ui' import { object, string } from 'yup' import { useOrganizationMemberInviteCreateMutation } from 'data/organizations/organization-member-invite-create-mutation' -import { OrganizationMember } from 'data/organizations/organization-members-query' +import type { OrganizationMember } from 'data/organizations/organization-members-query' import { doPermissionsCheck, useGetPermissions, useStore } from 'hooks' -import { Role } from 'types' +import type { Role } from 'types' export interface InviteMemberButtonProps { orgId: number diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx index 4e73f696c3d..6a22efd6008 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx @@ -19,10 +19,10 @@ import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useOrganizationMemberDeleteMutation } from 'data/organizations/organization-member-delete-mutation' import { useOrganizationMemberInviteCreateMutation } from 'data/organizations/organization-member-invite-create-mutation' import { useOrganizationMemberInviteDeleteMutation } from 'data/organizations/organization-member-invite-delete-mutation' -import { OrganizationMember } from 'data/organizations/organization-members-query' +import type { OrganizationMember } from 'data/organizations/organization-members-query' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useCheckPermissions, useIsFeatureEnabled, useSelectedOrganization, useStore } from 'hooks' -import { Role } from 'types' +import type { Role } from 'types' import { isInviteExpired } from '../Organization.utils' import { useGetRolesManagementPermissions } from './TeamSettings.utils' diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.utils.ts b/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.utils.ts index 942362c98bb..7f5136cba16 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.utils.ts +++ b/apps/studio/components/interfaces/Organization/TeamSettings/TeamSettings.utils.ts @@ -1,7 +1,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { OrganizationMember } from 'data/organizations/organization-members-query' +import type { OrganizationMember } from 'data/organizations/organization-members-query' import { doPermissionsCheck, useGetPermissions } from 'hooks' -import { Permission, Role } from 'types' +import type { Permission, Role } from 'types' export const useGetRolesManagementPermissions = ( orgId?: number, diff --git a/apps/studio/components/interfaces/Organization/Usage/Activity.tsx b/apps/studio/components/interfaces/Organization/Usage/Activity.tsx index 6ff0b0c997b..f80c6923fb6 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Activity.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Activity.tsx @@ -1,6 +1,6 @@ import { DataPoint } from 'data/analytics/constants' import { PricingMetric, useOrgDailyStatsQuery } from 'data/analytics/org-daily-stats-query' -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' import UsageSection from './UsageSection/UsageSection' export interface ActivityProps { diff --git a/apps/studio/components/interfaces/Organization/Usage/Bandwidth.tsx b/apps/studio/components/interfaces/Organization/Usage/Bandwidth.tsx index bac6769df6b..f6bbf70669b 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Bandwidth.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Bandwidth.tsx @@ -1,6 +1,6 @@ import { DataPoint } from 'data/analytics/constants' import { PricingMetric, useOrgDailyStatsQuery } from 'data/analytics/org-daily-stats-query' -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' import UsageSection from './UsageSection/UsageSection' export interface BandwidthProps { diff --git a/apps/studio/components/interfaces/Organization/Usage/Compute.tsx b/apps/studio/components/interfaces/Organization/Usage/Compute.tsx index f4b54733bc0..7753a06f78a 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Compute.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Compute.tsx @@ -1,6 +1,6 @@ import { DataPoint } from 'data/analytics/constants' import { ComputeUsageMetric, computeUsageMetricLabel } from 'data/analytics/org-daily-stats-query' -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' import SectionContent from './SectionContent' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import AlertError from 'components/ui/AlertError' diff --git a/apps/studio/components/interfaces/Organization/Usage/SizeAndCounts.tsx b/apps/studio/components/interfaces/Organization/Usage/SizeAndCounts.tsx index 9ba7b468ef4..96bc874ff8e 100644 --- a/apps/studio/components/interfaces/Organization/Usage/SizeAndCounts.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/SizeAndCounts.tsx @@ -1,6 +1,6 @@ import { DataPoint } from 'data/analytics/constants' import { PricingMetric, useOrgDailyStatsQuery } from 'data/analytics/org-daily-stats-query' -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' import UsageSection from './UsageSection/UsageSection' export interface SizeAndCountsProps { diff --git a/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx b/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx index ba4785f9f49..f56de7d4206 100644 --- a/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/TotalUsage.tsx @@ -1,4 +1,4 @@ -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' import SectionContent from './SectionContent' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import AlertError from 'components/ui/AlertError' diff --git a/apps/studio/components/interfaces/Organization/Usage/Usage.constants.tsx b/apps/studio/components/interfaces/Organization/Usage/Usage.constants.tsx index 708de836d82..d4e6a4708ed 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Usage.constants.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Usage.constants.tsx @@ -1,7 +1,7 @@ import { USAGE_APPROACHING_THRESHOLD } from 'components/interfaces/Billing/Billing.constants' import { EgressType, PricingMetric } from 'data/analytics/org-daily-stats-query' -import { OrgSubscription } from 'data/subscriptions/types' -import { OrgUsageResponse } from 'data/usage/org-usage-query' +import type { OrgSubscription } from 'data/subscriptions/types' +import type { OrgUsageResponse } from 'data/usage/org-usage-query' import { Alert } from 'ui' export const COLOR_MAP = { diff --git a/apps/studio/components/interfaces/Organization/Usage/Usage.utils.ts b/apps/studio/components/interfaces/Organization/Usage/Usage.utils.ts index ab58f60e7ca..4e68b9e278a 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Usage.utils.ts +++ b/apps/studio/components/interfaces/Organization/Usage/Usage.utils.ts @@ -1,5 +1,5 @@ import { DataPoint } from 'data/analytics/constants' -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' // [Joshen] This is just for development to generate some test data for chart rendering export const generateUsageData = (attribute: string, days: number): DataPoint[] => { diff --git a/apps/studio/components/interfaces/Organization/Usage/UsageChartTooltips.tsx b/apps/studio/components/interfaces/Organization/Usage/UsageChartTooltips.tsx index ea59cdd0649..da6f20200c6 100644 --- a/apps/studio/components/interfaces/Organization/Usage/UsageChartTooltips.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/UsageChartTooltips.tsx @@ -1,5 +1,5 @@ import clsx from 'clsx' -import { Payload, ValueType } from 'recharts/types/component/DefaultTooltipContent' +import type { Payload, ValueType } from 'recharts/types/component/DefaultTooltipContent' import { Attribute, COLOR_MAP } from './Usage.constants' export interface SingleAttributeTooltipContentProps { diff --git a/apps/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx b/apps/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx index 987f544f56f..e0a01bd76c1 100644 --- a/apps/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/UsageSection/AttributeUsage.tsx @@ -6,11 +6,11 @@ import AlertError from 'components/ui/AlertError' import Panel from 'components/ui/Panel' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import SparkBar from 'components/ui/SparkBar' -import { OrgSubscription } from 'data/subscriptions/types' -import { OrgMetricsUsage, OrgUsageResponse } from 'data/usage/org-usage-query' +import type { OrgSubscription } from 'data/subscriptions/types' +import type { OrgMetricsUsage, OrgUsageResponse } from 'data/usage/org-usage-query' import { USAGE_APPROACHING_THRESHOLD } from 'lib/constants' import { useMemo } from 'react' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { Button, IconAlertTriangle, IconBarChart2 } from 'ui' import SectionContent from '../SectionContent' import { CategoryAttribute } from '../Usage.constants' diff --git a/apps/studio/components/interfaces/Organization/Usage/UsageSection/UsageSection.tsx b/apps/studio/components/interfaces/Organization/Usage/UsageSection/UsageSection.tsx index 7f8347332ac..f5a4fe47b8f 100644 --- a/apps/studio/components/interfaces/Organization/Usage/UsageSection/UsageSection.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/UsageSection/UsageSection.tsx @@ -1,6 +1,6 @@ import { ScaffoldContainer, ScaffoldDivider } from 'components/layouts/Scaffold' import { DataPoint } from 'data/analytics/constants' -import { OrgSubscription } from 'data/subscriptions/types' +import type { OrgSubscription } from 'data/subscriptions/types' import { useOrgUsageQuery } from 'data/usage/org-usage-query' import SectionHeader from '../SectionHeader' import { CategoryMetaKey, USAGE_CATEGORIES } from '../Usage.constants' diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Bucket.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Bucket.tsx index 02361fe320e..22bf7499a4e 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Bucket.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Bucket.tsx @@ -6,7 +6,7 @@ import { formatBytes } from 'lib/helpers' import { useAppStateSnapshot } from 'state/app-state' import { DOCS_RESOURCE_CONTENT } from '../ProjectAPIDocs.constants' import ResourceContent from '../ResourceContent' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const Bucket = ({ language, apikey, endpoint }: ContentProps) => { const { ref } = useParams() diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunction.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunction.tsx index 0bc0fcd63c8..dca7cce0c52 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunction.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunction.tsx @@ -4,7 +4,7 @@ import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' import { useAppStateSnapshot } from 'state/app-state' import { DOCS_RESOURCE_CONTENT } from '../ProjectAPIDocs.constants' import ResourceContent from '../ResourceContent' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const Bucket = ({ language, apikey = 'API_KEY', endpoint }: ContentProps) => { const { ref } = useParams() diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunctions.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunctions.tsx index c3ed52dfdb1..c33ccd8a267 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunctions.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/EdgeFunctions.tsx @@ -1,6 +1,6 @@ import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const EdgeFunctions = ({ language }: ContentProps) => { return ( diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx index 9a669a98b8f..165c1bce3dd 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entities.tsx @@ -7,7 +7,7 @@ import { generateTypes } from 'data/projects/project-type-generation-query' import { useStore } from 'hooks' import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const Entities = ({ language }: ContentProps) => { const { ui } = useStore() diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entity.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entity.tsx index a497204147b..5d35d677bd8 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entity.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Entity.tsx @@ -6,7 +6,7 @@ import { useProjectJsonSchemaQuery } from 'data/docs/project-json-schema-query' import { useAppStateSnapshot } from 'state/app-state' import { DOCS_RESOURCE_CONTENT } from '../ProjectAPIDocs.constants' import ResourceContent from '../ResourceContent' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' import { tempRemovePostgrestText } from './Content.utils' import LanguageSelector from '../LanguageSelector' diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Introduction.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Introduction.tsx index c308dd63ba1..a79d78b3ac4 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Introduction.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Introduction.tsx @@ -4,7 +4,7 @@ import { Button, IconCopy, Input } from 'ui' import { useProjectApiQuery } from 'data/config/project-api-query' import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' import { copyToClipboard } from 'lib/helpers' import { useEffect, useState } from 'react' diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/RPC.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/RPC.tsx index f57d4af9d25..09cc8e1d785 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/RPC.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/RPC.tsx @@ -8,7 +8,7 @@ import { useOpenAPISpecQuery } from 'data/open-api/api-spec-query' import { useAppStateSnapshot } from 'state/app-state' import { DOCS_RESOURCE_CONTENT } from '../ProjectAPIDocs.constants' import ResourceContent from '../ResourceContent' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const RPC = ({ language }: ContentProps) => { const { ref } = useParams() diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Realtime.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Realtime.tsx index abf69033170..e628ddca522 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Realtime.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Realtime.tsx @@ -1,6 +1,6 @@ import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const Realtime = ({ language }: ContentProps) => { return ( diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Storage.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Storage.tsx index c9a76f5c415..18f7b851799 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/Storage.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/Storage.tsx @@ -1,6 +1,6 @@ import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const Storage = ({ language }: ContentProps) => { return ( diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/StoredProcedures.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/StoredProcedures.tsx index 977e88a777d..20ef8e3767c 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/StoredProcedures.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/StoredProcedures.tsx @@ -1,6 +1,6 @@ import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const StoredProcedures = ({ language }: ContentProps) => { return ( diff --git a/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx b/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx index 4f75a2c2663..22e762d9eb5 100644 --- a/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx +++ b/apps/studio/components/interfaces/ProjectAPIDocs/Content/UserManagement.tsx @@ -1,6 +1,6 @@ import ContentSnippet from '../ContentSnippet' import { DOCS_CONTENT } from '../ProjectAPIDocs.constants' -import { ContentProps } from './Content.types' +import type { ContentProps } from './Content.types' const UserManagement = ({ language, apikey, endpoint }: ContentProps) => { return ( diff --git a/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx b/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx index dde4f3d36ad..db121fd1bb3 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx @@ -5,7 +5,7 @@ import { Button, IconX, cn } from 'ui' import CopyButton from 'components/ui/CopyButton' import Telemetry from 'lib/telemetry' -import { LogData } from './Messages.types' +import type { LogData } from './Messages.types' import { SelectedRealtimeMessagePanel } from './SelectedRealtimeMessagePanel' export interface MessageSelectionProps { diff --git a/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx b/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx index 75473d1a61d..3078c96e5f2 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx @@ -10,7 +10,7 @@ import ShimmerLine from 'components/ui/ShimmerLine' import Telemetry from 'lib/telemetry' import { useRouter } from 'next/router' import MessageSelection from './MessageSelection' -import { LogData } from './Messages.types' +import type { LogData } from './Messages.types' import NoChannelEmptyState from './NoChannelEmptyState' import { ColumnRenderer } from './RealtimeMessageColumnRenderer' diff --git a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeMessageColumnRenderer.tsx b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeMessageColumnRenderer.tsx index ac0315e1274..9c7308c6a23 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeMessageColumnRenderer.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeMessageColumnRenderer.tsx @@ -1,7 +1,7 @@ import { Column } from 'react-data-grid' import { IconAlertTriangle, IconBroadcast, IconDatabaseChanges, IconPresence, cn } from 'ui' -import { LogData, PreviewLogData } from './Messages.types' +import type { LogData, PreviewLogData } from './Messages.types' import { RowLayout } from './MessagesFormatters' import { isErrorLog } from './MessagesTable' diff --git a/apps/studio/components/interfaces/Realtime/Inspector/SelectedRealtimeMessagePanel.tsx b/apps/studio/components/interfaces/Realtime/Inspector/SelectedRealtimeMessagePanel.tsx index 44f0a236042..529dfb5dca9 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/SelectedRealtimeMessagePanel.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/SelectedRealtimeMessagePanel.tsx @@ -1,4 +1,4 @@ -import { LogData } from './Messages.types' +import type { LogData } from './Messages.types' import { jsonSyntaxHighlight, SelectionDetailedTimestampRow } from './MessagesFormatters' const LogsDivider = () => { diff --git a/apps/studio/components/interfaces/Realtime/Inspector/useRealtimeMessages.ts b/apps/studio/components/interfaces/Realtime/Inspector/useRealtimeMessages.ts index 9dd8a914613..6e3dd7a23ab 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/useRealtimeMessages.ts +++ b/apps/studio/components/interfaces/Realtime/Inspector/useRealtimeMessages.ts @@ -6,7 +6,7 @@ import toast from 'react-hot-toast' import { useProjectApiQuery } from 'data/config/project-api-query' import { uuidv4 } from 'lib/helpers' import { EMPTY_ARR } from 'lib/void' -import { LogData } from './Messages.types' +import type { LogData } from './Messages.types' function reducer( state: LogData[], diff --git a/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx b/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx index bed81a02361..18e49316f3d 100644 --- a/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx +++ b/apps/studio/components/interfaces/Reports/ReportFilterBar.tsx @@ -22,7 +22,7 @@ import { import DatePickers from '../Settings/Logs/Logs.DatePickers' import { REPORTS_DATEPICKER_HELPERS } from './Reports.constants' -import { ReportFilterItem } from './Reports.types' +import type { ReportFilterItem } from './Reports.types' interface ReportFilterBarProps { filters: ReportFilterItem[] diff --git a/apps/studio/components/interfaces/Reports/ReportWidget.tsx b/apps/studio/components/interfaces/Reports/ReportWidget.tsx index 17a409494b8..f8bf9fa3524 100644 --- a/apps/studio/components/interfaces/Reports/ReportWidget.tsx +++ b/apps/studio/components/interfaces/Reports/ReportWidget.tsx @@ -3,7 +3,7 @@ import Panel from 'components/ui/Panel' import { NextRouter, useRouter } from 'next/router' import { Button, IconExternalLink, IconHelpCircle, Loading } from 'ui' import { LogsEndpointParams } from '../Settings/Logs' -import { BaseReportParams, ReportQueryType } from './Reports.types' +import type { BaseReportParams, ReportQueryType } from './Reports.types' export interface ReportWidgetProps { data: T[] diff --git a/apps/studio/components/interfaces/Reports/Reports.queries.ts b/apps/studio/components/interfaces/Reports/Reports.queries.ts index 11e6cdded25..a20c94b481b 100644 --- a/apps/studio/components/interfaces/Reports/Reports.queries.ts +++ b/apps/studio/components/interfaces/Reports/Reports.queries.ts @@ -1,8 +1,6 @@ -import { useProjectContentStore } from 'stores/projectContentStore' import { PRESET_CONFIG } from './Reports.constants' import { Presets } from './Reports.types' import useDbQuery from 'hooks/analytics/useDbQuery' -import { useMutation, useQuery } from '@tanstack/react-query' type QueryPerformanceQueryOpts = { searchQuery: string diff --git a/apps/studio/components/interfaces/Reports/Reports.types.ts b/apps/studio/components/interfaces/Reports/Reports.types.ts index b1f5c8da7be..17e18e61120 100644 --- a/apps/studio/components/interfaces/Reports/Reports.types.ts +++ b/apps/studio/components/interfaces/Reports/Reports.types.ts @@ -1,4 +1,4 @@ -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { DEFAULT_QUERY_PARAMS } from './Reports.constants' export enum Presets { diff --git a/apps/studio/components/interfaces/Reports/Reports.utils.tsx b/apps/studio/components/interfaces/Reports/Reports.utils.tsx index 3182492f658..cbf86b4693c 100644 --- a/apps/studio/components/interfaces/Reports/Reports.utils.tsx +++ b/apps/studio/components/interfaces/Reports/Reports.utils.tsx @@ -1,6 +1,6 @@ import useDbQuery, { DbQueryHook } from 'hooks/analytics/useDbQuery' import useLogsQuery, { LogsQueryHook } from 'hooks/analytics/useLogsQuery' -import { BaseQueries, PresetConfig, ReportQuery } from './Reports.types' +import type { BaseQueries, PresetConfig, ReportQuery } from './Reports.types' /** * Converts a query params string to an object diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx index b86d8b24b83..216963c7a3d 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/RoleImpersonationPopover.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { Button, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, Popover_Shadcn_, cn } from 'ui' -import { User } from 'data/auth/users-query' +import type { User } from 'data/auth/users-query' import { ChevronDown, User as IconUser } from 'lucide-react' import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state' import { getAvatarUrl, getDisplayName } from '../Auth/Users/UserListItem.utils' diff --git a/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx b/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx index 213ce51acf4..2d0c335907c 100644 --- a/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx +++ b/apps/studio/components/interfaces/SQLEditor/DownloadSnippetModal.tsx @@ -1,4 +1,4 @@ -import { ModalProps } from '@ui/components/Modal/Modal' +import type { ModalProps } from '@ui/components/Modal/Modal' import { snakeCase } from 'lodash' import Link from 'next/link' import { useState } from 'react' diff --git a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx index b6a50b8ad43..9430592dd39 100644 --- a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx @@ -5,12 +5,12 @@ import { useRouter } from 'next/router' import { MutableRefObject, useEffect, useRef, useState } from 'react' import { cn } from 'ui' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useLocalStorageQuery, useSelectedProject } from 'hooks' import { useProfile } from 'lib/profile' import { useSqlEditorStateSnapshot } from 'state/sql-editor' import { untitledSnippetTitle } from './SQLEditor.constants' -import { IStandaloneCodeEditor } from './SQLEditor.types' +import type { IStandaloneCodeEditor } from './SQLEditor.types' import { createSqlSnippetSkeleton } from './SQLEditor.utils' import { LOCAL_STORAGE_KEYS } from 'lib/constants' diff --git a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx index 268dea8c989..d9bba744401 100644 --- a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx +++ b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx @@ -1,7 +1,7 @@ import { useParams } from 'common' import { useSqlTitleGenerateMutation } from 'data/ai/sql-title-mutation' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { isError } from 'data/utils/error-check' import { useSelectedOrganization, useStore } from 'hooks' import { useEffect, useState } from 'react' diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts b/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts index 4d7055b9ebd..95ef97c400e 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts @@ -1,6 +1,6 @@ import { stripIndent } from 'common-tags' -import { SqlSnippets, UserContent } from 'types' -import { SQLTemplate } from './SQLEditor.types' +import type { SqlSnippets, UserContent } from 'types' +import type { SQLTemplate } from './SQLEditor.types' export const SQL_TEMPLATES: SQLTemplate[] = [ { diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx index 91fa4582592..713ddefb011 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx @@ -1,4 +1,4 @@ -import { Monaco } from '@monaco-editor/react' +import type { Monaco } from '@monaco-editor/react' import { useParams, useTelemetryProps } from 'common' import { AnimatePresence, motion } from 'framer-motion' import dynamic from 'next/dynamic' @@ -31,7 +31,7 @@ import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' import { useSqlEditMutation } from 'data/ai/sql-edit-mutation' import { useSqlGenerateMutation } from 'data/ai/sql-generate-mutation' import { useSqlTitleGenerateMutation } from 'data/ai/sql-title-mutation' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useEntityDefinitionsQuery } from 'data/database/entity-definitions-query' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation' diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts b/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts index 24012e3a73c..18ca6c224cd 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts @@ -1,6 +1,6 @@ // @ts-ignore import { NEW_SQL_SNIPPET_SKELETON, destructiveSqlRegex } from './SQLEditor.constants' -import { SqlSnippets, UserContent } from 'types' +import type { SqlSnippets, UserContent } from 'types' import { DiffType } from './SQLEditor.types' import { removeCommentsFromSql } from 'lib/helpers' import { stripIndent } from 'common-tags' diff --git a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx index 988b254a787..7db43451822 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react-lite' import { useParams, useTelemetryProps } from 'common' import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.constants' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useCheckPermissions, useSelectedProject, useStore } from 'hooks' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' diff --git a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx index df84619c0f9..390f495976d 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx @@ -5,7 +5,7 @@ import { observer } from 'mobx-react-lite' import { useTelemetryProps } from 'common' import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.constants' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useCheckPermissions, useStore } from 'hooks' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx index 9e5dc5b4a84..53b373ffa91 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/FavoriteButton.tsx @@ -7,7 +7,7 @@ import { } from 'ui' import { useQueryClient } from '@tanstack/react-query' import { contentKeys } from 'data/content/keys' -import { Content, ContentData } from 'data/content/content-query' +import type { Content, ContentData } from 'data/content/content-query' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useSqlEditorStateSnapshot } from 'state/sql-editor' diff --git a/apps/studio/components/interfaces/Settings/Addons/Addons.tsx b/apps/studio/components/interfaces/Settings/Addons/Addons.tsx index 2361900fc4d..187b3339195 100644 --- a/apps/studio/components/interfaces/Settings/Addons/Addons.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/Addons.tsx @@ -40,7 +40,7 @@ import { useInfraMonitoringQuery } from 'data/analytics/infra-monitoring-query' import { useProjectSettingsQuery } from 'data/config/project-settings-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' -import { ProjectAddonVariantMeta } from 'data/subscriptions/types' +import type { ProjectAddonVariantMeta } from 'data/subscriptions/types' import { useFlag, useProjectByRef, useSelectedOrganization } from 'hooks' import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils' import { BASE_PATH, INSTANCE_MICRO_SPECS, INSTANCE_NANO_SPECS } from 'lib/constants' diff --git a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx index 32343e818f2..041bd8725d6 100644 --- a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx @@ -29,7 +29,7 @@ import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-que import { useProjectAddonRemoveMutation } from 'data/subscriptions/project-addon-remove-mutation' import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon-update-mutation' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' -import { AddonVariantId, ProjectAddonVariantMeta } from 'data/subscriptions/types' +import type { AddonVariantId, ProjectAddonVariantMeta } from 'data/subscriptions/types' import { useCheckPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils' import { INSTANCE_MICRO_SPECS, PROJECT_STATUS } from 'lib/constants' diff --git a/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx index c70c8ffe13f..b8b4affbbfa 100644 --- a/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx @@ -24,7 +24,7 @@ import { SidePanel, } from 'ui' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { AddonVariantId } from 'data/subscriptions/types' +import type { AddonVariantId } from 'data/subscriptions/types' import { formatCurrency } from 'lib/helpers' import { useFlag } from 'hooks' diff --git a/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx index 3286477e8e3..e652ff5078e 100644 --- a/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx @@ -9,7 +9,7 @@ import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-que import { useProjectAddonRemoveMutation } from 'data/subscriptions/project-addon-remove-mutation' import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon-update-mutation' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' -import { AddonVariantId } from 'data/subscriptions/types' +import type { AddonVariantId } from 'data/subscriptions/types' import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { formatCurrency } from 'lib/helpers' import Telemetry from 'lib/telemetry' diff --git a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx index 70a052fa4d0..86c5cba401e 100644 --- a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx @@ -17,7 +17,7 @@ import { subscriptionHasHipaaAddon } from 'components/interfaces/Billing/Subscri import { CriticalIcon, WarningIcon } from 'components/ui/Icons' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { AddonVariantId } from 'data/subscriptions/types' +import type { AddonVariantId } from 'data/subscriptions/types' import { formatCurrency } from 'lib/helpers' import { useSubscriptionPageStateSnapshot } from 'state/subscription-page' import { diff --git a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.utils.ts b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.utils.ts index 70b0671d318..e04f1d64f19 100644 --- a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.utils.ts +++ b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/DatabaseSettings.utils.ts @@ -1,4 +1,4 @@ -import { PoolingConfiguration } from 'data/database/pooling-configuration-query' +import type { PoolingConfiguration } from 'data/database/pooling-configuration-query' export const getConnectionStrings = ( connectionInfo: { diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx index 1724ed66231..b7d20ff1703 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainActivate.tsx @@ -17,7 +17,7 @@ import { useProjectApiQuery } from 'data/config/project-api-query' import { useCheckCNAMERecordMutation } from 'data/custom-domains/check-cname-mutation' import { useCustomDomainActivateMutation } from 'data/custom-domains/custom-domains-activate-mutation' import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation' -import { CustomDomainResponse } from 'data/custom-domains/custom-domains-query' +import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query' import { useStore } from 'hooks' export type CustomDomainActivateProps = { diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainDelete.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainDelete.tsx index 9c6a909a18a..4e4341ef4c2 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainDelete.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainDelete.tsx @@ -6,7 +6,7 @@ import { Button, IconExternalLink, IconTrash } from 'ui' import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' import Panel from 'components/ui/Panel' import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation' -import { CustomDomainResponse } from 'data/custom-domains/custom-domains-query' +import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query' import { useStore } from 'hooks' export type CustomDomainDeleteProps = { diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainVerify.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainVerify.tsx index 4356a6a677e..bd2083d96b0 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainVerify.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainVerify.tsx @@ -14,9 +14,9 @@ import { } from 'ui' import Panel from 'components/ui/Panel' -import { ProjectApiResponse } from 'data/config/project-api-query' +import type { ProjectApiResponse } from 'data/config/project-api-query' import { useCustomDomainDeleteMutation } from 'data/custom-domains/custom-domains-delete-mutation' -import { CustomDomainResponse } from 'data/custom-domains/custom-domains-query' +import type { CustomDomainResponse } from 'data/custom-domains/custom-domains-query' import { useCustomDomainReverifyMutation } from 'data/custom-domains/custom-domains-reverify-mutation' import DNSRecord from './DNSRecord' diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DropReplicaConfirmationModal.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DropReplicaConfirmationModal.tsx index 0ee6a859a46..50ea8ea2e21 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DropReplicaConfirmationModal.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DropReplicaConfirmationModal.tsx @@ -10,7 +10,7 @@ import { import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useReadReplicaRemoveMutation } from 'data/read-replicas/replica-remove-mutation' -import { Database } from 'data/read-replicas/replicas-query' +import type { Database } from 'data/read-replicas/replicas-query' import { formatDatabaseID } from 'data/read-replicas/replicas.utils' interface DropReplicaConfirmationModalProps { diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.utils.ts b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.utils.ts index c7a4ab2e687..2cf452f0d59 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.utils.ts +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.utils.ts @@ -8,8 +8,8 @@ import { NODE_WIDTH, } from './InstanceConfiguration.constants' import { groupBy } from 'lodash' -import { Database } from 'data/read-replicas/replicas-query' -import { LoadBalancer } from 'data/read-replicas/load-balancers-query' +import type { Database } from 'data/read-replicas/replicas-query' +import type { LoadBalancer } from 'data/read-replicas/load-balancers-query' // [Joshen] Just FYI the nodes generation assumes each project only has one load balancer // Will need to change if this eventually becomes otherwise diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx index 7e3fe15e480..07aa954d7b4 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx @@ -36,7 +36,7 @@ import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' import { useBranchesQuery } from 'data/branches/branches-query' import { useGitHubBranchesQuery } from 'data/integrations/github-branches-query' import { useGitHubConnectionUpdateMutation } from 'data/integrations/github-connection-update-mutation' -import { IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { IntegrationProjectConnection } from 'data/integrations/integrations.types' import { useSelectedOrganization, useSelectedProject } from 'hooks' interface GitHubIntegrationConnectionFormProps { diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx index a9645e1005b..35be467a13b 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx @@ -13,7 +13,10 @@ import { import { useBranchesDisableMutation } from 'data/branches/branches-disable-mutation' import { useGitHubConnectionDeleteMutation } from 'data/integrations/github-connection-delete-mutation' import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' -import { IntegrationName, IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { + IntegrationName, + IntegrationProjectConnection, +} from 'data/integrations/integrations.types' import { useSelectedOrganization, useSelectedProject, useStore } from 'hooks' import { OPT_IN_TAGS } from 'lib/constants' import { useSidePanelsStateSnapshot } from 'state/side-panels' diff --git a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx index e4574e7045b..4078c84eb67 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx @@ -17,7 +17,10 @@ import { import * as z from 'zod' import { ScaffoldDivider } from 'components/layouts/Scaffold' -import { Integration, IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { + Integration, + IntegrationProjectConnection, +} from 'data/integrations/integrations.types' import { useVercelConnectionUpdateMutation } from 'data/integrations/vercel-connection-update-mutate' import { useFlag, useStore } from 'hooks' diff --git a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx index 0055238a699..53b49161d45 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx @@ -18,7 +18,10 @@ import { import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only' import { useIntegrationsVercelInstalledConnectionDeleteMutation } from 'data/integrations/integrations-vercel-installed-connection-delete-mutation' import { useVercelProjectsQuery } from 'data/integrations/integrations-vercel-projects-query' -import { IntegrationName, IntegrationProjectConnection } from 'data/integrations/integrations.types' +import type { + IntegrationName, + IntegrationProjectConnection, +} from 'data/integrations/integrations.types' import { useSelectedOrganization, useSelectedProject, useStore } from 'hooks' import { pluralize } from 'lib/helpers' import { getIntegrationConfigurationUrl } from 'lib/integration-utils' diff --git a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx index 17ef7e738e5..19f3a978bdd 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabaseApiColumnRender.tsx @@ -1,5 +1,5 @@ import { Column } from 'react-data-grid' -import { LogData } from '../Logs.types' +import type { LogData } from '../Logs.types' import { ResponseCodeFormatter, RowLayout, diff --git a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx index 9704667ae67..687410b835b 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/DatabasePostgresColumnRender.tsx @@ -1,5 +1,5 @@ import { Column } from 'react-data-grid' -import { LogData } from '../Logs.types' +import type { LogData } from '../Logs.types' import { RowLayout, SeverityFormatter, diff --git a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx index ed4e9c10a42..c1ebb546780 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsEdgeColumnRender.tsx @@ -1,5 +1,5 @@ import { Column } from 'react-data-grid' -import { LogData } from '../Logs.types' +import type { LogData } from '../Logs.types' import { ResponseCodeFormatter, RowLayout, diff --git a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx index 33ce303e045..5983e74eacb 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogColumnRenderers/FunctionsLogsColumnRender.tsx @@ -1,5 +1,5 @@ import { Column } from 'react-data-grid' -import { LogData } from '../Logs.types' +import type { LogData } from '../Logs.types' import { RowLayout, SeverityFormatter, diff --git a/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx b/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx index b96a88dfc5a..a98008faeeb 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogEventChart.tsx @@ -1,5 +1,5 @@ import BarChart from 'components/ui/Charts/BarChart' -import { Datum } from 'components/ui/Charts/Charts.types' +import type { Datum } from 'components/ui/Charts/Charts.types' import { EventChartData } from '.' export interface LogEventChartProps { diff --git a/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx b/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx index b791eaa29b0..c88a751281c 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogSelection.tsx @@ -10,7 +10,7 @@ import { LogsEndpointParams, unixMicroToIsoTimestamp, } from '.' -import { LogData, QueryType } from './Logs.types' +import type { LogData, QueryType } from './Logs.types' import AuthSelectionRenderer from './LogSelectionRenderers/AuthSelectionRenderer' import DatabaseApiSelectionRender from './LogSelectionRenderers/DatabaseApiSelectionRender' import DatabasePostgresSelectionRender from './LogSelectionRenderers/DatabasePostgresSelectionRender' diff --git a/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx b/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx index ae9c56950c8..c9e802289d8 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogTable.tsx @@ -28,7 +28,7 @@ import DefaultPreviewColumnRenderer from './LogColumnRenderers/DefaultPreviewCol import FunctionsEdgeColumnRender from './LogColumnRenderers/FunctionsEdgeColumnRender' import FunctionsLogsColumnRender from './LogColumnRenderers/FunctionsLogsColumnRender' import LogSelection, { LogSelectionProps } from './LogSelection' -import { LogData, QueryType } from './Logs.types' +import type { LogData, QueryType } from './Logs.types' import DefaultErrorRenderer from './LogsErrorRenderers/DefaultErrorRenderer' import ResourcesExceededErrorRenderer from './LogsErrorRenderers/ResourcesExceededErrorRenderer' import { CSVLink } from 'react-csv' diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts b/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts index 0346c3f4797..6f63652772f 100644 --- a/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts +++ b/apps/studio/components/interfaces/Settings/Logs/Logs.types.ts @@ -1,4 +1,4 @@ -import { Datum } from 'components/ui/Charts/Charts.types' +import type { Datum } from 'components/ui/Charts/Charts.types' import React from 'react' interface Metadata { diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts b/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts index a0133c2f4af..73a036c4309 100644 --- a/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts +++ b/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts @@ -6,7 +6,7 @@ import { useEffect } from 'react' import logConstants from 'shared-data/logConstants' import BackwardIterator from 'components/ui/CodeEditor/Providers/BackwardIterator' -import { PlanId } from 'data/subscriptions/types' +import type { PlanId } from 'data/subscriptions/types' import { Filters, LogData, LogsEndpointParams, LogsTableName, SQL_FILTER_TEMPLATES } from '.' /** diff --git a/apps/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx b/apps/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx index 11925c422cd..5d881103338 100644 --- a/apps/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/RecentQueriesItem.tsx @@ -1,7 +1,7 @@ import { Button, IconPlay } from 'ui' import Table from 'components/to-be-cleaned/Table' import { useRouter } from 'next/router' -import { LogSqlSnippets } from 'types' +import type { LogSqlSnippets } from 'types' import SqlSnippetCode from './Logs.SqlSnippetCode' interface Props { diff --git a/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx b/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx index 6c17951aed3..6d05a4ad92e 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Secrets/DeleteSecretModal.tsx @@ -4,7 +4,7 @@ import { Modal } from 'ui' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useVaultSecretDeleteMutation } from 'data/vault/vault-secret-delete-mutation' import { useStore } from 'hooks' -import { VaultSecret } from 'types' +import type { VaultSecret } from 'types' interface DeleteSecretModalProps { selectedSecret: VaultSecret | undefined diff --git a/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx b/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx index 9c83c613482..a91ba6cecc0 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Secrets/EditSecretModal.tsx @@ -8,7 +8,7 @@ import { usePgSodiumKeyCreateMutation } from 'data/pg-sodium-keys/pg-sodium-key- import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query' import { useVaultSecretUpdateMutation } from 'data/vault/vault-secret-update-mutation' import { useStore } from 'hooks' -import { VaultSecret } from 'types' +import type { VaultSecret } from 'types' import EncryptionKeySelector from '../Keys/EncryptionKeySelector' interface EditSecretModalProps { diff --git a/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx b/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx index 4366896e4a1..9f4177203a7 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx @@ -23,7 +23,7 @@ import { import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query' import { useCheckPermissions } from 'hooks' -import { VaultSecret } from 'types' +import type { VaultSecret } from 'types' interface SecretRowProps { secret: VaultSecret diff --git a/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx b/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx index e978dc8e0aa..30c62774ddd 100644 --- a/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx +++ b/apps/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx @@ -11,7 +11,7 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte import Divider from 'components/ui/Divider' import { useVaultSecretsQuery } from 'data/vault/vault-secrets-query' import { useCheckPermissions } from 'hooks' -import { VaultSecret } from 'types' +import type { VaultSecret } from 'types' import AddNewSecretModal from './AddNewSecretModal' import DeleteSecretModal from './DeleteSecretModal' import EditSecretModal from './EditSecretModal' diff --git a/apps/studio/components/interfaces/SignIn/SignInForm.tsx b/apps/studio/components/interfaces/SignIn/SignInForm.tsx index 84a88eb6568..506b13568e4 100644 --- a/apps/studio/components/interfaces/SignIn/SignInForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInForm.tsx @@ -1,6 +1,5 @@ import HCaptcha from '@hcaptcha/react-hcaptcha' -import * as Sentry from '@sentry/nextjs' -import { AuthError } from '@supabase/supabase-js' +import type { AuthError } from '@supabase/supabase-js' import { useQueryClient } from '@tanstack/react-query' import Link from 'next/link' import { useRouter } from 'next/router' diff --git a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx index d30110e2ff2..f5f2cfc2c64 100644 --- a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx @@ -1,5 +1,5 @@ import { AuthError } from '@supabase/gotrue-js' -import { Factor } from '@supabase/supabase-js' +import type { Factor } from '@supabase/supabase-js' import { useQueryClient } from '@tanstack/react-query' import Link from 'next/link' import { useRouter } from 'next/router' diff --git a/apps/studio/components/interfaces/Storage/EditBucketModal.tsx b/apps/studio/components/interfaces/Storage/EditBucketModal.tsx index bb470d8e067..c030d2cd4c5 100644 --- a/apps/studio/components/interfaces/Storage/EditBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/EditBucketModal.tsx @@ -22,7 +22,7 @@ import { Modal, Toggle, } from 'ui' -import { StorageBucket } from './Storage.types' +import type { StorageBucket } from './Storage.types' export interface EditBucketModalProps { visible: boolean diff --git a/apps/studio/components/interfaces/Storage/Storage.types.ts b/apps/studio/components/interfaces/Storage/Storage.types.ts index 14216ae8d95..37b00902f28 100644 --- a/apps/studio/components/interfaces/Storage/Storage.types.ts +++ b/apps/studio/components/interfaces/Storage/Storage.types.ts @@ -1,4 +1,4 @@ -import { PolicyFormField } from 'components/interfaces/Auth/Policies/Policies.types' +import type { PolicyFormField } from 'components/interfaces/Auth/Policies/Policies.types' export interface StoragePolicyFormField extends PolicyFormField { allowedOperations: string[] diff --git a/apps/studio/components/interfaces/Support/SupportForm.tsx b/apps/studio/components/interfaces/Support/SupportForm.tsx index 7545bda0b21..fad2969fe46 100644 --- a/apps/studio/components/interfaces/Support/SupportForm.tsx +++ b/apps/studio/components/interfaces/Support/SupportForm.tsx @@ -27,7 +27,7 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { getProjectAuthConfig } from 'data/auth/auth-config-query' import { useSendSupportTicketMutation } from 'data/feedback/support-ticket-send' import { useOrganizationsQuery } from 'data/organizations/organizations-query' -import { Project } from 'data/projects/project-detail-query' +import type { Project } from 'data/projects/project-detail-query' import { useProjectsQuery } from 'data/projects/projects-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useFlag, useStore } from 'hooks' diff --git a/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx b/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx index 862349967e4..1fae2696aaf 100644 --- a/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import toast from 'react-hot-toast' import { Alert, Button, Checkbox, IconExternalLink, Modal } from 'ui' -import { SupaRow } from 'components/grid' +import type { SupaRow } from 'components/grid' import { formatFilterURLParams } from 'components/grid/SupabaseGrid.utils' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' @@ -13,11 +13,10 @@ import { useTableRowTruncateMutation } from 'data/table-rows/table-row-truncate- import { useTableDeleteMutation } from 'data/tables/table-delete-mutation' import { useGetTables } from 'data/tables/tables-query' import { useUrlState } from 'hooks' -import { TableLike } from 'hooks/misc/useTable' +import type { TableLike } from 'hooks/misc/useTable' import { noop } from 'lib/void' import { useGetImpersonatedRole } from 'state/role-impersonation-state' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { tableKeys } from 'data/tables/keys' export type DeleteConfirmationDialogsProps = { projectRef?: string diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx index 98872c0c5b1..37298ca9a5a 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnDefaultValue.tsx @@ -1,11 +1,11 @@ import { noop } from 'lodash' import { Select } from 'ui' -import { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' +import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' import { POSTGRES_DATA_TYPES } from '../SidePanelEditor.constants' -import { ColumnField } from '../SidePanelEditor.types' +import type { ColumnField } from '../SidePanelEditor.types' import { typeExpressionSuggestions } from './ColumnEditor.constants' -import { Suggestion } from './ColumnEditor.types' +import type { Suggestion } from './ColumnEditor.types' import InputWithSuggestions from './InputWithSuggestions' interface ColumnDefaultValueProps { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.constants.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.constants.ts index 434a83f28c3..ad364b3ca4f 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.constants.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.constants.ts @@ -1,5 +1,5 @@ -import { Dictionary } from 'types' -import { Suggestion } from './ColumnEditor.types' +import type { Dictionary } from 'types' +import type { Suggestion } from './ColumnEditor.types' const defaultTimeBasedExpressions: Suggestion[] = [ { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx index fd562a11a04..000d0c387e9 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx @@ -31,12 +31,16 @@ import { } from 'data/database/foreign-key-constraints-query' import { useEnumeratedTypesQuery } from 'data/enumerated-types/enumerated-types-query' import { EXCLUDED_SCHEMAS_WITHOUT_EXTENSIONS } from 'lib/constants/schemas' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import ActionBar from '../ActionBar' -import { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' +import type { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' import { formatForeignKeys } from '../ForeignKeySelector/ForeignKeySelector.utils' import { TEXT_TYPES } from '../SidePanelEditor.constants' -import { ColumnField, CreateColumnPayload, UpdateColumnPayload } from '../SidePanelEditor.types' +import type { + ColumnField, + CreateColumnPayload, + UpdateColumnPayload, +} from '../SidePanelEditor.types' import ColumnDefaultValue from './ColumnDefaultValue' import { generateColumnField, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.utils.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.utils.ts index d5afd301545..29f91559951 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.utils.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.utils.ts @@ -1,9 +1,9 @@ import type { PostgresColumn, PostgresTable } from '@supabase/postgres-meta' import { find, isEqual, isNull } from 'lodash' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import { FOREIGN_KEY_CASCADE_ACTION } from 'data/database/database-query-constants' -import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' +import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' import { uuidv4 } from 'lib/helpers' import { ColumnField, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx index d55d02e9e09..7b398f584de 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx @@ -6,8 +6,8 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' import useTable from 'hooks/misc/useTable' import { ForeignKeySelector } from '../ForeignKeySelector/ForeignKeySelector' -import { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' -import { ColumnField } from '../SidePanelEditor.types' +import type { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' +import type { ColumnField } from '../SidePanelEditor.types' import { ForeignKeyRow } from '../TableEditor/ForeignKeysManagement/ForeignKeyRow' import { checkIfRelationChanged } from '../TableEditor/ForeignKeysManagement/ForeignKeysManagement.utils' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx index bd9443e4be8..7385da373ba 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnType.tsx @@ -20,9 +20,9 @@ import { POSTGRES_DATA_TYPE_OPTIONS, RECOMMENDED_ALTERNATIVE_DATA_TYPE, } from '../SidePanelEditor.constants' -import { PostgresDataTypeOption } from '../SidePanelEditor.types' +import type { PostgresDataTypeOption } from '../SidePanelEditor.types' import { ListPlus } from 'lucide-react' -import { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' +import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' interface ColumnTypeProps { value: string diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/InputWithSuggestions.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/InputWithSuggestions.tsx index 5a63560fa75..2a787b8f7a6 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/InputWithSuggestions.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/InputWithSuggestions.tsx @@ -20,7 +20,7 @@ import { Input, } from 'ui' -import { Suggestion } from './ColumnEditor.types' +import type { Suggestion } from './ColumnEditor.types' const MAX_SUGGESTIONS = 3 diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx index 16f0a622a9f..036b66936aa 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx @@ -1,4 +1,4 @@ -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { sortBy } from 'lodash' import { Table } from 'lucide-react' import { Fragment, useEffect, useState } from 'react' @@ -26,9 +26,9 @@ import { useTableEditorStateSnapshot } from 'state/table-editor' import ActionBar from '../ActionBar' import { NUMERICAL_TYPES, TEXT_TYPES } from '../SidePanelEditor.constants' import { FOREIGN_KEY_CASCADE_OPTIONS } from './ForeignKeySelector.constants' -import { ForeignKey } from './ForeignKeySelector.types' +import type { ForeignKey } from './ForeignKeySelector.types' import { generateCascadeActionDescription } from './ForeignKeySelector.utils' -import { ColumnField } from '../SidePanelEditor.types' +import type { ColumnField } from '../SidePanelEditor.types' const EMPTY_STATE: ForeignKey = { id: undefined, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.utils.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.utils.tsx index 5b5352ac721..39d7f79553d 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.utils.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.utils.tsx @@ -2,9 +2,9 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { IconHelpCircle } from 'ui' import { FOREIGN_KEY_CASCADE_ACTION } from 'data/database/database-query-constants' -import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' +import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' import { getForeignKeyCascadeAction } from '../ColumnEditor/ColumnEditor.utils' -import { ForeignKey } from './ForeignKeySelector.types' +import type { ForeignKey } from './ForeignKeySelector.types' export const formatForeignKeys = (fks: ForeignKeyConstraint[]): ForeignKey[] => { return fks.map((x) => { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx index 2d22e95b91a..01735c01ae6 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx @@ -1,4 +1,4 @@ -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { useState } from 'react' import { DndProvider } from 'react-dnd' import { HTML5Backend } from 'react-dnd-html5-backend' @@ -10,7 +10,7 @@ import RefreshButton from 'components/grid/components/header/RefreshButton' import { FilterPopover } from 'components/grid/components/header/filter' import { SortPopover } from 'components/grid/components/header/sort' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' +import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' import { useTableRowsQuery } from 'data/table-rows/table-rows-query' import { useTableQuery } from 'data/tables/table-query' import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx index d27be3f85ce..699a0f0cd36 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/SelectorGrid.tsx @@ -1,5 +1,5 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import { SupaRow, SupaTable } from 'components/grid' +import type { SupaRow, SupaTable } from 'components/grid' import { COLUMN_MIN_WIDTH } from 'components/grid/constants' import { ESTIMATED_CHARACTER_PIXEL_WIDTH, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx index 9754a3f8ca0..f09076ef328 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/InputField.tsx @@ -3,7 +3,7 @@ import { Button, IconEdit2, IconLink, Input, Listbox, Select } from 'ui' import { DATETIME_TYPES, JSON_TYPES, TEXT_TYPES } from '../SidePanelEditor.constants' import { DateTimeInput } from './DateTimeInput' -import { RowField } from './RowEditor.types' +import type { RowField } from './RowEditor.types' export interface InputFieldProps { field: RowField diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownPane.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownPane.tsx index 38bd01beb42..9894c655630 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownPane.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownPane.tsx @@ -1,7 +1,7 @@ import { isNull, noop } from 'lodash' import { IconChevronRight } from 'ui' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' interface DrilldownPaneProps { pane: number diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownViewer.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownViewer.tsx index 8fda83bfecf..49d6f37d19f 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownViewer.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/DrilldownViewer/DrilldownViewer.tsx @@ -1,7 +1,7 @@ import { isEmpty, last } from 'lodash' import { useState } from 'react' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import DrilldownBreadCrumbs from './DrilldownBreadCrumbs' import DrilldownPane from './DrilldownPane' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx index 90652720084..8995af9a952 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx @@ -1,5 +1,5 @@ import type { PostgresTable } from '@supabase/postgres-meta' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import { isEmpty, isUndefined, noop, partition } from 'lodash' import { useEffect, useMemo, useState } from 'react' import { SidePanel } from 'ui' @@ -11,7 +11,7 @@ import ForeignRowSelector from './ForeignRowSelector/ForeignRowSelector' import HeaderTitle from './HeaderTitle' import InputField from './InputField' import { JsonEditor } from './JsonEditor' -import { JsonEditValue, RowField } from './RowEditor.types' +import type { JsonEditValue, RowField } from './RowEditor.types' import { generateRowFields, generateRowObjectFromFields, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.ts index 43e863e68f2..55e83c2a5d0 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.ts @@ -1,5 +1,5 @@ import type { PostgresTable } from '@supabase/postgres-meta' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import dayjs from 'dayjs' import { compact, find, isEqual, isNull, isString, isUndefined, omitBy } from 'lodash' @@ -10,7 +10,7 @@ import { TIMESTAMP_TYPES, TIME_TYPES, } from '../SidePanelEditor.constants' -import { RowField } from './RowEditor.types' +import type { RowField } from './RowEditor.types' export const generateRowFields = ( row: Dictionary | undefined, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.constants.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.constants.ts index 47140892b7f..a57859a09a9 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.constants.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.constants.ts @@ -1,5 +1,5 @@ import { sortBy, concat } from 'lodash' -import { PostgresDataTypeOption } from './SidePanelEditor.types' +import type { PostgresDataTypeOption } from './SidePanelEditor.types' export const NUMERICAL_TYPES = [ 'int2', diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx index 20810bdc520..227d0aef15d 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx @@ -10,7 +10,7 @@ import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useDatabasePublicationCreateMutation } from 'data/database-publications/database-publications-create-mutation' import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query' import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation' -import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' +import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' import { entityTypeKeys } from 'data/entity-types/keys' import { sqlKeys } from 'data/sql/keys' import { useTableRowCreateMutation } from 'data/table-rows/table-row-create-mutation' @@ -20,14 +20,14 @@ import { getTables } from 'data/tables/tables-query' import { useStore, useUrlState } from 'hooks' import { useGetImpersonatedRole } from 'state/role-impersonation-state' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import { ColumnEditor, RowEditor, SpreadsheetImport, TableEditor } from '.' -import { ForeignKey } from './ForeignKeySelector/ForeignKeySelector.types' +import type { ForeignKey } from './ForeignKeySelector/ForeignKeySelector.types' import ForeignRowSelector from './RowEditor/ForeignRowSelector/ForeignRowSelector' import JsonEditor from './RowEditor/JsonEditor/JsonEditor' import { TextEditor } from './RowEditor/TextEditor' import SchemaEditor from './SchemaEditor' -import { ColumnField, CreateColumnPayload, UpdateColumnPayload } from './SidePanelEditor.types' +import type { ColumnField, CreateColumnPayload, UpdateColumnPayload } from './SidePanelEditor.types' import { createColumn, createTable, @@ -37,8 +37,8 @@ import { updateColumn, updateTable, } from './SidePanelEditor.utils' -import { ImportContent } from './TableEditor/TableEditor.types' -import { Constraint } from 'data/database/constraints-query' +import type { ImportContent } from './TableEditor/TableEditor.types' +import type { Constraint } from 'data/database/constraints-query' export interface SidePanelEditorProps { editable?: boolean diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx index e9bf7ee13ed..5795e48f70f 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.utils.tsx @@ -1,4 +1,4 @@ -import { PostgresPrimaryKey, PostgresTable } from '@supabase/postgres-meta' +import type { PostgresPrimaryKey, PostgresTable } from '@supabase/postgres-meta' import { chunk, find, isEmpty, isEqual } from 'lodash' import Papa from 'papaparse' import { useEffect, useState } from 'react' @@ -24,16 +24,16 @@ import { getTables } from 'data/tables/tables-query' import { getViews } from 'data/views/views-query' import { useStore } from 'hooks' import { timeout, tryParseJson } from 'lib/helpers' -import { IMetaStore } from 'stores/pgmeta/MetaStore' +import type { IMetaStore } from 'stores/pgmeta/MetaStore' import { generateCreateColumnPayload, generateUpdateColumnPayload, } from './ColumnEditor/ColumnEditor.utils' -import { ForeignKey } from './ForeignKeySelector/ForeignKeySelector.types' -import { ColumnField, CreateColumnPayload, UpdateColumnPayload } from './SidePanelEditor.types' +import type { ForeignKey } from './ForeignKeySelector/ForeignKeySelector.types' +import type { ColumnField, CreateColumnPayload, UpdateColumnPayload } from './SidePanelEditor.types' import { checkIfRelationChanged } from './TableEditor/ForeignKeysManagement/ForeignKeysManagement.utils' -import { ImportContent } from './TableEditor/TableEditor.types' -import { Constraint } from 'data/database/constraints-query' +import type { ImportContent } from './TableEditor/TableEditor.types' +import type { Constraint } from 'data/database/constraints-query' const BATCH_SIZE = 1000 const CHUNK_SIZE = 1024 * 1024 * 0.1 // 0.1MB diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadSheetImportConfiguration.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadSheetImportConfiguration.tsx index a80e2283b99..d21cc095668 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadSheetImportConfiguration.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadSheetImportConfiguration.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx' import { useState } from 'react' import { Button, Collapsible, IconChevronDown, SidePanel } from 'ui' -import { SpreadsheetData } from './SpreadsheetImport.types' +import type { SpreadsheetData } from './SpreadsheetImport.types' interface SpreadSheetImportConfigurationProps { spreadsheetData: SpreadsheetData diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.constants.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.constants.ts index 7c29186ce9a..e25fdbe42b2 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.constants.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.constants.ts @@ -1,4 +1,4 @@ -import { SpreadsheetData } from './SpreadsheetImport.types' +import type { SpreadsheetData } from './SpreadsheetImport.types' export const UPLOAD_FILE_TYPES = [ 'text/csv', diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx index b7735a82981..3f5ca626dc6 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx @@ -1,17 +1,17 @@ import Link from 'next/link' -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { debounce, includes, noop } from 'lodash' import { useCallback, useEffect, useState } from 'react' import { Button, IconExternalLink, SidePanel, Tabs } from 'ui' import { useStore } from 'hooks' import ActionBar from '../ActionBar' -import { ImportContent } from '../TableEditor/TableEditor.types' +import type { ImportContent } from '../TableEditor/TableEditor.types' import SpreadSheetFileUpload from './SpreadSheetFileUpload' import SpreadsheetImportConfiguration from './SpreadSheetImportConfiguration' import SpreadSheetTextInput from './SpreadSheetTextInput' import { EMPTY_SPREADSHEET_DATA, UPLOAD_FILE_TYPES } from './SpreadsheetImport.constants' -import { SpreadsheetData } from './SpreadsheetImport.types' +import type { SpreadsheetData } from './SpreadsheetImport.types' import { acceptedFileExtension, parseSpreadsheet, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.types.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.types.ts index 553a1dfa6c9..54771df8f74 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.types.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.types.ts @@ -1,4 +1,4 @@ -import { Dictionary } from 'types' +import type { Dictionary } from 'types' export interface SpreadsheetData { headers: string[] diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImportPreview.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImportPreview.tsx index 46d002c9d45..e9c0c638637 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImportPreview.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImportPreview.tsx @@ -11,8 +11,8 @@ import { SidePanel, } from 'ui' -import { PostgresTable } from '@supabase/postgres-meta' -import { SpreadsheetData } from './SpreadsheetImport.types' +import type { PostgresTable } from '@supabase/postgres-meta' +import type { SpreadsheetData } from './SpreadsheetImport.types' import SpreadsheetPreviewGrid from './SpreadsheetPreviewGrid' const MAX_ROWS = 20 diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx index b9104a5154e..141518e4fc6 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx @@ -1,13 +1,13 @@ import { noop } from 'lodash' import { Checkbox, IconMenu, IconSettings, IconX, Input, Popover } from 'ui' -import { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' +import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' import { EMPTY_ARR, EMPTY_OBJ } from 'lib/void' import { typeExpressionSuggestions } from '../ColumnEditor/ColumnEditor.constants' -import { Suggestion } from '../ColumnEditor/ColumnEditor.types' +import type { Suggestion } from '../ColumnEditor/ColumnEditor.types' import ColumnType from '../ColumnEditor/ColumnType' import InputWithSuggestions from '../ColumnEditor/InputWithSuggestions' -import { ColumnField } from '../SidePanelEditor.types' +import type { ColumnField } from '../SidePanelEditor.types' /** * [Joshen] For context: diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx index 72decdd4b43..c0c183f9956 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx @@ -10,13 +10,13 @@ import { import { Alert, Button, IconEdit, IconExternalLink, IconHelpCircle, IconKey, IconTrash } from 'ui' import InformationBox from 'components/ui/InformationBox' -import { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' +import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' import { generateColumnField } from '../ColumnEditor/ColumnEditor.utils' -import { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' +import type { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' import { TEXT_TYPES } from '../SidePanelEditor.constants' -import { ColumnField, ExtendedPostgresRelationship } from '../SidePanelEditor.types' +import type { ColumnField, ExtendedPostgresRelationship } from '../SidePanelEditor.types' import Column from './Column' -import { ImportContent } from './TableEditor.types' +import type { ImportContent } from './TableEditor.types' interface ColumnManagementProps { columns?: ColumnField[] diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeyRow.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeyRow.tsx index 3787487df2d..f0ae05142db 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeyRow.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeyRow.tsx @@ -5,7 +5,7 @@ import SVG from 'react-inlinesvg' import { Badge, Button, IconArrowRight } from 'ui' import { BASE_PATH } from 'lib/constants' -import { ForeignKey } from '../../ForeignKeySelector/ForeignKeySelector.types' +import type { ForeignKey } from '../../ForeignKeySelector/ForeignKeySelector.types' interface ForeignKeyProps { foreignKey: ForeignKey diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.tsx index 2115fb9e03c..f016c0f7416 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.tsx @@ -6,11 +6,11 @@ import AlertError from 'components/ui/AlertError' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { ForeignKeySelector } from '../../ForeignKeySelector/ForeignKeySelector' -import { TableField } from '../TableEditor.types' +import type { TableField } from '../TableEditor.types' import { ForeignKeyRow } from './ForeignKeyRow' -import { ForeignKey } from '../../ForeignKeySelector/ForeignKeySelector.types' +import type { ForeignKey } from '../../ForeignKeySelector/ForeignKeySelector.types' import { checkIfRelationChanged } from './ForeignKeysManagement.utils' import { uuidv4 } from 'lib/helpers' diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.utils.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.utils.ts index 7d8c54e726d..13f38a6092f 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.utils.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.utils.ts @@ -1,5 +1,5 @@ -import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' -import { ForeignKey } from '../../ForeignKeySelector/ForeignKeySelector.types' +import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' +import type { ForeignKey } from '../../ForeignKeySelector/ForeignKeySelector.types' import { isEqual } from 'lodash' export const checkIfRelationChanged = (existing: ForeignKeyConstraint, state: ForeignKey) => { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.constants.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.constants.ts index 069d613bdf0..3a8fbc9430e 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.constants.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.constants.ts @@ -1,5 +1,5 @@ import { uuidv4 } from 'lib/helpers' -import { ColumnField } from '../SidePanelEditor.types' +import type { ColumnField } from '../SidePanelEditor.types' export const DEFAULT_COLUMNS: ColumnField[] = [ { diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx index c380a34b371..264958f5f59 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx @@ -22,15 +22,15 @@ import { EXCLUDED_SCHEMAS_WITHOUT_EXTENSIONS } from 'lib/constants/schemas' import { useTableEditorStateSnapshot } from 'state/table-editor' import { SpreadsheetImport } from '../' import ActionBar from '../ActionBar' -import { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' +import type { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' import { formatForeignKeys } from '../ForeignKeySelector/ForeignKeySelector.utils' -import { ColumnField } from '../SidePanelEditor.types' +import type { ColumnField } from '../SidePanelEditor.types' import ColumnManagement from './ColumnManagement' import { ForeignKeysManagement } from './ForeignKeysManagement/ForeignKeysManagement' import HeaderTitle from './HeaderTitle' import RLSDisableModalContent from './RLSDisableModal' import { DEFAULT_COLUMNS } from './TableEditor.constants' -import { ImportContent, TableField } from './TableEditor.types' +import type { ImportContent, TableField } from './TableEditor.types' import { formatImportedContentToColumnFields, generateTableField, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.types.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.types.ts index 18cd6f1f87c..32e17c65317 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.types.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.types.ts @@ -1,5 +1,5 @@ -import { Dictionary } from 'types' -import { ColumnField } from '../SidePanelEditor.types' +import type { Dictionary } from 'types' +import type { ColumnField } from '../SidePanelEditor.types' export interface TableField { id: number diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.utils.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.utils.ts index c79570968ce..82bd8a63d67 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.utils.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.utils.ts @@ -1,14 +1,14 @@ import { some } from 'lodash' import type { PostgresColumn, PostgresTable } from '@supabase/postgres-meta' -import { ImportContent, TableField } from './TableEditor.types' +import type { ImportContent, TableField } from './TableEditor.types' import { DEFAULT_COLUMNS } from './TableEditor.constants' -import { ColumnField } from '../SidePanelEditor.types' +import type { ColumnField } from '../SidePanelEditor.types' import { generateColumnField, generateColumnFieldFromPostgresColumn, } from '../ColumnEditor/ColumnEditor.utils' -import { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' +import type { ForeignKeyConstraint } from 'data/database/foreign-key-constraints-query' export const validateFields = (field: TableField) => { const errors = {} as any diff --git a/apps/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx index 8adbe4342f4..85cd6b28494 100644 --- a/apps/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx @@ -20,12 +20,12 @@ import { sqlKeys } from 'data/sql/keys' import { useTableRowUpdateMutation } from 'data/table-rows/table-row-update-mutation' import { useCheckPermissions, useLatest, useStore, useUrlState } from 'hooks' import useEntityType from 'hooks/misc/useEntityType' -import { TableLike } from 'hooks/misc/useTable' +import type { TableLike } from 'hooks/misc/useTable' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' import { EMPTY_ARR } from 'lib/void' import { useGetImpersonatedRole } from 'state/role-impersonation-state' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { Dictionary, SchemaView } from 'types' +import type { Dictionary, SchemaView } from 'types' import GridHeaderActions from './GridHeaderActions' import NotFoundState from './NotFoundState' import { SidePanelEditor } from './SidePanelEditor' diff --git a/apps/studio/components/layouts/APIAuthorizationLayout.tsx b/apps/studio/components/layouts/APIAuthorizationLayout.tsx index 08a179110f5..960dd6f8f83 100644 --- a/apps/studio/components/layouts/APIAuthorizationLayout.tsx +++ b/apps/studio/components/layouts/APIAuthorizationLayout.tsx @@ -3,7 +3,7 @@ import { BASE_PATH } from 'lib/constants' import { useTheme } from 'next-themes' import Head from 'next/head' import Image from 'next/legacy/image' -import { PropsWithChildren } from 'react' +import type { PropsWithChildren } from 'react' export interface APIAuthorizationLayoutProps {} diff --git a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx index ecbef0713e5..9ff40c78187 100644 --- a/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx +++ b/apps/studio/components/layouts/AccountLayout/AccountLayout.tsx @@ -7,7 +7,7 @@ import { useFlag, useSelectedOrganization, withAuth } from 'hooks' import { useSignOut } from 'lib/auth' import { IS_PLATFORM } from 'lib/constants' import SettingsLayout from '../SettingsLayout/SettingsLayout' -import { SidebarSection } from './AccountLayout.types' +import type { SidebarSection } from './AccountLayout.types' import WithSidebar from './WithSidebar' export interface AccountLayoutProps { diff --git a/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx b/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx index 81b4f347cfc..2a308c682cd 100644 --- a/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx +++ b/apps/studio/components/layouts/AccountLayout/WithSidebar.tsx @@ -5,7 +5,7 @@ import { Badge, IconArrowUpRight, IconLogOut, Menu } from 'ui' import { useFlag } from 'hooks' import { LayoutHeader } from '../ProjectLayout/LayoutHeader' -import { SidebarLink, SidebarSection } from './AccountLayout.types' +import type { SidebarLink, SidebarSection } from './AccountLayout.types' interface WithSidebarProps { title: string diff --git a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx index 4dd459aeb71..dfd40edd4f6 100644 --- a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx +++ b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/GithubRepositorySelection.tsx @@ -3,7 +3,7 @@ import { EmptyIntegrationConnection, IntegrationConnection, } from 'components/interfaces/Integrations/IntegrationPanels' -import { GitHubConnection } from 'data/integrations/github-connections-query' +import type { GitHubConnection } from 'data/integrations/github-connections-query' import { useSelectedOrganization } from 'hooks' import { useSidePanelsStateSnapshot } from 'state/side-panels' import { diff --git a/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx b/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx index 3d7fa037419..35f7477dc9a 100644 --- a/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx +++ b/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx @@ -8,7 +8,7 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { ProjectInfo, useProjectsQuery } from 'data/projects/projects-query' import { useIsFeatureEnabled, useSelectedOrganization, useSelectedProject } from 'hooks' import { IS_PLATFORM } from 'lib/constants' -import { Organization } from 'types' +import type { Organization } from 'types' import { Button, CommandEmpty_Shadcn_, diff --git a/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts b/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts index 4704150201f..bbdf9edad7e 100644 --- a/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts +++ b/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts @@ -1,4 +1,4 @@ -import { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' +import type { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' import { IS_PLATFORM } from 'lib/constants' export const generateAuthMenu = ( diff --git a/apps/studio/components/layouts/BillingLayout.tsx b/apps/studio/components/layouts/BillingLayout.tsx index abb764fd1cc..b62bd596fac 100644 --- a/apps/studio/components/layouts/BillingLayout.tsx +++ b/apps/studio/components/layouts/BillingLayout.tsx @@ -1,5 +1,5 @@ import Link from 'next/link' -import { PropsWithChildren } from 'react' +import type { PropsWithChildren } from 'react' import { ProjectLayout } from 'components/layouts' import { useSelectedOrganization, useSelectedProject, withAuth } from 'hooks' diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.ts b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.ts index 5ae95f71503..4f6f6f81c07 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.ts +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseMenu.utils.ts @@ -1,5 +1,5 @@ -import { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' -import { Project } from 'data/projects/project-detail-query' +import type { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' +import type { Project } from 'data/projects/project-detail-query' import { IS_PLATFORM } from 'lib/constants' export const generateDatabaseMenu = ( diff --git a/apps/studio/components/layouts/DocsLayout/DocsLayout.utils.tsx b/apps/studio/components/layouts/DocsLayout/DocsLayout.utils.tsx index beb9bf2efce..dd1efef6c57 100644 --- a/apps/studio/components/layouts/DocsLayout/DocsLayout.utils.tsx +++ b/apps/studio/components/layouts/DocsLayout/DocsLayout.utils.tsx @@ -1,5 +1,5 @@ import SVG from 'react-inlinesvg' -import { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' +import type { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' import { IconBook, IconBookOpen } from 'ui' import { BASE_PATH } from 'lib/constants' diff --git a/apps/studio/components/layouts/FunctionsLayout.tsx b/apps/studio/components/layouts/FunctionsLayout.tsx index 2247126ac9e..a41dd3b0ab1 100644 --- a/apps/studio/components/layouts/FunctionsLayout.tsx +++ b/apps/studio/components/layouts/FunctionsLayout.tsx @@ -2,7 +2,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { observer } from 'mobx-react-lite' import Link from 'next/link' -import { PropsWithChildren } from 'react' +import type { PropsWithChildren } from 'react' import { Button, IconCode, IconExternalLink } from 'ui' import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' diff --git a/apps/studio/components/layouts/IntegrationsLayout/Integrations.utils.ts b/apps/studio/components/layouts/IntegrationsLayout/Integrations.utils.ts index 0d19f996f5c..3875773143c 100644 --- a/apps/studio/components/layouts/IntegrationsLayout/Integrations.utils.ts +++ b/apps/studio/components/layouts/IntegrationsLayout/Integrations.utils.ts @@ -1,6 +1,6 @@ -import { IntegrationsData } from 'data/integrations/integrations-query' -import { IntegrationName } from 'data/integrations/integrations.types' -import { Organization } from 'types' +import type { IntegrationsData } from 'data/integrations/integrations-query' +import type { IntegrationName } from 'data/integrations/integrations.types' +import type { Organization } from 'types' export function getHasInstalledObject({ integrationName, diff --git a/apps/studio/components/layouts/LogsLayout/LogsMenu.utils.ts b/apps/studio/components/layouts/LogsLayout/LogsMenu.utils.ts index d4fd1fd22a2..5c34890d454 100644 --- a/apps/studio/components/layouts/LogsLayout/LogsMenu.utils.ts +++ b/apps/studio/components/layouts/LogsLayout/LogsMenu.utils.ts @@ -1,5 +1,8 @@ -import { ProductMenuGroup, ProductMenuGroupItem } from 'components/ui/ProductMenu/ProductMenu.types' -import { Project } from 'data/projects/project-detail-query' +import type { + ProductMenuGroup, + ProductMenuGroupItem, +} from 'components/ui/ProductMenu/ProductMenu.types' +import type { Project } from 'data/projects/project-detail-query' import { IS_PLATFORM } from 'lib/constants' export const generateLogsMenu = ( diff --git a/apps/studio/components/layouts/OrganizationLayout.tsx b/apps/studio/components/layouts/OrganizationLayout.tsx index 58093c0e8af..7e18c7a7df7 100644 --- a/apps/studio/components/layouts/OrganizationLayout.tsx +++ b/apps/studio/components/layouts/OrganizationLayout.tsx @@ -1,5 +1,5 @@ import { useRouter } from 'next/router' -import { PropsWithChildren } from 'react' +import type { PropsWithChildren } from 'react' import { useParams } from 'common' import { useFlag, useIsFeatureEnabled, useSelectedOrganization } from 'hooks' @@ -13,7 +13,6 @@ const OrganizationLayout = ({ children }: PropsWithChildren<{}>) => { const selectedOrganization = useSelectedOrganization() const router = useRouter() const { slug } = useParams() - const id = router.asPath.split('/').at(-1)?.split('?')[0]?.split('#')[0] const invoicesEnabled = useIsFeatureEnabled('billing:invoices') diff --git a/apps/studio/components/layouts/ProjectLayout/ConnectingState.tsx b/apps/studio/components/layouts/ProjectLayout/ConnectingState.tsx index 3944a18b3a4..3ddee584421 100644 --- a/apps/studio/components/layouts/ProjectLayout/ConnectingState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ConnectingState.tsx @@ -7,7 +7,7 @@ import { Badge, Button, IconExternalLink, IconLoader, IconMonitor, IconServer } import ShimmerLine from 'components/ui/ShimmerLine' import { setProjectPostgrestStatus } from 'data/projects/projects-query' import pingPostgrest from 'lib/pingPostgrest' -import { Project } from 'data/projects/project-detail-query' +import type { Project } from 'data/projects/project-detail-query' export interface ConnectingStateProps { project: Project diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopoverV2/NotificationRow.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopoverV2/NotificationRow.tsx index c525b3c1011..355bf61de16 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopoverV2/NotificationRow.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/NotificationsPopoverV2/NotificationRow.tsx @@ -9,10 +9,10 @@ import { Button, IconArchive, IconExternalLink } from 'ui' import { Markdown } from 'components/interfaces/Markdown' import { CriticalIcon, WarningIcon } from 'components/ui/Icons' -import { ItemRenderer } from 'components/ui/InfiniteList' +import type { ItemRenderer } from 'components/ui/InfiniteList' import { Notification, NotificationData } from 'data/notifications/notifications-v2-query' import { ProjectInfo } from 'data/projects/projects-query' -import { Organization } from 'types' +import type { Organization } from 'types' interface NotificationRowProps { setRowHeight: (idx: number, height: number) => void diff --git a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx index f584fcd1a00..30ecb4d6c66 100644 --- a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx +++ b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx @@ -1,5 +1,5 @@ -import { Route } from 'components/ui/ui.types' -import { Project } from 'data/projects/project-detail-query' +import type { Route } from 'components/ui/ui.types' +import type { Project } from 'data/projects/project-detail-query' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' import { Auth, diff --git a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx index 0e1dc0770c6..8849eac61e7 100644 --- a/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx +++ b/apps/studio/components/layouts/ProjectLayout/NavigationBar/NavigationIconLink.tsx @@ -3,7 +3,7 @@ import Link from 'next/link' import { AnchorHTMLAttributes, forwardRef } from 'react' import { cn } from 'ui' -import { Route } from 'components/ui/ui.types' +import type { Route } from 'components/ui/ui.types' import { useAppStateSnapshot } from 'state/app-state' interface NavigationIconButtonProps extends AnchorHTMLAttributes { diff --git a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.ts b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.ts index ca762cb2df0..dc5230b9404 100644 --- a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.ts +++ b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsMenu.utils.ts @@ -1,7 +1,7 @@ -import { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' -import { Project } from 'data/projects/project-detail-query' +import type { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' +import type { Project } from 'data/projects/project-detail-query' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' -import { Organization } from 'types' +import type { Organization } from 'types' export const generateSettingsMenu = ( ref?: string, diff --git a/apps/studio/components/layouts/RealtimeLayout/RealtimeMenu.utils.ts b/apps/studio/components/layouts/RealtimeLayout/RealtimeMenu.utils.ts index e6d83293fb0..c8d612494a7 100644 --- a/apps/studio/components/layouts/RealtimeLayout/RealtimeMenu.utils.ts +++ b/apps/studio/components/layouts/RealtimeLayout/RealtimeMenu.utils.ts @@ -1,5 +1,5 @@ -import { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' -import { Project } from 'data/projects/project-detail-query' +import type { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' +import type { Project } from 'data/projects/project-detail-query' export const generateRealtimeMenu = (project?: Project): ProductMenuGroup[] => { const ref = project?.ref ?? 'default' diff --git a/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx b/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx index 20c100e91db..d4e8fac4baa 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/QueryItem.tsx @@ -27,7 +27,7 @@ import SimpleCodeBlock from 'components/to-be-cleaned/SimpleCodeBlock' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import CopyButton from 'components/ui/CopyButton' import { useContentDeleteMutation } from 'data/content/content-delete-mutation' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useSqlEditorStateSnapshot } from 'state/sql-editor' import { QueryItemActions } from './QueryItemActions' diff --git a/apps/studio/components/layouts/SQLEditorLayout/QueryItemActions.tsx b/apps/studio/components/layouts/SQLEditorLayout/QueryItemActions.tsx index a01b5a7c930..2eedc7458d9 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/QueryItemActions.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/QueryItemActions.tsx @@ -18,7 +18,7 @@ import { } from 'ui' import { createSqlSnippetSkeleton } from 'components/interfaces/SQLEditor/SQLEditor.utils' -import { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useCheckPermissions, useSelectedProject, useStore } from 'hooks' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' diff --git a/apps/studio/components/layouts/StorageLayout/BucketRow.tsx b/apps/studio/components/layouts/StorageLayout/BucketRow.tsx index fb54059a4d3..3d69401793b 100644 --- a/apps/studio/components/layouts/StorageLayout/BucketRow.tsx +++ b/apps/studio/components/layouts/StorageLayout/BucketRow.tsx @@ -17,7 +17,7 @@ import { IconXCircle, } from 'ui' -import { Bucket } from 'data/storage/buckets-query' +import type { Bucket } from 'data/storage/buckets-query' import { useCheckPermissions } from 'hooks' export interface BucketRowProps { diff --git a/apps/studio/components/layouts/StorageLayout/StorageBucketsError.tsx b/apps/studio/components/layouts/StorageLayout/StorageBucketsError.tsx index c5bddff3a9c..247847fdae4 100644 --- a/apps/studio/components/layouts/StorageLayout/StorageBucketsError.tsx +++ b/apps/studio/components/layouts/StorageLayout/StorageBucketsError.tsx @@ -1,6 +1,6 @@ import { useParams } from 'common' import Link from 'next/link' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { Alert, Button } from 'ui' export interface StorageBucketsErrorProps { diff --git a/apps/studio/components/layouts/StorageLayout/StorageMenu.tsx b/apps/studio/components/layouts/StorageLayout/StorageMenu.tsx index f272bb2d967..594e943b816 100644 --- a/apps/studio/components/layouts/StorageLayout/StorageMenu.tsx +++ b/apps/studio/components/layouts/StorageLayout/StorageMenu.tsx @@ -16,7 +16,7 @@ import { import CreateBucketModal from 'components/interfaces/Storage/CreateBucketModal' import EditBucketModal from 'components/interfaces/Storage/EditBucketModal' -import { StorageBucket } from 'components/interfaces/Storage/Storage.types' +import type { StorageBucket } from 'components/interfaces/Storage/Storage.types' import { DeleteBucketModal } from 'components/to-be-cleaned/Storage' import { EmptyBucketModal } from 'components/to-be-cleaned/Storage/EmptyBucketModal' import ShimmeringLoader from 'components/ui/ShimmeringLoader' diff --git a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx index f72e396098a..6f68ae1466a 100644 --- a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx @@ -20,9 +20,9 @@ import { } from 'ui' import { parseSupaTable } from 'components/grid' -import { ItemRenderer } from 'components/ui/InfiniteList' +import type { ItemRenderer } from 'components/ui/InfiniteList' import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' -import { Entity } from 'data/entity-types/entity-type-query' +import type { Entity } from 'data/entity-types/entity-type-query' import { fetchAllTableRows } from 'data/table-rows/table-rows-query' import { getTable } from 'data/tables/table-query' import { useStore } from 'hooks' diff --git a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx index 6d2afdd80df..96d2134c589 100644 --- a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx @@ -57,11 +57,9 @@ const TableEditorMenu = () => { isError, error, refetch, - isRefetching, hasNextPage, isFetchingNextPage, fetchNextPage, - isPreviousData: isSearching, } = useEntityTypesQuery( { projectRef: project?.ref, diff --git a/apps/studio/components/layouts/VercelIntegrationLayout.tsx b/apps/studio/components/layouts/VercelIntegrationLayout.tsx index 8c42daffedb..34bf4f2983a 100644 --- a/apps/studio/components/layouts/VercelIntegrationLayout.tsx +++ b/apps/studio/components/layouts/VercelIntegrationLayout.tsx @@ -1,5 +1,5 @@ import Head from 'next/head' -import { PropsWithChildren } from 'react' +import type { PropsWithChildren } from 'react' import Divider from 'components/ui/Divider' import { BASE_PATH } from 'lib/constants' diff --git a/apps/studio/components/layouts/WizardLayout.tsx b/apps/studio/components/layouts/WizardLayout.tsx index 5e51f9721b8..d181a263a1a 100644 --- a/apps/studio/components/layouts/WizardLayout.tsx +++ b/apps/studio/components/layouts/WizardLayout.tsx @@ -5,7 +5,7 @@ import { IconChevronRight } from 'ui' import { withAuth } from 'hooks' import { BASE_PATH } from 'lib/constants' -import { Organization, Project } from 'types' +import type { Organization, Project } from 'types' import { FeedbackDropdown } from './ProjectLayout/LayoutHeader/FeedbackDropdown' import HelpPopover from './ProjectLayout/LayoutHeader/HelpPopover' diff --git a/apps/studio/components/to-be-cleaned/Charts/ChartHandler.tsx b/apps/studio/components/to-be-cleaned/Charts/ChartHandler.tsx index e996f82213c..2b7f8062ea8 100644 --- a/apps/studio/components/to-be-cleaned/Charts/ChartHandler.tsx +++ b/apps/studio/components/to-be-cleaned/Charts/ChartHandler.tsx @@ -1,4 +1,4 @@ -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import { isUndefined } from 'lodash' import { useRouter } from 'next/router' import { PropsWithChildren, useEffect, useState } from 'react' @@ -7,7 +7,7 @@ import { Button, IconActivity, IconAlertCircle, IconBarChart, IconLoader } from import AreaChart from 'components/ui/Charts/AreaChart' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ChartData } from './ChartHandler.types' +import type { ChartData } from './ChartHandler.types' import { BarChart } from './ChartRenderer' interface ChartHandlerProps { diff --git a/apps/studio/components/to-be-cleaned/Storage/EmptyBucketModal.tsx b/apps/studio/components/to-be-cleaned/Storage/EmptyBucketModal.tsx index 3bf0fd86d25..c8ec9060e0c 100644 --- a/apps/studio/components/to-be-cleaned/Storage/EmptyBucketModal.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/EmptyBucketModal.tsx @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useBucketEmptyMutation } from 'data/storage/bucket-empty-mutation' -import { Bucket } from 'data/storage/buckets-query' +import type { Bucket } from 'data/storage/buckets-query' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' import { AlertDescription_Shadcn_, diff --git a/apps/studio/components/to-be-cleaned/Storage/Storage.utils.ts b/apps/studio/components/to-be-cleaned/Storage/Storage.utils.ts index 79406cf3487..5a50eab4ec4 100644 --- a/apps/studio/components/to-be-cleaned/Storage/Storage.utils.ts +++ b/apps/studio/components/to-be-cleaned/Storage/Storage.utils.ts @@ -1,6 +1,6 @@ import { groupBy, difference } from 'lodash' import { STORAGE_CLIENT_LIBRARY_MAPPINGS } from './Storage.constants' -import { StoragePolicyFormField } from 'components/interfaces/Storage/Storage.types' +import type { StoragePolicyFormField } from 'components/interfaces/Storage/Storage.types' const shortHash = (str: string) => { let hash = 0 diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorer.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorer.tsx index 7b5b02dcb99..9392c7e5db9 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorer.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorer.tsx @@ -7,7 +7,7 @@ import FolderContextMenu from './FolderContextMenu' import ColumnContextMenu from './ColumnContextMenu' import FileExplorerColumn from './FileExplorerColumn' import { noop } from 'lodash' -import { StorageColumn } from '../Storage.types' +import type { StorageColumn } from '../Storage.types' export interface FileExplorerProps { view: string diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerColumn.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerColumn.tsx index b2ccb1cf02a..19a316628d6 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerColumn.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerColumn.tsx @@ -15,7 +15,7 @@ import { STORAGE_ROW_TYPES, STORAGE_VIEWS, } from '../Storage.constants' -import { StorageColumn } from '../Storage.types' +import type { StorageColumn } from '../Storage.types' import FileExplorerRow from './FileExplorerRow' const DragOverOverlay = ({ isOpen, onDragLeave, onDrop, folderIsEmpty }: any) => { diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx index 05ceb155cc9..6ece67a3f98 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx @@ -28,7 +28,7 @@ import { IconTrash2, } from 'ui' -import { ItemRenderer } from 'components/ui/InfiniteList' +import type { ItemRenderer } from 'components/ui/InfiniteList' import { useCheckPermissions } from 'hooks' import { BASE_PATH } from 'lib/constants' import { formatBytes } from 'lib/helpers' diff --git a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/StorageExplorer.tsx b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/StorageExplorer.tsx index 1f8bbb6ab7f..0c0beb8cbd1 100644 --- a/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/StorageExplorer.tsx +++ b/apps/studio/components/to-be-cleaned/Storage/StorageExplorer/StorageExplorer.tsx @@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from 'react' import { useProjectSettingsQuery } from 'data/config/project-settings-query' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' -import { Bucket } from 'data/storage/buckets-query' +import type { Bucket } from 'data/storage/buckets-query' import { useStore } from 'hooks' import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' import { copyToClipboard } from 'lib/helpers' diff --git a/apps/studio/components/ui/AlertError.tsx b/apps/studio/components/ui/AlertError.tsx index 331e2c1beb1..4bb1a367db3 100644 --- a/apps/studio/components/ui/AlertError.tsx +++ b/apps/studio/components/ui/AlertError.tsx @@ -1,5 +1,5 @@ import Link from 'next/link' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, diff --git a/apps/studio/components/ui/Charts/AreaChart.tsx b/apps/studio/components/ui/Charts/AreaChart.tsx index d0f0e0bbfa0..4d6fcef6861 100644 --- a/apps/studio/components/ui/Charts/AreaChart.tsx +++ b/apps/studio/components/ui/Charts/AreaChart.tsx @@ -4,7 +4,7 @@ import utc from 'dayjs/plugin/utc' import { useState } from 'react' import { Area, AreaChart as RechartAreaChart, Tooltip, XAxis } from 'recharts' import ChartHeader from './ChartHeader' -import { CommonChartProps, Datum } from './Charts.types' +import type { CommonChartProps, Datum } from './Charts.types' import { numberFormatter, useChartSize } from './Charts.utils' import ChartNoData from './NoDataPlaceholder' dayjs.extend(utc) diff --git a/apps/studio/components/ui/Charts/BarChart.tsx b/apps/studio/components/ui/Charts/BarChart.tsx index 9f843aa9426..2e45ba94213 100644 --- a/apps/studio/components/ui/Charts/BarChart.tsx +++ b/apps/studio/components/ui/Charts/BarChart.tsx @@ -3,9 +3,9 @@ import dayjs from 'dayjs' import utc from 'dayjs/plugin/utc' import { useState } from 'react' import { Bar, BarChart as RechartBarChart, Cell, Tooltip, XAxis, Legend } from 'recharts' -import { CategoricalChartState } from 'recharts/types/chart/generateCategoricalChart' +import type { CategoricalChartState } from 'recharts/types/chart/generateCategoricalChart' import ChartHeader from './ChartHeader' -import { CommonChartProps, Datum } from './Charts.types' +import type { CommonChartProps, Datum } from './Charts.types' import { numberFormatter, useChartSize } from './Charts.utils' import ChartNoData from './NoDataPlaceholder' dayjs.extend(utc) diff --git a/apps/studio/components/ui/Charts/Charts.utils.tsx b/apps/studio/components/ui/Charts/Charts.utils.tsx index 34c9f6783f1..89acca19e3b 100644 --- a/apps/studio/components/ui/Charts/Charts.utils.tsx +++ b/apps/studio/components/ui/Charts/Charts.utils.tsx @@ -2,7 +2,7 @@ import dayjs from 'dayjs' import React, { useMemo } from 'react' import { ResponsiveContainer } from 'recharts' import { DateTimeFormats } from './Charts.constants' -import { CommonChartProps, StackedChartProps } from './Charts.types' +import type { CommonChartProps, StackedChartProps } from './Charts.types' import utc from 'dayjs/plugin/utc' dayjs.extend(utc) diff --git a/apps/studio/components/ui/Charts/StackedBarChart.tsx b/apps/studio/components/ui/Charts/StackedBarChart.tsx index 3c252cc7039..1bf9b9a4528 100644 --- a/apps/studio/components/ui/Charts/StackedBarChart.tsx +++ b/apps/studio/components/ui/Charts/StackedBarChart.tsx @@ -10,7 +10,7 @@ import { genStackColorScales, ValidStackColor, } from './Charts.constants' -import { CommonChartProps } from './Charts.types' +import type { CommonChartProps } from './Charts.types' import { numberFormatter, precisionFormatter, diff --git a/apps/studio/components/ui/CodeEditor/Providers/PgSQLCompletionProvider.ts b/apps/studio/components/ui/CodeEditor/Providers/PgSQLCompletionProvider.ts index e9534735c9b..599c67c4e04 100644 --- a/apps/studio/components/ui/CodeEditor/Providers/PgSQLCompletionProvider.ts +++ b/apps/studio/components/ui/CodeEditor/Providers/PgSQLCompletionProvider.ts @@ -1,8 +1,8 @@ -import { RefObject } from 'react' +import type { RefObject } from 'react' import BackwardIterator from './BackwardIterator' -import { Schema } from 'data/database/schemas-query' -import { TableColumn } from 'data/database/table-columns-query' -import { DatabaseFunction } from 'data/database/functions-query' +import type { Schema } from 'data/database/schemas-query' +import type { TableColumn } from 'data/database/table-columns-query' +import type { DatabaseFunction } from 'data/database/functions-query' // [Joshen] Needs to be fixed diff --git a/apps/studio/components/ui/DatePicker/TimeSplitInput.tsx b/apps/studio/components/ui/DatePicker/TimeSplitInput.tsx index b86024b611c..9021eb08793 100644 --- a/apps/studio/components/ui/DatePicker/TimeSplitInput.tsx +++ b/apps/studio/components/ui/DatePicker/TimeSplitInput.tsx @@ -3,7 +3,7 @@ import { IconClock } from 'ui' import { format } from 'date-fns' -import { TimeSplitInputProps, TimeType } from './DatePicker.types' +import type { TimeSplitInputProps, TimeType } from './DatePicker.types' const TimeSplitInput = ({ type, diff --git a/apps/studio/components/ui/Flag/FlagProvider.tsx b/apps/studio/components/ui/Flag/FlagProvider.tsx index e949bca4201..57f11d9fd69 100644 --- a/apps/studio/components/ui/Flag/FlagProvider.tsx +++ b/apps/studio/components/ui/Flag/FlagProvider.tsx @@ -1,4 +1,4 @@ -import { User } from '@supabase/supabase-js' +import type { User } from '@supabase/supabase-js' import { PropsWithChildren, useEffect, useState } from 'react' import { IS_PLATFORM } from 'lib/constants' diff --git a/apps/studio/components/ui/OveragesBanner/OveragesBanner.utils.ts b/apps/studio/components/ui/OveragesBanner/OveragesBanner.utils.ts index 9011364f955..0a33a6342ce 100644 --- a/apps/studio/components/ui/OveragesBanner/OveragesBanner.utils.ts +++ b/apps/studio/components/ui/OveragesBanner/OveragesBanner.utils.ts @@ -1,4 +1,4 @@ -import { OrgMetricsUsage } from 'data/usage/org-usage-query' +import type { OrgMetricsUsage } from 'data/usage/org-usage-query' export const getResourcesExceededLimitsOrg = (usageMetrics: OrgMetricsUsage[]): string[] => { if (!usageMetrics.length) return [] diff --git a/apps/studio/components/ui/ProductMenu/ProductMenu.tsx b/apps/studio/components/ui/ProductMenu/ProductMenu.tsx index 7f9e952de2c..2993d7d1535 100644 --- a/apps/studio/components/ui/ProductMenu/ProductMenu.tsx +++ b/apps/studio/components/ui/ProductMenu/ProductMenu.tsx @@ -1,6 +1,6 @@ import { Badge, Menu } from 'ui' -import { ProductMenuGroup } from './ProductMenu.types' +import type { ProductMenuGroup } from './ProductMenu.types' import ProductMenuItem from './ProductMenuItem' interface ProductMenuProps { diff --git a/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.utils.ts b/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.utils.ts index 8665089241b..23e35345f36 100644 --- a/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.utils.ts +++ b/apps/studio/components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner.utils.ts @@ -1,4 +1,4 @@ -import { ResourceWarning } from 'data/usage/resource-warnings-query' +import type { ResourceWarning } from 'data/usage/resource-warnings-query' import { RESOURCE_WARNING_MESSAGES } from './ResourceExhaustionWarningBanner.constants' export const getWarningContent = ( diff --git a/apps/studio/data/__templates/resource-query.ts b/apps/studio/data/__templates/resource-query.ts index 6fa63c86e78..0f0b0501376 100644 --- a/apps/studio/data/__templates/resource-query.ts +++ b/apps/studio/data/__templates/resource-query.ts @@ -2,7 +2,7 @@ import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query import { useCallback } from 'react' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { resourceKeys } from './keys' export type ResourceVariables = { diff --git a/apps/studio/data/__templates/resource-update-mutation.ts b/apps/studio/data/__templates/resource-update-mutation.ts index 2fd34512f8f..ae277f09c54 100644 --- a/apps/studio/data/__templates/resource-update-mutation.ts +++ b/apps/studio/data/__templates/resource-update-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { handleError, patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { resourceKeys } from './keys' export type ResourceUpdateVariables = { diff --git a/apps/studio/data/__templates/resources-query.ts b/apps/studio/data/__templates/resources-query.ts index 5ed424df8b4..9d15bd55ee7 100644 --- a/apps/studio/data/__templates/resources-query.ts +++ b/apps/studio/data/__templates/resources-query.ts @@ -2,7 +2,7 @@ import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query import { useCallback } from 'react' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { resourceKeys } from './keys' export type ResourcesVariables = { diff --git a/apps/studio/data/access-tokens/access-tokens-create-mutation.ts b/apps/studio/data/access-tokens/access-tokens-create-mutation.ts index 6fb92b70ed4..6afa1a4d01c 100644 --- a/apps/studio/data/access-tokens/access-tokens-create-mutation.ts +++ b/apps/studio/data/access-tokens/access-tokens-create-mutation.ts @@ -2,8 +2,8 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { isResponseOk, post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' -import { AccessToken } from './access-tokens-query' +import type { ResponseError } from 'types' +import type { AccessToken } from './access-tokens-query' import { accessTokenKeys } from './keys' export type AccessTokenCreateVariables = { diff --git a/apps/studio/data/access-tokens/access-tokens-delete-mutation.ts b/apps/studio/data/access-tokens/access-tokens-delete-mutation.ts index f94f5734be6..84e7047ecad 100644 --- a/apps/studio/data/access-tokens/access-tokens-delete-mutation.ts +++ b/apps/studio/data/access-tokens/access-tokens-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { delete_, isResponseOk } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { accessTokenKeys } from './keys' export type AccessTokenDeleteVariables = { diff --git a/apps/studio/data/ai/sql-debug-mutation.ts b/apps/studio/data/ai/sql-debug-mutation.ts index 61843e3f308..32f3a462704 100644 --- a/apps/studio/data/ai/sql-debug-mutation.ts +++ b/apps/studio/data/ai/sql-debug-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { isResponseOk, post } from 'lib/common/fetch' import { BASE_PATH } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SqlDebugResponse = { solution: string diff --git a/apps/studio/data/ai/sql-edit-mutation.ts b/apps/studio/data/ai/sql-edit-mutation.ts index 891bd7ace12..0127f17d1bf 100644 --- a/apps/studio/data/ai/sql-edit-mutation.ts +++ b/apps/studio/data/ai/sql-edit-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { isResponseOk, post } from 'lib/common/fetch' import { BASE_PATH } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SqlEditResponse = { sql: string diff --git a/apps/studio/data/ai/sql-generate-mutation.ts b/apps/studio/data/ai/sql-generate-mutation.ts index fa076045b2c..e26b54a0776 100644 --- a/apps/studio/data/ai/sql-generate-mutation.ts +++ b/apps/studio/data/ai/sql-generate-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { isResponseOk, post } from 'lib/common/fetch' import { BASE_PATH } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SqlGenerateResponse = { title: string diff --git a/apps/studio/data/ai/sql-title-mutation.ts b/apps/studio/data/ai/sql-title-mutation.ts index 339cb0ec66a..7306ec2df7a 100644 --- a/apps/studio/data/ai/sql-title-mutation.ts +++ b/apps/studio/data/ai/sql-title-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { isResponseOk, post } from 'lib/common/fetch' import { BASE_PATH } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SqlTitleGenerateResponse = { title: string diff --git a/apps/studio/data/analytics/infra-monitoring-query.ts b/apps/studio/data/analytics/infra-monitoring-query.ts index 6f8101451af..ce73629d8b4 100644 --- a/apps/studio/data/analytics/infra-monitoring-query.ts +++ b/apps/studio/data/analytics/infra-monitoring-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import dayjs from 'dayjs' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { AnalyticsData } from './constants' +import type { AnalyticsData } from './constants' import { analyticsKeys } from './keys' export type InfraMonitoringVariables = { diff --git a/apps/studio/data/analytics/org-daily-compute-stats-query.ts b/apps/studio/data/analytics/org-daily-compute-stats-query.ts index a4bf2e24e1f..60232b64243 100644 --- a/apps/studio/data/analytics/org-daily-compute-stats-query.ts +++ b/apps/studio/data/analytics/org-daily-compute-stats-query.ts @@ -1,9 +1,9 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import dayjs from 'dayjs' import { get } from 'data/fetchers' -import { AnalyticsData } from './constants' +import type { AnalyticsData } from './constants' import { analyticsKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrgDailyComputeStatsVariables = { // API parameters diff --git a/apps/studio/data/analytics/org-daily-stats-query.ts b/apps/studio/data/analytics/org-daily-stats-query.ts index 9e92da29293..90202c60cf7 100644 --- a/apps/studio/data/analytics/org-daily-stats-query.ts +++ b/apps/studio/data/analytics/org-daily-stats-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import dayjs from 'dayjs' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { AnalyticsData } from './constants' +import type { AnalyticsData } from './constants' import { analyticsKeys } from './keys' export enum EgressType { diff --git a/apps/studio/data/analytics/project-log-requests-count-query.ts b/apps/studio/data/analytics/project-log-requests-count-query.ts index dd092593fc1..e5436f71363 100644 --- a/apps/studio/data/analytics/project-log-requests-count-query.ts +++ b/apps/studio/data/analytics/project-log-requests-count-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { analyticsKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectLogRequestsCountVariables = { projectRef?: string diff --git a/apps/studio/data/api-authorization/api-authorization-approve-mutation.ts b/apps/studio/data/api-authorization/api-authorization-approve-mutation.ts index 1185cc12dfd..8ee802a666f 100644 --- a/apps/studio/data/api-authorization/api-authorization-approve-mutation.ts +++ b/apps/studio/data/api-authorization/api-authorization-approve-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_ADMIN_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ApiAuthorizationApproveVariables = { id: string diff --git a/apps/studio/data/api-authorization/api-authorization-decline-mutation.ts b/apps/studio/data/api-authorization/api-authorization-decline-mutation.ts index aaff42dca99..5a55574d679 100644 --- a/apps/studio/data/api-authorization/api-authorization-decline-mutation.ts +++ b/apps/studio/data/api-authorization/api-authorization-decline-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_ADMIN_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ApiAuthorizationDeclineVariables = { id: string diff --git a/apps/studio/data/api-authorization/api-authorization-query.ts b/apps/studio/data/api-authorization/api-authorization-query.ts index bfd3efc235a..425cb98deb7 100644 --- a/apps/studio/data/api-authorization/api-authorization-query.ts +++ b/apps/studio/data/api-authorization/api-authorization-query.ts @@ -1,4 +1,4 @@ -import { OAuthScope } from '@supabase/shared-types/out/constants' +import type { OAuthScope } from '@supabase/shared-types/out/constants' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_ADMIN_URL } from 'lib/constants' diff --git a/apps/studio/data/auth/auth-config-query.ts b/apps/studio/data/auth/auth-config-query.ts index 293b47b039a..d8a6e34c4a6 100644 --- a/apps/studio/data/auth/auth-config-query.ts +++ b/apps/studio/data/auth/auth-config-query.ts @@ -1,8 +1,8 @@ import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get, handleError } from 'data/fetchers' import { useCallback } from 'react' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { authKeys } from './keys' export type AuthConfigVariables = { diff --git a/apps/studio/data/auth/auth-config-update-mutation.ts b/apps/studio/data/auth/auth-config-update-mutation.ts index c64a0d903a2..7e0c9f21000 100644 --- a/apps/studio/data/auth/auth-config-update-mutation.ts +++ b/apps/studio/data/auth/auth-config-update-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { authKeys } from './keys' export type AuthConfigUpdateVariables = { diff --git a/apps/studio/data/auth/user-create-mutation.ts b/apps/studio/data/auth/user-create-mutation.ts index 233ac115447..b737368acee 100644 --- a/apps/studio/data/auth/user-create-mutation.ts +++ b/apps/studio/data/auth/user-create-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { authKeys } from './keys' export type UserCreateVariables = { diff --git a/apps/studio/data/auth/user-delete-mfa-factors-mutation.ts b/apps/studio/data/auth/user-delete-mfa-factors-mutation.ts index 96a05ee37d2..1b58cfcc842 100644 --- a/apps/studio/data/auth/user-delete-mfa-factors-mutation.ts +++ b/apps/studio/data/auth/user-delete-mfa-factors-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type UserDeleteMFAFactorsVariables = { projectRef: string diff --git a/apps/studio/data/auth/user-delete-mutation.ts b/apps/studio/data/auth/user-delete-mutation.ts index c5007295417..a6a50713e69 100644 --- a/apps/studio/data/auth/user-delete-mutation.ts +++ b/apps/studio/data/auth/user-delete-mutation.ts @@ -3,8 +3,8 @@ import toast from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' -import { User } from './users-query' +import type { ResponseError } from 'types' +import type { User } from './users-query' import { authKeys } from './keys' export type UserDeleteVariables = { diff --git a/apps/studio/data/auth/user-invite-mutation.ts b/apps/studio/data/auth/user-invite-mutation.ts index ed92c179c15..ca0924e05a5 100644 --- a/apps/studio/data/auth/user-invite-mutation.ts +++ b/apps/studio/data/auth/user-invite-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { API_URL } from 'lib/constants' import { authKeys } from './keys' diff --git a/apps/studio/data/auth/user-reset-password-mutation.ts b/apps/studio/data/auth/user-reset-password-mutation.ts index 14220772625..ff76c1a1b15 100644 --- a/apps/studio/data/auth/user-reset-password-mutation.ts +++ b/apps/studio/data/auth/user-reset-password-mutation.ts @@ -3,8 +3,8 @@ import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' -import { User } from './users-query' +import type { ResponseError } from 'types' +import type { User } from './users-query' export type UserResetPasswordVariables = { projectRef: string diff --git a/apps/studio/data/auth/user-send-magic-link-mutation.ts b/apps/studio/data/auth/user-send-magic-link-mutation.ts index ad339580490..6caed79dea3 100644 --- a/apps/studio/data/auth/user-send-magic-link-mutation.ts +++ b/apps/studio/data/auth/user-send-magic-link-mutation.ts @@ -3,8 +3,8 @@ import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' -import { User } from './users-query' +import type { ResponseError } from 'types' +import type { User } from './users-query' export type UserSendMagicLinkVariables = { projectRef: string diff --git a/apps/studio/data/auth/user-send-otp-mutation.ts b/apps/studio/data/auth/user-send-otp-mutation.ts index 35df55e88c2..7630b637656 100644 --- a/apps/studio/data/auth/user-send-otp-mutation.ts +++ b/apps/studio/data/auth/user-send-otp-mutation.ts @@ -3,8 +3,8 @@ import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' -import { User } from './users-query' +import type { ResponseError } from 'types' +import type { User } from './users-query' export type UserSendOTPVariables = { projectRef: string diff --git a/apps/studio/data/auth/users-query.ts b/apps/studio/data/auth/users-query.ts index a4fcc4123c4..8a9486f302a 100644 --- a/apps/studio/data/auth/users-query.ts +++ b/apps/studio/data/auth/users-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { authKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' export type UsersVariables = { projectRef?: string diff --git a/apps/studio/data/banned-ips/banned-ips-delete-mutations.ts b/apps/studio/data/banned-ips/banned-ips-delete-mutations.ts index fda7e1b04ae..179ef255ef8 100644 --- a/apps/studio/data/banned-ips/banned-ips-delete-mutations.ts +++ b/apps/studio/data/banned-ips/banned-ips-delete-mutations.ts @@ -1,6 +1,6 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { BannedIPKeys } from './keys' import toast from 'react-hot-toast' diff --git a/apps/studio/data/banned-ips/banned-ips-query.ts b/apps/studio/data/banned-ips/banned-ips-query.ts index 66e914ee14c..0ac314d39e1 100644 --- a/apps/studio/data/banned-ips/banned-ips-query.ts +++ b/apps/studio/data/banned-ips/banned-ips-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { handleError, post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { BannedIPKeys } from './keys' export type BannedIPVariables = { diff --git a/apps/studio/data/branches/branch-create-mutation.ts b/apps/studio/data/branches/branch-create-mutation.ts index 45ae4585913..c056ae84f0d 100644 --- a/apps/studio/data/branches/branch-create-mutation.ts +++ b/apps/studio/data/branches/branch-create-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { branchKeys } from './keys' import { projectKeys } from 'data/projects/keys' diff --git a/apps/studio/data/branches/branch-delete-mutation.ts b/apps/studio/data/branches/branch-delete-mutation.ts index 736a66b9162..2ebe359a25f 100644 --- a/apps/studio/data/branches/branch-delete-mutation.ts +++ b/apps/studio/data/branches/branch-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { branchKeys } from './keys' export type BranchDeleteVariables = { diff --git a/apps/studio/data/branches/branch-query.ts b/apps/studio/data/branches/branch-query.ts index 5b40d9f8178..4959e155748 100644 --- a/apps/studio/data/branches/branch-query.ts +++ b/apps/studio/data/branches/branch-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { branchKeys } from './keys' export type BranchVariables = { diff --git a/apps/studio/data/branches/branch-update-mutation.ts b/apps/studio/data/branches/branch-update-mutation.ts index 2b70d82bb48..5ccec5ecbd8 100644 --- a/apps/studio/data/branches/branch-update-mutation.ts +++ b/apps/studio/data/branches/branch-update-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { branchKeys } from './keys' export type BranchUpdateVariables = { diff --git a/apps/studio/data/branches/branches-disable-mutation.ts b/apps/studio/data/branches/branches-disable-mutation.ts index 32f3cdbaedc..c5185da3899 100644 --- a/apps/studio/data/branches/branches-disable-mutation.ts +++ b/apps/studio/data/branches/branches-disable-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' import { projectKeys } from 'data/projects/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { deleteBranch } from './branch-delete-mutation' import { branchKeys } from './keys' diff --git a/apps/studio/data/branches/branches-query.ts b/apps/studio/data/branches/branches-query.ts index 91a95c3d753..67c27347e40 100644 --- a/apps/studio/data/branches/branches-query.ts +++ b/apps/studio/data/branches/branches-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { branchKeys } from './keys' export type BranchesVariables = { diff --git a/apps/studio/data/config/jwt-secret-update-mutation.ts b/apps/studio/data/config/jwt-secret-update-mutation.ts index 6d50154a832..95087a12902 100644 --- a/apps/studio/data/config/jwt-secret-update-mutation.ts +++ b/apps/studio/data/config/jwt-secret-update-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { configKeys } from './keys' export type JwtSecretUpdateVariables = { diff --git a/apps/studio/data/config/pgbouncer-enabled-query.ts b/apps/studio/data/config/pgbouncer-enabled-query.ts index 6a7b84ac92a..fa176d2e9a6 100644 --- a/apps/studio/data/config/pgbouncer-enabled-query.ts +++ b/apps/studio/data/config/pgbouncer-enabled-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { configKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { get } from 'data/fetchers' import { IS_PLATFORM } from 'lib/constants' diff --git a/apps/studio/data/config/project-api-query.ts b/apps/studio/data/config/project-api-query.ts index 64ae4284cfa..ae1e960a9d8 100644 --- a/apps/studio/data/config/project-api-query.ts +++ b/apps/studio/data/config/project-api-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { configKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectApiVariables = { projectRef?: string diff --git a/apps/studio/data/config/project-disk-resize-mutation.ts b/apps/studio/data/config/project-disk-resize-mutation.ts index c07ca3245f1..dcc9977bb5f 100644 --- a/apps/studio/data/config/project-disk-resize-mutation.ts +++ b/apps/studio/data/config/project-disk-resize-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { usageKeys } from '../usage/keys' export type ProjectDiskResizeVariables = { diff --git a/apps/studio/data/config/project-postgrest-config-update-mutation.ts b/apps/studio/data/config/project-postgrest-config-update-mutation.ts index 8b87c192ae2..0e319361257 100644 --- a/apps/studio/data/config/project-postgrest-config-update-mutation.ts +++ b/apps/studio/data/config/project-postgrest-config-update-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { configKeys } from './keys' export type ProjectPostgrestConfigUpdateVariables = { diff --git a/apps/studio/data/config/project-settings-query.ts b/apps/studio/data/config/project-settings-query.ts index 91de0d3df78..7123a015e65 100644 --- a/apps/studio/data/config/project-settings-query.ts +++ b/apps/studio/data/config/project-settings-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get } from 'data/fetchers' import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { configKeys } from './keys' export type ProjectSettingsVariables = { diff --git a/apps/studio/data/config/project-storage-config-query.ts b/apps/studio/data/config/project-storage-config-query.ts index 6fdefd55786..8408f0e74d9 100644 --- a/apps/studio/data/config/project-storage-config-query.ts +++ b/apps/studio/data/config/project-storage-config-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { configKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectStorageConfigVariables = { projectRef?: string diff --git a/apps/studio/data/config/project-storage-config-update-mutation.ts b/apps/studio/data/config/project-storage-config-update-mutation.ts index d1faba61008..b3ff8aa6eaa 100644 --- a/apps/studio/data/config/project-storage-config-update-mutation.ts +++ b/apps/studio/data/config/project-storage-config-update-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { configKeys } from './keys' export type ProjectStorageConfigUpdateUpdateVariables = { diff --git a/apps/studio/data/config/project-temp-disable-read-only-mutation.ts b/apps/studio/data/config/project-temp-disable-read-only-mutation.ts index 769fce31388..b7c47d4173c 100644 --- a/apps/studio/data/config/project-temp-disable-read-only-mutation.ts +++ b/apps/studio/data/config/project-temp-disable-read-only-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' import { usageKeys } from 'data/usage/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type TempDisableReadOnlyModeVariables = { projectRef: string diff --git a/apps/studio/data/config/project-upgrade-eligibility-query.ts b/apps/studio/data/config/project-upgrade-eligibility-query.ts index 1968c3efa75..685618c8c6d 100644 --- a/apps/studio/data/config/project-upgrade-eligibility-query.ts +++ b/apps/studio/data/config/project-upgrade-eligibility-query.ts @@ -3,7 +3,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_ADMIN_URL } from 'lib/constants' import { configKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectUpgradeEligibilityVariables = { projectRef?: string } export type ProjectUpgradeEligibilityResponse = { diff --git a/apps/studio/data/content/content-delete-mutation.ts b/apps/studio/data/content/content-delete-mutation.ts index 91dc03c343f..fdae3e32f0f 100644 --- a/apps/studio/data/content/content-delete-mutation.ts +++ b/apps/studio/data/content/content-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { contentKeys } from './keys' type DeleteContentVariables = { projectRef: string; ids: string[] } diff --git a/apps/studio/data/content/content-insert-mutation.ts b/apps/studio/data/content/content-insert-mutation.ts index e7499042335..c7bdfab3b3c 100644 --- a/apps/studio/data/content/content-insert-mutation.ts +++ b/apps/studio/data/content/content-insert-mutation.ts @@ -1,10 +1,10 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { post } from 'data/fetchers' -import { ResponseError } from 'types' -import { Content } from './content-query' +import type { ResponseError } from 'types' +import type { Content } from './content-query' import { contentKeys } from './keys' export type InsertContentPayload = Omit & { diff --git a/apps/studio/data/content/content-query.ts b/apps/studio/data/content/content-query.ts index 364e7499b43..578b7bf674e 100644 --- a/apps/studio/data/content/content-query.ts +++ b/apps/studio/data/content/content-query.ts @@ -2,7 +2,7 @@ import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { useCallback } from 'react' -import { Dashboards, LogSqlSnippets, Owner, SqlSnippets } from 'types' +import type { Dashboards, LogSqlSnippets, Owner, SqlSnippets } from 'types' import { contentKeys } from './keys' type ContentBase = { diff --git a/apps/studio/data/content/content-upsert-mutation.ts b/apps/studio/data/content/content-upsert-mutation.ts index faaf59eca9b..a3fe29ef1cd 100644 --- a/apps/studio/data/content/content-upsert-mutation.ts +++ b/apps/studio/data/content/content-upsert-mutation.ts @@ -1,10 +1,10 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { put } from 'data/fetchers' -import { ResponseError } from 'types' -import { Content } from './content-query' +import type { ResponseError } from 'types' +import type { Content } from './content-query' import { contentKeys } from './keys' export type UpsertContentPayload = Omit & { diff --git a/apps/studio/data/custom-domains/check-cname-mutation.ts b/apps/studio/data/custom-domains/check-cname-mutation.ts index 62bfcaf7de7..5249707314c 100644 --- a/apps/studio/data/custom-domains/check-cname-mutation.ts +++ b/apps/studio/data/custom-domains/check-cname-mutation.ts @@ -1,7 +1,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type CheckCNAMERecordVariables = { domain: string diff --git a/apps/studio/data/custom-domains/custom-domains-activate-mutation.ts b/apps/studio/data/custom-domains/custom-domains-activate-mutation.ts index c0c44d6e52c..091b8e196a3 100644 --- a/apps/studio/data/custom-domains/custom-domains-activate-mutation.ts +++ b/apps/studio/data/custom-domains/custom-domains-activate-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { customDomainKeys } from './keys' export type CustomDomainActivateVariables = { diff --git a/apps/studio/data/custom-domains/custom-domains-create-mutation.ts b/apps/studio/data/custom-domains/custom-domains-create-mutation.ts index 816a978b955..b50b0a1bd00 100644 --- a/apps/studio/data/custom-domains/custom-domains-create-mutation.ts +++ b/apps/studio/data/custom-domains/custom-domains-create-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { customDomainKeys } from './keys' export type CustomDomainCreateVariables = { diff --git a/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts b/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts index 615b0a583f9..2285c138304 100644 --- a/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts +++ b/apps/studio/data/custom-domains/custom-domains-delete-mutation.ts @@ -1,7 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { del } from 'data/fetchers' import { toast } from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { customDomainKeys } from './keys' export type CustomDomainDeleteVariables = { diff --git a/apps/studio/data/custom-domains/custom-domains-query.ts b/apps/studio/data/custom-domains/custom-domains-query.ts index 4a4ea190cbc..1ffd8cd0f8e 100644 --- a/apps/studio/data/custom-domains/custom-domains-query.ts +++ b/apps/studio/data/custom-domains/custom-domains-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get, handleError } from 'data/fetchers' import { IS_PLATFORM } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { customDomainKeys } from './keys' export type CustomDomainsVariables = { diff --git a/apps/studio/data/custom-domains/custom-domains-reverify-mutation.ts b/apps/studio/data/custom-domains/custom-domains-reverify-mutation.ts index a33fe58a6ed..8d7988a2ba1 100644 --- a/apps/studio/data/custom-domains/custom-domains-reverify-mutation.ts +++ b/apps/studio/data/custom-domains/custom-domains-reverify-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { post } from 'data/fetchers' import { toast } from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { customDomainKeys } from './keys' export type CustomDomainReverifyVariables = { diff --git a/apps/studio/data/database-columns/database-column-create-mutation.ts b/apps/studio/data/database-columns/database-column-create-mutation.ts index 1df9fd8364a..28793eaa760 100644 --- a/apps/studio/data/database-columns/database-column-create-mutation.ts +++ b/apps/studio/data/database-columns/database-column-create-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type CreateColumnBody = components['schemas']['CreateColumnBody'] diff --git a/apps/studio/data/database-columns/database-column-delete-mutation.ts b/apps/studio/data/database-columns/database-column-delete-mutation.ts index e4c9960104a..b067ea240c9 100644 --- a/apps/studio/data/database-columns/database-column-delete-mutation.ts +++ b/apps/studio/data/database-columns/database-column-delete-mutation.ts @@ -2,10 +2,10 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { sqlKeys } from 'data/sql/keys' import { entityTypeKeys } from 'data/entity-types/keys' -import { TableLike } from 'hooks/misc/useTable' +import type { TableLike } from 'hooks/misc/useTable' import { tableKeys } from 'data/tables/keys' import { viewKeys } from 'data/views/keys' diff --git a/apps/studio/data/database-columns/database-column-update-mutation.ts b/apps/studio/data/database-columns/database-column-update-mutation.ts index 01b80d363eb..17ba65de6a5 100644 --- a/apps/studio/data/database-columns/database-column-update-mutation.ts +++ b/apps/studio/data/database-columns/database-column-update-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type UpdateColumnBody = components['schemas']['UpdateColumnBody'] diff --git a/apps/studio/data/database-extensions/database-extension-disable-mutation.ts b/apps/studio/data/database-extensions/database-extension-disable-mutation.ts index 93e0740c124..a1e3d029136 100644 --- a/apps/studio/data/database-extensions/database-extension-disable-mutation.ts +++ b/apps/studio/data/database-extensions/database-extension-disable-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseExtensionsKeys } from './keys' export type DatabaseExtensionDisableVariables = { diff --git a/apps/studio/data/database-extensions/database-extension-enable-mutation.ts b/apps/studio/data/database-extensions/database-extension-enable-mutation.ts index 855426a78bc..4f88ed07992 100644 --- a/apps/studio/data/database-extensions/database-extension-enable-mutation.ts +++ b/apps/studio/data/database-extensions/database-extension-enable-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseExtensionsKeys } from './keys' import { executeSql } from 'data/sql/execute-sql-query' diff --git a/apps/studio/data/database-extensions/database-extensions-query.ts b/apps/studio/data/database-extensions/database-extensions-query.ts index 47b2086eb42..2d57aecf21d 100644 --- a/apps/studio/data/database-extensions/database-extensions-query.ts +++ b/apps/studio/data/database-extensions/database-extensions-query.ts @@ -1,6 +1,6 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseExtensionsKeys } from './keys' export type DatabaseExtensionsVariables = { diff --git a/apps/studio/data/database-functions/database-functions-create-mutation.ts b/apps/studio/data/database-functions/database-functions-create-mutation.ts index 0e75b1b1101..b43c65ea3ef 100644 --- a/apps/studio/data/database-functions/database-functions-create-mutation.ts +++ b/apps/studio/data/database-functions/database-functions-create-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseFunctionsKeys } from './keys' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' export type DatabaseFunctionCreateVariables = { projectRef: string diff --git a/apps/studio/data/database-functions/database-functions-delete-mutation.ts b/apps/studio/data/database-functions/database-functions-delete-mutation.ts index ff125580ba8..1b6a6c3191e 100644 --- a/apps/studio/data/database-functions/database-functions-delete-mutation.ts +++ b/apps/studio/data/database-functions/database-functions-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseFunctionsKeys } from './keys' export type DatabaseFunctionDeleteVariables = { diff --git a/apps/studio/data/database-functions/database-functions-query.ts b/apps/studio/data/database-functions/database-functions-query.ts index 4f2af0855ed..4e42d9a43c1 100644 --- a/apps/studio/data/database-functions/database-functions-query.ts +++ b/apps/studio/data/database-functions/database-functions-query.ts @@ -1,8 +1,8 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseFunctionsKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' export type DatabaseFunctionsVariables = { projectRef?: string diff --git a/apps/studio/data/database-functions/database-functions-update-mutation.ts b/apps/studio/data/database-functions/database-functions-update-mutation.ts index ccda983833e..0010303742c 100644 --- a/apps/studio/data/database-functions/database-functions-update-mutation.ts +++ b/apps/studio/data/database-functions/database-functions-update-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseFunctionsKeys } from './keys' export type DatabaseFunctionUpdateVariables = { diff --git a/apps/studio/data/database-policies/database-policies-query.ts b/apps/studio/data/database-policies/database-policies-query.ts index 7245e5af1d1..4dcc3618de8 100644 --- a/apps/studio/data/database-policies/database-policies-query.ts +++ b/apps/studio/data/database-policies/database-policies-query.ts @@ -1,7 +1,7 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databasePoliciesKeys } from './keys' export type DatabasePoliciesVariables = { diff --git a/apps/studio/data/database-policies/database-policy-create-mutation.ts b/apps/studio/data/database-policies/database-policy-create-mutation.ts index c0eb3a3978f..eb23a4e6117 100644 --- a/apps/studio/data/database-policies/database-policy-create-mutation.ts +++ b/apps/studio/data/database-policies/database-policy-create-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databasePoliciesKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' type CreatePolicyBody = components['schemas']['CreatePolicyBody'] diff --git a/apps/studio/data/database-policies/database-policy-delete-mutation.ts b/apps/studio/data/database-policies/database-policy-delete-mutation.ts index e7de0668589..d312458f630 100644 --- a/apps/studio/data/database-policies/database-policy-delete-mutation.ts +++ b/apps/studio/data/database-policies/database-policy-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databasePoliciesKeys } from './keys' export type DatabasePolicyDeleteVariables = { diff --git a/apps/studio/data/database-policies/database-policy-update-mutation.ts b/apps/studio/data/database-policies/database-policy-update-mutation.ts index 9640784b8a9..6accc7fdc9d 100644 --- a/apps/studio/data/database-policies/database-policy-update-mutation.ts +++ b/apps/studio/data/database-policies/database-policy-update-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databasePoliciesKeys } from './keys' export type DatabasePolicyUpdateVariables = { diff --git a/apps/studio/data/database-publications/database-publications-create-mutation.ts b/apps/studio/data/database-publications/database-publications-create-mutation.ts index 79545fbf589..2945ce701e0 100644 --- a/apps/studio/data/database-publications/database-publications-create-mutation.ts +++ b/apps/studio/data/database-publications/database-publications-create-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databasePublicationsKeys } from './keys' export type DatabasePublicationCreateVariables = { diff --git a/apps/studio/data/database-publications/database-publications-query.ts b/apps/studio/data/database-publications/database-publications-query.ts index 4c4055703f1..72e376d8604 100644 --- a/apps/studio/data/database-publications/database-publications-query.ts +++ b/apps/studio/data/database-publications/database-publications-query.ts @@ -1,6 +1,6 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databasePublicationsKeys } from './keys' export type DatabasePublicationsVariables = { diff --git a/apps/studio/data/database-publications/database-publications-update-mutation.ts b/apps/studio/data/database-publications/database-publications-update-mutation.ts index 990f15adf85..42f98b61e30 100644 --- a/apps/studio/data/database-publications/database-publications-update-mutation.ts +++ b/apps/studio/data/database-publications/database-publications-update-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databasePublicationsKeys } from './keys' export type DatabasePublicationUpdateVariables = { diff --git a/apps/studio/data/database-roles/database-role-create-mutation.ts b/apps/studio/data/database-roles/database-role-create-mutation.ts index 1d359a7407d..ecaaa44fa47 100644 --- a/apps/studio/data/database-roles/database-role-create-mutation.ts +++ b/apps/studio/data/database-roles/database-role-create-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseRolesKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' type CreateRoleBody = components['schemas']['CreateRoleBody'] diff --git a/apps/studio/data/database-roles/database-role-delete-mutation.ts b/apps/studio/data/database-roles/database-role-delete-mutation.ts index c735da3e9bd..ac0569614ab 100644 --- a/apps/studio/data/database-roles/database-role-delete-mutation.ts +++ b/apps/studio/data/database-roles/database-role-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseRolesKeys } from './keys' export type DatabaseRoleDeleteVariables = { diff --git a/apps/studio/data/database-roles/database-role-update-mutation.ts b/apps/studio/data/database-roles/database-role-update-mutation.ts index f55623e43a8..c8876fb55e7 100644 --- a/apps/studio/data/database-roles/database-role-update-mutation.ts +++ b/apps/studio/data/database-roles/database-role-update-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseRolesKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' type UpdateRoleBody = components['schemas']['UpdateRoleBody'] diff --git a/apps/studio/data/database-roles/database-roles-query.ts b/apps/studio/data/database-roles/database-roles-query.ts index 4c276154d39..fc107b656a2 100644 --- a/apps/studio/data/database-roles/database-roles-query.ts +++ b/apps/studio/data/database-roles/database-roles-query.ts @@ -1,8 +1,8 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' -import { PostgresRole } from '@supabase/postgres-meta' +import type { PostgresRole } from '@supabase/postgres-meta' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseRolesKeys } from './keys' export type DatabaseRolesVariables = { diff --git a/apps/studio/data/database-triggers/database-trigger-create-mutation.ts b/apps/studio/data/database-triggers/database-trigger-create-mutation.ts index d20ade72ef7..4b9a819fa26 100644 --- a/apps/studio/data/database-triggers/database-trigger-create-mutation.ts +++ b/apps/studio/data/database-triggers/database-trigger-create-mutation.ts @@ -1,10 +1,10 @@ -import { PostgresTrigger } from '@supabase/postgres-meta' +import type { PostgresTrigger } from '@supabase/postgres-meta' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseTriggerKeys } from './keys' export type DatabaseTriggerCreateVariables = { diff --git a/apps/studio/data/database-triggers/database-trigger-delete-mutation.ts b/apps/studio/data/database-triggers/database-trigger-delete-mutation.ts index e8d1fce75b5..275b4ed2a66 100644 --- a/apps/studio/data/database-triggers/database-trigger-delete-mutation.ts +++ b/apps/studio/data/database-triggers/database-trigger-delete-mutation.ts @@ -1,11 +1,11 @@ import { toast } from 'react-hot-toast' -import { PostgresTrigger } from '@supabase/postgres-meta' +import type { PostgresTrigger } from '@supabase/postgres-meta' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { databaseTriggerKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type DatabaseTriggerDeleteVariables = { id: number diff --git a/apps/studio/data/database-triggers/database-trigger-update-mutation.ts b/apps/studio/data/database-triggers/database-trigger-update-mutation.ts index 7e29c2bf500..77ae421992d 100644 --- a/apps/studio/data/database-triggers/database-trigger-update-mutation.ts +++ b/apps/studio/data/database-triggers/database-trigger-update-mutation.ts @@ -1,10 +1,10 @@ -import { PostgresTrigger } from '@supabase/postgres-meta' +import type { PostgresTrigger } from '@supabase/postgres-meta' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseTriggerKeys } from './keys' export type DatabaseTriggerUpdateVariables = { diff --git a/apps/studio/data/database-triggers/database-trigger-update-transaction-mutation.ts b/apps/studio/data/database-triggers/database-trigger-update-transaction-mutation.ts index 3f4c1536244..57a5991a455 100644 --- a/apps/studio/data/database-triggers/database-trigger-update-transaction-mutation.ts +++ b/apps/studio/data/database-triggers/database-trigger-update-transaction-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { executeSql } from 'data/sql/execute-sql-query' import { quoteLiteral } from 'lib/pg-format' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseTriggerKeys } from './keys' // [Joshen] Writing this query within FE as the PATCH endpoint from pg-meta only supports updating diff --git a/apps/studio/data/database-triggers/database-triggers-query.ts b/apps/studio/data/database-triggers/database-triggers-query.ts index 8c3202045f2..46fc96cfc2b 100644 --- a/apps/studio/data/database-triggers/database-triggers-query.ts +++ b/apps/studio/data/database-triggers/database-triggers-query.ts @@ -1,9 +1,9 @@ -import { PostgresTrigger } from '@supabase/postgres-meta' +import type { PostgresTrigger } from '@supabase/postgres-meta' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { databaseTriggerKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type DatabaseTriggersVariables = { projectRef?: string diff --git a/apps/studio/data/database/backup-download-mutation.ts b/apps/studio/data/database/backup-download-mutation.ts index 7079cbd6d2b..8c9d4a832b1 100644 --- a/apps/studio/data/database/backup-download-mutation.ts +++ b/apps/studio/data/database/backup-download-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { Backup } from './backup-restore-mutation' export type BackupDownloadVariables = { diff --git a/apps/studio/data/database/backup-restore-mutation.ts b/apps/studio/data/database/backup-restore-mutation.ts index e8f27f9e628..8fb0ff7fb7f 100644 --- a/apps/studio/data/database/backup-restore-mutation.ts +++ b/apps/studio/data/database/backup-restore-mutation.ts @@ -2,8 +2,8 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' -import { components } from 'data/api' +import type { ResponseError } from 'types' +import type { components } from 'data/api' export type BackupRestoreVariables = { ref: string diff --git a/apps/studio/data/database/backups-query.ts b/apps/studio/data/database/backups-query.ts index 95908321674..d2c38ae3555 100644 --- a/apps/studio/data/database/backups-query.ts +++ b/apps/studio/data/database/backups-query.ts @@ -1,9 +1,9 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' export type BackupsVariables = { projectRef?: string diff --git a/apps/studio/data/database/database-password-reset-mutation.ts b/apps/studio/data/database/database-password-reset-mutation.ts index fef0e3c6fb3..832fe483098 100644 --- a/apps/studio/data/database/database-password-reset-mutation.ts +++ b/apps/studio/data/database/database-password-reset-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' import { projectKeys } from 'data/projects/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type DatabasePasswordResetVariables = { ref: string diff --git a/apps/studio/data/database/hooks-enable-mutation.ts b/apps/studio/data/database/hooks-enable-mutation.ts index 6ca08f5090b..504e891968e 100644 --- a/apps/studio/data/database/hooks-enable-mutation.ts +++ b/apps/studio/data/database/hooks-enable-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseKeys } from './keys' export type HooksEnableVariables = { diff --git a/apps/studio/data/database/indexes-query.ts b/apps/studio/data/database/indexes-query.ts index 8ccd8971234..e45702479cc 100644 --- a/apps/studio/data/database/indexes-query.ts +++ b/apps/studio/data/database/indexes-query.ts @@ -1,6 +1,6 @@ import { UseQueryOptions } from '@tanstack/react-query' import { ExecuteSqlData, useExecuteSqlQuery } from '../sql/execute-sql-query' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' // [Joshen] Future refactor to move to pg-meta once available diff --git a/apps/studio/data/database/pitr-restore-mutation.ts b/apps/studio/data/database/pitr-restore-mutation.ts index b94c070e0ad..8089acb85d9 100644 --- a/apps/studio/data/database/pitr-restore-mutation.ts +++ b/apps/studio/data/database/pitr-restore-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type PitrRestoreVariables = { ref: string diff --git a/apps/studio/data/database/pooling-configuration-query.ts b/apps/studio/data/database/pooling-configuration-query.ts index 7e03ccb3cd5..006bcde9676 100644 --- a/apps/studio/data/database/pooling-configuration-query.ts +++ b/apps/studio/data/database/pooling-configuration-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseKeys } from './keys' export type PoolingConfigurationVariables = { diff --git a/apps/studio/data/database/pooling-configuration-update-mutation.ts b/apps/studio/data/database/pooling-configuration-update-mutation.ts index aa0bb1aceb9..96bcc57afff 100644 --- a/apps/studio/data/database/pooling-configuration-update-mutation.ts +++ b/apps/studio/data/database/pooling-configuration-update-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseKeys } from './keys' export type PoolingConfigurationUpdateVariables = { diff --git a/apps/studio/data/database/schema-create-mutation.ts b/apps/studio/data/database/schema-create-mutation.ts index a5519a6e9aa..4bdc1aca4f8 100644 --- a/apps/studio/data/database/schema-create-mutation.ts +++ b/apps/studio/data/database/schema-create-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseKeys } from './keys' export type SchemaCreateVariables = { diff --git a/apps/studio/data/database/schemas-query.ts b/apps/studio/data/database/schemas-query.ts index 926d19a13a1..4fdbf7a1d51 100644 --- a/apps/studio/data/database/schemas-query.ts +++ b/apps/studio/data/database/schemas-query.ts @@ -1,8 +1,8 @@ import { QueryClient, useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { databaseKeys } from './keys' export type SchemasVariables = { diff --git a/apps/studio/data/documents/document-query.ts b/apps/studio/data/documents/document-query.ts index 708db983b41..a9a674e61fc 100644 --- a/apps/studio/data/documents/document-query.ts +++ b/apps/studio/data/documents/document-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { documentKeys } from './keys' export type DocType = 'standard-security-questionnaire' | 'soc2-type-2-report' diff --git a/apps/studio/data/edge-functions/edge-functions-delete-mutation.ts b/apps/studio/data/edge-functions/edge-functions-delete-mutation.ts index c1ec1a32526..eb5c2cb5d49 100644 --- a/apps/studio/data/edge-functions/edge-functions-delete-mutation.ts +++ b/apps/studio/data/edge-functions/edge-functions-delete-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_ADMIN_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { edgeFunctionsKeys } from './keys' export type EdgeFunctionsDeleteVariables = { diff --git a/apps/studio/data/edge-functions/edge-functions-query.ts b/apps/studio/data/edge-functions/edge-functions-query.ts index 2c34d320c9d..6792b10fe92 100644 --- a/apps/studio/data/edge-functions/edge-functions-query.ts +++ b/apps/studio/data/edge-functions/edge-functions-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_ADMIN_URL, IS_PLATFORM } from 'lib/constants' import { edgeFunctionsKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type EdgeFunctionsVariables = { projectRef?: string } diff --git a/apps/studio/data/edge-functions/edge-functions-update-mutation.ts b/apps/studio/data/edge-functions/edge-functions-update-mutation.ts index a77f9d0e3d1..2bd6c09e0b6 100644 --- a/apps/studio/data/edge-functions/edge-functions-update-mutation.ts +++ b/apps/studio/data/edge-functions/edge-functions-update-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_ADMIN_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { edgeFunctionsKeys } from './keys' export type EdgeFunctionsUpdateVariables = { diff --git a/apps/studio/data/entity-types/entity-types-infinite-query.ts b/apps/studio/data/entity-types/entity-types-infinite-query.ts index 8e911e2af3d..f24f0bf96d1 100644 --- a/apps/studio/data/entity-types/entity-types-infinite-query.ts +++ b/apps/studio/data/entity-types/entity-types-infinite-query.ts @@ -1,6 +1,6 @@ import { useInfiniteQuery, UseInfiniteQueryOptions } from '@tanstack/react-query' import { executeSql, ExecuteSqlVariables } from 'data/sql/execute-sql-query' -import { Entity } from './entity-type-query' +import type { Entity } from './entity-type-query' import { entityTypeKeys } from './keys' export type EntityTypesVariables = { diff --git a/apps/studio/data/enumerated-types/enumerated-type-create-mutation.ts b/apps/studio/data/enumerated-types/enumerated-type-create-mutation.ts index 29e53e4c136..37fa2323d92 100644 --- a/apps/studio/data/enumerated-types/enumerated-type-create-mutation.ts +++ b/apps/studio/data/enumerated-types/enumerated-type-create-mutation.ts @@ -1,7 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { enumeratedTypesKeys } from './keys' import { executeSql } from 'data/sql/execute-sql-query' import { wrapWithTransaction } from 'data/sql/utils/transaction' diff --git a/apps/studio/data/enumerated-types/enumerated-type-delete-mutation.ts b/apps/studio/data/enumerated-types/enumerated-type-delete-mutation.ts index 7461f6c1e5d..a4cf539aec5 100644 --- a/apps/studio/data/enumerated-types/enumerated-type-delete-mutation.ts +++ b/apps/studio/data/enumerated-types/enumerated-type-delete-mutation.ts @@ -1,7 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { enumeratedTypesKeys } from './keys' import { executeSql } from 'data/sql/execute-sql-query' diff --git a/apps/studio/data/enumerated-types/enumerated-type-update-mutation.ts b/apps/studio/data/enumerated-types/enumerated-type-update-mutation.ts index 6048694212d..037314bcb6e 100644 --- a/apps/studio/data/enumerated-types/enumerated-type-update-mutation.ts +++ b/apps/studio/data/enumerated-types/enumerated-type-update-mutation.ts @@ -1,7 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { enumeratedTypesKeys } from './keys' import { executeSql } from 'data/sql/execute-sql-query' import { wrapWithTransaction } from 'data/sql/utils/transaction' diff --git a/apps/studio/data/enumerated-types/enumerated-types-query.ts b/apps/studio/data/enumerated-types/enumerated-types-query.ts index 942ee05ff1a..f8b9a7cf7ac 100644 --- a/apps/studio/data/enumerated-types/enumerated-types-query.ts +++ b/apps/studio/data/enumerated-types/enumerated-types-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { enumeratedTypesKeys } from './keys' export type EnumeratedTypesVariables = { diff --git a/apps/studio/data/fdw/fdw-create-mutation.ts b/apps/studio/data/fdw/fdw-create-mutation.ts index 046e36754e5..36e936df1a6 100644 --- a/apps/studio/data/fdw/fdw-create-mutation.ts +++ b/apps/studio/data/fdw/fdw-create-mutation.ts @@ -10,7 +10,7 @@ import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' import { wrapWithTransaction } from 'data/sql/utils/transaction' import { vaultSecretsKeys } from 'data/vault/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { entityTypeKeys } from 'data/entity-types/keys' export type FDWCreateVariables = { diff --git a/apps/studio/data/fdw/fdw-delete-mutation.ts b/apps/studio/data/fdw/fdw-delete-mutation.ts index cd495398a22..9c121f9aa4e 100644 --- a/apps/studio/data/fdw/fdw-delete-mutation.ts +++ b/apps/studio/data/fdw/fdw-delete-mutation.ts @@ -1,13 +1,13 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { WrapperMeta } from 'components/interfaces/Database/Wrappers/Wrappers.types' +import type { WrapperMeta } from 'components/interfaces/Database/Wrappers/Wrappers.types' import { pgSodiumKeys } from 'data/pg-sodium-keys/keys' import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' import { wrapWithTransaction } from 'data/sql/utils/transaction' import { vaultSecretsKeys } from 'data/vault/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { FDW } from './fdws-query' import { entityTypeKeys } from 'data/entity-types/keys' diff --git a/apps/studio/data/fdw/fdw-update-mutation.ts b/apps/studio/data/fdw/fdw-update-mutation.ts index fd808471af3..9268d6b7dc7 100644 --- a/apps/studio/data/fdw/fdw-update-mutation.ts +++ b/apps/studio/data/fdw/fdw-update-mutation.ts @@ -1,13 +1,13 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { WrapperMeta } from 'components/interfaces/Database/Wrappers/Wrappers.types' +import type { WrapperMeta } from 'components/interfaces/Database/Wrappers/Wrappers.types' import { pgSodiumKeys } from 'data/pg-sodium-keys/keys' import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' import { wrapWithTransaction } from 'data/sql/utils/transaction' import { vaultSecretsKeys } from 'data/vault/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { getCreateFDWSql } from './fdw-create-mutation' import { getDeleteFDWSql } from './fdw-delete-mutation' import { FDW } from './fdws-query' diff --git a/apps/studio/data/feedback/exit-survey-send.ts b/apps/studio/data/feedback/exit-survey-send.ts index d95a8422356..d710e69d9e0 100644 --- a/apps/studio/data/feedback/exit-survey-send.ts +++ b/apps/studio/data/feedback/exit-survey-send.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SendDowngradeFeedbackVariables = { projectRef?: string diff --git a/apps/studio/data/feedback/feedback-send.ts b/apps/studio/data/feedback/feedback-send.ts index 969919c3979..6bd5b084e49 100644 --- a/apps/studio/data/feedback/feedback-send.ts +++ b/apps/studio/data/feedback/feedback-send.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import toast from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SendFeedbackVariables = { message: string diff --git a/apps/studio/data/feedback/support-ticket-send.ts b/apps/studio/data/feedback/support-ticket-send.ts index 334a5faeba8..aa7ad8f6450 100644 --- a/apps/studio/data/feedback/support-ticket-send.ts +++ b/apps/studio/data/feedback/support-ticket-send.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type sendSupportTicketVariables = { subject: string diff --git a/apps/studio/data/fetchers.ts b/apps/studio/data/fetchers.ts index 0799e1a1dcb..88df2a923bb 100644 --- a/apps/studio/data/fetchers.ts +++ b/apps/studio/data/fetchers.ts @@ -2,8 +2,8 @@ import { API_URL, IS_PLATFORM } from 'lib/constants' import { getAccessToken } from 'lib/gotrue' import { uuidv4 } from 'lib/helpers' import createClient from 'openapi-fetch' -import { paths } from './api' // generated from openapi-typescript -import { ResponseError } from 'types' +import type { paths } from './api' // generated from openapi-typescript +import type { ResponseError } from 'types' const DEFAULT_HEADERS = { 'Content-Type': 'application/json', diff --git a/apps/studio/data/foreign-tables/foreign-table-query.ts b/apps/studio/data/foreign-tables/foreign-table-query.ts index 01ac0317ebf..d6e3af3748f 100644 --- a/apps/studio/data/foreign-tables/foreign-table-query.ts +++ b/apps/studio/data/foreign-tables/foreign-table-query.ts @@ -1,4 +1,4 @@ -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' diff --git a/apps/studio/data/integrations/github-authorization-create-mutation.ts b/apps/studio/data/integrations/github-authorization-create-mutation.ts index b7c9d56f2d0..53e73b0f524 100644 --- a/apps/studio/data/integrations/github-authorization-create-mutation.ts +++ b/apps/studio/data/integrations/github-authorization-create-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type GitHubAuthorizationCreateVariables = { code: string diff --git a/apps/studio/data/integrations/github-authorization-query.ts b/apps/studio/data/integrations/github-authorization-query.ts index d2be21a104e..03b1846330d 100644 --- a/apps/studio/data/integrations/github-authorization-query.ts +++ b/apps/studio/data/integrations/github-authorization-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' // FIXME(kamil): Do not retry, a single check is fine. diff --git a/apps/studio/data/integrations/github-branch-check-query.ts b/apps/studio/data/integrations/github-branch-check-query.ts index 0c82002e71b..9ac754fe668 100644 --- a/apps/studio/data/integrations/github-branch-check-query.ts +++ b/apps/studio/data/integrations/github-branch-check-query.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type GithubBranchVariables = { connectionId: number diff --git a/apps/studio/data/integrations/github-branches-query.ts b/apps/studio/data/integrations/github-branches-query.ts index 94260616aa9..9b621eab61d 100644 --- a/apps/studio/data/integrations/github-branches-query.ts +++ b/apps/studio/data/integrations/github-branches-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { integrationKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type GitHubBranchesVariables = { connectionId?: number diff --git a/apps/studio/data/integrations/github-connection-create-mutation.ts b/apps/studio/data/integrations/github-connection-create-mutation.ts index 62a494ed2e1..569827c5f5e 100644 --- a/apps/studio/data/integrations/github-connection-create-mutation.ts +++ b/apps/studio/data/integrations/github-connection-create-mutation.ts @@ -2,8 +2,8 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' -import { GitHubConnectionCreateVariables } from './integrations.types' +import type { ResponseError } from 'types' +import type { GitHubConnectionCreateVariables } from './integrations.types' import { integrationKeys } from './keys' export async function createGitHubConnection({ connection }: GitHubConnectionCreateVariables) { diff --git a/apps/studio/data/integrations/github-connection-delete-mutation.ts b/apps/studio/data/integrations/github-connection-delete-mutation.ts index d6fc6067e10..85c59938212 100644 --- a/apps/studio/data/integrations/github-connection-delete-mutation.ts +++ b/apps/studio/data/integrations/github-connection-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' type DeleteVariables = { diff --git a/apps/studio/data/integrations/github-connection-update-mutation.ts b/apps/studio/data/integrations/github-connection-update-mutation.ts index 3af0320f8ea..9424cdd73c4 100644 --- a/apps/studio/data/integrations/github-connection-update-mutation.ts +++ b/apps/studio/data/integrations/github-connection-update-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' type UpdateVariables = { diff --git a/apps/studio/data/integrations/github-connections-query.ts b/apps/studio/data/integrations/github-connections-query.ts index ef491049153..638445d0297 100644 --- a/apps/studio/data/integrations/github-connections-query.ts +++ b/apps/studio/data/integrations/github-connections-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' export type GitHubConnectionsVariables = { diff --git a/apps/studio/data/integrations/github-pull-requests-query.ts b/apps/studio/data/integrations/github-pull-requests-query.ts index 76345211bdc..6adfbeaa95d 100644 --- a/apps/studio/data/integrations/github-pull-requests-query.ts +++ b/apps/studio/data/integrations/github-pull-requests-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { integrationKeys } from './keys' -import { ResponseError } from 'types' -import { components } from 'data/api' +import type { ResponseError } from 'types' +import type { components } from 'data/api' export type GitHubPullRequestsVariables = { connectionId?: number diff --git a/apps/studio/data/integrations/github-repositories-query.ts b/apps/studio/data/integrations/github-repositories-query.ts index 07fc7ad3c9b..d03f7d06448 100644 --- a/apps/studio/data/integrations/github-repositories-query.ts +++ b/apps/studio/data/integrations/github-repositories-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' export async function getGitHubRepositories(signal?: AbortSignal) { diff --git a/apps/studio/data/integrations/integrations-query-org-only.ts b/apps/studio/data/integrations/integrations-query-org-only.ts index 926897a5dba..93872903086 100644 --- a/apps/studio/data/integrations/integrations-query-org-only.ts +++ b/apps/studio/data/integrations/integrations-query-org-only.ts @@ -2,8 +2,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' -import { Integration, IntegrationsVariables } from './integrations.types' +import type { ResponseError } from 'types' +import type { Integration, IntegrationsVariables } from './integrations.types' import { integrationKeys } from './keys' export type IntegrationsResponse = Integration[] diff --git a/apps/studio/data/integrations/integrations-query.ts b/apps/studio/data/integrations/integrations-query.ts index 9ec6b5a0353..cae79239865 100644 --- a/apps/studio/data/integrations/integrations-query.ts +++ b/apps/studio/data/integrations/integrations-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' export async function getIntegrations(signal?: AbortSignal) { diff --git a/apps/studio/data/integrations/integrations-vercel-connection-sync-envs-mutation.ts b/apps/studio/data/integrations/integrations-vercel-connection-sync-envs-mutation.ts index 78240f76f43..ebd690f9908 100644 --- a/apps/studio/data/integrations/integrations-vercel-connection-sync-envs-mutation.ts +++ b/apps/studio/data/integrations/integrations-vercel-connection-sync-envs-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type IntegrationsVercelConnectionSyncEnvsVariables = { connectionId: string diff --git a/apps/studio/data/integrations/integrations-vercel-connections-create-mutation.ts b/apps/studio/data/integrations/integrations-vercel-connections-create-mutation.ts index 7a4ab1b9bca..21f9050ddb7 100644 --- a/apps/studio/data/integrations/integrations-vercel-connections-create-mutation.ts +++ b/apps/studio/data/integrations/integrations-vercel-connections-create-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' -import { IntegrationConnectionsCreateVariables } from './integrations.types' +import type { IntegrationConnectionsCreateVariables } from './integrations.types' import { useIntegrationInstallationSnapshot } from 'state/integration-installation' export async function createIntegrationVercelConnections({ diff --git a/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts b/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts index 9a8de1036ba..c7a5d1b1ec0 100644 --- a/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts +++ b/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts @@ -1,7 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { delete_, isResponseOk } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError, UserContent } from 'types' +import type { ResponseError, UserContent } from 'types' import { integrationKeys } from './keys' import { toast } from 'react-hot-toast' diff --git a/apps/studio/data/integrations/integrations-vercel-projects-query.ts b/apps/studio/data/integrations/integrations-vercel-projects-query.ts index 5f21333cbc7..a7568f0539a 100644 --- a/apps/studio/data/integrations/integrations-vercel-projects-query.ts +++ b/apps/studio/data/integrations/integrations-vercel-projects-query.ts @@ -1,7 +1,7 @@ import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { useCallback } from 'react' -import { VercelFramework } from './integrations.types' +import type { VercelFramework } from './integrations.types' import { integrationKeys } from './keys' export type VercelProjectsVariables = { diff --git a/apps/studio/data/integrations/integrations.types.ts b/apps/studio/data/integrations/integrations.types.ts index efd87d3f4f6..844b531a735 100644 --- a/apps/studio/data/integrations/integrations.types.ts +++ b/apps/studio/data/integrations/integrations.types.ts @@ -1,4 +1,4 @@ -import { components } from 'data/api' +import type { components } from 'data/api' export type VercelFramework = | ( diff --git a/apps/studio/data/integrations/vercel-connection-update-mutate.ts b/apps/studio/data/integrations/vercel-connection-update-mutate.ts index 0f48971a7df..89194cf0288 100644 --- a/apps/studio/data/integrations/vercel-connection-update-mutate.ts +++ b/apps/studio/data/integrations/vercel-connection-update-mutate.ts @@ -2,8 +2,8 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' -import { UpdateConnectionPayload } from './integrations.types' +import type { ResponseError } from 'types' +import type { UpdateConnectionPayload } from './integrations.types' import { integrationKeys } from './keys' export async function updateVercelConnection({ diff --git a/apps/studio/data/integrations/vercel-integration-create-mutation.ts b/apps/studio/data/integrations/vercel-integration-create-mutation.ts index 15c7b7966e9..6798d5b4a24 100644 --- a/apps/studio/data/integrations/vercel-integration-create-mutation.ts +++ b/apps/studio/data/integrations/vercel-integration-create-mutation.ts @@ -3,7 +3,7 @@ import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { integrationKeys } from './keys' import { toast } from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type VercelIntegrationCreateVariables = { code: string diff --git a/apps/studio/data/invoices/invoice-query.ts b/apps/studio/data/invoices/invoice-query.ts index e1ff6e23fd5..3ad78d6d1db 100644 --- a/apps/studio/data/invoices/invoice-query.ts +++ b/apps/studio/data/invoices/invoice-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { invoicesKeys } from './keys' export type InvoiceVariables = { diff --git a/apps/studio/data/invoices/invoices-count-query.ts b/apps/studio/data/invoices/invoices-count-query.ts index 241ff0c5341..f301925b87d 100644 --- a/apps/studio/data/invoices/invoices-count-query.ts +++ b/apps/studio/data/invoices/invoices-count-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { head } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { invoicesKeys } from './keys' export type InvoicesCountVariables = { diff --git a/apps/studio/data/invoices/invoices-overdue-query.ts b/apps/studio/data/invoices/invoices-overdue-query.ts index a34b563e09f..a5597c76e1d 100644 --- a/apps/studio/data/invoices/invoices-overdue-query.ts +++ b/apps/studio/data/invoices/invoices-overdue-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { invoicesKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' export type OverdueInvoicesResponse = components['schemas']['OverdueInvoiceCount'] diff --git a/apps/studio/data/invoices/invoices-query.ts b/apps/studio/data/invoices/invoices-query.ts index 617fd32b6a3..f6248b0827b 100644 --- a/apps/studio/data/invoices/invoices-query.ts +++ b/apps/studio/data/invoices/invoices-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { invoicesKeys } from './keys' export type InvoicesVariables = { diff --git a/apps/studio/data/invoices/org-invoice-upcoming-query.ts b/apps/studio/data/invoices/org-invoice-upcoming-query.ts index 8d39a183fc3..cc6533fbcd1 100644 --- a/apps/studio/data/invoices/org-invoice-upcoming-query.ts +++ b/apps/studio/data/invoices/org-invoice-upcoming-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { invoicesKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { PricingMetric } from 'data/analytics/org-daily-stats-query' export type UpcomingInvoiceVariables = { diff --git a/apps/studio/data/materialized-views/materialized-view-query.ts b/apps/studio/data/materialized-views/materialized-view-query.ts index b718d8dbe83..0b714667b9b 100644 --- a/apps/studio/data/materialized-views/materialized-view-query.ts +++ b/apps/studio/data/materialized-views/materialized-view-query.ts @@ -1,4 +1,4 @@ -import { PostgresMaterializedView } from '@supabase/postgres-meta' +import type { PostgresMaterializedView } from '@supabase/postgres-meta' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' diff --git a/apps/studio/data/misc/get-default-region-query.ts b/apps/studio/data/misc/get-default-region-query.ts index fb5c623eaf2..31b0fbd20d5 100644 --- a/apps/studio/data/misc/get-default-region-query.ts +++ b/apps/studio/data/misc/get-default-region-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { miscKeys } from './keys' import { COUNTRY_LAT_LON } from 'components/interfaces/ProjectCreation/ProjectCreation.constants' import { getDistanceLatLonKM } from 'lib/helpers' diff --git a/apps/studio/data/misc/reset-password-mutation.ts b/apps/studio/data/misc/reset-password-mutation.ts index c9f1e6cbb12..f4b4de7e327 100644 --- a/apps/studio/data/misc/reset-password-mutation.ts +++ b/apps/studio/data/misc/reset-password-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ResetPasswordVariables = { email: string diff --git a/apps/studio/data/misc/signup-mutation.ts b/apps/studio/data/misc/signup-mutation.ts index d056c3cbc21..4713a950cdb 100644 --- a/apps/studio/data/misc/signup-mutation.ts +++ b/apps/studio/data/misc/signup-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SignUpVariables = { email: string diff --git a/apps/studio/data/network-restrictions/network-retrictions-apply-mutation.ts b/apps/studio/data/network-restrictions/network-retrictions-apply-mutation.ts index 455594126ad..52b93336630 100644 --- a/apps/studio/data/network-restrictions/network-retrictions-apply-mutation.ts +++ b/apps/studio/data/network-restrictions/network-retrictions-apply-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { networkRestrictionKeys } from './keys' export type NetworkRestrictionsApplyVariables = { diff --git a/apps/studio/data/notifications/notifications-dismiss-mutation.ts b/apps/studio/data/notifications/notifications-dismiss-mutation.ts index 81f5e2c8b61..f7d4c9c7349 100644 --- a/apps/studio/data/notifications/notifications-dismiss-mutation.ts +++ b/apps/studio/data/notifications/notifications-dismiss-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { notificationKeys } from './keys' export type NotificationsDismissVariables = { diff --git a/apps/studio/data/notifications/notifications-query.ts b/apps/studio/data/notifications/notifications-query.ts index 031ba399f68..052cd4ae473 100644 --- a/apps/studio/data/notifications/notifications-query.ts +++ b/apps/studio/data/notifications/notifications-query.ts @@ -1,4 +1,4 @@ -import { Notification } from '@supabase/shared-types/out/notifications' +import type { Notification } from '@supabase/shared-types/out/notifications' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' diff --git a/apps/studio/data/notifications/notifications-update-mutation.ts b/apps/studio/data/notifications/notifications-update-mutation.ts index 88fa96b24c1..e601f8ba38c 100644 --- a/apps/studio/data/notifications/notifications-update-mutation.ts +++ b/apps/studio/data/notifications/notifications-update-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { notificationKeys } from './keys' export type NotificationsUpdateVariables = { diff --git a/apps/studio/data/notifications/notifications-v2-archive-all-mutation.ts b/apps/studio/data/notifications/notifications-v2-archive-all-mutation.ts index 02d0a507551..a8401911315 100644 --- a/apps/studio/data/notifications/notifications-v2-archive-all-mutation.ts +++ b/apps/studio/data/notifications/notifications-v2-archive-all-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { notificationKeys } from './keys' export async function archiveAllNotifications() { diff --git a/apps/studio/data/notifications/notifications-v2-query.ts b/apps/studio/data/notifications/notifications-v2-query.ts index 9df9b8e5412..669400d4faa 100644 --- a/apps/studio/data/notifications/notifications-v2-query.ts +++ b/apps/studio/data/notifications/notifications-v2-query.ts @@ -1,8 +1,8 @@ import { useInfiniteQuery, UseInfiniteQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { components } from 'data/api' -import { ResponseError } from 'types' +import type { components } from 'data/api' +import type { ResponseError } from 'types' import { notificationKeys } from './keys' const NOTIFICATIONS_PAGE_LIMIT = 10 diff --git a/apps/studio/data/notifications/notifications-v2-summary-query.ts b/apps/studio/data/notifications/notifications-v2-summary-query.ts index 8cf0b4ed091..8204845afb4 100644 --- a/apps/studio/data/notifications/notifications-v2-summary-query.ts +++ b/apps/studio/data/notifications/notifications-v2-summary-query.ts @@ -1,8 +1,8 @@ -import { Notification } from '@supabase/shared-types/out/notifications' +import type { Notification } from '@supabase/shared-types/out/notifications' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { notificationKeys } from './keys' export type NotificationsResponse = Notification[] diff --git a/apps/studio/data/notifications/notifications-v2-update-mutation.ts b/apps/studio/data/notifications/notifications-v2-update-mutation.ts index f8269138cf8..4ed3818a37e 100644 --- a/apps/studio/data/notifications/notifications-v2-update-mutation.ts +++ b/apps/studio/data/notifications/notifications-v2-update-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type NotificationsUpdateVariables = { ids: string[] diff --git a/apps/studio/data/oauth/authorized-app-revoke-mutation.ts b/apps/studio/data/oauth/authorized-app-revoke-mutation.ts index 304b58bbd6d..11fb114586b 100644 --- a/apps/studio/data/oauth/authorized-app-revoke-mutation.ts +++ b/apps/studio/data/oauth/authorized-app-revoke-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' export type AuthorizedAppRevokeVariables = { diff --git a/apps/studio/data/oauth/authorized-apps-query.ts b/apps/studio/data/oauth/authorized-apps-query.ts index b35995693a8..fcf8f11cf0d 100644 --- a/apps/studio/data/oauth/authorized-apps-query.ts +++ b/apps/studio/data/oauth/authorized-apps-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { oauthAppKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type AuthorizedAppsVariables = { slug?: string diff --git a/apps/studio/data/oauth/oauth-app-create-mutation.ts b/apps/studio/data/oauth/oauth-app-create-mutation.ts index ae71bad9e47..d47deb1f7bc 100644 --- a/apps/studio/data/oauth/oauth-app-create-mutation.ts +++ b/apps/studio/data/oauth/oauth-app-create-mutation.ts @@ -1,10 +1,10 @@ -import { OAuthScope } from '@supabase/shared-types/out/constants' +import type { OAuthScope } from '@supabase/shared-types/out/constants' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' export type OAuthAppCreateVariables = { diff --git a/apps/studio/data/oauth/oauth-app-delete-mutation.ts b/apps/studio/data/oauth/oauth-app-delete-mutation.ts index 94d982a7109..471a93f11c8 100644 --- a/apps/studio/data/oauth/oauth-app-delete-mutation.ts +++ b/apps/studio/data/oauth/oauth-app-delete-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' export type OAuthAppDeleteVariables = { diff --git a/apps/studio/data/oauth/oauth-app-update-mutation.ts b/apps/studio/data/oauth/oauth-app-update-mutation.ts index ddd4ac6af18..8b2513bfc0c 100644 --- a/apps/studio/data/oauth/oauth-app-update-mutation.ts +++ b/apps/studio/data/oauth/oauth-app-update-mutation.ts @@ -1,10 +1,10 @@ -import { OAuthScope } from '@supabase/shared-types/out/constants' +import type { OAuthScope } from '@supabase/shared-types/out/constants' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { put } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' export type OAuthAppUpdateVariables = { diff --git a/apps/studio/data/oauth/oauth-apps-query.ts b/apps/studio/data/oauth/oauth-apps-query.ts index 3a30e47d489..63ea17efcd4 100644 --- a/apps/studio/data/oauth/oauth-apps-query.ts +++ b/apps/studio/data/oauth/oauth-apps-query.ts @@ -1,8 +1,8 @@ -import { OAuthScope } from '@supabase/shared-types/out/constants' +import type { OAuthScope } from '@supabase/shared-types/out/constants' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' export type OAuthAppsVariables = { diff --git a/apps/studio/data/open-api/api-spec-query.ts b/apps/studio/data/open-api/api-spec-query.ts index 489746e2b21..bbb362f2f59 100644 --- a/apps/studio/data/open-api/api-spec-query.ts +++ b/apps/studio/data/open-api/api-spec-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { openApiKeys } from './keys' export type OpenAPISpecVariables = { diff --git a/apps/studio/data/organizations/free-project-limit-check-query.ts b/apps/studio/data/organizations/free-project-limit-check-query.ts index bce36e2e6b3..8f7a46f9a90 100644 --- a/apps/studio/data/organizations/free-project-limit-check-query.ts +++ b/apps/studio/data/organizations/free-project-limit-check-query.ts @@ -1,7 +1,6 @@ -import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' +import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { useCallback } from 'react' import { organizationKeys } from './keys' export type MemberWithFreeProjectLimit = { diff --git a/apps/studio/data/organizations/organization-audit-logs-query.ts b/apps/studio/data/organizations/organization-audit-logs-query.ts index 269419e97bd..0c3a63c76a7 100644 --- a/apps/studio/data/organizations/organization-audit-logs-query.ts +++ b/apps/studio/data/organizations/organization-audit-logs-query.ts @@ -3,7 +3,7 @@ import dayjs from 'dayjs' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type AuditLog = { diff --git a/apps/studio/data/organizations/organization-billing-subscription-preview.ts b/apps/studio/data/organizations/organization-billing-subscription-preview.ts index 93d23d6133a..3d2ba7a852b 100644 --- a/apps/studio/data/organizations/organization-billing-subscription-preview.ts +++ b/apps/studio/data/organizations/organization-billing-subscription-preview.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { post } from 'data/fetchers' import { organizationKeys } from './keys' -import { ResponseError } from 'types' -import { SubscriptionTier } from 'data/subscriptions/types' +import type { ResponseError } from 'types' +import type { SubscriptionTier } from 'data/subscriptions/types' export type OrganizationBillingSubscriptionPreviewVariables = { organizationSlug?: string diff --git a/apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts b/apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts index e8525103870..9e171d74c85 100644 --- a/apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts +++ b/apps/studio/data/organizations/organization-by-fly-organization-id-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import toast from 'react-hot-toast' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrganizationByFlyOrgIdVariables = { flyOrganizationId: string diff --git a/apps/studio/data/organizations/organization-create-mutation.ts b/apps/studio/data/organizations/organization-create-mutation.ts index 40966f240ee..daa82c1e998 100644 --- a/apps/studio/data/organizations/organization-create-mutation.ts +++ b/apps/studio/data/organizations/organization-create-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' import { permissionKeys } from 'data/permissions/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationCreateVariables = { diff --git a/apps/studio/data/organizations/organization-customer-profile-query.ts b/apps/studio/data/organizations/organization-customer-profile-query.ts index a5719b52316..63bf11ab89e 100644 --- a/apps/studio/data/organizations/organization-customer-profile-query.ts +++ b/apps/studio/data/organizations/organization-customer-profile-query.ts @@ -1,9 +1,8 @@ -import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' +import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { useCallback } from 'react' import { organizationKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrganizationCustomerProfileVariables = { slug?: string diff --git a/apps/studio/data/organizations/organization-customer-profile-update-mutation.ts b/apps/studio/data/organizations/organization-customer-profile-update-mutation.ts index 47f3cd7a942..c03b3d5a134 100644 --- a/apps/studio/data/organizations/organization-customer-profile-update-mutation.ts +++ b/apps/studio/data/organizations/organization-customer-profile-update-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationCustomerProfileUpdateVariables = { diff --git a/apps/studio/data/organizations/organization-delete-mutation.ts b/apps/studio/data/organizations/organization-delete-mutation.ts index db4af223347..e075389270e 100644 --- a/apps/studio/data/organizations/organization-delete-mutation.ts +++ b/apps/studio/data/organizations/organization-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' import { permissionKeys } from 'data/permissions/keys' diff --git a/apps/studio/data/organizations/organization-join-decline-mutation.ts b/apps/studio/data/organizations/organization-join-decline-mutation.ts index 480bcd1a57e..397ceeb0cad 100644 --- a/apps/studio/data/organizations/organization-join-decline-mutation.ts +++ b/apps/studio/data/organizations/organization-join-decline-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrganizationJoinDeclineVariables = { slug: string diff --git a/apps/studio/data/organizations/organization-join-mutation.ts b/apps/studio/data/organizations/organization-join-mutation.ts index 0a7c407e69c..3f07c2d4757 100644 --- a/apps/studio/data/organizations/organization-join-mutation.ts +++ b/apps/studio/data/organizations/organization-join-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationJoinVariables = { diff --git a/apps/studio/data/organizations/organization-join-token-validation-query.ts b/apps/studio/data/organizations/organization-join-token-validation-query.ts index 09c7af60ccd..cbc28c9d778 100644 --- a/apps/studio/data/organizations/organization-join-token-validation-query.ts +++ b/apps/studio/data/organizations/organization-join-token-validation-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { components } from 'data/api' -import { ResponseError } from 'types' +import type { components } from 'data/api' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationJoinTokenValidationVariables = { diff --git a/apps/studio/data/organizations/organization-member-delete-mutation.ts b/apps/studio/data/organizations/organization-member-delete-mutation.ts index 9c7092b6222..cc888e9787b 100644 --- a/apps/studio/data/organizations/organization-member-delete-mutation.ts +++ b/apps/studio/data/organizations/organization-member-delete-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationMemberDeleteVariables = { diff --git a/apps/studio/data/organizations/organization-member-invite-create-mutation.ts b/apps/studio/data/organizations/organization-member-invite-create-mutation.ts index d9534743384..487c8b0ae44 100644 --- a/apps/studio/data/organizations/organization-member-invite-create-mutation.ts +++ b/apps/studio/data/organizations/organization-member-invite-create-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationMemberInviteCreateVariables = { diff --git a/apps/studio/data/organizations/organization-member-invite-delete-mutation.ts b/apps/studio/data/organizations/organization-member-invite-delete-mutation.ts index 97ffcb9d626..41a640feb65 100644 --- a/apps/studio/data/organizations/organization-member-invite-delete-mutation.ts +++ b/apps/studio/data/organizations/organization-member-invite-delete-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationMemberInviteDeleteVariables = { diff --git a/apps/studio/data/organizations/organization-member-update-mutation.ts b/apps/studio/data/organizations/organization-member-update-mutation.ts index 15181506d5e..58f6fa7b0b2 100644 --- a/apps/studio/data/organizations/organization-member-update-mutation.ts +++ b/apps/studio/data/organizations/organization-member-update-mutation.ts @@ -3,7 +3,7 @@ import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { organizationKeys } from './keys' import { toast } from 'react-hot-toast' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrganizationMemberUpdateVariables = { slug: string diff --git a/apps/studio/data/organizations/organization-members-query.ts b/apps/studio/data/organizations/organization-members-query.ts index bb7d124e428..581f0a2dd50 100644 --- a/apps/studio/data/organizations/organization-members-query.ts +++ b/apps/studio/data/organizations/organization-members-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationMembersVariables = { diff --git a/apps/studio/data/organizations/organization-payment-method-delete-mutation.ts b/apps/studio/data/organizations/organization-payment-method-delete-mutation.ts index 34d8181755d..ce3bf220dc1 100644 --- a/apps/studio/data/organizations/organization-payment-method-delete-mutation.ts +++ b/apps/studio/data/organizations/organization-payment-method-delete-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' export type OrganizationPaymentMethodDeleteVariables = { diff --git a/apps/studio/data/organizations/organization-payment-method-setup-intent-mutation.ts b/apps/studio/data/organizations/organization-payment-method-setup-intent-mutation.ts index e442afa877f..d6f581f32ca 100644 --- a/apps/studio/data/organizations/organization-payment-method-setup-intent-mutation.ts +++ b/apps/studio/data/organizations/organization-payment-method-setup-intent-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrganizationPaymentMethodSetupIntentVariables = { slug: string diff --git a/apps/studio/data/organizations/organization-payment-methods-query.ts b/apps/studio/data/organizations/organization-payment-methods-query.ts index 1632feff6c4..2ab0d9ca69f 100644 --- a/apps/studio/data/organizations/organization-payment-methods-query.ts +++ b/apps/studio/data/organizations/organization-payment-methods-query.ts @@ -1,9 +1,8 @@ -import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' +import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { useCallback } from 'react' import { organizationKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrganizationPaymentMethodsVariables = { slug?: string } export type OrganizationPaymentMethod = { diff --git a/apps/studio/data/organizations/organization-roles-query.ts b/apps/studio/data/organizations/organization-roles-query.ts index 5079dcb0f4b..517d6359386 100644 --- a/apps/studio/data/organizations/organization-roles-query.ts +++ b/apps/studio/data/organizations/organization-roles-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError, Role } from 'types' +import type { ResponseError, Role } from 'types' import { organizationKeys } from './keys' export type OrganizationRolesVariables = { diff --git a/apps/studio/data/organizations/organization-tax-ids-query.ts b/apps/studio/data/organizations/organization-tax-ids-query.ts index df39b05b599..8b650ef6089 100644 --- a/apps/studio/data/organizations/organization-tax-ids-query.ts +++ b/apps/studio/data/organizations/organization-tax-ids-query.ts @@ -3,7 +3,7 @@ import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { useCallback } from 'react' import { organizationKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrganizationTaxIDsVariables = { slug?: string diff --git a/apps/studio/data/organizations/organization-tax-ids-update-mutation.ts b/apps/studio/data/organizations/organization-tax-ids-update-mutation.ts index 69153bdd356..9a87e5b4c3a 100644 --- a/apps/studio/data/organizations/organization-tax-ids-update-mutation.ts +++ b/apps/studio/data/organizations/organization-tax-ids-update-mutation.ts @@ -3,9 +3,9 @@ import { toast } from 'react-hot-toast' import { delete_, post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' -import { TaxId } from './organization-tax-ids-query' +import type { TaxId } from './organization-tax-ids-query' export interface TaxIdValue { id: string diff --git a/apps/studio/data/organizations/organization-update-mutation.ts b/apps/studio/data/organizations/organization-update-mutation.ts index 7550c0637da..b89d3ac700c 100644 --- a/apps/studio/data/organizations/organization-update-mutation.ts +++ b/apps/studio/data/organizations/organization-update-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { organizationKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' export type OrganizationUpdateVariables = { slug: string diff --git a/apps/studio/data/organizations/organizations-query.ts b/apps/studio/data/organizations/organizations-query.ts index be097cd02e5..5d081a9d91f 100644 --- a/apps/studio/data/organizations/organizations-query.ts +++ b/apps/studio/data/organizations/organizations-query.ts @@ -2,7 +2,7 @@ import { QueryClient, useQuery, useQueryClient, UseQueryOptions } from '@tanstac import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { useCallback } from 'react' -import { Organization, ResponseError } from 'types' +import type { Organization, ResponseError } from 'types' import { organizationKeys } from './keys' export async function getOrganizations(signal?: AbortSignal): Promise { diff --git a/apps/studio/data/permissions/permissions-query.ts b/apps/studio/data/permissions/permissions-query.ts index 6d685c87c49..e247de4f916 100644 --- a/apps/studio/data/permissions/permissions-query.ts +++ b/apps/studio/data/permissions/permissions-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL, IS_PLATFORM } from 'lib/constants' -import { Permission, ResponseError } from 'types' +import type { Permission, ResponseError } from 'types' import { permissionKeys } from './keys' export type PermissionsResponse = Permission[] diff --git a/apps/studio/data/pg-sodium-keys/pg-sodium-key-create-mutation.ts b/apps/studio/data/pg-sodium-keys/pg-sodium-key-create-mutation.ts index 930e32af5de..0bb24027091 100644 --- a/apps/studio/data/pg-sodium-keys/pg-sodium-key-create-mutation.ts +++ b/apps/studio/data/pg-sodium-keys/pg-sodium-key-create-mutation.ts @@ -2,8 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import toast from 'react-hot-toast' import { executeSql } from 'data/sql/execute-sql-query' -import { sqlKeys } from 'data/sql/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { pgSodiumKeys } from './keys' export type CreateEncryptionKeyVariables = { diff --git a/apps/studio/data/pg-sodium-keys/pg-sodium-key-delete-mutation.ts b/apps/studio/data/pg-sodium-keys/pg-sodium-key-delete-mutation.ts index a5bdac551d7..e6dfb8cfc0c 100644 --- a/apps/studio/data/pg-sodium-keys/pg-sodium-key-delete-mutation.ts +++ b/apps/studio/data/pg-sodium-keys/pg-sodium-key-delete-mutation.ts @@ -3,9 +3,8 @@ import toast from 'react-hot-toast' import { Query } from 'components/grid/query/Query' import { executeSql } from 'data/sql/execute-sql-query' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { pgSodiumKeys } from './keys' -import { sqlKeys } from 'data/sql/keys' export type VaultSecretDeleteVariables = { projectRef: string diff --git a/apps/studio/data/privileges/column-privileges-grant-mutation.ts b/apps/studio/data/privileges/column-privileges-grant-mutation.ts index d068d9a0cff..54c551ea636 100644 --- a/apps/studio/data/privileges/column-privileges-grant-mutation.ts +++ b/apps/studio/data/privileges/column-privileges-grant-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { privilegeKeys } from './keys' export type ColumnPrivilegesGrant = components['schemas']['GrantColumnPrivilegesBody'] diff --git a/apps/studio/data/privileges/column-privileges-query.ts b/apps/studio/data/privileges/column-privileges-query.ts index e2e69eda20f..06b4242489d 100644 --- a/apps/studio/data/privileges/column-privileges-query.ts +++ b/apps/studio/data/privileges/column-privileges-query.ts @@ -1,9 +1,9 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { privilegeKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' export type ColumnPrivilegesVariables = { projectRef?: string diff --git a/apps/studio/data/privileges/column-privileges-revoke-mutation.ts b/apps/studio/data/privileges/column-privileges-revoke-mutation.ts index 71ebaa7e9b7..5a2bd2d0e51 100644 --- a/apps/studio/data/privileges/column-privileges-revoke-mutation.ts +++ b/apps/studio/data/privileges/column-privileges-revoke-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { privilegeKeys } from './keys' export type ColumnPrivilegesRevoke = components['schemas']['RevokeColumnPrivilegesBody'] diff --git a/apps/studio/data/privileges/table-privileges-grant-mutation.ts b/apps/studio/data/privileges/table-privileges-grant-mutation.ts index 1865b497d13..a609b0f6ffb 100644 --- a/apps/studio/data/privileges/table-privileges-grant-mutation.ts +++ b/apps/studio/data/privileges/table-privileges-grant-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { privilegeKeys } from './keys' export type TablePrivilegesGrant = components['schemas']['GrantTablePrivilegesBody'] diff --git a/apps/studio/data/privileges/table-privileges-query.ts b/apps/studio/data/privileges/table-privileges-query.ts index 0d7572f732d..1e025e6d3db 100644 --- a/apps/studio/data/privileges/table-privileges-query.ts +++ b/apps/studio/data/privileges/table-privileges-query.ts @@ -1,8 +1,8 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { privilegeKeys } from './keys' export type TablePrivilegesVariables = { diff --git a/apps/studio/data/privileges/table-privileges-revoke-mutation.ts b/apps/studio/data/privileges/table-privileges-revoke-mutation.ts index 337800c5c62..ae352fbb808 100644 --- a/apps/studio/data/privileges/table-privileges-revoke-mutation.ts +++ b/apps/studio/data/privileges/table-privileges-revoke-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { privilegeKeys } from './keys' export type TablePrivilegesRevoke = components['schemas']['RevokeTablePrivilegesBody'] diff --git a/apps/studio/data/profile/mfa-authenticator-assurance-level-query.ts b/apps/studio/data/profile/mfa-authenticator-assurance-level-query.ts index d0d5c440e35..ad093941f40 100644 --- a/apps/studio/data/profile/mfa-authenticator-assurance-level-query.ts +++ b/apps/studio/data/profile/mfa-authenticator-assurance-level-query.ts @@ -1,8 +1,8 @@ -import { AuthMFAGetAuthenticatorAssuranceLevelResponse } from '@supabase/supabase-js' +import type { AuthMFAGetAuthenticatorAssuranceLevelResponse } from '@supabase/supabase-js' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { auth } from 'lib/gotrue' import { profileKeys } from './keys' -import { Profile } from './types' +import type { Profile } from './types' export type ProfileResponse = Profile diff --git a/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts b/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts index 7edd05daefe..29f3d141661 100644 --- a/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts +++ b/apps/studio/data/profile/mfa-challenge-and-verify-mutation.ts @@ -1,4 +1,4 @@ -import { AuthMFAVerifyResponse, MFAChallengeAndVerifyParams } from '@supabase/supabase-js' +import type { AuthMFAVerifyResponse, MFAChallengeAndVerifyParams } from '@supabase/supabase-js' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { auth } from 'lib/gotrue' import { profileKeys } from './keys' diff --git a/apps/studio/data/profile/mfa-enroll-mutation.ts b/apps/studio/data/profile/mfa-enroll-mutation.ts index 332f3e7aa7a..905f0a18c2c 100644 --- a/apps/studio/data/profile/mfa-enroll-mutation.ts +++ b/apps/studio/data/profile/mfa-enroll-mutation.ts @@ -1,4 +1,4 @@ -import { AuthMFAEnrollResponse, MFAEnrollParams } from '@supabase/supabase-js' +import type { AuthMFAEnrollResponse, MFAEnrollParams } from '@supabase/supabase-js' import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { auth } from 'lib/gotrue' import { toast } from 'react-hot-toast' diff --git a/apps/studio/data/profile/mfa-list-factors-query.ts b/apps/studio/data/profile/mfa-list-factors-query.ts index 108cce7bbdb..a4a7f9ae8c4 100644 --- a/apps/studio/data/profile/mfa-list-factors-query.ts +++ b/apps/studio/data/profile/mfa-list-factors-query.ts @@ -1,4 +1,4 @@ -import { AuthMFAListFactorsResponse, Factor } from '@supabase/supabase-js' +import type { AuthMFAListFactorsResponse, Factor } from '@supabase/supabase-js' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { auth } from 'lib/gotrue' import { profileKeys } from './keys' diff --git a/apps/studio/data/profile/mfa-unenroll-mutation.ts b/apps/studio/data/profile/mfa-unenroll-mutation.ts index e10a772e0f3..581d83a78f5 100644 --- a/apps/studio/data/profile/mfa-unenroll-mutation.ts +++ b/apps/studio/data/profile/mfa-unenroll-mutation.ts @@ -1,4 +1,4 @@ -import { AuthMFAUnenrollResponse, MFAUnenrollParams } from '@supabase/supabase-js' +import type { AuthMFAUnenrollResponse, MFAUnenrollParams } from '@supabase/supabase-js' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { auth } from 'lib/gotrue' import { profileKeys } from './keys' diff --git a/apps/studio/data/profile/profile-audit-logs-query.ts b/apps/studio/data/profile/profile-audit-logs-query.ts index 6c536df3795..5b850b54a73 100644 --- a/apps/studio/data/profile/profile-audit-logs-query.ts +++ b/apps/studio/data/profile/profile-audit-logs-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { AuditLog } from 'data/organizations/organization-audit-logs-query' -import { ResponseError } from 'types' +import type { AuditLog } from 'data/organizations/organization-audit-logs-query' +import type { ResponseError } from 'types' import { profileKeys } from './keys' export type ProfileAuditLogsVariables = { diff --git a/apps/studio/data/profile/profile-create-mutation.ts b/apps/studio/data/profile/profile-create-mutation.ts index 37ff0d23424..cecd1ad8276 100644 --- a/apps/studio/data/profile/profile-create-mutation.ts +++ b/apps/studio/data/profile/profile-create-mutation.ts @@ -5,9 +5,9 @@ import { organizationKeys } from 'data/organizations/keys' import { permissionKeys } from 'data/permissions/keys' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { profileKeys } from './keys' -import { Profile } from './types' +import type { Profile } from './types' export type ProfileResponse = Profile diff --git a/apps/studio/data/profile/profile-query.ts b/apps/studio/data/profile/profile-query.ts index 86a59c86e26..1a536b77864 100644 --- a/apps/studio/data/profile/profile-query.ts +++ b/apps/studio/data/profile/profile-query.ts @@ -2,9 +2,9 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' import { API_URL, IS_PLATFORM } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { profileKeys } from './keys' -import { Profile } from './types' +import type { Profile } from './types' export type ProfileResponse = Profile diff --git a/apps/studio/data/profile/profile-update-mutation.ts b/apps/studio/data/profile/profile-update-mutation.ts index 39cc5bd1c6c..eed2847c746 100644 --- a/apps/studio/data/profile/profile-update-mutation.ts +++ b/apps/studio/data/profile/profile-update-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { profileKeys } from './keys' export type ProfileUpdateVariables = { diff --git a/apps/studio/data/profile/types.ts b/apps/studio/data/profile/types.ts index f9224301270..c16127203bb 100644 --- a/apps/studio/data/profile/types.ts +++ b/apps/studio/data/profile/types.ts @@ -1,4 +1,4 @@ -import { components } from 'data/api' +import type { components } from 'data/api' export type Profile = components['schemas']['ProfileResponse'] diff --git a/apps/studio/data/projects/project-by-fly-extension-id-mutation.ts b/apps/studio/data/projects/project-by-fly-extension-id-mutation.ts index fc6b3e32740..63dcc99cf13 100644 --- a/apps/studio/data/projects/project-by-fly-extension-id-mutation.ts +++ b/apps/studio/data/projects/project-by-fly-extension-id-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import toast from 'react-hot-toast' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectByFlyExtensionIdVariables = { flyExtensionId: string diff --git a/apps/studio/data/projects/project-create-mutation.ts b/apps/studio/data/projects/project-create-mutation.ts index 411de893df8..dd46ed8026e 100644 --- a/apps/studio/data/projects/project-create-mutation.ts +++ b/apps/studio/data/projects/project-create-mutation.ts @@ -1,10 +1,10 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { post } from 'data/fetchers' -import { PRICING_TIER_PRODUCT_IDS, PROVIDERS } from 'lib/constants' -import { ResponseError } from 'types' +import { PROVIDERS } from 'lib/constants' +import type { ResponseError } from 'types' import { projectKeys } from './keys' export type DbInstanceSize = components['schemas']['DesiredInstanceSize'] diff --git a/apps/studio/data/projects/project-delete-mutation.ts b/apps/studio/data/projects/project-delete-mutation.ts index feab99f1c68..6eaeaf1055b 100644 --- a/apps/studio/data/projects/project-delete-mutation.ts +++ b/apps/studio/data/projects/project-delete-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { projectKeys } from './keys' export type ProjectDeleteVariables = { diff --git a/apps/studio/data/projects/project-detail-query.ts b/apps/studio/data/projects/project-detail-query.ts index 4e346a22b0d..971fbbea5cd 100644 --- a/apps/studio/data/projects/project-detail-query.ts +++ b/apps/studio/data/projects/project-detail-query.ts @@ -1,9 +1,9 @@ import { QueryClient, useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { projectKeys } from './keys' -import { components } from 'data/api' +import type { components } from 'data/api' export type ProjectDetailVariables = { ref?: string } diff --git a/apps/studio/data/projects/project-pause-mutation.ts b/apps/studio/data/projects/project-pause-mutation.ts index a7ceada4d5a..c4de3a1f733 100644 --- a/apps/studio/data/projects/project-pause-mutation.ts +++ b/apps/studio/data/projects/project-pause-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectPauseVariables = { ref: string diff --git a/apps/studio/data/projects/project-restart-mutation.ts b/apps/studio/data/projects/project-restart-mutation.ts index 13ced13112d..f6de0ae1be2 100644 --- a/apps/studio/data/projects/project-restart-mutation.ts +++ b/apps/studio/data/projects/project-restart-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectRestartVariables = { ref: string diff --git a/apps/studio/data/projects/project-restart-services-mutation.ts b/apps/studio/data/projects/project-restart-services-mutation.ts index 0739ab2e42b..edbb5f70935 100644 --- a/apps/studio/data/projects/project-restart-services-mutation.ts +++ b/apps/studio/data/projects/project-restart-services-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectRestartServicesVariables = { ref: string diff --git a/apps/studio/data/projects/project-restore-mutation.ts b/apps/studio/data/projects/project-restore-mutation.ts index 4fe249a0952..f4ef82e3772 100644 --- a/apps/studio/data/projects/project-restore-mutation.ts +++ b/apps/studio/data/projects/project-restore-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectRestoreVariables = { ref: string diff --git a/apps/studio/data/projects/project-status-query.ts b/apps/studio/data/projects/project-status-query.ts index d5d4339d424..1d2ac92f0cc 100644 --- a/apps/studio/data/projects/project-status-query.ts +++ b/apps/studio/data/projects/project-status-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { projectKeys } from './keys' export type ProjectStatusVariables = { diff --git a/apps/studio/data/projects/project-type-generation-query.ts b/apps/studio/data/projects/project-type-generation-query.ts index f950459d43f..290c88d0316 100644 --- a/apps/studio/data/projects/project-type-generation-query.ts +++ b/apps/studio/data/projects/project-type-generation-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { projectKeys } from './keys' export type GenerateTypesVariables = { ref?: string } diff --git a/apps/studio/data/projects/project-update-mutation.ts b/apps/studio/data/projects/project-update-mutation.ts index 92de3c042b9..00f4d457f5e 100644 --- a/apps/studio/data/projects/project-update-mutation.ts +++ b/apps/studio/data/projects/project-update-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { projectKeys } from './keys' export type ProjectUpdateVariables = { diff --git a/apps/studio/data/projects/project-upgrade-mutation.ts b/apps/studio/data/projects/project-upgrade-mutation.ts index 8bec6df6c10..8d1040c73fc 100644 --- a/apps/studio/data/projects/project-upgrade-mutation.ts +++ b/apps/studio/data/projects/project-upgrade-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectUpgradeVariables = { ref: string diff --git a/apps/studio/data/projects/projects-query.ts b/apps/studio/data/projects/projects-query.ts index 3b1276a1746..3bb52c015df 100644 --- a/apps/studio/data/projects/projects-query.ts +++ b/apps/studio/data/projects/projects-query.ts @@ -1,11 +1,11 @@ import { QueryClient, useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' import { useCallback, useRef } from 'react' -import { components } from 'data/api' +import type { components } from 'data/api' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { projectKeys } from './keys' -import { Project } from './project-detail-query' +import type { Project } from './project-detail-query' export type ProjectsVariables = { ref?: string diff --git a/apps/studio/data/read-replicas/load-balancers-query.ts b/apps/studio/data/read-replicas/load-balancers-query.ts index e80df9f15ed..38c34fadd49 100644 --- a/apps/studio/data/read-replicas/load-balancers-query.ts +++ b/apps/studio/data/read-replicas/load-balancers-query.ts @@ -1,9 +1,9 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get, handleError } from 'data/fetchers' import { useProjectDetailQuery } from 'data/projects/project-detail-query' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { replicaKeys } from './keys' export type LoadBalancersVariables = { diff --git a/apps/studio/data/read-replicas/replica-remove-mutation.ts b/apps/studio/data/read-replicas/replica-remove-mutation.ts index 416830d6a6b..6cbc22aab3e 100644 --- a/apps/studio/data/read-replicas/replica-remove-mutation.ts +++ b/apps/studio/data/read-replicas/replica-remove-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { replicaKeys } from './keys' -import { Database } from './replicas-query' +import type { Database } from './replicas-query' export type ReadReplicaRemoveVariables = { projectRef: string diff --git a/apps/studio/data/read-replicas/replica-setup-mutation.ts b/apps/studio/data/read-replicas/replica-setup-mutation.ts index 44f44e32e4e..6fc0f28cc0b 100644 --- a/apps/studio/data/read-replicas/replica-setup-mutation.ts +++ b/apps/studio/data/read-replicas/replica-setup-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { replicaKeys } from './keys' -import { Database } from './replicas-query' +import type { Database } from './replicas-query' export type Region = | 'us-east-1' diff --git a/apps/studio/data/read-replicas/replicas-query.ts b/apps/studio/data/read-replicas/replicas-query.ts index a4ad7f648db..545f17b34e0 100644 --- a/apps/studio/data/read-replicas/replicas-query.ts +++ b/apps/studio/data/read-replicas/replicas-query.ts @@ -1,9 +1,9 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { components } from 'data/api' +import type { components } from 'data/api' import { get } from 'data/fetchers' import { useProjectDetailQuery } from 'data/projects/project-detail-query' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { replicaKeys } from './keys' export type ReadReplicasVariables = { diff --git a/apps/studio/data/read-replicas/replicas-status-query.ts b/apps/studio/data/read-replicas/replicas-status-query.ts index a0430316a42..b1645bb7cdb 100644 --- a/apps/studio/data/read-replicas/replicas-status-query.ts +++ b/apps/studio/data/read-replicas/replicas-status-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { useProjectDetailQuery } from 'data/projects/project-detail-query' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { replicaKeys } from './keys' export type ReadReplicasStatusesVariables = { diff --git a/apps/studio/data/secrets/secrets-create-mutation.ts b/apps/studio/data/secrets/secrets-create-mutation.ts index 7b97c4275c2..d2d6354de70 100644 --- a/apps/studio/data/secrets/secrets-create-mutation.ts +++ b/apps/studio/data/secrets/secrets-create-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { secretsKeys } from './keys' export type SecretsCreateVariables = { diff --git a/apps/studio/data/secrets/secrets-delete-mutation.ts b/apps/studio/data/secrets/secrets-delete-mutation.ts index 26768ac5ef8..c887aae19d0 100644 --- a/apps/studio/data/secrets/secrets-delete-mutation.ts +++ b/apps/studio/data/secrets/secrets-delete-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { secretsKeys } from './keys' export type SecretsDeleteVariables = { diff --git a/apps/studio/data/secrets/secrets-query.ts b/apps/studio/data/secrets/secrets-query.ts index 0ffabb9a5dd..a06a5fbc96d 100644 --- a/apps/studio/data/secrets/secrets-query.ts +++ b/apps/studio/data/secrets/secrets-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { secretsKeys } from './keys' -import { ResponseError } from 'types' -import { components } from 'data/api' +import type { ResponseError } from 'types' +import type { components } from 'data/api' export type SecretsVariables = { projectRef?: string diff --git a/apps/studio/data/service-status/edge-functions-status-query.ts b/apps/studio/data/service-status/edge-functions-status-query.ts index 6e8eacaca36..9010e058064 100644 --- a/apps/studio/data/service-status/edge-functions-status-query.ts +++ b/apps/studio/data/service-status/edge-functions-status-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'lib/common/fetch' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { serviceStatusKeys } from './keys' export type EdgeFunctionServiceStatusVariables = { diff --git a/apps/studio/data/service-status/postgres-service-status-query.ts b/apps/studio/data/service-status/postgres-service-status-query.ts index db3a22a7311..0ba96d5e079 100644 --- a/apps/studio/data/service-status/postgres-service-status-query.ts +++ b/apps/studio/data/service-status/postgres-service-status-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { post } from 'lib/common/fetch' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { serviceStatusKeys } from './keys' import { API_URL } from 'lib/constants' diff --git a/apps/studio/data/service-status/service-status-query.ts b/apps/studio/data/service-status/service-status-query.ts index 38c82b0e23e..332d01079db 100644 --- a/apps/studio/data/service-status/service-status-query.ts +++ b/apps/studio/data/service-status/service-status-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { serviceStatusKeys } from './keys' export type ProjectServiceStatusVariables = { diff --git a/apps/studio/data/sql/keys.ts b/apps/studio/data/sql/keys.ts index b651bbfe087..06fc4f4c803 100644 --- a/apps/studio/data/sql/keys.ts +++ b/apps/studio/data/sql/keys.ts @@ -1,4 +1,4 @@ -import { QueryKey } from '@tanstack/react-query' +import type { QueryKey } from '@tanstack/react-query' export const sqlKeys = { query: (projectRef: string | undefined, queryKey: QueryKey) => diff --git a/apps/studio/data/ssl-enforcement/ssl-enforcement-update-mutation.ts b/apps/studio/data/ssl-enforcement/ssl-enforcement-update-mutation.ts index ca0e41cf65b..e4b5d88f2ad 100644 --- a/apps/studio/data/ssl-enforcement/ssl-enforcement-update-mutation.ts +++ b/apps/studio/data/ssl-enforcement/ssl-enforcement-update-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { put } from 'lib/common/fetch' import { API_ADMIN_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { sslEnforcementKeys } from './keys' export type SSLEnforcementUpdateVariables = { diff --git a/apps/studio/data/storage/bucket-create-mutation.ts b/apps/studio/data/storage/bucket-create-mutation.ts index 56602c3b993..16089a2a175 100644 --- a/apps/studio/data/storage/bucket-create-mutation.ts +++ b/apps/studio/data/storage/bucket-create-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { storageKeys } from './keys' export type BucketCreateVariables = { diff --git a/apps/studio/data/storage/bucket-delete-mutation.ts b/apps/studio/data/storage/bucket-delete-mutation.ts index 399dcc20d1e..63142b9c93c 100644 --- a/apps/studio/data/storage/bucket-delete-mutation.ts +++ b/apps/studio/data/storage/bucket-delete-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { delete_, post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { storageKeys } from './keys' export type BucketDeleteVariables = { diff --git a/apps/studio/data/storage/bucket-empty-mutation.ts b/apps/studio/data/storage/bucket-empty-mutation.ts index 2e14636ccb4..ab50fda6feb 100644 --- a/apps/studio/data/storage/bucket-empty-mutation.ts +++ b/apps/studio/data/storage/bucket-empty-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { storageKeys } from './keys' export type BucketEmptyVariables = { diff --git a/apps/studio/data/storage/bucket-update-mutation.ts b/apps/studio/data/storage/bucket-update-mutation.ts index ec920849b1e..be17dd7f714 100644 --- a/apps/studio/data/storage/bucket-update-mutation.ts +++ b/apps/studio/data/storage/bucket-update-mutation.ts @@ -3,7 +3,7 @@ import { toast } from 'react-hot-toast' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { storageKeys } from './keys' export type BucketUpdateVariables = { diff --git a/apps/studio/data/storage/buckets-query.ts b/apps/studio/data/storage/buckets-query.ts index 762df8b94bf..613578063d1 100644 --- a/apps/studio/data/storage/buckets-query.ts +++ b/apps/studio/data/storage/buckets-query.ts @@ -3,7 +3,7 @@ import { get } from 'data/fetchers' import { API_URL } from 'lib/constants' import { useCallback } from 'react' import { storageKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type BucketsVariables = { projectRef?: string } diff --git a/apps/studio/data/stripe/setup-intent-mutation.ts b/apps/studio/data/stripe/setup-intent-mutation.ts index cad5489d964..37d9153a66b 100644 --- a/apps/studio/data/stripe/setup-intent-mutation.ts +++ b/apps/studio/data/stripe/setup-intent-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions } from '@tanstack/react-query' import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type SetupIntentVariables = { hcaptchaToken: string diff --git a/apps/studio/data/subscriptions/org-subscription-cancel-schedule-mutation.ts b/apps/studio/data/subscriptions/org-subscription-cancel-schedule-mutation.ts index de320dbf0a6..a5ecb39b648 100644 --- a/apps/studio/data/subscriptions/org-subscription-cancel-schedule-mutation.ts +++ b/apps/studio/data/subscriptions/org-subscription-cancel-schedule-mutation.ts @@ -2,7 +2,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { subscriptionKeys } from './keys' export type OrganizationBillingSubscriptionCancelScheduleVariables = { diff --git a/apps/studio/data/subscriptions/org-subscription-query.ts b/apps/studio/data/subscriptions/org-subscription-query.ts index c28c69c2443..d4faeb1d255 100644 --- a/apps/studio/data/subscriptions/org-subscription-query.ts +++ b/apps/studio/data/subscriptions/org-subscription-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { subscriptionKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type OrgSubscriptionVariables = { orgSlug?: string diff --git a/apps/studio/data/subscriptions/org-subscription-update-mutation.ts b/apps/studio/data/subscriptions/org-subscription-update-mutation.ts index da5490d4db4..bb1869fa064 100644 --- a/apps/studio/data/subscriptions/org-subscription-update-mutation.ts +++ b/apps/studio/data/subscriptions/org-subscription-update-mutation.ts @@ -1,10 +1,10 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { put } from 'data/fetchers' import { toast } from 'react-hot-toast' -import { ResponseError } from 'types/base' +import type { ResponseError } from 'types/base' import { subscriptionKeys } from './keys' import { usageKeys } from 'data/usage/keys' -import { SubscriptionTier } from './types' +import type { SubscriptionTier } from './types' import { invoicesKeys } from 'data/invoices/keys' export type OrgSubscriptionUpdateVariables = { diff --git a/apps/studio/data/subscriptions/project-addon-remove-mutation.ts b/apps/studio/data/subscriptions/project-addon-remove-mutation.ts index 5c0bcf06b87..0b8b5261359 100644 --- a/apps/studio/data/subscriptions/project-addon-remove-mutation.ts +++ b/apps/studio/data/subscriptions/project-addon-remove-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { del } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { subscriptionKeys } from './keys' -import { AddonVariantId } from './types' +import type { AddonVariantId } from './types' export type ProjectAddonRemoveVariables = { projectRef: string diff --git a/apps/studio/data/subscriptions/project-addon-update-mutation.ts b/apps/studio/data/subscriptions/project-addon-update-mutation.ts index 010dada62a9..73638b12763 100644 --- a/apps/studio/data/subscriptions/project-addon-update-mutation.ts +++ b/apps/studio/data/subscriptions/project-addon-update-mutation.ts @@ -2,9 +2,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react import { toast } from 'react-hot-toast' import { post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { subscriptionKeys } from './keys' -import { AddonVariantId, ProjectAddonType } from './types' +import type { AddonVariantId, ProjectAddonType } from './types' export type ProjectAddonUpdateVariables = { projectRef: string diff --git a/apps/studio/data/subscriptions/project-addons-query.ts b/apps/studio/data/subscriptions/project-addons-query.ts index f81ee6df3c9..eb037de72b0 100644 --- a/apps/studio/data/subscriptions/project-addons-query.ts +++ b/apps/studio/data/subscriptions/project-addons-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { subscriptionKeys } from './keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProjectAddonsVariables = { projectRef?: string diff --git a/apps/studio/data/subscriptions/types.ts b/apps/studio/data/subscriptions/types.ts index e4ec4475247..a47351d1549 100644 --- a/apps/studio/data/subscriptions/types.ts +++ b/apps/studio/data/subscriptions/types.ts @@ -1,4 +1,4 @@ -import { components } from 'data/api' +import type { components } from 'data/api' export type SubscriptionTier = | 'tier_free' diff --git a/apps/studio/data/table-rows/table-row-create-mutation.ts b/apps/studio/data/table-rows/table-row-create-mutation.ts index 1a3cc009716..2a136b0dad2 100644 --- a/apps/studio/data/table-rows/table-row-create-mutation.ts +++ b/apps/studio/data/table-rows/table-row-create-mutation.ts @@ -5,7 +5,7 @@ import { Query, SupaTable } from 'components/grid' import { sqlKeys } from 'data/sql/keys' import { ImpersonationRole, wrapWithRoleImpersonation } from 'lib/role-impersonation' import { isRoleImpersonationEnabled } from 'state/role-impersonation-state' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { executeSql } from 'data/sql/execute-sql-query' export type TableRowCreateVariables = { diff --git a/apps/studio/data/table-rows/table-row-delete-all-mutation.ts b/apps/studio/data/table-rows/table-row-delete-all-mutation.ts index a35d7937240..c63c992d4cf 100644 --- a/apps/studio/data/table-rows/table-row-delete-all-mutation.ts +++ b/apps/studio/data/table-rows/table-row-delete-all-mutation.ts @@ -6,7 +6,7 @@ import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' import { ImpersonationRole, wrapWithRoleImpersonation } from 'lib/role-impersonation' import { isRoleImpersonationEnabled } from 'state/role-impersonation-state' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { formatFilterValue } from './utils' export type TableRowDeleteAllVariables = { diff --git a/apps/studio/data/table-rows/table-row-delete-mutation.ts b/apps/studio/data/table-rows/table-row-delete-mutation.ts index 1cbff02d640..9ebd685c439 100644 --- a/apps/studio/data/table-rows/table-row-delete-mutation.ts +++ b/apps/studio/data/table-rows/table-row-delete-mutation.ts @@ -4,10 +4,10 @@ import { toast } from 'react-hot-toast' import { Query, SupaRow } from 'components/grid' import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' -import { Table } from 'data/tables/table-query' +import type { Table } from 'data/tables/table-query' import { ImpersonationRole, wrapWithRoleImpersonation } from 'lib/role-impersonation' import { isRoleImpersonationEnabled } from 'state/role-impersonation-state' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { getPrimaryKeys } from './utils' export type TableRowDeleteVariables = { diff --git a/apps/studio/data/table-rows/table-row-truncate-mutation.ts b/apps/studio/data/table-rows/table-row-truncate-mutation.ts index c14b8aa25c8..44688fc0ace 100644 --- a/apps/studio/data/table-rows/table-row-truncate-mutation.ts +++ b/apps/studio/data/table-rows/table-row-truncate-mutation.ts @@ -4,7 +4,7 @@ import { toast } from 'react-hot-toast' import { Query, SupaTable } from 'components/grid' import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type TableRowTruncateVariables = { projectRef: string diff --git a/apps/studio/data/table-rows/table-row-update-mutation.ts b/apps/studio/data/table-rows/table-row-update-mutation.ts index e11e1095458..b00b202d9ed 100644 --- a/apps/studio/data/table-rows/table-row-update-mutation.ts +++ b/apps/studio/data/table-rows/table-row-update-mutation.ts @@ -6,7 +6,7 @@ import { executeSql } from 'data/sql/execute-sql-query' import { sqlKeys } from 'data/sql/keys' import { ImpersonationRole, wrapWithRoleImpersonation } from 'lib/role-impersonation' import { isRoleImpersonationEnabled } from 'state/role-impersonation-state' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type TableRowUpdateVariables = { projectRef: string diff --git a/apps/studio/data/table-rows/table-rows-count-query.ts b/apps/studio/data/table-rows/table-rows-count-query.ts index 9f2446d88f3..8f5c3e271e1 100644 --- a/apps/studio/data/table-rows/table-rows-count-query.ts +++ b/apps/studio/data/table-rows/table-rows-count-query.ts @@ -1,4 +1,4 @@ -import { QueryKey, UseQueryOptions } from '@tanstack/react-query' +import type { QueryKey, UseQueryOptions } from '@tanstack/react-query' import { Filter, Query, SupaTable } from 'components/grid' import { ImpersonationRole, wrapWithRoleImpersonation } from 'lib/role-impersonation' diff --git a/apps/studio/data/table-rows/table-rows-query.ts b/apps/studio/data/table-rows/table-rows-query.ts index 1f6bd4df728..879d4c8d37e 100644 --- a/apps/studio/data/table-rows/table-rows-query.ts +++ b/apps/studio/data/table-rows/table-rows-query.ts @@ -1,4 +1,4 @@ -import { QueryKey, UseQueryOptions } from '@tanstack/react-query' +import type { QueryKey, UseQueryOptions } from '@tanstack/react-query' import { IS_PLATFORM } from 'common' import { Filter, Query, Sort, SupaRow, SupaTable } from 'components/grid' diff --git a/apps/studio/data/table-rows/utils.ts b/apps/studio/data/table-rows/utils.ts index 55c6c305b07..b5796abed1b 100644 --- a/apps/studio/data/table-rows/utils.ts +++ b/apps/studio/data/table-rows/utils.ts @@ -1,7 +1,7 @@ -import { Filter, ServiceError, SupaTable } from 'components/grid' +import type { Filter, ServiceError, SupaTable } from 'components/grid' import { ERROR_PRIMARY_KEY_NOTFOUND } from 'components/grid/constants' import { isNumericalColumn } from 'components/grid/utils' -import { Table } from 'data/tables/table-query' +import type { Table } from 'data/tables/table-query' /** * temporary fix until we implement a better filter UI diff --git a/apps/studio/data/tables/table-create-mutation.ts b/apps/studio/data/tables/table-create-mutation.ts index fc1975ed6d1..ad99da6c144 100644 --- a/apps/studio/data/tables/table-create-mutation.ts +++ b/apps/studio/data/tables/table-create-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { handleError, post } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { tableKeys } from './keys' export type CreateTableBody = components['schemas']['CreateTableBody'] diff --git a/apps/studio/data/tables/table-delete-mutation.ts b/apps/studio/data/tables/table-delete-mutation.ts index cd8d7be5dce..1f445aca64d 100644 --- a/apps/studio/data/tables/table-delete-mutation.ts +++ b/apps/studio/data/tables/table-delete-mutation.ts @@ -4,7 +4,7 @@ import { toast } from 'react-hot-toast' import { entityTypeKeys } from 'data/entity-types/keys' import { del, handleError } from 'data/fetchers' import { viewKeys } from 'data/views/keys' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { tableKeys } from './keys' export type TableDeleteVariables = { diff --git a/apps/studio/data/tables/table-query.ts b/apps/studio/data/tables/table-query.ts index 2bec6eb5a18..ae9b159e9f3 100644 --- a/apps/studio/data/tables/table-query.ts +++ b/apps/studio/data/tables/table-query.ts @@ -1,4 +1,4 @@ -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' // import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' diff --git a/apps/studio/data/tables/table-update-mutation.ts b/apps/studio/data/tables/table-update-mutation.ts index 274b91c035e..76db54f9a98 100644 --- a/apps/studio/data/tables/table-update-mutation.ts +++ b/apps/studio/data/tables/table-update-mutation.ts @@ -1,9 +1,9 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'react-hot-toast' -import { components } from 'data/api' +import type { components } from 'data/api' import { handleError, patch } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { tableKeys } from './keys' export type UpdateTableBody = components['schemas']['UpdateTableBody'] diff --git a/apps/studio/data/tables/tables-query.ts b/apps/studio/data/tables/tables-query.ts index 14472190c21..8e1ebf85199 100644 --- a/apps/studio/data/tables/tables-query.ts +++ b/apps/studio/data/tables/tables-query.ts @@ -1,10 +1,10 @@ -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' import { sortBy } from 'lodash' import { useCallback } from 'react' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { tableKeys } from './keys' export type TablesVariables = { diff --git a/apps/studio/data/usage/org-usage-query.ts b/apps/studio/data/usage/org-usage-query.ts index 4bc23315c7a..d7a2216c325 100644 --- a/apps/studio/data/usage/org-usage-query.ts +++ b/apps/studio/data/usage/org-usage-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { usageKeys } from './keys' -import { ResponseError } from 'types' -import { components } from 'data/api' +import type { ResponseError } from 'types' +import type { components } from 'data/api' export type OrgUsageVariables = { orgSlug?: string diff --git a/apps/studio/data/usage/resource-warnings-query.ts b/apps/studio/data/usage/resource-warnings-query.ts index 7a1c588f52f..78817a1f3af 100644 --- a/apps/studio/data/usage/resource-warnings-query.ts +++ b/apps/studio/data/usage/resource-warnings-query.ts @@ -2,8 +2,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get } from 'data/fetchers' import { usageKeys } from './keys' -import { ResponseError } from 'types' -import { components } from 'data/api' +import type { ResponseError } from 'types' +import type { components } from 'data/api' import { IS_PLATFORM } from 'common' export async function getResourceWarnings(signal?: AbortSignal) { diff --git a/apps/studio/data/vault/vault-secret-create-mutation.ts b/apps/studio/data/vault/vault-secret-create-mutation.ts index 147a96cc03e..67798e557c2 100644 --- a/apps/studio/data/vault/vault-secret-create-mutation.ts +++ b/apps/studio/data/vault/vault-secret-create-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { Query } from 'components/grid/query/Query' import { executeSql } from 'data/sql/execute-sql-query' -import { ResponseError, VaultSecret } from 'types' +import type { ResponseError, VaultSecret } from 'types' import { vaultSecretsKeys } from './keys' import { sqlKeys } from 'data/sql/keys' diff --git a/apps/studio/data/vault/vault-secret-delete-mutation.ts b/apps/studio/data/vault/vault-secret-delete-mutation.ts index 0bed4e196bf..0532ef5ab3b 100644 --- a/apps/studio/data/vault/vault-secret-delete-mutation.ts +++ b/apps/studio/data/vault/vault-secret-delete-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { Query } from 'components/grid/query/Query' import { executeSql } from 'data/sql/execute-sql-query' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { vaultSecretsKeys } from './keys' import { sqlKeys } from 'data/sql/keys' diff --git a/apps/studio/data/vault/vault-secret-update-mutation.ts b/apps/studio/data/vault/vault-secret-update-mutation.ts index 96a00180814..c8ba8fcf1ad 100644 --- a/apps/studio/data/vault/vault-secret-update-mutation.ts +++ b/apps/studio/data/vault/vault-secret-update-mutation.ts @@ -3,7 +3,7 @@ import toast from 'react-hot-toast' import { Query } from 'components/grid/query/Query' import { executeSql } from 'data/sql/execute-sql-query' -import { ResponseError, VaultSecret } from 'types' +import type { ResponseError, VaultSecret } from 'types' import { vaultSecretsKeys } from './keys' import { sqlKeys } from 'data/sql/keys' diff --git a/apps/studio/data/vault/vault-secrets-query.ts b/apps/studio/data/vault/vault-secrets-query.ts index cb3621aa5c2..8ac2377ee97 100644 --- a/apps/studio/data/vault/vault-secrets-query.ts +++ b/apps/studio/data/vault/vault-secrets-query.ts @@ -1,6 +1,6 @@ import { UseQueryOptions } from '@tanstack/react-query' import { Query } from 'components/grid/query/Query' -import { VaultSecret } from 'types' +import type { VaultSecret } from 'types' import { ExecuteSqlData, useExecuteSqlQuery } from '../sql/execute-sql-query' import { vaultSecretsKeys } from './keys' diff --git a/apps/studio/data/views/view-query.ts b/apps/studio/data/views/view-query.ts index 5a7b365f317..ae6d11b6c2d 100644 --- a/apps/studio/data/views/view-query.ts +++ b/apps/studio/data/views/view-query.ts @@ -1,8 +1,8 @@ -import { PostgresView } from '@supabase/postgres-meta' +import type { PostgresView } from '@supabase/postgres-meta' import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { viewKeys } from './keys' export type ViewVariables = { diff --git a/apps/studio/data/views/views-query.ts b/apps/studio/data/views/views-query.ts index 12767524c84..b5c884f06f0 100644 --- a/apps/studio/data/views/views-query.ts +++ b/apps/studio/data/views/views-query.ts @@ -2,7 +2,7 @@ import { UseQueryOptions, useQuery, useQueryClient } from '@tanstack/react-query import { useCallback } from 'react' import { get, handleError } from 'data/fetchers' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' import { viewKeys } from './keys' export type ViewsVariables = { diff --git a/apps/studio/hooks/analytics/useLogsQuery.tsx b/apps/studio/hooks/analytics/useLogsQuery.tsx index e0b0516d27c..2460f8d2c2e 100644 --- a/apps/studio/hooks/analytics/useLogsQuery.tsx +++ b/apps/studio/hooks/analytics/useLogsQuery.tsx @@ -5,7 +5,11 @@ import { getDefaultHelper, } from 'components/interfaces/Settings/Logs' import { Dispatch, SetStateAction, useState } from 'react' -import { LogsEndpointParams, Logs, LogData } from 'components/interfaces/Settings/Logs/Logs.types' +import type { + LogsEndpointParams, + Logs, + LogData, +} from 'components/interfaces/Settings/Logs/Logs.types' import { API_URL } from 'lib/constants' import { get, isResponseOk } from 'lib/common/fetch' export interface LogsQueryHook { diff --git a/apps/studio/hooks/misc/useCheckPermissions.ts b/apps/studio/hooks/misc/useCheckPermissions.ts index c8b7d4fb640..b88983594e0 100644 --- a/apps/studio/hooks/misc/useCheckPermissions.ts +++ b/apps/studio/hooks/misc/useCheckPermissions.ts @@ -4,7 +4,7 @@ import jsonLogic from 'json-logic-js' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { IS_PLATFORM } from 'lib/constants' -import { Permission } from 'types' +import type { Permission } from 'types' import { useSelectedOrganization } from './useSelectedOrganization' const toRegexpString = (actionOrResource: string) => diff --git a/apps/studio/hooks/misc/useEntityType.ts b/apps/studio/hooks/misc/useEntityType.ts index 52211c72833..336b83fb5df 100644 --- a/apps/studio/hooks/misc/useEntityType.ts +++ b/apps/studio/hooks/misc/useEntityType.ts @@ -1,6 +1,6 @@ import { useQueryClient } from '@tanstack/react-query' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { Entity, useEntityTypeQuery } from 'data/entity-types/entity-type-query' +import { type Entity, useEntityTypeQuery } from 'data/entity-types/entity-type-query' import { entityTypeKeys } from 'data/entity-types/keys' import { useMemo } from 'react' diff --git a/apps/studio/hooks/misc/useIsFeatureEnabled.ts b/apps/studio/hooks/misc/useIsFeatureEnabled.ts index e3117e901ef..2542fb5ddb3 100644 --- a/apps/studio/hooks/misc/useIsFeatureEnabled.ts +++ b/apps/studio/hooks/misc/useIsFeatureEnabled.ts @@ -1,4 +1,4 @@ -import { Feature } from 'data/profile/types' +import type { Feature } from 'data/profile/types' import { useProfile } from 'lib/profile' function checkFeature(feature: Feature, features?: Feature[]) { diff --git a/apps/studio/hooks/misc/useStore.tsx b/apps/studio/hooks/misc/useStore.tsx index be8ae8c5048..0f5b229a303 100644 --- a/apps/studio/hooks/misc/useStore.tsx +++ b/apps/studio/hooks/misc/useStore.tsx @@ -3,7 +3,7 @@ import { createContext, PropsWithChildren, useContext, useEffect } from 'react' import toast from 'react-hot-toast' import SparkBar from 'components/ui/SparkBar' -import { IRootStore } from 'stores' +import type { IRootStore } from 'stores' import { useSelectedProject } from './useSelectedProject' const StoreContext = createContext(undefined!) diff --git a/apps/studio/lib/api/apiAuthenticate.ts b/apps/studio/lib/api/apiAuthenticate.ts index d7d85dcee84..f121dfa050a 100644 --- a/apps/studio/lib/api/apiAuthenticate.ts +++ b/apps/studio/lib/api/apiAuthenticate.ts @@ -1,6 +1,6 @@ import type { NextApiRequest, NextApiResponse } from 'next' import { readOnly } from './supabaseClient' -import { SupaResponse, User } from 'types' +import type { SupaResponse, User } from 'types' import { getAuth0Id, getAuthUser, getIdentity } from 'lib/gotrue' /** diff --git a/apps/studio/lib/api/apiWrapper.ts b/apps/studio/lib/api/apiWrapper.ts index 4b9008a09c3..a0deb511610 100644 --- a/apps/studio/lib/api/apiWrapper.ts +++ b/apps/studio/lib/api/apiWrapper.ts @@ -1,6 +1,6 @@ import { withSentry } from '@sentry/nextjs' import { isResponseOk } from 'lib/common/fetch' -import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' import { IS_PLATFORM } from '../constants' import { apiAuthenticate } from './apiAuthenticate' diff --git a/apps/studio/lib/common/fetch/base.ts b/apps/studio/lib/common/fetch/base.ts index c7140a3820d..38f4eda7dcd 100644 --- a/apps/studio/lib/common/fetch/base.ts +++ b/apps/studio/lib/common/fetch/base.ts @@ -1,6 +1,6 @@ import { getAccessToken } from 'lib/gotrue' import { isUndefined } from 'lodash' -import { SupaResponse } from 'types/base' +import type { SupaResponse } from 'types/base' export function handleError(e: any, requestId: string): SupaResponse { const message = e?.message ? `An error has occurred: ${e.message}` : 'An error has occurred' diff --git a/apps/studio/lib/common/fetch/delete.ts b/apps/studio/lib/common/fetch/delete.ts index 6a68c4b001b..b8da5a117dc 100644 --- a/apps/studio/lib/common/fetch/delete.ts +++ b/apps/studio/lib/common/fetch/delete.ts @@ -1,6 +1,6 @@ import { handleError, handleResponse, handleResponseError, constructHeaders } from './base' import { uuidv4 } from '../../helpers' -import { SupaResponse } from 'types/base' +import type { SupaResponse } from 'types/base' /** * @deprecated please use del method from data/fetchers instead diff --git a/apps/studio/lib/common/fetch/get.ts b/apps/studio/lib/common/fetch/get.ts index 5c3c895a58f..941c5eb4b58 100644 --- a/apps/studio/lib/common/fetch/get.ts +++ b/apps/studio/lib/common/fetch/get.ts @@ -1,6 +1,6 @@ import { handleError, handleResponse, handleResponseError, constructHeaders } from './base' import { uuidv4 } from '../../helpers' -import { SupaResponse } from 'types/base' +import type { SupaResponse } from 'types/base' /** * @deprecated please use get method from data/fetchers instead diff --git a/apps/studio/lib/common/fetch/head.ts b/apps/studio/lib/common/fetch/head.ts index dcdb88e864c..97d3e514c62 100644 --- a/apps/studio/lib/common/fetch/head.ts +++ b/apps/studio/lib/common/fetch/head.ts @@ -1,6 +1,6 @@ import { handleError, handleHeadResponse, handleResponseError, constructHeaders } from './base' import { uuidv4 } from '../../helpers' -import { SupaResponse } from 'types/base' +import type { SupaResponse } from 'types/base' /** * @deprecated please use head method from data/fetchers instead diff --git a/apps/studio/lib/common/fetch/patch.ts b/apps/studio/lib/common/fetch/patch.ts index f99f3ca8ef0..f8b3bb47d4a 100644 --- a/apps/studio/lib/common/fetch/patch.ts +++ b/apps/studio/lib/common/fetch/patch.ts @@ -1,6 +1,6 @@ import { constructHeaders, handleError, handleResponse, handleResponseError } from './base' import { uuidv4 } from '../../helpers' -import { SupaResponse } from 'types/base' +import type { SupaResponse } from 'types/base' /** * @deprecated please use patch method from data/fetchers instead diff --git a/apps/studio/lib/common/fetch/post.ts b/apps/studio/lib/common/fetch/post.ts index 2f398b470c4..32e717e54a7 100644 --- a/apps/studio/lib/common/fetch/post.ts +++ b/apps/studio/lib/common/fetch/post.ts @@ -1,6 +1,6 @@ import { handleError, handleResponse, handleResponseError, constructHeaders } from './base' import { uuidv4 } from 'lib/helpers' -import { SupaResponse } from 'types/base' +import type { SupaResponse } from 'types/base' /** * @deprecated please use post method from data/fetchers instead diff --git a/apps/studio/lib/common/fetch/put.ts b/apps/studio/lib/common/fetch/put.ts index 1eec77c933f..a2439e23d87 100644 --- a/apps/studio/lib/common/fetch/put.ts +++ b/apps/studio/lib/common/fetch/put.ts @@ -1,6 +1,6 @@ import { constructHeaders, handleError, handleResponse, handleResponseError } from './base' import { uuidv4 } from '../../helpers' -import { SupaResponse } from 'types/base' +import type { SupaResponse } from 'types/base' /** * @deprecated please use post method from data/fetchers instead diff --git a/apps/studio/lib/configcat.ts b/apps/studio/lib/configcat.ts index 6f9f4177679..048e0bda771 100644 --- a/apps/studio/lib/configcat.ts +++ b/apps/studio/lib/configcat.ts @@ -1,4 +1,4 @@ -import { User } from '@supabase/supabase-js' +import type { User } from '@supabase/supabase-js' import * as configcat from 'configcat-js' let client: configcat.IConfigCatClient diff --git a/apps/studio/lib/constants/infrastructure.ts b/apps/studio/lib/constants/infrastructure.ts index a05be565680..6107a01645e 100644 --- a/apps/studio/lib/constants/infrastructure.ts +++ b/apps/studio/lib/constants/infrastructure.ts @@ -1,4 +1,4 @@ -import { components } from 'data/api' +import type { components } from 'data/api' export type CloudProvider = 'FLY' | 'AWS' export type Region = typeof AWS_REGIONS | typeof FLY_REGIONS diff --git a/apps/studio/lib/integration-utils.ts b/apps/studio/lib/integration-utils.ts index b71945aa0bd..d33610e48c8 100644 --- a/apps/studio/lib/integration-utils.ts +++ b/apps/studio/lib/integration-utils.ts @@ -1,5 +1,5 @@ -import { Integration } from 'data/integrations/integrations.types' -import { SupaResponse } from 'types' +import type { Integration } from 'data/integrations/integrations.types' +import type { SupaResponse } from 'types' import { isResponseOk } from './common/fetch' async function fetchGitHub(url: string, responseJson = true): Promise> { diff --git a/apps/studio/lib/profile.tsx b/apps/studio/lib/profile.tsx index 41203d29913..2e779f1b815 100644 --- a/apps/studio/lib/profile.tsx +++ b/apps/studio/lib/profile.tsx @@ -5,10 +5,10 @@ import { useIsLoggedIn, useTelemetryProps } from 'common' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useProfileCreateMutation } from 'data/profile/profile-create-mutation' import { useProfileQuery } from 'data/profile/profile-query' -import { Profile } from 'data/profile/types' +import type { Profile } from 'data/profile/types' import { useStore } from 'hooks' import Telemetry from 'lib/telemetry' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' export type ProfileContextType = { profile: Profile | undefined diff --git a/apps/studio/lib/role-impersonation.ts b/apps/studio/lib/role-impersonation.ts index 634045fc9ec..4901119789a 100644 --- a/apps/studio/lib/role-impersonation.ts +++ b/apps/studio/lib/role-impersonation.ts @@ -1,4 +1,4 @@ -import { User } from 'data/auth/users-query' +import type { User } from 'data/auth/users-query' import { uuidv4 } from './helpers' type PostgrestImpersonationRole = diff --git a/apps/studio/lib/telemetry.ts b/apps/studio/lib/telemetry.ts index 00fa755e193..08496f8ee66 100644 --- a/apps/studio/lib/telemetry.ts +++ b/apps/studio/lib/telemetry.ts @@ -1,7 +1,7 @@ import { post } from 'lib/common/fetch' import { API_URL, IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants' -import { NextRouter } from 'next/router' -import { User } from 'types' +import type { NextRouter } from 'next/router' +import type { User } from 'types' export interface TelemetryProps { screenResolution?: string diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx index 42a3b45a640..1889589c012 100644 --- a/apps/studio/pages/_app.tsx +++ b/apps/studio/pages/_app.tsx @@ -54,7 +54,7 @@ import { ProfileProvider } from 'lib/profile' import { useAppStateSnapshot } from 'state/app-state' import { RootStore } from 'stores' import HCaptchaLoadedStore from 'stores/hcaptcha-loaded-store' -import { AppPropsWithLayout } from 'types' +import type { AppPropsWithLayout } from 'types' import { Toaster } from 'ui' import { FeaturePreviewContextProvider } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import FeaturePreviewModal from 'components/interfaces/App/FeaturePreview/FeaturePreviewModal' diff --git a/apps/studio/pages/account/audit.tsx b/apps/studio/pages/account/audit.tsx index 1e6398b63d4..11125b8b49a 100644 --- a/apps/studio/pages/account/audit.tsx +++ b/apps/studio/pages/account/audit.tsx @@ -2,7 +2,7 @@ import { AuditLogs } from 'components/interfaces/Account' import { AccountLayout } from 'components/layouts' import { ScaffoldContainerLegacy } from 'components/layouts/Scaffold' import { FormHeader } from 'components/ui/Forms' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const User: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/account/me.tsx b/apps/studio/pages/account/me.tsx index ae09829457f..e109f0b743f 100644 --- a/apps/studio/pages/account/me.tsx +++ b/apps/studio/pages/account/me.tsx @@ -13,7 +13,7 @@ import Panel from 'components/ui/Panel' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useFlag, useIsFeatureEnabled } from 'hooks' import { useProfile } from 'lib/profile' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const User: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/account/security.tsx b/apps/studio/pages/account/security.tsx index 37855cffc83..4ca6e0ae9e4 100644 --- a/apps/studio/pages/account/security.tsx +++ b/apps/studio/pages/account/security.tsx @@ -1,4 +1,4 @@ -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { Badge, cn, Collapsible, IconSmartphone } from 'ui' import { TOTPFactors } from 'components/interfaces/Account' diff --git a/apps/studio/pages/account/tokens.tsx b/apps/studio/pages/account/tokens.tsx index 51a767a0d18..da86f7daf8b 100644 --- a/apps/studio/pages/account/tokens.tsx +++ b/apps/studio/pages/account/tokens.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { FormHeader } from 'components/ui/Forms' import { AccountLayout } from 'components/layouts' import { diff --git a/apps/studio/pages/api/projects/[ref]/content.ts b/apps/studio/pages/api/projects/[ref]/content.ts index 6345476fa57..2fb7bd01c41 100644 --- a/apps/studio/pages/api/projects/[ref]/content.ts +++ b/apps/studio/pages/api/projects/[ref]/content.ts @@ -1,6 +1,6 @@ import { NextApiRequest, NextApiResponse } from 'next' import apiWrapper from 'lib/api/apiWrapper' -import { UserContent } from 'types' +import type { UserContent } from 'types' export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler) diff --git a/apps/studio/pages/authorize.tsx b/apps/studio/pages/authorize.tsx index 6183ac81c1d..b9181d5afeb 100644 --- a/apps/studio/pages/authorize.tsx +++ b/apps/studio/pages/authorize.tsx @@ -12,7 +12,7 @@ import { useApiAuthorizationDeclineMutation } from 'data/api-authorization/api-a import { useApiAuthorizationQuery } from 'data/api-authorization/api-authorization-query' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useStore, withAuth } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { Alert, Button, Listbox } from 'ui' // Need to handle if no organizations in account diff --git a/apps/studio/pages/forgot-password.tsx b/apps/studio/pages/forgot-password.tsx index 4efe3077133..44b43b46cc6 100644 --- a/apps/studio/pages/forgot-password.tsx +++ b/apps/studio/pages/forgot-password.tsx @@ -1,7 +1,7 @@ import ForgotPasswordForm from 'components/interfaces/SignIn/ForgotPasswordForm' import { ForgotPasswordLayout } from 'components/layouts' import Link from 'next/link' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ForgotPasswordPage: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx b/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx index 0cabcedb04f..0b5e5ebd7cf 100644 --- a/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx +++ b/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx @@ -20,7 +20,7 @@ import { AWS_REGIONS, DEFAULT_MINIMUM_PASSWORD_STRENGTH, PROVIDERS } from 'lib/c import { passwordStrength } from 'lib/helpers' import { getInitialMigrationSQLFromGitHubRepo } from 'lib/integration-utils' import { useIntegrationInstallationSnapshot } from 'state/integration-installation' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { Alert, Button, Checkbox, Input, Listbox } from 'ui' const VercelIntegration: NextPageWithLayout = () => { diff --git a/apps/studio/pages/integrations/vercel/[slug]/marketplace/choose-project.tsx b/apps/studio/pages/integrations/vercel/[slug]/marketplace/choose-project.tsx index 420a6610d3f..42ca0935117 100644 --- a/apps/studio/pages/integrations/vercel/[slug]/marketplace/choose-project.tsx +++ b/apps/studio/pages/integrations/vercel/[slug]/marketplace/choose-project.tsx @@ -18,7 +18,7 @@ import { useProjectsQuery } from 'data/projects/projects-query' import { BASE_PATH, PROJECT_STATUS } from 'lib/constants' import { EMPTY_ARR } from 'lib/void' import { useIntegrationInstallationSnapshot } from 'state/integration-installation' -import { NextPageWithLayout, Organization } from 'types' +import type { NextPageWithLayout, Organization } from 'types' const VERCEL_ICON = ( Vercel Icon diff --git a/apps/studio/pages/integrations/vercel/install.tsx b/apps/studio/pages/integrations/vercel/install.tsx index f2c707c4117..1318c60ec4d 100644 --- a/apps/studio/pages/integrations/vercel/install.tsx +++ b/apps/studio/pages/integrations/vercel/install.tsx @@ -13,7 +13,7 @@ import { useVercelIntegrationCreateMutation } from 'data/integrations/vercel-int import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useStore } from 'hooks' import Link from 'next/link' -import { NextPageWithLayout, Organization } from 'types' +import type { NextPageWithLayout, Organization } from 'types' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, diff --git a/apps/studio/pages/new/[slug].tsx b/apps/studio/pages/new/[slug].tsx index 0fdc1557886..9325a1c8c81 100644 --- a/apps/studio/pages/new/[slug].tsx +++ b/apps/studio/pages/new/[slug].tsx @@ -33,9 +33,9 @@ import { Region, } from 'lib/constants' import { passwordStrength, pluckObjectFields } from 'lib/helpers' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { Badge, Button, IconExternalLink, IconUsers, Input, Listbox } from 'ui' -import { components } from 'data/api' +import type { components } from 'data/api' import { WizardLayoutWithoutAuth } from 'components/layouts/WizardLayout' type DesiredInstanceSize = components['schemas']['DesiredInstanceSize'] diff --git a/apps/studio/pages/new/index.tsx b/apps/studio/pages/new/index.tsx index 5319effb991..95fbc992686 100644 --- a/apps/studio/pages/new/index.tsx +++ b/apps/studio/pages/new/index.tsx @@ -10,7 +10,7 @@ import { WizardLayout } from 'components/layouts' import { useSetupIntent } from 'data/stripe/setup-intent-mutation' import { STRIPE_PUBLIC_KEY } from 'lib/constants' import { useIsHCaptchaLoaded } from 'stores/hcaptcha-loaded-store' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const stripePromise = loadStripe(STRIPE_PUBLIC_KEY) diff --git a/apps/studio/pages/org/[slug]/apps.tsx b/apps/studio/pages/org/[slug]/apps.tsx index b55b3ebd927..8d1d248ce4b 100644 --- a/apps/studio/pages/org/[slug]/apps.tsx +++ b/apps/studio/pages/org/[slug]/apps.tsx @@ -3,7 +3,7 @@ import { OrganizationLayout } from 'components/layouts' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgOAuthApps: NextPageWithLayout = () => { const selectedOrganization = useSelectedOrganization() diff --git a/apps/studio/pages/org/[slug]/audit.tsx b/apps/studio/pages/org/[slug]/audit.tsx index e8ae6ef1e4c..94dd76ac24a 100644 --- a/apps/studio/pages/org/[slug]/audit.tsx +++ b/apps/studio/pages/org/[slug]/audit.tsx @@ -3,7 +3,7 @@ import { OrganizationLayout } from 'components/layouts' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgAuditLogs: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() diff --git a/apps/studio/pages/org/[slug]/billing.tsx b/apps/studio/pages/org/[slug]/billing.tsx index 4555aac2a9d..f973ac75108 100644 --- a/apps/studio/pages/org/[slug]/billing.tsx +++ b/apps/studio/pages/org/[slug]/billing.tsx @@ -9,7 +9,7 @@ import { ORG_SETTINGS_PANEL_KEYS, useOrgSettingsPageStateSnapshot, } from 'state/organization-settings' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgBillingSettings: NextPageWithLayout = () => { const { panel } = useParams() diff --git a/apps/studio/pages/org/[slug]/documents.tsx b/apps/studio/pages/org/[slug]/documents.tsx index d890fc06c6d..b92bdbe9f2c 100644 --- a/apps/studio/pages/org/[slug]/documents.tsx +++ b/apps/studio/pages/org/[slug]/documents.tsx @@ -1,4 +1,4 @@ -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { OrganizationLayout } from 'components/layouts' import { Documents } from 'components/interfaces/Organization' diff --git a/apps/studio/pages/org/[slug]/general.tsx b/apps/studio/pages/org/[slug]/general.tsx index 9e1803d79b9..4eb742b05ac 100644 --- a/apps/studio/pages/org/[slug]/general.tsx +++ b/apps/studio/pages/org/[slug]/general.tsx @@ -3,7 +3,7 @@ import { OrganizationLayout } from 'components/layouts' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgGeneralSettings: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() diff --git a/apps/studio/pages/org/[slug]/index.tsx b/apps/studio/pages/org/[slug]/index.tsx index f52f3bcc022..060d94ab9e9 100644 --- a/apps/studio/pages/org/[slug]/index.tsx +++ b/apps/studio/pages/org/[slug]/index.tsx @@ -11,7 +11,7 @@ import { useGitHubConnectionsQuery } from 'data/integrations/github-connections- import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-org-only' import { useProjectsQuery } from 'data/projects/projects-query' import { useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ProjectsPage: NextPageWithLayout = () => { const { diff --git a/apps/studio/pages/org/[slug]/integrations.tsx b/apps/studio/pages/org/[slug]/integrations.tsx index 0e54ef2778c..87fdf96add2 100644 --- a/apps/studio/pages/org/[slug]/integrations.tsx +++ b/apps/studio/pages/org/[slug]/integrations.tsx @@ -1,4 +1,4 @@ -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { OrganizationLayout } from 'components/layouts' import { IntegrationSettings } from 'components/interfaces/Organization' diff --git a/apps/studio/pages/org/[slug]/invoices.tsx b/apps/studio/pages/org/[slug]/invoices.tsx index 7d9f643546f..a532196b72e 100644 --- a/apps/studio/pages/org/[slug]/invoices.tsx +++ b/apps/studio/pages/org/[slug]/invoices.tsx @@ -3,7 +3,7 @@ import { OrganizationLayout } from 'components/layouts' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgInvoices: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() diff --git a/apps/studio/pages/org/[slug]/team.tsx b/apps/studio/pages/org/[slug]/team.tsx index de36efe5d32..4c46eec6c11 100644 --- a/apps/studio/pages/org/[slug]/team.tsx +++ b/apps/studio/pages/org/[slug]/team.tsx @@ -3,7 +3,7 @@ import { OrganizationLayout } from 'components/layouts' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgTeamSettings: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() diff --git a/apps/studio/pages/org/[slug]/usage.tsx b/apps/studio/pages/org/[slug]/usage.tsx index 67585db31f9..484ed40d286 100644 --- a/apps/studio/pages/org/[slug]/usage.tsx +++ b/apps/studio/pages/org/[slug]/usage.tsx @@ -3,7 +3,7 @@ import { OrganizationLayout } from 'components/layouts' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgUsage: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() diff --git a/apps/studio/pages/project/[ref]/api/graphiql.tsx b/apps/studio/pages/project/[ref]/api/graphiql.tsx index c5f19532f03..e8e8598cd2b 100644 --- a/apps/studio/pages/project/[ref]/api/graphiql.tsx +++ b/apps/studio/pages/project/[ref]/api/graphiql.tsx @@ -18,7 +18,7 @@ import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-ex import { API_URL, IS_PLATFORM } from 'lib/constants' import { getRoleImpersonationJWT } from 'lib/role-impersonation' import { useGetImpersonatedRole } from 'state/role-impersonation-state' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const GraphiQLPage: NextPageWithLayout = () => { const { resolvedTheme } = useTheme() diff --git a/apps/studio/pages/project/[ref]/api/index.tsx b/apps/studio/pages/project/[ref]/api/index.tsx index 3e83002e03d..899fa9ef981 100644 --- a/apps/studio/pages/project/[ref]/api/index.tsx +++ b/apps/studio/pages/project/[ref]/api/index.tsx @@ -9,7 +9,7 @@ import { DocsLayout } from 'components/layouts' import { useProjectApiQuery } from 'data/config/project-api-query' import { useProjectJsonSchemaQuery } from 'data/docs/project-json-schema-query' import { snakeToCamel } from 'lib/helpers' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageContext = createContext(null) diff --git a/apps/studio/pages/project/[ref]/auth/column-privileges.tsx b/apps/studio/pages/project/[ref]/auth/column-privileges.tsx index 973c1e2ae63..3ca71115b86 100644 --- a/apps/studio/pages/project/[ref]/auth/column-privileges.tsx +++ b/apps/studio/pages/project/[ref]/auth/column-privileges.tsx @@ -1,4 +1,4 @@ -import { PostgresRole } from '@supabase/postgres-meta' +import type { PostgresRole } from '@supabase/postgres-meta' import { useParams } from 'common' import { XIcon } from 'lucide-react' import Link from 'next/link' @@ -35,7 +35,7 @@ import { useTablesQuery } from 'data/tables/tables-query' import { useLocalStorage } from 'hooks' import { LOCAL_STORAGE_KEYS } from 'lib/constants' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { useAppStateSnapshot } from 'state/app-state' const EDITABLE_ROLES = ['authenticated', 'anon', 'service_role'] diff --git a/apps/studio/pages/project/[ref]/auth/hooks.tsx b/apps/studio/pages/project/[ref]/auth/hooks.tsx index e6e13fd19f1..7713c734dce 100644 --- a/apps/studio/pages/project/[ref]/auth/hooks.tsx +++ b/apps/studio/pages/project/[ref]/auth/hooks.tsx @@ -6,7 +6,7 @@ import { AuthLayout } from 'components/layouts' import { FormsContainer } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const Hooks: NextPageWithLayout = () => { const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') diff --git a/apps/studio/pages/project/[ref]/auth/index.tsx b/apps/studio/pages/project/[ref]/auth/index.tsx index 4544e8a6cdb..b6252441731 100644 --- a/apps/studio/pages/project/[ref]/auth/index.tsx +++ b/apps/studio/pages/project/[ref]/auth/index.tsx @@ -1,7 +1,7 @@ import { observer } from 'mobx-react-lite' import { AuthLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const Authentication: NextPageWithLayout = () => { return <>{/*

Use this as a template for authentication pages

*/} diff --git a/apps/studio/pages/project/[ref]/auth/policies.tsx b/apps/studio/pages/project/[ref]/auth/policies.tsx index f3cc4c7e0ca..86b2e177206 100644 --- a/apps/studio/pages/project/[ref]/auth/policies.tsx +++ b/apps/studio/pages/project/[ref]/auth/policies.tsx @@ -1,5 +1,5 @@ import * as Tooltip from '@radix-ui/react-tooltip' -import { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta' +import type { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { partition } from 'lodash' import { useEffect, useState } from 'react' @@ -20,7 +20,7 @@ import { useTablesQuery } from 'data/tables/tables-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { Button, IconExternalLink, IconSearch, Input } from 'ui' /** diff --git a/apps/studio/pages/project/[ref]/auth/providers.tsx b/apps/studio/pages/project/[ref]/auth/providers.tsx index ea9d2e25a11..93c03890799 100644 --- a/apps/studio/pages/project/[ref]/auth/providers.tsx +++ b/apps/studio/pages/project/[ref]/auth/providers.tsx @@ -5,7 +5,7 @@ import { AuthLayout } from 'components/layouts' import { FormsContainer } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') diff --git a/apps/studio/pages/project/[ref]/auth/rate-limits.tsx b/apps/studio/pages/project/[ref]/auth/rate-limits.tsx index 2ed9bff964f..705a81047ef 100644 --- a/apps/studio/pages/project/[ref]/auth/rate-limits.tsx +++ b/apps/studio/pages/project/[ref]/auth/rate-limits.tsx @@ -5,7 +5,7 @@ import { AuthLayout } from 'components/layouts' import { FormsContainer } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') diff --git a/apps/studio/pages/project/[ref]/auth/templates.tsx b/apps/studio/pages/project/[ref]/auth/templates.tsx index f403d698ed0..0710001fff7 100644 --- a/apps/studio/pages/project/[ref]/auth/templates.tsx +++ b/apps/studio/pages/project/[ref]/auth/templates.tsx @@ -5,7 +5,7 @@ import { AuthLayout } from 'components/layouts' import { FormsContainer } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') diff --git a/apps/studio/pages/project/[ref]/auth/url-configuration.tsx b/apps/studio/pages/project/[ref]/auth/url-configuration.tsx index e910d8ab261..560632d38ae 100644 --- a/apps/studio/pages/project/[ref]/auth/url-configuration.tsx +++ b/apps/studio/pages/project/[ref]/auth/url-configuration.tsx @@ -6,7 +6,7 @@ import { AuthLayout } from 'components/layouts' import { FormsContainer } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const URLConfiguration: NextPageWithLayout = () => { const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') diff --git a/apps/studio/pages/project/[ref]/auth/users.tsx b/apps/studio/pages/project/[ref]/auth/users.tsx index 1767354d942..45a315c1131 100644 --- a/apps/studio/pages/project/[ref]/auth/users.tsx +++ b/apps/studio/pages/project/[ref]/auth/users.tsx @@ -1,6 +1,6 @@ import { Users } from 'components/interfaces/Auth/Users' import { AuthLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const UsersPage: NextPageWithLayout = () => { return diff --git a/apps/studio/pages/project/[ref]/branches.tsx b/apps/studio/pages/project/[ref]/branches.tsx index dd2573bdab4..cd3e6b107cd 100644 --- a/apps/studio/pages/project/[ref]/branches.tsx +++ b/apps/studio/pages/project/[ref]/branches.tsx @@ -1,6 +1,6 @@ import BranchManagement from 'components/interfaces/BranchManagement/BranchManagement' import { ProjectLayoutWithAuth } from 'components/layouts/ProjectLayout/ProjectLayout' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const BranchManagementPage: NextPageWithLayout = () => { return diff --git a/apps/studio/pages/project/[ref]/building.tsx b/apps/studio/pages/project/[ref]/building.tsx index 88255e3d491..e1e600e0089 100644 --- a/apps/studio/pages/project/[ref]/building.tsx +++ b/apps/studio/pages/project/[ref]/building.tsx @@ -1,7 +1,7 @@ import { ProjectLayoutWithAuth } from 'components/layouts/ProjectLayout/ProjectLayout' import { useRouter } from 'next/router' import { useEffect } from 'react' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ProjectBuildingPage: NextPageWithLayout = () => { return diff --git a/apps/studio/pages/project/[ref]/database/backups/pitr.tsx b/apps/studio/pages/project/[ref]/database/backups/pitr.tsx index 0f6f7c1036c..7e8b641d68a 100644 --- a/apps/studio/pages/project/[ref]/database/backups/pitr.tsx +++ b/apps/studio/pages/project/[ref]/database/backups/pitr.tsx @@ -10,7 +10,7 @@ import UpgradeToPro from 'components/ui/UpgradeToPro' import { useBackupsQuery } from 'data/database/backups-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useCheckPermissions, usePermissionsLoaded, useSelectedOrganization } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import DatabaseBackupsNav from 'components/interfaces/Database/Backups/DatabaseBackupsNav' const DatabasePhysicalBackups: NextPageWithLayout = () => { diff --git a/apps/studio/pages/project/[ref]/database/backups/scheduled.tsx b/apps/studio/pages/project/[ref]/database/backups/scheduled.tsx index 9ca82a280f6..d702ce67417 100644 --- a/apps/studio/pages/project/[ref]/database/backups/scheduled.tsx +++ b/apps/studio/pages/project/[ref]/database/backups/scheduled.tsx @@ -11,7 +11,7 @@ import NoPermission from 'components/ui/NoPermission' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useBackupsQuery } from 'data/database/backups-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { IconInfo, Tabs } from 'ui' import DatabaseBackupsNav from 'components/interfaces/Database/Backups/DatabaseBackupsNav' diff --git a/apps/studio/pages/project/[ref]/database/extensions.tsx b/apps/studio/pages/project/[ref]/database/extensions.tsx index 171528d9333..c982c9dd42d 100644 --- a/apps/studio/pages/project/[ref]/database/extensions.tsx +++ b/apps/studio/pages/project/[ref]/database/extensions.tsx @@ -5,7 +5,7 @@ import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const DatabaseExtensions: NextPageWithLayout = () => { const canReadExtensions = useCheckPermissions( diff --git a/apps/studio/pages/project/[ref]/database/functions.tsx b/apps/studio/pages/project/[ref]/database/functions.tsx index 47765d795f0..bf2d66c8f28 100644 --- a/apps/studio/pages/project/[ref]/database/functions.tsx +++ b/apps/studio/pages/project/[ref]/database/functions.tsx @@ -7,7 +7,7 @@ import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const FunctionsPage: NextPageWithLayout = () => { const [selectedFunction, setSelectedFunction] = useState() diff --git a/apps/studio/pages/project/[ref]/database/hooks.tsx b/apps/studio/pages/project/[ref]/database/hooks.tsx index 1ff5a7484a9..1d54496413a 100644 --- a/apps/studio/pages/project/[ref]/database/hooks.tsx +++ b/apps/studio/pages/project/[ref]/database/hooks.tsx @@ -14,7 +14,7 @@ import NoPermission from 'components/ui/NoPermission' import { useHooksEnableMutation } from 'data/database/hooks-enable-mutation' import { useSchemasQuery } from 'data/database/schemas-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const HooksPage: NextPageWithLayout = () => { const { project } = useProjectContext() diff --git a/apps/studio/pages/project/[ref]/database/index.tsx b/apps/studio/pages/project/[ref]/database/index.tsx index e5d224ba985..8580eef05bd 100644 --- a/apps/studio/pages/project/[ref]/database/index.tsx +++ b/apps/studio/pages/project/[ref]/database/index.tsx @@ -1,5 +1,5 @@ import { DatabaseLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const Database: NextPageWithLayout = () => { return <>{/*

Use this as a page template for database

*/} diff --git a/apps/studio/pages/project/[ref]/database/indexes.tsx b/apps/studio/pages/project/[ref]/database/indexes.tsx index 97c834a167e..72c8b34d418 100644 --- a/apps/studio/pages/project/[ref]/database/indexes.tsx +++ b/apps/studio/pages/project/[ref]/database/indexes.tsx @@ -1,7 +1,7 @@ import Indexes from 'components/interfaces/Database/Indexes/Indexes' import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const IndexesPage: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/database/migrations.tsx b/apps/studio/pages/project/[ref]/database/migrations.tsx index 9d7fc9bc9a0..9e8f9061dae 100644 --- a/apps/studio/pages/project/[ref]/database/migrations.tsx +++ b/apps/studio/pages/project/[ref]/database/migrations.tsx @@ -1,7 +1,7 @@ import Migrations from 'components/interfaces/Database/Migrations/Migrations' import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const MigrationsPage: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/database/replication.tsx b/apps/studio/pages/project/[ref]/database/replication.tsx index e6dcabcc7ee..68bb20bab86 100644 --- a/apps/studio/pages/project/[ref]/database/replication.tsx +++ b/apps/studio/pages/project/[ref]/database/replication.tsx @@ -8,7 +8,7 @@ import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import NoPermission from 'components/ui/NoPermission' import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' // [Joshen] Technically, best that we have these as separate URLs // makes it easier to manage state, but foresee that this page might diff --git a/apps/studio/pages/project/[ref]/database/roles.tsx b/apps/studio/pages/project/[ref]/database/roles.tsx index 133f57e796e..6d4f48871ad 100644 --- a/apps/studio/pages/project/[ref]/database/roles.tsx +++ b/apps/studio/pages/project/[ref]/database/roles.tsx @@ -1,7 +1,7 @@ import { RolesList } from 'components/interfaces/Database' import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const DatabaseRoles: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/database/schemas.tsx b/apps/studio/pages/project/[ref]/database/schemas.tsx index 5563db13520..390eea29f1f 100644 --- a/apps/studio/pages/project/[ref]/database/schemas.tsx +++ b/apps/studio/pages/project/[ref]/database/schemas.tsx @@ -8,7 +8,7 @@ import AlertError from 'components/ui/AlertError' import SchemaSelector from 'components/ui/SchemaSelector' import { useSchemasQuery } from 'data/database/schemas-query' import { EXCLUDED_SCHEMAS } from 'lib/constants/schemas' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const SchemasPage: NextPageWithLayout = () => { const { project } = useProjectContext() diff --git a/apps/studio/pages/project/[ref]/database/tables.tsx b/apps/studio/pages/project/[ref]/database/tables.tsx index 3401501391b..96804803cd2 100644 --- a/apps/studio/pages/project/[ref]/database/tables.tsx +++ b/apps/studio/pages/project/[ref]/database/tables.tsx @@ -1,15 +1,15 @@ import { useParams } from 'common' import { useState } from 'react' -import { PostgresTable } from '@supabase/postgres-meta' +import type { PostgresTable } from '@supabase/postgres-meta' import { ColumnList, TableList } from 'components/interfaces/Database' import { SidePanelEditor } from 'components/interfaces/TableGridEditor' import DeleteConfirmationDialogs from 'components/interfaces/TableGridEditor/DeleteConfirmationDialogs' import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' -import { Table } from 'data/tables/table-query' +import type { Table } from 'data/tables/table-query' import { useTableEditorStateSnapshot } from 'state/table-editor' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import useTable from 'hooks/misc/useTable' const DatabaseTables: NextPageWithLayout = () => { diff --git a/apps/studio/pages/project/[ref]/database/triggers.tsx b/apps/studio/pages/project/[ref]/database/triggers.tsx index dd363817016..4fd2c098dce 100644 --- a/apps/studio/pages/project/[ref]/database/triggers.tsx +++ b/apps/studio/pages/project/[ref]/database/triggers.tsx @@ -7,7 +7,7 @@ import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const TriggersPage: NextPageWithLayout = () => { const [selectedTrigger, setSelectedTrigger] = useState() diff --git a/apps/studio/pages/project/[ref]/database/types.tsx b/apps/studio/pages/project/[ref]/database/types.tsx index 6edecf41260..450b9a8fee3 100644 --- a/apps/studio/pages/project/[ref]/database/types.tsx +++ b/apps/studio/pages/project/[ref]/database/types.tsx @@ -9,7 +9,7 @@ import { ScaffoldSectionContent, ScaffoldSectionDetail, } from 'components/layouts/Scaffold' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const DatabaseEnumeratedTypes: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/database/wrappers/[id].tsx b/apps/studio/pages/project/[ref]/database/wrappers/[id].tsx index d7fca6009d8..1259a2c67ed 100644 --- a/apps/studio/pages/project/[ref]/database/wrappers/[id].tsx +++ b/apps/studio/pages/project/[ref]/database/wrappers/[id].tsx @@ -4,7 +4,7 @@ import { EditWrapper } from 'components/interfaces/Database' import { DatabaseLayout } from 'components/layouts' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const DatabaseWrappersNew: NextPageWithLayout = () => { const canReadWrappers = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'wrappers') diff --git a/apps/studio/pages/project/[ref]/database/wrappers/index.tsx b/apps/studio/pages/project/[ref]/database/wrappers/index.tsx index 77da4de2ac5..7b18ac978df 100644 --- a/apps/studio/pages/project/[ref]/database/wrappers/index.tsx +++ b/apps/studio/pages/project/[ref]/database/wrappers/index.tsx @@ -5,7 +5,7 @@ import { DatabaseLayout } from 'components/layouts' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const DatabaseWrappers: NextPageWithLayout = () => { const canReadWrappers = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'tables') diff --git a/apps/studio/pages/project/[ref]/database/wrappers/new.tsx b/apps/studio/pages/project/[ref]/database/wrappers/new.tsx index 4aa779c2906..0ca29ffc4c0 100644 --- a/apps/studio/pages/project/[ref]/database/wrappers/new.tsx +++ b/apps/studio/pages/project/[ref]/database/wrappers/new.tsx @@ -4,7 +4,7 @@ import { CreateWrapper } from 'components/interfaces/Database' import { DatabaseLayout } from 'components/layouts' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const DatabaseWrappersNew: NextPageWithLayout = () => { const canCreateWrappers = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') diff --git a/apps/studio/pages/project/[ref]/editor/[id].tsx b/apps/studio/pages/project/[ref]/editor/[id].tsx index 1b84514ea61..f392a1f4e77 100644 --- a/apps/studio/pages/project/[ref]/editor/[id].tsx +++ b/apps/studio/pages/project/[ref]/editor/[id].tsx @@ -6,7 +6,7 @@ import { TableEditorLayout } from 'components/layouts' import { ProjectContextFromParamsProvider } from 'components/layouts/ProjectLayout/ProjectContext' import useTable from 'hooks/misc/useTable' import { useRouter } from 'next/router' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const TableEditorPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/project/[ref]/editor/index.tsx b/apps/studio/pages/project/[ref]/editor/index.tsx index 55c2cfe0189..f5773b81f96 100644 --- a/apps/studio/pages/project/[ref]/editor/index.tsx +++ b/apps/studio/pages/project/[ref]/editor/index.tsx @@ -4,8 +4,8 @@ import { useParams } from 'common' import { EmptyState, SidePanelEditor } from 'components/interfaces/TableGridEditor' import { TableEditorLayout } from 'components/layouts' import { ProjectContextFromParamsProvider } from 'components/layouts/ProjectLayout/ProjectContext' -import { Table } from 'data/tables/table-query' -import { NextPageWithLayout } from 'types' +import type { Table } from 'data/tables/table-query' +import type { NextPageWithLayout } from 'types' const TableEditorPage: NextPageWithLayout = () => { const { ref: projectRef } = useParams() diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx index 030918419f7..88e563b343f 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/details.tsx @@ -1,6 +1,6 @@ import { EdgeFunctionDetails } from 'components/interfaces/Functions' import FunctionsLayout from 'components/layouts/FunctionsLayout' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => PageLayout.getLayout = (page) => {page} diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx index 1ddd875a970..0316665378a 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/index.tsx @@ -17,7 +17,7 @@ import { useFunctionsResourceUsageQuery } from 'data/analytics/functions-resourc import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' import { useCheckPermissions } from 'hooks' import useFillTimeseriesSorted from 'hooks/analytics/useFillTimeseriesSorted' -import { ChartIntervals, NextPageWithLayout } from 'types' +import type { ChartIntervals, NextPageWithLayout } from 'types' const CHART_INTERVALS: ChartIntervals[] = [ { diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx index 409d295fb8a..94d90a18b09 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/invocations.tsx @@ -3,7 +3,7 @@ import { useParams } from 'common' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import FunctionsLayout from 'components/layouts/FunctionsLayout' import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' /** * Placeholder page for logs previewers until we figure out where to slot them diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx index 404985c654a..429241aeda1 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/logs.tsx @@ -1,5 +1,5 @@ import { observer } from 'mobx-react-lite' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { useParams } from 'common/hooks' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import FunctionsLayout from 'components/layouts/FunctionsLayout' diff --git a/apps/studio/pages/project/[ref]/functions/index.tsx b/apps/studio/pages/project/[ref]/functions/index.tsx index fb4755a8794..bfd9e6b3260 100644 --- a/apps/studio/pages/project/[ref]/functions/index.tsx +++ b/apps/studio/pages/project/[ref]/functions/index.tsx @@ -12,7 +12,7 @@ import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { const { ref } = useParams() diff --git a/apps/studio/pages/project/[ref]/index.tsx b/apps/studio/pages/project/[ref]/index.tsx index a64e832739a..2e6b233a64c 100644 --- a/apps/studio/pages/project/[ref]/index.tsx +++ b/apps/studio/pages/project/[ref]/index.tsx @@ -12,7 +12,7 @@ import ProjectUpgradeFailedBanner from 'components/ui/ProjectUpgradeFailedBanner import { useSelectedProject } from 'hooks' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const Home: NextPageWithLayout = () => { const project = useSelectedProject() diff --git a/apps/studio/pages/project/[ref]/logs/auth-logs.tsx b/apps/studio/pages/project/[ref]/logs/auth-logs.tsx index de0f83e1d43..61ba4ceaddb 100644 --- a/apps/studio/pages/project/[ref]/logs/auth-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/auth-logs.tsx @@ -5,7 +5,7 @@ import { LogsLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const LogsPage: NextPageWithLayout = () => { const { project } = useProjectContext() diff --git a/apps/studio/pages/project/[ref]/logs/edge-logs.tsx b/apps/studio/pages/project/[ref]/logs/edge-logs.tsx index 94fc37d0a85..4d2c517b187 100644 --- a/apps/studio/pages/project/[ref]/logs/edge-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/edge-logs.tsx @@ -2,7 +2,7 @@ import { useRouter } from 'next/router' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import { LogsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx index 0980bc94b3c..23d42bef428 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx @@ -37,7 +37,7 @@ import useLogsQuery from 'hooks/analytics/useLogsQuery' import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt' import { LOCAL_STORAGE_KEYS } from 'lib/constants' import { uuidv4 } from 'lib/helpers' -import { LogSqlSnippets, NextPageWithLayout } from 'types' +import type { LogSqlSnippets, NextPageWithLayout } from 'types' const PLACEHOLDER_QUERY = 'select\n cast(timestamp as datetime) as timestamp,\n event_message, metadata \nfrom edge_logs \nlimit 5' diff --git a/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx b/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx index 23f0851b43b..65d3cd86987 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/recent.tsx @@ -7,7 +7,7 @@ import LogsLayout from 'components/layouts/LogsLayout/LogsLayout' import Table from 'components/to-be-cleaned/Table' import LogsExplorerHeader from 'components/ui/Logs/LogsExplorerHeader' import { useLocalStorage } from 'hooks' -import { LogSqlSnippets, NextPageWithLayout } from 'types' +import type { LogSqlSnippets, NextPageWithLayout } from 'types' export const LogsSavedPage: NextPageWithLayout = () => { const { ref } = useParams() diff --git a/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx b/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx index 6b121f1ae30..6549bb5823f 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/saved.tsx @@ -7,7 +7,7 @@ import { LogsLayout } from 'components/layouts' import Table from 'components/to-be-cleaned/Table' import LogsExplorerHeader from 'components/ui/Logs/LogsExplorerHeader' import { useContentQuery } from 'data/content/content-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' export const LogsSavedPage: NextPageWithLayout = () => { const { ref } = useParams() diff --git a/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx b/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx index 59e3814d89b..633da843ac6 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/templates.tsx @@ -6,7 +6,7 @@ import { LogTemplate, TEMPLATES } from 'components/interfaces/Settings/Logs' import LogsLayout from 'components/layouts/LogsLayout/LogsLayout' import CardButton from 'components/ui/CardButton' import LogsExplorerHeader from 'components/ui/Logs/LogsExplorerHeader' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' export const LogsTemplatesPage: NextPageWithLayout = () => { const { ref: projectRef } = useParams() diff --git a/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx b/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx index 1b69384a7e1..ac8d3c81a2a 100644 --- a/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/pooler-logs.tsx @@ -4,7 +4,7 @@ import { LogsTableName } from 'components/interfaces/Settings/Logs' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import { LogsLayout } from 'components/layouts' import { usePoolingConfigurationQuery } from 'data/database/pooling-configuration-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { Loading } from 'components/ui/Loading' export const LogPage: NextPageWithLayout = () => { diff --git a/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx b/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx index 796854e036d..e8277e57f10 100644 --- a/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/postgres-logs.tsx @@ -2,7 +2,7 @@ import { useRouter } from 'next/router' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import { LogsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx b/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx index e3499994612..9d265ead1dc 100644 --- a/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/postgrest-logs.tsx @@ -3,7 +3,7 @@ import { useRouter } from 'next/router' import { LogsTableName } from 'components/interfaces/Settings/Logs' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import { LogsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx b/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx index 06a216fad65..edc0fbff207 100644 --- a/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/realtime-logs.tsx @@ -2,7 +2,7 @@ import { useRouter } from 'next/router' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import { LogsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/project/[ref]/logs/storage-logs.tsx b/apps/studio/pages/project/[ref]/logs/storage-logs.tsx index 40b8ee28b31..3aceb7b19a9 100644 --- a/apps/studio/pages/project/[ref]/logs/storage-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/storage-logs.tsx @@ -2,7 +2,7 @@ import { useRouter } from 'next/router' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import { LogsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' export const LogPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/project/[ref]/realtime/inspector.tsx b/apps/studio/pages/project/[ref]/realtime/inspector.tsx index e23f5f7f97c..3d3c3efe2f2 100644 --- a/apps/studio/pages/project/[ref]/realtime/inspector.tsx +++ b/apps/studio/pages/project/[ref]/realtime/inspector.tsx @@ -1,5 +1,5 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { RealtimeInspector } from 'components/interfaces/Realtime/Inspector' import RealtimeLayout from 'components/layouts/RealtimeLayout/RealtimeLayout' diff --git a/apps/studio/pages/project/[ref]/reports/[id].tsx b/apps/studio/pages/project/[ref]/reports/[id].tsx index 05069cb2c68..fd048568f65 100644 --- a/apps/studio/pages/project/[ref]/reports/[id].tsx +++ b/apps/studio/pages/project/[ref]/reports/[id].tsx @@ -1,7 +1,7 @@ import Reports from 'components/interfaces/Reports/Reports' import { ReportsLayout } from 'components/layouts' import EditReportModal from 'components/to-be-cleaned/Reports/EditReportModal' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => ( <> diff --git a/apps/studio/pages/project/[ref]/reports/database.tsx b/apps/studio/pages/project/[ref]/reports/database.tsx index 08308123808..e55d4e0983b 100644 --- a/apps/studio/pages/project/[ref]/reports/database.tsx +++ b/apps/studio/pages/project/[ref]/reports/database.tsx @@ -20,10 +20,10 @@ import DateRangePicker from 'components/to-be-cleaned/DateRangePicker' import Table from 'components/to-be-cleaned/Table' import Panel from 'components/ui/Panel' import { useDatabaseSizeQuery } from 'data/database/database-size-query' -import { DbQueryHook } from 'hooks/analytics/useDbQuery' +import type { DbQueryHook } from 'hooks/analytics/useDbQuery' import { TIME_PERIODS_INFRA } from 'lib/constants/metrics' import { formatBytes } from 'lib/helpers' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const DatabaseReport: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/reports/index.tsx b/apps/studio/pages/project/[ref]/reports/index.tsx index 5bf2027ab5f..bbcb2d7d49c 100644 --- a/apps/studio/pages/project/[ref]/reports/index.tsx +++ b/apps/studio/pages/project/[ref]/reports/index.tsx @@ -10,7 +10,7 @@ import { Loading } from 'components/ui/Loading' import { useCheckPermissions, useStore } from 'hooks' import { useProfile } from 'lib/profile' import { useProjectContentStore } from 'stores/projectContentStore' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { CreateReportModal } from 'components/interfaces/Reports/Reports.CreateReportModal' export const UserReportPage: NextPageWithLayout = () => { diff --git a/apps/studio/pages/project/[ref]/reports/query-performance.tsx b/apps/studio/pages/project/[ref]/reports/query-performance.tsx index 224d28e89ac..ac235d68aa5 100644 --- a/apps/studio/pages/project/[ref]/reports/query-performance.tsx +++ b/apps/studio/pages/project/[ref]/reports/query-performance.tsx @@ -34,7 +34,7 @@ import Table from 'components/to-be-cleaned/Table' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { executeSql } from 'data/sql/execute-sql-query' import { useFlag } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' type QueryPerformancePreset = 'time' | 'frequent' | 'slowest' diff --git a/apps/studio/pages/project/[ref]/reports/storage.tsx b/apps/studio/pages/project/[ref]/reports/storage.tsx index fc77bdd08d1..80a147f492e 100644 --- a/apps/studio/pages/project/[ref]/reports/storage.tsx +++ b/apps/studio/pages/project/[ref]/reports/storage.tsx @@ -1,5 +1,5 @@ import { observer } from 'mobx-react-lite' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { ReportsLayout } from 'components/layouts' import { PRESET_CONFIG, diff --git a/apps/studio/pages/project/[ref]/settings/addons.tsx b/apps/studio/pages/project/[ref]/settings/addons.tsx index b6c18133f2d..f2ecf92b3d0 100644 --- a/apps/studio/pages/project/[ref]/settings/addons.tsx +++ b/apps/studio/pages/project/[ref]/settings/addons.tsx @@ -1,6 +1,6 @@ import Addons from 'components/interfaces/Settings/Addons/Addons' import { SettingsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ProjectAddons: NextPageWithLayout = () => { return diff --git a/apps/studio/pages/project/[ref]/settings/api.tsx b/apps/studio/pages/project/[ref]/settings/api.tsx index 658356e69e4..2f4446fdaf2 100644 --- a/apps/studio/pages/project/[ref]/settings/api.tsx +++ b/apps/studio/pages/project/[ref]/settings/api.tsx @@ -1,6 +1,6 @@ import ServiceList from 'components/interfaces/Settings/API/ServiceList' import { SettingsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ApiSettings: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/settings/auth.tsx b/apps/studio/pages/project/[ref]/settings/auth.tsx index a96017e7b15..4183bf35886 100644 --- a/apps/studio/pages/project/[ref]/settings/auth.tsx +++ b/apps/studio/pages/project/[ref]/settings/auth.tsx @@ -10,7 +10,7 @@ import { FormHeader } from 'components/ui/Forms' import NoPermission from 'components/ui/NoPermission' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useCheckPermissions, usePermissionsLoaded } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const AuthSettings: NextPageWithLayout = () => { const isPermissionsLoaded = usePermissionsLoaded() diff --git a/apps/studio/pages/project/[ref]/settings/billing/usage.tsx b/apps/studio/pages/project/[ref]/settings/billing/usage.tsx index 77a4e9b1624..2a84f5e0c0c 100644 --- a/apps/studio/pages/project/[ref]/settings/billing/usage.tsx +++ b/apps/studio/pages/project/[ref]/settings/billing/usage.tsx @@ -1,5 +1,5 @@ import { SettingsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { useRouter } from 'next/router' import { useEffect } from 'react' import { useSelectedOrganization } from 'hooks' diff --git a/apps/studio/pages/project/[ref]/settings/database.tsx b/apps/studio/pages/project/[ref]/settings/database.tsx index 86395618170..f4ceecc5eea 100644 --- a/apps/studio/pages/project/[ref]/settings/database.tsx +++ b/apps/studio/pages/project/[ref]/settings/database.tsx @@ -5,7 +5,7 @@ import { } from 'components/interfaces/Settings/Database' import { SettingsLayout } from 'components/layouts' import { observer } from 'mobx-react-lite' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import BannedIPs from 'components/interfaces/Settings/Database/BannedIPs' import { DatabaseReadOnlyAlert } from 'components/interfaces/Settings/Database/DatabaseReadOnlyAlert' diff --git a/apps/studio/pages/project/[ref]/settings/functions.tsx b/apps/studio/pages/project/[ref]/settings/functions.tsx index cffa8f66673..e13db6297db 100644 --- a/apps/studio/pages/project/[ref]/settings/functions.tsx +++ b/apps/studio/pages/project/[ref]/settings/functions.tsx @@ -1,6 +1,6 @@ import EdgeFunctionSecrets from 'components/interfaces/Functions/EdgeFunctionSecrets/EdgeFunctionSecrets' import { SettingsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/settings/general.tsx b/apps/studio/pages/project/[ref]/settings/general.tsx index 7d15f69fe2b..8abcbe7f75a 100644 --- a/apps/studio/pages/project/[ref]/settings/general.tsx +++ b/apps/studio/pages/project/[ref]/settings/general.tsx @@ -7,7 +7,7 @@ import { import { SettingsLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useIsFeatureEnabled } from 'hooks' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ProjectSettings: NextPageWithLayout = () => { const { project } = useProjectContext() diff --git a/apps/studio/pages/project/[ref]/settings/index.tsx b/apps/studio/pages/project/[ref]/settings/index.tsx index de9d7c708d1..80acf1c70ca 100644 --- a/apps/studio/pages/project/[ref]/settings/index.tsx +++ b/apps/studio/pages/project/[ref]/settings/index.tsx @@ -1,7 +1,7 @@ import { observer } from 'mobx-react-lite' import { SettingsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const Settings: NextPageWithLayout = () => { return <>{/*

Use this as a page template for settings pages

*/} diff --git a/apps/studio/pages/project/[ref]/settings/infrastructure.tsx b/apps/studio/pages/project/[ref]/settings/infrastructure.tsx index a5456c9de88..3c640727222 100644 --- a/apps/studio/pages/project/[ref]/settings/infrastructure.tsx +++ b/apps/studio/pages/project/[ref]/settings/infrastructure.tsx @@ -2,7 +2,7 @@ import InfrastructureActivity from 'components/interfaces/Settings/Infrastructur import InfrastructureInfo from 'components/interfaces/Settings/Infrastructure/InfrastructureInfo' import { SettingsLayout } from 'components/layouts' import { ScaffoldDivider } from 'components/layouts/Scaffold' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ProjectInfrastructure: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/settings/integrations.tsx b/apps/studio/pages/project/[ref]/settings/integrations.tsx index bb9bbc89de2..dbd9a203c0e 100644 --- a/apps/studio/pages/project/[ref]/settings/integrations.tsx +++ b/apps/studio/pages/project/[ref]/settings/integrations.tsx @@ -1,6 +1,6 @@ import IntegrationSettings from 'components/interfaces/Settings/Integrations/IntegrationsSettings' import { SettingsLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const OrgIntegrationSettings: NextPageWithLayout = () => { return diff --git a/apps/studio/pages/project/[ref]/settings/storage.tsx b/apps/studio/pages/project/[ref]/settings/storage.tsx index 96caad2fbdb..ecbcb6b4fdc 100644 --- a/apps/studio/pages/project/[ref]/settings/storage.tsx +++ b/apps/studio/pages/project/[ref]/settings/storage.tsx @@ -1,6 +1,6 @@ import { SettingsLayout } from 'components/layouts' import { StorageSettings } from 'components/to-be-cleaned/Storage' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/project/[ref]/settings/vault/keys.tsx b/apps/studio/pages/project/[ref]/settings/vault/keys.tsx index a3716a453bf..20d4f47830b 100644 --- a/apps/studio/pages/project/[ref]/settings/vault/keys.tsx +++ b/apps/studio/pages/project/[ref]/settings/vault/keys.tsx @@ -7,7 +7,7 @@ import { SettingsLayout } from 'components/layouts' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormHeader } from 'components/ui/Forms' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import Link from 'next/link' import VaultNavTabs from 'components/interfaces/Settings/Vault/VaultNavTabs' diff --git a/apps/studio/pages/project/[ref]/settings/vault/secrets.tsx b/apps/studio/pages/project/[ref]/settings/vault/secrets.tsx index 503d5108564..8140d093233 100644 --- a/apps/studio/pages/project/[ref]/settings/vault/secrets.tsx +++ b/apps/studio/pages/project/[ref]/settings/vault/secrets.tsx @@ -6,7 +6,7 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte import { FormHeader } from 'components/ui/Forms' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import VaultNavTabs from 'components/interfaces/Settings/Vault/VaultNavTabs' const VaultSettingsSecrets: NextPageWithLayout = () => { diff --git a/apps/studio/pages/project/[ref]/sql/[id].tsx b/apps/studio/pages/project/[ref]/sql/[id].tsx index eeca39984aa..accfced29d6 100644 --- a/apps/studio/pages/project/[ref]/sql/[id].tsx +++ b/apps/studio/pages/project/[ref]/sql/[id].tsx @@ -9,7 +9,7 @@ import { useKeywordsQuery } from 'data/database/keywords-query' import { useSchemasQuery } from 'data/database/schemas-query' import { useTableColumnsQuery } from 'data/database/table-columns-query' import { useFormatQueryMutation } from 'data/sql/format-sql-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import SQLEditor from 'components/interfaces/SQLEditor/SQLEditor' import { SQLEditorLayout } from 'components/layouts' diff --git a/apps/studio/pages/project/[ref]/sql/quickstarts.tsx b/apps/studio/pages/project/[ref]/sql/quickstarts.tsx index 5b2edba2fdc..fe8ae458afe 100644 --- a/apps/studio/pages/project/[ref]/sql/quickstarts.tsx +++ b/apps/studio/pages/project/[ref]/sql/quickstarts.tsx @@ -1,5 +1,5 @@ import { observer } from 'mobx-react-lite' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { SQLEditorLayout } from 'components/layouts' import SQLQuickstarts from 'components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts' diff --git a/apps/studio/pages/project/[ref]/sql/templates.tsx b/apps/studio/pages/project/[ref]/sql/templates.tsx index 050b608233b..9a12c0a78bf 100644 --- a/apps/studio/pages/project/[ref]/sql/templates.tsx +++ b/apps/studio/pages/project/[ref]/sql/templates.tsx @@ -1,5 +1,5 @@ import { observer } from 'mobx-react-lite' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' import { SQLEditorLayout } from 'components/layouts' import SQLTemplates from 'components/interfaces/SQLEditor/SQLTemplates/SQLTemplates' diff --git a/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx b/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx index e631591593c..38559efc142 100644 --- a/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx +++ b/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx @@ -7,7 +7,7 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte import StorageBucketsError from 'components/layouts/StorageLayout/StorageBucketsError' import { StorageExplorer } from 'components/to-be-cleaned/Storage' import { useBucketsQuery } from 'data/storage/buckets-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { const { ref, bucketId } = useParams() diff --git a/apps/studio/pages/project/[ref]/storage/buckets/index.tsx b/apps/studio/pages/project/[ref]/storage/buckets/index.tsx index 072f853fb75..e92ef391bc8 100644 --- a/apps/studio/pages/project/[ref]/storage/buckets/index.tsx +++ b/apps/studio/pages/project/[ref]/storage/buckets/index.tsx @@ -5,7 +5,7 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte import StorageBucketsError from 'components/layouts/StorageLayout/StorageBucketsError' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import { useBucketsQuery } from 'data/storage/buckets-query' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' /** * PageLayout is used to setup layout - as usual it will requires inject global store diff --git a/apps/studio/pages/project/[ref]/storage/index.tsx b/apps/studio/pages/project/[ref]/storage/index.tsx index 884d5909fff..23206ef662a 100644 --- a/apps/studio/pages/project/[ref]/storage/index.tsx +++ b/apps/studio/pages/project/[ref]/storage/index.tsx @@ -1,7 +1,7 @@ import { observer } from 'mobx-react-lite' import { StorageLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const Storage: NextPageWithLayout = () => { return <>{/*

Use this as a template for storage pages

*/} diff --git a/apps/studio/pages/project/[ref]/storage/policies.tsx b/apps/studio/pages/project/[ref]/storage/policies.tsx index 2a99d20adac..f0cbe7b0b8d 100644 --- a/apps/studio/pages/project/[ref]/storage/policies.tsx +++ b/apps/studio/pages/project/[ref]/storage/policies.tsx @@ -1,6 +1,6 @@ import { StorageLayout } from 'components/layouts' import { StoragePolicies } from 'components/to-be-cleaned/Storage' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const StoragePoliciesPage: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/projects.tsx b/apps/studio/pages/projects.tsx index 05ebe5d58c0..9a2fc5231f0 100644 --- a/apps/studio/pages/projects.tsx +++ b/apps/studio/pages/projects.tsx @@ -10,7 +10,7 @@ import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useAutoProjectsPrefetch } from 'data/projects/projects-query' import { useFlag, useIsFeatureEnabled } from 'hooks' import { IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ProjectsPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/reset-password.tsx b/apps/studio/pages/reset-password.tsx index f691d5a91e7..d8dbf7bcd8f 100644 --- a/apps/studio/pages/reset-password.tsx +++ b/apps/studio/pages/reset-password.tsx @@ -2,7 +2,7 @@ import ResetPasswordForm from 'components/interfaces/SignIn/ResetPasswordForm' import { ForgotPasswordLayout } from 'components/layouts' import { withAuth } from 'hooks' import Link from 'next/link' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const ResetPasswordPage: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/sign-in-mfa.tsx b/apps/studio/pages/sign-in-mfa.tsx index d72348b7431..1eeb20fe3be 100644 --- a/apps/studio/pages/sign-in-mfa.tsx +++ b/apps/studio/pages/sign-in-mfa.tsx @@ -9,7 +9,7 @@ import { SignInLayout } from 'components/layouts' import { Loading } from 'components/ui/Loading' import { auth, buildPathWithParams, getAccessToken, getReturnToPath } from 'lib/gotrue' import Telemetry from 'lib/telemetry' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const SignInMfaPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/sign-in-sso.tsx b/apps/studio/pages/sign-in-sso.tsx index fe1896dfc5b..348d36f5ba7 100644 --- a/apps/studio/pages/sign-in-sso.tsx +++ b/apps/studio/pages/sign-in-sso.tsx @@ -1,6 +1,6 @@ import SignInSSOForm from 'components/interfaces/SignIn/SignInSSOForm' import { SignInLayout } from 'components/layouts' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const SignInSSOPage: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/sign-in.tsx b/apps/studio/pages/sign-in.tsx index 6609705ddb5..e9d03e1caea 100644 --- a/apps/studio/pages/sign-in.tsx +++ b/apps/studio/pages/sign-in.tsx @@ -7,7 +7,7 @@ import { SignInLayout } from 'components/layouts' import { IS_PLATFORM } from 'lib/constants' import { useRouter } from 'next/router' import { useEffect } from 'react' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const SignInPage: NextPageWithLayout = () => { const router = useRouter() diff --git a/apps/studio/pages/sign-up.tsx b/apps/studio/pages/sign-up.tsx index 81e9aff76a3..4dc6e50ad33 100644 --- a/apps/studio/pages/sign-up.tsx +++ b/apps/studio/pages/sign-up.tsx @@ -2,7 +2,7 @@ import SignInWithGitHub from 'components/interfaces/SignIn/SignInWithGitHub' import SignUpForm from 'components/interfaces/SignIn/SignUpForm' import { SignInLayout } from 'components/layouts' import Link from 'next/link' -import { NextPageWithLayout } from 'types' +import type { NextPageWithLayout } from 'types' const SignUpPage: NextPageWithLayout = () => { return ( diff --git a/apps/studio/pages/vercel/integrate.tsx b/apps/studio/pages/vercel/integrate.tsx index 04a8e2183c2..ea09d378697 100644 --- a/apps/studio/pages/vercel/integrate.tsx +++ b/apps/studio/pages/vercel/integrate.tsx @@ -6,7 +6,7 @@ import { useRouter } from 'next/router' import { ChangeEvent, createContext, useContext, useEffect, useState } from 'react' import { toast } from 'react-hot-toast' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import VercelIntegrationLayout from 'components/layouts/VercelIntegrationLayout' import { createVercelEnv, diff --git a/apps/studio/pages/vercel/setupProject.tsx b/apps/studio/pages/vercel/setupProject.tsx index c1a90490f38..4fa8bed92e3 100644 --- a/apps/studio/pages/vercel/setupProject.tsx +++ b/apps/studio/pages/vercel/setupProject.tsx @@ -7,7 +7,7 @@ import { ChangeEvent, createContext, useContext, useEffect, useRef, useState } f import { toast } from 'react-hot-toast' import { Button, Input, Listbox } from 'ui' -import { Dictionary } from 'types' +import type { Dictionary } from 'types' import VercelIntegrationLayout from 'components/layouts/VercelIntegrationLayout' import { createVercelEnv, diff --git a/apps/studio/state/sql-editor.ts b/apps/studio/state/sql-editor.ts index fdc98e1b0ab..6764bdac3ac 100644 --- a/apps/studio/state/sql-editor.ts +++ b/apps/studio/state/sql-editor.ts @@ -4,8 +4,8 @@ import { proxy, snapshot, subscribe, useSnapshot } from 'valtio' import { devtools, proxySet } from 'valtio/utils' import { upsertContent, UpsertContentPayload } from 'data/content/content-upsert-mutation' -import { SqlSnippet } from 'data/content/sql-snippets-query' -import { SqlSnippets } from 'types' +import type { SqlSnippet } from 'data/content/sql-snippets-query' +import type { SqlSnippets } from 'types' export type StateSnippet = { snippet: SqlSnippet diff --git a/apps/studio/state/table-editor.tsx b/apps/studio/state/table-editor.tsx index 4103dfcbfd1..cc1f72ea2b3 100644 --- a/apps/studio/state/table-editor.tsx +++ b/apps/studio/state/table-editor.tsx @@ -1,8 +1,8 @@ -import { PostgresColumn } from '@supabase/postgres-meta' -import { SupaRow } from 'components/grid' -import { Dictionary } from 'types' +import type { PostgresColumn } from '@supabase/postgres-meta' +import type { SupaRow } from 'components/grid' +import type { Dictionary } from 'types' import { ForeignRowSelectorProps } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector' -import { JsonEditValue } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.types' +import type { JsonEditValue } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.types' import { PropsWithChildren, createContext, useContext, useRef } from 'react' import { proxy, useSnapshot } from 'valtio' diff --git a/apps/studio/stores/RootStore.ts b/apps/studio/stores/RootStore.ts index c428eec6a4b..0f59e15a128 100644 --- a/apps/studio/stores/RootStore.ts +++ b/apps/studio/stores/RootStore.ts @@ -1,6 +1,6 @@ import { configure } from 'mobx' -import { Project } from 'data/projects/project-detail-query' +import type { Project } from 'data/projects/project-detail-query' import UiStore, { IUiStore } from './UiStore' import MetaStore, { IMetaStore } from './pgmeta/MetaStore' diff --git a/apps/studio/stores/UiStore.ts b/apps/studio/stores/UiStore.ts index 91734dd99de..345bbbb3fa8 100644 --- a/apps/studio/stores/UiStore.ts +++ b/apps/studio/stores/UiStore.ts @@ -1,8 +1,8 @@ import { action, makeAutoObservable } from 'mobx' import { uuidv4 } from 'lib/helpers' -import { Notification } from 'types' -import { IRootStore } from './RootStore' +import type { Notification } from 'types' +import type { IRootStore } from './RootStore' export interface IUiStore { language: 'en-US' diff --git a/apps/studio/stores/authConfig/schema/AuthProviders/AuthTemplatesValidation.tsx b/apps/studio/stores/authConfig/schema/AuthProviders/AuthTemplatesValidation.tsx index e14db176c22..466aa4945e5 100644 --- a/apps/studio/stores/authConfig/schema/AuthProviders/AuthTemplatesValidation.tsx +++ b/apps/studio/stores/authConfig/schema/AuthProviders/AuthTemplatesValidation.tsx @@ -1,4 +1,4 @@ -import { FormSchema } from 'types' +import type { FormSchema } from 'types' import { object, string } from 'yup' const JSON_SCHEMA_VERSION = 'http://json-schema.org/draft-07/schema#' diff --git a/apps/studio/stores/pgmeta/MetaStore.ts b/apps/studio/stores/pgmeta/MetaStore.ts index 7dee87467ad..87b23323129 100644 --- a/apps/studio/stores/pgmeta/MetaStore.ts +++ b/apps/studio/stores/pgmeta/MetaStore.ts @@ -2,9 +2,9 @@ import { makeObservable } from 'mobx' import { post } from 'lib/common/fetch' import { API_URL, IS_PLATFORM } from 'lib/constants' -import { ResponseError } from 'types' +import type { ResponseError } from 'types' -import { IRootStore } from '../RootStore' +import type { IRootStore } from '../RootStore' export interface IMetaStore { projectRef?: string diff --git a/apps/studio/stores/projectContentStore.ts b/apps/studio/stores/projectContentStore.ts index 6abf8092fe0..cac7ff84f35 100644 --- a/apps/studio/stores/projectContentStore.ts +++ b/apps/studio/stores/projectContentStore.ts @@ -1,7 +1,7 @@ import { makeObservable, observable, computed } from 'mobx' import { get, patch, post, delete_ } from 'lib/common/fetch' import { keyBy } from 'lodash' -import { UserContent } from 'types' +import type { UserContent } from 'types' import { API_URL } from 'lib/constants' /** diff --git a/apps/studio/types/next.ts b/apps/studio/types/next.ts index 440e552e411..1748d732da0 100644 --- a/apps/studio/types/next.ts +++ b/apps/studio/types/next.ts @@ -1,6 +1,6 @@ -import { NextPage } from 'next' -import { AppProps } from 'next/app' -import { ComponentType, ReactElement, ReactNode } from 'react' +import type { NextPage } from 'next' +import type { AppProps } from 'next/app' +import type { ComponentType, ReactElement, ReactNode } from 'react' export type AppPropsWithLayout = AppProps<{ dehydratedState: any }> & { Component: NextPageWithLayout From 7ce6958030508ec2acf14cba2d557c874a658546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thor=20=E9=9B=B7=E7=A5=9E=20Schaeff?= <5748289+thorwebdev@users.noreply.github.com> Date: Mon, 4 Mar 2024 22:24:32 +0800 Subject: [PATCH 38/62] feat: add rbac claim auth hook. (#21263) * feat: add rbac claim auth hook. * feat: get user role from jwt. * chore: update full-schema. * feat: add RBAC guide. * feat: use plpgsql. * Apply suggestions from code review Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * chore: make top level claim. * chore: set search_paths. * chore: accessing custom claims. --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- .../NavigationMenu.constants.ts | 4 + apps/docs/content/guides/auth/auth-hooks.mdx | 2 +- ...ims-and-role-based-access-control-rbac.mdx | 278 ++++++++ .../slack-clone/nextjs-slack-clone/README.md | 169 +---- .../nextjs-slack-clone/components/Layout.js | 7 +- .../nextjs-slack-clone/components/Message.js | 7 +- .../nextjs-slack-clone/full-schema.sql | 105 ++- .../nextjs-slack-clone/lib/Store.js | 61 +- .../nextjs-slack-clone/package-lock.json | 611 +++++------------- .../nextjs-slack-clone/package.json | 4 +- .../nextjs-slack-clone/pages/_app.js | 24 +- .../nextjs-slack-clone/supabase/.gitignore | 4 + .../nextjs-slack-clone/supabase/config.toml | 155 +++++ .../migrations/20240214102356_init.sql | 165 +++++ .../migrations/20240214114147_auth-hook.sql | 58 ++ .../nextjs-slack-clone/supabase/seed.sql | 23 + 16 files changed, 969 insertions(+), 708 deletions(-) create mode 100644 apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx create mode 100644 examples/slack-clone/nextjs-slack-clone/supabase/.gitignore create mode 100644 examples/slack-clone/nextjs-slack-clone/supabase/config.toml create mode 100644 examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214102356_init.sql create mode 100644 examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214114147_auth-hook.sql create mode 100644 examples/slack-clone/nextjs-slack-clone/supabase/seed.sql diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index b533e6779b9..3f3f3cf9754 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -607,6 +607,10 @@ export const auth = { name: 'Column Level Security', url: '/guides/auth/column-level-security', }, + { + name: 'Custom Claims & RBAC', + url: '/guides/auth/custom-claims-and-role-based-access-control-rbac', + }, ], }, { diff --git a/apps/docs/content/guides/auth/auth-hooks.mdx b/apps/docs/content/guides/auth/auth-hooks.mdx index f094433bcd6..c6a833b30fc 100644 --- a/apps/docs/content/guides/auth/auth-hooks.mdx +++ b/apps/docs/content/guides/auth/auth-hooks.mdx @@ -572,7 +572,7 @@ as $$ is_admin boolean; begin -- Check if the user is marked as admin in the profiles table - select is_admin into is_admin from profiles where user_id = event->>'user_id'::uuid; + select is_admin into is_admin from profiles where user_id = (event->>'user_id')::uuid; -- Proceed only if the user is an admin if is_admin then diff --git a/apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx b/apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx new file mode 100644 index 00000000000..b1f22158f9b --- /dev/null +++ b/apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx @@ -0,0 +1,278 @@ +--- +id: 'custom-claims-and-role-based-access-control-rbac' +title: 'Custom Claims & Role-based Access Control (RBAC)' +description: 'Use Auth Hooks to add custom claims for managing role-based access control.' +--- + +Custom Claims are special attributes attached to a user that you can use to control access to portions of your application. For example: + +```json +{ + "user_role": "admin", + "plan": "TRIAL", + "user_level": 100, + "group_name": "Super Guild!", + "joined_on": "2022-05-20T14:28:18.217Z", + "group_manager": false, + "items": ["toothpick", "string", "ring"] +} +``` + +To implement Role-Based Access Control (RBAC) with `custom claims`, use a [Custom Access Token Auth Hook](/guides/auth/auth-hooks#hook-custom-access-token). This hook runs before a token is issued. You can use it to add additional claims to the user's JWT. + +This guide uses the [Slack Clone example](https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone) to demonstrate how to add a `user_role` claim and use it in your [Row Level Security (RLS) policies](/guides/auth/row-level-security). + +## Create a table to track user roles and permissions + +In this example, you will implement two user roles with specific permissions: + +- `moderator`: A moderator can delete all messages but not channels. +- `admin`: An admin can delete all messages and channels. + +```sql supabase/migrations/init.sql +-- Custom types +create type public.app_permission as enum ('channels.delete', 'messages.delete'); +create type public.app_role as enum ('admin', 'moderator'); + +-- USER ROLES +create table public.user_roles ( + id bigint generated by default as identity primary key, + user_id uuid references public.users on delete cascade not null, + role app_role not null, + unique (user_id, role) +); +comment on table public.user_roles is 'Application roles for each user.'; + +-- ROLE PERMISSIONS +create table public.role_permissions ( + id bigint generated by default as identity primary key, + role app_role not null, + permission app_permission not null, + unique (role, permission) +); +comment on table public.role_permissions is 'Application permissions for each role.'; +``` + + + + For the [full schema](https://github.com/supabase/supabase/blob/master/examples/slack-clone/nextjs-slack-clone/README.md), see the example application on [GitHub](https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone). + + + +You can now manage your roles and permissions in SQL. For example, to add the mentioned roles and permissions from above, run: + +```sql supabase/seed.sql +insert into public.role_permissions (role, permission) +values + ('admin', 'channels.delete'), + ('admin', 'messages.delete'), + ('moderator', 'messages.delete'); +``` + +## Create Auth Hook to apply user role + +The [Custom Access Token Auth Hook](/guides/auth/auth-hooks#hook-custom-access-token) runs before a token is issued. You can use it edit the JWT. + + + + +```sql supabase/migrations/auth_hook.sql +-- Create the auth hook function +create or replace function public.custom_access_token_hook(event jsonb) +returns jsonb +language plpgsql +immutable +as $$ + declare + claims jsonb; + user_role public.app_role; + begin + -- Check if the user is marked as admin in the profiles table + select role into user_role from public.user_roles where user_id = (event->>'user_id')::uuid; + + claims := event->'claims'; + + if user_role is not null then + -- Set the claim + claims := jsonb_set(claims, '{user_role}', to_jsonb(user_role)); + else + claims := jsonb_set(claims, '{user_role}', 'null'); + end if; + + -- Update the 'claims' object in the original event + event := jsonb_set(event, '{claims}', claims); + + -- Return the modified or original event + return event; + end; +$$; + +grant usage on schema public to supabase_auth_admin; + +grant execute + on function public.custom_access_token_hook + to supabase_auth_admin; + +revoke execute + on function public.custom_access_token_hook + from authenticated, anon; + +grant all + on table public.user_roles +to supabase_auth_admin; + +revoke all + on table public.user_roles + from authenticated, anon; + +create policy "Allow auth admin to read user roles" ON public.user_roles +as permissive for select +to supabase_auth_admin +using (true) +``` + + + + +```sql supabase/migrations/auth_hook.sql +-- Enable the "plv8" extension +create extension plv8; + +-- Create the auth hook function +create or replace function custom_access_token_hook(event jsonb) +returns jsonb +language plv8 +as $$ + var user_role; + + // Fetch the current user's user_role from the public user_roles table. + var result = plv8.execute("select role from public.user_roles where user_id = $1", [event.user_id]); + if (result.length > 0) { + user_role = result[0].role; + } else { + // Assign null + user_role = null; + } + + // Check if 'claims' exists in the event object; if not, initialize it + if (!event.claims) { + event.claims = {}; + } + + // Update the level in the claims + event.claims.user_role = user_role; + + return event; +$$; + +grant usage on schema public to supabase_auth_admin; + +grant execute + on function public.custom_access_token_hook + to supabase_auth_admin; + +revoke execute + on function public.custom_access_token_hook + from authenticated, anon; + +grant all + on table public.user_roles +to supabase_auth_admin; + +revoke all + on table public.user_roles + from authenticated, anon; + +create policy "Allow auth admin to read user roles" ON public.user_roles +as permissive for select +to supabase_auth_admin +using (true) +``` + + + + +### Enable the hook + +In the dashboard, navigate to [`Authentication > Hooks (Beta)`](/dashboard/project/_/auth/hooks) and select the appropriate PostgreSQL function from the dropdown menu. + +When developing locally, follow the [local development](/guides/auth/auth-hooks#local-development) instructions. + + + +To learn more about Auth Hooks, see the [Auth Hooks docs](/guides/auth/auth-hooks). + + + +## Accessing custom claims in RLS policies + +To utilize Role-Based Access Control (RBAC) in Row Level Security (RLS) policies, create an `authorize` method that reads the user's role from their JWT and checks the role's permissions: + +```sql supabase/migrations/init.sql +create function public.authorize( + requested_permission app_permission, + user_id uuid +) +returns boolean as $$ +declare + bind_permissions int; +begin + select count(*) + from public.role_permissions + where role_permissions.permission = authorize.requested_permission + and role_permissions.role = (auth.jwt() ->> 'user_role')::public.app_role + into bind_permissions; + + return bind_permissions > 0; +end; +$$ language plpgsql security definer set search_path = public; +``` + + + +You can read more about using functions in RLS policies in the [RLS guide](/guides/auth/row-level-security#using-functions). + + + +You can then use the `authorize` method within your RLS policies. For example, to enable the desired delete access, you would add the following policies: + +```sql +create policy "Allow authorized delete access" on public.channels for delete using ( authorize('channels.delete', auth.uid()) ); +create policy "Allow authorized delete access" on public.messages for delete using ( authorize('messages.delete', auth.uid()) ); +``` + +## Accessing custom claims in your application + +The auth hook will only modify the access token JWT but not the auth response. Therefore, to access the custom claims in your application, e.g. your browser client, or server-side middleware, you will need to decode the `access_token` JWT on the auth session. + +In a JavaScript client application you can for example use the [`jwt-decode` package](https://www.npmjs.com/package/jwt-decode): + +```js +import { jwtDecode } from 'jwt-decode' + +const { subscription: authListener } = supabase.auth.onAuthStateChange(async (event, session) => { + if (session) { + const jwt = jwtDecode(session.access_token) + const userRole = jwt.user_role + } +}) +``` + +For server-side logic you can use packages like [express-jwt](https://github.com/auth0/express-jwt), [koa-jwt](https://github.com/stiang/koa-jwt), [PyJWT](https://github.com/jpadilla/pyjwt), [dart_jsonwebtoken](https://pub.dev/packages/dart_jsonwebtoken), [Microsoft.AspNetCore.Authentication.JwtBearer](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer), etc. + +## Conclusion + +You now have a robust system in place to manage user roles and permissions within your database that automatically propagates to Supabase Auth. + +## More resources + +- [Auth Hooks](/guides/auth/auth-hooks) +- [Row Level Security](/guides/auth/row-level-security) +- [RLS Functions](/guides/auth/row-level-security#using-functions) +- [Next.js Slack Clone Example](https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone) diff --git a/examples/slack-clone/nextjs-slack-clone/README.md b/examples/slack-clone/nextjs-slack-clone/README.md index 6041b6b84ea..183701a7358 100644 --- a/examples/slack-clone/nextjs-slack-clone/README.md +++ b/examples/slack-clone/nextjs-slack-clone/README.md @@ -115,173 +115,8 @@ When you start a Postgres database on Supabase, we populate it with an `auth` sc When a user logs in, they are issued a JWT with the role `authenticated` and their UUID. We can use these details to provide fine-grained control over what each user can and cannot do. -Full schema here with role-based access control: - -```sql --- --- For use with https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone --- - --- Custom types -create type public.app_permission as enum ('channels.delete', 'messages.delete'); -create type public.app_role as enum ('admin', 'moderator'); -create type public.user_status as enum ('ONLINE', 'OFFLINE'); - --- USERS -create table public.users ( - id uuid not null primary key, -- UUID from auth.users - username text, - status user_status default 'OFFLINE'::public.user_status -); -comment on table public.users is 'Profile data for each user.'; -comment on column public.users.id is 'References the internal Supabase Auth user.'; - --- CHANNELS -create table public.channels ( - id bigint generated by default as identity primary key, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, - slug text not null unique, - created_by uuid references public.users not null -); -comment on table public.channels is 'Topics and groups.'; - --- MESSAGES -create table public.messages ( - id bigint generated by default as identity primary key, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, - message text, - user_id uuid references public.users not null, - channel_id bigint references public.channels on delete cascade not null -); -comment on table public.messages is 'Individual messages sent by each user.'; - --- USER ROLES -create table public.user_roles ( - id bigint generated by default as identity primary key, - user_id uuid references public.users on delete cascade not null, - role app_role not null, - unique (user_id, role) -); -comment on table public.user_roles is 'Application roles for each user.'; - --- ROLE PERMISSIONS -create table public.role_permissions ( - id bigint generated by default as identity primary key, - role app_role not null, - permission app_permission not null, - unique (role, permission) -); -comment on table public.role_permissions is 'Application permissions for each role.'; - --- authorize with role-based access control (RBAC) -create function public.authorize( - requested_permission app_permission, - user_id uuid -) -returns boolean as $$ -declare - bind_permissions int; -begin - select count(*) - from public.role_permissions - inner join public.user_roles on role_permissions.role = user_roles.role - where role_permissions.permission = authorize.requested_permission - and user_roles.user_id = authorize.user_id - into bind_permissions; - - return bind_permissions > 0; -end; -$$ language plpgsql security definer; - --- Secure the tables -alter table public.users enable row level security; -alter table public.channels enable row level security; -alter table public.messages enable row level security; -alter table public.user_roles enable row level security; -alter table public.role_permissions enable row level security; -create policy "Allow logged-in read access" on public.users for select using ( auth.role() = 'authenticated' ); -create policy "Allow individual insert access" on public.users for insert with check ( auth.uid() = id ); -create policy "Allow individual update access" on public.users for update using ( auth.uid() = id ); -create policy "Allow logged-in read access" on public.channels for select using ( auth.role() = 'authenticated' ); -create policy "Allow individual insert access" on public.channels for insert with check ( auth.uid() = created_by ); -create policy "Allow individual delete access" on public.channels for delete using ( auth.uid() = created_by ); -create policy "Allow authorized delete access" on public.channels for delete using ( authorize('channels.delete', auth.uid()) ); -create policy "Allow logged-in read access" on public.messages for select using ( auth.role() = 'authenticated' ); -create policy "Allow individual insert access" on public.messages for insert with check ( auth.uid() = user_id ); -create policy "Allow individual update access" on public.messages for update using ( auth.uid() = user_id ); -create policy "Allow individual delete access" on public.messages for delete using ( auth.uid() = user_id ); -create policy "Allow authorized delete access" on public.messages for delete using ( authorize('messages.delete', auth.uid()) ); -create policy "Allow individual read access" on public.user_roles for select using ( auth.uid() = user_id ); - --- Send "previous data" on change -alter table public.users replica identity full; -alter table public.channels replica identity full; -alter table public.messages replica identity full; - --- inserts a row into public.users and assigns roles -create function public.handle_new_user() -returns trigger as $$ -declare is_admin boolean; -begin - insert into public.users (id, username) - values (new.id, new.email); - - select count(*) = 1 from auth.users into is_admin; - - if position('+supaadmin@' in new.email) > 0 then - insert into public.user_roles (user_id, role) values (new.id, 'admin'); - elsif position('+supamod@' in new.email) > 0 then - insert into public.user_roles (user_id, role) values (new.id, 'moderator'); - end if; - - return new; -end; -$$ language plpgsql security definer; - --- trigger the function every time a user is created -create trigger on_auth_user_created - after insert on auth.users - for each row execute procedure public.handle_new_user(); - -/** - * REALTIME SUBSCRIPTIONS - * Only allow realtime listening on public tables. - */ - -begin; - -- remove the realtime publication - drop publication if exists supabase_realtime; - - -- re-create the publication but don't enable it for any tables - create publication supabase_realtime; -commit; - --- add tables to the publication -alter publication supabase_realtime add table public.channels; -alter publication supabase_realtime add table public.messages; -alter publication supabase_realtime add table public.users; - --- DUMMY DATA -insert into public.users (id, username) -values - ('8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e', 'supabot'); - -insert into public.channels (slug, created_by) -values - ('public', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), - ('random', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); - -insert into public.messages (message, channel_id, user_id) -values - ('Hello World 👋', 1, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), - ('Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.', 2, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); - -insert into public.role_permissions (role, permission) -values - ('admin', 'channels.delete'), - ('admin', 'messages.delete'), - ('moderator', 'messages.delete'); -``` +- For the full schema refer to [full-schema.sql](./full-schema.sql). +- For documentation on Role-based Access Control, refer to the [docs](https://supabase.com/docs/guides/auth/custom-claims-and-role-based-access-control-rbac). ## Authors diff --git a/examples/slack-clone/nextjs-slack-clone/components/Layout.js b/examples/slack-clone/nextjs-slack-clone/components/Layout.js index a592e0d83be..46da4ce13dc 100644 --- a/examples/slack-clone/nextjs-slack-clone/components/Layout.js +++ b/examples/slack-clone/nextjs-slack-clone/components/Layout.js @@ -5,7 +5,7 @@ import { addChannel, deleteChannel } from '~/lib/Store' import TrashIcon from '~/components/TrashIcon' export default function Layout(props) { - const { signOut, user, userRoles } = useContext(UserContext) + const { signOut, user } = useContext(UserContext) const slugify = (text) => { return text @@ -60,7 +60,6 @@ export default function Layout(props) { key={x.id} isActiveChannel={x.id === props.activeChannelId} user={user} - userRoles={userRoles} /> ))} @@ -73,13 +72,13 @@ export default function Layout(props) { ) } -const SidebarItem = ({ channel, isActiveChannel, user, userRoles }) => ( +const SidebarItem = ({ channel, isActiveChannel, user }) => ( <>
  • {channel.slug} - {channel.id !== 1 && (channel.created_by === user?.id || userRoles.includes('admin')) && ( + {channel.id !== 1 && (channel.created_by === user?.id || user?.appRole === 'admin') && ( diff --git a/examples/slack-clone/nextjs-slack-clone/components/Message.js b/examples/slack-clone/nextjs-slack-clone/components/Message.js index 201012e089d..825bbca39aa 100644 --- a/examples/slack-clone/nextjs-slack-clone/components/Message.js +++ b/examples/slack-clone/nextjs-slack-clone/components/Message.js @@ -4,20 +4,19 @@ import { deleteMessage } from '~/lib/Store' import TrashIcon from '~/components/TrashIcon' const Message = ({ message }) => { - const { user, userRoles } = useContext(UserContext) + const { user } = useContext(UserContext) return (
    - {(user?.id === message.user_id || - userRoles.some((role) => ['admin', 'moderator'].includes(role))) && ( + {(user?.id === message.user_id || ['admin', 'moderator'].includes(user?.appRole)) && ( )}
    -

    {message.author.username}

    +

    {message?.author?.username}

    {message.message}

    diff --git a/examples/slack-clone/nextjs-slack-clone/full-schema.sql b/examples/slack-clone/nextjs-slack-clone/full-schema.sql index 58b277df895..1fafb7f5bef 100644 --- a/examples/slack-clone/nextjs-slack-clone/full-schema.sql +++ b/examples/slack-clone/nextjs-slack-clone/full-schema.sql @@ -9,7 +9,7 @@ create type public.user_status as enum ('ONLINE', 'OFFLINE'); -- USERS create table public.users ( - id uuid not null primary key, -- UUID from auth.users + id uuid references auth.users not null primary key, -- UUID from auth.users username text, status user_status default 'OFFLINE'::public.user_status ); @@ -64,14 +64,13 @@ declare begin select count(*) from public.role_permissions - inner join public.user_roles on role_permissions.role = user_roles.role where role_permissions.permission = authorize.requested_permission - and user_roles.user_id = authorize.user_id + and role_permissions.role = (auth.jwt() ->> 'user_role')::public.app_role into bind_permissions; return bind_permissions > 0; end; -$$ language plpgsql security definer; +$$ language plpgsql security definer set search_path = public; -- Secure the tables alter table public.users enable row level security; @@ -116,7 +115,7 @@ begin return new; end; -$$ language plpgsql security definer; +$$ language plpgsql security definer set search_path = auth, public; -- trigger the function every time a user is created create trigger on_auth_user_created @@ -141,24 +140,86 @@ alter publication supabase_realtime add table public.channels; alter publication supabase_realtime add table public.messages; alter publication supabase_realtime add table public.users; --- DUMMY DATA -insert into public.users (id, username) -values - ('8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e', 'supabot'); +/** + * AUTH HOOKS + * Create an auth hook to add a custom claim to the access token jwt. + */ -insert into public.channels (slug, created_by) -values - ('public', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), - ('random', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); +-- Create the auth hook function +-- https://supabase.com/docs/guides/auth/auth-hooks#hook-custom-access-token +create or replace function public.custom_access_token_hook(event jsonb) +returns jsonb +language plpgsql +immutable +as $$ + declare + claims jsonb; + user_role public.app_role; + begin + -- Check if the user is marked as admin in the profiles table + select role into user_role from public.user_roles where user_id = (event->>'user_id')::uuid; -insert into public.messages (message, channel_id, user_id) -values - ('Hello World 👋', 1, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), - ('Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.', 2, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); + claims := event->'claims'; + + if user_role is not null then + -- Set the claim + claims := jsonb_set(claims, '{user_role}', to_jsonb(user_role)); + else + claims := jsonb_set(claims, '{user_role}', 'null'); + end if; + + -- Update the 'claims' object in the original event + event := jsonb_set(event, '{claims}', claims); + + -- Return the modified or original event + return event; + end; +$$; + +grant usage on schema public to supabase_auth_admin; + +grant execute + on function public.custom_access_token_hook + to supabase_auth_admin; + +revoke execute + on function public.custom_access_token_hook + from authenticated, anon; + +grant all + on table public.user_roles +to supabase_auth_admin; + +revoke all + on table public.user_roles + from authenticated, anon; + +create policy "Allow auth admin to read user roles" ON public.user_roles +as permissive for select +to supabase_auth_admin +using (true) + + +/** + * HELPER FUNCTIONS + * Create test user helper method. + */ +create or replace function public.create_user( + email text +) returns uuid + security definer + set search_path = auth +as $$ + declare + user_id uuid; +begin + user_id := extensions.uuid_generate_v4(); -insert into public.role_permissions (role, permission) -values - ('admin', 'channels.delete'), - ('admin', 'messages.delete'), - ('moderator', 'messages.delete'); + insert into auth.users (id, email) + values (user_id, email) + returning id into user_id; + + return user_id; +end; +$$ language plpgsql; diff --git a/examples/slack-clone/nextjs-slack-clone/lib/Store.js b/examples/slack-clone/nextjs-slack-clone/lib/Store.js index c4382c872c4..545cf55e372 100644 --- a/examples/slack-clone/nextjs-slack-clone/lib/Store.js +++ b/examples/slack-clone/nextjs-slack-clone/lib/Store.js @@ -1,7 +1,10 @@ import { useState, useEffect } from 'react' -import { createPagesBrowserClient } from '@supabase/auth-helpers-nextjs' +import { createClient } from '@supabase/supabase-js' -export const supabase = createPagesBrowserClient() +export const supabase = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY +) /** * @param {number} channelId the currently selected Channel @@ -23,38 +26,28 @@ export const useStore = (props) => { // Listen for new and deleted messages const messageListener = supabase .channel('public:messages') - .on( - 'postgres_changes', - { event: 'INSERT', schema: 'public', table: 'messages' }, - (payload) => handleNewMessage(payload.new) + .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, (payload) => + handleNewMessage(payload.new) ) - .on( - 'postgres_changes', - { event: 'DELETE', schema: 'public', table: 'messages' }, - (payload) => handleDeletedMessage(payload.old) + .on('postgres_changes', { event: 'DELETE', schema: 'public', table: 'messages' }, (payload) => + handleDeletedMessage(payload.old) ) .subscribe() // Listen for changes to our users const userListener = supabase .channel('public:users') - .on( - 'postgres_changes', - { event: '*', schema: 'public', table: 'users' }, - (payload) => handleNewOrUpdatedUser(payload.new) + .on('postgres_changes', { event: '*', schema: 'public', table: 'users' }, (payload) => + handleNewOrUpdatedUser(payload.new) ) .subscribe() // Listen for new and deleted channels const channelListener = supabase .channel('public:channels') - .on( - 'postgres_changes', - { event: 'INSERT', schema: 'public', table: 'channels' }, - (payload) => handleNewChannel(payload.new) + .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'channels' }, (payload) => + handleNewChannel(payload.new) ) - .on( - 'postgres_changes', - { event: 'DELETE', schema: 'public', table: 'channels' }, - (payload) => handleDeletedChannel(payload.old) + .on('postgres_changes', { event: 'DELETE', schema: 'public', table: 'channels' }, (payload) => + handleDeletedChannel(payload.old) ) .subscribe() // Cleanup on unmount @@ -151,20 +144,6 @@ export const fetchUser = async (userId, setState) => { } } -/** - * Fetch all roles for the current user - * @param {function} setState Optionally pass in a hook or callback to set the state - */ -export const fetchUserRoles = async (setState) => { - try { - let { data } = await supabase.from('user_roles').select(`*`) - if (setState) setState(data) - return data - } catch (error) { - console.log('error', error) - } -} - /** * Fetch all messages and their authors * @param {number} channelId @@ -191,7 +170,10 @@ export const fetchMessages = async (channelId, setState) => { */ export const addChannel = async (slug, user_id) => { try { - let { data } = await supabase.from('channels').insert([{ slug, created_by: user_id }]).select() + let { data } = await supabase + .from('channels') + .insert([{ slug, created_by: user_id }]) + .select() return data } catch (error) { console.log('error', error) @@ -206,7 +188,10 @@ export const addChannel = async (slug, user_id) => { */ export const addMessage = async (message, channel_id, user_id) => { try { - let { data } = await supabase.from('messages').insert([{ message, channel_id, user_id }]).select() + let { data } = await supabase + .from('messages') + .insert([{ message, channel_id, user_id }]) + .select() return data } catch (error) { console.log('error', error) diff --git a/examples/slack-clone/nextjs-slack-clone/package-lock.json b/examples/slack-clone/nextjs-slack-clone/package-lock.json index dd187f4f898..2ac89187de9 100644 --- a/examples/slack-clone/nextjs-slack-clone/package-lock.json +++ b/examples/slack-clone/nextjs-slack-clone/package-lock.json @@ -9,8 +9,8 @@ "version": "0.2.0", "license": "MIT", "dependencies": { - "@supabase/auth-helpers-nextjs": "^0.7.2", - "@supabase/supabase-js": "^2.26.0", + "@supabase/supabase-js": "^2.39.6", + "jwt-decode": "^4.0.0", "next": "latest", "react": "^18.2.0", "react-dom": "^18.2.0" @@ -307,98 +307,90 @@ "node": ">= 8" } }, - "node_modules/@supabase/auth-helpers-nextjs": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-nextjs/-/auth-helpers-nextjs-0.7.2.tgz", - "integrity": "sha512-n5IyGBYJV/WiR5Rgw4CUaiJYiOv9yW2of4ZP4EyzKt2O6/6rztt7PcGE4AoK2vERw+fb5F2QtJBdt6J5eOYCCw==", - "dependencies": { - "@supabase/auth-helpers-shared": "0.4.1", - "set-cookie-parser": "^2.6.0" - }, - "peerDependencies": { - "@supabase/supabase-js": "^2.19.0" - } - }, - "node_modules/@supabase/auth-helpers-shared": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-shared/-/auth-helpers-shared-0.4.1.tgz", - "integrity": "sha512-IEDX9JzWkIjQiLUaP4Qy5YDiG0jFQatWfS+jw8cCQs6QfbNdEPd2Y3qonwGHnM90CZom9SvjuylBv2pFVAL7Lw==", - "dependencies": { - "jose": "^4.14.3" - }, - "peerDependencies": { - "@supabase/supabase-js": "^2.19.0" - } - }, "node_modules/@supabase/functions-js": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.1.2.tgz", - "integrity": "sha512-QCR6pwJs9exCl37bmpMisUd6mf+0SUBJ6mUpiAjEkSJ/+xW8TCuO14bvkWHADd5hElJK9MxNlMQXxSA4DRz9nQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.1.5.tgz", + "integrity": "sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw==", "dependencies": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/gotrue-js": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.38.0.tgz", - "integrity": "sha512-iitNthPLQjAD73FtnUNUalwPFpsiiE7t/0mVw14b+3rqzr52Efri8gAjzT9hi7p35uOLA76HMY3aWJj6Gy7ozw==", + "version": "2.62.2", + "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.62.2.tgz", + "integrity": "sha512-AP6e6W9rQXFTEJ7sTTNYQrNf0LCcnt1hUW+RIgUK+Uh3jbWvcIST7wAlYyNZiMlS9+PYyymWQ+Ykz/rOYSO0+A==", "dependencies": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" } }, "node_modules/@supabase/postgrest-js": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.7.1.tgz", - "integrity": "sha512-xPRYLaZrkLbXNlzmHW6Wtf9hmcBLjjI5xUz2zj8oE2hgXGaYoZBBkpN9bmW9i17Z1f6Ujxa942AqK439XOA36A==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.9.2.tgz", + "integrity": "sha512-I6yHo8CC9cxhOo6DouDMy9uOfW7hjdsnCxZiaJuIVZm1dBGTFiQPgfMa9zXCamEWzNyWRjZvupAUuX+tqcl5Sw==", "dependencies": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/realtime-js": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.7.3.tgz", - "integrity": "sha512-c7TzL81sx2kqyxsxcDduJcHL9KJdCOoKimGP6lQSqiZKX42ATlBZpWbyy9KFGFBjAP4nyopMf5JhPi2ZH9jyNw==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.9.3.tgz", + "integrity": "sha512-lAp50s2n3FhGJFq+wTSXLNIDPw5Y0Wxrgt44eM5nLSA3jZNUUP3Oq2Ccd1CbZdVntPCWLZvJaU//pAd2NE+QnQ==", "dependencies": { + "@supabase/node-fetch": "^2.6.14", "@types/phoenix": "^1.5.4", - "@types/websocket": "^1.0.3", - "websocket": "^1.0.34" + "@types/ws": "^8.5.10", + "ws": "^8.14.2" } }, "node_modules/@supabase/storage-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.1.tgz", - "integrity": "sha512-nkR0fQA9ScAtIKA3vNoPEqbZv1k5B5HVRYEvRWdlP6mUpFphM9TwPL2jZ/ztNGMTG5xT6SrHr+H7Ykz8qzbhjw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.5.tgz", + "integrity": "sha512-OpLoDRjFwClwc2cjTJZG8XviTiQH4Ik8sCiMK5v7et0MDu2QlXjCAW3ljxJB5+z/KazdMOTnySi+hysxWUPu3w==", "dependencies": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/supabase-js": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.26.0.tgz", - "integrity": "sha512-RXmTPTobaYAwkSobadHZmEVLmzX3SGrtRZIGfLWnLv92VzBRrjuXn0a+bJqKl50GUzsyqPA+j5pod7EwMkcH5A==", + "version": "2.39.6", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.39.6.tgz", + "integrity": "sha512-HlflDzem0+l3KYYTqHV0UsqkDooV9my5UcBCV2zvvTrl77UtW97uKTZWn9lSWMuiy+ZvRLsiuG+WTiBuKMQl0Q==", "dependencies": { - "@supabase/functions-js": "^2.1.0", - "@supabase/gotrue-js": "^2.31.0", - "@supabase/postgrest-js": "^1.7.0", - "@supabase/realtime-js": "^2.7.3", - "@supabase/storage-js": "^2.5.1", - "cross-fetch": "^3.1.5" + "@supabase/functions-js": "2.1.5", + "@supabase/gotrue-js": "2.62.2", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "1.9.2", + "@supabase/realtime-js": "2.9.3", + "@supabase/storage-js": "2.5.5" } }, "node_modules/@types/node": { - "version": "20.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz", - "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==" + "version": "20.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", + "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/phoenix": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.0.tgz", - "integrity": "sha512-qwfpsHmFuhAS/dVd4uBIraMxRd56vwBUYQGZ6GpXnFuM2XMRFJbIyruFKKlW2daQliuYZwe0qfn/UjFCDKic5g==" + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.4.tgz", + "integrity": "sha512-B34A7uot1Cv0XtaHRYDATltAdKx0BvVKNgYNqE4WjtPUa4VQJM7kxeXcVKaH+KS+kCmZ+6w+QaUdcljiheiBJA==" }, - "node_modules/@types/websocket": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.5.tgz", - "integrity": "sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==", + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dependencies": { "@types/node": "*" } @@ -530,18 +522,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/bufferutil": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", - "integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -612,14 +592,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/cross-fetch": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.7.tgz", - "integrity": "sha512-Ff9FKeIMm0Rx1o8TEV87bTK5M232akt7uSAYrSTU/QA/W6Jj9P+fWn1mxGgl+dwDzpFoAY35OIS2SJXA8WEWKA==", - "dependencies": { - "node-fetch": "2.6.12" - } - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -632,23 +604,6 @@ "node": ">=4" } }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -667,39 +622,6 @@ "integrity": "sha512-sxX0LXh+uL41hSJsujAN86PjhrV/6c79XmpY0TvjZStV6VxIgarf8SRkUoUTuYmFcZQTemsoqo8qXOGw5npWfw==", "dev": true }, - "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -709,19 +631,6 @@ "node": ">=6" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -919,11 +828,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "node_modules/jiti": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", @@ -933,19 +837,19 @@ "jiti": "bin/jiti.js" } }, - "node_modules/jose": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", - "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -1006,11 +910,6 @@ "node": "*" } }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -1088,11 +987,6 @@ } } }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, "node_modules/next/node_modules/postcss": { "version": "8.4.5", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", @@ -1110,35 +1004,6 @@ "url": "https://opencollective.com/postcss/" } }, - "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/node-releases": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", @@ -1492,11 +1357,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/set-cookie-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", - "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" - }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -1671,18 +1531,10 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/update-browserslist-db": { "version": "1.0.11", @@ -1714,18 +1566,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1737,22 +1577,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "node_modules/websocket": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", - "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", - "dependencies": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -1768,12 +1592,24 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { - "node": ">=0.10.32" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/yaml": { @@ -1943,92 +1779,87 @@ "fastq": "^1.6.0" } }, - "@supabase/auth-helpers-nextjs": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-nextjs/-/auth-helpers-nextjs-0.7.2.tgz", - "integrity": "sha512-n5IyGBYJV/WiR5Rgw4CUaiJYiOv9yW2of4ZP4EyzKt2O6/6rztt7PcGE4AoK2vERw+fb5F2QtJBdt6J5eOYCCw==", - "requires": { - "@supabase/auth-helpers-shared": "0.4.1", - "set-cookie-parser": "^2.6.0" - } - }, - "@supabase/auth-helpers-shared": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@supabase/auth-helpers-shared/-/auth-helpers-shared-0.4.1.tgz", - "integrity": "sha512-IEDX9JzWkIjQiLUaP4Qy5YDiG0jFQatWfS+jw8cCQs6QfbNdEPd2Y3qonwGHnM90CZom9SvjuylBv2pFVAL7Lw==", - "requires": { - "jose": "^4.14.3" - } - }, "@supabase/functions-js": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.1.2.tgz", - "integrity": "sha512-QCR6pwJs9exCl37bmpMisUd6mf+0SUBJ6mUpiAjEkSJ/+xW8TCuO14bvkWHADd5hElJK9MxNlMQXxSA4DRz9nQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.1.5.tgz", + "integrity": "sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw==", "requires": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "@supabase/gotrue-js": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.38.0.tgz", - "integrity": "sha512-iitNthPLQjAD73FtnUNUalwPFpsiiE7t/0mVw14b+3rqzr52Efri8gAjzT9hi7p35uOLA76HMY3aWJj6Gy7ozw==", + "version": "2.62.2", + "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.62.2.tgz", + "integrity": "sha512-AP6e6W9rQXFTEJ7sTTNYQrNf0LCcnt1hUW+RIgUK+Uh3jbWvcIST7wAlYyNZiMlS9+PYyymWQ+Ykz/rOYSO0+A==", "requires": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" + } + }, + "@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "requires": { + "whatwg-url": "^5.0.0" } }, "@supabase/postgrest-js": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.7.1.tgz", - "integrity": "sha512-xPRYLaZrkLbXNlzmHW6Wtf9hmcBLjjI5xUz2zj8oE2hgXGaYoZBBkpN9bmW9i17Z1f6Ujxa942AqK439XOA36A==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.9.2.tgz", + "integrity": "sha512-I6yHo8CC9cxhOo6DouDMy9uOfW7hjdsnCxZiaJuIVZm1dBGTFiQPgfMa9zXCamEWzNyWRjZvupAUuX+tqcl5Sw==", "requires": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "@supabase/realtime-js": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.7.3.tgz", - "integrity": "sha512-c7TzL81sx2kqyxsxcDduJcHL9KJdCOoKimGP6lQSqiZKX42ATlBZpWbyy9KFGFBjAP4nyopMf5JhPi2ZH9jyNw==", + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.9.3.tgz", + "integrity": "sha512-lAp50s2n3FhGJFq+wTSXLNIDPw5Y0Wxrgt44eM5nLSA3jZNUUP3Oq2Ccd1CbZdVntPCWLZvJaU//pAd2NE+QnQ==", "requires": { + "@supabase/node-fetch": "^2.6.14", "@types/phoenix": "^1.5.4", - "@types/websocket": "^1.0.3", - "websocket": "^1.0.34" + "@types/ws": "^8.5.10", + "ws": "^8.14.2" } }, "@supabase/storage-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.1.tgz", - "integrity": "sha512-nkR0fQA9ScAtIKA3vNoPEqbZv1k5B5HVRYEvRWdlP6mUpFphM9TwPL2jZ/ztNGMTG5xT6SrHr+H7Ykz8qzbhjw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.5.tgz", + "integrity": "sha512-OpLoDRjFwClwc2cjTJZG8XviTiQH4Ik8sCiMK5v7et0MDu2QlXjCAW3ljxJB5+z/KazdMOTnySi+hysxWUPu3w==", "requires": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "@supabase/supabase-js": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.26.0.tgz", - "integrity": "sha512-RXmTPTobaYAwkSobadHZmEVLmzX3SGrtRZIGfLWnLv92VzBRrjuXn0a+bJqKl50GUzsyqPA+j5pod7EwMkcH5A==", + "version": "2.39.6", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.39.6.tgz", + "integrity": "sha512-HlflDzem0+l3KYYTqHV0UsqkDooV9my5UcBCV2zvvTrl77UtW97uKTZWn9lSWMuiy+ZvRLsiuG+WTiBuKMQl0Q==", "requires": { - "@supabase/functions-js": "^2.1.0", - "@supabase/gotrue-js": "^2.31.0", - "@supabase/postgrest-js": "^1.7.0", - "@supabase/realtime-js": "^2.7.3", - "@supabase/storage-js": "^2.5.1", - "cross-fetch": "^3.1.5" + "@supabase/functions-js": "2.1.5", + "@supabase/gotrue-js": "2.62.2", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "1.9.2", + "@supabase/realtime-js": "2.9.3", + "@supabase/storage-js": "2.5.5" } }, "@types/node": { - "version": "20.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz", - "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==" + "version": "20.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", + "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", + "requires": { + "undici-types": "~5.26.4" + } }, "@types/phoenix": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.0.tgz", - "integrity": "sha512-qwfpsHmFuhAS/dVd4uBIraMxRd56vwBUYQGZ6GpXnFuM2XMRFJbIyruFKKlW2daQliuYZwe0qfn/UjFCDKic5g==" + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.4.tgz", + "integrity": "sha512-B34A7uot1Cv0XtaHRYDATltAdKx0BvVKNgYNqE4WjtPUa4VQJM7kxeXcVKaH+KS+kCmZ+6w+QaUdcljiheiBJA==" }, - "@types/websocket": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.5.tgz", - "integrity": "sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==", + "@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "requires": { "@types/node": "*" } @@ -2112,14 +1943,6 @@ "update-browserslist-db": "^1.0.11" } }, - "bufferutil": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz", - "integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==", - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2159,37 +1982,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "cross-fetch": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.7.tgz", - "integrity": "sha512-Ff9FKeIMm0Rx1o8TEV87bTK5M232akt7uSAYrSTU/QA/W6Jj9P+fWn1mxGgl+dwDzpFoAY35OIS2SJXA8WEWKA==", - "requires": { - "node-fetch": "2.6.12" - } - }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, "didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2208,56 +2006,12 @@ "integrity": "sha512-sxX0LXh+uL41hSJsujAN86PjhrV/6c79XmpY0TvjZStV6VxIgarf8SRkUoUTuYmFcZQTemsoqo8qXOGw5npWfw==", "dev": true }, - "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, - "ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "requires": { - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - } - } - }, "fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -2408,27 +2162,22 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "devOptional": true }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "jiti": { "version": "1.18.2", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", "dev": true }, - "jose": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", - "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==" + }, "lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -2474,11 +2223,6 @@ "brace-expansion": "^1.1.7" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -2530,24 +2274,6 @@ } } }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, - "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==" - }, "node-releases": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", @@ -2766,11 +2492,6 @@ "loose-envify": "^1.1.0" } }, - "set-cookie-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", - "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" - }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -2892,18 +2613,10 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "update-browserslist-db": { "version": "1.0.11", @@ -2915,14 +2628,6 @@ "picocolors": "^1.0.0" } }, - "utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "requires": { - "node-gyp-build": "^4.3.0" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2934,19 +2639,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, - "websocket": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", - "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", - "requires": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - } - }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -2962,10 +2654,11 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==" + "ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "requires": {} }, "yaml": { "version": "2.3.1", diff --git a/examples/slack-clone/nextjs-slack-clone/package.json b/examples/slack-clone/nextjs-slack-clone/package.json index 4af29dafd8a..ecdf31d00da 100644 --- a/examples/slack-clone/nextjs-slack-clone/package.json +++ b/examples/slack-clone/nextjs-slack-clone/package.json @@ -9,8 +9,8 @@ "start": "next start" }, "dependencies": { - "@supabase/supabase-js": "^2.26.0", - "@supabase/auth-helpers-nextjs": "^0.7.2", + "@supabase/supabase-js": "^2.39.6", + "jwt-decode": "^4.0.0", "next": "latest", "react": "^18.2.0", "react-dom": "^18.2.0" diff --git a/examples/slack-clone/nextjs-slack-clone/pages/_app.js b/examples/slack-clone/nextjs-slack-clone/pages/_app.js index 3db2d706fa3..d915c72915d 100644 --- a/examples/slack-clone/nextjs-slack-clone/pages/_app.js +++ b/examples/slack-clone/nextjs-slack-clone/pages/_app.js @@ -2,13 +2,13 @@ import '~/styles/style.scss' import React, { useState, useEffect } from 'react' import { useRouter } from 'next/router' import UserContext from 'lib/UserContext' -import { supabase, fetchUserRoles } from 'lib/Store' +import { supabase } from 'lib/Store' +import { jwtDecode } from 'jwt-decode' export default function SupabaseSlackClone({ Component, pageProps }) { const [userLoaded, setUserLoaded] = useState(false) const [user, setUser] = useState(null) const [session, setSession] = useState(null) - const [userRoles, setUserRoles] = useState([]) const router = useRouter() useEffect(() => { @@ -18,27 +18,31 @@ export default function SupabaseSlackClone({ Component, pageProps }) { ) { setSession(session) const currentUser = session?.user + if (session) { + const jwt = jwtDecode(session.access_token) + currentUser.appRole = jwt.user_role + } setUser(currentUser ?? null) setUserLoaded(!!currentUser) if (currentUser) { - signIn(currentUser.id, currentUser.email) router.push('/channels/[id]', '/channels/1') } } - supabase.auth.getSession().then(({ data: { session }}) => saveSession(session)) + supabase.auth.getSession().then(({ data: { session } }) => saveSession(session)) - const { subscription: authListener } = supabase.auth.onAuthStateChange(async (event, session) => saveSession(session)) + const { subscription: authListener } = supabase.auth.onAuthStateChange( + async (event, session) => { + console.log(session) + saveSession(session) + } + ) return () => { authListener.unsubscribe() } }, []) - const signIn = async () => { - await fetchUserRoles((userRoles) => setUserRoles(userRoles.map((userRole) => userRole.role))) - } - const signOut = async () => { const { error } = await supabase.auth.signOut() if (!error) { @@ -51,8 +55,6 @@ export default function SupabaseSlackClone({ Component, pageProps }) { value={{ userLoaded, user, - userRoles, - signIn, signOut, }} > diff --git a/examples/slack-clone/nextjs-slack-clone/supabase/.gitignore b/examples/slack-clone/nextjs-slack-clone/supabase/.gitignore new file mode 100644 index 00000000000..a3ad88055b7 --- /dev/null +++ b/examples/slack-clone/nextjs-slack-clone/supabase/.gitignore @@ -0,0 +1,4 @@ +# Supabase +.branches +.temp +.env diff --git a/examples/slack-clone/nextjs-slack-clone/supabase/config.toml b/examples/slack-clone/nextjs-slack-clone/supabase/config.toml new file mode 100644 index 00000000000..c5ff45b294f --- /dev/null +++ b/examples/slack-clone/nextjs-slack-clone/supabase/config.toml @@ -0,0 +1,155 @@ +# A string used to distinguish different Supabase projects on the same host. Defaults to the +# working directory name when running `supabase init`. +project_id = "slack-clone" + +[api] +enabled = true +# Port to use for the API URL. +port = 54321 +# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API +# endpoints. public and storage are always included. +schemas = ["public", "storage", "graphql_public"] +# Extra schemas to add to the search_path of every request. public is always included. +extra_search_path = ["public", "extensions"] +# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size +# for accidental or malicious requests. +max_rows = 1000 + +[db] +# Port to use for the local database URL. +port = 54322 +# Port used by db diff command to initialize the shadow database. +shadow_port = 54320 +# The database major version to use. This has to be the same as your remote database's. Run `SHOW +# server_version;` on the remote database to check. +major_version = 15 + +[db.pooler] +enabled = false +# Port to use for the local connection pooler. +port = 54329 +# Specifies when a server connection can be reused by other clients. +# Configure one of the supported pooler modes: `transaction`, `session`. +pool_mode = "transaction" +# How many server connections to allow per user/database pair. +default_pool_size = 20 +# Maximum number of client connections allowed. +max_client_conn = 100 + +[realtime] +enabled = true +# Bind realtime via either IPv4 or IPv6. (default: IPv6) +# ip_version = "IPv6" + +[studio] +enabled = true +# Port to use for Supabase Studio. +port = 54323 +# External URL of the API server that frontend connects to. +api_url = "http://127.0.0.1" + +# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they +# are monitored, and you can view the emails that would have been sent from the web interface. +[inbucket] +enabled = true +# Port to use for the email testing server web interface. +port = 54324 +# Uncomment to expose additional ports for testing user applications that send emails. +# smtp_port = 54325 +# pop3_port = 54326 + +[storage] +enabled = true +# The maximum file size allowed (e.g. "5MB", "500KB"). +file_size_limit = "50MiB" + +[auth] +enabled = true +# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used +# in emails. +site_url = "http://127.0.0.1:3000" +# A list of *exact* URLs that auth providers are permitted to redirect to post authentication. +additional_redirect_urls = ["https://127.0.0.1:3000"] +# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week). +jwt_expiry = 3600 +# If disabled, the refresh token will never expire. +enable_refresh_token_rotation = true +# Allows refresh tokens to be reused after expiry, up to the specified interval in seconds. +# Requires enable_refresh_token_rotation = true. +refresh_token_reuse_interval = 10 +# Allow/disallow new user signups to your project. +enable_signup = true + +[auth.email] +# Allow/disallow new user signups via email to your project. +enable_signup = true +# If enabled, a user will be required to confirm any email change on both the old, and new email +# addresses. If disabled, only the new email is required to confirm. +double_confirm_changes = true +# If enabled, users need to confirm their email address before signing in. +enable_confirmations = false + +# Uncomment to customize email template +# [auth.email.template.invite] +# subject = "You have been invited" +# content_path = "./supabase/templates/invite.html" + +[auth.sms] +# Allow/disallow new user signups via SMS to your project. +enable_signup = true +# If enabled, users need to confirm their phone number before signing in. +enable_confirmations = false +# Template for sending OTP to users +template = "Your code is {{ .Code }} ." + +# Use pre-defined map of phone number to OTP for testing. +[auth.sms.test_otp] +# 4152127777 = "123456" + +# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`. +[auth.sms.twilio] +enabled = false +account_sid = "" +message_service_sid = "" +# DO NOT commit your Twilio auth token to git. Use environment variable substitution instead: +auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)" + +# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`, +# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`, +# `twitter`, `slack`, `spotify`, `workos`, `zoom`. +[auth.external.apple] +enabled = false +client_id = "" +# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead: +secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)" +# Overrides the default auth redirectUrl. +redirect_uri = "" +# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure, +# or any other third-party OIDC providers. +url = "" + +# Enable auth hooks +# https://supabase.com/docs/guides/auth/auth-hooks#local-development +[auth.hook.custom_access_token] +enabled = true +uri = "pg-functions://postgres/public/custom_access_token_hook" + +[analytics] +enabled = false +port = 54327 +vector_port = 54328 +# Configure one of the supported backends: `postgres`, `bigquery`. +backend = "postgres" + +# Experimental features may be deprecated any time +[experimental] +# Configures Postgres storage engine to use OrioleDB (S3) +orioledb_version = "" +# Configures S3 bucket URL, eg. .s3-.amazonaws.com +s3_host = "env(S3_HOST)" +# Configures S3 bucket region, eg. us-east-1 +s3_region = "env(S3_REGION)" +# Configures AWS_ACCESS_KEY_ID for S3 bucket +s3_access_key = "env(S3_ACCESS_KEY)" +# Configures AWS_SECRET_ACCESS_KEY for S3 bucket +s3_secret_key = "env(S3_SECRET_KEY)" diff --git a/examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214102356_init.sql b/examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214102356_init.sql new file mode 100644 index 00000000000..fd568a6d106 --- /dev/null +++ b/examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214102356_init.sql @@ -0,0 +1,165 @@ +-- +-- For use with https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone +-- + +-- Custom types +create type public.app_permission as enum ('channels.delete', 'messages.delete'); +create type public.app_role as enum ('admin', 'moderator'); +create type public.user_status as enum ('ONLINE', 'OFFLINE'); + +-- USERS +create table public.users ( + id uuid references auth.users not null primary key, -- UUID from auth.users + username text, + status user_status default 'OFFLINE'::public.user_status +); +comment on table public.users is 'Profile data for each user.'; +comment on column public.users.id is 'References the internal Supabase Auth user.'; + +-- CHANNELS +create table public.channels ( + id bigint generated by default as identity primary key, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, + slug text not null unique, + created_by uuid references public.users not null +); +comment on table public.channels is 'Topics and groups.'; + +-- MESSAGES +create table public.messages ( + id bigint generated by default as identity primary key, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, + message text, + user_id uuid references public.users not null, + channel_id bigint references public.channels on delete cascade not null +); +comment on table public.messages is 'Individual messages sent by each user.'; + +-- USER ROLES +create table public.user_roles ( + id bigint generated by default as identity primary key, + user_id uuid references public.users on delete cascade not null, + role app_role not null, + unique (user_id, role) +); +comment on table public.user_roles is 'Application roles for each user.'; + +-- ROLE PERMISSIONS +create table public.role_permissions ( + id bigint generated by default as identity primary key, + role app_role not null, + permission app_permission not null, + unique (role, permission) +); +comment on table public.role_permissions is 'Application permissions for each role.'; + +-- authorize with role-based access control (RBAC) +create function public.authorize( + requested_permission app_permission, + user_id uuid +) +returns boolean as $$ +declare + bind_permissions int; +begin + select count(*) + from public.role_permissions + where role_permissions.permission = authorize.requested_permission + and role_permissions.role = (auth.jwt() ->> 'user_role')::public.app_role + into bind_permissions; + + return bind_permissions > 0; +end; +$$ language plpgsql security definer set search_path = public; + +-- Secure the tables +alter table public.users enable row level security; +alter table public.channels enable row level security; +alter table public.messages enable row level security; +alter table public.user_roles enable row level security; +alter table public.role_permissions enable row level security; +create policy "Allow logged-in read access" on public.users for select using ( auth.role() = 'authenticated' ); +create policy "Allow individual insert access" on public.users for insert with check ( auth.uid() = id ); +create policy "Allow individual update access" on public.users for update using ( auth.uid() = id ); +create policy "Allow logged-in read access" on public.channels for select using ( auth.role() = 'authenticated' ); +create policy "Allow individual insert access" on public.channels for insert with check ( auth.uid() = created_by ); +create policy "Allow individual delete access" on public.channels for delete using ( auth.uid() = created_by ); +create policy "Allow authorized delete access" on public.channels for delete using ( authorize('channels.delete', auth.uid()) ); +create policy "Allow logged-in read access" on public.messages for select using ( auth.role() = 'authenticated' ); +create policy "Allow individual insert access" on public.messages for insert with check ( auth.uid() = user_id ); +create policy "Allow individual update access" on public.messages for update using ( auth.uid() = user_id ); +create policy "Allow individual delete access" on public.messages for delete using ( auth.uid() = user_id ); +create policy "Allow authorized delete access" on public.messages for delete using ( authorize('messages.delete', auth.uid()) ); +create policy "Allow individual read access" on public.user_roles for select using ( auth.uid() = user_id ); + +-- Send "previous data" on change +alter table public.users replica identity full; +alter table public.channels replica identity full; +alter table public.messages replica identity full; + +-- inserts a row into public.users and assigns roles +create function public.handle_new_user() +returns trigger as $$ +declare is_admin boolean; +begin + insert into public.users (id, username) + values (new.id, new.email); + + select count(*) = 1 from auth.users into is_admin; + + if position('+supaadmin@' in new.email) > 0 then + insert into public.user_roles (user_id, role) values (new.id, 'admin'); + elsif position('+supamod@' in new.email) > 0 then + insert into public.user_roles (user_id, role) values (new.id, 'moderator'); + end if; + + return new; +end; +$$ language plpgsql security definer set search_path = auth, public; + +-- trigger the function every time a user is created +create trigger on_auth_user_created + after insert on auth.users + for each row execute procedure public.handle_new_user(); + +/** + * REALTIME SUBSCRIPTIONS + * Only allow realtime listening on public tables. + */ + +begin; + -- remove the realtime publication + drop publication if exists supabase_realtime; + + -- re-create the publication but don't enable it for any tables + create publication supabase_realtime; +commit; + +-- add tables to the publication +alter publication supabase_realtime add table public.channels; +alter publication supabase_realtime add table public.messages; +alter publication supabase_realtime add table public.users; + +/** + * HELPER FUNCTIONS + * Create test user helper method. + */ +create or replace function public.create_user( + email text +) returns uuid + security definer + set search_path = auth +as $$ + declare + user_id uuid; +begin + user_id := extensions.uuid_generate_v4(); + + insert into auth.users (id, email) + values (user_id, email) + returning id into user_id; + + return user_id; +end; +$$ language plpgsql; + diff --git a/examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214114147_auth-hook.sql b/examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214114147_auth-hook.sql new file mode 100644 index 00000000000..ea17d1dec7a --- /dev/null +++ b/examples/slack-clone/nextjs-slack-clone/supabase/migrations/20240214114147_auth-hook.sql @@ -0,0 +1,58 @@ +/** + * AUTH HOOKS + * Create an auth hook to add a custom claim to the access token jwt. + */ + +-- Create the auth hook function +-- https://supabase.com/docs/guides/auth/auth-hooks#hook-custom-access-token +create or replace function public.custom_access_token_hook(event jsonb) +returns jsonb +language plpgsql +immutable +as $$ + declare + claims jsonb; + user_role public.app_role; + begin + -- Check if the user is marked as admin in the profiles table + select role into user_role from public.user_roles where user_id = (event->>'user_id')::uuid; + + claims := event->'claims'; + + if user_role is not null then + -- Set the claim + claims := jsonb_set(claims, '{user_role}', to_jsonb(user_role)); + else + claims := jsonb_set(claims, '{user_role}', 'null'); + end if; + + -- Update the 'claims' object in the original event + event := jsonb_set(event, '{claims}', claims); + + -- Return the modified or original event + return event; + end; +$$; + +grant usage on schema public to supabase_auth_admin; + +grant execute + on function public.custom_access_token_hook + to supabase_auth_admin; + +revoke execute + on function public.custom_access_token_hook + from authenticated, anon; + +grant all + on table public.user_roles +to supabase_auth_admin; + +revoke all + on table public.user_roles + from authenticated, anon; + +create policy "Allow auth admin to read user roles" ON public.user_roles +as permissive for select +to supabase_auth_admin +using (true) diff --git a/examples/slack-clone/nextjs-slack-clone/supabase/seed.sql b/examples/slack-clone/nextjs-slack-clone/supabase/seed.sql new file mode 100644 index 00000000000..5e208015da7 --- /dev/null +++ b/examples/slack-clone/nextjs-slack-clone/supabase/seed.sql @@ -0,0 +1,23 @@ +insert into public.role_permissions (role, permission) +values + ('admin', 'channels.delete'), + ('admin', 'messages.delete'), + ('moderator', 'messages.delete'); + +DO $$ +DECLARE + user_id uuid; +BEGIN + user_id := public.create_user('supabot+supaadmin@example.com'); + + insert into public.channels (slug, created_by) + values + ('public', user_id), + ('random', user_id); + + insert into public.messages (message, channel_id, user_id) + values + ('Hello World 👋', 1, user_id), + ('Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.', 2, user_id); +END $$; + From b7ea0994e451c4287f28a1cca066863bdaafcfb1 Mon Sep 17 00:00:00 2001 From: Michael Owen <62911962+eastcoasting@users.noreply.github.com> Date: Mon, 4 Mar 2024 13:36:44 -0500 Subject: [PATCH 39/62] Format numbers in statistics charts #21742 (#21750) use Intl.NumberFormat() without explicit locale. --- apps/studio/components/interfaces/Home/ProjectUsage.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/studio/components/interfaces/Home/ProjectUsage.tsx b/apps/studio/components/interfaces/Home/ProjectUsage.tsx index cdd7def1fe3..bbf1f9870c7 100644 --- a/apps/studio/components/interfaces/Home/ProjectUsage.tsx +++ b/apps/studio/components/interfaces/Home/ProjectUsage.tsx @@ -71,6 +71,7 @@ const ProjectUsage = () => { endDateLocal.toISOString() ) const datetimeFormat = selectedInterval.format || 'MMM D, ha' + const numberFormat = new Intl.NumberFormat() const handleBarClick = ( value: UsageApiCounts, @@ -129,7 +130,7 @@ const ProjectUsage = () => { yAxisKey="total_rest_requests" onBarClick={(v: unknown) => handleBarClick(v as UsageApiCounts, 'rest')} customDateFormat={datetimeFormat} - highlightedValue={sumBy(charts, 'total_rest_requests')} + highlightedValue={numberFormat.format(sumBy(charts, 'total_rest_requests'))} /> @@ -154,7 +155,7 @@ const ProjectUsage = () => { yAxisKey="total_auth_requests" onBarClick={(v: unknown) => handleBarClick(v as UsageApiCounts, 'auth')} customDateFormat={datetimeFormat} - highlightedValue={sumBy(charts || [], 'total_auth_requests')} + highlightedValue={numberFormat.format(sumBy(charts || [], 'total_auth_requests'))} /> @@ -181,7 +182,7 @@ const ProjectUsage = () => { yAxisKey="total_storage_requests" onBarClick={(v: unknown) => handleBarClick(v as UsageApiCounts, 'storage')} customDateFormat={datetimeFormat} - highlightedValue={sumBy(charts, 'total_storage_requests')} + highlightedValue={numberFormat.format(sumBy(charts, 'total_storage_requests'))} /> @@ -206,7 +207,7 @@ const ProjectUsage = () => { yAxisKey="total_realtime_requests" onBarClick={(v: unknown) => handleBarClick(v as UsageApiCounts, 'realtime')} customDateFormat={datetimeFormat} - highlightedValue={sumBy(charts, 'total_realtime_requests')} + highlightedValue={numberFormat.format(sumBy(charts, 'total_realtime_requests'))} /> From 4085e3130430a612767cae39081ffbe6a1069067 Mon Sep 17 00:00:00 2001 From: Wen Bo Xie <5532241+w3b6x9@users.noreply.github.com> Date: Mon, 4 Mar 2024 15:09:12 -0800 Subject: [PATCH 40/62] docs: re-order Read Replicas doc sections (#21703) * docs: re-order Read Replicas doc sections * chore: fix typo about compute size change * Update apps/docs/content/guides/platform/read-replicas.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/docs/content/guides/platform/read-replicas.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * Update apps/docs/content/guides/platform/read-replicas.mdx Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> * docs: remove duplicate image --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- .../content/guides/platform/read-replicas.mdx | 167 +++++++++--------- .../Addons/ComputeInstanceSidePanel.tsx | 4 +- 2 files changed, 81 insertions(+), 90 deletions(-) diff --git a/apps/docs/content/guides/platform/read-replicas.mdx b/apps/docs/content/guides/platform/read-replicas.mdx index 29f048a7a1b..d638036313c 100644 --- a/apps/docs/content/guides/platform/read-replicas.mdx +++ b/apps/docs/content/guides/platform/read-replicas.mdx @@ -1,71 +1,15 @@ --- title: 'Read Replicas' -description: 'Spin up additional read-only databases for your project.' -subtitle: 'Spin up additional read-only databases for your project' +description: 'Deploy additional read-only databases in multiple regions for your project.' +subtitle: 'Deploy additional read-only databases in multiple regions for your project' --- - + -To try out read replicas, [request access here](https://forms.supabase.com/read-replica). +[Request early access here](https://forms.supabase.com/read-replica). -Read replicas continuously replicate data from a primary database. You can both read and write data on a primary database, but you can _only_ read (for example, use `select` statements), and not write, on a read replica. - -| | select | insert | update | delete | -| ------------ | ------ | ------ | ------ | ------ | -| Primary | ✅ | ✅ | ✅ | ✅ | -| Read Replica | ✅ | - | - | - | - -When you create a project, the automatically created database is considered the primary database. If you then add read replicas, they will receive and synchronize data from this primary database. Replication is asynchronous. It happens in the background, so transactions on the primary aren't blocked. The time delay between writing data to the primary and the read replica receiving the change is called replication lag. - -Read replicas have many applications: - -- They reduce read load on the primary database. - - For example, you can use a read replica for complex analytical queries and reserve the primary for user-facing create, update, and delete operations. -- For projects that need to cover a global audience, additional databases can be spun up closer to users in any of our twelve supported regions to reduce latency. -- Read replicas provide data redundancy. - -## How are Read Replicas made? - -We use a hybrid approach to replicate data from a primary to its read replicas, combining the native methods of streaming replication and file-based log shipping. - -### Streaming replication - -Postgres generates a Write Ahead Log (WAL) as database changes occur. With streaming replication, these changes stream from the primary to the read replica server. The WAL alone is sufficient to reconstruct the database to its current state. - -This replication method is fast, since changes are streamed directly from the primary to the read replica. On the other hand, it faces challenges when the read replica can't keep up with the WAL changes from its primary. This can happen when the read replica is too small, running on degraded hardware, or has a heavier workload running. - -To address this, Postgres does provide tunable configuration, like `wal_keep_size`, to adjust the WAL retained by the primary. If the read replica fails to “catch up” before the WAL surpasses the `wal_keep_size` setting, the replication is terminated. Tuning is a bit of an art - the amount of WAL required is variable for every situation. - -### File-based log shipping - -In this replication method, the primary continuously buffers WAL changes to a local file and then sends the file to the read replica. If multiple read replicas are present, files could also be sent to an intermediary location accessible by all. The read replica then reads the WAL files and applies those changes. There is higher replication lag than streaming replication since the primary buffers the changes locally first. It also means there is a small chance that WAL changes do not reach read replicas if the primary goes down before the file is transferred. In these cases, if the primary fails a replica using streaming replication would (in most cases) be more up-to-date than a replica using file-based log shipping. - -### File-based log shipping 🤝 streaming replication - -
    - - - -
    How replication is achieved.
    - -
    - -We bring these two methods together to achieve quick, stable, and reliable replication. Each method addresses the limitations of the other. Streaming replication minimizes replication lag, while file-based log shipping provides a fallback. For file-based log shipping, we use our existing Point In Time Recovery (PITR) infrastructure. We regularly archive files from the primary using [WAL-G](https://github.com/wal-g/wal-g), an open source archival and restoration tool, and ship the WAL files to S3. - -We combine it with streaming replication to reduce replication lag. Once WAL-G files have been synced from S3, read replicas connect to the primary and stream the WAL directly. - -## Getting started -
    -Read replicas can be managed from the [infrastructure settings page](https://supabase.com/dashboard/project/_/settings/infrastructure). For now, each project can only spin up to two read replicas. Read replicas also inherit the compute size of their primary database. +Read Replicas are Postgres databases that are continuously synced to a Supabase project's Primary database. You can both read from and write to a Primary database, but you can _only_ read from a Read Replica, such as using `select` statements. -Read replicas offer the following features: +| | select | insert | update | delete | +| ------------ | ------ | ------ | ------ | ------ | +| Primary | ✅ | ✅ | ✅ | ✅ | +| Read Replica | ✅ | - | - | - | + +A database is spun up automatically with every Supabase project. This database is the Primary database. You can choose to add Read Replicas to your project and those Replicas will receive and synchronize data from the Primary database. + +Replication is asynchronous and happens in the background so transactions on the Primary aren't blocked. The time delay between writing data to the Primary and the Read Replica receiving the change is replication lag. + +Read Replicas have many applications: + +- They reduce read load on the Primary database. + - For example, you can use a Read Replica for complex analytical queries and reserve the Primary for user-facing create, update, and delete operations. +- For projects that need to cover a global audience, additional databases can be deployed closer to users in any of our twelve supported regions to reduce latency. +- Read Replicas provide data redundancy. + +## Prerequisites + +A project needs to satisfy these requirements to deploy a Read Replica: + +1. Running on AWS. + - Support for projects on Fly.io is coming. +1. Running on at least a [Small compute add-on](/docs/guides/platform/compute-add-ons). + - Read Replicas are currently placed on the same compute instance as the database to make sure they can keep up with the Primary's activities. +1. Using [physical backups](/docs/guides/platform/backups#point-in-time-recovery) + - Physical backups are automatically enabled if using [PITR](/docs/guides/platform/backups#point-in-time-recovery) +1. Running on Postgres 15. + - For projects running on older versions of PostgreSQL, you will need to [upgrade to the latest platform version](/docs/guides/platform/migrating-and-upgrading-projects#pgupgrade). + +## Getting started + +Read Replicas can be managed from the [infrastructure settings page](https://supabase.com/dashboard/project/_/settings/infrastructure). For now, each project can only deploy up to two Read Replicas and all Read Replicas inherit the compute size of their Primary database. + +Read Replicas offer the following features: ### Dedicated endpoints -Each read replica has its own dedicated database and API endpoints. The database endpoint can be found in your [dashboard database settings](https://supabase.com/dashboard/project/_/settings/database) under **Connection info**. The API endpoint can be found in [dashboard API settings](https://supabase.com/dashboard/project/_/settings/api) under **Project URL**. +Each Read Replica has its own dedicated database and API endpoints. The database endpoint can be found in your [dashboard database settings](https://supabase.com/dashboard/project/_/settings/database) under **Connection info**. The API endpoint can be found in [dashboard API settings](https://supabase.com/dashboard/project/_/settings/api) under **Project URL**. -A read replica's API endpoint only supports `GET` requests to the [REST API](https://supabase.com/docs/guides/api). Requests towards other Supabase products, such as Auth, Storage, and Realtime are not able to utilize a read replica nor its API endpoint for now. We are working on adding read replica support for them. +A Read Replica's API endpoint only supports `GET` requests to the [REST API](https://supabase.com/docs/guides/api). Requests towards other Supabase products, such as Auth, Storage, and Realtime, are not able to utilize a Read Replica nor its API endpoint for now. We are working on adding Read Replica support for them. ### Dedicated connection pool -A connection pool through Supavisor is also available for each read replica. Its unique connection string can be found in your [dashboard database settings](https://supabase.com/dashboard/project/_/settings/database) under **Connection string**. +A connection pool through Supavisor is also available for each Read Replica. Its unique connection string can be found in your [dashboard database settings](https://supabase.com/dashboard/project/_/settings/database) under **Connection string**. ### Querying through the SQL editor @@ -112,45 +89,59 @@ A connection pool through Supavisor is also available for each read replica. Its
    -In the SQL editor, you can choose if you want to run the query on the primary or one of the replicas. +In the SQL editor, you can choose if you want to run the query on the Primary or one of the Replicas. ### API load balancer -When read replicas are spun up, an API load balancer becomes available for the project. An endpoint for it is provisioned and can be found [here](https://supabase.com/dashboard/project/_/settings/api). +When Read Replicas are deployed, an API load balancer becomes available for the project. An endpoint for it is provisioned and can be found [here](https://supabase.com/dashboard/project/_/settings/api). -The load balancer uses a round-robin strategy to route `GET` requests to any of the API endpoints available, including that of the primary database. Non-`GET` requests can also be sent through this endpoint. They are immediately redirected to the primary database. +The load balancer uses a round-robin strategy to route `GET` requests to any of the API endpoints available, including that of the Primary database. Non-`GET` requests can also be sent through this endpoint. They are immediately redirected to the Primary database. -Similar to the read replica API endpoints, only requests to the REST API are available for now. Support for other Supabase products will become available once read replica support has been completed for them. +Similar to the Read Replica API endpoints, only requests to the REST API are available for now. Support for other Supabase products will become available once Read Replica support has been completed for them. -When a project no longer has any read replicas, the load balancer and its endpoint are brought down as well. +When a project no longer has any Read Replicas, the load balancer and its endpoint are brought down as well. ### Centralized configuration management -All settings made through the dashboard will be propagated across all databases of a project. This ensures that no read replica get out of sync with its primary database or with other read replicas. +All settings made through the dashboard will be propagated across all databases of a project. This ensures that no Read Replica get out of sync with its Primary database or with other Read Replicas. -## Limitations +## How are Read Replicas made? -### Prerequisites for using read replicas +We use a hybrid approach to replicate data from a Primary to its Read Replicas, combining the native methods of streaming replication and file-based log shipping. -A project needs to satisfy these requirements to spin up a read replica: +### Streaming replication -1. Running on AWS. - - Support for projects on Fly.io will be added at a later date. -1. Running on at least a [Small compute add-on](/docs/guides/platform/compute-add-ons). -1. Using [physical backups](/docs/guides/platform/backups#point-in-time-recovery) - - Physical backups are automatically enabled if using [PITR](/docs/guides/platform/backups#point-in-time-recovery) -1. Running on Postgres 15. - - For projects running on older versions of PostgreSQL, you will need to [upgrade to the latest platform version](/docs/guides/platform/migrating-and-upgrading-projects#pgupgrade). +Postgres generates a Write Ahead Log (WAL) as database changes occur. With streaming replication, these changes stream from the Primary to the Read Replica server. The WAL alone is sufficient to reconstruct the database to its current state. -### Read replicas need to be brought down before starting the following procedures +This replication method is fast, since changes are streamed directly from the Primary to the Read Replica. On the other hand, it faces challenges when the Read Replica can't keep up with the WAL changes from its Primary. This can happen when the Read Replica is too small, running on degraded hardware, or has a heavier workload running. -The following procedures require all read replicas for a project to be brought down before they can be started: +To address this, Postgres does provide tunable configuration, like `wal_keep_size`, to adjust the WAL retained by the Primary. If the Read Replica fails to “catch up” before the WAL surpasses the `wal_keep_size` setting, the replication is terminated. Tuning is a bit of an art - the amount of WAL required is variable for every situation. -1. [Upgrading a project](/docs/guides/platform/migrating-and-upgrading-projects#pgupgrade) -1. Performing [data restoration](/docs/guides/platform/backups#pitr-restoration-process). +### File-based log shipping -Once these operations complete, read replicas can be spun back up. +In this replication method, the Primary continuously buffers WAL changes to a local file and then sends the file to the Read Replica. If multiple Read Replicas are present, files could also be sent to an intermediary location accessible by all. The Read Replica then reads the WAL files and applies those changes. There is higher replication lag than streaming replication since the Primary buffers the changes locally first. It also means there is a small chance that WAL changes do not reach Read Replicas if the Primary goes down before the file is transferred. In these cases, if the Primary fails a Replica using streaming replication would (in most cases) be more up-to-date than a Replica using file-based log shipping. -### Compute Add-ons +### File-based log shipping 🤝 streaming replication -In order to avoid replicas being unable to keep up with activity on the primaries they're following, Read Replicas are currently placed on the same Compute Add-on as the primary they're following. +
    + +
    Map view of Primary and Read Replica databases
    +
    + +We bring these two methods together to achieve quick, stable, and reliable replication. Each method addresses the limitations of the other. Streaming replication minimizes replication lag, while file-based log shipping provides a fallback. For file-based log shipping, we use our existing Point In Time Recovery (PITR) infrastructure. We regularly archive files from the Primary using [WAL-G](https://github.com/wal-g/wal-g), an open source archival and restoration tool, and ship the WAL files to S3. + +We combine it with streaming replication to reduce replication lag. Once WAL-G files have been synced from S3, Read Replicas connect to the Primary and stream the WAL directly. + +## Operations blocked by Read Replicas + +### Project upgrades and data restorations + +The following procedures require all Read Replicas for a project to be brought down before they can be performed: + +1. [Project upgrades](/docs/guides/platform/migrating-and-upgrading-projects#pgupgrade) +1. [Data restorations](/docs/guides/platform/backups#pitr-restoration-process) + +These operations need to be completed before Read Replicas can be re-deployed. diff --git a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx index 041bd8725d6..dbf847aa52f 100644 --- a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx @@ -399,7 +399,7 @@ const ComputeInstanceSidePanel = () => { - Your project will need to be restarted when changing it's compute size + Your project will need to be restarted when changing its compute size Your project will be unavailable for up to 2 minutes while the changes take place. @@ -485,7 +485,7 @@ const ComputeInstanceSidePanel = () => { Your project will be unavailable for up to 2 minutes while the changes take place. From 148a872e17265b051139873910dc9ae5194b214c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Tue, 5 Mar 2024 00:37:25 +0100 Subject: [PATCH 41/62] docs(branching): Specify that only migrations are applied (#21759) --- apps/docs/content/guides/platform/branching.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/content/guides/platform/branching.mdx b/apps/docs/content/guides/platform/branching.mdx index 57d949e501c..e766fb1db27 100644 --- a/apps/docs/content/guides/platform/branching.mdx +++ b/apps/docs/content/guides/platform/branching.mdx @@ -119,7 +119,7 @@ For security reasons, Preview Branches do not contain production data. Future ve ### Merging production changes -When you merge your Git branch into the production branch, all changes will be applied to your Production environment. +When you merge your Git branch into the production branch, all new migrations will be applied to your Production environment. ### Git providers From 70c118df900e4cd334fd5975f005f9cbb823599e Mon Sep 17 00:00:00 2001 From: Madhav Bansal <52946553+madhav23bansal@users.noreply.github.com> Date: Tue, 5 Mar 2024 06:41:57 +0530 Subject: [PATCH 42/62] Guide to Setting Up TextLocal as Your Phone Login Provider (#21499) * Add TextLocal SMS Login to NavigationMenu.constants.ts and create guide for Phone Auth with TextLocal * Fix typo in Textlocal SMS Login * Update Textlocal integration and documentation for DLT compliance. * Addressed comments * Update Textlocal SMS Login name * Update Textlocal SMS Login name to 'Textlocal SMS Login (Community Supported)' --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- .../NavigationMenu.constants.ts | 6 ++ .../guides/auth/phone-login/textlocal.mdx | 63 +++++++++++++++++++ apps/docs/public/img/icons/textlocal-icon.svg | 22 +++++++ 3 files changed, 91 insertions(+) create mode 100644 apps/docs/content/guides/auth/phone-login/textlocal.mdx create mode 100644 apps/docs/public/img/icons/textlocal-icon.svg diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 3f3f3cf9754..8fca482d4a6 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -492,6 +492,12 @@ export const PhoneLoginsItems = [ isDarkMode: true, hasLightIcon: true, }, + { + name: 'Textlocal SMS Login (Community Supported)', + icon: '/docs/img/icons/textlocal-icon', + url: '/guides/auth/phone-login/textlocal', + linkDescription: 'Textlocal is a cloud-based SMS platform offering bulk messaging services.', + }, ] export const auth = { diff --git a/apps/docs/content/guides/auth/phone-login/textlocal.mdx b/apps/docs/content/guides/auth/phone-login/textlocal.mdx new file mode 100644 index 00000000000..9a717bfca17 --- /dev/null +++ b/apps/docs/content/guides/auth/phone-login/textlocal.mdx @@ -0,0 +1,63 @@ +--- +id: 'auth-textlocal' +title: 'Phone Auth with Textlocal' +subtitle: 'How to set up and use Mobile OTP with Textlocal and Supabase.' +description: 'How to set up and use Mobile OTP with Textlocal and Supabase.' +--- + + + +To manage costs related to SMS authentication, consider setting project rate limits and configuring CAPTCHA. For additional cost-control strategies, visit the Production Checklist. + +Also check country-specific regulations around sending SMS messages, for example, India's TRAI DLT +regulations. + + + +## Prerequisites + +Before you begin, ensure you have the following: + +- **A Textlocal account**: Sign up for [TextLocal](https://www.textlocal.com/signup) to start sending SMS messages. +- **A Supabase project**: Necessary for SMS authentication integration. Create your project in the [Supabase Dashboard](https://supabase.com/dashboard). +- **A mobile phone**: To receive SMS messages and test your setup. + +## Setting up Textlocal as your SMS provider + +To integrate Textlocal with Supabase: + +1. [Get a Textlocal API key](#get-a-textlocal-api-key) +2. [Customize your sender name](#customize-your-sender-name-optional) +3. [Configure your Supabase project](#configure-supabase) + +### Get a Textlocal API key + +1. Log into your Textlocal account and go to `Settings` > `API Keys`. +2. Generate a new API Key. Save your new API key in a safe location. + +### Customize your sender name (Optional) + +Textlocal defaults to `TXTLCL` as the sender name for all messages. You can customize this to better reflect your brand: + +1. In your Textlocal dashboard, go to `Settings` > `All Settings` > `Sender Names`. +2. Change your sender name. + +### Configure Supabase + +To set up Textlocal as your SMS provider in Supabase, follow these steps: + +1. In your Supabase Dashboard, go to the [Auth Providers section](https://supabase.com/dashboard/project/_/auth/providers). +2. From the list of available authentication providers, select `Phone`. +3. Toggle `Enable Phone Provider`. +4. Under `SMS Provider`, select `Textlocal.` +5. Enter your Textlocal API Key and Sender Name. +6. Customize your SMS Message (optional). + +## Next steps + +To implement Phone Login, see the docs on [using Phone Login](/docs/guides/auth/phone-login#using-phone-login). + +## Resources + +- [Textlocal Signup](https://www.textlocal.com/sign-up) +- [Supabase Dashboard](https://supabase.com/dashboard) diff --git a/apps/docs/public/img/icons/textlocal-icon.svg b/apps/docs/public/img/icons/textlocal-icon.svg new file mode 100644 index 00000000000..6a15d728bd3 --- /dev/null +++ b/apps/docs/public/img/icons/textlocal-icon.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + \ No newline at end of file From cc2425d11b7c75508a7ad0e66244aa7ad9bab1c8 Mon Sep 17 00:00:00 2001 From: Div Arora Date: Tue, 5 Mar 2024 09:43:06 +0800 Subject: [PATCH 43/62] fix: typo in region name (#21761) --- .../InstanceConfiguration.constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants.ts b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants.ts index c103157e0d4..a2a9ad88ef1 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants.ts +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants.ts @@ -39,7 +39,7 @@ export const AWS_REGIONS_VALUES: { [key: string]: string } = { NORTHEAST_ASIA_2: 'ap-northeast-2', CENTRAL_CANADA: 'ca-central-1', WEST_US: 'us-west-1', - EAST_US: 'es-east-1', + EAST_US: 'us-east-1', WEST_EU: 'eu-west-1', WEST_EU_2: 'eu-west-2', CENTRAL_EU: 'eu-central-1', From 33d73f2e7a20db29913ae3135fbe98bb7393fce7 Mon Sep 17 00:00:00 2001 From: Ariel Nathan <23708562+ariel-nathan@users.noreply.github.com> Date: Mon, 4 Mar 2024 21:55:48 -0500 Subject: [PATCH 44/62] docs: reword phone login sentence (#21716) Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- apps/docs/content/guides/auth/phone-login.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/content/guides/auth/phone-login.mdx b/apps/docs/content/guides/auth/phone-login.mdx index a608bcb26eb..e35520a002a 100644 --- a/apps/docs/content/guides/auth/phone-login.mdx +++ b/apps/docs/content/guides/auth/phone-login.mdx @@ -108,7 +108,7 @@ curl -X POST 'https://cvwawazfelidkloqmbma.supabase.co/auth/v1/signup' \ The user receives an SMS with a 6-digit pin that you must [verify](/docs/guides/auth/phone-login#verify-a-user) within 60 seconds. -After their phone number is verified, the user can use their phone number and password to sign in with needing to reverify each time: +Once a user's phone number is verified, they can sign in using their phone number and password without requiring phone number re-verification at each sign-in: Date: Mon, 4 Mar 2024 22:28:56 -0500 Subject: [PATCH 45/62] fixed local development link in RBAC docs (#21762) --- .../auth/custom-claims-and-role-based-access-control-rbac.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx b/apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx index b1f22158f9b..acd69948b93 100644 --- a/apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx +++ b/apps/docs/content/guides/auth/custom-claims-and-role-based-access-control-rbac.mdx @@ -202,7 +202,7 @@ using (true) In the dashboard, navigate to [`Authentication > Hooks (Beta)`](/dashboard/project/_/auth/hooks) and select the appropriate PostgreSQL function from the dropdown menu. -When developing locally, follow the [local development](/guides/auth/auth-hooks#local-development) instructions. +When developing locally, follow the [local development](/docs/guides/auth/auth-hooks#local-development) instructions. From 950a3f8efbdd1eba6145e47492726fa2bf81687c Mon Sep 17 00:00:00 2001 From: Copple <10214025+kiwicopple@users.noreply.github.com> Date: Tue, 5 Mar 2024 04:29:05 +0100 Subject: [PATCH 46/62] chore: update self-hosted image versions (#21763) chore: update image versions for docker/docker-compose.yml --- docker/docker-compose.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 75a059d3cf3..0313ecf14cb 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -10,7 +10,7 @@ services: studio: container_name: supabase-studio - image: supabase/studio:20240205-b145c86 + image: supabase/studio:20240301-0942bfe restart: unless-stopped healthcheck: test: @@ -76,7 +76,7 @@ services: auth: container_name: supabase-auth - image: supabase/gotrue:v2.132.3 + image: supabase/gotrue:v2.143.0 depends_on: db: # Disable this if you are using an external Postgres database @@ -156,7 +156,7 @@ services: realtime: # This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain container_name: realtime-dev.supabase-realtime - image: supabase/realtime:v2.25.50 + image: supabase/realtime:v2.25.66 depends_on: db: # Disable this if you are using an external Postgres database @@ -256,7 +256,7 @@ services: meta: container_name: supabase-meta - image: supabase/postgres-meta:v0.77.2 + image: supabase/postgres-meta:v0.79.0 depends_on: db: # Disable this if you are using an external Postgres database @@ -274,7 +274,7 @@ services: functions: container_name: supabase-edge-functions - image: supabase/edge-runtime:v1.36.1 + image: supabase/edge-runtime:v1.38.0 restart: unless-stopped depends_on: analytics: From 21d1b8afbb94251e090d28368412e5675e4db2e8 Mon Sep 17 00:00:00 2001 From: Copple <10214025+kiwicopple@users.noreply.github.com> Date: Tue, 5 Mar 2024 05:27:37 +0100 Subject: [PATCH 47/62] chore: update cli reference doc (#21764) * chore: update cli reference doc * Update apps/docs/spec/cli_v1_commands.yaml --------- Co-authored-by: Han Qiao --- apps/docs/spec/cli_v1_commands.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/docs/spec/cli_v1_commands.yaml b/apps/docs/spec/cli_v1_commands.yaml index 80b218faaaf..fff89d8dfde 100644 --- a/apps/docs/spec/cli_v1_commands.yaml +++ b/apps/docs/spec/cli_v1_commands.yaml @@ -1,7 +1,7 @@ clispec: '001' info: id: cli - version: 1.145.4 + version: 1.148.6 title: Supabase CLI language: sh source: https://github.com/supabase/cli @@ -2349,8 +2349,6 @@ commands: - id: supabase-gen-types-typescript title: supabase gen types typescript summary: Generate types for TypeScript - description: | - Generate types for TypeScript. Must specify one of --local, --linked, --project-id, or --db-url tags: [] links: [] usage: supabase gen types typescript [flags] @@ -2378,8 +2376,8 @@ commands: description: Generate types from a project ID. default_value: '' - id: schema - name: --schema - description: Schemas to generate types for. + name: -s, --schema + description: Comma separated list of schema to include. default_value: '[]' - id: supabase-gen-keys title: supabase gen keys From cb7c67864b2b5deee7fb0498622fc146712fc46b Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Mon, 4 Mar 2024 23:32:46 -0500 Subject: [PATCH 48/62] chore: linting rule tweaks and error fixes (#21678) --- .vale.ini | 6 +- apps/docs/content/guides/ai.mdx | 12 ++++ .../content/guides/database/extensions.mdx | 4 +- .../guides/database/extensions/hypopg.mdx | 8 +-- .../database/extensions/pg_jsonschema.mdx | 4 +- .../database/extensions/pg_plan_filter.mdx | 6 +- .../guides/database/extensions/pgaudit.mdx | 22 +++--- .../guides/database/extensions/pgjwt.mdx | 8 +-- .../guides/database/extensions/pgroonga.mdx | 8 +-- .../guides/database/extensions/pgrouting.mdx | 10 +-- .../guides/database/extensions/pgsodium.mdx | 10 +-- .../guides/database/extensions/pgtap.mdx | 6 +- .../guides/database/extensions/plv8.mdx | 4 +- .../guides/database/full-text-search.mdx | 34 ++++++++- .../guides/database/managing-timezones.mdx | 2 +- .../database/postgres/cascade-deletes.mdx | 22 +++--- .../database/postgres/configuration.mdx | 2 +- .../guides/database/postgres/roles.mdx | 8 +-- .../database/postgres/row-level-security.mdx | 6 +- .../guides/database/postgres/triggers.mdx | 2 +- .../guides/database/query-optimization.mdx | 4 +- apps/docs/content/guides/database/vault.mdx | 8 +-- .../content/guides/functions/dart-edge.mdx | 9 ++- .../guides/getting-started/architecture.mdx | 16 ++--- .../guides/getting-started/features.mdx | 4 +- .../tutorials/with-angular.mdx | 2 +- .../tutorials/with-expo-react-native.mdx | 4 ++ .../tutorials/with-ionic-angular.mdx | 2 +- .../getting-started/tutorials/with-kotlin.mdx | 4 +- .../tutorials/with-redwoodjs.mdx | 8 +-- .../getting-started/tutorials/with-refine.mdx | 4 +- .../tutorials/with-sveltekit.mdx | 2 +- apps/docs/content/guides/realtime.mdx | 16 ++--- apps/docs/content/guides/resources.mdx | 2 + .../content/guides/self-hosting/docker.mdx | 6 +- vale/styles/Custom/Acronyms.yml | 5 +- vale/styles/Custom/Capitalize.yml | 11 +++ vale/styles/Custom/Exclamation.yml | 12 ---- vale/styles/Custom/Filler.yml | 12 ++++ vale/styles/Custom/Parens.yml | 3 +- vale/styles/Custom/Will.yml | 7 -- vale/styles/Custom/WordList.yml | 41 ++++++----- .../config/vocabularies/Supabase/accept.txt | 72 +++++++++++++++++-- 43 files changed, 281 insertions(+), 157 deletions(-) create mode 100644 vale/styles/Custom/Capitalize.yml delete mode 100644 vale/styles/Custom/Exclamation.yml create mode 100644 vale/styles/Custom/Filler.yml delete mode 100644 vale/styles/Custom/Will.yml diff --git a/.vale.ini b/.vale.ini index 6b721717743..1ff9438668a 100644 --- a/.vale.ini +++ b/.vale.ini @@ -8,5 +8,7 @@ mdx = md [*] BasedOnStyles = Vale, Custom -BlockIgnores = (?s) *(.*?) -TokenIgnores = (href=".*?") +BlockIgnores = (?s) *(.*?), \ +(?s) *(export\s+const\s+\S+\s*=\s*\[.*?\]), \ +(?s) *() +TokenIgnores = (href\s*([=:])\s*['"].*?\1), \ diff --git a/apps/docs/content/guides/ai.mdx b/apps/docs/content/guides/ai.mdx index 66c7ffbedae..f089f7a57c0 100644 --- a/apps/docs/content/guides/ai.mdx +++ b/apps/docs/content/guides/ai.mdx @@ -20,6 +20,8 @@ The toolkit includes: Check out all of the AI [templates and examples](https://github.com/supabase/supabase/tree/master/examples/ai) in our GitHub repository. +{/* */} +
    {examples.map((x) => (
    @@ -66,8 +68,12 @@ export const examples = [ }, ] +{/* */} + ## Integrations +{/* */} +
    {integrations.map((x) => (
    @@ -104,8 +110,12 @@ export const integrations = [ }, ] +{/* */} + ## Case studies +{/* */} +
    {[ { @@ -134,3 +144,5 @@ export const integrations = [
    ))}
    + +{/* */} diff --git a/apps/docs/content/guides/database/extensions.mdx b/apps/docs/content/guides/database/extensions.mdx index 5566a391f6a..d5fb2834e26 100644 --- a/apps/docs/content/guides/database/extensions.mdx +++ b/apps/docs/content/guides/database/extensions.mdx @@ -36,7 +36,7 @@ drop extension pgtap; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension call `drop extension`. @@ -48,7 +48,7 @@ Most extensions are installed under the `extensions` schema, which is accessible If you need to restrict user access to tables managed by extensions, we recommend creating a separate schema for installing that specific extension. -Some extensions can only be created under a specific schema, for eg. `postgis_tiger_geocoder` extension creates a schema named `tiger`. Before enabling such extensions, make sure you have not created a conflicting schema with the same name. +Some extensions can only be created under a specific schema, for example, `postgis_tiger_geocoder` extension creates a schema named `tiger`. Before enabling such extensions, make sure you have not created a conflicting schema with the same name. In addition to the pre-configured extensions, you can also install your own SQL extensions directly in the database using Supabase's SQL editor. The SQL code for the extensions, including plpgsql extensions, can be added through the SQL editor. diff --git a/apps/docs/content/guides/database/extensions/hypopg.mdx b/apps/docs/content/guides/database/extensions/hypopg.mdx index 90c8184bbfe..643c0322352 100644 --- a/apps/docs/content/guides/database/extensions/hypopg.mdx +++ b/apps/docs/content/guides/database/extensions/hypopg.mdx @@ -21,7 +21,7 @@ The motivation for HypoPG is to allow users to quickly search for an index to im 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "hypopg" and enable the extension. +3. Search for `hypopg` and enable the extension. @@ -35,7 +35,7 @@ create extension hypopg with schema extensions; drop extension if exists hypopg; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension you can call `drop extension`. It's good practice to create the extension within a separate schema (like `extensions`) to keep the `public` schema clean. @@ -104,10 +104,10 @@ create index on account(id); - [`hypo_create_index(text)`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#create-a-hypothetical-index): A function to create a hypothetical index. - [`hypopg_list_indexes`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A View that lists all hypothetical indexes that have been created. -- [`hypopg()`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A function that lists all hypothetical indexes that have been created with the same format as pg_index. +- [`hypopg()`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A function that lists all hypothetical indexes that have been created with the same format as `pg_index`. - [`hypopg_get_index_def(oid)`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A function to display the `create index` statement that would create the index. - [`hypopg_get_relation_size(oid)`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A function to estimate how large a hypothetical index would be. -- [`hypopg_drop_index(oid)`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A function to remove a given hypothetical index by oid. +- [`hypopg_drop_index(oid)`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A function to remove a given hypothetical index by `oid`. - [`hypopg_reset()`](https://hypopg.readthedocs.io/en/rel1_stable/usage.html#manipulate-hypothetical-indexes): A function to remove all hypothetical indexes. ## Resources diff --git a/apps/docs/content/guides/database/extensions/pg_jsonschema.mdx b/apps/docs/content/guides/database/extensions/pg_jsonschema.mdx index 9261c0a65f8..2770de88178 100644 --- a/apps/docs/content/guides/database/extensions/pg_jsonschema.mdx +++ b/apps/docs/content/guides/database/extensions/pg_jsonschema.mdx @@ -19,7 +19,7 @@ description: 'Validate json/jsonb with JSON Schema in PostgreSQL.' 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "pg_jsonschema" and enable the extension. +3. Search for `pg_jsonschema` and enable the extension. @@ -33,7 +33,7 @@ create extension pg_jsonschema with schema extensions; drop extension if exists pg_jsonschema; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension you can call `drop extension`. It's good practice to create the extension within a separate schema (like `extensions`) to keep the `public` schema clean. diff --git a/apps/docs/content/guides/database/extensions/pg_plan_filter.mdx b/apps/docs/content/guides/database/extensions/pg_plan_filter.mdx index 9bc6095b4d2..4c9cba45291 100644 --- a/apps/docs/content/guides/database/extensions/pg_plan_filter.mdx +++ b/apps/docs/content/guides/database/extensions/pg_plan_filter.mdx @@ -4,7 +4,7 @@ title: 'pg_plan_filter: Restrict Total Cost' description: 'Block queries over a total cost limit' --- -[pg_plan_filter](https://github.com/pgexperts/pg_plan_filter) is PostgreSQL extension to block execution of statements where query planner's estimate of the total cost exceeds a threshold. This is intended to give database administrators a way to restrict the contribution an individual query has on database load. +[`pg_plan_filter`](https://github.com/pgexperts/pg_plan_filter) is PostgreSQL extension to block execution of statements where query planner's estimate of the total cost exceeds a threshold. This is intended to give database administrators a way to restrict the contribution an individual query has on database load. ## Enable the extension @@ -27,7 +27,7 @@ alter database some_db set session_preload_libraries = 'plan_filter'; `plan_filter.statement_cost_limit`: restricts the maximum total cost for executed statements `plan_filter.limit_select_only`: restricts to `select` statements -Note that `limit_select_only = true` is not the same as read-only because `select` statements may modify data e.g. through a function call. +Note that `limit_select_only = true` is not the same as read-only because `select` statements may modify data, for example, through a function call. ## Example @@ -88,4 +88,4 @@ HINT: The plan for your query shows that it would probably have an excessive ru ## Resources -- Official [pg_plan_filter documentation](https://github.com/pgexperts/pg_plan_filter) +- Official [`pg_plan_filter` documentation](https://github.com/pgexperts/pg_plan_filter) diff --git a/apps/docs/content/guides/database/extensions/pgaudit.mdx b/apps/docs/content/guides/database/extensions/pgaudit.mdx index 5229ffb0ee9..65d8717c67e 100644 --- a/apps/docs/content/guides/database/extensions/pgaudit.mdx +++ b/apps/docs/content/guides/database/extensions/pgaudit.mdx @@ -21,7 +21,7 @@ PGAudit grants fine grain control over which statements and objects are emitted 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "pgaudit" and enable the extension. +3. Search for `pgaudit` and enable the extension. @@ -35,7 +35,7 @@ create extension pgaudit; drop extension if exists pgaudit; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension you can call `drop extension`. @@ -45,13 +45,13 @@ To disable an extension you can call `drop extension`. The `pgaudit.log` setting controls which statements to log. Available values include: -- **read**: `SELECT` and `COPY` when the source is a relation or a query. -- **write**: `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, and `COPY` when the destination is a relation. -- **function**: Function calls and `DO` blocks. -- **role**: Statements related to roles and privileges: `GRANT`, `REVOKE`, `CREATE/ALTER/DROP ROLE`. -- **ddl**: All `DDL` that is not included in the `ROLE` class. -- **misc**: Miscellaneous commands, e.g. `DISCARD`, `FETCH`, `CHECKPOINT`, `VACUUM`, `SET`. -- **misc_set**: Miscellaneous `SET` commands, e.g. `SET ROLE`. +- `read`: `SELECT` and `COPY` when the source is a relation or a query. +- `write`: `INSERT`, `UPDATE`, `DELETE`, `TRUNCATE`, and `COPY` when the destination is a relation. +- `function`: Function calls and `DO` blocks. +- `role`: Statements related to roles and privileges: `GRANT`, `REVOKE`, `CREATE/ALTER/DROP ROLE`. +- `ddl`: All `DDL` that is not included in the `ROLE` class. +- `misc`: Miscellaneous commands, for example, `DISCARD`, `FETCH`, `CHECKPOINT`, `VACUUM`, `SET`. +- `misc_set`: Miscellaneous `SET` commands, for example, `SET ROLE`. - **all**: Include all of the above. @@ -59,7 +59,7 @@ For a full list of available settings see [settings docs](https://github.com/pga -We don't currently support configuring `pgaudit.log_parameter` because it may log secrets in encrypted columns if you are using [pgsodium](/docs/guides/database/extensions/pgsodium) or [Vault](/docs/guides/database/vault). +We don't currently support configuring `pgaudit.log_parameter` because it may log secrets in encrypted columns if you are using [`pgsodium`](/docs/guides/database/extensions/pgsodium) or [Vault](/docs/guides/database/vault). You can upvote this [feature request](https://github.com/orgs/supabase/discussions/20183) if you'd like this restriction lifted. @@ -67,7 +67,7 @@ You can upvote this [feature request](https://github.com/orgs/supabase/discussio ## Example -Given a pgaudit setting +Given a `pgaudit` setting {/* prettier-ignore */} ```sql diff --git a/apps/docs/content/guides/database/extensions/pgjwt.mdx b/apps/docs/content/guides/database/extensions/pgjwt.mdx index 3b4fcc23aca..7d8c71069d1 100644 --- a/apps/docs/content/guides/database/extensions/pgjwt.mdx +++ b/apps/docs/content/guides/database/extensions/pgjwt.mdx @@ -4,7 +4,7 @@ title: 'pgjwt: JSON Web Tokens' description: 'Encode and decode JWTs in PostgreSQL' --- -The [pgjwt](https://github.com/michelp/pgjwt) (PostgreSQL JSON Web Token) extension allows you to create and parse [JSON Web Tokens (JWTs)](https://en.wikipedia.org/wiki/JSON_Web_Token) within a PostgreSQL database. JWTs are commonly used for authentication and authorization in web applications and services. +The [`pgjwt`](https://github.com/michelp/pgjwt) (PostgreSQL JSON Web Token) extension allows you to create and parse [JSON Web Tokens (JWTs)](https://en.wikipedia.org/wiki/JSON_Web_Token) within a PostgreSQL database. JWTs are commonly used for authentication and authorization in web applications and services. ## Enable the extension @@ -19,7 +19,7 @@ The [pgjwt](https://github.com/michelp/pgjwt) (PostgreSQL JSON Web Token) extens 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "pgjwt" and enable the extension. +3. Search for `pgjwt` and enable the extension. @@ -33,7 +33,7 @@ create extension pgjwt schema extensions; drop extension if exists pgjwt; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension you can call `drop extension`. It's good practice to create the extension within a separate schema (like `extensions`) to keep the `public` schema clean. @@ -67,7 +67,7 @@ select ); ``` -The pgjwt_encode function returns a string that represents the JWT, which can then be safely transmitted between parties. +The `pgjwt_encode` function returns a string that represents the JWT, which can then be safely transmitted between parties. {/* prettier-ignore */} ``` diff --git a/apps/docs/content/guides/database/extensions/pgroonga.mdx b/apps/docs/content/guides/database/extensions/pgroonga.mdx index dbdbbe423b5..e3728d85ed2 100644 --- a/apps/docs/content/guides/database/extensions/pgroonga.mdx +++ b/apps/docs/content/guides/database/extensions/pgroonga.mdx @@ -20,7 +20,7 @@ tocVideo: 'Mmmv9g_MiBA' 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "pgroonga" and enable the extension. +3. Search for `pgroonga` and enable the extension. @@ -34,7 +34,7 @@ create extension pgroonga with schema extensions; drop extension if exists pgroonga; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension you can call `drop extension`. @@ -92,7 +92,7 @@ Index Scan using ix_memos_content on memos (cost=0.00..1.11 rows=1 width=36) (2 rows) ``` -The pgroonga index is used to retrieve the result set: +The `pgroonga` index is used to retrieve the result set: ```markdown | id | content | @@ -102,7 +102,7 @@ The pgroonga index is used to retrieve the result set: ## Full text search -The `&@~` operator performs full text search. It returns any matching results. Unlike `LIKE` operator, pgroonga can search any text that contains the keyword case insensitive. +The `&@~` operator performs full text search. It returns any matching results. Unlike `LIKE` operator, `pgroonga` can search any text that contains the keyword case insensitive. Take the following example: diff --git a/apps/docs/content/guides/database/extensions/pgrouting.mdx b/apps/docs/content/guides/database/extensions/pgrouting.mdx index c257613decc..083b19df884 100644 --- a/apps/docs/content/guides/database/extensions/pgrouting.mdx +++ b/apps/docs/content/guides/database/extensions/pgrouting.mdx @@ -4,7 +4,7 @@ title: 'pgrouting: Geospatial Routing' description: 'Extends PostGIS with Geospatial Routing' --- -[pgRouting](http://pgrouting.org) is PostgreSQL and [PostGIS](http://postgis.net) extension adding geospatial routing functionality. +[`pgRouting`](http://pgrouting.org) is PostgreSQL and [PostGIS](http://postgis.net) extension adding geospatial routing functionality. The core functionality of `pgRouting` is a set of path finding algorithms including: @@ -33,7 +33,7 @@ The core functionality of `pgRouting` is a set of path finding algorithms includ 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "pgrouting" and enable the extension. +3. Search for `pgrouting` and enable the extension. @@ -47,7 +47,7 @@ create extension pgrouting cascade; drop extension if exists pgRouting; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension you can call `drop extension`. @@ -55,9 +55,9 @@ To disable an extension you can call `drop extension`. ## Example -As an example, we'll solve the [traveling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) using the pgRouting's `pgr_TSPeuclidean` function from some PostGIS coordinates. +As an example, we'll solve the [traveling salesperson problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) using the `pgRouting`'s `pgr_TSPeuclidean` function from some PostGIS coordinates. -A summary of the traveling salesman problem is, given a set of city coordinates, solve for a path that goes through each city and minimizes the total distance traveled. +A summary of the traveling salesperson problem is, given a set of city coordinates, solve for a path that goes through each city and minimizes the total distance traveled. First we populate a table with some X, Y coordinates diff --git a/apps/docs/content/guides/database/extensions/pgsodium.mdx b/apps/docs/content/guides/database/extensions/pgsodium.mdx index 4c68884799d..8c139f9ef80 100644 --- a/apps/docs/content/guides/database/extensions/pgsodium.mdx +++ b/apps/docs/content/guides/database/extensions/pgsodium.mdx @@ -4,13 +4,13 @@ title: 'pgsodium: Encryption Features' description: 'Encryption library for PostgreSQL' --- -[pgsodium](https://github.com/michelp/pgsodium) is a PostgreSQL extension which provides SQL access to [libsodium's](https://doc.libsodium.org/) high-level cryptographic algorithms. +[`pgsodium`](https://github.com/michelp/pgsodium) is a PostgreSQL extension which provides SQL access to [`libsodium`'s](https://doc.libsodium.org/) high-level cryptographic algorithms. -libsodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing, and more. It is a portable, cross-compilable, installable, and packageable fork of the [NaCl](http://nacl.cr.yp.to/) library, with a compatible but extended API to improve usability even further. +`libsodium` is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing, and more. It is a portable, cross-compilable, installable, and packageable fork of the [NaCl](http://nacl.cr.yp.to/) library, with a compatible but extended API to improve usability even further. The design choices emphasize security and ease of use. But despite the emphasis on high security, primitives are faster across-the-board than most implementations. -pgsodium exposes the following libsodium APIs to SQL: +`pgsodium` exposes the following `libsodium` APIs to SQL: - [Generating Random Data](https://github.com/michelp/pgsodium/#generating-random-data) - [Secret key cryptography](https://github.com/michelp/pgsodium/#secret-key-cryptography) @@ -53,7 +53,7 @@ Note that Supabase projects are already encrypted at rest by default. ## Get the root encryption key for your Supabase project -Encryption requires keys. Keeping the keys in the same database as the encrypted data would be unsafe. For more information about managing the pgsodium root encryption key on your Supabase project see **[encryption key location](/docs/guides/database/vault#encryption-key-location)**. This key is required to decrypt values stored in [Supabase Vault](/docs/guides/database/vault) and data encrypted with Transparent Column Encryption. +Encryption requires keys. Keeping the keys in the same database as the encrypted data would be unsafe. For more information about managing the `pgsodium` root encryption key on your Supabase project see **[encryption key location](/docs/guides/database/vault#encryption-key-location)**. This key is required to decrypt values stored in [Supabase Vault](/docs/guides/database/vault) and data encrypted with Transparent Column Encryption. ## Enable the extension @@ -68,7 +68,7 @@ Encryption requires keys. Keeping the keys in the same database as the encrypted 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "pgsodium" and enable the extension. +3. Search for `pgsodium` and enable the extension. diff --git a/apps/docs/content/guides/database/extensions/pgtap.mdx b/apps/docs/content/guides/database/extensions/pgtap.mdx index 8b00e4c1bbb..bbcd7c3b125 100644 --- a/apps/docs/content/guides/database/extensions/pgtap.mdx +++ b/apps/docs/content/guides/database/extensions/pgtap.mdx @@ -26,7 +26,7 @@ Let's cover some basic concepts: 1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. -3. Search for "pgtap" and enable the extension. +3. Search for `pgtap` and enable the extension. @@ -39,7 +39,7 @@ create extension pgtap with schema extensions; drop extension if exists pgtap; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension you can call `drop extension`. It's good practice to create the extension within a separate schema (like `extensions`) to keep the `public` schema clean. @@ -149,7 +149,7 @@ rollback; API: - [`function_returns()`](https://pgtap.org/documentation.html#function_returns): Tests that a particular function returns a particular data type -- [`is_definer()`](https://pgtap.org/documentation.html#is_definer): Tests that a function is a security definer (i.e., a “setuid” function). +- [`is_definer()`](https://pgtap.org/documentation.html#is_definer): Tests that a function is a security definer (that is, a `setuid` function). ## Resources diff --git a/apps/docs/content/guides/database/extensions/plv8.mdx b/apps/docs/content/guides/database/extensions/plv8.mdx index 30ac72e01da..a27592d1270 100644 --- a/apps/docs/content/guides/database/extensions/plv8.mdx +++ b/apps/docs/content/guides/database/extensions/plv8.mdx @@ -8,7 +8,7 @@ The `plv8` extension allows you use JavaScript within Postgres. ## Overview -While Postgres natively runs SQL, it can also run other "procedural languages". +While Postgres natively runs SQL, it can also run other procedural languages. `plv8` allows you to run JavaScript code - specifically any code that runs on the [V8 JavaScript engine](https://v8.dev). It can be used for database functions, triggers, queries and more. @@ -39,7 +39,7 @@ create extension plv8; drop extension if exists plv8; ``` -Even though the SQL code is `create extension`, this is the equivalent of "enabling the extension". +Even though the SQL code is `create extension`, this is the equivalent of enabling the extension. To disable an extension, call `drop extension`. Procedural languages are automatically installed within `pg_catalog`, so you don't need to specify a schema. diff --git a/apps/docs/content/guides/database/full-text-search.mdx b/apps/docs/content/guides/database/full-text-search.mdx index c8511c962ab..fde0c4b5b60 100644 --- a/apps/docs/content/guides/database/full-text-search.mdx +++ b/apps/docs/content/guides/database/full-text-search.mdx @@ -30,6 +30,8 @@ For this guide we'll use the following example data: > +{/* */} + | id | title | author | description | | --- | ----------------------------------- | ---------------------- | ------------------------------------------------------------------ | | 1 | The Poky Little Puppy | Janette Sebring Lowrey | Puppy is slower than other, bigger animals. | @@ -38,6 +40,8 @@ For this guide we'll use the following example data: | 4 | Green Eggs and Ham | Dr. Seuss | Sam has changing food preferences and eats unusually colored food. | | 5 | Harry Potter and the Goblet of Fire | J.K. Rowling | Fourth year of school starts, big drama ensues. | +{/* */} + @@ -80,7 +84,7 @@ The functions we'll cover in this guide are: ### `to_tsvector()` [#to-tsvector] -Converts your data into searchable "tokens". `to_tsvector()` stands for "to text search vector". For example: +Converts your data into searchable tokens. `to_tsvector()` stands for "to text search vector." For example: ```sql select to_tsvector('green eggs and ham'); @@ -91,10 +95,10 @@ Collectively these tokens are called a "document" which Postgres can use for com ### `to_tsquery()` [#to-tsquery] -Converts a query string into "tokens" to match. `to_tsquery()` stands for "to text search query". +Converts a query string into tokens to match. `to_tsquery()` stands for "to text search query." This conversion step is important because we will want to "fuzzy match" on keywords. -For example if a user searches for "eggs", and a column has the value "egg", we probably still want to return a match. +For example if a user searches for `eggs`, and a column has the value `egg`, we probably still want to return a match. ### Match: `@@` [#match] @@ -253,11 +257,15 @@ val data = supabase.from("books").select { +{/* */} + | id | title | author | description | | --- | ----------------------------------- | ----------------- | ----------------------------------------------- | | 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. | | 5 | Harry Potter and the Goblet of Fire | J.K. Rowling | Fourth year of school starts, big drama ensues. | +{/* */} + @@ -338,11 +346,15 @@ val data = supabase.from("books").select { +{/* */} + | id | title | author | description | | --- | --------------------- | ---------------------- | ------------------------------------------- | | 1 | The Poky Little Puppy | Janette Sebring Lowrey | Puppy is slower than other, bigger animals. | | 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. | +{/* */} + @@ -403,10 +415,14 @@ val data = supabase.from("books").select { +{/* */} + | id | title | author | description | | --- | ------ | ----------------- | -------------------------------- | | 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. | +{/* */} + @@ -467,11 +483,15 @@ val data = supabase.from("books").select { +{/* */} + | id | title | author | description | | --- | --------------------- | ---------------------- | ------------------------------------------- | | 1 | The Poky Little Puppy | Janette Sebring Lowrey | Puppy is slower than other, bigger animals. | | 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. | +{/* */} + @@ -514,6 +534,8 @@ from books; +{/* */} + | id | fts | | --- | --------------------------------------------------------------------------------------------------------------- | | 1 | 'anim':7 'bigger':6 'littl':10 'poki':9 'puppi':1,11 'slower':3 | @@ -522,6 +544,8 @@ from books; | 4 | 'chang':3 'color':9 'eat':7 'egg':12 'food':4,10 'green':11 'ham':14 'prefer':5 'sam':1 'unus':8 | | 5 | 'big':6 'drama':7 'ensu':8 'fire':15 'fourth':1 'goblet':13 'harri':9 'potter':10 'school':4 'start':5 'year':2 | +{/* */} + @@ -578,10 +602,14 @@ val data = supabase.from("books").select { +{/* */} + | id | title | author | description | fts | | --- | ------ | ----------------- | -------------------------------- | ------------------------------------------------------- | | 3 | Tootle | Gertrude Crampton | Little toy train has big dreams. | 'big':5 'dream':6 'littl':1 'tootl':7 'toy':2 'train':3 | +{/* */} + diff --git a/apps/docs/content/guides/database/managing-timezones.mdx b/apps/docs/content/guides/database/managing-timezones.mdx index 2b3ab247ae6..d74a40bf348 100644 --- a/apps/docs/content/guides/database/managing-timezones.mdx +++ b/apps/docs/content/guides/database/managing-timezones.mdx @@ -6,7 +6,7 @@ description: 'How to change your database timezone.' --- Every Supabase database is set to UTC timezone by default. We strongly recommend keeping it this way, even if your users are in a different location. -This is because it makes it much easier to calculate differences between timezones if you adopt the mental model that "everything in my database is in UTC time". +This is because it makes it much easier to calculate differences between timezones if you adopt the mental model that "everything in my database is in UTC time." ### Change timezone diff --git a/apps/docs/content/guides/database/postgres/cascade-deletes.mdx b/apps/docs/content/guides/database/postgres/cascade-deletes.mdx index 8f3b223a120..cad764f94dd 100644 --- a/apps/docs/content/guides/database/postgres/cascade-deletes.mdx +++ b/apps/docs/content/guides/database/postgres/cascade-deletes.mdx @@ -6,10 +6,10 @@ footerHelpType: 'postgres' There are 5 options for foreign key constraint deletes: -1. **CASCADE:** When a row is deleted from the parent table, all related rows in the child table(s) are deleted as well. -2. **RESTRICT:** When a row is deleted from the parent table, the delete operation is aborted if there are any related rows in the child table(s). -3. **SET NULL:** When a row is deleted from the parent table, the values of the foreign key columns in the child table(s) are set to NULL. -4. **SET DEFAULT:** When a row is deleted from the parent table, the values of the foreign key columns in the child table(s) are set to their default values. +1. **CASCADE:** When a row is deleted from the parent table, all related rows in the child tables are deleted as well. +2. **RESTRICT:** When a row is deleted from the parent table, the delete operation is aborted if there are any related rows in the child tables. +3. **SET NULL:** When a row is deleted from the parent table, the values of the foreign key columns in the child tables are set to NULL. +4. **SET DEFAULT:** When a row is deleted from the parent table, the values of the foreign key columns in the child tables are set to their default values. 5. **NO ACTION:** This option is similar to RESTRICT, but it also has the option to be “deferred” to the end of a transaction. This means that other cascading deletes can run first, and then this delete constraint will only throw an error if there is referenced data remaining _at the end of the transaction_. These options can be specified when defining a foreign key constraint using the "ON DELETE" clause. For example, the following SQL statement creates a foreign key constraint with the `CASCADE` option: @@ -20,7 +20,7 @@ add constraint fk_parent foreign key (parent_id) references parent_table (id) on delete cascade; ``` -This means that when a row is deleted from the "parent_table", all related rows in the "child_table" will be deleted as well. +This means that when a row is deleted from the `parent_table`, all related rows in the `child_table` will be deleted as well. ## `RESTRICT` vs `NO ACTION` @@ -28,11 +28,11 @@ The difference between `NO ACTION` and `RESTRICT` is subtle and can be a bit con Both `NO ACTION` and `RESTRICT` are used to prevent deletion of a row in a parent table if there are related rows in a child table. However, there is a subtle difference in how they behave. -When a foreign key constraint is defined with the option `RESTRICT`, it means that if a row in the parent table is deleted, the database will immediately raise an error and prevent the deletion of the row in the parent table. The database will not delete, update or set to NULL any rows in the referenced table(s). +When a foreign key constraint is defined with the option `RESTRICT`, it means that if a row in the parent table is deleted, the database will immediately raise an error and prevent the deletion of the row in the parent table. The database will not delete, update or set to NULL any rows in the referenced tables. When a foreign key constraint is defined with the option `NO ACTION`, it means that if a row in the parent table is deleted, the database will also raise an error and prevent the deletion of the row in the parent table. However unlike `RESTRICT`, `NO ACTION` has the option defer the check using `INITIALLY DEFERRED`. This will only raise the above error _if_ the referenced rows still exist at the end of the transaction. -The difference from `RESTRICT` is that a constraint marked as `NO ACTION INITIALLY DEFERRED` is deferred until the end of the transaction, rather than running immediately. If, for example there is another foreign key constraint between the same tables marked as `CASCADE`, the cascade will occur first and delete the referenced rows, and no error will be thrown by the deferred constraint. Otherwise if there are still rows referencing the parent row by the end of the transaction, an error will be raised just like before. Just like `RESTRICT`, the database will not delete, update or set to NULL any rows in the referenced table(s). +The difference from `RESTRICT` is that a constraint marked as `NO ACTION INITIALLY DEFERRED` is deferred until the end of the transaction, rather than running immediately. If, for example there is another foreign key constraint between the same tables marked as `CASCADE`, the cascade will occur first and delete the referenced rows, and no error will be thrown by the deferred constraint. Otherwise if there are still rows referencing the parent row by the end of the transaction, an error will be raised just like before. Just like `RESTRICT`, the database will not delete, update or set to NULL any rows in the referenced tables. In practice, you can use either `NO ACTION` or `RESTRICT` depending on your needs. `NO ACTION` is the default behavior if you do not specify anything. If you prefer to defer the check until the end of the transaction, use `NO ACTION INITIALLY DEFERRED`. @@ -48,10 +48,10 @@ Let's further illustrate the difference with an example. We'll use the following `parent` -| id | name | parent_id | -| --- | ------- | --------- | -| 1 | Charles | 1 | -| 2 | Diana | 1 | +| id | name | `parent_id` | +| --- | ------- | ----------- | +| 1 | Charles | 1 | +| 2 | Diana | 1 | `child` diff --git a/apps/docs/content/guides/database/postgres/configuration.mdx b/apps/docs/content/guides/database/postgres/configuration.mdx index f9177a0a251..087176ba1d2 100644 --- a/apps/docs/content/guides/database/postgres/configuration.mdx +++ b/apps/docs/content/guides/database/postgres/configuration.mdx @@ -36,7 +36,7 @@ This data can further be used in conjunction with the [`explain`](https://www.po ## Managing timezones Every Supabase database is set to UTC timezone by default. We strongly recommend keeping it this way, even if your users are in a different location. -This is because it makes it much easier to calculate differences between timezones if you adopt the mental model that "everything in my database is in UTC time". +This is because it makes it much easier to calculate differences between timezones if you adopt the mental model that "everything in my database is in UTC time." ### Change timezone diff --git a/apps/docs/content/guides/database/postgres/roles.mdx b/apps/docs/content/guides/database/postgres/roles.mdx index 257d777cd2d..bacad005667 100644 --- a/apps/docs/content/guides/database/postgres/roles.mdx +++ b/apps/docs/content/guides/database/postgres/roles.mdx @@ -38,11 +38,11 @@ Your Postgres database is the core of your Supabase project, so it's important t ### Special symbols in passwords -If you use special symbols in your postgres password, you must remember to [percent-encode](https://en.wikipedia.org/wiki/Percent-encoding) your password later if using the postgres connection string e.g. `postgresql://postgres.projectref:p%3Dword@aws-0-us-east-1.pooler.supabase.com:6543/postgres` +If you use special symbols in your postgres password, you must remember to [percent-encode](https://en.wikipedia.org/wiki/Percent-encoding) your password later if using the postgres connection string, for example, `postgresql://postgres.projectref:p%3Dword@aws-0-us-east-1.pooler.supabase.com:6543/postgres` ### Changing your project password -When you created your project you were also asked to enter a password. This is actually the password for the `postgres` role in your database. You can update this from the Dashboard under the [database settings](https://supabase.com/dashboard/project/_/settings/database) page. You should _never_ give this to 3rd-party service unless you absolutely trust them. Instead, we recommend that you create a new user for every service that you want to give access too. This will also help you with debugging - you can see every query that each role is executing in your database within `pg_stat_statements`. +When you created your project you were also asked to enter a password. This is actually the password for the `postgres` role in your database. You can update this from the Dashboard under the [database settings](https://supabase.com/dashboard/project/_/settings/database) page. You should _never_ give this to third-party service unless you absolutely trust them. Instead, we recommend that you create a new user for every service that you want to give access too. This will also help you with debugging - you can see every query that each role is executing in your database within `pg_stat_statements`. ## Granting permissions @@ -86,7 +86,7 @@ The default Postgres role. This has admin privileges. ### `anon` -For "anonymous access". This is the role which the API (PostgREST) will use when a user _is not_ logged in. +For "anonymous access." This is the role which the API (PostgREST) will use when a user _is not_ logged in. ### `authenticator` @@ -95,7 +95,7 @@ A special role for the API (PostgREST). It has very limited access, and is used ### `authenticated` -For "authenticated access". This is the role which the API (PostgREST) will use when a user _is_ logged in. +For "authenticated access." This is the role which the API (PostgREST) will use when a user _is_ logged in. ### `service_role` diff --git a/apps/docs/content/guides/database/postgres/row-level-security.mdx b/apps/docs/content/guides/database/postgres/row-level-security.mdx index 286391079de..6d7450c3407 100644 --- a/apps/docs/content/guides/database/postgres/row-level-security.mdx +++ b/apps/docs/content/guides/database/postgres/row-level-security.mdx @@ -11,7 +11,7 @@ When you need granular authorization rules, nothing beats Postgres's [Row Level RLS is incredibly powerful and flexible, allowing you to write complex SQL rules that fit your unique business needs. RLS can be [combined with Supabase Auth](/docs/guides/auth/row-level-security) for end-to-end user security from the browser to the database. -RLS is a Postgres primitive and can provide "[defense in depth]()" to protect your data from malicious actors even when accessed through 3rd party tooling. +RLS is a Postgres primitive and can provide "[defense in depth]()" to protect your data from malicious actors even when accessed through third-party tooling. ## Policies @@ -219,7 +219,7 @@ to authenticated using ( (select auth.uid()) = user_id ); ``` -This method works well for JWT functions like `auth.uid()` and `auth.jwt()` as well as `security definer` Functions. Wrapping the function causes an initPlan to be run by the Postgres optimizer, which allows it to "cache" the results per-statement, rather than calling the function on each row. +This method works well for JWT functions like `auth.uid()` and `auth.jwt()` as well as `security definer` Functions. Wrapping the function causes an `initPlan` to be run by the Postgres optimizer, which allows it to "cache" the results per-statement, rather than calling the function on each row. @@ -239,7 +239,7 @@ You can only use this technique if the results of the query or function do not c ### Add filters to every query -Policies are "implicit where clauses", so it's common to run `select` statements without any filters. This is a bad pattern for performance. Instead of doing this (JS client example): +Policies are "implicit where clauses," so it's common to run `select` statements without any filters. This is a bad pattern for performance. Instead of doing this (JS client example): {/* prettier-ignore */} ```js diff --git a/apps/docs/content/guides/database/postgres/triggers.mdx b/apps/docs/content/guides/database/postgres/triggers.mdx index 21db2217f59..e405dfff549 100644 --- a/apps/docs/content/guides/database/postgres/triggers.mdx +++ b/apps/docs/content/guides/database/postgres/triggers.mdx @@ -99,7 +99,7 @@ execute function after_delete_function(); There are two options available for executing triggers: - `for each row`: specifies that the trigger function should be executed once for each affected row. -- `for each statement`: the trigger is executed once for the entire operation (eg, once on insert). This can be more efficient than `for each row` when dealing with multiple rows affected by a single SQL statement, as they allow you to perform calculations or updates on groups of rows at once. +- `for each statement`: the trigger is executed once for the entire operation (for example, once on insert). This can be more efficient than `for each row` when dealing with multiple rows affected by a single SQL statement, as they allow you to perform calculations or updates on groups of rows at once. ## Dropping a trigger diff --git a/apps/docs/content/guides/database/query-optimization.mdx b/apps/docs/content/guides/database/query-optimization.mdx index 7602ae4603e..bf3c2f169b3 100644 --- a/apps/docs/content/guides/database/query-optimization.mdx +++ b/apps/docs/content/guides/database/query-optimization.mdx @@ -14,7 +14,7 @@ This guide is intended to: This is not a comprehensive resource, but rather a helpful starting point for your optimization journey. -If you're new to query optimization, you may be interested in [index_advisor](/docs/guides/database/extensions/index_advisor), our tool for automatically detecting indexes that improve performance on a given query. +If you're new to query optimization, you may be interested in [`index_advisor`](/docs/guides/database/extensions/index_advisor), our tool for automatically detecting indexes that improve performance on a given query. ## Example query @@ -66,7 +66,7 @@ create index idx_orders_customer_id on orders (customer_id); Sorting can also be optimized by indexing: -- An index on `b.date_of_purchase` wcan improve the sorting process, and is particularly beneficial when a subset of rows is being returned with a `limit` clause. +- An index on `b.date_of_purchase` can improve the sorting process, and is particularly beneficial when a subset of rows is being returned with a `limit` clause. ```sql create index idx_orders_date_of_purchase on orders (date_of_purchase); diff --git a/apps/docs/content/guides/database/vault.mdx b/apps/docs/content/guides/database/vault.mdx index a16f814633d..12aa4cc193b 100644 --- a/apps/docs/content/guides/database/vault.mdx +++ b/apps/docs/content/guides/database/vault.mdx @@ -79,7 +79,7 @@ updated_at | 2022-12-14 02:34:23.85159+00 -Alternatively, you can create a secret by `insert`ing data into the `vault.secret` table: +Alternatively, you can create a secret by inserting data into the `vault.secret` table: {/* prettier-ignore */} ```sql @@ -206,11 +206,11 @@ updated_at | 2022-12-14 02:51:13.938396+00 >
    -As we mentioned, the Vault uses pgsodium's Transparent Column Encryption (TCE) to store secrets in an authenticated encrypted form. There are some details around that you may be curious about, what does authenticated mean, and where are encryption keys store? This section explains those details. +As we mentioned, the Vault uses `pgsodium`'s Transparent Column Encryption (TCE) to store secrets in an authenticated encrypted form. There are some details around that you may be curious about, what does authenticated mean, and where are encryption keys store? This section explains those details. ### Authenticated encryption with associated data -The first important feature of TCE is that it uses an [Authenticated Encryption with Associated Data]() encryption algorithm (based on libsodium). +The first important feature of TCE is that it uses an [Authenticated Encryption with Associated Data]() encryption algorithm (based on `libsodium`). ### Encryption key location @@ -218,7 +218,7 @@ The first important feature of TCE is that it uses an [Authenticated Encryption **Associated Data** means that you can include any other columns from the same row as part of the signature computation. This doesn't encrypt those other columns - rather it ensures that your encrypted value is only associated with columns from that row. If an attacker were to copy an encrypted value from another row to the current one, the signature would be rejected (assuming you used a unique column in the associated data). -Another important feature of pgsodium is that the encryption keys are never stored in the database alongside the encrypted data. Instead, only a **Key ID** is stored, which is a reference to the key that is only accessible outside of SQL. Even if an attacker can capture a dump of your entire database, they will see only encrypted data and key IDs, _never the raw key itself_. +Another important feature of `pgsodium` is that the encryption keys are never stored in the database alongside the encrypted data. Instead, only a **Key ID** is stored, which is a reference to the key that is only accessible outside of SQL. Even if an attacker can capture a dump of your entire database, they will see only encrypted data and key IDs, _never the raw key itself_. This is an important safety precaution - there is little value in storing the encryption key in the database itself as this would be like locking your front door but leaving the key in the lock! Storing the key outside the database fixes this issue. diff --git a/apps/docs/content/guides/functions/dart-edge.mdx b/apps/docs/content/guides/functions/dart-edge.mdx index 98b45295dfe..7c50737ddd5 100644 --- a/apps/docs/content/guides/functions/dart-edge.mdx +++ b/apps/docs/content/guides/functions/dart-edge.mdx @@ -13,7 +13,7 @@ Dart Edge is an experimental project - it's probably not ready for production us -## Pre requirements +## Prerequisites Make sure you have [the edge CLI](https://docs.dartedge.dev/#getting-started) installed in addition to [the Supabase CLI](https://supabase.com/docs/guides/cli#installation). @@ -74,7 +74,7 @@ Now let’s try to interact with our Supabase database. We will start by install ### Add dependencies -Add [supabase](https://pub.dev/packages/supabase) to interact with Supabase service. +Add [`supabase`](https://pub.dev/packages/supabase) to interact with Supabase service. ```bash dart pub add supabase @@ -125,14 +125,13 @@ supabase: project_path: './supabase' ``` -Also, currently Dart Edge doesn't work with the latest versions of Flutter. If you do have the latest version of Flutter on your machine, you can use [FVM](https://fvm.app/) to use an older version of Flutter for your Dart Edge project. +Also, currently Dart Edge doesn't work with the latest versions of Flutter. If you do have the latest version of Flutter on your machine, you can use [Flutter Version Management (FVM)](https://fvm.app/) to use an older version of Flutter for your Dart Edge project. ```bash fvm use 3.7.12 -f ``` -You can read more about how to configure FVM (Flutter -Version Management) for your project in the [FVM documentation](https://fvm.app/documentation/getting-started). +You can read more about how to configure FVM for your project in the [FVM documentation](https://fvm.app/documentation/getting-started). Run the following command to compile your Dart code. This command will start a watcher that will recompile anytime you make changes to your code. diff --git a/apps/docs/content/guides/getting-started/architecture.mdx b/apps/docs/content/guides/getting-started/architecture.mdx index 9e3bd8f92f0..943f13b702d 100644 --- a/apps/docs/content/guides/getting-started/architecture.mdx +++ b/apps/docs/content/guides/getting-started/architecture.mdx @@ -29,7 +29,7 @@ Each Supabase project consists of several tools: ### 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. +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) @@ -57,7 +57,7 @@ A JWT-based API for managing users and issuing access tokens. This integrates wi ### 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. +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) @@ -86,8 +86,8 @@ An S3-compatible object storage service that stores metadata in Postgres. 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) +- Official Docs: [Deno documentation](https://deno.land/) +- Source code: [Deno source code](https://github.com/denoland/deno) - License: [MIT](https://github.com/denoland/deno/blob/main/LICENSE.md) - Language: TypeScript / Rust @@ -104,14 +104,14 @@ A RESTful API for managing your Postgres. Fetch tables, add roles, and run queri A cloud-native, multi-tenant Postgres connection pooler. -- Official Docs: [Supavisor Github Pages](https://supabase.github.io/supavisor/) -- Source code: [supabase/supavisor](https://github.com/supabase/supavisor) +- Official Docs: [Supavisor GitHub Pages](https://supabase.github.io/supavisor/) +- Source code: [`supabase/supavisor`](https://github.com/supabase/supavisor) - License: [Apache 2.0](https://github.com/supabase/supavisor/blob/main/LICENSE) - Language: Elixir ### Kong (API gateway) -A cloud-native API gateway, built on top of Nginx. +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) @@ -144,7 +144,7 @@ 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 and CSV files). If a new standard emerges which competes with a "Supabase" approach, we will deprecate the approach in favor of the standard. +We use existing standards to increase portability (like `pg_dump` and 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 diff --git a/apps/docs/content/guides/getting-started/features.mdx b/apps/docs/content/guides/getting-started/features.mdx index d9956b15c21..e7127c000ea 100644 --- a/apps/docs/content/guides/getting-started/features.mdx +++ b/apps/docs/content/guides/getting-started/features.mdx @@ -68,7 +68,7 @@ Provide phone logins using a third-party SMS provider. [Docs](/docs/guides/auth/ Control the data each user can access with Postgres Policies. [Docs](/docs/guides/auth/row-level-security). -### Serverside Auth helpers +### Server-side Auth helpers Helpers for implementing user authentication in popular frameworks like [Next.js](/docs/guides/auth/auth-helpers/nextjs) and [SvelteKit](/docs/guides/auth/auth-helpers/sveltekit) @@ -82,7 +82,7 @@ Build login and registration pages with custom themes. [Docs](/docs/guides/auth/ ### Auto-generated REST API -RESTful APIs are autogenerated from your database, without a single line of code. [Docs](/docs/guides/api#rest-api-overview). +RESTful APIs are auto-generated from your database, without a single line of code. [Docs](/docs/guides/api#rest-api-overview). ### Auto-generated GraphQL API diff --git a/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx b/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx index 62d9f2c0644..4a308fe33fc 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-angular.mdx @@ -492,7 +492,7 @@ export class AvatarComponent { ### Add the new widget -And then we can add the widget on top of the **AccountComponent** html template: +And then we can add the widget on top of the **AccountComponent** HTML template: ```html src/app/account.component.html
    diff --git a/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx b/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx index 0bacd902411..43873bc3d77 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-expo-react-native.mdx @@ -460,6 +460,8 @@ expo install expo-image-picker Let's create an avatar for the user so that they can upload a profile photo. We can start by creating a new component: +{/* */} + ```tsx components/Avatar.tsx import { useState, useEffect } from 'react' import { supabase } from '../lib/supabase' @@ -593,6 +595,8 @@ const styles = StyleSheet.create({ }) ``` +{/* */} + ### Add the new widget And then we can add the widget to the Account page: diff --git a/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx b/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx index e2a685dbbcd..db01f52844a 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-ionic-angular.mdx @@ -138,7 +138,7 @@ export class SupabaseService { Let's set up a route to manage logins and signups. We'll use Magic Links so users can sign in with their email without using passwords. Create a **LoginPage** with the `ionic g page login` Ionic CLI command. -> This guide will show the template inline, but the example app will have templateUrls +> This guide will show the template inline, but the example app will have `templateUrl`s ```ts src/app/login/login.page.ts import { Component, OnInit } from '@angular/core' diff --git a/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx b/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx index 167a5b595b5..65bd550fc5e 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-kotlin.mdx @@ -33,7 +33,7 @@ Open Android Studio > New Project > Base Activity (Jetpack Compose). Create or edit the `local.properties` file at the root (same level as `build.gradle`) of your project. -> **Note**: Do not commit this file to your source control, e.g. by adding it to your `.gitignore` file! +> **Note**: Do not commit this file to your source control, for example, by adding it to your `.gitignore` file! ```kotlin SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY @@ -75,7 +75,7 @@ val apiKey = BuildConfig.SUPABASE_ANON_KEY ![Gradle dependencies](/docs/img/guides/kotlin/gradle-dependencies.png) -In the `build.gradle` (app) file, add these dependencies then press "Sync now". Replace the dependency version placeholders `$supabase_version` and `$ktor_version` with their respective latest versions. +In the `build.gradle` (app) file, add these dependencies then press "Sync now." Replace the dependency version placeholders `$supabase_version` and `$ktor_version` with their respective latest versions. ```kotlin implementation "io.github.jan-tennert.supabase:postgrest-kt:$supabase_version" diff --git a/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx b/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx index f98fe348e90..58300bd88f3 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-redwoodjs.mdx @@ -17,12 +17,12 @@ If you get stuck while working through this guide, refer to the [full example on A Redwood application is split into two parts: a frontend and a backend. This is represented as two node projects within a single monorepo. -The frontend project is called **`web`** and the backend project is called **`api`**. For clarity, we will refer to these in prose as **"sides"**, i.e. the "web side" and the "api side". +The frontend project is called **`web`** and the backend project is called **`api`**. For clarity, we will refer to these in prose as **"sides,"** that is, the `web side` and the `api side`. They are separate projects because code on the `web side` will end up running in the user's browser while code on the `api side` will run on a server somewhere. -Important: When this guide refers to "API", that means the Supabase API and when it refers to "api side", that means the RedwoodJS `api side`. +Important: When this guide refers to "API," that means the Supabase API and when it refers to `api side`, that means the RedwoodJS `api side`. @@ -51,7 +51,7 @@ RedwoodJS requires Node.js `>= 14.x <= 16.x` and Yarn `>= 1.15`. -Make sure you have installed yarn since RedwoodJS relies on it to [manage its packages in workspaces](https://classic.yarnpkg.com/lang/en/docs/workspaces/) for its `web` and `api` "sides". +Make sure you have installed yarn since RedwoodJS relies on it to [manage its packages in workspaces](https://classic.yarnpkg.com/lang/en/docs/workspaces/) for its `web` and `api` "sides." ### Initialize a RedwoodJS app @@ -428,7 +428,7 @@ export default Account ``` You'll see the use of `useAuth()` several times. Redwood's `useAuth` hook provides convenient ways to access -logIn, logOut, currentUser, and access the `supabase` authenticate client. We'll use it to get an instance +`logIn`, `logOut`, `currentUser`, and access the `supabase` authenticate client. We'll use it to get an instance of the supabase client to interact with your API. ### Update home page diff --git a/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx b/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx index e3f09494ada..502e4d6cd3a 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-refine.mdx @@ -90,7 +90,7 @@ VITE_SUPABASE_URL=YOUR_SUPABASE_URL VITE_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY ``` -The `supabaseClient` will be used in fetch calls to Supabase endpoints from our app. As we'll see below, the client is instrumental in implementing authentication using refine's auth provider methods and CRUD actions with appropriate data provider methods. +The `supabaseClient` will be used in fetch calls to Supabase endpoints from our app. As we'll see below, the client is instrumental in implementing authentication using Refine's auth provider methods and CRUD actions with appropriate data provider methods. One optional step is to update the CSS file `src/App.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/refine-user-management/src/App.css). @@ -404,7 +404,7 @@ Notice above that, we are using three refine hooks, namely the [`useGetIdentity( `useForm()`, in contrast, is a data hook that exposes a series of useful objects that serve the edit form. For example, we are grabbing the `onFinish` function to submit the form with the `handleSubmit` event handler. We are also using `formLoading` property to present state changes of the submitted form. -The `useForm()` hook is a higher-level hook built on top of refine's `useForm()` core hook. It fully supports form state management, field validation and submission using React Hook Form. Behind the scenes, it invokes the `dataProvider.getOne` method to get the user profile data from our Supabase `/profiles` endpoint and also invokes `dataProvider.update` method when `onFinish()` is called. +The `useForm()` hook is a higher-level hook built on top of Refine's `useForm()` core hook. It fully supports form state management, field validation and submission using React Hook Form. Behind the scenes, it invokes the `dataProvider.getOne` method to get the user profile data from our Supabase `/profiles` endpoint and also invokes `dataProvider.update` method when `onFinish()` is called. ### Launch! diff --git a/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx b/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx index 10a8982af85..7610c78ef0e 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-sveltekit.mdx @@ -228,7 +228,7 @@ Add the `Auth` component to your home page
    ``` -Create a `src/routes/+page.server.ts` file that will return our website url to be used in our `redirectTo` above. +Create a `src/routes/+page.server.ts` file that will return our website URL to be used in our `redirectTo` above. ```ts // src/routes/+page.server.ts diff --git a/apps/docs/content/guides/realtime.mdx b/apps/docs/content/guides/realtime.mdx index fa76be5970d..dee6cf6766f 100644 --- a/apps/docs/content/guides/realtime.mdx +++ b/apps/docs/content/guides/realtime.mdx @@ -120,7 +120,13 @@ called `supabase_realtime`, and by managing this publication you can control whi ## Examples
    - {examples.map((x) => ( + {[ + { + name: 'Multiplayer.dev', + description: 'Mouse movements and chat messages.', + href: 'https://multiplayer.dev', + }, + ].map((x) => (
    {x.description} @@ -129,14 +135,6 @@ called `supabase_realtime`, and by managing this publication you can control whi ))}
    -export const examples = [ - { - name: 'Multiplayer.dev', - description: 'Mouse movements and chat messages.', - href: 'https://multiplayer.dev', - }, -] - ## Resources Find the source code and documentation in the Supabase GitHub repository. diff --git a/apps/docs/content/guides/resources.mdx b/apps/docs/content/guides/resources.mdx index d455bae4919..d69a46f7a1e 100644 --- a/apps/docs/content/guides/resources.mdx +++ b/apps/docs/content/guides/resources.mdx @@ -4,6 +4,8 @@ description: 'Resources for getting started building with Supabase.' hideToc: true --- +{/* */} +
    diff --git a/apps/docs/content/guides/self-hosting/docker.mdx b/apps/docs/content/guides/self-hosting/docker.mdx index 24d5793860d..4fee2c0d8ba 100644 --- a/apps/docs/content/guides/self-hosting/docker.mdx +++ b/apps/docs/content/guides/self-hosting/docker.mdx @@ -57,7 +57,7 @@ You should change these credentials as soon as possible using the [instructions] ### Accessing the APIs -Each of the APIs are available through the the same API gateway: +Each of the APIs are available through the same API gateway: - REST: `http://:8000/rest/v1/` - Auth: `http://:8000/auth/v1/` @@ -243,7 +243,7 @@ Each system can be [configured](../self-hosting#configuration) independently. So #### Configuring an email server -You will need to use a production-ready SMTP server for sending emails. You can configure the SMTP server by updating the the following environment variables: +You will need to use a production-ready SMTP server for sending emails. You can configure the SMTP server by updating the following environment variables: ```sh .env SMTP_ADMIN_EMAIL= @@ -318,8 +318,6 @@ docker rm supabase-analytics --- -{/* Finish with a video. This also appears in the Sidebar via the "tocVideo" metadata */} - ## Demo A minimal setup working on Ubuntu, hosted on Digital Ocean. diff --git a/vale/styles/Custom/Acronyms.yml b/vale/styles/Custom/Acronyms.yml index 2fdabe6af4c..025136da501 100644 --- a/vale/styles/Custom/Acronyms.yml +++ b/vale/styles/Custom/Acronyms.yml @@ -1,5 +1,5 @@ extends: conditional -message: "Spell out '%s', if it's unfamiliar to the audience." +message: "The first instance of '%s' should be spelled out, followed by the acronym in brackets. For example: 'Data Definition Language (DDL)'" link: 'https://developers.google.com/style/abbreviations' level: suggestion ignorecase: false @@ -9,6 +9,7 @@ second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' # ... with the exception of these: exceptions: - API + - ARM - ASP - CLI - CPU @@ -20,6 +21,7 @@ exceptions: - FAQ - GCC - GDB + - GDPR - GET - GPT - GPU @@ -61,6 +63,7 @@ exceptions: - URI - URL - USB + - USD - UTF - XML - XSS diff --git a/vale/styles/Custom/Capitalize.yml b/vale/styles/Custom/Capitalize.yml new file mode 100644 index 00000000000..5413e132ab8 --- /dev/null +++ b/vale/styles/Custom/Capitalize.yml @@ -0,0 +1,11 @@ +extends: substitution +message: "Captalize this to make it a proper noun: '%s' -> '%s'" +link: 'https://developers.google.com/style/word-list' +level: warning +ignorecase: false +action: + name: replace +swap: + auth hooks?: Auth Hooks? + edge functions?: Edge Functions? + 'role[- ]?based access control: Role-Based Access Control diff --git a/vale/styles/Custom/Exclamation.yml b/vale/styles/Custom/Exclamation.yml deleted file mode 100644 index b4e4a1f7e9a..00000000000 --- a/vale/styles/Custom/Exclamation.yml +++ /dev/null @@ -1,12 +0,0 @@ -extends: existence -message: "Don't use exclamation points in text." -link: "https://developers.google.com/style/exclamation-points" -nonword: true -level: error -action: - name: edit - params: - - trim_right - - "!" -tokens: - - '\w+!(?:\s|$)' diff --git a/vale/styles/Custom/Filler.yml b/vale/styles/Custom/Filler.yml new file mode 100644 index 00000000000..6535e560b7a --- /dev/null +++ b/vale/styles/Custom/Filler.yml @@ -0,0 +1,12 @@ +extends: existence +message: "Don't use '%s'. The sentence is more concise and/or the tone is more neutral without it." +ignorecase: true +level: error +tokens: + - easily + - easy + - just + - please + - simple + - simply + - that's it diff --git a/vale/styles/Custom/Parens.yml b/vale/styles/Custom/Parens.yml index 3b8711d0c88..74a7d65bded 100644 --- a/vale/styles/Custom/Parens.yml +++ b/vale/styles/Custom/Parens.yml @@ -4,4 +4,5 @@ link: 'https://developers.google.com/style/parentheses' nonword: true level: suggestion tokens: - - '\(.+\)' + # Ignore acronym definitions + - '\([^A-Z]+\)' diff --git a/vale/styles/Custom/Will.yml b/vale/styles/Custom/Will.yml deleted file mode 100644 index 128a918362b..00000000000 --- a/vale/styles/Custom/Will.yml +++ /dev/null @@ -1,7 +0,0 @@ -extends: existence -message: "Avoid using '%s'." -link: 'https://developers.google.com/style/tense' -ignorecase: true -level: warning -tokens: - - will diff --git a/vale/styles/Custom/WordList.yml b/vale/styles/Custom/WordList.yml index bb53e8f7471..34d5459eb40 100644 --- a/vale/styles/Custom/WordList.yml +++ b/vale/styles/Custom/WordList.yml @@ -1,40 +1,42 @@ extends: substitution message: "Use '%s' instead of '%s'." -link: "https://developers.google.com/style/word-list" +link: 'https://developers.google.com/style/word-list' level: warning ignorecase: false action: name: replace swap: - "(?:API Console|dev|developer) key": API key - "(?:cell ?phone|smart ?phone)": phone|mobile phone - "(?:dev|developer|APIs) console": API console - "(?:e-mail|Email|E-mail)": email - "(?:file ?path|path ?name)": path - "(?:kill|terminate|abort)": stop|exit|cancel|end - "(?:OAuth ?2|Oauth)": OAuth 2.0 - "(?:ok|Okay)": OK|okay - "(?:WiFi|wifi)": Wi-Fi - "(?i)postgresql": Postgres - "(?i)repository": repo + '(?:API Console|dev|developer) key': API key + '(?:cell ?phone|smart ?phone)': phone|mobile phone + '(?:dev|developer|APIs) console': API console + '(?:e-mail|Email|E-mail)': email + '(?:file ?path|path ?name)': path + '(?:kill|terminate|abort)': stop|exit|cancel|end + '(?:Nginx|nginx)': NGINX + '(?:OAuth ?2|Oauth)': OAuth 2.0 + '(?:ok|Okay)': OK|okay + '(?:WiFi|wifi)': Wi-Fi + '(?i)postgresql': Postgres + '(?i)repository': repo '[\.]+apk': APK '3\-D': 3D 'Google (?:I\-O|IO)': Google I/O - "tap (?:&|and) hold": touch & hold - "un(?:check|select)": clear + 'Next(?:js)?': Next.js (if referring to the framework) + 'tap (?:&|and) hold': touch & hold + 'un(?:check|select)': clear + 'utili[sz](?:e[ds]|ing)': use, used, uses, etc. above: preceding account name: username action bar: app bar - admin: administrator Ajax: AJAX a\.k\.a|aka: or|also known as Android device: Android-powered device android: Android API explorer: APIs Explorer - application: app approx\.: approximately authN: authentication authZ: authorization + autogenerated: auto-generated autoupdate: automatically update cellular data: mobile data cellular network: mobile network @@ -54,10 +56,12 @@ swap: file name: filename firewalls: firewall rules functionality: capability|feature + Github: GitHub Google account: Google Account Google accounts: Google Accounts Googling: search with Google grayed-out: unavailable + head over to: go to|see HTTPs: HTTPS in order to: to ingest: import|load @@ -68,9 +72,14 @@ swap: open-source: open source overview screen: recents screen regex: regular expression + refer to: see + serverside: server-side SHA1: SHA-1|HAS-SHA1 sign into: sign in to + sign-ins?: signin(s) (noun) or sign in (verb) sign-?on: single sign-on + sign-outs?: signout(s) (noun) or sign out (verb) + sign-ups?: signup(s) (noun) or sign up (verb) static IP address: static external IP address stylesheet: style sheet synch: sync diff --git a/vale/styles/config/vocabularies/Supabase/accept.txt b/vale/styles/config/vocabularies/Supabase/accept.txt index f02c243b654..331d4806080 100644 --- a/vale/styles/config/vocabularies/Supabase/accept.txt +++ b/vale/styles/config/vocabularies/Supabase/accept.txt @@ -1,18 +1,82 @@ +APIs +[Aa]uth +Berri +[Cc]hatbots? ChatGPT Clippy Colab +[Cc]omposable CPUs? +[Dd]eclarative(ly)? [Dd]eduplicat(e|ion) +[Dd]eeplinks? +[Dd]egit +[Dd]eserializ(e|ed|es|ing) +Deno +[Dd]ev +[Dd]otenv +[Ee]nv +[Ee]nums? +Firestore +Hashicorp +[Gg]eospatial GPUs? +Gradle +GraphQL +Groonga +href +Infisical IVFFlat +JetBrains +Jetpack +JWTs +Lua +Markprompt +[Mm]iddleware +[Nn]amespace(d|s)? +Next.js +Nuxt +OAuth OpenAI +[Pp]ackageable +[Pp]asscodes? +[Pp]asswordless [Pp]erformant +PGAudit +PGroonga pgvector -Postgres +Pinecone +plpgsql +[Pp]olyfill(s|ed)? +[Pp]ooler +[Pp]ostgres +[Pp]rebuild +Prisma +[Rr]ealtime +Refine's +[Rr]eindex(ed|es|ing)? repo +RESTful +[Rr]evalidated? Roboflow [Ss]crollable +[Ss]erializ(e|ed|es|ing) +[Ss]igncryption +[Ss]ignins? +[Ss]ignouts? +[Ss]ignups? SQLAlchemy -Supabase -[Uu]psert - +[Ss]upabase +Supavisor +[Ss]upersets? +Terraform +[Tt]odos? +[Uu]npaus(e|es|ed|ing) +[Uu]psert(s|ed|ing)? +[Uu]pvot(es|ed|ing) +Vercel +Vite +VSCode +Vue +[Ww]eb[Ss]ockets? +Xcode From 136728f6abe5aae7d24d6d1c4022d027b19d640f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Tue, 5 Mar 2024 12:49:58 +0800 Subject: [PATCH 49/62] perf: reorganize a few imports to improve bundle size (#21743) --- .../AIPolicyEditorPanel/RLSCodeEditor.tsx | 2 +- .../Policies/AIPolicyEditorPanel/index.tsx | 1 - .../SQLEditor/SQLEditor.constants.ts | 1526 +---------------- .../interfaces/SQLEditor/SQLEditor.queries.ts | 1517 ++++++++++++++++ .../interfaces/SQLEditor/SQLEditor.types.ts | 2 +- .../interfaces/SQLEditor/SQLEditor.utils.ts | 20 +- .../SQLEditor/SQLTemplates/SQLQuickstarts.tsx | 2 +- .../SQLEditor/SQLTemplates/SQLTemplates.tsx | 2 +- .../data/database/database-query-constants.ts | 570 +----- .../database/database-table-definition.ts | 569 ++++++ apps/studio/lib/helpers.ts | 53 +- apps/studio/lib/password-strength.ts | 46 + apps/studio/lib/uuid.ts | 7 + apps/studio/lib/vercelConfigs.ts | 2 +- packages/common/Providers.tsx | 2 +- 15 files changed, 2161 insertions(+), 2160 deletions(-) create mode 100644 apps/studio/components/interfaces/SQLEditor/SQLEditor.queries.ts create mode 100644 apps/studio/data/database/database-table-definition.ts create mode 100644 apps/studio/lib/password-strength.ts create mode 100644 apps/studio/lib/uuid.ts diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx index 6ce0ff4cc0a..39691c5082d 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/RLSCodeEditor.tsx @@ -1,5 +1,5 @@ import Editor, { OnChange, OnMount } from '@monaco-editor/react' -import { editor } from 'monaco-editor' +import type { editor } from 'monaco-editor' import { MutableRefObject, useRef } from 'react' import { cn } from 'ui' diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx index fcb02298024..0465ac80834 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/index.tsx @@ -52,7 +52,6 @@ import RLSCodeEditor from './RLSCodeEditor' import { PolicyTemplates } from './PolicyTemplates' import { subscriptionHasHipaaAddon } from 'components/interfaces/Billing/Subscription/Subscription.utils' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import CardButton from 'components/ui/CardButton' const DiffEditor = dynamic( () => import('@monaco-editor/react').then(({ DiffEditor }) => DiffEditor), diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts b/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts index 95ef97c400e..df5798c3ceb 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.constants.ts @@ -1,1522 +1,4 @@ -import { stripIndent } from 'common-tags' import type { SqlSnippets, UserContent } from 'types' -import type { SQLTemplate } from './SQLEditor.types' - -export const SQL_TEMPLATES: SQLTemplate[] = [ - { - id: 1, - type: 'template', - title: 'Create table', - description: 'Basic table template. Change "table_name" to the name you prefer.', - sql: `create table table_name ( - id bigint generated by default as identity primary key, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, - updated_at timestamp with time zone default timezone('utc'::text, now()) not null, - data jsonb, - name text -);`, - }, - { - id: 2, - type: 'template', - title: 'Add view', - description: - 'Template to add a view. Make sure to change the table and column names to ones that already exist.', - sql: `CREATE VIEW countries_view AS -SELECT id, continent -FROM countries;`, - }, - { - id: 3, - type: 'template', - title: 'Add column', - description: 'Template to add a column. Make sure to change the name and type.', - sql: `alter table table_name -add column new_column_name data_type;`, - }, - { - id: 4, - type: 'template', - title: 'Add comments', - description: 'Templates to add a comment to either a table or a column.', - sql: `comment on table table_name is 'Table description'; -comment on column table_name.column_name is 'Column description';`, - }, - { - id: 5, - type: 'template', - title: 'Show extensions', - description: 'Get a list of extensions in your database and status.', - sql: `select - name, comment, default_version, installed_version -from - pg_available_extensions -order by - name asc;`, - }, - { - id: 6, - type: 'template', - title: 'Show version', - description: 'Get your Postgres version.', - sql: `select * from - (select version()) as version, - (select current_setting('server_version_num')) as version_number;`, - }, - { - id: 7, - type: 'template', - title: 'Show active connections', - description: 'Get the number of active and max connections.', - sql: `select * from -(select count(pid) as active_connections FROM pg_stat_activity where state = 'active') active_connections, -(select setting as max_connections from pg_settings where name = 'max_connections') max_connections;`, - }, - { - id: 8, - type: 'template', - title: 'Automatically update timestamps', - description: 'Update a column timestamp on every update.', - sql: ` -create extension if not exists moddatetime schema extensions; - --- assuming the table name is "todos", and a timestamp column "updated_at" --- this trigger will set the "updated_at" column to the current timestamp for every update -create trigger - handle_updated_at before update -on todos -for each row execute - procedure moddatetime(updated_at); - `.trim(), - }, - { - id: 9, - type: 'template', - title: 'Increment field value', - description: 'Update a field with incrementing value using stored procedure.', - sql: ` -create function increment(row_id int) -returns void as -$$ - update table_name - set field_name = field_name + 1 - where id = row_id; -$$ -language sql volatile; - --- you can call the function from your browser with supabase-js --- const { data, error } = await supabase.rpc('increment', { row_id: 2 }) - `.trim(), - }, - { - id: 10, - type: 'template', - title: 'pg_stat_statements report', - description: 'Select from pg_stat_statements and view recent queries', - sql: `-- pg_stat_statements report - --- A limit of 100 has been added below - -select - auth.rolname, - statements.query, - statements.calls, - -- -- Postgres 13, 14 - statements.total_exec_time + statements.total_plan_time as total_time, - statements.min_exec_time + statements.min_plan_time as min_time, - statements.max_exec_time + statements.max_plan_time as max_time, - statements.mean_exec_time + statements.mean_plan_time as mean_time, - -- -- Postgres <= 12 - -- total_time, - -- min_time, - -- max_time, - -- mean_time, - statements.rows / statements.calls as avg_rows, - statements.wal_bytes, - statements.wal_records - from pg_stat_statements as statements - inner join pg_authid as auth on statements.userid = auth.oid - order by - total_time desc - limit - 100;`, - }, - { - id: 11, - type: 'quickstart', - title: 'Countries', - description: 'Create a table with all the countries in the world.', - sql: `create type public.continents as enum ( - 'Africa', - 'Antarctica', - 'Asia', - 'Europe', - 'Oceania', - 'North America', - 'South America' -); -create table public.countries ( - id bigint generated by default as identity primary key, - name text, - iso2 text not null, - iso3 text, - local_name text, - continent continents -); -comment on table countries is 'Full list of countries.'; -comment on column countries.name is 'Full country name.'; -comment on column countries.iso2 is 'ISO 3166-1 alpha-2 code.'; -comment on column countries.iso3 is 'ISO 3166-1 alpha-3 code.'; -comment on column countries.local_name is 'Local variation of the name.'; -insert into public.countries (name,iso2,iso3,local_name,continent) values - ('Bonaire, Sint Eustatius and Saba','BQ','BES',null,null), - ('Curaçao','CW','CUW',null,null), - ('Guernsey','GG','GGY',null,null), - ('Isle of Man','IM','IMN',null,null), - ('Jersey','JE','JEY',null,null), - ('Åland Islands','AX','ALA',null,null), - ('Montenegro','ME','MNE',null,null), - ('Saint Barthélemy','BL','BLM',null,null), - ('Saint Martin (French part)','MF','MAF',null,null), - ('Serbia','RS','SRB',null,null), - ('Sint Maarten (Dutch part)','SX','SXM',null,null), - ('South Sudan','SS','SSD',null,null), - ('Timor-Leste','TL','TLS',null,null), - ('American Samoa','as','ASM','Amerika Samoa','Oceania'), - ('Andorra','AD','AND','Andorra','Europe'), - ('Angola','AO','AGO','Angola','Africa'), - ('Anguilla','AI','AIA','Anguilla','North America'), - ('Antarctica','AQ','ATA','','Antarctica'), - ('Antigua and Barbuda','AG','ATG','Antigua and Barbuda','North America'), - ('Argentina','AR','ARG','Argentina','South America'), - ('Armenia','AM','ARM','Hajastan','Asia'), - ('Aruba','AW','ABW','Aruba','North America'), - ('Australia','AU','AUS','Australia','Oceania'), - ('Austria','AT','AUT','Österreich','Europe'), - ('Azerbaijan','AZ','AZE','Azerbaijan','Asia'), - ('Bahamas','BS','BHS','The Bahamas','North America'), - ('Bahrain','BH','BHR','Al-Bahrayn','Asia'), - ('Bangladesh','BD','BGD','Bangladesh','Asia'), - ('Barbados','BB','BRB','Barbados','North America'), - ('Belarus','BY','BLR','Belarus','Europe'), - ('Belgium','BE','BEL','Belgium/Belgique','Europe'), - ('Belize','BZ','BLZ','Belize','North America'), - ('Benin','BJ','BEN','Benin','Africa'), - ('Bermuda','BM','BMU','Bermuda','North America'), - ('Bhutan','BT','BTN','Druk-Yul','Asia'), - ('Bolivia','BO','BOL','Bolivia','South America'), - ('Bosnia and Herzegovina','BA','BIH','Bosna i Hercegovina','Europe'), - ('Botswana','BW','BWA','Botswana','Africa'), - ('Bouvet Island','BV','BVT','Bouvet Island','Antarctica'), - ('Brazil','BR','BRA','Brasil','South America'), - ('British Indian Ocean Territory','IO','IOT','British Indian Ocean Territory','Africa'), - ('Brunei Darussalam','BN','BRN','Brunei Darussalam','Asia'), - ('Bulgaria','BG','BGR','Balgarija','Europe'), - ('Burkina Faso','BF','BFA','Burkina Faso','Africa'), - ('Burundi','BI','BDI','Burundi/Uburundi','Africa'), - ('Cambodia','KH','KHM','Cambodia','Asia'), - ('Cameroon','CM','CMR','Cameroun/Cameroon','Africa'), - ('Canada','CA','CAN','Canada','North America'), - ('Cape Verde','CV','CPV','Cabo Verde','Africa'), - ('Cayman Islands','KY','CYM','Cayman Islands','North America'), - ('Central African Republic','CF','CAF','Centrafrique','Africa'), - ('Chad','TD','TCD','Tchad/Tshad','Africa'), - ('Chile','CL','CHL','Chile','South America'), - ('China','CN','CHN','Zhongquo','Asia'), - ('Christmas Island','CX','CXR','Christmas Island','Oceania'), - ('Cocos (Keeling) Islands','CC','CCK','Cocos (Keeling) Islands','Oceania'), - ('Colombia','CO','COL','Colombia','South America'), - ('Comoros','KM','COM','Komori/Comores','Africa'), - ('Congo','CG','COG','Congo','Africa'), - ('Congo, the Democratic Republic of the','CD','COD','Republique Democratique du Congo','Africa'), - ('Cook Islands','CK','COK','The Cook Islands','Oceania'), - ('Costa Rica','CR','CRI','Costa Rica','North America'), - ('Cote DIvoire','CI','CIV','Côte dIvoire','Africa'), - ('Croatia','HR','HRV','Hrvatska','Europe'), - ('Cuba','CU','CUB','Cuba','North America'), - ('Cyprus','CY','CYP','Cyprus','Asia'), - ('Czech Republic','CZ','CZE','Czech','Europe'), - ('Denmark','DK','DNK','Danmark','Europe'), - ('Djibouti','DJ','DJI','Djibouti/Jibuti','Africa'), - ('Dominica','DM','DMA','Dominica','North America'), - ('Dominican Republic','DO','DOM','Republica Dominicana','North America'), - ('Ecuador','EC','ECU','Ecuador','South America'), - ('Egypt','EG','EGY','Misr','Africa'), - ('El Salvador','SV','SLV','El Salvador','North America'), - ('Equatorial Guinea','GQ','GNQ','Guinea Ecuatorial','Africa'), - ('Eritrea','ER','ERI','Ertra','Africa'), - ('Estonia','EE','EST','Eesti','Europe'), - ('Ethiopia','ET','ETH','Yeityopiya','Africa'), - ('Falkland Islands (Malvinas)','FK','FLK','Falkland Islands','South America'), - ('Faroe Islands','FO','FRO','Faroe Islands','Europe'), - ('Fiji','FJ','FJI','Fiji Islands','Oceania'), - ('Finland','FI','FIN','Suomi','Europe'), - ('France','FR','FRA','France','Europe'), - ('French Guiana','GF','GUF','Guyane francaise','South America'), - ('French Polynesia','PF','PYF','Polynésie française','Oceania'), - ('French Southern Territories','TF','ATF','Terres australes françaises','Antarctica'), - ('Gabon','GA','GAB','Le Gabon','Africa'), - ('Gambia','GM','GMB','The Gambia','Africa'), - ('Georgia','GE','GEO','Sakartvelo','Asia'), - ('Germany','DE','DEU','Deutschland','Europe'), - ('Ghana','GH','GHA','Ghana','Africa'), - ('Gibraltar','GI','GIB','Gibraltar','Europe'), - ('Greece','GR','GRC','Greece','Europe'), - ('Greenland','GL','GRL','Kalaallit Nunaat','North America'), - ('Grenada','GD','GRD','Grenada','North America'), - ('Guadeloupe','GP','GLP','Guadeloupe','North America'), - ('Guam','GU','GUM','Guam','Oceania'), - ('Guatemala','GT','GTM','Guatemala','North America'), - ('Guinea','GN','GIN','Guinea','Africa'), - ('Guinea-Bissau','GW','GNB','Guinea-Bissau','Africa'), - ('Guyana','GY','GUY','Guyana','South America'), - ('Haiti','HT','HTI','Haiti/Dayti','North America'), - ('Heard Island and Mcdonald Islands','HM','HMD','Heard and McDonald Islands','Antarctica'), - ('Holy See (Vatican City State)','VA','VAT','Santa Sede/Città del Vaticano','Europe'), - ('Honduras','HN','HND','Honduras','North America'), - ('Hong Kong','HK','HKG','Xianggang/Hong Kong','Asia'), - ('Hungary','HU','HUN','Hungary','Europe'), - ('Iceland','IS','ISL','Iceland','Europe'), - ('India','IN','IND','Bharat/India','Asia'), - ('Indonesia','ID','IDN','Indonesia','Asia'), - ('Iran, Islamic Republic of','IR','IRN','Iran','Asia'), - ('Iraq','IQ','IRQ','Al-Irāq','Asia'), - ('Ireland','IE','IRL','Ireland','Europe'), - ('Israel','IL','ISR','Yisrael','Asia'), - ('Italy','IT','ITA','Italia','Europe'), - ('Jamaica','JM','JAM','Jamaica','North America'), - ('Japan','JP','JPN','Nihon/Nippon','Asia'), - ('Jordan','JO','JOR','Al-Urdunn','Asia'), - ('Kazakhstan','KZ','KAZ','Qazaqstan','Asia'), - ('Kenya','KE','KEN','Kenya','Africa'), - ('Kiribati','KI','KIR','Kiribati','Oceania'), - ('Korea, Democratic People''s Republic of','KP','PRK','Choson Minjujuui Inmin Konghwaguk (Bukhan)','Asia'), - ('Korea, Republic of','KR','KOR','Taehan-minguk (Namhan)','Asia'), - ('Kuwait','KW','KWT','Al-Kuwayt','Asia'), - ('Kyrgyzstan','KG','KGZ','Kyrgyzstan','Asia'), - ('Lao People''s Democratic Republic','LA','LAO','Lao','Asia'), - ('Latvia','LV','LVA','Latvija','Europe'), - ('Lebanon','LB','LBN','Lubnan','Asia'), - ('Lesotho','LS','LSO','Lesotho','Africa'), - ('Liberia','LR','LBR','Liberia','Africa'), - ('Libya','LY','LBY','Libiya','Africa'), - ('Liechtenstein','LI','LIE','Liechtenstein','Europe'), - ('Lithuania','LT','LTU','Lietuva','Europe'), - ('Luxembourg','LU','LUX','Luxembourg','Europe'), - ('Macao','MO','MAC','Macau/Aomen','Asia'), - ('Macedonia, the Former Yugoslav Republic of','MK','MKD','Makedonija','Europe'), - ('Madagascar','MG','MDG','Madagasikara/Madagascar','Africa'), - ('Malawi','MW','MWI','Malawi','Africa'), - ('Malaysia','MY','MYS','Malaysia','Asia'), - ('Maldives','MV','MDV','Dhivehi Raajje/Maldives','Asia'), - ('Mali','ML','MLI','Mali','Africa'), - ('Malta','MT','MLT','Malta','Europe'), - ('Marshall Islands','MH','MHL','Marshall Islands/Majol','Oceania'), - ('Martinique','MQ','MTQ','Martinique','North America'), - ('Mauritania','MR','MRT','Muritaniya/Mauritanie','Africa'), - ('Mauritius','MU','MUS','Mauritius','Africa'), - ('Mayotte','YT','MYT','Mayotte','Africa'), - ('Mexico','MX','MEX','Mexico','North America'), - ('Micronesia, Federated States of','FM','FSM','Micronesia','Oceania'), - ('Moldova, Republic of','MD','MDA','Moldova','Europe'), - ('Monaco','MC','MCO','Monaco','Europe'), - ('Mongolia','MN','MNG','Mongol Uls','Asia'), - ('Albania','AL','ALB','Republika e Shqipërisë','Europe'), - ('Montserrat','MS','MSR','Montserrat','North America'), - ('Morocco','MA','MAR','Al-Maghrib','Africa'), - ('Mozambique','MZ','MOZ','Mozambique','Africa'), - ('Myanmar','MM','MMR','Myanma Pye','Asia'), - ('Namibia','NA','NAM','Namibia','Africa'), - ('Nauru','NR','NRU','Naoero/Nauru','Oceania'), - ('Nepal','NP','NPL','Nepal','Asia'), - ('Netherlands','NL','NLD','Nederland','Europe'), - ('New Caledonia','NC','NCL','Nouvelle-Calédonie','Oceania'), - ('New Zealand','NZ','NZL','New Zealand/Aotearoa','Oceania'), - ('Nicaragua','NI','NIC','Nicaragua','North America'), - ('Niger','NE','NER','Niger','Africa'), - ('Nigeria','NG','NGA','Nigeria','Africa'), - ('Niue','NU','NIU','Niue','Oceania'), - ('Norfolk Island','NF','NFK','Norfolk Island','Oceania'), - ('Northern Mariana Islands','MP','MNP','Northern Mariana Islands','Oceania'), - ('Norway','NO','NOR','Norge','Europe'), - ('Oman','OM','OMN','Oman','Asia'), - ('Pakistan','PK','PAK','Pakistan','Asia'), - ('Palau','PW','PLW','Belau/Palau','Oceania'), - ('Palestine, State of','PS','PSE','Filastin','Asia'), - ('Panama','PA','PAN','República de Panamá','North America'), - ('Papua New Guinea','PG','PNG','Papua New Guinea/Papua Niugini','Oceania'), - ('Paraguay','PY','PRY','Paraguay','South America'), - ('Peru','PE','PER','Perú/Piruw','South America'), - ('Philippines','PH','PHL','Pilipinas','Asia'), - ('Pitcairn','PN','PCN','Pitcairn','Oceania'), - ('Poland','PL','POL','Polska','Europe'), - ('Portugal','PT','PRT','Portugal','Europe'), - ('Puerto Rico','PR','PRI','Puerto Rico','North America'), - ('Qatar','QA','QAT','Qatar','Asia'), - ('Reunion','RE','REU','Reunion','Africa'), - ('Romania','RO','ROM','Romania','Europe'), - ('Russian Federation','RU','RUS','Rossija','Europe'), - ('Rwanda','RW','RWA','Rwanda/Urwanda','Africa'), - ('Saint Helena, Ascension and Tristan da Cunha','SH','SHN','Saint Helena','Africa'), - ('Saint Kitts and Nevis','KN','KNA','Saint Kitts and Nevis','North America'), - ('Saint Lucia','LC','LCA','Saint Lucia','North America'), - ('Saint Pierre and Miquelon','PM','SPM','Saint-Pierre-et-Miquelon','North America'), - ('Saint Vincent and the Grenadines','VC','VCT','Saint Vincent and the Grenadines','North America'), - ('Samoa','WS','WSM','Samoa','Oceania'), - ('San Marino','SM','SMR','San Marino','Europe'), - ('Sao Tome and Principe','ST','STP','São Tomé e Príncipe','Africa'), - ('Saudi Arabia','SA','SAU','Al-Mamlaka al-Arabiya as-Saudiya','Asia'), - ('Senegal','SN','SEN','Sénégal/Sounougal','Africa'), - ('Seychelles','SC','SYC','Sesel/Seychelles','Africa'), - ('Sierra Leone','SL','SLE','Sierra Leone','Africa'), - ('Singapore','SG','SGP','Singapore/Singapura/Xinjiapo/Singapur','Asia'), - ('Slovakia','SK','SVK','Slovensko','Europe'), - ('Slovenia','SI','SVN','Slovenija','Europe'), - ('Solomon Islands','SB','SLB','Solomon Islands','Oceania'), - ('Somalia','SO','SOM','Soomaaliya','Africa'), - ('South Africa','ZA','ZAF','South Africa','Africa'), - ('South Georgia and the South Sandwich Islands','GS','SGS','South Georgia and the South Sandwich Islands','Antarctica'), - ('Spain','ES','ESP','España','Europe'), - ('Sri Lanka','LK','LKA','Sri Lanka/Ilankai','Asia'), - ('Sudan','SD','SDN','As-Sudan','Africa'), - ('Suriname','SR','SUR','Suriname','South America'), - ('Svalbard and Jan Mayen','SJ','SJM','Svalbard og Jan Mayen','Europe'), - ('Swaziland','SZ','SWZ','kaNgwane','Africa'), - ('Sweden','SE','SWE','Sverige','Europe'), - ('Switzerland','CH','CHE','Schweiz/Suisse/Svizzera/Svizra','Europe'), - ('Syrian Arab Republic','SY','SYR','Suriya','Asia'), - ('Taiwan (Province of China)','TW','TWN','Tai-wan','Asia'), - ('Tajikistan','TJ','TJK','Tajikistan','Asia'), - ('Tanzania, United Republic of','TZ','TZA','Tanzania','Africa'), - ('Thailand','TH','THA','Prathet Thai','Asia'), - ('Togo','TG','TGO','Togo','Africa'), - ('Tokelau','TK','TKL','Tokelau','Oceania'), - ('Tonga','TO','TON','Tonga','Oceania'), - ('Trinidad and Tobago','TT','TTO','Trinidad and Tobago','North America'), - ('Tunisia','TN','TUN','Tunis/Tunisie','Africa'), - ('Turkey','TR','TUR','Türkiye','Asia'), - ('Turkmenistan','TM','TKM','Türkmenistan','Asia'), - ('Turks and Caicos Islands','TC','TCA','The Turks and Caicos Islands','North America'), - ('Tuvalu','TV','TUV','Tuvalu','Oceania'), - ('Uganda','UG','UGA','Uganda','Africa'), - ('Ukraine','UA','UKR','Ukrajina','Europe'), - ('United Arab Emirates','AE','ARE','Al-Amirat al-Arabiya al-Muttahida','Asia'), - ('United Kingdom','GB','GBR','United Kingdom','Europe'), - ('United States','US','USA','United States','North America'), - ('United States Minor Outlying Islands','UM','UMI','United States Minor Outlying Islands','Oceania'), - ('Uruguay','UY','URY','Uruguay','South America'), - ('Uzbekistan','UZ','UZB','Uzbekiston','Asia'), - ('Vanuatu','VU','VUT','Vanuatu','Oceania'), - ('Venezuela','VE','VEN','Venezuela','South America'), - ('Viet Nam','VN','VNM','Viet Nam','Asia'), - ('Virgin Islands (British)','VG','VGB','British Virgin Islands','North America'), - ('Virgin Islands (U.S.)','VI','VIR','Virgin Islands of the United States','North America'), - ('Wallis and Futuna','WF','WLF','Wallis-et-Futuna','Oceania'), - ('Western Sahara','EH','ESH','As-Sahrawiya','Africa'), - ('Yemen','YE','YEM','Al-Yaman','Asia'), - ('Zambia','ZM','ZMB','Zambia','Africa'), - ('Zimbabwe','ZW','ZWE','Zimbabwe','Africa'), - ('Afghanistan','AF','AFG','Afganistan/Afqanestan','Asia'), - ('Algeria','DZ','DZA','Al-Jazair/Algerie','Africa'); -`.trim(), - }, - { - id: 12, - type: 'quickstart', - title: 'Slack Clone', - description: 'Build a basic slack clone with Row Level Security.', - sql: ` --- --- For use with https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone - --- Custom types -create type public.app_permission as enum ('channels.delete', 'messages.delete'); -create type public.app_role as enum ('admin', 'moderator'); -create type public.user_status as enum ('ONLINE', 'OFFLINE'); - --- USERS -create table public.users ( - id uuid not null primary key, -- UUID from auth.users - username text, - status user_status default 'OFFLINE'::public.user_status -); -comment on table public.users is 'Profile data for each user.'; -comment on column public.users.id is 'References the internal Supabase Auth user.'; - --- CHANNELS -create table public.channels ( - id bigint generated by default as identity primary key, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, - slug text not null unique, - created_by uuid references public.users not null -); -comment on table public.channels is 'Topics and groups.'; - --- MESSAGES -create table public.messages ( - id bigint generated by default as identity primary key, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, - message text, - user_id uuid references public.users not null, - channel_id bigint references public.channels on delete cascade not null -); -comment on table public.messages is 'Individual messages sent by each user.'; - --- USER ROLES -create table public.user_roles ( - id bigint generated by default as identity primary key, - user_id uuid references public.users on delete cascade not null, - role app_role not null, - unique (user_id, role) -); -comment on table public.user_roles is 'Application roles for each user.'; - --- ROLE PERMISSIONS -create table public.role_permissions ( - id bigint generated by default as identity primary key, - role app_role not null, - permission app_permission not null, - unique (role, permission) -); -comment on table public.role_permissions is 'Application permissions for each role.'; - --- authorize with role-based access control (RBAC) -create function public.authorize( - requested_permission app_permission, - user_id uuid -) -returns boolean as -$$ - declare - bind_permissions int; - begin - select - count(*) - from public.role_permissions - inner join public.user_roles on role_permissions.role = user_roles.role - where - role_permissions.permission = authorize.requested_permission and - user_roles.user_id = authorize.user_id - into bind_permissions; - - return bind_permissions > 0; - end; -$$ -language plpgsql security definer; - --- Secure the tables -alter table public.users - enable row level security; -alter table public.channels - enable row level security; -alter table public.messages - enable row level security; -alter table public.user_roles - enable row level security; -alter table public.role_permissions - enable row level security; - -create policy "Allow logged-in read access" on public.users - for select using (auth.role() = 'authenticated'); -create policy "Allow individual insert access" on public.users - for insert with check (auth.uid() = id); -create policy "Allow individual update access" on public.users - for update using ( auth.uid() = id ); -create policy "Allow logged-in read access" on public.channels - for select using (auth.role() = 'authenticated'); -create policy "Allow individual insert access" on public.channels - for insert with check (auth.uid() = created_by); -create policy "Allow individual delete access" on public.channels - for delete using (auth.uid() = created_by); -create policy "Allow authorized delete access" on public.channels - for delete using (authorize('channels.delete', auth.uid())); -create policy "Allow logged-in read access" on public.messages - for select using (auth.role() = 'authenticated'); -create policy "Allow individual insert access" on public.messages - for insert with check (auth.uid() = user_id); -create policy "Allow individual update access" on public.messages - for update using (auth.uid() = user_id); -create policy "Allow individual delete access" on public.messages - for delete using (auth.uid() = user_id); -create policy "Allow authorized delete access" on public.messages - for delete using (authorize('messages.delete', auth.uid())); -create policy "Allow individual read access" on public.user_roles - for select using (auth.uid() = user_id); - --- Send "previous data" on change -alter table public.users - replica identity full; -alter table public.channels - replica identity full; -alter table public.messages - replica identity full; - --- inserts a row into public.users and assigns roles -create function public.handle_new_user() -returns trigger as -$$ - declare is_admin boolean; - begin - insert into public.users (id, username) - values (new.id, new.email); - - select count(*) = 1 from auth.users into is_admin; - - if position('+supaadmin@' in new.email) > 0 then - insert into public.user_roles (user_id, role) values (new.id, 'admin'); - elsif position('+supamod@' in new.email) > 0 then - insert into public.user_roles (user_id, role) values (new.id, 'moderator'); - end if; - - return new; - end; -$$ language plpgsql security definer; - --- trigger the function every time a user is created -create trigger on_auth_user_created - after insert on auth.users - for each row execute procedure public.handle_new_user(); - -/** - * REALTIME SUBSCRIPTIONS - * Only allow realtime listening on public tables. - */ - -begin; - -- remove the realtime publication - drop publication if exists supabase_realtime; - - -- re-create the publication but don't enable it for any tables - create publication supabase_realtime; -commit; - --- add tables to the publication -alter publication supabase_realtime add table public.channels; -alter publication supabase_realtime add table public.messages; -alter publication supabase_realtime add table public.users; - --- DUMMY DATA -insert into public.users (id, username) -values - ('8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e', 'supabot'); - -insert into public.channels (slug, created_by) -values - ('public', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), - ('random', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); - -insert into public.messages (message, channel_id, user_id) -values - ('Hello World 👋', 1, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), - ('Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.', 2, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); - -insert into public.role_permissions (role, permission) -values - ('admin', 'channels.delete'), - ('admin', 'messages.delete'), - ('moderator', 'messages.delete'); -`.trim(), - }, - { - id: 13, - type: 'quickstart', - title: 'Todo List', - description: 'Build a basic todo list with Row Level Security.', - sql: ` --- --- For use with: --- https://github.com/supabase/supabase/tree/master/examples/todo-list/sveltejs-todo-list or --- https://github.com/supabase/examples-archive/tree/main/supabase-js-v1/todo-list --- - -create table todos ( - id bigint generated by default as identity primary key, - user_id uuid references auth.users not null, - task text check (char_length(task) > 3), - is_complete boolean default false, - inserted_at timestamp with time zone default timezone('utc'::text, now()) not null -); -alter table todos enable row level security; -create policy "Individuals can create todos." on todos for - insert with check (auth.uid() = user_id); -create policy "Individuals can view their own todos. " on todos for - select using (auth.uid() = user_id); -create policy "Individuals can update their own todos." on todos for - update using (auth.uid() = user_id); -create policy "Individuals can delete their own todos." on todos for - delete using (auth.uid() = user_id); -`.trim(), - }, - { - id: 14, - type: 'quickstart', - title: 'Stripe Subscriptions', - description: 'Starter template for the Next.js Stripe Subscriptions Starter.', - sql: ` -/** -* USERS -* Note: This table contains user data. Users should only be able to view and update their own data. -*/ -create table users ( - -- UUID from auth.users - id uuid references auth.users not null primary key, - full_name text, - avatar_url text, - -- The customer's billing address, stored in JSON format. - billing_address jsonb, - -- Stores your customer's payment instruments. - payment_method jsonb -); -alter table users - enable row level security; -create policy "Can view own user data." on users - for select using (auth.uid() = id); -create policy "Can update own user data." on users - for update using (auth.uid() = id); - -/** -* This trigger automatically creates a user entry when a new user signs up via Supabase Auth. -*/ -create function public.handle_new_user() -returns trigger as -$$ - begin - insert into public.users (id, full_name, avatar_url) - values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); - return new; - end; -$$ -language plpgsql security definer; - -create trigger on_auth_user_created - after insert on auth.users - for each row - execute procedure public.handle_new_user(); - -/** -* CUSTOMERS -* Note: this is a private table that contains a mapping of user IDs to Strip customer IDs. -*/ -create table customers ( - -- UUID from auth.users - id uuid references auth.users not null primary key, - -- The user's customer ID in Stripe. User must not be able to update this. - stripe_customer_id text -); -alter table customers enable row level security; --- No policies as this is a private table that the user must not have access to. - -/** -* PRODUCTS -* Note: products are created and managed in Stripe and synced to our DB via Stripe webhooks. -*/ -create table products ( - -- Product ID from Stripe, e.g. prod_1234. - id text primary key, - -- Whether the product is currently available for purchase. - active boolean, - -- The product's name, meant to be displayable to the customer. Whenever this product is sold via a subscription, name will show up on associated invoice line item descriptions. - name text, - -- The product's description, meant to be displayable to the customer. Use this field to optionally store a long form explanation of the product being sold for your own rendering purposes. - description text, - -- A URL of the product image in Stripe, meant to be displayable to the customer. - image text, - -- Set of key-value pairs, used to store additional information about the object in a structured format. - metadata jsonb -); -alter table products - enable row level security; -create policy "Allow public read-only access." on products - for select using (true); - -/** -* PRICES -* Note: prices are created and managed in Stripe and synced to our DB via Stripe webhooks. -*/ -create type pricing_type as enum ('one_time', 'recurring'); -create type pricing_plan_interval as enum ('day', 'week', 'month', 'year'); -create table prices ( - -- Price ID from Stripe, e.g. price_1234. - id text primary key, - -- The ID of the prduct that this price belongs to. - product_id text references products, - -- Whether the price can be used for new purchases. - active boolean, - -- A brief description of the price. - description text, - -- The unit amount as a positive integer in the smallest currency unit (e.g., 100 cents for US$1.00 or 100 for ¥100, a zero-decimal currency). - unit_amount bigint, - -- Three-letter ISO currency code, in lowercase. - currency text check (char_length(currency) = 3), - -- One of \`one_time\` or \`recurring\` depending on whether the price is for a one-time purchase or a recurring (subscription) purchase. - type pricing_type, - -- The frequency at which a subscription is billed. One of \`day\`, \`week\`, \`month\` or \`year\`. - interval pricing_plan_interval, - -- The number of intervals (specified in the \`interval\` attribute) between subscription billings. For example, \`interval=month\` and \`interval_count=3\` bills every 3 months. - interval_count integer, - -- Default number of trial days when subscribing a customer to this price using [\`trial_from_plan=true\`](https://stripe.com/docs/api#create_subscription-trial_from_plan). - trial_period_days integer, - -- Set of key-value pairs, used to store additional information about the object in a structured format. - metadata jsonb -); -alter table prices - enable row level security; -create policy "Allow public read-only access." on prices - for select using (true); - -/** -* SUBSCRIPTIONS -* Note: subscriptions are created and managed in Stripe and synced to our DB via Stripe webhooks. -*/ -create type subscription_status as enum ('trialing', 'active', 'canceled', 'incomplete', 'incomplete_expired', 'past_due', 'unpaid'); -create table subscriptions ( - -- Subscription ID from Stripe, e.g. sub_1234. - id text primary key, - user_id uuid references auth.users not null, - -- The status of the subscription object, one of subscription_status type above. - status subscription_status, - -- Set of key-value pairs, used to store additional information about the object in a structured format. - metadata jsonb, - -- ID of the price that created this subscription. - price_id text references prices, - -- Quantity multiplied by the unit amount of the price creates the amount of the subscription. Can be used to charge multiple seats. - quantity integer, - -- If true the subscription has been canceled by the user and will be deleted at the end of the billing period. - cancel_at_period_end boolean, - -- Time at which the subscription was created. - created timestamp with time zone default timezone('utc'::text, now()) not null, - -- Start of the current period that the subscription has been invoiced for. - current_period_start timestamp with time zone default timezone('utc'::text, now()) not null, - -- End of the current period that the subscription has been invoiced for. At the end of this period, a new invoice will be created. - current_period_end timestamp with time zone default timezone('utc'::text, now()) not null, - -- If the subscription has ended, the timestamp of the date the subscription ended. - ended_at timestamp with time zone default timezone('utc'::text, now()), - -- A date in the future at which the subscription will automatically get canceled. - cancel_at timestamp with time zone default timezone('utc'::text, now()), - -- If the subscription has been canceled, the date of that cancellation. If the subscription was canceled with \`cancel_at_period_end\`, \`canceled_at\` will still reflect the date of the initial cancellation request, not the end of the subscription period when the subscription is automatically moved to a canceled state. - canceled_at timestamp with time zone default timezone('utc'::text, now()), - -- If the subscription has a trial, the beginning of that trial. - trial_start timestamp with time zone default timezone('utc'::text, now()), - -- If the subscription has a trial, the end of that trial. - trial_end timestamp with time zone default timezone('utc'::text, now()) -); -alter table subscriptions - enable row level security; -create policy "Can only view own subs data." on subscriptions - for select using (auth.uid() = user_id); - -/** - * REALTIME SUBSCRIPTIONS - * Only allow realtime listening on public tables. - */ -drop publication if exists supabase_realtime; -create publication supabase_realtime - for table products, prices; -`.trim(), - }, - { - id: 15, - type: 'quickstart', - title: 'User Management Starter', - description: 'Sets up a public Profiles table which you can access with your API.', - sql: ` --- Create a table for public profiles -create table profiles ( - id uuid references auth.users on delete cascade not null primary key, - updated_at timestamp with time zone, - username text unique, - full_name text, - avatar_url text, - website text, - - constraint username_length check (char_length(username) >= 3) -); --- Set up Row Level Security (RLS) --- See https://supabase.com/docs/guides/auth/row-level-security for more details. -alter table profiles - enable row level security; - -create policy "Public profiles are viewable by everyone." on profiles - for select using (true); - -create policy "Users can insert their own profile." on profiles - for insert with check (auth.uid() = id); - -create policy "Users can update own profile." on profiles - for update using (auth.uid() = id); - --- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth. --- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details. -create function public.handle_new_user() -returns trigger as $$ -begin - insert into public.profiles (id, full_name, avatar_url) - values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); - return new; -end; -$$ language plpgsql security definer; -create trigger on_auth_user_created - after insert on auth.users - for each row execute procedure public.handle_new_user(); - --- Set up Storage! -insert into storage.buckets (id, name) - values ('avatars', 'avatars'); - --- Set up access controls for storage. --- See https://supabase.com/docs/guides/storage#policy-examples for more details. -create policy "Avatar images are publicly accessible." on storage.objects - for select using (bucket_id = 'avatars'); - -create policy "Anyone can upload an avatar." on storage.objects - for insert with check (bucket_id = 'avatars'); -`.trim(), - }, - { - id: 16, - type: 'quickstart', - title: 'NextAuth Schema Setup', - description: 'Sets up a the Schema and Tables for the NextAuth Supabase Adapter.', - sql: ` --- --- Name: next_auth; Type: SCHEMA; --- -CREATE SCHEMA next_auth; - -GRANT USAGE ON SCHEMA next_auth TO service_role; -GRANT ALL ON SCHEMA next_auth TO postgres; - --- --- Create users table --- -CREATE TABLE IF NOT EXISTS next_auth.users -( - id uuid NOT NULL DEFAULT gen_random_uuid(), - name text, - email text, - "emailVerified" timestamp with time zone, - image text, - CONSTRAINT users_pkey PRIMARY KEY (id), - CONSTRAINT email_unique UNIQUE (email) -); - -GRANT ALL ON TABLE next_auth.users TO postgres; -GRANT ALL ON TABLE next_auth.users TO service_role; - ---- uid() function to be used in RLS policies -CREATE FUNCTION next_auth.uid() RETURNS uuid - LANGUAGE sql STABLE - AS $$ - select - coalesce( - nullif(current_setting('request.jwt.claim.sub', true), ''), - (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub') - )::uuid -$$; - --- --- Create sessions table --- -CREATE TABLE IF NOT EXISTS next_auth.sessions -( - id uuid NOT NULL DEFAULT gen_random_uuid(), - expires timestamp with time zone NOT NULL, - "sessionToken" text NOT NULL, - "userId" uuid, - CONSTRAINT sessions_pkey PRIMARY KEY (id), - CONSTRAINT sessionToken_unique UNIQUE ("sessionToken"), - CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId") - REFERENCES next_auth.users (id) MATCH SIMPLE - ON UPDATE NO ACTION - ON DELETE CASCADE -); - -GRANT ALL ON TABLE next_auth.sessions TO postgres; -GRANT ALL ON TABLE next_auth.sessions TO service_role; - --- --- Create accounts table --- -CREATE TABLE IF NOT EXISTS next_auth.accounts -( - id uuid NOT NULL DEFAULT gen_random_uuid(), - type text NOT NULL, - provider text NOT NULL, - "providerAccountId" text NOT NULL, - refresh_token text, - access_token text, - expires_at bigint, - token_type text, - scope text, - id_token text, - session_state text, - oauth_token_secret text, - oauth_token text, - "userId" uuid, - CONSTRAINT accounts_pkey PRIMARY KEY (id), - CONSTRAINT provider_unique UNIQUE (provider, "providerAccountId"), - CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") - REFERENCES next_auth.users (id) MATCH SIMPLE - ON UPDATE NO ACTION - ON DELETE CASCADE -); - -GRANT ALL ON TABLE next_auth.accounts TO postgres; -GRANT ALL ON TABLE next_auth.accounts TO service_role; - --- --- Create verification_tokens table --- -CREATE TABLE IF NOT EXISTS next_auth.verification_tokens -( - identifier text, - token text, - expires timestamp with time zone NOT NULL, - CONSTRAINT verification_tokens_pkey PRIMARY KEY (token), - CONSTRAINT token_unique UNIQUE (token), - CONSTRAINT token_identifier_unique UNIQUE (token, identifier) -); - -GRANT ALL ON TABLE next_auth.verification_tokens TO postgres; -GRANT ALL ON TABLE next_auth.verification_tokens TO service_role; -`.trim(), - }, - { - id: 17, - type: 'template', - title: 'Most frequently invoked', - description: 'Most frequently called queries in your database.', - sql: `-- Most frequently called queries - --- A limit of 100 has been added below - -select - auth.rolname, - statements.query, - statements.calls, - -- -- Postgres 13, 14, 15 - statements.total_exec_time + statements.total_plan_time as total_time, - statements.min_exec_time + statements.min_plan_time as min_time, - statements.max_exec_time + statements.max_plan_time as max_time, - statements.mean_exec_time + statements.mean_plan_time as mean_time, - -- -- Postgres <= 12 - -- total_time, - -- min_time, - -- max_time, - -- mean_time, - statements.rows / statements.calls as avg_rows - - from pg_stat_statements as statements - inner join pg_authid as auth on statements.userid = auth.oid - order by - statements.calls desc - limit - 100;`, - }, - { - id: 18, - type: 'template', - title: 'Most time consuming', - description: 'Aggregate time spent on a query type.', - sql: `-- Most time consuming queries - --- A limit of 100 has been added below - -select - auth.rolname, - statements.query, - statements.calls, - statements.total_exec_time + statements.total_plan_time as total_time, - to_char(((statements.total_exec_time + statements.total_plan_time)/sum(statements.total_exec_time + statements.total_plan_time) over()) * 100, 'FM90D0') || '%' as prop_total_time - from pg_stat_statements as statements - inner join pg_authid as auth on statements.userid = auth.oid - order by - total_time desc - limit - 100;`, - }, - { - id: 19, - type: 'template', - title: 'Slowest execution time', - description: 'Slowest queries based on max execution time.', - sql: `-- Slowest queries by max execution time - --- A limit of 100 has been added below - -select - auth.rolname, - statements.query, - statements.calls, - -- -- Postgres 13, 14, 15 - statements.total_exec_time + statements.total_plan_time as total_time, - statements.min_exec_time + statements.min_plan_time as min_time, - statements.max_exec_time + statements.max_plan_time as max_time, - statements.mean_exec_time + statements.mean_plan_time as mean_time, - -- -- Postgres <= 12 - -- total_time, - -- min_time, - -- max_time, - -- mean_time, - statements.rows / statements.calls as avg_rows - from pg_stat_statements as statements - inner join pg_authid as auth on statements.userid = auth.oid - order by - max_time desc - limit - 100;`, - }, - { - id: 20, - type: 'template', - title: 'Hit rate', - description: 'See your cache and index hit rate.', - sql: `-- Cache and index hit rate - -select - 'index hit rate' as name, - (sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) as ratio - from pg_statio_user_indexes - union all - select - 'table hit rate' as name, - sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) as ratio - from pg_statio_user_tables;`, - }, - { - id: 21, - type: 'quickstart', - title: 'OpenAI Vector Search', - description: 'Template for the Next.js OpenAI Doc Search Starter.', - sql: ` --- Enable pg_vector extension -create extension if not exists vector with schema public; - --- Create tables -create table "public"."nods_page" ( - id bigserial primary key, - parent_page_id bigint references public.nods_page, - path text not null unique, - checksum text, - meta jsonb, - type text, - source text -); -alter table "public"."nods_page" enable row level security; - -create table "public"."nods_page_section" ( - id bigserial primary key, - page_id bigint not null references public.nods_page on delete cascade, - content text, - token_count int, - embedding vector(1536), - slug text, - heading text -); -alter table "public"."nods_page_section" enable row level security; - --- Create embedding similarity search functions -create or replace function match_page_sections(embedding vector(1536), match_threshold float, match_count int, min_content_length int) -returns table (id bigint, page_id bigint, slug text, heading text, content text, similarity float) -language plpgsql -as $$ -#variable_conflict use_variable -begin - return query - select - nods_page_section.id, - nods_page_section.page_id, - nods_page_section.slug, - nods_page_section.heading, - nods_page_section.content, - (nods_page_section.embedding <#> embedding) * -1 as similarity - from nods_page_section - - -- We only care about sections that have a useful amount of content - where length(nods_page_section.content) >= min_content_length - - -- The dot product is negative because of a Postgres limitation, so we negate it - and (nods_page_section.embedding <#> embedding) * -1 > match_threshold - - -- OpenAI embeddings are normalized to length 1, so - -- cosine similarity and dot product will produce the same results. - -- Using dot product which can be computed slightly faster. - -- - -- For the different syntaxes, see https://github.com/pgvector/pgvector - order by nods_page_section.embedding <#> embedding - - limit match_count; -end; -$$; - -create or replace function get_page_parents(page_id bigint) -returns table (id bigint, parent_page_id bigint, path text, meta jsonb) -language sql -as $$ - with recursive chain as ( - select * - from nods_page - where id = page_id - - union all - - select child.* - from nods_page as child - join chain on chain.parent_page_id = child.id - ) - select id, parent_page_id, path, meta - from chain; -$$; -`.trim(), - }, - { - id: 22, - type: 'template', - title: 'Replication status report', - description: 'See the status of your replication slots and replication lag.', - sql: `-- Replication status report - -SELECT - s.slot_name, - s.active, - COALESCE(r.state, 'N/A') as state, - COALESCE(r.client_addr, null) as replication_client_address, - GREATEST(0, ROUND((redo_lsn-restart_lsn)/1024/1024/1024, 2)) as replication_lag_gb -FROM pg_control_checkpoint(), pg_replication_slots s -LEFT JOIN pg_stat_replication r ON (r.pid = s.active_pid); -`, - }, - { - id: 23, - type: 'quickstart', - title: 'LangChain', - description: 'LangChain is a popular framework for working with AI, Vectors, and embeddings.', - sql: ` --- Enable the pgvector extension to work with embedding vectors -create extension vector; - --- Create a table to store your documents -create table documents ( - id bigserial primary key, - content text, -- corresponds to Document.pageContent - metadata jsonb, -- corresponds to Document.metadata - embedding vector(1536) -- 1536 works for OpenAI embeddings, change if needed -); - --- Create a function to search for documents -create function match_documents ( - query_embedding vector(1536), - match_count int default null, - filter jsonb DEFAULT '{}' -) returns table ( - id bigint, - content text, - metadata jsonb, - similarity float -) -language plpgsql -as $$ -#variable_conflict use_column -begin - return query - select - id, - content, - metadata, - 1 - (documents.embedding <=> query_embedding) as similarity - from documents - where metadata @> filter - order by documents.embedding <=> query_embedding - limit match_count; -end; -$$; -`.trim(), - }, - { - id: 24, - type: 'template', - title: 'Install dbdev', - description: 'dbdev is a client for installing 3rd party packages into your database.', - sql: ` -create extension if not exists http with schema extensions; -create extension if not exists pg_tle; -select pgtle.uninstall_extension_if_exists('supabase-dbdev'); -drop extension if exists "supabase-dbdev"; -select - pgtle.install_extension( - 'supabase-dbdev', - resp.contents ->> 'version', - 'PostgreSQL package manager', - resp.contents ->> 'sql' - ) -from http( - ( - 'GET', - 'https://api.database.dev/rest/v1/' - || 'package_versions?select=sql,version' - || '&package_name=eq.supabase-dbdev' - || '&order=version.desc' - || '&limit=1', - array[ - ('apiKey', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhtdXB0cHBsZnZpaWZyYndtbXR2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODAxMDczNzIsImV4cCI6MTk5NTY4MzM3Mn0.z2CN0mvO2No8wSi46Gw59DFGCTJrzM0AQKsu_5k134s')::http_header - ], - null, - null - ) -) x, -lateral ( - select - ((row_to_json(x) -> 'content') #>> '{}')::json -> 0 -) resp(contents); -create extension "supabase-dbdev"; -select dbdev.install('supabase-dbdev'); -drop extension if exists "supabase-dbdev"; -create extension "supabase-dbdev"; -`.trim(), - }, - { - id: 25, - type: 'template', - title: 'Large objects', - description: 'List large objects (tables/indexes) in your database.', - sql: `SELECT - SCHEMA_NAME, - relname, - table_size - FROM - (SELECT - pg_catalog.pg_namespace.nspname AS SCHEMA_NAME, - relname, - pg_relation_size(pg_catalog.pg_class.oid) AS table_size - FROM pg_catalog.pg_class - JOIN pg_catalog.pg_namespace ON relnamespace = pg_catalog.pg_namespace.oid - ) t - WHERE SCHEMA_NAME NOT LIKE 'pg_%' - ORDER BY table_size DESC - LIMIT 25`.trim(), - }, - { - id: 26, - type: 'template', - title: 'Limit MFA verification attempts to one in 2 seconds', - description: - 'Create an Auth hook that limits the number of failed MFA verification attempts to one in 2 seconds.', - sql: ` -create function public.hook_mfa_verification_attempt(event jsonb) - returns jsonb - language plpgsql -as $$ - declare - last_failed_at timestamp; - begin - if event->'valid' is true then - -- code is valid, accept it - return jsonb_build_object('decision', 'continue'); - end if; - - select last_failed_at into last_failed_at - from public.mfa_failed_verification_attempts - where - user_id = (event->'user_id')::uuid - and - factor_id = event->'factor_id'; - - if last_failed_at is not null and now() - last_failed_at < interval '2 seconds' then - -- last attempt was done too quickly - return jsonb_build_object( - 'error', jsonb_build_object( - 'http_code', 429, - 'message', 'Please wait a moment before trying again.' - ) - ); - end if; - - -- record this failed attempt - insert into public.mfa_failed_verification_attempts - ( - user_id, - factor_id, - last_refreshed_at - ) - values - ( - event->'user_id', - event->'factor_id', - now() - ) - on conflict do update - set last_refreshed_at = now(); - - -- finally let Supabase Auth do the default behavior for a failed attempt - return jsonb_build_object('decision', 'continue'); - end; -$$; - --- Assign appropriate permissions and revoke access -grant execute - on function public.hook_mfa_verification_attempt - to supabase_auth_admin; - -grant all - on table public.mfa_failed_verification_attempts - to supabase_auth_admin; - -revoke execute - on function public.hook_mfa_verification_attempt - from authenticated, anon; - -revoke all - on table public.mfa_failed_verification_attempts - from authenticated, anon; - -grant usage on schema public to supabase_auth_admin;`.trim(), - }, - { - id: 27, - type: 'template', - title: 'Add Auth Hook (Password Verification Attempt)', - description: - 'Create an Auth Hook that limits number of failed password verification attempts to one in 10 seconds', - sql: ` -create function public.hook_password_verification_attempt(event jsonb) -returns jsonb -language plpgsql -as $$ - declare - last_failed_at timestamp; - begin - if event->'valid' is true then - -- password is valid, accept it - return jsonb_build_object('decision', 'continue'); - end if; - - select last_failed_at into last_failed_at - from public.password_failed_verification_attempts - where - user_id = (event->'user_id')::uuid; - - if last_failed_at is not null and now() - last_failed_at < interval '10 seconds' then - -- last attempt was done too quickly - return jsonb_build_object( - 'error', jsonb_build_object( - 'http_code', 429, - 'message', 'Please wait a moment before trying again.' - ) - ); - end if; - - -- record this failed attempt - insert into public.password_failed_verification_attempts - ( - user_id, - last_failed_at - ) - values - ( - event->'user_id', - now() - ) - on conflict do update - set last_failed_at = now(); - - -- finally let Supabase Auth do the default behavior for a failed attempt - return jsonb_build_object('decision', 'continue'); - end; -$$; - --- Assign appropriate permissions -grant execute - on function public.hook_password_verification_attempt - to supabase_auth_admin; - -grant all - on table public.password_failed_verification_attempts - to supabase_auth_admin; - -revoke execute - on function public.hook_password_verification_attempt - from authenticated, anon; - -revoke all - on table public.password_failed_verification_attempts - from authenticated, anon; - -grant usage on schema public to supabase_auth_admin;`.trim(), - }, - { - id: 28, - type: 'template', - title: 'Add Auth Hook (Custom Access Token)', - description: 'Create an Auth Hook to add custom claims to your Auth Token', - sql: ` --- Assumes that there is an is_admin flag on the profiles table. -create or replace function public.custom_access_token_hook(event jsonb) -returns jsonb -language plpgsql -as $$ - declare - claims jsonb; - is_admin boolean; - begin - -- Check if the user is marked as admin in the profiles table - select is_admin into is_admin from profiles where user_id = (event->>'user_id')::uuid; - - -- Proceed only if the user is an admin - if is_admin then - claims := event->'claims'; - - -- Check if 'user_metadata' exists in claims - if jsonb_typeof(claims->'user_metadata') is null then - -- If 'user_metadata' does not exist, create an empty object - claims := jsonb_set(claims, '{user_metadata}', '{}'); - end if; - - -- Set a claim of 'admin' - claims := jsonb_set(claims, '{user_metadata, admin}', 'true'); - - -- Update the 'claims' object in the original event - event := jsonb_set(event, '{claims}', claims); - end if; - - -- Return the modified or original event - return event; - end; -$$; - -grant execute - on function public.custom_access_token_hook - to supabase_auth_admin; - -revoke execute - on function public.custom_access_token_hook - from authenticated, anon; - -grant usage on schema public to supabase_auth_admin;`.trim(), - }, - - { - id: 29, - type: 'template', - title: 'Add Auth Hook (General)', - description: 'Create an Auth Hook', - sql: ` -create or replace function public.custom_access_token_hook(event jsonb) -returns jsonb -language plpgsql -as $$ -declare - -- Insert variables here -begin - -- Insert logic here - return event; -end; -$$; --- Permissions for the hook -grant execute on function public.custom_access_token_hook to supabase_auth_admin; -revoke execute on function public.custom_access_token_hook from authenticated, anon; - `, - }, -] const SQL_SNIPPET_SCHEMA_VERSION = '1.0' @@ -1533,10 +15,10 @@ export const NEW_SQL_SNIPPET_SKELETON: UserContent = { }, } -export const sqlAiDisclaimerComment = stripIndent` - -- Supabase AI is experimental and may produce incorrect answers - -- Always verify the output before executing -` +export const sqlAiDisclaimerComment = ` +-- Supabase AI is experimental and may produce incorrect answers +-- Always verify the output before executing +`.trim() export const untitledSnippetTitle = 'Untitled query' diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.queries.ts b/apps/studio/components/interfaces/SQLEditor/SQLEditor.queries.ts new file mode 100644 index 00000000000..4aa2a91e71b --- /dev/null +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.queries.ts @@ -0,0 +1,1517 @@ +import type { SQLTemplate } from './SQLEditor.types' + +export const SQL_TEMPLATES: SQLTemplate[] = [ + { + id: 1, + type: 'template', + title: 'Create table', + description: 'Basic table template. Change "table_name" to the name you prefer.', + sql: `create table table_name ( + id bigint generated by default as identity primary key, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, + updated_at timestamp with time zone default timezone('utc'::text, now()) not null, + data jsonb, + name text +);`, + }, + { + id: 2, + type: 'template', + title: 'Add view', + description: + 'Template to add a view. Make sure to change the table and column names to ones that already exist.', + sql: `CREATE VIEW countries_view AS +SELECT id, continent +FROM countries;`, + }, + { + id: 3, + type: 'template', + title: 'Add column', + description: 'Template to add a column. Make sure to change the name and type.', + sql: `alter table table_name +add column new_column_name data_type;`, + }, + { + id: 4, + type: 'template', + title: 'Add comments', + description: 'Templates to add a comment to either a table or a column.', + sql: `comment on table table_name is 'Table description'; +comment on column table_name.column_name is 'Column description';`, + }, + { + id: 5, + type: 'template', + title: 'Show extensions', + description: 'Get a list of extensions in your database and status.', + sql: `select + name, comment, default_version, installed_version +from + pg_available_extensions +order by + name asc;`, + }, + { + id: 6, + type: 'template', + title: 'Show version', + description: 'Get your Postgres version.', + sql: `select * from + (select version()) as version, + (select current_setting('server_version_num')) as version_number;`, + }, + { + id: 7, + type: 'template', + title: 'Show active connections', + description: 'Get the number of active and max connections.', + sql: `select * from +(select count(pid) as active_connections FROM pg_stat_activity where state = 'active') active_connections, +(select setting as max_connections from pg_settings where name = 'max_connections') max_connections;`, + }, + { + id: 8, + type: 'template', + title: 'Automatically update timestamps', + description: 'Update a column timestamp on every update.', + sql: ` +create extension if not exists moddatetime schema extensions; + +-- assuming the table name is "todos", and a timestamp column "updated_at" +-- this trigger will set the "updated_at" column to the current timestamp for every update +create trigger + handle_updated_at before update +on todos +for each row execute + procedure moddatetime(updated_at); + `.trim(), + }, + { + id: 9, + type: 'template', + title: 'Increment field value', + description: 'Update a field with incrementing value using stored procedure.', + sql: ` +create function increment(row_id int) +returns void as +$$ + update table_name + set field_name = field_name + 1 + where id = row_id; +$$ +language sql volatile; + +-- you can call the function from your browser with supabase-js +-- const { data, error } = await supabase.rpc('increment', { row_id: 2 }) + `.trim(), + }, + { + id: 10, + type: 'template', + title: 'pg_stat_statements report', + description: 'Select from pg_stat_statements and view recent queries', + sql: `-- pg_stat_statements report + +-- A limit of 100 has been added below + +select + auth.rolname, + statements.query, + statements.calls, + -- -- Postgres 13, 14 + statements.total_exec_time + statements.total_plan_time as total_time, + statements.min_exec_time + statements.min_plan_time as min_time, + statements.max_exec_time + statements.max_plan_time as max_time, + statements.mean_exec_time + statements.mean_plan_time as mean_time, + -- -- Postgres <= 12 + -- total_time, + -- min_time, + -- max_time, + -- mean_time, + statements.rows / statements.calls as avg_rows, + statements.wal_bytes, + statements.wal_records + from pg_stat_statements as statements + inner join pg_authid as auth on statements.userid = auth.oid + order by + total_time desc + limit + 100;`, + }, + { + id: 11, + type: 'quickstart', + title: 'Countries', + description: 'Create a table with all the countries in the world.', + sql: `create type public.continents as enum ( + 'Africa', + 'Antarctica', + 'Asia', + 'Europe', + 'Oceania', + 'North America', + 'South America' +); +create table public.countries ( + id bigint generated by default as identity primary key, + name text, + iso2 text not null, + iso3 text, + local_name text, + continent continents +); +comment on table countries is 'Full list of countries.'; +comment on column countries.name is 'Full country name.'; +comment on column countries.iso2 is 'ISO 3166-1 alpha-2 code.'; +comment on column countries.iso3 is 'ISO 3166-1 alpha-3 code.'; +comment on column countries.local_name is 'Local variation of the name.'; +insert into public.countries (name,iso2,iso3,local_name,continent) values + ('Bonaire, Sint Eustatius and Saba','BQ','BES',null,null), + ('Curaçao','CW','CUW',null,null), + ('Guernsey','GG','GGY',null,null), + ('Isle of Man','IM','IMN',null,null), + ('Jersey','JE','JEY',null,null), + ('Åland Islands','AX','ALA',null,null), + ('Montenegro','ME','MNE',null,null), + ('Saint Barthélemy','BL','BLM',null,null), + ('Saint Martin (French part)','MF','MAF',null,null), + ('Serbia','RS','SRB',null,null), + ('Sint Maarten (Dutch part)','SX','SXM',null,null), + ('South Sudan','SS','SSD',null,null), + ('Timor-Leste','TL','TLS',null,null), + ('American Samoa','as','ASM','Amerika Samoa','Oceania'), + ('Andorra','AD','AND','Andorra','Europe'), + ('Angola','AO','AGO','Angola','Africa'), + ('Anguilla','AI','AIA','Anguilla','North America'), + ('Antarctica','AQ','ATA','','Antarctica'), + ('Antigua and Barbuda','AG','ATG','Antigua and Barbuda','North America'), + ('Argentina','AR','ARG','Argentina','South America'), + ('Armenia','AM','ARM','Hajastan','Asia'), + ('Aruba','AW','ABW','Aruba','North America'), + ('Australia','AU','AUS','Australia','Oceania'), + ('Austria','AT','AUT','Österreich','Europe'), + ('Azerbaijan','AZ','AZE','Azerbaijan','Asia'), + ('Bahamas','BS','BHS','The Bahamas','North America'), + ('Bahrain','BH','BHR','Al-Bahrayn','Asia'), + ('Bangladesh','BD','BGD','Bangladesh','Asia'), + ('Barbados','BB','BRB','Barbados','North America'), + ('Belarus','BY','BLR','Belarus','Europe'), + ('Belgium','BE','BEL','Belgium/Belgique','Europe'), + ('Belize','BZ','BLZ','Belize','North America'), + ('Benin','BJ','BEN','Benin','Africa'), + ('Bermuda','BM','BMU','Bermuda','North America'), + ('Bhutan','BT','BTN','Druk-Yul','Asia'), + ('Bolivia','BO','BOL','Bolivia','South America'), + ('Bosnia and Herzegovina','BA','BIH','Bosna i Hercegovina','Europe'), + ('Botswana','BW','BWA','Botswana','Africa'), + ('Bouvet Island','BV','BVT','Bouvet Island','Antarctica'), + ('Brazil','BR','BRA','Brasil','South America'), + ('British Indian Ocean Territory','IO','IOT','British Indian Ocean Territory','Africa'), + ('Brunei Darussalam','BN','BRN','Brunei Darussalam','Asia'), + ('Bulgaria','BG','BGR','Balgarija','Europe'), + ('Burkina Faso','BF','BFA','Burkina Faso','Africa'), + ('Burundi','BI','BDI','Burundi/Uburundi','Africa'), + ('Cambodia','KH','KHM','Cambodia','Asia'), + ('Cameroon','CM','CMR','Cameroun/Cameroon','Africa'), + ('Canada','CA','CAN','Canada','North America'), + ('Cape Verde','CV','CPV','Cabo Verde','Africa'), + ('Cayman Islands','KY','CYM','Cayman Islands','North America'), + ('Central African Republic','CF','CAF','Centrafrique','Africa'), + ('Chad','TD','TCD','Tchad/Tshad','Africa'), + ('Chile','CL','CHL','Chile','South America'), + ('China','CN','CHN','Zhongquo','Asia'), + ('Christmas Island','CX','CXR','Christmas Island','Oceania'), + ('Cocos (Keeling) Islands','CC','CCK','Cocos (Keeling) Islands','Oceania'), + ('Colombia','CO','COL','Colombia','South America'), + ('Comoros','KM','COM','Komori/Comores','Africa'), + ('Congo','CG','COG','Congo','Africa'), + ('Congo, the Democratic Republic of the','CD','COD','Republique Democratique du Congo','Africa'), + ('Cook Islands','CK','COK','The Cook Islands','Oceania'), + ('Costa Rica','CR','CRI','Costa Rica','North America'), + ('Cote DIvoire','CI','CIV','Côte dIvoire','Africa'), + ('Croatia','HR','HRV','Hrvatska','Europe'), + ('Cuba','CU','CUB','Cuba','North America'), + ('Cyprus','CY','CYP','Cyprus','Asia'), + ('Czech Republic','CZ','CZE','Czech','Europe'), + ('Denmark','DK','DNK','Danmark','Europe'), + ('Djibouti','DJ','DJI','Djibouti/Jibuti','Africa'), + ('Dominica','DM','DMA','Dominica','North America'), + ('Dominican Republic','DO','DOM','Republica Dominicana','North America'), + ('Ecuador','EC','ECU','Ecuador','South America'), + ('Egypt','EG','EGY','Misr','Africa'), + ('El Salvador','SV','SLV','El Salvador','North America'), + ('Equatorial Guinea','GQ','GNQ','Guinea Ecuatorial','Africa'), + ('Eritrea','ER','ERI','Ertra','Africa'), + ('Estonia','EE','EST','Eesti','Europe'), + ('Ethiopia','ET','ETH','Yeityopiya','Africa'), + ('Falkland Islands (Malvinas)','FK','FLK','Falkland Islands','South America'), + ('Faroe Islands','FO','FRO','Faroe Islands','Europe'), + ('Fiji','FJ','FJI','Fiji Islands','Oceania'), + ('Finland','FI','FIN','Suomi','Europe'), + ('France','FR','FRA','France','Europe'), + ('French Guiana','GF','GUF','Guyane francaise','South America'), + ('French Polynesia','PF','PYF','Polynésie française','Oceania'), + ('French Southern Territories','TF','ATF','Terres australes françaises','Antarctica'), + ('Gabon','GA','GAB','Le Gabon','Africa'), + ('Gambia','GM','GMB','The Gambia','Africa'), + ('Georgia','GE','GEO','Sakartvelo','Asia'), + ('Germany','DE','DEU','Deutschland','Europe'), + ('Ghana','GH','GHA','Ghana','Africa'), + ('Gibraltar','GI','GIB','Gibraltar','Europe'), + ('Greece','GR','GRC','Greece','Europe'), + ('Greenland','GL','GRL','Kalaallit Nunaat','North America'), + ('Grenada','GD','GRD','Grenada','North America'), + ('Guadeloupe','GP','GLP','Guadeloupe','North America'), + ('Guam','GU','GUM','Guam','Oceania'), + ('Guatemala','GT','GTM','Guatemala','North America'), + ('Guinea','GN','GIN','Guinea','Africa'), + ('Guinea-Bissau','GW','GNB','Guinea-Bissau','Africa'), + ('Guyana','GY','GUY','Guyana','South America'), + ('Haiti','HT','HTI','Haiti/Dayti','North America'), + ('Heard Island and Mcdonald Islands','HM','HMD','Heard and McDonald Islands','Antarctica'), + ('Holy See (Vatican City State)','VA','VAT','Santa Sede/Città del Vaticano','Europe'), + ('Honduras','HN','HND','Honduras','North America'), + ('Hong Kong','HK','HKG','Xianggang/Hong Kong','Asia'), + ('Hungary','HU','HUN','Hungary','Europe'), + ('Iceland','IS','ISL','Iceland','Europe'), + ('India','IN','IND','Bharat/India','Asia'), + ('Indonesia','ID','IDN','Indonesia','Asia'), + ('Iran, Islamic Republic of','IR','IRN','Iran','Asia'), + ('Iraq','IQ','IRQ','Al-Irāq','Asia'), + ('Ireland','IE','IRL','Ireland','Europe'), + ('Israel','IL','ISR','Yisrael','Asia'), + ('Italy','IT','ITA','Italia','Europe'), + ('Jamaica','JM','JAM','Jamaica','North America'), + ('Japan','JP','JPN','Nihon/Nippon','Asia'), + ('Jordan','JO','JOR','Al-Urdunn','Asia'), + ('Kazakhstan','KZ','KAZ','Qazaqstan','Asia'), + ('Kenya','KE','KEN','Kenya','Africa'), + ('Kiribati','KI','KIR','Kiribati','Oceania'), + ('Korea, Democratic People''s Republic of','KP','PRK','Choson Minjujuui Inmin Konghwaguk (Bukhan)','Asia'), + ('Korea, Republic of','KR','KOR','Taehan-minguk (Namhan)','Asia'), + ('Kuwait','KW','KWT','Al-Kuwayt','Asia'), + ('Kyrgyzstan','KG','KGZ','Kyrgyzstan','Asia'), + ('Lao People''s Democratic Republic','LA','LAO','Lao','Asia'), + ('Latvia','LV','LVA','Latvija','Europe'), + ('Lebanon','LB','LBN','Lubnan','Asia'), + ('Lesotho','LS','LSO','Lesotho','Africa'), + ('Liberia','LR','LBR','Liberia','Africa'), + ('Libya','LY','LBY','Libiya','Africa'), + ('Liechtenstein','LI','LIE','Liechtenstein','Europe'), + ('Lithuania','LT','LTU','Lietuva','Europe'), + ('Luxembourg','LU','LUX','Luxembourg','Europe'), + ('Macao','MO','MAC','Macau/Aomen','Asia'), + ('Macedonia, the Former Yugoslav Republic of','MK','MKD','Makedonija','Europe'), + ('Madagascar','MG','MDG','Madagasikara/Madagascar','Africa'), + ('Malawi','MW','MWI','Malawi','Africa'), + ('Malaysia','MY','MYS','Malaysia','Asia'), + ('Maldives','MV','MDV','Dhivehi Raajje/Maldives','Asia'), + ('Mali','ML','MLI','Mali','Africa'), + ('Malta','MT','MLT','Malta','Europe'), + ('Marshall Islands','MH','MHL','Marshall Islands/Majol','Oceania'), + ('Martinique','MQ','MTQ','Martinique','North America'), + ('Mauritania','MR','MRT','Muritaniya/Mauritanie','Africa'), + ('Mauritius','MU','MUS','Mauritius','Africa'), + ('Mayotte','YT','MYT','Mayotte','Africa'), + ('Mexico','MX','MEX','Mexico','North America'), + ('Micronesia, Federated States of','FM','FSM','Micronesia','Oceania'), + ('Moldova, Republic of','MD','MDA','Moldova','Europe'), + ('Monaco','MC','MCO','Monaco','Europe'), + ('Mongolia','MN','MNG','Mongol Uls','Asia'), + ('Albania','AL','ALB','Republika e Shqipërisë','Europe'), + ('Montserrat','MS','MSR','Montserrat','North America'), + ('Morocco','MA','MAR','Al-Maghrib','Africa'), + ('Mozambique','MZ','MOZ','Mozambique','Africa'), + ('Myanmar','MM','MMR','Myanma Pye','Asia'), + ('Namibia','NA','NAM','Namibia','Africa'), + ('Nauru','NR','NRU','Naoero/Nauru','Oceania'), + ('Nepal','NP','NPL','Nepal','Asia'), + ('Netherlands','NL','NLD','Nederland','Europe'), + ('New Caledonia','NC','NCL','Nouvelle-Calédonie','Oceania'), + ('New Zealand','NZ','NZL','New Zealand/Aotearoa','Oceania'), + ('Nicaragua','NI','NIC','Nicaragua','North America'), + ('Niger','NE','NER','Niger','Africa'), + ('Nigeria','NG','NGA','Nigeria','Africa'), + ('Niue','NU','NIU','Niue','Oceania'), + ('Norfolk Island','NF','NFK','Norfolk Island','Oceania'), + ('Northern Mariana Islands','MP','MNP','Northern Mariana Islands','Oceania'), + ('Norway','NO','NOR','Norge','Europe'), + ('Oman','OM','OMN','Oman','Asia'), + ('Pakistan','PK','PAK','Pakistan','Asia'), + ('Palau','PW','PLW','Belau/Palau','Oceania'), + ('Palestine, State of','PS','PSE','Filastin','Asia'), + ('Panama','PA','PAN','República de Panamá','North America'), + ('Papua New Guinea','PG','PNG','Papua New Guinea/Papua Niugini','Oceania'), + ('Paraguay','PY','PRY','Paraguay','South America'), + ('Peru','PE','PER','Perú/Piruw','South America'), + ('Philippines','PH','PHL','Pilipinas','Asia'), + ('Pitcairn','PN','PCN','Pitcairn','Oceania'), + ('Poland','PL','POL','Polska','Europe'), + ('Portugal','PT','PRT','Portugal','Europe'), + ('Puerto Rico','PR','PRI','Puerto Rico','North America'), + ('Qatar','QA','QAT','Qatar','Asia'), + ('Reunion','RE','REU','Reunion','Africa'), + ('Romania','RO','ROM','Romania','Europe'), + ('Russian Federation','RU','RUS','Rossija','Europe'), + ('Rwanda','RW','RWA','Rwanda/Urwanda','Africa'), + ('Saint Helena, Ascension and Tristan da Cunha','SH','SHN','Saint Helena','Africa'), + ('Saint Kitts and Nevis','KN','KNA','Saint Kitts and Nevis','North America'), + ('Saint Lucia','LC','LCA','Saint Lucia','North America'), + ('Saint Pierre and Miquelon','PM','SPM','Saint-Pierre-et-Miquelon','North America'), + ('Saint Vincent and the Grenadines','VC','VCT','Saint Vincent and the Grenadines','North America'), + ('Samoa','WS','WSM','Samoa','Oceania'), + ('San Marino','SM','SMR','San Marino','Europe'), + ('Sao Tome and Principe','ST','STP','São Tomé e Príncipe','Africa'), + ('Saudi Arabia','SA','SAU','Al-Mamlaka al-Arabiya as-Saudiya','Asia'), + ('Senegal','SN','SEN','Sénégal/Sounougal','Africa'), + ('Seychelles','SC','SYC','Sesel/Seychelles','Africa'), + ('Sierra Leone','SL','SLE','Sierra Leone','Africa'), + ('Singapore','SG','SGP','Singapore/Singapura/Xinjiapo/Singapur','Asia'), + ('Slovakia','SK','SVK','Slovensko','Europe'), + ('Slovenia','SI','SVN','Slovenija','Europe'), + ('Solomon Islands','SB','SLB','Solomon Islands','Oceania'), + ('Somalia','SO','SOM','Soomaaliya','Africa'), + ('South Africa','ZA','ZAF','South Africa','Africa'), + ('South Georgia and the South Sandwich Islands','GS','SGS','South Georgia and the South Sandwich Islands','Antarctica'), + ('Spain','ES','ESP','España','Europe'), + ('Sri Lanka','LK','LKA','Sri Lanka/Ilankai','Asia'), + ('Sudan','SD','SDN','As-Sudan','Africa'), + ('Suriname','SR','SUR','Suriname','South America'), + ('Svalbard and Jan Mayen','SJ','SJM','Svalbard og Jan Mayen','Europe'), + ('Swaziland','SZ','SWZ','kaNgwane','Africa'), + ('Sweden','SE','SWE','Sverige','Europe'), + ('Switzerland','CH','CHE','Schweiz/Suisse/Svizzera/Svizra','Europe'), + ('Syrian Arab Republic','SY','SYR','Suriya','Asia'), + ('Taiwan (Province of China)','TW','TWN','Tai-wan','Asia'), + ('Tajikistan','TJ','TJK','Tajikistan','Asia'), + ('Tanzania, United Republic of','TZ','TZA','Tanzania','Africa'), + ('Thailand','TH','THA','Prathet Thai','Asia'), + ('Togo','TG','TGO','Togo','Africa'), + ('Tokelau','TK','TKL','Tokelau','Oceania'), + ('Tonga','TO','TON','Tonga','Oceania'), + ('Trinidad and Tobago','TT','TTO','Trinidad and Tobago','North America'), + ('Tunisia','TN','TUN','Tunis/Tunisie','Africa'), + ('Turkey','TR','TUR','Türkiye','Asia'), + ('Turkmenistan','TM','TKM','Türkmenistan','Asia'), + ('Turks and Caicos Islands','TC','TCA','The Turks and Caicos Islands','North America'), + ('Tuvalu','TV','TUV','Tuvalu','Oceania'), + ('Uganda','UG','UGA','Uganda','Africa'), + ('Ukraine','UA','UKR','Ukrajina','Europe'), + ('United Arab Emirates','AE','ARE','Al-Amirat al-Arabiya al-Muttahida','Asia'), + ('United Kingdom','GB','GBR','United Kingdom','Europe'), + ('United States','US','USA','United States','North America'), + ('United States Minor Outlying Islands','UM','UMI','United States Minor Outlying Islands','Oceania'), + ('Uruguay','UY','URY','Uruguay','South America'), + ('Uzbekistan','UZ','UZB','Uzbekiston','Asia'), + ('Vanuatu','VU','VUT','Vanuatu','Oceania'), + ('Venezuela','VE','VEN','Venezuela','South America'), + ('Viet Nam','VN','VNM','Viet Nam','Asia'), + ('Virgin Islands (British)','VG','VGB','British Virgin Islands','North America'), + ('Virgin Islands (U.S.)','VI','VIR','Virgin Islands of the United States','North America'), + ('Wallis and Futuna','WF','WLF','Wallis-et-Futuna','Oceania'), + ('Western Sahara','EH','ESH','As-Sahrawiya','Africa'), + ('Yemen','YE','YEM','Al-Yaman','Asia'), + ('Zambia','ZM','ZMB','Zambia','Africa'), + ('Zimbabwe','ZW','ZWE','Zimbabwe','Africa'), + ('Afghanistan','AF','AFG','Afganistan/Afqanestan','Asia'), + ('Algeria','DZ','DZA','Al-Jazair/Algerie','Africa'); +`.trim(), + }, + { + id: 12, + type: 'quickstart', + title: 'Slack Clone', + description: 'Build a basic slack clone with Row Level Security.', + sql: ` +-- +-- For use with https://github.com/supabase/supabase/tree/master/examples/slack-clone/nextjs-slack-clone + +-- Custom types +create type public.app_permission as enum ('channels.delete', 'messages.delete'); +create type public.app_role as enum ('admin', 'moderator'); +create type public.user_status as enum ('ONLINE', 'OFFLINE'); + +-- USERS +create table public.users ( + id uuid not null primary key, -- UUID from auth.users + username text, + status user_status default 'OFFLINE'::public.user_status +); +comment on table public.users is 'Profile data for each user.'; +comment on column public.users.id is 'References the internal Supabase Auth user.'; + +-- CHANNELS +create table public.channels ( + id bigint generated by default as identity primary key, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, + slug text not null unique, + created_by uuid references public.users not null +); +comment on table public.channels is 'Topics and groups.'; + +-- MESSAGES +create table public.messages ( + id bigint generated by default as identity primary key, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null, + message text, + user_id uuid references public.users not null, + channel_id bigint references public.channels on delete cascade not null +); +comment on table public.messages is 'Individual messages sent by each user.'; + +-- USER ROLES +create table public.user_roles ( + id bigint generated by default as identity primary key, + user_id uuid references public.users on delete cascade not null, + role app_role not null, + unique (user_id, role) +); +comment on table public.user_roles is 'Application roles for each user.'; + +-- ROLE PERMISSIONS +create table public.role_permissions ( + id bigint generated by default as identity primary key, + role app_role not null, + permission app_permission not null, + unique (role, permission) +); +comment on table public.role_permissions is 'Application permissions for each role.'; + +-- authorize with role-based access control (RBAC) +create function public.authorize( + requested_permission app_permission, + user_id uuid +) +returns boolean as +$$ + declare + bind_permissions int; + begin + select + count(*) + from public.role_permissions + inner join public.user_roles on role_permissions.role = user_roles.role + where + role_permissions.permission = authorize.requested_permission and + user_roles.user_id = authorize.user_id + into bind_permissions; + + return bind_permissions > 0; + end; +$$ +language plpgsql security definer; + +-- Secure the tables +alter table public.users + enable row level security; +alter table public.channels + enable row level security; +alter table public.messages + enable row level security; +alter table public.user_roles + enable row level security; +alter table public.role_permissions + enable row level security; + +create policy "Allow logged-in read access" on public.users + for select using (auth.role() = 'authenticated'); +create policy "Allow individual insert access" on public.users + for insert with check (auth.uid() = id); +create policy "Allow individual update access" on public.users + for update using ( auth.uid() = id ); +create policy "Allow logged-in read access" on public.channels + for select using (auth.role() = 'authenticated'); +create policy "Allow individual insert access" on public.channels + for insert with check (auth.uid() = created_by); +create policy "Allow individual delete access" on public.channels + for delete using (auth.uid() = created_by); +create policy "Allow authorized delete access" on public.channels + for delete using (authorize('channels.delete', auth.uid())); +create policy "Allow logged-in read access" on public.messages + for select using (auth.role() = 'authenticated'); +create policy "Allow individual insert access" on public.messages + for insert with check (auth.uid() = user_id); +create policy "Allow individual update access" on public.messages + for update using (auth.uid() = user_id); +create policy "Allow individual delete access" on public.messages + for delete using (auth.uid() = user_id); +create policy "Allow authorized delete access" on public.messages + for delete using (authorize('messages.delete', auth.uid())); +create policy "Allow individual read access" on public.user_roles + for select using (auth.uid() = user_id); + +-- Send "previous data" on change +alter table public.users + replica identity full; +alter table public.channels + replica identity full; +alter table public.messages + replica identity full; + +-- inserts a row into public.users and assigns roles +create function public.handle_new_user() +returns trigger as +$$ + declare is_admin boolean; + begin + insert into public.users (id, username) + values (new.id, new.email); + + select count(*) = 1 from auth.users into is_admin; + + if position('+supaadmin@' in new.email) > 0 then + insert into public.user_roles (user_id, role) values (new.id, 'admin'); + elsif position('+supamod@' in new.email) > 0 then + insert into public.user_roles (user_id, role) values (new.id, 'moderator'); + end if; + + return new; + end; +$$ language plpgsql security definer; + +-- trigger the function every time a user is created +create trigger on_auth_user_created + after insert on auth.users + for each row execute procedure public.handle_new_user(); + +/** + * REALTIME SUBSCRIPTIONS + * Only allow realtime listening on public tables. + */ + +begin; + -- remove the realtime publication + drop publication if exists supabase_realtime; + + -- re-create the publication but don't enable it for any tables + create publication supabase_realtime; +commit; + +-- add tables to the publication +alter publication supabase_realtime add table public.channels; +alter publication supabase_realtime add table public.messages; +alter publication supabase_realtime add table public.users; + +-- DUMMY DATA +insert into public.users (id, username) +values + ('8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e', 'supabot'); + +insert into public.channels (slug, created_by) +values + ('public', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), + ('random', '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); + +insert into public.messages (message, channel_id, user_id) +values + ('Hello World 👋', 1, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'), + ('Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.', 2, '8d0fd2b3-9ca7-4d9e-a95f-9e13dded323e'); + +insert into public.role_permissions (role, permission) +values + ('admin', 'channels.delete'), + ('admin', 'messages.delete'), + ('moderator', 'messages.delete'); +`.trim(), + }, + { + id: 13, + type: 'quickstart', + title: 'Todo List', + description: 'Build a basic todo list with Row Level Security.', + sql: ` +-- +-- For use with: +-- https://github.com/supabase/supabase/tree/master/examples/todo-list/sveltejs-todo-list or +-- https://github.com/supabase/examples-archive/tree/main/supabase-js-v1/todo-list +-- + +create table todos ( + id bigint generated by default as identity primary key, + user_id uuid references auth.users not null, + task text check (char_length(task) > 3), + is_complete boolean default false, + inserted_at timestamp with time zone default timezone('utc'::text, now()) not null +); +alter table todos enable row level security; +create policy "Individuals can create todos." on todos for + insert with check (auth.uid() = user_id); +create policy "Individuals can view their own todos. " on todos for + select using (auth.uid() = user_id); +create policy "Individuals can update their own todos." on todos for + update using (auth.uid() = user_id); +create policy "Individuals can delete their own todos." on todos for + delete using (auth.uid() = user_id); +`.trim(), + }, + { + id: 14, + type: 'quickstart', + title: 'Stripe Subscriptions', + description: 'Starter template for the Next.js Stripe Subscriptions Starter.', + sql: ` +/** +* USERS +* Note: This table contains user data. Users should only be able to view and update their own data. +*/ +create table users ( + -- UUID from auth.users + id uuid references auth.users not null primary key, + full_name text, + avatar_url text, + -- The customer's billing address, stored in JSON format. + billing_address jsonb, + -- Stores your customer's payment instruments. + payment_method jsonb +); +alter table users + enable row level security; +create policy "Can view own user data." on users + for select using (auth.uid() = id); +create policy "Can update own user data." on users + for update using (auth.uid() = id); + +/** +* This trigger automatically creates a user entry when a new user signs up via Supabase Auth. +*/ +create function public.handle_new_user() +returns trigger as +$$ + begin + insert into public.users (id, full_name, avatar_url) + values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); + return new; + end; +$$ +language plpgsql security definer; + +create trigger on_auth_user_created + after insert on auth.users + for each row + execute procedure public.handle_new_user(); + +/** +* CUSTOMERS +* Note: this is a private table that contains a mapping of user IDs to Strip customer IDs. +*/ +create table customers ( + -- UUID from auth.users + id uuid references auth.users not null primary key, + -- The user's customer ID in Stripe. User must not be able to update this. + stripe_customer_id text +); +alter table customers enable row level security; +-- No policies as this is a private table that the user must not have access to. + +/** +* PRODUCTS +* Note: products are created and managed in Stripe and synced to our DB via Stripe webhooks. +*/ +create table products ( + -- Product ID from Stripe, e.g. prod_1234. + id text primary key, + -- Whether the product is currently available for purchase. + active boolean, + -- The product's name, meant to be displayable to the customer. Whenever this product is sold via a subscription, name will show up on associated invoice line item descriptions. + name text, + -- The product's description, meant to be displayable to the customer. Use this field to optionally store a long form explanation of the product being sold for your own rendering purposes. + description text, + -- A URL of the product image in Stripe, meant to be displayable to the customer. + image text, + -- Set of key-value pairs, used to store additional information about the object in a structured format. + metadata jsonb +); +alter table products + enable row level security; +create policy "Allow public read-only access." on products + for select using (true); + +/** +* PRICES +* Note: prices are created and managed in Stripe and synced to our DB via Stripe webhooks. +*/ +create type pricing_type as enum ('one_time', 'recurring'); +create type pricing_plan_interval as enum ('day', 'week', 'month', 'year'); +create table prices ( + -- Price ID from Stripe, e.g. price_1234. + id text primary key, + -- The ID of the prduct that this price belongs to. + product_id text references products, + -- Whether the price can be used for new purchases. + active boolean, + -- A brief description of the price. + description text, + -- The unit amount as a positive integer in the smallest currency unit (e.g., 100 cents for US$1.00 or 100 for ¥100, a zero-decimal currency). + unit_amount bigint, + -- Three-letter ISO currency code, in lowercase. + currency text check (char_length(currency) = 3), + -- One of \`one_time\` or \`recurring\` depending on whether the price is for a one-time purchase or a recurring (subscription) purchase. + type pricing_type, + -- The frequency at which a subscription is billed. One of \`day\`, \`week\`, \`month\` or \`year\`. + interval pricing_plan_interval, + -- The number of intervals (specified in the \`interval\` attribute) between subscription billings. For example, \`interval=month\` and \`interval_count=3\` bills every 3 months. + interval_count integer, + -- Default number of trial days when subscribing a customer to this price using [\`trial_from_plan=true\`](https://stripe.com/docs/api#create_subscription-trial_from_plan). + trial_period_days integer, + -- Set of key-value pairs, used to store additional information about the object in a structured format. + metadata jsonb +); +alter table prices + enable row level security; +create policy "Allow public read-only access." on prices + for select using (true); + +/** +* SUBSCRIPTIONS +* Note: subscriptions are created and managed in Stripe and synced to our DB via Stripe webhooks. +*/ +create type subscription_status as enum ('trialing', 'active', 'canceled', 'incomplete', 'incomplete_expired', 'past_due', 'unpaid'); +create table subscriptions ( + -- Subscription ID from Stripe, e.g. sub_1234. + id text primary key, + user_id uuid references auth.users not null, + -- The status of the subscription object, one of subscription_status type above. + status subscription_status, + -- Set of key-value pairs, used to store additional information about the object in a structured format. + metadata jsonb, + -- ID of the price that created this subscription. + price_id text references prices, + -- Quantity multiplied by the unit amount of the price creates the amount of the subscription. Can be used to charge multiple seats. + quantity integer, + -- If true the subscription has been canceled by the user and will be deleted at the end of the billing period. + cancel_at_period_end boolean, + -- Time at which the subscription was created. + created timestamp with time zone default timezone('utc'::text, now()) not null, + -- Start of the current period that the subscription has been invoiced for. + current_period_start timestamp with time zone default timezone('utc'::text, now()) not null, + -- End of the current period that the subscription has been invoiced for. At the end of this period, a new invoice will be created. + current_period_end timestamp with time zone default timezone('utc'::text, now()) not null, + -- If the subscription has ended, the timestamp of the date the subscription ended. + ended_at timestamp with time zone default timezone('utc'::text, now()), + -- A date in the future at which the subscription will automatically get canceled. + cancel_at timestamp with time zone default timezone('utc'::text, now()), + -- If the subscription has been canceled, the date of that cancellation. If the subscription was canceled with \`cancel_at_period_end\`, \`canceled_at\` will still reflect the date of the initial cancellation request, not the end of the subscription period when the subscription is automatically moved to a canceled state. + canceled_at timestamp with time zone default timezone('utc'::text, now()), + -- If the subscription has a trial, the beginning of that trial. + trial_start timestamp with time zone default timezone('utc'::text, now()), + -- If the subscription has a trial, the end of that trial. + trial_end timestamp with time zone default timezone('utc'::text, now()) +); +alter table subscriptions + enable row level security; +create policy "Can only view own subs data." on subscriptions + for select using (auth.uid() = user_id); + +/** + * REALTIME SUBSCRIPTIONS + * Only allow realtime listening on public tables. + */ +drop publication if exists supabase_realtime; +create publication supabase_realtime + for table products, prices; +`.trim(), + }, + { + id: 15, + type: 'quickstart', + title: 'User Management Starter', + description: 'Sets up a public Profiles table which you can access with your API.', + sql: ` +-- Create a table for public profiles +create table profiles ( + id uuid references auth.users on delete cascade not null primary key, + updated_at timestamp with time zone, + username text unique, + full_name text, + avatar_url text, + website text, + + constraint username_length check (char_length(username) >= 3) +); +-- Set up Row Level Security (RLS) +-- See https://supabase.com/docs/guides/auth/row-level-security for more details. +alter table profiles + enable row level security; + +create policy "Public profiles are viewable by everyone." on profiles + for select using (true); + +create policy "Users can insert their own profile." on profiles + for insert with check (auth.uid() = id); + +create policy "Users can update own profile." on profiles + for update using (auth.uid() = id); + +-- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth. +-- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details. +create function public.handle_new_user() +returns trigger as $$ +begin + insert into public.profiles (id, full_name, avatar_url) + values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); + return new; +end; +$$ language plpgsql security definer; +create trigger on_auth_user_created + after insert on auth.users + for each row execute procedure public.handle_new_user(); + +-- Set up Storage! +insert into storage.buckets (id, name) + values ('avatars', 'avatars'); + +-- Set up access controls for storage. +-- See https://supabase.com/docs/guides/storage#policy-examples for more details. +create policy "Avatar images are publicly accessible." on storage.objects + for select using (bucket_id = 'avatars'); + +create policy "Anyone can upload an avatar." on storage.objects + for insert with check (bucket_id = 'avatars'); +`.trim(), + }, + { + id: 16, + type: 'quickstart', + title: 'NextAuth Schema Setup', + description: 'Sets up a the Schema and Tables for the NextAuth Supabase Adapter.', + sql: ` +-- +-- Name: next_auth; Type: SCHEMA; +-- +CREATE SCHEMA next_auth; + +GRANT USAGE ON SCHEMA next_auth TO service_role; +GRANT ALL ON SCHEMA next_auth TO postgres; + +-- +-- Create users table +-- +CREATE TABLE IF NOT EXISTS next_auth.users +( + id uuid NOT NULL DEFAULT gen_random_uuid(), + name text, + email text, + "emailVerified" timestamp with time zone, + image text, + CONSTRAINT users_pkey PRIMARY KEY (id), + CONSTRAINT email_unique UNIQUE (email) +); + +GRANT ALL ON TABLE next_auth.users TO postgres; +GRANT ALL ON TABLE next_auth.users TO service_role; + +--- uid() function to be used in RLS policies +CREATE FUNCTION next_auth.uid() RETURNS uuid + LANGUAGE sql STABLE + AS $$ + select + coalesce( + nullif(current_setting('request.jwt.claim.sub', true), ''), + (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub') + )::uuid +$$; + +-- +-- Create sessions table +-- +CREATE TABLE IF NOT EXISTS next_auth.sessions +( + id uuid NOT NULL DEFAULT gen_random_uuid(), + expires timestamp with time zone NOT NULL, + "sessionToken" text NOT NULL, + "userId" uuid, + CONSTRAINT sessions_pkey PRIMARY KEY (id), + CONSTRAINT sessionToken_unique UNIQUE ("sessionToken"), + CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId") + REFERENCES next_auth.users (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE CASCADE +); + +GRANT ALL ON TABLE next_auth.sessions TO postgres; +GRANT ALL ON TABLE next_auth.sessions TO service_role; + +-- +-- Create accounts table +-- +CREATE TABLE IF NOT EXISTS next_auth.accounts +( + id uuid NOT NULL DEFAULT gen_random_uuid(), + type text NOT NULL, + provider text NOT NULL, + "providerAccountId" text NOT NULL, + refresh_token text, + access_token text, + expires_at bigint, + token_type text, + scope text, + id_token text, + session_state text, + oauth_token_secret text, + oauth_token text, + "userId" uuid, + CONSTRAINT accounts_pkey PRIMARY KEY (id), + CONSTRAINT provider_unique UNIQUE (provider, "providerAccountId"), + CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") + REFERENCES next_auth.users (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE CASCADE +); + +GRANT ALL ON TABLE next_auth.accounts TO postgres; +GRANT ALL ON TABLE next_auth.accounts TO service_role; + +-- +-- Create verification_tokens table +-- +CREATE TABLE IF NOT EXISTS next_auth.verification_tokens +( + identifier text, + token text, + expires timestamp with time zone NOT NULL, + CONSTRAINT verification_tokens_pkey PRIMARY KEY (token), + CONSTRAINT token_unique UNIQUE (token), + CONSTRAINT token_identifier_unique UNIQUE (token, identifier) +); + +GRANT ALL ON TABLE next_auth.verification_tokens TO postgres; +GRANT ALL ON TABLE next_auth.verification_tokens TO service_role; +`.trim(), + }, + { + id: 17, + type: 'template', + title: 'Most frequently invoked', + description: 'Most frequently called queries in your database.', + sql: `-- Most frequently called queries + +-- A limit of 100 has been added below + +select + auth.rolname, + statements.query, + statements.calls, + -- -- Postgres 13, 14, 15 + statements.total_exec_time + statements.total_plan_time as total_time, + statements.min_exec_time + statements.min_plan_time as min_time, + statements.max_exec_time + statements.max_plan_time as max_time, + statements.mean_exec_time + statements.mean_plan_time as mean_time, + -- -- Postgres <= 12 + -- total_time, + -- min_time, + -- max_time, + -- mean_time, + statements.rows / statements.calls as avg_rows + + from pg_stat_statements as statements + inner join pg_authid as auth on statements.userid = auth.oid + order by + statements.calls desc + limit + 100;`, + }, + { + id: 18, + type: 'template', + title: 'Most time consuming', + description: 'Aggregate time spent on a query type.', + sql: `-- Most time consuming queries + +-- A limit of 100 has been added below + +select + auth.rolname, + statements.query, + statements.calls, + statements.total_exec_time + statements.total_plan_time as total_time, + to_char(((statements.total_exec_time + statements.total_plan_time)/sum(statements.total_exec_time + statements.total_plan_time) over()) * 100, 'FM90D0') || '%' as prop_total_time + from pg_stat_statements as statements + inner join pg_authid as auth on statements.userid = auth.oid + order by + total_time desc + limit + 100;`, + }, + { + id: 19, + type: 'template', + title: 'Slowest execution time', + description: 'Slowest queries based on max execution time.', + sql: `-- Slowest queries by max execution time + +-- A limit of 100 has been added below + +select + auth.rolname, + statements.query, + statements.calls, + -- -- Postgres 13, 14, 15 + statements.total_exec_time + statements.total_plan_time as total_time, + statements.min_exec_time + statements.min_plan_time as min_time, + statements.max_exec_time + statements.max_plan_time as max_time, + statements.mean_exec_time + statements.mean_plan_time as mean_time, + -- -- Postgres <= 12 + -- total_time, + -- min_time, + -- max_time, + -- mean_time, + statements.rows / statements.calls as avg_rows + from pg_stat_statements as statements + inner join pg_authid as auth on statements.userid = auth.oid + order by + max_time desc + limit + 100;`, + }, + { + id: 20, + type: 'template', + title: 'Hit rate', + description: 'See your cache and index hit rate.', + sql: `-- Cache and index hit rate + +select + 'index hit rate' as name, + (sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) as ratio + from pg_statio_user_indexes + union all + select + 'table hit rate' as name, + sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) as ratio + from pg_statio_user_tables;`, + }, + { + id: 21, + type: 'quickstart', + title: 'OpenAI Vector Search', + description: 'Template for the Next.js OpenAI Doc Search Starter.', + sql: ` +-- Enable pg_vector extension +create extension if not exists vector with schema public; + +-- Create tables +create table "public"."nods_page" ( + id bigserial primary key, + parent_page_id bigint references public.nods_page, + path text not null unique, + checksum text, + meta jsonb, + type text, + source text +); +alter table "public"."nods_page" enable row level security; + +create table "public"."nods_page_section" ( + id bigserial primary key, + page_id bigint not null references public.nods_page on delete cascade, + content text, + token_count int, + embedding vector(1536), + slug text, + heading text +); +alter table "public"."nods_page_section" enable row level security; + +-- Create embedding similarity search functions +create or replace function match_page_sections(embedding vector(1536), match_threshold float, match_count int, min_content_length int) +returns table (id bigint, page_id bigint, slug text, heading text, content text, similarity float) +language plpgsql +as $$ +#variable_conflict use_variable +begin + return query + select + nods_page_section.id, + nods_page_section.page_id, + nods_page_section.slug, + nods_page_section.heading, + nods_page_section.content, + (nods_page_section.embedding <#> embedding) * -1 as similarity + from nods_page_section + + -- We only care about sections that have a useful amount of content + where length(nods_page_section.content) >= min_content_length + + -- The dot product is negative because of a Postgres limitation, so we negate it + and (nods_page_section.embedding <#> embedding) * -1 > match_threshold + + -- OpenAI embeddings are normalized to length 1, so + -- cosine similarity and dot product will produce the same results. + -- Using dot product which can be computed slightly faster. + -- + -- For the different syntaxes, see https://github.com/pgvector/pgvector + order by nods_page_section.embedding <#> embedding + + limit match_count; +end; +$$; + +create or replace function get_page_parents(page_id bigint) +returns table (id bigint, parent_page_id bigint, path text, meta jsonb) +language sql +as $$ + with recursive chain as ( + select * + from nods_page + where id = page_id + + union all + + select child.* + from nods_page as child + join chain on chain.parent_page_id = child.id + ) + select id, parent_page_id, path, meta + from chain; +$$; +`.trim(), + }, + { + id: 22, + type: 'template', + title: 'Replication status report', + description: 'See the status of your replication slots and replication lag.', + sql: `-- Replication status report + +SELECT + s.slot_name, + s.active, + COALESCE(r.state, 'N/A') as state, + COALESCE(r.client_addr, null) as replication_client_address, + GREATEST(0, ROUND((redo_lsn-restart_lsn)/1024/1024/1024, 2)) as replication_lag_gb +FROM pg_control_checkpoint(), pg_replication_slots s +LEFT JOIN pg_stat_replication r ON (r.pid = s.active_pid); +`, + }, + { + id: 23, + type: 'quickstart', + title: 'LangChain', + description: 'LangChain is a popular framework for working with AI, Vectors, and embeddings.', + sql: ` +-- Enable the pgvector extension to work with embedding vectors +create extension vector; + +-- Create a table to store your documents +create table documents ( + id bigserial primary key, + content text, -- corresponds to Document.pageContent + metadata jsonb, -- corresponds to Document.metadata + embedding vector(1536) -- 1536 works for OpenAI embeddings, change if needed +); + +-- Create a function to search for documents +create function match_documents ( + query_embedding vector(1536), + match_count int default null, + filter jsonb DEFAULT '{}' +) returns table ( + id bigint, + content text, + metadata jsonb, + similarity float +) +language plpgsql +as $$ +#variable_conflict use_column +begin + return query + select + id, + content, + metadata, + 1 - (documents.embedding <=> query_embedding) as similarity + from documents + where metadata @> filter + order by documents.embedding <=> query_embedding + limit match_count; +end; +$$; +`.trim(), + }, + { + id: 24, + type: 'template', + title: 'Install dbdev', + description: 'dbdev is a client for installing 3rd party packages into your database.', + sql: ` +create extension if not exists http with schema extensions; +create extension if not exists pg_tle; +select pgtle.uninstall_extension_if_exists('supabase-dbdev'); +drop extension if exists "supabase-dbdev"; +select + pgtle.install_extension( + 'supabase-dbdev', + resp.contents ->> 'version', + 'PostgreSQL package manager', + resp.contents ->> 'sql' + ) +from http( + ( + 'GET', + 'https://api.database.dev/rest/v1/' + || 'package_versions?select=sql,version' + || '&package_name=eq.supabase-dbdev' + || '&order=version.desc' + || '&limit=1', + array[ + ('apiKey', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InhtdXB0cHBsZnZpaWZyYndtbXR2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODAxMDczNzIsImV4cCI6MTk5NTY4MzM3Mn0.z2CN0mvO2No8wSi46Gw59DFGCTJrzM0AQKsu_5k134s')::http_header + ], + null, + null + ) +) x, +lateral ( + select + ((row_to_json(x) -> 'content') #>> '{}')::json -> 0 +) resp(contents); +create extension "supabase-dbdev"; +select dbdev.install('supabase-dbdev'); +drop extension if exists "supabase-dbdev"; +create extension "supabase-dbdev"; +`.trim(), + }, + { + id: 25, + type: 'template', + title: 'Large objects', + description: 'List large objects (tables/indexes) in your database.', + sql: `SELECT + SCHEMA_NAME, + relname, + table_size + FROM + (SELECT + pg_catalog.pg_namespace.nspname AS SCHEMA_NAME, + relname, + pg_relation_size(pg_catalog.pg_class.oid) AS table_size + FROM pg_catalog.pg_class + JOIN pg_catalog.pg_namespace ON relnamespace = pg_catalog.pg_namespace.oid + ) t + WHERE SCHEMA_NAME NOT LIKE 'pg_%' + ORDER BY table_size DESC + LIMIT 25`.trim(), + }, + { + id: 26, + type: 'template', + title: 'Limit MFA verification attempts to one in 2 seconds', + description: + 'Create an Auth hook that limits the number of failed MFA verification attempts to one in 2 seconds.', + sql: ` +create function public.hook_mfa_verification_attempt(event jsonb) + returns jsonb + language plpgsql +as $$ + declare + last_failed_at timestamp; + begin + if event->'valid' is true then + -- code is valid, accept it + return jsonb_build_object('decision', 'continue'); + end if; + + select last_failed_at into last_failed_at + from public.mfa_failed_verification_attempts + where + user_id = (event->'user_id')::uuid + and + factor_id = event->'factor_id'; + + if last_failed_at is not null and now() - last_failed_at < interval '2 seconds' then + -- last attempt was done too quickly + return jsonb_build_object( + 'error', jsonb_build_object( + 'http_code', 429, + 'message', 'Please wait a moment before trying again.' + ) + ); + end if; + + -- record this failed attempt + insert into public.mfa_failed_verification_attempts + ( + user_id, + factor_id, + last_refreshed_at + ) + values + ( + event->'user_id', + event->'factor_id', + now() + ) + on conflict do update + set last_refreshed_at = now(); + + -- finally let Supabase Auth do the default behavior for a failed attempt + return jsonb_build_object('decision', 'continue'); + end; +$$; + +-- Assign appropriate permissions and revoke access +grant execute + on function public.hook_mfa_verification_attempt + to supabase_auth_admin; + +grant all + on table public.mfa_failed_verification_attempts + to supabase_auth_admin; + +revoke execute + on function public.hook_mfa_verification_attempt + from authenticated, anon; + +revoke all + on table public.mfa_failed_verification_attempts + from authenticated, anon; + +grant usage on schema public to supabase_auth_admin;`.trim(), + }, + { + id: 27, + type: 'template', + title: 'Add Auth Hook (Password Verification Attempt)', + description: + 'Create an Auth Hook that limits number of failed password verification attempts to one in 10 seconds', + sql: ` +create function public.hook_password_verification_attempt(event jsonb) +returns jsonb +language plpgsql +as $$ + declare + last_failed_at timestamp; + begin + if event->'valid' is true then + -- password is valid, accept it + return jsonb_build_object('decision', 'continue'); + end if; + + select last_failed_at into last_failed_at + from public.password_failed_verification_attempts + where + user_id = (event->'user_id')::uuid; + + if last_failed_at is not null and now() - last_failed_at < interval '10 seconds' then + -- last attempt was done too quickly + return jsonb_build_object( + 'error', jsonb_build_object( + 'http_code', 429, + 'message', 'Please wait a moment before trying again.' + ) + ); + end if; + + -- record this failed attempt + insert into public.password_failed_verification_attempts + ( + user_id, + last_failed_at + ) + values + ( + event->'user_id', + now() + ) + on conflict do update + set last_failed_at = now(); + + -- finally let Supabase Auth do the default behavior for a failed attempt + return jsonb_build_object('decision', 'continue'); + end; +$$; + +-- Assign appropriate permissions +grant execute + on function public.hook_password_verification_attempt + to supabase_auth_admin; + +grant all + on table public.password_failed_verification_attempts + to supabase_auth_admin; + +revoke execute + on function public.hook_password_verification_attempt + from authenticated, anon; + +revoke all + on table public.password_failed_verification_attempts + from authenticated, anon; + +grant usage on schema public to supabase_auth_admin;`.trim(), + }, + { + id: 28, + type: 'template', + title: 'Add Auth Hook (Custom Access Token)', + description: 'Create an Auth Hook to add custom claims to your Auth Token', + sql: ` +-- Assumes that there is an is_admin flag on the profiles table. +create or replace function public.custom_access_token_hook(event jsonb) +returns jsonb +language plpgsql +as $$ + declare + claims jsonb; + is_admin boolean; + begin + -- Check if the user is marked as admin in the profiles table + select is_admin into is_admin from profiles where user_id = (event->>'user_id')::uuid; + + -- Proceed only if the user is an admin + if is_admin then + claims := event->'claims'; + + -- Check if 'user_metadata' exists in claims + if jsonb_typeof(claims->'user_metadata') is null then + -- If 'user_metadata' does not exist, create an empty object + claims := jsonb_set(claims, '{user_metadata}', '{}'); + end if; + + -- Set a claim of 'admin' + claims := jsonb_set(claims, '{user_metadata, admin}', 'true'); + + -- Update the 'claims' object in the original event + event := jsonb_set(event, '{claims}', claims); + end if; + + -- Return the modified or original event + return event; + end; +$$; + +grant execute + on function public.custom_access_token_hook + to supabase_auth_admin; + +revoke execute + on function public.custom_access_token_hook + from authenticated, anon; + +grant usage on schema public to supabase_auth_admin;`.trim(), + }, + + { + id: 29, + type: 'template', + title: 'Add Auth Hook (General)', + description: 'Create an Auth Hook', + sql: ` +create or replace function public.custom_access_token_hook(event jsonb) +returns jsonb +language plpgsql +as $$ +declare + -- Insert variables here +begin + -- Insert logic here + return event; +end; +$$; +-- Permissions for the hook +grant execute on function public.custom_access_token_hook to supabase_auth_admin; +revoke execute on function public.custom_access_token_hook from authenticated, anon; + `, + }, +] diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.types.ts b/apps/studio/components/interfaces/SQLEditor/SQLEditor.types.ts index a084da9cd23..5eb20e019ac 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.types.ts +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.types.ts @@ -1,4 +1,4 @@ -import { DiffOnMount, OnMount } from '@monaco-editor/react' +import type { DiffOnMount, OnMount } from '@monaco-editor/react' import { Dispatch, SetStateAction } from 'react' export interface SQLTemplate { diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts b/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts index 18ca6c224cd..3d5478114ab 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts @@ -1,9 +1,7 @@ -// @ts-ignore import { NEW_SQL_SNIPPET_SKELETON, destructiveSqlRegex } from './SQLEditor.constants' import type { SqlSnippets, UserContent } from 'types' import { DiffType } from './SQLEditor.types' import { removeCommentsFromSql } from 'lib/helpers' -import { stripIndent } from 'common-tags' export const createSqlSnippetSkeleton = ({ id, @@ -62,17 +60,17 @@ export function checkDestructiveQuery(sql: string) { return destructiveSqlRegex.some((regex) => regex.test(removeCommentsFromSql(sql))) } -export const generateMigrationCliCommand = (id: string, name: string, isNpx = false) => stripIndent` - ${isNpx ? 'npx ' : ''}supabase snippets download ${id} | - ${isNpx ? 'npx ' : ''}supabase migration new ${name} +export const generateMigrationCliCommand = (id: string, name: string, isNpx = false) => ` +${isNpx ? 'npx ' : ''}supabase snippets download ${id} | +${isNpx ? 'npx ' : ''}supabase migration new ${name} ` -export const generateSeedCliCommand = (id: string, isNpx = false) => stripIndent` - ${isNpx ? 'npx ' : ''}supabase snippets download ${id} >> \\ - supabase/seed.sql +export const generateSeedCliCommand = (id: string, isNpx = false) => ` +${isNpx ? 'npx ' : ''}supabase snippets download ${id} >> \\ + supabase/seed.sql ` -export const generateFileCliCommand = (id: string, name: string, isNpx = false) => stripIndent` - ${isNpx ? 'npx ' : ''}supabase snippets download ${id} > \\ - ${name}.sql +export const generateFileCliCommand = (id: string, name: string, isNpx = false) => ` +${isNpx ? 'npx ' : ''}supabase snippets download ${id} > \\ + ${name}.sql ` diff --git a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx index 7db43451822..1bb12104b9f 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx @@ -3,7 +3,7 @@ import { partition } from 'lodash' import { observer } from 'mobx-react-lite' import { useParams, useTelemetryProps } from 'common' -import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.constants' +import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries' import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useCheckPermissions, useSelectedProject, useStore } from 'hooks' import { uuidv4 } from 'lib/helpers' diff --git a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx index 390f495976d..2de33112c81 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx @@ -3,7 +3,7 @@ import { partition } from 'lodash' import { observer } from 'mobx-react-lite' import { useTelemetryProps } from 'common' -import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.constants' +import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useCheckPermissions, useStore } from 'hooks' diff --git a/apps/studio/data/database/database-query-constants.ts b/apps/studio/data/database/database-query-constants.ts index 67934d5f686..328a469fecb 100644 --- a/apps/studio/data/database/database-query-constants.ts +++ b/apps/studio/data/database/database-query-constants.ts @@ -1,4 +1,4 @@ -import minify from 'pg-minify' +export { CREATE_PG_GET_TABLEDEF_SQL } from './database-table-definition' // https://www.postgresql.org/docs/current/catalog-pg-constraint.html @@ -9,571 +9,3 @@ export enum FOREIGN_KEY_CASCADE_ACTION { SET_NULL = 'n', SET_DEFAULT = 'd', } - -// Derived from https://github.com/MichaelDBA/pg_get_tabledef -// NOTE: when updating, \n must be replaced with \\n in the SQL below - -export const CREATE_PG_GET_TABLEDEF_SQL = minify( - /* SQL */ ` - DROP TYPE IF EXISTS pg_temp.tabledefs CASCADE; - CREATE TYPE pg_temp.tabledefs AS ENUM ('PKEY_INTERNAL','PKEY_EXTERNAL','FKEYS_INTERNAL', 'FKEYS_EXTERNAL', 'FKEYS_COMMENTED', 'FKEYS_NONE', 'INCLUDE_TRIGGERS', 'NO_TRIGGERS'); - - -- DROP FUNCTION pg_temp.pg_get_coldef(text,text,text,boolean); - CREATE OR REPLACE FUNCTION pg_temp.pg_get_coldef( - in_schema text, - in_table text, - in_column text, - oldway boolean default False - ) - RETURNS text - LANGUAGE plpgsql VOLATILE - AS - $$ - DECLARE - coldef text; - BEGIN - IF oldway THEN - SELECT pg_catalog.format_type(a.atttypid, a.atttypmod) INTO coldef FROM pg_namespace n, pg_class c, pg_attribute a, pg_type t - WHERE n.nspname = in_schema AND n.oid = c.relnamespace AND c.relname = in_table AND a.attname = in_column and a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid ORDER BY a.attnum; - ELSE - -- a.attrelid::regclass::text, a.attname - SELECT CASE WHEN a.atttypid = ANY ('{int,int8,int2}'::regtype[]) AND EXISTS (SELECT FROM pg_attrdef ad WHERE ad.adrelid = a.attrelid AND ad.adnum = a.attnum AND - pg_get_expr(ad.adbin, ad.adrelid) = 'nextval(''' || (pg_get_serial_sequence (a.attrelid::regclass::text, a.attname))::regclass || '''::regclass)') THEN CASE a.atttypid - WHEN 'int'::regtype THEN 'serial' WHEN 'int8'::regtype THEN 'bigserial' WHEN 'int2'::regtype THEN 'smallserial' END ELSE format_type(a.atttypid, a.atttypmod) END AS data_type - INTO coldef FROM pg_namespace n, pg_class c, pg_attribute a, pg_type t - WHERE n.nspname = in_schema AND n.oid = c.relnamespace AND c.relname = in_table AND a.attname = in_column and a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid ORDER BY a.attnum; - END IF; - RETURN coldef; - END; - $$; - - -- SELECT * FROM pg_temp.pg_get_tabledef('sample', 'address', false); - DROP FUNCTION IF EXISTS pg_temp.pg_get_tabledef(character varying,character varying,boolean,tabledefs[]); - CREATE OR REPLACE FUNCTION pg_temp.pg_get_tabledef( - in_schema varchar, - in_table varchar, - _verbose boolean, - VARIADIC arr pg_temp.tabledefs[] DEFAULT '{}':: pg_temp.tabledefs[] - ) - RETURNS text - LANGUAGE plpgsql VOLATILE - AS - $$ - DECLARE - v_qualified text := ''; - v_table_ddl text; - v_table_oid int; - v_colrec record; - v_constraintrec record; - v_trigrec record; - v_indexrec record; - v_primary boolean := False; - v_constraint_name text; - v_constraint_def text; - v_pkey_def text := ''; - v_fkey_defs text; - v_trigger text := ''; - v_partition_key text := ''; - v_partbound text; - v_parent text; - v_parent_schema text; - v_persist text; - v_temp text := ''; - v_relopts text; - v_tablespace text; - v_pgversion int; - bSerial boolean; - bPartition boolean; - bInheritance boolean; - bRelispartition boolean; - constraintarr text[] := '{}'; - constraintelement text; - bSkip boolean; - bVerbose boolean := False; - v_cnt1 integer; - v_cnt2 integer; - - -- assume defaults for ENUMs at the getgo - pkcnt int := 0; - fkcnt int := 0; - trigcnt int := 0; - pktype tabledefs := 'PKEY_INTERNAL'; - fktype tabledefs := 'FKEYS_INTERNAL'; - trigtype tabledefs := 'NO_TRIGGERS'; - arglen integer; - vargs text; - avarg tabledefs; - - -- exception variables - v_ret text; - v_diag1 text; - v_diag2 text; - v_diag3 text; - v_diag4 text; - v_diag5 text; - v_diag6 text; - - BEGIN - SET client_min_messages = 'notice'; - IF _verbose THEN bVerbose = True; END IF; - - -- v17 fix: handle case-sensitive - -- v_qualified = in_schema || '.' || in_table; - - arglen := array_length($4, 1); - IF arglen IS NULL THEN - -- nothing to do, so assume defaults - NULL; - ELSE - -- loop thru args - -- IF 'NO_TRIGGERS' = ANY ($4) - -- select array_to_string($4, ',', '***') INTO vargs; - IF bVerbose THEN RAISE NOTICE 'arguments=%', $4; END IF; - FOREACH avarg IN ARRAY $4 LOOP - IF bVerbose THEN RAISE INFO 'arg=%', avarg; END IF; - IF avarg = 'FKEYS_INTERNAL' OR avarg = 'FKEYS_EXTERNAL' OR avarg = 'FKEYS_COMMENTED' THEN - fkcnt = fkcnt + 1; - fktype = avarg; - ELSEIF avarg = 'INCLUDE_TRIGGERS' OR avarg = 'NO_TRIGGERS' THEN - trigcnt = trigcnt + 1; - trigtype = avarg; - ELSEIF avarg = 'PKEY_EXTERNAL' THEN - pkcnt = pkcnt + 1; - pktype = avarg; - END IF; - END LOOP; - IF fkcnt > 1 THEN - RAISE WARNING 'Only one foreign key option can be provided. You provided %', fkcnt; - RETURN ''; - ELSEIF trigcnt > 1 THEN - RAISE WARNING 'Only one trigger option can be provided. You provided %', trigcnt; - RETURN ''; - ELSEIF pkcnt > 1 THEN - RAISE WARNING 'Only one pkey option can be provided. You provided %', pkcnt; - RETURN ''; - END IF; - END IF; - - SELECT c.oid, (select setting from pg_settings where name = 'server_version_num') INTO v_table_oid, v_pgversion FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE c.relkind in ('r','p') AND c.relname = in_table AND n.nspname = in_schema; - - -- throw an error if table was not found - IF (v_table_oid IS NULL) THEN - RAISE EXCEPTION 'table does not exist'; - END IF; - - -- get user-defined tablespaces if applicable - SELECT tablespace INTO v_temp FROM pg_tables WHERE schemaname = in_schema and tablename = in_table and tablespace IS NOT NULL; - IF v_temp IS NULL THEN - v_tablespace := 'TABLESPACE pg_default'; - ELSE - v_tablespace := 'TABLESPACE ' || v_temp; - END IF; - - -- also see if there are any SET commands for this table, ie, autovacuum_enabled=off, fillfactor=70 - WITH relopts AS (SELECT unnest(c.reloptions) relopts FROM pg_class c, pg_namespace n WHERE n.nspname = in_schema and n.oid = c.relnamespace and c.relname = in_table) - SELECT string_agg(r.relopts, ', ') as relopts INTO v_temp from relopts r; - IF v_temp IS NULL THEN - v_relopts := ''; - ELSE - v_relopts := ' WITH (' || v_temp || ')'; - END IF; - - -- ----------------------------------------------------------------------------------- - -- Create table defs for partitions/children using inheritance or declarative methods. - -- inheritance: pg_class.relkind = 'r' pg_class.relispartition=false pg_class.relpartbound is NULL - -- declarative: pg_class.relkind = 'r' pg_class.relispartition=true pg_class.relpartbound is NOT NULL - -- ----------------------------------------------------------------------------------- - v_partbound := ''; - bPartition := False; - bInheritance := False; - IF v_pgversion < 100000 THEN - -- Issue#11: handle parent schema - SELECT c2.relname parent, c2.relnamespace::regnamespace INTO v_parent, v_parent_schema from pg_class c1, pg_namespace n, pg_inherits i, pg_class c2 - WHERE n.nspname = in_schema and n.oid = c1.relnamespace and c1.relname = in_table and c1.oid = i.inhrelid and i.inhparent = c2.oid and c1.relkind = 'r'; - IF (v_parent IS NOT NULL) THEN - bPartition := True; - bInheritance := True; - END IF; - ELSE - -- Issue#11: handle parent schema - SELECT c2.relname parent, c1.relispartition, pg_get_expr(c1.relpartbound, c1.oid, true), c2.relnamespace::regnamespace INTO v_parent, bRelispartition, v_partbound, v_parent_schema from pg_class c1, pg_namespace n, pg_inherits i, pg_class c2 - WHERE n.nspname = in_schema and n.oid = c1.relnamespace and c1.relname = in_table and c1.oid = i.inhrelid and i.inhparent = c2.oid and c1.relkind = 'r'; - IF (v_parent IS NOT NULL) THEN - bPartition := True; - IF bRelispartition THEN - bInheritance := False; - ELSE - bInheritance := True; - END IF; - END IF; - END IF; - IF bPartition THEN - --Issue#17 fix for case-sensitive tables - -- SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s - -- WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = quote_ident(in_schema) AND t.table_name = quote_ident(in_table) AND t.table_type = 'BASE TABLE'); - SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s - WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = in_schema AND t.table_name = in_table AND t.table_type = 'BASE TABLE'); - - --Issue#19 put double-quotes around SQL keyword column names - SELECT COUNT(*) INTO v_cnt2 FROM pg_get_keywords() WHERE word = v_colrec.column_name AND catcode = 'R'; - - IF bInheritance THEN - -- inheritance-based - IF v_cnt1 > 0 OR v_cnt2 > 0 THEN - v_table_ddl := 'CREATE TABLE ' || in_schema || '."' || in_table || '"( '|| E'\\n'; - ELSE - v_table_ddl := 'CREATE TABLE ' || in_schema || '.' || in_table || '( '|| E'\\n'; - END IF; - - -- Jump to constraints section to add the check constraints - ELSE - -- declarative-based - IF v_relopts <> '' THEN - IF v_cnt1 > 0 OR v_cnt2 > 0 THEN - v_table_ddl := 'CREATE TABLE ' || in_schema || '."' || in_table || '" PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || v_relopts || ' ' || v_tablespace || '; ' || E'\\n'; - ELSE - v_table_ddl := 'CREATE TABLE ' || in_schema || '.' || in_table || ' PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || v_relopts || ' ' || v_tablespace || '; ' || E'\\n'; - END IF; - ELSE - IF v_cnt1 > 0 OR v_cnt2 > 0 THEN - v_table_ddl := 'CREATE TABLE ' || in_schema || '."' || in_table || '" PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || ' ' || v_tablespace || '; ' || E'\\n'; - ELSE - v_table_ddl := 'CREATE TABLE ' || in_schema || '.' || in_table || ' PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || ' ' || v_tablespace || '; ' || E'\\n'; - END IF; - END IF; - -- Jump to constraints and index section to add the check constraints and indexes and perhaps FKeys - END IF; - END IF; - IF bVerbose THEN RAISE INFO '(1)tabledef so far: %', v_table_ddl; END IF; - - IF NOT bPartition THEN - -- see if this is unlogged or temporary table - select c.relpersistence into v_persist from pg_class c, pg_namespace n where n.nspname = in_schema and n.oid = c.relnamespace and c.relname = in_table and c.relkind = 'r'; - IF v_persist = 'u' THEN - v_temp := 'UNLOGGED'; - ELSIF v_persist = 't' THEN - v_temp := 'TEMPORARY'; - ELSE - v_temp := ''; - END IF; - END IF; - - -- start the create definition for regular tables unless we are in progress creating an inheritance-based child table - IF NOT bPartition THEN - --Issue#17 fix for case-sensitive tables - -- SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s - -- WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = quote_ident(in_schema) AND t.table_name = quote_ident(in_table) AND t.table_type = 'BASE TABLE'); - SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s - WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = in_schema AND t.table_name = in_table AND t.table_type = 'BASE TABLE'); - IF v_cnt1 > 0 THEN - v_table_ddl := 'CREATE ' || v_temp || ' TABLE ' || in_schema || '."' || in_table || '" (' || E'\\n'; - ELSE - v_table_ddl := 'CREATE ' || v_temp || ' TABLE ' || in_schema || '.' || in_table || ' (' || E'\\n'; - END IF; - END IF; - -- RAISE INFO 'DEBUG2: tabledef so far: %', v_table_ddl; - -- define all of the columns in the table unless we are in progress creating an inheritance-based child table - IF NOT bPartition THEN - FOR v_colrec IN - SELECT c.column_name, c.data_type, c.udt_name, c.udt_schema, c.character_maximum_length, c.is_nullable, c.column_default, c.numeric_precision, c.numeric_scale, c.is_identity, c.identity_generation - FROM information_schema.columns c WHERE (table_schema, table_name) = (in_schema, in_table) ORDER BY ordinal_position - LOOP - IF bVerbose THEN RAISE INFO '(col loop) name=% type=% udt_name=% udt_schema=%', v_colrec.column_name, v_colrec.data_type, v_colrec.udt_name, v_colrec.udt_schema; END IF; - -- v17 fix: handle case-sensitive for pg_get_serial_sequence that requires SQL Identifier handling - -- SELECT CASE WHEN pg_get_serial_sequence(v_qualified, v_colrec.column_name) IS NOT NULL THEN True ELSE False END into bSerial; - SELECT CASE WHEN pg_get_serial_sequence(quote_ident(in_schema) || '.' || quote_ident(in_table), v_colrec.column_name) IS NOT NULL THEN True ELSE False END into bSerial; - IF bVerbose THEN - -- v17 fix: handle case-sensitive for pg_get_serial_sequence that requires SQL Identifier handling - -- SELECT pg_get_serial_sequence(v_qualified, v_colrec.column_name) into v_temp; - SELECT pg_get_serial_sequence(quote_ident(in_schema) || '.' || quote_ident(in_table), v_colrec.column_name) into v_temp; - IF v_temp IS NULL THEN v_temp = 'NA'; END IF; - SELECT pg_temp.pg_get_coldef(in_schema, in_table,v_colrec.column_name) INTO v_diag1; - --RAISE NOTICE 'DEBUG table: % Column: % datatype: % Serial=% serialval=% coldef=%', v_qualified, v_colrec.column_name, v_colrec.data_type, bSerial, v_temp, v_diag1; - --RAISE NOTICE 'DEBUG tabledef: %', v_table_ddl; - END IF; - - --Issue#17 put double-quotes around case-sensitive column names - SELECT COUNT(*) INTO v_cnt1 FROM information_schema.columns t WHERE EXISTS (SELECT REGEXP_MATCHES(s.column_name, '([A-Z]+)','g') FROM information_schema.columns s - WHERE t.table_schema=s.table_schema and t.table_name=s.table_name and t.column_name=s.column_name AND t.table_schema = quote_ident(in_schema) AND column_name = v_colrec.column_name); - - --Issue#19 put double-quotes around SQL keyword column names - SELECT COUNT(*) INTO v_cnt2 FROM pg_get_keywords() WHERE word = v_colrec.column_name AND catcode = 'R'; - - IF v_cnt1 > 0 OR v_cnt2 > 0 THEN - v_table_ddl := v_table_ddl || ' "' || v_colrec.column_name || '" '; - ELSE - v_table_ddl := v_table_ddl || ' ' || v_colrec.column_name || ' '; - END IF; - - v_table_ddl := v_table_ddl || - CASE WHEN v_colrec.udt_name in ('geometry', 'box2d', 'box2df', 'box3d', 'geography', 'geometry_dump', 'gidx', 'spheroid', 'valid_detail') - THEN v_colrec.udt_name - WHEN v_colrec.data_type = 'USER-DEFINED' - THEN v_colrec.udt_schema || '.' || v_colrec.udt_name - WHEN v_colrec.data_type = 'ARRAY' - -- Issue#6 fix: handle arrays - THEN pg_temp.pg_get_coldef(in_schema, in_table,v_colrec.column_name) - -- v17 fix: handle case-sensitive for pg_get_serial_sequence that requires SQL Identifier handling - -- WHEN pg_get_serial_sequence(v_qualified, v_colrec.column_name) IS NOT NULL - WHEN pg_get_serial_sequence(quote_ident(in_schema) || '.' || quote_ident(in_table), v_colrec.column_name) IS NOT NULL - -- Issue#8 fix: handle serial. Note: NOT NULL is implied so no need to declare it explicitly - THEN pg_temp.pg_get_coldef(in_schema, in_table,v_colrec.column_name) - ELSE v_colrec.data_type END - || CASE WHEN v_colrec.is_identity = 'YES' THEN CASE WHEN v_colrec.identity_generation = 'ALWAYS' THEN ' GENERATED ALWAYS AS IDENTITY' ELSE ' GENERATED BY DEFAULT AS IDENTITY' END ELSE '' END - || CASE WHEN v_colrec.character_maximum_length IS NOT NULL THEN ('(' || v_colrec.character_maximum_length || ')') - WHEN v_colrec.numeric_precision > 0 AND v_colrec.numeric_scale > 0 THEN '(' || v_colrec.numeric_precision || ',' || v_colrec.numeric_scale || ')' - ELSE '' END || ' ' - || CASE WHEN bSerial THEN '' ELSE CASE WHEN v_colrec.is_nullable = 'NO' THEN 'NOT NULL' ELSE 'NULL' END END - || CASE WHEN bSerial THEN '' ELSE CASE WHEN v_colrec.column_default IS NOT null THEN (' DEFAULT ' || v_colrec.column_default) ELSE '' END END - || ',' || E'\\n'; - END LOOP; - END IF; - IF bVerbose THEN RAISE INFO '(2)tabledef so far: %', v_table_ddl; END IF; - - -- define all the constraints: conparentid does not exist pre PGv11 - IF v_pgversion < 110000 THEN - FOR v_constraintrec IN - SELECT con.conname as constraint_name, con.contype as constraint_type, - CASE - WHEN con.contype = 'p' THEN 1 -- primary key constraint - WHEN con.contype = 'u' THEN 2 -- unique constraint - WHEN con.contype = 'f' THEN 3 -- foreign key constraint - WHEN con.contype = 'c' THEN 4 - ELSE 5 - END as type_rank, - pg_get_constraintdef(con.oid) as constraint_definition - FROM pg_catalog.pg_constraint con JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace - WHERE nsp.nspname = in_schema AND rel.relname = in_table ORDER BY type_rank - LOOP - IF v_constraintrec.type_rank = 1 THEN - v_primary := True; - IF pkcnt = 0 THEN - v_constraint_name := v_constraintrec.constraint_name; - v_constraint_def := v_constraintrec.constraint_definition; - ELSE - -- Issue#16 handle external PG def - v_constraint_name := v_constraintrec.constraint_name; - SELECT 'ALTER TABLE ONLY ' || in_schema || '.' || c.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' INTO v_pkey_def - FROM pg_catalog.pg_constraint r, pg_class c, pg_namespace n where r.conrelid = c.oid and r.contype = 'p' and n.oid = r.connamespace and n.nspname = in_schema AND c.relname = in_table; - END IF; - IF bPartition THEN - continue; - END IF; - ELSE - v_constraint_name := v_constraintrec.constraint_name; - v_constraint_def := v_constraintrec.constraint_definition; - END IF; - if bVerbose THEN RAISE INFO 'DEBUG4: constraint name=% constraint_def=%', v_constraint_name,v_constraint_def; END IF; - constraintarr := constraintarr || v_constraintrec.constraint_name:: text; - - IF fktype <> 'FKEYS_INTERNAL' AND v_constraintrec.constraint_type = 'f' THEN - continue; - END IF; - - IF pkcnt = 0 THEN - v_table_ddl := v_table_ddl || ' ' -- note: two char spacer to start, to indent the column - || 'CONSTRAINT' || ' ' - || v_constraint_name || ' ' - || v_constraint_def - || ',' || E'\\n'; - END IF; - END LOOP; - - ELSE - FOR v_constraintrec IN - SELECT con.conname as constraint_name, con.contype as constraint_type, - CASE - WHEN con.contype = 'p' THEN 1 -- primary key constraint - WHEN con.contype = 'u' THEN 2 -- unique constraint - WHEN con.contype = 'f' THEN 3 -- foreign key constraint - WHEN con.contype = 'c' THEN 4 - ELSE 5 - END as type_rank, - pg_get_constraintdef(con.oid) as constraint_definition - FROM pg_catalog.pg_constraint con JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace - WHERE nsp.nspname = in_schema AND rel.relname = in_table - --Issue#13 added this condition: - AND con.conparentid = 0 - ORDER BY type_rank - LOOP - IF v_constraintrec.type_rank = 1 THEN - v_primary := True; - IF pkcnt = 0 THEN - v_constraint_name := v_constraintrec.constraint_name; - v_constraint_def := v_constraintrec.constraint_definition; - ELSE - -- Issue#16 handle external PG def - v_constraint_name := v_constraintrec.constraint_name; - SELECT 'ALTER TABLE ONLY ' || in_schema || '.' || c.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' INTO v_pkey_def - FROM pg_catalog.pg_constraint r, pg_class c, pg_namespace n where r.conrelid = c.oid and r.contype = 'p' and n.oid = r.connamespace and n.nspname = in_schema AND c.relname = in_table; - END IF; - IF bPartition THEN - continue; - END IF; - ELSE - v_constraint_name := v_constraintrec.constraint_name; - v_constraint_def := v_constraintrec.constraint_definition; - END IF; - -- SELECT 'ALTER TABLE ONLY ' || c.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' as pkeyddl FROM pg_catalog.pg_constraint r, pg_class c, pg_namespace n where r.conrelid = c.oid and r.contype = 'p' and n.oid = r.connamespace and n.nspname = 'sample' AND c.relname = 'extensions_table'; - if bVerbose THEN RAISE INFO 'DEBUG4: constraint name=% constraint_def=%', v_constraint_name,v_constraint_def; END IF; - constraintarr := constraintarr || v_constraintrec.constraint_name:: text; - - IF fktype <> 'FKEYS_INTERNAL' AND v_constraintrec.constraint_type = 'f' THEN - continue; - END IF; - - IF pkcnt = 0 THEN - v_table_ddl := v_table_ddl || ' ' -- note: two char spacer to start, to indent the column - || 'CONSTRAINT' || ' ' - || v_constraint_name || ' ' - || v_constraint_def - || ',' || E'\\n'; - END IF; - END LOOP; - END IF; - IF bVerbose THEN RAISE INFO '(3)tabledef so far: %', v_table_ddl; END IF; - - -- drop the last comma before ending the create statement - v_table_ddl = substr(v_table_ddl, 0, length(v_table_ddl) - 1) || E'\\n'; - - -- --------------------------------------------------------------------------- - -- at this point we have everything up to the last table-enclosing parenthesis - -- --------------------------------------------------------------------------- - IF bVerbose THEN RAISE INFO '(4)tabledef so far: %', v_table_ddl; END IF; - - -- See if this is an inheritance-based child table and finish up the table create. - IF bPartition and bInheritance THEN - -- Issue#11: handle parent schema - -- v_table_ddl := v_table_ddl || ') INHERITS (' || in_schema || '.' || v_parent || ') ' || E'\\n' || v_relopts || ' ' || v_tablespace || ';' || E'\\n'; - IF v_parent_schema = '' OR v_parent_schema IS NULL THEN v_parent_schema = in_schema; END IF; - v_table_ddl := v_table_ddl || ') INHERITS (' || v_parent_schema || '.' || v_parent || ') ' || E'\\n' || v_relopts || ' ' || v_tablespace || ';' || E'\\n'; - END IF; - - IF v_pgversion >= 100000 AND NOT bPartition and NOT bInheritance THEN - -- See if this is a partitioned table (pg_class.relkind = 'p') and add the partitioned key - SELECT pg_get_partkeydef(c1.oid) as partition_key INTO v_partition_key FROM pg_class c1 JOIN pg_namespace n ON (n.oid = c1.relnamespace) LEFT JOIN pg_partitioned_table p ON (c1.oid = p.partrelid) - WHERE n.nspname = in_schema and n.oid = c1.relnamespace and c1.relname = in_table and c1.relkind = 'p'; - - IF v_partition_key IS NOT NULL AND v_partition_key <> '' THEN - -- add partition clause - -- NOTE: cannot specify default tablespace for partitioned relations - -- v_table_ddl := v_table_ddl || ') PARTITION BY ' || v_partition_key || ' ' || v_tablespace || ';' || E'\\n'; - v_table_ddl := v_table_ddl || ') PARTITION BY ' || v_partition_key || ';' || E'\\n'; - ELSEIF v_relopts <> '' THEN - v_table_ddl := v_table_ddl || ') ' || v_relopts || ' ' || v_tablespace || ';' || E'\\n'; - ELSE - -- end the create definition - v_table_ddl := v_table_ddl || ') ' || v_tablespace || ';' || E'\\n'; - END IF; - END IF; - - IF bVerbose THEN RAISE INFO '(5)tabledef so far: %', v_table_ddl; END IF; - - -- Add closing paren for regular tables - -- IF NOT bPartition THEN - -- v_table_ddl := v_table_ddl || ') ' || v_relopts || ' ' || v_tablespace || E';\\n'; - -- END IF; - -- RAISE NOTICE 'ddlsofar3: %', v_table_ddl; - - -- Issue#16 create the external PKEY def if indicated - IF v_pkey_def <> '' THEN - v_table_ddl := v_table_ddl || v_pkey_def || E'\\n'; - END IF; - - IF bVerbose THEN RAISE INFO '(6)tabledef so far: %', v_table_ddl; END IF; - - -- create indexes - FOR v_indexrec IN - SELECT indexdef, COALESCE(tablespace, 'pg_default') as tablespace, indexname FROM pg_indexes WHERE (schemaname, tablename) = (in_schema, in_table) - LOOP - -- RAISE INFO 'DEBUG6: indexname=%', v_indexrec.indexname; - -- loop through constraints and skip ones already defined - bSkip = False; - FOREACH constraintelement IN ARRAY constraintarr - LOOP - IF constraintelement = v_indexrec.indexname THEN - -- RAISE INFO 'DEBUG7: skipping index, %', v_indexrec.indexname; - bSkip = True; - EXIT; - END IF; - END LOOP; - if bSkip THEN CONTINUE; END IF; - - -- Add IF NOT EXISTS clause so partition index additions will not be created if declarative partition in effect and index already created on parent - v_indexrec.indexdef := REPLACE(v_indexrec.indexdef, 'CREATE INDEX', 'CREATE INDEX IF NOT EXISTS'); - -- RAISE INFO 'DEBUG8: adding index, %', v_indexrec.indexname; - - -- NOTE: cannot specify default tablespace for partitioned relations - IF v_partition_key IS NOT NULL AND v_partition_key <> '' THEN - v_table_ddl := v_table_ddl || v_indexrec.indexdef || ';' || E'\\n'; - ELSE - v_table_ddl := v_table_ddl || v_indexrec.indexdef || ' TABLESPACE ' || v_indexrec.tablespace || ';' || E'\\n'; - END IF; - - END LOOP; - IF bVerbose THEN RAISE INFO '(7)tabledef so far: %', v_table_ddl; END IF; - - -- Handle external foreign key defs here if applicable. - IF fktype = 'FKEYS_EXTERNAL' THEN - -- Issue#13 fix here too for conparentid = 0. and had to change to a loop to handle multiple return set, not a select into variable syntax. - -- Also had to account for PG V10 where there is no conparentid - IF v_pgversion < 110000 THEN - FOR v_constraintrec IN - SELECT 'ALTER TABLE ONLY ' || n.nspname || '.' || c2.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' as fkeydef - FROM pg_constraint r, pg_class c1, pg_namespace n, pg_class c2 where r.conrelid = c1.oid and r.contype = 'f' and n.nspname = in_schema and n.oid = r.connamespace and r.conrelid = c2.oid and c2.relname = in_table - LOOP - v_table_ddl := v_table_ddl || v_constraintrec.fkeydef || ';' || E'\\n'; - IF bVerbose THEN RAISE INFO 'keydef = %', v_constraintrec.fkeydef; END IF; - END LOOP; - ELSE - FOR v_constraintrec IN - SELECT 'ALTER TABLE ONLY ' || n.nspname || '.' || c2.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' as fkeydef - FROM pg_constraint r, pg_class c1, pg_namespace n, pg_class c2 where r.conrelid = c1.oid and r.contype = 'f' and n.nspname = in_schema and n.oid = r.connamespace and r.conrelid = c2.oid and c2.relname = in_table and r.conparentid = 0 - LOOP - v_table_ddl := v_table_ddl || v_constraintrec.fkeydef || E'\\n'; - IF bVerbose THEN RAISE INFO 'keydef = %', v_constraintrec.fkeydef; END IF; - END LOOP; - END IF; - - ELSIF fktype = 'FKEYS_COMMENTED' THEN - SELECT '-- ALTER TABLE ONLY ' || n.nspname || '.' || c2.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' into v_fkey_defs - FROM pg_constraint r, pg_class c1, pg_namespace n, pg_class c2 where r.conrelid = c1.oid and r.contype = 'f' and n.nspname = in_schema and n.oid = r.connamespace and r.conrelid = c2.oid and c2.relname = in_table; - IF v_fkey_defs IS NOT NULL THEN - v_table_ddl := v_table_ddl || v_fkey_defs; - END IF; - END IF; - IF bVerbose THEN RAISE INFO '(8)tabledef so far: %', v_table_ddl; END IF; - - IF trigtype = 'INCLUDE_TRIGGERS' THEN - -- Issue#14: handle multiple triggers for a table - FOR v_trigrec IN - select pg_get_triggerdef(t.oid, True) || ';' as triggerdef FROM pg_trigger t, pg_class c, pg_namespace n - WHERE n.nspname = in_schema and n.oid = c.relnamespace and c.relname = in_table and c.relkind = 'r' and t.tgrelid = c.oid and NOT t.tgisinternal - LOOP - v_table_ddl := v_table_ddl || v_trigrec.triggerdef; - v_table_ddl := v_table_ddl || E'\\n'; - IF bVerbose THEN RAISE INFO 'triggerdef = %', v_trigrec.triggerdef; END IF; - END LOOP; - END IF; - - -- add empty line - v_table_ddl := v_table_ddl || E'\\n'; - - RETURN v_table_ddl; - - EXCEPTION - WHEN others THEN - BEGIN - GET STACKED DIAGNOSTICS v_diag1 = MESSAGE_TEXT, v_diag2 = PG_EXCEPTION_DETAIL, v_diag3 = PG_EXCEPTION_HINT, v_diag4 = RETURNED_SQLSTATE, v_diag5 = PG_CONTEXT, v_diag6 = PG_EXCEPTION_CONTEXT; - -- v_ret := 'line=' || v_diag6 || '. '|| v_diag4 || '. ' || v_diag1 || ' .' || v_diag2 || ' .' || v_diag3; - v_ret := 'line=' || v_diag6 || '. '|| v_diag4 || '. ' || v_diag1; - RAISE EXCEPTION '%', v_ret; - -- put additional coding here if necessarY - RETURN ''; - END; - - END; - $$;`, - { compress: true, removeAll: true } -) diff --git a/apps/studio/data/database/database-table-definition.ts b/apps/studio/data/database/database-table-definition.ts new file mode 100644 index 00000000000..bc968581287 --- /dev/null +++ b/apps/studio/data/database/database-table-definition.ts @@ -0,0 +1,569 @@ +import minify from 'pg-minify' + +// Derived from https://github.com/MichaelDBA/pg_get_tabledef +// NOTE: when updating, \n must be replaced with \\n in the SQL below + +export const CREATE_PG_GET_TABLEDEF_SQL = minify( + /* SQL */ ` + DROP TYPE IF EXISTS pg_temp.tabledefs CASCADE; + CREATE TYPE pg_temp.tabledefs AS ENUM ('PKEY_INTERNAL','PKEY_EXTERNAL','FKEYS_INTERNAL', 'FKEYS_EXTERNAL', 'FKEYS_COMMENTED', 'FKEYS_NONE', 'INCLUDE_TRIGGERS', 'NO_TRIGGERS'); + + -- DROP FUNCTION pg_temp.pg_get_coldef(text,text,text,boolean); + CREATE OR REPLACE FUNCTION pg_temp.pg_get_coldef( + in_schema text, + in_table text, + in_column text, + oldway boolean default False + ) + RETURNS text + LANGUAGE plpgsql VOLATILE + AS + $$ + DECLARE + coldef text; + BEGIN + IF oldway THEN + SELECT pg_catalog.format_type(a.atttypid, a.atttypmod) INTO coldef FROM pg_namespace n, pg_class c, pg_attribute a, pg_type t + WHERE n.nspname = in_schema AND n.oid = c.relnamespace AND c.relname = in_table AND a.attname = in_column and a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid ORDER BY a.attnum; + ELSE + -- a.attrelid::regclass::text, a.attname + SELECT CASE WHEN a.atttypid = ANY ('{int,int8,int2}'::regtype[]) AND EXISTS (SELECT FROM pg_attrdef ad WHERE ad.adrelid = a.attrelid AND ad.adnum = a.attnum AND + pg_get_expr(ad.adbin, ad.adrelid) = 'nextval(''' || (pg_get_serial_sequence (a.attrelid::regclass::text, a.attname))::regclass || '''::regclass)') THEN CASE a.atttypid + WHEN 'int'::regtype THEN 'serial' WHEN 'int8'::regtype THEN 'bigserial' WHEN 'int2'::regtype THEN 'smallserial' END ELSE format_type(a.atttypid, a.atttypmod) END AS data_type + INTO coldef FROM pg_namespace n, pg_class c, pg_attribute a, pg_type t + WHERE n.nspname = in_schema AND n.oid = c.relnamespace AND c.relname = in_table AND a.attname = in_column and a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid ORDER BY a.attnum; + END IF; + RETURN coldef; + END; + $$; + + -- SELECT * FROM pg_temp.pg_get_tabledef('sample', 'address', false); + DROP FUNCTION IF EXISTS pg_temp.pg_get_tabledef(character varying,character varying,boolean,tabledefs[]); + CREATE OR REPLACE FUNCTION pg_temp.pg_get_tabledef( + in_schema varchar, + in_table varchar, + _verbose boolean, + VARIADIC arr pg_temp.tabledefs[] DEFAULT '{}':: pg_temp.tabledefs[] + ) + RETURNS text + LANGUAGE plpgsql VOLATILE + AS + $$ + DECLARE + v_qualified text := ''; + v_table_ddl text; + v_table_oid int; + v_colrec record; + v_constraintrec record; + v_trigrec record; + v_indexrec record; + v_primary boolean := False; + v_constraint_name text; + v_constraint_def text; + v_pkey_def text := ''; + v_fkey_defs text; + v_trigger text := ''; + v_partition_key text := ''; + v_partbound text; + v_parent text; + v_parent_schema text; + v_persist text; + v_temp text := ''; + v_relopts text; + v_tablespace text; + v_pgversion int; + bSerial boolean; + bPartition boolean; + bInheritance boolean; + bRelispartition boolean; + constraintarr text[] := '{}'; + constraintelement text; + bSkip boolean; + bVerbose boolean := False; + v_cnt1 integer; + v_cnt2 integer; + + -- assume defaults for ENUMs at the getgo + pkcnt int := 0; + fkcnt int := 0; + trigcnt int := 0; + pktype tabledefs := 'PKEY_INTERNAL'; + fktype tabledefs := 'FKEYS_INTERNAL'; + trigtype tabledefs := 'NO_TRIGGERS'; + arglen integer; + vargs text; + avarg tabledefs; + + -- exception variables + v_ret text; + v_diag1 text; + v_diag2 text; + v_diag3 text; + v_diag4 text; + v_diag5 text; + v_diag6 text; + + BEGIN + SET client_min_messages = 'notice'; + IF _verbose THEN bVerbose = True; END IF; + + -- v17 fix: handle case-sensitive + -- v_qualified = in_schema || '.' || in_table; + + arglen := array_length($4, 1); + IF arglen IS NULL THEN + -- nothing to do, so assume defaults + NULL; + ELSE + -- loop thru args + -- IF 'NO_TRIGGERS' = ANY ($4) + -- select array_to_string($4, ',', '***') INTO vargs; + IF bVerbose THEN RAISE NOTICE 'arguments=%', $4; END IF; + FOREACH avarg IN ARRAY $4 LOOP + IF bVerbose THEN RAISE INFO 'arg=%', avarg; END IF; + IF avarg = 'FKEYS_INTERNAL' OR avarg = 'FKEYS_EXTERNAL' OR avarg = 'FKEYS_COMMENTED' THEN + fkcnt = fkcnt + 1; + fktype = avarg; + ELSEIF avarg = 'INCLUDE_TRIGGERS' OR avarg = 'NO_TRIGGERS' THEN + trigcnt = trigcnt + 1; + trigtype = avarg; + ELSEIF avarg = 'PKEY_EXTERNAL' THEN + pkcnt = pkcnt + 1; + pktype = avarg; + END IF; + END LOOP; + IF fkcnt > 1 THEN + RAISE WARNING 'Only one foreign key option can be provided. You provided %', fkcnt; + RETURN ''; + ELSEIF trigcnt > 1 THEN + RAISE WARNING 'Only one trigger option can be provided. You provided %', trigcnt; + RETURN ''; + ELSEIF pkcnt > 1 THEN + RAISE WARNING 'Only one pkey option can be provided. You provided %', pkcnt; + RETURN ''; + END IF; + END IF; + + SELECT c.oid, (select setting from pg_settings where name = 'server_version_num') INTO v_table_oid, v_pgversion FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind in ('r','p') AND c.relname = in_table AND n.nspname = in_schema; + + -- throw an error if table was not found + IF (v_table_oid IS NULL) THEN + RAISE EXCEPTION 'table does not exist'; + END IF; + + -- get user-defined tablespaces if applicable + SELECT tablespace INTO v_temp FROM pg_tables WHERE schemaname = in_schema and tablename = in_table and tablespace IS NOT NULL; + IF v_temp IS NULL THEN + v_tablespace := 'TABLESPACE pg_default'; + ELSE + v_tablespace := 'TABLESPACE ' || v_temp; + END IF; + + -- also see if there are any SET commands for this table, ie, autovacuum_enabled=off, fillfactor=70 + WITH relopts AS (SELECT unnest(c.reloptions) relopts FROM pg_class c, pg_namespace n WHERE n.nspname = in_schema and n.oid = c.relnamespace and c.relname = in_table) + SELECT string_agg(r.relopts, ', ') as relopts INTO v_temp from relopts r; + IF v_temp IS NULL THEN + v_relopts := ''; + ELSE + v_relopts := ' WITH (' || v_temp || ')'; + END IF; + + -- ----------------------------------------------------------------------------------- + -- Create table defs for partitions/children using inheritance or declarative methods. + -- inheritance: pg_class.relkind = 'r' pg_class.relispartition=false pg_class.relpartbound is NULL + -- declarative: pg_class.relkind = 'r' pg_class.relispartition=true pg_class.relpartbound is NOT NULL + -- ----------------------------------------------------------------------------------- + v_partbound := ''; + bPartition := False; + bInheritance := False; + IF v_pgversion < 100000 THEN + -- Issue#11: handle parent schema + SELECT c2.relname parent, c2.relnamespace::regnamespace INTO v_parent, v_parent_schema from pg_class c1, pg_namespace n, pg_inherits i, pg_class c2 + WHERE n.nspname = in_schema and n.oid = c1.relnamespace and c1.relname = in_table and c1.oid = i.inhrelid and i.inhparent = c2.oid and c1.relkind = 'r'; + IF (v_parent IS NOT NULL) THEN + bPartition := True; + bInheritance := True; + END IF; + ELSE + -- Issue#11: handle parent schema + SELECT c2.relname parent, c1.relispartition, pg_get_expr(c1.relpartbound, c1.oid, true), c2.relnamespace::regnamespace INTO v_parent, bRelispartition, v_partbound, v_parent_schema from pg_class c1, pg_namespace n, pg_inherits i, pg_class c2 + WHERE n.nspname = in_schema and n.oid = c1.relnamespace and c1.relname = in_table and c1.oid = i.inhrelid and i.inhparent = c2.oid and c1.relkind = 'r'; + IF (v_parent IS NOT NULL) THEN + bPartition := True; + IF bRelispartition THEN + bInheritance := False; + ELSE + bInheritance := True; + END IF; + END IF; + END IF; + IF bPartition THEN + --Issue#17 fix for case-sensitive tables + -- SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s + -- WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = quote_ident(in_schema) AND t.table_name = quote_ident(in_table) AND t.table_type = 'BASE TABLE'); + SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s + WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = in_schema AND t.table_name = in_table AND t.table_type = 'BASE TABLE'); + + --Issue#19 put double-quotes around SQL keyword column names + SELECT COUNT(*) INTO v_cnt2 FROM pg_get_keywords() WHERE word = v_colrec.column_name AND catcode = 'R'; + + IF bInheritance THEN + -- inheritance-based + IF v_cnt1 > 0 OR v_cnt2 > 0 THEN + v_table_ddl := 'CREATE TABLE ' || in_schema || '."' || in_table || '"( '|| E'\\n'; + ELSE + v_table_ddl := 'CREATE TABLE ' || in_schema || '.' || in_table || '( '|| E'\\n'; + END IF; + + -- Jump to constraints section to add the check constraints + ELSE + -- declarative-based + IF v_relopts <> '' THEN + IF v_cnt1 > 0 OR v_cnt2 > 0 THEN + v_table_ddl := 'CREATE TABLE ' || in_schema || '."' || in_table || '" PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || v_relopts || ' ' || v_tablespace || '; ' || E'\\n'; + ELSE + v_table_ddl := 'CREATE TABLE ' || in_schema || '.' || in_table || ' PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || v_relopts || ' ' || v_tablespace || '; ' || E'\\n'; + END IF; + ELSE + IF v_cnt1 > 0 OR v_cnt2 > 0 THEN + v_table_ddl := 'CREATE TABLE ' || in_schema || '."' || in_table || '" PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || ' ' || v_tablespace || '; ' || E'\\n'; + ELSE + v_table_ddl := 'CREATE TABLE ' || in_schema || '.' || in_table || ' PARTITION OF ' || in_schema || '.' || v_parent || ' ' || v_partbound || ' ' || v_tablespace || '; ' || E'\\n'; + END IF; + END IF; + -- Jump to constraints and index section to add the check constraints and indexes and perhaps FKeys + END IF; + END IF; + IF bVerbose THEN RAISE INFO '(1)tabledef so far: %', v_table_ddl; END IF; + + IF NOT bPartition THEN + -- see if this is unlogged or temporary table + select c.relpersistence into v_persist from pg_class c, pg_namespace n where n.nspname = in_schema and n.oid = c.relnamespace and c.relname = in_table and c.relkind = 'r'; + IF v_persist = 'u' THEN + v_temp := 'UNLOGGED'; + ELSIF v_persist = 't' THEN + v_temp := 'TEMPORARY'; + ELSE + v_temp := ''; + END IF; + END IF; + + -- start the create definition for regular tables unless we are in progress creating an inheritance-based child table + IF NOT bPartition THEN + --Issue#17 fix for case-sensitive tables + -- SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s + -- WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = quote_ident(in_schema) AND t.table_name = quote_ident(in_table) AND t.table_type = 'BASE TABLE'); + SELECT count(*) INTO v_cnt1 FROM information_schema.tables t WHERE EXISTS (SELECT REGEXP_MATCHES(s.table_name, '([A-Z]+)','g') FROM information_schema.tables s + WHERE t.table_schema=s.table_schema AND t.table_name=s.table_name AND t.table_schema = in_schema AND t.table_name = in_table AND t.table_type = 'BASE TABLE'); + IF v_cnt1 > 0 THEN + v_table_ddl := 'CREATE ' || v_temp || ' TABLE ' || in_schema || '."' || in_table || '" (' || E'\\n'; + ELSE + v_table_ddl := 'CREATE ' || v_temp || ' TABLE ' || in_schema || '.' || in_table || ' (' || E'\\n'; + END IF; + END IF; + -- RAISE INFO 'DEBUG2: tabledef so far: %', v_table_ddl; + -- define all of the columns in the table unless we are in progress creating an inheritance-based child table + IF NOT bPartition THEN + FOR v_colrec IN + SELECT c.column_name, c.data_type, c.udt_name, c.udt_schema, c.character_maximum_length, c.is_nullable, c.column_default, c.numeric_precision, c.numeric_scale, c.is_identity, c.identity_generation + FROM information_schema.columns c WHERE (table_schema, table_name) = (in_schema, in_table) ORDER BY ordinal_position + LOOP + IF bVerbose THEN RAISE INFO '(col loop) name=% type=% udt_name=% udt_schema=%', v_colrec.column_name, v_colrec.data_type, v_colrec.udt_name, v_colrec.udt_schema; END IF; + -- v17 fix: handle case-sensitive for pg_get_serial_sequence that requires SQL Identifier handling + -- SELECT CASE WHEN pg_get_serial_sequence(v_qualified, v_colrec.column_name) IS NOT NULL THEN True ELSE False END into bSerial; + SELECT CASE WHEN pg_get_serial_sequence(quote_ident(in_schema) || '.' || quote_ident(in_table), v_colrec.column_name) IS NOT NULL THEN True ELSE False END into bSerial; + IF bVerbose THEN + -- v17 fix: handle case-sensitive for pg_get_serial_sequence that requires SQL Identifier handling + -- SELECT pg_get_serial_sequence(v_qualified, v_colrec.column_name) into v_temp; + SELECT pg_get_serial_sequence(quote_ident(in_schema) || '.' || quote_ident(in_table), v_colrec.column_name) into v_temp; + IF v_temp IS NULL THEN v_temp = 'NA'; END IF; + SELECT pg_temp.pg_get_coldef(in_schema, in_table,v_colrec.column_name) INTO v_diag1; + --RAISE NOTICE 'DEBUG table: % Column: % datatype: % Serial=% serialval=% coldef=%', v_qualified, v_colrec.column_name, v_colrec.data_type, bSerial, v_temp, v_diag1; + --RAISE NOTICE 'DEBUG tabledef: %', v_table_ddl; + END IF; + + --Issue#17 put double-quotes around case-sensitive column names + SELECT COUNT(*) INTO v_cnt1 FROM information_schema.columns t WHERE EXISTS (SELECT REGEXP_MATCHES(s.column_name, '([A-Z]+)','g') FROM information_schema.columns s + WHERE t.table_schema=s.table_schema and t.table_name=s.table_name and t.column_name=s.column_name AND t.table_schema = quote_ident(in_schema) AND column_name = v_colrec.column_name); + + --Issue#19 put double-quotes around SQL keyword column names + SELECT COUNT(*) INTO v_cnt2 FROM pg_get_keywords() WHERE word = v_colrec.column_name AND catcode = 'R'; + + IF v_cnt1 > 0 OR v_cnt2 > 0 THEN + v_table_ddl := v_table_ddl || ' "' || v_colrec.column_name || '" '; + ELSE + v_table_ddl := v_table_ddl || ' ' || v_colrec.column_name || ' '; + END IF; + + v_table_ddl := v_table_ddl || + CASE WHEN v_colrec.udt_name in ('geometry', 'box2d', 'box2df', 'box3d', 'geography', 'geometry_dump', 'gidx', 'spheroid', 'valid_detail') + THEN v_colrec.udt_name + WHEN v_colrec.data_type = 'USER-DEFINED' + THEN v_colrec.udt_schema || '.' || v_colrec.udt_name + WHEN v_colrec.data_type = 'ARRAY' + -- Issue#6 fix: handle arrays + THEN pg_temp.pg_get_coldef(in_schema, in_table,v_colrec.column_name) + -- v17 fix: handle case-sensitive for pg_get_serial_sequence that requires SQL Identifier handling + -- WHEN pg_get_serial_sequence(v_qualified, v_colrec.column_name) IS NOT NULL + WHEN pg_get_serial_sequence(quote_ident(in_schema) || '.' || quote_ident(in_table), v_colrec.column_name) IS NOT NULL + -- Issue#8 fix: handle serial. Note: NOT NULL is implied so no need to declare it explicitly + THEN pg_temp.pg_get_coldef(in_schema, in_table,v_colrec.column_name) + ELSE v_colrec.data_type END + || CASE WHEN v_colrec.is_identity = 'YES' THEN CASE WHEN v_colrec.identity_generation = 'ALWAYS' THEN ' GENERATED ALWAYS AS IDENTITY' ELSE ' GENERATED BY DEFAULT AS IDENTITY' END ELSE '' END + || CASE WHEN v_colrec.character_maximum_length IS NOT NULL THEN ('(' || v_colrec.character_maximum_length || ')') + WHEN v_colrec.numeric_precision > 0 AND v_colrec.numeric_scale > 0 THEN '(' || v_colrec.numeric_precision || ',' || v_colrec.numeric_scale || ')' + ELSE '' END || ' ' + || CASE WHEN bSerial THEN '' ELSE CASE WHEN v_colrec.is_nullable = 'NO' THEN 'NOT NULL' ELSE 'NULL' END END + || CASE WHEN bSerial THEN '' ELSE CASE WHEN v_colrec.column_default IS NOT null THEN (' DEFAULT ' || v_colrec.column_default) ELSE '' END END + || ',' || E'\\n'; + END LOOP; + END IF; + IF bVerbose THEN RAISE INFO '(2)tabledef so far: %', v_table_ddl; END IF; + + -- define all the constraints: conparentid does not exist pre PGv11 + IF v_pgversion < 110000 THEN + FOR v_constraintrec IN + SELECT con.conname as constraint_name, con.contype as constraint_type, + CASE + WHEN con.contype = 'p' THEN 1 -- primary key constraint + WHEN con.contype = 'u' THEN 2 -- unique constraint + WHEN con.contype = 'f' THEN 3 -- foreign key constraint + WHEN con.contype = 'c' THEN 4 + ELSE 5 + END as type_rank, + pg_get_constraintdef(con.oid) as constraint_definition + FROM pg_catalog.pg_constraint con JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace + WHERE nsp.nspname = in_schema AND rel.relname = in_table ORDER BY type_rank + LOOP + IF v_constraintrec.type_rank = 1 THEN + v_primary := True; + IF pkcnt = 0 THEN + v_constraint_name := v_constraintrec.constraint_name; + v_constraint_def := v_constraintrec.constraint_definition; + ELSE + -- Issue#16 handle external PG def + v_constraint_name := v_constraintrec.constraint_name; + SELECT 'ALTER TABLE ONLY ' || in_schema || '.' || c.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' INTO v_pkey_def + FROM pg_catalog.pg_constraint r, pg_class c, pg_namespace n where r.conrelid = c.oid and r.contype = 'p' and n.oid = r.connamespace and n.nspname = in_schema AND c.relname = in_table; + END IF; + IF bPartition THEN + continue; + END IF; + ELSE + v_constraint_name := v_constraintrec.constraint_name; + v_constraint_def := v_constraintrec.constraint_definition; + END IF; + if bVerbose THEN RAISE INFO 'DEBUG4: constraint name=% constraint_def=%', v_constraint_name,v_constraint_def; END IF; + constraintarr := constraintarr || v_constraintrec.constraint_name:: text; + + IF fktype <> 'FKEYS_INTERNAL' AND v_constraintrec.constraint_type = 'f' THEN + continue; + END IF; + + IF pkcnt = 0 THEN + v_table_ddl := v_table_ddl || ' ' -- note: two char spacer to start, to indent the column + || 'CONSTRAINT' || ' ' + || v_constraint_name || ' ' + || v_constraint_def + || ',' || E'\\n'; + END IF; + END LOOP; + + ELSE + FOR v_constraintrec IN + SELECT con.conname as constraint_name, con.contype as constraint_type, + CASE + WHEN con.contype = 'p' THEN 1 -- primary key constraint + WHEN con.contype = 'u' THEN 2 -- unique constraint + WHEN con.contype = 'f' THEN 3 -- foreign key constraint + WHEN con.contype = 'c' THEN 4 + ELSE 5 + END as type_rank, + pg_get_constraintdef(con.oid) as constraint_definition + FROM pg_catalog.pg_constraint con JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace + WHERE nsp.nspname = in_schema AND rel.relname = in_table + --Issue#13 added this condition: + AND con.conparentid = 0 + ORDER BY type_rank + LOOP + IF v_constraintrec.type_rank = 1 THEN + v_primary := True; + IF pkcnt = 0 THEN + v_constraint_name := v_constraintrec.constraint_name; + v_constraint_def := v_constraintrec.constraint_definition; + ELSE + -- Issue#16 handle external PG def + v_constraint_name := v_constraintrec.constraint_name; + SELECT 'ALTER TABLE ONLY ' || in_schema || '.' || c.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' INTO v_pkey_def + FROM pg_catalog.pg_constraint r, pg_class c, pg_namespace n where r.conrelid = c.oid and r.contype = 'p' and n.oid = r.connamespace and n.nspname = in_schema AND c.relname = in_table; + END IF; + IF bPartition THEN + continue; + END IF; + ELSE + v_constraint_name := v_constraintrec.constraint_name; + v_constraint_def := v_constraintrec.constraint_definition; + END IF; + -- SELECT 'ALTER TABLE ONLY ' || c.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' as pkeyddl FROM pg_catalog.pg_constraint r, pg_class c, pg_namespace n where r.conrelid = c.oid and r.contype = 'p' and n.oid = r.connamespace and n.nspname = 'sample' AND c.relname = 'extensions_table'; + if bVerbose THEN RAISE INFO 'DEBUG4: constraint name=% constraint_def=%', v_constraint_name,v_constraint_def; END IF; + constraintarr := constraintarr || v_constraintrec.constraint_name:: text; + + IF fktype <> 'FKEYS_INTERNAL' AND v_constraintrec.constraint_type = 'f' THEN + continue; + END IF; + + IF pkcnt = 0 THEN + v_table_ddl := v_table_ddl || ' ' -- note: two char spacer to start, to indent the column + || 'CONSTRAINT' || ' ' + || v_constraint_name || ' ' + || v_constraint_def + || ',' || E'\\n'; + END IF; + END LOOP; + END IF; + IF bVerbose THEN RAISE INFO '(3)tabledef so far: %', v_table_ddl; END IF; + + -- drop the last comma before ending the create statement + v_table_ddl = substr(v_table_ddl, 0, length(v_table_ddl) - 1) || E'\\n'; + + -- --------------------------------------------------------------------------- + -- at this point we have everything up to the last table-enclosing parenthesis + -- --------------------------------------------------------------------------- + IF bVerbose THEN RAISE INFO '(4)tabledef so far: %', v_table_ddl; END IF; + + -- See if this is an inheritance-based child table and finish up the table create. + IF bPartition and bInheritance THEN + -- Issue#11: handle parent schema + -- v_table_ddl := v_table_ddl || ') INHERITS (' || in_schema || '.' || v_parent || ') ' || E'\\n' || v_relopts || ' ' || v_tablespace || ';' || E'\\n'; + IF v_parent_schema = '' OR v_parent_schema IS NULL THEN v_parent_schema = in_schema; END IF; + v_table_ddl := v_table_ddl || ') INHERITS (' || v_parent_schema || '.' || v_parent || ') ' || E'\\n' || v_relopts || ' ' || v_tablespace || ';' || E'\\n'; + END IF; + + IF v_pgversion >= 100000 AND NOT bPartition and NOT bInheritance THEN + -- See if this is a partitioned table (pg_class.relkind = 'p') and add the partitioned key + SELECT pg_get_partkeydef(c1.oid) as partition_key INTO v_partition_key FROM pg_class c1 JOIN pg_namespace n ON (n.oid = c1.relnamespace) LEFT JOIN pg_partitioned_table p ON (c1.oid = p.partrelid) + WHERE n.nspname = in_schema and n.oid = c1.relnamespace and c1.relname = in_table and c1.relkind = 'p'; + + IF v_partition_key IS NOT NULL AND v_partition_key <> '' THEN + -- add partition clause + -- NOTE: cannot specify default tablespace for partitioned relations + -- v_table_ddl := v_table_ddl || ') PARTITION BY ' || v_partition_key || ' ' || v_tablespace || ';' || E'\\n'; + v_table_ddl := v_table_ddl || ') PARTITION BY ' || v_partition_key || ';' || E'\\n'; + ELSEIF v_relopts <> '' THEN + v_table_ddl := v_table_ddl || ') ' || v_relopts || ' ' || v_tablespace || ';' || E'\\n'; + ELSE + -- end the create definition + v_table_ddl := v_table_ddl || ') ' || v_tablespace || ';' || E'\\n'; + END IF; + END IF; + + IF bVerbose THEN RAISE INFO '(5)tabledef so far: %', v_table_ddl; END IF; + + -- Add closing paren for regular tables + -- IF NOT bPartition THEN + -- v_table_ddl := v_table_ddl || ') ' || v_relopts || ' ' || v_tablespace || E';\\n'; + -- END IF; + -- RAISE NOTICE 'ddlsofar3: %', v_table_ddl; + + -- Issue#16 create the external PKEY def if indicated + IF v_pkey_def <> '' THEN + v_table_ddl := v_table_ddl || v_pkey_def || E'\\n'; + END IF; + + IF bVerbose THEN RAISE INFO '(6)tabledef so far: %', v_table_ddl; END IF; + + -- create indexes + FOR v_indexrec IN + SELECT indexdef, COALESCE(tablespace, 'pg_default') as tablespace, indexname FROM pg_indexes WHERE (schemaname, tablename) = (in_schema, in_table) + LOOP + -- RAISE INFO 'DEBUG6: indexname=%', v_indexrec.indexname; + -- loop through constraints and skip ones already defined + bSkip = False; + FOREACH constraintelement IN ARRAY constraintarr + LOOP + IF constraintelement = v_indexrec.indexname THEN + -- RAISE INFO 'DEBUG7: skipping index, %', v_indexrec.indexname; + bSkip = True; + EXIT; + END IF; + END LOOP; + if bSkip THEN CONTINUE; END IF; + + -- Add IF NOT EXISTS clause so partition index additions will not be created if declarative partition in effect and index already created on parent + v_indexrec.indexdef := REPLACE(v_indexrec.indexdef, 'CREATE INDEX', 'CREATE INDEX IF NOT EXISTS'); + -- RAISE INFO 'DEBUG8: adding index, %', v_indexrec.indexname; + + -- NOTE: cannot specify default tablespace for partitioned relations + IF v_partition_key IS NOT NULL AND v_partition_key <> '' THEN + v_table_ddl := v_table_ddl || v_indexrec.indexdef || ';' || E'\\n'; + ELSE + v_table_ddl := v_table_ddl || v_indexrec.indexdef || ' TABLESPACE ' || v_indexrec.tablespace || ';' || E'\\n'; + END IF; + + END LOOP; + IF bVerbose THEN RAISE INFO '(7)tabledef so far: %', v_table_ddl; END IF; + + -- Handle external foreign key defs here if applicable. + IF fktype = 'FKEYS_EXTERNAL' THEN + -- Issue#13 fix here too for conparentid = 0. and had to change to a loop to handle multiple return set, not a select into variable syntax. + -- Also had to account for PG V10 where there is no conparentid + IF v_pgversion < 110000 THEN + FOR v_constraintrec IN + SELECT 'ALTER TABLE ONLY ' || n.nspname || '.' || c2.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' as fkeydef + FROM pg_constraint r, pg_class c1, pg_namespace n, pg_class c2 where r.conrelid = c1.oid and r.contype = 'f' and n.nspname = in_schema and n.oid = r.connamespace and r.conrelid = c2.oid and c2.relname = in_table + LOOP + v_table_ddl := v_table_ddl || v_constraintrec.fkeydef || ';' || E'\\n'; + IF bVerbose THEN RAISE INFO 'keydef = %', v_constraintrec.fkeydef; END IF; + END LOOP; + ELSE + FOR v_constraintrec IN + SELECT 'ALTER TABLE ONLY ' || n.nspname || '.' || c2.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' as fkeydef + FROM pg_constraint r, pg_class c1, pg_namespace n, pg_class c2 where r.conrelid = c1.oid and r.contype = 'f' and n.nspname = in_schema and n.oid = r.connamespace and r.conrelid = c2.oid and c2.relname = in_table and r.conparentid = 0 + LOOP + v_table_ddl := v_table_ddl || v_constraintrec.fkeydef || E'\\n'; + IF bVerbose THEN RAISE INFO 'keydef = %', v_constraintrec.fkeydef; END IF; + END LOOP; + END IF; + + ELSIF fktype = 'FKEYS_COMMENTED' THEN + SELECT '-- ALTER TABLE ONLY ' || n.nspname || '.' || c2.relname || ' ADD CONSTRAINT ' || r.conname || ' ' || pg_catalog.pg_get_constraintdef(r.oid, true) || ';' into v_fkey_defs + FROM pg_constraint r, pg_class c1, pg_namespace n, pg_class c2 where r.conrelid = c1.oid and r.contype = 'f' and n.nspname = in_schema and n.oid = r.connamespace and r.conrelid = c2.oid and c2.relname = in_table; + IF v_fkey_defs IS NOT NULL THEN + v_table_ddl := v_table_ddl || v_fkey_defs; + END IF; + END IF; + IF bVerbose THEN RAISE INFO '(8)tabledef so far: %', v_table_ddl; END IF; + + IF trigtype = 'INCLUDE_TRIGGERS' THEN + -- Issue#14: handle multiple triggers for a table + FOR v_trigrec IN + select pg_get_triggerdef(t.oid, True) || ';' as triggerdef FROM pg_trigger t, pg_class c, pg_namespace n + WHERE n.nspname = in_schema and n.oid = c.relnamespace and c.relname = in_table and c.relkind = 'r' and t.tgrelid = c.oid and NOT t.tgisinternal + LOOP + v_table_ddl := v_table_ddl || v_trigrec.triggerdef; + v_table_ddl := v_table_ddl || E'\\n'; + IF bVerbose THEN RAISE INFO 'triggerdef = %', v_trigrec.triggerdef; END IF; + END LOOP; + END IF; + + -- add empty line + v_table_ddl := v_table_ddl || E'\\n'; + + RETURN v_table_ddl; + + EXCEPTION + WHEN others THEN + BEGIN + GET STACKED DIAGNOSTICS v_diag1 = MESSAGE_TEXT, v_diag2 = PG_EXCEPTION_DETAIL, v_diag3 = PG_EXCEPTION_HINT, v_diag4 = RETURNED_SQLSTATE, v_diag5 = PG_CONTEXT, v_diag6 = PG_EXCEPTION_CONTEXT; + -- v_ret := 'line=' || v_diag6 || '. '|| v_diag4 || '. ' || v_diag1 || ' .' || v_diag2 || ' .' || v_diag3; + v_ret := 'line=' || v_diag6 || '. '|| v_diag4 || '. ' || v_diag1; + RAISE EXCEPTION '%', v_ret; + -- put additional coding here if necessarY + RETURN ''; + END; + + END; + $$;`, + { compress: true, removeAll: true } +) diff --git a/apps/studio/lib/helpers.ts b/apps/studio/lib/helpers.ts index b09b1829750..b84febda2d2 100644 --- a/apps/studio/lib/helpers.ts +++ b/apps/studio/lib/helpers.ts @@ -1,7 +1,5 @@ -import { post } from 'lib/common/fetch' -import { API_URL, DEFAULT_MINIMUM_PASSWORD_STRENGTH, PASSWORD_STRENGTH } from 'lib/constants' -import { toast } from 'react-hot-toast' -import { v4 as _uuidV4 } from 'uuid' +export { default as passwordStrength } from './password-strength' +export { default as uuidv4 } from './uuid' export const tryParseJson = (jsonString: any) => { try { @@ -50,10 +48,6 @@ export const removeJSONTrailingComma = (jsonString: string) => { return jsonString.replace(/,\s*(?=[\}\]])/g, '') } -export const uuidv4 = () => { - return _uuidV4() -} - export const timeout = (ms: number) => { return new Promise((resolve) => setTimeout(resolve, ms)) } @@ -163,49 +157,6 @@ export const copyToClipboard = async (str: string | Promise, callback = } } -export async function passwordStrength(value: string) { - let message: string = '' - let warning: string = '' - let strength: number = 0 - - if (value && value !== '') { - if (value.length > 99) { - message = `${PASSWORD_STRENGTH[0]} Maximum length of password exceeded` - warning = `Password should be less than 100 characters` - } else { - // [Joshen] Unable to use RQ atm due to our Jest tests being in JS - const response = await post(`${API_URL}/profile/password-check`, { password: value }) - if (!response.error) { - const { result } = response - const resultScore = result?.score ?? 0 - - const score = (PASSWORD_STRENGTH as any)[resultScore] - const suggestions = result.feedback?.suggestions - ? result.feedback.suggestions.join(' ') - : '' - - message = `${score} ${suggestions}` - strength = resultScore - - // warning message for anything below 4 strength :string - if (resultScore < DEFAULT_MINIMUM_PASSWORD_STRENGTH) { - warning = `${ - result?.feedback?.warning ? result?.feedback?.warning + '.' : '' - } You need a stronger password.` - } - } else { - toast.error(`Failed to check password strength: ${response.error.message}`) - } - } - } - - return { - message, - warning, - strength, - } -} - export const detectBrowser = () => { if (!navigator) return undefined diff --git a/apps/studio/lib/password-strength.ts b/apps/studio/lib/password-strength.ts new file mode 100644 index 00000000000..d1da5a4255e --- /dev/null +++ b/apps/studio/lib/password-strength.ts @@ -0,0 +1,46 @@ +import { post } from 'lib/common/fetch' +import { API_URL, DEFAULT_MINIMUM_PASSWORD_STRENGTH, PASSWORD_STRENGTH } from 'lib/constants' +import { toast } from 'react-hot-toast' + +export default async function passwordStrength(value: string) { + let message: string = '' + let warning: string = '' + let strength: number = 0 + + if (value && value !== '') { + if (value.length > 99) { + message = `${PASSWORD_STRENGTH[0]} Maximum length of password exceeded` + warning = `Password should be less than 100 characters` + } else { + // [Joshen] Unable to use RQ atm due to our Jest tests being in JS + const response = await post(`${API_URL}/profile/password-check`, { password: value }) + if (!response.error) { + const { result } = response + const resultScore = result?.score ?? 0 + + const score = (PASSWORD_STRENGTH as any)[resultScore] + const suggestions = result.feedback?.suggestions + ? result.feedback.suggestions.join(' ') + : '' + + message = `${score} ${suggestions}` + strength = resultScore + + // warning message for anything below 4 strength :string + if (resultScore < DEFAULT_MINIMUM_PASSWORD_STRENGTH) { + warning = `${ + result?.feedback?.warning ? result?.feedback?.warning + '.' : '' + } You need a stronger password.` + } + } else { + toast.error(`Failed to check password strength: ${response.error.message}`) + } + } + } + + return { + message, + warning, + strength, + } +} diff --git a/apps/studio/lib/uuid.ts b/apps/studio/lib/uuid.ts new file mode 100644 index 00000000000..c33432b302d --- /dev/null +++ b/apps/studio/lib/uuid.ts @@ -0,0 +1,7 @@ +import { v4 as _uuidV4 } from 'uuid' + +const uuidv4 = () => { + return _uuidV4() +} + +export default uuidv4 diff --git a/apps/studio/lib/vercelConfigs.ts b/apps/studio/lib/vercelConfigs.ts index c59555650ed..d0dd57aa583 100644 --- a/apps/studio/lib/vercelConfigs.ts +++ b/apps/studio/lib/vercelConfigs.ts @@ -1,4 +1,4 @@ -import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.constants' +import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries' const QuickStart = SQL_TEMPLATES.filter((template) => template.type === 'quickstart') diff --git a/packages/common/Providers.tsx b/packages/common/Providers.tsx index dcb2d3e5162..123c17134fc 100644 --- a/packages/common/Providers.tsx +++ b/packages/common/Providers.tsx @@ -1,5 +1,5 @@ import { ThemeProvider as NextThemesProvider } from 'next-themes' -import { type ThemeProviderProps } from 'next-themes/dist/types' +import type { ThemeProviderProps } from 'next-themes/dist/types' export function ThemeProvider({ children, ...props }: ThemeProviderProps) { // @ts-ignore next-themes is old :/ From 0073518136033b68952a7799d862ae61789da1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Tue, 5 Mar 2024 12:51:11 +0800 Subject: [PATCH 50/62] perf: improve prism-react-renderer setup (#21752) --- .../AIPolicyEditorPanel/PolicyTemplates.tsx | 1 - .../interfaces/Auth/Users/UsersListItem.tsx | 4 +-- .../interfaces/SignIn/SignInMfaForm.tsx | 2 +- .../to-be-cleaned/SimpleCodeBlock.tsx | 20 ++++---------- apps/studio/lib/gotrue.ts | 2 +- apps/studio/package.json | 3 +-- apps/studio/pages/_app.tsx | 7 +---- package-lock.json | 27 +++++++++++++++---- packages/common/auth.tsx | 2 +- 9 files changed, 33 insertions(+), 35 deletions(-) diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyTemplates.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyTemplates.tsx index 8e3a65e5ff0..62f1fffdf32 100644 --- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyTemplates.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/PolicyTemplates.tsx @@ -8,7 +8,6 @@ import CardButton from 'components/ui/CardButton' import CopyButton from 'components/ui/CopyButton' import NoSearchResults from 'components/ui/NoSearchResults' import { getGeneralPolicyTemplates } from '../PolicyEditorModal/PolicyEditorModal.constants' -import { PolicyTemplate } from '../PolicyTemplates/PolicyTemplates.constants' interface PolicyTemplatesProps { selectedTemplate?: string diff --git a/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx b/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx index 1d300bcd92e..dc2d8eb11ee 100644 --- a/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx +++ b/apps/studio/components/interfaces/Auth/Users/UsersListItem.tsx @@ -56,9 +56,7 @@ const UserListItem = ({
    - - {user.id} - + {user.id}
    ...
    diff --git a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx index f5f2cfc2c64..23108222919 100644 --- a/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx +++ b/apps/studio/components/interfaces/SignIn/SignInMfaForm.tsx @@ -1,4 +1,4 @@ -import { AuthError } from '@supabase/gotrue-js' +import type { AuthError } from '@supabase/gotrue-js' import type { Factor } from '@supabase/supabase-js' import { useQueryClient } from '@tanstack/react-query' import Link from 'next/link' diff --git a/apps/studio/components/to-be-cleaned/SimpleCodeBlock.tsx b/apps/studio/components/to-be-cleaned/SimpleCodeBlock.tsx index 31750374f04..f238c8fa330 100644 --- a/apps/studio/components/to-be-cleaned/SimpleCodeBlock.tsx +++ b/apps/studio/components/to-be-cleaned/SimpleCodeBlock.tsx @@ -5,16 +5,15 @@ * LICENSE file in the root directory of this source tree. */ -import rangeParser from 'parse-numeric-range' -import Highlight, { Language, defaultProps } from 'prism-react-renderer' -import darkTheme from 'prism-react-renderer/themes/vsDark' -import lightTheme from 'prism-react-renderer/themes/nightOwlLight' +import { Prism, themes, Highlight, Language } from 'prism-react-renderer' import { PropsWithChildren, useEffect, useRef, useState } from 'react' import { Button } from 'ui' import { useTheme } from 'next-themes' import { copyToClipboard } from 'lib/helpers' +import { dart } from 'lib/constants/prism' + +dart(Prism) -const highlightLinesRangeRegex = /{([\d,-]+)}/ const prism = { defaultLanguage: 'js', plugins: ['line-numbers', 'show-language'], @@ -23,7 +22,6 @@ const prism = { interface SimpleCodeBlockProps { parentClassName?: string className?: string - metastring?: string showCopy?: boolean } @@ -31,20 +29,13 @@ const SimpleCodeBlock = ({ children, parentClassName, className: languageClassName, - metastring, showCopy = true, }: PropsWithChildren) => { const { resolvedTheme } = useTheme() const [showCopied, setShowCopied] = useState(false) const target = useRef(null) - const button = useRef(null) let highlightLines: any = [] - if (metastring && highlightLinesRangeRegex.test(metastring)) { - const highlightLinesRange = metastring.match(highlightLinesRangeRegex)?.[1] - if (highlightLinesRange) highlightLines = rangeParser(highlightLinesRange).filter((n) => n > 0) - } - useEffect(() => { if (!showCopied) return const timer = setTimeout(() => setShowCopied(false), 2000) @@ -63,8 +54,7 @@ const SimpleCodeBlock = ({ return ( diff --git a/apps/studio/lib/gotrue.ts b/apps/studio/lib/gotrue.ts index 2884a5395fb..140cddcfe22 100644 --- a/apps/studio/lib/gotrue.ts +++ b/apps/studio/lib/gotrue.ts @@ -1,4 +1,4 @@ -import { Session, User } from '@supabase/gotrue-js' +import type { Session, User } from '@supabase/gotrue-js' import { gotrueClient } from 'common' export const auth = gotrueClient diff --git a/apps/studio/package.json b/apps/studio/package.json index 0536949144d..af058be1ed5 100644 --- a/apps/studio/package.json +++ b/apps/studio/package.json @@ -69,10 +69,9 @@ "openapi-fetch": "^0.6.1", "p-queue": "^6.6.2", "papaparse": "^5.3.1", - "parse-numeric-range": "^1.3.0", "path-to-regexp": "^6.2.0", "pg-minify": "^1.6.3", - "prism-react-renderer": "^1.2.1", + "prism-react-renderer": "^2.3.1", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.0", "react-contexify": "^5.0.0", diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx index 1889589c012..ed5273a01f7 100644 --- a/apps/studio/pages/_app.tsx +++ b/apps/studio/pages/_app.tsx @@ -31,8 +31,6 @@ import utc from 'dayjs/plugin/utc' import Head from 'next/head' import { useEffect, useMemo, useRef, useState } from 'react' import toast from 'react-hot-toast' -// @ts-ignore -import Prism from 'prism-react-renderer/prism' import { ConsentToast } from 'ui-patterns/ConsentToast' import PortalToast from 'ui/src/layout/PortalToast' @@ -49,11 +47,10 @@ import { useRootQueryClient } from 'data/query-client' import { StoreProvider } from 'hooks' import { AuthProvider } from 'lib/auth' import { BASE_PATH, IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants' -import { dart } from 'lib/constants/prism' + import { ProfileProvider } from 'lib/profile' import { useAppStateSnapshot } from 'state/app-state' import { RootStore } from 'stores' -import HCaptchaLoadedStore from 'stores/hcaptcha-loaded-store' import type { AppPropsWithLayout } from 'types' import { Toaster } from 'ui' import { FeaturePreviewContextProvider } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' @@ -63,7 +60,6 @@ dayjs.extend(customParseFormat) dayjs.extend(utc) dayjs.extend(timezone) dayjs.extend(relativeTime) -dart(Prism) loader.config({ // [Joshen] Attempt for offline support/bypass ISP issues is to store the assets required for monaco @@ -180,7 +176,6 @@ function CustomApp({ Component, pageProps }: AppPropsWithLayout) { - {!isTestEnv && } diff --git a/package-lock.json b/package-lock.json index 81a1b75a996..34fa14583c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1160,10 +1160,9 @@ "openapi-fetch": "^0.6.1", "p-queue": "^6.6.2", "papaparse": "^5.3.1", - "parse-numeric-range": "^1.3.0", "path-to-regexp": "^6.2.0", "pg-minify": "^1.6.3", - "prism-react-renderer": "^1.2.1", + "prism-react-renderer": "^2.3.1", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.0", "react-contexify": "^5.0.0", @@ -14724,6 +14723,11 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/prismjs": { + "version": "1.26.3", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", + "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==" + }, "node_modules/@types/prop-types": { "version": "15.7.8", "license": "MIT" @@ -33205,10 +33209,23 @@ } }, "node_modules/prism-react-renderer": { - "version": "1.3.5", - "license": "MIT", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz", + "integrity": "sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw==", + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, "peerDependencies": { - "react": ">=0.14.9" + "react": ">=16.0.0" + } + }, + "node_modules/prism-react-renderer/node_modules/clsx": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", + "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", + "engines": { + "node": ">=6" } }, "node_modules/prismjs": { diff --git a/packages/common/auth.tsx b/packages/common/auth.tsx index 4d5a943ab9d..86cfffdaabc 100644 --- a/packages/common/auth.tsx +++ b/packages/common/auth.tsx @@ -1,4 +1,4 @@ -import { Session } from '@supabase/supabase-js' +import type { Session } from '@supabase/supabase-js' import { createContext, PropsWithChildren, From c98c59938ad60ddc0dfc6ee3dbffd5bbea14f413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Tue, 5 Mar 2024 12:51:47 +0800 Subject: [PATCH 51/62] perf: lazyload feature preview modal (#21744) --- apps/studio/pages/_app.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx index ed5273a01f7..205530c14af 100644 --- a/apps/studio/pages/_app.tsx +++ b/apps/studio/pages/_app.tsx @@ -54,13 +54,25 @@ import { RootStore } from 'stores' import type { AppPropsWithLayout } from 'types' import { Toaster } from 'ui' import { FeaturePreviewContextProvider } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' -import FeaturePreviewModal from 'components/interfaces/App/FeaturePreview/FeaturePreviewModal' +import dynamic from 'next/dynamic' dayjs.extend(customParseFormat) dayjs.extend(utc) dayjs.extend(timezone) dayjs.extend(relativeTime) +/** + * FeaturePreviewModal is quite heavy with react-markdown and other dependencies, not needed on initial load, + * so we will load it lazily. + */ +const LazyFeaturePreviewModal = dynamic( + () => + import('components/interfaces/App/FeaturePreview/FeaturePreviewModal').then( + (mod) => mod.default + ), + { ssr: false } +) + loader.config({ // [Joshen] Attempt for offline support/bypass ISP issues is to store the assets required for monaco // locally. We're however, only storing the assets which we need (based on what the network tab loads @@ -166,7 +178,7 @@ function CustomApp({ Component, pageProps }: AppPropsWithLayout) { {getLayout()} - + From f16810af06fd42c613d5d93bd314e23b10c0ebd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Gr=C3=BCneberg?= Date: Tue, 5 Mar 2024 12:52:39 +0800 Subject: [PATCH 52/62] perf: load hcaptcha on demand (#21745) --- .../Payment/AddNewPaymentMethodModal.tsx | 4 +-- apps/studio/pages/new/index.tsx | 17 ++++++---- apps/studio/stores/hcaptcha-loaded-store.tsx | 31 ------------------- 3 files changed, 13 insertions(+), 39 deletions(-) delete mode 100644 apps/studio/stores/hcaptcha-loaded-store.tsx diff --git a/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx b/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx index 0041cbb6207..f822b55b0b5 100644 --- a/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx +++ b/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx @@ -8,7 +8,6 @@ import { Modal } from 'ui' import { useOrganizationPaymentMethodSetupIntent } from 'data/organizations/organization-payment-method-setup-intent-mutation' import { useSelectedOrganization, useStore } from 'hooks' import { STRIPE_PUBLIC_KEY } from 'lib/constants' -import { useIsHCaptchaLoaded } from 'stores/hcaptcha-loaded-store' import AddPaymentMethodForm from './AddPaymentMethodForm' interface AddNewPaymentMethodModalProps { @@ -31,7 +30,7 @@ const AddNewPaymentMethodModal = ({ const [intent, setIntent] = useState() const selectedOrganization = useSelectedOrganization() - const captchaLoaded = useIsHCaptchaLoaded() + const [captchaLoaded, setHCaptchaLoaded] = useState(false) const [captchaToken, setCaptchaToken] = useState(null) const [captchaRef, setCaptchaRef] = useState(null) @@ -126,6 +125,7 @@ const AddNewPaymentMethodModal = ({ onExpire={() => { setCaptchaToken(null) }} + onLoad={() => setHCaptchaLoaded(true)} /> { const { resolvedTheme } = useTheme() const [intent, setIntent] = useState() - const captchaLoaded = useIsHCaptchaLoaded() + const [captchaLoaded, setHCaptchaLoaded] = useState(false) const [captchaToken, setCaptchaToken] = useState(null) const [captchaRef, setCaptchaRef] = useState(null) @@ -86,13 +85,19 @@ const Wizard: NextPageWithLayout = () => { ref={captchaRefCallback} sitekey={process.env.NEXT_PUBLIC_HCAPTCHA_SITE_KEY!} size="invisible" + onOpen={() => { + // [Joshen] This is to ensure that hCaptcha popup remains clickable + if (document !== undefined) document.body.classList.add('!pointer-events-auto') + }} + onClose={() => { + onLocalCancel() + if (document !== undefined) document.body.classList.remove('!pointer-events-auto') + }} onVerify={(token) => { setCaptchaToken(token) + if (document !== undefined) document.body.classList.remove('!pointer-events-auto') }} - onClose={onLocalCancel} - onExpire={() => { - setCaptchaToken(null) - }} + onLoad={() => setHCaptchaLoaded(true)} /> {intent && ( diff --git a/apps/studio/stores/hcaptcha-loaded-store.tsx b/apps/studio/stores/hcaptcha-loaded-store.tsx deleted file mode 100644 index 008053d20b0..00000000000 --- a/apps/studio/stores/hcaptcha-loaded-store.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import HCaptcha from '@hcaptcha/react-hcaptcha' -import { proxy, useSnapshot } from 'valtio' - -const hCaptchaLoadedStoreState = proxy({ - loaded: false, - setLoaded() { - hCaptchaLoadedStoreState.loaded = true - }, -}) - -export const useIsHCaptchaLoaded = () => { - const snap = useSnapshot(hCaptchaLoadedStoreState) - - return snap.loaded -} - -const HCaptchaLoadedStore = () => { - const onLoad = () => { - hCaptchaLoadedStoreState.setLoaded() - } - - return ( - - ) -} - -export default HCaptchaLoadedStore From c390068102091b76b4fd0d6c3e22d25f55e4c114 Mon Sep 17 00:00:00 2001 From: Beng Eu Date: Tue, 5 Mar 2024 13:14:43 +0800 Subject: [PATCH 53/62] fix: handle new size for connection pooling settings (#21700) --- .../ConnectionPooling.constants.ts | 8 ++++++ .../ConnectionPooling/ConnectionPooling.tsx | 26 +++++++++++-------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.constants.ts b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.constants.ts index facaaac1308..3d7f7ea2653 100644 --- a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.constants.ts +++ b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.constants.ts @@ -2,6 +2,14 @@ // https://github.com/supabase/infrastructure/blob/develop/worker/src/lib/constants.ts#L544-L596 export const POOLING_OPTIMIZATIONS = { + ci_nano: { + maxClientConn: 100, + poolSize: 10, + }, + ci_micro: { + maxClientConn: 200, + poolSize: 15, + }, ci_small: { maxClientConn: 200, poolSize: 15, diff --git a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx index a0902130f68..8b218e9602f 100644 --- a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx +++ b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx @@ -1,6 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' +import { capitalize } from 'lodash' import { Fragment, useEffect } from 'react' import { SubmitHandler, useForm } from 'react-hook-form' import { @@ -68,14 +69,17 @@ export const ConnectionPooling = () => { const { data: addons } = useProjectAddonsQuery({ projectRef }) const computeInstance = addons?.selected_addons.find((addon) => addon.type === 'compute_instance') - const defaultPoolSize = - POOLING_OPTIMIZATIONS?.[ - computeInstance?.variant.identifier as keyof typeof POOLING_OPTIMIZATIONS - ]?.poolSize ?? 15 // [TODO] 15 is for micro, need to change to 10 for nano - const defaultMaxClientConn = - POOLING_OPTIMIZATIONS?.[ - computeInstance?.variant.identifier as keyof typeof POOLING_OPTIMIZATIONS - ]?.maxClientConn ?? 200 + const poolingOptimizations = + POOLING_OPTIMIZATIONS[ + (computeInstance?.variant.identifier as keyof typeof POOLING_OPTIMIZATIONS) ?? + project?.infra_compute_size === 'nano' + ? 'ci_nano' + : 'ci_micro' + ] + const defaultPoolSize = poolingOptimizations.poolSize ?? 15 + const defaultMaxClientConn = poolingOptimizations.maxClientConn ?? 200 + const computeSize = + computeInstance?.variant.name ?? capitalize(project?.infra_compute_size) ?? 'Micro' const { data: poolingInfo, @@ -317,7 +321,7 @@ export const ConnectionPooling = () => { The maximum number of connections made to the underlying Postgres cluster, per user+db combination. Pool size has a default of {defaultPoolSize} based - on your compute size of {computeInstance?.variant.name ?? 'Micro'}. + on your compute size of {computeSize}. Please refer to our{' '} @@ -354,8 +358,8 @@ export const ConnectionPooling = () => { The maximum number of concurrent client connections allowed. This value is - fixed at {defaultMaxClientConn} based on your compute size of{' '} - {computeInstance?.variant.name ?? 'Micro'} and cannot be changed. + fixed at {defaultMaxClientConn} based on your compute size of {computeSize}{' '} + and cannot be changed. Please refer to our{' '} From 5b9630ecfc61af015b53ecdd05bbf7f6569d0b92 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Tue, 5 Mar 2024 13:44:44 +0800 Subject: [PATCH 54/62] Chore/upgrade sb (#21726) * remove un-needed stuff * Update preview.js * Update preview.js * upgrade sb * Update preview.js * Update main.js --- apps/storybook/.storybook/main.js | 5 +- apps/storybook/.storybook/preview.js | 15 - apps/storybook/package.json | 24 +- package-lock.json | 3245 +++++++++++++++++++++++--- 4 files changed, 2883 insertions(+), 406 deletions(-) diff --git a/apps/storybook/.storybook/main.js b/apps/storybook/.storybook/main.js index cdbe12a8b27..210cbfea196 100644 --- a/apps/storybook/.storybook/main.js +++ b/apps/storybook/.storybook/main.js @@ -26,8 +26,9 @@ const config = { getAbsolutePath('@storybook/addon-onboarding'), getAbsolutePath('@storybook/addon-interactions'), getAbsolutePath('@storybook/addon-mdx-gfm'), - '@storybook/addon-styling-webpack', - '@storybook/addon-themes', + getAbsolutePath('@storybook/addon-styling-webpack'), + getAbsolutePath('@storybook/addon-themes'), + getAbsolutePath('@storybook/addon-mdx-gfm'), ], framework: { name: getAbsolutePath('@storybook/nextjs'), diff --git a/apps/storybook/.storybook/preview.js b/apps/storybook/.storybook/preview.js index b627b087019..2075734049b 100644 --- a/apps/storybook/.storybook/preview.js +++ b/apps/storybook/.storybook/preview.js @@ -1,19 +1,6 @@ import { withThemeByClassName } from '@storybook/addon-themes' import './preview.css' -/** @type { import('@storybook/react').Preview } */ -const preview = { - parameters: { - actions: { argTypesRegex: '^on[A-Z].*' }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/i, - }, - }, - }, -} - export const decorators = [ withThemeByClassName({ themes: { @@ -24,5 +11,3 @@ export const decorators = [ defaultTheme: 'dark', }), ] - -export default preview diff --git a/apps/storybook/package.json b/apps/storybook/package.json index dfc418104c0..9fedddb1606 100644 --- a/apps/storybook/package.json +++ b/apps/storybook/package.json @@ -11,18 +11,22 @@ "author": "", "license": "ISC", "devDependencies": { - "@storybook/addon-essentials": "^7.6.17", - "@storybook/addon-interactions": "^7.6.17", - "@storybook/addon-links": "^7.6.17", - "@storybook/addon-onboarding": "^1.0.11", + "@storybook/addon-essentials": "^8.0.0-rc.1", + "@storybook/addon-interactions": "^8.0.0-rc.1", + "@storybook/addon-links": "^8.0.0-rc.1", + "@storybook/addon-mdx-gfm": "^8.0.0-rc.1", + "@storybook/addon-onboarding": "^8.0.0-rc.1", "@storybook/addon-styling-webpack": "^0.0.6", - "@storybook/addon-themes": "^7.6.17", - "@storybook/blocks": "^7.6.17", - "@storybook/nextjs": "^7.6.17", - "@storybook/react": "^7.6.17", - "@storybook/test": "^7.6.17", + "@storybook/addon-themes": "^8.0.0-rc.1", + "@storybook/blocks": "^8.0.0-rc.1", + "@storybook/nextjs": "^8.0.0-rc.1", + "@storybook/react": "^8.0.0-rc.1", + "@storybook/test": "^8.0.0-rc.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "storybook": "^7.0.0" + "storybook": "^8.0.0-rc.1" + }, + "dependencies": { + "@storybook/node-logger": "^8.0.0-rc.1" } } diff --git a/package-lock.json b/package-lock.json index 34fa14583c0..a4d8b2e5139 100644 --- a/package-lock.json +++ b/package-lock.json @@ -760,30 +760,366 @@ "apps/storybook": { "version": "1.0.0", "license": "ISC", + "dependencies": { + "@storybook/node-logger": "^8.0.0-rc.1" + }, "devDependencies": { - "@storybook/addon-essentials": "^7.6.17", - "@storybook/addon-interactions": "^7.6.17", - "@storybook/addon-links": "^7.6.17", - "@storybook/addon-onboarding": "^1.0.11", + "@storybook/addon-essentials": "^8.0.0-rc.1", + "@storybook/addon-interactions": "^8.0.0-rc.1", + "@storybook/addon-links": "^8.0.0-rc.1", + "@storybook/addon-mdx-gfm": "^8.0.0-rc.1", + "@storybook/addon-onboarding": "^8.0.0-rc.1", "@storybook/addon-styling-webpack": "^0.0.6", - "@storybook/addon-themes": "^7.6.17", - "@storybook/blocks": "^7.6.17", - "@storybook/nextjs": "^7.6.17", - "@storybook/react": "^7.6.17", - "@storybook/test": "^7.6.17", + "@storybook/addon-themes": "^8.0.0-rc.1", + "@storybook/blocks": "^8.0.0-rc.1", + "@storybook/nextjs": "^8.0.0-rc.1", + "@storybook/react": "^8.0.0-rc.1", + "@storybook/test": "^8.0.0-rc.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "storybook": "^7.0.0" + "storybook": "^8.0.0-rc.1" + } + }, + "apps/storybook/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "apps/storybook/node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "apps/storybook/node_modules/@storybook/addon-actions": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.0.0-rc.1.tgz", + "integrity": "sha512-Xl8RA2obW0MJ6Y8hQxx8LmwoNt0gKT20UADYp+QusaV4prGw9XVf43eJWq704LO4dq7HFTah3hkDLwGhTsJ5hw==", + "dev": true, + "dependencies": { + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-backgrounds": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.0.0-rc.1.tgz", + "integrity": "sha512-29E8XT0IJnwe2N0SyQpMZgOCKoPz/zjzOyucQj0vyG+ZXUXugiyVMI6jWitkUxYydwJWvsuaem+/OGfC5SdaWg==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-controls": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.0.0-rc.1.tgz", + "integrity": "sha512-Yat3OuFbhxD2vjEhT1NxiiKNuGxPUKvlSRgBxlD++8XuWKm6HFeGh2R3OwIndaYvsbpzrV8F4GKM4NYrCaONfQ==", + "dev": true, + "dependencies": { + "@storybook/blocks": "8.0.0-rc.1", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-docs": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.0.0-rc.1.tgz", + "integrity": "sha512-oDktwaXuDUV+laLg6BB4mEXdncAHyHeePO9eE0t0lqxU50qkqxQ1OJqafyM1Cbrt/8SNVFlvd+XYKaZCLPyW5w==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/components": "8.0.0-rc.1", + "@storybook/csf-plugin": "8.0.0-rc.1", + "@storybook/csf-tools": "8.0.0-rc.1", + "@storybook/global": "^5.0.0", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/react-dom-shim": "8.0.0-rc.1", + "@storybook/theming": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "fs-extra": "^11.1.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-essentials": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.0.0-rc.1.tgz", + "integrity": "sha512-HgzsK9TRncn7MJ6QZBJGWyhcpyll3UEMknSenX9e5HYSd4npMFyqi6EAFPYQTBtjqEHsjdeRzGiuSX64a9UBLQ==", + "dev": true, + "dependencies": { + "@storybook/addon-actions": "8.0.0-rc.1", + "@storybook/addon-backgrounds": "8.0.0-rc.1", + "@storybook/addon-controls": "8.0.0-rc.1", + "@storybook/addon-docs": "8.0.0-rc.1", + "@storybook/addon-highlight": "8.0.0-rc.1", + "@storybook/addon-measure": "8.0.0-rc.1", + "@storybook/addon-outline": "8.0.0-rc.1", + "@storybook/addon-toolbars": "8.0.0-rc.1", + "@storybook/addon-viewport": "8.0.0-rc.1", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/manager-api": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-highlight": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.0.0-rc.1.tgz", + "integrity": "sha512-RKqSfHJhZPDh2BXOZ4sYwfvUKZguUmEPqk+dpWixMk56aOPoVp8VN0KR2lHAYauGs4DuvuvrlHMgERYpQdXebw==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-interactions": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.0.0-rc.1.tgz", + "integrity": "sha512-IRoA3UpkK67YpWWnfDZ6QGvWlv36WsRLtyy3QyxfKyJXMVirXz6hvIE3KKWRTpPASjNIhI/z1hkVg3RGDCMkQA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/types": "8.0.0-rc.1", + "jest-mock": "^27.0.6", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-links": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.0.0-rc.1.tgz", + "integrity": "sha512-BP2l4E47ZwvzGrzK1LaivpjA0nZ1STgT8JN2aC7NP9hLgQ/7B5sgTkBCrNl0eSfmgPqkQnHxr1iSB4e0FDOThA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "apps/storybook/node_modules/@storybook/addon-mdx-gfm": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-mdx-gfm/-/addon-mdx-gfm-8.0.0-rc.1.tgz", + "integrity": "sha512-PTM7pHShv3574Xln8d2dTy39yoq0VBeaFRfOmb88WAMfb4DU4Vrb9TWa+/vsYs0Ajp4lfxeBuxIbNTjXDCQpSQ==", + "dev": true, + "dependencies": { + "@storybook/node-logger": "8.0.0-rc.1", + "remark-gfm": "^4.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-measure": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.0.0-rc.1.tgz", + "integrity": "sha512-fqv2DKAikZZjQ2RjQzVoUXyWh/JP9cp9HKaJXMvw0jRXjpi2aI02bjn8aCr/NUuiOKGJp/Fcf8LNXJlYYPYfZQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-outline": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.0.0-rc.1.tgz", + "integrity": "sha512-8E6s6DuRopjq0NIt6SuM7tgt1FXaMvinuIqlodd6LXr0hW4Z3c0dnO78AQ0CeJcSKvaQkhEyGHGsV5ULmgVUSQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-toolbars": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.0.0-rc.1.tgz", + "integrity": "sha512-05Od+T4xaxjPExVAO67wa1B47psETRX7Yon7lWQsGChe62bGa4LZLRJ0pzU8a+9ocCA3r+gANYzhcRcrQ4NYKQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/addon-viewport": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.0.0-rc.1.tgz", + "integrity": "sha512-bVQH/apQ4rj/yLDjF/pweB0kb7arYP4CftJ9Adln2ampXq7pGUWttWv0+5R+aNzJYbK5n3BwqaldmquJAR/C6g==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/blocks": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.0.0-rc.1.tgz", + "integrity": "sha512-AkFJPxetXgcVWyv2KyNud/za8p+UnHdMSnDXeEl9TEnh13A3pxby0ogOghIbtb28pW4yagc9rigpAeR71lQJMA==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/components": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/csf": "^0.1.2", + "@storybook/docs-tools": "8.0.0-rc.1", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@storybook/manager-api": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/theming": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "7.3.2", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "tocbot": "^4.20.1", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "apps/storybook/node_modules/@storybook/builder-manager": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-8.0.0-rc.1.tgz", + "integrity": "sha512-kOsNHnDx2l9ZnOPxBcnmGUM3wJtCPKOuHfppUC9dqWNqvc7uhuQt0tR96nhpim7fqADbr9VwM54bR5jjipKvxQ==", + "dev": true, + "dependencies": { + "@fal-works/esbuild-plugin-global-externals": "^2.1.2", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/manager": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@types/ejs": "^3.1.1", + "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", + "browser-assert": "^1.2.1", + "ejs": "^3.1.8", + "esbuild": "^0.18.0", + "esbuild-plugin-alias": "^0.2.1", + "express": "^4.17.3", + "fs-extra": "^11.1.0", + "process": "^0.11.10", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, "apps/storybook/node_modules/@storybook/channels": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.17.tgz", - "integrity": "sha512-GFG40pzaSxk1hUr/J/TMqW5AFDDPUSu+HkeE/oqSWJbOodBOLJzHN6CReJS6y1DjYSZLNFt1jftPWZZInG/XUA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.0.0-rc.1.tgz", + "integrity": "sha512-RKAIVK7A1CgBAIALg3zp6KvVLwSv9FaCu2EWNH47krBD4gsaalzDcVa6PJrxqjRuPqmQLv1bkugOBhBKs1ZRyg==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.2.0", @@ -794,10 +1130,62 @@ "url": "https://opencollective.com/storybook" } }, + "apps/storybook/node_modules/@storybook/cli": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-8.0.0-rc.1.tgz", + "integrity": "sha512-B7XebUK63lhScJO+U9XNA3y98MYR4K98zkijYkH3xe5eKjd17aa4hr1VszmKJbsgs8dzP0ZZpcp5MlKrCKZR+w==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/types": "^7.23.0", + "@ndelangen/get-tarball": "^3.0.7", + "@storybook/codemod": "8.0.0-rc.1", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/core-server": "8.0.0-rc.1", + "@storybook/csf-tools": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/telemetry": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "get-npm-tarball-url": "^2.0.3", + "giget": "^1.0.0", + "globby": "^11.0.2", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^3.1.1", + "prompts": "^2.4.0", + "read-pkg-up": "^7.0.1", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^1.0.1", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" + }, + "bin": { + "getstorybook": "bin/index.js", + "sb": "bin/index.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, "apps/storybook/node_modules/@storybook/client-logger": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.17.tgz", - "integrity": "sha512-6WBYqixAXNAXlSaBWwgljWpAu10tPRBJrcFvx2gPUne58EeMM20Gi/iHYBz2kMCY+JLAgeIH7ZxInqwO8vDwiQ==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.0.0-rc.1.tgz", + "integrity": "sha512-YZ3F1LS8GVkdoE4HWIxtR854bR2gc45Qz30gNNwRAaiWmPEnPbcv2v8gCDIfvhn+dEiO0sBq6pO4rCS3ZgWW2w==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0" @@ -807,36 +1195,75 @@ "url": "https://opencollective.com/storybook" } }, - "apps/storybook/node_modules/@storybook/core-client": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.6.17.tgz", - "integrity": "sha512-LuDbADK+DPNAOOCXOlvY09hdGVueXlDetsdOJ/DgYnSa9QSWv9Uv+F8QcEgR3QckZJbPlztKJIVLgP2n/Xkijw==", + "apps/storybook/node_modules/@storybook/codemod": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.0.0-rc.1.tgz", + "integrity": "sha512-5GDCci06/lddHZo9Bxq488p0BuQpu6IFQ1J1/QRgbrNMJcPFv+D7B9nwtgQ+cdi3XNzc7RuMJLjMyyCf2entGw==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/preview-api": "7.6.17" + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/csf-tools": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^11.0.2", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^3.1.1", + "recast": "^0.23.1", + "tiny-invariant": "^1.3.1" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" } }, - "apps/storybook/node_modules/@storybook/core-common": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.17.tgz", - "integrity": "sha512-me2TP3Q9/qzqCLoDHUSsUF+VS1MHxfHbTVF6vAz0D/COTxzsxLpu9TxTbzJoBCxse6XRb6wWI1RgF1mIcjic7g==", + "apps/storybook/node_modules/@storybook/components": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.0.0-rc.1.tgz", + "integrity": "sha512-yOL/m3s/uhjhMgy0FdjQZFDn3FOcbx9R0SA0ba07RLJ9qKQU6Ece5yg25Xp+kvAz643EwNr0HcpyfIvCMj0U7w==", "dev": true, "dependencies": { - "@storybook/core-events": "7.6.17", - "@storybook/node-logger": "7.6.17", - "@storybook/types": "7.6.17", - "@types/find-cache-dir": "^3.2.1", - "@types/node": "^18.0.0", - "@types/node-fetch": "^2.6.4", - "@types/pretty-hrtime": "^1.0.0", + "@radix-ui/react-slot": "^1.0.2", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@storybook/theming": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "memoizerific": "^1.11.3", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "apps/storybook/node_modules/@storybook/core-common": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-8.0.0-rc.1.tgz", + "integrity": "sha512-hRMOZ0HIYtM2WQx+kJPR4s2pZULMvla7xCHlczuy6/mtsDVd62H8IA7syvtrk/Tj2SxlrLO7l4JN5QdVhLryMg==", + "dev": true, + "dependencies": { + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/csf-tools": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.0", + "cross-spawn": "^7.0.3", "esbuild": "^0.18.0", "esbuild-register": "^3.5.0", + "execa": "^5.0.0", "file-system-cache": "2.3.0", "find-cache-dir": "^3.0.0", "find-up": "^5.0.0", @@ -849,7 +1276,11 @@ "pkg-dir": "^5.0.0", "pretty-hrtime": "^1.0.3", "resolve-from": "^5.0.0", - "ts-dedent": "^2.0.0" + "semver": "^7.3.7", + "tempy": "^1.0.1", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util": "^0.12.4" }, "funding": { "type": "opencollective", @@ -857,9 +1288,9 @@ } }, "apps/storybook/node_modules/@storybook/core-events": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.17.tgz", - "integrity": "sha512-AriWMCm/k1cxlv10f+jZ1wavThTRpLaN3kY019kHWbYT9XgaSuLU67G7GPr3cGnJ6HuA6uhbzu8qtqVCd6OfXA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.0.0-rc.1.tgz", + "integrity": "sha512-IOgwjetxT+6YCze5ZWnXuR1uDuJOq54RfhHSXBgO8RFPM9eZ2NTggAEaFcge8gL01CfOusWEeF2Ebl2buwuTbQ==", "dev": true, "dependencies": { "ts-dedent": "^2.0.0" @@ -869,15 +1300,111 @@ "url": "https://opencollective.com/storybook" } }, - "apps/storybook/node_modules/@storybook/docs-tools": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.6.17.tgz", - "integrity": "sha512-bYrLoj06adqklyLkEwD32C0Ww6t+9ZVvrJHiVT42bIhTRpFiFPAetl1a9KPHtFLnfduh4n2IxIr1jv32ThPDTA==", + "apps/storybook/node_modules/@storybook/core-server": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-8.0.0-rc.1.tgz", + "integrity": "sha512-q5wgVPJS7i+lN0lpDvxrzICkw1ewGYgbpWlvp9bShObHctH2oPjjAAEB1DdyFLCPDmkokyygpM/iBBWW3oP3Pw==", "dev": true, "dependencies": { - "@storybook/core-common": "7.6.17", - "@storybook/preview-api": "7.6.17", - "@storybook/types": "7.6.17", + "@aw-web-design/x-default-browser": "1.4.126", + "@babel/core": "^7.23.9", + "@discoveryjs/json-ext": "^0.5.3", + "@storybook/builder-manager": "8.0.0-rc.1", + "@storybook/channels": "8.0.0-rc.1", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/csf": "^0.1.2", + "@storybook/csf-tools": "8.0.0-rc.1", + "@storybook/docs-mdx": "3.0.0", + "@storybook/global": "^5.0.0", + "@storybook/manager": "8.0.0-rc.1", + "@storybook/manager-api": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/telemetry": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "@types/detect-port": "^1.3.0", + "@types/node": "^18.0.0", + "@types/pretty-hrtime": "^1.0.0", + "@types/semver": "^7.3.4", + "better-opn": "^3.0.2", + "chalk": "^4.1.0", + "cli-table3": "^0.6.1", + "compression": "^1.7.4", + "detect-port": "^1.3.0", + "express": "^4.17.3", + "fs-extra": "^11.1.0", + "globby": "^11.0.2", + "ip": "^2.0.1", + "lodash": "^4.17.21", + "open": "^8.4.0", + "pretty-hrtime": "^1.0.3", + "prompts": "^2.4.0", + "read-pkg-up": "^7.0.1", + "semver": "^7.3.7", + "telejson": "^7.2.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "watchpack": "^2.2.0", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/csf-plugin": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.0.0-rc.1.tgz", + "integrity": "sha512-s1RJQwF+shalDESPzVMi2lw19sbs3VwHY8hjK1QYmjq6J7KzUOxN6MuOocWYJl0i35crSeZ99pB+EP6sWKElmA==", + "dev": true, + "dependencies": { + "@storybook/csf-tools": "8.0.0-rc.1", + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/csf-tools": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-8.0.0-rc.1.tgz", + "integrity": "sha512-WsrztCyi3Ij3oA00OGJslKGgev2Cyuh//+n2IKRGJVbjNO2xHKDFTYa4MEonUw376g3JUy1U6OavSVqbJsgVKg==", + "dev": true, + "dependencies": { + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "8.0.0-rc.1", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/docs-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-3.0.0.tgz", + "integrity": "sha512-NmiGXl2HU33zpwTv1XORe9XG9H+dRUC1Jl11u92L4xr062pZtrShLmD4VKIsOQujxhhOrbxpwhNOt+6TdhyIdQ==", + "dev": true + }, + "apps/storybook/node_modules/@storybook/docs-tools": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-8.0.0-rc.1.tgz", + "integrity": "sha512-KmXVzD32fQ7wRfktTHobnczv/NreNFtHg2fKj6HZqrmL/TluDkIfF5MQMz7+u+gVz0OKV6REcwqLIVB5VKxEqg==", + "dev": true, + "dependencies": { + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", "@types/doctrine": "^0.0.3", "assert": "^2.1.0", "doctrine": "^3.0.0", @@ -888,34 +1415,69 @@ "url": "https://opencollective.com/storybook" } }, - "apps/storybook/node_modules/@storybook/node-logger": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.17.tgz", - "integrity": "sha512-w59MQuXhhUNrUVmVkXhMwIg2nvFWjdDczLTwYLorhfsE36CWeUOY5QCZWQy0Qf/h+jz8Uo7Evy64qn18v9C4wA==", + "apps/storybook/node_modules/@storybook/manager": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-8.0.0-rc.1.tgz", + "integrity": "sha512-+WnIRLyqNGOnQ/taUautCLfwtXt6EWK/X+ocyq9uycNL5QozBEDFBis8Opk3BQ+gYUyajbIvFoeuwEpMLQk1yg==", "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" } }, - "apps/storybook/node_modules/@storybook/preview-api": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.17.tgz", - "integrity": "sha512-wLfDdI9RWo1f2zzFe54yRhg+2YWyxLZvqdZnSQ45mTs4/7xXV5Wfbv3QNTtcdw8tT3U5KRTrN1mTfTCiRJc0Kw==", + "apps/storybook/node_modules/@storybook/manager-api": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.0.0-rc.1.tgz", + "integrity": "sha512-LEwuiCqQLycehYI+J58Q7RoOLeVWjUuX0skXbJnFPGs5AP3CpnKR9nJn1JzzY9Yojbn0snShbmCHPzdFrT/VMw==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.17", + "@storybook/router": "8.0.0-rc.1", + "@storybook/theming": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "store2": "^2.14.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/node-logger": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-8.0.0-rc.1.tgz", + "integrity": "sha512-WFIK9NRclmSepPsTmVOcxzVGv/yyjAckiL3Z/iV2idwP4Qj/TT/FGFGAPs7oGSiQfgP80FMifDFN6tcZ0awpYQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/preview-api": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.0.0-rc.1.tgz", + "integrity": "sha512-1qR5PdEzVwrNDqh0NAQFeCaYhygMGSSkHYwZVIBfXzwB5196zQ7miPR6mQ/6oqa0LdRESSVS5GbfbovmvzwPQQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/csf": "^0.1.2", + "@storybook/global": "^5.0.0", + "@storybook/types": "8.0.0-rc.1", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -925,18 +1487,17 @@ } }, "apps/storybook/node_modules/@storybook/react": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-7.6.17.tgz", - "integrity": "sha512-lVqzQSU03rRJWYW+gK2gq6mSo3/qtnVICY8B8oP7gc36jVu4ksDIu45bTfukM618ODkUZy0vZe6T4engK3azjA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.0.0-rc.1.tgz", + "integrity": "sha512-0Aqzv46KiIJzAn48ON8sCDz02uQE0UxYWqrYV4I/QDGomcCArJUSHzw/umOIzJIidHhOwaijhlsAi7FHhmeiWA==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/core-client": "7.6.17", - "@storybook/docs-tools": "7.6.17", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/docs-tools": "8.0.0-rc.1", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.6.17", - "@storybook/react-dom-shim": "7.6.17", - "@storybook/types": "7.6.17", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/react-dom-shim": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", "@types/escodegen": "^0.0.6", "@types/estree": "^0.0.51", "@types/node": "^18.0.0", @@ -948,12 +1509,13 @@ "lodash": "^4.17.21", "prop-types": "^15.7.2", "react-element-to-jsx-string": "^15.0.0", + "semver": "^7.3.7", "ts-dedent": "^2.0.0", "type-fest": "~2.19", "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", @@ -962,7 +1524,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "typescript": "*" + "typescript": ">= 4.2.x" }, "peerDependenciesMeta": { "typescript": { @@ -971,9 +1533,9 @@ } }, "apps/storybook/node_modules/@storybook/react-dom-shim": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.6.17.tgz", - "integrity": "sha512-32Sa/G+WnvaPiQ1Wvjjw5UM9rr2c4GDohwCcWVv3/LJuiFPqNS6zglAtmnsrlIBnUwRBMLMh/ekCTdqMiUmfDw==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.0.0-rc.1.tgz", + "integrity": "sha512-TQK0Tn5R77+yp4BJSrStPOr81sKjHIGKv1LmxP6Ja3by2dC0jyepv4ydMXyaEJPFeMEwq5P1iXOpJLG3dAkBYw==", "dev": true, "funding": { "type": "opencollective", @@ -984,14 +1546,76 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "apps/storybook/node_modules/@storybook/types": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.17.tgz", - "integrity": "sha512-GRY0xEJQ0PrL7DY2qCNUdIfUOE0Gsue6N+GBJw9ku1IUDFLJRDOF+4Dx2BvYcVCPI5XPqdWKlEyZdMdKjiQN7Q==", + "apps/storybook/node_modules/@storybook/router": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-8.0.0-rc.1.tgz", + "integrity": "sha512-kB3oqbCcYlKSaA7WF2SLFU6QdJeOvezmsfJFXVMNONbjy2vYHlLq7SGv0b1sHF0hJ4NkGdRtPes+cJkJvl3Hhg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@types/babel__core": "^7.0.0", + "@storybook/client-logger": "8.0.0-rc.1", + "memoizerific": "^1.11.3", + "qs": "^6.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/telemetry": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-8.0.0-rc.1.tgz", + "integrity": "sha512-tFohcpWoC/BIM9Km2EhyoPp4K2+uWisDicvE0aPVZQTNFDxdPswyhkkhKFR38/WfzUptnSV6kmMVTyq2u7h44Q==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/csf-tools": "8.0.0-rc.1", + "chalk": "^4.1.0", + "detect-package-manager": "^2.0.1", + "fetch-retry": "^5.0.2", + "fs-extra": "^11.1.0", + "read-pkg-up": "^7.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "apps/storybook/node_modules/@storybook/theming": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.0.0-rc.1.tgz", + "integrity": "sha512-IpgvelBRetiZJ4wuof2I4vrUnDPDO9YV+N2+1kofsGUkS/hdXaznwwMotJOkN4olh9zVFSzWUfZxZcqeOhDbUA==", + "dev": true, + "dependencies": { + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "apps/storybook/node_modules/@storybook/types": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.0.0-rc.1.tgz", + "integrity": "sha512-Sebh9Ju3UDSXFuk9gOZH22AP6gbs2Tk+fdjhx8GFhUWNJkvG2qY7Sgk51z9tDpMSnkoKLC/QXg0NXJUIPCgoEg==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.0-rc.1", "@types/express": "^4.7.0", "file-system-cache": "2.3.0" }, @@ -1006,15 +1630,45 @@ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, + "apps/storybook/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, "apps/storybook/node_modules/@types/node": { - "version": "18.19.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.20.tgz", - "integrity": "sha512-SKXZvI375jkpvAj8o+5U2518XQv76mAsixqfXiVyWyXZbVWQK25RurFovYpVIxVzul0rZoH58V/3SkEnm7s3qA==", + "version": "18.19.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.21.tgz", + "integrity": "sha512-2Q2NeB6BmiTFQi4DHBzncSoq/cJMLDdhPaAoJFnFCyD9a8VPZRf7a1GAwp1Edb7ROaZc5Jz/tnZyL6EsWMRaqw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, + "apps/storybook/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "apps/storybook/node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, + "apps/storybook/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, "apps/storybook/node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -1067,6 +1721,15 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "apps/storybook/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "apps/storybook/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1076,13 +1739,145 @@ "node": ">=8" } }, - "apps/storybook/node_modules/storybook": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.6.17.tgz", - "integrity": "sha512-8+EIo91bwmeFWPg1eysrxXlhIYv3OsXrznTr4+4Eq0NikqAoq6oBhtlN5K2RGS2lBVF537eN+9jTCNbR+WrzDA==", + "apps/storybook/node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", "dev": true, "dependencies": { - "@storybook/cli": "7.6.17" + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "apps/storybook/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "apps/storybook/node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "apps/storybook/node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "apps/storybook/node_modules/storybook": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.0.0-rc.1.tgz", + "integrity": "sha512-xDP+liIHa77bksUNLOpFCii8396lbZVamoZZBDRMKaFGABTswhF5VtirlQY32qfPo2z94WdbMhj55O+STpPqQg==", + "dev": true, + "dependencies": { + "@storybook/cli": "8.0.0-rc.1" }, "bin": { "sb": "index.js", @@ -1105,6 +1900,74 @@ "node": ">=8" } }, + "apps/storybook/node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "apps/storybook/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "apps/studio": { "version": "0.0.9", "dependencies": { @@ -2324,9 +3187,9 @@ } }, "node_modules/@babel/core": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", - "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", + "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -2334,11 +3197,11 @@ "@babel/generator": "^7.23.6", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.6", - "@babel/parser": "^7.23.6", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.6", - "@babel/types": "^7.23.6", + "@babel/helpers": "^7.24.0", + "@babel/parser": "^7.24.0", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -2661,14 +3524,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", - "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", + "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.6", - "@babel/types": "^7.23.6" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -2689,9 +3552,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", + "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -4276,22 +5139,23 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", - "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", + "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.23.5", @@ -4300,8 +5164,8 @@ "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -4310,9 +5174,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", @@ -10191,17 +11055,13 @@ } }, "node_modules/@storybook/addon-onboarding": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-1.0.11.tgz", - "integrity": "sha512-0Sa7PJDsM6AANOWZX7vq3kgCbS9AZFjr3tfr3bLGfXviwIBKjoZDDdIErJkS3D4mNcDa78lYQvp3PTCKwLIJ9A==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.0.0-rc.1.tgz", + "integrity": "sha512-Nl12TaDUg0+KtH6c1WQ2ziUm2DAcHJ5h8I//N5/LcvItkvKhiqCcmfexOIxcaTkAxN8gM4vNPfNnCjccV9CEtA==", "dev": true, - "dependencies": { - "@storybook/telemetry": "^7.1.0", - "react-confetti": "^6.1.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, "node_modules/@storybook/addon-outline": { @@ -10231,9 +11091,9 @@ } }, "node_modules/@storybook/addon-themes": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/addon-themes/-/addon-themes-7.6.17.tgz", - "integrity": "sha512-i/dI3GKlJmQv0Di9HM3fKJvFIab55kvva0vXCGBkqSw3wYoZuq++npkWeDnjjZUvggV12H2RTdGqYwMCXB/GHg==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-themes/-/addon-themes-8.0.0-rc.1.tgz", + "integrity": "sha512-v8Qu1pxlksL5ucl+/fkBfs796eqoi7hCdR8wDCGHxY+z9ihWsyKCs9DMoOV4MpKgtGdzbAdejC72OpRXCBrd+g==", "dev": true, "dependencies": { "ts-dedent": "^2.0.0" @@ -11978,17 +12838,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/icons": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.5.tgz", + "integrity": "sha512-m3jnuE+zmkZy6K+cdUDzAoUuCJyl0fWCAXPCji7VZCH1TzFohyvnPqhc9JMkQpanej2TOW3wWXaplPzHghcBSg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@storybook/instrumenter": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-7.6.17.tgz", - "integrity": "sha512-zTLIPTt1fvlWgkIVUyQpF327iVE+EiPdpM0Or0aARaNfIikPRBTcjU+6cK96E+Ust2E1qKajEjIuv4i4lLQPng==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.0.0-rc.1.tgz", + "integrity": "sha512-YxB7UlU+s7D4Qjc2jor+pEBzGHFKCHgqaw15DoU1g2e6bSrzavg9NvcOkduqMUEh3hmuw0PXnLzHIC7epul1oQ==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.6.17", + "@storybook/preview-api": "8.0.0-rc.1", "@vitest/utils": "^0.34.6", "util": "^0.12.4" }, @@ -11998,13 +12871,13 @@ } }, "node_modules/@storybook/instrumenter/node_modules/@storybook/channels": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.17.tgz", - "integrity": "sha512-GFG40pzaSxk1hUr/J/TMqW5AFDDPUSu+HkeE/oqSWJbOodBOLJzHN6CReJS6y1DjYSZLNFt1jftPWZZInG/XUA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.0.0-rc.1.tgz", + "integrity": "sha512-RKAIVK7A1CgBAIALg3zp6KvVLwSv9FaCu2EWNH47krBD4gsaalzDcVa6PJrxqjRuPqmQLv1bkugOBhBKs1ZRyg==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.2.0", @@ -12016,9 +12889,9 @@ } }, "node_modules/@storybook/instrumenter/node_modules/@storybook/client-logger": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.17.tgz", - "integrity": "sha512-6WBYqixAXNAXlSaBWwgljWpAu10tPRBJrcFvx2gPUne58EeMM20Gi/iHYBz2kMCY+JLAgeIH7ZxInqwO8vDwiQ==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.0.0-rc.1.tgz", + "integrity": "sha512-YZ3F1LS8GVkdoE4HWIxtR854bR2gc45Qz30gNNwRAaiWmPEnPbcv2v8gCDIfvhn+dEiO0sBq6pO4rCS3ZgWW2w==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0" @@ -12029,9 +12902,9 @@ } }, "node_modules/@storybook/instrumenter/node_modules/@storybook/core-events": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.17.tgz", - "integrity": "sha512-AriWMCm/k1cxlv10f+jZ1wavThTRpLaN3kY019kHWbYT9XgaSuLU67G7GPr3cGnJ6HuA6uhbzu8qtqVCd6OfXA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.0.0-rc.1.tgz", + "integrity": "sha512-IOgwjetxT+6YCze5ZWnXuR1uDuJOq54RfhHSXBgO8RFPM9eZ2NTggAEaFcge8gL01CfOusWEeF2Ebl2buwuTbQ==", "dev": true, "dependencies": { "ts-dedent": "^2.0.0" @@ -12042,23 +12915,23 @@ } }, "node_modules/@storybook/instrumenter/node_modules/@storybook/preview-api": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.17.tgz", - "integrity": "sha512-wLfDdI9RWo1f2zzFe54yRhg+2YWyxLZvqdZnSQ45mTs4/7xXV5Wfbv3QNTtcdw8tT3U5KRTrN1mTfTCiRJc0Kw==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.0.0-rc.1.tgz", + "integrity": "sha512-1qR5PdEzVwrNDqh0NAQFeCaYhygMGSSkHYwZVIBfXzwB5196zQ7miPR6mQ/6oqa0LdRESSVS5GbfbovmvzwPQQ==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.17", + "@storybook/types": "8.0.0-rc.1", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -12068,13 +12941,12 @@ } }, "node_modules/@storybook/instrumenter/node_modules/@storybook/types": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.17.tgz", - "integrity": "sha512-GRY0xEJQ0PrL7DY2qCNUdIfUOE0Gsue6N+GBJw9ku1IUDFLJRDOF+4Dx2BvYcVCPI5XPqdWKlEyZdMdKjiQN7Q==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.0.0-rc.1.tgz", + "integrity": "sha512-Sebh9Ju3UDSXFuk9gOZH22AP6gbs2Tk+fdjhx8GFhUWNJkvG2qY7Sgk51z9tDpMSnkoKLC/QXg0NXJUIPCgoEg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@types/babel__core": "^7.0.0", + "@storybook/channels": "8.0.0-rc.1", "@types/express": "^4.7.0", "file-system-cache": "2.3.0" }, @@ -12159,9 +13031,9 @@ "license": "MIT" }, "node_modules/@storybook/nextjs": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-7.6.17.tgz", - "integrity": "sha512-bD9x6HzH/fxiFnghOQfDM60tNUNxFNVVCZi6OvTRxVVz/5xdqbVnYVOuaJeUSLuUnGs7ALYfx8+2OTJQ9NrwRA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-8.0.0-rc.1.tgz", + "integrity": "sha512-98Npq+eKTK7jCcQ7A3ACcyD/4QX8Rg9J1nh5BlWFrfb3v9lGrUtd3ewrMyffz5uHtJ5Oyenqc15pgb6dinDGJQ==", "dev": true, "dependencies": { "@babel/core": "^7.23.2", @@ -12177,16 +13049,19 @@ "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.2", "@babel/runtime": "^7.23.2", - "@storybook/addon-actions": "7.6.17", - "@storybook/builder-webpack5": "7.6.17", - "@storybook/core-common": "7.6.17", - "@storybook/core-events": "7.6.17", - "@storybook/node-logger": "7.6.17", - "@storybook/preset-react-webpack": "7.6.17", - "@storybook/preview-api": "7.6.17", - "@storybook/react": "7.6.17", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", + "@storybook/addon-actions": "8.0.0-rc.1", + "@storybook/builder-webpack5": "8.0.0-rc.1", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/preset-react-webpack": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/react": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", "@types/node": "^18.0.0", "@types/semver": "^7.3.4", + "babel-loader": "^9.1.3", "css-loader": "^6.7.3", "find-up": "^5.0.0", "fs-extra": "^11.1.0", @@ -12196,6 +13071,7 @@ "pnp-webpack-plugin": "^1.7.0", "postcss": "^8.4.21", "postcss-loader": "^7.0.2", + "react-refresh": "^0.14.0", "resolve-url-loader": "^5.0.0", "sass-loader": "^12.4.0", "semver": "^7.3.5", @@ -12207,23 +13083,19 @@ "tsconfig-paths-webpack-plugin": "^4.0.1" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@next/font": "^13.0.0|| ^14.0.0", - "next": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0", + "next": "^13.5.0 || ^14.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "@next/font": { - "optional": true - }, "typescript": { "optional": true }, @@ -12232,25 +13104,40 @@ } } }, - "node_modules/@storybook/nextjs/node_modules/@storybook/builder-webpack5": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.6.17.tgz", - "integrity": "sha512-GMaBd8/RzivuAmWrYSt9Rga3j8WLcu5LCMYiPVs+XKXsKAC8lTkV0WRWh8Nk6wTmfzsRQ2acwFjSG5oE4ClZKA==", + "node_modules/@storybook/nextjs/node_modules/@storybook/addon-actions": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.0.0-rc.1.tgz", + "integrity": "sha512-Xl8RA2obW0MJ6Y8hQxx8LmwoNt0gKT20UADYp+QusaV4prGw9XVf43eJWq704LO4dq7HFTah3hkDLwGhTsJ5hw==", "dev": true, "dependencies": { - "@babel/core": "^7.23.2", - "@storybook/channels": "7.6.17", - "@storybook/client-logger": "7.6.17", - "@storybook/core-common": "7.6.17", - "@storybook/core-events": "7.6.17", - "@storybook/core-webpack": "7.6.17", - "@storybook/node-logger": "7.6.17", - "@storybook/preview": "7.6.17", - "@storybook/preview-api": "7.6.17", - "@swc/core": "^1.3.82", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/nextjs/node_modules/@storybook/builder-webpack5": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.0.0-rc.1.tgz", + "integrity": "sha512-TyYc+Phb+92l5V+rjD3kx2RjWFE9tmQaX6okiOBHlmpgBeyDkTWZXhLAbOcTaEZs0kZ7V+OCpWbXxfTteD/fXg==", + "dev": true, + "dependencies": { + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/core-webpack": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/preview": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", "@types/node": "^18.0.0", "@types/semver": "^7.3.4", - "babel-loader": "^9.0.0", "browser-assert": "^1.2.1", "case-sensitive-paths-webpack-plugin": "^2.4.0", "cjs-module-lexer": "^1.2.3", @@ -12266,7 +13153,6 @@ "process": "^0.11.10", "semver": "^7.3.7", "style-loader": "^3.3.1", - "swc-loader": "^0.2.3", "terser-webpack-plugin": "^5.3.1", "ts-dedent": "^2.0.0", "url": "^0.11.0", @@ -12288,13 +13174,13 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/channels": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.17.tgz", - "integrity": "sha512-GFG40pzaSxk1hUr/J/TMqW5AFDDPUSu+HkeE/oqSWJbOodBOLJzHN6CReJS6y1DjYSZLNFt1jftPWZZInG/XUA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.0.0-rc.1.tgz", + "integrity": "sha512-RKAIVK7A1CgBAIALg3zp6KvVLwSv9FaCu2EWNH47krBD4gsaalzDcVa6PJrxqjRuPqmQLv1bkugOBhBKs1ZRyg==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.2.0", @@ -12306,9 +13192,9 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/client-logger": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.17.tgz", - "integrity": "sha512-6WBYqixAXNAXlSaBWwgljWpAu10tPRBJrcFvx2gPUne58EeMM20Gi/iHYBz2kMCY+JLAgeIH7ZxInqwO8vDwiQ==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.0.0-rc.1.tgz", + "integrity": "sha512-YZ3F1LS8GVkdoE4HWIxtR854bR2gc45Qz30gNNwRAaiWmPEnPbcv2v8gCDIfvhn+dEiO0sBq6pO4rCS3ZgWW2w==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0" @@ -12318,36 +13204,23 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/nextjs/node_modules/@storybook/core-client": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.6.17.tgz", - "integrity": "sha512-LuDbADK+DPNAOOCXOlvY09hdGVueXlDetsdOJ/DgYnSa9QSWv9Uv+F8QcEgR3QckZJbPlztKJIVLgP2n/Xkijw==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/preview-api": "7.6.17" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, "node_modules/@storybook/nextjs/node_modules/@storybook/core-common": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.6.17.tgz", - "integrity": "sha512-me2TP3Q9/qzqCLoDHUSsUF+VS1MHxfHbTVF6vAz0D/COTxzsxLpu9TxTbzJoBCxse6XRb6wWI1RgF1mIcjic7g==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-8.0.0-rc.1.tgz", + "integrity": "sha512-hRMOZ0HIYtM2WQx+kJPR4s2pZULMvla7xCHlczuy6/mtsDVd62H8IA7syvtrk/Tj2SxlrLO7l4JN5QdVhLryMg==", "dev": true, "dependencies": { - "@storybook/core-events": "7.6.17", - "@storybook/node-logger": "7.6.17", - "@storybook/types": "7.6.17", - "@types/find-cache-dir": "^3.2.1", - "@types/node": "^18.0.0", - "@types/node-fetch": "^2.6.4", - "@types/pretty-hrtime": "^1.0.0", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/csf-tools": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.0", + "cross-spawn": "^7.0.3", "esbuild": "^0.18.0", "esbuild-register": "^3.5.0", + "execa": "^5.0.0", "file-system-cache": "2.3.0", "find-cache-dir": "^3.0.0", "find-up": "^5.0.0", @@ -12360,7 +13233,11 @@ "pkg-dir": "^5.0.0", "pretty-hrtime": "^1.0.3", "resolve-from": "^5.0.0", - "ts-dedent": "^2.0.0" + "semver": "^7.3.7", + "tempy": "^1.0.1", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0", + "util": "^0.12.4" }, "funding": { "type": "opencollective", @@ -12368,9 +13245,9 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/core-events": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.17.tgz", - "integrity": "sha512-AriWMCm/k1cxlv10f+jZ1wavThTRpLaN3kY019kHWbYT9XgaSuLU67G7GPr3cGnJ6HuA6uhbzu8qtqVCd6OfXA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.0.0-rc.1.tgz", + "integrity": "sha512-IOgwjetxT+6YCze5ZWnXuR1uDuJOq54RfhHSXBgO8RFPM9eZ2NTggAEaFcge8gL01CfOusWEeF2Ebl2buwuTbQ==", "dev": true, "dependencies": { "ts-dedent": "^2.0.0" @@ -12381,14 +13258,14 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/core-webpack": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.6.17.tgz", - "integrity": "sha512-PyGrFhRM8sTONGwwLWLqBQ1HO+LBnVZ+5TOQO7ejQfdV2FWyNOzjBXm2e5jL/C6XlqiEhmL5pyHEyDBaQJQ3KA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.0.0-rc.1.tgz", + "integrity": "sha512-s57kgVhU56C7E5oU7JtV5jsIfjSX3qSBn2Aqao58HhCMpQHPYy+Ez8VuuS5o3WM654yImAPq/4gD3slTQqrfiA==", "dev": true, "dependencies": { - "@storybook/core-common": "7.6.17", - "@storybook/node-logger": "7.6.17", - "@storybook/types": "7.6.17", + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", "@types/node": "^18.0.0", "ts-dedent": "^2.0.0" }, @@ -12397,15 +13274,36 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/nextjs/node_modules/@storybook/docs-tools": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.6.17.tgz", - "integrity": "sha512-bYrLoj06adqklyLkEwD32C0Ww6t+9ZVvrJHiVT42bIhTRpFiFPAetl1a9KPHtFLnfduh4n2IxIr1jv32ThPDTA==", + "node_modules/@storybook/nextjs/node_modules/@storybook/csf-tools": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-8.0.0-rc.1.tgz", + "integrity": "sha512-WsrztCyi3Ij3oA00OGJslKGgev2Cyuh//+n2IKRGJVbjNO2xHKDFTYa4MEonUw376g3JUy1U6OavSVqbJsgVKg==", "dev": true, "dependencies": { - "@storybook/core-common": "7.6.17", - "@storybook/preview-api": "7.6.17", - "@storybook/types": "7.6.17", + "@babel/generator": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "@storybook/csf": "^0.1.2", + "@storybook/types": "8.0.0-rc.1", + "fs-extra": "^11.1.0", + "recast": "^0.23.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/nextjs/node_modules/@storybook/docs-tools": { + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-8.0.0-rc.1.tgz", + "integrity": "sha512-KmXVzD32fQ7wRfktTHobnczv/NreNFtHg2fKj6HZqrmL/TluDkIfF5MQMz7+u+gVz0OKV6REcwqLIVB5VKxEqg==", + "dev": true, + "dependencies": { + "@storybook/core-common": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", "@types/doctrine": "^0.0.3", "assert": "^2.1.0", "doctrine": "^3.0.0", @@ -12417,9 +13315,9 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/node-logger": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.6.17.tgz", - "integrity": "sha512-w59MQuXhhUNrUVmVkXhMwIg2nvFWjdDczLTwYLorhfsE36CWeUOY5QCZWQy0Qf/h+jz8Uo7Evy64qn18v9C4wA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-8.0.0-rc.1.tgz", + "integrity": "sha512-WFIK9NRclmSepPsTmVOcxzVGv/yyjAckiL3Z/iV2idwP4Qj/TT/FGFGAPs7oGSiQfgP80FMifDFN6tcZ0awpYQ==", "dev": true, "funding": { "type": "opencollective", @@ -12427,54 +13325,46 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/preset-react-webpack": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-7.6.17.tgz", - "integrity": "sha512-gn/LvIbll9loOkzwbFlxzOZGmJ6t1vF2/gfi+p/N/AifDYe8+LVM1QV4KRVKt6UEJwsQd79lKf7vPH92AQaKKQ==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.0.0-rc.1.tgz", + "integrity": "sha512-LbxngVsSAAKjMd4AtYROiLyaJ8tk22EuOIEPQ5r+dpcv92nTWLc7NHe83LrWAvxKizb0G1+T5QLLK7ZOjSKvKA==", "dev": true, "dependencies": { - "@babel/preset-flow": "^7.22.15", - "@babel/preset-react": "^7.22.15", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11", - "@storybook/core-webpack": "7.6.17", - "@storybook/docs-tools": "7.6.17", - "@storybook/node-logger": "7.6.17", - "@storybook/react": "7.6.17", + "@storybook/core-webpack": "8.0.0-rc.1", + "@storybook/docs-tools": "8.0.0-rc.1", + "@storybook/node-logger": "8.0.0-rc.1", + "@storybook/react": "8.0.0-rc.1", "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", "@types/node": "^18.0.0", "@types/semver": "^7.3.4", - "babel-plugin-add-react-displayname": "^0.0.5", "fs-extra": "^11.1.0", "magic-string": "^0.30.5", "react-docgen": "^7.0.0", - "react-refresh": "^0.14.0", + "resolve": "^1.22.8", "semver": "^7.3.7", "webpack": "5" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@babel/core": "^7.22.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, "typescript": { "optional": true } } }, "node_modules/@storybook/nextjs/node_modules/@storybook/preview": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.6.17.tgz", - "integrity": "sha512-LvkMYK/y6alGjwRVNDIKL1lFlbyZ0H0c8iAbcQkiMoaFiujMQyVswMDKlWcj42Upfr/B1igydiruomc+eUt0mw==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-8.0.0-rc.1.tgz", + "integrity": "sha512-n860bAvJDsTdLmfACra9Z0ZZSOgL9krrc6R4ocxO0qWSq6JnjWy8s5JrlXqm4i9tcB+821QcspHlSngMtSajzw==", "dev": true, "funding": { "type": "opencollective", @@ -12482,23 +13372,23 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/preview-api": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.17.tgz", - "integrity": "sha512-wLfDdI9RWo1f2zzFe54yRhg+2YWyxLZvqdZnSQ45mTs4/7xXV5Wfbv3QNTtcdw8tT3U5KRTrN1mTfTCiRJc0Kw==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.0.0-rc.1.tgz", + "integrity": "sha512-1qR5PdEzVwrNDqh0NAQFeCaYhygMGSSkHYwZVIBfXzwB5196zQ7miPR6mQ/6oqa0LdRESSVS5GbfbovmvzwPQQ==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.17", + "@storybook/types": "8.0.0-rc.1", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -12508,18 +13398,17 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/react": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-7.6.17.tgz", - "integrity": "sha512-lVqzQSU03rRJWYW+gK2gq6mSo3/qtnVICY8B8oP7gc36jVu4ksDIu45bTfukM618ODkUZy0vZe6T4engK3azjA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.0.0-rc.1.tgz", + "integrity": "sha512-0Aqzv46KiIJzAn48ON8sCDz02uQE0UxYWqrYV4I/QDGomcCArJUSHzw/umOIzJIidHhOwaijhlsAi7FHhmeiWA==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/core-client": "7.6.17", - "@storybook/docs-tools": "7.6.17", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/docs-tools": "8.0.0-rc.1", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.6.17", - "@storybook/react-dom-shim": "7.6.17", - "@storybook/types": "7.6.17", + "@storybook/preview-api": "8.0.0-rc.1", + "@storybook/react-dom-shim": "8.0.0-rc.1", + "@storybook/types": "8.0.0-rc.1", "@types/escodegen": "^0.0.6", "@types/estree": "^0.0.51", "@types/node": "^18.0.0", @@ -12531,12 +13420,13 @@ "lodash": "^4.17.21", "prop-types": "^15.7.2", "react-element-to-jsx-string": "^15.0.0", + "semver": "^7.3.7", "ts-dedent": "^2.0.0", "type-fest": "~2.19", "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "funding": { "type": "opencollective", @@ -12545,7 +13435,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "typescript": "*" + "typescript": ">= 4.2.x" }, "peerDependenciesMeta": { "typescript": { @@ -12554,9 +13444,9 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/react-dom-shim": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.6.17.tgz", - "integrity": "sha512-32Sa/G+WnvaPiQ1Wvjjw5UM9rr2c4GDohwCcWVv3/LJuiFPqNS6zglAtmnsrlIBnUwRBMLMh/ekCTdqMiUmfDw==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.0.0-rc.1.tgz", + "integrity": "sha512-TQK0Tn5R77+yp4BJSrStPOr81sKjHIGKv1LmxP6Ja3by2dC0jyepv4ydMXyaEJPFeMEwq5P1iXOpJLG3dAkBYw==", "dev": true, "funding": { "type": "opencollective", @@ -12568,13 +13458,12 @@ } }, "node_modules/@storybook/nextjs/node_modules/@storybook/types": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.17.tgz", - "integrity": "sha512-GRY0xEJQ0PrL7DY2qCNUdIfUOE0Gsue6N+GBJw9ku1IUDFLJRDOF+4Dx2BvYcVCPI5XPqdWKlEyZdMdKjiQN7Q==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.0.0-rc.1.tgz", + "integrity": "sha512-Sebh9Ju3UDSXFuk9gOZH22AP6gbs2Tk+fdjhx8GFhUWNJkvG2qY7Sgk51z9tDpMSnkoKLC/QXg0NXJUIPCgoEg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@types/babel__core": "^7.0.0", + "@storybook/channels": "8.0.0-rc.1", "@types/express": "^4.7.0", "file-system-cache": "2.3.0" }, @@ -12590,14 +13479,20 @@ "dev": true }, "node_modules/@storybook/nextjs/node_modules/@types/node": { - "version": "18.19.20", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.20.tgz", - "integrity": "sha512-SKXZvI375jkpvAj8o+5U2518XQv76mAsixqfXiVyWyXZbVWQK25RurFovYpVIxVzul0rZoH58V/3SkEnm7s3qA==", + "version": "18.19.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.21.tgz", + "integrity": "sha512-2Q2NeB6BmiTFQi4DHBzncSoq/cJMLDdhPaAoJFnFCyD9a8VPZRf7a1GAwp1Edb7ROaZc5Jz/tnZyL6EsWMRaqw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, + "node_modules/@storybook/nextjs/node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@storybook/nextjs/node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -12681,9 +13576,9 @@ } }, "node_modules/@storybook/nextjs/node_modules/magic-string": { - "version": "0.30.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", - "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -13286,21 +14181,20 @@ } }, "node_modules/@storybook/test": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/test/-/test-7.6.17.tgz", - "integrity": "sha512-WGrmUUtKiuq3bzDsN4MUvluGcX120jwczMik1GDTyxS+JBoe7P0t2Y8dDuVs/l3nZd1J7qY4z0RGxMDYqONIOw==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.0.0-rc.1.tgz", + "integrity": "sha512-yojmb5MBHSgIRuFQacNVTosyryfbsUBeM3YGHllOwOl7O2A72nwjyP5Zs73QmmZ9Z5zOENPRh/oDGlbinvdRIQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", - "@storybook/instrumenter": "7.6.17", - "@storybook/preview-api": "7.6.17", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", + "@storybook/instrumenter": "8.0.0-rc.1", + "@storybook/preview-api": "8.0.0-rc.1", "@testing-library/dom": "^9.3.1", - "@testing-library/jest-dom": "^6.1.3", - "@testing-library/user-event": "14.3.0", - "@types/chai": "^4", - "@vitest/expect": "^0.34.2", - "@vitest/spy": "^0.34.1", + "@testing-library/jest-dom": "^6.4.0", + "@testing-library/user-event": "^14.5.2", + "@vitest/expect": "1.1.3", + "@vitest/spy": "^1.1.3", "chai": "^4.3.7", "util": "^0.12.4" }, @@ -13310,13 +14204,13 @@ } }, "node_modules/@storybook/test/node_modules/@storybook/channels": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.6.17.tgz", - "integrity": "sha512-GFG40pzaSxk1hUr/J/TMqW5AFDDPUSu+HkeE/oqSWJbOodBOLJzHN6CReJS6y1DjYSZLNFt1jftPWZZInG/XUA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-8.0.0-rc.1.tgz", + "integrity": "sha512-RKAIVK7A1CgBAIALg3zp6KvVLwSv9FaCu2EWNH47krBD4gsaalzDcVa6PJrxqjRuPqmQLv1bkugOBhBKs1ZRyg==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.2.0", @@ -13328,9 +14222,9 @@ } }, "node_modules/@storybook/test/node_modules/@storybook/client-logger": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.6.17.tgz", - "integrity": "sha512-6WBYqixAXNAXlSaBWwgljWpAu10tPRBJrcFvx2gPUne58EeMM20Gi/iHYBz2kMCY+JLAgeIH7ZxInqwO8vDwiQ==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-8.0.0-rc.1.tgz", + "integrity": "sha512-YZ3F1LS8GVkdoE4HWIxtR854bR2gc45Qz30gNNwRAaiWmPEnPbcv2v8gCDIfvhn+dEiO0sBq6pO4rCS3ZgWW2w==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0" @@ -13341,9 +14235,9 @@ } }, "node_modules/@storybook/test/node_modules/@storybook/core-events": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.6.17.tgz", - "integrity": "sha512-AriWMCm/k1cxlv10f+jZ1wavThTRpLaN3kY019kHWbYT9XgaSuLU67G7GPr3cGnJ6HuA6uhbzu8qtqVCd6OfXA==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-8.0.0-rc.1.tgz", + "integrity": "sha512-IOgwjetxT+6YCze5ZWnXuR1uDuJOq54RfhHSXBgO8RFPM9eZ2NTggAEaFcge8gL01CfOusWEeF2Ebl2buwuTbQ==", "dev": true, "dependencies": { "ts-dedent": "^2.0.0" @@ -13354,23 +14248,23 @@ } }, "node_modules/@storybook/test/node_modules/@storybook/preview-api": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.6.17.tgz", - "integrity": "sha512-wLfDdI9RWo1f2zzFe54yRhg+2YWyxLZvqdZnSQ45mTs4/7xXV5Wfbv3QNTtcdw8tT3U5KRTrN1mTfTCiRJc0Kw==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.0.0-rc.1.tgz", + "integrity": "sha512-1qR5PdEzVwrNDqh0NAQFeCaYhygMGSSkHYwZVIBfXzwB5196zQ7miPR6mQ/6oqa0LdRESSVS5GbfbovmvzwPQQ==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@storybook/client-logger": "7.6.17", - "@storybook/core-events": "7.6.17", + "@storybook/channels": "8.0.0-rc.1", + "@storybook/client-logger": "8.0.0-rc.1", + "@storybook/core-events": "8.0.0-rc.1", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.17", + "@storybook/types": "8.0.0-rc.1", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "synchronous-promise": "^2.0.15", + "tiny-invariant": "^1.3.1", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -13380,13 +14274,12 @@ } }, "node_modules/@storybook/test/node_modules/@storybook/types": { - "version": "7.6.17", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.6.17.tgz", - "integrity": "sha512-GRY0xEJQ0PrL7DY2qCNUdIfUOE0Gsue6N+GBJw9ku1IUDFLJRDOF+4Dx2BvYcVCPI5XPqdWKlEyZdMdKjiQN7Q==", + "version": "8.0.0-rc.1", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-8.0.0-rc.1.tgz", + "integrity": "sha512-Sebh9Ju3UDSXFuk9gOZH22AP6gbs2Tk+fdjhx8GFhUWNJkvG2qY7Sgk51z9tDpMSnkoKLC/QXg0NXJUIPCgoEg==", "dev": true, "dependencies": { - "@storybook/channels": "7.6.17", - "@types/babel__core": "^7.0.0", + "@storybook/channels": "8.0.0-rc.1", "@types/express": "^4.7.0", "file-system-cache": "2.3.0" }, @@ -13396,9 +14289,9 @@ } }, "node_modules/@storybook/test/node_modules/@testing-library/user-event": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.3.0.tgz", - "integrity": "sha512-P02xtBBa8yMaLhK8CzJCIns8rqwnF6FxhR9zs810flHOBXUYCFjLd8Io1rQrAkQRWEmW2PGdZIEdMxf/KLsqFA==", + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", "dev": true, "engines": { "node": ">=12", @@ -13885,16 +14778,17 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "6.1.3", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.2.tgz", + "integrity": "sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==", "dev": true, - "license": "MIT", "dependencies": { - "@adobe/css-tools": "^4.3.0", + "@adobe/css-tools": "^4.3.2", "@babel/runtime": "^7.9.2", "aria-query": "^5.0.0", "chalk": "^3.0.0", "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", + "dom-accessibility-api": "^0.6.3", "lodash": "^4.17.15", "redent": "^3.0.0" }, @@ -13905,6 +14799,7 @@ }, "peerDependencies": { "@jest/globals": ">= 28", + "@types/bun": "latest", "@types/jest": ">= 28", "jest": ">= 28", "vitest": ">= 0.32" @@ -13913,6 +14808,9 @@ "@jest/globals": { "optional": true }, + "@types/bun": { + "optional": true + }, "@types/jest": { "optional": true }, @@ -13950,6 +14848,12 @@ "node": ">=8" } }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, "node_modules/@testing-library/jest-dom/node_modules/has-flag": { "version": "4.0.0", "dev": true, @@ -14128,12 +15032,6 @@ "resolved": "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.2.tgz", "integrity": "sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg==" }, - "node_modules/@types/chai": { - "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.12.tgz", - "integrity": "sha512-zNKDHG/1yxm8Il6uCCVsm+dRdEsJlFoDu73X17y09bId6UwoYww+vFBsAcRzl8knM1sab3Dp1VRikFQwDOtDDw==", - "dev": true - }, "node_modules/@types/classnames": { "version": "2.3.1", "dev": true, @@ -15157,26 +16055,85 @@ "license": "ISC" }, "node_modules/@vitest/expect": { - "version": "0.34.7", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.7.tgz", - "integrity": "sha512-G9iEtwrD6ZQ4MVHZufif9Iqz3eLtuwBBNx971fNAGPaugM7ftAWjQN+ob2zWhtzURp8RK3zGXOxVb01mFo3zAQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.1.3.tgz", + "integrity": "sha512-MnJqsKc1Ko04lksF9XoRJza0bGGwTtqfbyrsYv5on4rcEkdo+QgUdITenBQBUltKzdxW7K3rWh+nXRULwsdaVg==", "dev": true, "dependencies": { - "@vitest/spy": "0.34.7", - "@vitest/utils": "0.34.7", + "@vitest/spy": "1.1.3", + "@vitest/utils": "1.1.3", "chai": "^4.3.10" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/spy": { - "version": "0.34.7", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.7.tgz", - "integrity": "sha512-NMMSzOY2d8L0mcOt4XcliDOS1ISyGlAXuQtERWVOoVHnKwmG+kKhinAiGw3dTtMQWybfa89FG8Ucg9tiC/FhTQ==", + "node_modules/@vitest/expect/node_modules/@vitest/spy": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.1.3.tgz", + "integrity": "sha512-Ec0qWyGS5LhATFQtldvChPTAHv08yHIOZfiNcjwRQbFPHpkih0md9KAbs7TfeIfL7OFKoe7B/6ukBTqByubXkQ==", "dev": true, "dependencies": { - "tinyspy": "^2.1.1" + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/expect/node_modules/@vitest/utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.1.3.tgz", + "integrity": "sha512-Dyt3UMcdElTll2H75vhxfpZu03uFpXRCHxWnzcrFjZxT1kTbq8ALUYIeBgGolo1gldVdI0YSlQRacsqxTwNqwg==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/expect/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/expect/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/expect/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/@vitest/spy": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", + "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -23404,6 +24361,28 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/hast-util-parse-selector": { "version": "2.2.5", "license": "MIT", @@ -27947,6 +28926,34 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mdast-util-from-markdown": { "version": "2.0.0", "license": "MIT", @@ -28363,6 +29370,761 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "dev": true, + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-gfm-footnote/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-gfm-strikethrough/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/mdast-util-gfm-table/node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-gfm-table/node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table/node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table/node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-table/node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-gfm-table/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-gfm-task-list-item/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/mdast-util-gfm/node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm/node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm/node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm/node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm/node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/mdast-util-gfm/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-mdx": { "version": "2.0.1", "license": "MIT", @@ -28977,6 +30739,692 @@ ], "license": "MIT" }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dev": true, + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==", + "dev": true, + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-core-commonmark": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", + "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-subtokenize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", + "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.0.0.tgz", + "integrity": "sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dev": true, + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.0.1.tgz", + "integrity": "sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==", + "dev": true, + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-extension-gfm/node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm/node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, "node_modules/micromark-extension-mdx-expression": { "version": "1.0.8", "funding": [ @@ -33764,21 +36212,6 @@ "react-dom": ">=16.8.0" } }, - "node_modules/react-confetti": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", - "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", - "dev": true, - "dependencies": { - "tween-functions": "^1.2.0" - }, - "engines": { - "node": ">=10.18" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.1 || ^18.0.0" - } - }, "node_modules/react-contexify": { "version": "5.0.0", "license": "MIT", @@ -35045,6 +37478,66 @@ "jsesc": "bin/jsesc" } }, + "node_modules/rehype-external-links": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", + "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-is-element": "^3.0.0", + "is-absolute-url": "^4.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-external-links/node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/rehype-external-links/node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/rehype-external-links/node_modules/is-absolute-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rehype-external-links/node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-slug": { "version": "5.1.0", "license": "MIT", @@ -39738,12 +42231,6 @@ "win32" ] }, - "node_modules/tween-functions": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", - "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "license": "MIT", From e9763360a145d50f77ffe54ee4dd5f3af21fdd41 Mon Sep 17 00:00:00 2001 From: hallidayo <22655069+Hallidayo@users.noreply.github.com> Date: Tue, 5 Mar 2024 05:49:38 +0000 Subject: [PATCH 55/62] docs: nextjs missing createClient example code (#21532) added createClient function example Co-authored-by: Chris Gwilliams <517923+encima@users.noreply.github.com> --- .../getting-started/quickstarts/nextjs.mdx | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx b/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx index 0568426c37e..65ab0d417e3 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx @@ -92,6 +92,8 @@ hideToc: true + + ```ts app/notes/page.tsx import { createClient } from '@/utils/supabase/server'; @@ -103,6 +105,47 @@ hideToc: true } ``` + ```ts utils/supabase/server.ts + import { createServerClient, type CookieOptions } from '@supabase/ssr' + import { cookies } from 'next/headers' + + export function createClient() { + const cookieStore = cookies() + + return createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value + }, + set(name: string, value: string, options: CookieOptions) { + try { + cookieStore.set({ name, value, ...options }) + } catch (error) { + // The `set` method was called from a Server Component. + // This can be ignored if you have middleware refreshing + // user sessions. + } + }, + remove(name: string, options: CookieOptions) { + try { + cookieStore.set({ name, value: '', ...options }) + } catch (error) { + // The `delete` method was called from a Server Component. + // This can be ignored if you have middleware refreshing + // user sessions. + } + }, + }, + } + ) + } + ``` + + + From 4f7874edfe5c2d52c9efd7d8ef43889f3a05af9f Mon Sep 17 00:00:00 2001 From: Menushka Weeratunga <5711536+menushka@users.noreply.github.com> Date: Tue, 5 Mar 2024 01:04:26 -0500 Subject: [PATCH 56/62] docs: Add missing import (#21767) Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- apps/docs/content/guides/auth/server-side/nextjs.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/docs/content/guides/auth/server-side/nextjs.mdx b/apps/docs/content/guides/auth/server-side/nextjs.mdx index 080dadd151e..71f357f53c1 100644 --- a/apps/docs/content/guides/auth/server-side/nextjs.mdx +++ b/apps/docs/content/guides/auth/server-side/nextjs.mdx @@ -204,6 +204,7 @@ It's safe to trust `getUser()` because it sends a request to the Supabase Auth s ```ts middleware.ts import { updateSession } from '@/utils/supabase/middleware' +import { type NextRequest } from 'next/server' export async function middleware(request: NextRequest) { return await updateSession(request) From fb9e6aa9b1c90282a252dc41c52667c30ec92723 Mon Sep 17 00:00:00 2001 From: Minh Au Date: Mon, 4 Mar 2024 22:04:48 -0800 Subject: [PATCH 57/62] Sync NextJs Quick Start and Web App Tutorials (#21718) * rename 'web app tutorials' to 'web app demos' * replace auth helper with server-side auth * add more descriptive instructions * fix small typos * create a section on supabase utitlies * update middleware section to include utilities * update supabase auth ui to include the utilities * add a login/signup form * replace supabase auth ui section with a note * update PCKE section to use /auth/confirm route instead of /auth/callback * update Account Page section to use utilities and switch locations * update Sign out section to use utilities * update bonus section to include utilities * minor fixes * Apply suggestions from code review * format * format * fix js examples --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- .../NavigationMenu.constants.ts | 2 +- apps/docs/content/guides/getting-started.mdx | 2 +- .../getting-started/tutorials/with-nextjs.mdx | 1095 ++++++++++++----- 3 files changed, 792 insertions(+), 307 deletions(-) diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 8fca482d4a6..c96b1d55091 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -264,7 +264,7 @@ export const gettingstarted: NavMenuConstant = { ], }, { - name: 'Web app tutorials', + name: 'Web app demos', items: [ { name: 'Next.js', diff --git a/apps/docs/content/guides/getting-started.mdx b/apps/docs/content/guides/getting-started.mdx index 5265ed88ec6..5d59dbce971 100644 --- a/apps/docs/content/guides/getting-started.mdx +++ b/apps/docs/content/guides/getting-started.mdx @@ -183,7 +183,7 @@ hideToc: true })}
    -### Web app tutorials +### Web app demos
    { diff --git a/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx b/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx index 9c409a64564..39d061a003e 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx @@ -55,7 +55,7 @@ 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). +Create a `.env.local` file at the root of the project, and paste the API URL and the `anon` key that you copied [earlier](#get-the-api-keys). ```bash .env.local NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL @@ -67,280 +67,613 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY An optional step is to update the CSS file `app/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-user-management/app/globals.css). -### Supabase Auth Helpers +### Supabase Server-Side Auth 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](/docs/guides/auth/auth-helpers/nextjs) to make user management and data fetching within Next.js as easy as possible. +To better integrate with the framework, we've created the `@supabase/ssr` package for Server-Side Auth. It has all the functionalities to quickly configure your Supabase project to use cookies for storing user sessions. See the [Next.js Server-Side Auth guide](/docs/guides/auth/server-side/nextjs) for more information. -Install the auth helpers for Next.js +Install the package for Next.js. ```bash -npm install @supabase/auth-helpers-nextjs @supabase/supabase-js +npm install @supabase/ssr ``` +### Supabase utilities + +There are two different types of clients in Supabase: + +1. **Client Component client** - To access Supabase from Client Components, which run in the browser. +2. **Server Component client** - To access Supabase from Server Components, Server Actions, and Route Handlers, which run only on the server. + +It is recommended to create the following essential utilities files for creating clients, and organize them within `utils/supabase` at the root of the project. + + + + + +Create a `client.js` and a `server.js` with the following functionalities for client-side Supabase and server-side Supabase, respectively. + + + +```jsx utils/supabase/client.js +import { createBrowserClient } from '@supabase/ssr' + +export function createClient() { + // Create a supabase client on the browser with project's credentials + return createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ) +} +``` + +```jsx utils/supabase/server.js +import { createServerClient } from '@supabase/ssr' +import { cookies } from 'next/headers' + +export function createClient() { + const cookieStore = cookies() + + // Create a server's supabase client with newly configured cookie, + // which could be used to maintain user's session + return createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value + }, + set(name, value, options) { + try { + cookieStore.set({ name, value, ...options }) + } catch (error) { + // The `set` method was called from a Server Component. + // This can be ignored if you have middleware refreshing + // user sessions. + } + }, + remove(name, options) { + try { + cookieStore.set({ name, value: '', ...options }) + } catch (error) { + // The `delete` method was called from a Server Component. + // This can be ignored if you have middleware refreshing + // user sessions. + } + }, + }, + } + ) +} +``` + + + + + + + + + +```tsx utils/supabase/client.ts +import { createBrowserClient } from '@supabase/ssr' + +export function createClient() { + // Create a supabase client on the browser with project's credentials + return createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ) +} +``` + +```tsx utils/supabase/server.ts +import { createServerClient, type CookieOptions } from '@supabase/ssr' +import { cookies } from 'next/headers' + +export function createClient() { + const cookieStore = cookies() + + // Create a server's supabase client with newly configured cookie, + // which could be used to maintain user's session + return createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value + }, + set(name: string, value: string, options: CookieOptions) { + try { + cookieStore.set({ name, value, ...options }) + } catch (error) { + // The `set` method was called from a Server Component. + // This can be ignored if you have middleware refreshing + // user sessions. + } + }, + remove(name: string, options: CookieOptions) { + try { + cookieStore.set({ name, value: '', ...options }) + } catch (error) { + // The `delete` method was called from a Server Component. + // This can be ignored if you have middleware refreshing + // user sessions. + } + }, + }, + } + ) +} +``` + + + + + + + ### Next.js middleware - - +Since Server Components can't write cookies, you need middleware to refresh expired Auth tokens and store them. This is accomplished by: -Create a `middleware.js` file and include the following content to: +- Refreshing the Auth token with the call to `supabase.auth.getUser`. +- Passing the refreshed Auth token to Server Components through `request.cookies.set`, so they don't attempt to refresh the same token themselves. +- Passing the refreshed Auth token to the browser, so it replaces the old token. This is done with `response.cookies.set`. -- Verify if there is an authenticated Supabase user -- Validate if the user is authenticated and currently on the sign-in page, redirecting them to the `account` page -- Verify if the user is not authenticated and currently on the account page, redirecting them to the `sign-in` page. +You could also add a matcher, so that the middleware only runs on route that access Supabase. For more information, check out this [documentation](https://nextjs.org/docs/app/building-your-application/routing/middleware#matching-paths). -```tsx middleware.js -import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' -import { NextResponse } from 'next/server' + -export async function middleware(req) { - const res = NextResponse.next() - const supabase = createMiddlewareClient({ req, res }) +Be careful when protecting pages. The server gets the user session from the cookies, which can be spoofed by anyone. - const { - data: { user }, - } = await supabase.auth.getUser() +Always use `supabase.auth.getUser()` to protect pages and user data. - // if user is signed in and the current path is / redirect the user to /account - if (user && req.nextUrl.pathname === '/') { - return NextResponse.redirect(new URL('/account', req.url)) - } +_Never_ trust `supabase.auth.getSession()` inside server code such as middleware. It isn't guaranteed to revalidate the Auth token. - // if user is not signed in and the current path is not / redirect the user to / - if (!user && req.nextUrl.pathname !== '/') { - return NextResponse.redirect(new URL('/', req.url)) - } - - return res -} - -export const config = { - matcher: ['/', '/account'], -} -``` - - - - -Create a `middleware.ts` file and include the following content to: - -- Verify if there is an authenticated Supabase user -- Validate if the user is authenticated and currently on the sign-in page, redirecting them to the `account` page -- Verify if the user is not authenticated and currently on the account page, redirecting them to the `sign-in` page. - -```tsx middleware.ts -import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs' -import { NextResponse } from 'next/server' - -import type { NextRequest } from 'next/server' - -export async function middleware(req: NextRequest) { - const res = NextResponse.next() - const supabase = createMiddlewareClient({ req, res }) - - const { - data: { user }, - } = await supabase.auth.getUser() - - // if user is signed in and the current path is / redirect the user to /account - if (user && req.nextUrl.pathname === '/') { - return NextResponse.redirect(new URL('/account', req.url)) - } - - // if user is not signed in and the current path is not / redirect the user to / - if (!user && req.nextUrl.pathname !== '/') { - return NextResponse.redirect(new URL('/', req.url)) - } - - return res -} - -export const config = { - matcher: ['/', '/account'], -} -``` - - - - -### Set up a login component - -#### Supabase Auth UI - -We can use the [Supabase Auth UI](/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 @supabase/auth-ui-shared -``` - -Create an `AuthForm` client side component with the `Auth` component rendered within it: - - - - -```jsx app/auth-form.jsx -'use client' -import { Auth } from '@supabase/auth-ui-react' -import { ThemeSupa } from '@supabase/auth-ui-shared' -import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' - -export default function AuthForm() { - const supabase = createClientComponentClient() - - return ( - - ) -} -``` - - - - -```jsx app/auth-form.tsx -'use client' -import { Auth } from '@supabase/auth-ui-react' -import { ThemeSupa } from '@supabase/auth-ui-shared' -import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' -import { Database } from './database.types' - -export default function AuthForm() { - const supabase = createClientComponentClient() - - return ( - - ) -} -``` - - - - - - -If you are using TypeScript for this project, see [generating types](/docs/guides/api/rest/generating-types) to automatically generate types from your database tables. +It's safe to trust `getUser()` because it sends a request to the Supabase Auth server every time to revalidate the Auth token. -Add the `AuthForm` component to your home page + -```jsx app/page.js -import AuthForm from './auth-form' + -export default function Home() { +Create a `middleware.js` file at the project root and another one within the `utils/supabase` folder. The `utils/supabase` file contains the logic for updating the session. This is used by the `middleware.js` file, which is a Next.js convention. + + + +```jsx middleware.js +import { updateSession } from '@/utils/supabase/middleware' + +export async function middleware(request) { + // update user's auth session + return await updateSession(request) +} + +export const config = { + matcher: [ + /* + * Match all request paths except for the ones starting with: + * - _next/static (static files) + * - _next/image (image optimization files) + * - favicon.ico (favicon file) + * Feel free to modify this pattern to include more paths. + */ + '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)', + ], +} +``` + +```jsx utils/supabase/middleware.js +import { createServerClient } from '@supabase/ssr' +import { NextResponse } from 'next/server' + +export async function updateSession(request) { + let response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + + const supabase = createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY, + { + cookies: { + get(name) { + return request.cookies.get(name)?.value + }, + set(name, value, options) { + request.cookies.set({ + name, + value, + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + response.cookies.set({ + name, + value, + ...options, + }) + }, + remove(name, options) { + request.cookies.set({ + name, + value: '', + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + response.cookies.set({ + name, + value: '', + ...options, + }) + }, + }, + } + ) + + // refreshing the auth token + await supabase.auth.getUser() + + return response +} +``` + + + + + + + +Create a `middleware.ts` file at the project root and another one within the `util/ssupbase` folder. The `utils/supabase` file contains the logic for updating the session. This is used by the `middleware.js` file, which is a Next.js convention. + + + +```tsx middleware.ts +import { type NextRequest } from 'next/server' +import { updateSession } from '@/utils/supabase/middleware' + +export async function middleware(request: NextRequest) { + // update user's auth session + return await updateSession(request) +} + +export const config = { + matcher: [ + /* + * Match all request paths except for the ones starting with: + * - _next/static (static files) + * - _next/image (image optimization files) + * - favicon.ico (favicon file) + * Feel free to modify this pattern to include more paths. + */ + '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)', + ], +} +``` + +```tsx utils/supabase/middleware.ts +import { createServerClient, type CookieOptions } from '@supabase/ssr' +import { NextResponse, type NextRequest } from 'next/server' + +export async function updateSession(request: NextRequest) { + let response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + + const supabase = createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return request.cookies.get(name)?.value + }, + set(name: string, value: string, options: CookieOptions) { + request.cookies.set({ + name, + value, + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + response.cookies.set({ + name, + value, + ...options, + }) + }, + remove(name: string, options: CookieOptions) { + request.cookies.set({ + name, + value: '', + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + response.cookies.set({ + name, + value: '', + ...options, + }) + }, + }, + } + ) + + // refreshing the auth token + await supabase.auth.getUser() + + return response +} +``` + + + + + + + +## Set up a login page + +### Login and Signup form + +Create a login/signup page for your application: + + + + + +Create a new folder named `login`, containing a `page.jsx` file with a login/signup form. + +```jsx app/login/page.jsx +import { login, signup } from './actions' + +export default function LoginPage() { return ( -
    -
    -

    Supabase Auth + Storage

    -

    - Experience our Auth and Storage through a simple profile management example. Create a user - profile and upload an avatar image. Fast, simple, secure. -

    -
    -
    - -
    -
    + + + + + + + + ) } ``` +
    + + + +Create a new folder named `login`, containing a `page.jsx` file with a login/signup form. + +```tsx app/login/page.tsx +import { login, signup } from './actions' + +export default function LoginPage() { + return ( +
    + + + + + + + + ) +} +``` + +
    + +
    + +Navigate to `http://localhost:3000/login`. You should see your login form, but it's not yet hooked up to the actual login function. Next, you need to create the login/signup actions. They will: + +- Retrieve the user's information. +- Send that information to Supabase as a signup request, which in turns will send a confirmation email. +- Handle any error that arises. + + + +Note that cookies is called before any calls to Supabase, which opts fetch calls out of Next.js's caching. This is important for authenticated data fetches, to ensure that users get access only to their own data. + +See the Next.js docs to learn more about [opting out of data caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#opting-out-of-data-caching). + + + + + + + + + +```js app/login/action.js +'use server' + +import { revalidatePath } from 'next/cache' +import { redirect } from 'next/navigation' + +import { createClient } from '@/utils/supabase/server' + +export async function login(formData) { + const supabase = createClient() + + // type-casting here for convenience + // in practice, you should validate your inputs + const data = { + email: formData.get('email'), + password: formData.get('password'), + } + + const { error } = await supabase.auth.signInWithPassword(data) + + if (error) { + redirect('/error') + } + + revalidatePath('/', 'layout') + redirect('/account') +} + +export async function signup(formData) { + const supabase = createClient() + + const data = { + email: formData.get('email'), + password: formData.get('password'), + } + + const { error } = await supabase.auth.signUp(data) + + if (error) { + redirect('/error') + } + + revalidatePath('/', 'layout') + redirect('/account') +} +``` + +```jsx app/error/page.jsx +export default function ErrorPage() { + return

    Sorry, something went wrong

    +} +``` + +
    + +
    + + + + + +```ts app/login/action.ts +'use server' + +import { revalidatePath } from 'next/cache' +import { redirect } from 'next/navigation' + +import { createClient } from '@/utils/supabase/server' + +export async function login(formData: FormData) { + const supabase = createClient() + + // type-casting here for convenience + // in practice, you should validate your inputs + const data = { + email: formData.get('email') as string, + password: formData.get('password') as string, + } + + const { error } = await supabase.auth.signInWithPassword(data) + + if (error) { + redirect('/error') + } + + revalidatePath('/', 'layout') + redirect('/account') +} + +export async function signup(formData: FormData) { + const supabase = createClient() + + // type-casting here for convenience + // in practice, you should validate your inputs + const data = { + email: formData.get('email') as string, + password: formData.get('password') as string, + } + + const { error } = await supabase.auth.signUp(data) + + if (error) { + redirect('/error') + } + + revalidatePath('/', 'layout') + redirect('/account') +} +``` + +```tsx app/error/page.tsx +export default function ErrorPage() { + return

    Sorry, something went wrong

    +} +``` + +
    + +
    + +When you enter your email and password, you will receive an email with the title **Confirm Your Signup**. Congrats 🎉!!! + +
    + ### Proof Key for Code Exchange (PKCE) -As we are employing Proof Key for Code Exchange (PKCE) in our authentication flow, it is necessary to create a route handler responsible for exchanging the code for a session. +Upon sign up, an email will be sent to the user with a unique hash code. This key can then be sent back to the application for verification, thus authenticating the user. The method is referred to as Proof Key for Code Exchange (PKCE). As we are employing PKCE in our authentication flow, it is necessary to create a route handler responsible for exchanging the code for a session. In the following code snippet, we perform the following steps: -- Retrieve the code sent back from the Supabase Auth server using the `code` query parameter. +- Retrieve the code sent back from the Supabase Auth server using the `token_hash` query parameter. - Exchange this code for a session, which we store in our chosen storage mechanism (in this case, cookies). - Finally, we redirect the user to the `account` page. - - + -```js app/auth/callback/route.js -import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs' -import { cookies } from 'next/headers' -import { NextResponse } from 'next/server' +Did you know? You could also customize emails sent out to new users, including the email's looks, content, and query parameters. Check out the [settings of your project](/dashboard/project/_/auth/templates). -export async function GET(req) { - const cookieStore = cookies() - const supabase = createRouteHandlerClient({ cookies: () => cookieStore }) - const { searchParams } = new URL(req.url) - const code = searchParams.get('code') - - if (code) { - await supabase.auth.exchangeCodeForSession(code) - } - - return NextResponse.redirect(new URL('/account', req.url)) -} -``` - - - - -```ts app/auth/callback/route.ts -import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs' -import { cookies } from 'next/headers' -import { NextRequest, NextResponse } from 'next/server' - -export async function GET(req: NextRequest) { - const cookieStore = cookies() - const supabase = createRouteHandlerClient({ cookies: () => cookieStore }) - const { searchParams } = new URL(req.url) - const code = searchParams.get('code') - - if (code) { - await supabase.auth.exchangeCodeForSession(code) - } - - return NextResponse.redirect(new URL('/account', req.url)) -} -``` - - - - -### Sign out - -Let's create a route handler to handle the signout from the server side. + + -```js app/auth/signout/route.js -import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs' -import { cookies } from 'next/headers' -import { NextResponse } from 'next/server' - -export async function POST(req) { - const cookieStore = cookies() - const supabase = createRouteHandlerClient({ cookies: () => cookieStore }) - - // Check if we have a session - const { - data: { user }, - } = await supabase.auth.getUser() - - if (user) { - await supabase.auth.signOut() - } - - return NextResponse.redirect(new URL('/', req.url), { - status: 302, - }) -} -``` - - - - -```ts app/auth/signout/route.ts -import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs' -import { cookies } from 'next/headers' +```js app/auth/confirm/route.js import { type NextRequest, NextResponse } from 'next/server' -export async function POST(req: NextRequest) { - const cookieStore = cookies() - const supabase = createRouteHandlerClient({ cookies: () => cookieStore }) +import { createClient } from '@/utils/supabase/server' - // Check if we have a session - const { - data: { session }, - } = await supabase.auth.getSession() +// Creating a handler to a GET request to route /auth/confirm +export async function GET(request) { + const { searchParams } = new URL(request.url) + const token_hash = searchParams.get('token_hash') + const type = searchParams.get('type') + const next = '/account' - if (session) { - await supabase.auth.signOut() + // Create redirect link without the secret token + const redirectTo = request.nextUrl.clone() + redirectTo.pathname = next + redirectTo.searchParams.delete('token_hash') + redirectTo.searchParams.delete('type') + + if (token_hash && type) { + const supabase = createClient() + + const { error } = await supabase.auth.verifyOtp({ + type, + token_hash, + }) + if (!error) { + redirectTo.searchParams.delete('next') + return NextResponse.redirect(redirectTo) + } } - return NextResponse.redirect(new URL('/', req.url), { - status: 302, - }) + // return the user to an error page with some instructions + redirectTo.pathname = '/error' + return NextResponse.redirect(redirectTo) } ``` + + + +```ts app/auth/confirm/route.ts +import { type EmailOtpType } from '@supabase/supabase-js' +import { type NextRequest, NextResponse } from 'next/server' + +import { createClient } from '@/utils/supabase/server' + +// Creating a handler to a GET request to route /auth/confirm +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url) + const token_hash = searchParams.get('token_hash') + const type = searchParams.get('type') as EmailOtpType | null + const next = '/account' + + // Create redirect link without the secret token + const redirectTo = request.nextUrl.clone() + redirectTo.pathname = next + redirectTo.searchParams.delete('token_hash') + redirectTo.searchParams.delete('type') + + if (token_hash && type) { + const supabase = createClient() + + const { error } = await supabase.auth.verifyOtp({ + type, + token_hash, + }) + if (!error) { + redirectTo.searchParams.delete('next') + return NextResponse.redirect(redirectTo) + } + } + + // return the user to an error page with some instructions + redirectTo.pathname = '/error' + return NextResponse.redirect(redirectTo) +} +``` + + + ### Account page @@ -418,15 +781,18 @@ Let's create a new component for that called `AccountForm` within the `app/accou defaultActiveId="js" queryGroup="language" > + + + ```jsx app/account/account-form.jsx 'use client' import { useCallback, useEffect, useState } from 'react' -import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' +import { createClient } from '@/utils/supabase/client' export default function AccountForm({ user }) { - const supabase = createClientComponentClient() + const supabase = createClient() const [loading, setLoading] = useState(true) const [fullname, setFullname] = useState(null) const [username, setUsername] = useState(null) @@ -541,17 +907,22 @@ export default function AccountForm({ user }) { } ``` + + + + + ```tsx app/account/account-form.tsx 'use client' import { useCallback, useEffect, useState } from 'react' -import { Database } from '../database.types' -import { User, createClientComponentClient } from '@supabase/auth-helpers-nextjs' +import { createClient } from '@/utils/supabase/client' +import { type User } from '@supabase/supabase-js' export default function AccountForm({ user }: { user: User | null }) { - const supabase = createClientComponentClient() + const supabase = createClient() const [loading, setLoading] = useState(true) const [fullname, setFullname] = useState(null) const [username, setUsername] = useState(null) @@ -569,6 +940,7 @@ export default function AccountForm({ user }: { user: User | null }) { .single() if (error && status !== 406) { + console.log(error) throw error } @@ -675,7 +1047,10 @@ export default function AccountForm({ user }: { user: User | null }) { } ``` + + + Create an account page for the `AccountForm` component we just created @@ -687,16 +1062,15 @@ Create an account page for the `AccountForm` component we just created defaultActiveId="js" queryGroup="language" > + ```jsx app/account/page.jsx -import { createServerComponentClient } from '@supabase/auth-helpers-nextjs' -import { cookies } from 'next/headers' import AccountForm from './account-form' +import { createClient } from '@/utils/supabase/server' export default async function Account() { - const cookieStore = cookies() - const supabase = createServerComponentClient({ cookies: () => cookieStore }) + const supabase = createClient() const { data: { user }, @@ -707,16 +1081,15 @@ export default async function Account() { ``` + ```tsx app/account/page.tsx -import { createServerComponentClient } from '@supabase/auth-helpers-nextjs' -import { cookies } from 'next/headers' -import { Database } from '../database.types' import AccountForm from './account-form' +import { createClient } from '@/utils/supabase/server' export default async function Account() { - const supabase = createServerComponentClient({ cookies }) + const supabase = createClient() const { data: { user }, @@ -729,6 +1102,76 @@ export default async function Account() { +### Sign out + +Let's create a route handler to handle the signout from the server side. Make sure to check if the user is logged in first! + + + + + +```js app/auth/signout/route.js +import { createClient } from '@/utils/supabase/server' +import { revalidatePath } from 'next/cache' +import { NextResponse } from 'next/server' + +export async function POST(req) { + const supabase = createClient() + + // Check if a user's logged in + const { + data: { user }, + } = await supabase.auth.getUser() + + if (user) { + await supabase.auth.signOut() + } + + revalidatePath('/', 'layout') + return NextResponse.redirect(new URL('/login', req.url), { + status: 302, + }) +} +``` + + + + + +```ts app/auth/signout/route.ts +import { createClient } from '@/utils/supabase/server' +import { revalidatePath } from 'next/cache' +import { type NextRequest, NextResponse } from 'next/server' + +export async function POST(req: NextRequest) { + const supabase = createClient() + + // Check if a user's logged in + const { + data: { user }, + } = await supabase.auth.getUser() + + if (user) { + await supabase.auth.signOut() + } + + revalidatePath('/', 'layout') + return NextResponse.redirect(new URL('/login', req.url), { + status: 302, + }) +} +``` + + + + + ### Launch! Now that we have all the pages, route handlers and components in place, let's run this in a terminal window: @@ -755,17 +1198,18 @@ Let's create an avatar widget for the user so that they can upload a profile pho defaultActiveId="js" queryGroup="language" > + ```jsx app/account/avatar.jsx 'use client' import React, { useEffect, useState } from 'react' -import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' +import { createClient } from '@/utils/supabase/client' import Image from 'next/image' export default function Avatar({ uid, url, size, onUpload }) { - const supabase = createClientComponentClient() - const [avatarUrl, setAvatarUrl] = useState(null) + const supabase = createClient() + const [avatarUrl, setAvatarUrl] = useState(url) const [uploading, setUploading] = useState(false) useEffect(() => { @@ -848,15 +1292,14 @@ export default function Avatar({ uid, url, size, onUpload }) { ``` + ```tsx app/account/avatar.tsx 'use client' import React, { useEffect, useState } from 'react' -import { Database } from '../database.types' -import { createClientComponentClient } from '@supabase/auth-helpers-nextjs' +import { createClient } from '@/utils/supabase/client' import Image from 'next/image' -type Profiles = Database['public']['Tables']['profiles']['Row'] export default function Avatar({ uid, @@ -864,13 +1307,13 @@ export default function Avatar({ size, onUpload, }: { - uid: string - url: Profiles['avatar_url'] + uid: string | null + url: string | null size: number onUpload: (url: string) => void }) { - const supabase = createClientComponentClient() - const [avatarUrl, setAvatarUrl] = useState(url) + const supabase = createClient() + const [avatarUrl, setAvatarUrl] = useState(url) const [uploading, setUploading] = useState(false) useEffect(() => { @@ -953,13 +1396,24 @@ export default function Avatar({ ``` + ### Add the new widget And then we can add the widget to the `AccountForm` component: -```jsx app/account/account-form.js + + + + +```jsx app/account/account-form.jsx // Import the new component import Avatar from './avatar' @@ -969,7 +1423,7 @@ return (
    {/* Add to the body */} { @@ -982,6 +1436,37 @@ return ( ) ``` + + + + +```tsx app/account/account-form.tsx +// Import the new component +import Avatar from './avatar' + +// ... + +return ( +
    + {/* Add to the body */} + { + setAvatarUrl(url) + updateProfile({ fullname, username, website, avatar_url: url }) + }} + /> + {/* ... */} +
    +) +``` + +
    + + + ### Storage management From 64863f407f9026bf520164f875dffd164b7cef01 Mon Sep 17 00:00:00 2001 From: Tyler Date: Tue, 5 Mar 2024 15:06:07 +0900 Subject: [PATCH 58/62] docs: Add `params` option to reference docs so that non-js client libs can add parameters (#21708) * Adds params option for reference docs * move params below description * Apply suggestions from code review * Update apps/docs/spec/supabase_dart_v2.yml --- .../reference/RefFunctionSection.tsx | 4 +- apps/docs/spec/supabase_dart_v2.yml | 38 +++++++++++++++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/apps/docs/components/reference/RefFunctionSection.tsx b/apps/docs/components/reference/RefFunctionSection.tsx index 19d14023f54..983594113ad 100644 --- a/apps/docs/components/reference/RefFunctionSection.tsx +++ b/apps/docs/components/reference/RefFunctionSection.tsx @@ -22,7 +22,7 @@ const RefFunctionSection: React.FC = (props) => { const tsDefinition = hasTsRef && props.typeSpec ? extractTsDocNode(hasTsRef, props.typeSpec) : null - const parameters = hasTsRef && tsDefinition ? generateParameters(tsDefinition) : '' + const parameters = hasTsRef && tsDefinition ? generateParameters(tsDefinition) : item.params const shortText = hasTsRef && tsDefinition ? tsDefinition.signatures[0].comment.shortText : '' return ( @@ -51,7 +51,7 @@ const RefFunctionSection: React.FC = (props) => {
    )} - {/* // parameters */} + {/* parameters */} {parameters && (
    Parameters
    diff --git a/apps/docs/spec/supabase_dart_v2.yml b/apps/docs/spec/supabase_dart_v2.yml index 3657561a065..c10621ba3da 100644 --- a/apps/docs/spec/supabase_dart_v2.yml +++ b/apps/docs/spec/supabase_dart_v2.yml @@ -6,8 +6,6 @@ info: description: | Supabase Dart. - - definition: spec/enrichments/tsdoc_v2/combined.json slugPrefix: '/' specUrl: https://github.com/supabase/supabase/edit/master/apps/docs/spec/supabase_dart_v2.yml libraries: @@ -23,7 +21,41 @@ functions: The Supabase client is your entrypoint to the rest of the Supabase functionality and is the easiest way to interact with everything we offer within the Supabase ecosystem. - + params: + - name: url + isOptional: false + type: string + description: The unique Supabase URL which is supplied when you create a new project in your project dashboard. + - name: anonKey + isOptional: false + type: string + description: The unique Supabase Key which is supplied when you create a new project in your project dashboard. + - name: authOptions + isOptional: true + type: FlutterAuthClientOptions + description: Options to change the Auth behaviors. + subContent: + - name: authFlowType + isOptional: true + type: AuthFlowType + description: Whether to use the `pkce` flow or the `implicit` flow. Defaults to `pkce`. + - name: localStorage + isOptional: true + type: LocalStorage + description: Parameter to override the local storage to store auth tokens. + - name: autoRefreshToken + isOptional: true + type: boolean + description: Whether to automatically refresh the token when it expires. Defaults to `true`. + - name: realtimeClientOptions + isOptional: true + type: RealtimeClientOptions + description: Options to change the Realtime behaviors. + subContent: + - name: logLevel + isOptional: true + type: RealtimeLogLevel + description: Level of realtime server logs to to be logged. examples: - id: flutter-initialize name: For Flutter From 4d829bfb93f5b7a58c8034bb6edab244a1a56efa Mon Sep 17 00:00:00 2001 From: Leo <45669613+Hahlh@users.noreply.github.com> Date: Tue, 5 Mar 2024 07:27:20 +0100 Subject: [PATCH 59/62] Add missing import to nextjs.mdx (#21527) * Add missing import to nextjs.mdx * Update apps/docs/content/guides/auth/server-side/nextjs.mdx --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- apps/docs/content/guides/auth/server-side/nextjs.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/docs/content/guides/auth/server-side/nextjs.mdx b/apps/docs/content/guides/auth/server-side/nextjs.mdx index 71f357f53c1..fc5e8e8aced 100644 --- a/apps/docs/content/guides/auth/server-side/nextjs.mdx +++ b/apps/docs/content/guides/auth/server-side/nextjs.mdx @@ -203,6 +203,7 @@ It's safe to trust `getUser()` because it sends a request to the Supabase Auth s ```ts middleware.ts +import { type NextRequest } from 'next/server' import { updateSession } from '@/utils/supabase/middleware' import { type NextRequest } from 'next/server' From c7650b100ed11db0a2216d8c72a4ecbe0b312f46 Mon Sep 17 00:00:00 2001 From: Ryan Halliday Date: Tue, 5 Mar 2024 19:33:22 +1300 Subject: [PATCH 60/62] Update next.js setup docs email template (#21466) * Update next.js setup docs email template The email templates need to have the type parameter. The wording here is a bit clumsy but it's hard to convey succinctly. A variable for the email type would be kinda cool. I was getting 401 `AuthApiError: Email link is invalid or has expired` until I changed this for my `magiclink` * Update apps/docs/content/guides/auth/server-side/nextjs.mdx --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> --- apps/docs/content/guides/auth/server-side/nextjs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/content/guides/auth/server-side/nextjs.mdx b/apps/docs/content/guides/auth/server-side/nextjs.mdx index fc5e8e8aced..633ffaaeb66 100644 --- a/apps/docs/content/guides/auth/server-side/nextjs.mdx +++ b/apps/docs/content/guides/auth/server-side/nextjs.mdx @@ -402,7 +402,7 @@ If you have email confirmation turned on (the default), a new user will receive Change the email template to support a server-side authentication flow. -Go to the [Auth templates](https://supabase.com/dashboard/project/_/auth/templates) page in your dashboard. In each email template, change `{{ .ConfirmationURL }}` to `{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=signup`. +Go to the [Auth templates](https://supabase.com/dashboard/project/_/auth/templates) page in your dashboard. In the `Confirm signup` template, change `{{ .ConfirmationURL }}` to `{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=signup`. From 9a68e5a377eaed06e57355936e2063974253c078 Mon Sep 17 00:00:00 2001 From: Nick James <142161096+kitchenchem224@users.noreply.github.com> Date: Mon, 4 Mar 2024 22:38:20 -0800 Subject: [PATCH 61/62] Update with-svelte.mdx (#21432) ### Account page fixed sign out function --- .../content/guides/getting-started/tutorials/with-svelte.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx b/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx index e95078cce5f..b85eb77996c 100644 --- a/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx +++ b/apps/docs/content/guides/getting-started/tutorials/with-svelte.mdx @@ -117,7 +117,7 @@ Let's set up a Svelte component to manage logins and sign ups. We'll use Magic L 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.svelte`. -```html src/lib/Account.svelte +```tsx src/lib/Account.svelte