node.jstypescriptcyclic

Running a Node.js TypeScript App on Cyclic.sh from a repo subdirectory


I am trying to run a Node.js TypeScript app on Cyclic.sh from a subdirectory in the repo and I am having trouble. There is nothing in their tutorials about both TypeScript and a subdirectory, so I am looking for some guidance here. My specs:

The repo

Cyclic (advanced) Build Options:

/lol-pickem-api/package.json

  "main": "server.js",
  "scripts": {
    "build": "tsc --build",
    "build:watch": "tsc --watch",
    "start": "node dist/server.js",
    "start:watch": "rm -rf \"./dist/*\" && tsc-watch --onSuccess \"node -r source-map-support/register .\"",
    "debug": "rm -rf \"./dist/*\" && tsc-watch --onSuccess \"node --inspect -r source-map-support/register .\""
  },

/lol-pickem-api/tsconfig.json

{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es6",
    "module": "commonjs",
    "outDir": "./dist",
    "baseUrl": "./src",
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts", "./package.json"],
  "exclude": ["node_modules"]
}

The errors:

2023-07-18 16:40:31.061: node:internal/modules/cjs/loader:1031
  throw err;
  ^

Error: Cannot find module '/var/task/dist/server.js'
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1028:15)
    at Function.Module._load (node:internal/modules/cjs/loader:873:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:22:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}
2023-07-18 16:40:31.076: 

2023-07-18 16:40:31.076: ERROR: Failed to run "npm run start". Start script defined in package.json:

            "scripts": {
                "start":  "node dist/server.js"
                 ...
            
Exited with code: 1
2023-07-18 16:40:31.088: [CYCLIC] ERROR: No response from server on port 3000
2023-07-18 16:40:31.593: node:internal/modules/cjs/loader:1031
  throw err;
  ^

Error: Cannot find module '/var/task/dist/server.js'
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1028:15)
    at Function.Module._load (node:internal/modules/cjs/loader:873:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:22:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}


ERROR: Failed to run "npm run start". Start script defined in package.json:

            "scripts": {
                "start":  "node dist/server.js"
                 ...
            
Exited with code: 1
2023-07-18 16:40:31.733: node:internal/modules/cjs/loader:1031
  throw err;
  ^

Error: Cannot find module '/var/task/dist/server.js'
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:1028:15)
    at Function.Module._load (node:internal/modules/cjs/loader:873:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:22:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}
2023-07-18 16:40:31.751: 

2023-07-18 16:40:31.751: ERROR: Failed to run "npm run start". Start script defined in package.json:

            "scripts": {
                "start":  "node dist/server.js"
                 ...
            
2023-07-18 16:40:31.751: Exited with code: 1
2023-07-18 16:40:31.759: [CYCLIC] ERROR: No response from server on port 3000

Any and all help would be much appreciated!


Solution

  • Try "start": "node src/server.js" directly (as if no dist subfolder)

    While Cyclic docs may not be explicit about it, if you define an output path, the latter becomes the current working directory of your final app bundle. That is why that output path must also contain your package.json file.

    And another consequence is that all runtime file paths (in particular for the start script) are relative to that new cwd.

    Therefore in your case, after build you have:

    /lol-pickem-api
    └── dist
        ├── src
        │   └── server.js
        └── package.json
    

    With Output Path: lol-pickem-api/dist, Cyclic bundles only that subdirectory, which becomes the cwd.

    When launching your app, Cyclic then finds the package.json file inside, with a start script and executes it.

    The path is now relative to the cwd, hence server.js is in src subfolder. And you can just execute node src/server.js.


    Additionally, make sure your node_modules dependencies are also available within your dist output path: as mentioned above, only that folder is bundled, so you need to have:

    /lol-pickem-api
    └── dist
        ├── node_modules
        ├── src
        │   └── server.js
        └── package.json