-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't execute CLI migrations using ESM typescript #4793
Comments
Same here. Tried to hunt it down and got to this issue gulpjs/rechoir#43 |
so is there any solution to this? |
Run node with the node --loader ts-node/esm ./node_modules/.bin/knex -x ts migrate:make example_migration |
any library with .js is trash for typescript support apparently |
I managed to get typescript migrations working under esm: Excerpt from package.json: {
"type": "module",
"scripts": {
"migrate:latest": "NODE_OPTIONS='--loader ts-node/esm' yarn run knex migrate:latest",
},
"devDependencies": {
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
}
} excerpt from tsconfig.json: {
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"exclude": ["node_modules"],
"ts-node": {
"experimentalSpecifierResolution": "node",
"require": ["dotenv/config"],
"typeCheck": false,
"files": true,
"esm": true,
"swc": true,
"ignore": [
"(?:^|/)node_modules/",
"(?:^|/)\\.next/",
".yarn/*",
]
}
} excerpt from knexfile.js const commonConf = {
client: "pg",
migrations: {
tableName: "knex_migrations",
directory: "./migrations",
loadExtensions: ['.js', '.ts']
},
pool: {
min: 1,
max: 1,
},
};
export default commonConf; $ cat migrations/20230214154135_hello.ts import { Knex } from "knex";
export async function up(knex: Knex): Promise<void> {
console.log("HELLO");
throw new Error("HELLO");
}
export async function down(knex: Knex): Promise<void> {
} $ node --version
v16.18.1
$ yarn --version
3.4.1
$ yarn migrate:latest
(node:810828) ExperimentalWarning: Custom ESM Loaders is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:810856) ExperimentalWarning: Custom ESM Loaders is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
HELLO
migration file "20230214154135_hello.ts" failed
migration failed with error: HELLO
HELLO
Error: HELLO
at Module.up (file:///migrations/20230214154135_hello.ts:6:9)
at /node_modules/knex/lib/migrations/migrate/Migrator.js:519:40
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Migrator._runBatch (/node_modules/knex/lib/migrations/migrate/Migrator.js:381:19) |
My workaround to use knex from cli is to use custom knex cli wrapper with self-defined knex instance. This custom cli can be invoked using tsx, e.g. You can also setup a knex script in {
"scripts": {
"knex": "tsx knex-cli.ts"
}
} Then you replace typical call to knex from npx to npm run, e.g. (In my dev machine, I setup The import { knex } from './db.js'
async function main() {
let args = process.argv.slice(2)
if (args.length == 0) {
console.error('Error: missing knex command in argument')
return
}
type MigrationResult = [batch: number, migrations: string[]]
function showMigrationResult(
label: string,
[batch, migrations]: MigrationResult,
) {
if (migrations.length === 0) {
console.log('No migrations affected.')
return
}
console.log(label, 'batch:', batch)
console.log('migrations:')
console.log(migrations.map(s => '- ' + s).join('\n'))
}
switch (args[0]) {
case 'migrate:up': {
showMigrationResult('migrate:up', await knex.migrate.up())
break
}
case 'migrate:down': {
showMigrationResult('migrate:down', await knex.migrate.down())
break
}
case 'migrate:latest': {
showMigrationResult('migrate:latest', await knex.migrate.latest())
break
}
case 'migrate:rollback': {
let config = undefined
let all = args[1] === '--all'
showMigrationResult('rollback', await knex.migrate.rollback(config, all))
break
}
case 'migrate:status': {
type Result = [{ name: string }[], { file: string }[]]
let [done, pending] = (await knex.migrate.list()) as Result
console.log(done.length, 'applied migrations')
for (let each of done) {
console.log('- ' + each.name)
}
console.log(pending.length, 'pending migrations')
for (let each of pending) {
console.log('- ' + each.file)
}
break
}
default: {
console.error('Error: unknown arguments:', args)
}
}
}
main()
.catch(e => console.error(e))
.then(() => knex.destroy()) |
What is './db.js'? I am getting these errors
|
@beenotung awesome work! Here's the same script with added support for import knex from '@server/db/knex';
type MigrationResult = [batch: number, migrations: string[]];
function showMigrationResult(
label: string,
[batch, migrations]: MigrationResult,
) {
if (migrations.length === 0) {
console.log('No migrations affected.');
return;
}
console.log(label, 'batch:', batch);
console.log('migrations:');
console.log(migrations.map((s) => '- ' + s).join('\n'));
}
async function main() {
const args = process.argv.slice(2);
if (args.length == 0) {
console.error('Error: missing knex command in argument');
return;
}
switch (args[0]) {
case 'migrate:up': {
showMigrationResult('migrate:up', await knex.migrate.up());
break;
}
case 'migrate:down': {
showMigrationResult('migrate:down', await knex.migrate.down());
break;
}
case 'migrate:latest': {
showMigrationResult('migrate:latest', await knex.migrate.latest());
break;
}
case 'migrate:rollback': {
const config = undefined;
const all = args[1] === '--all';
showMigrationResult('rollback', await knex.migrate.rollback(config, all));
break;
}
case 'migrate:status': {
type Result = [{ name: string }[], { file: string }[]];
const [done, pending] = (await knex.migrate.list()) as Result;
console.log(done.length, 'applied migrations');
for (const each of done) {
console.log('- ' + each.name);
}
console.log(pending.length, 'pending migrations');
for (const each of pending) {
console.log('- ' + each.file);
}
break;
}
case 'migrate:make': {
const result = await knex.migrate.make(args[1]);
console.log(result);
break;
}
default: {
console.error('Error: unknown arguments:', args);
}
}
}
main()
.catch((e) => console.error(e))
.then(() => knex.destroy()); |
The Here's mine for example: import { sqlConfig } from '@server/config/env';
import knex from 'knex';
export default knex({
client: 'mssql',
connection: {
server: sqlConfig.server,
database: sqlConfig.database,
user: sqlConfig.user,
password: sqlConfig.password,
port: sqlConfig.port,
options: {
encrypt: false,
enableArithAbort: true,
},
pool: {
max: 100,
min: 5,
idleTimeoutMillis: 30000,
},
requestTimeout: 6000000,
},
pool: { min: 0, max: 100 },
}); |
Thanks, I got it working finally - I had to dynamically import the db file since I'm using dotenv to get a different database file depending on environment - was missing a |
Ended up making an
|
Environment
Knex version: ^0.95.12
Database + version: Mysql 8.0.26
OS: Windows 10
@lorefnon
Bug
Explain what kind of behaviour you are getting and how you think it should do
I am trying to do typescript migrations using the ESM. Using "type": "module" on package.json with module ESNext (project requirements).
I would expect a successful migration without errors.
Error message
package.json
tsconfig.json
knexfile.ts
The text was updated successfully, but these errors were encountered: