convex-actions-general について
Convex のアクション、HTTP エンドポイント、データベース機能を扱う開発ガイドです。バリデーター、ファイルストレージ、スケジューリング、TypeScript の型の使い方も説明します。
主な機能
- 01アクションと HTTP エンドポイントの開発
- 02引数とスキーマの検証
- 03データベーススキーマとインデックスの設計
- 04環境変数とスケジューリングの設定
- 05ファイルストレージの利用
- 06TypeScript の型パターン
活用シーン
- 01外部 API 呼び出しや長時間タスクの実装
- 02Webhook や公開 API エンドポイントの作成
- 03データベースのテーブルとインデックスの設計
- 04定期実行タスクやファイルアップロードの設定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ sstobo/ convex-skills --skill convex-actions-generalインストール後、Claude Code で/convex-actions-generalを入力して読み込まれたか確認します。
同梱ファイルreferences/actions-and-general.md
詳細
Convex Actions and General Guidelines Skill
このスキルでは、Convex のアクション、HTTP エンドポイント、バリデーター、スキーマ設計、ファイルストレージ、環境変数、スケジューリング、TypeScript のベストプラクティスについて、包括的なガイダンスを提供します。
このスキルを使用する場面
次の場合にこのスキルを使用してください:
- 外部 API 呼び出しや長時間実行タスクのアクション関数を実装する場合
- Webhook やパブリック API 用の HTTP エンドポイントを作成する場合
- 関数の引数やデータベーススキーマのバリデーターを定義する場合
- テーブル、インデックス、検索機能を備えたデータベーススキーマを設計する場合
- シークレットや設定用の環境変数を設定する場合
- cron ジョブやスケジュール済みタスクを実装する場合
- アップロードやダウンロード用のファイルストレージを扱う場合
- Convex 固有の TypeScript パターンや型を使用する場合
- Convex の制限やパフォーマンス上の制約を把握する場合
スキルのリソース
このスキルには、以下を網羅した包括的なリファレンスドキュメント references/actions-and-general.md が含まれています。
アクションと HTTP
- アクション:Node.js モジュール用の
"use node"を使ったアクションの定義- V8 と Node ランタイムの違い
- アクションの制限(タイムアウト 10 分、データベースへのアクセス不可)
- 外部 API やサービスの呼び出し
- HTTP エンドポイント:httpRouter を使った
convex/http.tsの設定- パスの登録と完全一致
- リクエストとレスポンスの処理
- メソッドの定義(POST、GET など)
バリデーターと型
- Convex のすべての型を対象としたバリデーターの完全なリファレンス
- 一般的なバリデーター:
v.object()、v.array()、v.string()、v.number()、v.id()、v.boolean()、v.null() v.union()とv.literal()を使った判別可能なユニオン型- オブジェクトのフィールド名に関する ASCII 要件
- サイズと要素数の上限
関数の開発
- すべての関数型に対応する新しい関数構文
- 関数の登録パターン(
query、mutation、action、internalQuery、internalMutation、internalAction) - ランタイム間での関数呼び出しパターン
apiオブジェクトとinternalオブジェクトを介した関数参照- ファイルベースのルーティング規則
API 設計
- パブリック関数とプライベート関数の整理
convex/ディレクトリ内の適切なファイル構成- パブリック関数と内部関数の可視性
- 一貫性のある API サーフェス
データベースとスキーマ
- スキーマ定義:
convex/schema.tsの構造- システムフィールド(
_id、_creationTime) - バリデーターを使ったテーブル定義
- システムフィールド(
- インデックス:効率的なインデックスの作成
- 組み込みインデックス(by_id、by_creation_time)
- カスタムインデックスの命名とフィールド順序
- 複雑なクエリ用の複数フィールドインデックス
- 全文検索:検索インデックスの定義
- 検索フィールドとフィルターフィールド
- ドット記法によるネストされたフィールドパス
環境と設定
- 環境変数:
process.envの使用- シークレット(API キー、認証情報)の保存
- デプロイごとの設定
- あらゆる関数型からのアクセス
- スケジューリング:
- Cron:
crons.interval()とcrons.cron()の使用 - スケジューラー:mutation/action からの
ctx.scheduler.runAfter()の使用 - 認証状態の伝播(スケジュール済みジョブには伝播しません)
- タイミングの制約とベストプラクティス
- Cron:
ファイルストレージ
ctx.storage.generateUploadUrl()によるアップロード URL の生成ctx.storage.getUrl()による署名付き URL の取得_storageシステムテーブルからのファイルメタデータの取得- ストレージ操作での Blob 変換
- 完全な例:チャットアプリケーションでの画像アップロード
制限とパフォーマンス
- 関数の引数と戻り値:最大 8 MiB
- データベース操作:mutation あたり最大 8192 件のドキュメント書き込み、query あたり最大 16384 件の読み取り
- 実行タイムアウト:query/mutation は 1 秒、action は 10 分
- 配列の要素数:最大 8192 件
- Object/Record のフィールド数:最大 1024 件
- ネストの深さ:最大 16
- Record のサイズ:最大 1 MiB
- HTTP ストリーミング:最大出力 20 MiB
TypeScript
- 厳密なドキュメント ID を指定する
Id<'tableName'>型 - ドキュメントの型安全性を確保する
Doc<'tableName'>型 - 適切な型付けが適用された
Record<KeyType, ValueType> - 判別共用体のための
as const - 同じファイル内の関数呼び出しに対する型注釈
- Node.js モジュール用の
@types/node
このスキルの使い方
- 包括的なパターンについて、
references/actions-and-general.mdのリファレンスドキュメントを確認します - 適切な Node.js モジュールの処理を行い、アクションを定義する構文に従います
- すべての関数引数とスキーマフィールドにバリデーターを正しく使用します
- アクセスパターンに適したインデックスを使ってスキーマを設計します
- シークレットと設定用の環境変数を設定します
- crons またはスケジューラーを使って、バックグラウンドタスクのスケジュールを設定します
- 適切な URL 生成とメタデータの検索を行って、ファイルストレージを処理します
- 制限を理解し、それを遵守できるようにアプリケーションを設計します
Id型と適切なジェネリクスを使い、TypeScript を厳密に使用します
一般的な主なガイドライン
- すべての関数(クエリ、ミューテーション、アクション)で必ず引数バリデーターを使用します
- データベースにファイル URL を保存せず、代わりにファイル ID を保存します
- オブジェクトに保存する前に、非 ASCII 文字(絵文字)を ASCII コードに変換します
- 認証状態はスケジュール済みジョブに引き継がれません。内部関数を使用します
- スケジュール済み関数は 10 秒に 1 回を超える頻度で実行しないでください
- ランタイムをまたぐ場合(V8 から Node へ)を除き、別のアクションからアクションを呼び出さないでください
- Convex のオブジェクトでは、ASCII 文字のみのフィールド名を使用する必要があります
- 特にドキュメント ID については、TypeScript の型を厳密に扱います
例:HTTP エンドポイントを備えたアクションの全体例
// convex/ai.ts
"use node";
import { action } from "./_generated/server";
import { v } from "convex/values";
import { internal } from "./_generated/api";
import OpenAI from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export const generateResponse = action({
args: {
channelId: v.id("channels"),
},
handler: async (ctx, args) => {
// Actions can't access ctx.db, but can call mutations
const context = await ctx.runQuery(internal.functions.loadContext, {
channelId: args.channelId,
});
const response = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: context,
});
const content = response.choices[0].message.content;
if (!content) throw new Error("No content in response");
await ctx.runMutation(internal.functions.writeAgentResponse, {
channelId: args.channelId,
content,
});
return null;
},
});
例:HTTP エンドポイント
// convex/http.ts
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
const http = httpRouter();
http.route({
path: "/webhook",
method: "POST",
handler: httpAction(async (ctx, req) => {
const body = await req.json();
// Process webhook payload
return new Response(JSON.stringify({ success: true }), { status: 200 });
}),
});
export default http;
詳細や追加のパターンについては、完全版のリファレンスドキュメントを参照してください。
コメント
Markdown 対応