knex: javascript knexfile can't run typescript migrations
Environment
Knex version: 0.21.1 Database + version: postgres 12 OS: Linux
Bug
- Description
When the knexfile has js extension, typescript migrations and seeds can’t be run. The error thrown suggests these files are not loaded with typescript loader. Changing knexfile extension to ts fixes the problem.
This is rather unexpected, as the documentation suggests that knex can run migrations of different types, no matter what the knexfile extension is.
loadExtensions: array of file extensions which knex will treat as migrations.
- Error message
import Knex from 'knex';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1047:16)
at Module._compile (internal/modules/cjs/loader.js:1097:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
at Module.load (internal/modules/cjs/loader.js:977:32)
at Function.Module._load (internal/modules/cjs/loader.js:877:14)
at Module.require (internal/modules/cjs/loader.js:1019:19)
at require (internal/modules/cjs/helpers.js:77:18)
at FsMigrations.getMigration (/home/przemek/DEV/sundae/sundae-collab-demo-api/node_modules/knex/lib/migrate/sources/fs-migrations.js:82:12)
at /home/przemek/DEV/sundae/sundae-collab-demo-api/node_modules/knex/lib/migrate/Migrator.js:76:67
at Array.some (<anonymous>)
- Knexfile content
require('dotenv').config();
const defaultSettings = {
// client
// connection
};
module.exports.development = {
...defaultSettings,
migrations: {
loadExtensions: ['.ts'],
extension: 'ts',
},
seeds: {
loadExtensions: ['.ts'],
},
};
module.exports.test = {
...defaultSettings,
migrations: {
loadExtensions: ['.ts'],
extension: 'ts',
},
seeds: {
loadExtensions: ['.ts'],
},
};
module.exports.production = {
...defaultSettings,
migrations: {
directory: 'build/migrations',
},
seeds: {
directory: 'build/seeds',
},
};
Feature discussion / request
- Explain what is your use case
I want to run Typescript migrations and seeds in development environment. In production, where Typescript and ts-node might not be present, compiled migrations and seeds should be used instead. Ideally, one js knexfile would handle both cases.
- Explain what kind of feature would support this
Knexfile extension should not influence migration and seed loading. When loadExtensions includes .ts, typescript migrations and seeds should be loaded and run.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 8
- Comments: 22
For those seeing
for me the fix was that I was missing ts-node from my package.json. A simple
was all I needed.
@abcd-ca You can use:
knex uses ts-node’s require hook for
.tsextension and that can accept TS compiler options throughTS_NODE_COMPILER_OPTIONSenv variable. These options will be merged into what you have in your tsconfig.json.@abcd-ca I resolved it below code.
@lorefnon That gave me this alternative idea:
created a tsconfig.knexcli.json containing an override for module,
Then when running my commands,
TS_NODE_PROJECT=tsconfig.knexcli.json knex migrate:latestJust slightly cleaner because the JSON when in an npm script needs to escape the quotes and gets a bit busy looking. Thanks!
@prk3 If you specify
loadExtensions: ['.js']in the config for production env it should work as expected.The default value of loadExtensions comes from here which will have to be overridden if you have some files matching those extensions which you don’t want to process.
Hello @prk3 I have the same problem, when run knex migrate in heroku cli
Still having issues with this.
This is the error I am getting:
SyntaxError: Cannot use import statement outside a module@abcd-ca’s method of
in tsconfig.json worked for me as well
~I just noticed that 0.21.1 in the changelog has a bug fix that looks related which I suspect might be causing this side effect issue.~
This was incorrect, I tried with 0.21.0 and it didn’t fix it. I got the knexfile.ts to work with the
importby changing"module": "esnext"to"module": "commonjs"in tsconfig.json. The problem is in my case is that I am using Next.js 9 (9.4.0) and when I run the app, Next.js changes the module setting back to esnext which is apparently a known issue. So, I think this is not a knex problem but if you don’t know thatmodulemust becommonjsthen you’re in trouble – I’d recommend adding it to the docs.I resolve with:
yarn add ts-node -Dand add in package.json scripts:
now use
yarn knex <your command>