darkmatter-ts-toolchain について
Darkmatterのリポジトリ向けに、TypeScriptの規約と推奨スタックを定めるスキルです。ツール、設計、テスト、データアクセス、デプロイ、リリースの手順を示します。
主な機能
- 01Bunのみでのパッケージ管理
- 02TypeScriptによる運用スクリプト
- 03Effectと型付きRPCの推奨スタック
- 04Postgresを優先するデータ規約
- 05Alchemyによるデプロイ規則
- 06型チェック、テスト、lintの順次実行
活用シーン
- 01新しいTypeScriptリポジトリの構築
- 02Darkmatter規約へのリポジトリ統一
- 03PR提出前の変更検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ darkmatter/ skills --skill darkmatter-ts-toolchainインストール後、Claude Code で/darkmatter-ts-toolchainを入力して読み込まれたか確認します。
詳細
Darkmatter TypeScript ツールチェーン
platform、nixmac-web などの TS リポジトリ全体に適用する規約です。参照用モノレポとして、darkmatter/template カタログに新しいリポジトリを合わせてください。このスタックは意図的に選定されています。慣れ親しんだデフォルト(npm、jest、wrangler、デフォルトデータベースとしての D1)に置き換えると、別の規約が生まれ、CI が壊れます。
可読性とモジュール境界には codebase-design を適用してください。ツールチェーンのチェックは、一貫性のある実装と小さな公開インターフェースを支援します。関数の長さだけでヘルパーを設けるべきかどうかは決まりません。
運用スクリプト — bash ではなく TypeScript
リポジトリが TypeScript のみで構成される場合、ユーティリティスクリプトと CI スクリプトには TypeScript を使用します(scripts/*.ts、bun scripts/ci.ts)。.sh ファイルは追加しないでください。ADR-0012 を参照してください。
パッケージ管理 — Bun のみ
- インストール:
bun install。CI ではbun install --frozen-lockfileを使用します。CI で "lockfile had changes, but lockfile is frozen" というエラーが発生した場合、ロックファイルがpackage.jsonと一致していません。ローカルでbun installを実行してbun.lockをコミットすれば修正できます。「修正」のためにロックファイルを削除してはいけません。 - スクリプトの実行には
bun run <script>を、ツールの実行にはbun x <tool>を使用します。 - モノレポでは Turbo とワークスペース(
@repo/*パッケージ)を使用します。アプリ間で相対パスの../../インポートを使うのではなく、共有コードをワークスペースパッケージに追加してください。 - 共有依存関係のバージョンはルートの
workspaces.catalogに記述します。パッケージマニフェストではバージョンを繰り返し記述せず、catalog:またはworkspace:*を使用してください。
推奨スタックのデフォルト
対象のリポジトリに文書化された例外がない限り、次のデフォルトを使用してください。
| 領域 | デフォルト |
|---|---|
| ランタイム/パッケージマネージャー | Bun、ワークスペースカタログ、Node が必要な場合は Node >= 24 |
| Effect | Effect 4、effect-solutions、@effect/tsgo、@effect/vitest、@effect/platform-bun |
| エージェント | 独自実装のエージェントループや重複した規約よりも、effect/unstable/ai/effect-agent API を優先 |
| 型付き RPC | [email protected] と、>=1.13 の @orpc/server、@orpc/client、@orpc/contract、@orpc/shared。使用ルールについては effect-typescript を読み込む |
| データ | まず Postgres を選択します。クエリの多い TypeScript では Kysely + pg を、Effect ネイティブのデータベースサービスでは Effect SQL Postgres を推奨します。デフォルトの永続化レイヤーとして D1 や sqlite を選んではいけません。 |
| デプロイ | Alchemy が管理するインフラ。アプリに応じて、一般に Cloudflare Workers または AWS を使用 |
| Web/UI | Vite または vite-plus、Vitest、React 19、Tailwind v4、shadcn/Radix、リポジトリの共有 UI パッケージ |
| リント/フォーマット | Effect/tsgo ルールを備えた oxlint、フォーマットには oxfmt |
次の順序で検証
bun run typecheck # tsgo -p tsconfig.json (NOT tsc)
bun run test # vitest
bun run lint # oxlint
bun run fmt:check # oxfmt
まず、変更をカバーする最小の対象(単一のテストファイル、単一のパッケージ)を実行し、引き継ぎ前にリポジトリ全体のチェックを実行してください。3 つすべてが main で成功する必要があります。マージキューでは必須チェックが適用されます。認証情報で保護を迂回できる場合でも、直接 push するより PR を優先してください。
テストファイルは、対象ソースと同じ場所にある <file>.test.ts です。Vitest はどこにあってもテストを検出します(include: ["**/*.test.ts"])。パッケージごとに test/ や tests/ ディレクトリを追加しないでください。リポジトリルートの tests/ は、実際のサーバーを起動するか、複数のパッケージにまたがるエンドツーエンドテスト専用です。
意味のある I/O には Effect を使用する
ネットワーク、データベース、キュー、再試行など、実際の I/O を伴うコードには Effect を使用します。サービス、Layer、型付きエラーを使い、設定には Config を使用します(名前付き設定ファイルを使い、環境変数とフラグで上書きします:ADR-0014)。パターンを確認するには、effect-typescript スキルを読み込んでください。単純な接着コードなら通常の async/await で問題ありません。単一の fetch を形式的にラップする必要はありません。
Promise ベースのドライバーはアダプター境界で Effect に変換し、内部の処理では Effect を使い続けます。処理が完了するまで、永続化、エラー処理、クリーンアップを自分で管理してください。処理を観測しないまま成功を返してはいけません。
データベースクエリとデコードは、それを所有するアダプター内に置きます。プロジェクト固有の決定がない限り、新しいアプリのデータには Postgres を使います。クエリの多いサービスには pg と Kysely を、リポジトリですでに永続化を Effect サービスと Layer として構成している場合は Effect SQL Postgres を使います。D1/sqlite は、限定的なプラットフォーム内の状態、デモ、または明示的なエッジ環境の制約がある場合にのみ有効です。プロビジョニングが簡単だからという理由でデフォルトにしないでください。必要に応じて既存の型付きクエリツールを使います。行の検証とクエリ動作の検証を行えば、パラメーター化 SQL も使用できます。行のジェネリック型はデータの検証にはなりません。また、可読性を高める変更のために ORM への移行は必要ありません。ADR-0015 を参照してください。
デプロイ — Alchemy を使用し、wrangler は使用しない
- インフラストラクチャは
alchemy.run.tsでコードとして定義します。wrangler.tomlは禁止されています。 - デプロイ:
STAGE=prod bun run deploy(アプリごとに実行します。必要な環境変数はアプリの README/実行設定を確認してください)。シークレットはデプロイ時にhimitsu read <path>から取得し、設定には SOPS を使います。ハードコードは厳禁です。 - Alchemy の設定スキーマでは、環境変数に
SOPS_AGE_KEYを明示的に設定する必要があります。~/.config/sops/age/keys.txtへのフォールバックはありません:SOPS_AGE_KEY=$(grep '^AGE-SECRET-KEY-' ~/.config/sops/age/keys.txt | head -1)。 - Vite アプリでは、
ssrビルドの前にclientビルドを実行する必要があります(ハイドレーションマニフェスト)。
リリース
Changesets がリリースの信頼できる情報源です。ユーザー向けの変更には .changeset/*.md を含めます。バージョンの更新と変更履歴は自動生成し、手作業では編集しません。
初心者が意外に感じるスタイルルール
- 有用なヘルパー: 名前によって重要な判断が隠れている場合や、有用な再利用が可能になる場合は、処理を切り出します。純粋な転送ラッパーはインライン化します。短いヘルパーや一度しか使わないヘルパーでも、役に立つ場合があります。既存のリンター診断を確認し、不要な間接化を修正してください。ルールを黙って無効にしてはいけません。
- ファイルの上限: 設定済みの上限を維持します。新しいファイルを作る場合は、空行とコメントを除いて 300 行を目安にします。責務ごとに分割するか、モジュールの凝集性を保ったまま上限を引き上げる、または例外を設ける場合は、その理由を記録してください。行数制限を満たすためだけに転送用ファイルを作ってはいけません。
- Conventional Commits を使用し、件名は 50 文字以内にします。理由が明らかでない場合にのみ本文を記述します。
- 問題は発生源で修正し、不要になった互換性維持用の経路を削除します。明示的な公開再エクスポートと、実際の外部 API を変換するアダプターは維持してください。有用な契約を追加しない内部の転送チェーンは削除します。