Guide/guides
Guren アップグレードガイド
マイナーバージョン間のアップグレード時に使用する手順です。
Guren アップグレードガイド
マイナーバージョン間のアップグレード時に使用する手順です。
必須アップグレード手順
CHANGELOG.mdとリリースノートを確認docs/ja/guides/release-policy.mdの互換性マトリクスを確認- 依存更新と生成物再生成
bun install
bunx guren codegen
- 非推奨APIの使用箇所を確認
bunx guren upgrade --check-only
非推奨化されたバージョン、削除予定バージョン、置き換え先、使用しているファイルが項目ごとに表示されます。ファイルへの書き込みは行いません。
- 検証実行
bun run build
bun run typecheck
bun run test
- 対象バージョンの移行メモを適用
移行メモ
1.x → 2.0.0
構造的マスアサインメント保護
- 何が変わったか:
static guardedとstatic strictFillableは削除されました。fillableは常に厳格で、主キー(id)は常に黙って除外されます。AuthenticatableModelのサブクラスでは、パスワードハッシュとリメンバートークンのカラムは一括代入できません。リクエストボディにこれらが含まれると、fillableの内容に関わらずMassAssignmentExceptionがスローされます。 - 誰に影響するか:
guardedやstrictFillableを宣言しているモデル(guren checkがエラーとして検出します)、およびcreate()/update()で計算済みハッシュやリメンバートークンを一括代入しているコード。 - 移行方法:
guarded/strictFillableの宣言を削除してください(bunx guren upgrade --check-onlyが対象ファイルを一覧します)。guardedがidと認証情報カラム以外のアプリ固有フィールド(tenantIdやisAdminなど)を含んでいた場合、行の削除によりそれらは一括代入可能になります。それらを含まないstatic fillable = [...]を宣言して保護を維持してください。strictFillable = falseに依存していたモデルでは、新たにスローされる例外が「黙って破棄されていたフィールド」を示します。fillableに追加するかペイロードから除いてください。create({ ..., passwordHash })はcreate({ ..., password })に置き換えてモデルにハッシュ化させるか、信頼できるサーバーサイドの値にはforceCreate({ ..., passwordHash: 'oauth:...' })を使ってください(リクエスト入力には決して使わないこと)。
// Before
export class User extends defineModel(users, { base: AuthenticatableModel }) {
static fillable = ['name', 'email', 'password']
static guarded = ['id', 'passwordHash', 'rememberToken'] // check がエラーにする
}
// After — 認証情報カラムはフレームワークが拒否する
export class User extends defineModel(users, { base: AuthenticatableModel }) {
static fillable = ['name', 'email', 'password']
}
ModelUserProvider は認証情報カラム名をモデル(passwordHashField / 新設の rememberTokenField)から読み取るため、カラムをリネームしてもプロバイダー側の設定は不要です(明示的な passwordColumn / rememberTokenColumn オプションは引き続き優先されます)。defineModel() の非推奨だった createType オプションは削除されました。optionalOnCreate / requireOnCreate を使ってください。
rc → 1.0.0
厳格なマスアサインメント
- 何が変わったか:
fillableを定義したモデルで、許可リスト外のフィールドをcreate()/update()に渡すとMassAssignmentExceptionがスローされるようになりました。以前は余分なフィールドは黙って破棄されていました。 - 誰に影響するか: フィルタリングしていないオブジェクト(スプレッドしたリクエストボディ、マージしたデフォルト値など)を
create()/update()に渡しているコード。 - 移行方法: 許可リスト内のフィールドだけを渡すか、シーダーやシステムレコードなど信頼できるサーバーサイドのデータには
forceCreate()/forceUpdate()を使用してください。
// Before: authorId silently dropped when not in fillable
await Post.create({ ...data, authorId: user.id })
// After: either add authorId to fillable, or use forceCreate for trusted data
await Post.forceCreate({ ...validated, authorId: user.id })
認証ユーザーレコードのサニタイズ
- 何が変わったか:
auth.user()の返すオブジェクトに、パスワードカラム、remember トークンカラム、モデルがhiddenに列挙したフィールドが含まれなくなりました。 - 誰に影響するか: 認証済みユーザーオブジェクトからこれらのフィールドを読み取っていたコード。
- 移行方法: 生のレコードが必要なまれなサーバーサイド処理では、モデルを明示的にロードしてください(例:
User.findOrFail(user.id))。
SSE ブロードキャスティング
- 何が変わったか: 認可関数が未登録の
private-/presence-チャンネルはデフォルトで拒否されるようになりました。また、購読には SSE のconnectedイベントで配信されるclientIdが必要です。 - 誰に影響するか: SSE ブロードキャスティングエンドポイントを使用しているアプリ。
- 移行方法:
broadcast.privateChannel()/broadcast.presenceChannel()で認可関数を登録し、connectedイベントからclientIdを取得してPOST /broadcasting/authに送信すると、認可と購読が 1 回のリクエストで行われます。詳細はブロードキャスティングガイドを参照してください。
アップグレードの検証:
bun run typecheck && bun run test
破壊的変更テンプレート(今後のリリース用)
各項目で次を記載します。
- 何が変わったか
- なぜ変えたか
- 誰に影響するか
- Before/After のコード例
- 1コマンドでの確認手順