From dff6c817aeb1299a8c799d0c3db574243adecf68 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Tue, 18 Feb 2025 06:07:53 -0330 Subject: [PATCH] Chore/assistant in self hosted (#33422) * Add layoutheader to self-hosted to allow showing assistant * Fix layout * Remove debug checks * Check for key * Dont load tables * Fix assistant error handling * Yeet * Update turbo.json * Another one * god * Fix * Add fallback * last attempt to fix * Clean up * take the wheel * Tiny fix * Skip enrich query for local, to match prod --------- Co-authored-by: Alaister Young Co-authored-by: Joshen Lim --- .../LayoutHeader/LayoutHeader.tsx | 30 ++- .../layouts/ProjectLayout/ProjectLayout.tsx | 6 - .../ui/AIAssistantPanel/AIAssistant.tsx | 27 ++- .../subscriptions/project-addons-query.ts | 3 +- apps/studio/lib/api/apiHelpers.ts | 3 +- apps/studio/lib/constants/index.ts | 14 +- apps/studio/pages/api/ai/sql/generate-v3.ts | 228 +++++++++--------- apps/studio/pages/api/ai/sql/tools.ts | 27 +-- .../api/platform/pg-meta/[ref]/query/index.ts | 16 +- .../scripts/generate-env.js | 2 +- turbo.json | 3 +- 11 files changed, 187 insertions(+), 172 deletions(-) diff --git a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx index 1e02d2fea2..502aa9150a 100644 --- a/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx +++ b/apps/studio/components/layouts/ProjectLayout/LayoutHeader/LayoutHeader.tsx @@ -21,7 +21,6 @@ import BreadcrumbsView from './BreadcrumbsView' import { FeedbackDropdown } from './FeedbackDropdown' import HelpPopover from './HelpPopover' import NotificationsPopoverV2 from './NotificationsPopoverV2/NotificationsPopover' - const LayoutHeaderDivider = () => (
- {projectRef && ( - - Supabase - + + Supabase + + + {!IS_PLATFORM && ( +
Default project
)} - {projectRef && ( + {projectRef && IS_PLATFORM && ( <>
- {exceedingLimits && (
@@ -129,7 +129,6 @@ const LayoutHeader = ({
)} - {selectedProject && isBranchingEnabled && ( <> @@ -144,7 +143,6 @@ const LayoutHeader = ({
)} - {/* Additional breadcrumbs are supplied */}
diff --git a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx index 64add79fe3..1e83cb1737 100644 --- a/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx +++ b/apps/studio/components/layouts/ProjectLayout/ProjectLayout.tsx @@ -24,7 +24,6 @@ import { ProjectPausedState } from './PausedState/ProjectPausedState' import PauseFailedState from './PauseFailedState' import PausingState from './PausingState' import ProductMenuBar from './ProductMenuBar' -import { ProjectContextProvider } from './ProjectContext' import { ResizingState } from './ResizingState' import RestartingState from './RestartingState' import RestoreFailedState from './RestoreFailedState' @@ -62,8 +61,6 @@ export interface ProjectLayoutProps { isBlocking?: boolean product?: string productMenu?: ReactNode - hideHeader?: boolean - hideIconBar?: boolean selectedTable?: string resizableSidebar?: boolean } @@ -77,8 +74,6 @@ const ProjectLayout = forwardRef { const router = useRouter() const [isClient, setIsClient] = useState(false) - const { ref: projectRef } = useParams() const selectedOrganization = useSelectedOrganization() const selectedProject = useSelectedProject() const { aiAssistantPanel, setAiAssistantPanel, mobileMenuOpen, setMobileMenuOpen } = diff --git a/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx b/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx index 225f61a72a..da9803891d 100644 --- a/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx +++ b/apps/studio/components/ui/AIAssistantPanel/AIAssistant.tsx @@ -96,7 +96,7 @@ export const AIAssistant = ({ const [lastSentMessage, setLastSentMessage] = useState() const [isConfirmOptInModalOpen, setIsConfirmOptInModalOpen] = useState(false) - const { data: check } = useCheckOpenAIKeyQuery() + const { data: check, isSuccess } = useCheckOpenAIKeyQuery() const isApiKeySet = IS_PLATFORM || !!check?.hasKey const isInSQLEditor = router.pathname.includes('/sql/[id]') @@ -106,11 +106,14 @@ export const AIAssistant = ({ const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: selectedOrganization?.slug }) const hasHipaaAddon = subscriptionHasHipaaAddon(subscription) - const { data: tables, isLoading: isLoadingTables } = useTablesQuery({ - projectRef: project?.ref, - connectionString: project?.connectionString, - schema: 'public', - }) + const { data: tables, isLoading: isLoadingTables } = useTablesQuery( + { + projectRef: project?.ref, + connectionString: project?.connectionString, + schema: 'public', + }, + { enabled: isApiKeySet } + ) const currentTable = tables?.find((t) => t.id.toString() === entityId) const currentSchema = searchParams?.get('schema') ?? 'public' @@ -137,6 +140,10 @@ export const AIAssistant = ({ table: currentTable?.name, }, onFinish: (message) => saveLatestMessage(message), + onError: (error) => { + const errorMessage = JSON.parse(error.message).message + toast.error(errorMessage) + }, }) const canUpdateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') @@ -370,14 +377,14 @@ export const AIAssistant = ({ ))}
- ) : isLoadingTables ? ( + ) : isLoadingTables && isApiKeySet ? (
{/* [Joshen] We could try play around with a custom loader for the assistant here */}
) : (tables ?? [])?.length > 0 ? ( - ) : ( + ) : isApiKeySet ? (

Welcome to Supabase!

@@ -428,7 +435,7 @@ export const AIAssistant = ({ ))}

- )} + ) : null} @@ -495,7 +502,7 @@ export const AIAssistant = ({ /> )} - {!isApiKeySet && ( + {isSuccess && !isApiKeySet && ( ( subscriptionKeys.addons(projectRef), ({ signal }) => getProjectAddons({ projectRef }, signal), { - enabled: enabled && typeof projectRef !== 'undefined', + enabled: enabled && IS_PLATFORM && typeof projectRef !== 'undefined', ...options, } ) diff --git a/apps/studio/lib/api/apiHelpers.ts b/apps/studio/lib/api/apiHelpers.ts index e361cd0541..735a33e30a 100644 --- a/apps/studio/lib/api/apiHelpers.ts +++ b/apps/studio/lib/api/apiHelpers.ts @@ -1,5 +1,5 @@ -import { snakeCase } from 'lodash' import { IS_PLATFORM } from 'lib/constants' +import { snakeCase } from 'lodash' /** * Construct headers for api request. @@ -13,6 +13,7 @@ export function constructHeaders(headers: { [prop: string]: any }) { const cleansedHeaders = { Accept: headers.Accept, Authorization: headers.Authorization, + cookie: headers.cookie, 'Content-Type': headers['Content-Type'], 'x-connection-encrypted': headers['x-connection-encrypted'], } as any diff --git a/apps/studio/lib/constants/index.ts b/apps/studio/lib/constants/index.ts index 0f6e01097c..5f37947e32 100644 --- a/apps/studio/lib/constants/index.ts +++ b/apps/studio/lib/constants/index.ts @@ -5,8 +5,18 @@ export * from './infrastructure' export const IS_PLATFORM = process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' export const DEFAULT_HOME = IS_PLATFORM ? '/projects' : '/project/default' -// TODO: Replace PG_META_URL with STUDIO_PG_META_URL and remove all references to PLATFORM_PG_META_URL -export const API_URL = IS_PLATFORM ? process.env.NEXT_PUBLIC_API_URL! : '/api' +export const API_URL = (() => { + // If running in platform, use API_URL from the env var + if (IS_PLATFORM) return process.env.NEXT_PUBLIC_API_URL! + // If running in browser, let it add the host + if (typeof window !== 'undefined') return '/api' + // If running self-hosted Vercel preview, use VERCEL_URL + if (!!process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}/api` + // If running on self-hosted, use NEXT_PUBLIC_SITE_URL + if (!!process.env.NEXT_PUBLIC_SITE_URL) return `${process.env.NEXT_PUBLIC_SITE_URL}/api` + return '/api' +})() + export const PG_META_URL = IS_PLATFORM ? process.env.PLATFORM_PG_META_URL : process.env.STUDIO_PG_META_URL diff --git a/apps/studio/pages/api/ai/sql/generate-v3.ts b/apps/studio/pages/api/ai/sql/generate-v3.ts index 4055873541..d0b280c4e4 100644 --- a/apps/studio/pages/api/ai/sql/generate-v3.ts +++ b/apps/studio/pages/api/ai/sql/generate-v3.ts @@ -37,117 +37,129 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse) { }) } + const cookie = req.headers.cookie const authorization = req.headers.authorization - const { result: schemas } = includeSchemaMetadata - ? await executeSql( - { - projectRef, - connectionString, - sql: pgMetaSchemasList.sql, - }, - undefined, - { - 'Content-Type': 'application/json', - ...(authorization && { Authorization: authorization }), - } - ) - : { result: [] } + try { + const { result: schemas } = includeSchemaMetadata + ? await executeSql( + { + projectRef, + connectionString, + sql: pgMetaSchemasList.sql, + }, + undefined, + { + 'Content-Type': 'application/json', + ...(cookie && { cookie }), + ...(authorization && { Authorization: authorization }), + } + ) + : { result: [] } - const result = await streamText({ - model: openai('gpt-4o-mini'), - maxSteps: 5, - system: ` - You are a Supabase Postgres expert who can do the following things. - - # You generate and debug SQL - The generated SQL (must be valid SQL), and must adhere to the following: - - Always use double apostrophe in SQL strings (eg. 'Night''s watch') - - Always use semicolons - - Output as markdown - - Always include code snippets if available - - If a code snippet is SQL, the first line of the snippet should always be -- props: {"title": "Query title", "runQuery": "false", "isChart": "true", "xAxis": "columnOrAlias", "yAxis": "columnOrAlias"} - - Only include one line of comment props per markdown snippet, even if the snippet has multiple queries - - Only set chart to true if the query makes sense as a chart. xAxis and yAxis need to be columns or aliases returned by the query. - - Only set runQuery to true if the query has no risk of writing data and is not a debugging request. Set it to false if there are any values that need to be replaced with real data. - - Explain what the snippet does in a sentence or two before showing it - - Use vector(384) data type for any embedding/vector related query - - When debugging, retrieve sql schema details to ensure sql is correct - - In Supabase, the auth schema already has a users table which is used to store users. It is common practice to create a profiles table in the public schema that links to auth.users to store user information instead. You don't need to create a new users table. - - Never suggest creating a view to retrieve information from the users table of the auth schema. This is against our best practices. - - When generating tables, do the following: - - Ensure that all tables always have a primary key - - Ensure that all tables have RLS enabled. Inform the user that they will need to create RLS policies before being able to read or write to the table over Supabase APIs. - - For primary keys, always use "id bigint primary key generated always as identity" (not serial) - - Prefer creating foreign key references in the create statement - - Prefer 'text' over 'varchar' - - Prefer 'timestamp with time zone' over 'date' - - If a foreign key is created, include a statement to create a database index on the columns involved in the foreign key. This is a best practice as it is common to use foreign key columns in join conditions when querying the database, hence the index will improve the performance of those joins and reduce database resource consumption. - - If the table is a foreign table, create it in a new schema called private. If the private schema doesnt exist, create it. - - Explain to the user that we create it outside of the public schema as it can present a security risk as foreign tables views cannot be configured to respect RLS policies. Provide this link for users to view more details about the security risk: https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0017_foreign_table_in_api - - When generating views, do the following: - - All views should include 'with (security_invoker=on)' clause in the SQL statement for creating views (only views though - do not do this for tables) - - Place the 'with (security_invoker=on)' immediately after the CREATE VIEW statement, before AS - - If the view is a materialized view, create it in a new schema called private. If the private schema doesnt exist, create it. - - Explain to the user that we create it outside of the public schema as it can present a security risk as materialized views cannot be configured to respect RLS policies of the underlying tables they are built upon, nor can they be secured with RLS directly. Provide this link for users to view more details about the security risk: https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0016_materialized_view_in_api - - When installing database extensions, do the following: - - Never install extensions in the public schema - - Extensions should be installed in the extensions schema, or a dedicated schema - - Feel free to suggest corrections for suspected typos. - - # You write row level security policies. - - Your purpose is to generate a policy with the constraints given by the user. - - First, use getSchema to retrieve more information about a schema or schemas that will contain policies, usually the public schema. - - Then retrieve existing RLS policies and guidelines on how to write policies using the getRlsKnowledge tool . - - Then write new policies or update existing policies based on the prompt - - When asked to suggest policies, either alter existing policies or add new ones to the public schema. - - When writing policies that use a function from the auth schema, ensure that the calls are wrapped with parentheses e.g select auth.uid() should be written as (select auth.uid()) instead - - # You write database functions - Your purpose is to generate a database function with the constraints given by the user. The output may also include a database trigger - if the function returns a type of trigger. When generating functions, do the following: - - If the function returns a trigger type, ensure that it uses security definer, otherwise default to security invoker. Include this in the create functions SQL statement. - - Ensure to set the search_path configuration parameter as '', include this in the create functions SQL statement. - - Default to create or replace whenever possible for updating an existing function, otherwise use the alter function statement - Please make sure that all queries are valid Postgres SQL queries - - # You write edge functions - Your purpose is to generate entire edge functions with the constraints given by the user. - - First, always use the getEdgeFunctionKnowledge tool to get knowledge about how to write edge functions for Supabase - - When writing edge functions, always ensure that they are written in TypeScript and Deno JavaScript runtime. - - When writing edge functions, write complete code so the user doesn't need to replace any placeholders. - - When writing edge functions, always ensure that they are written in a way that is compatible with the database schema. - - When suggesting edge functions, follow the guidelines in getEdgeFunctionKnowledge tool. Always create personalised edge functions based on the database schema - - When outputting edge functions, always include a props comment in the first line of the code block: - -- props: {"name": "function-name", "title": "Human readable title"} - - The function name in the props must be URL-friendly (use hyphens instead of spaces or underscores) - - Always wrap the edge function code in a markdown code block with the language set to 'edge' - - The props comment must be the first line inside the code block, followed by the actual function code - - # You convert sql to supabase-js client code - Use the convertSqlToSupabaseJs tool to convert select sql to supabase-js client code. Only provide js code snippets if explicitly asked. If conversion isn't supported, build a postgres function instead and suggest using supabase-js to call it via "const { data, error } = await supabase.rpc('echo', { say: '👋'})" - - # For all your abilities, follow these instructions: - - First look at the list of provided schemas and if needed, get more information about a schema. You will almost always need to retrieve information about the public schema before answering a question. - - If the question is about users or involves creating a users table, also retrieve the auth schema. - - If it a query is a destructive query e.g. table drop, ask for confirmation before writing the query. The user will still have to run the query once you create it + const result = await streamText({ + model: openai('gpt-4o-mini'), + maxSteps: 5, + system: ` + You are a Supabase Postgres expert who can do the following things. + # You generate and debug SQL + The generated SQL (must be valid SQL), and must adhere to the following: + - Always use double apostrophe in SQL strings (eg. 'Night''s watch') + - Always use semicolons + - Output as markdown + - Always include code snippets if available + - If a code snippet is SQL, the first line of the snippet should always be -- props: {"title": "Query title", "runQuery": "false", "isChart": "true", "xAxis": "columnOrAlias", "yAxis": "columnOrAlias"} + - Only include one line of comment props per markdown snippet, even if the snippet has multiple queries + - Only set chart to true if the query makes sense as a chart. xAxis and yAxis need to be columns or aliases returned by the query. + - Only set runQuery to true if the query has no risk of writing data and is not a debugging request. Set it to false if there are any values that need to be replaced with real data. + - Explain what the snippet does in a sentence or two before showing it + - Use vector(384) data type for any embedding/vector related query + - When debugging, retrieve sql schema details to ensure sql is correct + - In Supabase, the auth schema already has a users table which is used to store users. It is common practice to create a profiles table in the public schema that links to auth.users to store user information instead. You don't need to create a new users table. + - Never suggest creating a view to retrieve information from the users table of the auth schema. This is against our best practices. + + When generating tables, do the following: + - Ensure that all tables always have a primary key + - Ensure that all tables have RLS enabled. Inform the user that they will need to create RLS policies before being able to read or write to the table over Supabase APIs. + - For primary keys, always use "id bigint primary key generated always as identity" (not serial) + - Prefer creating foreign key references in the create statement + - Prefer 'text' over 'varchar' + - Prefer 'timestamp with time zone' over 'date' + - If a foreign key is created, include a statement to create a database index on the columns involved in the foreign key. This is a best practice as it is common to use foreign key columns in join conditions when querying the database, hence the index will improve the performance of those joins and reduce database resource consumption. + - If the table is a foreign table, create it in a new schema called private. If the private schema doesnt exist, create it. + - Explain to the user that we create it outside of the public schema as it can present a security risk as foreign tables views cannot be configured to respect RLS policies. Provide this link for users to view more details about the security risk: https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0017_foreign_table_in_api + + When generating views, do the following: + - All views should include 'with (security_invoker=on)' clause in the SQL statement for creating views (only views though - do not do this for tables) + - Place the 'with (security_invoker=on)' immediately after the CREATE VIEW statement, before AS + - If the view is a materialized view, create it in a new schema called private. If the private schema doesnt exist, create it. + - Explain to the user that we create it outside of the public schema as it can present a security risk as materialized views cannot be configured to respect RLS policies of the underlying tables they are built upon, nor can they be secured with RLS directly. Provide this link for users to view more details about the security risk: https://supabase.com/docs/guides/database/database-advisors?queryGroups=lint&lint=0016_materialized_view_in_api + + When installing database extensions, do the following: + - Never install extensions in the public schema + - Extensions should be installed in the extensions schema, or a dedicated schema + + Feel free to suggest corrections for suspected typos. + + # You write row level security policies. + + Your purpose is to generate a policy with the constraints given by the user. + - First, use getSchema to retrieve more information about a schema or schemas that will contain policies, usually the public schema. + - Then retrieve existing RLS policies and guidelines on how to write policies using the getRlsKnowledge tool . + - Then write new policies or update existing policies based on the prompt + - When asked to suggest policies, either alter existing policies or add new ones to the public schema. + - When writing policies that use a function from the auth schema, ensure that the calls are wrapped with parentheses e.g select auth.uid() should be written as (select auth.uid()) instead + + # You write database functions + Your purpose is to generate a database function with the constraints given by the user. The output may also include a database trigger + if the function returns a type of trigger. When generating functions, do the following: + - If the function returns a trigger type, ensure that it uses security definer, otherwise default to security invoker. Include this in the create functions SQL statement. + - Ensure to set the search_path configuration parameter as '', include this in the create functions SQL statement. + - Default to create or replace whenever possible for updating an existing function, otherwise use the alter function statement + Please make sure that all queries are valid Postgres SQL queries + + # You write edge functions + Your purpose is to generate entire edge functions with the constraints given by the user. + - First, always use the getEdgeFunctionKnowledge tool to get knowledge about how to write edge functions for Supabase + - When writing edge functions, always ensure that they are written in TypeScript and Deno JavaScript runtime. + - When writing edge functions, write complete code so the user doesn't need to replace any placeholders. + - When writing edge functions, always ensure that they are written in a way that is compatible with the database schema. + - When suggesting edge functions, follow the guidelines in getEdgeFunctionKnowledge tool. Always create personalised edge functions based on the database schema + - When outputting edge functions, always include a props comment in the first line of the code block: + -- props: {"name": "function-name", "title": "Human readable title"} + - The function name in the props must be URL-friendly (use hyphens instead of spaces or underscores) + - Always wrap the edge function code in a markdown code block with the language set to 'edge' + - The props comment must be the first line inside the code block, followed by the actual function code + + # You convert sql to supabase-js client code + Use the convertSqlToSupabaseJs tool to convert select sql to supabase-js client code. Only provide js code snippets if explicitly asked. If conversion isn't supported, build a postgres function instead and suggest using supabase-js to call it via "const { data, error } = await supabase.rpc('echo', { say: '👋'})" + + # For all your abilities, follow these instructions: + - First look at the list of provided schemas and if needed, get more information about a schema. You will almost always need to retrieve information about the public schema before answering a question. + - If the question is about users or involves creating a users table, also retrieve the auth schema. + - If it a query is a destructive query e.g. table drop, ask for confirmation before writing the query. The user will still have to run the query once you create it + + + Here are the existing database schema names you can retrieve: ${schemas} + + ${schema !== undefined && includeSchemaMetadata ? `The user is currently looking at the ${schema} schema.` : ''} + ${table !== undefined && includeSchemaMetadata ? `The user is currently looking at the ${table} table.` : ''} + `, + messages, + tools: getTools({ + projectRef, + connectionString, + cookie, + authorization, + includeSchemaMetadata, + }), + }) - Here are the existing database schema names you can retrieve: ${schemas} - - ${schema !== undefined && includeSchemaMetadata ? `The user is currently looking at the ${schema} schema.` : ''} - ${table !== undefined && includeSchemaMetadata ? `The user is currently looking at the ${table} table.` : ''} - `, - messages, - tools: getTools({ projectRef, connectionString, authorization, includeSchemaMetadata }), - }) - - // write the data stream to the response - // Note: this is sent as a single response, not a stream - result.pipeDataStreamToResponse(res) + // write the data stream to the response + // Note: this is sent as a single response, not a stream + result.pipeDataStreamToResponse(res) + } catch (error: any) { + return res.status(500).json({ message: error.message }) + } } diff --git a/apps/studio/pages/api/ai/sql/tools.ts b/apps/studio/pages/api/ai/sql/tools.ts index d3b212ce83..a0da432e70 100644 --- a/apps/studio/pages/api/ai/sql/tools.ts +++ b/apps/studio/pages/api/ai/sql/tools.ts @@ -2,23 +2,31 @@ import { tool } from 'ai' import { stripIndent } from 'common-tags' import { z } from 'zod' +import { processSql, renderSupabaseJs } from '@supabase/sql-to-rest' +import { getDatabaseFunctions } from 'data/database-functions/database-functions-query' import { getDatabasePolicies } from 'data/database-policies/database-policies-query' import { getEntityDefinitionsSql } from 'data/database/entity-definitions-query' import { executeSql } from 'data/sql/execute-sql-query' -import { processSql, renderSupabaseJs } from '@supabase/sql-to-rest' -import { getDatabaseFunctions } from 'data/database-functions/database-functions-query' export const getTools = ({ projectRef, connectionString, + cookie, authorization, includeSchemaMetadata, }: { projectRef: string connectionString: string + cookie?: string authorization?: string includeSchemaMetadata: boolean }) => { + const headers = { + 'Content-Type': 'application/json', + ...(cookie && { cookie }), + ...(authorization && { Authorization: authorization }), + } + return { getSchema: tool({ description: 'Get more information about one or more schemas', @@ -35,10 +43,7 @@ export const getTools = ({ sql: getEntityDefinitionsSql({ schemas }), }, undefined, - { - 'Content-Type': 'application/json', - ...(authorization && { Authorization: authorization }), - } + headers ) : { result: [] } @@ -82,10 +87,7 @@ export const getTools = ({ connectionString, }, undefined, - { - 'Content-Type': 'application/json', - ...(authorization && { Authorization: authorization }), - } + headers ) : [] @@ -357,10 +359,7 @@ export const getTools = ({ connectionString, }, undefined, - { - 'Content-Type': 'application/json', - ...(authorization && { Authorization: authorization }), - } + headers ) : [] diff --git a/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts b/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts index c207469056..fc76638b99 100644 --- a/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts +++ b/apps/studio/pages/api/platform/pg-meta/[ref]/query/index.ts @@ -1,8 +1,8 @@ -import { NextApiRequest, NextApiResponse } from 'next' -import apiWrapper from 'lib/api/apiWrapper' import { constructHeaders } from 'lib/api/apiHelpers' -import { PG_META_URL } from 'lib/constants' +import apiWrapper from 'lib/api/apiWrapper' import { post } from 'lib/common/fetch' +import { PG_META_URL } from 'lib/constants' +import { NextApiRequest, NextApiResponse } from 'next' export default (req: NextApiRequest, res: NextApiResponse) => apiWrapper(req, res, handler, { withAuth: true }) @@ -22,7 +22,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { const handlePost = async (req: NextApiRequest, res: NextApiResponse) => { const { query } = req.body const headers = constructHeaders(req.headers) - const response = await post(`${PG_META_URL}/query`, { query: enrichQuery(query) }, { headers }) + const response = await post(`${PG_META_URL}/query`, { query }, { headers }) if (response.error) { return res.status(400).json(response.error) @@ -30,11 +30,3 @@ const handlePost = async (req: NextApiRequest, res: NextApiResponse) => { return res.status(200).json(response) } } - -const enrichQuery = (query: string) => ` --- source: dashboard --- user: ${'self host'} --- date: ${new Date().toISOString()} - -${query} -` diff --git a/tests/local-studio-tests/scripts/generate-env.js b/tests/local-studio-tests/scripts/generate-env.js index 5804e6a522..f1df4987dc 100644 --- a/tests/local-studio-tests/scripts/generate-env.js +++ b/tests/local-studio-tests/scripts/generate-env.js @@ -21,7 +21,7 @@ const defaultEnv = { SENTRY_IGNORE_API_RESOLUTION_ERROR: '1', LOGFLARE_URL: 'http://localhost:54329', LOGFLARE_API_KEY: 'api-key', - NEXT_PUBLIC_SITE_URL: 'http://localhost:3000', + NEXT_PUBLIC_SITE_URL: 'http://localhost:8082', NEXT_PUBLIC_GOTRUE_URL: '$SUPABASE_PUBLIC_URL/auth/v1', NEXT_PUBLIC_HCAPTCHA_SITE_KEY: '10000000-ffff-ffff-ffff-000000000001', NEXT_PUBLIC_NODE_ENV: 'test', diff --git a/turbo.json b/turbo.json index f4aca92dca..ba28942aff 100644 --- a/turbo.json +++ b/turbo.json @@ -70,7 +70,8 @@ "AWS_SECRET_ACCESS_KEY", "FORCE_ASSET_CDN", "ASSET_CDN_S3_ENDPOINT", - "SITE_NAME" + "SITE_NAME", + "VERCEL_URL" ], "outputs": [".next/**", "!.next/cache/**"] },