I want to migrate a SQlite database:

knex --knexfile knexfile.ts migrate:latest

However this gives the following typescript error:

⨯ Unable to compile TypeScript:
knexfile.ts:1:18 - error TS2307: Cannot find module 'path' or its corresponding type declarations.

1 import path from 'path';
                   ~~~~~~
knexfile.ts:4:1 - error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.

4 module.exports = {
  ~~~~~~
knexfile.ts:7:28 - error TS2304: Cannot find name '__dirname'.

7     filename: path.resolve(__dirname, 'src', 'database', 'database.sqlite'),
                             ~~~~~~~~~
knexfile.ts:10:29 - error TS2304: Cannot find name '__dirname'.

10     directory: path.resolve(__dirname, 'src', 'database', 'migrations'),
                               ~~~~~~~~~
knexfile.ts:13:29 - error TS2304: Cannot find name '__dirname'.

13     directory: path.resolve(__dirname, 'src', 'database', 'seeds'),
                               ~~~~~~~~~

TSError: ⨯ Unable to compile TypeScript:
knexfile.ts:1:18 - error TS2307: Cannot find module 'path' or its corresponding type declarations.

1 import path from 'path';
                   ~~~~~~
knexfile.ts:4:1 - error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.

4 module.exports = {
  ~~~~~~
knexfile.ts:7:28 - error TS2304: Cannot find name '__dirname'.

7     filename: path.resolve(__dirname, 'src', 'database', 'database.sqlite'),
                             ~~~~~~~~~
knexfile.ts:10:29 - error TS2304: Cannot find name '__dirname'.

10     directory: path.resolve(__dirname, 'src', 'database', 'migrations'),
                               ~~~~~~~~~
knexfile.ts:13:29 - error TS2304: Cannot find name '__dirname'.

13     directory: path.resolve(__dirname, 'src', 'database', 'seeds'),
                               ~~~~~~~~~

Bellow is my knexfile:

import path from 'path';
import 'dotenv/config';

module.exports = {
  client: 'sqlite3',
  connection: {
    filename: path.resolve(__dirname, 'src', 'database', 'database.sqlite'),
  },
  migrations: {
    directory: path.resolve(__dirname, 'src', 'database', 'migrations'),
  },
  seeds: {
    directory: path.resolve(__dirname, 'src', 'database', 'seeds'),
  },
  useNullAsDefault: true,
};

How can I address such issue? I am using the following dependencies:

devDependencies dependencies
"@types/bcryptjs": "^2.4.2", "@vscode/sqlite3": "^5.0.8"
"@types/cors": "^2.8.7", "bcryptjs": "^2.4.3"
"@types/express": "^4.17.7", "cors": "^2.8.5"
"@types/jsonwebtoken": "^8.5.8" "dotenv": "^8.2.0"
"@types/node": "^17.0.24" "express": "^4.17.1"
"knex-types": "^0.3.2" "jsonwebtoken": "^8.5.1"
"ts-node-dev": "^1.0.0-pre.56" "knex": "^1.0.7"
"typescript": "^4.6.3" "ts-node": "^8.10.2"
"sqlite3": "^5.0.3"

Edit package.json file

{
  "name": "imonitor-server",
  "version": "1.0.0",
  "description": "",
  "main": "src/server.ts",
  "scripts": {
    "start": "node build/src/server.js",
    "postinstall": "tsc",
    "dev": "tsnd --transpile-only --ignore-watch node_modules --respawn src/server.ts",
    "knex:migrate": "knex --knexfile knexfile.ts migrate:latest",
    "knex:seed": "knex --knexfile knexfile.ts seed:run",
    "knex:rollback": "knex --knexfile knexfile.ts migrate:rollback",
    "build": "tsc"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/lucasbbs/imonitor-backend.git"
  },
  "keywords": [],
  "engines": {
    "node": "16.14.0",
    "npm": "8.3.1"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/lucasbbs/imonitor-backend/issues"
  },
  "homepage": "https://github.com/lucasbbs/imonitor-backend#readme",
  "devDependencies": {
    "@types/bcryptjs": "^2.4.2",
    "@types/cors": "^2.8.7",
    "@types/express": "^4.17.7",
    "@types/jsonwebtoken": "^8.5.8",
    "@types/node": "^17.0.24",
    "knex-types": "^0.3.2",
    "ts-node-dev": "^1.0.0-pre.56",
    "typescript": "^4.6.3"
  },
  "dependencies": {
    "@vscode/sqlite3": "^5.0.8",
    "bcryptjs": "^2.4.3",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "knex": "^1.0.7",
    "pg": "^8.3.0",
    "sqlite3": "^5.0.3",
    "ts-node": "^8.10.2"
  }
}

2

There are 2 answers

0
Chris On BEST ANSWER

TypeScript

The immediate issue here is that you're trying use TypeScript at runtime, but you've defined @types/node as a development dependency. By default, Heroku strips devDependencies from your project after building it.

One option is to skip the pruning step, which will leave your devDependencies in place, but that likely isn't the right choice. Normally you'll want these dependencies to be stripped. Among other reasons, this reduces the size of your application slug.

Another option is to move @types/node from devDependencies to dependencies. But I don't think that's the right move here, either. My gut says you shouldn't be using TypeScript at all in production.

Since your build script simply runs tsc, I wonder if it has already compiled your knexfile.ts to knexfile.js. If it did, you can try running the JavaScript file directly:

knex --knexfile knexfile.js migrate:latest

Since that's the default file that Knex looks for, you can actually skip the argument entirely:

knex migrate:latest

SQLite

This should get your migrations going, but you're going to run into another issue: Heroku's ephemeral filesystem makes SQLite a poor database choice.

Any changes you make to the database, including schema changes introduced by your migrations, will be lost whenever your dyno restarts. This happens frequently (at least once per day).

To resolve that issue, you'll want to switch from SQLite to a client-server database. Heroku's own Postgres service is a reasonable starting point, but there are other database addons if you prefer. You can also host your own database elsewhere on the cloud, e.g. on Microsoft Azure or AWS.

0
Juan David Arce On

I had the same issue with another module, I was trying to import @mui/x-data-grid in a file, but got the same error. I found as mentioned by @Chris above that the library was in the dependencies object not in the devDependencies, so I just have to remove it and install it again on the devDependencies, now the error message is gone. It seems that @types/node must be in the same dependencies object (dev or not) as the module you are trying to use.