convex-core について
Convex アプリケーション開発者向けの基礎スキルです。データモデリング、データベースクエリ、検証、関数作成を扱い、型付きスキーマと安全な操作を重視します。
主な機能
- 01スキーマとテーブルのモデリング
- 02引数と戻り値の検証
- 03インデックスクエリとページネーション
- 04query、mutation、action のパターン
- 05TypeScript とデータベース操作の指針
活用シーン
- 01Convex テーブルとバリデーターの定義
- 02型付き query と mutation 関数の作成
- 03インデックスを使った読み取りの最適化
- 04大規模なクエリ結果のページネーション
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ igorwarzocha/ opencode-workflows --skill convex-coreインストール後、Claude Code で/convex-coreを入力して読み込まれたか確認します。
詳細
Convex のモデリングと関数作成の基本パターンです。このスキルは Convex で作業する際のデフォルトの基準です。
- **スキーマ**: https://docs.convex.dev/database/schemas
- **データの読み取りとインデックス**: https://docs.convex.dev/database/reading-data/indexes
- **バリデーション**: https://docs.convex.dev/functions/validation
- **関数**: https://docs.convex.dev/functions
- **ページネーション**: https://docs.convex.dev/database/pagination
- **システムテーブル**: https://docs.convex.dev/database/advanced/system-tables
- スキーマ: `convex/schema.ts` で `defineSchema`/`defineTable` を使用します。バリデーターには `v` を使用します。
- オプション: `schemaValidation: false` は実行時バリデーションを無効にします。`strictTableNameTypes: false` は TS の型で未宣言のテーブルを許可します。
- バリデーション: クエリ/ミューテーション/アクションには `args`/`returns` バリデーターを使用します。オブジェクトでは余分なプロパティは拒否されます。`undefined` は無効です(`null` を使用してください)。
- 判別可能なユニオン: 型安全な状態/種別の定義には、`as const` とともに `v.union` および `v.literal` を使用します。
- 型: 64 ビット整数には `v.bigint()` ではなく `v.int64()` を使用します。明示的に null を返す場合は `v.null()` を使用します。
- ID: 生の文字列の代わりに `Id<"table">` と `v.id("table")` を使用します。
- レコード: `v.record(keys, values)` のキーは ASCII で空でなく、`_` または `$` で始まってはなりません。
- バリデーターの合成: オブジェクトバリデーターでは `Infer`、`.pick`、`.omit`、`.extend`、`.partial` を使用できます。
スキーマのルール
- すべてのテーブルは、
convex/schema.tsでdefineSchema/defineTableを使用して定義しなければなりません。 - システムフィールド:
_id(v.id(tableName))と_creationTime(v.number())は自動的に追加されます。 - すべてのフィールドに
v.*バリデーターを使用しなければなりません。必要な場合を除き、v.any()の使用は避けるべきです。 - インデックスの命名: 名前にはすべてのフィールドを含めます。例:
"by_field1_and_field2"。 - インデックスのルール:
.index(name, [fields...])を使用しなければなりません。- フィールドの順序は重要です。範囲式はインデックスの順序に従わなければなりません。
- 上限: インデックスあたり 16 フィールド、テーブルあたり 32 インデックスです。
関数のルール
args、returns、handlerを含む新しい関数構文を使用しなければなりません。- HTTP アクションを除き、常に
argsとreturnsを検証しなければなりません。 - 読み取りには
query、書き込みにはmutation、外部処理や長時間実行する処理にはactionを使用します。 - アクションから
ctx.dbにアクセスしてはなりません。ctx.runQuery/ctx.runMutationを使用しなければなりません。 - 循環依存: 同じファイル内の関数を
ctx.run*で呼び出す場合、受け取り側の変数に明示的な戻り値の型注釈を付けなければなりません。
データベース操作
ctx.db.get、ctx.db.patch、ctx.db.replace、ctx.db.deleteの第 1 引数には、テーブル名を明示しなければなりません。- 置換: ドキュメント全体の置換には
ctx.db.replaceを使用します(対象が存在しない場合はエラーになります)。 - パッチ: 浅いマージによる更新には
ctx.db.patchを使用します(対象が存在しない場合はエラーになります)。 - 削除: Convex のクエリは
.delete()をサポートしていません。結果に.collect()を適用し、反復処理でctx.db.delete(id)を呼び出さなければなりません。 - 一意性: ドキュメントを 1 件だけ取得するには
.unique()を使用します。複数のドキュメントが一致した場合は必ずエラーになります。 - 本番環境のクエリでは
filterを使用してはなりません。インデックスと.withIndexを使用します。
TypeScript のベストプラクティス
- 判別可能なユニオンでは、文字列リテラルに
as constを使用しなければなりません。 - 配列は
const array: Array<T> = [...]、レコードはconst record: Record<K, V> = {...}として定義しなければなりません。 - すべてのドキュメント識別子には、
stringよりもId<"table">を優先しなければなりません。
クエリのパフォーマンス
- 大きなテーブルでは
.filterより.withIndexを優先するべきです。 - 範囲指定なしで
.withIndexを使用する場合、take、first、unique、paginateのいずれかと必ず組み合わせなければなりません。 - 検索の上限: 1024 件を超えるドキュメントに対して
collect()を呼び出すとエラーになります。大きなデータセットにはtake(n)、paginate()、またはfor awaitによる反復処理を使用するべきです。 - 非同期反復: 大きな結果セットをストリーミングする場合は、
.collect()ではなくfor await (const row of query)を使用します。
ページネーション
- args では
paginationOptsValidatorを必ず使用してください。 .paginate()は{ page, isDone, continueCursor }を返します。- ページはリアクティブです。サイズは変更される可能性があります。
.paginate()の戻り値オブジェクト全体に対して厳密なreturnsバリデーターを使用することは避けてください。pageを検証するか、v.any()を使用してください。
クライアントのパターン
convex/_generated/apiのapi.*参照を必ず使用してください。- React フック:
useQuery、useMutation、useAction、usePaginatedQuery。 - レンダリング中にミューテーションやアクションを呼び出してはいけません。
安全性
- 関数ごとに必ず認証を適用してください。
ctx.authヘルパーを使用して ID を確認してください。 - 公開関数で機密性の高いロジックを公開してはいけません。必ず内部関数を使用してください。
コメント
Markdown 対応