Search code examples
node.jstypescriptherokuscheduler

How to run a TypeScript file in Heroku Scheduler?


I've got a TypeScript server on Heroku, and I'm trying to schedule a job to run every hour. The app itself works great and serves all the data it needs to, but when I try to run a job through "Heroku Scheduler" it will fail.

This is the command I use to start the job: npx ts-node src/scheduler/weatherAlertCheck.ts

The errors/issues I encounter:

  1. I will be prompted with this in the terminal (while I'm testing)
Need to install the following packages:
ts-node@10.9.1
Ok to proceed? (y)
  1. I get an error that seems clearly related to the first issue:
/app/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:859
    return new TSError(diagnosticText, diagnosticCodes, diagnostics);
           ^
TSError: ⨯ Unable to compile TypeScript:
src/controllers/notifications.ts:3:35 - error TS7016: Could not find a declaration file for module 'express'. '/app/node_modules/express/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/express` if it exists or add a new declaration (.d.ts) file containing `declare module 'express';`

3 import { Request, Response } from "express";
                                    ~~~~~~~~~

So I believe that the scheduler isn't compiling TypeScript before running the command, but I'm not quite sure how to fix that. If I'm wrong, please let me know what else I should try.

Edit: For addition help, here's the look of my package.json

{
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/jsonwebtoken": "^9.0.1",
    "@types/node": "^18.14.0",
    "nodemon": "^2.0.20",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4"
  },
  "scripts": {
    "dev": "npx nodemon",
    "build": "tsc",
    "postinstall": "npm run build",
    "start": "node build/main.js"
  },
  "dependencies": {
    "@parse/node-apn": "^5.1.0",
    "@types/jsonwebtoken": "^9.0.1",
    "axios": "^1.2.6",
    "body-parser": "^1.20.1",
    "dotenv": "^16.0.3",
    "express": "^4.18.2",
    "fs": "^0.0.1-security",
    "jsonwebtoken": "^8.5.1",
    "knex": "^2.4.0",
    "pg": "^8.8.0",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4"
  }
}

Solution

  • Your start script is done correctly: it runs the compiled JavaScript file, not the source TypeScript file.

    Your scheduled job should follow the same pattern, e.g. something like

    node dist/scheduler/weatherAlertCheck.js
    

    if src/scheduler/weatherAlertCheck.ts gets compiled to dist/scheduler/weatherAlertCheck.js.

    Note that ts-node and typescript should probably be declared as dev dependencies and not regular dependencies. All TypeScript code should be compiled to JavaScript at build time (dev dependencies are available at build time) and the compiled JavaScript should be used at runtime.