I am creating boilerplate for microservices using express, Typescript and Lerna. My setup is working fine locally but when I use PM2 for prod deployment its giving following error.
Error: Directory import '/Users/dramor/Development/POC/micro-poc/packages/api-gateway/dist/config' is not supported resolving ES modules imported from /Users/dramor/Development/POC/micro-poc/packages/api-gateway/dist/index.js
/pacakges/api-gateway/src/index.ts
import { initConfig } from './config';
import express from 'express';
import { authenticateJWT, handleLoginReq } from './config/passport';
import _ from 'lodash';
// ..rest of the code
PM2 is expecting file but found config directory, but when we change import to /config.ts then typescripts gives error
An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled.
if I use allowImportingTsExtensions = true with emitDeclarationOnly = true then dist folder does not create JS files. It creates only type definitions.
Possible solutions could :
- Import with .ts extension and generate dist with JS
- Map import of /config to /config.ts or /config/index.ts in PM2
I am attaching configuration for more clarity
Directory structure:
boilerplate
--packages
-- api-gateway
-- package.json
-- tsconfig.json (extending root config, provided below)
tsconfig.json
Related dependencies from root package.json
"lerna": "^8.0.2",
"lodash": "^4.17.21",
"nodemon": "^3.0.2",
"pm2": "^5.3.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
root - tsconfig.json
{
"compilerOptions": {
"target": "es2020",
"module": "es2022",
"lib": ["es2020"],
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"baseUrl": ".",
"paths": {
"*": ["types/*"],
"@/*": ["*"]
},
"rootDir": "./packages",
"sourceMap": true,
"declaration": true,
"noUnusedParameters": false,
"exactOptionalPropertyTypes": false
},
"ts-node": {
"esm": true
}
}
/packages/api-gateway/tsconfig.json
{
"extends":"../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
},
"include": ["**/*.ts"],
"exclude": ["node_modules", "dist"]
}
/packages/api-gateway/pakage.json
{
"name": "@boilerplate/api-gateway",
"version": "1.0.0",
"main": "dist/main.js",
"type": "module",
"devDependencies": {
"@types/express": "^4.17.21"
},
"scripts": {
"clean": "rm -rf dist",
"build": "yarn clean && tsc --build",
"debug": "nodemon --inspect src/index",
"dev": "nodemon src/index.ts",
"prod": "NODE_ENV=prod pm2-runtime dist/index.js",
"test": "echo TODO && exit 1"
},
"nodemonConfig": {
"env": {
"NODE_ENV": "development"
},
"execMap": {
"js": "babel-node"
},
"ext": "ts,js,json",
"verbose": true,
"watch": [
"src"
]
},
"babel": {
"plugins": [
[
"@babel/transform-runtime"
],
"@babel/plugin-proposal-class-properties"
],
"presets": [
"@babel/preset-env"
]
},
"dependencies": {
"@types/jsonwebtoken": "^9.0.5",
"@types/lodash": "^4.14.202",
"@types/passport": "^1.0.16",
"@types/passport-jwt": "^4.0.1",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.2",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1"
}
}
If I fix PM2 problem then typescript throws an error and if typescript errors are fixed then build fails with error mentioned at start.
How can I solve this issue so that PM2 runs fine with or without .ts extensions? Or is there better approach to do this?