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"
}
}
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 stripsdevDependencies
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
fromdevDependencies
todependencies
. 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 runstsc
, I wonder if it has already compiled yourknexfile.ts
toknexfile.js
. If it did, you can try running the JavaScript file directly:Since that's the default file that Knex looks for, you can actually skip the argument entirely:
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.