`migration:generate` / `seed:generate` always emit `.js`, which breaks in `"type": "module"` projects — allow configuring the file extension (e.g. `.cjs`)
还没有人认领这个 Issue。
评估
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 新手友好度
- 76/100
- Issue 类型
- 功能
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- javascript, node.js
- 领域
- cli
调研方向
Start with src/helpers/path-helper.js, then trace getMigrationPath and getSeederPath from src/commands/migration_generate.js and src/commands/seed_generate.js. Check how src/core/yargs.js receives .sequelizerc values and how src/core/migrator.js recognizes extensions. Done means generation accepts js, cjs, ts, and cts, defaults to js, rejects mjs, and produces files the existing loader can load.
由索引模型根据 Issue 内容生成。
描述
What you are doing?
In a project whose package.json has "type": "module" (common with TypeScript ESM setups), generating a migration and running it fails, because the generated file is CommonJS but has a .js extension, which Node treats as ESM in that scope.
// package.json
{ "type": "module" }
npx sequelize-cli migration:generate --name add-users-table
# -> migrations/20261001000000-add-users-table.js (content: module.exports = { up, down })
npx sequelize-cli db:migrate
What do you expect to happen?
A way to tell the CLI which extension to use for generated migrations and seeders, for example:
npx sequelize-cli migration:generate --name add-users-table --extension cjs
or once in .sequelizerc (whose keys are already passed to yargs as config, see src/core/yargs.js#L6-L17):
// .sequelizerc
module.exports = {
'migrations-path': 'migrations',
extension: 'cjs',
};
so the generated file is 20261001000000-add-users-table.cjs, which db:migrate already loads correctly.
What is actually happening?
The extension is hardcoded to js:
src/helpers/path-helper.js#L47-L49:getFileExtension()always returns'js', even thoughaddFileExtension(basename, options)already passes anoptionsargument to it.src/commands/migration_generate.js#L21andsrc/commands/seed_generate.js#L19build the path through it.- The templates are CommonJS:
src/assets/migrations/skeleton.js#L4,src/assets/seeders/skeleton.js#L4.
Migrations are then loaded with a plain require() by Umzug v2 (umzug/src/migration.js#L68). Under "type": "module" a .js file is ESM, so loading it fails:
# Node 22
module is not defined in ES module scope
# Node < 20.19 / < 22.12
ERR_REQUIRE_ESM
The loader side already supports .cjs: the migrator pattern is /^(?!.*\.d\.ts$).*\.(cjs|js|cts|ts)$/ (src/core/migrator.js#L49), added in #905. Only generation is missing.
Current workaround
We wrap the generate command in a small script that renames the output from .js to .cjs:
#!/usr/bin/env bash
# bin/generate-migration.sh — usage: bin/generate-migration.sh --name <name>
set -euo pipefail
MIGRATIONS_DIR="migrations"
before=$(ls "$MIGRATIONS_DIR")
npx sequelize-cli migration:generate "$@"
for f in "$MIGRATIONS_DIR"/*.js; do
name=$(basename "$f")
if ! grep -qxF "$name" <<< "$before"; then
mv "$f" "${f%.js}.cjs"
echo "Renamed $name -> ${name%.js}.cjs"
fi
done
This works, but every project using "type": "module" has to reinvent it, and it's easy to forget when someone runs sequelize-cli migration:generate directly. A built-in option would remove the need for it.
Proposed change
- Add an
--extensionoption tomigration:generateandseed:generate, settable from.sequelizerclike other options. - Accept only extensions the migrator actually loads (
js,cjs,ts,cts) via yargschoices, defaultjs, so behaviour is unchanged for existing users. - Reject
mjs, since the migrator pattern skips.mjsfiles silently and Umzug v2 loads withrequire(). - Pass the extension explicitly through
getMigrationPath/getSeederPath→getFileName→getFileExtension(extension)(returningextension || 'js'), rather than reading globalargsinsidegetFileExtension(). The same helper is also used bygetModelPath()(path-helper.js#L76) andinit(init-helper.js#L58), and the generatedmodels/index.jsonly loads.jsfiles (models/index.js#L25), so a global setting would silently break model loading. - Template content stays CommonJS, since every accepted extension is loaded through
require().
Related
- #905: added support for running
.cjsmigrations (this is the generation counterpart) - #1436: same root cause (hardcoded extension in
getFileExtension), asking for.tsgeneration. The proposed option would cover that request too. - #960: generated files not working in ESM projects; option to choose CJS vs ESM
- #987 / #990: ESM/CJS support for config and
.sequelizerc
Dialect: any
Database version: N/A
Sequelize CLI version: 6.6.5
Sequelize version: 6.37.7
Node version: 22.x
Would you resolve this issue by submitting a Pull Request?
- Yes, I have the time and I know how to start.
- 主要语言
- JavaScript
- 星标
- 2.6k
- 派生
- 524
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 提供 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
sequelize/cli 的其他 Issue
-
`sequelize init` writes JSON content into `.js` config file when using `.sequelizerc`可能已有人在做 @sanskarajput 于 181 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 68/100
-
难度 3/5 1-2 天 新手友好度 68/100
-
难度 3/5 1-2 天 新手友好度 48/100
-
难度 3/5 1-2 天 新手友好度 55/100
-
难度 3/5 1-2 天 新手友好度 45/100
相似的 Issue
-
automated issue report
难度 2/5 1-3 小时 新手友好度 62/100
-
难度 2/5 1-3 小时 新手友好度 75/100
-
难度 2/5 1-3 小时 新手友好度 70/100
维护者通常 1 天内回复
-
0. to triage bug
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 70/100
sindresorhus/eslint-plugin-unicorn#3825 ·
维护者通常 1 天内回复