issue with path resolved on complex app nestjs based - node.js

I building a boildplate for nestjs and microservices (still work in progress)
now i got an issue that i try to run the app or run the test and it give me this
the code located github link
the issue that on tsconfig.json i added paths
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist/apps",
"baseUrl": "./",
"incremental": true,
"paths": {
"#frontapi/*": ["./apps/front-api/src/*"],
"#config/*": ["./apps/config-server/src/*"],
"#entities/*": ["./apps/entities-server/src/*"],
"#devops/*": ["./apps/devops-mcu/src/*"],
"#tasks/*": ["./apps/task-que-handler/src/*"],
"#logicBus/*": ["./apps/logic-bus/src/*"],
"#common/*": ["./apps/common/*"]
}
},
"exclude": [
"node_modules",
"dist"
]
}
and i run the package json two of the commands for testing:
"start:frontapi": "npm run start:frontapi:env && tsc-watch -p tsconfig.build.json --onSuccess \"node -r tsconfig-paths/register -r ts-node/register --inspect-brk=5858 dist/front-api/src/main.js\"",
and
"test:e2e": "npm run clean&&tsc -p tsconfig.build.json && jest --config ./apps/front-api/test/jest-e2e.json",
and both give me that it dont located #common/config/configuration
and i have no idea what i have missing here and help with this one
Edit there is file called jest-e2e.json this his content
{
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e-spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"moduleNameMapper": {
"^#frontapi/(.*)$": "./apps/front-api/src/$1",
"^#config/(.*)$": "./apps/config-server/src/$1",
"^#entities/(.*)$": "./apps/entities-server/src/$1",
"^#devops/(.*)$": "./apps/devops-mcu/src/$1",
"^#tasks/(.*)$": "./apps/task-que-handler/src/$1",
"^#logicBus/(.*)$": "./apps/logic-bus/src/$1",
"^#common/(.*)$": "./apps/common/$1"
}
}
please let me know if i missing something here or you missing something will do my best to provide

I was facing the same issue.
After taking a look at your project structure, I have some suggestions/observations. I will focus on apps/front-api.
There you have the jest.e2e.json file inside the test directory
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
...,
"moduleNameMapper": {
"^#frontapi/(.*)$": "./apps/front-api/src/$1",
"^#config/(.*)$": "./apps/config-server/src/$1",
"^#entities/(.*)$": "./apps/entities-server/src/$1",
"^#devops/(.*)$": "./apps/devops-mcu/src/$1",
"^#tasks/(.*)$": "./apps/task-que-handler/src/$1",
"^#logicBus/(.*)$": "./apps/logic-bus/src/$1",
"^#common/(.*)$": "./apps/common/$1"
}
}
I'd like to point out that the rootDir: '.' makes reference to the directory the file is in, so in this case rootDir value will be /path/to/your/projectShowCase/backend/apps/front-api/test.
The important thing is that you can use relative paths in the moduleNameMapper. For instance:
"moduleNameMapper": {
"^#frontapi/(.*)$": "<rootDir>/../src/$1",
"^#config/(.*)$": "<rootDir>/../../config-server/src/$1",
...,
"^#common/(.*)$": "<rootDir>/../../common/$1"
}
You just need to map each dependency to its specific path

Related

NodeJS Typescript doesn't convert to relative path

I have Node project with Typescript.
I want to import this module in getToken.ts
import {apiRoot} from '#App/utils/apiRoot';
For absolute path I have a config like this.
tsconfig.json
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"baseUrl": "./",
"paths": {
"#App/*": [ "src/*"]
},
"typeRoots": ["./node_modules/#types", "./src/types"],
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
tsconfig.build.json
{
"extends": "./tsconfig.json",
"exclude": [
"__test__/**/*.spec.ts",
"__test__/**/*.test.ts"
]
}
In package.json
"scripts": {
"dev": "tsc --project tsconfig.build.json && concurrently \"tsc -w\" \"nodemon dist/index.js\"",
},
When I run npm run dev
I got an error
Error: Cannot find module '#App/utils/apiRoot'
I check to build file in dist folder (getToken.js) and I see
const apiRoot_1 = require("#App/utils/apiRoot");
I use same technic and same path for testing with Jest without a problem in same project. How can i solve this problem?

tsconfig problems with test and compiling

This is my tsconfig.json
{
"compilerOptions": {
"noImplicitAny": true,
"declaration": false,
"strict": true,
"strictNullChecks": false,
"target": "ES2019",
"module": "commonjs",
"resolveJsonModule": true,
"allowJs": true,
"checkJs": false,
"outDir": "dist",
"esModuleInterop": true,
"inlineSourceMap": true,
"rootDir": "./",
"baseUrl": "./",
"typeRoots": [
"./node_modules/#types"
],
"paths": {
"#/*": [
"src/*"
]
}
},
"include": [
"src/**/*.ts",
"src/**/*.js",
"src/**/*.json",
"tests/**/*.ts"
],
}
My architecture is as follows:
├── tests
├── src
├── eslint.yml
├── tsconfig.json
├── package.json
The problem with this structure is that in the dist folder it looks like this:
dist
├── tests
├── src
So I could change rootDir to src, problem that the tests folder cannot be outside of src.
What I want is to be able to use typescript in both the tests folder and the src folder. What would be the solution in that case. I've searched in several places and haven't found a solution to my problem.
Maybe some changes might affect eslint, because it imports tsconfig.json
My eslintrc.yml:
env:
es2017: true
node: true
jest: true
extends:
- airbnb-base
- "eslint:recommended"
- "plugin:import/typescript"
parser: "#typescript-eslint/parser"
parserOptions:
ecmaVersion: 2020
sourceType: module
project: "./tsconfig.json"
plugins:
- "#typescript-eslint"
settings:
"import/resolver":
typescript: {}
ignorePatterns:
- "dist/*"
Any idea how to solve this problem?
I would advise you to follow the pattern where tests are put in the same folder as the source files they're testing but with an infix test. It will make your life easier in the long run.
Buuut... given your current needs:
1. Post-process output folder
The simplest solution is to replace your (presumed) build script, in package.json:
{
...
"scripts": {
...
"build": "tsc",
...
},
...
}
with the following, updating the output folder as desired
{
...
"scripts": {
...
"build": "tsc && rm -rf ./dist/tests && mv ./dist/src/* ./dist && rmdir ./dist/src",
...
},
...
}
2. Extend Typescript config
You can also add an extra Typescript config only used by Lint. Set rootDir to ./src and remove the include that involves the tests folder in tsconfig.json and then add the following tsconfig.eslint.json Typescript config:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"rootDir": "./"
},
"include": [
"src/**/*.ts",
"src/**/*.js",
"src/**/*.json",
"tests/**/*.ts"
],
}
Now use this config in your .eslintrc.yml only and it should work since it overrides both the rootDir and the include array.
I would have wished for some other solutions as well but even though you can add a temporary rootDir as a command line option to tsc, it will complain about includes that are outside of the root dir and there is no smooth way to replace the include array on the command line (except for literally lining up all the files to compile which is not an option).
In some project I was really motivated to keep a separate tests folder as you do here, but I remember that in the end, I just fell back to the tests-in-sources pattern instead because of the number of ridiculous configuration problems that I got with this other approach.
Following #fast-reflexes answer and after a lot of research I arrived at the following answer:
On package.json keep using only tsc command to compile:
{
...
"scripts": {
...
"build": "tsc",
...
},
...
}
My tsconfig.json change a little bit.
{
"compilerOptions": {
"noImplicitAny": true,
"declaration": false,
"strict": true,
"strictNullChecks": false,
"target": "ES2019",
"module": "commonjs",
"resolveJsonModule": true,
"allowJs": true,
"checkJs": false,
"outDir": "dist",
"esModuleInterop": true,
"inlineSourceMap": true,
"rootDir": "./src", // this line changed
"baseUrl": "./src", // this line changed
"typeRoots": [
"./node_modules/#types"
],
"paths": {
"#/*": [
"*" // this line changed
]
}
},
"include": [
"src/**/*.ts",
"src/**/*.js",
"src/**/*.json" // remove line related to tests
],
}
Created tsconfig.eslint.json.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"rootDir": "./",
"baseUrl": "./",
"paths": {
"#/*": [
"src/*"
]
}
},
"include": [
"src/**/*.ts",
"src/**/*.js",
"src/**/*.json",
"tests/**/*.spec.ts" // line related to tests
]
}
My eslintrc.yml changed:
env:
es2017: true
node: true
jest: true
extends:
- airbnb-base
- "eslint:recommended"
- "plugin:import/typescript"
parser: "#typescript-eslint/parser"
parserOptions:
ecmaVersion: 2020
sourceType: module
project:
- "./tsconfig.json"
- "./tsconfig.eslint.json" <-- added this file
plugins:
- "#typescript-eslint"
settings:
"import/resolver":
typescript: {}
ignorePatterns:
- ".eslintrc.yml" <-- added this file
- "dist/*"
My architecture is as follows:
├── dist
├── subfolders_without_tests
├── tests
├── tsconfig.json <-- added this file
├── src
├── eslintrc.yml
├── jest.config.js
├── tsconfig.json
├── tsconfig.eslint.json <-- added this file
├── package.json
My jest.config.js:
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig.json');
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/?(*.)+(spec|test).ts'],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/' }),
modulePathIgnorePatterns: ['<rootDir>/dist'],
coveragePathIgnorePatterns: [
'<rootDir>/dist',
],
coverageReporters: ['json', 'lcov', 'text', 'cobertura', 'text-summary'],
moduleDirectories: ['node_modules', 'src'],
collectCoverage: false,
collectCoverageFrom: ['src/**/*.{ts,js,jsx}'],
};
Other related links:
https://github.com/microsoft/vscode/issues/12463#issuecomment-389733188
https://medium.com/#gokulc/configuring-module-resolution-on-typescript-and-jest-b17a93ebf54d
I was with the same problem and found the following solution.
Remove rootDirfrom tsconfig.json
Use the includes property to include src and tests dir
//tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"allowJs": true,
"resolveJsonModule": true,
"outDir": "./dist",
// "rootDir": "./src",
...
},
"include": [
"src/**/*.ts",
"src/**/*.js",
"src/**/*.json",
"tests/**/*.spec.ts"
]
Use swc as the builder tool
//.swcrc
{
"env": {
"targets": {
"node": 16
}
},
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false
}
},
"module": {
"type": "commonjs"
}
}
//package.json
{
...
"scripts": {
...
"build": "swc src -d dist --copy-files"
...
},
...

How to do module resolution in typescript to output for node?

tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"allowJs": false,
"strict": true,
"target": "es6",
"module": "commonjs",
"lib": ["dom", "es6", "es5", "es2017", "esnext.asynciterable"],
"sourceMap": true,
"moduleResolution": "node",
"paths": {
"src/*": ["src/*"]
},
"declaration": true,
"rootDir": "./src",
"outDir": "dist"
},
"exclude": ["dist"],
"include": [ "src"]
}
Original Folder structure
src /
util/
getSomething.ts
index.ts
Output Folder structure
dist /
util/
getSomething.js
index.js
index.ts
import getSomething from 'src/util/getSomething';
package.json script
{
"build": "tsc && tspath -f",
"start": "node dist/index.js"
}
The build works but when I run start I get error.
Is there a way to have a root based module resolution?
I followed this example (just replacing ~ with src) and it is giving me this problem.
Unless there is an alternative solution to tspath.
https://haseebmajid.dev/blog/better-imports-with-babel-tspath
Note: I am using windows 10.
npm start
Error: Cannot find module './src\util\getSomething'
Require stack:
c:\apps\example-typescript-node\dist\index.js
Answered here:
https://github.com/duffman/tspath/issues/33
I have resolved my problem. I had to ensure my rootDir was ./ not src.
Then targeting index.js inside dist/src/ not dist/
tsconfig.json
{
"compilerOptions": {
"rootDir": "./"
}
}
package.json
{
"build": "tsc && tspath -f",
"start": "node dist/src/index.js"
}

How nestjs configures path aliases in a project

I configured the path alias in tsconfig.json of the nestjs project, but there was an error while running.
I tried to configure like Angular, but there was an error in nestjs
This is my tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"paths": {
"~auth/*": ["src/auth/*"]
}
},
"exclude": ["node_modules"]
}
Use it like this
import { userLoginJwt } from '~auth/jwt-names'
Startup error
$ npm run start:dev
[0] internal/modules/cjs/loader.js:584
[0] throw err;
[0] ^
[0]
[0] Error: Cannot find module 'src/auth/jwt-names'
Sorry, I emphasize here that running npm run start works fine, but running npm run start:dev can lead to unexpected situations.
This job, I work:
Modify my 'tsconfig.json'
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./src",
"incremental": true,
"paths": {
"~auth/*": ["auth/*"]
}
},
"exclude": ["node_modules"]
}
Add 'tsconfig-paths-bootstrap.js' file
// tsconfig-paths-bootstrap.js
const tsConfig = require('./tsconfig.json');
const tsConfigPaths = require('tsconfig-paths');
tsConfigPaths.register({
baseUrl: tsConfig.compilerOptions.outDir,
paths: tsConfig.compilerOptions.paths,
});
Modify the 'nodemon.json' file
{
"watch": ["dist"],
"ext": "js",
"exec": "node -r ./tsconfig-paths-bootstrap.js dist/main.js"
}
Use path alias
import { userLoginJwt } from '~auth/jwt-names';
Now executing the npm run start:dev error has disappeared.
src is not an available folder after compilation, as all the code is moved to the dist folder. Rather, what you should do in your tsconfig is set up a baseUrl to point to src and the outDir to point to dist then remove src from your paths. I'd also suggest reading up on Typescript path mapping to get a better understanding of what is happening.
TL;DR;
Update your package.json
"start:dev": "nest start --watch --exec 'node -r tsconfig-paths/register -r ts-node/register ./src/main.ts'"
Use npm run start:dev
Only needs:
"moduleResolution": "node",
"baseUrl": "src",
"paths": {
"#lib/*": ["lib/*"],
"#models/*": ["models/*"],
"#plugins/*": ["plugins/*"],
"#routes/*": ["routes/*"],
"#services/*": ["services/*"],
"#api": ["api/index"]
}
https://medium.com/zero-equals-false/how-to-use-module-path-aliases-in-visual-studio-typescript-and-javascript-e7851df8eeaa
How nestjs configures path aliases in a project
It doesn't you are showing us the tsconfig file - its TS that is declaring the paths
"paths": {
"~auth/*": ["src/auth/*"]
}
would be better if it followed what appears to be a convention of adding # instead of tilda
"paths": {
"#auth/*": ["src/auth/*"]
}
Or just all
"paths": {
"*": [
"./*"
]
},
So thats the path reference sorted... now onto tsconfig-paths for using short paths after compilation. So the above will be good for the TS, but after its been transpiled to JS the paths are no longer referenced as its JS now... which is why it fails with the start command.
You will need to create a bootstrap script like shown in the docs and calling that in your package.json just before the build command.

Jest / Ts-Jest / Babel : Debug Failure. False expression: Output generation failed

With TypeScript 2.8, we have now the possiblity to generate .d.ts only from source files. So my tsconfig.json becomes :
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"target": "es5",
"lib": ["ES6","ES2017","ESNext"],
"downlevelIteration": true,
"moduleResolution": "node",
"declaration": true,
"emitDeclarationOnly": true,
"declarationDir": "./lib"
},
"exclude": [
"node_modules"
],
"include": [
"src/**/*"
],
"strict": true
}
The problem is the build is broken with that (https://travis-ci.org/jy95/mediaScan/jobs/359573738).
My repo : https://github.com/jy95/mediaScan/tree/prettier
Any ideas how to fix it ?
My jest.config.js :
// jest.config.js
module.exports = {
verbose: true,
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testMatch": [
"<rootDir>/__tests__/**/*.(ts|tsx|js)"
],
"testPathIgnorePatterns": ["<rootDir>/node_modules/", "<rootDir>/__tests__/__helpers__/"],
"collectCoverage": true
};
Thanks
I've experienced similar issue when was switching jest to process .js files with ts-jest instead of babel-jest.
Error happens (according to stacktrace) at getConstructorDefinedThisAssignmentTypes in typescript.js. And is most likely caused by incorrect or missing types. Add some breakpoints or log types there/declarations to see what exactly is failing.
You can try to upgrade typescript to the latest version, it might give more valuable error message, and try to tsc --noEmit to see if there are some loose ends with your types.
Also sometimes npx jest --clearCache helps

Resources