From 0f4ad7dad352eeee83097366cce1f3846480b820 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Tue, 5 Aug 2025 13:52:27 +0700 Subject: [PATCH 01/28] Factor in filters and sorts for export via CLI option (#37399) * Factor in filters and sorts for export via CLI option * Add align * Update * Smol fix --- .../grid/components/header/ExportDialog.tsx | 55 +++++++++++++----- .../grid/components/header/Header.tsx | 8 +-- .../TableEditorLayout/EntityListItem.tsx | 17 ++++-- .../TableEditorLayout/TableEditorMenu.tsx | 30 ++++++---- .../data/table-rows/table-rows-query.ts | 56 ++++++++++++------- .../pages/project/[ref]/editor/[id].tsx | 2 +- .../pages/project/[ref]/editor/index.tsx | 2 +- .../studio/pages/project/[ref]/editor/new.tsx | 2 +- 8 files changed, 115 insertions(+), 57 deletions(-) diff --git a/apps/studio/components/grid/components/header/ExportDialog.tsx b/apps/studio/components/grid/components/header/ExportDialog.tsx index 59ffe39bd9a..93aa9ef8ecc 100644 --- a/apps/studio/components/grid/components/header/ExportDialog.tsx +++ b/apps/studio/components/grid/components/header/ExportDialog.tsx @@ -1,8 +1,13 @@ +import { useState } from 'react' + import { useParams } from 'common' +import { Filter, Sort, SupaTable } from 'components/grid/types' import { getConnectionStrings } from 'components/interfaces/Connect/DatabaseSettings.utils' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' +import { getAllTableRowsSql } from 'data/table-rows/table-rows-query' import { pluckObjectFields } from 'lib/helpers' -import { useState } from 'react' +import { RoleImpersonationState, wrapWithRoleImpersonation } from 'lib/role-impersonation' +import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state' import { Button, cn, @@ -22,13 +27,25 @@ import { import { Admonition } from 'ui-patterns' interface ExportDialogProps { - table?: { name: string; schema: string } + table?: SupaTable + filters?: Filter[] + sorts?: Sort[] + ignoreRoleImpersonation?: boolean + open: boolean onOpenChange: (open: boolean) => void } -export const ExportDialog = ({ table, open, onOpenChange }: ExportDialogProps) => { +export const ExportDialog = ({ + table, + filters = [], + sorts = [], + ignoreRoleImpersonation = false, + open, + onOpenChange, +}: ExportDialogProps) => { const { ref: projectRef } = useParams() + const roleImpersonationState = useRoleImpersonationStateSnapshot() const [selectedTab, setSelectedTab] = useState('csv') @@ -48,10 +65,18 @@ export const ExportDialog = ({ table, open, onOpenChange }: ExportDialogProps) = }) const outputName = `${table?.name}_rows` + const queryChains = !table ? undefined : getAllTableRowsSql({ table, sorts, filters }) + const query = !!queryChains + ? ignoreRoleImpersonation + ? queryChains.toSql() + : wrapWithRoleImpersonation( + queryChains.toSql(), + roleImpersonationState as RoleImpersonationState + ) + : '' const csvExportCommand = ` -${connectionStrings.direct.psql} -c "COPY (SELECT * FROM "${table?.schema}"."${table?.name}") TO STDOUT WITH CSV HEADER DELIMITER ',';" > ${outputName}.csv -`.trim() +${connectionStrings.direct.psql} -c "COPY (${query}) TO STDOUT WITH CSV HEADER DELIMITER ',';" > ${outputName}.csv`.trim() const sqlExportCommand = ` pg_dump -h ${db_host} -p ${db_port} -d ${db_name} -U ${db_user} --table="${table?.schema}.${table?.name}" --data-only --column-inserts > ${outputName}.sql @@ -95,6 +120,12 @@ pg_dump -h ${db_host} -p ${db_port} -d ${db_name} -U ${db_user} --table="${table value={sqlExportCommand} className="[&_code]:text-[12px] [&_code]:text-foreground" /> + @@ -107,15 +138,11 @@ pg_dump -h ${db_host} -p ${db_port} -d ${db_name} -U ${db_user} --table="${table

{selectedTab === 'sql' && ( - -

- If you run into a server version mismatch error, you will need to update{' '} - pg_dump before running the command. -

-
+

+ Note: pg_dump needs to match your project's Postgres version. If you run + into a server version mismatch error, you will need to update pg_dump{' '} + before running the command. +

)} diff --git a/apps/studio/components/grid/components/header/Header.tsx b/apps/studio/components/grid/components/header/Header.tsx index baeeecc662f..bb401db90e8 100644 --- a/apps/studio/components/grid/components/header/Header.tsx +++ b/apps/studio/components/grid/components/header/Header.tsx @@ -504,11 +504,9 @@ const RowHeader = () => { Export - + Export as CSV Export as SQL - {/* [Joshen] Should make this available for all cases, but that'll involve updating - the Dialog's SQL output to be dynamic based on any filters applied */} {snap.allRowsSelected ? ( setShowExportModal(true)}>
@@ -535,7 +533,9 @@ const RowHeader = () => {
setShowExportModal(false)} /> diff --git a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx index e693516ccb8..c8ee912c07f 100644 --- a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx @@ -1,5 +1,5 @@ import saveAs from 'file-saver' -import { Clipboard, Copy, Download, Edit, Lock, MoreHorizontal, Trash } from 'lucide-react' +import { Clipboard, Copy, Download, Edit, Lock, MoreVertical, Trash } from 'lucide-react' import Link from 'next/link' import Papa from 'papaparse' import { toast } from 'sonner' @@ -30,6 +30,7 @@ import { useTableEditorStateSnapshot } from 'state/table-editor' import { createTabId, useTabsStateSnapshot } from 'state/tabs' import { Badge, + Button, cn, copyToClipboard, DropdownMenu, @@ -242,7 +243,7 @@ const EntityListItem: ItemRenderer = ({ isOpened: isOpened && !isPreview, isPreview, }), - 'px-4' + 'pl-4 pr-1' )} onDoubleClick={(e) => { e.preventDefault() @@ -285,8 +286,16 @@ const EntityListItem: ItemRenderer = ({ {canEdit && ( - - + + +
+ + {isValidEdgeFunction && ( + + )} +
)} From 47249dc8b45b14cd84d7ae467d65ac659e33ab95 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Tue, 5 Aug 2025 14:14:28 +0700 Subject: [PATCH 03/28] Add a CTA to run the command of the cron job (#37621) --- .../CronJobs/CronJobTableCell.tsx | 32 ++++++++- .../database-cron-job-run-mutation.ts | 66 +++++++++++++++++++ 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 apps/studio/data/database-cron-jobs/database-cron-job-run-mutation.ts diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobTableCell.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobTableCell.tsx index 8ea872bb67a..ea33c32f928 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobTableCell.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobTableCell.tsx @@ -1,9 +1,10 @@ import dayjs from 'dayjs' -import { Clipboard, Edit, MoreVertical, Trash } from 'lucide-react' +import { Clipboard, Edit, MoreVertical, Play, Trash } from 'lucide-react' import { parseAsString, useQueryState } from 'nuqs' import { useState } from 'react' import { toast } from 'sonner' +import { useDatabaseCronJobRunCommandMutation } from 'data/database-cron-jobs/database-cron-job-run-mutation' import { CronJob } from 'data/database-cron-jobs/database-cron-jobs-infinite-query' import { useDatabaseCronJobToggleMutation } from 'data/database-cron-jobs/database-cron-jobs-toggle-mutation' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' @@ -74,15 +75,29 @@ export const CronJobTableCell = ({ ? getNextRun(schedule, latest_run) : value + const { mutate: runCronJob, isLoading: isRunning } = useDatabaseCronJobRunCommandMutation({ + onSuccess: () => { + toast.success(`Command from "${jobname}" ran successfully`) + }, + }) + const { mutate: toggleDatabaseCronJob, isLoading: isToggling } = useDatabaseCronJobToggleMutation( { - onSuccess: () => { - toast.success('Successfully asdasd') + onSuccess: (_, vars) => { + toast.success(`Successfully ${vars.active ? 'enabled' : 'disabled'} "${jobname}"`) setShowToggleModal(false) }, } ) + const onRunCronJob = () => { + runCronJob({ + projectRef: project?.ref!, + connectionString: project?.connectionString, + jobId: jobid, + }) + } + const onConfirmToggle = () => { toggleDatabaseCronJob({ projectRef: project?.ref!, @@ -100,12 +115,23 @@ export const CronJobTableCell = ({ - - - - )} - - ) + return } const AuthLayout = ({ children }: PropsWithChildren<{}>) => { diff --git a/apps/studio/components/layouts/ProjectLayout/ProductMenuBar.tsx b/apps/studio/components/layouts/ProjectLayout/ProductMenuBar.tsx index b579a00c078..3895c1115a4 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProductMenuBar.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProductMenuBar.tsx @@ -1,21 +1,22 @@ import { PropsWithChildren } from 'react' +import { cn } from 'ui' interface ProductMenuBarProps { title: string + className?: string } -const ProductMenuBar = ({ title, children }: PropsWithChildren) => { +const ProductMenuBar = ({ title, children, className }: PropsWithChildren) => { return (

{title}

-
{children}
+
{children}
) } diff --git a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx index 1e2a94dc719..f183b8a9bb5 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx @@ -10,8 +10,8 @@ import { AIAssistant } from 'components/ui/AIAssistantPanel/AIAssistant' import { EditorPanel } from 'components/ui/EditorPanel/EditorPanel' import { Loading } from 'components/ui/Loading' import { ResourceExhaustionWarningBanner } from 'components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProject, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import { PROJECT_STATUS } from 'lib/constants' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' @@ -66,6 +66,7 @@ export interface ProjectLayoutProps { productMenu?: ReactNode selectedTable?: string resizableSidebar?: boolean + productMenuClassName?: string } const ProjectLayout = forwardRef>( @@ -79,13 +80,14 @@ const ProjectLayout = forwardRef { const router = useRouter() const [isClient, setIsClient] = useState(false) - const selectedOrganization = useSelectedOrganization() - const selectedProject = useSelectedProject() + const { data: selectedOrganization } = useSelectedOrganizationQuery() + const { data: selectedProject } = useSelectedProjectQuery() const { editorPanel, @@ -190,7 +192,9 @@ const ProjectLayout = forwardRef - {productMenu} + + {productMenu} + diff --git a/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx b/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx index f13ca0793be..c9b6b7a342f 100644 --- a/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx @@ -1,7 +1,8 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' +import { PropsWithChildren } from 'react' + import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' -import { PropsWithChildren } from 'react' import { ProjectLayoutWithAuth } from '../ProjectLayout/ProjectLayout' const TableEditorLayout = ({ children }: PropsWithChildren<{}>) => { @@ -16,7 +17,7 @@ const TableEditorLayout = ({ children }: PropsWithChildren<{}>) => { ) } - return <>{children} + return children } export default TableEditorLayout diff --git a/apps/studio/components/layouts/editors/EditorBaseLayout.tsx b/apps/studio/components/layouts/editors/EditorBaseLayout.tsx index 9f0da404d7f..27c4b4a41be 100644 --- a/apps/studio/components/layouts/editors/EditorBaseLayout.tsx +++ b/apps/studio/components/layouts/editors/EditorBaseLayout.tsx @@ -11,12 +11,18 @@ import { useEditorType } from './EditorsLayout.hooks' export interface ExplorerLayoutProps extends ComponentProps { children: ReactNode - hideTabs?: boolean title?: string product?: string + productMenuClassName?: string } -export const EditorBaseLayout = ({ children, title, product, ...props }: ExplorerLayoutProps) => { +export const EditorBaseLayout = ({ + children, + title, + product, + productMenuClassName, + productMenu, +}: ExplorerLayoutProps) => { const { ref } = useParams() const pathname = usePathname() const editor = useEditorType() @@ -28,7 +34,13 @@ export const EditorBaseLayout = ({ children, title, product, ...props }: Explore pathname === `/project/${ref}/editor` || pathname === `/project/${ref}/sql` || hasNoOpenTabs return ( - +
{ className="w-fit mt-4" onClick={() => setIsConfirmOptInModalOpen(true)} > - Update AI settings + Permission settings )} diff --git a/apps/studio/components/ui/ProductMenu/ProductMenu.tsx b/apps/studio/components/ui/ProductMenu/ProductMenu.tsx index 67cc2c49e39..d55a15a053b 100644 --- a/apps/studio/components/ui/ProductMenu/ProductMenu.tsx +++ b/apps/studio/components/ui/ProductMenu/ProductMenu.tsx @@ -10,7 +10,7 @@ interface ProductMenuProps { const ProductMenu = ({ page, menu }: ProductMenuProps) => { return ( -
+
{menu.map((group, idx) => (
diff --git a/apps/studio/pages/project/[ref]/editor/[id].tsx b/apps/studio/pages/project/[ref]/editor/[id].tsx index 3a1f9c8697a..6f11123aa8f 100644 --- a/apps/studio/pages/project/[ref]/editor/[id].tsx +++ b/apps/studio/pages/project/[ref]/editor/[id].tsx @@ -56,7 +56,11 @@ const TableEditorPage: NextPageWithLayout = () => { TableEditorPage.getLayout = (page) => ( - } product="Table Editor"> + } + product="Table Editor" + productMenuClassName="overflow-y-hidden" + > {page} diff --git a/apps/studio/pages/project/[ref]/editor/index.tsx b/apps/studio/pages/project/[ref]/editor/index.tsx index 71e4686868b..6ba1073515f 100644 --- a/apps/studio/pages/project/[ref]/editor/index.tsx +++ b/apps/studio/pages/project/[ref]/editor/index.tsx @@ -47,7 +47,11 @@ const TableEditorPage: NextPageWithLayout = () => { TableEditorPage.getLayout = (page) => ( - } product="Table Editor"> + } + product="Table Editor" + productMenuClassName="overflow-y-hidden" + > {page} diff --git a/apps/studio/pages/project/[ref]/editor/new.tsx b/apps/studio/pages/project/[ref]/editor/new.tsx index 48546300b92..ec76bdc6a49 100644 --- a/apps/studio/pages/project/[ref]/editor/new.tsx +++ b/apps/studio/pages/project/[ref]/editor/new.tsx @@ -27,7 +27,11 @@ const EditorNewPage: NextPageWithLayout = () => { EditorNewPage.getLayout = (page) => ( - } product="Table Editor"> + } + product="Table Editor" + productMenuClassName="overflow-y-hidden" + > {page} diff --git a/apps/studio/styles/main.scss b/apps/studio/styles/main.scss index 1fab429887c..9a0898e8eac 100644 --- a/apps/studio/styles/main.scss +++ b/apps/studio/styles/main.scss @@ -2,7 +2,6 @@ @tailwind components; @tailwind utilities; -@import './../../../packages/ui/build/css/source/global.css'; @import './../../../packages/ui/build/css/source/global.css'; @import './../../../packages/ui/build/css/themes/dark.css'; @import './../../../packages/ui/build/css/themes/light.css'; From a88a71f33943b5e609436f79ff12fff5da5819db Mon Sep 17 00:00:00 2001 From: Saxon Fletcher Date: Tue, 5 Aug 2025 17:46:55 +1000 Subject: [PATCH 05/28] truncate branch project card (#37679) --- .../components/interfaces/Home/ProjectList/ProjectCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx index bab4d0c394f..0f2283b1b97 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectCard.tsx @@ -65,7 +65,7 @@ const ProjectCard = ({
-

{githubRepository}

+

{githubRepository}

)}
From bab22d9e7e7bff1dc0a8c40acfd8845651730010 Mon Sep 17 00:00:00 2001 From: Chris Chinchilla Date: Tue, 5 Aug 2025 11:13:57 +0200 Subject: [PATCH 06/28] docs: Add react Router to SSr auth guide (#37514) * Clarify where to add utils folder * Add React Router * Revert "Clarify where to add utils folder" This reverts commit 89f72c6bea0038bd9b6a8eeb32e08ddaa3aba4e3. --- .../auth/server-side/creating-a-client.mdx | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/apps/docs/content/guides/auth/server-side/creating-a-client.mdx b/apps/docs/content/guides/auth/server-side/creating-a-client.mdx index b5f0276ac2d..7e8a38450e9 100644 --- a/apps/docs/content/guides/auth/server-side/creating-a-client.mdx +++ b/apps/docs/content/guides/auth/server-side/creating-a-client.mdx @@ -77,6 +77,14 @@ SUPABASE_URL=your_supabase_project_url SUPABASE_ANON_KEY=your_supabase_anon_key ``` + + + +```bash .env +SUPABASE_URL=your_supabase_project_url +SUPABASE_ANON_KEY=your_supabase_anon_key +``` + @@ -660,6 +668,105 @@ export default function Index() { + + + + + +```ts _index.tsx +import { LoaderFunctionArgs } from 'react-router' +import { createServerClient, parseCookieHeader, serializeCookieHeader } from '@supabase/ssr' + +export async function loader({ request }: LoaderFunctionArgs) { + const headers = new Headers() + + const supabase = createServerClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!, { + cookies: { + getAll() { + return parseCookieHeader(request.headers.get('Cookie') ?? '') + }, + setAll(cookiesToSet) { + cookiesToSet.forEach(({ name, value, options }) => + headers.append('Set-Cookie', serializeCookieHeader(name, value, options)) + ) + }, + }, + }) + + return new Response('...', { + headers, + }) +} +``` + + + + + +```ts _index.tsx +import { type ActionFunctionArgs } from '@react-router' +import { createServerClient, parseCookieHeader, serializeCookieHeader } from '@supabase/ssr' + +export async function action({ request }: ActionFunctionArgs) { + const headers = new Headers() + + const supabase = createServerClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!, { + cookies: { + getAll() { + return parseCookieHeader(request.headers.get('Cookie') ?? '') + }, + setAll(cookiesToSet) { + cookiesToSet.forEach(({ name, value, options }) => + headers.append('Set-Cookie', serializeCookieHeader(name, value, options)) + ) + }, + }, + }) + + return new Response('...', { + headers, + }) +} +``` + + + + + +```ts _index.tsx +import { type LoaderFunctionArgs } from "react-router"; +import { useLoaderData } from "react-router"; +import { createBrowserClient } from "@supabase/ssr"; + +export async function loader({}: LoaderFunctionArgs) { + return { + env: { + SUPABASE_URL: process.env.SUPABASE_URL!, + SUPABASE_ANON_KEY: process.env.SUPABASE_ANON_KEY!, + }, + }; +} + +export default function Index() { + const { env } = useLoaderData(); + + const supabase = createBrowserClient(env.SUPABASE_URL, env.SUPABASE_ANON_KEY); + + return ... +} +``` + + + + + + Date: Tue, 5 Aug 2025 02:31:32 -0700 Subject: [PATCH 07/28] Update `@deprecated` suggestions for `ui` package components (#36944) update deprecation hints This updates the deprecation notices for components in the `ui` package to follow this format: ``` /** @deprecated Use `import { } from "ui"` instead */ ``` The intent here is to be more explicit about what import a developer should be using instead to replace the deprecated component. Most of these notices were using a confusing relative path segment, which made it unclear as to which library the suggested replacement was coming from. --- packages/ui/src/components/Accordion/Accordion.tsx | 2 +- packages/ui/src/components/Alert/Alert.tsx | 2 +- packages/ui/src/components/Breadcrumb/Breadcrumb.tsx | 2 +- packages/ui/src/components/Checkbox/Checkbox.tsx | 2 +- packages/ui/src/components/Collapsible/Collapsible.tsx | 2 +- packages/ui/src/components/Form/Form.tsx | 2 +- packages/ui/src/components/Input/Input.tsx | 2 +- packages/ui/src/components/InputNumber/InputNumber.tsx | 2 +- packages/ui/src/components/InputOld/Input.js | 2 +- packages/ui/src/components/Listbox/Listbox2.tsx | 2 +- packages/ui/src/components/Modal/Modal.tsx | 2 +- packages/ui/src/components/Popover/Popover.tsx | 2 +- packages/ui/src/components/Radio/Radio.tsx | 2 +- packages/ui/src/components/RadioOld/Radio.js | 2 +- packages/ui/src/components/Select/Select.tsx | 2 +- packages/ui/src/components/Tabs/Tabs.tsx | 2 +- packages/ui/src/components/Toggle/Toggle.tsx | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/ui/src/components/Accordion/Accordion.tsx b/packages/ui/src/components/Accordion/Accordion.tsx index 26a1629099c..4b793744c12 100644 --- a/packages/ui/src/components/Accordion/Accordion.tsx +++ b/packages/ui/src/components/Accordion/Accordion.tsx @@ -39,7 +39,7 @@ export interface AccordionProps { } /** - * @deprecated Use ./Accordion_Shadcn_ instead + * @deprecated Use `import { Accordion_Shadcn_ } from "ui"` instead */ function Accordion({ children, diff --git a/packages/ui/src/components/Alert/Alert.tsx b/packages/ui/src/components/Alert/Alert.tsx index 34f40e9d2f0..1c49c76c460 100644 --- a/packages/ui/src/components/Alert/Alert.tsx +++ b/packages/ui/src/components/Alert/Alert.tsx @@ -27,7 +27,7 @@ const icons: Record = { } /** - * @deprecated Use Alert_Shadcn_. For studio use Admonition + * @deprecated Use `import { Alert_Shadcn_ } from "ui"` instead. For studio use `Admonition` */ export function Alert({ variant = 'neutral', diff --git a/packages/ui/src/components/Breadcrumb/Breadcrumb.tsx b/packages/ui/src/components/Breadcrumb/Breadcrumb.tsx index 35a06b85221..7de226f7170 100644 --- a/packages/ui/src/components/Breadcrumb/Breadcrumb.tsx +++ b/packages/ui/src/components/Breadcrumb/Breadcrumb.tsx @@ -10,7 +10,7 @@ interface Props { } /** - * @deprecated Use ./Breadcrumb_shadcn_ instead + * @deprecated Use `import { Breadcrumb_shadcn_ } from "ui"` instead */ const Breadcrumb = ({ className, style, children, spacing = 'small' }: Props) => { let classes = [BreadcrumbStyle['sbui-breadcrumb--container']] diff --git a/packages/ui/src/components/Checkbox/Checkbox.tsx b/packages/ui/src/components/Checkbox/Checkbox.tsx index 0f37e7022c2..f98fafb97ce 100644 --- a/packages/ui/src/components/Checkbox/Checkbox.tsx +++ b/packages/ui/src/components/Checkbox/Checkbox.tsx @@ -36,7 +36,7 @@ interface GroupProps { } /** - * @deprecated Use ./Checkbox_shadcn_ instead + * @deprecated Use `import { Checkbox_shadcn_ } from "ui"` instead */ function Group({ id, diff --git a/packages/ui/src/components/Collapsible/Collapsible.tsx b/packages/ui/src/components/Collapsible/Collapsible.tsx index 88da35cb689..cbc4941a821 100644 --- a/packages/ui/src/components/Collapsible/Collapsible.tsx +++ b/packages/ui/src/components/Collapsible/Collapsible.tsx @@ -9,7 +9,7 @@ export interface CollapsibleProps extends RadixCollapsible.CollapsibleProps { } /** - * @deprecated Use ./Collapsible_shadcn_ instead + * @deprecated Use `import { Collapsible_shadcn_ } from "ui"` instead */ export const Collapsible = ({ open = undefined, diff --git a/packages/ui/src/components/Form/Form.tsx b/packages/ui/src/components/Form/Form.tsx index 781d3da032f..47bd2c8202c 100644 --- a/packages/ui/src/components/Form/Form.tsx +++ b/packages/ui/src/components/Form/Form.tsx @@ -32,7 +32,7 @@ function errorReducer(state: any, action: any) { } /** - * @deprecated Use ./Form_shadcn_ instead + * @deprecated Use `import { Form_shadcn_ } from "ui"` instead */ export default function Form({ validate, ...props }: Props) { const [fieldLevelErrors, dispatchErrors] = useReducer(errorReducer, null) diff --git a/packages/ui/src/components/Input/Input.tsx b/packages/ui/src/components/Input/Input.tsx index d827478f87e..35f21c2aa8a 100644 --- a/packages/ui/src/components/Input/Input.tsx +++ b/packages/ui/src/components/Input/Input.tsx @@ -38,7 +38,7 @@ export interface Props } /** - * @deprecated Use ./Input_shadcn_ instead or ./ui-patterns/data-inputs/input + * @deprecated Use `import { Input_shadcn_ } from "ui"` instead or ./ui-patterns/data-inputs/input */ function Input({ autoComplete, diff --git a/packages/ui/src/components/InputNumber/InputNumber.tsx b/packages/ui/src/components/InputNumber/InputNumber.tsx index 91501de58ae..e4aad0c0f75 100644 --- a/packages/ui/src/components/InputNumber/InputNumber.tsx +++ b/packages/ui/src/components/InputNumber/InputNumber.tsx @@ -27,7 +27,7 @@ export interface Props extends Omit, } /** - * @deprecated Use ./Input_shadcn_ with type="number" instead or ./ui-patterns/data-inputs/input with type="number" + * @deprecated Use `import { Input_shadcn_ } from "ui"` with `type="number"` instead or ./ui-patterns/data-inputs/input with `type="number"` */ function InputNumber({ defaultValue, diff --git a/packages/ui/src/components/InputOld/Input.js b/packages/ui/src/components/InputOld/Input.js index 8ccf6b8bd46..00c287a4d64 100644 --- a/packages/ui/src/components/InputOld/Input.js +++ b/packages/ui/src/components/InputOld/Input.js @@ -5,7 +5,7 @@ import './Input.css' export const SIZES = ['small', 'medium'] /** - * @deprecated Use ./Input_shadcn_ with type="number" instead or ./ui-patterns/data-inputs/input with type="number" + * @deprecated Use `import { Input_shadcn_ } from "ui"` with `type="number"` instead or ./ui-patterns/data-inputs/input with `type="number"` */ const Input = ({ className = '', diff --git a/packages/ui/src/components/Listbox/Listbox2.tsx b/packages/ui/src/components/Listbox/Listbox2.tsx index f6e90ad0dcb..2b4aa34a328 100644 --- a/packages/ui/src/components/Listbox/Listbox2.tsx +++ b/packages/ui/src/components/Listbox/Listbox2.tsx @@ -38,7 +38,7 @@ export interface Props extends Omit } /** - * @deprecated Use ./Select_shadcn_ or follow ComboBox convention or use ./ui-patterns/multi-select + * @deprecated Use `import { Select_shadcn_ } from "ui"` or follow ComboBox convention or use ./ui-patterns/multi-select */ function Listbox({ children, diff --git a/packages/ui/src/components/Modal/Modal.tsx b/packages/ui/src/components/Modal/Modal.tsx index ebdf78b5e22..df2b7adfd9d 100644 --- a/packages/ui/src/components/Modal/Modal.tsx +++ b/packages/ui/src/components/Modal/Modal.tsx @@ -62,7 +62,7 @@ interface ModalType Separator: React.ComponentType } -/** @deprecated use instead */ +/** @deprecated Use `import { Dialog } from "ui"` instead */ const Modal = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef & ModalProps diff --git a/packages/ui/src/components/Popover/Popover.tsx b/packages/ui/src/components/Popover/Popover.tsx index faea74be735..59a3cf4aa2d 100644 --- a/packages/ui/src/components/Popover/Popover.tsx +++ b/packages/ui/src/components/Popover/Popover.tsx @@ -30,7 +30,7 @@ interface RootProps { } /** - * @deprecated Use ./Popover_shadcn_ instead + * @deprecated Use `import { Popover_shadcn_ } from "ui"` instead */ function Popover({ align = 'center', diff --git a/packages/ui/src/components/Radio/Radio.tsx b/packages/ui/src/components/Radio/Radio.tsx index 7fa77a8a23b..19ecc83375c 100644 --- a/packages/ui/src/components/Radio/Radio.tsx +++ b/packages/ui/src/components/Radio/Radio.tsx @@ -34,7 +34,7 @@ interface GroupProps { } /** - * @deprecated Use ./RadioGroup_Shadcn_ instead + * @deprecated Use `import { RadioGroup_Shadcn_ } from "ui"` instead */ function RadioGroup({ id, diff --git a/packages/ui/src/components/RadioOld/Radio.js b/packages/ui/src/components/RadioOld/Radio.js index bab2deab778..8601699b2f4 100644 --- a/packages/ui/src/components/RadioOld/Radio.js +++ b/packages/ui/src/components/RadioOld/Radio.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types' import './Radio.css' /** - * @deprecated Use ./RadioGroupItem_Shadcn_ and ./RadioGroup_Shadcn_ instead + * @deprecated Use `import { RadioGroup_Shadcn_, RadioGroupItem_Shadcn_ } from "ui"` instead */ const Radio = ({ className = '', label = '', containerClassName = '', children, ...props }) => { return ( diff --git a/packages/ui/src/components/Select/Select.tsx b/packages/ui/src/components/Select/Select.tsx index d6d40e73e19..5794abf5c01 100644 --- a/packages/ui/src/components/Select/Select.tsx +++ b/packages/ui/src/components/Select/Select.tsx @@ -41,7 +41,7 @@ export interface Props extends Omit export const ColLayout = (props: any) =>
{props.children}
/** - * @deprecated Use ./Select_shadcn_ instead + * @deprecated Use `import { Select_shadcn_ } from "ui"` instead */ function Select({ autoComplete, diff --git a/packages/ui/src/components/Tabs/Tabs.tsx b/packages/ui/src/components/Tabs/Tabs.tsx index 7d09ba8440f..eb96b4bfa7d 100644 --- a/packages/ui/src/components/Tabs/Tabs.tsx +++ b/packages/ui/src/components/Tabs/Tabs.tsx @@ -38,7 +38,7 @@ interface TabsSubComponents { } /** - * @deprecated Use ./Tabs_shadcn_ instead + * @deprecated Use `import { Tabs_shadcn_ } from "ui"` instead */ const Tabs: React.FC> & TabsSubComponents = ({ defaultActiveId, diff --git a/packages/ui/src/components/Toggle/Toggle.tsx b/packages/ui/src/components/Toggle/Toggle.tsx index 658e9e567d4..3093b267436 100644 --- a/packages/ui/src/components/Toggle/Toggle.tsx +++ b/packages/ui/src/components/Toggle/Toggle.tsx @@ -27,7 +27,7 @@ interface Props extends Omit, 'size'> { } /** - * @deprecated Use ./Switch instead + * @deprecated Use `import { Switch } from "ui"` instead */ function Toggle({ disabled, From 61dedfa76f2838281c5dcbcc8b057c3e0cb6d94d Mon Sep 17 00:00:00 2001 From: Michael Ong Date: Tue, 5 Aug 2025 18:33:32 +0800 Subject: [PATCH 08/28] Chore/add e2e test for database (#37452) * chore: add tests for database * chore: add final tests and some refactoring * chore: update playwright config --- .../Functions/CreateFunction/index.tsx | 2 +- .../Functions/FunctionsList/FunctionList.tsx | 7 +- .../interfaces/Database/Indexes/Indexes.tsx | 1 + .../Database/Schemas/SchemaGraph.tsx | 1 + .../Triggers/TriggersList/TriggerList.tsx | 7 +- e2e/studio/features/database.spec.ts | 772 ++++++++++++++++++ e2e/studio/playwright.config.ts | 1 + e2e/studio/utils/wait-for-response.ts | 15 + 8 files changed, 803 insertions(+), 3 deletions(-) create mode 100644 e2e/studio/features/database.spec.ts create mode 100644 e2e/studio/utils/wait-for-response.ts diff --git a/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx b/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx index d481d68ea27..f4c4932120e 100644 --- a/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx +++ b/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx @@ -186,7 +186,7 @@ const CreateFunction = ({ func, visible, setVisible }: CreateFunctionProps) => { layout="horizontal" > - + )} diff --git a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx index f5de47e02cb..84ee90a9da9 100644 --- a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx +++ b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx @@ -112,7 +112,12 @@ const FunctionList = ({ {canUpdateFunctions ? ( - {!isSchemaLocked && ( -
- -
-
-``` - - +<$CodeSample +path="user-management/svelte-user-management/src/lib/Auth.svelte" +meta="name=src/lib/Auth.svelte" +/> ### Account page -After a user is signed in we can allow them to edit their profile details and manage their account. -Let's create a new component for that called `Account.svelte`. +After a user is signed in, allow them to edit their profile details and manage their account. +Create a new component for that called `Account.svelte`. -<$CodeTabs> - -```tsx name=src/lib/Account.svelte - - -
-
Email: {session.user.email}
-
- - -
-
- - -
-
- -
- -
-``` - - +<$CodeSample +path="/user-management/svelte-user-management/src/lib/Account.svelte" +lines={[[1, 4], [7, 11], [14, 33], [34,53], [55,73], [75,-1]]} +meta="src/lib/Account.svelte" +/> ### Launch! -Now that we have all the components in place, let's update `App.svelte`: +Now that you have all the components in place, update `App.svelte`: -<$CodeTabs> - -```html name=src/App.svelte - - -
- {#if !session} - - {:else} - - {/if} -
-``` - - +<$CodeSample +path="user-management/svelte-user-management/src/App.svelte" +meta="name=src/App.svelte" +/> Once that's done, run this in a terminal window: @@ -273,7 +98,7 @@ And then open the browser to [localhost:5173](http://localhost:5173) and you sho -Svelte uses Vite and the default port is `5173`, Supabase uses `port 3000`. To change the redirection port for Supabase go to: `Authentication > Settings` and change the `Site Url` to `http://localhost:5173/` +Svelte uses Vite and the default port is `5173`, Supabase uses `port 3000`. To change the redirection port for Supabase go to: **Authentication > URL Configuration** and change the **Site URL** to `http://localhost:5173/` @@ -285,118 +110,21 @@ Every Supabase project is configured with [Storage](/docs/guides/storage) for ma ### Create an upload widget -Let's create an avatar for the user so that they can upload a profile photo. We can start by creating a new component: +Create an avatar for the user so that they can upload a profile photo. Start by creating a new component: -<$CodeTabs> - -```html name=src/lib/Avatar.svelte - - -
- {#if avatarUrl} {avatarUrl {:else} -
- {/if} -
- - - - -
-
-``` - - +<$CodeSample +path="user-management/svelte-user-management/src/lib/Avatar.svelte" +meta="name=src/lib/Avatar.svelte" +/> ### Add the new widget -And then we can add the widget to the Account page: +And then you can add the widget to the Account page: -<$CodeTabs> - -```html name=src/lib/Account.svelte - - -
- - - - - -``` - - +<$CodeSample +path="/user-management/svelte-user-management/src/lib/Account.svelte" +lines={[[1,1], [5,5], [71,73], [74,74], [92,-1]]} +meta="src/lib/Account.svelte" +/> At this stage you have a fully functional application! diff --git a/apps/docs/features/directives/CodeSample.ts b/apps/docs/features/directives/CodeSample.ts index 952597c0b9f..d962ca8486a 100644 --- a/apps/docs/features/directives/CodeSample.ts +++ b/apps/docs/features/directives/CodeSample.ts @@ -344,6 +344,8 @@ function matchLang(lang: string) { return 'swift' case 'sql': return 'sql' + case 'svelte': + return 'svelte' default: return null } diff --git a/examples/user-management/svelte-user-management/package-lock.json b/examples/user-management/svelte-user-management/package-lock.json index c4e3bb78e65..c68ba1f838c 100644 --- a/examples/user-management/svelte-user-management/package-lock.json +++ b/examples/user-management/svelte-user-management/package-lock.json @@ -1,381 +1,1029 @@ { - "name": "svelte-user-management", + "name": "supabase-svelte", "version": "0.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "svelte-user-management", + "name": "supabase-svelte", "version": "0.0.0", "dependencies": { - "@supabase/supabase-js": "^2.0.4" + "@supabase/supabase-js": "^2.53.0" }, "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^1.0.1", - "@tsconfig/svelte": "^3.0.0", - "svelte": "^3.49.0", - "svelte-check": "^2.8.0", - "svelte-preprocess": "^4.10.7", - "tslib": "^2.4.0", - "typescript": "^4.6.4", - "vite": "^3.2.7" + "@sveltejs/vite-plugin-svelte": "^6.1.0", + "@tsconfig/svelte": "^5.0.4", + "svelte": "^5.37.3", + "svelte-check": "^4.3.1", + "typescript": "~5.9.2", + "vite": "^7.0.6" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", + "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", + "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", + "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", "cpu": [ - "loong64" + "arm64" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", + "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", + "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", + "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", + "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", + "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", + "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", + "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", + "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", + "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", + "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", + "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", + "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", + "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", + "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", + "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", + "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", + "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", + "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", + "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", + "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", + "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", + "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", + "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", + "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", + "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", + "cpu": [ + "arm64" + ], "dev": true, - "engines": { - "node": ">= 8" - } + "license": "MIT", + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", + "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", + "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", + "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", + "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", + "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", + "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", + "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", + "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", + "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", + "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", + "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", + "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", + "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", + "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", + "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", + "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", + "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", + "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@supabase/auth-js": { + "version": "2.71.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.71.1.tgz", + "integrity": "sha512-mMIQHBRc+SKpZFRB2qtupuzulaUhFYupNyxqDj5Jp/LyPvcWvjaJzZzObv6URtL/O6lPxkanASnotGtNpS3H2Q==", + "license": "MIT", "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" + "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/functions-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.0.0.tgz", - "integrity": "sha512-ozb7bds2yvf5k7NM2ZzUkxvsx4S4i2eRKFSJetdTADV91T65g4gCzEs9L3LUXSrghcGIkUaon03VPzOrFredqg==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.5.tgz", + "integrity": "sha512-v5GSqb9zbosquTo6gBwIiq7W9eQ7rE5QazsK/ezNiQXdCbY+bH8D9qEaBIkhVvX4ZRW5rP03gEfw5yw9tiq4EQ==", + "license": "MIT", "dependencies": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, - "node_modules/@supabase/gotrue-js": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.2.1.tgz", - "integrity": "sha512-CgQaYAJmGbOLPSqan4mjRgGikzsrlkKdPq0UNG7WZQv5HlHJlAYW8HeyNw/SKfIbxQBm8s2dBCeUyX+NdfB2Rw==", + "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==", + "license": "MIT", "dependencies": { - "cross-fetch": "^3.1.5" + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" } }, "node_modules/@supabase/postgrest-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.1.0.tgz", - "integrity": "sha512-qkY8TqIu5sJuae8gjeDPjEqPrefzcTraW9PNSVJQHq4TEv98ZmwaXGwBGz0bVL63bqrGA5hqREbQHkANUTXrvA==", + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.19.4.tgz", + "integrity": "sha512-O4soKqKtZIW3olqmbXXbKugUtByD2jPa8kL2m2c1oozAO11uCcGrRhkZL0kVxjBLrXHE0mdSkFsMj7jDSfyNpw==", + "license": "MIT", "dependencies": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/realtime-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.1.0.tgz", - "integrity": "sha512-iplLCofTeYjnx9FIOsIwHLhMp0+7UVyiA4/sCeq40VdOgN9eTIhjEno9Tgh4dJARi4aaXoKfRX1DTxgZaOpPAw==", + "version": "2.11.15", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.11.15.tgz", + "integrity": "sha512-HQKRnwAqdVqJW/P9TjKVK+/ETpW4yQ8tyDPPtRMKOH4Uh3vQD74vmj353CYs8+YwVBKubeUOOEpI9CT8mT4obw==", + "license": "MIT", "dependencies": { - "@types/phoenix": "^1.5.4", - "websocket": "^1.0.34" + "@supabase/node-fetch": "^2.6.13", + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "isows": "^1.0.7", + "ws": "^8.18.2" } }, "node_modules/@supabase/storage-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.0.0.tgz", - "integrity": "sha512-7kXThdRt/xqnOOvZZxBqNkeX1CFNUWc0hYBJtNN/Uvt8ok9hD14foYmroWrHn046wEYFqUrB9U35JYsfTrvltA==", + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.10.4.tgz", + "integrity": "sha512-cvL02GarJVFcNoWe36VBybQqTVRq6wQSOCvTS64C+eyuxOruFIm1utZAY0xi2qKtHJO3EjKaj8iWJKySusDmAQ==", + "license": "MIT", "dependencies": { - "cross-fetch": "^3.1.5" + "@supabase/node-fetch": "^2.6.14" } }, "node_modules/@supabase/supabase-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.0.4.tgz", - "integrity": "sha512-Z5uLyJm9bz5LMFnt5d1I6ccxVTdvKbJa0RsYGgKlA+QiyGvBxRRvVh8pqlYP1571DlycGG7bWngNwdv7/pehrg==", + "version": "2.53.0", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.53.0.tgz", + "integrity": "sha512-Vg9sl0oFn55cCPaEOsDsRDbxOVccxRrK/cikjL1XbywHEOfyA5SOOEypidMvQLwgoAfnC2S4D9BQwJDcZs7/TQ==", + "license": "MIT", "dependencies": { - "@supabase/functions-js": "^2.0.0", - "@supabase/gotrue-js": "^2.2.0", - "@supabase/postgrest-js": "^1.1.0", - "@supabase/realtime-js": "^2.1.0", - "@supabase/storage-js": "^2.0.0", - "cross-fetch": "^3.1.5" + "@supabase/auth-js": "2.71.1", + "@supabase/functions-js": "2.4.5", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "1.19.4", + "@supabase/realtime-js": "2.11.15", + "@supabase/storage-js": "^2.10.4" + } + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", + "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" } }, "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.2.tgz", - "integrity": "sha512-8tTVbNuraeDchBaArNbwaZLpO0feM7BRSdZU5yeM4Clasx2p1p1CYBoWh+VgxZlxiark49HXummkHqKztbl8lA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.1.0.tgz", + "integrity": "sha512-+U6lz1wvGEG/BvQyL4z/flyNdQ9xDNv5vrh+vWBWTHaebqT0c9RNggpZTo/XSPoHsSCWBlYaTlRX8pZ9GATXCw==", "dev": true, + "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^4.2.1", - "debug": "^4.3.4", - "deepmerge": "^4.2.2", + "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0-next.1", + "debug": "^4.4.1", + "deepmerge": "^4.3.1", "kleur": "^4.1.5", - "magic-string": "^0.26.2", - "svelte-hmr": "^0.14.12" + "magic-string": "^0.30.17", + "vitefu": "^1.1.1" }, "engines": { - "node": "^14.18.0 || >= 16" + "node": "^20.19 || ^22.12 || >=24" }, "peerDependencies": { - "diff-match-patch": "^1.0.5", - "svelte": "^3.44.0", - "vite": "^3.0.0" + "svelte": "^5.0.0", + "vite": "^6.3.0 || ^7.0.0" + } + }, + "node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.0.tgz", + "integrity": "sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.1" }, - "peerDependenciesMeta": { - "diff-match-patch": { - "optional": true - } + "engines": { + "node": "^20.19 || ^22.12 || >=24" + }, + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", + "svelte": "^5.0.0", + "vite": "^6.3.0 || ^7.0.0" } }, "node_modules/@tsconfig/svelte": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-3.0.0.tgz", - "integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==", - "dev": true + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.4.tgz", + "integrity": "sha512-BV9NplVgLmSi4mwKzD8BD/NQ8erOY/nUE/GpgWe2ckx+wIQF5RyRirn/QsSSCPeulVpc3RA/iJt6DpfTIZps0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "18.7.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz", - "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==", - "dev": true + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.0.tgz", + "integrity": "sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.10.0" + } }, "node_modules/@types/phoenix": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.5.4.tgz", - "integrity": "sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ==" + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", + "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==", + "license": "MIT" }, - "node_modules/@types/pug": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", - "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", - "dev": true - }, - "node_modules/@types/sass": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", - "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", - "dev": true, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", "dependencies": { "@types/node": "*" } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 8" + "node": ">=0.4.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "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" + "node": ">= 14.16.0" }, - "engines": { - "node": ">=6.14.2" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "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": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -387,487 +1035,96 @@ } }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", - "dev": true - }, - "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/esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", + "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" + "@esbuild/aix-ppc64": "0.25.8", + "@esbuild/android-arm": "0.25.8", + "@esbuild/android-arm64": "0.25.8", + "@esbuild/android-x64": "0.25.8", + "@esbuild/darwin-arm64": "0.25.8", + "@esbuild/darwin-x64": "0.25.8", + "@esbuild/freebsd-arm64": "0.25.8", + "@esbuild/freebsd-x64": "0.25.8", + "@esbuild/linux-arm": "0.25.8", + "@esbuild/linux-arm64": "0.25.8", + "@esbuild/linux-ia32": "0.25.8", + "@esbuild/linux-loong64": "0.25.8", + "@esbuild/linux-mips64el": "0.25.8", + "@esbuild/linux-ppc64": "0.25.8", + "@esbuild/linux-riscv64": "0.25.8", + "@esbuild/linux-s390x": "0.25.8", + "@esbuild/linux-x64": "0.25.8", + "@esbuild/netbsd-arm64": "0.25.8", + "@esbuild/netbsd-x64": "0.25.8", + "@esbuild/openbsd-arm64": "0.25.8", + "@esbuild/openbsd-x64": "0.25.8", + "@esbuild/openharmony-arm64": "0.25.8", + "@esbuild/sunos-x64": "0.25.8", + "@esbuild/win32-arm64": "0.25.8", + "@esbuild/win32-ia32": "0.25.8", + "@esbuild/win32-x64": "0.25.8" } }, - "node_modules/esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", - "cpu": [ - "x64" - ], + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "license": "MIT" }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", - "cpu": [ - "arm64" - ], + "node_modules/esrap": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz", + "integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "MIT", "dependencies": { - "type": "^2.7.2" + "@jridgewell/sourcemap-codec": "^1.4.15" } }, - "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.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" }, - "engines": { - "node": ">=8.6.0" + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -876,233 +1133,56 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@types/estree": "^1.0.6" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "node_modules/isows": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", + "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "peerDependencies": { + "ws": "*" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "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/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true, + "license": "MIT" + }, "node_modules/magic-string": { - "version": "0.26.2", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz", - "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, + "license": "MIT", "dependencies": { - "sourcemap-codec": "^1.4.8" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/mri": { @@ -1110,20 +1190,22 @@ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -1131,6 +1213,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1138,107 +1221,30 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "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/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "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.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -1254,138 +1260,76 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, + "license": "MIT", "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "node": ">= 14.18.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", + "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.46.2", + "@rollup/rollup-android-arm64": "4.46.2", + "@rollup/rollup-darwin-arm64": "4.46.2", + "@rollup/rollup-darwin-x64": "4.46.2", + "@rollup/rollup-freebsd-arm64": "4.46.2", + "@rollup/rollup-freebsd-x64": "4.46.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", + "@rollup/rollup-linux-arm-musleabihf": "4.46.2", + "@rollup/rollup-linux-arm64-gnu": "4.46.2", + "@rollup/rollup-linux-arm64-musl": "4.46.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", + "@rollup/rollup-linux-ppc64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-musl": "4.46.2", + "@rollup/rollup-linux-s390x-gnu": "4.46.2", + "@rollup/rollup-linux-x64-gnu": "4.46.2", + "@rollup/rollup-linux-x64-musl": "4.46.2", + "@rollup/rollup-win32-arm64-msvc": "4.46.2", + "@rollup/rollup-win32-ia32-msvc": "4.46.2", + "@rollup/rollup-win32-x64-msvc": "4.46.2", "fsevents": "~2.3.2" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", "dev": true, + "license": "MIT", "dependencies": { "mri": "^1.1.0" }, @@ -1393,289 +1337,167 @@ "node": ">=6" } }, - "node_modules/sander": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", - "integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==", - "dev": true, - "dependencies": { - "es6-promise": "^3.1.2", - "graceful-fs": "^4.1.3", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.2" - } - }, - "node_modules/sorcery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", - "integrity": "sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==", - "dev": true, - "dependencies": { - "buffer-crc32": "^0.2.5", - "minimist": "^1.2.0", - "sander": "^0.5.0", - "sourcemap-codec": "^1.3.0" - }, - "bin": { - "sorcery": "bin/index.js" - } - }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/svelte": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz", - "integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==", + "version": "5.37.3", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.37.3.tgz", + "integrity": "sha512-7t/ejshehHd+95z3Z7ebS7wsqHDQxi/8nBTuTRwpMgNegfRBfuitCSKTUDKIBOExqfT2+DhQ2VLG8Xn+cBXoaQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", + "@types/estree": "^1.0.5", + "acorn": "^8.12.1", + "aria-query": "^5.3.1", + "axobject-query": "^4.1.0", + "clsx": "^2.1.1", + "esm-env": "^1.2.1", + "esrap": "^2.1.0", + "is-reference": "^3.0.3", + "locate-character": "^3.0.0", + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" + }, "engines": { - "node": ">= 8" + "node": ">=18" } }, "node_modules/svelte-check": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.8.1.tgz", - "integrity": "sha512-cibyY1sgt3ONIDnQbSgV2X9AJFhwEslRHNo95lijrYfPzVEvTvbmL2ohsUyqB5L7j1GhLXtQbjCJ4lZZ/fwbeQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.3.1.tgz", + "integrity": "sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.9", - "chokidar": "^3.4.1", - "fast-glob": "^3.2.7", - "import-fresh": "^3.2.1", + "@jridgewell/trace-mapping": "^0.3.25", + "chokidar": "^4.0.1", + "fdir": "^6.2.0", "picocolors": "^1.0.0", - "sade": "^1.7.4", - "svelte-preprocess": "^4.0.0", - "typescript": "*" + "sade": "^1.7.4" }, "bin": { "svelte-check": "bin/svelte-check" }, - "peerDependencies": { - "svelte": "^3.24.0" - } - }, - "node_modules/svelte-hmr": { - "version": "0.14.12", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz", - "integrity": "sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==", - "dev": true, "engines": { - "node": "^12.20 || ^14.13.1 || >= 16" + "node": ">= 18.0.0" }, "peerDependencies": { - "svelte": ">=3.19.0" + "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": ">=5.0.0" } }, - "node_modules/svelte-preprocess": { - "version": "4.10.7", - "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz", - "integrity": "sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==", + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@types/pug": "^2.0.4", - "@types/sass": "^1.16.0", - "detect-indent": "^6.0.0", - "magic-string": "^0.25.7", - "sorcery": "^0.10.0", - "strip-indent": "^3.0.0" + "fdir": "^6.4.4", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 9.11.2" + "node": ">=12.0.0" }, - "peerDependencies": { - "@babel/core": "^7.10.2", - "coffeescript": "^2.5.1", - "less": "^3.11.3 || ^4.0.0", - "postcss": "^7 || ^8", - "postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0", - "pug": "^3.0.0", - "sass": "^1.26.8", - "stylus": "^0.55.0", - "sugarss": "^2.0.0", - "svelte": "^3.23.0", - "typescript": "^3.9.5 || ^4.0.0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "coffeescript": { - "optional": true - }, - "less": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "postcss": { - "optional": true - }, - "postcss-load-config": { - "optional": true - }, - "pug": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/svelte-preprocess/node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "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" - } + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, - "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/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "license": "MIT" }, "node_modules/vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", + "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "^0.15.9", - "postcss": "^8.4.18", - "resolve": "^1.22.1", - "rollup": "^2.79.1" + "esbuild": "^0.25.0", + "fdir": "^6.4.6", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.40.0", + "tinyglobby": "^0.2.14" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -1684,1192 +1506,78 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", + "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", + "dev": true, + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true } } }, "node_modules/webidl-conversions": { "version": "3.0.1", "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/websocket/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/websocket/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "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.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", "engines": { - "node": ">=0.10.32" - } - } - }, - "dependencies": { - "@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", - "dev": true, - "optional": true - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "requires": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - } - }, - "@supabase/functions-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.0.0.tgz", - "integrity": "sha512-ozb7bds2yvf5k7NM2ZzUkxvsx4S4i2eRKFSJetdTADV91T65g4gCzEs9L3LUXSrghcGIkUaon03VPzOrFredqg==", - "requires": { - "cross-fetch": "^3.1.5" - } - }, - "@supabase/gotrue-js": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.2.1.tgz", - "integrity": "sha512-CgQaYAJmGbOLPSqan4mjRgGikzsrlkKdPq0UNG7WZQv5HlHJlAYW8HeyNw/SKfIbxQBm8s2dBCeUyX+NdfB2Rw==", - "requires": { - "cross-fetch": "^3.1.5" - } - }, - "@supabase/postgrest-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.1.0.tgz", - "integrity": "sha512-qkY8TqIu5sJuae8gjeDPjEqPrefzcTraW9PNSVJQHq4TEv98ZmwaXGwBGz0bVL63bqrGA5hqREbQHkANUTXrvA==", - "requires": { - "cross-fetch": "^3.1.5" - } - }, - "@supabase/realtime-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.1.0.tgz", - "integrity": "sha512-iplLCofTeYjnx9FIOsIwHLhMp0+7UVyiA4/sCeq40VdOgN9eTIhjEno9Tgh4dJARi4aaXoKfRX1DTxgZaOpPAw==", - "requires": { - "@types/phoenix": "^1.5.4", - "websocket": "^1.0.34" - } - }, - "@supabase/storage-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.0.0.tgz", - "integrity": "sha512-7kXThdRt/xqnOOvZZxBqNkeX1CFNUWc0hYBJtNN/Uvt8ok9hD14foYmroWrHn046wEYFqUrB9U35JYsfTrvltA==", - "requires": { - "cross-fetch": "^3.1.5" - } - }, - "@supabase/supabase-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.0.4.tgz", - "integrity": "sha512-Z5uLyJm9bz5LMFnt5d1I6ccxVTdvKbJa0RsYGgKlA+QiyGvBxRRvVh8pqlYP1571DlycGG7bWngNwdv7/pehrg==", - "requires": { - "@supabase/functions-js": "^2.0.0", - "@supabase/gotrue-js": "^2.2.0", - "@supabase/postgrest-js": "^1.1.0", - "@supabase/realtime-js": "^2.1.0", - "@supabase/storage-js": "^2.0.0", - "cross-fetch": "^3.1.5" - } - }, - "@sveltejs/vite-plugin-svelte": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.2.tgz", - "integrity": "sha512-8tTVbNuraeDchBaArNbwaZLpO0feM7BRSdZU5yeM4Clasx2p1p1CYBoWh+VgxZlxiark49HXummkHqKztbl8lA==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^4.2.1", - "debug": "^4.3.4", - "deepmerge": "^4.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.26.2", - "svelte-hmr": "^0.14.12" - } - }, - "@tsconfig/svelte": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-3.0.0.tgz", - "integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==", - "dev": true - }, - "@types/node": { - "version": "18.7.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz", - "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==", - "dev": true - }, - "@types/phoenix": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.5.4.tgz", - "integrity": "sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ==" - }, - "@types/pug": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", - "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", - "dev": true - }, - "@types/sass": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", - "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true - }, - "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" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "requires": { - "node-fetch": "2.6.7" - } - }, - "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": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "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-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==", - "dev": true - }, - "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" - } - }, - "esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" - } - }, - "esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", - "dev": true, - "optional": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "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" + "node": ">=10.0.0" }, - "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.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true - }, - "magic-string": { - "version": "0.26.2", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz", - "integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true - }, - "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.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==" - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", - "dev": true, - "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "requires": { - "mri": "^1.1.0" - } - }, - "sander": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", - "integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==", - "dev": true, - "requires": { - "es6-promise": "^3.1.2", - "graceful-fs": "^4.1.3", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.2" - } - }, - "sorcery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", - "integrity": "sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.5", - "minimist": "^1.2.0", - "sander": "^0.5.0", - "sourcemap-codec": "^1.3.0" - } - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "svelte": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz", - "integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==", - "dev": true - }, - "svelte-check": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.8.1.tgz", - "integrity": "sha512-cibyY1sgt3ONIDnQbSgV2X9AJFhwEslRHNo95lijrYfPzVEvTvbmL2ohsUyqB5L7j1GhLXtQbjCJ4lZZ/fwbeQ==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.9", - "chokidar": "^3.4.1", - "fast-glob": "^3.2.7", - "import-fresh": "^3.2.1", - "picocolors": "^1.0.0", - "sade": "^1.7.4", - "svelte-preprocess": "^4.0.0", - "typescript": "*" - } - }, - "svelte-hmr": { - "version": "0.14.12", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz", - "integrity": "sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==", - "dev": true, - "requires": {} - }, - "svelte-preprocess": { - "version": "4.10.7", - "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz", - "integrity": "sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==", - "dev": true, - "requires": { - "@types/pug": "^2.0.4", - "@types/sass": "^1.16.0", - "detect-indent": "^6.0.0", - "magic-string": "^0.25.7", - "sorcery": "^0.10.0", - "strip-indent": "^3.0.0" - }, - "dependencies": { - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - } - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "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" - } - }, - "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "dev": true - }, - "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" - } - }, - "vite": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.7.tgz", - "integrity": "sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==", - "dev": true, - "requires": { - "esbuild": "^0.15.9", - "fsevents": "~2.3.2", - "postcss": "^8.4.18", - "resolve": "^1.22.1", - "rollup": "^2.79.1" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "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": { + "peerDependencies": { "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" + "utf-8-validate": ">=5.0.2" }, - "dependencies": { - "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" - } + "peerDependenciesMeta": { + "bufferutil": { + "optional": true }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "utf-8-validate": { + "optional": true } } }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "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==" + "node_modules/zimmerframe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", + "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", + "dev": true, + "license": "MIT" } } } diff --git a/examples/user-management/svelte-user-management/package.json b/examples/user-management/svelte-user-management/package.json index 520ec9b77f9..c84388af29a 100644 --- a/examples/user-management/svelte-user-management/package.json +++ b/examples/user-management/svelte-user-management/package.json @@ -1,25 +1,23 @@ { - "name": "svelte-user-management", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", - "check": "svelte-check --tsconfig ./tsconfig.json" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^1.0.1", - "@tsconfig/svelte": "^3.0.0", - "svelte": "^3.49.0", - "svelte-check": "^2.8.0", - "svelte-preprocess": "^4.10.7", - "tslib": "^2.4.0", - "typescript": "^4.6.4", - "vite": "^4.3.9" - }, - "dependencies": { - "@supabase/supabase-js": "^2.0.4" - } + "name": "supabase-svelte", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^6.1.0", + "@tsconfig/svelte": "^5.0.4", + "svelte": "^5.37.3", + "svelte-check": "^4.3.1", + "typescript": "~5.9.2", + "vite": "^7.0.6" + }, + "dependencies": { + "@supabase/supabase-js": "^2.53.0" + } } diff --git a/examples/user-management/svelte-user-management/src/App.svelte b/examples/user-management/svelte-user-management/src/App.svelte index 0d2b3e5715c..1005bbda028 100644 --- a/examples/user-management/svelte-user-management/src/App.svelte +++ b/examples/user-management/svelte-user-management/src/App.svelte @@ -1,11 +1,11 @@ -
- + { e.preventDefault(); updateProfile(); }} class="form-widget">
Email: {session.user.email}
+
@@ -83,10 +87,14 @@
- diff --git a/examples/user-management/svelte-user-management/src/lib/Auth.svelte b/examples/user-management/svelte-user-management/src/lib/Auth.svelte index 9de46d08824..6647c864cd8 100644 --- a/examples/user-management/svelte-user-management/src/lib/Auth.svelte +++ b/examples/user-management/svelte-user-management/src/lib/Auth.svelte @@ -1,30 +1,30 @@

Supabase + Svelte

Sign in via magic link with your email below

-
+ { e.preventDefault(); handleLogin(); }}>
-
diff --git a/examples/user-management/svelte-user-management/src/lib/Avatar.svelte b/examples/user-management/svelte-user-management/src/lib/Avatar.svelte index 91f418e1e90..7b5237cf2ae 100644 --- a/examples/user-management/svelte-user-management/src/lib/Avatar.svelte +++ b/examples/user-management/svelte-user-management/src/lib/Avatar.svelte @@ -1,84 +1,87 @@
- {#if avatarUrl} + {#if avatarUrl} {avatarUrl {:else} -
+
{/if}
diff --git a/examples/user-management/svelte-user-management/src/main.ts b/examples/user-management/svelte-user-management/src/main.ts index 5c1f795f9f5..664a057afa0 100644 --- a/examples/user-management/svelte-user-management/src/main.ts +++ b/examples/user-management/svelte-user-management/src/main.ts @@ -1,8 +1,9 @@ +import { mount } from 'svelte' import './app.css' import App from './App.svelte' -const app = new App({ - target: document.getElementById('app') +const app = mount(App, { + target: document.getElementById('app')!, }) export default app diff --git a/examples/user-management/svelte-user-management/src/schema.ts b/examples/user-management/svelte-user-management/src/schema.ts deleted file mode 100644 index 7800a5bd9ef..00000000000 --- a/examples/user-management/svelte-user-management/src/schema.ts +++ /dev/null @@ -1,40 +0,0 @@ -export type Json = string | number | boolean | null | { [key: string]: Json } | Json[] - -export interface Database { - public: { - Tables: { - profiles: { - Row: { - id: string - updated_at: string | null - username: string | null - avatar_url: string | null - website: string | null - } - Insert: { - id: string - updated_at?: string | null - username?: string | null - avatar_url?: string | null - website?: string | null - } - Update: { - id?: string - updated_at?: string | null - username?: string | null - avatar_url?: string | null - website?: string | null - } - } - } - Views: { - [_ in never]: never - } - Functions: { - [_ in never]: never - } - Enums: { - [_ in never]: never - } - } -} diff --git a/examples/user-management/svelte-user-management/src/supabaseClient.ts b/examples/user-management/svelte-user-management/src/supabaseClient.ts index 1bf5c30842c..89f1679a796 100644 --- a/examples/user-management/svelte-user-management/src/supabaseClient.ts +++ b/examples/user-management/svelte-user-management/src/supabaseClient.ts @@ -1,7 +1,6 @@ import { createClient } from '@supabase/supabase-js' -import type { Database } from './schema' const supabaseUrl = import.meta.env.VITE_SUPABASE_URL const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY -export const supabase = createClient(supabaseUrl, supabaseAnonKey) +export const supabase = createClient(supabaseUrl, supabaseAnonKey) \ No newline at end of file diff --git a/examples/user-management/svelte-user-management/svelte.config.js b/examples/user-management/svelte-user-management/svelte.config.js index 3630bb3963b..b0683fd24d7 100644 --- a/examples/user-management/svelte-user-management/svelte.config.js +++ b/examples/user-management/svelte-user-management/svelte.config.js @@ -1,7 +1,7 @@ -import sveltePreprocess from 'svelte-preprocess' +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' export default { - // Consult https://github.com/sveltejs/svelte-preprocess + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess // for more information about preprocessors - preprocess: sveltePreprocess() + preprocess: vitePreprocess(), } diff --git a/examples/user-management/svelte-user-management/tsconfig.app.json b/examples/user-management/svelte-user-management/tsconfig.app.json new file mode 100644 index 00000000000..d9387fd5347 --- /dev/null +++ b/examples/user-management/svelte-user-management/tsconfig.app.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "resolveJsonModule": true, + /** + * Typecheck JS in `.svelte` and `.js` files by default. + * Disable checkJs if you'd like to use dynamic types in JS. + * Note that setting allowJs false does not prevent the use + * of JS in `.svelte` files. + */ + "allowJs": true, + "checkJs": true, + "isolatedModules": true, + "moduleDetection": "force" + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/user-management/svelte-user-management/tsconfig.json b/examples/user-management/svelte-user-management/tsconfig.json index d38303196ae..1ffef600d95 100644 --- a/examples/user-management/svelte-user-management/tsconfig.json +++ b/examples/user-management/svelte-user-management/tsconfig.json @@ -1,21 +1,7 @@ { - "extends": "@tsconfig/svelte/tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "resolveJsonModule": true, - "baseUrl": ".", - /** - * Typecheck JS in `.svelte` and `.js` files by default. - * Disable checkJs if you'd like to use dynamic types in JS. - * Note that setting allowJs false does not prevent the use - * of JS in `.svelte` files. - */ - "allowJs": true, - "checkJs": true, - "isolatedModules": true - }, - "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], - "references": [{ "path": "./tsconfig.node.json" }] + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] } diff --git a/examples/user-management/svelte-user-management/tsconfig.node.json b/examples/user-management/svelte-user-management/tsconfig.node.json index 65dbdb96ae5..f85a39906e5 100644 --- a/examples/user-management/svelte-user-management/tsconfig.node.json +++ b/examples/user-management/svelte-user-management/tsconfig.node.json @@ -1,8 +1,25 @@ { "compilerOptions": { - "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], "module": "ESNext", - "moduleResolution": "Node" + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true }, "include": ["vite.config.ts"] } diff --git a/examples/user-management/svelte-user-management/vite.config.ts b/examples/user-management/svelte-user-management/vite.config.ts index 401b4d4bd6b..d32eba1d63f 100644 --- a/examples/user-management/svelte-user-management/vite.config.ts +++ b/examples/user-management/svelte-user-management/vite.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'vite' import { svelte } from '@sveltejs/vite-plugin-svelte' -// https://vitejs.dev/config/ +// https://vite.dev/config/ export default defineConfig({ - plugins: [svelte()] + plugins: [svelte()], }) From f6419a49f425ef77c2ab2b9ad518d7c1a4862ed0 Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo <31685197+soedirgo@users.noreply.github.com> Date: Tue, 5 Aug 2025 22:22:56 +0800 Subject: [PATCH 12/28] fix(pg-meta): update reserved words (#37693) --- packages/pg-meta/src/pg-format/reserved.ts | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/packages/pg-meta/src/pg-format/reserved.ts b/packages/pg-meta/src/pg-format/reserved.ts index cd7c9143a78..7fbb5bc1334 100644 --- a/packages/pg-meta/src/pg-format/reserved.ts +++ b/packages/pg-meta/src/pg-format/reserved.ts @@ -19,13 +19,19 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'AUTHORIZATION', 'BACKUP', 'BETWEEN', + 'BIGINT', 'BINARY', + 'BIT', 'BLANKSASNULL', + 'BOOLEAN', 'BOTH', 'BYTEDICT', 'CASE', 'CAST', + 'CHAR', + 'CHARACTER', 'CHECK', + 'COALESCE', 'COLLATE', 'COLUMN', 'CONSTRAINT', @@ -39,6 +45,8 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURRENT_USER_ID', + 'DEC', + 'DECIMAL', 'DEFAULT', 'DEFERRABLE', 'DEFLATE', @@ -57,9 +65,12 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'ENCRYPTION', 'END', 'EXCEPT', + 'EXISTS', 'EXPLICIT', + 'EXTRACT', 'FALSE', 'FETCH', + 'FLOAT', 'FOR', 'FOREIGN', 'FREEZE', @@ -68,7 +79,9 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'GLOBALDICT256', 'GLOBALDICT64K', 'GRANT', + 'GREATEST', 'GROUP', + 'GROUPING', 'GZIP', 'HAVING', 'IDENTITY', @@ -77,13 +90,29 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'IN', 'INITIALLY', 'INNER', + 'INOUT', + 'INT', + 'INTEGER', 'INTERSECT', + 'INTERVAL', 'INTO', 'IS', 'ISNULL', 'JOIN', + 'JSON', + 'JSON_ARRAY', + 'JSON_ARRAYAGG', + 'JSON_EXISTS', + 'JSON_OBJECT', + 'JSON_OBJECTAGG', + 'JSON_QUERY', + 'JSON_SCALAR', + 'JSON_SERIALIZE', + 'JSON_TABLE', + 'JSON_VALUE', 'LATERAL', 'LEADING', + 'LEAST', 'LEFT', 'LIKE', 'LIMIT', @@ -93,16 +122,23 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'LUNS', 'LZO', 'LZOP', + 'MERGE_ACTION', 'MINUS', 'MOSTLY13', 'MOSTLY32', 'MOSTLY8', + 'NATIONAL', 'NATURAL', + 'NCHAR', 'NEW', + 'NONE', + 'NORMALIZE', 'NOT', 'NOTNULL', 'NULL', + 'NULLIF', 'NULLS', + 'NUMERIC', 'OFF', 'OFFLINE', 'OFFSET', @@ -112,15 +148,20 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'OPEN', 'OR', 'ORDER', + 'OUT', 'OUTER', 'OVERLAPS', + 'OVERLAY', 'PARALLEL', 'PARTITION', 'PERCENT', 'PLACING', + 'POSITION', + 'PRECISION', 'PRIMARY', 'RAW', 'READRATIO', + 'REAL', 'RECOVER', 'REFERENCES', 'REJECTLOG', @@ -128,10 +169,14 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'RESTORE', 'RETURNING', 'RIGHT', + 'ROW', 'SELECT', 'SESSION_USER', + 'SETOF', 'SIMILAR', + 'SMALLINT', 'SOME', + 'SUBSTRING', 'SYMMETRIC', 'SYSDATE', 'SYSTEM', @@ -141,15 +186,21 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'TEXT255', 'TEXT32K', 'THEN', + 'TIME', + 'TIMESTAMP', 'TO', 'TOP', 'TRAILING', + 'TREAT', + 'TRIM', 'TRUE', 'TRUNCATECOLUMNS', 'UNION', 'UNIQUE', 'USER', 'USING', + 'VALUES', + 'VARCHAR', 'VARIADIC', 'VERBOSE', 'WALLET', @@ -158,4 +209,15 @@ export const POSTGRESQL_RESERVED_WORDS = new Set([ 'WINDOW', 'WITH', 'WITHOUT', + 'XMLATTRIBUTES', + 'XMLCONCAT', + 'XMLELEMENT', + 'XMLEXISTS', + 'XMLFOREST', + 'XMLNAMESPACES', + 'XMLPARSE', + 'XMLPI', + 'XMLROOT', + 'XMLSERIALIZE', + 'XMLTABLE', ]) From 98ab06097baf7ac13d0bdaf4cf9645748eb864e1 Mon Sep 17 00:00:00 2001 From: "kemal.earth" <606977+kemaldotearth@users.noreply.github.com> Date: Tue, 5 Aug 2025 16:03:28 +0100 Subject: [PATCH 13/28] fix(studio): storage settings inputs (#37691) fix: storage settings inputs The inputs for upload file size limit were overflowing out of the box, even on larger screens. Uses flex instead of grid to handle the inputs gracefully. --- .../interfaces/Storage/StorageSettings/StorageSettings.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx b/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx index 43868c50c03..8bbb2885aca 100644 --- a/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx +++ b/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx @@ -171,8 +171,8 @@ const StorageSettings = () => {
-
-
+
+
{ )} />
-
+
Date: Tue, 5 Aug 2025 11:37:53 -0400 Subject: [PATCH 14/28] Update custom-postgres-config.mdx | added new supautil enabled settings (#34001) * Update custom-postgres-config.mdx | added new supautil enabled settings * Update custom-postgres-config.mdx --- .../database/custom-postgres-config.mdx | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/apps/docs/content/guides/database/custom-postgres-config.mdx b/apps/docs/content/guides/database/custom-postgres-config.mdx index cacda90ffda..d650c5db263 100644 --- a/apps/docs/content/guides/database/custom-postgres-config.mdx +++ b/apps/docs/content/guides/database/custom-postgres-config.mdx @@ -48,18 +48,24 @@ show "statement_timeout"; Some settings can only be modified by a superuser. Supabase pre-enables the [`supautils` extension](https://supabase.com/blog/roles-postgres-hooks#setting-up-the-supautils-extension), which allows the `postgres` role to retain certain superuser privileges. It enables modification of the below reserved configurations at the `role` level: -| Setting | Description | -| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `auto_explain.log_min_duration` | Logs query plans taking longer than this duration. | -| `auto_explain.log_nested_statements` | Log nested statements' plans. | -| `log_min_messages` | Minimum severity level of messages to log. | -| `pg_net.ttl` | Sets how long the [pg_net extension](/docs/guides/database/extensions/pg_net) saves responses | -| `pg_net.batch_size` | Sets how many requests the [pg_net extension](/docs/guides/database/extensions/pg_net) can make per second | -| `pgaudit.*` | Configures the [PGAudit extension](https://supabase.com/docs/guides/database/extensions/pgaudit). The `log_parameter` is still restricted to protect secrets | -| `pgrst.*` | [`PostgREST` settings](https://docs.postgrest.org/en/stable/references/configuration.html#db-aggregates-enabled) | -| `plan_filter.*` | Configures the [pg_plan_filter extension](https://supabase.com/docs/guides/database/extensions/pg_plan_filter) | -| `session_replication_role` | Sets the session's behavior for triggers and rewrite rules. | -| `track_io_timing` | Collects timing statistics for database I/O activity. | +| Setting | Description | +| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `auto_explain.*` | Configures the [auto_explain module](https://www.postgresql.org/docs/current/auto-explain.html). Can be configured to log execution plans for queries expected to exceed x seconds, including function queries. | +| `log_lock_waits` | Controls whether a log message is produced when a session waits longer than [deadlock_timeout](https://www.postgresql.org/docs/current/runtime-config-locks.html#GUC-DEADLOCK-TIMEOUT) to acquire a lock. | +| `log_min_duration_statement` | Causes the duration of each completed statement to be logged if the statement ran for at least the specified amount of time. | +| `log_min_messages` | Minimum severity level of messages to log. | +| `log_replication_commands` | Logs all replication commands | +| `log_statement` | Controls which SQL statements are logged. Valid values are `none` (off), `ddl`, `mod`, and `all` (all statements). | +| `log_temp_files` | Controls logging of temporary file names and sizes. | +| `pg_net.ttl` | Sets how long the [pg_net extension](/docs/guides/database/extensions/pg_net) saves responses | +| `pg_net.batch_size` | Sets how many requests the [pg_net extension](/docs/guides/database/extensions/pg_net) can make per second | +| `pg_stat_statements.*` | Configures the [pg_stat_statements extension](https://www.postgresql.org/docs/current/pgstatstatements.html). | +| `pgaudit.*` | Configures the [PGAudit extension](https://supabase.com/docs/guides/database/extensions/pgaudit). The `log_parameter` is still restricted to protect secrets | +| `pgrst.*` | [`PostgREST` settings](https://docs.postgrest.org/en/stable/references/configuration.html#db-aggregates-enabled) | +| `plan_filter.*` | Configures the [pg_plan_filter extension](https://supabase.com/docs/guides/database/extensions/pg_plan_filter) | +| `session_replication_role` | Sets the session's behavior for triggers and rewrite rules. | +| `track_io_timing` | Collects timing statistics for database I/O activity. | +| `wal_compression` | This parameter enables compression of WAL using the specified compression method. | For example, to enable `log_nested_statements` for the `postgres` role, execute: From 3e25e4dd374e5d865206ba210c3e3e3083ec28dd Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Tue, 5 Aug 2025 14:22:23 -0400 Subject: [PATCH 15/28] chore: remove troubleshooting codeowners (#37697) Code ownership was temporary while ironing out problems with sync workflow. It seems more stable now, so I'm removing codeownership to make sure people aren't blocked on troubleshooting updates while I'm away. --- .github/CODEOWNERS | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 043d489e617..2da257c744c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,9 +5,6 @@ /apps/studio/ @supabase/Dashboard -# temporary until we've ironed out all the problems with sync workflow -/apps/docs/content/troubleshooting/ @charislam - /apps/www/ @supabase/marketing /apps/www/public/images/blog @supabase/marketing /apps/www/lib/redirects.js From a69d464dfaf651cdc10533b3e1c4b34c05e7603c Mon Sep 17 00:00:00 2001 From: Sami Fouad <6378290+samifouad@users.noreply.github.com> Date: Tue, 5 Aug 2025 16:31:01 -0600 Subject: [PATCH 16/28] Update broken link in auth-apple.mdx (#37689) Apple changed the URL associated with Apple JS. Provided updated link where needed. --- apps/docs/content/guides/auth/social-login/auth-apple.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/docs/content/guides/auth/social-login/auth-apple.mdx b/apps/docs/content/guides/auth/social-login/auth-apple.mdx index a40f572ef8b..0751f22c12e 100644 --- a/apps/docs/content/guides/auth/social-login/auth-apple.mdx +++ b/apps/docs/content/guides/auth/social-login/auth-apple.mdx @@ -15,7 +15,7 @@ There are three general ways to use Sign in with Apple, depending on the applica - Sign in on the web or in web-based apps - Using an OAuth flow initiated by Supabase Auth using the [Sign in with Apple REST API](https://developer.apple.com/documentation/signinwithapplerestapi). - - Using [Sign in with Apple JS](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js) directly in the browser, usually suitable for websites. + - Using [Sign in with Apple JS](https://developer.apple.com/documentation/signinwithapplejs/) directly in the browser, usually suitable for websites. - Sign in natively inside iOS, macOS, watchOS or tvOS apps using [Apple's Authentication Services](https://developer.apple.com/documentation/authenticationservices) In some cases you're able to use the OAuth flow within web-based native apps such as with [React Native](https://reactnative.dev), [Expo](https://expo.dev) or other similar frameworks. It is best practice to use native Sign in with Apple capabilities on those platforms instead. @@ -95,7 +95,7 @@ curl -X PATCH "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \ ## Using sign in with Apple JS - [Sign in with Apple JS](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js) is an official Apple framework for authenticating Apple users on websites. Although it can be used in web-based apps, those use cases will benefit more with the OAuth flow described above. We recommend using this method on classic websites only. + [Sign in with Apple JS](https://developer.apple.com/documentation/signinwithapplejs/) is an official Apple framework for authenticating Apple users on websites. Although it can be used in web-based apps, those use cases will benefit more with the OAuth flow described above. We recommend using this method on classic websites only. You can use the `signInWithIdToken()` method from the Supabase JavaScript library on the website to obtain an access and refresh token once the user has given consent using Sign in with Apple JS: From 8b72d96d66ed4238840991efbbe63a06e89eb5c3 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Tue, 5 Aug 2025 18:31:11 -0400 Subject: [PATCH 17/28] docs: add product-specific troubleshooting views (#37671) We have a global troubleshooting view at /guides/troubleshooting, but for greater visibility, we should also have product-specific troubleshooting views. This is the same view and same data as the global page, but filtered down to a specific product. --- .../app/guides/auth/troubleshooting/page.tsx | 15 ++++ .../guides/database/troubleshooting/page.tsx | 15 ++++ .../guides/functions/troubleshooting/page.tsx | 15 ++++ .../guides/realtime/troubleshooting/page.tsx | 15 ++++ .../guides/storage/troubleshooting/page.tsx | 15 ++++ .../NavigationMenu.constants.ts | 15 +++- .../docs/Troubleshooting.ui.client.tsx | 42 ++++------ .../docs/features/docs/Troubleshooting.ui.tsx | 82 +++++++++++++++++-- .../features/docs/Troubleshooting.utils.ts | 57 +++++++++++++ .../docs/TroubleshootingSection.page.tsx | 68 +++++++++++++++ 10 files changed, 305 insertions(+), 34 deletions(-) create mode 100644 apps/docs/app/guides/auth/troubleshooting/page.tsx create mode 100644 apps/docs/app/guides/database/troubleshooting/page.tsx create mode 100644 apps/docs/app/guides/functions/troubleshooting/page.tsx create mode 100644 apps/docs/app/guides/realtime/troubleshooting/page.tsx create mode 100644 apps/docs/app/guides/storage/troubleshooting/page.tsx create mode 100644 apps/docs/features/docs/TroubleshootingSection.page.tsx diff --git a/apps/docs/app/guides/auth/troubleshooting/page.tsx b/apps/docs/app/guides/auth/troubleshooting/page.tsx new file mode 100644 index 00000000000..90c21d5119a --- /dev/null +++ b/apps/docs/app/guides/auth/troubleshooting/page.tsx @@ -0,0 +1,15 @@ +import SectionTroubleshootingPage, { + generateSectionTroubleshootingMetadata, +} from '~/features/docs/TroubleshootingSection.page' + +export default async function AuthTroubleshootingPage() { + return ( + + ) +} + +export const metadata = generateSectionTroubleshootingMetadata('auth', 'Auth') diff --git a/apps/docs/app/guides/database/troubleshooting/page.tsx b/apps/docs/app/guides/database/troubleshooting/page.tsx new file mode 100644 index 00000000000..9d1c292cd53 --- /dev/null +++ b/apps/docs/app/guides/database/troubleshooting/page.tsx @@ -0,0 +1,15 @@ +import SectionTroubleshootingPage, { + generateSectionTroubleshootingMetadata, +} from '~/features/docs/TroubleshootingSection.page' + +export default async function DatabaseTroubleshootingPage() { + return ( + + ) +} + +export const metadata = generateSectionTroubleshootingMetadata('database', 'Database') diff --git a/apps/docs/app/guides/functions/troubleshooting/page.tsx b/apps/docs/app/guides/functions/troubleshooting/page.tsx new file mode 100644 index 00000000000..7d2195292dd --- /dev/null +++ b/apps/docs/app/guides/functions/troubleshooting/page.tsx @@ -0,0 +1,15 @@ +import SectionTroubleshootingPage, { + generateSectionTroubleshootingMetadata, +} from '~/features/docs/TroubleshootingSection.page' + +export default async function FunctionsTroubleshootingPage() { + return ( + + ) +} + +export const metadata = generateSectionTroubleshootingMetadata('functions', 'Edge Functions') diff --git a/apps/docs/app/guides/realtime/troubleshooting/page.tsx b/apps/docs/app/guides/realtime/troubleshooting/page.tsx new file mode 100644 index 00000000000..3f4347e436b --- /dev/null +++ b/apps/docs/app/guides/realtime/troubleshooting/page.tsx @@ -0,0 +1,15 @@ +import SectionTroubleshootingPage, { + generateSectionTroubleshootingMetadata, +} from '~/features/docs/TroubleshootingSection.page' + +export default async function RealtimeTroubleshootingPage() { + return ( + + ) +} + +export const metadata = generateSectionTroubleshootingMetadata('realtime', 'Realtime') diff --git a/apps/docs/app/guides/storage/troubleshooting/page.tsx b/apps/docs/app/guides/storage/troubleshooting/page.tsx new file mode 100644 index 00000000000..97ed429fb41 --- /dev/null +++ b/apps/docs/app/guides/storage/troubleshooting/page.tsx @@ -0,0 +1,15 @@ +import SectionTroubleshootingPage, { + generateSectionTroubleshootingMetadata, +} from '~/features/docs/TroubleshootingSection.page' + +export default async function StorageTroubleshootingPage() { + return ( + + ) +} + +export const metadata = generateSectionTroubleshootingMetadata('storage', 'Storage') diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index 30a3a53bd70..3513c721d95 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -653,7 +653,10 @@ export const auth = { }, { name: 'Debugging', - items: [{ name: 'Error Codes', url: '/guides/auth/debugging/error-codes' }], + items: [ + { name: 'Error Codes', url: '/guides/auth/debugging/error-codes' }, + { name: 'Troubleshooting', url: '/guides/auth/troubleshooting' }, + ], }, { name: 'Third-party auth', @@ -962,6 +965,10 @@ export const database: NavMenuConstant = { name: 'Supavisor', url: '/guides/database/supavisor', }, + { + name: 'Troubleshooting', + url: '/guides/database/troubleshooting', + }, ], }, ormQuickstarts, @@ -1630,7 +1637,10 @@ export const realtime: NavMenuConstant = { { name: 'Debugging', url: undefined, - items: [{ name: 'Operational Error Codes', url: '/guides/realtime/error_codes', items: [] }], + items: [ + { name: 'Operational Error Codes', url: '/guides/realtime/error_codes', items: [] }, + { name: 'Troubleshooting', url: '/guides/realtime/troubleshooting' }, + ], }, ], } @@ -1752,6 +1762,7 @@ export const storage: NavMenuConstant = { items: [ { name: 'Logs', url: '/guides/storage/debugging/logs' }, { name: 'Error Codes', url: '/guides/storage/debugging/error-codes' }, + { name: 'Troubleshooting', url: '/guides/storage/troubleshooting' }, ], }, { diff --git a/apps/docs/features/docs/Troubleshooting.ui.client.tsx b/apps/docs/features/docs/Troubleshooting.ui.client.tsx index c125d0e7dd1..784ead6a35f 100644 --- a/apps/docs/features/docs/Troubleshooting.ui.client.tsx +++ b/apps/docs/features/docs/Troubleshooting.ui.client.tsx @@ -4,6 +4,7 @@ import { ChevronDown, RotateCw, Search, X } from 'lucide-react' import { useQueryStates } from 'nuqs' import { useEffect, useRef, useState, Suspense, useCallback, useMemo } from 'react' +import { useBreakpoint } from 'common' import { Input_Shadcn_, cn, @@ -13,22 +14,13 @@ import { CollapsibleContent_Shadcn_ as CollapsibleContent, } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' - -import { - MultiSelector, - MultiSelectorContent, - MultiSelectorInput, - MultiSelectorItem, - MultiSelectorList, - MultiSelectorTrigger, -} from 'ui-patterns/multi-select' +import { MultiSelector } from 'ui-patterns/multi-select' import { type ITroubleshootingMetadata } from './Troubleshooting.utils' import { TROUBLESHOOTING_CONTAINER_ID, TROUBLESHOOTING_DATA_ATTRIBUTES, troubleshootingSearchParams, } from './Troubleshooting.utils.shared' -import { useBreakpoint } from 'common' function useTroubleshootingSearchState() { const [_state, _setState] = useQueryStates(troubleshootingSearchParams) @@ -115,10 +107,10 @@ function entryMatchesFilter( } interface TroubleshootingFilterProps { - products: string[] + className?: string + products?: string[] errors: ITroubleshootingMetadata['errors'] keywords: string[] - className?: string } export function TroubleshootingFilter(props: TroubleshootingFilterProps) { @@ -223,18 +215,20 @@ function TroubleshootingFilterInternal({ <>

Search and filter

- - - - - {products?.map((product) => ( - - {product} - - ))} - - - + {!!products && ( + + + + + {products?.map((product) => ( + + {product} + + ))} + + + + )} diff --git a/apps/docs/features/docs/Troubleshooting.ui.tsx b/apps/docs/features/docs/Troubleshooting.ui.tsx index 9926dabe1af..0f0aaceb3af 100644 --- a/apps/docs/features/docs/Troubleshooting.ui.tsx +++ b/apps/docs/features/docs/Troubleshooting.ui.tsx @@ -1,15 +1,19 @@ -import { Wrench } from 'lucide-react' import Link from 'next/link' -import { type PropsWithChildren, useCallback } from 'react' +import { Fragment } from 'react' +import { cn } from 'ui' +import { TroubleshootingFilter } from './Troubleshooting.ui.client' import { type ITroubleshootingEntry, + type ITroubleshootingMetadata, getArticleSlug, getTroubleshootingUpdatedDates, } from './Troubleshooting.utils' -import { TroubleshootingFilter } from './Troubleshooting.ui.client' -import { formatError, TROUBLESHOOTING_DATA_ATTRIBUTES } from './Troubleshooting.utils.shared' -import { cn } from 'ui' +import { + formatError, + TROUBLESHOOTING_DATA_ATTRIBUTES, + TROUBLESHOOTING_CONTAINER_ID, +} from './Troubleshooting.utils.shared' export async function TroubleshootingPreview({ entry }: { entry: ITroubleshootingEntry }) { const dateUpdated = entry.data.database_id.startsWith('pseudo-') @@ -55,10 +59,10 @@ export async function TroubleshootingPreview({ entry }: { entry: ITroubleshootin .map(formatError) .filter(Boolean) .map((error, index) => ( - <> - {error} + + {error} {index < (entry.data.errors?.length || 0) - 1 ? ', ' : ''} - + ))} )} @@ -83,3 +87,65 @@ export async function TroubleshootingPreview({ entry }: { entry: ITroubleshootin
) } + +export function TroubleshootingHeader({ + title, + description, + keywords, + products, + errors, +}: { + title: string + description: string + keywords: Array + products?: Array + errors: ITroubleshootingMetadata['errors'] +}) { + return ( +
+
+

{title}

+

{description}

+
+ +
+
+ ) +} + +export function TroubleshootingEntries({ + name, + entries, +}: { + name: string + entries: Array +}) { + return ( +
+

Matching troubleshooting entries

+ {entries.length === 0 ? ( +
+

+ No troubleshooting guides available for {name} yet. +

+
+ ) : ( +
    + {entries.map((entry) => ( +
  • + +
  • + ))} +
+ )} +
+ ) +} diff --git a/apps/docs/features/docs/Troubleshooting.utils.ts b/apps/docs/features/docs/Troubleshooting.utils.ts index f789f1101f4..ce613c7ef43 100644 --- a/apps/docs/features/docs/Troubleshooting.utils.ts +++ b/apps/docs/features/docs/Troubleshooting.utils.ts @@ -113,3 +113,60 @@ async function getTroubleshootingUpdatedDatesInternal() { }, new Map()) } export const getTroubleshootingUpdatedDates = cache(getTroubleshootingUpdatedDatesInternal) + +async function getTroubleshootingEntriesByTopicImpl( + topic: ITroubleshootingMetadata['topics'][number] +) { + const allEntries = await getAllTroubleshootingEntries() + return allEntries.filter((entry) => entry.data.topics.includes(topic)) +} +export const getTroubleshootingEntriesByTopic = cache_fullProcess_withDevCacheBust( + getTroubleshootingEntriesByTopicImpl, + TROUBLESHOOTING_DIRECTORY, + () => JSON.stringify([]) +) + +export async function getTroubleshootingKeywordsByTopic( + topic: ITroubleshootingMetadata['topics'][number] +) { + const entries = await getTroubleshootingEntriesByTopic(topic) + const keywords = new Set() + for (const entry of entries) { + for (const entryTopic of entry.data.topics) { + keywords.add(entryTopic) + } + for (const keyword of entry.data.keywords ?? []) { + keywords.add(keyword) + } + } + return Array.from(keywords).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())) +} + +export async function getTroubleshootingErrorsByTopic( + topic: ITroubleshootingMetadata['topics'][number] +) { + const entries = await getTroubleshootingEntriesByTopic(topic) + const allErrors = new Set( + entries + .flatMap((entry) => entry.data.errors ?? []) + .filter((error) => error?.http_status_code || error?.code) + ) + + const seen = new Set() + for (const error of allErrors) { + const key = formatError(error) + if (seen.has(key)) { + allErrors.delete(error) + } + seen.add(key) + } + + function sortErrors( + a: NonNullable[number], + b: NonNullable[number] + ) { + return formatError(a).localeCompare(formatError(b)) + } + + return Array.from(allErrors).sort(sortErrors) +} diff --git a/apps/docs/features/docs/TroubleshootingSection.page.tsx b/apps/docs/features/docs/TroubleshootingSection.page.tsx new file mode 100644 index 00000000000..9358ca24b19 --- /dev/null +++ b/apps/docs/features/docs/TroubleshootingSection.page.tsx @@ -0,0 +1,68 @@ +import { type Metadata } from 'next' + +import { TroubleshootingHeader, TroubleshootingEntries } from '~/features/docs/Troubleshooting.ui' +import { + TroubleshootingFilterEmptyState, + TroubleshootingListController, +} from '~/features/docs/Troubleshooting.ui.client' +import { + type ITroubleshootingMetadata, + getTroubleshootingEntriesByTopic, + getTroubleshootingErrorsByTopic, + getTroubleshootingKeywordsByTopic, +} from '~/features/docs/Troubleshooting.utils' +import { PROD_URL } from '~/lib/constants' + +interface SectionTroubleshootingPageProps { + topic: ITroubleshootingMetadata['topics'][number] + sectionName: string + description?: string +} + +export default async function SectionTroubleshootingPage({ + topic, + sectionName, + description, +}: SectionTroubleshootingPageProps) { + // All other fetches are dependent on getTroubleshootingEntriesByTopic, which + // is cached, so it's run first to populate the cache + const troubleshootingEntries = await getTroubleshootingEntriesByTopic(topic) + const [keywords, errors] = await Promise.all([ + getTroubleshootingKeywordsByTopic(topic), + getTroubleshootingErrorsByTopic(topic), + ]) + + const pageTitle = `${sectionName} Troubleshooting` + const pageDescription = + description || `Search or browse troubleshooting guides for common ${sectionName} issues.` + + return ( +
+ +
+
+ + + +
+
+
+ ) +} + +export function generateSectionTroubleshootingMetadata( + topic: string, + sectionName: string +): Metadata { + return { + title: `Supabase Docs | ${sectionName} Troubleshooting`, + alternates: { + canonical: `${PROD_URL}/guides/${topic}/troubleshooting`, + }, + } +} From 768a991d20213d293a7cf00f8388baeaf5368232 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Tue, 5 Aug 2025 18:31:27 -0400 Subject: [PATCH 18/28] docs: add docs on how to unban ips from dashboard (#37669) --- ...d-when-trying-to-connect-to-supabase-database-hwG0Dr.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/docs/content/troubleshooting/error-connection-refused-when-trying-to-connect-to-supabase-database-hwG0Dr.mdx b/apps/docs/content/troubleshooting/error-connection-refused-when-trying-to-connect-to-supabase-database-hwG0Dr.mdx index ae4057d5efc..7f1c8e763c9 100644 --- a/apps/docs/content/troubleshooting/error-connection-refused-when-trying-to-connect-to-supabase-database-hwG0Dr.mdx +++ b/apps/docs/content/troubleshooting/error-connection-refused-when-trying-to-connect-to-supabase-database-hwG0Dr.mdx @@ -21,6 +21,12 @@ Is the server running on that host and accepting TCP/IP connections?`, this coul These bans will clear after 30mins but you can unban the IPs using the Supabase CLI https://supabase.com/docs/guides/cli following the commands below. +## Unban IPs using the Dashboard + +Go to [Database Settings](https://supabase.com/dashboard/project/_/database/settings#banned-ips) and click **Unban IP**. + +## Unban IPs using the CLI + How to list the banned IPs: ``` From 553da3cb281d020a2e0f7cf66bea00d8206f137a Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Tue, 5 Aug 2025 18:35:36 -0400 Subject: [PATCH 19/28] chore: generate pages on demand for staging (#37207) Continuing the work to generate pages on-demand in staging so we can lower preview build times --- apps/docs/app/guides/ai/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/api/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/auth/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/cron/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/database/[[...slug]]/page.tsx | 6 +++--- .../database/extensions/wrappers/[[...slug]]/page.tsx | 7 +++++-- apps/docs/app/guides/deployment/[[...slug]]/page.tsx | 6 +++--- .../app/guides/deployment/terraform/[[...slug]]/page.tsx | 8 +++++--- apps/docs/app/guides/functions/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/getting-started/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/graphql/[[...slug]]/page.tsx | 8 +++++--- apps/docs/app/guides/integrations/[[...slug]]/page.tsx | 6 +++--- .../app/guides/local-development/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/platform/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/queues/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/resources/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/security/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx | 6 +++--- apps/docs/app/guides/telemetry/[[...slug]]/page.tsx | 6 +++--- 19 files changed, 63 insertions(+), 56 deletions(-) diff --git a/apps/docs/app/guides/ai/[[...slug]]/page.tsx b/apps/docs/app/guides/ai/[[...slug]]/page.tsx index a28fcec584a..f517756dd71 100644 --- a/apps/docs/app/guides/ai/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/ai/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const AiGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('ai') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('ai') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['ai', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/api/[[...slug]]/page.tsx b/apps/docs/app/guides/api/[[...slug]]/page.tsx index a4a486a7d12..f68aadb62e4 100644 --- a/apps/docs/app/guides/api/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/api/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const ApiGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('api') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('api') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['api', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/auth/[[...slug]]/page.tsx b/apps/docs/app/guides/auth/[[...slug]]/page.tsx index c114d44da86..49c670824a4 100644 --- a/apps/docs/app/guides/auth/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/auth/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const AuthGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('auth') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('auth') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['auth', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/cron/[[...slug]]/page.tsx b/apps/docs/app/guides/cron/[[...slug]]/page.tsx index f8a57df5367..e77e622d824 100644 --- a/apps/docs/app/guides/cron/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/cron/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const CronGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('cron') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('cron') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['cron', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/database/[[...slug]]/page.tsx b/apps/docs/app/guides/database/[[...slug]]/page.tsx index fde70f6e2b3..8b6622d22fc 100644 --- a/apps/docs/app/guides/database/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/database/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const DatabaseGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('database') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('database') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['database', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx index 394c771b240..d695b03374a 100644 --- a/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/database/extensions/wrappers/[[...slug]]/page.tsx @@ -22,8 +22,7 @@ import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' import { octokit } from '~/lib/octokit' import { SerializeOptions } from '~/types/next-mdx-remote-serialize' - -export const dynamicParams = false +import { IS_PROD } from 'common' // We fetch these docs at build time from an external repo const org = 'supabase' @@ -416,6 +415,10 @@ const urlTransform: UrlTransformFunction = (url) => { } const generateStaticParams = async () => { + if (IS_PROD) { + return [] + } + const mdxPaths = await genGuidesStaticParams('database/extensions/wrappers')() const federatedPaths = pageMap.map(({ slug }) => ({ slug: [slug], diff --git a/apps/docs/app/guides/deployment/[[...slug]]/page.tsx b/apps/docs/app/guides/deployment/[[...slug]]/page.tsx index b9c78bf2b21..7b8be32adcc 100644 --- a/apps/docs/app/guides/deployment/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/deployment/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const DeploymentGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('deployment') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('deployment') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['deployment', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx b/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx index 2bb83de9298..ac534357703 100644 --- a/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/deployment/terraform/[[...slug]]/page.tsx @@ -17,8 +17,8 @@ import { terraformDocsRepo, } from '../terraformConstants' import { SerializeOptions } from '~/types/next-mdx-remote-serialize' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' // Each external docs page is mapped to a local page const pageMap = [ @@ -142,7 +142,9 @@ const getContent = async ({ slug }: Params) => { } } -const generateStaticParams = async () => pageMap.map(({ slug }) => ({ slug: slug ? [slug] : [] })) +const generateStaticParams = IS_PROD + ? async () => pageMap.map(({ slug }) => ({ slug: slug ? [slug] : [] })) + : getEmptyArray const generateMetadata = genGuideMeta(getContent) export default TerraformDocs diff --git a/apps/docs/app/guides/functions/[[...slug]]/page.tsx b/apps/docs/app/guides/functions/[[...slug]]/page.tsx index 9a2d3afc802..e416a7b17ae 100644 --- a/apps/docs/app/guides/functions/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/functions/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const FunctionsGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('functions') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('functions') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['functions', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/getting-started/[[...slug]]/page.tsx b/apps/docs/app/guides/getting-started/[[...slug]]/page.tsx index 130dbe1455a..52e9425c92f 100644 --- a/apps/docs/app/guides/getting-started/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/getting-started/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const GettingStartedGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('getting-started') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('getting-started') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['getting-started', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/graphql/[[...slug]]/page.tsx b/apps/docs/app/guides/graphql/[[...slug]]/page.tsx index 64b69a6a8c3..472bd90083c 100644 --- a/apps/docs/app/guides/graphql/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/graphql/[[...slug]]/page.tsx @@ -10,8 +10,8 @@ import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition' import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle' import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs' import { SerializeOptions } from '~/types/next-mdx-remote-serialize' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' // We fetch these docs at build time from an external repo const org = 'supabase' @@ -190,7 +190,9 @@ const urlTransform: UrlTransformFunction = (url) => { } } -const generateStaticParams = async () => pageMap.map(({ slug }) => ({ slug: slug ? [slug] : [] })) +const generateStaticParams = IS_PROD + ? async () => pageMap.map(({ slug }) => ({ slug: slug ? [slug] : [] })) + : getEmptyArray const generateMetadata = genGuideMeta(getContent) export default PGGraphQLDocs diff --git a/apps/docs/app/guides/integrations/[[...slug]]/page.tsx b/apps/docs/app/guides/integrations/[[...slug]]/page.tsx index a7aa94254f4..819c1e0bfd7 100644 --- a/apps/docs/app/guides/integrations/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/integrations/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const IntegrationsGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('integrations') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('integrations') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['integrations', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/local-development/[[...slug]]/page.tsx b/apps/docs/app/guides/local-development/[[...slug]]/page.tsx index 006d4f49ac3..4166055f268 100644 --- a/apps/docs/app/guides/local-development/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/local-development/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const LocalDevelopmentGuidePage = async (props: { params: Promise }) => return } -const generateStaticParams = genGuidesStaticParams('local-development') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('local-development') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['local-development', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/platform/[[...slug]]/page.tsx b/apps/docs/app/guides/platform/[[...slug]]/page.tsx index 3f0a8c13b28..7ca75717816 100644 --- a/apps/docs/app/guides/platform/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/platform/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const PlatformGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('platform') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('platform') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['platform', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/queues/[[...slug]]/page.tsx b/apps/docs/app/guides/queues/[[...slug]]/page.tsx index 42e5de3b554..991c81c189b 100644 --- a/apps/docs/app/guides/queues/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/queues/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const QueuesGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('queues') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('queues') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['queues', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/resources/[[...slug]]/page.tsx b/apps/docs/app/guides/resources/[[...slug]]/page.tsx index f3f98d791cb..c4ef4796b42 100644 --- a/apps/docs/app/guides/resources/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/resources/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const ResourcesGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('resources') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('resources') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['resources', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/security/[[...slug]]/page.tsx b/apps/docs/app/guides/security/[[...slug]]/page.tsx index 0e8fb207219..4a62d58281d 100644 --- a/apps/docs/app/guides/security/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/security/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const SecurityGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('security') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('security') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['security', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx b/apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx index 11b33e3894d..39f7d03b452 100644 --- a/apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/self-hosting/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const SelfHostingGuidePage = async (props: { params: Promise }) => { return } -const generateStaticParams = genGuidesStaticParams('self-hosting') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('self-hosting') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['self-hosting', ...(params.slug ?? [])]) ) diff --git a/apps/docs/app/guides/telemetry/[[...slug]]/page.tsx b/apps/docs/app/guides/telemetry/[[...slug]]/page.tsx index 69dfb1381d2..26be534bde8 100644 --- a/apps/docs/app/guides/telemetry/[[...slug]]/page.tsx +++ b/apps/docs/app/guides/telemetry/[[...slug]]/page.tsx @@ -4,8 +4,8 @@ import { genGuidesStaticParams, } from '~/features/docs/GuidesMdx.utils' import { GuideTemplate } from '~/features/docs/GuidesMdx.template' - -export const dynamicParams = false +import { IS_PROD } from 'common' +import { getEmptyArray } from '~/features/helpers.fn' type Params = { slug?: string[] } @@ -17,7 +17,7 @@ const MonitoringTroubleshootingGuidePage = async (props: { params: Promise } -const generateStaticParams = genGuidesStaticParams('telemetry') +const generateStaticParams = IS_PROD ? genGuidesStaticParams('telemetry') : getEmptyArray const generateMetadata = genGuideMeta((params: { slug?: string[] }) => getGuidesMarkdown(['telemetry', ...(params.slug ?? [])]) ) From 662741a9d778e39dabbc3ca924cb4edd2912a100 Mon Sep 17 00:00:00 2001 From: Tristan Yang Date: Wed, 6 Aug 2025 06:45:18 +0800 Subject: [PATCH 20/28] Update custom-domains.mdx (#37675) missing --experimental flag in activate vanity subdomain cli --- apps/docs/content/guides/platform/custom-domains.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/content/guides/platform/custom-domains.mdx b/apps/docs/content/guides/platform/custom-domains.mdx index 90f577dc6fb..32226013bb8 100644 --- a/apps/docs/content/guides/platform/custom-domains.mdx +++ b/apps/docs/content/guides/platform/custom-domains.mdx @@ -193,7 +193,7 @@ Once you've chosen an available subdomain and have done all the necessary prepar Use the [`vanity-subdomains activate`](/docs/reference/cli/supabase-vanity-subdomains-activate) command to activate and claim your subdomain: ```bash -supabase vanity-subdomains --project-ref abcdefghijklmnopqrst activate --desired-subdomain my-example-brand +supabase vanity-subdomains --project-ref abcdefghijklmnopqrst activate --desired-subdomain my-example-brand --experimental ``` If you wish to use the new domain in client code, you can set it up like so: From 16fa59f127bb23b95ba333a5f2fde1b10fed3c7e Mon Sep 17 00:00:00 2001 From: Danny White <3104761+dnywh@users.noreply.github.com> Date: Wed, 6 Aug 2025 09:47:23 +1000 Subject: [PATCH 21/28] feat: sticky storage config (#37654) * feat: move storage settings * feat: redirect * feat: database settings in service area * feat: move data api settings * fix: revert data API placement * feat: minor UX touches * fix: simplify configuration group * feat: references to database settings * feat: references to storage settings * fix: redirects and formatting * fix: Import StorageMenu dynamically to avoid SSR issues with useLocalStorage * feat: sticky sidebar footer * fix: move Data API closer to semantic siblings * fix: revert smart comma * Shift bucket sort logic into storage explorer store * Small fix and clean up * fix: correct background-color class --------- Co-authored-by: Joshen Lim --- apps/studio/components/interfaces/Storage/StorageMenu.tsx | 6 ++---- .../components/layouts/ProjectLayout/ProjectLayout.tsx | 8 +++++++- .../components/layouts/StorageLayout/StorageLayout.tsx | 7 ++++++- .../ui-patterns/src/MobileSheetNav/MobileSheetNav.tsx | 7 ++++--- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/apps/studio/components/interfaces/Storage/StorageMenu.tsx b/apps/studio/components/interfaces/Storage/StorageMenu.tsx index 9683bbe95d9..44e88926c81 100644 --- a/apps/studio/components/interfaces/Storage/StorageMenu.tsx +++ b/apps/studio/components/interfaces/Storage/StorageMenu.tsx @@ -67,7 +67,7 @@ const StorageMenu = () => { return ( <> - +
{ )}
-
- -
+
Configuration} /> diff --git a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx index f183b8a9bb5..3675e8f9dee 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx @@ -66,6 +66,7 @@ export interface ProjectLayoutProps { productMenu?: ReactNode selectedTable?: string resizableSidebar?: boolean + stickySidebarBottom?: boolean productMenuClassName?: string } @@ -80,6 +81,7 @@ const ProjectLayout = forwardRef - + {productMenu} diff --git a/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx b/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx index 43086ce4f42..79c1898809f 100644 --- a/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx +++ b/apps/studio/components/layouts/StorageLayout/StorageLayout.tsx @@ -11,7 +11,12 @@ export interface StorageLayoutProps { const StorageLayout = ({ title, children }: StorageLayoutProps) => { return ( - }> + } + > {children} ) diff --git a/packages/ui-patterns/src/MobileSheetNav/MobileSheetNav.tsx b/packages/ui-patterns/src/MobileSheetNav/MobileSheetNav.tsx index 0b9a7421579..872d4952af9 100644 --- a/packages/ui-patterns/src/MobileSheetNav/MobileSheetNav.tsx +++ b/packages/ui-patterns/src/MobileSheetNav/MobileSheetNav.tsx @@ -11,7 +11,8 @@ const MobileSheetNav: React.FC<{ children: React.ReactNode open?: boolean onOpenChange(open: boolean): void -}> = ({ children, open = false, onOpenChange }) => { + stickyBottom?: boolean +}> = ({ children, open = false, onOpenChange, stickyBottom = false }) => { const router = useRouter() const { width } = useWindowSize() @@ -31,8 +32,8 @@ const MobileSheetNav: React.FC<{ size="full" side="bottom" className={cn( - 'rounded-t-lg overflow-hidden overflow-y-scroll', - 'h-[85dvh] md:max-h-[500px] py-2' + 'rounded-t-lg overflow-hidden overflow-y-scroll h-[85dvh] md:max-h-[500px]', + stickyBottom ? 'pt-2 pb-0' : 'py-2' )} > }>{children} From 32b5d8c244e4e06a15e090f35776e4472a7f8ca5 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Tue, 5 Aug 2025 21:33:30 -0230 Subject: [PATCH 22/28] feat: enable Self-Service Single Sign-On (SSO) for orgs (#36732) * Start * Add join org logic * Regenerate the API types and add RQ hooks. * Various fixes to the UI for SSO config. * Refactor the components to use RHF. * Fix the loading/error states in the main file. * fix: minor changes to SSO UI * Expanded default attribute mapping preset for `Okta` to include `user_name`, `first_name`, and `last_name` to match our docs. * Normalized role casing in the "Join Organization on Signup" dropdown to match the roles expected by the backend (`Owner`, `Administrator`, `Developer`). * Added the role (`Read-only`) to the selectable roles for auto-join. * Call update mutation when an `ssoConfig` has been retrieved. * Treats `404` as a valid "create" flow state rather than an error. * Conditionally renders the SSO config form when config is successfully loaded *or* when the provider is not found, allowing users to onboard from scratch and disable the provider. * chore: prettier * feat: add a button linking to SSO setup docs * Revert "feat: add a button linking to SSO setup docs" This will be included in a separate docs pr. This reverts commit 0b616fdd2e2a656decad4fd1c8d0951fb0cbf1bd. * General clean up * Nit copy * Add empty state for SSO * Smol change * One last tweak --------- Co-authored-by: Chris Stockton <180184+cstockton@users.noreply.github.com> Co-authored-by: Ivan Vasilov Co-authored-by: Chris Stockton Co-authored-by: Joshen Lim --- .../Organization/SSO/AttributeMapping.tsx | 218 +++++++++++++ .../SSO/JoinOrganizationOnSignup.tsx | 73 +++++ .../interfaces/Organization/SSO/SSOConfig.tsx | 296 ++++++++++++++++++ .../Organization/SSO/SSODomains.tsx | 66 ++++ .../Organization/SSO/SSOMetadata.tsx | 130 ++++++++ .../OrganizationSettingsLayout.tsx | 6 + apps/studio/data/api-keys/api-keys-query.ts | 15 +- .../api-keys/legacy-api-keys-status-query.ts | 13 +- apps/studio/data/sso/keys.ts | 3 + .../data/sso/sso-config-create-mutation.ts | 54 ++++ apps/studio/data/sso/sso-config-query.ts | 54 ++++ .../data/sso/sso-config-update-mutation.ts | 58 ++++ apps/studio/pages/org/[slug]/sso.tsx | 19 ++ packages/api-types/types/platform.d.ts | 278 ++++++++++++++++ 14 files changed, 1269 insertions(+), 14 deletions(-) create mode 100644 apps/studio/components/interfaces/Organization/SSO/AttributeMapping.tsx create mode 100644 apps/studio/components/interfaces/Organization/SSO/JoinOrganizationOnSignup.tsx create mode 100644 apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx create mode 100644 apps/studio/components/interfaces/Organization/SSO/SSODomains.tsx create mode 100644 apps/studio/components/interfaces/Organization/SSO/SSOMetadata.tsx create mode 100644 apps/studio/data/sso/keys.ts create mode 100644 apps/studio/data/sso/sso-config-create-mutation.ts create mode 100644 apps/studio/data/sso/sso-config-query.ts create mode 100644 apps/studio/data/sso/sso-config-update-mutation.ts create mode 100644 apps/studio/pages/org/[slug]/sso.tsx diff --git a/apps/studio/components/interfaces/Organization/SSO/AttributeMapping.tsx b/apps/studio/components/interfaces/Organization/SSO/AttributeMapping.tsx new file mode 100644 index 00000000000..1f6977824d9 --- /dev/null +++ b/apps/studio/components/interfaces/Organization/SSO/AttributeMapping.tsx @@ -0,0 +1,218 @@ +import { Plus, Trash } from 'lucide-react' +import { UseFormReturn, useFieldArray } from 'react-hook-form' + +import { + Button, + FormControl_Shadcn_, + FormField_Shadcn_, + FormItem_Shadcn_, + FormMessage_Shadcn_, + Input_Shadcn_, +} from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' +import type { SSOConfigFormSchema } from './SSOConfig' + +type ProviderAttribute = 'emailMapping' | 'userNameMapping' | 'firstNameMapping' | 'lastNameMapping' + +type ProviderPreset = { + name: string + attributeMapping: { + keys: { + email?: { name: string } + user_name?: { name: string } + first_name?: { name: string } + last_name?: { name: string } + name_identifier?: { name: string } + } + } +} + +const PROVIDER_PRESETS: ProviderPreset[] = [ + { + name: 'GSuite', + attributeMapping: { + keys: { + email: { + name: 'email', + }, + user_name: { + name: 'user_name', + }, + first_name: { + name: 'first_name', + }, + last_name: { + name: 'last_name', + }, + }, + }, + }, + { + name: 'Azure', + attributeMapping: { + keys: { + email: { + name: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress', + }, + name_identifier: { + name: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier', + }, + first_name: { + name: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname', + }, + last_name: { + name: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname', + }, + }, + }, + }, + { + name: 'Okta', + attributeMapping: { + keys: { + email: { + name: 'email', + }, + user_name: { + name: 'user_name', + }, + first_name: { + name: 'first_name', + }, + last_name: { + name: 'last_name', + }, + }, + }, + }, +] as const + +export const AttributeMapping = ({ + form, + emailField, + userNameField, + firstNameField, + lastNameField, +}: { + form: UseFormReturn + emailField: ProviderAttribute + userNameField: ProviderAttribute + firstNameField: ProviderAttribute + lastNameField: ProviderAttribute +}) => { + // Helper to apply a preset + function applyPreset(preset: ProviderPreset) { + const keys = preset.attributeMapping.keys + // Set each field if present in the preset, otherwise clear + form.setValue(emailField, [{ value: keys.email?.name ?? '' }]) + form.setValue(userNameField, [{ value: keys.user_name?.name ?? '' }]) + form.setValue(firstNameField, [{ value: keys.first_name?.name ?? '' }]) + form.setValue(lastNameField, [{ value: keys.last_name?.name ?? '' }]) + } + + return ( + +

Map SSO attributes to user fields

+
+

Presets for supported identity providers:

+
+ {PROVIDER_PRESETS.map((preset) => ( + + ))} +
+
+
+ } + className="gap-1" + > +
+ + + + +
+ + ) +} + +const MappingFieldArray = ({ + form, + fieldName, + label, + required, + placeholder, +}: { + form: UseFormReturn + fieldName: ProviderAttribute + label: string + required: boolean + placeholder?: string +}) => { + const { fields, append, remove } = useFieldArray({ + control: form.control, + name: fieldName, + }) + + return ( +
+
+ {label} + {required ? <> : Optional} +
+
+ {fields.map((field, idx) => ( +
+ ( + + + + + + + )} + /> +
+ ))} + + +
+
+ ) +} diff --git a/apps/studio/components/interfaces/Organization/SSO/JoinOrganizationOnSignup.tsx b/apps/studio/components/interfaces/Organization/SSO/JoinOrganizationOnSignup.tsx new file mode 100644 index 00000000000..c03389a6908 --- /dev/null +++ b/apps/studio/components/interfaces/Organization/SSO/JoinOrganizationOnSignup.tsx @@ -0,0 +1,73 @@ +import { useForm } from 'react-hook-form' + +import { + FormControl_Shadcn_, + FormField_Shadcn_, + Select_Shadcn_, + SelectContent_Shadcn_, + SelectGroup_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, + SelectValue_Shadcn_, + Switch, +} from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' +import { SSOConfigFormSchema } from './SSOConfig' + +export const JoinOrganizationOnSignup = ({ + form, +}: { + form: ReturnType> +}) => { + const joinOrgOnSignup = form.watch('joinOrgOnSignup') + + return ( +
+ ( + + + + + + )} + /> + {joinOrgOnSignup && ( + ( + + + field.onChange(val)}> + + + + + + Owner + Administrator + Developer + Read-only + + + + + + )} + /> + )} +
+ ) +} diff --git a/apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx b/apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx new file mode 100644 index 00000000000..666dd44c44c --- /dev/null +++ b/apps/studio/components/interfaces/Organization/SSO/SSOConfig.tsx @@ -0,0 +1,296 @@ +import { zodResolver } from '@hookform/resolvers/zod' +import Link from 'next/link' +import { useEffect } from 'react' +import { SubmitHandler, useForm } from 'react-hook-form' +import z from 'zod' + +import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' +import AlertError from 'components/ui/AlertError' +import { InlineLink } from 'components/ui/InlineLink' +import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' +import { useSSOConfigCreateMutation } from 'data/sso/sso-config-create-mutation' +import { useOrgSSOConfigQuery } from 'data/sso/sso-config-query' +import { useSSOConfigUpdateMutation } from 'data/sso/sso-config-update-mutation' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { + AlertDescription_Shadcn_, + AlertTitle_Shadcn_, + Alert_Shadcn_, + Button, + Card, + CardContent, + CardFooter, + FormControl_Shadcn_, + FormField_Shadcn_, + Form_Shadcn_, + Switch, + WarningIcon, +} from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' +import { AttributeMapping } from './AttributeMapping' +import { JoinOrganizationOnSignup } from './JoinOrganizationOnSignup' +import { SSODomains } from './SSODomains' +import { SSOMetadata } from './SSOMetadata' + +const FormSchema = z + .object({ + enabled: z.boolean(), + domains: z + .array( + z.object({ + value: z.string().trim().min(1, 'Please provide a domain'), + }) + ) + .min(1, 'At least one domain is required'), + metadataXmlUrl: z.string().trim().optional(), + metadataXmlFile: z.string().trim().optional(), + emailMapping: z.array(z.object({ value: z.string().trim().min(1, 'This field is required') })), + userNameMapping: z.array(z.object({ value: z.string().trim() })), + firstNameMapping: z.array(z.object({ value: z.string().trim() })), + lastNameMapping: z.array(z.object({ value: z.string().trim() })), + joinOrgOnSignup: z.boolean(), + roleOnJoin: z.string().optional(), + }) + // set the error on both fields + .refine((data) => data.metadataXmlUrl || data.metadataXmlFile, { + message: 'Please provide either a metadata XML URL or upload a metadata XML file', + path: ['metadataXmlUrl'], + }) + .refine((data) => data.metadataXmlUrl || data.metadataXmlFile, { + message: 'Please provide either a metadata XML URL or upload a metadata XML file', + path: ['metadataXmlFile'], + }) + +export type SSOConfigFormSchema = z.infer + +export const SSOConfig = () => { + const FORM_ID = 'sso-config-form' + + const { data: organization, isLoading: isLoadingOrganization } = useSelectedOrganizationQuery() + const plan = organization?.plan.id + const canSetupSSOConfig = ['team', 'enterprise'].includes(plan ?? '') + + const { + data: ssoConfig, + isLoading: isLoadingSSOConfig, + isSuccess, + isError, + error: configError, + } = useOrgSSOConfigQuery({ orgSlug: organization?.slug }, { enabled: !!organization }) + + const isSSOProviderNotFound = ssoConfig === null + + const form = useForm({ + resolver: zodResolver(FormSchema), + defaultValues: { + enabled: false, + domains: [{ value: '' }], + metadataXmlUrl: '', + metadataXmlFile: '', + emailMapping: [{ value: '' }], + userNameMapping: [{ value: '' }], + firstNameMapping: [{ value: '' }], + lastNameMapping: [{ value: '' }], + joinOrgOnSignup: false, + roleOnJoin: 'Developer', + }, + }) + + const isSSOEnabled = form.watch('enabled') + + const { mutate: createSSOConfig, isLoading: isCreating } = useSSOConfigCreateMutation({ + onSuccess: () => form.reset(), + }) + + const { mutate: updateSSOConfig, isLoading: isUpdating } = useSSOConfigUpdateMutation({ + onSuccess: () => form.reset(), + }) + + const onSubmit: SubmitHandler = (values) => { + const roleOnJoin = (values.roleOnJoin || 'Developer') as + | 'Administrator' + | 'Developer' + | 'Owner' + | 'Read-only' + | undefined + + const payload = { + slug: organization!.slug, + config: { + enabled: values.enabled, + domains: values.domains.map((d) => d.value), + metadata_xml_file: values.metadataXmlFile!, + metadata_xml_url: values.metadataXmlUrl!, + email_mapping: values.emailMapping.map((item) => item.value).filter(Boolean), + first_name_mapping: values.firstNameMapping.map((item) => item.value).filter(Boolean), + last_name_mapping: values.lastNameMapping.map((item) => item.value).filter(Boolean), + user_name_mapping: values.userNameMapping.map((item) => item.value).filter(Boolean), + join_org_on_signup_enabled: values.joinOrgOnSignup, + join_org_on_signup_role: roleOnJoin, + }, + } + + if (!!ssoConfig) { + updateSSOConfig(payload) + } else { + createSSOConfig(payload) + } + } + + useEffect(() => { + if (ssoConfig) { + form.reset({ + enabled: ssoConfig.enabled, + domains: ssoConfig.domains.map((domain) => ({ value: domain })), + metadataXmlUrl: ssoConfig.metadata_xml_url, + metadataXmlFile: ssoConfig.metadata_xml_file, + emailMapping: ssoConfig.email_mapping.map((email) => ({ value: email })), + userNameMapping: ssoConfig.user_name_mapping.map((userName) => ({ value: userName })), + firstNameMapping: ssoConfig.first_name_mapping.map((firstName) => ({ value: firstName })), + lastNameMapping: ssoConfig.last_name_mapping.map((lastName) => ({ value: lastName })), + joinOrgOnSignup: ssoConfig.join_org_on_signup_enabled, + roleOnJoin: ssoConfig.join_org_on_signup_role, + }) + } + }, [ssoConfig, form]) + + return ( + + + {!!plan && !canSetupSSOConfig ? ( + + +
+
+ + Organization Single Sign-on (SSO) is available from Team plan and above + + +

+ SSO as a login option provides additional acccount security for your team by + enforcing the use of an identity provider when logging into Supabase. Upgrade to + Team or above to set up SSO for your organization. +

+
+
+ +
+ +
+
+
+ ) : ( + <> + {isLoadingSSOConfig && ( + + + + + + )} + + {isError && !isSSOProviderNotFound && ( + + )} + + {(isSuccess || isSSOProviderNotFound) && ( + +
+ + + ( + + Enable and configure SSO for your organization. Learn more about SSO{' '} + + here + + . + + } + > + + + + + )} + /> + + + {(isSSOEnabled || ssoConfig) && ( + <> + + + + + + + + + + + + + + + + + )} + + + {form.formState.isDirty && ( + + )} + + + +
+
+ )} + + )} +
+
+ ) +} diff --git a/apps/studio/components/interfaces/Organization/SSO/SSODomains.tsx b/apps/studio/components/interfaces/Organization/SSO/SSODomains.tsx new file mode 100644 index 00000000000..996ddb5297d --- /dev/null +++ b/apps/studio/components/interfaces/Organization/SSO/SSODomains.tsx @@ -0,0 +1,66 @@ +import { Plus, Trash } from 'lucide-react' +import { useFieldArray, useForm } from 'react-hook-form' + +import { + Button, + FormControl_Shadcn_, + FormField_Shadcn_, + FormItem_Shadcn_, + FormMessage_Shadcn_, + Input_Shadcn_, +} from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' +import { SSOConfigFormSchema } from './SSOConfig' + +export const SSODomains = ({ form }: { form: ReturnType> }) => { + const { fields, append, remove } = useFieldArray({ + control: form.control, + name: 'domains', + }) + + return ( + <> + +
+ {fields.map((field, idx) => ( +
+ ( + + + + + + + )} + /> + +
+ ))} +
+ +
+
+
+ + ) +} diff --git a/apps/studio/components/interfaces/Organization/SSO/SSOMetadata.tsx b/apps/studio/components/interfaces/Organization/SSO/SSOMetadata.tsx new file mode 100644 index 00000000000..65a9db5f888 --- /dev/null +++ b/apps/studio/components/interfaces/Organization/SSO/SSOMetadata.tsx @@ -0,0 +1,130 @@ +import { Upload } from 'lucide-react' +import { useEffect, useRef, useState } from 'react' +import { useForm } from 'react-hook-form' + +import { + Button, + FormControl_Shadcn_, + FormField_Shadcn_, + FormItem_Shadcn_, + FormMessage_Shadcn_, + Input_Shadcn_, + Tabs_Shadcn_, + TabsContent_Shadcn_, + TabsList_Shadcn_, + TabsTrigger_Shadcn_, +} from 'ui' +import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' +import { SSOConfigFormSchema } from './SSOConfig' + +export const SSOMetadata = ({ + form, +}: { + form: ReturnType> +}) => { + const fileInputRef = useRef(null) + const [fileName, setFileName] = useState(null) + const [tab, setTab] = useState<'url' | 'file'>('url') + + useEffect(() => { + if (form.getValues('metadataXmlFile')) { + setTab('file') + } else if (form.getValues('metadataXmlUrl')) { + setTab('url') + } + }, [form]) + + const handleFileChange = async (e: React.ChangeEvent) => { + form.clearErrors('metadataXmlFile') + const file = e.target.files?.[0] + if (!file) return + if (!file.name.endsWith('.xml')) { + form.setError('metadataXmlFile', { + type: 'manual', + message: 'Please upload a valid .xml file', + }) + return + } + try { + const text = await file.text() + form.setValue('metadataXmlFile', text, { shouldDirty: true }) + setFileName(file.name) + } catch (err) { + form.setError('metadataXmlFile', { + type: 'manual', + message: 'Failed to read file', + }) + } + } + + return ( + +
+ setTab(value as 'url' | 'file')} + className="max-w-2xl" + > + + + URL + + + Upload file + + + + ( + + + + + + + )} + /> + + + ( +
+
+ + + {fileName && {fileName}} +
+ +
+ )} + /> +
+
+
+
+ ) +} diff --git a/apps/studio/components/layouts/ProjectLayout/OrganizationSettingsLayout.tsx b/apps/studio/components/layouts/ProjectLayout/OrganizationSettingsLayout.tsx index b52a30832ac..eff4dd29ec7 100644 --- a/apps/studio/components/layouts/ProjectLayout/OrganizationSettingsLayout.tsx +++ b/apps/studio/components/layouts/ProjectLayout/OrganizationSettingsLayout.tsx @@ -39,6 +39,12 @@ function OrganizationSettingsLayout({ children }: PropsWithChildren) { label: 'OAuth Apps', href: `/org/${slug}/apps`, }, + + { + label: 'SSO', + href: `/org/${slug}/sso`, + }, + { label: 'Audit Logs', href: `/org/${slug}/audit`, diff --git a/apps/studio/data/api-keys/api-keys-query.ts b/apps/studio/data/api-keys/api-keys-query.ts index 24911001188..5b746e88be7 100644 --- a/apps/studio/data/api-keys/api-keys-query.ts +++ b/apps/studio/data/api-keys/api-keys-query.ts @@ -1,7 +1,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' + import { get, handleError } from 'data/fetchers' import { ResponseError } from 'types' - import { apiKeysKeys } from './keys' type LegacyKeys = { @@ -58,9 +58,7 @@ async function getAPIKeys({ projectRef, reveal }: APIKeysVariables, signal?: Abo signal, }) - if (error) { - handleError(error) - } + if (error) handleError(error) // [Jonny]: Overriding the types here since some stuff is not actually nullable or optional return data as unknown as APIKey[] @@ -70,16 +68,17 @@ export type APIKeysData = Awaited> export const useAPIKeysQuery = ( { projectRef, reveal = false }: APIKeysVariables, - { enabled, ...options }: UseQueryOptions = {} -) => - useQuery( + { enabled = true, ...options }: UseQueryOptions = {} +) => { + return useQuery( apiKeysKeys.list(projectRef, reveal), ({ signal }) => getAPIKeys({ projectRef, reveal }, signal), { - enabled: enabled && !!projectRef, + enabled: enabled && typeof projectRef !== 'undefined', ...options, } ) +} export const getKeys = (apiKeys: APIKey[] = []) => { const anonKey = apiKeys.find((x) => x.name === 'anon') diff --git a/apps/studio/data/api-keys/legacy-api-keys-status-query.ts b/apps/studio/data/api-keys/legacy-api-keys-status-query.ts index d768d3713e7..73f509780f1 100644 --- a/apps/studio/data/api-keys/legacy-api-keys-status-query.ts +++ b/apps/studio/data/api-keys/legacy-api-keys-status-query.ts @@ -1,4 +1,5 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' + import { get, handleError } from 'data/fetchers' import { IS_PLATFORM } from 'lib/constants' import { ResponseError } from 'types' @@ -19,10 +20,7 @@ async function getLegacyAPIKeysStatus( signal, }) - if (error) { - handleError(error) - } - + if (error) handleError(error) return data } @@ -30,13 +28,16 @@ type LegacyAPIKeysStatusData = Awaited export const useLegacyAPIKeysStatusQuery = ( { projectRef }: LegacyAPIKeysStatusVariables, - { enabled, ...options }: UseQueryOptions = {} + { + enabled = true, + ...options + }: UseQueryOptions = {} ) => useQuery( apiKeysKeys.status(projectRef), ({ signal }) => getLegacyAPIKeysStatus({ projectRef }, signal), { - enabled: IS_PLATFORM && enabled && !!projectRef, + enabled: IS_PLATFORM && enabled && typeof projectRef !== 'undefined', ...options, } ) diff --git a/apps/studio/data/sso/keys.ts b/apps/studio/data/sso/keys.ts new file mode 100644 index 00000000000..02c05a3c3a5 --- /dev/null +++ b/apps/studio/data/sso/keys.ts @@ -0,0 +1,3 @@ +export const orgSSOKeys = { + orgSSOConfig: (orgSlug: string | undefined) => ['organizations', orgSlug, 'sso'] as const, +} diff --git a/apps/studio/data/sso/sso-config-create-mutation.ts b/apps/studio/data/sso/sso-config-create-mutation.ts new file mode 100644 index 00000000000..b8df359367f --- /dev/null +++ b/apps/studio/data/sso/sso-config-create-mutation.ts @@ -0,0 +1,54 @@ +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' +import { toast } from 'sonner' + +import type { components } from 'data/api' +import { handleError, post } from 'data/fetchers' +import type { ResponseError } from 'types' +import { orgSSOKeys } from './keys' + +export type SSOConfigCreateVariables = { + slug: string + config: components['schemas']['CreateSSOProviderBody'] +} + +export async function createSSOConfig({ slug, config }: SSOConfigCreateVariables) { + const { data, error } = await post('/platform/organizations/{slug}/sso', { + params: { path: { slug } }, + body: config, + }) + + if (error) handleError(error) + return data +} + +type SSOConfigCreateData = Awaited> + +export const useSSOConfigCreateMutation = ({ + onSuccess, + onError, + ...options +}: Omit< + UseMutationOptions, + 'mutationFn' +> = {}) => { + const queryClient = useQueryClient() + + return useMutation( + (vars) => createSSOConfig(vars), + { + async onSuccess(data, variables, context) { + const { slug } = variables + await queryClient.invalidateQueries(orgSSOKeys.orgSSOConfig(slug)) + await onSuccess?.(data, variables, context) + }, + async onError(data, variables, context) { + if (onError === undefined) { + toast.error(`Failed to create SSO configuration: ${data.message}`) + } else { + onError(data, variables, context) + } + }, + ...options, + } + ) +} diff --git a/apps/studio/data/sso/sso-config-query.ts b/apps/studio/data/sso/sso-config-query.ts new file mode 100644 index 00000000000..5651b7da8a3 --- /dev/null +++ b/apps/studio/data/sso/sso-config-query.ts @@ -0,0 +1,54 @@ +import { useQuery, UseQueryOptions } from '@tanstack/react-query' + +import { get, handleError } from 'data/fetchers' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { IS_PLATFORM } from 'lib/constants' +import type { ResponseError } from 'types' +import { orgSSOKeys } from './keys' + +export type OrgSSOConfigVariables = { + orgSlug?: string +} + +export async function getOrgSSOConfig({ orgSlug }: OrgSSOConfigVariables, signal?: AbortSignal) { + if (!orgSlug) throw new Error('Organization slug is required') + + const { data, error } = await get('/platform/organizations/{slug}/sso', { + params: { path: { slug: orgSlug } }, + signal, + }) + + if (error) { + const ssoNotSetUp = + (error as any)?.code === 404 && + (error as any)?.message?.includes('Failed to find an existing SSO Provider') + + if (ssoNotSetUp) { + return null + } else { + handleError(error) + } + } + return data +} + +export type OrgSSOConfigData = Awaited> +export type OrgSSOConfigError = ResponseError + +export const useOrgSSOConfigQuery = ( + { orgSlug }: OrgSSOConfigVariables, + { enabled = true, ...options }: UseQueryOptions = {} +) => { + const { data: organization } = useSelectedOrganizationQuery() + const plan = organization?.plan.id + const canSetupSSOConfig = ['team', 'enterprise'].includes(plan ?? '') + + return useQuery( + orgSSOKeys.orgSSOConfig(orgSlug), + ({ signal }) => getOrgSSOConfig({ orgSlug }, signal), + { + enabled: enabled && IS_PLATFORM && typeof orgSlug !== 'undefined' && canSetupSSOConfig, + ...options, + } + ) +} diff --git a/apps/studio/data/sso/sso-config-update-mutation.ts b/apps/studio/data/sso/sso-config-update-mutation.ts new file mode 100644 index 00000000000..cca2b2fa7e9 --- /dev/null +++ b/apps/studio/data/sso/sso-config-update-mutation.ts @@ -0,0 +1,58 @@ +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' +import { toast } from 'sonner' + +import type { components } from 'data/api' +import { handleError, put } from 'data/fetchers' +import type { ResponseError } from 'types' +import { orgSSOKeys } from './keys' + +export type SSOConfigUpdateVariables = { + slug: string + config: Partial +} + +export async function updateSSOConfig({ slug, config }: SSOConfigUpdateVariables) { + const { data, error } = await put('/platform/organizations/{slug}/sso', { + params: { path: { slug } }, + body: config as components['schemas']['UpdateSSOProviderBody'], + }) + + if (error) handleError(error) + return data +} + +type SSOConfigUpdateData = Awaited> + +export const useSSOConfigUpdateMutation = ({ + onSuccess, + onError, + ...options +}: Omit< + UseMutationOptions, + 'mutationFn' +> = {}) => { + const queryClient = useQueryClient() + + return useMutation( + (vars) => updateSSOConfig(vars), + { + async onSuccess(data, variables, context) { + const { slug } = variables + await queryClient.invalidateQueries(orgSSOKeys.orgSSOConfig(slug)) + await onSuccess?.(data, variables, context) + }, + async onError(data, variables, context) { + if (onError === undefined) { + if (data.message === '') { + toast.error(`Failed to update SSO configuration.`) + } else { + toast.error(`${data.message}`) + } + } else { + onError(data, variables, context) + } + }, + ...options, + } + ) +} diff --git a/apps/studio/pages/org/[slug]/sso.tsx b/apps/studio/pages/org/[slug]/sso.tsx new file mode 100644 index 00000000000..ede05456713 --- /dev/null +++ b/apps/studio/pages/org/[slug]/sso.tsx @@ -0,0 +1,19 @@ +import { SSOConfig } from 'components/interfaces/Organization/SSO/SSOConfig' +import DefaultLayout from 'components/layouts/DefaultLayout' +import OrganizationLayout from 'components/layouts/OrganizationLayout' +import OrganizationSettingsLayout from 'components/layouts/ProjectLayout/OrganizationSettingsLayout' +import type { NextPageWithLayout } from 'types' + +const OrgSSO: NextPageWithLayout = () => { + return +} + +OrgSSO.getLayout = (page) => ( + + + {page} + + +) + +export default OrgSSO diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts index 1064e1a8f17..8f303e30822 100644 --- a/packages/api-types/types/platform.d.ts +++ b/packages/api-types/types/platform.d.ts @@ -1533,6 +1533,26 @@ export interface paths { patch?: never trace?: never } + '/platform/organizations/{slug}/sso': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Get the organization's SSO Provider */ + get: operations['SSOProvidersController_getSSOProvider'] + /** Update the organization's SSO Provider */ + put: operations['SSOProvidersController_updateSSOProvider'] + /** Create the organization's SSO Provider */ + post: operations['SSOProvidersController_createSSOProvider'] + /** Delete the organization's SSO Provider */ + delete: operations['SSOProvidersController_deleteSSOProvider'] + options?: never + head?: never + patch?: never + trace?: never + } '/platform/organizations/{slug}/tax-ids': { parameters: { query?: never @@ -4908,6 +4928,62 @@ export interface components { /** @description Source id */ id: number } + CreateSSOProviderBody: + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping: string[] + } + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping: string[] + } + CreateSSOProviderResponse: + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping: string[] + } + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping: string[] + } CreateStorageBucketBody: { allowed_mime_types?: string[] file_size_limit?: number @@ -5552,6 +5628,34 @@ export interface components { } path: string[] } + GetSSOProviderResponse: + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping: string[] + } + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping: string[] + } GetStorageCredentialsResponse: { data: { created_at: string @@ -8629,6 +8733,62 @@ export interface components { UpdateSecretsResponse: { message: string } + UpdateSSOProviderBody: + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping: string[] + } + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping: string[] + } + UpdateSSOProviderResponse: + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file: string + /** Format: uri */ + metadata_xml_url?: string + user_name_mapping: string[] + } + | { + domains: string[] + email_mapping: string[] + enabled: boolean + first_name_mapping: string[] + join_org_on_signup_enabled: boolean + /** @enum {string} */ + join_org_on_signup_role?: 'Administrator' | 'Developer' | 'Owner' | 'Read-only' + last_name_mapping: string[] + metadata_xml_file?: string + metadata_xml_url: string + user_name_mapping: string[] + } UpdateStorageBucketBody: { allowed_mime_types?: string[] | null file_size_limit?: number | null @@ -12524,6 +12684,124 @@ export interface operations { } } } + SSOProvidersController_getSSOProvider: { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['GetSSOProviderResponse'] + } + } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + SSOProvidersController_updateSSOProvider: { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['UpdateSSOProviderBody'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['UpdateSSOProviderResponse'] + } + } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + SSOProvidersController_createSSOProvider: { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['CreateSSOProviderBody'] + } + } + responses: { + 201: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['CreateSSOProviderResponse'] + } + } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + SSOProvidersController_deleteSSOProvider: { + parameters: { + query?: never + header?: never + path: { + /** @description Organization slug */ + slug: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content?: never + } + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } TaxIdsController_getTaxId: { parameters: { query?: never From 8b98da65c0fdad21820d88b36f927de3f11fb142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20Caba=C3=A7o?= Date: Wed, 6 Aug 2025 01:47:17 +0100 Subject: [PATCH 23/28] realtime: fix blogpost example to work properly for delete use cases (#37704) --- ...25-04-02-realtime-broadcast-from-database.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/www/_blog/2025-04-02-realtime-broadcast-from-database.mdx b/apps/www/_blog/2025-04-02-realtime-broadcast-from-database.mdx index 7c6a0f2b0b1..c312bc3f06a 100644 --- a/apps/www/_blog/2025-04-02-realtime-broadcast-from-database.mdx +++ b/apps/www/_blog/2025-04-02-realtime-broadcast-from-database.mdx @@ -88,14 +88,14 @@ language plpgsql as $$ begin perform realtime.broadcast_changes( - 'topic:' || new.id::text, -- topic - tg_op, -- event - tg_op, -- operation - tg_table_name, -- table - tg_table_schema, -- schema - new, -- new record - old -- old record - ); + 'topic:' || coalesce(NEW.topic, OLD.topic) ::text, -- topic - the topic to which we're broadcasting + TG_OP, -- event - the event that triggered the function + TG_OP, -- operation - the operation that triggered the function + TG_TABLE_NAME, -- table - the table that caused the trigger + TG_TABLE_SCHEMA, -- schema - the schema of the table that caused the trigger + NEW, -- new record - the record after the change + OLD -- old record - the record before the change + ); return null; end; $$; From 8f6bb2515fd8fcf73c99711de1d34ac01cdd1f1d Mon Sep 17 00:00:00 2001 From: Greggors Date: Tue, 5 Aug 2025 18:26:27 -0700 Subject: [PATCH 24/28] Add Greg Kress to humans.txt (#37702) --- apps/docs/public/humans.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/docs/public/humans.txt b/apps/docs/public/humans.txt index 58db9f6a50c..5024bf43949 100644 --- a/apps/docs/public/humans.txt +++ b/apps/docs/public/humans.txt @@ -46,6 +46,7 @@ Etienne Stalmans Fabrizio Fenoglio Felipe Stival Francesco Sansalvadore +Greg Kress Greg P Greg Richardson Guilherme Souza From 09b7cb6957062e0cc9de79dfd9f79a86ea64ddc6 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Tue, 5 Aug 2025 22:47:58 -0400 Subject: [PATCH 25/28] fix: typo (#37700) --- .../JwtSecrets/jwt-secret-keys-table/rotate-key-dialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/rotate-key-dialog.tsx b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/rotate-key-dialog.tsx index ebff98a2202..1fb7657a1a8 100644 --- a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/rotate-key-dialog.tsx +++ b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/rotate-key-dialog.tsx @@ -222,7 +222,7 @@ export function RotateKeyDialog({ onCheckedChange={(value) => setEdgeFunctionsVerifyJWTUnderstood(!!value)} />

- The following Edge Functions may stop funtioning for signed-in users as they + The following Edge Functions may stop functioning for signed-in users as they verify the legacy JWT secret:{' '} {verifyJWTEdgeFunctions .map(({ name }) => ( From cab05855332250d4c3af9d3119589ff800d7f789 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 6 Aug 2025 10:53:10 +0700 Subject: [PATCH 26/28] Fe 1799/consolidate to useselectedprojectquery and (#37684) * Replace all usage of useProjectContext with useSelectedProjectQuery * Replace all usage of useSelectedProject with useSelectedProjectQuery * Replace all usage of useProjectByRef with useProjectByRefQuery * Replace all usage of useSelectedOrganization with useSelectedOrganizationQuery * Deprecate useSelectedProject, useSelectedOrganization, and useProjectByRef hooks * Deprecate ProjecContext --- apps/studio/components/grid/SupabaseGrid.tsx | 5 +- .../grid/components/editor/JsonEditor.tsx | 6 +- .../grid/components/editor/TextEditor.tsx | 6 +- .../grid/components/footer/Footer.tsx | 4 +- .../footer/pagination/Pagination.tsx | 4 +- .../formatter/ForeignKeyFormatter.tsx | 5 +- .../formatter/ReferenceRecordPeek.tsx | 4 +- .../components/grid/components/grid/Grid.tsx | 9 +-- .../grid/components/grid/Grid.utils.tsx | 6 +- .../grid/components/header/Header.tsx | 4 +- .../grid/hooks/useSaveTableEditorState.ts | 4 +- .../interfaces/Advisors/AdvisorRuleItem.tsx | 4 +- .../interfaces/Advisors/CreateRuleSheet.tsx | 5 +- .../interfaces/App/CommandMenu/ApiUrl.tsx | 4 +- .../FeaturePreview/FeaturePreviewContext.tsx | 4 +- .../FeaturePreview/FeaturePreviewModal.tsx | 4 +- .../interfaces/App/RouteValidationWrapper.tsx | 4 +- .../Auth/AdvancedAuthSettingsForm.tsx | 6 +- .../interfaces/Auth/Hooks/AddHookDropdown.tsx | 4 +- .../interfaces/Auth/Hooks/CreateHookSheet.tsx | 6 +- .../interfaces/Auth/Hooks/HooksListing.tsx | 4 +- .../MfaAuthSettingsForm.tsx | 8 +-- .../interfaces/Auth/Policies/Policies.tsx | 4 +- .../Policies/PolicyEditor/PolicyRoles.tsx | 6 +- .../PolicyEditorPanel/PolicyDetailsV2.tsx | 4 +- .../Auth/Policies/PolicyEditorPanel/index.tsx | 6 +- .../Policies/PolicyTableRow/PolicyRow.tsx | 4 +- .../Auth/Policies/PolicyTableRow/index.tsx | 4 +- .../SessionsAuthSettingsForm.tsx | 6 +- .../interfaces/Auth/Users/UsersV2.tsx | 4 +- .../Payment/AddNewPaymentMethodModal.tsx | 4 +- .../Billing/Payment/AddPaymentMethodForm.tsx | 4 +- .../BranchManagement/Branch.Commands.tsx | 4 +- .../BranchManagement/CreateBranchModal.tsx | 17 +++-- .../BranchManagement/EditBranchModal.tsx | 10 +-- .../BranchManagement/OutOfDateNotice.tsx | 14 ++-- .../interfaces/BranchManagement/ReviewRow.tsx | 8 +-- .../BranchManagement/ReviewWithAI.tsx | 18 ++--- .../components/interfaces/Connect/Connect.tsx | 4 +- .../interfaces/Connect/ConnectTabContent.tsx | 4 +- .../Connect/DatabaseConnectionString.tsx | 4 +- .../Database/Backups/BackupsList.tsx | 4 +- .../Database/Backups/DatabaseBackupsNav.tsx | 5 +- .../RestoreToNewProject/BackupsList.tsx | 8 +-- .../ConfirmRestoreDialog.tsx | 8 +-- .../CreateNewProjectDialog.tsx | 8 +-- .../CreateEnumeratedTypeSidePanel.tsx | 12 ++-- .../DeleteEnumeratedTypeModal.tsx | 7 +- .../EditEnumeratedTypeSidePanel.tsx | 16 ++--- .../EnumeratedTypes/EnumeratedTypes.tsx | 10 +-- .../Extensions/EnableExtensionModal.tsx | 5 +- .../Database/Extensions/ExtensionCard.tsx | 5 +- .../Database/Extensions/Extensions.tsx | 4 +- .../Functions/CreateFunction/index.tsx | 6 +- .../Database/Functions/DeleteFunction.tsx | 4 +- .../Functions/FunctionsList/FunctionList.tsx | 4 +- .../Functions/FunctionsList/FunctionsList.tsx | 4 +- .../Database/Hooks/DeleteHookModal.tsx | 4 +- .../Database/Hooks/EditHookPanel.tsx | 4 +- .../Database/Hooks/FormContents.tsx | 4 +- .../Database/Hooks/HTTPRequestFields.tsx | 4 +- .../Database/Hooks/HooksList/HookList.tsx | 4 +- .../Database/Hooks/HooksList/HooksList.tsx | 4 +- .../Database/Indexes/CreateIndexSidePanel.tsx | 5 +- .../interfaces/Database/Indexes/Indexes.tsx | 4 +- .../Database/Migrations/Migrations.tsx | 4 +- .../Database/Privileges/Privileges.utils.ts | 6 +- .../Publications/PublicationsList.tsx | 6 +- .../Publications/PublicationsTableItem.tsx | 4 +- .../Publications/PublicationsTables.tsx | 4 +- .../Database/Roles/CreateRolePanel.tsx | 4 +- .../Database/Roles/DeleteRoleModal.tsx | 6 +- .../interfaces/Database/Roles/RoleRow.tsx | 4 +- .../interfaces/Database/Roles/RolesList.tsx | 4 +- .../Database/Schemas/SchemaGraph.tsx | 19 ++++-- .../interfaces/Database/Tables/ColumnList.tsx | 4 +- .../interfaces/Database/Tables/TableList.tsx | 4 +- .../Database/Triggers/ChooseFunctionForm.tsx | 4 +- .../Database/Triggers/DeleteTrigger.tsx | 4 +- .../Database/Triggers/TriggerSheet.tsx | 4 +- .../Triggers/TriggersList/TriggerList.tsx | 4 +- .../Triggers/TriggersList/TriggersList.tsx | 4 +- .../DiskManagement/DiskManagementForm.tsx | 13 ++-- .../DiskManagementReviewAndSubmitDialog.tsx | 8 +-- .../fields/ComputeSizeField.tsx | 11 ++-- .../DiskManagement/fields/DiskSizeField.tsx | 8 +-- .../fields/StorageTypeField.tsx | 4 +- .../DiskManagement/ui/DiskSpaceBar.tsx | 4 +- .../ui/SpendCapDisabledSection.tsx | 8 +-- .../interfaces/Docs/Description.tsx | 6 +- .../DeployEdgeFunctionButton.tsx | 4 +- .../EdgeFunctionTesterSheet.tsx | 4 +- .../Functions/EdgeFunctionsListItem.tsx | 4 +- .../Functions/FunctionsEmptyState.tsx | 4 +- .../interfaces/Home/ExampleProject.tsx | 4 +- .../Home/ProjectList/ProjectList.tsx | 4 +- .../interfaces/Home/ProjectUsage.tsx | 4 +- .../interfaces/Home/ProjectUsageSection.tsx | 4 +- .../interfaces/Home/ServiceStatus.tsx | 4 +- .../CronJobs/CreateCronJobSheet.tsx | 4 +- .../CronJobs/CronJobScheduleSection.tsx | 4 +- .../Integrations/CronJobs/CronJobsTab.tsx | 4 +- .../Integrations/CronJobs/DeleteCronJob.tsx | 4 +- .../CronJobs/EdgeFunctionSection.tsx | 4 +- .../Integrations/CronJobs/PreviousRunsTab.tsx | 4 +- .../Integrations/GraphQL/GraphiQLTab.tsx | 4 +- .../Integration/IntegrationOverviewTab.tsx | 4 +- .../Integrations/Landing/IntegrationCard.tsx | 4 +- .../Landing/useInstalledIntegrations.tsx | 4 +- .../Integrations/Queues/CreateQueueSheet.tsx | 6 +- .../Integrations/Queues/OverviewTab.tsx | 4 +- .../Integrations/Queues/QueueTab.tsx | 4 +- .../Integrations/Queues/QueuesRows.tsx | 4 +- .../Integrations/Queues/QueuesSettings.tsx | 4 +- .../Integrations/Queues/QueuesTab.tsx | 4 +- .../Queues/SingleQueue/DeleteQueue.tsx | 4 +- .../SingleQueue/MessageDetailsPanel.tsx | 4 +- .../Queues/SingleQueue/PurgeQueue.tsx | 4 +- .../Queues/SingleQueue/QueueSettings.tsx | 4 +- .../Queues/SingleQueue/SendMessageModal.tsx | 4 +- .../Queues/UpgradeDatabaseAlert.tsx | 4 +- .../Vault/Secrets/AddNewSecretModal.tsx | 8 +-- .../Vault/Secrets/DeleteSecretModal.tsx | 4 +- .../Vault/Secrets/EditSecretModal.tsx | 6 +- .../Integrations/Vault/Secrets/SecretRow.tsx | 5 +- .../Vault/Secrets/SecretsManagement.tsx | 4 +- .../VercelGithub/IntegrationConnection.tsx | 4 +- .../VercelGithub/ProjectLinker.tsx | 4 +- .../Integrations/Webhooks/OverviewTab.tsx | 4 +- .../Wrappers/CreateIcebergWrapperSheet.tsx | 8 +-- .../Wrappers/CreateWrapperSheet.tsx | 8 +-- .../Wrappers/DeleteWrapperModal.tsx | 4 +- .../Wrappers/EditWrapperSheet.tsx | 4 +- .../Integrations/Wrappers/OverviewTab.tsx | 4 +- .../Integrations/Wrappers/WrapperTable.tsx | 4 +- .../Wrappers/WrapperTableEditor.tsx | 4 +- .../Integrations/Wrappers/WrappersTab.tsx | 4 +- .../jwt-secret-keys-table/index.tsx | 4 +- .../interfaces/LogDrains/LogDrains.tsx | 4 +- .../BillingSettings/BillingEmail.tsx | 4 +- .../BillingSettings/BillingSettings.tsx | 4 +- .../PaymentMethods/PaymentMethods.tsx | 4 +- .../BillingSettings/Restriction.tsx | 18 +++-- .../Subscription/PaymentMethodSelection.tsx | 36 +++++----- .../Subscription/PlanUpdateSidePanel.tsx | 7 +- .../Organization/Documents/SOC2.tsx | 4 +- .../Documents/SecurityQuestionnaire.tsx | 4 +- .../DeleteOrganizationButton.tsx | 4 +- .../OrganizationDeletePanel.tsx | 4 +- .../OrganizationDetailsForm.tsx | 4 +- .../IntegrationSettings.tsx | 6 +- .../SidePanelVercelProjectLinker.tsx | 4 +- .../SecuritySettings/SecuritySettings.tsx | 4 +- .../TeamSettings/InviteMemberButton.tsx | 4 +- .../TeamSettings/LeaveTeamButton.tsx | 4 +- .../Organization/TeamSettings/MemberRow.tsx | 4 +- .../UpdateRolesConfirmationModal.tsx | 4 +- .../UpdateRolesPanel/UpdateRolesPanel.tsx | 4 +- .../interfaces/Organization/Usage/Usage.tsx | 4 +- .../PostgresVersionSelector.tsx | 4 +- .../EnableIndexAdvisorButton.tsx | 4 +- .../IndexAdvisorDisabledState.tsx | 6 +- .../QueryPerformance/IndexSuggestionIcon.tsx | 4 +- .../QueryPerformance/QueryIndexes.tsx | 4 +- .../QueryPerformance/QueryPerformance.tsx | 4 +- .../QueryPerformanceFilterBar.tsx | 4 +- .../hooks/useIndexInvalidation.ts | 4 +- .../hooks/useIsIndexAdvisorStatus.ts | 4 +- .../Inspector/ChooseChannelPopover/index.tsx | 4 +- .../interfaces/Realtime/Inspector/Header.tsx | 4 +- .../Realtime/Inspector/MessageSelection.tsx | 4 +- .../Realtime/Inspector/MessagesTable.tsx | 4 +- .../RealtimeFilterPopover/TableSelector.tsx | 6 +- .../Inspector/RealtimeFilterPopover/index.tsx | 4 +- .../Inspector/RealtimeTokensPopover/index.tsx | 4 +- .../interfaces/Realtime/Inspector/index.tsx | 4 +- .../interfaces/Realtime/Policies.tsx | 6 +- .../interfaces/Realtime/RealtimeSettings.tsx | 8 +-- .../interfaces/Reports/CreateReportModal.tsx | 4 +- .../interfaces/Reports/GridResize.tsx | 8 +-- .../interfaces/Reports/MetricOptions.tsx | 4 +- .../interfaces/Reports/ReportChart.tsx | 4 +- .../components/interfaces/Reports/Reports.tsx | 8 +-- .../UserImpersonationSelector.tsx | 4 +- .../interfaces/SQLEditor/MonacoEditor.tsx | 4 +- .../SQLEditor/OngoingQueriesPanel.tsx | 8 +-- .../interfaces/SQLEditor/RenameQueryModal.tsx | 4 +- .../interfaces/SQLEditor/SQLEditor.tsx | 11 ++-- .../SQLEditor/SQLTemplates/SQLQuickstarts.tsx | 8 +-- .../SQLEditor/SQLTemplates/SQLTemplates.tsx | 8 +-- .../SQLEditor/UtilityPanel/UtilityPanel.tsx | 4 +- .../UtilityPanel/UtilityTabResults.tsx | 6 +- .../components/interfaces/SQLEditor/hooks.ts | 4 +- .../interfaces/SQLEditor/useAddDefinitions.ts | 9 +-- .../Settings/API/HardenAPIModal.tsx | 4 +- .../Settings/API/PostgrestConfig.tsx | 4 +- .../interfaces/Settings/API/ServiceList.tsx | 11 +--- .../interfaces/Settings/Addons/Addons.tsx | 22 ++++--- .../Settings/Addons/CustomDomainSidePanel.tsx | 6 +- .../Settings/Addons/IPv4SidePanel.tsx | 4 +- .../Settings/Addons/PITRSidePanel.tsx | 10 ++- .../Settings/Database/BannedIPs.tsx | 4 +- .../ConnectionPooling/ConnectionPooling.tsx | 4 +- .../Database/DatabaseReadOnlyAlert.tsx | 4 +- .../DatabaseSettings/ResetDbPassword.tsx | 8 +-- .../Database/DiskSizeConfiguration.tsx | 9 ++- .../Database/DiskSizeConfigurationModal.tsx | 8 +-- .../NetworkRestrictions.tsx | 4 +- .../Settings/Database/SSLConfiguration.tsx | 4 +- .../ProjectComplianceMode.tsx | 4 +- .../CustomDomainConfig/CustomDomainConfig.tsx | 4 +- .../CustomDomainsConfigureHostname.tsx | 4 +- .../DeleteProjectButton.tsx | 4 +- .../DeleteProjectPanel/DeleteProjectModal.tsx | 8 +-- .../DeleteProjectPanel/DeleteProjectPanel.tsx | 9 ++- .../interfaces/Settings/General/General.tsx | 11 ++-- .../Infrastructure/PauseProjectButton.tsx | 13 ++-- .../ProjectUpgradeAlert.tsx | 4 +- .../Infrastructure/RestartServerButton.tsx | 9 +-- .../TransferProjectButton.tsx | 4 +- .../TransferProjectPanel.tsx | 15 +++-- .../Infrastructure/InfrastructureActivity.tsx | 8 +-- .../DeployNewReplicaPanel.tsx | 8 +-- .../InstanceConfiguration.tsx | 5 +- .../Infrastructure/InfrastructureInfo.tsx | 5 +- .../GitHubIntegrationConnectionForm.tsx | 26 ++++---- .../GithubIntegration/GitHubStatus.tsx | 8 +-- .../GithubIntegration/GithubSection.tsx | 9 ++- .../Integrations/IntegrationsSettings.tsx | 6 +- .../VercelIntegrationConnectionForm.tsx | 4 +- .../VercelIntegration/VercelSection.tsx | 8 +-- .../Settings/Logs/LogsPreviewer.tsx | 4 +- .../Settings/Logs/UpgradePrompt.tsx | 4 +- apps/studio/components/interfaces/Sidebar.tsx | 9 ++- .../AnalyticBucketDetails/CopyEnvButton.tsx | 4 +- .../DecryptedReadOnlyInput.tsx | 4 +- .../AnalyticBucketDetails/NamespaceRow.tsx | 4 +- .../SimpleConfigurationDetails.tsx | 4 +- .../Storage/AnalyticBucketDetails/index.tsx | 4 +- .../useIcebergWrapper.tsx | 4 +- .../interfaces/Storage/CreateBucketModal.tsx | 6 +- .../interfaces/Storage/DeleteBucketModal.tsx | 4 +- .../Storage/ImportForeignSchemaDialog.tsx | 4 +- .../StoragePolicies/StoragePolicies.tsx | 6 +- .../Storage/StorageSettings/S3Connection.tsx | 8 +-- .../StorageSettings/StorageSettings.tsx | 4 +- .../DeleteConfirmationDialogs.tsx | 4 +- .../TableGridEditor/GridHeaderActions.tsx | 8 +-- .../ColumnEditor/ColumnEditor.tsx | 4 +- .../ColumnEditor/ColumnForeignKey.tsx | 4 +- .../ForeignKeySelector/ForeignKeySelector.tsx | 4 +- .../ForeignRowSelector/ForeignRowSelector.tsx | 4 +- .../RowEditor/JsonEditor/JsonEditor.tsx | 4 +- .../SidePanelEditor/RowEditor/RowEditor.tsx | 4 +- .../SidePanelEditor/RowEditor/TextEditor.tsx | 4 +- .../SidePanelEditor/SchemaEditor.tsx | 4 +- .../SidePanelEditor/SidePanelEditor.tsx | 4 +- .../SpreadsheetImport/SpreadsheetImport.tsx | 4 +- .../SidePanelEditor/TableEditor/Column.tsx | 4 +- .../TableEditor/ColumnManagement.tsx | 4 +- .../ForeignKeysManagement.tsx | 4 +- .../TableEditor/TableEditor.tsx | 8 +-- .../TableGridEditor/TableDefinition.tsx | 4 +- .../ViewEntityAutofixSecurityModal.tsx | 4 +- .../layouts/AdvisorsLayout/AdvisorsLayout.tsx | 4 +- .../layouts/AppLayout/BranchDropdown.tsx | 4 +- .../BranchingPlanNotice.tsx | 4 +- .../AppLayout/OrganizationDropdown.tsx | 4 +- .../layouts/AppLayout/ProjectDropdown.tsx | 16 ++--- .../layouts/DatabaseLayout/DatabaseLayout.tsx | 6 +- .../layouts/DocsLayout/DocsLayout.tsx | 4 +- .../EdgeFunctionDetailsLayout.tsx | 4 +- .../layouts/Integrations/header.tsx | 4 +- .../layouts/Integrations/layout.tsx | 4 +- .../components/layouts/Integrations/tabs.tsx | 4 +- .../components/layouts/OrganizationLayout.tsx | 4 +- .../layouts/ProjectLayout/BuildingState.tsx | 4 +- .../FeedbackDropdown/FeedbackWidget.tsx | 4 +- .../LayoutHeader/HelpPopover.tsx | 8 +-- .../ProjectLayout/LayoutHeader/HomeIcon.tsx | 4 +- .../LayoutHeader/LayoutHeader.tsx | 8 +-- .../LayoutHeader/MergeRequestButton.tsx | 19 +++--- .../ProjectLayout/PauseFailedState.tsx | 4 +- .../PausedState/PauseDisabledState.tsx | 4 +- .../PausedState/ProjectPausedState.tsx | 8 +-- .../layouts/ProjectLayout/ProjectContext.tsx | 59 +++++------------ .../layouts/ProjectLayout/ProjectLayout.tsx | 6 +- .../ProjectLayout/RestoreFailedState.tsx | 4 +- .../layouts/ProjectLayout/RestoringState.tsx | 4 +- .../UpgradingState/UpgradingState.tsx | 4 +- .../ProjectSettingsLayout/SettingsLayout.tsx | 8 +-- .../layouts/RealtimeLayout/RealtimeLayout.tsx | 4 +- .../SQLEditorLayout/SqlEditor.Commands.tsx | 8 +-- .../TableEditorLayout/EntityListItem.tsx | 4 +- .../TableEditor.Commands.tsx | 4 +- .../TableEditorLayout/TableEditorMenu.tsx | 4 +- .../studio/components/layouts/Tabs/NewTab.tsx | 8 +-- .../ui/AIAssistantPanel/AIAssistant.tsx | 8 +-- .../AIAssistantPanel/DisplayBlockRenderer.tsx | 4 +- .../ui/AIAssistantPanel/MessageMarkdown.tsx | 8 +-- .../components/ui/CodeEditor/CodeEditor.tsx | 4 +- .../EdgeFunctionBlock/EdgeFunctionBlock.tsx | 4 +- .../components/ui/EditorPanel/EditorPanel.tsx | 4 +- .../studio/components/ui/FunctionSelector.tsx | 10 +-- .../components/ui/GrafanaPromoBanner.tsx | 11 ++-- apps/studio/components/ui/GroupsTelemetry.tsx | 4 +- .../ProjectSettings/ToggleLegacyApiKeys.tsx | 4 +- .../ui/QueryBlock/EditQueryButton.tsx | 4 +- apps/studio/components/ui/SchemaComboBox.tsx | 5 +- apps/studio/components/ui/SchemaSelector.tsx | 4 +- apps/studio/components/ui/SqlEditor.tsx | 2 - apps/studio/components/ui/UpgradeToPro.tsx | 8 +-- apps/studio/data/auth/users-infinite-query.ts | 4 +- .../project-upgrade-eligibility-query.ts | 4 +- .../database-extensions-query.ts | 10 +-- .../database-policies-query.ts | 6 +- apps/studio/data/lint/lint-query.ts | 4 +- apps/studio/data/lint/lint-rules-query.ts | 4 +- .../prefetchers/project.$ref.editor.$id.tsx | 4 +- .../data/prefetchers/project.$ref.editor.tsx | 4 +- apps/studio/data/reports/api-report-query.ts | 2 - apps/studio/data/sql/execute-sql-query.ts | 6 +- apps/studio/data/storage/buckets-query.ts | 4 +- .../iceberg-wrapper-create-mutation.ts | 4 +- apps/studio/hooks/analytics/useDbQuery.tsx | 4 +- apps/studio/hooks/forms/useAIOptInForm.ts | 4 +- apps/studio/hooks/misc/useCurrentOrgPlan.ts | 4 +- apps/studio/hooks/misc/useOrgOptedIntoAi.ts | 8 +-- .../hooks/misc/useOrganizationRestrictions.ts | 4 +- .../hooks/misc/useSelectedOrganization.ts | 33 +--------- apps/studio/hooks/misc/useSelectedProject.ts | 65 ++----------------- apps/studio/hooks/misc/useUpgradePrompt.tsx | 4 +- apps/studio/hooks/ui/useFlag.ts | 4 +- apps/studio/hooks/useProtectedSchemas.ts | 4 +- .../[slug]/deploy-button/new-project.tsx | 4 +- apps/studio/pages/new/[slug].tsx | 4 +- apps/studio/pages/org/[slug]/apps.tsx | 4 +- apps/studio/pages/org/[slug]/audit.tsx | 5 +- apps/studio/pages/org/[slug]/general.tsx | 5 +- apps/studio/pages/org/[slug]/index.tsx | 4 +- apps/studio/pages/org/[slug]/security.tsx | 5 +- apps/studio/pages/org/[slug]/team.tsx | 4 +- apps/studio/pages/org/[slug]/usage.tsx | 5 +- .../project/[ref]/advisors/performance.tsx | 4 +- .../pages/project/[ref]/advisors/security.tsx | 4 +- .../pages/project/[ref]/auth/policies.tsx | 4 +- .../pages/project/[ref]/branches/index.tsx | 8 +-- .../project/[ref]/branches/merge-requests.tsx | 12 ++-- .../project/[ref]/database/backups/pitr.tsx | 9 ++- .../backups/restore-to-new-project.tsx | 13 ++-- .../[ref]/database/column-privileges.tsx | 4 +- .../project/[ref]/database/publications.tsx | 6 +- .../project/[ref]/database/tables/[id].tsx | 7 +- .../pages/project/[ref]/editor/[id].tsx | 4 +- .../[ref]/functions/[functionSlug]/code.tsx | 8 +-- .../pages/project/[ref]/functions/index.tsx | 8 --- .../pages/project/[ref]/functions/new.tsx | 8 +-- apps/studio/pages/project/[ref]/index.tsx | 14 ++-- .../pages/project/[ref]/logs/auth-logs.tsx | 4 +- .../project/[ref]/logs/explorer/index.tsx | 7 +- .../studio/pages/project/[ref]/logs/index.tsx | 4 +- apps/studio/pages/project/[ref]/merge.tsx | 10 +-- .../pages/project/[ref]/reports/database.tsx | 8 +-- .../pages/project/[ref]/reports/storage.tsx | 43 ++++++------ .../project/[ref]/settings/billing/usage.tsx | 8 +-- .../pages/project/[ref]/settings/general.tsx | 8 +-- .../[ref]/storage/buckets/[bucketId].tsx | 10 +-- .../project/[ref]/storage/buckets/index.tsx | 8 +-- apps/studio/state/ai-assistant-state.tsx | 4 +- .../studio/state/role-impersonation-state.tsx | 4 +- apps/studio/state/storage-explorer.tsx | 4 +- 371 files changed, 1066 insertions(+), 1221 deletions(-) diff --git a/apps/studio/components/grid/SupabaseGrid.tsx b/apps/studio/components/grid/SupabaseGrid.tsx index d6dfe395600..3129c172d0e 100644 --- a/apps/studio/components/grid/SupabaseGrid.tsx +++ b/apps/studio/components/grid/SupabaseGrid.tsx @@ -5,7 +5,6 @@ import { HTML5Backend } from 'react-dnd-html5-backend' import { createPortal } from 'react-dom' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useTableRowsQuery } from 'data/table-rows/table-rows-query' import { RoleImpersonationState } from 'lib/role-impersonation' import { EMPTY_ARR } from 'lib/void' @@ -20,6 +19,7 @@ import Header, { HeaderProps } from './components/header/Header' import { RowContextMenu } from './components/menu' import { GridProps } from './types' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useTableFilter } from './hooks/useTableFilter' import { useTableSort } from './hooks/useTableSort' @@ -35,8 +35,7 @@ export const SupabaseGrid = ({ const { id: _id } = useParams() const tableId = _id ? Number(_id) : undefined - const { project } = useProjectContext() - + const { data: project } = useSelectedProjectQuery() const tableEditorSnap = useTableEditorStateSnapshot() const snap = useTableEditorTableStateSnapshot() diff --git a/apps/studio/components/grid/components/editor/JsonEditor.tsx b/apps/studio/components/grid/components/editor/JsonEditor.tsx index af7a7a2a7c3..004e9b45f0b 100644 --- a/apps/studio/components/grid/components/editor/JsonEditor.tsx +++ b/apps/studio/components/grid/components/editor/JsonEditor.tsx @@ -4,10 +4,11 @@ import type { RenderEditCellProps } from 'react-data-grid' import { toast } from 'sonner' import { useParams } from 'common' +import { isValueTruncated } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' import { useGetCellValueMutation } from 'data/table-rows/get-cell-value-mutation' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { prettifyJSON, removeJSONTrailingComma, tryParseJson } from 'lib/helpers' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { Popover, Tooltip, TooltipContent, TooltipTrigger } from 'ui' @@ -15,7 +16,6 @@ import { BlockKeys } from '../common/BlockKeys' import { MonacoEditor } from '../common/MonacoEditor' import { NullValue } from '../common/NullValue' import { TruncatedWarningOverlay } from './TruncatedWarningOverlay' -import { isValueTruncated } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' const verifyJSON = (value: string) => { try { @@ -55,7 +55,7 @@ export const JsonEditor = ({ const snap = useTableEditorTableStateSnapshot() const { id: _id } = useParams() const id = _id ? Number(_id) : undefined - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable } = useTableEditorQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/grid/components/editor/TextEditor.tsx b/apps/studio/components/grid/components/editor/TextEditor.tsx index 00f17acbb05..15e111e13fd 100644 --- a/apps/studio/components/grid/components/editor/TextEditor.tsx +++ b/apps/studio/components/grid/components/editor/TextEditor.tsx @@ -4,10 +4,11 @@ import type { RenderEditCellProps } from 'react-data-grid' import { toast } from 'sonner' import { useParams } from 'common' +import { isValueTruncated } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' import { useGetCellValueMutation } from 'data/table-rows/get-cell-value-mutation' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { Button, Popover, Tooltip, TooltipContent, TooltipTrigger, cn } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' @@ -16,7 +17,6 @@ import { EmptyValue } from '../common/EmptyValue' import { MonacoEditor } from '../common/MonacoEditor' import { NullValue } from '../common/NullValue' import { TruncatedWarningOverlay } from './TruncatedWarningOverlay' -import { isValueTruncated } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' export const TextEditor = ({ row, @@ -33,7 +33,7 @@ export const TextEditor = ({ const snap = useTableEditorTableStateSnapshot() const { id: _id } = useParams() const id = _id ? Number(_id) : undefined - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable } = useTableEditorQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/grid/components/footer/Footer.tsx b/apps/studio/components/grid/components/footer/Footer.tsx index e7c7d3bd90e..f4680d0acac 100644 --- a/apps/studio/components/grid/components/footer/Footer.tsx +++ b/apps/studio/components/grid/components/footer/Footer.tsx @@ -1,9 +1,9 @@ import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { GridFooter } from 'components/ui/GridFooter' import TwoOptionToggle from 'components/ui/TwoOptionToggle' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike, isViewLike } from 'data/table-editor/table-editor-types' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useUrlState } from 'hooks/ui/useUrlState' import RefreshButton from '../header/RefreshButton' import { Pagination } from './pagination' @@ -13,9 +13,9 @@ export interface FooterProps { } const Footer = ({ isRefetching }: FooterProps) => { - const { project } = useProjectContext() const { id: _id } = useParams() const id = _id ? Number(_id) : undefined + const { data: project } = useSelectedProjectQuery() const { data: entity } = useTableEditorQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/grid/components/footer/pagination/Pagination.tsx b/apps/studio/components/grid/components/footer/pagination/Pagination.tsx index af4f18ff65e..ed6472e9ba0 100644 --- a/apps/studio/components/grid/components/footer/pagination/Pagination.tsx +++ b/apps/studio/components/grid/components/footer/pagination/Pagination.tsx @@ -3,10 +3,10 @@ import { useEffect, useState } from 'react' import { useParams } from 'common' import { useTableFilter } from 'components/grid/hooks/useTableFilter' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTable } from 'data/table-editor/table-editor-types' import { THRESHOLD_COUNT, useTableRowsCountQuery } from 'data/table-rows/table-rows-count-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { RoleImpersonationState } from 'lib/role-impersonation' import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state' import { useTableEditorStateSnapshot } from 'state/table-editor' @@ -27,7 +27,7 @@ const Pagination = () => { const { id: _id } = useParams() const id = _id ? Number(_id) : undefined - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const tableEditorSnap = useTableEditorStateSnapshot() const snap = useTableEditorTableStateSnapshot() diff --git a/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx b/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx index b7fa6d9138b..ad4a8d06546 100644 --- a/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx +++ b/apps/studio/components/grid/components/formatter/ForeignKeyFormatter.tsx @@ -3,11 +3,11 @@ import type { PropsWithChildren } from 'react' import type { RenderCellProps } from 'react-data-grid' import { convertByteaToHex } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' import { useTablesQuery } from 'data/tables/tables-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Popover_Shadcn_, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_ } from 'ui' import type { SupaRow } from '../../types' import { NullValue } from '../common/NullValue' @@ -18,9 +18,8 @@ interface Props extends PropsWithChildren> { } export const ForeignKeyFormatter = (props: Props) => { - const { project } = useProjectContext() - const { tableId, row, column } = props + const { data: project } = useSelectedProjectQuery() const { data } = useTableEditorQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/grid/components/formatter/ReferenceRecordPeek.tsx b/apps/studio/components/grid/components/formatter/ReferenceRecordPeek.tsx index b6ed3fbb781..20b11ea6139 100644 --- a/apps/studio/components/grid/components/formatter/ReferenceRecordPeek.tsx +++ b/apps/studio/components/grid/components/formatter/ReferenceRecordPeek.tsx @@ -11,7 +11,7 @@ import { import { convertByteaToHex } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' import { EditorTablePageLink } from 'data/prefetchers/project.$ref.editor.$id' import { useTableRowsQuery } from 'data/table-rows/table-rows-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' @@ -23,7 +23,7 @@ interface ReferenceRecordPeekProps { export const ReferenceRecordPeek = ({ table, column, value }: ReferenceRecordPeekProps) => { const { ref } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data, error, isSuccess, isError, isLoading } = useTableRowsQuery( { diff --git a/apps/studio/components/grid/components/grid/Grid.tsx b/apps/studio/components/grid/components/grid/Grid.tsx index fe907cabf8a..1fb1d700460 100644 --- a/apps/studio/components/grid/components/grid/Grid.tsx +++ b/apps/studio/components/grid/components/grid/Grid.tsx @@ -3,12 +3,12 @@ import DataGrid, { CalculatedColumn, DataGridHandle } from 'react-data-grid' import { handleCopyCell } from 'components/grid/SupabaseGrid.utils' import { formatForeignKeys } from 'components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useTableEditorStateSnapshot } from 'state/table-editor' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { Button, cn } from 'ui' @@ -54,6 +54,9 @@ export const Grid = memo( const tableEditorSnap = useTableEditorStateSnapshot() const snap = useTableEditorTableStateSnapshot() + const { data: org } = useSelectedOrganizationQuery() + const { data: project } = useSelectedProjectQuery() + const onRowsChange = useOnRowsChange(rows) function onSelectedRowsChange(selectedRows: Set) { @@ -71,8 +74,6 @@ export const Grid = memo( const tableEntityType = snap.originalTable?.entity_type const { mutate: sendEvent } = useSendEventMutation() - const org = useSelectedOrganization() - const { project } = useProjectContext() const { data } = useForeignKeyConstraintsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/grid/components/grid/Grid.utils.tsx b/apps/studio/components/grid/components/grid/Grid.utils.tsx index eeed6d155fa..e348b4defa2 100644 --- a/apps/studio/components/grid/components/grid/Grid.utils.tsx +++ b/apps/studio/components/grid/components/grid/Grid.utils.tsx @@ -5,20 +5,20 @@ import { toast } from 'sonner' import { SupaRow } from 'components/grid/types' import { convertByteaToHex } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import { isTableLike } from 'data/table-editor/table-editor-types' import { tableRowKeys } from 'data/table-rows/keys' import { useTableRowUpdateMutation } from 'data/table-rows/table-row-update-mutation' import type { TableRowsData } from 'data/table-rows/table-rows-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useGetImpersonatedRoleState } from 'state/role-impersonation-state' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { Dictionary } from 'types' export function useOnRowsChange(rows: SupaRow[]) { - const { project } = useProjectContext() - const snap = useTableEditorTableStateSnapshot() const queryClient = useQueryClient() + const { data: project } = useSelectedProjectQuery() + const snap = useTableEditorTableStateSnapshot() const getImpersonatedRoleState = useGetImpersonatedRoleState() const { mutate: mutateUpdateTableRow } = useTableRowUpdateMutation({ diff --git a/apps/studio/components/grid/components/header/Header.tsx b/apps/studio/components/grid/components/header/Header.tsx index bb401db90e8..0985c79f2e8 100644 --- a/apps/studio/components/grid/components/header/Header.tsx +++ b/apps/studio/components/grid/components/header/Header.tsx @@ -11,13 +11,13 @@ import { useTableFilter } from 'components/grid/hooks/useTableFilter' import { useTableSort } from 'components/grid/hooks/useTableSort' import GridHeaderActions from 'components/interfaces/TableGridEditor/GridHeaderActions' import { formatTableRowsToSQL } from 'components/interfaces/TableGridEditor/TableEntity.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useTableRowsCountQuery } from 'data/table-rows/table-rows-count-query' import { fetchAllTableRows, useTableRowsQuery } from 'data/table-rows/table-rows-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { RoleImpersonationState } from 'lib/role-impersonation' import { useRoleImpersonationStateSnapshot, @@ -222,7 +222,7 @@ const DefaultHeader = () => { } const RowHeader = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const tableEditorSnap = useTableEditorStateSnapshot() const snap = useTableEditorTableStateSnapshot() diff --git a/apps/studio/components/grid/hooks/useSaveTableEditorState.ts b/apps/studio/components/grid/hooks/useSaveTableEditorState.ts index 9157100956c..cab483a243b 100644 --- a/apps/studio/components/grid/hooks/useSaveTableEditorState.ts +++ b/apps/studio/components/grid/hooks/useSaveTableEditorState.ts @@ -1,14 +1,14 @@ import { useCallback } from 'react' import { saveTableEditorStateToLocalStorage } from 'components/grid/SupabaseGrid.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' /** * Hook for saving state and triggering side effects. */ export function useSaveTableEditorState() { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const snap = useTableEditorTableStateSnapshot() const saveDataAndTriggerSideEffects = useCallback( diff --git a/apps/studio/components/interfaces/Advisors/AdvisorRuleItem.tsx b/apps/studio/components/interfaces/Advisors/AdvisorRuleItem.tsx index 47cb816ab38..afd8c3016d9 100644 --- a/apps/studio/components/interfaces/Advisors/AdvisorRuleItem.tsx +++ b/apps/studio/components/interfaces/Advisors/AdvisorRuleItem.tsx @@ -9,7 +9,7 @@ import { DocsButton } from 'components/ui/DocsButton' import { useLintRuleDeleteMutation } from 'data/lint/delete-lint-rule-mutation' import { useProjectLintRulesQuery } from 'data/lint/lint-rules-query' import { useOrganizationMembersQuery } from 'data/organizations/organization-members-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Badge, Button, @@ -40,7 +40,7 @@ const SIMPLIFIED_INTERFACE = true export const AdvisorRuleItem = ({ lint }: AdvisorRuleItemProps) => { const { ref: projectRef } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const [open, setOpen] = useState(false) const [expandedLint, setExpandedLint] = useState() diff --git a/apps/studio/components/interfaces/Advisors/CreateRuleSheet.tsx b/apps/studio/components/interfaces/Advisors/CreateRuleSheet.tsx index a9d5f53280f..e825a9ff1e7 100644 --- a/apps/studio/components/interfaces/Advisors/CreateRuleSheet.tsx +++ b/apps/studio/components/interfaces/Advisors/CreateRuleSheet.tsx @@ -8,7 +8,7 @@ import * as z from 'zod' import { useParams } from 'common' import { useLintRuleCreateMutation } from 'data/lint/create-lint-rule-mutation' import { useOrganizationMembersQuery } from 'data/organizations/organization-members-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useRouter } from 'next/router' import { Button, @@ -68,10 +68,9 @@ const defaultValues = { export const CreateRuleSheet = ({ lint, open, onOpenChange }: CreateRuleSheetProps) => { const router = useRouter() const { ref: projectRef } = useParams() - // const [_, setExpandedLint] = useQueryState('lint') const routeCategory = router.pathname.split('/').pop() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const { data: members = [] } = useOrganizationMembersQuery({ slug: organization?.slug }) const { mutate: createRule, isLoading: isCreating } = useLintRuleCreateMutation({ diff --git a/apps/studio/components/interfaces/App/CommandMenu/ApiUrl.tsx b/apps/studio/components/interfaces/App/CommandMenu/ApiUrl.tsx index dfad51d0667..f84d8c6bb41 100644 --- a/apps/studio/components/interfaces/App/CommandMenu/ApiUrl.tsx +++ b/apps/studio/components/interfaces/App/CommandMenu/ApiUrl.tsx @@ -1,7 +1,7 @@ import { Link } from 'lucide-react' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, copyToClipboard } from 'ui' import { useRegisterCommands, useSetCommandMenuOpen } from 'ui-patterns/CommandMenu' import { COMMAND_MENU_SECTIONS } from './CommandMenu.utils' @@ -10,7 +10,7 @@ import { orderCommandSectionsByPriority } from './ordering' export function useApiUrlCommand() { const setIsOpen = useSetCommandMenuOpen() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: settings } = useProjectSettingsV2Query( { projectRef: project?.ref }, { enabled: !!project } diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx index 2578ca33fa2..3cf9aaec856 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx +++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx @@ -11,7 +11,7 @@ import { } from 'react' import { FeatureFlagContext, LOCAL_STORAGE_KEYS } from 'common' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useFlag, useIsRealtimeSettingsFFEnabled } from 'hooks/ui/useFlag' import { EMPTY_OBJ } from 'lib/void' import { FEATURE_PREVIEWS } from './FeaturePreview.constants' @@ -92,7 +92,7 @@ export const useIsInlineEditorEnabled = () => { } export const useUnifiedLogsPreview = () => { - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const { flags, onUpdateFlag } = useFeaturePreviewContext() const isTeamsOrEnterprise = ['team', 'enterprise'].includes(organization?.plan.id ?? '') diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx index ba83954fe4b..9234e4fe8be 100644 --- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx +++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx @@ -4,7 +4,7 @@ import { ReactNode } from 'react' import { LOCAL_STORAGE_KEYS, useParams } from 'common' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { Badge, Button, Modal, ScrollArea, cn } from 'ui' import { AdvisorRulesPreview } from './AdvisorRulesPreview' @@ -38,7 +38,7 @@ const FeaturePreviewModal = () => { closeFeaturePreviewModal, isFeaturePreviewReleasedToPublic, } = useFeaturePreviewModal() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const featurePreviewContext = useFeaturePreviewContext() const { mutate: sendEvent } = useSendEventMutation() diff --git a/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx b/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx index 22b473f6d9f..4ddb8e1039d 100644 --- a/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx +++ b/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx @@ -7,7 +7,7 @@ import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useProjectsQuery } from 'data/projects/projects-query' import useLatest from 'hooks/misc/useLatest' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' @@ -20,7 +20,7 @@ const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => { const snap = useAppStateSnapshot() const isUserMFAEnabled = useIsMFAEnabled() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const [dashboardHistory, _, { isSuccess: isSuccessStorage }] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.DASHBOARD_HISTORY(ref ?? ''), diff --git a/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm.tsx index b0bc8294855..65357542272 100644 --- a/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/AdvancedAuthSettingsForm.tsx @@ -7,12 +7,13 @@ import * as z from 'zod' import { useParams } from 'common' import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold' +import { StringNumberOrNull } from 'components/ui/Forms/Form.constants' import NoPermission from 'components/ui/NoPermission' import UpgradeToPro from 'components/ui/UpgradeToPro' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { AlertDescription_Shadcn_, @@ -30,7 +31,6 @@ import { WarningIcon, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' -import { StringNumberOrNull } from 'components/ui/Forms/Form.constants' const FormSchema = z.object({ API_MAX_REQUEST_DURATION: z.coerce @@ -42,7 +42,7 @@ const FormSchema = z.object({ export const AdvancedAuthSettingsForm = () => { const { ref: projectRef } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') diff --git a/apps/studio/components/interfaces/Auth/Hooks/AddHookDropdown.tsx b/apps/studio/components/interfaces/Auth/Hooks/AddHookDropdown.tsx index 7e1ab1988cf..87ca544e5c4 100644 --- a/apps/studio/components/interfaces/Auth/Hooks/AddHookDropdown.tsx +++ b/apps/studio/components/interfaces/Auth/Hooks/AddHookDropdown.tsx @@ -5,7 +5,7 @@ import { useParams } from 'common' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, DropdownMenu, @@ -30,7 +30,7 @@ export const AddHookDropdown = ({ onSelectHook, }: AddHookDropdownProps) => { const { ref: projectRef } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const { data: authConfig } = useAuthConfigQuery({ projectRef }) const canUpdateAuthHook = useCheckPermissions(PermissionAction.AUTH_EXECUTE, '*') diff --git a/apps/studio/components/interfaces/Auth/Hooks/CreateHookSheet.tsx b/apps/studio/components/interfaces/Auth/Hooks/CreateHookSheet.tsx index 9534e48e2de..2e97de91220 100644 --- a/apps/studio/components/interfaces/Auth/Hooks/CreateHookSheet.tsx +++ b/apps/studio/components/interfaces/Auth/Hooks/CreateHookSheet.tsx @@ -9,13 +9,14 @@ import * as z from 'zod' import { useParams } from 'common' import { convertArgumentTypes } from 'components/interfaces/Database/Functions/Functions.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import CodeEditor from 'components/ui/CodeEditor/CodeEditor' +import { DocsButton } from 'components/ui/DocsButton' import FunctionSelector from 'components/ui/FunctionSelector' import SchemaSelector from 'components/ui/SchemaSelector' import { AuthConfigResponse } from 'data/auth/auth-config-query' import { useAuthHooksUpdateMutation } from 'data/auth/auth-hooks-update-mutation' import { executeSql } from 'data/sql/execute-sql-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, FormControl_Shadcn_, @@ -38,7 +39,6 @@ import { import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { HOOKS_DEFINITIONS, HOOK_DEFINITION_TITLE, Hook } from './hooks.constants' import { extractMethod, getRevokePermissionStatements, isValidHook } from './hooks.utils' -import { DocsButton } from 'components/ui/DocsButton' interface CreateHookSheetProps { visible: boolean @@ -115,7 +115,7 @@ export const CreateHookSheet = ({ onDelete, }: CreateHookSheetProps) => { const { ref: projectRef } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const definition = useMemo( () => HOOKS_DEFINITIONS.find((d) => d.title === title) || HOOKS_DEFINITIONS[0], diff --git a/apps/studio/components/interfaces/Auth/Hooks/HooksListing.tsx b/apps/studio/components/interfaces/Auth/Hooks/HooksListing.tsx index 7be01b06262..ac4fc3e093e 100644 --- a/apps/studio/components/interfaces/Auth/Hooks/HooksListing.tsx +++ b/apps/studio/components/interfaces/Auth/Hooks/HooksListing.tsx @@ -2,13 +2,13 @@ import { useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' import CodeEditor from 'components/ui/CodeEditor/CodeEditor' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthHooksUpdateMutation } from 'data/auth/auth-hooks-update-mutation' import { executeSql } from 'data/sql/execute-sql-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { cn } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { AddHookDropdown } from './AddHookDropdown' @@ -19,7 +19,7 @@ import { extractMethod, getRevokePermissionStatements, isValidHook } from './hoo export const HooksListing = () => { const { ref: projectRef } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: authConfig, error: authConfigError, isError } = useAuthConfigQuery({ projectRef }) const [selectedHook, setSelectedHook] = useState(null) diff --git a/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx index c3a1dafb47f..4a00780db53 100644 --- a/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx @@ -12,7 +12,7 @@ import UpgradeToPro from 'components/ui/UpgradeToPro' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { AlertDescription_Shadcn_, @@ -26,13 +26,13 @@ import { FormField_Shadcn_, Form_Shadcn_, Input_Shadcn_, - Select_Shadcn_, + PrePostTab, SelectContent_Shadcn_, SelectItem_Shadcn_, SelectTrigger_Shadcn_, SelectValue_Shadcn_, + Select_Shadcn_, WarningIcon, - PrePostTab, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' @@ -90,7 +90,7 @@ const MfaAuthSettingsForm = () => { const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const isProPlanAndUp = organization?.plan?.id !== 'free' const promptProPlanUpgrade = IS_PLATFORM && !isProPlanAndUp diff --git a/apps/studio/components/interfaces/Auth/Policies/Policies.tsx b/apps/studio/components/interfaces/Auth/Policies/Policies.tsx index 2cb2d1d1516..047b511de69 100644 --- a/apps/studio/components/interfaces/Auth/Policies/Policies.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/Policies.tsx @@ -11,12 +11,12 @@ import { PolicyTableRowProps, } from 'components/interfaces/Auth/Policies/PolicyTableRow' 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 InformationBox from 'components/ui/InformationBox' import { useDatabasePolicyDeleteMutation } from 'data/database-policies/database-policy-delete-mutation' import { useTableUpdateMutation } from 'data/tables/table-update-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' interface PoliciesProps { @@ -38,7 +38,7 @@ const Policies = ({ }: PoliciesProps) => { const router = useRouter() const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [selectedTableToToggleRLS, setSelectedTableToToggleRLS] = useState<{ id: number diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/PolicyRoles.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/PolicyRoles.tsx index 3c9ad8509ff..6e99a16b60a 100644 --- a/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/PolicyRoles.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/PolicyEditor/PolicyRoles.tsx @@ -1,11 +1,11 @@ import { SYSTEM_ROLES } from 'components/interfaces/Database/Roles/Roles.constants' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' -import MultiSelect from 'ui-patterns/MultiSelectDeprecated' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useDatabaseRolesQuery } from 'data/database-roles/database-roles-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { sortBy } from 'lodash' +import MultiSelect from 'ui-patterns/MultiSelectDeprecated' interface PolicyRolesProps { selectedRoles: string[] @@ -14,7 +14,7 @@ interface PolicyRolesProps { type SystemRole = (typeof SYSTEM_ROLES)[number] const PolicyRoles = ({ selectedRoles, onUpdateSelectedRoles }: PolicyRolesProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data, error, isLoading, isError, isSuccess } = useDatabaseRolesQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx index b166b82833f..259f5e7fd01 100644 --- a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx @@ -3,10 +3,10 @@ import { useEffect, useState } from 'react' import { UseFormReturn } from 'react-hook-form' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseRolesQuery } from 'data/database-roles/database-roles-query' import { useTablesQuery } from 'data/tables/tables-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, CommandEmpty_Shadcn_, @@ -60,7 +60,7 @@ export const PolicyDetailsV2 = ({ onUpdateCommand, authContext, }: PolicyDetailsV2Props) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [open, setOpen] = useState(false) const canUpdatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx index 1684ca6286d..da7f29f264c 100644 --- a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx @@ -16,7 +16,7 @@ import { useDatabasePolicyUpdateMutation } from 'data/database-policies/database import { databasePoliciesKeys } from 'data/database-policies/keys' import { QueryResponseError, useExecuteSqlMutation } from 'data/sql/execute-sql-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Checkbox_Shadcn_, @@ -33,9 +33,9 @@ import { cn, } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' -import { checkIfPolicyHasChanged, generateCreatePolicyQuery } from './PolicyEditorPanel.utils' import { LockedCreateQuerySection, LockedRenameQuerySection } from './LockedQuerySection' import { PolicyDetailsV2 } from './PolicyDetailsV2' +import { checkIfPolicyHasChanged, generateCreatePolicyQuery } from './PolicyEditorPanel.utils' import { PolicyEditorPanelHeader } from './PolicyEditorPanelHeader' import { PolicyTemplates } from './PolicyTemplates' import { QueryError } from './QueryError' @@ -65,7 +65,7 @@ export const PolicyEditorPanel = memo(function ({ }: PolicyEditorPanelProps) { const { ref } = useParams() const queryClient = useQueryClient() - const selectedProject = useSelectedProject() + const { data: selectedProject } = useSelectedProjectQuery() const canUpdatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx index e59ef503ed1..2bb0216f800 100644 --- a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx @@ -3,11 +3,11 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { noop } from 'lodash' import { Edit, MoreVertical, Trash } from 'lucide-react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DropdownMenuItemTooltip } from 'components/ui/DropdownMenuItemTooltip' import Panel from 'components/ui/Panel' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { Badge, @@ -40,7 +40,7 @@ const PolicyRow = ({ const aiSnap = useAiAssistantStateSnapshot() const canUpdatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'policies') - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: authConfig } = useAuthConfigQuery({ projectRef: project?.ref }) // override islocked for Realtime messages table diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/index.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/index.tsx index 4b115b87f96..8732566cc23 100644 --- a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/index.tsx +++ b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/index.tsx @@ -2,12 +2,12 @@ import type { PostgresPolicy } from '@supabase/postgres-meta' import { noop } from 'lodash' import { Info } from 'lucide-react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import Panel from 'components/ui/Panel' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' import { useTableRolesAccessQuery } from 'data/tables/table-roles-access-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' import PolicyRow from './PolicyRow' @@ -40,7 +40,7 @@ export const PolicyTableRow = ({ onSelectEditPolicy = noop, onSelectDeletePolicy = noop, }: PolicyTableRowProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() // [Joshen] Changes here are so that warnings are more accurate and granular instead of purely relying if RLS is disabled or enabled // The following scenarios are technically okay if the table has RLS disabled, in which it won't be publicly readable / writable diff --git a/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx index 55b4b7a9dac..5f9f9d892d6 100644 --- a/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx +++ b/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx @@ -12,7 +12,7 @@ import UpgradeToPro from 'components/ui/UpgradeToPro' import { useAuthConfigQuery } from 'data/auth/auth-config-query' import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { AlertDescription_Shadcn_, @@ -62,7 +62,7 @@ const UserSessionsSchema = z.object({ const SessionsAuthSettingsForm = () => { const { ref: projectRef } = useParams() const { data: authConfig, error: authConfigError, isError } = useAuthConfigQuery({ projectRef }) - const { mutate: updateAuthConfig, isLoading: isUpdatingConfig } = useAuthConfigUpdateMutation() + const { mutate: updateAuthConfig } = useAuthConfigUpdateMutation() // Separate loading states for each form const [isUpdatingRefreshTokens, setIsUpdatingRefreshTokens] = useState(false) @@ -71,7 +71,7 @@ const SessionsAuthSettingsForm = () => { const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue') const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const isProPlanAndUp = organization?.plan?.id !== 'free' const promptProPlanUpgrade = IS_PLATFORM && !isProPlanAndUp diff --git a/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx b/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx index 2a142149b00..f4c14588849 100644 --- a/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx +++ b/apps/studio/components/interfaces/Auth/Users/UsersV2.tsx @@ -7,7 +7,6 @@ import { toast } from 'sonner' import { LOCAL_STORAGE_KEYS, useParams } from 'common' import { useIsAPIDocsSidePanelEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import APIDocsButton from 'components/ui/APIDocsButton' import { ButtonTooltip } from 'components/ui/ButtonTooltip' @@ -18,6 +17,7 @@ import { useUserDeleteMutation } from 'data/auth/user-delete-mutation' import { useUsersCountQuery } from 'data/auth/users-count-query' import { User, useUsersInfiniteQuery } from 'data/auth/users-infinite-query' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { isAtBottom } from 'lib/helpers' import { Button, @@ -61,7 +61,7 @@ export type Filter = 'all' | 'verified' | 'unverified' | 'anonymous' export const UsersV2 = () => { const queryClient = useQueryClient() const { ref: projectRef } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const gridRef = useRef(null) const xScroll = useRef(0) const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled() diff --git a/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx b/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx index e4feb1d958f..d75a742e5c0 100644 --- a/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx +++ b/apps/studio/components/interfaces/Billing/Payment/AddNewPaymentMethodModal.tsx @@ -7,7 +7,7 @@ import { toast } from 'sonner' import { Modal } from 'ui' import { useOrganizationPaymentMethodSetupIntent } from 'data/organizations/organization-payment-method-setup-intent-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { STRIPE_PUBLIC_KEY } from 'lib/constants' import AddPaymentMethodForm from './AddPaymentMethodForm' import { getStripeElementsAppearanceOptions } from './Payment.utils' @@ -29,7 +29,7 @@ const AddNewPaymentMethodModal = ({ }: AddNewPaymentMethodModalProps) => { const { resolvedTheme } = useTheme() const [intent, setIntent] = useState() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const [captchaToken, setCaptchaToken] = useState(null) const [captchaRef, setCaptchaRef] = useState(null) diff --git a/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx b/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx index 0171d9f5610..9e7a6dec940 100644 --- a/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx +++ b/apps/studio/components/interfaces/Billing/Payment/AddPaymentMethodForm.tsx @@ -9,7 +9,7 @@ import { useOrganizationCustomerProfileUpdateMutation } from 'data/organizations import { useOrganizationPaymentMethodMarkAsDefaultMutation } from 'data/organizations/organization-payment-method-default-mutation' import { useOrganizationTaxIdQuery } from 'data/organizations/organization-tax-id-query' import { useOrganizationTaxIdUpdateMutation } from 'data/organizations/organization-tax-id-update-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { isEqual } from 'lodash' import { useRef, useState } from 'react' import { toast } from 'sonner' @@ -27,7 +27,7 @@ interface AddPaymentMethodFormProps { // Small UX annoyance here, that the page will be refreshed const AddPaymentMethodForm = ({ onCancel, onConfirm }: AddPaymentMethodFormProps) => { - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { data: customerProfile, isLoading: customerProfileLoading } = useOrganizationCustomerProfileQuery({ diff --git a/apps/studio/components/interfaces/BranchManagement/Branch.Commands.tsx b/apps/studio/components/interfaces/BranchManagement/Branch.Commands.tsx index 6980de47929..cb13759dd0f 100644 --- a/apps/studio/components/interfaces/BranchManagement/Branch.Commands.tsx +++ b/apps/studio/components/interfaces/BranchManagement/Branch.Commands.tsx @@ -1,7 +1,7 @@ import { Forward, GitBranch } from 'lucide-react' import { useBranchesQuery } from 'data/branches/branches-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PageType, useRegisterCommands, useRegisterPage, useSetPage } from 'ui-patterns/CommandMenu' import { COMMAND_MENU_SECTIONS } from '../App/CommandMenu/CommandMenu.utils' import { orderCommandSectionsByPriority } from '../App/CommandMenu/ordering' @@ -12,7 +12,7 @@ const EMPTY_ARRAY = [] as Array export function useBranchCommands() { const setPage = useSetPage() - const selectedProject = useSelectedProject() + const { data: selectedProject } = useSelectedProjectQuery() const isBranchingEnabled = selectedProject?.is_branch_enabled === true let { data: branches } = useBranchesQuery( diff --git a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx index 266b0a636c4..f814b5f291f 100644 --- a/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx +++ b/apps/studio/components/interfaces/BranchManagement/CreateBranchModal.tsx @@ -9,6 +9,7 @@ import { useForm } from 'react-hook-form' import { toast } from 'sonner' import * as z from 'zod' +import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { useIsBranching2Enabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { BranchingPITRNotice } from 'components/layouts/AppLayout/EnableBranchingButton/BranchingPITRNotice' @@ -23,8 +24,10 @@ import { useGitHubConnectionsQuery } from 'data/integrations/github-connections- import { projectKeys } from 'data/projects/keys' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { useFlag } from 'hooks/ui/useFlag' import { BASE_PATH, IS_PLATFORM } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' import { @@ -46,22 +49,18 @@ import { cn, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' -import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useFlag } from 'hooks/ui/useFlag' export const CreateBranchModal = () => { const allowDataBranching = useFlag('allowDataBranching') const { ref } = useParams() const router = useRouter() const queryClient = useQueryClient() - const projectDetails = useSelectedProject() - const selectedOrg = useSelectedOrganization() + const { data: projectDetails } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const gitlessBranching = useIsBranching2Enabled() const { showCreateBranchModal, setShowCreateBranchModal } = useAppStateSnapshot() - const organization = useSelectedOrganization() - const isProPlanAndUp = organization?.plan?.id !== 'free' + const isProPlanAndUp = selectedOrg?.plan?.id !== 'free' const promptProPlanUpgrade = IS_PLATFORM && !isProPlanAndUp const isBranch = projectDetails?.parent_project_ref !== undefined diff --git a/apps/studio/components/interfaces/BranchManagement/EditBranchModal.tsx b/apps/studio/components/interfaces/BranchManagement/EditBranchModal.tsx index bed088dd528..9fa327912c2 100644 --- a/apps/studio/components/interfaces/BranchManagement/EditBranchModal.tsx +++ b/apps/studio/components/interfaces/BranchManagement/EditBranchModal.tsx @@ -8,15 +8,15 @@ import { toast } from 'sonner' import * as z from 'zod' import { useParams } from 'common' +import { useIsBranching2Enabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import AlertError from 'components/ui/AlertError' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' import { Branch, 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 } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' -import { useIsBranching2Enabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { useRouter } from 'next/router' import { @@ -48,8 +48,8 @@ interface EditBranchModalProps { export const EditBranchModal = ({ branch, visible, onClose }: EditBranchModalProps) => { const { ref } = useParams() const router = useRouter() - const projectDetails = useSelectedProject() - const selectedOrg = useSelectedOrganization() + const { data: projectDetails } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const gitlessBranching = useIsBranching2Enabled() const [isGitBranchValid, setIsGitBranchValid] = useState(false) diff --git a/apps/studio/components/interfaces/BranchManagement/OutOfDateNotice.tsx b/apps/studio/components/interfaces/BranchManagement/OutOfDateNotice.tsx index c90b7f99166..1c86de5f881 100644 --- a/apps/studio/components/interfaces/BranchManagement/OutOfDateNotice.tsx +++ b/apps/studio/components/interfaces/BranchManagement/OutOfDateNotice.tsx @@ -1,5 +1,8 @@ +import { useSendEventMutation } from 'data/telemetry/send-event-mutation' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { GitBranchIcon } from 'lucide-react' import { useState } from 'react' -import { Button } from 'ui' import { AlertDialog, AlertDialogAction, @@ -10,12 +13,9 @@ import { AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, + Button, } from 'ui' -import { GitBranchIcon } from 'lucide-react' import { Admonition } from 'ui-patterns' -import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' interface OutOfDateNoticeProps { isBranchOutOfDateMigrations: boolean @@ -44,8 +44,8 @@ export const OutOfDateNotice = ({ }: OutOfDateNoticeProps) => { const [isDialogOpen, setIsDialogOpen] = useState(false) const hasOutdatedMigrations = isBranchOutOfDateMigrations && missingMigrationsCount > 0 - const selectedOrg = useSelectedOrganization() - const project = useSelectedProject() + const { data: selectedOrg } = useSelectedOrganizationQuery() + const { data: project } = useSelectedProjectQuery() const { mutate: sendEvent } = useSendEventMutation() const isBranch = project?.parent_project_ref !== undefined diff --git a/apps/studio/components/interfaces/BranchManagement/ReviewRow.tsx b/apps/studio/components/interfaces/BranchManagement/ReviewRow.tsx index 4dd71e3d8b2..4d1e1409dde 100644 --- a/apps/studio/components/interfaces/BranchManagement/ReviewRow.tsx +++ b/apps/studio/components/interfaces/BranchManagement/ReviewRow.tsx @@ -2,10 +2,13 @@ import dayjs from 'dayjs' import { MoreVertical, X } from 'lucide-react' import { useRouter } from 'next/router' +import { useQueryClient } from '@tanstack/react-query' import { useParams } from 'common' import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' import type { Branch } from 'data/branches/branches-query' import { branchKeys } from 'data/branches/keys' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { toast } from 'sonner' import { Button, DropdownMenu, @@ -13,9 +16,6 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from 'ui' -import { toast } from 'sonner' -import { useQueryClient } from '@tanstack/react-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' interface ReviewRowProps { branch: Branch @@ -23,7 +23,7 @@ interface ReviewRowProps { export const ReviewRow = ({ branch }: ReviewRowProps) => { const router = useRouter() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { ref: projectRef } = useParams() const queryClient = useQueryClient() diff --git a/apps/studio/components/interfaces/BranchManagement/ReviewWithAI.tsx b/apps/studio/components/interfaces/BranchManagement/ReviewWithAI.tsx index 59d87fbf04a..9a93e5eaac3 100644 --- a/apps/studio/components/interfaces/BranchManagement/ReviewWithAI.tsx +++ b/apps/studio/components/interfaces/BranchManagement/ReviewWithAI.tsx @@ -1,12 +1,12 @@ -import { AiIconAnimation } from 'ui' -import { useProjectByRef } from 'hooks/misc/useSelectedProject' -import { useTablesQuery } from 'data/tables/tables-query' -import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' -import { Branch } from 'data/branches/branches-query' -import { tablesToSQL } from 'lib/helpers' import { ButtonTooltip } from 'components/ui/ButtonTooltip' +import { Branch } from 'data/branches/branches-query' +import { useTablesQuery } from 'data/tables/tables-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useProjectByRefQuery } from 'hooks/misc/useSelectedProject' +import { tablesToSQL } from 'lib/helpers' +import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' +import { AiIconAnimation } from 'ui' interface ReviewWithAIProps { currentBranch?: Branch @@ -24,11 +24,11 @@ export const ReviewWithAI = ({ disabled = false, }: ReviewWithAIProps) => { const aiSnap = useAiAssistantStateSnapshot() - const selectedOrg = useSelectedOrganization() + const { data: selectedOrg } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() // Get parent project for production schema - const parentProject = useProjectByRef(parentProjectRef) + const { data: parentProject } = useProjectByRefQuery(parentProjectRef) // Fetch production schema tables const { data: productionTables } = useTablesQuery( diff --git a/apps/studio/components/interfaces/Connect/Connect.tsx b/apps/studio/components/interfaces/Connect/Connect.tsx index 3a68ee63758..03482aeee43 100644 --- a/apps/studio/components/interfaces/Connect/Connect.tsx +++ b/apps/studio/components/interfaces/Connect/Connect.tsx @@ -10,7 +10,7 @@ import Panel from 'components/ui/Panel' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { Button, @@ -35,7 +35,7 @@ import ConnectTabContent from './ConnectTabContent' export const Connect = () => { const { ref: projectRef } = useParams() - const selectedProject = useSelectedProject() + const { data: selectedProject } = useSelectedProjectQuery() const isActiveHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY const [showConnect, setShowConnect] = useQueryState( diff --git a/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx b/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx index de37317c0db..890ceb58df6 100644 --- a/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx +++ b/apps/studio/components/interfaces/Connect/ConnectTabContent.tsx @@ -7,7 +7,7 @@ import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query import { usePgbouncerConfigQuery } from 'data/database/pgbouncer-config-query' import { useSupavisorConfigurationQuery } from 'data/database/supavisor-configuration-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { pluckObjectFields } from 'lib/helpers' import { cn } from 'ui' import { getAddons } from '../Billing/Subscription/Subscription.utils' @@ -30,7 +30,7 @@ interface ConnectContentTabProps extends HTMLAttributes { const ConnectTabContent = forwardRef( ({ projectKeys, filePath, ...props }, ref) => { const { ref: projectRef } = useParams() - const selectedOrg = useSelectedOrganization() + const { data: selectedOrg } = useSelectedOrganizationQuery() const allowPgBouncerSelection = useMemo(() => selectedOrg?.plan.id !== 'free', [selectedOrg]) const { data: settings } = useProjectSettingsV2Query({ projectRef }) diff --git a/apps/studio/components/interfaces/Connect/DatabaseConnectionString.tsx b/apps/studio/components/interfaces/Connect/DatabaseConnectionString.tsx index 325f0bf85ac..e7d36449fdc 100644 --- a/apps/studio/components/interfaces/Connect/DatabaseConnectionString.tsx +++ b/apps/studio/components/interfaces/Connect/DatabaseConnectionString.tsx @@ -12,7 +12,7 @@ import { useSupavisorConfigurationQuery } from 'data/database/supavisor-configur import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { pluckObjectFields } from 'lib/helpers' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' @@ -63,7 +63,7 @@ const StepLabel = ({ */ export const DatabaseConnectionString = () => { const { ref: projectRef } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const state = useDatabaseSelectorStateSnapshot() const [selectedTab, setSelectedTab] = useState('uri') diff --git a/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx b/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx index b84b9d16c33..484bfe785ec 100644 --- a/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx +++ b/apps/studio/components/interfaces/Database/Backups/BackupsList.tsx @@ -6,12 +6,12 @@ import { useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' 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 { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import BackupItem from './BackupItem' @@ -23,7 +23,7 @@ const BackupsList = () => { const queryClient = useQueryClient() const { ref: projectRef } = useParams() - const { project: selectedProject } = useProjectContext() + const { data: selectedProject } = useSelectedProjectQuery() const isHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY const [selectedBackup, setSelectedBackup] = useState() diff --git a/apps/studio/components/interfaces/Database/Backups/DatabaseBackupsNav.tsx b/apps/studio/components/interfaces/Database/Backups/DatabaseBackupsNav.tsx index f13ffca7e40..19e115c528a 100644 --- a/apps/studio/components/interfaces/Database/Backups/DatabaseBackupsNav.tsx +++ b/apps/studio/components/interfaces/Database/Backups/DatabaseBackupsNav.tsx @@ -1,7 +1,6 @@ -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Link from 'next/link' -import React from 'react' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, NavMenu, NavMenuItem } from 'ui' type Props = { @@ -9,7 +8,7 @@ type Props = { } function DatabaseBackupsNav({ active }: Props) { - const { ref, cloud_provider } = useProjectContext()?.project || {} + const { ref, cloud_provider } = useSelectedProjectQuery()?.data || {} const navMenuItems = [ { diff --git a/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/BackupsList.tsx b/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/BackupsList.tsx index b02999f6667..e25d3fad340 100644 --- a/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/BackupsList.tsx +++ b/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/BackupsList.tsx @@ -1,7 +1,7 @@ -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Panel from 'components/ui/Panel' import { useCloneBackupsQuery } from 'data/projects/clone-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, Button } from 'ui' import { TimestampInfo } from 'ui-patterns' import BackupsEmpty from '../BackupsEmpty' @@ -12,8 +12,8 @@ interface BackupsListProps { } export const BackupsList = ({ onSelectRestore, disabled }: BackupsListProps) => { - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const isFreePlan = organization?.plan?.id === 'free' diff --git a/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/ConfirmRestoreDialog.tsx b/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/ConfirmRestoreDialog.tsx index cc5b5c40dfe..3df3aa095cb 100644 --- a/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/ConfirmRestoreDialog.tsx +++ b/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/ConfirmRestoreDialog.tsx @@ -1,5 +1,5 @@ -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Dialog, @@ -26,8 +26,8 @@ export const ConfirmRestoreDialog = ({ onSelectContinue, additionalMonthlySpend, }: ConfirmRestoreDialogProps) => { - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() return (

diff --git a/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/CreateNewProjectDialog.tsx b/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/CreateNewProjectDialog.tsx index db1beed78f5..f76fe3ab7d6 100644 --- a/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/CreateNewProjectDialog.tsx +++ b/apps/studio/components/interfaces/Database/Backups/RestoreToNewProject/CreateNewProjectDialog.tsx @@ -5,11 +5,11 @@ import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { z } from 'zod' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import PasswordStrengthBar from 'components/ui/PasswordStrengthBar' import { useProjectCloneMutation } from 'data/projects/clone-mutation' import { useCloneBackupsQuery } from 'data/projects/clone-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { passwordStrength } from 'lib/helpers' import { generateStrongPassword } from 'lib/project' import { @@ -48,8 +48,8 @@ export const CreateNewProjectDialog = ({ onCloneSuccess, additionalMonthlySpend, }: CreateNewProjectDialogProps) => { - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const [passwordStrengthScore, setPasswordStrengthScore] = useState(0) const [passwordStrengthMessage, setPasswordStrengthMessage] = useState('') diff --git a/apps/studio/components/interfaces/Database/EnumeratedTypes/CreateEnumeratedTypeSidePanel.tsx b/apps/studio/components/interfaces/Database/EnumeratedTypes/CreateEnumeratedTypeSidePanel.tsx index 3efc7c9a9bb..0e7ef55f107 100644 --- a/apps/studio/components/interfaces/Database/EnumeratedTypes/CreateEnumeratedTypeSidePanel.tsx +++ b/apps/studio/components/interfaces/Database/EnumeratedTypes/CreateEnumeratedTypeSidePanel.tsx @@ -1,9 +1,14 @@ import { zodResolver } from '@hookform/resolvers/zod' +import { AlertCircle, ExternalLink, Plus } from 'lucide-react' import Link from 'next/link' import { useEffect, useRef } from 'react' import { DragDropContext, Droppable, DroppableProvided } from 'react-beautiful-dnd' import { useFieldArray, useForm } from 'react-hook-form' import { toast } from 'sonner' +import * as z from 'zod' + +import { useEnumeratedTypeCreateMutation } from 'data/enumerated-types/enumerated-type-create-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -20,13 +25,8 @@ import { SidePanel, cn, } from 'ui' -import * as z from 'zod' - -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { useEnumeratedTypeCreateMutation } from 'data/enumerated-types/enumerated-type-create-mutation' import EnumeratedTypeValueRow from './EnumeratedTypeValueRow' import { NATIVE_POSTGRES_TYPES } from './EnumeratedTypes.constants' -import { AlertCircle, ExternalLink, Plus } from 'lucide-react' interface CreateEnumeratedTypeSidePanelProps { visible: boolean @@ -41,7 +41,7 @@ const CreateEnumeratedTypeSidePanel = ({ }: CreateEnumeratedTypeSidePanelProps) => { const initialValues = { name: '', description: '', values: [{ value: '' }] } const submitRef = useRef(null) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: createEnumeratedType, isLoading: isCreating } = useEnumeratedTypeCreateMutation({ onSuccess: (res, vars) => { toast.success(`Successfully created type "${vars.name}"`) diff --git a/apps/studio/components/interfaces/Database/EnumeratedTypes/DeleteEnumeratedTypeModal.tsx b/apps/studio/components/interfaces/Database/EnumeratedTypes/DeleteEnumeratedTypeModal.tsx index 47ae59ee3bc..92e509c6956 100644 --- a/apps/studio/components/interfaces/Database/EnumeratedTypes/DeleteEnumeratedTypeModal.tsx +++ b/apps/studio/components/interfaces/Database/EnumeratedTypes/DeleteEnumeratedTypeModal.tsx @@ -1,6 +1,7 @@ -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { useEnumeratedTypeDeleteMutation } from 'data/enumerated-types/enumerated-type-delete-mutation' import { toast } from 'sonner' + +import { useEnumeratedTypeDeleteMutation } from 'data/enumerated-types/enumerated-type-delete-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' interface DeleteEnumeratedTypeModalProps { @@ -14,7 +15,7 @@ const DeleteEnumeratedTypeModal = ({ selectedEnumeratedType, onClose, }: DeleteEnumeratedTypeModalProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: deleteEnumeratedType, isLoading: isDeleting } = useEnumeratedTypeDeleteMutation({ onSuccess: () => { toast.success(`Successfully deleted "${selectedEnumeratedType.name}"`) diff --git a/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx b/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx index 02f695e575c..8beba161e56 100644 --- a/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx +++ b/apps/studio/components/interfaces/Database/EnumeratedTypes/EditEnumeratedTypeSidePanel.tsx @@ -1,8 +1,15 @@ import { zodResolver } from '@hookform/resolvers/zod' +import { AlertCircle, ExternalLink, Plus } from 'lucide-react' import Link from 'next/link' import { useEffect, useRef } from 'react' +import { DragDropContext, Droppable, DroppableProvided } from 'react-beautiful-dnd' import { useFieldArray, useForm } from 'react-hook-form' import { toast } from 'sonner' +import * as z from 'zod' + +import { useEnumeratedTypeUpdateMutation } from 'data/enumerated-types/enumerated-type-update-mutation' +import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -19,14 +26,7 @@ import { SidePanel, cn, } from 'ui' -import * as z from 'zod' - -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { useEnumeratedTypeUpdateMutation } from 'data/enumerated-types/enumerated-type-update-mutation' -import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' -import { DragDropContext, Droppable, DroppableProvided } from 'react-beautiful-dnd' import EnumeratedTypeValueRow from './EnumeratedTypeValueRow' -import { AlertCircle, ExternalLink, Plus } from 'lucide-react' interface EditEnumeratedTypeSidePanelProps { visible: boolean @@ -40,7 +40,7 @@ const EditEnumeratedTypeSidePanel = ({ onClose, }: EditEnumeratedTypeSidePanelProps) => { const submitRef = useRef(null) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: updateEnumeratedType, isLoading: isCreating } = useEnumeratedTypeUpdateMutation({ onSuccess: (_, vars) => { toast.success(`Successfully updated type "${vars.name.updated}"`) diff --git a/apps/studio/components/interfaces/Database/EnumeratedTypes/EnumeratedTypes.tsx b/apps/studio/components/interfaces/Database/EnumeratedTypes/EnumeratedTypes.tsx index 53b3c1f65ff..0f8007c0484 100644 --- a/apps/studio/components/interfaces/Database/EnumeratedTypes/EnumeratedTypes.tsx +++ b/apps/studio/components/interfaces/Database/EnumeratedTypes/EnumeratedTypes.tsx @@ -1,18 +1,17 @@ import { Edit, MoreVertical, Search, Trash } from 'lucide-react' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' import SchemaSelector from 'components/ui/SchemaSelector' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' -import { useSchemasQuery } from 'data/database/schemas-query' import { EnumeratedType, useEnumeratedTypesQuery, } from 'data/enumerated-types/enumerated-types-query' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { Button, @@ -28,18 +27,13 @@ import DeleteEnumeratedTypeModal from './DeleteEnumeratedTypeModal' import EditEnumeratedTypeSidePanel from './EditEnumeratedTypeSidePanel' const EnumeratedTypes = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [search, setSearch] = useState('') const { selectedSchema, setSelectedSchema } = useQuerySchemaState() const [showCreateTypePanel, setShowCreateTypePanel] = useState(false) const [selectedTypeToEdit, setSelectedTypeToEdit] = useState() const [selectedTypeToDelete, setSelectedTypeToDelete] = useState() - const { data: schemas } = useSchemasQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - }) - const { data, error, isLoading, isError, isSuccess } = useEnumeratedTypesQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx b/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx index 180631cb85b..6a0595903cb 100644 --- a/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx +++ b/apps/studio/components/interfaces/Database/Extensions/EnableExtensionModal.tsx @@ -3,13 +3,12 @@ import { Database, ExternalLinkIcon, Plus } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useDatabaseExtensionEnableMutation } from 'data/database-extensions/database-extension-enable-mutation' import { useSchemasQuery } from 'data/database/schemas-query' import { executeSql } from 'data/sql/execute-sql-query' -import { useIsOrioleDb } from 'hooks/misc/useSelectedProject' +import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -32,7 +31,7 @@ interface EnableExtensionModalProps { } const EnableExtensionModal = ({ visible, extension, onCancel }: EnableExtensionModalProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const isOrioleDb = useIsOrioleDb() const [defaultSchema, setDefaultSchema] = useState() const [fetchingSchemaInfo, setFetchingSchemaInfo] = useState(false) diff --git a/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx b/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx index b68d93f3c97..68d280a0268 100644 --- a/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx +++ b/apps/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx @@ -4,12 +4,11 @@ import Link from 'next/link' import { useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabaseExtensionDisableMutation } from 'data/database-extensions/database-extension-disable-mutation' import { DatabaseExtension } from 'data/database-extensions/database-extensions-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useIsOrioleDb } from 'hooks/misc/useSelectedProject' +import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { extensions } from 'shared-data' import { Button, cn, Switch, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { Admonition } from 'ui-patterns' @@ -22,7 +21,7 @@ interface ExtensionCardProps { } const ExtensionCard = ({ extension }: ExtensionCardProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const isOn = extension.installed_version !== null const isOrioleDb = useIsOrioleDb() diff --git a/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx b/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx index 98f74fd2443..73ca129d0c5 100644 --- a/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx +++ b/apps/studio/components/interfaces/Database/Extensions/Extensions.tsx @@ -4,13 +4,13 @@ import { AlertCircle, Search } from 'lucide-react' import { useEffect, useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import InformationBox from 'components/ui/InformationBox' import NoSearchResults from 'components/ui/NoSearchResults' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Input } from 'ui' import ExtensionCard from './ExtensionCard' import ExtensionCardSkeleton from './ExtensionCardSkeleton' @@ -18,7 +18,7 @@ import { HIDDEN_EXTENSIONS, SEARCH_TERMS } from './Extensions.constants' const Extensions = () => { const { filter } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [filterString, setFilterString] = useState('') const { data, isLoading } = useDatabaseExtensionsQuery({ diff --git a/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx b/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx index f4c4932120e..8c8bc254bb2 100644 --- a/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx +++ b/apps/studio/components/interfaces/Database/Functions/CreateFunction/index.tsx @@ -7,12 +7,12 @@ import { toast } from 'sonner' import z from 'zod' import { POSTGRES_DATA_TYPES } from 'components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.constants' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import SchemaSelector from 'components/ui/SchemaSelector' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useDatabaseFunctionCreateMutation } from 'data/database-functions/database-functions-create-mutation' import { DatabaseFunction } from 'data/database-functions/database-functions-query' import { useDatabaseFunctionUpdateMutation } from 'data/database-functions/database-functions-update-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProtectedSchemas } from 'hooks/useProtectedSchemas' import type { FormSchema } from 'types' import { @@ -69,7 +69,7 @@ const FormSchema = z.object({ }) const CreateFunction = ({ func, visible, setVisible }: CreateFunctionProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isClosingPanel, setIsClosingPanel] = useState(false) const [advancedSettingsShown, setAdvancedSettingsShown] = useState(false) // For now, there's no AI assistant for functions @@ -601,7 +601,7 @@ const FormFieldConfigParams = ({ readonly }: FormFieldConfigParamsProps) => { const ALL_ALLOWED_LANGUAGES = ['plpgsql', 'sql', 'plcoffee', 'plv8', 'plls'] const FormFieldLanguage = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: enabledExtensions } = useDatabaseExtensionsQuery( { diff --git a/apps/studio/components/interfaces/Database/Functions/DeleteFunction.tsx b/apps/studio/components/interfaces/Database/Functions/DeleteFunction.tsx index 134881ccb2d..7d674b0a3fb 100644 --- a/apps/studio/components/interfaces/Database/Functions/DeleteFunction.tsx +++ b/apps/studio/components/interfaces/Database/Functions/DeleteFunction.tsx @@ -1,8 +1,8 @@ import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseFunctionDeleteMutation } from 'data/database-functions/database-functions-delete-mutation' import { DatabaseFunction } from 'data/database-functions/database-functions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' interface DeleteFunctionProps { @@ -12,7 +12,7 @@ interface DeleteFunctionProps { } const DeleteFunction = ({ func, visible, setVisible }: DeleteFunctionProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { name, schema } = func ?? {} const { mutate: deleteDatabaseFunction, isLoading } = useDatabaseFunctionDeleteMutation({ diff --git a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx index 84ee90a9da9..9e42241f27c 100644 --- a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx +++ b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx @@ -3,11 +3,11 @@ import { includes, noop, sortBy } from 'lodash' import { Edit, Edit2, FileText, MoreVertical, Trash } from 'lucide-react' import { useRouter } from 'next/router' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabaseFunctionsQuery } from 'data/database-functions/database-functions-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { Button, @@ -34,7 +34,7 @@ const FunctionList = ({ deleteFunction = noop, }: FunctionListProps) => { const router = useRouter() - const { project: selectedProject } = useProjectContext() + const { data: selectedProject } = useSelectedProjectQuery() const aiSnap = useAiAssistantStateSnapshot() const { data: functions } = useDatabaseFunctionsQuery({ diff --git a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx index 22427a0581b..0af82c75f81 100644 --- a/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx +++ b/apps/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx @@ -5,7 +5,6 @@ import { Search } from 'lucide-react' import { useRouter } from 'next/router' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' @@ -16,6 +15,7 @@ import { useDatabaseFunctionsQuery } from 'data/database-functions/database-func import { useSchemasQuery } from 'data/database/schemas-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { AiIconAnimation, Input } from 'ui' @@ -35,7 +35,7 @@ const FunctionsList = ({ }: FunctionsListProps) => { const router = useRouter() const { search } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const aiSnap = useAiAssistantStateSnapshot() const { selectedSchema, setSelectedSchema } = useQuerySchemaState() diff --git a/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx b/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx index 9c91091af8d..04f11b34b81 100644 --- a/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/DeleteHookModal.tsx @@ -1,8 +1,8 @@ import type { PostgresTrigger } from '@supabase/postgres-meta' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseTriggerDeleteMutation } from 'data/database-triggers/database-trigger-delete-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' interface DeleteHookModalProps { @@ -14,7 +14,7 @@ interface DeleteHookModalProps { const DeleteHookModal = ({ selectedHook, visible, onClose }: DeleteHookModalProps) => { const { name, schema } = selectedHook ?? {} - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: deleteDatabaseTrigger, isLoading: isDeleting } = useDatabaseTriggerDeleteMutation( { onSuccess: () => { diff --git a/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx b/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx index 430f7008c21..eab82c99f22 100644 --- a/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/EditHookPanel.tsx @@ -4,11 +4,11 @@ import { useEffect, useMemo, useRef, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseTriggerCreateMutation } from 'data/database-triggers/database-trigger-create-mutation' import { useDatabaseTriggerUpdateMutation } from 'data/database-triggers/database-trigger-update-transaction-mutation' import { getTableEditor } from 'data/table-editor/table-editor-query' import { useTablesQuery } from 'data/tables/tables-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { isValidHttpUrl, uuidv4 } from 'lib/helpers' import { Button, Form, SidePanel } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' @@ -85,7 +85,7 @@ export const EditHookPanel = ({ visible, selectedHook, onClose }: EditHookPanelP })) }) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data } = useTablesQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/Database/Hooks/FormContents.tsx b/apps/studio/components/interfaces/Database/Hooks/FormContents.tsx index a1a9dbe3239..1f042b695ac 100644 --- a/apps/studio/components/interfaces/Database/Hooks/FormContents.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/FormContents.tsx @@ -6,7 +6,7 @@ import { useParams } from 'common' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { Checkbox, Input, Listbox, Radio, SidePanel } from 'ui' import { HTTPArgument, isEdgeFunction } from './EditHookPanel' @@ -45,7 +45,7 @@ export const FormContents = ({ submitRef, }: FormContentsProps) => { const { ref } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const restUrl = project?.restUrl const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co' diff --git a/apps/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx b/apps/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx index ec8cf9e4d75..fbf3f3e3dd1 100644 --- a/apps/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/HTTPRequestFields.tsx @@ -2,11 +2,11 @@ import { ChevronDown, Plus, X } from 'lucide-react' import Link from 'next/link' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { Button, @@ -48,7 +48,7 @@ const HTTPRequestFields = ({ onRemoveParameter, }: HTTPRequestFieldsProps) => { const { ref } = useParams() - const { project: selectedProject } = useProjectContext() + const { data: selectedProject } = useSelectedProjectQuery() const { data: functions } = useEdgeFunctionsQuery({ projectRef: ref }) const { data: apiKeys } = useAPIKeysQuery({ projectRef: ref, reveal: true }) diff --git a/apps/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx b/apps/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx index 00ba6d9259a..4f37d899979 100644 --- a/apps/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx @@ -4,11 +4,11 @@ import { Edit3, MoreVertical, Trash } from 'lucide-react' import Image from 'next/legacy/image' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabaseHooksQuery } from 'data/database-triggers/database-triggers-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { Badge, @@ -29,7 +29,7 @@ export interface HookListProps { const HookList = ({ schema, filterString, editHook = noop, deleteHook = noop }: HookListProps) => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: hooks } = useDatabaseHooksQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx b/apps/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx index ea3bd83c61a..e255efb78d0 100644 --- a/apps/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx +++ b/apps/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx @@ -3,7 +3,6 @@ import { includes, map as lodashMap, uniqBy } from 'lodash' import { Search } from 'lucide-react' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { DocsButton } from 'components/ui/DocsButton' @@ -11,6 +10,7 @@ import NoSearchResults from 'components/ui/NoSearchResults' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useDatabaseHooksQuery } from 'data/database-triggers/database-triggers-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { noop } from 'lib/void' import { Input } from 'ui' import HooksListEmpty from './HooksListEmpty' @@ -23,7 +23,7 @@ export interface HooksListProps { } const HooksList = ({ createHook = noop, editHook = noop, deleteHook = noop }: HooksListProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: hooks, isLoading, diff --git a/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx b/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx index 0dcef19d54b..fbf2c949d63 100644 --- a/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx +++ b/apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx @@ -3,7 +3,6 @@ import Link from 'next/link' import { Fragment, useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import CodeEditor from 'components/ui/CodeEditor/CodeEditor' import { DocsButton } from 'components/ui/DocsButton' import ShimmeringLoader from 'components/ui/ShimmeringLoader' @@ -11,7 +10,7 @@ import { useDatabaseIndexCreateMutation } from 'data/database-indexes/index-crea import { useSchemasQuery } from 'data/database/schemas-query' import { useTableColumnsQuery } from 'data/database/table-columns-query' import { useEntityTypesQuery } from 'data/entity-types/entity-types-infinite-query' -import { useIsOrioleDb } from 'hooks/misc/useSelectedProject' +import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, CommandEmpty_Shadcn_, @@ -45,7 +44,7 @@ interface CreateIndexSidePanelProps { } const CreateIndexSidePanel = ({ visible, onClose }: CreateIndexSidePanelProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const isOrioleDb = useIsOrioleDb() const [selectedSchema, setSelectedSchema] = useState('public') diff --git a/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx b/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx index 761ca6dc64c..3fe2c0dff97 100644 --- a/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx +++ b/apps/studio/components/interfaces/Database/Indexes/Indexes.tsx @@ -4,7 +4,6 @@ import { useEffect, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -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/CodeEditor' @@ -14,6 +13,7 @@ import { useDatabaseIndexDeleteMutation } from 'data/database-indexes/index-dele import { DatabaseIndex, useIndexesQuery } from 'data/database-indexes/indexes-query' import { useSchemasQuery } from 'data/database/schemas-query' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { Button, Input, SidePanel } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' @@ -21,7 +21,7 @@ import { ProtectedSchemaWarning } from '../ProtectedSchemaWarning' import CreateIndexSidePanel from './CreateIndexSidePanel' const Indexes = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { schema: urlSchema, table } = useParams() const [search, setSearch] = useState('') diff --git a/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx b/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx index 60a04c36b40..0d7206b0fa7 100644 --- a/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx +++ b/apps/studio/components/interfaces/Database/Migrations/Migrations.tsx @@ -2,11 +2,11 @@ import dayjs from 'dayjs' import Link from 'next/link' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import CodeEditor from 'components/ui/CodeEditor/CodeEditor' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { DatabaseMigration, useMigrationsQuery } from 'data/database/migrations-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Search } from 'lucide-react' import { Button, Input, SidePanel } from 'ui' import { Admonition } from 'ui-patterns' @@ -16,7 +16,7 @@ const Migrations = () => { const [search, setSearch] = useState('') const [selectedMigration, setSelectedMigration] = useState() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data, isLoading, isSuccess, isError, error } = useMigrationsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts b/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts index ee91af701eb..1cad017ce32 100644 --- a/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts +++ b/apps/studio/components/interfaces/Database/Privileges/Privileges.utils.ts @@ -1,13 +1,13 @@ import { useQueryClient } from '@tanstack/react-query' import { useCallback, useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { grantColumnPrivileges } from 'data/privileges/column-privileges-grant-mutation' import type { ColumnPrivilege } from 'data/privileges/column-privileges-query' import { ColumnPrivilegesRevoke, revokeColumnPrivileges, } from 'data/privileges/column-privileges-revoke-mutation' +import { privilegeKeys } from 'data/privileges/keys' import { TablePrivilegesGrant, grantTablePrivileges, @@ -17,12 +17,12 @@ import { TablePrivilegesRevoke, revokeTablePrivileges, } from 'data/privileges/table-privileges-revoke-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { ALL_PRIVILEGE_TYPES, COLUMN_PRIVILEGE_TYPES, ColumnPrivilegeType, } from './Privileges.constants' -import { privilegeKeys } from 'data/privileges/keys' export interface PrivilegeOperation { object: 'table' | 'column' @@ -266,7 +266,7 @@ export function usePrivilegesState({ } export function useApplyPrivilegeOperations(callback?: () => void) { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const queryClient = useQueryClient() const [isLoading, setIsLoading] = useState(false) diff --git a/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx b/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx index a3be0cde9bb..cd47055410a 100644 --- a/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx +++ b/apps/studio/components/interfaces/Database/Publications/PublicationsList.tsx @@ -5,15 +5,15 @@ import { toast } from 'sonner' import { Button, Input, 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 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/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { AlertCircle, Search } from 'lucide-react' import PublicationSkeleton from './PublicationSkeleton' -import { Search, AlertCircle } from 'lucide-react' interface PublicationEvent { event: string @@ -25,7 +25,7 @@ interface PublicationsListProps { } const PublicationsList = ({ onSelectPublication = noop }: PublicationsListProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [filterString, setFilterString] = useState('') const { data, isLoading } = useDatabasePublicationsQuery({ diff --git a/apps/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx b/apps/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx index 8c10afa389f..0628aefae27 100644 --- a/apps/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx +++ b/apps/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx @@ -3,10 +3,10 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useState } from 'react' import { Badge, Toggle } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import { useDatabasePublicationUpdateMutation } from 'data/database-publications/database-publications-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { toast } from 'sonner' interface PublicationsTableItemProps { @@ -15,7 +15,7 @@ interface PublicationsTableItemProps { } const PublicationsTableItem = ({ table, selectedPublication }: PublicationsTableItemProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const enabledForAllTables = selectedPublication.tables == null const [checked, setChecked] = useState( diff --git a/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx b/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx index a67ff1ea131..01b65876670 100644 --- a/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx +++ b/apps/studio/components/interfaces/Database/Publications/PublicationsTables.tsx @@ -2,7 +2,6 @@ import type { PostgresPublication } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useMemo, useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' @@ -10,6 +9,7 @@ import InformationBox from 'components/ui/InformationBox' import { Loading } from 'components/ui/Loading' import { useTablesQuery } from 'data/tables/tables-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProtectedSchemas } from 'hooks/useProtectedSchemas' import { AlertCircle, ChevronLeft, Search } from 'lucide-react' import { Button, Input } from 'ui' @@ -21,7 +21,7 @@ interface PublicationsTablesProps { } const PublicationsTables = ({ selectedPublication, onSelectBack }: PublicationsTablesProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [filterString, setFilterString] = useState('') const canUpdatePublications = useCheckPermissions( diff --git a/apps/studio/components/interfaces/Database/Roles/CreateRolePanel.tsx b/apps/studio/components/interfaces/Database/Roles/CreateRolePanel.tsx index 481d06b26e1..0d604816196 100644 --- a/apps/studio/components/interfaces/Database/Roles/CreateRolePanel.tsx +++ b/apps/studio/components/interfaces/Database/Roles/CreateRolePanel.tsx @@ -3,9 +3,9 @@ import { SubmitHandler, useForm } from 'react-hook-form' import { toast } from 'sonner' import z from 'zod' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormActions } from 'components/ui/Forms/FormActions' import { useDatabaseRoleCreateMutation } from 'data/database-roles/database-role-create-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { FormControl_Shadcn_, FormField_Shadcn_, @@ -47,7 +47,7 @@ const initialValues = { const CreateRolePanel = ({ visible, onClose }: CreateRolePanelProps) => { const formId = 'create-new-role' - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const form = useForm>({ resolver: zodResolver(FormSchema), diff --git a/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx b/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx index fae48ec353b..9ae12e45753 100644 --- a/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx +++ b/apps/studio/components/interfaces/Database/Roles/DeleteRoleModal.tsx @@ -1,9 +1,9 @@ import type { PostgresRole } from '@supabase/postgres-meta' import { toast } from 'sonner' -import { Modal } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseRoleDeleteMutation } from 'data/database-roles/database-role-delete-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { Modal } from 'ui' interface DeleteRoleModalProps { role: PostgresRole @@ -12,7 +12,7 @@ interface DeleteRoleModalProps { } const DeleteRoleModal = ({ role, visible, onClose }: DeleteRoleModalProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: deleteDatabaseRole, isLoading: isDeleting } = useDatabaseRoleDeleteMutation({ onSuccess: () => { diff --git a/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx b/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx index 1e4e15b6cac..5f109a3597a 100644 --- a/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx +++ b/apps/studio/components/interfaces/Database/Roles/RoleRow.tsx @@ -15,9 +15,9 @@ import { TooltipTrigger, } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseRoleUpdateMutation } from 'data/database-roles/database-role-update-mutation' import { PgRole } from 'data/database-roles/database-roles-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { ChevronUp, HelpCircle, MoreVertical, Trash } from 'lucide-react' import { ROLE_PERMISSIONS } from './Roles.constants' @@ -28,7 +28,7 @@ interface RoleRowProps { } const RoleRow = ({ role, disabled = false, onSelectDelete }: RoleRowProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isExpanded, setIsExpanded] = useState(false) const { mutate: updateDatabaseRole, isLoading: isUpdating } = useDatabaseRoleUpdateMutation() diff --git a/apps/studio/components/interfaces/Database/Roles/RolesList.tsx b/apps/studio/components/interfaces/Database/Roles/RolesList.tsx index 3726a78c7d4..47568a0768e 100644 --- a/apps/studio/components/interfaces/Database/Roles/RolesList.tsx +++ b/apps/studio/components/interfaces/Database/Roles/RolesList.tsx @@ -3,13 +3,13 @@ import { partition, sortBy } from 'lodash' import { Plus, Search, X } from 'lucide-react' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import NoSearchResults from 'components/ui/NoSearchResults' import SparkBar from 'components/ui/SparkBar' import { useDatabaseRolesQuery } from 'data/database-roles/database-roles-query' import { useMaxConnectionsQuery } from 'data/database/max-connections-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, Button, Input, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import CreateRolePanel from './CreateRolePanel' import DeleteRoleModal from './DeleteRoleModal' @@ -20,7 +20,7 @@ import { SUPABASE_ROLES } from './Roles.constants' type SUPABASE_ROLE = (typeof SUPABASE_ROLES)[number] const RolesList = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [filterString, setFilterString] = useState('') const [filterType, setFilterType] = useState<'all' | 'active'>('all') diff --git a/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx b/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx index 85f6c70aab2..61e1d483f12 100644 --- a/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx +++ b/apps/studio/components/interfaces/Database/Schemas/SchemaGraph.tsx @@ -1,13 +1,13 @@ import type { PostgresSchema } from '@supabase/postgres-meta' import { toPng, toSvg } from 'html-to-image' -import { Check, Download, Loader2, Clipboard, Info } from 'lucide-react' +import { Check, Clipboard, Download, Loader2 } from 'lucide-react' import { useTheme } from 'next-themes' import { useEffect, useMemo, useState } from 'react' import ReactFlow, { Background, BackgroundVariant, MiniMap, useReactFlow } from 'reactflow' import 'reactflow/dist/style.css' +import { toast } from 'sonner' import { LOCAL_STORAGE_KEYS, useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import AlertError from 'components/ui/AlertError' import { ButtonTooltip } from 'components/ui/ButtonTooltip' @@ -16,19 +16,24 @@ import { useSchemasQuery } from 'data/database/schemas-query' import { useTablesQuery } from 'data/tables/tables-query' import { useLocalStorage } from 'hooks/misc/useLocalStorage' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' -import { toast } from 'sonner' -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from 'ui' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { tablesToSQL } from 'lib/helpers' +import { + copyToClipboard, + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from 'ui' import { SchemaGraphLegend } from './SchemaGraphLegend' import { getGraphDataFromTables, getLayoutedElementsViaDagre } from './Schemas.utils' import { TableNode } from './SchemaTableNode' -import { copyToClipboard } from 'ui' -import { tablesToSQL } from 'lib/helpers' // [Joshen] Persisting logic: Only save positions to local storage WHEN a node is moved OR when explicitly clicked to reset layout export const SchemaGraph = () => { const { ref } = useParams() const { resolvedTheme } = useTheme() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { selectedSchema, setSelectedSchema } = useQuerySchemaState() const [copied, setCopied] = useState(false) diff --git a/apps/studio/components/interfaces/Database/Tables/ColumnList.tsx b/apps/studio/components/interfaces/Database/Tables/ColumnList.tsx index e3830b6680e..ba4eedf9839 100644 --- a/apps/studio/components/interfaces/Database/Tables/ColumnList.tsx +++ b/apps/studio/components/interfaces/Database/Tables/ColumnList.tsx @@ -5,7 +5,6 @@ import Link from 'next/link' import { useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' @@ -14,6 +13,7 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { Button, @@ -42,7 +42,7 @@ const ColumnList = ({ const { id: _id, ref } = useParams() const id = _id ? Number(_id) : undefined - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable, error, diff --git a/apps/studio/components/interfaces/Database/Tables/TableList.tsx b/apps/studio/components/interfaces/Database/Tables/TableList.tsx index 500bc001642..c3eea9f3055 100644 --- a/apps/studio/components/interfaces/Database/Tables/TableList.tsx +++ b/apps/studio/components/interfaces/Database/Tables/TableList.tsx @@ -20,7 +20,6 @@ import { useRouter } from 'next/router' import { useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { ButtonTooltip } from 'components/ui/ButtonTooltip' @@ -35,6 +34,7 @@ import { useTablesQuery } from 'data/tables/tables-query' import { useViewsQuery } from 'data/views/views-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { Button, @@ -72,7 +72,7 @@ const TableList = ({ }: TableListProps) => { const router = useRouter() const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const prefetchEditorTablePage = usePrefetchEditorTablePage() diff --git a/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx b/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx index 809bb86edd0..c29ac4fdc92 100644 --- a/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx +++ b/apps/studio/components/interfaces/Database/Triggers/ChooseFunctionForm.tsx @@ -13,7 +13,7 @@ import { useDatabaseFunctionsQuery, type DatabaseFunction, } from 'data/database-functions/database-functions-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { ChevronDown, HelpCircle, Terminal } from 'lucide-react' export interface ChooseFunctionFormProps { @@ -23,7 +23,7 @@ export interface ChooseFunctionFormProps { } const ChooseFunctionForm = ({ visible, onChange, setVisible }: ChooseFunctionFormProps) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data = [] } = useDatabaseFunctionsQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/Database/Triggers/DeleteTrigger.tsx b/apps/studio/components/interfaces/Database/Triggers/DeleteTrigger.tsx index bca6a011c20..6bd72bb9f0e 100644 --- a/apps/studio/components/interfaces/Database/Triggers/DeleteTrigger.tsx +++ b/apps/studio/components/interfaces/Database/Triggers/DeleteTrigger.tsx @@ -1,8 +1,8 @@ import { PostgresTrigger } from '@supabase/postgres-meta' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseTriggerDeleteMutation } from 'data/database-triggers/database-trigger-delete-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' interface DeleteTriggerProps { @@ -12,7 +12,7 @@ interface DeleteTriggerProps { } export const DeleteTrigger = ({ trigger, visible, setVisible }: DeleteTriggerProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { name, schema } = trigger ?? {} const { mutate: deleteDatabaseTrigger, isLoading } = useDatabaseTriggerDeleteMutation() diff --git a/apps/studio/components/interfaces/Database/Triggers/TriggerSheet.tsx b/apps/studio/components/interfaces/Database/Triggers/TriggerSheet.tsx index 5d381c00588..37206dbaccb 100644 --- a/apps/studio/components/interfaces/Database/Triggers/TriggerSheet.tsx +++ b/apps/studio/components/interfaces/Database/Triggers/TriggerSheet.tsx @@ -10,7 +10,7 @@ import FormBoxEmpty from 'components/ui/FormBoxEmpty' import { useDatabaseTriggerCreateMutation } from 'data/database-triggers/database-trigger-create-mutation' import { useDatabaseTriggerUpdateMutation } from 'data/database-triggers/database-trigger-update-mutation' import { useTablesQuery } from 'data/tables/tables-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProtectedSchemas } from 'hooks/useProtectedSchemas' import { Button, @@ -80,7 +80,7 @@ interface TriggerSheetProps { } export const TriggerSheet = ({ selectedTrigger, open, setOpen }: TriggerSheetProps) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const [showFunctionSelector, setShowFunctionSelector] = useState(false) diff --git a/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx b/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx index 905bda55407..809b5d65bcc 100644 --- a/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx +++ b/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx @@ -2,11 +2,11 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { includes, sortBy } from 'lodash' import { Check, Edit, Edit2, MoreVertical, Trash, X } from 'lucide-react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabaseTriggersQuery } from 'data/database-triggers/database-triggers-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { Badge, @@ -36,7 +36,7 @@ const TriggerList = ({ editTrigger, deleteTrigger, }: TriggerListProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const aiSnap = useAiAssistantStateSnapshot() const { data: triggers } = useDatabaseTriggersQuery({ diff --git a/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx b/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx index df5058fe2dc..6cb57562621 100644 --- a/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx +++ b/apps/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx @@ -4,7 +4,6 @@ import { noop } from 'lodash' import { Plus, Search } from 'lucide-react' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlphaPreview from 'components/to-be-cleaned/AlphaPreview' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import Table from 'components/to-be-cleaned/Table' @@ -16,6 +15,7 @@ import { useDatabaseTriggersQuery } from 'data/database-triggers/database-trigge import { useTablesQuery } from 'data/tables/tables-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema, useProtectedSchemas } from 'hooks/useProtectedSchemas' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { AiIconAnimation, Input } from 'ui' @@ -33,7 +33,7 @@ const TriggersList = ({ editTrigger = noop, deleteTrigger = noop, }: TriggersListProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const aiSnap = useAiAssistantStateSnapshot() const { selectedSchema, setSelectedSchema } = useQuerySchemaState() const [filterString, setFilterString] = useState('') diff --git a/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx b/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx index 71aab9991c1..85e194c4f37 100644 --- a/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx +++ b/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx @@ -9,7 +9,6 @@ import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { MAX_WIDTH_CLASSES, PADDING_CLASSES, ScaffoldContainer } from 'components/layouts/Scaffold' import { DocsButton } from 'components/ui/DocsButton' import { @@ -27,7 +26,12 @@ import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { AddonVariantId } from 'data/subscriptions/types' import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { + useIsAwsCloudProvider, + useIsAwsK8sCloudProvider, + useSelectedProjectQuery, +} from 'hooks/misc/useSelectedProject' import { GB, PROJECT_STATUS } from 'lib/constants' import { CloudProvider } from 'shared-data' import { @@ -60,12 +64,11 @@ import { } from './ui/DiskManagement.constants' import { NoticeBar } from './ui/NoticeBar' import { SpendCapDisabledSection } from './ui/SpendCapDisabledSection' -import { useIsAwsCloudProvider, useIsAwsK8sCloudProvider } from 'hooks/misc/useSelectedProject' export function DiskManagementForm() { // isLoading is used to avoid a useCheckPermissions() race condition - const { project, isLoading: isProjectLoading } = useProjectContext() - const org = useSelectedOrganization() + const { data: project, isLoading: isProjectLoading } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { ref: projectRef } = useParams() const queryClient = useQueryClient() diff --git a/apps/studio/components/interfaces/DiskManagement/DiskManagementReviewAndSubmitDialog.tsx b/apps/studio/components/interfaces/DiskManagement/DiskManagementReviewAndSubmitDialog.tsx index d1d40d15e07..03b3d42a7f2 100644 --- a/apps/studio/components/interfaces/DiskManagement/DiskManagementReviewAndSubmitDialog.tsx +++ b/apps/studio/components/interfaces/DiskManagement/DiskManagementReviewAndSubmitDialog.tsx @@ -3,11 +3,11 @@ import { ChevronRight } from 'lucide-react' import { useMemo } from 'react' import { UseFormReturn } from 'react-hook-form' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { formatCurrency } from 'lib/helpers' import { Alert_Shadcn_, @@ -148,8 +148,8 @@ export const DiskManagementReviewAndSubmitDialog = ({ message, buttonSize = 'medium', }: DiskSizeMeterProps) => { - const { project } = useProjectContext() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { formState, getValues } = form diff --git a/apps/studio/components/interfaces/DiskManagement/fields/ComputeSizeField.tsx b/apps/studio/components/interfaces/DiskManagement/fields/ComputeSizeField.tsx index 3e26ae3e02d..7962668be3e 100644 --- a/apps/studio/components/interfaces/DiskManagement/fields/ComputeSizeField.tsx +++ b/apps/studio/components/interfaces/DiskManagement/fields/ComputeSizeField.tsx @@ -3,11 +3,11 @@ import { useMemo } from 'react' import { UseFormReturn } from 'react-hook-form' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import { InlineLink } from 'components/ui/InlineLink' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils' import { InstanceSpecs } from 'lib/constants' import Link from 'next/link' @@ -52,10 +52,9 @@ type ComputeSizeFieldProps = { export function ComputeSizeField({ form, disabled }: ComputeSizeFieldProps) { const { ref } = useParams() - const org = useSelectedOrganization() - const { control, formState, setValue, trigger } = form + const { data: org } = useSelectedOrganizationQuery() + const { data: project, isLoading: isProjectLoading } = useSelectedProjectQuery() - const { project, isLoading: isProjectLoading } = useProjectContext() const { data: addons, isLoading: isAddonsLoading, @@ -64,6 +63,8 @@ export function ComputeSizeField({ form, disabled }: ComputeSizeFieldProps) { const isLoading = isProjectLoading || isAddonsLoading + const { control, formState, setValue, trigger } = form + const availableAddons = useMemo(() => { return addons?.available_addons ?? [] }, [addons]) diff --git a/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx b/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx index 85c4bc6ea59..97b201fbbe2 100644 --- a/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx +++ b/apps/studio/components/interfaces/DiskManagement/fields/DiskSizeField.tsx @@ -6,8 +6,8 @@ import { DocsButton } from 'components/ui/DocsButton' import { useDiskAttributesQuery } from 'data/config/disk-attributes-query' import { useDiskUtilizationQuery } from 'data/config/disk-utilization-query' import dayjs from 'dayjs' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { GB } from 'lib/constants' import { Button, FormControl_Shadcn_, FormField_Shadcn_, Input_Shadcn_, Skeleton, cn } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' @@ -35,8 +35,8 @@ export function DiskSizeField({ }: DiskSizeFieldProps) { const { ref: projectRef } = useParams() const { control, formState, setValue, trigger, getValues, resetField, watch } = form - const org = useSelectedOrganization() - const project = useSelectedProject() + const { data: org } = useSelectedOrganizationQuery() + const { data: project } = useSelectedProjectQuery() const { isLoading: isLoadingDiskAttributes, diff --git a/apps/studio/components/interfaces/DiskManagement/fields/StorageTypeField.tsx b/apps/studio/components/interfaces/DiskManagement/fields/StorageTypeField.tsx index 266fd36f46b..6f19256fcf1 100644 --- a/apps/studio/components/interfaces/DiskManagement/fields/StorageTypeField.tsx +++ b/apps/studio/components/interfaces/DiskManagement/fields/StorageTypeField.tsx @@ -3,7 +3,7 @@ import { UseFormReturn } from 'react-hook-form' import { useParams } from 'common' import { InlineLink } from 'components/ui/InlineLink' import { useDiskAttributesQuery } from 'data/config/disk-attributes-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, buttonVariants, @@ -33,7 +33,7 @@ type StorageTypeFieldProps = { export function StorageTypeField({ form, disableInput }: StorageTypeFieldProps) { const { control, trigger } = form - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { ref: projectRef } = useParams() const isIo2Supported = IO2_AVAILABLE_REGIONS.includes(project?.region ?? '') diff --git a/apps/studio/components/interfaces/DiskManagement/ui/DiskSpaceBar.tsx b/apps/studio/components/interfaces/DiskManagement/ui/DiskSpaceBar.tsx index efcac13c873..5eb8b609d99 100644 --- a/apps/studio/components/interfaces/DiskManagement/ui/DiskSpaceBar.tsx +++ b/apps/studio/components/interfaces/DiskManagement/ui/DiskSpaceBar.tsx @@ -7,7 +7,7 @@ import { UseFormReturn } from 'react-hook-form' import { useParams } from 'common' import { useDiskBreakdownQuery } from 'data/config/disk-breakdown-query' import { useDiskUtilizationQuery } from 'data/config/disk-utilization-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { GB } from 'lib/constants' import { formatBytes } from 'lib/helpers' import { useMemo } from 'react' @@ -24,7 +24,7 @@ export default function DiskSpaceBar({ form }: DiskSpaceBarProps) { const { resolvedTheme } = useTheme() const { formState, watch } = form const isDarkMode = resolvedTheme?.includes('dark') - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: diskUtil, diff --git a/apps/studio/components/interfaces/DiskManagement/ui/SpendCapDisabledSection.tsx b/apps/studio/components/interfaces/DiskManagement/ui/SpendCapDisabledSection.tsx index 812ff2a4f5b..58fb36352a6 100644 --- a/apps/studio/components/interfaces/DiskManagement/ui/SpendCapDisabledSection.tsx +++ b/apps/studio/components/interfaces/DiskManagement/ui/SpendCapDisabledSection.tsx @@ -1,7 +1,8 @@ import { AnimatePresence, motion } from 'framer-motion' import Link from 'next/link' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_ as AlertDescription, AlertTitle_Shadcn_ as AlertTitle, @@ -9,11 +10,10 @@ import { cn, } from 'ui' import { Admonition } from 'ui-patterns/admonition' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' export function SpendCapDisabledSection() { - const org = useSelectedOrganization() - const project = useSelectedProject() + const { data: org } = useSelectedOrganizationQuery() + const { data: project } = useSelectedProjectQuery() const isSpendCapEnabled = org?.plan.id !== 'free' && !org?.usage_billing_enabled && project?.cloud_provider !== 'FLY' diff --git a/apps/studio/components/interfaces/Docs/Description.tsx b/apps/studio/components/interfaces/Docs/Description.tsx index 6672a3abe6c..dc9dfb112d7 100644 --- a/apps/studio/components/interfaces/Docs/Description.tsx +++ b/apps/studio/components/interfaces/Docs/Description.tsx @@ -3,13 +3,13 @@ import { noop } from 'lodash' import { useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AutoTextArea from 'components/to-be-cleaned/forms/AutoTextArea' import { executeSql } from 'data/sql/execute-sql-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { timeout } from 'lib/helpers' -import { Button } from 'ui' import { Loader } from 'lucide-react' +import { Button } from 'ui' // Removes some auto-generated Postgrest text // Ideally PostgREST wouldn't add this if there is already a comment @@ -35,7 +35,7 @@ const Description = ({ content, metadata, onChange = noop }: DescrptionProps) => const contentText = temp_removePostgrestText(content || '').trim() const [value, setValue] = useState(contentText) const [isUpdating, setIsUpdating] = useState(false) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { table, column, rpc } = metadata diff --git a/apps/studio/components/interfaces/EdgeFunctions/DeployEdgeFunctionButton.tsx b/apps/studio/components/interfaces/EdgeFunctions/DeployEdgeFunctionButton.tsx index 6517056113f..9412f8ae035 100644 --- a/apps/studio/components/interfaces/EdgeFunctions/DeployEdgeFunctionButton.tsx +++ b/apps/studio/components/interfaces/EdgeFunctions/DeployEdgeFunctionButton.tsx @@ -4,7 +4,7 @@ import { useRouter } from 'next/router' import { useParams } from 'common' import { TerminalInstructions } from 'components/interfaces/Functions/TerminalInstructions' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { AiIconAnimation, @@ -23,7 +23,7 @@ import { export const DeployEdgeFunctionButton = () => { const router = useRouter() const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const snap = useAiAssistantStateSnapshot() const { mutate: sendEvent } = useSendEventMutation() diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx index 4e07ccbf571..4f2d3fb18d2 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionTesterSheet.tsx @@ -12,7 +12,7 @@ import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-co import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useEdgeFunctionTestMutation } from 'data/edge-functions/edge-function-test-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { prettifyJSON } from 'lib/helpers' import { getRoleImpersonationJWT } from 'lib/role-impersonation' @@ -80,7 +80,7 @@ const FormSchema = z.object({ type FormValues = z.infer export const EdgeFunctionTesterSheet = ({ visible, onClose }: EdgeFunctionTesterSheetProps) => { - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { ref: projectRef, functionSlug } = useParams() const getImpersonatedRoleState = useGetImpersonatedRoleState() diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx index 0d99237296c..55fae1e47a5 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx @@ -4,10 +4,10 @@ import { useRouter } from 'next/router' import { useState } from 'react' 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 type { EdgeFunctionsResponse } from 'data/edge-functions/edge-functions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { copyToClipboard, Tooltip, TooltipContent, TooltipTrigger } from 'ui' interface EdgeFunctionsListItemProps { @@ -17,7 +17,7 @@ interface EdgeFunctionsListItemProps { export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemProps) => { const router = useRouter() const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isCopied, setIsCopied] = useState(false) const { data: customDomainData } = useCustomDomainsQuery({ projectRef: ref }) diff --git a/apps/studio/components/interfaces/Functions/FunctionsEmptyState.tsx b/apps/studio/components/interfaces/Functions/FunctionsEmptyState.tsx index 92a46f598da..2d288a5bfc2 100644 --- a/apps/studio/components/interfaces/Functions/FunctionsEmptyState.tsx +++ b/apps/studio/components/interfaces/Functions/FunctionsEmptyState.tsx @@ -8,7 +8,7 @@ import { DocsButton } from 'components/ui/DocsButton' import { ResourceItem } from 'components/ui/Resource/ResourceItem' import { ResourceList } from 'components/ui/Resource/ResourceList' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { AiIconAnimation, @@ -37,7 +37,7 @@ export const FunctionsEmptyState = () => { const aiSnap = useAiAssistantStateSnapshot() const { mutate: sendEvent } = useSendEventMutation() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() return ( <> diff --git a/apps/studio/components/interfaces/Home/ExampleProject.tsx b/apps/studio/components/interfaces/Home/ExampleProject.tsx index 2c8bcf1f0d6..13a10c1a00b 100644 --- a/apps/studio/components/interfaces/Home/ExampleProject.tsx +++ b/apps/studio/components/interfaces/Home/ExampleProject.tsx @@ -4,7 +4,7 @@ import Link from 'next/link' import { useParams } from 'common' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH } from 'lib/constants' interface ExampleProjectProps { @@ -17,7 +17,7 @@ interface ExampleProjectProps { const ExampleProject = ({ framework, title, description, url }: ExampleProjectProps) => { const { resolvedTheme } = useTheme() const { ref: projectRef } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() diff --git a/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx b/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx index c0fb01b1a05..cdf47010073 100644 --- a/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx +++ b/apps/studio/components/interfaces/Home/ProjectList/ProjectList.tsx @@ -9,7 +9,7 @@ import { usePermissionsQuery } from 'data/permissions/permissions-query' import { ProjectInfo, useProjectsQuery } from 'data/projects/projects-query' import { ResourceWarning, useResourceWarningsQuery } from 'data/usage/resource-warnings-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { makeRandomString } from 'lib/helpers' import type { Organization, ResponseError } from 'types' @@ -32,7 +32,7 @@ const ProjectList = ({ filterStatus, resetFilterStatus, }: ProjectListProps) => { - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const organization = organization_ ?? selectedOrganization const { diff --git a/apps/studio/components/interfaces/Home/ProjectUsage.tsx b/apps/studio/components/interfaces/Home/ProjectUsage.tsx index 5ecdfb3e224..59be56f713a 100644 --- a/apps/studio/components/interfaces/Home/ProjectUsage.tsx +++ b/apps/studio/components/interfaces/Home/ProjectUsage.tsx @@ -17,7 +17,7 @@ import { import { useFillTimeseriesSorted } from 'hooks/analytics/useFillTimeseriesSorted' import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { ChartIntervals } from 'types' import { Button, @@ -66,7 +66,7 @@ const CHART_INTERVALS: ChartIntervals[] = [ const ProjectUsage = () => { const router = useRouter() const { ref: projectRef } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const { projectAuthAll: authEnabled, projectStorageAll: storageEnabled } = useIsFeatureEnabled([ 'project_auth:all', diff --git a/apps/studio/components/interfaces/Home/ProjectUsageSection.tsx b/apps/studio/components/interfaces/Home/ProjectUsageSection.tsx index 0093aa5f566..cdaeb78f73e 100644 --- a/apps/studio/components/interfaces/Home/ProjectUsageSection.tsx +++ b/apps/studio/components/interfaces/Home/ProjectUsageSection.tsx @@ -4,11 +4,11 @@ import { ProjectUsageLoadingState } from 'components/layouts/ProjectLayout/Loadi import InformationBox from 'components/ui/InformationBox' import { useProjectLogRequestsCountQuery } from 'data/analytics/project-log-requests-count-query' import { useProjectLogStatsQuery } from 'data/analytics/project-log-stats-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import ProjectUsage from './ProjectUsage' export const ProjectUsageSection = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { error, isLoading } = useProjectLogRequestsCountQuery({ projectRef: project?.ref }) // wait for the stats to load before showing the usage section to eliminate multiple spinners diff --git a/apps/studio/components/interfaces/Home/ServiceStatus.tsx b/apps/studio/components/interfaces/Home/ServiceStatus.tsx index bcba3a9bc90..1481e45a357 100644 --- a/apps/studio/components/interfaces/Home/ServiceStatus.tsx +++ b/apps/studio/components/interfaces/Home/ServiceStatus.tsx @@ -12,7 +12,7 @@ import { useProjectServiceStatusQuery, } from 'data/service-status/service-status-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, InfoIcon, @@ -74,7 +74,7 @@ const StatusIcon = ({ export const ServiceStatus = () => { const { ref } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const [open, setOpen] = useState(false) const { diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet.tsx index 14337533f7a..bc6dcfa9963 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/CreateCronJobSheet.tsx @@ -10,7 +10,6 @@ import z from 'zod' import { useWatch } from '@ui/components/shadcn/ui/form' import { urlRegex } from 'components/interfaces/Auth/Auth.constants' import EnableExtensionModal from 'components/interfaces/Database/Extensions/EnableExtensionModal' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { getDatabaseCronJob } from 'data/database-cron-jobs/database-cron-job-query' import { useDatabaseCronJobCreateMutation } from 'data/database-cron-jobs/database-cron-jobs-create-mutation' @@ -19,6 +18,7 @@ import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-ex import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Form_Shadcn_, @@ -201,7 +201,7 @@ export const CreateCronJobSheet = ({ setIsClosing, onClose, }: CreateCronJobSheetProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: org } = useSelectedOrganizationQuery() const [searchQuery] = useQueryState('search', parseAsString.withDefault('')) const [isLoadingGetCronJob, setIsLoadingGetCronJob] = useState(false) diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobScheduleSection.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobScheduleSection.tsx index 813d94eecf9..eb5ba948104 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobScheduleSection.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobScheduleSection.tsx @@ -3,9 +3,9 @@ import { useEffect, useState } from 'react' import { UseFormReturn } from 'react-hook-form' import { useDebounce } from 'use-debounce' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useSqlCronGenerateMutation } from 'data/ai/sql-cron-mutation' import { useCronTimezoneQuery } from 'data/database-cron-jobs/database-cron-timezone-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Accordion_Shadcn_, AccordionContent_Shadcn_, @@ -33,7 +33,7 @@ interface CronJobScheduleSectionProps { } export const CronJobScheduleSection = ({ form, supportsSeconds }: CronJobScheduleSectionProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [inputValue, setInputValue] = useState('') const [debouncedValue] = useDebounce(inputValue, 750) diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx index b8c55cfddde..61dc269bffd 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/CronJobsTab.tsx @@ -6,7 +6,6 @@ import DataGrid, { DataGridHandle, Row } from 'react-data-grid' import { useParams } from 'common' import { CreateCronJobSheet } from 'components/interfaces/Integrations/CronJobs/CreateCronJobSheet' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useCronJobsCountQuery } from 'data/database-cron-jobs/database-cron-jobs-count-query' @@ -17,6 +16,7 @@ import { import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { isAtBottom } from 'lib/helpers' import { Button, cn, LoadingLine, Sheet, SheetContent } from 'ui' import { Input } from 'ui-patterns/DataInputs/Input' @@ -28,7 +28,7 @@ const EMPTY_CRON_JOB = { jobname: '', schedule: '', active: true, command: '' } export const CronjobsTab = () => { const router = useRouter() const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: org } = useSelectedOrganizationQuery() const xScroll = useRef(0) diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/DeleteCronJob.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/DeleteCronJob.tsx index 1aeb18f7b56..bfe269faf99 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/DeleteCronJob.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/DeleteCronJob.tsx @@ -1,11 +1,11 @@ import { parseAsString, useQueryState } from 'nuqs' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseCronJobDeleteMutation } from 'data/database-cron-jobs/database-cron-jobs-delete-mutation' import { CronJob } from 'data/database-cron-jobs/database-cron-jobs-infinite-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' @@ -16,7 +16,7 @@ interface DeleteCronJobProps { } export const DeleteCronJob = ({ cronJob, visible, onClose }: DeleteCronJobProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: org } = useSelectedOrganizationQuery() const [searchQuery] = useQueryState('search', parseAsString.withDefault('')) diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/EdgeFunctionSection.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/EdgeFunctionSection.tsx index 4f4148ff620..6883555c086 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/EdgeFunctionSection.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/EdgeFunctionSection.tsx @@ -2,8 +2,8 @@ import Link from 'next/link' import { UseFormReturn } from 'react-hook-form' import { useParams } from 'common/hooks' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useEffect, useMemo } from 'react' import { Button, @@ -35,7 +35,7 @@ const buildFunctionUrl = (slug: string, projectRef: string, restUrl?: string) => export const EdgeFunctionSection = ({ form }: HTTPRequestFieldsProps) => { const { ref } = useParams() - const { project: selectedProject } = useProjectContext() + const { data: selectedProject } = useSelectedProjectQuery() const { data: functions, isSuccess, isLoading } = useEdgeFunctionsQuery({ projectRef: ref }) const edgeFunctions = useMemo(() => functions ?? [], [functions]) diff --git a/apps/studio/components/interfaces/Integrations/CronJobs/PreviousRunsTab.tsx b/apps/studio/components/interfaces/Integrations/CronJobs/PreviousRunsTab.tsx index 64f3a709000..a4e94a4612a 100644 --- a/apps/studio/components/interfaces/Integrations/CronJobs/PreviousRunsTab.tsx +++ b/apps/studio/components/interfaces/Integrations/CronJobs/PreviousRunsTab.tsx @@ -5,7 +5,6 @@ import { UIEvent, useCallback, useMemo } from 'react' import DataGrid, { Column, Row } from 'react-data-grid' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useCronJobQuery } from 'data/database-cron-jobs/database-cron-job-query' import { CronJobRun, @@ -13,6 +12,7 @@ import { } from 'data/database-cron-jobs/database-cron-jobs-runs-infinite-query' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' import dayjs from 'dayjs' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, cn, @@ -155,7 +155,7 @@ function isAtBottom({ currentTarget }: UIEvent): boolean { export const PreviousRunsTab = () => { const { childId } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const jobId = Number(childId) diff --git a/apps/studio/components/interfaces/Integrations/GraphQL/GraphiQLTab.tsx b/apps/studio/components/interfaces/Integrations/GraphQL/GraphiQLTab.tsx index a7d1b024d3f..5ea6f0cfb08 100644 --- a/apps/studio/components/interfaces/Integrations/GraphQL/GraphiQLTab.tsx +++ b/apps/studio/components/interfaces/Integrations/GraphQL/GraphiQLTab.tsx @@ -7,12 +7,12 @@ import { toast } from 'sonner' import { useParams } from 'common' import ExtensionCard from 'components/interfaces/Database/Extensions/ExtensionCard' import GraphiQL from 'components/interfaces/GraphQL/GraphiQL' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { Loading } from 'components/ui/Loading' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useSessionAccessTokenQuery } from 'data/auth/session-access-token-query' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { API_URL, IS_PLATFORM } from 'lib/constants' import { getRoleImpersonationJWT } from 'lib/role-impersonation' import { useGetImpersonatedRoleState } from 'state/role-impersonation-state' @@ -20,7 +20,7 @@ import { useGetImpersonatedRoleState } from 'state/role-impersonation-state' export const GraphiQLTab = () => { const { resolvedTheme } = useTheme() const { ref: projectRef } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const currentTheme = resolvedTheme?.includes('dark') ? 'dark' : 'light' const { data, isLoading: isExtensionsLoading } = useDatabaseExtensionsQuery({ diff --git a/apps/studio/components/interfaces/Integrations/Integration/IntegrationOverviewTab.tsx b/apps/studio/components/interfaces/Integrations/Integration/IntegrationOverviewTab.tsx index cd4ce834f2b..cdedd52cfc1 100644 --- a/apps/studio/components/interfaces/Integrations/Integration/IntegrationOverviewTab.tsx +++ b/apps/studio/components/interfaces/Integrations/Integration/IntegrationOverviewTab.tsx @@ -4,7 +4,7 @@ import { PropsWithChildren, ReactNode } from 'react' import { useParams } from 'common' import { Markdown } from 'components/interfaces/Markdown' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, Separator } from 'ui' import { Admonition } from 'ui-patterns/admonition' import { INTEGRATIONS } from '../Landing/Integrations.constants' @@ -22,7 +22,7 @@ export const IntegrationOverviewTab = ({ }: PropsWithChildren) => { const { id } = useParams() const router = useRouter() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const integration = INTEGRATIONS.find((i) => i.id === id) diff --git a/apps/studio/components/interfaces/Integrations/Landing/IntegrationCard.tsx b/apps/studio/components/interfaces/Integrations/Landing/IntegrationCard.tsx index ddb7cd0e690..0f1cf568bc3 100644 --- a/apps/studio/components/interfaces/Integrations/Landing/IntegrationCard.tsx +++ b/apps/studio/components/interfaces/Integrations/Landing/IntegrationCard.tsx @@ -1,7 +1,7 @@ import { BadgeCheck } from 'lucide-react' import Link from 'next/link' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, cn } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' import { IntegrationDefinition } from './Integrations.constants' @@ -39,7 +39,7 @@ export const IntegrationCard = ({ description, isInstalled, }: IntegrationCardProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() return ( diff --git a/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx b/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx index 6ba86da73ac..9df420f1b13 100644 --- a/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx +++ b/apps/studio/components/interfaces/Integrations/Landing/useInstalledIntegrations.tsx @@ -3,13 +3,13 @@ import { useMemo } from 'react' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useSchemasQuery } from 'data/database/schemas-query' import { useFDWsQuery } from 'data/fdw/fdws-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { EMPTY_ARR } from 'lib/void' import { wrapperMetaComparator } from '../Wrappers/Wrappers.utils' import { INTEGRATIONS } from './Integrations.constants' export const useInstalledIntegrations = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data, diff --git a/apps/studio/components/interfaces/Integrations/Queues/CreateQueueSheet.tsx b/apps/studio/components/interfaces/Integrations/Queues/CreateQueueSheet.tsx index bf6e367fe45..d09f681b645 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/CreateQueueSheet.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/CreateQueueSheet.tsx @@ -4,10 +4,11 @@ import { toast } from 'sonner' import z from 'zod' import { Markdown } from 'components/interfaces/Markdown' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useDatabaseQueueCreateMutation } from 'data/database-queues/database-queues-create-mutation' import { useQueuesExposePostgrestStatusQuery } from 'data/database-queues/database-queues-expose-postgrest-status-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { useRouter } from 'next/router' import { Badge, Button, @@ -29,7 +30,6 @@ import { Admonition } from 'ui-patterns' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { QUEUE_TYPES } from './Queues.constants' -import { useRouter } from 'next/router' export interface CreateQueueSheetProps { isClosing: boolean @@ -79,7 +79,7 @@ export const CreateQueueSheet = ({ isClosing, setIsClosing, onClose }: CreateQue // 'extensions' // ) const router = useRouter() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: isExposed } = useQueuesExposePostgrestStatusQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/Integrations/Queues/OverviewTab.tsx b/apps/studio/components/interfaces/Integrations/Queues/OverviewTab.tsx index dba1d510846..4189e9287f7 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/OverviewTab.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/OverviewTab.tsx @@ -1,6 +1,6 @@ import { useParams } from 'common' import { useQueuesExposePostgrestStatusQuery } from 'data/database-queues/database-queues-expose-postgrest-status-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import Link from 'next/link' import { Button } from 'ui' import { Admonition } from 'ui-patterns' @@ -8,7 +8,7 @@ import { IntegrationOverviewTab } from '../Integration/IntegrationOverviewTab' export const QueuesOverviewTab = () => { const { ref } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: isExposed } = useQueuesExposePostgrestStatusQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/Integrations/Queues/QueueTab.tsx b/apps/studio/components/interfaces/Integrations/Queues/QueueTab.tsx index 53a53ae4888..f595ec0faa0 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/QueueTab.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/QueueTab.tsx @@ -12,13 +12,13 @@ import { QueueFilters } from 'components/interfaces/Integrations/Queues/SingleQu import { QueueSettings } from 'components/interfaces/Integrations/Queues/SingleQueue/QueueSettings' import { SendMessageModal } from 'components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal' import { Markdown } from 'components/interfaces/Markdown' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' import { useQueueMessagesInfiniteQuery } from 'data/database-queues/database-queue-messages-infinite-query' import { useQueuesExposePostgrestStatusQuery } from 'data/database-queues/database-queues-expose-postgrest-status-query' import { useTableUpdateMutation } from 'data/tables/table-update-mutation' import { useTablesQuery } from 'data/tables/tables-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, cn, @@ -33,7 +33,7 @@ import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' export const QueueTab = () => { const { childId: queueName, ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [openRlsPopover, setOpenRlsPopover] = useState(false) const [rlsConfirmModalOpen, setRlsConfirmModalOpen] = useState(false) diff --git a/apps/studio/components/interfaces/Integrations/Queues/QueuesRows.tsx b/apps/studio/components/interfaces/Integrations/Queues/QueuesRows.tsx index 852512632b5..bcb03caec59 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/QueuesRows.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/QueuesRows.tsx @@ -3,11 +3,11 @@ import { includes, sortBy } from 'lodash' import { Check, ChevronRight, Loader2, X } from 'lucide-react' import { useRouter } from 'next/router' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import { useQueuesMetricsQuery } from 'data/database-queues/database-queues-metrics-query' import { PostgresQueue } from 'data/database-queues/database-queues-query' import { useTablesQuery } from 'data/tables/tables-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { DATETIME_FORMAT } from 'lib/constants' interface QueuesRowsProps { @@ -17,7 +17,7 @@ interface QueuesRowsProps { const QueueRow = ({ queue }: { queue: PostgresQueue }) => { const router = useRouter() - const { project: selectedProject } = useProjectContext() + const { data: selectedProject } = useSelectedProjectQuery() const { data: queueTables } = useTablesQuery({ projectRef: selectedProject?.ref, diff --git a/apps/studio/components/interfaces/Integrations/Queues/QueuesSettings.tsx b/apps/studio/components/interfaces/Integrations/Queues/QueuesSettings.tsx index e5ceebe670a..a1ce96787c7 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/QueuesSettings.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/QueuesSettings.tsx @@ -22,7 +22,7 @@ import { import { useTableUpdateMutation } from 'data/tables/table-update-mutation' import { useTablesQuery } from 'data/tables/tables-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Form_Shadcn_, @@ -38,7 +38,7 @@ import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' // [Joshen] Not convinced with the UI and layout but getting the functionality out first export const QueuesSettings = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const canUpdatePostgrestConfig = useCheckPermissions( PermissionAction.UPDATE, 'custom_config_postgrest' diff --git a/apps/studio/components/interfaces/Integrations/Queues/QueuesTab.tsx b/apps/studio/components/interfaces/Integrations/Queues/QueuesTab.tsx index d3f3b3461fc..f3be8b1f782 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/QueuesTab.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/QueuesTab.tsx @@ -2,17 +2,17 @@ import { Search } from 'lucide-react' import { useQueryState } from 'nuqs' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useQueuesQuery } from 'data/database-queues/database-queues-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Input, Sheet, SheetContent } from 'ui' import { CreateQueueSheet } from './CreateQueueSheet' import { QueuesRows } from './QueuesRows' export const QueuesTab = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() // used for confirmation prompt in the Create Queue Sheet const [isClosingCreateQueueSheet, setIsClosingCreateQueueSheet] = useState(false) diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/DeleteQueue.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/DeleteQueue.tsx index 109dd4835b0..f572987e5ee 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/DeleteQueue.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/DeleteQueue.tsx @@ -1,8 +1,8 @@ import { useRouter } from 'next/router' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseQueueDeleteMutation } from 'data/database-queues/database-queues-delete-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' interface DeleteQueueProps { @@ -12,8 +12,8 @@ interface DeleteQueueProps { } const DeleteQueue = ({ queueName, visible, onClose }: DeleteQueueProps) => { - const { project } = useProjectContext() const router = useRouter() + const { data: project } = useSelectedProjectQuery() const { mutate: deleteDatabaseQueue, isLoading } = useDatabaseQueueDeleteMutation({ onSuccess: () => { diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/MessageDetailsPanel.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/MessageDetailsPanel.tsx index bc137f9d186..fd60f528330 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/MessageDetailsPanel.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/MessageDetailsPanel.tsx @@ -11,7 +11,7 @@ import { useDatabaseQueueMessageDeleteMutation } from 'data/database-queues/data import { PostgresQueueMessage } from 'data/database-queues/database-queue-messages-infinite-query' import { useDatabaseQueueMessageReadMutation } from 'data/database-queues/database-queue-messages-read-mutation' import dayjs from 'dayjs' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { prettifyJSON } from 'lib/helpers' import { Button, @@ -48,7 +48,7 @@ export const MessageDetailsPanel = ({ setSelectedMessage, }: MessageDetailsPanelProps) => { const { id: _id, childId: queueName } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() useEscapeKeydown(() => setSelectedMessage(null)) diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/PurgeQueue.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/PurgeQueue.tsx index 5743748e97a..b7c9ad924a9 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/PurgeQueue.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/PurgeQueue.tsx @@ -1,8 +1,8 @@ import { useRouter } from 'next/router' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseQueuePurgeMutation } from 'data/database-queues/database-queues-purge-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' interface PurgeQueueProps { @@ -12,8 +12,8 @@ interface PurgeQueueProps { } const PurgeQueue = ({ queueName, visible, onClose }: PurgeQueueProps) => { - const { project } = useProjectContext() const router = useRouter() + const { data: project } = useSelectedProjectQuery() const { mutate: purgeDatabaseQueue, isLoading } = useDatabaseQueuePurgeMutation({ onSuccess: () => { diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueSettings.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueSettings.tsx index 10420dc8667..14154c46689 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueSettings.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/QueueSettings.tsx @@ -19,7 +19,7 @@ import { useTablePrivilegesRevokeMutation, } from 'data/privileges/table-privileges-revoke-mutation' import { useTablesQuery } from 'data/tables/tables-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Sheet, @@ -53,7 +53,7 @@ interface QueueSettingsProps {} export const QueueSettings = ({}: QueueSettingsProps) => { const { childId: name } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const [open, setOpen] = useState(false) const [isSaving, setIsSaving] = useState(false) diff --git a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal.tsx b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal.tsx index af38654151a..713b36031dc 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/SingleQueue/SendMessageModal.tsx @@ -3,9 +3,9 @@ import { SubmitHandler, useForm } from 'react-hook-form' import z from 'zod' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import CodeEditor from 'components/ui/CodeEditor/CodeEditor' import { useDatabaseQueueMessageSendMutation } from 'data/database-queues/database-queue-messages-send-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useEffect } from 'react' import { toast } from 'sonner' import { Form_Shadcn_, FormControl_Shadcn_, FormField_Shadcn_, Input, Modal } from 'ui' @@ -38,7 +38,7 @@ const FORM_ID = 'QUEUES_SEND_MESSAGE_FORM' export const SendMessageModal = ({ visible, onClose }: SendMessageModalProps) => { const { childId: queueName } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const form = useForm({ resolver: zodResolver(FormSchema), defaultValues: { diff --git a/apps/studio/components/interfaces/Integrations/Queues/UpgradeDatabaseAlert.tsx b/apps/studio/components/interfaces/Integrations/Queues/UpgradeDatabaseAlert.tsx index c624aae72c8..fcabbb76d85 100644 --- a/apps/studio/components/interfaces/Integrations/Queues/UpgradeDatabaseAlert.tsx +++ b/apps/studio/components/interfaces/Integrations/Queues/UpgradeDatabaseAlert.tsx @@ -1,6 +1,6 @@ import Link from 'next/link' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button } from 'ui' import { Admonition } from 'ui-patterns/admonition' @@ -9,7 +9,7 @@ interface UpgradeDatabaseAlertProps { } export const UpgradeDatabaseAlert = ({ minimumVersion = '15.6' }: UpgradeDatabaseAlertProps) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() return ( { + const { data: project } = useSelectedProjectQuery() const [showSecretValue, setShowSecretValue] = useState(false) - const { project } = useProjectContext() const { mutateAsync: addSecret } = useVaultSecretCreateMutation() diff --git a/apps/studio/components/interfaces/Integrations/Vault/Secrets/DeleteSecretModal.tsx b/apps/studio/components/interfaces/Integrations/Vault/Secrets/DeleteSecretModal.tsx index c918cc9c8e2..ca1c36b0f1f 100644 --- a/apps/studio/components/interfaces/Integrations/Vault/Secrets/DeleteSecretModal.tsx +++ b/apps/studio/components/interfaces/Integrations/Vault/Secrets/DeleteSecretModal.tsx @@ -1,7 +1,7 @@ import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useVaultSecretDeleteMutation } from 'data/vault/vault-secret-delete-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { VaultSecret } from 'types' import { Modal } from 'ui' @@ -11,7 +11,7 @@ interface DeleteSecretModalProps { } const DeleteSecretModal = ({ selectedSecret, onClose }: DeleteSecretModalProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: deleteSecret, isLoading: isDeleting } = useVaultSecretDeleteMutation({ onSuccess: () => { toast.success(`Successfully deleted secret ${selectedSecret?.name}`) diff --git a/apps/studio/components/interfaces/Integrations/Vault/Secrets/EditSecretModal.tsx b/apps/studio/components/interfaces/Integrations/Vault/Secrets/EditSecretModal.tsx index 5c19268657a..02bc97521dd 100644 --- a/apps/studio/components/interfaces/Integrations/Vault/Secrets/EditSecretModal.tsx +++ b/apps/studio/components/interfaces/Integrations/Vault/Secrets/EditSecretModal.tsx @@ -1,14 +1,14 @@ import { isEmpty } from 'lodash' +import { Eye, EyeOff } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query' import { useVaultSecretUpdateMutation } from 'data/vault/vault-secret-update-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { VaultSecret } from 'types' import { Button, Form, Input, Modal } from 'ui' -import { EyeOff, Eye } from 'lucide-react' interface EditSecretModalProps { selectedSecret: VaultSecret | undefined @@ -16,8 +16,8 @@ interface EditSecretModalProps { } const EditSecretModal = ({ selectedSecret, onClose }: EditSecretModalProps) => { + const { data: project } = useSelectedProjectQuery() const [showSecretValue, setShowSecretValue] = useState(false) - const { project } = useProjectContext() const { mutateAsync: updateSecret } = useVaultSecretUpdateMutation() diff --git a/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretRow.tsx b/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretRow.tsx index f62dac4d194..f7b1f5719ff 100644 --- a/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretRow.tsx +++ b/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretRow.tsx @@ -1,7 +1,6 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import dayjs from 'dayjs' -import Link from 'next/link' import { useState } from 'react' import { Button, @@ -15,9 +14,9 @@ import { TooltipTrigger, } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Edit3, Eye, EyeOff, Key, Loader, MoreVertical, Trash } from 'lucide-react' import type { VaultSecret } from 'types' @@ -29,7 +28,7 @@ interface SecretRowProps { const SecretRow = ({ secret, onSelectEdit, onSelectRemove }: SecretRowProps) => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [revealSecret, setRevealSecret] = useState(false) const name = secret?.name ?? 'No name provided' diff --git a/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretsManagement.tsx b/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretsManagement.tsx index 47a7262ee50..8484346130f 100644 --- a/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretsManagement.tsx +++ b/apps/studio/components/interfaces/Integrations/Vault/Secrets/SecretsManagement.tsx @@ -4,11 +4,11 @@ import { Loader, Search, X } from 'lucide-react' import { Fragment, useEffect, useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { DocsButton } from 'components/ui/DocsButton' import { useVaultSecretsQuery } from 'data/vault/vault-secrets-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { VaultSecret } from 'types' import { Button, Input, Listbox, Separator } from 'ui' import AddNewSecretModal from './AddNewSecretModal' @@ -18,7 +18,7 @@ import SecretRow from './SecretRow' export const SecretsManagement = () => { const { search } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [searchValue, setSearchValue] = useState('') const [selectedSort, setSelectedSort] = useState<'updated_at' | 'name'>('updated_at') diff --git a/apps/studio/components/interfaces/Integrations/VercelGithub/IntegrationConnection.tsx b/apps/studio/components/interfaces/Integrations/VercelGithub/IntegrationConnection.tsx index a89becda650..b036d5976e7 100644 --- a/apps/studio/components/interfaces/Integrations/VercelGithub/IntegrationConnection.tsx +++ b/apps/studio/components/interfaces/Integrations/VercelGithub/IntegrationConnection.tsx @@ -12,6 +12,7 @@ import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useIntegrationsVercelConnectionSyncEnvsMutation } from 'data/integrations/integrations-vercel-connection-sync-envs-mutation' import type { IntegrationProjectConnection } from 'data/integrations/integrations.types' import { useProjectsQuery } from 'data/projects/projects-query' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, DropdownMenu, @@ -21,7 +22,6 @@ import { DropdownMenuTrigger, } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' interface IntegrationConnectionItemProps extends IntegrationConnectionProps { disabled?: boolean @@ -31,7 +31,7 @@ interface IntegrationConnectionItemProps extends IntegrationConnectionProps { const IntegrationConnectionItem = forwardRef( ({ disabled, onDeleteConnection, ...props }, ref) => { const router = useRouter() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { type, connection } = props const { data: projects } = useProjectsQuery() diff --git a/apps/studio/components/interfaces/Integrations/VercelGithub/ProjectLinker.tsx b/apps/studio/components/interfaces/Integrations/VercelGithub/ProjectLinker.tsx index 01fac072c7e..8a3569fa3d4 100644 --- a/apps/studio/components/interfaces/Integrations/VercelGithub/ProjectLinker.tsx +++ b/apps/studio/components/interfaces/Integrations/VercelGithub/ProjectLinker.tsx @@ -8,7 +8,7 @@ import { IntegrationConnectionsCreateVariables, IntegrationProjectConnection, } from 'data/integrations/integrations.types' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH } from 'lib/constants' import { openInstallGitHubIntegrationWindow } from 'lib/github' import { EMPTY_ARR } from 'lib/void' @@ -83,7 +83,7 @@ const ProjectLinker = ({ const supabaseProjectsComboBoxRef = useRef(null) const foreignProjectsComboBoxRef = useRef(null) - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const [supabaseProjectRef, setSupabaseProjectRef] = useState( defaultSupabaseProjectRef diff --git a/apps/studio/components/interfaces/Integrations/Webhooks/OverviewTab.tsx b/apps/studio/components/interfaces/Integrations/Webhooks/OverviewTab.tsx index e8b2ec79869..949180c05e8 100644 --- a/apps/studio/components/interfaces/Integrations/Webhooks/OverviewTab.tsx +++ b/apps/studio/components/interfaces/Integrations/Webhooks/OverviewTab.tsx @@ -2,19 +2,19 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import NoPermission from 'components/ui/NoPermission' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useHooksEnableMutation } from 'data/database/hooks-enable-mutation' import { useSchemasQuery } from 'data/database/schemas-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Admonition } from 'ui-patterns' import { IntegrationOverviewTab } from '../Integration/IntegrationOverviewTab' export const WebhooksOverviewTab = () => { - const { project } = useProjectContext() const { ref: projectRef } = useParams() + const { data: project } = useSelectedProjectQuery() const { data: schemas, diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/CreateIcebergWrapperSheet.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/CreateIcebergWrapperSheet.tsx index 9d22737a437..ab68c698cbc 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/CreateIcebergWrapperSheet.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/CreateIcebergWrapperSheet.tsx @@ -2,13 +2,13 @@ import { isEmpty } from 'lodash' import { useMemo, useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { useSchemaCreateMutation } from 'data/database/schema-create-mutation' import { useSchemasQuery } from 'data/database/schemas-query' import { useFDWCreateMutation } from 'data/fdw/fdw-create-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Form, @@ -62,8 +62,8 @@ export const CreateIcebergWrapperSheet = ({ setIsClosing, onClose, }: CreateWrapperSheetProps) => { - const { project } = useProjectContext() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() const [selectedTarget, setSelectedTarget] = useState('S3Tables') diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx index 54cd8ce1247..a2c7e0de25e 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/CreateWrapperSheet.tsx @@ -4,14 +4,14 @@ import { Edit, Trash } from 'lucide-react' import { useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useSchemaCreateMutation } from 'data/database/schema-create-mutation' import { invalidateSchemasQuery, useSchemasQuery } from 'data/database/schemas-query' import { useFDWCreateMutation } from 'data/fdw/fdw-create-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Form, @@ -47,8 +47,8 @@ export const CreateWrapperSheet = ({ }: CreateWrapperSheetProps) => { const queryClient = useQueryClient() - const { project } = useProjectContext() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() const [newTables, setNewTables] = useState([]) diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/DeleteWrapperModal.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/DeleteWrapperModal.tsx index ad70ed7ca21..afae20cee6c 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/DeleteWrapperModal.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/DeleteWrapperModal.tsx @@ -1,9 +1,9 @@ import { toast } from 'sonner' import { Modal } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useFDWDeleteMutation } from 'data/fdw/fdw-delete-mutation' import type { FDW } from 'data/fdw/fdws-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { getWrapperMetaForWrapper } from './Wrappers.utils' interface DeleteWrapperModalProps { @@ -12,7 +12,7 @@ interface DeleteWrapperModalProps { } const DeleteWrapperModal = ({ selectedWrapper, onClose }: DeleteWrapperModalProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: deleteFDW, isLoading: isDeleting } = useFDWDeleteMutation({ onSuccess: () => { toast.success(`Successfully disabled ${selectedWrapper?.name} foreign data wrapper`) diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/EditWrapperSheet.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/EditWrapperSheet.tsx index 041c2c518b9..1f4ff376537 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/EditWrapperSheet.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/EditWrapperSheet.tsx @@ -4,13 +4,13 @@ import { Edit, Trash } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { invalidateSchemasQuery } from 'data/database/schemas-query' import { useFDWUpdateMutation } from 'data/fdw/fdw-update-mutation' import { FDW } from 'data/fdw/fdws-query' import { getDecryptedValue } from 'data/vault/vault-secret-decrypted-value-query' import { useVaultSecretsQuery } from 'data/vault/vault-secrets-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Form, Input, SheetFooter, SheetHeader, SheetTitle } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import InputField from './InputField' @@ -41,7 +41,7 @@ export const EditWrapperSheet = ({ onClose, }: EditWrapperSheetProps) => { const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: secrets, isLoading: isSecretsLoading } = useVaultSecretsQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/OverviewTab.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/OverviewTab.tsx index 0e7cc5fe4df..f9ab42c19eb 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/OverviewTab.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/OverviewTab.tsx @@ -3,10 +3,10 @@ import Link from 'next/link' import { useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Alert_Shadcn_, AlertDescription_Shadcn_, @@ -24,7 +24,7 @@ import { WrapperTable } from './WrapperTable' export const WrapperOverviewTab = () => { const { id } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [createWrapperShown, setCreateWrapperShown] = useState(false) const [isClosingCreateWrapper, setisClosingCreateWrapper] = useState(false) const canCreateWrapper = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTable.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTable.tsx index 0e9fe095aaf..63bcb54f67a 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTable.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTable.tsx @@ -1,8 +1,8 @@ import { useMemo } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useFDWsQuery } from 'data/fdw/fdws-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Card, CardContent, @@ -23,7 +23,7 @@ interface WrapperTableProps { export const WrapperTable = ({ isLatest = false }: WrapperTableProps) => { const { id, ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const integration = INTEGRATIONS.find((i) => i.id === id) const { data } = useFDWsQuery({ diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTableEditor.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTableEditor.tsx index 8249e4737ea..92212d51b5f 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTableEditor.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/WrapperTableEditor.tsx @@ -2,7 +2,6 @@ import { Check, ChevronsUpDown, Database, Plus } from 'lucide-react' import { useEffect, useState } from 'react' import ActionBar from 'components/interfaces/TableGridEditor/SidePanelEditor/ActionBar' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useSchemasQuery } from 'data/database/schemas-query' import { @@ -28,6 +27,7 @@ import { import WrapperDynamicColumns from './WrapperDynamicColumns' import type { Table, TableOption } from './Wrappers.types' import { makeValidateRequired } from './Wrappers.utils' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' export type WrapperTableEditorProps = { visible: boolean @@ -216,7 +216,7 @@ const TableForm = ({ onSubmit: OnSubmitFn initialData: any }) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: schemas, isLoading, diff --git a/apps/studio/components/interfaces/Integrations/Wrappers/WrappersTab.tsx b/apps/studio/components/interfaces/Integrations/Wrappers/WrappersTab.tsx index 42b2eee1c13..f7367a370cc 100644 --- a/apps/studio/components/interfaces/Integrations/Wrappers/WrappersTab.tsx +++ b/apps/studio/components/interfaces/Integrations/Wrappers/WrappersTab.tsx @@ -2,10 +2,10 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { HTMLProps, ReactNode, useCallback, useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { FDW, useFDWsQuery } from 'data/fdw/fdws-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Sheet, SheetContent } from 'ui' import { CreateWrapperSheet } from './CreateWrapperSheet' import DeleteWrapperModal from './DeleteWrapperModal' @@ -15,7 +15,7 @@ import { WrapperTable } from './WrapperTable' export const WrappersTab = () => { const { id } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [selectedWrapperForDelete, setSelectedWrapperForDelete] = useState(null) const [createWrapperShown, setCreateWrapperShown] = useState(false) const [isClosingCreateWrapper, setisClosingCreateWrapper] = useState(false) diff --git a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx index 368b1d68388..ec3ee6d475f 100644 --- a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx +++ b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/index.tsx @@ -4,7 +4,6 @@ import { useMemo, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useLegacyAPIKeysStatusQuery } from 'data/api-keys/legacy-api-keys-status-query' import { useJWTSigningKeyDeleteMutation } from 'data/jwt-signing-keys/jwt-signing-key-delete-mutation' @@ -12,6 +11,7 @@ import { useJWTSigningKeyUpdateMutation } from 'data/jwt-signing-keys/jwt-signin import { JWTSigningKey, useJWTSigningKeysQuery } from 'data/jwt-signing-keys/jwt-signing-keys-query' import { useLegacyJWTSigningKeyCreateMutation } from 'data/jwt-signing-keys/legacy-jwt-signing-key-create-mutation' import { useLegacyJWTSigningKeyQuery } from 'data/jwt-signing-keys/legacy-jwt-signing-key-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useFlag } from 'hooks/ui/useFlag' import { AlertDialog, @@ -50,7 +50,7 @@ type DialogType = 'legacy' | 'create' | 'rotate' | 'key-details' | 'revoke' | 'd export default function JWTSecretKeysTable() { const { ref: projectRef } = useParams() - const { project, isLoading: isProjectLoading } = useProjectContext() + const { data: project, isLoading: isProjectLoading } = useSelectedProjectQuery() const newJwtSecrets = useFlag('newJwtSecrets') diff --git a/apps/studio/components/interfaces/LogDrains/LogDrains.tsx b/apps/studio/components/interfaces/LogDrains/LogDrains.tsx index f7009bbeaee..04c42ba4b81 100644 --- a/apps/studio/components/interfaces/LogDrains/LogDrains.tsx +++ b/apps/studio/components/interfaces/LogDrains/LogDrains.tsx @@ -10,7 +10,7 @@ import Panel from 'components/ui/Panel' import { useDeleteLogDrainMutation } from 'data/log-drains/delete-log-drain-mutation' import { LogDrainData, useLogDrainsQuery } from 'data/log-drains/log-drains-query' import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, DropdownMenu, @@ -35,7 +35,7 @@ export function LogDrains({ onNewDrainClick: (src: LogDrainType) => void onUpdateDrainClick: (drain: LogDrainData) => void }) { - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { isLoading: orgPlanLoading, plan } = useCurrentOrgPlan() const logDrainsEnabled = !orgPlanLoading && (plan?.id === 'team' || plan?.id === 'enterprise') diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx index 778dd9933ed..9584fd770d9 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx @@ -22,7 +22,7 @@ import { useAsyncCheckProjectPermissions, useCheckPermissions, } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { FormMessage_Shadcn_, Input_Shadcn_ } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { InfoTooltip } from 'ui-patterns/info-tooltip' @@ -41,7 +41,7 @@ const formSchema = z.object({ const BillingEmail = () => { const { slug } = useParams() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { name, billing_email } = selectedOrganization ?? {} diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx index 6a942301803..b705417e487 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx @@ -6,7 +6,7 @@ import { } from 'components/layouts/Scaffold' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { cn } from 'ui' import InvoicesSection from '../InvoicesSettings/InvoicesSection' import BillingBreakdown from './BillingBreakdown/BillingBreakdown' @@ -30,7 +30,7 @@ export const BillingSettings = () => { 'billing:invoices', ]) - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: org?.slug }) const isNotOrgWithPartnerBilling = !subscription?.billing_via_partner diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/PaymentMethods.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/PaymentMethods.tsx index 93e42b96b51..4b57b1f89f7 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/PaymentMethods.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/PaymentMethods/PaymentMethods.tsx @@ -23,7 +23,7 @@ import { useAsyncCheckProjectPermissions, useCheckPermissions, } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { getURL } from 'lib/helpers' import { Alert, Button } from 'ui' import ChangePaymentMethodModal from './ChangePaymentMethodModal' @@ -32,7 +32,7 @@ import DeletePaymentMethodModal from './DeletePaymentMethodModal' const PaymentMethods = () => { const { slug } = useParams() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const [selectedMethodForUse, setSelectedMethodForUse] = useState() const [selectedMethodToDelete, setSelectedMethodToDelete] = useState() const [showAddPaymentMethodModal, setShowAddPaymentMethodModal] = useState(false) diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Restriction.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Restriction.tsx index 93eaf26e1b0..a072b253996 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Restriction.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Restriction.tsx @@ -2,16 +2,22 @@ import dayjs from 'dayjs' import { ExternalLink } from 'lucide-react' import Link from 'next/link' -import { useOrgUsageQuery } from 'data/usage/org-usage-query' -import { VIOLATION_TYPE_LABELS } from 'data/usage/constants' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui' -import { CriticalIcon, WarningIcon } from 'ui' import { PricingMetric } from 'data/analytics/org-daily-stats-query' +import { VIOLATION_TYPE_LABELS } from 'data/usage/constants' +import { useOrgUsageQuery } from 'data/usage/org-usage-query' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { usePathname } from 'next/navigation' +import { + AlertDescription_Shadcn_, + AlertTitle_Shadcn_, + Alert_Shadcn_, + Button, + CriticalIcon, + WarningIcon, +} from 'ui' export const Restriction = () => { - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { data: usage, isSuccess: isSuccessOrgUsage } = useOrgUsageQuery({ orgSlug: org?.slug }) const pathname = usePathname() diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx index b775173a3c8..28ee8a2848e 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PaymentMethodSelection.tsx @@ -1,3 +1,8 @@ +import HCaptcha from '@hcaptcha/react-hcaptcha' +import { Elements } from '@stripe/react-stripe-js' +import { loadStripe, PaymentMethod, StripeElementsOptions } from '@stripe/stripe-js' +import { Loader, Plus } from 'lucide-react' +import { useTheme } from 'next-themes' import { forwardRef, useCallback, @@ -8,30 +13,23 @@ import { useState, } from 'react' import { toast } from 'sonner' -import { useOrganizationPaymentMethodsQuery } from 'data/organizations/organization-payment-methods-query' -import { - useSelectedOrganization, - useSelectedOrganizationQuery, -} from 'hooks/misc/useSelectedOrganization' -import { BASE_PATH, STRIPE_PUBLIC_KEY } from 'lib/constants' -import { Loader, Plus } from 'lucide-react' -import { Checkbox_Shadcn_, Listbox } from 'ui' -import HCaptcha from '@hcaptcha/react-hcaptcha' -import { useOrganizationPaymentMethodSetupIntent } from 'data/organizations/organization-payment-method-setup-intent-mutation' -import { SetupIntentResponse } from 'data/stripe/setup-intent-mutation' -import { loadStripe, PaymentMethod, StripeElementsOptions } from '@stripe/stripe-js' + +import { useParams } from 'common' import { getStripeElementsAppearanceOptions } from 'components/interfaces/Billing/Payment/Payment.utils' -import { useTheme } from 'next-themes' -import { Elements } from '@stripe/react-stripe-js' +import { useOrganizationCustomerProfileQuery } from 'data/organizations/organization-customer-profile-query' +import { useOrganizationPaymentMethodSetupIntent } from 'data/organizations/organization-payment-method-setup-intent-mutation' +import { useOrganizationPaymentMethodsQuery } from 'data/organizations/organization-payment-methods-query' +import { useOrganizationTaxIdQuery } from 'data/organizations/organization-tax-id-query' +import { SetupIntentResponse } from 'data/stripe/setup-intent-mutation' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useFlag } from 'hooks/ui/useFlag' +import { BASE_PATH, STRIPE_PUBLIC_KEY } from 'lib/constants' +import { Checkbox_Shadcn_, Listbox } from 'ui' +import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' import { NewPaymentMethodElement, type PaymentMethodElementRef, } from '../PaymentMethods/NewPaymentMethodElement' -import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' -import { useFlag } from 'hooks/ui/useFlag' -import { useOrganizationCustomerProfileQuery } from 'data/organizations/organization-customer-profile-query' -import { useOrganizationTaxIdQuery } from 'data/organizations/organization-tax-id-query' -import { useParams } from 'common' const stripePromise = loadStripe(STRIPE_PUBLIC_KEY) diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx index e8c1082ff4e..4059c82a682 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx @@ -4,6 +4,7 @@ import { Check, ExternalLink } from 'lucide-react' import { useRouter } from 'next/router' import { useEffect, useRef, useState } from 'react' +import { useParams } from 'common' import { StudioPricingSidePanelOpenedEvent } from 'common/telemetry-constants' import { getPlanChangeType } from 'components/interfaces/Billing/Subscription/Subscription.utils' import { ButtonTooltip } from 'components/ui/ButtonTooltip' @@ -18,10 +19,7 @@ import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-que import type { OrgPlan } from 'data/subscriptions/types' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { - useSelectedOrganization, - useSelectedOrganizationQuery, -} from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { formatCurrency } from 'lib/helpers' import { pickFeatures, pickFooter, plans as subscriptionsPlans } from 'shared-data/plans' import { useOrgSettingsPageStateSnapshot } from 'state/organization-settings' @@ -29,7 +27,6 @@ import { Button, SidePanel, cn } from 'ui' import DowngradeModal from './DowngradeModal' import { EnterpriseCard } from './EnterpriseCard' import { ExitSurveyModal } from './ExitSurveyModal' -import { useParams } from 'common' import MembersExceedLimitModal from './MembersExceedLimitModal' import { SubscriptionPlanUpdateDialog } from './SubscriptionPlanUpdateDialog' import UpgradeSurveyModal from './UpgradeModal' diff --git a/apps/studio/components/interfaces/Organization/Documents/SOC2.tsx b/apps/studio/components/interfaces/Organization/Documents/SOC2.tsx index 4e37ad5d597..a484b8f7887 100644 --- a/apps/studio/components/interfaces/Organization/Documents/SOC2.tsx +++ b/apps/studio/components/interfaces/Organization/Documents/SOC2.tsx @@ -12,12 +12,12 @@ import { import NoPermission from 'components/ui/NoPermission' import { getDocument } from 'data/documents/document-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' const SOC2 = () => { - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const slug = organization?.slug const canReadSubscriptions = useCheckPermissions( PermissionAction.BILLING_READ, diff --git a/apps/studio/components/interfaces/Organization/Documents/SecurityQuestionnaire.tsx b/apps/studio/components/interfaces/Organization/Documents/SecurityQuestionnaire.tsx index 1cf3dfbc831..7535133dc0e 100644 --- a/apps/studio/components/interfaces/Organization/Documents/SecurityQuestionnaire.tsx +++ b/apps/studio/components/interfaces/Organization/Documents/SecurityQuestionnaire.tsx @@ -12,10 +12,10 @@ import { import NoPermission from 'components/ui/NoPermission' import { getDocument } from 'data/documents/document-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' const SecurityQuestionnaire = () => { - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const slug = organization?.slug const canReadSubscriptions = useCheckPermissions( PermissionAction.BILLING_READ, diff --git a/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx b/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx index d0c2d51407f..de767135a0b 100644 --- a/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx +++ b/apps/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx @@ -7,12 +7,12 @@ import { LOCAL_STORAGE_KEYS } from 'common' import { useOrganizationDeleteMutation } from 'data/organizations/organization-delete-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, Form, Input, Modal } from 'ui' export const DeleteOrganizationButton = () => { const router = useRouter() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { slug: orgSlug, name: orgName } = selectedOrganization ?? {} const [isOpen, setIsOpen] = useState(false) diff --git a/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDeletePanel.tsx b/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDeletePanel.tsx index dc878869f72..c963d1006c5 100644 --- a/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDeletePanel.tsx +++ b/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDeletePanel.tsx @@ -1,11 +1,11 @@ import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold' import PartnerManagedResource from 'components/ui/PartnerManagedResource' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Admonition } from 'ui-patterns' import { DeleteOrganizationButton } from './DeleteOrganizationButton' const OrganizationDeletePanel = () => { - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() return ( diff --git a/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDetailsForm.tsx b/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDetailsForm.tsx index b264df89b00..72858b0761f 100644 --- a/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDetailsForm.tsx +++ b/apps/studio/components/interfaces/Organization/GeneralSettings/OrganizationDetailsForm.tsx @@ -12,7 +12,7 @@ import { FormActions } from 'components/ui/Forms/FormActions' import { useOrganizationUpdateMutation } from 'data/organizations/organization-update-mutation' import { invalidateOrganizationsQuery } from 'data/organizations/organizations-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { ResponseError } from 'types' import { Card, @@ -33,7 +33,7 @@ const OrgDetailsSchema = z.object({ export const OrganizationDetailsForm = () => { const { slug } = useParams() const queryClient = useQueryClient() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const canUpdateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') const { mutate: updateOrganization, isLoading: isUpdatingDetails } = diff --git a/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx b/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx index 5cd1f00d766..57e01183719 100644 --- a/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx +++ b/apps/studio/components/interfaces/Organization/IntegrationSettings/IntegrationSettings.tsx @@ -20,16 +20,16 @@ import { useGitHubConnectionDeleteMutation } from 'data/integrations/github-conn import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' import type { IntegrationProjectConnection } from 'data/integrations/integrations.types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH } from 'lib/constants' import { GITHUB_INTEGRATION_INSTALLATION_URL, GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL, } from 'lib/github' +import { useRouter } from 'next/router' import { useSidePanelsStateSnapshot } from 'state/side-panels' import { IntegrationConnectionItem } from '../../Integrations/VercelGithub/IntegrationConnection' import SidePanelVercelProjectLinker from './SidePanelVercelProjectLinker' -import { useRouter } from 'next/router' const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => { return ( @@ -42,8 +42,8 @@ const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => { } const IntegrationSettings = () => { - const org = useSelectedOrganization() const router = useRouter() + const { data: org } = useSelectedOrganizationQuery() const canReadGithubConnection = useCheckPermissions( PermissionAction.READ, diff --git a/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx b/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx index e710f0b5245..717c20edd60 100644 --- a/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx +++ b/apps/studio/components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker.tsx @@ -13,7 +13,7 @@ import { useOrgIntegrationsQuery } from 'data/integrations/integrations-query-or import { useIntegrationVercelConnectionsCreateMutation } from 'data/integrations/integrations-vercel-connections-create-mutation' import { useVercelProjectsQuery } from 'data/integrations/integrations-vercel-projects-query' import { useProjectsQuery } from 'data/projects/projects-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH } from 'lib/constants' import { EMPTY_ARR } from 'lib/void' import { useSidePanelsStateSnapshot } from 'state/side-panels' @@ -27,7 +27,7 @@ const VERCEL_ICON = ( const SidePanelVercelProjectLinker = () => { const { ref } = useParams() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const sidePanelStateSnapshot = useSidePanelsStateSnapshot() const organizationIntegrationId = sidePanelStateSnapshot.vercelConnectionsIntegrationId diff --git a/apps/studio/components/interfaces/Organization/SecuritySettings/SecuritySettings.tsx b/apps/studio/components/interfaces/Organization/SecuritySettings/SecuritySettings.tsx index 076e8ded568..e4934a603f2 100644 --- a/apps/studio/components/interfaces/Organization/SecuritySettings/SecuritySettings.tsx +++ b/apps/studio/components/interfaces/Organization/SecuritySettings/SecuritySettings.tsx @@ -17,7 +17,7 @@ import { useOrganizationMfaToggleMutation } from 'data/organizations/organizatio import { useOrganizationMfaQuery } from 'data/organizations/organization-mfa-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useProfile } from 'lib/profile' import { Alert_Shadcn_, @@ -45,7 +45,7 @@ const schema = z.object({ const SecuritySettings = () => { const { slug } = useParams() const { profile } = useProfile() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { data: members } = useOrganizationMembersQuery({ slug }) const canReadMfaConfig = useCheckPermissions(PermissionAction.READ, 'organizations') const canUpdateMfaConfig = useCheckPermissions(PermissionAction.UPDATE, 'organizations') diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx index ddbbc6cac15..35e10d24095 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx @@ -17,7 +17,7 @@ import { useProjectsQuery } from 'data/projects/projects-query' import { useHasAccessToProjectLevelPermissions } from 'data/subscriptions/org-subscription-query' import { doPermissionsCheck, useGetPermissions } from 'hooks/misc/useCheckPermissions' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useProfile } from 'lib/profile' import { Button, @@ -56,7 +56,7 @@ import { useGetRolesManagementPermissions } from './TeamSettings.utils' export const InviteMemberButton = () => { const { slug } = useParams() const { profile } = useProfile() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const { permissions: permissions } = useGetPermissions() const { organizationMembersCreate: organizationMembersCreationEnabled } = useIsFeatureEnabled([ diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/LeaveTeamButton.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/LeaveTeamButton.tsx index ed13b59e375..8249c8bbddd 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/LeaveTeamButton.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/LeaveTeamButton.tsx @@ -10,7 +10,7 @@ import { useOrganizationMembersQuery } from 'data/organizations/organization-mem import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useProfile } from 'lib/profile' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { hasMultipleOwners } from './TeamSettings.utils' @@ -19,7 +19,7 @@ export const LeaveTeamButton = () => { const router = useRouter() const { slug } = useParams() const { profile } = useProfile() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() // if organizationMembersDeletionEnabled is false, you also can't delete yourself const { organizationMembersDelete: organizationMembersDeletionEnabled } = useIsFeatureEnabled([ diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx index 068c517764d..ea047d76d18 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/MemberRow.tsx @@ -7,7 +7,7 @@ import { ProfileImage } from 'components/ui/ProfileImage' import { useOrganizationRolesV2Query } from 'data/organization-members/organization-roles-query' import { OrganizationMember } from 'data/organizations/organization-members-query' import { useProjectsQuery } from 'data/projects/projects-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { getGitHubProfileImgUrl } from 'lib/github' import { useProfile } from 'lib/profile' import { @@ -32,7 +32,7 @@ const MEMBER_ORIGIN_TO_MANAGED_BY = { export const MemberRow = ({ member }: MemberRowProps) => { const { profile } = useProfile() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { data: projects } = useProjectsQuery() const { data: roles, isLoading: isLoadingRoles } = useOrganizationRolesV2Query({ diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx index 246dfd391d0..711fe647580 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesConfirmationModal.tsx @@ -14,7 +14,7 @@ import { import { organizationKeys as organizationKeysV1 } from 'data/organizations/keys' import { OrganizationMember } from 'data/organizations/organization-members-query' import { useProjectsQuery } from 'data/projects/projects-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { ProjectRoleConfiguration, @@ -38,7 +38,7 @@ export const UpdateRolesConfirmationModal = ({ }: UpdateRolesConfirmationModal) => { const { slug } = useParams() const queryClient = useQueryClient() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const { data: projects } = useProjectsQuery() const { data: allRoles } = useOrganizationRolesV2Query({ slug: organization?.slug }) diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesPanel.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesPanel.tsx index 186beb2ea4d..57d0fd6f9eb 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesPanel.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/UpdateRolesPanel/UpdateRolesPanel.tsx @@ -10,7 +10,7 @@ import { OrganizationMember } from 'data/organizations/organization-members-quer import { usePermissionsQuery } from 'data/permissions/permissions-query' import { useProjectsQuery } from 'data/projects/projects-query' import { useHasAccessToProjectLevelPermissions } from 'data/subscriptions/org-subscription-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -58,7 +58,7 @@ interface UpdateRolesPanelProps { export const UpdateRolesPanel = ({ visible, member, onClose }: UpdateRolesPanelProps) => { const { slug } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const isOptedIntoProjectLevelPermissions = useHasAccessToProjectLevelPermissions(slug as string) const { data: projects } = useProjectsQuery() diff --git a/apps/studio/components/interfaces/Organization/Usage/Usage.tsx b/apps/studio/components/interfaces/Organization/Usage/Usage.tsx index 4ec02427c22..93796f2623e 100644 --- a/apps/studio/components/interfaces/Organization/Usage/Usage.tsx +++ b/apps/studio/components/interfaces/Organization/Usage/Usage.tsx @@ -16,7 +16,7 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useProjectsQuery } from 'data/projects/projects-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { TIME_PERIODS_BILLING, TIME_PERIODS_REPORTS } from 'lib/constants/metrics' import { cn, Listbox } from 'ui' import { Admonition } from 'ui-patterns' @@ -37,7 +37,7 @@ const Usage = () => { 'stripe.subscriptions' ) - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const { data: projects, isSuccess } = useProjectsQuery() const { data: subscription, diff --git a/apps/studio/components/interfaces/ProjectCreation/PostgresVersionSelector.tsx b/apps/studio/components/interfaces/ProjectCreation/PostgresVersionSelector.tsx index ea6f34e69ae..46aeca4c5e9 100644 --- a/apps/studio/components/interfaces/ProjectCreation/PostgresVersionSelector.tsx +++ b/apps/studio/components/interfaces/ProjectCreation/PostgresVersionSelector.tsx @@ -1,10 +1,10 @@ import { useEffect } from 'react' import { ControllerRenderProps, UseFormReturn } from 'react-hook-form' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useProjectCreationPostgresVersionsQuery } from 'data/config/project-creation-postgres-versions-query' import { useProjectUnpausePostgresVersionsQuery } from 'data/config/project-unpause-postgres-versions-query' import { PostgresEngine, ReleaseChannel } from 'data/projects/new-project.constants' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { CloudProvider } from 'shared-data' import { Badge, @@ -62,7 +62,7 @@ export const PostgresVersionSelector = ({ layout = 'horizontal', label = 'Postgres Version', }: PostgresVersionSelectorProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: createVersions, diff --git a/apps/studio/components/interfaces/QueryPerformance/EnableIndexAdvisorButton.tsx b/apps/studio/components/interfaces/QueryPerformance/EnableIndexAdvisorButton.tsx index 74c4b26ffd0..cf87f0da2a6 100644 --- a/apps/studio/components/interfaces/QueryPerformance/EnableIndexAdvisorButton.tsx +++ b/apps/studio/components/interfaces/QueryPerformance/EnableIndexAdvisorButton.tsx @@ -2,9 +2,9 @@ import { useState } from 'react' import { toast } from 'sonner' import { useIndexAdvisorStatus } from 'components/interfaces/QueryPerformance/hooks/useIsIndexAdvisorStatus' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseExtensionEnableMutation } from 'data/database-extensions/database-extension-enable-mutation' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDialog, AlertDialogAction, @@ -25,7 +25,7 @@ import { import { getIndexAdvisorExtensions } from './index-advisor.utils' export const EnableIndexAdvisorButton = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { isIndexAdvisorAvailable, isIndexAdvisorEnabled } = useIndexAdvisorStatus() diff --git a/apps/studio/components/interfaces/QueryPerformance/IndexAdvisorDisabledState.tsx b/apps/studio/components/interfaces/QueryPerformance/IndexAdvisorDisabledState.tsx index 62f3955956e..0a567b1c96d 100644 --- a/apps/studio/components/interfaces/QueryPerformance/IndexAdvisorDisabledState.tsx +++ b/apps/studio/components/interfaces/QueryPerformance/IndexAdvisorDisabledState.tsx @@ -2,17 +2,17 @@ import Link from 'next/link' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import { useDatabaseExtensionEnableMutation } from 'data/database-extensions/database-extension-enable-mutation' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' -import { getIndexAdvisorExtensions } from './index-advisor.utils' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui' import { Markdown } from '../Markdown' +import { getIndexAdvisorExtensions } from './index-advisor.utils' export const IndexAdvisorDisabledState = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: extensions } = useDatabaseExtensionsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/QueryPerformance/IndexSuggestionIcon.tsx b/apps/studio/components/interfaces/QueryPerformance/IndexSuggestionIcon.tsx index cf5163492b2..7ecc5975359 100644 --- a/apps/studio/components/interfaces/QueryPerformance/IndexSuggestionIcon.tsx +++ b/apps/studio/components/interfaces/QueryPerformance/IndexSuggestionIcon.tsx @@ -1,8 +1,8 @@ import { Loader2 } from 'lucide-react' import { MouseEvent, useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { GetIndexAdvisorResultResponse } from 'data/database/retrieve-index-advisor-result-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, cn, @@ -27,7 +27,7 @@ export const IndexSuggestionIcon = ({ indexAdvisorResult, onClickIcon, }: IndexSuggestionIconProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isCreatingIndex, setIsCreatingIndex] = useState(false) const [isHoverCardOpen, setIsHoverCardOpen] = useState(false) diff --git a/apps/studio/components/interfaces/QueryPerformance/QueryIndexes.tsx b/apps/studio/components/interfaces/QueryPerformance/QueryIndexes.tsx index 4730e3d2c5b..3ad1f99c133 100644 --- a/apps/studio/components/interfaces/QueryPerformance/QueryIndexes.tsx +++ b/apps/studio/components/interfaces/QueryPerformance/QueryIndexes.tsx @@ -3,11 +3,11 @@ import { useState } from 'react' import { AccordionTrigger } from '@ui/components/shadcn/ui/accordion' import { useIndexAdvisorStatus } from 'components/interfaces/QueryPerformance/hooks/useIsIndexAdvisorStatus' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useGetIndexAdvisorResult } from 'data/database/retrieve-index-advisor-result-query' import { useGetIndexesFromSelectQuery } from 'data/database/retrieve-index-from-select-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AccordionContent_Shadcn_, AccordionItem_Shadcn_, @@ -39,7 +39,7 @@ interface QueryIndexesProps { export const QueryIndexes = ({ selectedRow }: QueryIndexesProps) => { // [Joshen] TODO implement this logic once the linter rules are in const isLinterWarning = false - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [showStartupCosts, setShowStartupCosts] = useState(false) const [isExecuting, setIsExecuting] = useState(false) diff --git a/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx b/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx index b48872a14d3..a7272f278e3 100644 --- a/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx +++ b/apps/studio/components/interfaces/QueryPerformance/QueryPerformance.tsx @@ -5,12 +5,12 @@ import { useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' import { LOCAL_STORAGE_KEYS, useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { formatDatabaseID } from 'data/read-replicas/replicas.utils' import { executeSql } from 'data/sql/execute-sql-query' import { DbQueryHook } from 'hooks/analytics/useDbQuery' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { IS_PLATFORM } from 'lib/constants' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' import { @@ -43,7 +43,7 @@ export const QueryPerformance = ({ queryPerformanceQuery, }: QueryPerformanceProps) => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const state = useDatabaseSelectorStateSnapshot() const [{ preset }, setSearchParams] = useQueryStates({ diff --git a/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx b/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx index c233ce7f2c8..3112bb46f06 100644 --- a/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx +++ b/apps/studio/components/interfaces/QueryPerformance/QueryPerformanceFilterBar.tsx @@ -3,12 +3,12 @@ import { useRouter } from 'next/router' import { useState } from 'react' import { LOCAL_STORAGE_KEYS, useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DownloadResultsButton } from 'components/ui/DownloadResultsButton' import { FilterPopover } from 'components/ui/FilterPopover' import { useDatabaseRolesQuery } from 'data/database-roles/database-roles-query' import { DbQueryHook } from 'hooks/analytics/useDbQuery' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, DropdownMenu, @@ -29,7 +29,7 @@ export const QueryPerformanceFilterBar = ({ }) => { const router = useRouter() const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [showBottomSection] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.QUERY_PERF_SHOW_BOTTOM_SECTION, true diff --git a/apps/studio/components/interfaces/QueryPerformance/hooks/useIndexInvalidation.ts b/apps/studio/components/interfaces/QueryPerformance/hooks/useIndexInvalidation.ts index af87f833277..edea843039e 100644 --- a/apps/studio/components/interfaces/QueryPerformance/hooks/useIndexInvalidation.ts +++ b/apps/studio/components/interfaces/QueryPerformance/hooks/useIndexInvalidation.ts @@ -7,9 +7,9 @@ import { QueryPerformanceSort, useQueryPerformanceQuery, } from 'components/interfaces/Reports/Reports.queries' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { databaseIndexesKeys } from 'data/database-indexes/keys' import { databaseKeys } from 'data/database/keys' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { QUERY_PERFORMANCE_PRESET_MAP, QUERY_PERFORMANCE_REPORT_TYPES, @@ -19,7 +19,7 @@ import { useIndexAdvisorStatus } from './useIsIndexAdvisorStatus' export function useIndexInvalidation() { const router = useRouter() const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { isIndexAdvisorEnabled } = useIndexAdvisorStatus() const [{ preset: urlPreset, search: searchQuery, order, sort }] = useQueryStates({ diff --git a/apps/studio/components/interfaces/QueryPerformance/hooks/useIsIndexAdvisorStatus.ts b/apps/studio/components/interfaces/QueryPerformance/hooks/useIsIndexAdvisorStatus.ts index 0b326289a3c..5775541954b 100644 --- a/apps/studio/components/interfaces/QueryPerformance/hooks/useIsIndexAdvisorStatus.ts +++ b/apps/studio/components/interfaces/QueryPerformance/hooks/useIsIndexAdvisorStatus.ts @@ -1,6 +1,6 @@ import { getIndexAdvisorExtensions } from 'components/interfaces/QueryPerformance/index-advisor.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' /** * Hook to get both index advisor availability and enabled status @@ -9,7 +9,7 @@ import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-ex * enabled if the index_advisor and hypopg extensions are installed (their versions are not null) */ export function useIndexAdvisorStatus() { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: extensions } = useDatabaseExtensionsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/Realtime/Inspector/ChooseChannelPopover/index.tsx b/apps/studio/components/interfaces/Realtime/Inspector/ChooseChannelPopover/index.tsx index dccb5840b2f..e45ead06f10 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/ChooseChannelPopover/index.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/ChooseChannelPopover/index.tsx @@ -7,7 +7,7 @@ import * as z from 'zod' import { DocsButton } from 'components/ui/DocsButton' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, FormControl_Shadcn_, @@ -34,7 +34,7 @@ const FormSchema = z.object({ channel: z.string(), isPrivate: z.boolean() }) export const ChooseChannelPopover = ({ config, onChangeConfig }: ChooseChannelPopoverProps) => { const [open, setOpen] = useState(false) const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() const form = useForm>({ diff --git a/apps/studio/components/interfaces/Realtime/Inspector/Header.tsx b/apps/studio/components/interfaces/Realtime/Inspector/Header.tsx index 6645037ede1..d1bdff3faf3 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/Header.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/Header.tsx @@ -4,7 +4,7 @@ import { Dispatch, SetStateAction } from 'react' import { useParams } from 'common' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { ChooseChannelPopover } from './ChooseChannelPopover' import { RealtimeFilterPopover } from './RealtimeFilterPopover' import { RealtimeTokensPopover } from './RealtimeTokensPopover' @@ -18,7 +18,7 @@ interface HeaderProps { export const Header = ({ config, onChangeConfig }: HeaderProps) => { const { mutate: sendEvent } = useSendEventMutation() const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() return (
diff --git a/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx b/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx index 72d519dd7a3..4ac29213a72 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/MessageSelection.tsx @@ -4,7 +4,7 @@ import { useMemo } from 'react' import { useParams } from 'common' import CopyButton from 'components/ui/CopyButton' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, cn } from 'ui' import type { LogData } from './Messages.types' import { SelectedRealtimeMessagePanel } from './SelectedRealtimeMessagePanel' @@ -20,7 +20,7 @@ const MessageSelection = ({ log, onClose }: MessageSelectionProps) => { }, [log]) const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() return ( diff --git a/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx b/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx index bb2a21c889d..95fd72a350a 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/MessagesTable.tsx @@ -8,7 +8,7 @@ import { useParams } from 'common' import { DocsButton } from 'components/ui/DocsButton' import ShimmerLine from 'components/ui/ShimmerLine' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, IconBroadcast, IconDatabaseChanges, IconPresence, cn } from 'ui' import MessageSelection from './MessageSelection' import type { LogData } from './Messages.types' @@ -111,7 +111,7 @@ const MessagesTable = ({ const stringData = JSON.stringify(data) const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() useEffect(() => { diff --git a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/TableSelector.tsx b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/TableSelector.tsx index 4161433b7b8..af46d523278 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/TableSelector.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/TableSelector.tsx @@ -16,10 +16,10 @@ import { ScrollArea, } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useEntityTypesQuery } from 'data/entity-types/entity-types-infinite-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { debounce } from 'lodash' -import { Loader, Code, Check } from 'lucide-react' +import { Check, Code, Loader } from 'lucide-react' interface TableSelectorProps { className?: string @@ -40,7 +40,7 @@ const TableSelector = ({ }: TableSelectorProps) => { const [open, setOpen] = useState(false) const [initiallyLoaded, setInitiallyLoaded] = useState(false) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [searchInput, setSearchInput] = useState('') const { data, isLoading, isSuccess, isError, error, refetch } = useEntityTypesQuery({ diff --git a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/index.tsx b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/index.tsx index e9d6cbcca80..55f0fd2a566 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/index.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeFilterPopover/index.tsx @@ -4,7 +4,7 @@ import { Dispatch, SetStateAction, useState } from 'react' import { useParams } from 'common' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Badge, Button, @@ -34,7 +34,7 @@ export const RealtimeFilterPopover = ({ config, onChangeConfig }: RealtimeFilter const [tempConfig, setTempConfig] = useState(config) const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() const onOpen = (v: boolean) => { diff --git a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeTokensPopover/index.tsx b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeTokensPopover/index.tsx index cb6225cca9a..ef75536f4f4 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/RealtimeTokensPopover/index.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/RealtimeTokensPopover/index.tsx @@ -7,7 +7,7 @@ import { InlineLink } from 'components/ui/InlineLink' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import { getRoleImpersonationJWT } from 'lib/role-impersonation' import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state' @@ -20,7 +20,7 @@ interface RealtimeTokensPopoverProps { export const RealtimeTokensPopover = ({ config, onChangeConfig }: RealtimeTokensPopoverProps) => { const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const snap = useRoleImpersonationStateSnapshot() const { data: apiKeys } = useAPIKeysQuery({ diff --git a/apps/studio/components/interfaces/Realtime/Inspector/index.tsx b/apps/studio/components/interfaces/Realtime/Inspector/index.tsx index 2b330efc327..f742ea955e3 100644 --- a/apps/studio/components/interfaces/Realtime/Inspector/index.tsx +++ b/apps/studio/components/interfaces/Realtime/Inspector/index.tsx @@ -2,18 +2,18 @@ import { useParams } from 'common' import { useState } from 'react' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Header } from './Header' import MessagesTable from './MessagesTable' import { SendMessageModal } from './SendMessageModal' import { RealtimeConfig, useRealtimeMessages } from './useRealtimeMessages' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' /** * Acts as a container component for the entire log display */ export const RealtimeInspector = () => { const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const [sendMessageShown, setSendMessageShown] = useState(false) const [realtimeConfig, setRealtimeConfig] = useState({ diff --git a/apps/studio/components/interfaces/Realtime/Policies.tsx b/apps/studio/components/interfaces/Realtime/Policies.tsx index 56a17b589f8..cffdf03c235 100644 --- a/apps/studio/components/interfaces/Realtime/Policies.tsx +++ b/apps/studio/components/interfaces/Realtime/Policies.tsx @@ -1,16 +1,16 @@ import { PostgresPolicy } from '@supabase/postgres-meta' import { useState } from 'react' -import { PolicyEditorPanel } from 'components/interfaces/Auth/Policies/PolicyEditorPanel' import Policies from 'components/interfaces/Auth/Policies/Policies' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import { PolicyEditorPanel } from 'components/interfaces/Auth/Policies/PolicyEditorPanel' import AlertError from 'components/ui/AlertError' import { FormHeader } from 'components/ui/Forms/FormHeader' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useTablesQuery } from 'data/tables/tables-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' export const RealtimePolicies = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [showPolicyEditor, setShowPolicyEditor] = useState(false) const [selectedPolicyToEdit, setSelectedPolicyToEdit] = useState() diff --git a/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx b/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx index 4553a4ee9a1..a9e9e2c861e 100644 --- a/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx +++ b/apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx @@ -7,7 +7,6 @@ import { toast } from 'sonner' import * as z from 'zod' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldSection } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' @@ -20,7 +19,8 @@ import { useRealtimeConfigurationQuery, } from 'data/realtime/realtime-config-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Card, @@ -40,8 +40,8 @@ const formId = 'realtime-configuration-form' export const RealtimeSettings = () => { const { ref: projectRef } = useParams() - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const canUpdateConfig = useCheckPermissions(PermissionAction.REALTIME_ADMIN_READ, '*') const { data: maxConn } = useMaxConnectionsQuery({ diff --git a/apps/studio/components/interfaces/Reports/CreateReportModal.tsx b/apps/studio/components/interfaces/Reports/CreateReportModal.tsx index 22b4ec79af8..2980543610e 100644 --- a/apps/studio/components/interfaces/Reports/CreateReportModal.tsx +++ b/apps/studio/components/interfaces/Reports/CreateReportModal.tsx @@ -3,7 +3,7 @@ import { useMemo } from 'react' import { toast } from 'sonner' import { useContentUpsertMutation } from 'data/content/content-upsert-mutation' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' import { Button, Form, Input, Modal } from 'ui' @@ -18,7 +18,7 @@ export interface CreateReportModal { export const CreateReportModal = ({ visible, onCancel, afterSubmit }: CreateReportModal) => { const router = useRouter() const { profile } = useProfile() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const ref = project?.ref ?? 'default' // Preserve date range query parameters when navigating to new report diff --git a/apps/studio/components/interfaces/Reports/GridResize.tsx b/apps/studio/components/interfaces/Reports/GridResize.tsx index 8f126d91394..4283e1658e9 100644 --- a/apps/studio/components/interfaces/Reports/GridResize.tsx +++ b/apps/studio/components/interfaces/Reports/GridResize.tsx @@ -4,7 +4,6 @@ import 'react-resizable/css/styles.css' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DEFAULT_CHART_CONFIG } from 'components/ui/QueryBlock/QueryBlock' import { AnalyticsInterval } from 'data/analytics/constants' import { @@ -12,7 +11,8 @@ import { useContentUpsertMutation, } from 'data/content/content-upsert-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProfile } from 'lib/profile' import uuidv4 from 'lib/uuid' import { Dashboards } from 'types' @@ -54,8 +54,8 @@ export const GridResize = ({ }: GridResizeProps) => { const { ref } = useParams() const { profile } = useProfile() - const { project } = useProjectContext() - const selectedOrg = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() const { mutate: upsertContent } = useContentUpsertMutation() diff --git a/apps/studio/components/interfaces/Reports/MetricOptions.tsx b/apps/studio/components/interfaces/Reports/MetricOptions.tsx index fed79e7c292..53d39b157bc 100644 --- a/apps/studio/components/interfaces/Reports/MetricOptions.tsx +++ b/apps/studio/components/interfaces/Reports/MetricOptions.tsx @@ -6,7 +6,7 @@ import { useParams } from 'common' import { useContentQuery } from 'data/content/content-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Metric, METRIC_CATEGORIES, METRICS } from 'lib/constants/metrics' import { Dashboards } from 'types' import { @@ -39,7 +39,7 @@ interface MetricOptionsProps { export const MetricOptions = ({ config, handleChartSelection }: MetricOptionsProps) => { const { ref: projectRef } = useParams() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const [search, setSearch] = useState('') const { projectAuthAll: authEnabled, projectStorageAll: storageEnabled } = useIsFeatureEnabled([ diff --git a/apps/studio/components/interfaces/Reports/ReportChart.tsx b/apps/studio/components/interfaces/Reports/ReportChart.tsx index 9d5726fb889..41f9a8b4a2a 100644 --- a/apps/studio/components/interfaces/Reports/ReportChart.tsx +++ b/apps/studio/components/interfaces/Reports/ReportChart.tsx @@ -16,7 +16,7 @@ import LogChartHandler from 'components/ui/Charts/LogChartHandler' import Panel from 'components/ui/Panel' import { useFillTimeseriesSorted } from 'hooks/analytics/useFillTimeseriesSorted' import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useChartData } from 'hooks/useChartData' import type { UpdateDateRange } from 'pages/project/[ref]/reports/database' import { Button, cn } from 'ui' @@ -40,7 +40,7 @@ const ReportChart = ({ isLoading?: boolean className?: string }) => { - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { plan: orgPlan } = useCurrentOrgPlan() const orgPlanId = orgPlan?.id diff --git a/apps/studio/components/interfaces/Reports/Reports.tsx b/apps/studio/components/interfaces/Reports/Reports.tsx index ddc85aca621..044d4e73534 100644 --- a/apps/studio/components/interfaces/Reports/Reports.tsx +++ b/apps/studio/components/interfaces/Reports/Reports.tsx @@ -7,7 +7,6 @@ import { DragEvent, useEffect, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import DatabaseSelector from 'components/ui/DatabaseSelector' import { DateRangePicker } from 'components/ui/DateRangePicker' @@ -23,7 +22,8 @@ import { } from 'data/content/content-upsert-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Metric, TIME_PERIODS_REPORTS } from 'lib/constants/metrics' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' @@ -42,8 +42,8 @@ const DEFAULT_CHART_ROW_COUNT = 1 const Reports = () => { const { id, ref } = useParams() const { profile } = useProfile() - const { project } = useProjectContext() - const selectedOrg = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const queryClient = useQueryClient() const state = useDatabaseSelectorStateSnapshot() diff --git a/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx b/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx index d22edb156ce..befa9621cfb 100644 --- a/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx +++ b/apps/studio/components/interfaces/RoleImpersonationSelector/UserImpersonationSelector.tsx @@ -4,12 +4,12 @@ import { useMemo, useState } from 'react' import { toast } from 'sonner' import { LOCAL_STORAGE_KEYS, useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { InlineLink } from 'components/ui/InlineLink' import { User, useUsersInfiniteQuery } from 'data/auth/users-infinite-query' import { useCustomAccessTokenHookDetails } from 'hooks/misc/useCustomAccessTokenHookDetails' import { useLocalStorage } from 'hooks/misc/useLocalStorage' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state' import { ResponseError } from 'types' import { @@ -49,7 +49,7 @@ const UserImpersonationSelector = () => { const state = useRoleImpersonationStateSnapshot() const debouncedSearchText = useDebounce(searchText, 300) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data, isSuccess, isLoading, isError, error, isFetching, isPreviousData } = useUsersInfiniteQuery( diff --git a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx index f4316b09b04..59ea6403dc8 100644 --- a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx @@ -5,7 +5,7 @@ import { MutableRefObject, useEffect, useRef } from 'react' import { LOCAL_STORAGE_KEYS, useParams } from 'common' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProfile } from 'lib/profile' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' @@ -50,7 +50,7 @@ const MonacoEditor = ({ const router = useRouter() const { profile } = useProfile() const { ref, content } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const snapV2 = useSqlEditorV2StateSnapshot() const tabsSnap = useTabsStateSnapshot() diff --git a/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx b/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx index aaf067caba0..cd92098dd7a 100644 --- a/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx +++ b/apps/studio/components/interfaces/SQLEditor/OngoingQueriesPanel.tsx @@ -3,13 +3,15 @@ import { RefreshCw, StopCircle } from 'lucide-react' import { useEffect, useState } from 'react' import { toast } from 'sonner' +import { useParams } from 'common' import AlertError from 'components/ui/AlertError' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useQueryAbortMutation } from 'data/sql/abort-query-mutation' import { useOngoingQueriesQuery } from 'data/sql/ongoing-queries-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useUrlState } from 'hooks/ui/useUrlState' import { IS_PLATFORM } from 'lib/constants' +import { useAppStateSnapshot } from 'state/app-state' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' import { ResponseError } from 'types' import { @@ -27,13 +29,11 @@ import { cn, } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' -import { useAppStateSnapshot } from 'state/app-state' -import { useParams } from 'common' export const OngoingQueriesPanel = () => { const [_, setParams] = useUrlState({ replace: true }) const { viewOngoingQueries } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const state = useDatabaseSelectorStateSnapshot() const appState = useAppStateSnapshot() const [selectedId, setSelectedId] = useState() diff --git a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx index f06192a711d..4b0243cee09 100644 --- a/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx +++ b/apps/studio/components/interfaces/SQLEditor/RenameQueryModal.tsx @@ -12,7 +12,7 @@ import { import { Snippet } from 'data/content/sql-folders-query' import type { SqlSnippet } from 'data/content/sql-snippets-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' import { createTabId, useTabsStateSnapshot } from 'state/tabs' import { AiIconAnimation, Button, Form, Input, Modal } from 'ui' @@ -32,7 +32,7 @@ const RenameQueryModal = ({ onComplete, }: RenameQueryModalProps) => { const { ref } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const snapV2 = useSqlEditorV2StateSnapshot() const tabsSnap = useTabsStateSnapshot() diff --git a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx index 708e72eb52b..376abd4d2f7 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLEditor.tsx @@ -1,8 +1,7 @@ import type { Monaco } from '@monaco-editor/react' import { useQueryClient } from '@tanstack/react-query' import { useCompletion } from 'ai/react' -import { AnimatePresence, motion } from 'framer-motion' -import { ChevronUp, Command, Loader2 } from 'lucide-react' +import { ChevronUp, Loader2 } from 'lucide-react' import dynamic from 'next/dynamic' import { useRouter } from 'next/router' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -21,8 +20,8 @@ import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { isError } from 'data/utils/error-check' import { useOrgAiOptInLevel } from 'hooks/misc/useOrgOptedIntoAi' import { useSchemasForAi } from 'hooks/misc/useSchemasForAi' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { formatSql } from 'lib/formatSql' import { detectOS, uuidv4 } from 'lib/helpers' @@ -82,8 +81,8 @@ export const SQLEditor = () => { const { ref, id: urlId } = useParams() const { profile } = useProfile() - const project = useSelectedProject() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const queryClient = useQueryClient() const tabs = useTabsStateSnapshot() diff --git a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx index 49d4428342f..856b9295f85 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLQuickstarts.tsx @@ -8,8 +8,8 @@ import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries import { ActionCard } from 'components/layouts/Tabs/ActionCard' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' @@ -19,9 +19,9 @@ import { createSqlSnippetSkeletonV2 } from '../SQLEditor.utils' const SQLQuickstarts = () => { const router = useRouter() const { ref } = useParams() - const org = useSelectedOrganization() const { profile } = useProfile() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const [, quickStart] = partition(SQL_TEMPLATES, { type: 'template' }) const snapV2 = useSqlEditorV2StateSnapshot() diff --git a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx index 6ac7e907f49..fdb8549bb03 100644 --- a/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx +++ b/apps/studio/components/interfaces/SQLEditor/SQLTemplates/SQLTemplates.tsx @@ -5,11 +5,11 @@ import { toast } from 'sonner' import { useParams } from 'common' import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ActionCard } from 'components/layouts/Tabs/ActionCard' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' @@ -19,9 +19,9 @@ import { createSqlSnippetSkeletonV2 } from '../SQLEditor.utils' const SQLTemplates = () => { const router = useRouter() const { ref } = useParams() - const org = useSelectedOrganization() const { profile } = useProfile() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const [sql] = partition(SQL_TEMPLATES, { type: 'template' }) const snapV2 = useSqlEditorV2StateSnapshot() diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx index df4bd9d7292..e1554bca526 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityPanel.tsx @@ -5,7 +5,7 @@ import { DownloadResultsButton } from 'components/ui/DownloadResultsButton' import { useContentUpsertMutation } from 'data/content/content-upsert-mutation' import { Snippet } from 'data/content/sql-folders-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' import { TabsContent_Shadcn_, TabsList_Shadcn_, TabsTrigger_Shadcn_, Tabs_Shadcn_ } from 'ui' import { ChartConfig } from './ChartConfig' @@ -43,7 +43,7 @@ const UtilityPanel = ({ onDebug, }: UtilityPanelProps) => { const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const snapV2 = useSqlEditorV2StateSnapshot() const snippet = snapV2.snippets[id]?.snippet diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx index 2ba401c2127..12fc1bc9c63 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityTabResults.tsx @@ -6,9 +6,9 @@ import { useParams } from 'common' import { subscriptionHasHipaaAddon } from 'components/interfaces/Billing/Subscription/Subscription.utils' import CopyButton from 'components/ui/CopyButton' import { InlineLink, InlineLinkClassName } from 'components/ui/InlineLink' -import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' import { AiIconAnimation, Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' @@ -26,7 +26,7 @@ const UtilityTabResults = forwardRef( ({ id, isExecuting, isDisabled, isDebugging, onDebug }) => { const { ref } = useParams() const state = useDatabaseSelectorStateSnapshot() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const snapV2 = useSqlEditorV2StateSnapshot() const [, setShowConnect] = useQueryState('showConnect', parseAsBoolean.withDefault(false)) diff --git a/apps/studio/components/interfaces/SQLEditor/hooks.ts b/apps/studio/components/interfaces/SQLEditor/hooks.ts index 8c5550ca94a..bd1ac73fae7 100644 --- a/apps/studio/components/interfaces/SQLEditor/hooks.ts +++ b/apps/studio/components/interfaces/SQLEditor/hooks.ts @@ -4,8 +4,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' @@ -21,7 +21,7 @@ export const useNewQuery = () => { const router = useRouter() const { ref } = useParams() const { profile } = useProfile() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const snapV2 = useSqlEditorV2StateSnapshot() const canCreateSQLSnippet = useCheckPermissions(PermissionAction.CREATE, 'user_content', { diff --git a/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts b/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts index a3f770213eb..fe5a0e5e80a 100644 --- a/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts +++ b/apps/studio/components/interfaces/SQLEditor/useAddDefinitions.ts @@ -1,6 +1,8 @@ import { Monaco } from '@monaco-editor/react' +import { IDisposable } from 'monaco-editor' +import { useEffect, useRef } from 'react' + import { LOCAL_STORAGE_KEYS } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import getPgsqlCompletionProvider from 'components/ui/CodeEditor/Providers/PgSQLCompletionProvider' import getPgsqlSignatureHelpProvider from 'components/ui/CodeEditor/Providers/PgSQLSignatureHelpProvider' import { useDatabaseFunctionsQuery } from 'data/database-functions/database-functions-query' @@ -8,13 +10,12 @@ import { useKeywordsQuery } from 'data/database/keywords-query' import { useSchemasQuery } from 'data/database/schemas-query' import { useTableColumnsQuery } from 'data/database/table-columns-query' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { formatSql } from 'lib/formatSql' -import { IDisposable } from 'monaco-editor' -import { useEffect, useRef } from 'react' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' export const useAddDefinitions = (id: string, monaco: Monaco | null) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const snapV2 = useSqlEditorV2StateSnapshot() const [intellisenseEnabled] = useLocalStorageQuery( diff --git a/apps/studio/components/interfaces/Settings/API/HardenAPIModal.tsx b/apps/studio/components/interfaces/Settings/API/HardenAPIModal.tsx index 027786d1e67..dee54c4380b 100644 --- a/apps/studio/components/interfaces/Settings/API/HardenAPIModal.tsx +++ b/apps/studio/components/interfaces/Settings/API/HardenAPIModal.tsx @@ -8,7 +8,7 @@ import { useCreateAndExposeAPISchemaMutation } from 'data/api-settings/create-an import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' import { useProjectPostgrestConfigUpdateMutation } from 'data/config/project-postgrest-config-update-mutation' import { useSchemasQuery } from 'data/database/schemas-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -33,7 +33,7 @@ interface HardenAPIModalProps { } export const HardenAPIModal = ({ visible, onClose }: HardenAPIModalProps) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: schemas } = useSchemasQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx b/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx index a27a8a6096e..5285c0c7343 100644 --- a/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx +++ b/apps/studio/components/interfaces/Settings/API/PostgrestConfig.tsx @@ -9,7 +9,6 @@ import { toast } from 'sonner' import { z } from 'zod' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import { FormActions } from 'components/ui/Forms/FormActions' import { @@ -23,6 +22,7 @@ import { useProjectPostgrestConfigUpdateMutation } from 'data/config/project-pos import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' import { useSchemasQuery } from 'data/database/schemas-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -79,7 +79,7 @@ const formSchema = z export const PostgrestConfig = () => { const { ref: projectRef } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [showModal, setShowModal] = useState(false) diff --git a/apps/studio/components/interfaces/Settings/API/ServiceList.tsx b/apps/studio/components/interfaces/Settings/API/ServiceList.tsx index e76b3db209e..a12eb57794c 100644 --- a/apps/studio/components/interfaces/Settings/API/ServiceList.tsx +++ b/apps/studio/components/interfaces/Settings/API/ServiceList.tsx @@ -1,26 +1,21 @@ -import { useQueryClient } from '@tanstack/react-query' import { AlertCircle } from 'lucide-react' -import { useEffect, useRef } from 'react' -import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import DatabaseSelector from 'components/ui/DatabaseSelector' import Panel from 'components/ui/Panel' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' -import { configKeys } from 'data/config/keys' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' import { useLoadBalancersQuery } from 'data/read-replicas/load-balancers-query' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' import { Badge, Input } from 'ui' import { PostgrestConfig } from './PostgrestConfig' const ServiceList = () => { - const client = useQueryClient() - const { project, isLoading } = useProjectContext() - const { ref: projectRef, source } = useParams() + const { data: project, isLoading } = useSelectedProjectQuery() + const { ref: projectRef } = useParams() const state = useDatabaseSelectorStateSnapshot() const { data: customDomainData } = useCustomDomainsQuery({ projectRef }) diff --git a/apps/studio/components/interfaces/Settings/Addons/Addons.tsx b/apps/studio/components/interfaces/Settings/Addons/Addons.tsx index 74dc615cf2a..50cba0c77a5 100644 --- a/apps/studio/components/interfaces/Settings/Addons/Addons.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/Addons.tsx @@ -12,10 +12,7 @@ import { } from 'components/interfaces/Billing/Subscription/Subscription.utils' import { NoticeBar } from 'components/interfaces/DiskManagement/ui/NoticeBar' import ProjectUpdateDisabledTooltip from 'components/interfaces/Organization/BillingSettings/ProjectUpdateDisabledTooltip' -import { - useIsProjectActive, - useProjectContext, -} from 'components/layouts/ProjectLayout/ProjectContext' +import { useIsProjectActive } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldContainer, ScaffoldDivider, @@ -31,8 +28,12 @@ import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import type { ProjectAddonVariantMeta } from 'data/subscriptions/types' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useIsOrioleDbInAws, useProjectByRef } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { + useIsOrioleDbInAws, + useProjectByRefQuery, + useSelectedProjectQuery, +} from 'hooks/misc/useSelectedProject' import { useFlag } from 'hooks/ui/useFlag' import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils' import { BASE_PATH, INSTANCE_MICRO_SPECS, INSTANCE_NANO_SPECS } from 'lib/constants' @@ -48,13 +49,14 @@ const Addons = () => { const { resolvedTheme } = useTheme() const { ref: projectRef } = useParams() const { setPanel } = useAddonsPagePanel() - const selectedOrg = useSelectedOrganization() - const { project: selectedProject, isLoading: isLoadingProject } = useProjectContext() - const parentProject = useProjectByRef(selectedProject?.parent_project_ref) - const isBranch = parentProject !== undefined const isProjectActive = useIsProjectActive() const isOrioleDbInAws = useIsOrioleDbInAws() + const { data: selectedOrg } = useSelectedOrganizationQuery() + const { data: selectedProject, isLoading: isLoadingProject } = useSelectedProjectQuery() + const { data: parentProject } = useProjectByRefQuery(selectedProject?.parent_project_ref) + const isBranch = parentProject !== undefined + const { data: settings } = useProjectSettingsV2Query({ projectRef }) const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: selectedOrg?.slug }) diff --git a/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx index 940d5d36b1d..ba6ed51e6c3 100644 --- a/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx @@ -9,9 +9,10 @@ import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon- import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import type { AddonVariantId } from 'data/subscriptions/types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useFlag } from 'hooks/ui/useFlag' import { formatCurrency } from 'lib/helpers' +import { AlertCircle, ExternalLink } from 'lucide-react' import { useAddonsPagePanel } from 'state/addons-page' import { Alert, @@ -23,11 +24,10 @@ import { SidePanel, cn, } from 'ui' -import { ExternalLink, AlertCircle } from 'lucide-react' const CustomDomainSidePanel = () => { const { ref: projectRef } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const customDomainsDisabledDueToQuota = useFlag('customDomainsDisabledDueToQuota') const [selectedOption, setSelectedOption] = useState('cd_none') diff --git a/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx index fae1eb8662c..3aea5b7bdc6 100644 --- a/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/IPv4SidePanel.tsx @@ -11,7 +11,7 @@ import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon- import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import type { AddonVariantId } from 'data/subscriptions/types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useIsAwsCloudProvider } from 'hooks/misc/useSelectedProject' import { formatCurrency } from 'lib/helpers' import { useAddonsPagePanel } from 'state/addons-page' @@ -21,7 +21,7 @@ import { Admonition } from 'ui-patterns' const IPv4SidePanel = () => { const isAws = useIsAwsCloudProvider() const { ref: projectRef } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const [selectedOption, setSelectedOption] = useState('ipv4_none') diff --git a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx index 842f0f9d748..b60820f43b3 100644 --- a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx @@ -8,15 +8,14 @@ import { toast } from 'sonner' import { useParams } from 'common' import { subscriptionHasHipaaAddon } from 'components/interfaces/Billing/Subscription/Subscription.utils' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' -import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' 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 type { AddonVariantId } from 'data/subscriptions/types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { formatCurrency } from 'lib/helpers' import { useAddonsPagePanel } from 'state/addons-page' @@ -29,7 +28,6 @@ import { CriticalIcon, Radio, SidePanel, - WarningIcon, cn, } from 'ui' @@ -56,8 +54,8 @@ const PITR_CATEGORY_OPTIONS: { const PITRSidePanel = () => { const { ref: projectRef } = useParams() const { resolvedTheme } = useTheme() - const project = useSelectedProject() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const { data: projectSettings } = useProjectSettingsV2Query({ projectRef }) const [selectedCategory, setSelectedCategory] = useState<'on' | 'off'>('off') diff --git a/apps/studio/components/interfaces/Settings/Database/BannedIPs.tsx b/apps/studio/components/interfaces/Settings/Database/BannedIPs.tsx index cbc75a9970e..d38efacba8c 100644 --- a/apps/studio/components/interfaces/Settings/Database/BannedIPs.tsx +++ b/apps/studio/components/interfaces/Settings/Database/BannedIPs.tsx @@ -4,7 +4,6 @@ import { useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { DocsButton } from 'components/ui/DocsButton' @@ -14,12 +13,13 @@ import { useBannedIPsDeleteMutation } from 'data/banned-ips/banned-ips-delete-mu import { useBannedIPsQuery } from 'data/banned-ips/banned-ips-query' import { useUserIPAddressQuery } from 'data/misc/user-ip-address-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, Skeleton } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' const BannedIPs = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [selectedIPToUnban, setSelectedIPToUnban] = useState(null) // Track the selected IP for unban diff --git a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx index b9a95bb07fb..c993af5c00f 100644 --- a/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx +++ b/apps/studio/components/interfaces/Settings/Database/ConnectionPooling/ConnectionPooling.tsx @@ -7,7 +7,6 @@ import { toast } from 'sonner' import z from 'zod' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' import { setValueAsNullableNumber } from 'components/ui/Forms/Form.constants' @@ -20,6 +19,7 @@ import { usePgbouncerConfigurationUpdateMutation } from 'data/database/pgbouncer import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -48,7 +48,7 @@ const PoolingConfigurationFormSchema = z.object({ */ export const ConnectionPooling = () => { const { ref: projectRef } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: org } = useSelectedOrganizationQuery() const canUpdateConnectionPoolingConfiguration = useCheckPermissions( diff --git a/apps/studio/components/interfaces/Settings/Database/DatabaseReadOnlyAlert.tsx b/apps/studio/components/interfaces/Settings/Database/DatabaseReadOnlyAlert.tsx index 038df441a24..a5e4a9e7beb 100644 --- a/apps/studio/components/interfaces/Settings/Database/DatabaseReadOnlyAlert.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DatabaseReadOnlyAlert.tsx @@ -4,13 +4,13 @@ import Link from 'next/link' import { useState } from 'react' import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui' import ConfirmDisableReadOnlyModeModal from './DatabaseSettings/ConfirmDisableReadOnlyModal' export const DatabaseReadOnlyAlert = () => { const { ref: projectRef } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const [showConfirmationModal, setShowConfirmationModal] = useState(false) const { data: resourceWarnings } = useResourceWarningsQuery() diff --git a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx index 939ab6486cb..f3e4787a425 100644 --- a/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx @@ -4,15 +4,13 @@ import { useEffect, useRef, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { - useIsProjectActive, - useProjectContext, -} from 'components/layouts/ProjectLayout/ProjectContext' +import { useIsProjectActive } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import Panel from 'components/ui/Panel' import PasswordStrengthBar from 'components/ui/PasswordStrengthBar' import { useDatabasePasswordResetMutation } from 'data/database/database-password-reset-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { DEFAULT_MINIMUM_PASSWORD_STRENGTH } from 'lib/constants' import passwordStrength from 'lib/password-strength' import { generateStrongPassword } from 'lib/project' @@ -21,7 +19,7 @@ import { Button, Input, Modal } from 'ui' const ResetDbPassword = ({ disabled = false }) => { const { ref } = useParams() const isProjectActive = useIsProjectActive() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const canResetDbPassword = useCheckPermissions(PermissionAction.UPDATE, 'projects', { resource: { project_id: project?.id, diff --git a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx index 09da373613b..da6544a74b3 100644 --- a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx @@ -7,14 +7,14 @@ import { toast } from 'sonner' import { useParams } from 'common' import { Markdown } from 'components/interfaces/Markdown' import DiskSizeConfigurationModal from 'components/interfaces/Settings/Database/DiskSizeConfigurationModal' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { FormHeader } from 'components/ui/Forms/FormHeader' import Panel from 'components/ui/Panel' import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mutation' import { useDatabaseSizeQuery } from 'data/database/database-size-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useUrlState } from 'hooks/ui/useUrlState' import { formatBytes } from 'lib/helpers' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, InfoIcon } from 'ui' @@ -25,9 +25,8 @@ export interface DiskSizeConfigurationProps { const DiskSizeConfiguration = ({ disabled = false }: DiskSizeConfigurationProps) => { const { ref: projectRef } = useParams() - const { project } = useProjectContext() - - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const [{ show_increase_disk_size_modal }, setUrlParams] = useUrlState() const showIncreaseDiskSizeModal = show_increase_disk_size_modal === 'true' diff --git a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx index 5da9cc438e0..5e315cfa809 100644 --- a/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx +++ b/apps/studio/components/interfaces/Settings/Database/DiskSizeConfigurationModal.tsx @@ -7,10 +7,10 @@ import { toast } from 'sonner' import { number, object } from 'yup' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mutation' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -36,10 +36,10 @@ const DiskSizeConfigurationModal = ({ hideModal, }: DiskSizeConfigurationProps) => { const { ref: projectRef } = useParams() - const { project, isLoading: isLoadingProject } = useProjectContext() + const { data: organization } = useSelectedOrganizationQuery() + const { data: project, isLoading: isLoadingProject } = useSelectedProjectQuery() const { lastDatabaseResizeAt } = project ?? {} - const organization = useSelectedOrganization() const { data: projectSubscriptionData, isLoading: isLoadingSubscription } = useOrgSubscriptionQuery({ orgSlug: organization?.slug }, { enabled: visible }) diff --git a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx index dab32b15fd1..c03e52b884f 100644 --- a/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx +++ b/apps/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx @@ -3,7 +3,6 @@ import { AlertCircle, ChevronDown, Globe, Lock } from 'lucide-react' import { useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { DocsButton } from 'components/ui/DocsButton' import { FormHeader } from 'components/ui/Forms/FormHeader' @@ -12,6 +11,7 @@ import Panel from 'components/ui/Panel' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useNetworkRestrictionsQuery } from 'data/network-restrictions/network-restrictions-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, Button, @@ -68,7 +68,7 @@ const DisallowAllAccessButton = ({ disabled, onClick }: AccessButtonProps) => ( const NetworkRestrictions = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isAddingAddress, setIsAddingAddress] = useState() const [isAllowingAll, setIsAllowingAll] = useState(false) const [isDisallowingAll, setIsDisallowingAll] = useState(false) diff --git a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx index 9d65b35509b..1b5448d4ed9 100644 --- a/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx @@ -5,7 +5,6 @@ import { useEffect, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { DocsButton } from 'components/ui/DocsButton' import { FormHeader } from 'components/ui/Forms/FormHeader' @@ -15,10 +14,12 @@ import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query import { useSSLEnforcementQuery } from 'data/ssl-enforcement/ssl-enforcement-query' import { useSSLEnforcementUpdateMutation } from 'data/ssl-enforcement/ssl-enforcement-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Alert, Button, Switch, Tooltip, TooltipContent, TooltipTrigger } from 'ui' const SSLConfiguration = () => { const { ref } = useParams() + const { data: project } = useSelectedProjectQuery() const [isEnforced, setIsEnforced] = useState(false) const { data: settings } = useProjectSettingsV2Query({ projectRef: ref }) @@ -41,7 +42,6 @@ const SSLConfiguration = () => { } ) - const { project } = useProjectContext() const canUpdateSSLEnforcement = useCheckPermissions(PermissionAction.UPDATE, 'projects', { resource: { project_id: project?.id, diff --git a/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx b/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx index 41e7b0d2583..05e0cbc1020 100644 --- a/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx +++ b/apps/studio/components/interfaces/Settings/General/ComplianceConfig/ProjectComplianceMode.tsx @@ -4,7 +4,6 @@ import { useEffect, useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' import { FormHeader } from 'components/ui/Forms/FormHeader' @@ -14,11 +13,12 @@ import { InlineLink } from 'components/ui/InlineLink' import { useComplianceConfigUpdateMutation } from 'data/config/project-compliance-config-mutation' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Switch, Tooltip, TooltipContent, TooltipTrigger } from 'ui' const ComplianceConfig = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isSensitive, setIsSensitive] = useState(false) const canUpdateComplianceConfig = useCheckPermissions(PermissionAction.UPDATE, 'projects', { diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx index aa2391f660b..4b75d586b64 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainConfig.tsx @@ -7,7 +7,7 @@ import Panel from 'components/ui/Panel' import UpgradeToPro from 'components/ui/UpgradeToPro' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useFlag } from 'hooks/ui/useFlag' import CustomDomainActivate from './CustomDomainActivate' import CustomDomainDelete from './CustomDomainDelete' @@ -17,7 +17,7 @@ import CustomDomainsShimmerLoader from './CustomDomainsShimmerLoader' const CustomDomainConfig = () => { const { ref } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const customDomainsDisabledDueToQuota = useFlag('customDomainsDisabledDueToQuota') diff --git a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx index aeefdf15225..e0ab0c151b2 100644 --- a/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx +++ b/apps/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx @@ -2,7 +2,6 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import * as yup from 'yup' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import { FormActions } from 'components/ui/Forms/FormActions' import { FormPanel } from 'components/ui/Forms/FormPanel' @@ -11,6 +10,7 @@ import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query import { useCheckCNAMERecordMutation } from 'data/custom-domains/check-cname-mutation' import { useCustomDomainCreateMutation } from 'data/custom-domains/custom-domains-create-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Form, Input } from 'ui' const schema = yup.object({ @@ -19,7 +19,7 @@ const schema = yup.object({ const CustomDomainsConfigureHostname = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { mutate: checkCNAMERecord, isLoading: isCheckingRecord } = useCheckCNAMERecordMutation() const { mutate: createCustomDomain, isLoading: isCreating } = useCustomDomainCreateMutation() diff --git a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx index 961805f9013..c86e9f68d86 100644 --- a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx @@ -1,9 +1,9 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { DeleteProjectModal } from './DeleteProjectModal' export interface DeleteProjectButtonProps { @@ -11,7 +11,7 @@ export interface DeleteProjectButtonProps { } const DeleteProjectButton = ({ type = 'danger' }: DeleteProjectButtonProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isOpen, setIsOpen] = useState(false) const canDeleteProject = useCheckPermissions(PermissionAction.UPDATE, 'projects', { diff --git a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectModal.tsx b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectModal.tsx index 966e6d481e6..48f9dbf7df8 100644 --- a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectModal.tsx +++ b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectModal.tsx @@ -4,12 +4,12 @@ import { toast } from 'sonner' import { LOCAL_STORAGE_KEYS } from 'common' import { CANCELLATION_REASONS } from 'components/interfaces/Billing/Billing.constants' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useSendDowngradeFeedbackMutation } from 'data/feedback/exit-survey-send' import { useProjectDeleteMutation } from 'data/projects/project-delete-mutation' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Input } from 'ui' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' @@ -21,8 +21,8 @@ export const DeleteProjectModal = ({ onClose: () => void }) => { const router = useRouter() - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const [lastVisitedOrganization] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.LAST_VISITED_ORGANIZATION, diff --git a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx index 37834a42251..3281d25363c 100644 --- a/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx +++ b/apps/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel.tsx @@ -1,13 +1,12 @@ -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormHeader } from 'components/ui/Forms/FormHeader' -import PartnerManagedResource from 'components/ui/PartnerManagedResource' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, CriticalIcon } from 'ui' import DeleteProjectButton from './DeleteProjectButton' export const DeleteProjectPanel = () => { - const selectedOrganization = useSelectedOrganization() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() if (project === undefined) return null diff --git a/apps/studio/components/interfaces/Settings/General/General.tsx b/apps/studio/components/interfaces/Settings/General/General.tsx index 9c8aad82053..a459c6f3515 100644 --- a/apps/studio/components/interfaces/Settings/General/General.tsx +++ b/apps/studio/components/interfaces/Settings/General/General.tsx @@ -3,7 +3,6 @@ import { BarChart2 } from 'lucide-react' import Link from 'next/link' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormActions } from 'components/ui/Forms/FormActions' import { FormPanel } from 'components/ui/Forms/FormPanel' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' @@ -11,8 +10,8 @@ import Panel from 'components/ui/Panel' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useProjectUpdateMutation } from 'data/projects/project-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useProjectByRef } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useProjectByRefQuery, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -26,10 +25,10 @@ import PauseProjectButton from './Infrastructure/PauseProjectButton' import RestartServerButton from './Infrastructure/RestartServerButton' const General = () => { - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() - const parentProject = useProjectByRef(project?.parent_project_ref) + const { data: parentProject } = useProjectByRefQuery(project?.parent_project_ref) const isBranch = parentProject !== undefined const formId = 'project-general-settings' diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx index 47daf680895..9121f8caf89 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx @@ -5,24 +5,21 @@ import { useRouter } from 'next/router' import { useState } from 'react' import { toast } from 'sonner' -import { - useIsProjectActive, - useProjectContext, -} from 'components/layouts/ProjectLayout/ProjectContext' +import { useIsProjectActive } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useProjectPauseMutation } from 'data/projects/project-pause-mutation' import { setProjectStatus } from 'data/projects/projects-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useIsAwsK8sCloudProvider } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useIsAwsK8sCloudProvider, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' const PauseProjectButton = () => { const router = useRouter() const queryClient = useQueryClient() - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const isProjectActive = useIsProjectActive() const [isModalOpen, setIsModalOpen] = useState(false) diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx index c3ff46c0ac5..97704722f05 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/ProjectUpgradeAlert/ProjectUpgradeAlert.tsx @@ -19,7 +19,7 @@ import { import { ReleaseChannel } from 'data/projects/new-project.constants' import { useProjectUpgradeMutation } from 'data/projects/project-upgrade-mutation' import { setProjectStatus } from 'data/projects/projects-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useFlag } from 'hooks/ui/useFlag' import { PROJECT_STATUS } from 'lib/constants' import { @@ -67,7 +67,7 @@ const ProjectUpgradeAlert = () => { const router = useRouter() const { ref } = useParams() const queryClient = useQueryClient() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const [showUpgradeModal, setShowUpgradeModal] = useState(false) const projectUpgradeDisabled = useFlag('disableProjectUpgrade') diff --git a/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx b/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx index 4b00ae86f5d..e8c0cc61671 100644 --- a/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx @@ -5,16 +5,13 @@ import { useRouter } from 'next/router' import { useState } from 'react' import { toast } from 'sonner' -import { - useIsProjectActive, - useProjectContext, -} from 'components/layouts/ProjectLayout/ProjectContext' +import { useIsProjectActive } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useProjectRestartMutation } from 'data/projects/project-restart-mutation' import { useProjectRestartServicesMutation } from 'data/projects/project-restart-services-mutation' import { setProjectStatus } from 'data/projects/projects-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useIsAwsK8sCloudProvider } from 'hooks/misc/useSelectedProject' +import { useIsAwsK8sCloudProvider, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useFlag } from 'hooks/ui/useFlag' import { Button, @@ -29,7 +26,7 @@ import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' const RestartServerButton = () => { const router = useRouter() const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const isProjectActive = useIsProjectActive() const isAwsK8s = useIsAwsK8sCloudProvider() const [serviceToRestart, setServiceToRestart] = useState<'project' | 'database'>() diff --git a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx index 41eb53f14aa..cad1c7cfb4e 100644 --- a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx +++ b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectButton.tsx @@ -9,13 +9,13 @@ import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useProjectTransferMutation } from 'data/projects/project-transfer-mutation' import { useProjectTransferPreviewQuery } from 'data/projects/project-transfer-preview-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useFlag } from 'hooks/ui/useFlag' import { Button, InfoIcon, Listbox, Loading, Modal, WarningIcon } from 'ui' import { Admonition } from 'ui-patterns' const TransferProjectButton = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const projectRef = project?.ref const projectOrgId = project?.organization_id const [isOpen, setIsOpen] = useState(false) diff --git a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectPanel.tsx b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectPanel.tsx index 56e7d033d11..268a142522c 100644 --- a/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectPanel.tsx +++ b/apps/studio/components/interfaces/Settings/General/TransferProjectPanel/TransferProjectPanel.tsx @@ -1,13 +1,14 @@ -import { FormHeader } from 'components/ui/Forms/FormHeader' -import Panel from 'components/ui/Panel' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' -import TransferProjectButton from './TransferProjectButton' import { Truck } from 'lucide-react' -const TransferProjectPanel = () => { - const project = useSelectedProject() +import { FormHeader } from 'components/ui/Forms/FormHeader' +import Panel from 'components/ui/Panel' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import TransferProjectButton from './TransferProjectButton' - if (project === undefined) return <> +const TransferProjectPanel = () => { + const { data: project } = useSelectedProjectQuery() + + if (project === undefined) return null return (
diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx index 7f7f3d8a2a2..d0cd6341ad5 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureActivity.tsx @@ -29,8 +29,8 @@ import { useInfraMonitoringQuery } from 'data/analytics/infra-monitoring-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { INSTANCE_MICRO_SPECS, INSTANCE_NANO_SPECS, InstanceSpecs } from 'lib/constants' import { TIME_PERIODS_BILLING, TIME_PERIODS_REPORTS } from 'lib/constants/metrics' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' @@ -49,8 +49,8 @@ const NON_DEDICATED_IO_RESOURCES = [ const InfrastructureActivity = () => { const { ref: projectRef } = useParams() - const project = useSelectedProject() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const state = useDatabaseSelectorStateSnapshot() const [dateRange, setDateRange] = useState() diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx index c95cebc59c6..f4d374a3913 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/DeployNewReplicaPanel.tsx @@ -24,8 +24,8 @@ import { useReadReplicasQuery, } from 'data/read-replicas/replicas-query' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useIsAwsK8sCloudProvider, useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useIsAwsK8sCloudProvider, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AWS_REGIONS_DEFAULT, BASE_PATH } from 'lib/constants' import { formatCurrency } from 'lib/helpers' import type { AWS_REGIONS_KEYS } from 'shared-data' @@ -67,8 +67,8 @@ const DeployNewReplicaPanel = ({ onClose, }: DeployNewReplicaPanelProps) => { const { ref: projectRef } = useParams() - const project = useSelectedProject() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { data } = useReadReplicasQuery({ projectRef }) const { data: addons, isSuccess } = useProjectAddonsQuery({ projectRef }) diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx index d1edc21905d..e77f7ad6819 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.tsx @@ -7,7 +7,6 @@ import { useEffect, useMemo, useRef, useState } from 'react' import ReactFlow, { Background, Edge, ReactFlowProvider, useReactFlow } from 'reactflow' import 'reactflow/dist/style.css' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useLoadBalancersQuery } from 'data/read-replicas/load-balancers-query' @@ -17,7 +16,7 @@ import { useReadReplicasStatusesQuery, } from 'data/read-replicas/replicas-status-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useIsOrioleDb } from 'hooks/misc/useSelectedProject' +import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { timeout } from 'lib/helpers' import Link from 'next/link' import { type AWS_REGIONS_KEYS } from 'shared-data' @@ -47,7 +46,7 @@ const InstanceConfigurationUI = () => { const { resolvedTheme } = useTheme() const { ref: projectRef } = useParams() const numTransition = useRef() - const { project, isLoading: isLoadingProject } = useProjectContext() + const { data: project, isLoading: isLoadingProject } = useSelectedProjectQuery() const [view, setView] = useState<'flow' | 'map'>('flow') const [showDeleteAllModal, setShowDeleteAllModal] = useState(false) diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx index 5fa6bc930c8..c2e375ade9b 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/InfrastructureInfo.tsx @@ -1,5 +1,4 @@ import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldContainer, ScaffoldDivider, @@ -13,7 +12,7 @@ import { useProjectUpgradeEligibilityQuery } from 'data/config/project-upgrade-e import { useProjectServiceVersionsQuery } from 'data/projects/project-service-versions' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useIsOrioleDb } from 'hooks/misc/useSelectedProject' +import { useIsOrioleDb, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -35,7 +34,7 @@ import { const InfrastructureInfo = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const authEnabled = useIsFeatureEnabled('project_auth:all') diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx index 2d217b8d23d..75540458b2e 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubIntegrationConnectionForm.tsx @@ -1,7 +1,7 @@ import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { ChevronDown, Loader2, PlusIcon } from 'lucide-react' -import { useCallback, useEffect, useState, useMemo } from 'react' +import { useEffect, useMemo, useState } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' import * as z from 'zod' @@ -9,16 +9,16 @@ import * as z from 'zod' import { useBranchCreateMutation } from 'data/branches/branch-create-mutation' import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' import { useBranchesQuery } from 'data/branches/branches-query' -import { useCheckGithubBranchValidity } from 'data/integrations/github-branch-check-query' import { useGitHubAuthorizationQuery } from 'data/integrations/github-authorization-query' +import { useCheckGithubBranchValidity } from 'data/integrations/github-branch-check-query' import { useGitHubConnectionCreateMutation } from 'data/integrations/github-connection-create-mutation' import { useGitHubConnectionDeleteMutation } from 'data/integrations/github-connection-delete-mutation' import { useGitHubConnectionUpdateMutation } from 'data/integrations/github-connection-update-mutation' import { useGitHubRepositoriesQuery } from 'data/integrations/github-repositories-query' import type { GitHubConnection } from 'data/integrations/integrations.types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { openInstallGitHubIntegrationWindow } from 'lib/github' import { EMPTY_ARR } from 'lib/void' import { @@ -27,20 +27,20 @@ import { CardContent, CardFooter, cn, - Form_Shadcn_, - FormControl_Shadcn_, - FormField_Shadcn_, - Input_Shadcn_, - Switch, + Command_Shadcn_, CommandEmpty_Shadcn_, CommandGroup_Shadcn_, CommandInput_Shadcn_, CommandItem_Shadcn_, CommandList_Shadcn_, - Command_Shadcn_, + Form_Shadcn_, + FormControl_Shadcn_, + FormField_Shadcn_, + Input_Shadcn_, + Popover_Shadcn_, PopoverContent_Shadcn_, PopoverTrigger_Shadcn_, - Popover_Shadcn_, + Switch, } from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' @@ -65,8 +65,8 @@ const GitHubIntegrationConnectionForm = ({ disabled = false, connection, }: GitHubIntegrationConnectionFormProps) => { - const selectedProject = useSelectedProject() - const selectedOrganization = useSelectedOrganization() + const { data: selectedProject } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const [isConfirmingBranchChange, setIsConfirmingBranchChange] = useState(false) const [isConfirmingRepoChange, setIsConfirmingRepoChange] = useState(false) const [repoComboBoxOpen, setRepoComboboxOpen] = useState(false) diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubStatus.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubStatus.tsx index c525ced88a6..e67a721242c 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubStatus.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GitHubStatus.tsx @@ -5,15 +5,15 @@ import Link from 'next/link' import { useParams } from 'common' import { useBranchesQuery } from 'data/branches/branches-query' import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { HoverCard, HoverCardContent, HoverCardTrigger } from 'ui' export const GitHubStatus = () => { const { ref: projectRef } = useParams() - const selectedProject = useSelectedProject() - const selectedOrganization = useSelectedOrganization() + const { data: selectedProject } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const parentProjectRef = selectedProject?.parent_project_ref || projectRef const { data: connections } = useGitHubConnectionsQuery( diff --git a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx index 3a7483e7f28..7e17d3cf777 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx @@ -12,7 +12,7 @@ import NoPermission from 'components/ui/NoPermission' import UpgradeToPro from 'components/ui/UpgradeToPro' import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH, IS_PLATFORM } from 'lib/constants' import { cn } from 'ui' import GitHubIntegrationConnectionForm from './GitHubIntegrationConnectionForm' @@ -29,20 +29,19 @@ const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => { const GitHubSection = () => { const { ref: projectRef } = useParams() - const selectedOrganization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const canReadGitHubConnection = useCheckPermissions( PermissionAction.READ, 'integrations.github_connections' ) - const organization = useSelectedOrganization() const isProPlanAndUp = organization?.plan?.id !== 'free' const promptProPlanUpgrade = IS_PLATFORM && !isProPlanAndUp const { data: connections } = useGitHubConnectionsQuery( - { organizationId: selectedOrganization?.id }, - { enabled: !!projectRef && !!selectedOrganization?.id } + { organizationId: organization?.id }, + { enabled: !!projectRef && !!organization?.id } ) const existingConnection = useMemo( diff --git a/apps/studio/components/interfaces/Settings/Integrations/IntegrationsSettings.tsx b/apps/studio/components/interfaces/Settings/Integrations/IntegrationsSettings.tsx index fe23171ac31..51ce7d77558 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/IntegrationsSettings.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/IntegrationsSettings.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import SidePanelVercelProjectLinker from 'components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker' import { ScaffoldContainer, ScaffoldDivider } from 'components/layouts/Scaffold' -import { useProjectByRef, useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useProjectByRefQuery, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, WarningIcon } from 'ui' import GitHubSection from './GithubIntegration/GithubSection' @@ -19,8 +19,8 @@ export const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' } const IntegrationSettings = () => { - const project = useSelectedProject() - const parentProject = useProjectByRef(project?.parent_project_ref) + const { data: project } = useSelectedProjectQuery() + const { data: parentProject } = useProjectByRefQuery(project?.parent_project_ref) const isBranch = project?.parent_project_ref !== undefined return ( diff --git a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx index 63fb03aa3f3..6d49492a126 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelIntegrationConnectionForm.tsx @@ -10,7 +10,7 @@ import type { IntegrationProjectConnection, } from 'data/integrations/integrations.types' import { useVercelConnectionUpdateMutation } from 'data/integrations/vercel-connection-update-mutate' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import Link from 'next/link' import { AlertDescription_Shadcn_, @@ -38,7 +38,7 @@ const VercelIntegrationConnectionForm = ({ }) => { // NOTE(kamil): Ignore sync targets for Vercel Marketplace as it's not synchronized using integration, // but through a separate marketplace mechanism. It's not theoretically necessary, but we might have some stale data. - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const envSyncTargets = org?.managed_by === 'vercel-marketplace' ? [] : connection.env_sync_targets ?? [] diff --git a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx index 599729956ce..0e39d99946c 100644 --- a/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx +++ b/apps/studio/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection.tsx @@ -26,8 +26,8 @@ import type { IntegrationProjectConnection, } from 'data/integrations/integrations.types' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { pluralize } from 'lib/helpers' import { getIntegrationConfigurationUrl } from 'lib/integration-utils' import { useSidePanelsStateSnapshot } from 'state/side-panels' @@ -36,8 +36,8 @@ import { IntegrationImageHandler } from '../IntegrationsSettings' import VercelIntegrationConnectionForm from './VercelIntegrationConnectionForm' const VercelSection = ({ isProjectScoped }: { isProjectScoped: boolean }) => { - const project = useSelectedProject() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { data } = useOrgIntegrationsQuery({ orgSlug: org?.slug }) const sidePanelsStateSnapshot = useSidePanelsStateSnapshot() const isBranch = project?.parent_project_ref !== undefined diff --git a/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx b/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx index 83a8694afa1..c04be8882a9 100644 --- a/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/LogsPreviewer.tsx @@ -12,7 +12,7 @@ import useLogsPreview from 'hooks/analytics/useLogsPreview' import { useLogsUrlState } from 'hooks/analytics/useLogsUrlState' import { useSelectedLog } from 'hooks/analytics/useSelectedLog' import useSingleLog from 'hooks/analytics/useSingleLog' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt' import { useFlag } from 'hooks/ui/useFlag' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' @@ -64,7 +64,7 @@ export const LogsPreviewer = ({ const router = useRouter() const { db } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const state = useDatabaseSelectorStateSnapshot() const [showChart, setShowChart] = useState(true) diff --git a/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx b/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx index 5869c5b5f8b..b6414a5c37f 100644 --- a/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx +++ b/apps/studio/components/interfaces/Settings/Logs/UpgradePrompt.tsx @@ -1,6 +1,6 @@ import Link from 'next/link' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, Modal } from 'ui' import { TIER_QUERY_LIMITS } from './Logs.constants' @@ -26,7 +26,7 @@ const UpgradePrompt: React.FC = ({ description = 'Logs can be retained up to a duration of 3 months depending on the plan that your project is on.', source = 'logsRetentionUpgradePrompt', }) => { - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() return ( { const ProjectLinks = () => { const router = useRouter() const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const snap = useAppStateSnapshot() const isNewAPIDocsEnabled = useIsAPIDocsSidePanelEnabled() const { securityLints, errorLints } = useLints() @@ -344,7 +343,7 @@ const OrganizationLinks = () => { const router = useRouter() const { slug } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const isUserMFAEnabled = useIsMFAEnabled() const disableAccessMfa = org?.organization_requires_mfa && !isUserMFAEnabled diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/CopyEnvButton.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/CopyEnvButton.tsx index 1c45eda3cf0..922bd07e577 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/CopyEnvButton.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/CopyEnvButton.tsx @@ -2,9 +2,9 @@ import { Copy } from 'lucide-react' import { useCallback, useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { getDecryptedValue } from 'data/vault/vault-secret-decrypted-value-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { copyToClipboard } from 'ui' export const CopyEnvButton = ({ @@ -14,7 +14,7 @@ export const CopyEnvButton = ({ serverOptions: { name: string; secureEntry: boolean }[] values: Record }) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isLoading, setIsLoading] = useState(false) const onCopy = useCallback(async () => { diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx index fff4f06387f..2ec51c5f151 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/DecryptedReadOnlyInput.tsx @@ -2,8 +2,8 @@ import { ExternalLink, Eye, EyeOff, Loader } from 'lucide-react' import { useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Input, Tooltip, TooltipContent, TooltipTrigger } from 'ui' export const DecryptedReadOnlyInput = ({ @@ -18,7 +18,7 @@ export const DecryptedReadOnlyInput = ({ label: string }) => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [showHidden, setShowHidden] = useState(false) const { data: decryptedValue, isLoading: isDecryptedValueLoading } = diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx index 1c716007a56..a64264be2b1 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/NamespaceRow.tsx @@ -4,13 +4,13 @@ import { useMemo, useState } from 'react' import type { WrapperMeta } from 'components/interfaces/Integrations/Wrappers/Wrappers.types' import { FormattedWrapperTable } from 'components/interfaces/Integrations/Wrappers/Wrappers.utils' import { ImportForeignSchemaDialog } from 'components/interfaces/Storage/ImportForeignSchemaDialog' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useFDWImportForeignSchemaMutation } from 'data/fdw/fdw-import-foreign-schema-mutation' import { FDW } from 'data/fdw/fdws-query' import { useIcebergNamespaceTablesQuery } from 'data/storage/iceberg-namespace-tables-query' import { BASE_PATH } from 'lib/constants' import { Button, cn, TableCell, TableRow } from 'ui' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' type NamespaceRowProps = { bucketName: string @@ -33,7 +33,7 @@ export const NamespaceRow = ({ wrapperValues, wrapperMeta, }: NamespaceRowProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [importForeignSchemaShown, setImportForeignSchemaShown] = useState(false) const { data: tablesData, isLoading: isLoadingNamespaceTables } = useIcebergNamespaceTablesQuery( diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/SimpleConfigurationDetails.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/SimpleConfigurationDetails.tsx index dc8aafaa9eb..68085156f9f 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/SimpleConfigurationDetails.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/SimpleConfigurationDetails.tsx @@ -1,8 +1,8 @@ import Link from '@ui/components/Typography/Link' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldSectionDescription, ScaffoldSectionTitle } from 'components/layouts/Scaffold' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Card } from 'ui' import { getCatalogURI, getConnectionURL } from '../StorageSettings/StorageSettings.utils' import { DESCRIPTIONS } from './constants' @@ -19,7 +19,7 @@ const wrapperMeta = { } export const SimpleConfigurationDetails = ({ bucketName }: { bucketName: string }) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: apiKeys } = useAPIKeysQuery({ projectRef: project?.ref }) const { data: settings } = useProjectSettingsV2Query({ projectRef: project?.ref }) diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx index 25945e40d77..ca44692c2ef 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/index.tsx @@ -10,7 +10,6 @@ import { formatWrapperTables, wrapperMetaComparator, } from 'components/interfaces/Integrations/Wrappers/Wrappers.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldContainer, ScaffoldHeader, @@ -28,6 +27,7 @@ import { Bucket } from 'data/storage/buckets-query' import { useIcebergNamespacesQuery } from 'data/storage/iceberg-namespaces-query' import { useIcebergWrapperCreateMutation } from 'data/storage/iceberg-wrapper-create-mutation' import { useVaultSecretDecryptedValueQuery } from 'data/vault/vault-secret-decrypted-value-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Alert_Shadcn_, AlertDescription_Shadcn_, @@ -50,7 +50,7 @@ import { SimpleConfigurationDetails } from './SimpleConfigurationDetails' import { useIcebergWrapperExtension } from './useIcebergWrapper' export const AnalyticBucketDetails = ({ bucket }: { bucket: Bucket }) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: extensionsData } = useDatabaseExtensionsQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/useIcebergWrapper.tsx b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/useIcebergWrapper.tsx index 56387d46095..57cdbe2f21f 100644 --- a/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/useIcebergWrapper.tsx +++ b/apps/studio/components/interfaces/Storage/AnalyticBucketDetails/useIcebergWrapper.tsx @@ -1,9 +1,9 @@ import { INTEGRATIONS } from 'components/interfaces/Integrations/Landing/Integrations.constants' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' export const useIcebergWrapperExtension = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: extensionsData, isLoading: isExtensionsLoading } = useDatabaseExtensionsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx index 8fd84dcebc2..172d6a75754 100644 --- a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx @@ -16,7 +16,7 @@ import { useProjectStorageConfigQuery } from 'data/config/project-storage-config import { useBucketCreateMutation } from 'data/storage/bucket-create-mutation' import { useIcebergWrapperCreateMutation } from 'data/storage/iceberg-wrapper-create-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH, IS_PLATFORM } from 'lib/constants' import { Alert_Shadcn_, @@ -74,9 +74,9 @@ export type CreateBucketForm = z.infer const CreateBucketModal = ({ visible, onClose }: CreateBucketModalProps) => { const { ref } = useParams() - const org = useSelectedOrganization() - const { mutate: sendEvent } = useSendEventMutation() const router = useRouter() + const { data: org } = useSelectedOrganizationQuery() + const { mutate: sendEvent } = useSendEventMutation() const { mutateAsync: createBucket, isLoading: isCreating } = useBucketCreateMutation({ // [Joshen] Silencing the error here as it's being handled in onSubmit diff --git a/apps/studio/components/interfaces/Storage/DeleteBucketModal.tsx b/apps/studio/components/interfaces/Storage/DeleteBucketModal.tsx index ac7293b105c..0515641d074 100644 --- a/apps/studio/components/interfaces/Storage/DeleteBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/DeleteBucketModal.tsx @@ -3,11 +3,11 @@ import { get as _get, find } from 'lodash' import { useRouter } from 'next/router' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' import { useDatabasePolicyDeleteMutation } from 'data/database-policies/database-policy-delete-mutation' import { useBucketDeleteMutation } from 'data/storage/bucket-delete-mutation' import { Bucket, useBucketsQuery } from 'data/storage/buckets-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal' import { formatPoliciesForStorage } from './Storage.utils' @@ -20,7 +20,7 @@ export interface DeleteBucketModalProps { const DeleteBucketModal = ({ visible = false, bucket, onClose }: DeleteBucketModalProps) => { const router = useRouter() const { ref: projectRef } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data } = useBucketsQuery({ projectRef }) const { data: policies } = useDatabasePoliciesQuery({ diff --git a/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx b/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx index d7371c08591..869f88b7f04 100644 --- a/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx +++ b/apps/studio/components/interfaces/Storage/ImportForeignSchemaDialog.tsx @@ -6,12 +6,12 @@ import { toast } from 'sonner' import z from 'zod' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useSchemaCreateMutation } from 'data/database/schema-create-mutation' import { useSchemasQuery } from 'data/database/schemas-query' import { useFDWImportForeignSchemaMutation } from 'data/fdw/fdw-import-foreign-schema-mutation' import { useFDWUpdateMutation } from 'data/fdw/fdw-update-mutation' import { getFDWs } from 'data/fdw/fdws-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, Form_Shadcn_, FormField_Shadcn_, Input_Shadcn_, Modal } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import type { WrapperMeta } from '../Integrations/Wrappers/Wrappers.types' @@ -34,7 +34,7 @@ export const ImportForeignSchemaDialog = ({ visible, onClose, }: ImportForeignSchemaDialogProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { ref } = useParams() const [loading, setLoading] = useState(false) const [createSchemaSheetOpen, setCreateSchemaSheetOpen] = useState(false) diff --git a/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePolicies.tsx b/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePolicies.tsx index 1c29a199b90..0294019aa77 100644 --- a/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePolicies.tsx +++ b/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePolicies.tsx @@ -4,21 +4,21 @@ import { useState } from 'react' import { toast } from 'sonner' import PolicyEditorModal from 'components/interfaces/Auth/Policies/PolicyEditorModal' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' 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 { useBucketsQuery } from 'data/storage/buckets-query' +import { Loader } from 'lucide-react' import ConfirmModal from 'ui-patterns/Dialogs/ConfirmDialog' import { formatPoliciesForStorage } from '../Storage.utils' import StoragePoliciesBucketRow from './StoragePoliciesBucketRow' import StoragePoliciesEditPolicyModal from './StoragePoliciesEditPolicyModal' import StoragePoliciesPlaceholder from './StoragePoliciesPlaceholder' -import { Loader } from 'lucide-react' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' const StoragePolicies = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { ref: projectRef } = useParams() const { data, isLoading: isLoadingBuckets } = useBucketsQuery({ projectRef }) diff --git a/apps/studio/components/interfaces/Storage/StorageSettings/S3Connection.tsx b/apps/studio/components/interfaces/Storage/StorageSettings/S3Connection.tsx index 69b2e4d297c..e8fbe4a986a 100644 --- a/apps/studio/components/interfaces/Storage/StorageSettings/S3Connection.tsx +++ b/apps/studio/components/interfaces/Storage/StorageSettings/S3Connection.tsx @@ -8,10 +8,7 @@ import { toast } from 'sonner' import * as z from 'zod' import { useParams } from 'common' -import { - useIsProjectActive, - useProjectContext, -} from 'components/layouts/ProjectLayout/ProjectContext' +import { useIsProjectActive } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { FormHeader } from 'components/ui/Forms/FormHeader' @@ -22,6 +19,7 @@ import { useProjectStorageConfigQuery } from 'data/config/project-storage-config import { useProjectStorageConfigUpdateUpdateMutation } from 'data/config/project-storage-config-update-mutation' import { useStorageCredentialsQuery } from 'data/storage/s3-access-key-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, Alert_Shadcn_, @@ -44,7 +42,7 @@ import { getConnectionURL } from './StorageSettings.utils' export const S3Connection = () => { const { ref: projectRef } = useParams() const isProjectActive = useIsProjectActive() - const { project, isLoading: projectIsLoading } = useProjectContext() + const { data: project, isLoading: projectIsLoading } = useSelectedProjectQuery() const [openCreateCred, setOpenCreateCred] = useState(false) const [openDeleteDialog, setOpenDeleteDialog] = useState(false) diff --git a/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx b/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx index 8bbb2885aca..6ce9a20fdad 100644 --- a/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx +++ b/apps/studio/components/interfaces/Storage/StorageSettings/StorageSettings.tsx @@ -14,7 +14,7 @@ import UpgradeToPro from 'components/ui/UpgradeToPro' import { useProjectStorageConfigQuery } from 'data/config/project-storage-config-query' import { useProjectStorageConfigUpdateUpdateMutation } from 'data/config/project-storage-config-update-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { formatBytes } from 'lib/helpers' import { Button, @@ -59,7 +59,7 @@ const StorageSettings = () => { isError, } = useProjectStorageConfigQuery({ projectRef }) - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const isFreeTier = organization?.plan.id === 'free' const isSpendCapOn = organization?.plan.id === 'pro' && organization?.usage_billing_enabled === false diff --git a/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx b/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx index 06ace1d0d88..ad47117abb0 100644 --- a/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx @@ -4,13 +4,13 @@ import { toast } from 'sonner' import { useTableFilter } from 'components/grid/hooks/useTableFilter' import type { SupaRow } from 'components/grid/types' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseColumnDeleteMutation } from 'data/database-columns/database-column-delete-mutation' import { TableLike } from 'data/table-editor/table-editor-types' import { useTableRowDeleteAllMutation } from 'data/table-rows/table-row-delete-all-mutation' import { useTableRowDeleteMutation } from 'data/table-rows/table-row-delete-mutation' import { useTableRowTruncateMutation } from 'data/table-rows/table-row-truncate-mutation' import { useTableDeleteMutation } from 'data/tables/table-delete-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useGetImpersonatedRoleState } from 'state/role-impersonation-state' import { useTableEditorStateSnapshot } from 'state/table-editor' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, Checkbox } from 'ui' @@ -25,7 +25,7 @@ const DeleteConfirmationDialogs = ({ selectedTable, onTableDeleted, }: DeleteConfirmationDialogsProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const snap = useTableEditorStateSnapshot() const { filters, onApplyFilters } = useTableFilter() diff --git a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index f32a66bb37a..4c83d38d6f6 100644 --- a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -6,7 +6,6 @@ import { toast } from 'sonner' import { useParams } from 'common' import { getEntityLintDetails } from 'components/interfaces/TableGridEditor/TableEntity.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import APIDocsButton from 'components/ui/APIDocsButton' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' @@ -24,7 +23,8 @@ import { useTableUpdateMutation } from 'data/tables/table-update-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { useTableEditorTableStateSnapshot } from 'state/table-editor-table' import { @@ -48,8 +48,8 @@ export interface GridHeaderActionsProps { const GridHeaderActions = ({ table }: GridHeaderActionsProps) => { const { ref } = useParams() - const { project } = useProjectContext() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() // need project lints to get security status for views const { data: lints = [] } = useProjectLintsQuery({ projectRef: project?.ref }) diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx index 1cf289406bb..41fa34c9966 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnEditor.tsx @@ -5,7 +5,6 @@ import Link from 'next/link' import { useEffect, useState } from 'react' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection' import { CONSTRAINT_TYPE, @@ -17,6 +16,7 @@ import { useForeignKeyConstraintsQuery, } from 'data/database/foreign-key-constraints-query' import { useEnumeratedTypesQuery } from 'data/enumerated-types/enumerated-types-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProtectedSchemas } from 'hooks/useProtectedSchemas' import type { Dictionary } from 'types' import { Button, Checkbox, Input, SidePanel, Toggle } from 'ui' @@ -70,7 +70,7 @@ const ColumnEditor = ({ updateEditorDirty = noop, }: ColumnEditorProps) => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [errors, setErrors] = useState>({}) const [columnFields, setColumnFields] = useState() diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx index fc2eb6c60ce..9e8252da627 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ColumnEditor/ColumnForeignKey.tsx @@ -2,9 +2,9 @@ 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 { useTableEditorQuery } from 'data/table-editor/table-editor-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { ForeignKeySelector } from '../ForeignKeySelector/ForeignKeySelector' import type { ForeignKey } from '../ForeignKeySelector/ForeignKeySelector.types' import type { ColumnField } from '../SidePanelEditor.types' @@ -30,7 +30,7 @@ const ColumnForeignKey = ({ const [open, setOpen] = useState(false) const [selectedFk, setSelectedFk] = useState() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data } = useForeignKeyConstraintsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx index 3c696162ffd..9659674e3fc 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/ForeignKeySelector/ForeignKeySelector.tsx @@ -11,13 +11,13 @@ import { SidePanel, } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import InformationBox from 'components/ui/InformationBox' import { FOREIGN_KEY_CASCADE_ACTION } from 'data/database/database-query-constants' import { useSchemasQuery } from 'data/database/schemas-query' import { useTablesQuery } from 'data/tables/tables-query' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import ActionBar from '../ActionBar' import { NUMERICAL_TYPES, TEXT_TYPES } from '../SidePanelEditor.constants' @@ -56,7 +56,7 @@ export const ForeignKeySelector = ({ onClose, onSaveRelation, }: ForeignKeySelectorProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { selectedSchema } = useQuerySchemaState() const [fk, setFk] = useState(EMPTY_STATE) 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 dae748ae714..9a2a6ac1c87 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/ForeignRowSelector/ForeignRowSelector.tsx @@ -8,9 +8,9 @@ import RefreshButton from 'components/grid/components/header/RefreshButton' import { FilterPopoverPrimitive } from 'components/grid/components/header/filter/FilterPopoverPrimitive' import { SortPopoverPrimitive } from 'components/grid/components/header/sort/SortPopoverPrimitive' import type { Filter, Sort } from 'components/grid/types' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { useTableRowsQuery } from 'data/table-rows/table-rows-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { RoleImpersonationState, useRoleImpersonationStateSnapshot, @@ -37,7 +37,7 @@ const ForeignRowSelector = ({ closePanel, }: ForeignRowSelectorProps) => { const { id } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable } = useTableEditorQuery({ projectRef: project?.ref, connectionString: project?.connectionString, 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 f29dc32f442..f97e7345449 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/JsonEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/JsonEditor/JsonEditor.tsx @@ -9,7 +9,7 @@ import TwoOptionToggle from 'components/ui/TwoOptionToggle' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' import { useGetCellValueMutation } from 'data/table-rows/get-cell-value-mutation' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { minifyJSON, prettifyJSON, removeJSONTrailingComma, tryParseJson } from 'lib/helpers' import { Button, SidePanel, cn } from 'ui' import ActionBar from '../../ActionBar' @@ -40,7 +40,7 @@ const JsonEdit = ({ }: JsonEditProps) => { const { id: _id } = useParams() const id = _id ? Number(_id) : undefined - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable } = useTableEditorQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx index 25e9d608e03..c84c8b5b32e 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.tsx @@ -2,8 +2,8 @@ import type { PostgresTable } from '@supabase/postgres-meta' import { isEmpty, noop, partition } from 'lodash' import { useEffect, useMemo, useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { Dictionary } from 'types' import { SidePanel } from 'ui' import ActionBar from '../ActionBar' @@ -61,7 +61,7 @@ const RowEditor = ({ (rowField: any) => !rowField.isNullable ) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data } = useForeignKeyConstraintsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/TextEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/TextEditor.tsx index bb58a4ba5fa..5f7d353f6ac 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/TextEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/TextEditor.tsx @@ -11,7 +11,7 @@ import TwoOptionToggle from 'components/ui/TwoOptionToggle' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' import { useGetCellValueMutation } from 'data/table-rows/get-cell-value-mutation' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, SidePanel, cn } from 'ui' import ActionBar from '../ActionBar' import { isValueTruncated } from './RowEditor.utils' @@ -35,7 +35,7 @@ export const TextEditor = ({ }: TextEditorProps) => { const { id: _id } = useParams() const id = _id ? Number(_id) : undefined - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable } = useTableEditorQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx index 70eb7b5648e..3db2efb86f3 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SchemaEditor.tsx @@ -2,8 +2,8 @@ import { useEffect, useState } from 'react' import { toast } from 'sonner' import { Input, SidePanel } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useSchemaCreateMutation } from 'data/database/schema-create-mutation' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' interface SchemaEditorProps { visible: boolean @@ -12,7 +12,7 @@ interface SchemaEditorProps { } const SchemaEditor = ({ visible, onSuccess, closePanel }: SchemaEditorProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [errors, setErrors] = useState<{ name?: string }>({ name: undefined }) const [name, setName] = useState('') diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx index f15551a8c81..369adc2673a 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SidePanelEditor.tsx @@ -5,7 +5,6 @@ import { useState } from 'react' import { toast } from 'sonner' import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' 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' @@ -22,6 +21,7 @@ import { useTableRowUpdateMutation } from 'data/table-rows/table-row-update-muta import { tableKeys } from 'data/tables/keys' import { RetrieveTableResult } from 'data/tables/table-retrieve-query' import { getTables } from 'data/tables/tables-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useUrlState } from 'hooks/ui/useUrlState' import { useGetImpersonatedRoleState } from 'state/role-impersonation-state' import { useTableEditorStateSnapshot } from 'state/table-editor' @@ -73,7 +73,7 @@ const SidePanelEditor = ({ const [_, setParams] = useUrlState({ arrayKeys: ['filter', 'sort'] }) const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [isEdited, setIsEdited] = useState(false) const [isClosingPanel, setIsClosingPanel] = useState(false) diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx index 692be3d37a8..a187bca38c1 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.tsx @@ -7,7 +7,7 @@ import { toast } from 'sonner' import { useParams } from 'common' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, SidePanel, Tabs } from 'ui' import ActionBar from '../ActionBar' import type { ImportContent } from '../TableEditor/TableEditor.types' @@ -47,7 +47,7 @@ const SpreadsheetImport = ({ updateEditorDirty = noop, }: SpreadsheetImportProps) => { const { ref: projectRef } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const [tab, setTab] = useState<'fileUpload' | 'pasteText'>('fileUpload') const [input, setInput] = useState('') diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx index 4ab7e464521..40d4f40ec80 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx @@ -15,9 +15,9 @@ import { cn, } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { EMPTY_ARR, EMPTY_OBJ } from 'lib/void' import { useState } from 'react' import { typeExpressionSuggestions } from '../ColumnEditor/ColumnEditor.constants' @@ -71,7 +71,7 @@ const Column = ({ onRemoveColumn, onEditForeignKey, }: ColumnProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [open, setOpen] = useState(false) const suggestions: Suggestion[] = typeExpressionSuggestions?.[column.format] ?? [] diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx index bee42ddd7e5..a333fe9ac86 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ColumnManagement.tsx @@ -13,7 +13,7 @@ import { useParams } from 'common' import InformationBox from 'components/ui/InformationBox' import type { EnumeratedType } from 'data/enumerated-types/enumerated-types-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -58,7 +58,7 @@ const ColumnManagement = ({ onUpdateFkRelations, }: ColumnManagementProps) => { const { ref: projectRef } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const [open, setOpen] = useState(false) const [selectedColumn, setSelectedColumn] = useState() 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 ce381d418ce..1eb06b97c5a 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/ForeignKeysManagement/ForeignKeysManagement.tsx @@ -1,11 +1,11 @@ import { useState } from 'react' import { Button } from 'ui' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useForeignKeyConstraintsQuery } from 'data/database/foreign-key-constraints-query' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { ResponseError } from 'types' import { ForeignKeySelector } from '../../ForeignKeySelector/ForeignKeySelector' import type { ForeignKey } from '../../ForeignKeySelector/ForeignKeySelector.types' @@ -28,7 +28,7 @@ export const ForeignKeysManagement = ({ setEditorDirty, onUpdateFkRelations, }: ForeignKeysManagementProps) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { selectedSchema } = useQuerySchemaState() const [open, setOpen] = useState(false) diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx index 50e60b293d1..b1081d1e43d 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx @@ -3,7 +3,6 @@ import { isEmpty, isUndefined, noop } from 'lodash' import { useEffect, useState } from 'react' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { DocsButton } from 'components/ui/DocsButton' import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query' import { @@ -19,7 +18,8 @@ import { useEnumeratedTypesQuery } from 'data/enumerated-types/enumerated-types- import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useUrlState } from 'hooks/ui/useUrlState' import { useProtectedSchemas } from 'hooks/useProtectedSchemas' import { useTableEditorStateSnapshot } from 'state/table-editor' @@ -81,8 +81,8 @@ const TableEditor = ({ updateEditorDirty = noop, }: TableEditorProps) => { const snap = useTableEditorStateSnapshot() - const { project } = useProjectContext() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { selectedSchema } = useQuerySchemaState() const isNewRecord = isUndefined(table) const realtimeEnabled = useIsFeatureEnabled('realtime:all') diff --git a/apps/studio/components/interfaces/TableGridEditor/TableDefinition.tsx b/apps/studio/components/interfaces/TableGridEditor/TableDefinition.tsx index 34ce0d22e39..45e81d6abf8 100644 --- a/apps/studio/components/interfaces/TableGridEditor/TableDefinition.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/TableDefinition.tsx @@ -5,7 +5,6 @@ import { useMemo, useRef } from 'react' import { useParams } from 'common' import Footer from 'components/grid/components/footer/Footer' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useTableDefinitionQuery } from 'data/database/table-definition-query' import { useViewDefinitionQuery } from 'data/database/view-definition-query' @@ -16,6 +15,7 @@ import { isView, isViewLike, } from 'data/table-editor/table-editor-types' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { formatSql } from 'lib/formatSql' import { timeout } from 'lib/helpers' import { Button } from 'ui' @@ -29,7 +29,7 @@ const TableDefinition = ({ entity }: TableDefinitionProps) => { const editorRef = useRef(null) const monacoRef = useRef(null) const { resolvedTheme } = useTheme() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const viewResult = useViewDefinitionQuery( { diff --git a/apps/studio/components/interfaces/TableGridEditor/ViewEntityAutofixSecurityModal.tsx b/apps/studio/components/interfaces/TableGridEditor/ViewEntityAutofixSecurityModal.tsx index abb4a485bbe..d4029a6d970 100644 --- a/apps/studio/components/interfaces/TableGridEditor/ViewEntityAutofixSecurityModal.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/ViewEntityAutofixSecurityModal.tsx @@ -1,11 +1,11 @@ import { useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useViewDefinitionQuery } from 'data/database/view-definition-query' import { lintKeys } from 'data/lint/keys' import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation' import { Entity, isViewLike } from 'data/table-editor/table-editor-types' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { ScrollArea, SimpleCodeBlock } from 'ui' import { GenericSkeletonLoader } from 'ui-patterns' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' @@ -21,7 +21,7 @@ export default function ViewEntityAutofixSecurityModal({ isAutofixViewSecurityModalOpen, setIsAutofixViewSecurityModalOpen, }: ViewEntityAutofixSecurityModalProps) { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const queryClient = useQueryClient() const { isSuccess, isLoading, data } = useViewDefinitionQuery( { diff --git a/apps/studio/components/layouts/AdvisorsLayout/AdvisorsLayout.tsx b/apps/studio/components/layouts/AdvisorsLayout/AdvisorsLayout.tsx index c6a71104d75..69ffaba644b 100644 --- a/apps/studio/components/layouts/AdvisorsLayout/AdvisorsLayout.tsx +++ b/apps/studio/components/layouts/AdvisorsLayout/AdvisorsLayout.tsx @@ -3,7 +3,7 @@ import { PropsWithChildren } from 'react' import { useIsAdvisorRulesEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { ProductMenu } from 'components/ui/ProductMenu' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import ProjectLayout from '../ProjectLayout/ProjectLayout' import { generateAdvisorsMenu } from './AdvisorsMenu.utils' @@ -13,7 +13,7 @@ export interface AdvisorsLayoutProps { } const AdvisorsLayout = ({ children }: PropsWithChildren) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const advisorRules = useIsAdvisorRulesEnabled() const router = useRouter() diff --git a/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx b/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx index 08d4b8eb2a7..070a80311ba 100644 --- a/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx +++ b/apps/studio/components/layouts/AppLayout/BranchDropdown.tsx @@ -14,7 +14,7 @@ import { useState } from 'react' import { useParams } from 'common' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { Branch, useBranchesQuery } from 'data/branches/branches-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useAppStateSnapshot } from 'state/app-state' import { Badge, @@ -75,7 +75,7 @@ export const BranchDropdown = () => { const router = useRouter() const { ref } = useParams() const snap = useAppStateSnapshot() - const projectDetails = useSelectedProject() + const { data: projectDetails } = useSelectedProjectQuery() const [open, setOpen] = useState(false) diff --git a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx index 9c88b9f3241..b8b99c9d7ae 100644 --- a/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx +++ b/apps/studio/components/layouts/AppLayout/EnableBranchingButton/BranchingPlanNotice.tsx @@ -1,13 +1,13 @@ import { AlertCircleIcon } from 'lucide-react' import Link from 'next/link' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useAppStateSnapshot } from 'state/app-state' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui' export const BranchingPlanNotice = () => { const snap = useAppStateSnapshot() - const selectedOrg = useSelectedOrganization() + const { data: selectedOrg } = useSelectedOrganizationQuery() return ( diff --git a/apps/studio/components/layouts/AppLayout/OrganizationDropdown.tsx b/apps/studio/components/layouts/AppLayout/OrganizationDropdown.tsx index e0a4b5955d4..df9c502c731 100644 --- a/apps/studio/components/layouts/AppLayout/OrganizationDropdown.tsx +++ b/apps/studio/components/layouts/AppLayout/OrganizationDropdown.tsx @@ -8,7 +8,7 @@ import PartnerIcon from 'components/ui/PartnerIcon' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Badge, Button, @@ -29,7 +29,7 @@ import { export const OrganizationDropdown = () => { const router = useRouter() const { slug: routeSlug } = useParams() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { data: organizations, isLoading: isLoadingOrganizations } = useOrganizationsQuery() const organizationCreationEnabled = useIsFeatureEnabled('organizations:create') diff --git a/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx b/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx index 5b0c209fac7..bebe326aab6 100644 --- a/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx +++ b/apps/studio/components/layouts/AppLayout/ProjectDropdown.tsx @@ -8,8 +8,8 @@ import { useParams } from 'common' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { ProjectInfo, useProjectsQuery } from 'data/projects/projects-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useProjectByRef, useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { IS_PLATFORM } from 'lib/constants' import type { Organization } from 'types' import { @@ -27,7 +27,6 @@ import { ScrollArea, cn, } from 'ui' -import { useBranchesQuery } from 'data/branches/branches-query' // [Fran] the idea is to let users change projects without losing the current page, // but at the same time we need to redirect correctly between urls that might be @@ -91,21 +90,20 @@ const ProjectLink = ({ export const ProjectDropdown = () => { const router = useRouter() const { ref } = useParams() - const projectDetails = useSelectedProject() - const selectedOrganization = useSelectedOrganization() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: allProjects, isLoading: isLoadingProjects } = useProjectsQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const projectCreationEnabled = useIsFeatureEnabled('projects:create') - const isBranch = projectDetails?.parentRef !== projectDetails?.ref + const isBranch = project?.parentRef !== project?.ref const projects = allProjects ?.filter((x) => x.organization_id === selectedOrganization?.id) .sort((a, b) => a.name.localeCompare(b.name)) const selectedProject = isBranch - ? projects?.find((project) => project.ref === projectDetails?.parentRef) - : projects?.find((project) => project.ref === ref) + ? projects?.find((p) => p.ref === project?.parentRef) + : projects?.find((p) => p.ref === ref) const [open, setOpen] = useState(false) diff --git a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx index 232a284f306..b3a1b016cff 100644 --- a/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx +++ b/apps/studio/components/layouts/DatabaseLayout/DatabaseLayout.tsx @@ -5,18 +5,18 @@ import { useIsColumnLevelPrivilegesEnabled } from 'components/interfaces/App/Fea 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 } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' +import { useFlag } from 'hooks/ui/useFlag' import ProjectLayout from '../ProjectLayout/ProjectLayout' import { generateDatabaseMenu } from './DatabaseMenu.utils' -import { useFlag } from 'hooks/ui/useFlag' export interface DatabaseLayoutProps { title?: string } const DatabaseProductMenu = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const router = useRouter() const page = router.pathname.split('/')[4] diff --git a/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx b/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx index 7c7c50cc630..9c6169a5e2c 100644 --- a/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx +++ b/apps/studio/components/layouts/DocsLayout/DocsLayout.tsx @@ -7,7 +7,7 @@ import Error from 'components/ui/Error' import { ProductMenu } from 'components/ui/ProductMenu' import { useOpenAPISpecQuery } from 'data/open-api/api-spec-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import { PROJECT_STATUS } from 'lib/constants' import ProjectLayout from '../ProjectLayout/ProjectLayout' @@ -16,7 +16,7 @@ import { generateDocsMenu } from './DocsLayout.utils' function DocsLayout({ title, children }: { title: string; children: ReactElement }) { const router = useRouter() const { ref } = useParams() - const selectedProject = useSelectedProject() + const { data: selectedProject } = useSelectedProjectQuery() const isPaused = selectedProject?.status === PROJECT_STATUS.INACTIVE const { data, isLoading, error } = useOpenAPISpecQuery( diff --git a/apps/studio/components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout.tsx b/apps/studio/components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout.tsx index 127b273b0ef..d42be8ca5ae 100644 --- a/apps/studio/components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout.tsx +++ b/apps/studio/components/layouts/EdgeFunctionsLayout/EdgeFunctionDetailsLayout.tsx @@ -16,7 +16,7 @@ import { useEdgeFunctionBodyQuery } from 'data/edge-functions/edge-function-body import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { withAuth } from 'hooks/misc/withAuth' import { Button, @@ -38,7 +38,7 @@ const EdgeFunctionDetailsLayout = ({ children, }: PropsWithChildren) => { const router = useRouter() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { functionSlug, ref } = useParams() const { mutate: sendEvent } = useSendEventMutation() diff --git a/apps/studio/components/layouts/Integrations/header.tsx b/apps/studio/components/layouts/Integrations/header.tsx index 01b47a3e643..320406c222b 100644 --- a/apps/studio/components/layouts/Integrations/header.tsx +++ b/apps/studio/components/layouts/Integrations/header.tsx @@ -6,7 +6,7 @@ import { forwardRef, useRef } from 'react' import { useParams } from 'common' import { INTEGRATIONS } from 'components/interfaces/Integrations/Landing/Integrations.constants' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Badge, cn } from 'ui' interface HeaderProps { @@ -17,7 +17,7 @@ export const Header = forwardRef(({ scroll }, ref) const router = useRouter() const { id } = useParams() // Get project context - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() // Find the integration details based on ID const integration = INTEGRATIONS.find((i) => i.id === id) // Check if we're on the main integrations page diff --git a/apps/studio/components/layouts/Integrations/layout.tsx b/apps/studio/components/layouts/Integrations/layout.tsx index 1d7691dda01..10ed88f9571 100644 --- a/apps/studio/components/layouts/Integrations/layout.tsx +++ b/apps/studio/components/layouts/Integrations/layout.tsx @@ -9,7 +9,7 @@ import { ProductMenu } from 'components/ui/ProductMenu' import { ProductMenuGroup } from 'components/ui/ProductMenu/ProductMenu.types' import ProductMenuItem from 'components/ui/ProductMenu/ProductMenuItem' import { useScroll } from 'framer-motion' -import { useSelectedProject, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import { useFlag } from 'hooks/ui/useFlag' import { Menu, Separator } from 'ui' @@ -32,7 +32,7 @@ const IntegrationsLayout = ({ ...props }: PropsWithChildren) => { * Top level layout */ const IntegrationTopHeaderLayout = ({ ...props }: PropsWithChildren) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const router = useRouter() // Refs for the main scrollable area and header const mainElementRef = useRef(null) diff --git a/apps/studio/components/layouts/Integrations/tabs.tsx b/apps/studio/components/layouts/Integrations/tabs.tsx index 00f5adb90b0..2bb36708ff4 100644 --- a/apps/studio/components/layouts/Integrations/tabs.tsx +++ b/apps/studio/components/layouts/Integrations/tabs.tsx @@ -6,8 +6,8 @@ import { ComponentProps, ComponentType, useRef } from 'react' import { useBreakpoint, useParams } from 'common' import { INTEGRATIONS } from 'components/interfaces/Integrations/Landing/Integrations.constants' import { useInstalledIntegrations } from 'components/interfaces/Integrations/Landing/useInstalledIntegrations' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { cn, NavMenu, NavMenuItem } from 'ui' -import { useProjectContext } from '../ProjectLayout/ProjectContext' const MotionNavMenu = motion(NavMenu) as ComponentType & MotionProps> @@ -24,7 +24,7 @@ interface IntegrationTabsProps { export const IntegrationTabs = ({ scroll, isSticky }: IntegrationTabsProps) => { const navRef = useRef(null) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { id, pageId, childId, childLabel } = useParams() const isMobile = useBreakpoint('md') diff --git a/apps/studio/components/layouts/OrganizationLayout.tsx b/apps/studio/components/layouts/OrganizationLayout.tsx index c222ce03b0f..5df44aa907e 100644 --- a/apps/studio/components/layouts/OrganizationLayout.tsx +++ b/apps/studio/components/layouts/OrganizationLayout.tsx @@ -4,12 +4,12 @@ import { type PropsWithChildren } from 'react' import PartnerIcon from 'components/ui/PartnerIcon' import { PARTNER_TO_NAME } from 'components/ui/PartnerManagedResource' import { useVercelRedirectQuery } from 'data/integrations/vercel-redirect-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { withAuth } from 'hooks/misc/withAuth' import { Alert_Shadcn_, AlertTitle_Shadcn_, Button, cn } from 'ui' const OrganizationLayoutContent = ({ children }: PropsWithChildren<{}>) => { - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { data, isSuccess } = useVercelRedirectQuery({ installationId: selectedOrganization?.partner_id, }) diff --git a/apps/studio/components/layouts/ProjectLayout/BuildingState.tsx b/apps/studio/components/layouts/ProjectLayout/BuildingState.tsx index 76b8f85771c..f8ec5d42971 100644 --- a/apps/studio/components/layouts/ProjectLayout/BuildingState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/BuildingState.tsx @@ -10,13 +10,13 @@ import { DisplayApiSettings, DisplayConfigSettings } from 'components/ui/Project import { invalidateProjectDetailsQuery } from 'data/projects/project-detail-query' import { useProjectStatusQuery } from 'data/projects/project-status-query' import { invalidateProjectsQuery } from 'data/projects/projects-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { Badge, Button } from 'ui' const BuildingState = () => { const { ref } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const queryClient = useQueryClient() useProjectStatusQuery( diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx index 56cb0904912..91e2e2fd607 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/FeedbackDropdown/FeedbackWidget.tsx @@ -12,7 +12,7 @@ import { InlineLink } from 'components/ui/InlineLink' import { useFeedbackCategoryQuery } from 'data/feedback/feedback-category' import { useSendFeedbackMutation } from 'data/feedback/feedback-send' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { timeout } from 'lib/helpers' import { Button, @@ -47,7 +47,7 @@ export const FeedbackWidget = ({ const router = useRouter() const { ref, slug } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const uploadButtonRef = useRef(null) const [isSending, setSending] = useState(false) diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx index 8a658f4baf8..ca6289ea9d7 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HelpPopover.tsx @@ -6,7 +6,8 @@ import SVG from 'react-inlinesvg' import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { AiIconAnimation, @@ -18,12 +19,11 @@ import { PopoverTrigger_Shadcn_, Popover_Shadcn_, } from 'ui' -import { useProjectContext } from '../ProjectContext' export const HelpPopover = () => { const router = useRouter() - const { project } = useProjectContext() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const snap = useAiAssistantStateSnapshot() const { mutate: sendEvent } = useSendEventMutation() diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx index 3d854490469..aaed9c2cc79 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/HomeIcon.tsx @@ -5,11 +5,11 @@ import { useRouter } from 'next/router' import { LOCAL_STORAGE_KEYS } from 'common' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' export const HomeIcon = () => { - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { data: organizations } = useOrganizationsQuery() const router = useRouter() diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index 83eb677a997..17ca647da39 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -14,8 +14,8 @@ import { OrganizationDropdown } from 'components/layouts/AppLayout/OrganizationD import { ProjectDropdown } from 'components/layouts/AppLayout/ProjectDropdown' import { getResourcesExceededLimitsOrg } from 'components/ui/OveragesBanner/OveragesBanner.utils' import { useOrgUsageQuery } from 'data/usage/org-usage-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { IS_PLATFORM } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' import { Badge, cn } from 'ui' @@ -59,8 +59,8 @@ const LayoutHeader = ({ showProductMenu, }: LayoutHeaderProps) => { const { ref: projectRef, slug } = useParams() - const selectedProject = useSelectedProject() - const selectedOrganization = useSelectedOrganization() + const { data: selectedProject } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { setMobileMenuOpen } = useAppStateSnapshot() const gitlessBranching = useIsBranching2Enabled() diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/MergeRequestButton.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/MergeRequestButton.tsx index 977dd1bf517..5e1adb2c95a 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/MergeRequestButton.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/MergeRequestButton.tsx @@ -1,19 +1,20 @@ -import { ButtonTooltip } from 'components/ui/ButtonTooltip' import { GitMerge } from 'lucide-react' -import { useBranchesQuery } from 'data/branches/branches-query' -import { useParams } from 'common' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { useRouter } from 'next/router' -import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' -import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { toast } from 'sonner' +import { useParams } from 'common' +import { ButtonTooltip } from 'components/ui/ButtonTooltip' +import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation' +import { useBranchesQuery } from 'data/branches/branches-query' +import { useSendEventMutation } from 'data/telemetry/send-event-mutation' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' + export const MergeRequestButton = () => { const { ref } = useParams() const router = useRouter() - const projectDetails = useSelectedProject() - const selectedOrg = useSelectedOrganization() + const { data: projectDetails } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const projectRef = projectDetails?.parent_project_ref || ref diff --git a/apps/studio/components/layouts/ProjectLayout/PauseFailedState.tsx b/apps/studio/components/layouts/ProjectLayout/PauseFailedState.tsx index 63caa017d88..0ba928c7ed5 100644 --- a/apps/studio/components/layouts/ProjectLayout/PauseFailedState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/PauseFailedState.tsx @@ -10,12 +10,12 @@ import { DropdownMenuItemTooltip } from 'components/ui/DropdownMenuItemTooltip' import { useBackupDownloadMutation } from 'data/database/backup-download-mutation' import { useDownloadableBackupQuery } from 'data/database/backup-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, CriticalIcon, DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from 'ui' -import { useProjectContext } from './ProjectContext' const PauseFailedState = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [visible, setVisible] = useState(false) const canDeleteProject = useCheckPermissions(PermissionAction.UPDATE, 'projects', { diff --git a/apps/studio/components/layouts/ProjectLayout/PausedState/PauseDisabledState.tsx b/apps/studio/components/layouts/ProjectLayout/PausedState/PauseDisabledState.tsx index 4cc32d6c1e0..3fe78430a09 100644 --- a/apps/studio/components/layouts/ProjectLayout/PausedState/PauseDisabledState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/PausedState/PauseDisabledState.tsx @@ -8,6 +8,7 @@ import { useBackupDownloadMutation } from 'data/database/backup-download-mutatio import { useProjectPauseStatusQuery } from 'data/projects/project-pause-status-query' import { useStorageArchiveCreateMutation } from 'data/storage/storage-archive-create-mutation' import { useStorageArchiveQuery } from 'data/storage/storage-archive-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Database, Storage } from 'icons' import { PROJECT_STATUS } from 'lib/constants' import { @@ -21,11 +22,10 @@ import { DropdownMenuTrigger, WarningIcon, } from 'ui' -import { useProjectContext } from '../ProjectContext' export const PauseDisabledState = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [toastId, setToastId] = useState() const [refetchInterval, setRefetchInterval] = useState(false) diff --git a/apps/studio/components/layouts/ProjectLayout/PausedState/ProjectPausedState.tsx b/apps/studio/components/layouts/ProjectLayout/PausedState/ProjectPausedState.tsx index f684b37369e..dcfc4bb4c9b 100644 --- a/apps/studio/components/layouts/ProjectLayout/PausedState/ProjectPausedState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/PausedState/ProjectPausedState.tsx @@ -19,7 +19,8 @@ import { useProjectPauseStatusQuery } from 'data/projects/project-pause-status-q import { useProjectRestoreMutation } from 'data/projects/project-restore-mutation' import { setProjectStatus } from 'data/projects/projects-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useFlag, usePHFlag } from 'hooks/ui/useFlag' import { PROJECT_STATUS } from 'lib/constants' import { AWS_REGIONS, CloudProvider } from 'shared-data' @@ -33,7 +34,6 @@ import { Modal, } from 'ui' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' -import { useProjectContext } from '../ProjectContext' import { RestorePaidPlanProjectNotice } from '../RestorePaidPlanProjectNotice' import { PauseDisabledState } from './PauseDisabledState' @@ -54,8 +54,8 @@ export const extractPostgresVersionDetails = (value: string): PostgresVersionDet export const ProjectPausedState = ({ product }: ProjectPausedStateProps) => { const { ref } = useParams() const queryClient = useQueryClient() - const { project } = useProjectContext() - const selectedOrganization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const showPostgresVersionSelector = useFlag('showPostgresVersionSelector') const enableProBenefitWording = usePHFlag('proBenefitWording') diff --git a/apps/studio/components/layouts/ProjectLayout/ProjectContext.tsx b/apps/studio/components/layouts/ProjectLayout/ProjectContext.tsx index a3da2c23ed9..93626e0d1a0 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProjectContext.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProjectContext.tsx @@ -1,6 +1,6 @@ -import { createContext, PropsWithChildren, useContext, useMemo } from 'react' +import { PropsWithChildren } from 'react' -import { Project, useProjectDetailQuery } from 'data/projects/project-detail-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { AiAssistantStateContextProvider } from 'state/ai-assistant-state' import { DatabaseSelectorStateContextProvider } from 'state/database-selector' @@ -9,20 +9,6 @@ import { StorageExplorerStateContextProvider } from 'state/storage-explorer' import { TableEditorStateContextProvider } from 'state/table-editor' import { TabsStateContextProvider } from 'state/tabs' -export interface ProjectContextType { - project?: Project - isLoading: boolean -} - -const ProjectContext = createContext({ - project: undefined, - isLoading: true, -}) - -export default ProjectContext - -export const useProjectContext = () => useContext(ProjectContext) - type ProjectContextProviderProps = { projectRef: string | undefined } @@ -31,37 +17,24 @@ export const ProjectContextProvider = ({ projectRef, children, }: PropsWithChildren) => { - const { data: selectedProject, isLoading } = useProjectDetailQuery({ ref: projectRef }) - - const value = useMemo(() => { - return { - project: selectedProject, - isLoading: isLoading, - } - }, [selectedProject, isLoading]) - return ( - - - - - - - - {children} - - - - - - - + + + + + + + {children} + + + + + + ) } export const useIsProjectActive = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() return project?.status === PROJECT_STATUS.ACTIVE_HEALTHY } diff --git a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx index 3675e8f9dee..831d3c0a021 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx @@ -11,7 +11,7 @@ import { EditorPanel } from 'components/ui/EditorPanel/EditorPanel' import { Loading } from 'components/ui/Loading' import { ResourceExhaustionWarningBanner } from 'components/ui/ResourceExhaustionWarningBanner/ResourceExhaustionWarningBanner' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import { PROJECT_STATUS } from 'lib/constants' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' @@ -298,7 +298,7 @@ const MenuBarWrapper = ({ children, }: MenuBarWrapperProps) => { const router = useRouter() - const selectedProject = useSelectedProject() + const { data: selectedProject } = useSelectedProjectQuery() const requiresProjectDetails = !routesToIgnoreProjectDetailsRequest.includes(router.pathname) if (!isBlocking) { @@ -333,7 +333,7 @@ const ContentWrapper = ({ isLoading, isBlocking = true, children }: ContentWrapp const router = useRouter() const { ref } = useParams() const state = useDatabaseSelectorStateSnapshot() - const selectedProject = useSelectedProject() + const { data: selectedProject } = useSelectedProjectQuery() const isBranchesPage = router.pathname.includes('/project/[ref]/branches') const isSettingsPages = router.pathname.includes('/project/[ref]/settings') diff --git a/apps/studio/components/layouts/ProjectLayout/RestoreFailedState.tsx b/apps/studio/components/layouts/ProjectLayout/RestoreFailedState.tsx index bf20923f157..9120f3b2f4d 100644 --- a/apps/studio/components/layouts/ProjectLayout/RestoreFailedState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/RestoreFailedState.tsx @@ -10,12 +10,12 @@ import { DropdownMenuItemTooltip } from 'components/ui/DropdownMenuItemTooltip' import { useBackupDownloadMutation } from 'data/database/backup-download-mutation' import { useDownloadableBackupQuery } from 'data/database/backup-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { Button, CriticalIcon, DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from 'ui' -import { useProjectContext } from './ProjectContext' const RestoreFailedState = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [visible, setVisible] = useState(false) const canDeleteProject = useCheckPermissions(PermissionAction.UPDATE, 'projects', { diff --git a/apps/studio/components/layouts/ProjectLayout/RestoringState.tsx b/apps/studio/components/layouts/ProjectLayout/RestoringState.tsx index f6a4517eb23..7dc8355934b 100644 --- a/apps/studio/components/layouts/ProjectLayout/RestoringState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/RestoringState.tsx @@ -9,14 +9,14 @@ import { useBackupDownloadMutation } from 'data/database/backup-download-mutatio import { useDownloadableBackupQuery } from 'data/database/backup-query' import { invalidateProjectDetailsQuery } from 'data/projects/project-detail-query' import { useProjectStatusQuery } from 'data/projects/project-status-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { Button } from 'ui' -import { useProjectContext } from './ProjectContext' const RestoringState = () => { const { ref } = useParams() const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [loading, setLoading] = useState(false) const [isCompleted, setIsCompleted] = useState(false) diff --git a/apps/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx b/apps/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx index cafd0cd04ab..199e42864e7 100644 --- a/apps/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx +++ b/apps/studio/components/layouts/ProjectLayout/UpgradingState/UpgradingState.tsx @@ -18,16 +18,16 @@ import { useState } from 'react' import { useParams } from 'common' import { useProjectUpgradingStatusQuery } from 'data/config/project-upgrade-status-query' import { invalidateProjectDetailsQuery } from 'data/projects/project-detail-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { IS_PLATFORM } from 'lib/constants' import { Button, Tooltip, TooltipContent, TooltipTrigger } from 'ui' -import { useProjectContext } from '../ProjectContext' import { DATABASE_UPGRADE_MESSAGES } from './UpgradingState.constants' const UpgradingState = () => { const { ref } = useParams() const queryParams = useSearchParams() const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [loading, setLoading] = useState(false) const [isExpanded, setIsExpanded] = useState(false) const { data } = useProjectUpgradingStatusQuery( diff --git a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx index 574556e5097..b3a56eb2f7b 100644 --- a/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx +++ b/apps/studio/components/layouts/ProjectSettingsLayout/SettingsLayout.tsx @@ -4,8 +4,8 @@ import { PropsWithChildren, useEffect } from 'react' import { useParams } from 'common' import { ProductMenu } from 'components/ui/ProductMenu' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import { IS_PLATFORM } from 'lib/constants' import ProjectLayout from '../ProjectLayout/ProjectLayout' @@ -18,8 +18,8 @@ interface SettingsLayoutProps { const SettingsLayout = ({ title, children }: PropsWithChildren) => { const router = useRouter() const { ref } = useParams() - const project = useSelectedProject() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() useEffect(() => { if (!IS_PLATFORM) { diff --git a/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx b/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx index 8da40366074..e4cef928a73 100644 --- a/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx +++ b/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx @@ -3,7 +3,7 @@ import { PropsWithChildren } from 'react' import { useIsRealtimeSettingsEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext' import { ProductMenu } from 'components/ui/ProductMenu' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { withAuth } from 'hooks/misc/withAuth' import { useIsRealtimeSettingsFFEnabled } from 'hooks/ui/useFlag' import ProjectLayout from '../ProjectLayout/ProjectLayout' @@ -14,7 +14,7 @@ export interface RealtimeLayoutProps { } const RealtimeLayout = ({ title, children }: PropsWithChildren) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const enableRealtimeSettingsFF = useIsRealtimeSettingsFFEnabled() const enableRealtimeSettingsFP = useIsRealtimeSettingsEnabled() diff --git a/apps/studio/components/layouts/SQLEditorLayout/SqlEditor.Commands.tsx b/apps/studio/components/layouts/SQLEditorLayout/SqlEditor.Commands.tsx index efd0981dd29..512bc97ec97 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/SqlEditor.Commands.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/SqlEditor.Commands.tsx @@ -10,7 +10,7 @@ import { orderCommandSectionsByPriority } from 'components/interfaces/App/Comman import { useSqlSnippetsQuery, type SqlSnippet } from 'data/content/sql-snippets-query' import { usePrefetchTables, useTablesQuery, type TablesData } from 'data/tables/tables-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProtectedSchemas } from 'hooks/useProtectedSchemas' import { useProfile } from 'lib/profile' import { @@ -59,7 +59,7 @@ export function useSqlEditorGotoCommands(options?: CommandOptions) { const SNIPPET_PAGE_NAME = 'Snippets' export function useSnippetCommands() { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const setPage = useSetPage() useRegisterPage( @@ -251,7 +251,7 @@ function snippetValue(snippet: SqlSnippet) { const QUERY_TABLE_PAGE_NAME = 'Query a table' export function useQueryTableCommands(options?: CommandOptions) { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const setPage = useSetPage() const commandMenuOpen = useCommandMenuOpen() @@ -294,7 +294,7 @@ export function useQueryTableCommands(options?: CommandOptions) { function TableSelector() { const router = useRouter() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data: protectedSchemas } = useProtectedSchemas() const { data: tablesData, diff --git a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx index c8ee912c07f..c2e9ebd021b 100644 --- a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx @@ -25,6 +25,7 @@ import { getTableEditor } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' import { fetchAllTableRows } from 'data/table-rows/table-rows-query' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { formatSql } from 'lib/formatSql' import { useTableEditorStateSnapshot } from 'state/table-editor' import { createTabId, useTabsStateSnapshot } from 'state/tabs' @@ -46,7 +47,6 @@ import { TooltipTrigger, TreeViewItemVariant, } from 'ui' -import { useProjectContext } from '../ProjectLayout/ProjectContext' export interface EntityListItemProps { id: number | string @@ -69,7 +69,7 @@ const EntityListItem: ItemRenderer = ({ isActive: _isActive, onExportCLI, }) => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const snap = useTableEditorStateSnapshot() const { selectedSchema } = useQuerySchemaState() diff --git a/apps/studio/components/layouts/TableEditorLayout/TableEditor.Commands.tsx b/apps/studio/components/layouts/TableEditorLayout/TableEditor.Commands.tsx index 7d865165764..3207b4f872f 100644 --- a/apps/studio/components/layouts/TableEditorLayout/TableEditor.Commands.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/TableEditor.Commands.tsx @@ -3,12 +3,12 @@ import { Table2 } from 'lucide-react' import { useParams } from 'common' import { COMMAND_MENU_SECTIONS } from 'components/interfaces/App/CommandMenu/CommandMenu.utils' import { orderCommandSectionsByPriority } from 'components/interfaces/App/CommandMenu/ordering' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { CommandOptions } from 'ui-patterns/CommandMenu' import { useRegisterCommands } from 'ui-patterns/CommandMenu' export function useProjectLevelTableEditorCommands(options?: CommandOptions) { - let project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const ref = project?.ref || '_' useRegisterCommands( diff --git a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx index bc97706c627..6d6c2c19d93 100644 --- a/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx @@ -19,6 +19,7 @@ import { getTableEditor, useTableEditorQuery } from 'data/table-editor/table-edi import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useLocalStorage } from 'hooks/misc/useLocalStorage' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { useTableEditorStateSnapshot } from 'state/table-editor' import { @@ -36,7 +37,6 @@ import { InnerSideBarFilterSortDropdownItem, InnerSideBarFilters, } from 'ui-patterns/InnerSideMenu' -import { useProjectContext } from '../ProjectLayout/ProjectContext' import { useTableEditorTabsCleanUp } from '../Tabs/Tabs.utils' import EntityListItem from './EntityListItem' import { TableMenuEmptyState } from './TableMenuEmptyState' @@ -56,7 +56,7 @@ export const TableEditorMenu = () => { 'alphabetical' ) - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data, isLoading, diff --git a/apps/studio/components/layouts/Tabs/NewTab.tsx b/apps/studio/components/layouts/Tabs/NewTab.tsx index 8afcfe3bd4d..2170a76ee3c 100644 --- a/apps/studio/components/layouts/Tabs/NewTab.tsx +++ b/apps/studio/components/layouts/Tabs/NewTab.tsx @@ -10,7 +10,8 @@ import { SQL_TEMPLATES } from 'components/interfaces/SQLEditor/SQLEditor.queries import { createSqlSnippetSkeletonV2 } from 'components/interfaces/SQLEditor/SQLEditor.utils' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' @@ -26,7 +27,6 @@ import { TabsTrigger_Shadcn_, } from 'ui' import { useEditorType } from '../editors/EditorsLayout.hooks' -import { useProjectContext } from '../ProjectLayout/ProjectContext' import { ActionCard } from './ActionCard' import { RecentItems } from './RecentItems' @@ -35,8 +35,8 @@ export function NewTab() { const { ref } = useParams() const editor = useEditorType() const { profile } = useProfile() - const org = useSelectedOrganization() - const { project } = useProjectContext() + const { data: org } = useSelectedOrganizationQuery() + const { data: project } = useSelectedProjectQuery() const snap = useTableEditorStateSnapshot() const snapV2 = useSqlEditorV2StateSnapshot() diff --git a/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx b/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx index 945b8544a0d..167131a73f6 100644 --- a/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx @@ -14,8 +14,8 @@ import { useTablesQuery } from 'data/tables/tables-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' import { useOrgAiOptInLevel } from 'hooks/misc/useOrgOptedIntoAi' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useFlag } from 'hooks/ui/useFlag' import { BASE_PATH, IS_PLATFORM } from 'lib/constants' import uuidv4 from 'lib/uuid' @@ -75,8 +75,8 @@ interface AIAssistantProps { export const AIAssistant = ({ className }: AIAssistantProps) => { const router = useRouter() - const project = useSelectedProject() - const selectedOrganization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { ref, id: entityId } = useParams() const searchParams = useSearchParamsShallow() diff --git a/apps/studio/components/ui/AIAssistantPanel/DisplayBlockRenderer.tsx b/apps/studio/components/ui/AIAssistantPanel/DisplayBlockRenderer.tsx index 72592a6d443..81626c4c28f 100644 --- a/apps/studio/components/ui/AIAssistantPanel/DisplayBlockRenderer.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/DisplayBlockRenderer.tsx @@ -7,7 +7,7 @@ import { useParams } from 'common' import { ChartConfig } from 'components/interfaces/SQLEditor/UtilityPanel/ChartConfig' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useProfile } from 'lib/profile' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { Badge } from 'ui' @@ -44,7 +44,7 @@ export const DisplayBlockRenderer = ({ const router = useRouter() const { ref } = useParams() const { profile } = useProfile() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const snap = useAiAssistantStateSnapshot() const { mutate: sendEvent } = useSendEventMutation() diff --git a/apps/studio/components/ui/AIAssistantPanel/MessageMarkdown.tsx b/apps/studio/components/ui/AIAssistantPanel/MessageMarkdown.tsx index 8575b46fd3a..4d98316feb8 100644 --- a/apps/studio/components/ui/AIAssistantPanel/MessageMarkdown.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/MessageMarkdown.tsx @@ -14,8 +14,8 @@ import { import { ChartConfig } from 'components/interfaces/SQLEditor/UtilityPanel/ChartConfig' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useProfile } from 'lib/profile' import Link from 'next/link' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' @@ -229,8 +229,8 @@ export const MarkdownPre = ({ const { isLoading, readOnly } = useContext(MessageContext) const { mutate: sendEvent } = useSendEventMutation() const snap = useAiAssistantStateSnapshot() - const project = useSelectedProject() - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const canCreateSQLSnippet = useCheckPermissions(PermissionAction.CREATE, 'user_content', { resource: { type: 'sql', owner_id: profile?.id }, diff --git a/apps/studio/components/ui/CodeEditor/CodeEditor.tsx b/apps/studio/components/ui/CodeEditor/CodeEditor.tsx index 9b5a8eb2c1a..90532d12041 100644 --- a/apps/studio/components/ui/CodeEditor/CodeEditor.tsx +++ b/apps/studio/components/ui/CodeEditor/CodeEditor.tsx @@ -4,7 +4,7 @@ import { editor } from 'monaco-editor' import { MutableRefObject, useEffect, useRef, useState } from 'react' import { Markdown } from 'components/interfaces/Markdown' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { formatSql } from 'lib/formatSql' import { timeout } from 'lib/helpers' import { cn } from 'ui' @@ -61,7 +61,7 @@ const CodeEditor = ({ onInputChange = noop, }: CodeEditorProps) => { const monaco = useMonaco() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const hasValue = useRef() const ref = useRef() diff --git a/apps/studio/components/ui/EdgeFunctionBlock/EdgeFunctionBlock.tsx b/apps/studio/components/ui/EdgeFunctionBlock/EdgeFunctionBlock.tsx index 798b6390697..56ed55caff4 100644 --- a/apps/studio/components/ui/EdgeFunctionBlock/EdgeFunctionBlock.tsx +++ b/apps/studio/components/ui/EdgeFunctionBlock/EdgeFunctionBlock.tsx @@ -9,7 +9,7 @@ import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query import { useEdgeFunctionQuery } from 'data/edge-functions/edge-function-query' import { useEdgeFunctionDeployMutation } from 'data/edge-functions/edge-functions-deploy-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { Button, cn, CodeBlock, CodeBlockLang } from 'ui' import { Admonition } from 'ui-patterns' @@ -47,7 +47,7 @@ export const EdgeFunctionBlock = ({ const { data: existingFunction } = useEdgeFunctionQuery({ projectRef: ref, slug: functionName }) const { mutate: sendEvent } = useSendEventMutation() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutateAsync: deployFunction, isLoading: isDeploying } = useEdgeFunctionDeployMutation({ onSuccess: () => { diff --git a/apps/studio/components/ui/EditorPanel/EditorPanel.tsx b/apps/studio/components/ui/EditorPanel/EditorPanel.tsx index 0694fca9bdd..62d593fbab3 100644 --- a/apps/studio/components/ui/EditorPanel/EditorPanel.tsx +++ b/apps/studio/components/ui/EditorPanel/EditorPanel.tsx @@ -13,7 +13,7 @@ import { SqlRunButton } from 'components/interfaces/SQLEditor/UtilityPanel/RunBu import { useSqlTitleGenerateMutation } from 'data/ai/sql-title-mutation' import { QueryResponseError, useExecuteSqlMutation } from 'data/sql/execute-sql-mutation' import { useOrgAiOptInLevel } from 'hooks/misc/useOrgOptedIntoAi' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' @@ -50,7 +50,7 @@ interface EditorPanelProps { export const EditorPanel = ({ onChange }: EditorPanelProps) => { const { ref } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { editorPanel, setEditorPanel } = useAppStateSnapshot() const { profile } = useProfile() const snapV2 = useSqlEditorV2StateSnapshot() diff --git a/apps/studio/components/ui/FunctionSelector.tsx b/apps/studio/components/ui/FunctionSelector.tsx index eb39782dc2b..8eb073f80d6 100644 --- a/apps/studio/components/ui/FunctionSelector.tsx +++ b/apps/studio/components/ui/FunctionSelector.tsx @@ -2,11 +2,13 @@ import { uniqBy } from 'lodash' import { Check, ChevronsUpDown, Plus } from 'lucide-react' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import { useParams } from 'common' import { DatabaseFunctionsData, useDatabaseFunctionsQuery, } from 'data/database-functions/database-functions-query' +import Link from 'next/link' +import { useRouter } from 'next/router' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -24,9 +26,7 @@ import { Popover_Shadcn_, ScrollArea, } from 'ui' -import { useRouter } from 'next/router' -import Link from 'next/link' -import { useParams } from 'common' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' type DatabaseFunction = DatabaseFunctionsData[number] @@ -56,7 +56,7 @@ const FunctionSelector = ({ }: FunctionSelectorProps) => { const router = useRouter() const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [open, setOpen] = useState(false) const { data, error, isLoading, isError, isSuccess, refetch } = useDatabaseFunctionsQuery({ diff --git a/apps/studio/components/ui/GrafanaPromoBanner.tsx b/apps/studio/components/ui/GrafanaPromoBanner.tsx index 17b73b163e4..22598234352 100644 --- a/apps/studio/components/ui/GrafanaPromoBanner.tsx +++ b/apps/studio/components/ui/GrafanaPromoBanner.tsx @@ -1,11 +1,10 @@ -import React from 'react' -import Link from 'next/link' import { useParams } from 'common' -import { BookOpen } from 'lucide-react' -import { Alert_Shadcn_, AlertTitle_Shadcn_, AlertDescription_Shadcn_, cn, Button } from 'ui' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { BASE_PATH } from 'lib/constants' +import { BookOpen } from 'lucide-react' +import Link from 'next/link' +import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, Button, cn } from 'ui' const GrafanaPromoBanner = () => ( @@ -52,7 +51,7 @@ const GrafanaPromoBanner = () => ( const GrafanaBannerActions = ({ className }: { className?: string }) => { const { ref } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() return ( diff --git a/apps/studio/components/ui/GroupsTelemetry.tsx b/apps/studio/components/ui/GroupsTelemetry.tsx index d138179ec2e..c6477f8c4d5 100644 --- a/apps/studio/components/ui/GroupsTelemetry.tsx +++ b/apps/studio/components/ui/GroupsTelemetry.tsx @@ -7,7 +7,7 @@ import { LOCAL_STORAGE_KEYS, useParams, useTelemetryCookie, useUser } from 'comm import { useSendGroupsIdentifyMutation } from 'data/telemetry/send-groups-identify-mutation' import { useSendGroupsResetMutation } from 'data/telemetry/send-groups-reset-mutation' import { usePrevious } from 'hooks/deprecated' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' const getAnonId = async (id: string) => { @@ -28,7 +28,7 @@ const GroupsTelemetry = ({ hasAcceptedConsent }: { hasAcceptedConsent: boolean } const user = useUser() const router = useRouter() const { ref, slug } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const previousPathname = usePrevious(router.pathname) diff --git a/apps/studio/components/ui/ProjectSettings/ToggleLegacyApiKeys.tsx b/apps/studio/components/ui/ProjectSettings/ToggleLegacyApiKeys.tsx index c0a4698dc8d..19b67e34cc1 100644 --- a/apps/studio/components/ui/ProjectSettings/ToggleLegacyApiKeys.tsx +++ b/apps/studio/components/ui/ProjectSettings/ToggleLegacyApiKeys.tsx @@ -9,7 +9,7 @@ import { useLegacyAPIKeysStatusQuery } from 'data/api-keys/legacy-api-keys-statu import { useLegacyJWTSigningKeyQuery } from 'data/jwt-signing-keys/legacy-jwt-signing-key-query' import { useAuthorizedAppsQuery } from 'data/oauth/authorized-apps-query' import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { AlertDialog, AlertDialogAction, @@ -25,7 +25,7 @@ import Panel from '../Panel' export const ToggleLegacyApiKeysPanel = () => { const { ref: projectRef } = useParams() - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const [isConfirmOpen, setIsConfirmOpen] = useState(false) const [isAppsWarningOpen, setIsAppsWarningOpen] = useState(false) diff --git a/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx b/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx index 19cabf19ab1..8559432226d 100644 --- a/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx +++ b/apps/studio/components/ui/QueryBlock/EditQueryButton.tsx @@ -6,7 +6,7 @@ import { useIsInlineEditorEnabled } from 'components/interfaces/App/FeaturePrevi import { DiffType } from 'components/interfaces/SQLEditor/SQLEditor.types' import useNewQuery from 'components/interfaces/SQLEditor/hooks' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import Link from 'next/link' import { ComponentProps } from 'react' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' @@ -52,7 +52,7 @@ export const EditQueryButton = ({ content: { side: 'bottom', text: 'Edit in SQL Editor' }, } - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { mutate: sendEvent } = useSendEventMutation() if (id !== undefined) { diff --git a/apps/studio/components/ui/SchemaComboBox.tsx b/apps/studio/components/ui/SchemaComboBox.tsx index f4810f6df7c..42a409afdab 100644 --- a/apps/studio/components/ui/SchemaComboBox.tsx +++ b/apps/studio/components/ui/SchemaComboBox.tsx @@ -1,8 +1,8 @@ import { Check, ChevronsUpDown } from 'lucide-react' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useSchemasQuery } from 'data/database/schemas-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -19,7 +19,6 @@ import { Popover_Shadcn_, ScrollArea, } from 'ui' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' interface SchemaComboBoxProps { className?: string @@ -45,7 +44,7 @@ export const SchemaComboBox = ({ }: SchemaComboBoxProps) => { const [open, setOpen] = useState(false) - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const { data, isLoading: isSchemasLoading, diff --git a/apps/studio/components/ui/SchemaSelector.tsx b/apps/studio/components/ui/SchemaSelector.tsx index 2d17e6dc51e..d11e97581f0 100644 --- a/apps/studio/components/ui/SchemaSelector.tsx +++ b/apps/studio/components/ui/SchemaSelector.tsx @@ -2,9 +2,9 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { Check, ChevronsUpDown, Plus } from 'lucide-react' import { useState } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useSchemasQuery } from 'data/database/schemas-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, @@ -52,7 +52,7 @@ const SchemaSelector = ({ const [open, setOpen] = useState(false) const canCreateSchemas = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'schemas') - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data, isLoading: isSchemasLoading, diff --git a/apps/studio/components/ui/SqlEditor.tsx b/apps/studio/components/ui/SqlEditor.tsx index 1a85ebb2939..cd73a9438f6 100644 --- a/apps/studio/components/ui/SqlEditor.tsx +++ b/apps/studio/components/ui/SqlEditor.tsx @@ -2,7 +2,6 @@ import Editor, { OnChange, useMonaco } from '@monaco-editor/react' import { noop } from 'lodash' import { useEffect, useRef } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { formatSql } from 'lib/formatSql' // [Joshen] We should deprecate this and use CodeEditor instead @@ -28,7 +27,6 @@ const SqlEditor = ({ onInputChange = noop, }: SqlEditorProps) => { const monaco = useMonaco() - const { project } = useProjectContext() const editorRef = useRef() useEffect(() => { diff --git a/apps/studio/components/ui/UpgradeToPro.tsx b/apps/studio/components/ui/UpgradeToPro.tsx index a98778b7f39..e3576c27226 100644 --- a/apps/studio/components/ui/UpgradeToPro.tsx +++ b/apps/studio/components/ui/UpgradeToPro.tsx @@ -3,8 +3,8 @@ import Link from 'next/link' import { ReactNode } from 'react' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useFlag } from 'hooks/ui/useFlag' import { Button, cn } from 'ui' import { ButtonTooltip } from './ButtonTooltip' @@ -28,8 +28,8 @@ const UpgradeToPro = ({ source = 'upgrade', disabled = false, }: UpgradeToProProps) => { - const project = useSelectedProject() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const plan = organization?.plan?.id const canUpdateSubscription = useCheckPermissions( diff --git a/apps/studio/data/auth/users-infinite-query.ts b/apps/studio/data/auth/users-infinite-query.ts index 5f009a10d60..f64d68f7711 100644 --- a/apps/studio/data/auth/users-infinite-query.ts +++ b/apps/studio/data/auth/users-infinite-query.ts @@ -2,7 +2,7 @@ import { useInfiniteQuery, UseInfiniteQueryOptions } from '@tanstack/react-query import type { components } from 'data/api' import { executeSql, ExecuteSqlError } from 'data/sql/execute-sql-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { authKeys } from './keys' @@ -91,7 +91,7 @@ export const useUsersInfiniteQuery = ( { projectRef, connectionString, keywords, filter, providers, sort, order }: UsersVariables, { enabled = true, ...options }: UseInfiniteQueryOptions = {} ) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY return useInfiniteQuery( diff --git a/apps/studio/data/config/project-upgrade-eligibility-query.ts b/apps/studio/data/config/project-upgrade-eligibility-query.ts index f63fb0d4629..4515776f210 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 { components } from 'api-types' import { IS_PLATFORM } from 'common' import { get, handleError } from 'data/fetchers' -import { useProjectByRef } from 'hooks/misc/useSelectedProject' +import { useProjectByRefQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants/infrastructure' import type { ResponseError } from 'types' import { configKeys } from './keys' @@ -38,7 +38,7 @@ export const useProjectUpgradeEligibilityQuery = = {} ) => { - const project = useProjectByRef(projectRef) + const { data: project } = useProjectByRefQuery(projectRef) return useQuery( configKeys.upgradeEligibility(projectRef), ({ signal }) => getProjectUpgradeEligibility({ projectRef }, signal), diff --git a/apps/studio/data/database-extensions/database-extensions-query.ts b/apps/studio/data/database-extensions/database-extensions-query.ts index 76133e1dc17..5ea9faf1eba 100644 --- a/apps/studio/data/database-extensions/database-extensions-query.ts +++ b/apps/studio/data/database-extensions/database-extensions-query.ts @@ -1,11 +1,11 @@ +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' import { UseQueryOptions, useQuery } from '@tanstack/react-query' +import { components } from 'api-types' import { get, handleError } from 'data/fetchers' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' +import { PROJECT_STATUS } from 'lib/constants' import type { ResponseError } from 'types' import { databaseExtensionsKeys } from './keys' -import { components } from 'api-types' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' -import { PROJECT_STATUS } from 'lib/constants' -import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type DatabaseExtension = components['schemas']['PostgresExtension'] @@ -52,7 +52,7 @@ export const useDatabaseExtensionsQuery = ( ...options }: UseQueryOptions = {} ) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY return useQuery( diff --git a/apps/studio/data/database-policies/database-policies-query.ts b/apps/studio/data/database-policies/database-policies-query.ts index 291a263526e..f7de486f429 100644 --- a/apps/studio/data/database-policies/database-policies-query.ts +++ b/apps/studio/data/database-policies/database-policies-query.ts @@ -1,11 +1,11 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' import { get, handleError } from 'data/fetchers' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import type { ResponseError } from 'types' import { databasePoliciesKeys } from './keys' -import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type DatabasePoliciesVariables = { projectRef?: string @@ -53,7 +53,7 @@ export const useDatabasePoliciesQuery = ( ...options }: UseQueryOptions = {} ) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY return useQuery( diff --git a/apps/studio/data/lint/lint-query.ts b/apps/studio/data/lint/lint-query.ts index a342aafa23c..ca970d5d4e8 100644 --- a/apps/studio/data/lint/lint-query.ts +++ b/apps/studio/data/lint/lint-query.ts @@ -2,7 +2,7 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { components } from 'api-types' import { get, handleError } from 'data/fetchers' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { ResponseError } from 'types' import { lintKeys } from './keys' @@ -34,7 +34,7 @@ export const useProjectLintsQuery = ( { projectRef }: ProjectLintsVariables, { enabled = true, ...options }: UseQueryOptions = {} ) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY return useQuery( diff --git a/apps/studio/data/lint/lint-rules-query.ts b/apps/studio/data/lint/lint-rules-query.ts index 66d247ada3f..414a221b2ac 100644 --- a/apps/studio/data/lint/lint-rules-query.ts +++ b/apps/studio/data/lint/lint-rules-query.ts @@ -2,7 +2,7 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query' import { components } from 'api-types' import { get, handleError } from 'data/fetchers' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { ResponseError } from 'types' import { lintKeys } from './keys' @@ -39,7 +39,7 @@ export const useProjectLintRulesQuery = ( ...options }: UseQueryOptions = {} ) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY return useQuery( diff --git a/apps/studio/data/prefetchers/project.$ref.editor.$id.tsx b/apps/studio/data/prefetchers/project.$ref.editor.$id.tsx index fc22643e59a..3468fb8a62a 100644 --- a/apps/studio/data/prefetchers/project.$ref.editor.$id.tsx +++ b/apps/studio/data/prefetchers/project.$ref.editor.$id.tsx @@ -9,9 +9,9 @@ import { parseSupaTable, } from 'components/grid/SupabaseGrid.utils' import { Filter, Sort } from 'components/grid/types' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { prefetchTableEditor } from 'data/table-editor/table-editor-query' import { prefetchTableRows } from 'data/table-rows/table-rows-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { RoleImpersonationState } from 'lib/role-impersonation' import { useRoleImpersonationStateSnapshot } from 'state/role-impersonation-state' import { TABLE_EDITOR_DEFAULT_ROWS_PER_PAGE } from 'state/table-editor' @@ -64,7 +64,7 @@ export function prefetchEditorTablePage({ export function usePrefetchEditorTablePage() { const router = useRouter() const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const roleImpersonationState = useRoleImpersonationStateSnapshot() return useCallback( diff --git a/apps/studio/data/prefetchers/project.$ref.editor.tsx b/apps/studio/data/prefetchers/project.$ref.editor.tsx index 3fa3ca52c70..8efc57ea3c2 100644 --- a/apps/studio/data/prefetchers/project.$ref.editor.tsx +++ b/apps/studio/data/prefetchers/project.$ref.editor.tsx @@ -2,17 +2,17 @@ import { useQueryClient } from '@tanstack/react-query' import { useRouter } from 'next/router' import { PropsWithChildren, useCallback } from 'react' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { prefetchSchemas } from 'data/database/schemas-query' import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' import { prefetchEntityTypes } from 'data/entity-types/entity-types-infinite-query' import { useLocalStorage } from 'hooks/misc/useLocalStorage' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import PrefetchableLink, { PrefetchableLinkProps } from './PrefetchableLink' export function usePrefetchEditorIndexPage() { const router = useRouter() const queryClient = useQueryClient() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const [entityTypesSort] = useLocalStorage<'alphabetical' | 'grouped-alphabetical'>( 'table-editor-sort', diff --git a/apps/studio/data/reports/api-report-query.ts b/apps/studio/data/reports/api-report-query.ts index b3a1605df39..b005a1aaea6 100644 --- a/apps/studio/data/reports/api-report-query.ts +++ b/apps/studio/data/reports/api-report-query.ts @@ -6,11 +6,9 @@ import { PRESET_CONFIG } from 'components/interfaces/Reports/Reports.constants' import { ReportFilterItem } from 'components/interfaces/Reports/Reports.types' import { queriesFactory } from 'components/interfaces/Reports/Reports.utils' import type { LogsEndpointParams } from 'components/interfaces/Settings/Logs/Logs.types' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' export const useApiReport = () => { - const { project } = useProjectContext() const { ref: projectRef } = useParams() const state = useDatabaseSelectorStateSnapshot() diff --git a/apps/studio/data/sql/execute-sql-query.ts b/apps/studio/data/sql/execute-sql-query.ts index 65fe32a565b..50966f0bf7c 100644 --- a/apps/studio/data/sql/execute-sql-query.ts +++ b/apps/studio/data/sql/execute-sql-query.ts @@ -1,7 +1,8 @@ import { QueryKey, useQuery, UseQueryOptions } from '@tanstack/react-query' +import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' import { handleError as handleErrorFetchers, post } from 'data/fetchers' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { MB, PROJECT_STATUS } from 'lib/constants' import { ROLE_IMPERSONATION_NO_RESULTS, @@ -9,7 +10,6 @@ import { } from 'lib/role-impersonation' import type { ResponseError } from 'types' import { sqlKeys } from './keys' -import { DEFAULT_PLATFORM_APPLICATION_NAME } from '@supabase/pg-meta/src/constants' export type ExecuteSqlVariables = { projectRef?: string @@ -159,7 +159,7 @@ export const useExecuteSqlQuery = ( }: ExecuteSqlVariables, { enabled = true, ...options }: UseQueryOptions = {} ) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY return useQuery( diff --git a/apps/studio/data/storage/buckets-query.ts b/apps/studio/data/storage/buckets-query.ts index e26887d1a8f..814c9d941c4 100644 --- a/apps/studio/data/storage/buckets-query.ts +++ b/apps/studio/data/storage/buckets-query.ts @@ -2,7 +2,7 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' import { components } from 'api-types' import { get, handleError } from 'data/fetchers' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import type { ResponseError } from 'types' import { storageKeys } from './keys' @@ -32,7 +32,7 @@ export const useBucketsQuery = ( { projectRef }: BucketsVariables, { enabled = true, ...options }: UseQueryOptions = {} ) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isActive = project?.status === PROJECT_STATUS.ACTIVE_HEALTHY return useQuery( diff --git a/apps/studio/data/storage/iceberg-wrapper-create-mutation.ts b/apps/studio/data/storage/iceberg-wrapper-create-mutation.ts index 254297a3ca0..0601d3e87a4 100644 --- a/apps/studio/data/storage/iceberg-wrapper-create-mutation.ts +++ b/apps/studio/data/storage/iceberg-wrapper-create-mutation.ts @@ -6,15 +6,15 @@ import { getCatalogURI, getConnectionURL, } from 'components/interfaces/Storage/StorageSettings/StorageSettings.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { getKeys, useAPIKeysQuery } from 'data/api-keys/api-keys-query' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { FDWCreateVariables, useFDWCreateMutation } from 'data/fdw/fdw-create-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useS3AccessKeyCreateMutation } from './s3-access-key-create-mutation' export const useIcebergWrapperCreateMutation = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: apiKeys } = useAPIKeysQuery({ projectRef: project?.ref, reveal: true }) const { secretKey, serviceKey } = getKeys(apiKeys) diff --git a/apps/studio/hooks/analytics/useDbQuery.tsx b/apps/studio/hooks/analytics/useDbQuery.tsx index f1ab74f830e..64bdbcf2db1 100644 --- a/apps/studio/hooks/analytics/useDbQuery.tsx +++ b/apps/studio/hooks/analytics/useDbQuery.tsx @@ -6,9 +6,9 @@ import { MetaQueryResponse, ReportQuery, } from 'components/interfaces/Reports/Reports.types' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { executeSql } from 'data/sql/execute-sql-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' export interface DbQueryHook { @@ -36,7 +36,7 @@ const useDbQuery = ({ where?: string orderBy?: string }): DbQueryHook => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const state = useDatabaseSelectorStateSnapshot() const { data: databases } = useReadReplicasQuery({ projectRef: project?.ref }) diff --git a/apps/studio/hooks/forms/useAIOptInForm.ts b/apps/studio/hooks/forms/useAIOptInForm.ts index d81da03076f..bd602497bb7 100644 --- a/apps/studio/hooks/forms/useAIOptInForm.ts +++ b/apps/studio/hooks/forms/useAIOptInForm.ts @@ -11,7 +11,7 @@ import { invalidateOrganizationsQuery } from 'data/organizations/organizations-q import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' import { getAiOptInLevel } from 'hooks/misc/useOrgOptedIntoAi' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { OPT_IN_TAGS } from 'lib/constants' import type { ResponseError } from 'types' @@ -30,7 +30,7 @@ export type AIOptInFormValues = z.infer */ export const useAIOptInForm = (onSuccessCallback?: () => void) => { const queryClient = useQueryClient() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const canUpdateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') const [_, setUpdatedOptInSinceMCP] = useLocalStorageQuery( diff --git a/apps/studio/hooks/misc/useCurrentOrgPlan.ts b/apps/studio/hooks/misc/useCurrentOrgPlan.ts index f6da44ba56a..52daa937fde 100644 --- a/apps/studio/hooks/misc/useCurrentOrgPlan.ts +++ b/apps/studio/hooks/misc/useCurrentOrgPlan.ts @@ -1,7 +1,7 @@ -import { useSelectedOrganization } from './useSelectedOrganization' +import { useSelectedOrganizationQuery } from './useSelectedOrganization' export function useCurrentOrgPlan() { - const currentOrg = useSelectedOrganization() + const { data: currentOrg } = useSelectedOrganizationQuery() if (!currentOrg) { return { diff --git a/apps/studio/hooks/misc/useOrgOptedIntoAi.ts b/apps/studio/hooks/misc/useOrgOptedIntoAi.ts index d60a69b4d8b..ac10c5a6a7e 100644 --- a/apps/studio/hooks/misc/useOrgOptedIntoAi.ts +++ b/apps/studio/hooks/misc/useOrgOptedIntoAi.ts @@ -3,8 +3,8 @@ import { z } from 'zod' import { subscriptionHasHipaaAddon } from 'components/interfaces/Billing/Subscription/Subscription.utils' import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { IS_PLATFORM, OPT_IN_TAGS } from 'lib/constants' export const aiOptInLevelSchema = z.enum([ @@ -51,8 +51,8 @@ export function useOrgAiOptInLevel(): { includeSchemaMetadata: boolean isHipaaProjectDisallowed: boolean } { - const selectedProject = useSelectedProject() - const selectedOrganization = useSelectedOrganization() + const { data: selectedProject } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() // [Joshen] Default to disabled until migration to clean up existing opt in tags are completed // Once toggled on, then we can default to their set opt in level and clean up feature flag diff --git a/apps/studio/hooks/misc/useOrganizationRestrictions.ts b/apps/studio/hooks/misc/useOrganizationRestrictions.ts index 299732e6587..7e56c4c423c 100644 --- a/apps/studio/hooks/misc/useOrganizationRestrictions.ts +++ b/apps/studio/hooks/misc/useOrganizationRestrictions.ts @@ -3,7 +3,7 @@ import dayjs from 'dayjs' import { RESTRICTION_MESSAGES } from 'components/interfaces/Organization/restriction.constants' import { useOverdueInvoicesQuery } from 'data/invoices/invoices-overdue-query' import { useOrganizationsQuery } from 'data/organizations/organizations-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' export type WarningBannerProps = { type: 'danger' | 'warning' | 'note' @@ -13,7 +13,7 @@ export type WarningBannerProps = { } export function useOrganizationRestrictions() { - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { data: overdueInvoices } = useOverdueInvoicesQuery() const { data: organizations } = useOrganizationsQuery() diff --git a/apps/studio/hooks/misc/useSelectedOrganization.ts b/apps/studio/hooks/misc/useSelectedOrganization.ts index d937a06f8ed..84e47836a98 100644 --- a/apps/studio/hooks/misc/useSelectedOrganization.ts +++ b/apps/studio/hooks/misc/useSelectedOrganization.ts @@ -1,37 +1,6 @@ import { useIsLoggedIn, useParams } from 'common' import { useOrganizationsQuery } from 'data/organizations/organizations-query' -import { useMemo } from 'react' - -import { useProjectByRef, useProjectByRefQuery } from './useSelectedProject' - -/** - * @deprecated Use useSelectedOrganizationQuery instead for access to loading states etc - * - * Example migration: - * ``` - * // Old: - * const organization = useSelectedOrganization() - * - * // New: - * const { data: organization } = useSelectedOrganizationQuery() - * ``` - */ -export function useSelectedOrganization({ enabled = true } = {}) { - const isLoggedIn = useIsLoggedIn() - - const { ref, slug } = useParams() - const { data } = useOrganizationsQuery({ enabled: isLoggedIn && enabled }) - - const selectedProject = useProjectByRef(ref) - - return useMemo(() => { - return data?.find((org) => { - if (slug !== undefined) return org.slug === slug - if (selectedProject !== undefined) return org.id === selectedProject.organization_id - return undefined - }) - }, [data, selectedProject, slug]) -} +import { useProjectByRefQuery } from './useSelectedProject' export function useSelectedOrganizationQuery({ enabled = true } = {}) { const isLoggedIn = useIsLoggedIn() diff --git a/apps/studio/hooks/misc/useSelectedProject.ts b/apps/studio/hooks/misc/useSelectedProject.ts index a84a2df9b46..9159cccb8f0 100644 --- a/apps/studio/hooks/misc/useSelectedProject.ts +++ b/apps/studio/hooks/misc/useSelectedProject.ts @@ -1,32 +1,8 @@ -import { useMemo } from 'react' - import { useIsLoggedIn, useParams } from 'common' import { useProjectDetailQuery } from 'data/projects/project-detail-query' -import { ProjectInfo, useProjectsQuery } from 'data/projects/projects-query' +import { useProjectsQuery } from 'data/projects/projects-query' import { PROVIDERS } from 'lib/constants' -/** - * @deprecated Use useSelectedProjectQuery instead for access to loading states etc - * - * Example migration: - * ``` - * // Old: - * const project = useSelectedProject() - * - * // New: - * const { data: project } = useSelectedProjectQuery() - * ``` - */ -export function useSelectedProject({ enabled = true } = {}) { - const { ref } = useParams() - const { data } = useProjectDetailQuery({ ref }, { enabled }) - - return useMemo( - () => data && { ...data, parentRef: data?.parent_project_ref ?? data?.ref }, - [data] - ) -} - export function useSelectedProjectQuery({ enabled = true } = {}) { const { ref } = useParams() @@ -41,37 +17,6 @@ export function useSelectedProjectQuery({ enabled = true } = {}) { ) } -/** - * @deprecated Use useProjectByRefQuery instead for access to loading states etc - * - * Example migration: - * ``` - * // Old: - * const project = useProjectByRef(ref) - * - * // New: - * const { data: project } = useProjectByRefQuery(ref) - * ``` - */ -export function useProjectByRef( - ref?: string -): Omit | undefined { - const isLoggedIn = useIsLoggedIn() - - const { data: project } = useProjectDetailQuery({ ref }, { enabled: isLoggedIn }) - - // [Alaister]: This is here for the purpose of improving performance. - // Chances are, the user will already have the list of projects in the cache. - // We can't exclusively rely on this method, as useProjectsQuery does not return branch projects. - const { data: projects } = useProjectsQuery({ enabled: isLoggedIn }) - - return useMemo(() => { - if (!ref) return undefined - if (project) return project - return projects?.find((project) => project.ref === ref) - }, [project, projects, ref]) -} - export function useProjectByRefQuery(ref?: string) { const isLoggedIn = useIsLoggedIn() @@ -95,27 +40,27 @@ export function useProjectByRefQuery(ref?: string) { } export const useIsAwsCloudProvider = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isAws = project?.cloud_provider === PROVIDERS.AWS.id return isAws } export const useIsAwsK8sCloudProvider = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isAwsK8s = project?.cloud_provider === PROVIDERS.AWS_K8S.id return isAwsK8s } export const useIsOrioleDb = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isOrioleDb = project?.dbVersion?.endsWith('orioledb') return isOrioleDb } export const useIsOrioleDbInAws = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isOrioleDbInAws = project?.dbVersion?.endsWith('orioledb') && project?.cloud_provider === PROVIDERS.AWS.id return isOrioleDbInAws diff --git a/apps/studio/hooks/misc/useUpgradePrompt.tsx b/apps/studio/hooks/misc/useUpgradePrompt.tsx index 34542ea05c1..eadf613ee0b 100644 --- a/apps/studio/hooks/misc/useUpgradePrompt.tsx +++ b/apps/studio/hooks/misc/useUpgradePrompt.tsx @@ -1,9 +1,9 @@ import { maybeShowUpgradePrompt } from 'components/interfaces/Settings/Logs/Logs.utils' import { useEffect, useState } from 'react' -import { useSelectedOrganization } from './useSelectedOrganization' +import { useSelectedOrganizationQuery } from './useSelectedOrganization' export const useUpgradePrompt = (from: string) => { - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const [showUpgradePrompt, setShowUpgradePrompt] = useState(false) const shouldShowUpgradePrompt = maybeShowUpgradePrompt(from, organization?.plan?.id) diff --git a/apps/studio/hooks/ui/useFlag.ts b/apps/studio/hooks/ui/useFlag.ts index be76ab33fa0..8dd5262287e 100644 --- a/apps/studio/hooks/ui/useFlag.ts +++ b/apps/studio/hooks/ui/useFlag.ts @@ -2,7 +2,7 @@ import * as Sentry from '@sentry/nextjs' import { useFeatureFlags } from 'common' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { trackFeatureFlag } from 'lib/posthog' const isObjectEmpty = (obj: Object) => { @@ -58,7 +58,7 @@ export function usePHFlag(name: string) { } export const useIsRealtimeSettingsFFEnabled = () => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() // This flag is used to enable/disable the realtime settings for specific projects. const approvedProjects = useFlag('isRealtimeSettingsEnabledOnProjects') diff --git a/apps/studio/hooks/useProtectedSchemas.ts b/apps/studio/hooks/useProtectedSchemas.ts index 92dfcf9625d..49024dcac51 100644 --- a/apps/studio/hooks/useProtectedSchemas.ts +++ b/apps/studio/hooks/useProtectedSchemas.ts @@ -6,9 +6,9 @@ import { convertKVStringArrayToJson, wrapperMetaComparator, } from 'components/interfaces/Integrations/Wrappers/Wrappers.utils' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { QUEUES_SCHEMA } from 'data/database-queues/database-queues-toggle-postgrest-mutation' import { useFDWsQuery } from 'data/fdw/fdws-query' +import { useSelectedProjectQuery } from './misc/useSelectedProject' /** * A list of system schemas that users should not interact with @@ -37,7 +37,7 @@ export const INTERNAL_SCHEMAS = [ * Get the list of schemas used by IcebergFDWs */ const useIcebergFdwSchemasQuery = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const result = useFDWsQuery({ projectRef: project?.ref, connectionString: project?.connectionString, 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 01b7f9e074e..c8107f7a7b4 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 @@ -16,7 +16,7 @@ import { useIntegrationVercelConnectionsCreateMutation } from 'data/integrations import { useVercelProjectsQuery } from 'data/integrations/integrations-vercel-projects-query' import { useOrganizationsQuery } from 'data/organizations/organizations-query' import { useProjectCreateMutation } from 'data/projects/project-create-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { PROVIDERS } from 'lib/constants' import { getInitialMigrationSQLFromGitHubRepo } from 'lib/integration-utils' import passwordStrength from 'lib/password-strength' @@ -55,7 +55,7 @@ VercelIntegration.getLayout = (page) => ( const CreateProject = () => { const router = useRouter() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const [projectName, setProjectName] = useState('') const [dbPass, setDbPass] = useState('') const [passwordStrengthMessage, setPasswordStrengthMessage] = useState('') diff --git a/apps/studio/pages/new/[slug].tsx b/apps/studio/pages/new/[slug].tsx index 203dd05d980..84301d2040a 100644 --- a/apps/studio/pages/new/[slug].tsx +++ b/apps/studio/pages/new/[slug].tsx @@ -48,7 +48,7 @@ import { useProjectsQuery } from 'data/projects/projects-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { withAuth } from 'hooks/misc/withAuth' import { useFlag } from 'hooks/ui/useFlag' import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils' @@ -140,7 +140,7 @@ export type CreateProjectForm = z.infer const Wizard: NextPageWithLayout = () => { const router = useRouter() const { slug, projectName } = useParams() - const currentOrg = useSelectedOrganization() + const { data: currentOrg } = useSelectedOrganizationQuery() const isFreePlan = currentOrg?.plan?.id === 'free' const [lastVisitedOrganization] = useLocalStorageQuery( LOCAL_STORAGE_KEYS.LAST_VISITED_ORGANIZATION, diff --git a/apps/studio/pages/org/[slug]/apps.tsx b/apps/studio/pages/org/[slug]/apps.tsx index 757bba2adbf..616f81fca04 100644 --- a/apps/studio/pages/org/[slug]/apps.tsx +++ b/apps/studio/pages/org/[slug]/apps.tsx @@ -4,11 +4,11 @@ import OrganizationLayout from 'components/layouts/OrganizationLayout' import OrganizationSettingsLayout from 'components/layouts/ProjectLayout/OrganizationSettingsLayout' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { NextPageWithLayout } from 'types' const OrgOAuthApps: NextPageWithLayout = () => { - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const { isLoading: isLoadingPermissions } = usePermissionsQuery() return ( diff --git a/apps/studio/pages/org/[slug]/audit.tsx b/apps/studio/pages/org/[slug]/audit.tsx index b89da68c278..0baf587a80f 100644 --- a/apps/studio/pages/org/[slug]/audit.tsx +++ b/apps/studio/pages/org/[slug]/audit.tsx @@ -1,16 +1,15 @@ import { AuditLogs } from 'components/interfaces/Organization' -import AppLayout from 'components/layouts/AppLayout/AppLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import OrganizationLayout from 'components/layouts/OrganizationLayout' import OrganizationSettingsLayout from 'components/layouts/ProjectLayout/OrganizationSettingsLayout' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { NextPageWithLayout } from 'types' const OrgAuditLogs: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() return ( <>{selectedOrganization === undefined && isLoadingPermissions ? : } diff --git a/apps/studio/pages/org/[slug]/general.tsx b/apps/studio/pages/org/[slug]/general.tsx index 8e1ec1bea5e..73670d676f2 100644 --- a/apps/studio/pages/org/[slug]/general.tsx +++ b/apps/studio/pages/org/[slug]/general.tsx @@ -1,16 +1,15 @@ import { GeneralSettings as GeneralSettingsLegacy } from 'components/interfaces/Organization' -import AppLayout from 'components/layouts/AppLayout/AppLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import OrganizationLayout from 'components/layouts/OrganizationLayout' import OrganizationSettingsLayout from 'components/layouts/ProjectLayout/OrganizationSettingsLayout' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { NextPageWithLayout } from 'types' const OrgGeneralSettings: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() return ( <> diff --git a/apps/studio/pages/org/[slug]/index.tsx b/apps/studio/pages/org/[slug]/index.tsx index 7e8a9767a98..94ac9ca564c 100644 --- a/apps/studio/pages/org/[slug]/index.tsx +++ b/apps/studio/pages/org/[slug]/index.tsx @@ -8,13 +8,13 @@ import OrganizationLayout from 'components/layouts/OrganizationLayout' import { ScaffoldContainerLegacy } from 'components/layouts/Scaffold' import { InlineLink } from 'components/ui/InlineLink' import { useAutoProjectsPrefetch } from 'data/projects/projects-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { PROJECT_STATUS } from 'lib/constants' import type { NextPageWithLayout } from 'types' import { Admonition } from 'ui-patterns' const ProjectsPage: NextPageWithLayout = () => { - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const isUserMFAEnabled = useIsMFAEnabled() const disableAccessMfa = org?.organization_requires_mfa && !isUserMFAEnabled diff --git a/apps/studio/pages/org/[slug]/security.tsx b/apps/studio/pages/org/[slug]/security.tsx index b2f4af6ba6e..93bf795e639 100644 --- a/apps/studio/pages/org/[slug]/security.tsx +++ b/apps/studio/pages/org/[slug]/security.tsx @@ -1,16 +1,15 @@ import { SecuritySettings } from 'components/interfaces/Organization' -import AppLayout from 'components/layouts/AppLayout/AppLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import OrganizationLayout from 'components/layouts/OrganizationLayout' import OrganizationSettingsLayout from 'components/layouts/ProjectLayout/OrganizationSettingsLayout' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { NextPageWithLayout } from 'types' const OrgGeneralSettings: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() return ( <> diff --git a/apps/studio/pages/org/[slug]/team.tsx b/apps/studio/pages/org/[slug]/team.tsx index 08573e5d1a2..aef184ae3a8 100644 --- a/apps/studio/pages/org/[slug]/team.tsx +++ b/apps/studio/pages/org/[slug]/team.tsx @@ -4,12 +4,12 @@ import OrganizationLayout from 'components/layouts/OrganizationLayout' import OrganizationSettingsLayout from 'components/layouts/ProjectLayout/OrganizationSettingsLayout' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { NextPageWithLayout } from 'types' const OrgTeamSettings: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() return selectedOrganization === undefined && isLoadingPermissions ? : } diff --git a/apps/studio/pages/org/[slug]/usage.tsx b/apps/studio/pages/org/[slug]/usage.tsx index 277e8b8e931..9936b9e1a7a 100644 --- a/apps/studio/pages/org/[slug]/usage.tsx +++ b/apps/studio/pages/org/[slug]/usage.tsx @@ -1,16 +1,15 @@ import { Usage } from 'components/interfaces/Organization' -import AppLayout from 'components/layouts/AppLayout/AppLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import OrganizationLayout from 'components/layouts/OrganizationLayout' import OrganizationSettingsLayout from 'components/layouts/ProjectLayout/OrganizationSettingsLayout' import { Loading } from 'components/ui/Loading' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import type { NextPageWithLayout } from 'types' const OrgUsage: NextPageWithLayout = () => { const { isLoading: isLoadingPermissions } = usePermissionsQuery() - const selectedOrganization = useSelectedOrganization() + const { data: selectedOrganization } = useSelectedOrganizationQuery() return <>{selectedOrganization === undefined && isLoadingPermissions ? : } } diff --git a/apps/studio/pages/project/[ref]/advisors/performance.tsx b/apps/studio/pages/project/[ref]/advisors/performance.tsx index 083354b267c..8bccf30af72 100644 --- a/apps/studio/pages/project/[ref]/advisors/performance.tsx +++ b/apps/studio/pages/project/[ref]/advisors/performance.tsx @@ -11,13 +11,13 @@ import AdvisorsLayout from 'components/layouts/AdvisorsLayout/AdvisorsLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import { FormHeader } from 'components/ui/Forms/FormHeader' import { Lint, useProjectLintsQuery } from 'data/lint/lint-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' import { LoadingLine } from 'ui' const ProjectLints: NextPageWithLayout = () => { - const project = useSelectedProject() const { preset, id } = useParams() + const { data: project } = useSelectedProjectQuery() // need to maintain a list of filters for each tab const [filters, setFilters] = useState<{ level: LINTER_LEVELS; filters: string[] }[]>([ diff --git a/apps/studio/pages/project/[ref]/advisors/security.tsx b/apps/studio/pages/project/[ref]/advisors/security.tsx index 26d845ebe9f..a4e53ea2a2e 100644 --- a/apps/studio/pages/project/[ref]/advisors/security.tsx +++ b/apps/studio/pages/project/[ref]/advisors/security.tsx @@ -11,13 +11,13 @@ import AdvisorsLayout from 'components/layouts/AdvisorsLayout/AdvisorsLayout' import DefaultLayout from 'components/layouts/DefaultLayout' import { FormHeader } from 'components/ui/Forms/FormHeader' import { Lint, useProjectLintsQuery } from 'data/lint/lint-query' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' import { LoadingLine } from 'ui' const ProjectLints: NextPageWithLayout = () => { - const project = useSelectedProject() const { preset, id } = useParams() + const { data: project } = useSelectedProjectQuery() // need to maintain a list of filters for each tab const [filters, setFilters] = useState<{ level: LINTER_LEVELS; filters: string[] }[]>([ diff --git a/apps/studio/pages/project/[ref]/auth/policies.tsx b/apps/studio/pages/project/[ref]/auth/policies.tsx index 0b086d6c896..0e6ba60d9ac 100644 --- a/apps/studio/pages/project/[ref]/auth/policies.tsx +++ b/apps/studio/pages/project/[ref]/auth/policies.tsx @@ -10,7 +10,6 @@ import { PolicyEditorPanel } from 'components/interfaces/Auth/Policies/PolicyEdi import { generatePolicyUpdateSQL } from 'components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils' import AuthLayout from 'components/layouts/AuthLayout/AuthLayout' import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import AlertError from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' import NoPermission from 'components/ui/NoPermission' @@ -19,6 +18,7 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query' import { useTablesQuery } from 'data/tables/tables-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useUrlState } from 'hooks/ui/useUrlState' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import { useAppStateSnapshot } from 'state/app-state' @@ -66,7 +66,7 @@ const AuthPoliciesPage: NextPageWithLayout = () => { search?: string }>() const { schema = 'public', search: searchString = '' } = params - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { setEditorPanel } = useAppStateSnapshot() const isInlineEditorEnabled = useIsInlineEditorEnabled() diff --git a/apps/studio/pages/project/[ref]/branches/index.tsx b/apps/studio/pages/project/[ref]/branches/index.tsx index 3902c17937e..befbcd49271 100644 --- a/apps/studio/pages/project/[ref]/branches/index.tsx +++ b/apps/studio/pages/project/[ref]/branches/index.tsx @@ -20,8 +20,8 @@ import { Branch, useBranchesQuery } from 'data/branches/branches-query' import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useAppStateSnapshot } from 'state/app-state' import type { NextPageWithLayout } from 'types' import { Button } from 'ui' @@ -31,8 +31,8 @@ const BranchesPage: NextPageWithLayout = () => { const router = useRouter() const { ref } = useParams() const snap = useAppStateSnapshot() - const project = useSelectedProject() - const selectedOrg = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const [selectedBranchToDelete, setSelectedBranchToDelete] = useState() diff --git a/apps/studio/pages/project/[ref]/branches/merge-requests.tsx b/apps/studio/pages/project/[ref]/branches/merge-requests.tsx index 056a3e1c0b3..7c38093e329 100644 --- a/apps/studio/pages/project/[ref]/branches/merge-requests.tsx +++ b/apps/studio/pages/project/[ref]/branches/merge-requests.tsx @@ -25,8 +25,8 @@ import { Branch, useBranchesQuery } from 'data/branches/branches-query' import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' import { Button, @@ -41,8 +41,8 @@ import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' const MergeRequestsPage: NextPageWithLayout = () => { const router = useRouter() const { ref } = useParams() - const project = useSelectedProject() - const selectedOrg = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const gitlessBranching = useIsBranching2Enabled() const isBranch = project?.parent_project_ref !== undefined @@ -307,8 +307,8 @@ const MergeRequestsPage: NextPageWithLayout = () => { const MergeRequestsPageWrapper = ({ children }: PropsWithChildren<{}>) => { const router = useRouter() const { ref } = useParams() - const project = useSelectedProject() - const selectedOrg = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const gitlessBranching = useIsBranching2Enabled() const isBranch = project?.parent_project_ref !== undefined diff --git a/apps/studio/pages/project/[ref]/database/backups/pitr.tsx b/apps/studio/pages/project/[ref]/database/backups/pitr.tsx index 275ae658474..b66eb6904d1 100644 --- a/apps/studio/pages/project/[ref]/database/backups/pitr.tsx +++ b/apps/studio/pages/project/[ref]/database/backups/pitr.tsx @@ -6,7 +6,6 @@ import DatabaseBackupsNav from 'components/interfaces/Database/Backups/DatabaseB import { PITRNotice, PITRSelection } from 'components/interfaces/Database/Backups/PITR' import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout' import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' @@ -16,8 +15,8 @@ import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import UpgradeToPro from 'components/ui/UpgradeToPro' import { useBackupsQuery } from 'data/database/backups-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useIsOrioleDbInAws } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useIsOrioleDbInAws, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import type { NextPageWithLayout } from 'types' import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_ } from 'ui' @@ -49,8 +48,8 @@ DatabasePhysicalBackups.getLayout = (page) => ( const PITR = () => { const { ref: projectRef } = useParams() - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const isOrioleDbInAws = useIsOrioleDbInAws() const { data: backups, error, isLoading, isError, isSuccess } = useBackupsQuery({ projectRef }) diff --git a/apps/studio/pages/project/[ref]/database/backups/restore-to-new-project.tsx b/apps/studio/pages/project/[ref]/database/backups/restore-to-new-project.tsx index 4bd8caa152b..1e186f17cdd 100644 --- a/apps/studio/pages/project/[ref]/database/backups/restore-to-new-project.tsx +++ b/apps/studio/pages/project/[ref]/database/backups/restore-to-new-project.tsx @@ -13,7 +13,6 @@ import { DiskType } from 'components/interfaces/DiskManagement/ui/DiskManagement import { Markdown } from 'components/interfaces/Markdown' import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout' import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' import { FormHeader } from 'components/ui/Forms/FormHeader' @@ -25,8 +24,12 @@ import { useDiskAttributesQuery } from 'data/config/disk-attributes-query' import { useCloneBackupsQuery } from 'data/projects/clone-query' import { useCloneStatusQuery } from 'data/projects/clone-status-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useIsAwsK8sCloudProvider, useIsOrioleDb } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { + useIsAwsK8sCloudProvider, + useIsOrioleDb, + useSelectedProjectQuery, +} from 'hooks/misc/useSelectedProject' import { PROJECT_STATUS } from 'lib/constants' import { getDatabaseMajorVersion } from 'lib/helpers' import type { NextPageWithLayout } from 'types' @@ -58,8 +61,8 @@ RestoreToNewProjectPage.getLayout = (page) => ( ) const RestoreToNewProject = () => { - const { project } = useProjectContext() - const organization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() const isFreePlan = organization?.plan?.id === 'free' const isOrioleDb = useIsOrioleDb() const isAwsK8s = useIsAwsK8sCloudProvider() diff --git a/apps/studio/pages/project/[ref]/database/column-privileges.tsx b/apps/studio/pages/project/[ref]/database/column-privileges.tsx index 0d78688c571..899e0ba4360 100644 --- a/apps/studio/pages/project/[ref]/database/column-privileges.tsx +++ b/apps/studio/pages/project/[ref]/database/column-privileges.tsx @@ -19,7 +19,6 @@ import PrivilegesTable from 'components/interfaces/Database/Privileges/Privilege import { ProtectedSchemaWarning } from 'components/interfaces/Database/ProtectedSchemaWarning' import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout' import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' @@ -30,6 +29,7 @@ import { useTablePrivilegesQuery } from 'data/privileges/table-privileges-query' import { useTablesQuery } from 'data/tables/tables-query' import { useLocalStorage } from 'hooks/misc/useLocalStorage' import { useQuerySchemaState } from 'hooks/misc/useSchemaQueryState' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useIsProtectedSchema } from 'hooks/useProtectedSchemas' import type { NextPageWithLayout } from 'types' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui' @@ -38,7 +38,7 @@ const EDITABLE_ROLES = ['authenticated', 'anon', 'service_role'] const PrivilegesPage: NextPageWithLayout = () => { const { ref, table: paramTable } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { openFeaturePreviewModal } = useFeaturePreviewModal() const isEnabled = useIsColumnLevelPrivilegesEnabled() diff --git a/apps/studio/pages/project/[ref]/database/publications.tsx b/apps/studio/pages/project/[ref]/database/publications.tsx index e153e6e41c3..06b0c5bbffd 100644 --- a/apps/studio/pages/project/[ref]/database/publications.tsx +++ b/apps/studio/pages/project/[ref]/database/publications.tsx @@ -3,21 +3,21 @@ import { useState } from 'react' import { PublicationsList, PublicationsTables } from 'components/interfaces/Database' import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' +import DefaultLayout from 'components/layouts/DefaultLayout' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import { FormHeader } from 'components/ui/Forms/FormHeader' import NoPermission from 'components/ui/NoPermission' import { useDatabasePublicationsQuery } from 'data/database-publications/database-publications-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' -import DefaultLayout from 'components/layouts/DefaultLayout' // [Joshen] Technically, best that we have these as separate URLs // makes it easier to manage state, but foresee that this page might // be consolidated somewhere else eventually for better UX const DatabasePublications: NextPageWithLayout = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data } = useDatabasePublicationsQuery({ projectRef: project?.ref, diff --git a/apps/studio/pages/project/[ref]/database/tables/[id].tsx b/apps/studio/pages/project/[ref]/database/tables/[id].tsx index 9c834807105..3a0cf30b1c2 100644 --- a/apps/studio/pages/project/[ref]/database/tables/[id].tsx +++ b/apps/studio/pages/project/[ref]/database/tables/[id].tsx @@ -1,15 +1,16 @@ +import { ChevronRight } from 'lucide-react' + import { useParams } from 'common' import { ColumnList } from 'components/interfaces/Database' import { SidePanelEditor } from 'components/interfaces/TableGridEditor' import DeleteConfirmationDialogs from 'components/interfaces/TableGridEditor/DeleteConfirmationDialogs' import DatabaseLayout from 'components/layouts/DatabaseLayout/DatabaseLayout' import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold' import { FormHeader } from 'components/ui/Forms/FormHeader' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { isTableLike } from 'data/table-editor/table-editor-types' -import { ChevronRight } from 'lucide-react' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useTableEditorStateSnapshot } from 'state/table-editor' import { TableEditorTableStateContextProvider } from 'state/table-editor-table' import type { NextPageWithLayout } from 'types' @@ -21,7 +22,7 @@ const DatabaseTables: NextPageWithLayout = () => { const { id: _id } = useParams() const id = _id ? Number(_id) : undefined - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable, isLoading } = useTableEditorQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/pages/project/[ref]/editor/[id].tsx b/apps/studio/pages/project/[ref]/editor/[id].tsx index 6f11123aa8f..7b46f54fb69 100644 --- a/apps/studio/pages/project/[ref]/editor/[id].tsx +++ b/apps/studio/pages/project/[ref]/editor/[id].tsx @@ -4,10 +4,10 @@ import { useParams } from 'common' import { TableGridEditor } from 'components/interfaces/TableGridEditor/TableGridEditor' import DefaultLayout from 'components/layouts/DefaultLayout' import { EditorBaseLayout } from 'components/layouts/editors/EditorBaseLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import TableEditorLayout from 'components/layouts/TableEditorLayout/TableEditorLayout' import { TableEditorMenu } from 'components/layouts/TableEditorLayout/TableEditorMenu' import { useTableEditorQuery } from 'data/table-editor/table-editor-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { createTabId, useTabsStateSnapshot } from 'state/tabs' import type { NextPageWithLayout } from 'types' @@ -16,7 +16,7 @@ const TableEditorPage: NextPageWithLayout = () => { const id = _id ? Number(_id) : undefined const store = useTabsStateSnapshot() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { data: selectedTable, isLoading } = useTableEditorQuery({ projectRef: project?.ref, connectionString: project?.connectionString, diff --git a/apps/studio/pages/project/[ref]/functions/[functionSlug]/code.tsx b/apps/studio/pages/project/[ref]/functions/[functionSlug]/code.tsx index cd3a64bb5a7..48e95eca7bc 100644 --- a/apps/studio/pages/project/[ref]/functions/[functionSlug]/code.tsx +++ b/apps/studio/pages/project/[ref]/functions/[functionSlug]/code.tsx @@ -16,18 +16,18 @@ import { useEdgeFunctionDeployMutation } from 'data/edge-functions/edge-function import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useOrgAiOptInLevel } from 'hooks/misc/useOrgOptedIntoAi' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { LogoLoader } from 'ui' const CodePage = () => { const { ref, functionSlug } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { includeSchemaMetadata } = useOrgAiOptInLevel() const { mutate: sendEvent } = useSendEventMutation() - const org = useSelectedOrganization() const [showDeployWarning, setShowDeployWarning] = useState(false) const canDeployFunction = useCheckPermissions(PermissionAction.FUNCTIONS_WRITE, '*') diff --git a/apps/studio/pages/project/[ref]/functions/index.tsx b/apps/studio/pages/project/[ref]/functions/index.tsx index 29bb3e206c2..c7e4b532550 100644 --- a/apps/studio/pages/project/[ref]/functions/index.tsx +++ b/apps/studio/pages/project/[ref]/functions/index.tsx @@ -1,5 +1,4 @@ import { ExternalLink } from 'lucide-react' -import { useRouter } from 'next/router' import { useParams } from 'common' import { DeployEdgeFunctionButton } from 'components/interfaces/EdgeFunctions/DeployEdgeFunctionButton' @@ -17,17 +16,12 @@ import AlertError from 'components/ui/AlertError' import { DocsButton } from 'components/ui/DocsButton' import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' -import { useSendEventMutation } from 'data/telemetry/send-event-mutation' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' -import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import type { NextPageWithLayout } from 'types' import { Button } from 'ui' const EdgeFunctionsPage: NextPageWithLayout = () => { const { ref } = useParams() - const snap = useAiAssistantStateSnapshot() - const router = useRouter() const { data: functions, error, @@ -35,8 +29,6 @@ const EdgeFunctionsPage: NextPageWithLayout = () => { isError, isSuccess, } = useEdgeFunctionsQuery({ projectRef: ref }) - const { mutate: sendEvent } = useSendEventMutation() - const org = useSelectedOrganization() const hasFunctions = (functions ?? []).length > 0 diff --git a/apps/studio/pages/project/[ref]/functions/new.tsx b/apps/studio/pages/project/[ref]/functions/new.tsx index 3d469049680..f0e17bccf78 100644 --- a/apps/studio/pages/project/[ref]/functions/new.tsx +++ b/apps/studio/pages/project/[ref]/functions/new.tsx @@ -15,8 +15,8 @@ import FileExplorerAndEditor from 'components/ui/FileExplorerAndEditor/FileExplo import { useEdgeFunctionDeployMutation } from 'data/edge-functions/edge-functions-deploy-mutation' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useOrgAiOptInLevel } from 'hooks/misc/useOrgOptedIntoAi' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { BASE_PATH } from 'lib/constants' import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state' import { @@ -99,11 +99,11 @@ type FormValues = z.infer const NewFunctionPage = () => { const router = useRouter() const { ref, template } = useParams() - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { includeSchemaMetadata } = useOrgAiOptInLevel() const snap = useAiAssistantStateSnapshot() const { mutate: sendEvent } = useSendEventMutation() - const org = useSelectedOrganization() const [files, setFiles] = useState< { id: number; name: string; content: string; selected?: boolean }[] diff --git a/apps/studio/pages/project/[ref]/index.tsx b/apps/studio/pages/project/[ref]/index.tsx index 4a35f4f01db..5c0b6881ba1 100644 --- a/apps/studio/pages/project/[ref]/index.tsx +++ b/apps/studio/pages/project/[ref]/index.tsx @@ -18,8 +18,12 @@ import { useBranchesQuery } from 'data/branches/branches-query' import { useEdgeFunctionsQuery } from 'data/edge-functions/edge-functions-query' import { useReadReplicasQuery } from 'data/read-replicas/replicas-query' import { useTablesQuery } from 'data/tables/tables-query' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useIsOrioleDb, useProjectByRef, useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { + useIsOrioleDb, + useProjectByRefQuery, + useSelectedProjectQuery, +} from 'hooks/misc/useSelectedProject' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' import { useAppStateSnapshot } from 'state/app-state' import type { NextPageWithLayout } from 'types' @@ -37,9 +41,9 @@ import { import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' const Home: NextPageWithLayout = () => { - const organization = useSelectedOrganization() - const project = useSelectedProject() - const parentProject = useProjectByRef(project?.parent_project_ref) + const { data: project } = useSelectedProjectQuery() + const { data: organization } = useSelectedOrganizationQuery() + const { data: parentProject } = useProjectByRefQuery(project?.parent_project_ref) const isOrioleDb = useIsOrioleDb() const snap = useAppStateSnapshot() const { ref, enableBranching } = useParams() diff --git a/apps/studio/pages/project/[ref]/logs/auth-logs.tsx b/apps/studio/pages/project/[ref]/logs/auth-logs.tsx index 9bd55415626..44efb7b1dce 100644 --- a/apps/studio/pages/project/[ref]/logs/auth-logs.tsx +++ b/apps/studio/pages/project/[ref]/logs/auth-logs.tsx @@ -3,13 +3,13 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' import DefaultLayout from 'components/layouts/DefaultLayout' import LogsLayout from 'components/layouts/LogsLayout/LogsLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import NoPermission from 'components/ui/NoPermission' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' const LogsPage: NextPageWithLayout = () => { - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const canReadAuthLogs = useCheckPermissions(PermissionAction.ANALYTICS_READ, 'logflare') return !canReadAuthLogs ? ( diff --git a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx index 32a15ef2413..a62ec23c3f1 100644 --- a/apps/studio/pages/project/[ref]/logs/explorer/index.tsx +++ b/apps/studio/pages/project/[ref]/logs/explorer/index.tsx @@ -10,7 +10,6 @@ import { IS_PLATFORM, LOCAL_STORAGE_KEYS, useParams } from 'common' import { LOGS_LARGE_DATE_RANGE_DAYS_THRESHOLD, - LOGS_TABLES, TEMPLATES, } from 'components/interfaces/Settings/Logs/Logs.constants' import { @@ -37,7 +36,7 @@ import { } from 'data/content/content-upsert-mutation' import useLogsQuery from 'hooks/analytics/useLogsQuery' import { useLogsUrlState } from 'hooks/analytics/useLogsUrlState' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useUpgradePrompt } from 'hooks/misc/useUpgradePrompt' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' @@ -65,9 +64,9 @@ export const LogsExplorerPage: NextPageWithLayout = () => { const monaco = useMonaco() const router = useRouter() const { profile } = useProfile() - const { ref, q, queryId, source: routerSource } = useParams() + const { ref, q, queryId } = useParams() const projectRef = ref as string - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const editorRef = useRef() const [editorId] = useState(uuidv4()) diff --git a/apps/studio/pages/project/[ref]/logs/index.tsx b/apps/studio/pages/project/[ref]/logs/index.tsx index 26217594cb8..16e56270226 100644 --- a/apps/studio/pages/project/[ref]/logs/index.tsx +++ b/apps/studio/pages/project/[ref]/logs/index.tsx @@ -8,7 +8,7 @@ import DefaultLayout from 'components/layouts/DefaultLayout' import LogsLayout from 'components/layouts/LogsLayout/LogsLayout' import ProjectLayout from 'components/layouts/ProjectLayout/ProjectLayout' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { IS_PLATFORM } from 'lib/constants' import type { NextPageWithLayout } from 'types' @@ -17,7 +17,7 @@ export const LogPage: NextPageWithLayout = () => { const { ref } = useParams() const { hasLoaded } = useContext(FeatureFlagContext) - const org = useSelectedOrganization() + const { data: org } = useSelectedOrganizationQuery() const { isEnabled: isUnifiedLogsEnabled } = useUnifiedLogsPreview() const [lastVisitedLogsPage] = useLocalStorageQuery( diff --git a/apps/studio/pages/project/[ref]/merge.tsx b/apps/studio/pages/project/[ref]/merge.tsx index 0d175d2bfa3..298fc676a0b 100644 --- a/apps/studio/pages/project/[ref]/merge.tsx +++ b/apps/studio/pages/project/[ref]/merge.tsx @@ -25,8 +25,8 @@ import { useBranchesQuery } from 'data/branches/branches-query' import { useSendEventMutation } from 'data/telemetry/send-event-mutation' import { useBranchMergeDiff } from 'hooks/branches/useBranchMergeDiff' import { useWorkflowManagement } from 'hooks/branches/useWorkflowManagement' -import { useProjectByRef, useSelectedProject } from 'hooks/misc/useSelectedProject' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useProjectByRefQuery, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' import { Badge, @@ -44,8 +44,8 @@ import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' const MergePage: NextPageWithLayout = () => { const router = useRouter() const { ref } = useParams() - const project = useSelectedProject() - const selectedOrg = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrg } = useSelectedOrganizationQuery() const [isSubmitting, setIsSubmitting] = useState(false) const [workflowFinalStatus, setWorkflowFinalStatus] = useState(null) @@ -54,7 +54,7 @@ const MergePage: NextPageWithLayout = () => { const isBranch = project?.parent_project_ref !== undefined const parentProjectRef = project?.parent_project_ref - const parentProject = useProjectByRef(parentProjectRef) + const { data: parentProject } = useProjectByRefQuery(parentProjectRef) const { data: branches } = useBranchesQuery( { projectRef: parentProjectRef }, diff --git a/apps/studio/pages/project/[ref]/reports/database.tsx b/apps/studio/pages/project/[ref]/reports/database.tsx index 2352e82a66d..f7288df3aee 100644 --- a/apps/studio/pages/project/[ref]/reports/database.tsx +++ b/apps/studio/pages/project/[ref]/reports/database.tsx @@ -17,7 +17,6 @@ import DiskSizeConfigurationModal from 'components/interfaces/Settings/Database/ import { LogsDatePicker } from 'components/interfaces/Settings/Logs/Logs.DatePickers' import UpgradePrompt from 'components/interfaces/Settings/Logs/UpgradePrompt' import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ReportsLayout from 'components/layouts/ReportsLayout/ReportsLayout' import Table from 'components/to-be-cleaned/Table' import { ButtonTooltip } from 'components/ui/ButtonTooltip' @@ -35,11 +34,12 @@ import { getReportAttributes, getReportAttributesV2 } from 'data/reports/databas import { useDatabaseReport } from 'data/reports/database-report-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useReportDateRange } from 'hooks/misc/useReportDateRange' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useFlag } from 'hooks/ui/useFlag' import { formatBytes } from 'lib/helpers' import type { MultiAttribute } from 'components/ui/Charts/ComposedChart.utils' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' const DatabaseReport: NextPageWithLayout = () => { @@ -61,9 +61,9 @@ export default DatabaseReport const DatabaseUsage = () => { const { db, chart, ref } = useParams() - const { project } = useProjectContext() const isReportsV2 = useFlag('reportsDatabaseV2') - const org = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: org } = useSelectedOrganizationQuery() const { selectedDateRange, diff --git a/apps/studio/pages/project/[ref]/reports/storage.tsx b/apps/studio/pages/project/[ref]/reports/storage.tsx index d7a5d52c4ee..8135443dc82 100644 --- a/apps/studio/pages/project/[ref]/reports/storage.tsx +++ b/apps/studio/pages/project/[ref]/reports/storage.tsx @@ -1,37 +1,34 @@ -import Link from 'next/link' +import dayjs from 'dayjs' import { ArrowRight, ExternalLinkIcon, RefreshCw } from 'lucide-react' -import ReportHeader from 'components/interfaces/Reports/ReportHeader' -import ReportPadding from 'components/interfaces/Reports/ReportPadding' -import ReportFilterBar from 'components/interfaces/Reports/ReportFilterBar' -import ReportWidget from 'components/interfaces/Reports/ReportWidget' -import { - CacheHitRateChartRenderer, - TopCacheMissesRenderer, -} from 'components/interfaces/Reports/renderers/StorageRenderers' -import { - DatePickerValue, - LogsDatePicker, -} from 'components/interfaces/Settings/Logs/Logs.DatePickers' -import DefaultLayout from 'components/layouts/DefaultLayout' +import Link from 'next/link' + import { NetworkTrafficRenderer, ResponseSpeedChartRenderer, TopApiRoutesRenderer, TotalRequestsChartRenderer, } from 'components/interfaces/Reports/renderers/ApiRenderers' -import ReportsLayout from 'components/layouts/ReportsLayout/ReportsLayout' +import { + CacheHitRateChartRenderer, + TopCacheMissesRenderer, +} from 'components/interfaces/Reports/renderers/StorageRenderers' +import ReportFilterBar from 'components/interfaces/Reports/ReportFilterBar' +import ReportHeader from 'components/interfaces/Reports/ReportHeader' +import ReportPadding from 'components/interfaces/Reports/ReportPadding' import { REPORT_DATERANGE_HELPER_LABELS } from 'components/interfaces/Reports/Reports.constants' import ReportStickyNav from 'components/interfaces/Reports/ReportStickyNav' -import { useState } from 'react' - -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import { useReportDateRange } from 'hooks/misc/useReportDateRange' -import { useStorageReport } from 'data/reports/storage-report-query' +import ReportWidget from 'components/interfaces/Reports/ReportWidget' +import { + DatePickerValue, + LogsDatePicker, +} from 'components/interfaces/Settings/Logs/Logs.DatePickers' import UpgradePrompt from 'components/interfaces/Settings/Logs/UpgradePrompt' - -import type { NextPageWithLayout } from 'types' -import dayjs from 'dayjs' +import DefaultLayout from 'components/layouts/DefaultLayout' +import ReportsLayout from 'components/layouts/ReportsLayout/ReportsLayout' import { ButtonTooltip } from 'components/ui/ButtonTooltip' +import { useStorageReport } from 'data/reports/storage-report-query' +import { useReportDateRange } from 'hooks/misc/useReportDateRange' +import type { NextPageWithLayout } from 'types' export const StorageReport: NextPageWithLayout = () => { const report = useStorageReport() diff --git a/apps/studio/pages/project/[ref]/settings/billing/usage.tsx b/apps/studio/pages/project/[ref]/settings/billing/usage.tsx index 95b05e37631..1cf59bc6a0b 100644 --- a/apps/studio/pages/project/[ref]/settings/billing/usage.tsx +++ b/apps/studio/pages/project/[ref]/settings/billing/usage.tsx @@ -2,16 +2,16 @@ import { useRouter } from 'next/router' import { useEffect } from 'react' import { useParams } from 'common' -import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' -import type { NextPageWithLayout } from 'types' import DefaultLayout from 'components/layouts/DefaultLayout' +import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import type { NextPageWithLayout } from 'types' const ProjectBillingUsage: NextPageWithLayout = () => { // This component is only used for redirects, as nextjs cant redirect based on hash const router = useRouter() const { ref } = useParams() - const organization = useSelectedOrganization() + const { data: organization } = useSelectedOrganizationQuery() const hash = router.asPath.split('#')[1] const route = router.route diff --git a/apps/studio/pages/project/[ref]/settings/general.tsx b/apps/studio/pages/project/[ref]/settings/general.tsx index 6f0f7e92364..894cf9b36eb 100644 --- a/apps/studio/pages/project/[ref]/settings/general.tsx +++ b/apps/studio/pages/project/[ref]/settings/general.tsx @@ -7,17 +7,17 @@ import { } from 'components/interfaces/Settings/General' import { DeleteProjectPanel } from 'components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectPanel' import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout' import { ScaffoldContainer, ScaffoldHeader, ScaffoldTitle } from 'components/layouts/Scaffold' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' -import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' const ProjectSettings: NextPageWithLayout = () => { - const { project } = useProjectContext() - const selectedOrganization = useSelectedOrganization() + const { data: project } = useSelectedProjectQuery() + const { data: selectedOrganization } = useSelectedOrganizationQuery() const isBranch = !!project?.parent_project_ref const { projectsTransfer: projectTransferEnabled } = useIsFeatureEnabled(['projects:transfer']) diff --git a/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx b/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx index 0e2c5031023..4b432682bf8 100644 --- a/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx +++ b/apps/studio/pages/project/[ref]/storage/buckets/[bucketId].tsx @@ -1,18 +1,18 @@ import { useParams } from 'common' -import DefaultLayout from 'components/layouts/DefaultLayout' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import StorageBucketsError from 'components/interfaces/Storage/StorageBucketsError' -import StorageLayout from 'components/layouts/StorageLayout/StorageLayout' import { StorageExplorer } from 'components/interfaces/Storage' import { AnalyticBucketDetails } from 'components/interfaces/Storage/AnalyticBucketDetails' +import StorageBucketsError from 'components/interfaces/Storage/StorageBucketsError' import { useSelectedBucket } from 'components/interfaces/Storage/StorageExplorer/useSelectedBucket' +import DefaultLayout from 'components/layouts/DefaultLayout' +import StorageLayout from 'components/layouts/StorageLayout/StorageLayout' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { useStorageExplorerStateSnapshot } from 'state/storage-explorer' import type { NextPageWithLayout } from 'types' const PageLayout: NextPageWithLayout = () => { const { bucketId } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { projectRef } = useStorageExplorerStateSnapshot() const { bucket, error, isSuccess, isError } = useSelectedBucket() diff --git a/apps/studio/pages/project/[ref]/storage/buckets/index.tsx b/apps/studio/pages/project/[ref]/storage/buckets/index.tsx index 08680ac7113..941c380c52d 100644 --- a/apps/studio/pages/project/[ref]/storage/buckets/index.tsx +++ b/apps/studio/pages/project/[ref]/storage/buckets/index.tsx @@ -1,11 +1,11 @@ import { useParams } from 'common' -import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import StorageBucketsError from 'components/interfaces/Storage/StorageBucketsError' -import StorageLayout from 'components/layouts/StorageLayout/StorageLayout' import DefaultLayout from 'components/layouts/DefaultLayout' +import StorageLayout from 'components/layouts/StorageLayout/StorageLayout' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import { useBucketsQuery } from 'data/storage/buckets-query' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import type { NextPageWithLayout } from 'types' /** @@ -13,10 +13,10 @@ import type { NextPageWithLayout } from 'types' */ const PageLayout: NextPageWithLayout = () => { const { ref } = useParams() - const { project } = useProjectContext() + const { data: project } = useSelectedProjectQuery() const { error, isError } = useBucketsQuery({ projectRef: ref }) - if (!project) return
+ if (!project) return null if (isError) diff --git a/apps/studio/state/ai-assistant-state.tsx b/apps/studio/state/ai-assistant-state.tsx index b33feb97047..e26afde284f 100644 --- a/apps/studio/state/ai-assistant-state.tsx +++ b/apps/studio/state/ai-assistant-state.tsx @@ -6,7 +6,7 @@ import { v4 as uuidv4 } from 'uuid' import { proxy, snapshot, subscribe, useSnapshot } from 'valtio' import { LOCAL_STORAGE_KEYS } from 'common' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' type SuggestionsType = { title: string @@ -432,7 +432,7 @@ export type AiAssistantState = AiAssistantData & { export const AiAssistantStateContext = createContext(createAiAssistantState()) export const AiAssistantStateContextProvider = ({ children }: PropsWithChildren) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() // Initialize state. createAiAssistantState now just sets defaults. const [state] = useState(() => createAiAssistantState()) diff --git a/apps/studio/state/role-impersonation-state.tsx b/apps/studio/state/role-impersonation-state.tsx index 2d969f8ed0b..acdc579a746 100644 --- a/apps/studio/state/role-impersonation-state.tsx +++ b/apps/studio/state/role-impersonation-state.tsx @@ -4,7 +4,7 @@ import { proxy, snapshot, subscribe, useSnapshot } from 'valtio' import { useConstant } from 'common' import { executeSql } from 'data/sql/execute-sql-query' import useLatest from 'hooks/misc/useLatest' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { getPostgrestClaims, ImpersonationRole } from 'lib/role-impersonation' import { CustomAccessTokenHookDetails } from '../hooks/misc/useCustomAccessTokenHookDetails' @@ -58,7 +58,7 @@ export const RoleImpersonationStateContext = createContext { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() async function customizeAccessToken({ schema, functionName, diff --git a/apps/studio/state/storage-explorer.tsx b/apps/studio/state/storage-explorer.tsx index 35b1886f025..afa80ef49ad 100644 --- a/apps/studio/state/storage-explorer.tsx +++ b/apps/studio/state/storage-explorer.tsx @@ -42,7 +42,7 @@ import { downloadBucketObject } from 'data/storage/bucket-object-download-mutati import { listBucketObjects, StorageObject } from 'data/storage/bucket-objects-list-mutation' import { Bucket } from 'data/storage/buckets-query' import { moveStorageObject } from 'data/storage/object-move-mutation' -import { useSelectedProject } from 'hooks/misc/useSelectedProject' +import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { IS_PLATFORM, PROJECT_STATUS } from 'lib/constants' import { tryParseJson } from 'lib/helpers' import { lookupMime } from 'lib/mime' @@ -1743,7 +1743,7 @@ const StorageExplorerStateContext = createContext( ) export const StorageExplorerStateContextProvider = ({ children }: PropsWithChildren) => { - const project = useSelectedProject() + const { data: project } = useSelectedProjectQuery() const isPaused = project?.status === PROJECT_STATUS.INACTIVE const [state, setState] = useState(() => createStorageExplorerState(DEFAULT_STATE_CONFIG)) From 011f6c3e8782f6b2e6bb11a0a5fc6bc74c0e6ace Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 6 Aug 2025 11:11:14 +0700 Subject: [PATCH 27/28] Fix Table Editor not identifying truncated array column values properly (#37683) * Fix Table Editor not identifying truncated array column values properly * Add comment * update tests * Fix TS issues and shift test file to beside the file its testing * Fix tests --------- Co-authored-by: Jordi Enric --- .../grid/components/editor/JsonEditor.tsx | 2 +- .../RowEditor/RowEditor.utils.test.ts | 716 ++++++++++++++++++ .../RowEditor/RowEditor.utils.ts | 6 +- .../components/Editor/RowEditor.utils.test.ts | 235 ------ packages/pg-meta/src/query/table-row-query.ts | 3 + .../test/query/table-row-query.test.ts | 10 +- 6 files changed, 730 insertions(+), 242 deletions(-) create mode 100644 apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.test.ts delete mode 100644 apps/studio/tests/components/Editor/RowEditor.utils.test.ts diff --git a/apps/studio/components/grid/components/editor/JsonEditor.tsx b/apps/studio/components/grid/components/editor/JsonEditor.tsx index 004e9b45f0b..d1c441c0bc5 100644 --- a/apps/studio/components/grid/components/editor/JsonEditor.tsx +++ b/apps/studio/components/grid/components/editor/JsonEditor.tsx @@ -52,10 +52,10 @@ export const JsonEditor = ({ onRowChange, onExpandEditor, }: JsonEditorProps) => { - const snap = useTableEditorTableStateSnapshot() const { id: _id } = useParams() const id = _id ? Number(_id) : undefined const { data: project } = useSelectedProjectQuery() + const snap = useTableEditorTableStateSnapshot() const { data: selectedTable } = useTableEditorQuery({ projectRef: project?.ref, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.test.ts b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.test.ts new file mode 100644 index 00000000000..8d87b083417 --- /dev/null +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.test.ts @@ -0,0 +1,716 @@ +import { RowField } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.types' +import { + convertByteaToHex, + generateRowObjectFromFields, + isValueTruncated, + parseValue, + validateFields, +} from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' +import { describe, expect, it, vi } from 'vitest' + +describe('parseValue', () => { + it('should return null when originalValue is null', () => { + const originalValue = null + const format = 'some format' + expect(parseValue(originalValue, format)).toBeNull() + }) + + it('should return originalValue when it is 0', () => { + const originalValue = 0 + const format = 'some format' + expect(parseValue(originalValue, format)).toEqual(originalValue) + }) + + it('should return originalValue when it is an empty string', () => { + const originalValue = '' + const format = 'some format' + expect(parseValue(originalValue, format)).toEqual(originalValue) + }) + + it('should return originalValue when it is a number and format is not provided', () => { + const originalValue = 42 + const format = '' + expect(parseValue(originalValue, format)).toEqual(originalValue) + }) + + it('should return JSON string representation when originalValue is an empty array', () => { + const originalValue: any[] = [] + const format = 'some format' + const expectedValue = JSON.stringify(originalValue) + expect(parseValue(originalValue, format)).toEqual(expectedValue) + }) + + it('should return JSON string representation when originalValue is an empty object', () => { + const originalValue = {} + const format = 'some format' + const expectedValue = JSON.stringify(originalValue) + expect(parseValue(originalValue, format)).toEqual(expectedValue) + }) + + it('should return JSON string representation when originalValue is an object', () => { + const originalValue = { key: 'value' } + const format = 'some format' + expect(parseValue(originalValue, format)).toEqual(JSON.stringify(originalValue)) + }) + + it('should handle complex nested object with titles correctly', () => { + const originalValue = { + glossary: { + title: 'parent title', + subItem: { + title: 'subItem title', + items: ['item1', 'item2'], + }, + }, + } + const format = 'some format' + const expectedValue = JSON.stringify(originalValue) + expect(parseValue(originalValue, format)).toEqual(expectedValue) + }) + + it('should handle object with all values set to 0 correctly', () => { + const originalValue = { + width: 0, + height: 0, + length: 0, + weight: 0, + } + const format = 'some format' + const expectedValue = JSON.stringify(originalValue) + expect(parseValue(originalValue, format)).toEqual(expectedValue) + }) + it('should return string representation of originalValue when it is a boolean', () => { + const originalValue = true + const format = 'some format' + expect(parseValue(originalValue, format)).toEqual(originalValue.toString()) + }) + + it('should return originalValue for other cases', () => { + const originalValue = 'some value' + const format = 'some format' + expect(parseValue(originalValue, format)).toEqual(originalValue) + }) + + it('should return originalValue even when an error occurs', () => { + const originalValue = 'some value' + const format = 'some format' + // Mocking an error occurring during parsing + JSON.stringify = vi.fn(() => { + throw new Error('Mocked error') + }) + expect(parseValue(originalValue, format)).toEqual(originalValue) + }) +}) + +describe('generateRowObjectFromFields', () => { + it('should not force NULL values', () => { + const sampleRowFields: RowField[] = [ + { + id: '1', + name: 'id', + value: '', + comment: '', + defaultValue: null, + format: 'int8', + enums: [], + isNullable: false, + isIdentity: false, + isPrimaryKey: false, + }, + { + id: '2', + name: 'time_not_null', + value: '', + comment: '', + defaultValue: 'now()', + format: 'timestamptz', + isNullable: false, + enums: [], + isIdentity: false, + isPrimaryKey: false, + }, + { + id: '3', + name: 'time_nullable', + value: '', + comment: '', + defaultValue: 'now()', + format: 'timestamptz', + isNullable: true, + enums: [], + isIdentity: false, + isPrimaryKey: false, + }, + ] + const result = generateRowObjectFromFields(sampleRowFields) + expect(result).toEqual({}) + }) + it('should discern EMPTY values for text', () => { + const sampleRowFields: RowField[] = [ + { + id: '1', + name: 'id', + value: '', + comment: '', + defaultValue: null, + format: 'int8', + enums: [], + isNullable: false, + isIdentity: false, + isPrimaryKey: false, + }, + { + id: '2', + name: 'name', + value: '', + comment: '', + defaultValue: null, + format: 'text', + enums: [], + isNullable: false, + isIdentity: false, + isPrimaryKey: false, + }, + ] + const result = generateRowObjectFromFields(sampleRowFields) + expect(result).toEqual({ name: '' }) + }) + it('should discern NULL values for text', () => { + const sampleRowFields: RowField[] = [ + { + id: '1', + name: 'id', + value: '', + comment: '', + defaultValue: null, + format: 'int8', + enums: [], + isNullable: false, + isIdentity: false, + isPrimaryKey: false, + }, + { + id: '2', + name: 'name', + value: null, + comment: '', + defaultValue: null, + format: 'text', + enums: [], + isNullable: false, + isIdentity: false, + isPrimaryKey: false, + }, + ] + const result = generateRowObjectFromFields(sampleRowFields) + expect(result).toEqual({}) + }) + it('should discern NULL values for booleans', () => { + const sampleRowFields: RowField[] = [ + { + id: '1', + name: 'id', + value: '', + comment: '', + defaultValue: null, + format: 'int8', + enums: [], + isNullable: false, + isIdentity: false, + isPrimaryKey: false, + }, + { + id: '2', + name: 'bool-test', + value: null, + comment: '', + defaultValue: null, + format: 'bool', + enums: [], + isNullable: false, + isIdentity: false, + isPrimaryKey: false, + }, + ] + const result = generateRowObjectFromFields(sampleRowFields) + expect(result).toEqual({}) + }) +}) + +describe('isValueTruncated', () => { + it('should detect JSON truncated with ...', () => { + // Create a value larger than MAX_CHARACTERS (10KB) with "..." at the end + const value = '{"key": "value"}'.repeat(800) + '...' + expect(isValueTruncated(value)).toBe(true) + }) + + it('should detect array truncated with "..." element', () => { + // Simulate MAX_ARRAY_SIZE elements with "..." at the end + // This matches the pattern from table-row-query.ts: array_cat(column[1:50], array['...']) + const items = Array(50).fill('"item"').join(',') + const value = `[${items},"..."]` + expect(isValueTruncated(value)).toBe(true) + }) + + it('should verify coordination with table-row-query.ts truncation patterns', () => { + // Test the exact patterns that table-row-query.ts generates to ensure isValueTruncated stays in sync + + // Pattern 1: Text/JSON truncation (line 171 in table-row-query.ts) + // left(column::text, 10240) || '...' + const textTruncated = 'a'.repeat(10240) + '...' + expect(isValueTruncated(textTruncated)).toBe(true) + + // Pattern 2: Text array with MAX_ARRAY_SIZE elements + "..." (lines 194, 210) + // array_cat(column[1:50]::text[], array['...']::text[]) + const textArrayItems = Array(50).fill('"item"').join(',') + const textArrayTruncated = `[${textArrayItems},"..."]` + expect(isValueTruncated(textArrayTruncated)).toBe(true) + + // Pattern 3: JSON array with {"truncated": true} marker (lines 194, 210) + // array_cat(column[1:50]::json[], array['{"truncated": true}'::json]::json[]) + const jsonArrayTruncated = `[${Array(5).fill('{"key":"value"}').join(',')},{"truncated":true}]` + expect(isValueTruncated(jsonArrayTruncated)).toBe(true) + + // Pattern 4: Multi-dimensional array (lines 211-212) + // column[1:50]::type[] - no special marker, just detect by [[ pattern + expect(isValueTruncated('[["item"]]')).toBe(true) + expect(isValueTruncated('[["item1","item2"]]')).toBe(true) + }) + + it('should detect multidimensional arrays', () => { + expect(isValueTruncated('[["item1", "item2"]]')).toBe(true) + }) + + it('should detect truncated JSON arrays with truncated flag', () => { + expect(isValueTruncated('[{"a":1},{"b":2},{"truncated":true}]')).toBe(true) + }) + + it('should return false for normal values', () => { + expect(isValueTruncated('normal string')).toBe(false) + expect(isValueTruncated('{"key": "value"}')).toBe(false) + expect(isValueTruncated('["item1", "item2"]')).toBe(false) + expect(isValueTruncated(null)).toBe(false) + expect(isValueTruncated(undefined)).toBe(false) + }) + + it('should return false for empty strings', () => { + expect(isValueTruncated('')).toBe(false) + }) + + it('should handle non-string values', () => { + expect(isValueTruncated(123 as any)).toBe(false) + expect(isValueTruncated({} as any)).toBe(false) + }) + + it('should test edge cases that could break coordination with table-row-query.ts', () => { + // Test values that are just under/at the thresholds to ensure boundaries are correct + + // Text longer than MAX_CHARACTERS with "..." should be detected + const overLimitText = 'a'.repeat(10241) + '...' + expect(isValueTruncated(overLimitText)).toBe(true) + + // Text at exactly MAX_CHARACTERS should NOT be detected (false positive protection) + const exactLimitText = 'a'.repeat(10240) + expect(isValueTruncated(exactLimitText)).toBe(false) + + // Text much shorter than MAX_CHARACTERS with "..." should NOT be detected + const shortTextWithDots = 'short...' + expect(isValueTruncated(shortTextWithDots)).toBe(false) + + // Array with exactly MAX_ARRAY_SIZE elements + "..." should be detected + const exactArraySize = Array(50).fill('"x"').join(',') + expect(isValueTruncated(`[${exactArraySize},"..."]`)).toBe(true) + + // Array with less than MAX_ARRAY_SIZE elements + "..." should NOT be detected + const underArraySize = Array(49).fill('"x"').join(',') + expect(isValueTruncated(`[${underArraySize},"..."]`)).toBe(false) + + // Ensure false positives don't occur for normal arrays ending with "..." + expect(isValueTruncated('["normal", "array", "..."]')).toBe(false) + + // Ensure normal JSON objects with "truncated" key don't trigger false positives + expect(isValueTruncated('[{"data": "normal", "truncated": false}]')).toBe(false) + expect(isValueTruncated('{"truncated": true}')).toBe(false) + }) +}) + +describe('convertByteaToHex', () => { + it('should convert buffer data to hex', () => { + const input = { type: 'Buffer' as 'Buffer', data: [72, 101, 108, 108, 111] } + expect(convertByteaToHex(input)).toBe('\\x48656c6c6f') + }) + + it('should convert empty buffer', () => { + const input = { type: 'Buffer' as 'Buffer', data: [] } + expect(convertByteaToHex(input)).toBe('\\x') + }) + + it('should handle errors gracefully and return original value', () => { + const invalidInput = { type: 'Buffer' as 'Buffer', data: null as any } + expect(convertByteaToHex(invalidInput)).toBe(invalidInput) + }) + + it('should handle malformed input', () => { + const malformedInput = { type: 'NotBuffer' } as any + expect(convertByteaToHex(malformedInput)).toBe(malformedInput) + }) +}) + +describe('validateFields', () => { + const createField = (overrides: Partial): RowField => ({ + id: '1', + name: 'test_field', + comment: '', + format: 'text', + enums: [], + value: '', + defaultValue: null, + isNullable: true, + isIdentity: false, + isPrimaryKey: false, + ...overrides, + }) + + it('should validate array fields with valid JSON', () => { + const fields: RowField[] = [ + createField({ + name: 'tags', + format: '_text', + value: '["valid", "array"]', + }), + ] + expect(validateFields(fields)).toEqual({}) + }) + + it('should return error for invalid array', () => { + const fields: RowField[] = [ + createField({ + name: 'tags', + format: '_text', + value: '[invalid array', + }), + ] + expect(validateFields(fields)).toEqual({ tags: 'Value is an invalid array' }) + }) + + it('should handle JSON validation (minifyJSON dependency issue)', () => { + // Note: This test shows that minifyJSON currently fails on all JSON input + // This may be due to missing dependencies in the test environment + const fields: RowField[] = [ + createField({ + name: 'data', + format: 'jsonb', + value: '{}', + }), + ] + // Currently all JSON fails validation in test environment + expect(validateFields(fields)).toEqual({ data: 'Value is invalid JSON' }) + }) + + it('should return error for invalid JSON', () => { + const fields: RowField[] = [ + createField({ + name: 'data', + format: 'json', + value: '{invalid json}', + }), + ] + expect(validateFields(fields)).toEqual({ data: 'Value is invalid JSON' }) + }) + + it('should skip validation for truncated JSON values', () => { + // Create a value larger than MAX_CHARACTERS (10KB) with "..." at the end + const truncatedValue = '{"key": "value"}'.repeat(800) + '...' + const fields: RowField[] = [ + createField({ + name: 'data', + format: 'json', + value: truncatedValue, + }), + ] + expect(validateFields(fields)).toEqual({}) + }) + + it('should validate identity fields but ignore the early return', () => { + const fields: RowField[] = [ + createField({ + name: 'id', + format: '_text', + value: '[invalid array', + isIdentity: true, + }), + ] + // The early return in validateFields doesn't actually skip array/json validation + expect(validateFields(fields)).toEqual({ id: 'Value is an invalid array' }) + }) + + it('should validate fields with default values but ignore the early return', () => { + const fields: RowField[] = [ + createField({ + name: 'status', + format: 'json', + value: '{invalid json}', + defaultValue: 'active', + }), + ] + // The early return in validateFields doesn't actually skip array/json validation + expect(validateFields(fields)).toEqual({ status: 'Value is invalid JSON' }) + }) + + it('should handle empty JSON fields', () => { + const fields: RowField[] = [ + createField({ + name: 'data', + format: 'jsonb', + value: '', + }), + ] + expect(validateFields(fields)).toEqual({}) + }) + + it('should handle null values in JSON fields', () => { + const fields: RowField[] = [ + createField({ + name: 'data', + format: 'json', + value: null, + }), + ] + expect(validateFields(fields)).toEqual({}) + }) + + it('should validate multiple fields and return all errors', () => { + const fields: RowField[] = [ + createField({ + name: 'tags', + format: '_text', + value: '[invalid array', + }), + createField({ + name: 'data', + format: 'json', + value: '{invalid json}', + }), + createField({ + name: 'valid_field', + format: 'text', + value: 'valid value', + }), + ] + expect(validateFields(fields)).toEqual({ + tags: 'Value is an invalid array', + data: 'Value is invalid JSON', + }) + }) +}) + +describe('generateRowObjectFromFields - additional cases', () => { + const createField = (overrides: Partial): RowField => ({ + id: '1', + name: 'test_field', + comment: '', + format: 'text', + enums: [], + value: '', + defaultValue: null, + isNullable: true, + isIdentity: false, + isPrimaryKey: false, + ...overrides, + }) + + it('should handle array fields', () => { + const fields: RowField[] = [ + createField({ + name: 'tags', + format: '_text', + value: '["tag1", "tag2"]', + }), + ] + expect(generateRowObjectFromFields(fields)).toEqual({ tags: ['tag1', 'tag2'] }) + }) + + it('should handle null array fields', () => { + const fields: RowField[] = [ + createField({ + name: 'tags', + format: '_text', + value: null, + }), + ] + expect(generateRowObjectFromFields(fields)).toEqual({}) + }) + + it('should handle JSON fields', () => { + const fields: RowField[] = [ + createField({ + name: 'metadata', + format: 'jsonb', + value: '{"key": "value"}', + }), + ] + expect(generateRowObjectFromFields(fields)).toEqual({ metadata: { key: 'value' } }) + }) + + it('should handle JSON fields with object values', () => { + const fields: RowField[] = [ + createField({ + name: 'metadata', + format: 'json', + value: { key: 'value' } as any, + }), + ] + expect(generateRowObjectFromFields(fields)).toEqual({ metadata: { key: 'value' } }) + }) + + it('should handle boolean true/false/null', () => { + const fields: RowField[] = [ + createField({ + name: 'active', + format: 'bool', + value: 'true', + }), + createField({ + name: 'deleted', + format: 'bool', + value: 'false', + }), + createField({ + name: 'optional', + format: 'bool', + value: 'null', + }), + ] + // By default, null values are omitted unless includeNullProperties is true + const result = generateRowObjectFromFields(fields) + expect(result).toEqual({ active: true, deleted: false }) + }) + + it('should handle boolean true/false/null with includeNullProperties', () => { + const fields: RowField[] = [ + createField({ + name: 'active', + format: 'bool', + value: 'true', + }), + createField({ + name: 'deleted', + format: 'bool', + value: 'false', + }), + createField({ + name: 'optional', + format: 'bool', + value: 'null', + }), + ] + const result = generateRowObjectFromFields(fields, true) + expect(result).toEqual({ active: true, deleted: false, optional: null }) + }) + + it('should handle boolean with empty value', () => { + const fields: RowField[] = [ + createField({ + name: 'active', + format: 'bool', + value: '', + }), + ] + const result = generateRowObjectFromFields(fields) + expect(result).toEqual({}) + }) + + it('should handle datetime fields with seconds', () => { + const fields: RowField[] = [ + createField({ + name: 'created_at', + format: 'timestamptz', + value: '2023-12-01T10:30:45', + }), + ] + const result: any = generateRowObjectFromFields(fields) + expect(result.created_at).toBeDefined() + expect(typeof result.created_at).toBe('string') + }) + + it('should handle datetime fields without seconds', () => { + const fields: RowField[] = [ + createField({ + name: 'created_at', + format: 'timestamp', + value: '2023-12-01T10:30', + }), + ] + const result: any = generateRowObjectFromFields(fields) + expect(result.created_at).toBeDefined() + expect(typeof result.created_at).toBe('string') + }) + + it('should include null properties when includeNullProperties is true', () => { + const fields: RowField[] = [ + createField({ + name: 'optional_field', + format: 'text', + value: null, + }), + createField({ + name: 'active_field', + format: 'text', + value: 'value', + }), + ] + const result = generateRowObjectFromFields(fields, true) + expect(result).toEqual({ optional_field: null, active_field: 'value' }) + }) + + it('should omit null properties when includeNullProperties is false', () => { + const fields: RowField[] = [ + createField({ + name: 'optional_field', + format: 'text', + value: null, + }), + createField({ + name: 'active_field', + format: 'text', + value: 'value', + }), + ] + const result = generateRowObjectFromFields(fields, false) + expect(result).toEqual({ active_field: 'value' }) + }) + + it('should preserve empty strings for text types', () => { + const fields: RowField[] = [ + createField({ + name: 'description', + format: 'text', + value: '', + }), + createField({ + name: 'title', + format: 'varchar', + value: '', + }), + ] + const result = generateRowObjectFromFields(fields) + expect(result).toEqual({ description: '', title: '' }) + }) + + it('should convert empty values to null for non-text types', () => { + const fields: RowField[] = [ + createField({ + name: 'count', + format: 'int4', + value: '', + }), + createField({ + name: 'price', + format: 'numeric', + value: '', + }), + ] + const result = generateRowObjectFromFields(fields) + expect(result).toEqual({}) + }) +}) 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 d659a107e0e..1dbff8c42ed 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.ts +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils.ts @@ -275,7 +275,11 @@ export const isValueTruncated = (value: string | null | undefined) => { (value.match(/","/g) || []).length === MAX_ARRAY_SIZE) || // if the string represent a multi-dimentional array we always consider it as possibly truncated // so user load the whole value before edition - (typeof value === 'string' && value.startsWith('[["')) + (typeof value === 'string' && value.startsWith('[["')) || + // [Joshen] For json arrays, refer to getTableRowsSql from table-row-query + // for array types, we're adding {"truncated": true} as the last item of the JSON to + // maintain the JSON array structure + (typeof value === 'string' && value.endsWith(',{"truncated":true}]')) ) } diff --git a/apps/studio/tests/components/Editor/RowEditor.utils.test.ts b/apps/studio/tests/components/Editor/RowEditor.utils.test.ts deleted file mode 100644 index 280c0e02345..00000000000 --- a/apps/studio/tests/components/Editor/RowEditor.utils.test.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { RowField } from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.types' -import { - generateRowObjectFromFields, - parseValue, -} from 'components/interfaces/TableGridEditor/SidePanelEditor/RowEditor/RowEditor.utils' -import { describe, expect, it, vi } from 'vitest' - -describe('parseValue', () => { - it('should return null when originalValue is null', () => { - const originalValue = null - const format = 'some format' - expect(parseValue(originalValue, format)).toBeNull() - }) - - it('should return originalValue when it is 0', () => { - const originalValue = 0 - const format = 'some format' - expect(parseValue(originalValue, format)).toEqual(originalValue) - }) - - it('should return originalValue when it is an empty string', () => { - const originalValue = '' - const format = 'some format' - expect(parseValue(originalValue, format)).toEqual(originalValue) - }) - - it('should return originalValue when it is a number and format is not provided', () => { - const originalValue = 42 - const format = '' - expect(parseValue(originalValue, format)).toEqual(originalValue) - }) - - it('should return JSON string representation when originalValue is an empty array', () => { - const originalValue: any[] = [] - const format = 'some format' - const expectedValue = JSON.stringify(originalValue) - expect(parseValue(originalValue, format)).toEqual(expectedValue) - }) - - it('should return JSON string representation when originalValue is an empty object', () => { - const originalValue = {} - const format = 'some format' - const expectedValue = JSON.stringify(originalValue) - expect(parseValue(originalValue, format)).toEqual(expectedValue) - }) - - it('should return JSON string representation when originalValue is an object', () => { - const originalValue = { key: 'value' } - const format = 'some format' - expect(parseValue(originalValue, format)).toEqual(JSON.stringify(originalValue)) - }) - - it('should handle complex nested object with titles correctly', () => { - const originalValue = { - glossary: { - title: 'parent title', - subItem: { - title: 'subItem title', - items: ['item1', 'item2'], - }, - }, - } - const format = 'some format' - const expectedValue = JSON.stringify(originalValue) - expect(parseValue(originalValue, format)).toEqual(expectedValue) - }) - - it('should handle object with all values set to 0 correctly', () => { - const originalValue = { - width: 0, - height: 0, - length: 0, - weight: 0, - } - const format = 'some format' - const expectedValue = JSON.stringify(originalValue) - expect(parseValue(originalValue, format)).toEqual(expectedValue) - }) - it('should return string representation of originalValue when it is a boolean', () => { - const originalValue = true - const format = 'some format' - expect(parseValue(originalValue, format)).toEqual(originalValue.toString()) - }) - - it('should return originalValue for other cases', () => { - const originalValue = 'some value' - const format = 'some format' - expect(parseValue(originalValue, format)).toEqual(originalValue) - }) - - it('should return originalValue even when an error occurs', () => { - const originalValue = 'some value' - const format = 'some format' - // Mocking an error occurring during parsing - JSON.stringify = vi.fn(() => { - throw new Error('Mocked error') - }) - expect(parseValue(originalValue, format)).toEqual(originalValue) - }) -}) - -describe('generateRowObjectFromFields', () => { - it('should not force NULL values', () => { - const sampleRowFields: RowField[] = [ - { - id: '1', - name: 'id', - value: '', - comment: '', - defaultValue: null, - format: 'int8', - enums: [], - isNullable: false, - isIdentity: false, - isPrimaryKey: false, - }, - { - id: '2', - name: 'time_not_null', - value: '', - comment: '', - defaultValue: 'now()', - format: 'timestamptz', - isNullable: false, - enums: [], - isIdentity: false, - isPrimaryKey: false, - }, - { - id: '3', - name: 'time_nullable', - value: '', - comment: '', - defaultValue: 'now()', - format: 'timestamptz', - isNullable: true, - enums: [], - isIdentity: false, - isPrimaryKey: false, - }, - ] - const result = generateRowObjectFromFields(sampleRowFields) - expect(result).toEqual({}) - }) - it('should discern EMPTY values for text', () => { - const sampleRowFields: RowField[] = [ - { - id: '1', - name: 'id', - value: '', - comment: '', - defaultValue: null, - format: 'int8', - enums: [], - isNullable: false, - isIdentity: false, - isPrimaryKey: false, - }, - { - id: '2', - name: 'name', - value: '', - comment: '', - defaultValue: null, - format: 'text', - enums: [], - isNullable: false, - isIdentity: false, - isPrimaryKey: false, - }, - ] - const result = generateRowObjectFromFields(sampleRowFields) - expect(result).toEqual({ name: '' }) - }) - it('should discern NULL values for text', () => { - const sampleRowFields: RowField[] = [ - { - id: '1', - name: 'id', - value: '', - comment: '', - defaultValue: null, - format: 'int8', - enums: [], - isNullable: false, - isIdentity: false, - isPrimaryKey: false, - }, - { - id: '2', - name: 'name', - value: null, - comment: '', - defaultValue: null, - format: 'text', - enums: [], - isNullable: false, - isIdentity: false, - isPrimaryKey: false, - }, - ] - const result = generateRowObjectFromFields(sampleRowFields) - expect(result).toEqual({}) - }) - it('should discern NULL values for booleans', () => { - const sampleRowFields: RowField[] = [ - { - id: '1', - name: 'id', - value: '', - comment: '', - defaultValue: null, - format: 'int8', - enums: [], - isNullable: false, - isIdentity: false, - isPrimaryKey: false, - }, - { - id: '2', - name: 'bool-test', - value: null, - comment: '', - defaultValue: null, - format: 'bool', - enums: [], - isNullable: false, - isIdentity: false, - isPrimaryKey: false, - }, - ] - const result = generateRowObjectFromFields(sampleRowFields) - expect(result).toEqual({}) - }) -}) diff --git a/packages/pg-meta/src/query/table-row-query.ts b/packages/pg-meta/src/query/table-row-query.ts index 9c0a3f6e3a0..1ac95d1babb 100644 --- a/packages/pg-meta/src/query/table-row-query.ts +++ b/packages/pg-meta/src/query/table-row-query.ts @@ -84,6 +84,9 @@ export const getDefaultOrderByColumns = (table: Pick isValueTruncated needs to be revised + * if we're updating the truncation logic, as it'll affect whether the Table Editor displays + * the data as truncated or not */ export const shouldTruncateColumn = (columnFormat: string): boolean => LARGE_COLUMNS_TYPES_SET.has(columnFormat.toLowerCase()) diff --git a/packages/pg-meta/test/query/table-row-query.test.ts b/packages/pg-meta/test/query/table-row-query.test.ts index 62645f9012a..7007cd774c6 100644 --- a/packages/pg-meta/test/query/table-row-query.test.ts +++ b/packages/pg-meta/test/query/table-row-query.test.ts @@ -1653,16 +1653,16 @@ describe('Table Row Query', () => { else subject_id::text end as subject_id, case - when octet_length(timestamp::text) > 10240 + when octet_length("timestamp"::text) > 10240 then case - when array_ndims(timestamp) = 1 + when array_ndims("timestamp") = 1 then - (select array_cat(timestamp[1:50]::text[], array['...']::text[]))::text[] + (select array_cat("timestamp"[1:50]::text[], array['...']::text[]))::text[] else - timestamp[1:50]::text[] + "timestamp"[1:50]::text[] end - else timestamp::text[] + else "timestamp"::text[] end , case From 712a6b15e62d40862b56f1f684475b7c806f8284 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 6 Aug 2025 11:22:45 +0700 Subject: [PATCH 28/28] Chore/address danny friction log (#37659) * Standardize more icons for table editor and storage explorer * Standardize AI perms button CTA copy * Improve toast error copy for invalid folder name * Storage, open folder when its created * Highlight FileExplorerRowEditItem when there's issues with name * Adding a new folder, remove new row if onBlur and folder name has issues * Update tabel editor header action Auth policy -> RLS policy * Add dialog if navigating away from custom report while there's unsaved changes * Add cmd s shortcut to save snippet in SQL editor * Add toggling of favorite to context menu in sql editor * Update save query label * Fix SqlRunButton missing prop hasSelection for SQL editor --- .../components/interfaces/Reports/Reports.tsx | 323 ++++++++++-------- .../interfaces/SQLEditor/MonacoEditor.tsx | 11 + .../SQLEditor/UtilityPanel/RunButton.tsx | 3 +- .../SQLEditor/UtilityPanel/UtilityActions.tsx | 7 +- .../Storage/StorageExplorer/FileExplorer.tsx | 5 +- .../StorageExplorer/FileExplorerColumn.tsx | 5 +- .../StorageExplorer/FileExplorerRow.tsx | 31 +- .../FileExplorerRowEditing.tsx | 14 +- .../StorageExplorer/StorageExplorer.tsx | 1 - .../TableGridEditor/GridHeaderActions.tsx | 2 +- .../SQLEditorNavV2/SQLEditorTreeViewItem.tsx | 36 +- apps/studio/state/storage-explorer.tsx | 36 +- 12 files changed, 290 insertions(+), 184 deletions(-) diff --git a/apps/studio/components/interfaces/Reports/Reports.tsx b/apps/studio/components/interfaces/Reports/Reports.tsx index 044d4e73534..1bd29985dff 100644 --- a/apps/studio/components/interfaces/Reports/Reports.tsx +++ b/apps/studio/components/interfaces/Reports/Reports.tsx @@ -3,6 +3,7 @@ import { useQueryClient } from '@tanstack/react-query' import dayjs from 'dayjs' import { groupBy, isEqual, isNull } from 'lodash' import { ArrowRight, Plus, RefreshCw, Save } from 'lucide-react' +import { useRouter } from 'next/router' import { DragEvent, useEffect, useState } from 'react' import { toast } from 'sonner' @@ -30,6 +31,7 @@ import { useProfile } from 'lib/profile' import { useDatabaseSelectorStateSnapshot } from 'state/database-selector' import { Dashboards } from 'types' import { Button, cn, DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from 'ui' +import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { createSqlSnippetSkeletonV2 } from '../SQLEditor/SQLEditor.utils' import { ChartConfig } from '../SQLEditor/UtilityPanel/ChartConfig' import { GridResize } from './GridResize' @@ -40,6 +42,7 @@ const DEFAULT_CHART_COLUMN_COUNT = 1 const DEFAULT_CHART_ROW_COUNT = 1 const Reports = () => { + const router = useRouter() const { id, ref } = useParams() const { profile } = useProfile() const { data: project } = useSelectedProjectQuery() @@ -54,6 +57,9 @@ const Reports = () => { const [hasEdits, setHasEdits] = useState(false) const [isRefreshing, setIsRefreshing] = useState(false) + const [navigateUrl, setNavigateUrl] = useState() + const [confirmNavigate, setConfirmNavigate] = useState(false) + const { data: userContents, isLoading, @@ -352,6 +358,31 @@ const Reports = () => { checkEditState() }, [config]) + useEffect(() => { + const handleBeforeUnload = (e: BeforeUnloadEvent) => { + if (hasEdits) { + e.preventDefault() + e.returnValue = '' // deprecated, but older browsers still require this + } + } + + const handleBrowseAway = (url: string) => { + if (hasEdits && !confirmNavigate) { + setNavigateUrl(url) + throw 'Route change declined' // Just to prevent the route change + } else { + setNavigateUrl(undefined) + } + } + + window.addEventListener('beforeunload', handleBeforeUnload) + router.events.on('routeChangeStart', handleBrowseAway) + return () => { + window.removeEventListener('beforeunload', handleBeforeUnload) + router.events.off('routeChangeStart', handleBrowseAway) + } + }, [hasEdits, confirmNavigate, router]) + if (isLoading) { return } @@ -361,149 +392,167 @@ const Reports = () => { } return ( -
-
-
-

{currentReport?.name || 'Reports'}

-

{currentReport?.description}

+ <> +
+
+
+

{currentReport?.name || 'Reports'}

+

{currentReport?.description}

+
+ {hasEdits && ( +
+ + +
+ )}
- {hasEdits && ( +
- - + icon={} + className="w-7" + disabled={isRefreshing} + tooltip={{ content: { side: 'bottom', text: 'Refresh report' } }} + onClick={onRefreshReport} + /> +
+ +

+ SQL blocks are independent of the selected date range +

+
+ } + /> + + {startDate && endDate && ( +
+ + {dayjs(startDate).format('MMM D, YYYY')} + + + + + + {dayjs(endDate).format('MMM D, YYYY')} + +
+ )} +
+
+ +
+ {canUpdateReport ? ( + + + + + + + + + ) : ( + } + tooltip={{ + content: { + side: 'bottom', + className: 'w-56 text-center', + text: 'You need additional permissions to update custom reports', + }, + }} + > + Add block + + )} + +
+
+ + {config?.layout !== undefined && config.layout.length === 0 ? ( +
+ {canUpdateReport ? ( + + + + + + + + + ) : ( +

No charts set up yet in report

+ )} +
+ ) : ( +
+ {config && startDate && endDate && ( + + )}
)}
-
-
- } - className="w-7" - disabled={isRefreshing} - tooltip={{ content: { side: 'bottom', text: 'Refresh report' } }} - onClick={onRefreshReport} - /> -
- -

- SQL blocks are independent of the selected date range -

-
- } - /> - - {startDate && endDate && ( -
- - {dayjs(startDate).format('MMM D, YYYY')} - - - - - - {dayjs(endDate).format('MMM D, YYYY')} - -
- )} -
-
- -
- {canUpdateReport ? ( - - - - - - - - - ) : ( - } - tooltip={{ - content: { - side: 'bottom', - className: 'w-56 text-center', - text: 'You need additional permissions to update custom reports', - }, - }} - > - Add block - - )} - -
-
- - {config?.layout !== undefined && config.layout.length === 0 ? ( -
- {canUpdateReport ? ( - - - - - - - - - ) : ( -

No charts set up yet in report

- )} -
- ) : ( -
- {config && startDate && endDate && ( - - )} -
- )} -
+ { + setConfirmNavigate(true) + setNavigateUrl(undefined) + router.push(navigateUrl ?? '/') + }} + onCancel={() => setNavigateUrl(undefined)} + > +

+ Unsaved changes will be lost, are you sure you want to navigate away? +

+
+ ) } diff --git a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx index 59ea6403dc8..97f4fdb668e 100644 --- a/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx +++ b/apps/studio/components/interfaces/SQLEditor/MonacoEditor.tsx @@ -88,6 +88,17 @@ const MonacoEditor = ({ }, }) + editor.addAction({ + id: 'save-query', + label: 'Save Query', + keybindings: [monaco.KeyMod.CtrlCmd + monaco.KeyCode.KeyS], + contextMenuGroupId: 'operation', + contextMenuOrder: 0, + run: () => { + if (snippet) snapV2.addNeedsSaving(snippet.snippet.id) + }, + }) + editor.addAction({ id: 'explain-code', label: 'Explain Code', diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/RunButton.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/RunButton.tsx index 627e73768ab..19403f8278f 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/RunButton.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/RunButton.tsx @@ -1,5 +1,6 @@ -import { detectOS } from 'lib/helpers' import { Command, CornerDownLeft, Loader2 } from 'lucide-react' + +import { detectOS } from 'lib/helpers' import { Button } from 'ui' interface SqlRunButtonProps { diff --git a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx index 29a026d50dd..d7704a00b44 100644 --- a/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx +++ b/apps/studio/components/interfaces/SQLEditor/UtilityPanel/UtilityActions.tsx @@ -6,7 +6,6 @@ import { RoleImpersonationPopover } from 'components/interfaces/RoleImpersonatio import DatabaseSelector from 'components/ui/DatabaseSelector' import { useLocalStorageQuery } from 'hooks/misc/useLocalStorage' import { IS_PLATFORM } from 'lib/constants' -import { detectOS } from 'lib/helpers' import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' import { Button, @@ -27,7 +26,7 @@ export type UtilityActionsProps = { id: string isExecuting?: boolean isDisabled?: boolean - hasSelection: boolean + hasSelection?: boolean prettifyQuery: () => void executeQuery: () => void } @@ -36,11 +35,10 @@ const UtilityActions = ({ id, isExecuting = false, isDisabled = false, - hasSelection, + hasSelection = false, prettifyQuery, executeQuery, }: UtilityActionsProps) => { - const os = detectOS() const { ref } = useParams() const snapV2 = useSqlEditorV2StateSnapshot() @@ -189,6 +187,7 @@ const UtilityActions = ({ variant={IS_PLATFORM ? 'connected-on-both' : 'connected-on-right'} /> void @@ -23,7 +22,6 @@ export interface FileExplorerProps { const FileExplorer = ({ columns = [], - openedFolders = [], selectedItems = [], itemSearchString, onFilesUpload = noop, @@ -61,7 +59,6 @@ const FileExplorer = ({ key={`column-${index}`} index={index} column={column} - openedFolders={openedFolders} selectedItems={selectedItems} itemSearchString={itemSearchString} onFilesUpload={onFilesUpload} diff --git a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx index 84167c8d271..5d1ed5f3066 100644 --- a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx +++ b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx @@ -19,7 +19,7 @@ import { STORAGE_ROW_TYPES, STORAGE_VIEWS, } from '../Storage.constants' -import type { StorageColumn, StorageItem, StorageItemWithColumn } from '../Storage.types' +import type { StorageColumn, StorageItemWithColumn } from '../Storage.types' import FileExplorerRow from './FileExplorerRow' const DragOverOverlay = ({ isOpen, onDragLeave, onDrop, folderIsEmpty }: any) => { @@ -60,7 +60,6 @@ export interface FileExplorerColumnProps { index: number column: StorageColumn fullWidth?: boolean - openedFolders?: StorageItem[] selectedItems: StorageItemWithColumn[] itemSearchString: string onFilesUpload: (event: any, index: number) => void @@ -73,7 +72,6 @@ const FileExplorerColumn = ({ index = 0, column, fullWidth = false, - openedFolders = [], selectedItems = [], itemSearchString, onFilesUpload = noop, @@ -221,7 +219,6 @@ const FileExplorerColumn = ({ view: snap.view, columnIndex: index, selectedItems, - openedFolders, }} ItemComponent={FileExplorerRow} getItemSize={(index) => (index !== 0 && index === columnItems.length ? 85 : 37)} diff --git a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx index 306eb49098f..8979041793e 100644 --- a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx +++ b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx @@ -22,7 +22,6 @@ import type { ItemRenderer } from 'components/ui/InfiniteList' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { BASE_PATH } from 'lib/constants' import { formatBytes } from 'lib/helpers' -import { toast } from 'sonner' import { useStorageExplorerStateSnapshot } from 'state/storage-explorer' import { Checkbox, @@ -51,7 +50,6 @@ import { StorageItem, StorageItemWithColumn } from '../Storage.types' import FileExplorerRowEditing from './FileExplorerRowEditing' import { copyPathToFolder, downloadFile } from './StorageExplorer.utils' import { useCopyUrl } from './useCopyUrl' -import { useSelectedBucket } from './useSelectedBucket' export const RowIcon = ({ view, @@ -104,7 +102,6 @@ export interface FileExplorerRowProps { view: STORAGE_VIEWS columnIndex: number selectedItems: StorageItemWithColumn[] - openedFolders: StorageItem[] } const FileExplorerRow: ItemRenderer = ({ @@ -113,16 +110,14 @@ const FileExplorerRow: ItemRenderer = ({ view = STORAGE_VIEWS.COLUMNS, columnIndex = 0, selectedItems = [], - openedFolders = [], }) => { const { ref: projectRef, bucketId } = useParams() - const { bucket } = useSelectedBucket() const { selectedBucket, selectedFilePreview, + openedFolders, popColumnAtIndex, - pushOpenedFolderAtIndex, popOpenedFoldersAtIndex, clearSelectedItems, setSelectedFilePreview, @@ -131,22 +126,21 @@ const FileExplorerRow: ItemRenderer = ({ setSelectedItemsToDelete, setSelectedItemToRename, setSelectedItemsToMove, - fetchFolderContents, + openFolder, downloadFolder, selectRangeItems, } = useStorageExplorerStateSnapshot() + const { show } = useContextMenu() const { onCopyUrl } = useCopyUrl() const isPublic = selectedBucket.public const itemWithColumnIndex = { ...item, columnIndex } const isSelected = !!selectedItems.find((i) => i.id === item.id) const isOpened = - openedFolders.length > columnIndex ? isEqual(openedFolders[columnIndex], item) : false + openedFolders.length > columnIndex ? openedFolders[columnIndex].name === item.name : false const isPreviewed = !isEmpty(selectedFilePreview) && isEqual(selectedFilePreview?.id, item.id) const canUpdateFiles = useCheckPermissions(PermissionAction.STORAGE_WRITE, '*') - const { show } = useContextMenu() - const onSelectFile = async (columnIndex: number, file: StorageItem) => { popColumnAtIndex(columnIndex) popOpenedFoldersAtIndex(columnIndex - 1) @@ -154,21 +148,6 @@ const FileExplorerRow: ItemRenderer = ({ clearSelectedItems() } - const onSelectFolder = async (columnIndex: number, folder: StorageItem) => { - if (!bucket) return toast.error('Unable to retrieve bucket details') - - setSelectedFilePreview(undefined) - clearSelectedItems(columnIndex + 1) - popOpenedFoldersAtIndex(columnIndex - 1) - pushOpenedFolderAtIndex(folder, columnIndex) - await fetchFolderContents({ - bucketId: bucket.id, - folderId: folder.id, - folderName: folder.name, - index: columnIndex, - }) - } - const onCheckItem = (isShiftKeyHeld: boolean) => { // Select a range if shift is held down if (isShiftKeyHeld && selectedItems.length !== 0) { @@ -346,7 +325,7 @@ const FileExplorerRow: ItemRenderer = ({ event.preventDefault() if (item.status !== STORAGE_ROW_STATUS.LOADING && !isOpened && !isPreviewed) { item.type === STORAGE_ROW_TYPES.FOLDER || item.type === STORAGE_ROW_TYPES.BUCKET - ? onSelectFolder(columnIndex, item) + ? openFolder(columnIndex, item) : onSelectFile(columnIndex, item) } }} diff --git a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRowEditing.tsx b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRowEditing.tsx index 2be0df79f40..cd17e1b1622 100644 --- a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRowEditing.tsx +++ b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRowEditing.tsx @@ -30,7 +30,17 @@ const FileExplorerRowEditing = ({ item, view, columnIndex }: FileExplorerRowEdit const itemWithColumnIndex = { ...item, columnIndex } renameFolder(itemWithColumnIndex, name, columnIndex) } else { - addNewFolder(name, columnIndex) + addNewFolder({ + folderName: name, + columnIndex, + onError: () => { + if (event.type === 'blur') { + addNewFolder({ folderName: '', columnIndex }) + } else { + inputRef.current.select() + } + }, + }) } } @@ -47,7 +57,7 @@ const FileExplorerRowEditing = ({ item, view, columnIndex }: FileExplorerRowEdit const handleEsc = (event: KeyboardEvent) => { if (event.key === 'Escape') { if (item?.id !== undefined) onSaveItemName(item.name) - else addNewFolder('', columnIndex) + else addNewFolder({ folderName: '', columnIndex }) } } diff --git a/apps/studio/components/interfaces/Storage/StorageExplorer/StorageExplorer.tsx b/apps/studio/components/interfaces/Storage/StorageExplorer/StorageExplorer.tsx index cfc8ecd5c40..160e8118e4f 100644 --- a/apps/studio/components/interfaces/Storage/StorageExplorer/StorageExplorer.tsx +++ b/apps/studio/components/interfaces/Storage/StorageExplorer/StorageExplorer.tsx @@ -181,7 +181,6 @@ const StorageExplorer = ({ bucket }: StorageExplorerProps) => {
{ passHref href={`/project/${projectRef}/auth/policies?search=${table.id}&schema=${table.schema}`} > - Auth {policies.length > 1 ? 'policies' : 'policy'} + RLS {policies.length > 1 ? 'policies' : 'policy'} )} diff --git a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorTreeViewItem.tsx b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorTreeViewItem.tsx index 3633fdf5b74..d2c48404aa2 100644 --- a/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorTreeViewItem.tsx +++ b/apps/studio/components/layouts/SQLEditorLayout/SQLEditorNavV2/SQLEditorTreeViewItem.tsx @@ -6,7 +6,18 @@ import { Snippet } from 'data/content/sql-folders-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import useLatest from 'hooks/misc/useLatest' import { useProfile } from 'lib/profile' -import { Copy, Download, Edit, ExternalLink, Lock, Move, Plus, Share, Trash } from 'lucide-react' +import { + Copy, + Download, + Edit, + ExternalLink, + Heart, + Lock, + Move, + Plus, + Share, + Trash, +} from 'lucide-react' import Link from 'next/link' import { useRouter } from 'next/router' import { ComponentProps, useEffect } from 'react' @@ -19,6 +30,7 @@ import { ContextMenuTrigger_Shadcn_, ContextMenu_Shadcn_, TreeViewItem, + cn, } from 'ui' interface SQLEditorTreeViewItemProps @@ -85,6 +97,7 @@ export const SQLEditorTreeViewItem = ({ const isOwner = profile?.id === element?.metadata.owner_id const isSharedSnippet = element.metadata.visibility === 'project' + const isFavorite = element.metadata.favorite const isEditing = status === 'editing' const isSaving = status === 'saving' @@ -154,6 +167,14 @@ export const SQLEditorTreeViewItem = ({ } } + const onToggleFavorite = () => { + const snippetId = element.metadata.id + if (snippetId) { + if (isFavorite) snapV2.removeFavorite(snippetId) + else snapV2.addFavorite(snippetId) + } + } + return ( <> @@ -322,6 +343,19 @@ export const SQLEditorTreeViewItem = ({ Duplicate query )} + onToggleFavorite()} + onFocusCapture={(e) => e.stopPropagation()} + > + + {isFavorite ? 'Remove from' : 'Add to'} favorites + {onSelectDownload !== undefined && IS_PLATFORM && ( { + addNewFolder: async ({ + folderName, + columnIndex, + onError, + }: { + folderName: string + columnIndex: number + onError?: () => void + }) => { if (!state.supabaseClient) return console.error('Supabase Client is missing') const autofix = false @@ -284,10 +292,16 @@ function createStorageExplorerState({ autofix, columnIndex, }) - if (formattedName === null) return + if (formattedName === null) { + onError?.() + return + } if (!/^[a-zA-Z0-9_-\s]*$/.test(formattedName)) { - return toast.error('Folder name contains invalid special characters') + onError?.() + return toast.error( + 'Only alphanumeric characters, hyphens, and underscores are allowed for folder names.' + ) } if (formattedName.length === 0) { @@ -318,6 +332,9 @@ function createStorageExplorerState({ paths: [`${pathToFolder}/${EMPTY_FOLDER_PLACEHOLDER_FILE_NAME}`], }) } + + const newFolder = state.columns[columnIndex].items.find((x) => x.name === formattedName) + if (newFolder) state.openFolder(columnIndex, newFolder) }, fetchFolderContents: async ({ @@ -730,6 +747,19 @@ function createStorageExplorerState({ state.columns = updatedColumns }, + openFolder: async (columnIndex: number, folder: StorageItem) => { + state.setSelectedFilePreview(undefined) + state.clearSelectedItems(columnIndex + 1) + state.popOpenedFoldersAtIndex(columnIndex - 1) + state.pushOpenedFolderAtIndex(folder, columnIndex) + await state.fetchFolderContents({ + bucketId: state.selectedBucket.id, + folderId: folder.id, + folderName: folder.name, + index: columnIndex, + }) + }, + downloadFolder: async (folder: StorageItemWithColumn) => { let progress = 0 const toastId = toast.loading('Retrieving files from folder...')