Knex: migrate:make fails with TypeScript

Created on 18 Jan 2019  ·  27Comments  ·  Source: knex/knex

Environment

Knex version: 0.16.3 (Using TypeScript knexfile)
Database + version: PostgreSQL 10.5
OS: Windows 10 Pro 64 Bit

Bug

When running knex migrate:make somename, this is the output:

Requiring external module ts-node/register
Using environment: development
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
    at assertPath (path.js:39:11)
    at Object.resolve (path.js:166:7)
    at directories.map.directory (X:\Code\node\knextest\node_modules\knex\lib\migrate\MigrationGenerator.js:82:28)
    at Array.map (<anonymous>)
    at MigrationGenerator._absoluteConfigDirs (X:\Code\node\knextest\node_modules\knex\lib\migrate\MigrationGenerator.js:81:24)
    at MigrationGenerator._ensureFolder (X:\Code\node\knextest\node_modules\knex\lib\migrate\MigrationGenerator.js:41:23)
    at MigrationGenerator.make (X:\Code\node\knextest\node_modules\knex\lib\migrate\MigrationGenerator.js:35:17)
    at Migrator.make (X:\Code\node\knextest\node_modules\knex\lib\migrate\Migrator.js:122:27)
    at Command.commander.command.description.option.action (X:\Code\node\knextest\node_modules\knex\bin\cli.js:179:10)
    at Command.listener (X:\Code\node\knextest\node_modules\commander\index.js:315:8)
    at Command.emit (events.js:182:13)
    at Command.parseArgs (X:\Code\node\knextest\node_modules\commander\index.js:654:12)
    at Command.parse (X:\Code\node\knextest\node_modules\commander\index.js:474:21)
    at Liftoff.invoke (X:\Code\node\knextest\node_modules\knex\bin\cli.js:278:13)
    at Liftoff.execute (X:\Code\node\knextest\node_modules\liftoff\index.js:203:12)
    at module.exports (X:\Code\node\knextest\node_modules\flagged-respawn\index.js:51:3)

This is the content of my knexfile.ts:

module.exports = {
  development: {
    client: 'pg',
    connection: {
      host: 'localhost',
      database: 'postgres',
      user: 'postgres',
      password: 'pw',
    },
    migrations: {
      directory: 'migrations',
    },
  },
};

Some additional details:

  • knex migrate:make somename works if I change knexfile extension to .js. (knex 0.16.3)
  • knex migrate:make somename works like it should with TypeScript knexfile when using knex 0.15.1 and @types/knex 0.15.1 package.
  • I have not tried different database engines or the versions between knex 0.15.1 - 0.16.3.
bug migrations

Most helpful comment

We also use Knex for writing the query to a PostgreSQL server. We discovered that the best way to generate is as follow.

  1. Generate Migration File
knex migrate:make --knexfile knexfile.ts -x ts <your-migration-name>
  1. Run Migration File
knex migrate:latest --knexfile knexfile.ts 
  1. Generate seed File
knex seed:make --knexfile knexfile.ts -x ts <your-seed-name>
  1. Run seed File
knex seed:run --knexfile knexfile.ts 

The --knexfile knexfile.ts won't be necessary if you use knexfile.js since the typescript cannot provide any type checking for you for the config file.

All 27 comments

I think this is probably related: https://github.com/tgriesser/knex/issues/2998
I can confirm it works with 0.15.2, but not 0.16.x

I think this is probably related: #2998
I can confirm it works with 0.15.2, but not 0.16.x

Nope, this is different issue. and I can confirm that #2998 cannot be reproduced with given information.

Sounds like automatic knexfile resolving does not look for knexfile.ts, you can pass --knexfile knexfile.ts argument to command or give path directly to the migration generator command with:

knex migrate:make --migrations-directory . -x ts migration-name

I suppose client should look for knexfile.ts automatically though.

I first noticed this with migrate:latest, which interestingly throws a different error than migrate:make. Here's a simple repro where you can see both: https://github.com/jrr/knex-ts-issue-repro

Also noticed today that knex --knexfile knexfile.ts migrate:make (...) will create a .js file instead of .ts. (previously, when knex automatically picked up knexfile.ts, it would also automatically produce .ts migrations)

We also use Knex for writing the query to a PostgreSQL server. We discovered that the best way to generate is as follow.

  1. Generate Migration File
knex migrate:make --knexfile knexfile.ts -x ts <your-migration-name>
  1. Run Migration File
knex migrate:latest --knexfile knexfile.ts 
  1. Generate seed File
knex seed:make --knexfile knexfile.ts -x ts <your-seed-name>
  1. Run seed File
knex seed:run --knexfile knexfile.ts 

The --knexfile knexfile.ts won't be necessary if you use knexfile.js since the typescript cannot provide any type checking for you for the config file.

Any plans on fixing that? It's been hard to increase Knex adoption with this issue :/

@dgadelha Thanks for the reminder! I'll take a look today or tomorrow.

@dgadelha 0.17.6 with fix for this was released. Unfortunately, fix for resolving extension from knexfile extension will only be available on master (starting on it right now).

Also noticed today that knex --knexfile knexfile.ts migrate:make (...) will create a .js file instead of .ts. (previously, when knex automatically picked up knexfile.ts, it would also automatically produce .ts migrations)

@kibertoad Just installed 0.17.6 and that behavior still happens, even when specifying ".ts" in the Knexfile. Are they separate bugs?

@mathieumg Yes. See PR that I've created a couple of minutes ago and referenced from this issue :D

@kibertoad I did! The description makes it sounds like that was rather for inferring the extension based on the same extension as the Knexfile, so I wasn't sure.

The description makes it sounds like that was rather for inferring the extension based on the same extension as the Knexfile -> well yeah, it's about automatically inferring extension from knexfile, no matter whether it is explicitly specified one or the autoresolved one.
0.17.6 fixed autoresolution of TS knexfiles.

Alright! Because 0.17.6 with extension: "ts" still gave the ".js" result. Thanks for fixing those bugs! 😄

Because 0.17.6 with extension: "ts" still gave the ".js" result

Ah, you mean you have knexfile that has

{
...
migrations: {
  extension: "ts"
}

in it? That one was fixed in https://github.com/tgriesser/knex/commit/a65a95bc672563e01c08b40384e1dc2b079ecee1, you can already access it by locking your version at this commit (if you don't want to point at master directly).
Unfortunately it won't be backported to 0.17

0.18.0 is still quite ahead, but if depending on commits not an option for you, I could release next-1 instead.

Hey, I've commented the PR, thanks a lot!

@kibertoad Awesome, thanks for the precision! We can wait on 0.18, no stress. 😄

@kibertoad The commit you refer to only works if it is defined directly under

module.exports = {
  migrations: {
    extension: 'ts';
  }
}

But the migrations object that defines where to put, and read from, migrations have to be defined under

module.exports = {
  [environment]: {
    migrations: {
      directory: './migrations';
    }
}

If I move the migrations object out of the environment object the migrations directory will be ignored.

@ViggoV Thanks for the bug report! Will try to address this today.

@ViggoV Can you try latest master and report back if it works correctly in your case now?

Released in 0.18.0-next2

Sorry, I ended up switching to { ext: 'ts' } which works as I would expect but doesn't seem to be documented. I will test when I have the time

Hi i had the same problem. I solved requiring ts-node/register in my knexfile.ts like this

`
require('ts-node/register')
const s = require("./settings.js");
module.exports = {

client: 'pg',
connection: {
  user: s.user,
  host: s.host,
  database: 'starwars',
  password: s.password,
  ssl: true

}
};

`

I don't know if you already solved the issue but in my case the solution was very simple. I just move the _knexfile.js_ to the root of project. I installed the knex in directory "/backend" but for unknow reason the file moved to other directory. So I moved knexfile.js to "backend/knexfile.js" and works like a charm. I hope it will be useful for someone.

Hi @moacirandretti , my knexfile.ts it's in the root project, but cli heroku heroku run knex --knexfile knexfile.ts migrate: latest
return this message.

Running knex --knexfile knexfile.ts migrate: latest on ⬢ backend-ecolab ... up, run.5056 (Free)
Failed to load external module ts-node / register
Failed to load external module typescript-node / register
Failed to load external module typescript-register
Failed to load external module typescript-require
Failed to load external module sucrase / register / ts
Failed to load external module @ babel / register
Error: Cannot find module 'ts-node / register'
Require stack:
- /app/knexfile.ts
- /app/node_modules/knex/bin/cli.js
    at Function.Module._resolveFilename (internal / modules / cjs / loader.js: 966: 15)
    at Function.Module._load (internal / modules / cjs / loader.js: 842: 27)
    at Module.require (internal / modules / cjs / loader.js: 1026: 19)
    at require (internal / modules / cjs / helpers.js: 72: 18)
    at Object. <anonymous> (/app/knexfile.ts:1:1)
    at Module._compile (internal / modules / cjs / loader.js: 1138: 30)
    at Object.Module._extensions..js (internal / modules / cjs / loader.js: 1158: 10)
    at Module.load (internal / modules / cjs / loader.js: 986: 32)
    at Function.Module._load (internal / modules / cjs / loader.js: 879: 14)
    at Module.require (internal / modules / cjs / loader.js: 1026: 19)

I installed this package ts-node in dev dependency

I faced the same error.
knexfile.ts:

import dotenv from "dotenv";
import { Config } from "knex";
dotenv.config();

interface KnexConfig {
  [name: string]: Config;
}

const knexConfig: KnexConfig = {
  development: {
    client: "pg",
    connection: {
      host: process.env.DB_HOST || "127.0.0.1",
      user: process.env.DB_USERNAME || "postgres",
      password: process.env.DB_PASSWRORD || "postgres",
      database: process.env.DB_DEV_NAME || "done_list",
    },
    migrations: {
      directory: "./migrations",
      extension: "ts",
    },
  },
  test: {
    client: "pg",
    connection: {
      host: process.env.DB_HOST || "127.0.0.1",
      user: process.env.DB_USERNAME || "postgres",
      password: process.env.DB_PASSWRORD || "postgres",
      database: process.env.DB_DEV_NAME || "done_list_test",
    },
  },
};

export { knexConfig };

when I run knex migrate:make user I got an error, but when I run knex migrate:make --migrations-directory ./scr/migrations -x ts user as mentioned by this comment.

Typescript: 4.0.2
knex: 0.21.5
@types/knex: 0.16.1

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zettam picture zettam  ·  3Comments

mattgrande picture mattgrande  ·  3Comments

rarkins picture rarkins  ·  3Comments

aj0strow picture aj0strow  ·  3Comments

npow picture npow  ·  3Comments