feat: プロジェクト全体をnative ESMに移行 (#846) - #1236
Draft
hakatashi wants to merge 4 commits into
Draft
Conversation
package.jsonに"type": "module"を追加し、tsconfigのmodule/moduleResolutionを NodeNextに変更。ソースコードおよびtsgoでコンパイルした.buildディレクトリの いずれもNode.jsのnative ESMとして動作するようにした。 - 全CJS形式の.jsファイル(hangman, mahjong, prime, anime, dajare, summary等)を import/export構文に変換し、ESM化に伴って不要になったCJS互換スタブファイル (deploy/index.js, atequiz/index.js, lib/logger.js, lib/slackUtils.js, prime/primes.js)を削除 - lodashをlodash-esに置き換え - 相対importに拡張子(.js)を付与し、JSON importにimport attributesを付与 - __dirname/__filenameをimport.meta.urlベースの実装に置き換え - 実際にNode.jsのnative ESMで動かして発覚した実行時のみの問題を修正 (shogi9.js/p-queue/mailgun.js等のCJSパッケージのdouble-wrapped default export、 japanese/pino-std-serializers/jaconv/bcdice/fs-extra等の名前付きimportが cjs-module-lexerで解決できない問題、yargsのESMエントリでのAPI形状の違い、 require.main === moduleの残存など) - lib/startup.test.tsで拡張子解決の制約により除外されていたanime/hangman/ qrcode-quizを再度有効化 Closes #846 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VRu2pE3HCZkvpXgP7YGt9x
Contributor
|
えへ~ ありがとう! レビューさせてもらうにゃ! |
|
masterで追加された変更(atcoderの問題セット実績、sushi-botの週間早起き
ランキング実績、better-custom-responseのIt Works!実績)をESM移行ブランチに
取り込み、以下のコンフリクト・不整合を解決した。
- atcoder/index.ts: masterで `fetchUserACsInContest` が
`fetchUserACsInContests` にリネームされたのを取り込みつつ、import指定子に
ESM移行で必要な `.js` 拡張子を付与
- better-custom-response/custom-response.test.ts: masterで追加された
It Works! 実績のテストを取り込み、相対importに `.js` / `/index.js` を付与
- better-custom-response/custom-responses.ts, sushi-bot/index.test.ts:
自動マージで混入した拡張子なしの相対importを修正
- achievements/__mocks__/index.ts: 各exportを `vi.fn()` でラップ。
ESM移行でimport指定子が `../achievements/index.js` になった結果、
`vi.mock('../achievements')` がvitestの自動モック(spy)ではなく本ファイルの
手動モックを解決するようになり、masterから来たsushi-botのテストが
`expect(increment).toHaveBeenCalledWith(...)` で失敗するため
検証:
- npx tsgo --noEmit: エラーなし
- npx vitest run: 406/406件成功
- npm run build 後、atcoder / sushi-bot / better-custom-response を
plain NodeのネイティブESMでdynamic importできることを確認
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RCznY9JkQh5fEdyMWvFAAD
- lib/dotenv.ts を追加し、process.env をトップレベルで参照する lib/slack.ts と lib/logger.ts の先頭で import するようにした。index.ts の動的 import は slackUtils 経由の static import チェーンで先に評価されてしまい機能しておらず、 本番 (pm2 → 素の node) で Slack のトークン等が undefined になっていた - lib/utils.ts に unwrapDefault を追加し、6箇所に重複していた CJS interop の `X.default ?? X` を集約。any キャストと eslint-disable が不要になった - achievements/index.ts の NODE_ENV=test 用スタブを削除し index_development に フォールバックするようにした (シグネチャ不一致の重複実装を解消) - bin の remove-achievement / remove-category / state-file-to-firebase を TypeScript 化し、import 先を lib/firestore.js に修正 - hitandblow/index.test.ts と kirafan/quiz.ts の `.//index.js` を修正 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RCznY9JkQh5fEdyMWvFAAD
…ting JSON import assertions make TypeScript resolve ./state.json statically, which fails in CI where the gitignored file does not exist. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.







Summary
Issue #846 で提起されていたプロジェクト全体のESM化に対応します。ソースコード、および
tsgoでコンパイルした.buildディレクトリ内のプロダクションビルドの両方が、Node.jsのnative ESMとして動作することを目標としています。package.jsonに"type": "module"を追加し、tsconfig.jsonのmodule/moduleResolutionをNodeNextに変更.jsファイル(hangman, mahjong, prime, anime, dajare, summary 等)をimport/export構文に変換deploy/index.js,atequiz/index.js,lib/logger.js,lib/slackUtils.js,prime/primes.js— いずれも「〜のテスト環境でのrequire用スタブ」とコメントされていたもの)を削除lodashをlodash-esに置き換え.js)を付与し、JSON importにwith {type: 'json'}を付与__dirname/__filenameをimport.meta.urlベースの実装に置き換え(約40ファイル).buildを動かして初めて発覚した、実行時のみに顕在化する問題を多数修正shogi9.js/p-queue/mailgun.js等、tscのCJS出力に由来するdouble-wrapされたdefault exportの取り扱い(esbuild/vitestとNode.jsのCJS-ESM interopの挙動差にも対応するため??によるフォールバックを付与)japanese/pino-std-serializers/jaconv/bcdice/fs-extra/@hakatashi/riichi-core/pluscodes/prism-media/@google-cloud/text-to-speechの深いsubpath importなど、named importがcjs-module-lexerで静的に解決できないケースをdefault importからの分割代入に変更yargsのESMエントリポイントでAPIの形状が変わる問題(yargs.array(...)→yargs(hideBin(process.argv)).array(...))require.main === moduleの残存(sunrise/aiGeneration.ts)discord.js(デフォルトエクスポートなし)、sqlite(名前付きexportのみ)など、パッケージ側の実際のESM export形状に合わせたimportの修正lib/startup.test.tsで「CJSのため拡張子解決ができない」という理由で除外されていたanime/anime/anison/hangman/qrcode-quizを除外リストから外し、再度テスト対象に含めた検証
npx tsgo --noEmit: エラーなしnpx vitest run: 398/398件成功npm run buildで生成した.buildを実際にplain Nodeで動かす包括的スモークテスト(全ボットをdynamic importして起動を確認)を実施し、73/77ボットが問題なくimportできることを確認topic,api,wordhero/crossword,twenty-questions)はmasterブランチに既存の、NODE_ENV=production以外ではdb.collection()をモジュールトップレベルで無条件に呼び出してしまうバグによるもので、本PRの変更とは無関係(実運用ではNODE_ENV=productionのため問題なし)CLAUDE.local.mdの手順に従い、ngrok +npm run dev -- --only helloworldでdevサーバーを起動し、実際にSlackイベント(ngrok経由)を受信・処理できることを確認(Slack上でのメッセージ送信による応答確認は、dev workspace向けMCPツールが利用できなかったため未実施)Test plan
npx tsgo --noEmitが通ることnpx vitest runが全て通ることnpm run buildが成功し、.build/index.jsがplain Nodeで起動できること🤖 Generated with Claude Code
https://claude.ai/code/session_01VRu2pE3HCZkvpXgP7YGt9x