ronantakizawa/codereview-bench huggingface dataset:
Repository: supabase/supabase
File: apps/studio/lib/api/self-hosted/types.ts (TypeScript)

Code before:
import z from 'zod/v4'

export type WrappedSuccessResult<T> = { data: T; error: undefined }
export type WrappedErrorResult = { data: undefined; error: Error }
export type WrappedResult<R> = WrappedSuccessResult<R> | WrappedErrorResult

export const databaseErrorSchema = z.object({
  message: z.string(),
  code: z.string(),
})

export class DatabaseError extends Error {
  constructor(
    message: string,
    public code: string
  ) {
    super(message)
    this.name = 'DatabaseError'
  }
}


Review comment (suggestion):
We were already using this pattern previously on self-hosted functions, this just adds better type safety by making it explicit

Code after:
import z from 'zod/v4'

export type WrappedSuccessResult<T> = { data: T; error: undefined }
export type WrappedErrorResult = { data: undefined; error: Error }
export type WrappedResult<R> = WrappedSuccessResult<R> | WrappedErrorResult

export const databaseErrorSchema = z.object({
  message: z.string(),
  code: z.string(),
  formattedError: z.string(),
})

export class PgMetaDatabaseError extends Error {
  constructor(
    message: string,
    public code: string,
    public statusCode: number,
    public formattedError: string
  ) {
    super(message)
    this.name = 'PgMetaDatabaseError'
  }
}
Repository: supabase/supabase
File: packages/ui-patterns/src/McpUrlBuilder/constants.tsx (TypeScript)

Code before:
    description: 'Debug and troubleshoot issues',
  },
  {
    id: 'development',
    name: 'Development',
    description: 'Development tools and utilities',
  },
  {
    id: 'functions',
    name: 'Functions',
    description: 'Manage and deploy Edge Functions',
  },
  {
    id: 'branching',
    name: 'Branching',
    description: 'Manage database branches',
  },
  {
    id: 'storage',
    name: 'Storage',
    description: 'Manage files and storage buckets',
  },
]

export const FEATURE_GROUPS_NON_PLATFORM = FEATURE_GROUPS_PLATFORM.filter((group) =>
  ['docs', 'database'].includes(group.id)
)

export const MCP_CLIENTS: McpClient[] = [
  {
    key: 'cursor',
    label: 'Cursor',
    icon: 'cursor',
    configFile: '.cursor/mcp.json',
    externalDocsUrl: 'https://docs.cursor.com/context/mcp',
    generateDeepLink: (config) => {
      const name = 'supabase'
      const base64Config = Buffer.from(JSON.stringify(config.mcpServers.supabase)).toString(
        'base64'
      )
      return `cursor://anysphere.cursor-deeplink/mcp/install?name=${name}&config=${encodeURIComponent(base64Config)}`
    },
  },
  {
    key: 'vscode',
    label: 'VS Code',
    icon: 'vscode',
    configFile: '.vscode/mcp.json',
    externalDocsUrl: 'https://code.visualstudio.com/docs/copilot/chat/mcp-servers',
    transformConfig: (config): VSCodeMcpConfig => {
      return {

Review comment (suggestion):
Maybe could wire this up to the same list of constants as the query schema in the server implementation:

https://github.com/supabase/supabase/blob/90976b798848ccc5bcb9c9b67a302f51609882ad/apps/studio/pages/api/mcp/index.ts#L10

Code after:
    description: 'Debug and troubleshoot issues',
  },
  {
    id: 'development',
    name: 'Development',
    description: 'Development tools and utilities',
  },
  {
    id: 'functions',
    name: 'Functions',
    description: 'Manage and deploy Edge Functions',
  },
  {
    id: 'branching',
    name: 'Branching',
    description: 'Manage database branches',
  },
  {
    id: 'storage',
    name: 'Storage',
    description: 'Manage files and storage buckets',
  },
]

export const FEATURE_GROUPS_NON_PLATFORM = FEATURE_GROUPS_PLATFORM.filter((group) =>
  ['docs', 'database', 'development'].includes(group.id)
)

export const MCP_CLIENTS: McpClient[] = [
  {
    key: 'cursor',
    label: 'Cursor',
    icon: 'cursor',
    configFile: '.cursor/mcp.json',
    externalDocsUrl: 'https://docs.cursor.com/context/mcp',
    generateDeepLink: (config) => {
      const name = 'supabase'
      const base64Config = Buffer.from(JSON.stringify(config.mcpServers.supabase)).toString(
        'base64'
      )
      return `cursor://anysphere.cursor-deeplink/mcp/install?name=${name}&config=${encodeURIComponent(base64Config)}`
    },
  },
  {
    key: 'vscode',
    label: 'VS Code',
    icon: 'vscode',
    configFile: '.vscode/mcp.json',
    externalDocsUrl: 'https://code.visualstudio.com/docs/copilot/chat/mcp-servers',
    transformConfig: (config): VSCodeMcpConfig => {
      return {
Repository: supabase/supabase
File: apps/studio/pages/api/v1/projects/[ref]/types/typescript.ts (TypeScript)

Code before:

export default (req: NextApiRequest, res: NextApiResponse) =>
  apiWrapper(req, res, handler, { withAuth: true })

async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { method } = req

  switch (method) {
    case 'GET':
      return handleGetAll(req, res)
    default:
      res.setHeader('Allow', ['GET'])
      res.status(405).json({ error: { message: `Method ${method} Not Allowed` } })
  }
}

const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => {
  const headers = constructHeaders(req.headers)

  const { data, error } = await generateTypescriptTypes({ headers })

  if (error) {
    if (error instanceof PgMetaDatabaseError) {
      const { statusCode, message, formattedError } = error
      return res.status(statusCode).json({ message, formattedError })
    }
    const { message } = error
    return res.status(500).json({ message, formattedError: message })
  } else {
    return res.status(200).json(data)
  }
}


Review comment (suggestion):
I don't think `error` will ever be an instance of `PgMetaDatabaseError` since this is an error we manually create in `lib/api/self-hosted/query.ts`. Since you are using the `fetchGet` wrapper, you can probably check for `instanceof ResponseError` instead, then pull out the `message` and `code` as we did previously.

Code after:

export default (req: NextApiRequest, res: NextApiResponse) =>
  apiWrapper(req, res, handler, { withAuth: true })

async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { method } = req

  switch (method) {
    case 'GET':
      return handleGetAll(req, res)
    default:
      res.setHeader('Allow', ['GET'])
      res.status(405).json({ error: { message: `Method ${method} Not Allowed` } })
  }
}

const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => {
  const headers = constructHeaders(req.headers)

  const response = await generateTypescriptTypes({ headers })

  if (response instanceof ResponseError) {
    return res.status(response.code ?? 500).json({ message: response.message })
  }

  return res.status(200).json(response)
}
Repository: supabase/supabase
File: apps/studio/pages/api/v1/projects/[ref]/types/typescript.ts (TypeScript)

Code before:
export default (req: NextApiRequest, res: NextApiResponse) =>
  apiWrapper(req, res, handler, { withAuth: true })

async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { method } = req

  switch (method) {
    case 'GET':
      return handleGetAll(req, res)
    default:
      res.setHeader('Allow', ['GET'])
      res.status(405).json({ error: { message: `Method ${method} Not Allowed` } })
  }
}

const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => {
  const headers = constructHeaders(req.headers)

  const { data, error } = await generateTypescriptTypes({ headers })

  if (error) {
    if (error instanceof PgMetaDatabaseError) {
      const { statusCode, message, formattedError } = error
      return res.status(statusCode).json({ message, formattedError })
    }
    const { message } = error
    return res.status(500).json({ message, formattedError: message })
  } else {
    return res.status(200).json(data)
  }
}


Review comment (suggestion):
Am I missing something or is it impossible for this to be returned as a `PgMetaDatabaseError`? The only functions that check an error to possibly wrap it as a `PgMetaDatabaseError` are `executeQuery` and the `handlePost` from `/platform/pg-meta/[ref]/query`, but this is using `fetchGet`

Code after:
export default (req: NextApiRequest, res: NextApiResponse) =>
  apiWrapper(req, res, handler, { withAuth: true })

async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { method } = req

  switch (method) {
    case 'GET':
      return handleGetAll(req, res)
    default:
      res.setHeader('Allow', ['GET'])
      res.status(405).json({ error: { message: `Method ${method} Not Allowed` } })
  }
}

const handleGetAll = async (req: NextApiRequest, res: NextApiResponse) => {
  const headers = constructHeaders(req.headers)

  const response = await generateTypescriptTypes({ headers })

  if (response instanceof ResponseError) {
    return res.status(response.code ?? 500).json({ message: response.message })
  }

  return res.status(200).json(response)
}
Repository: supabase/supabase
File: apps/studio/lib/api/self-hosted/constants.ts (TypeScript)

Code before:
// Constants specific to self-hosted environments

export const ENCRYPTION_KEY = 'SAMPLE_KEY' // See postgres-meta `CRYPTO_KEY` fallback
export const POSTGRES_PORT = process.env.POSTGRES_PORT || 5432
export const POSTGRES_HOST = process.env.POSTGRES_HOST || 'db'
export const POSTGRES_DATABASE = process.env.POSTGRES_DB || 'postgres'
export const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD || 'postgres'
export const POSTGRES_USER_READ_WRITE = 'postgres'
export const POSTGRES_USER_READ_ONLY = 'supabase_read_only_user'


Review comment (security):
I'm not super familiar with the hosted platform, should this be synced with `postgres-meta`'s implementation of `getSecret('CRYPTO_KEY')`?

Code after:
// Constants specific to self-hosted environments

export const ENCRYPTION_KEY = process.env.PG_META_CRYPTO_KEY || 'SAMPLE_KEY'
export const POSTGRES_PORT = process.env.POSTGRES_PORT || 5432
export const POSTGRES_HOST = process.env.POSTGRES_HOST || 'db'
export const POSTGRES_DATABASE = process.env.POSTGRES_DB || 'postgres'
export const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD || 'postgres'
export const POSTGRES_USER_READ_WRITE = 'postgres'
export const POSTGRES_USER_READ_ONLY = 'supabase_read_only_user'
Repository: supabase/supabase
File: apps/studio/components/interfaces/Storage/StorageMenuV2.tsx (TypeScript)

Code before:
import Link from 'next/link'
import { useParams } from 'common'
import { Menu } from 'ui'
import { BUCKET_TYPES, BUCKET_TYPE_KEYS, DEFAULT_BUCKET_TYPE } from './Storage.constants'

const StorageMenuV2 = () => {
  const { ref, bucketType } = useParams()
  const selectedBucketType = bucketType || DEFAULT_BUCKET_TYPE

  return (
    <Menu type="pills" className="mt-6 flex flex-grow flex-col">
      <div className="mx-3">
        <Menu.Group title={<span className="uppercase font-mono">Bucket Types</span>} />

        {BUCKET_TYPE_KEYS.map((bucketTypeKey, idx: number) => {
          const isSelected = selectedBucketType === bucketTypeKey
          const config = BUCKET_TYPES[bucketTypeKey]

          return (
            <Link key={`${idx}_${bucketTypeKey}`} href={`/project/${ref}/storage/${bucketTypeKey}`}>
              <Menu.Item rounded active={isSelected}>
                <p className="truncate">{config.displayName}</p>
              </Menu.Item>
            </Link>
          )
        })}
      </div>
    </Menu>
  )
}


Review comment (suggestion):
Note this `ComponentNameV2` pattern will be used extensively as part of this work so the existing Storage UI can continue to function.

Code after:
import { useParams } from 'common'
import Link from 'next/link'
import { Menu } from 'ui'
import { BUCKET_TYPES, BUCKET_TYPE_KEYS, DEFAULT_BUCKET_TYPE } from './Storage.constants'

export const StorageMenuV2 = () => {
  const { ref, bucketType } = useParams()
  const selectedBucketType = bucketType || DEFAULT_BUCKET_TYPE

  return (
    <Menu type="pills" className="mt-6 flex flex-grow flex-col">
      <div className="mx-3">
        <Menu.Group title={<span className="uppercase font-mono">Bucket Types</span>} />

        {BUCKET_TYPE_KEYS.map((bucketTypeKey) => {
          const isSelected = selectedBucketType === bucketTypeKey
          const config = BUCKET_TYPES[bucketTypeKey]

          return (
            <Link key={bucketTypeKey} href={`/project/${ref}/storage/${bucketTypeKey}`}>
              <Menu.Item rounded active={isSelected}>
                <p className="truncate">{config.displayName}</p>
              </Menu.Item>
            </Link>
          )
        })}
      </div>
    </Menu>
  )
}
Repository: supabase/supabase
File: apps/studio/pages/project/[ref]/storage/[bucketType]/index.tsx (TypeScript)

Code before:
import { DocsButton } from 'components/ui/DocsButton'

const BucketTypePage: NextPageWithLayout = () => {
  const isStorageV2 = useFlag('storageAnalyticsVector')
  const { bucketType, ref } = useParams()
  const router = useRouter()

  useEffect(() => {
    if (!isStorageV2) {
      router.replace(`/project/${ref}/storage`)
    }
  }, [isStorageV2, ref, router])

  const bucketTypeKey = bucketType || DEFAULT_BUCKET_TYPE
  const config = BUCKET_TYPES[bucketTypeKey as keyof typeof BUCKET_TYPES]

  useEffect(() => {
    if (!config) {
      router.replace(`/project/${ref}/storage`)
    }
  }, [config, ref, router])

  return (
    <div>
      {/* [Danny] Purposefully duplicated directly below StorageLayout‘s config.description for now. Will be placed in a conditional empty state in next PR. TODO: consider reusing FormHeader for non-empty state.*/}
      <p className="text-foreground-light mb-4">{config.description}</p>
      <DocsButton href={config.docsUrl} />
    </div>
  )
}

BucketTypePage.getLayout = (page) => {
  // We need to get the bucketType from the router since it's not available in page.props
  const BucketTypeLayout = () => {
    const { bucketType } = useParams()
    const bucketTypeKey = bucketType || DEFAULT_BUCKET_TYPE
    const config = BUCKET_TYPES[bucketTypeKey as keyof typeof BUCKET_TYPES]

    return (
      <DefaultLayout>
        <StorageLayout title="Storage">
          <PageLayout
            title={`${config?.displayName || 'Storage'} Buckets`}
            subtitle={config?.description || 'Manage your storage buckets and files.'}
          >
            <ScaffoldContainer>{page}</ScaffoldContainer>
          </PageLayout>
        </StorageLayout>
      </DefaultLayout>
    )
  }

Review comment (suggestion):
As mentioned above: this `div` forms the placeholder for both the empty state and 1+ bucket state header. It will be replaced in the next PR as part of DEPR-90

Code after:
  const router = useRouter()
  const { bucketType, ref } = useParams()
  const isStorageV2 = useIsNewStorageUIEnabled()

  const bucketTypeKey = bucketType || DEFAULT_BUCKET_TYPE
  const config = BUCKET_TYPES[bucketTypeKey as keyof typeof BUCKET_TYPES]

  useEffect(() => {
    if (!isStorageV2) router.replace(`/project/${ref}/storage`)
  }, [isStorageV2, ref])

  useEffect(() => {
    if (!config) {
      router.replace(`/project/${ref}/storage`)
    }
  }, [config, ref, router])

  return (
    <div>
      {/* [Danny] Purposefully duplicated directly below StorageLayout's config.description for now. Will be placed in a conditional empty state in next PR. TODO: consider reusing FormHeader for non-empty state.*/}
      {/* <p className="text-foreground-light mb-4">{config.description}</p> */}
    </div>
  )
}

BucketTypePage.getLayout = (page) => {
  return <BucketTypeLayout>{page}</BucketTypeLayout>
}

export default BucketTypePage
Repository: supabase/supabase
File: apps/studio/components/interfaces/Storage/StorageMenuV2.tsx (TypeScript)

Code before:
import Link from 'next/link'
import { useParams } from 'common'
import { Menu } from 'ui'
import { BUCKET_TYPES, BUCKET_TYPE_KEYS, DEFAULT_BUCKET_TYPE } from './Storage.constants'

const StorageMenuV2 = () => {
  const { ref, bucketType } = useParams()
  const selectedBucketType = bucketType || DEFAULT_BUCKET_TYPE

  return (
    <Menu type="pills" className="mt-6 flex flex-grow flex-col">
      <div className="mx-3">
        <Menu.Group title={<span className="uppercase font-mono">Bucket Types</span>} />

        {BUCKET_TYPE_KEYS.map((bucketTypeKey, idx: number) => {
          const isSelected = selectedBucketType === bucketTypeKey
          const config = BUCKET_TYPES[bucketTypeKey]

          return (
            <Link key={`${idx}_${bucketTypeKey}`} href={`/project/${ref}/storage/${bucketTypeKey}`}>
              <Menu.Item rounded active={isSelected}>
                <p className="truncate">{config.displayName}</p>
              </Menu.Item>
            </Link>
          )
        })}
      </div>
    </Menu>
  )
}

export default StorageMenuV2


Review comment (suggestion):
don't need to use idx here - just the bucketTypeKey is good enough

Code after:
import { useParams } from 'common'
import Link from 'next/link'
import { Menu } from 'ui'
import { BUCKET_TYPES, BUCKET_TYPE_KEYS, DEFAULT_BUCKET_TYPE } from './Storage.constants'

export const StorageMenuV2 = () => {
  const { ref, bucketType } = useParams()
  const selectedBucketType = bucketType || DEFAULT_BUCKET_TYPE

  return (
    <Menu type="pills" className="mt-6 flex flex-grow flex-col">
      <div className="mx-3">
        <Menu.Group title={<span className="uppercase font-mono">Bucket Types</span>} />

        {BUCKET_TYPE_KEYS.map((bucketTypeKey) => {
          const isSelected = selectedBucketType === bucketTypeKey
          const config = BUCKET_TYPES[bucketTypeKey]

          return (
            <Link key={bucketTypeKey} href={`/project/${ref}/storage/${bucketTypeKey}`}>
              <Menu.Item rounded active={isSelected}>
                <p className="truncate">{config.displayName}</p>
              </Menu.Item>
            </Link>
          )
        })}
      </div>
    </Menu>
  )
}
Repository: supabase/supabase
File: packages/common/telemetry-constants.ts (TypeScript)

Code before:
 * @page API docs panel
 */
export interface ApiDocsCodeCopyButtonClickedEvent {
  action: 'api_docs_code_copy_button_clicked'
  properties: {
    /**
     * Title of the content being copied
     */
    title?: string
    /**
     * Selected programming language, e.g. js, bash
     */
    selectedLanguage?: string
  }
  groups: Partial<TelemetryGroups>
}

/**
 * User performed a search via the Auth Users page.
 *
 * @group Events
 * @source studio
 * @page /dashboard/project/{ref}/auth/users
 */
export interface AuthUsersSearchedEvent {
  action: 'auth_users_searched'
  properties: {
    /**
     * The trigger that initiated the search
     */
    trigger:
      | 'search_input'
      | 'refresh_button'
      | 'sort_change'
      | 'provider_filter'
      | 'user_type_filter'
    /**
     * The column being sorted on, e.g. email, phone, created_at, last_sign_in_at
     */
    sort_column: string
    /**
     * The sort order, either ascending or descending
     */
    sort_order: string
    /**
     * The authentication provider(s) being filtered on, e.g. email, phone, google, github
     */
    providers?: string[]
    /**
     * The user role(s) being filtered on, e.g. verified, unverified, anonymous
     */

Review comment (security):
```suggestion
  action: 'auth_users_search_submitted'
```

Code after:
 * @page API docs panel
 */
export interface ApiDocsCodeCopyButtonClickedEvent {
  action: 'api_docs_code_copy_button_clicked'
  properties: {
    /**
     * Title of the content being copied
     */
    title?: string
    /**
     * Selected programming language, e.g. js, bash
     */
    selectedLanguage?: string
  }
  groups: Partial<TelemetryGroups>
}

/**
 * User performed a search via the Auth Users page.
 *
 * @group Events
 * @source studio
 * @page /dashboard/project/{ref}/auth/users
 */
export interface AuthUsersSearchSubmittedEvent {
  action: 'auth_users_search_submitted'
  properties: {
    /**
     * The trigger that initiated the search
     */
    trigger:
      | 'search_input'
      | 'refresh_button'
      | 'sort_change'
      | 'provider_filter'
      | 'user_type_filter'
    /**
     * The column being sorted on, e.g. email, phone, created_at, last_sign_in_at
     */
    sort_column: string
    /**
     * The sort order, either ascending or descending
     */
    sort_order: string
    /**
     * The authentication provider(s) being filtered on, e.g. email, phone, google, github
     */
    providers?: string[]
    /**
     * The user role(s) being filtered on, e.g. verified, unverified, anonymous
     */
Repository: supabase/supabase
File: packages/common/telemetry-constants.ts (TypeScript)

Code before:
 * @source studio
 * @page API docs panel
 */
export interface ApiDocsCodeCopyButtonClickedEvent {
  action: 'api_docs_code_copy_button_clicked'
  properties: {
    /**
     * Title of the content being copied
     */
    title?: string
    /**
     * Selected programming language, e.g. js, bash
     */
    selectedLanguage?: string
  }
  groups: Partial<TelemetryGroups>
}

/**
 * User performed a search via the Auth Users page.
 *
 * @group Events
 * @source studio
 * @page /dashboard/project/{ref}/auth/users
 */
export interface AuthUsersSearchedEvent {
  action: 'auth_users_searched'
  properties: {
    /**
     * The trigger that initiated the search
     */
    trigger:
      | 'search_input'
      | 'refresh_button'
      | 'sort_change'
      | 'provider_filter'
      | 'user_type_filter'
    /**
     * The column being sorted on, e.g. email, phone, created_at, last_sign_in_at
     */
    sort_column: string
    /**
     * The sort order, either ascending or descending
     */
    sort_order: string
    /**
     * The authentication provider(s) being filtered on, e.g. email, phone, google, github
     */
    providers?: string[]
    /**
     * The user role(s) being filtered on, e.g. verified, unverified, anonymous

Review comment (security):
One quick note — I was chatting with @pamelachia and we were thinking it might be clearer to rename this to something like `AuthUsersSearchSubmittedEvent`. “Submitted” is the verb we already use in our event naming, and it better reflects the user action. This would also keep our event terminology consistent going forward.

```suggestion
export interface AuthUsersSearchSubmittedEvent {
```

Code after:
 * @source studio
 * @page API docs panel
 */
export interface ApiDocsCodeCopyButtonClickedEvent {
  action: 'api_docs_code_copy_button_clicked'
  properties: {
    /**
     * Title of the content being copied
     */
    title?: string
    /**
     * Selected programming language, e.g. js, bash
     */
    selectedLanguage?: string
  }
  groups: Partial<TelemetryGroups>
}

/**
 * User performed a search via the Auth Users page.
 *
 * @group Events
 * @source studio
 * @page /dashboard/project/{ref}/auth/users
 */
export interface AuthUsersSearchSubmittedEvent {
  action: 'auth_users_search_submitted'
  properties: {
    /**
     * The trigger that initiated the search
     */
    trigger:
      | 'search_input'
      | 'refresh_button'
      | 'sort_change'
      | 'provider_filter'
      | 'user_type_filter'
    /**
     * The column being sorted on, e.g. email, phone, created_at, last_sign_in_at
     */
    sort_column: string
    /**
     * The sort order, either ascending or descending
     */
    sort_order: string
    /**
     * The authentication provider(s) being filtered on, e.g. email, phone, google, github
     */
    providers?: string[]
    /**
     * The user role(s) being filtered on, e.g. verified, unverified, anonymous