mcpField
S
studio-queries

studio-queries

github.com/supabase開発114.3k215 回インストール今日更新
リポジトリ

studio-queries について

Studio のデータコードで使う React Query のパターンをまとめた開発スキルです。型付きクエリオプション、クエリキー、ミューテーションフック、コンポーネントの状態表示を扱います。

主な機能

  1. 01ドメイン別クエリキーの定義
  2. 02型付きクエリオプションの作成
  3. 03命令的なクエリ取得への対応
  4. 04キャッシュ無効化付きミューテーションフック
  5. 05待機・エラー・成功状態の表示

活用シーン

  1. 01Studio にデータクエリを追加
  2. 02React コンポーネント外でクエリデータを取得
  3. 03キャッシュ更新を伴うミューテーションを実装
  4. 04ロードとエラー状態を一貫して処理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/supabase/supabase --skill studio-queries

インストール後、Claude Code で/studio-queriesを入力して読み込まれたか確認します。

詳細

Studio のクエリとミューテーション(React Query)

apps/studio/data/ のパターンに従ってください。参考例:

  • クエリオプション:apps/studio/data/table-editor/table-editor-query.ts
  • ミューテーションフック:apps/studio/data/edge-functions/edge-functions-update-mutation.ts
  • キー:apps/studio/data/edge-functions/keys.ts

クエリキー

ドメインごとに keys.ts を定義してください。as const を使った配列キーで *Keys ヘルパーをエクスポートします。コンポーネント内にクエリキーを直接記述しないでください。

export const edgeFunctionsKeys = {
  list: (projectRef: string | undefined) => ['projects', projectRef, 'edge-functions'] as const,
  detail: (projectRef: string | undefined, slug: string | undefined) =>
    ['projects', projectRef, 'edge-function', slug, 'detail'] as const,
}

クエリオプション(推奨パターン)

@tanstack/react-query の queryOptions を使用してください。これにより型安全性が確保され、useQuery() と queryClient.fetchQuery() の両方で使用できます。

ルール:

  • XVariables、XData、XError の型をエクスポートします(ドメイン名を先頭に付けます)
  • getX(variables, signal?) 関数をプライベートに実装します:
    • 必須の変数がない場合はエラーをスローします
    • キャンセルに対応するため、signal を渡します
    • 失敗時は handleError(error) を呼び出します(この関数はスローします)。成功時は data を返します
    • エクスポートしないでください。命令的な取得には queryClient.fetchQuery(xQueryOptions(...)) を使用します
  • queryOptions を使って xQueryOptions() をエクスポートします
  • 必須の変数がそろうまでクエリが実行されないよう、enabled で制御します
  • プラットフォーム専用のクエリ:enabled に lib/constants の IS_PLATFORM を含めます
  • xQueryOptions に追加のパラメーターを加えないでください。呼び出し側で分割代入を使って上書きします:{ ...xQueryOptions(vars), enabled: true }
import { queryOptions } from '@tanstack/react-query'

import { xKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import { IS_PLATFORM } from '@/lib/constants'
import { ResponseError } from '@/types'

export type XVariables = { projectRef?: string }
export type XError = ResponseError

async function getX({ projectRef }: XVariables, signal?: AbortSignal) {
  if (!projectRef) throw new Error('projectRef is required')
  const { data, error } = await get('/v1/projects/{ref}/x', {
    params: { path: { ref: projectRef } },
    signal,
  })
  if (error) handleError(error)
  return data
}

export type XData = Awaited<ReturnType<typeof getX>>

export const xQueryOptions = ({ projectRef }: XVariables) =>
  queryOptions({
    queryKey: xKeys.list(projectRef),
    queryFn: ({ signal }) => getX({ projectRef }, signal),
    enabled: IS_PLATFORM && typeof projectRef !== 'undefined',
  })

コンポーネントでのクエリオプションの使用

import { useQuery } from '@tanstack/react-query'

import { xQueryOptions } from '@/data/x/x-query'

const { data, isPending, isError } = useQuery(xQueryOptions({ projectRef: project?.ref }))

命令的な取得(React の外部またはコールバック内)

const queryClient = useQueryClient()
const { data: project } = useSelectedProjectQuery()

const handleClick = useCallback(
  async (id: number) => {
    const data = await queryClient.fetchQuery(xQueryOptions({ id, projectRef: project?.ref }))
    // use data...
  },
  [project?.ref, queryClient]
)

ミューテーションフック

  • projectRef、識別子、payload を含む Variables 型をエクスポートします
  • 必須変数の検証と handleError を含む updateX(vars) 関数をプライベートに実装します
  • useXMutation() でラップします:
    • UseMutationOptions を受け取ります(mutationFn は除外します)
    • onSuccess で await Promise.all([...]) を使い、list() と detail() のキーを無効化します
    • onError が指定されていない場合は、デフォルトで toast.error(...) を表示します
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'

import { xKeys } from './keys'

type XUpdateVariables = { projectRef: string; slug: string; payload: XPayload }

export const useXUpdateMutation = ({
  onSuccess,
  onError,
  ...options
}: UseMutationOptions<XData, XError, XUpdateVariables> = {}) => {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: updateX,
    async onSuccess(data, variables, context) {
      await Promise.all([
        queryClient.invalidateQueries({
          queryKey: xKeys.detail(variables.projectRef, variables.slug),
        }),
        queryClient.invalidateQueries({ queryKey: xKeys.list(variables.projectRef) }),
      ])
      await onSuccess?.(data, variables, context)
    },
    async onError(error, variables, context) {
      if (onError === undefined) toast.error(`Failed to update: ${error.message}`)
      else onError(error, variables, context)
    },
    ...options,
  })
}

コンポーネントでの使用

  • React Query v5 のフラグを使います:初回読み込みには isPending、バックグラウンドでの再取得には isFetching を使用します
  • 状態は明示的に、pending → error → success の順にレンダリングします

コメント