Use of alias paths inside a referenced project - node.js

Since TypeScript 3, it is possible to use projects as references within a given project.
I was trying to use such feature on two personal projects I have but it was not working. So I decided to use a given example as a starting point: https://github.com/appzuka/project-references-example
When I launch npm run build, all projects compile successfully. I then decided to modify the tsconfig.json file of package animals to include the support of aliases. The file was modified as such:
{
"extends": "../../tsconfig-base.json",
"compilerOptions": {
"outDir": "lib",
"rootDir": ".",
"baseUrl": ".",
"paths": { "#animals/*": [ "*" ] }
},
"references": [
{ "path": "../core" }
]
}
(baseUrl and paths properties were added inside compilerOptions)
I then modified the first import of dog.tsx file this way:
import { Animal, Size } from #animals/animal;
When I try to build again the main project, it fails. The error is:
ERROR in C:\Users\User\Documents\project-references-example\packages\animals\dog.tsx
[tsl] ERROR in C:\Users\User\Documents\project-references-example\packages\animals\dog.tsx(1,30)
TS2307: Cannot find module '#animals/animal' or its corresponding type declarations.
To make it working, I need to add the alias also on the main project, like this (in tsconfig.json):
"paths": {
"#animals/*": [ "packages/animals/*" ]
}
Is there a possibility to use alias in a referenced project without having to specify such alias in the parent project?
Thank you!

Related

package.json export multiple search paths

I'm building some code in src to dist. I want any top-level files (dist/*.mjs) and any second-level files (dist/*/index.mjs) to be exports:
"exports": {
".": {
"import": "./dist/index.mjs",
"types": "./dist/index.d.ts"
},
"./*": {
"import": "./dist/*.mjs",
"types": "./dist/*.d.ts"
},
"./*": {
"import": "./dist/*/index.mjs",
"types": "./dist/*/index.d.ts"
},
}
The last item for obvious reasons (can't have two identical keys in JSON) does not work correctly. I can get one or the other working, but I'd like it to try one and fallback to the next.
In desperation I tried using an array there but it didn't work. Is there a strategy I can use here that will make this feasible? The build-tooling I am currently stuck with (tsup) doesn't seem to be able to build src/foo.ts into src/foo/index.mjs and I'd rather not write a post-processor to move them around, but I will if I have to.

NX Error for Relative Imports within the Same Project

I'm getting an error when using TS aliased paths within the same project: Projects should use relative imports to import from other files within the same project
I don't want this behavior. Any idea how to disable?
I tried playing with the #nrwl/nx/enforce-module-boundaries option, but it has almost no documentation around its options
// NX doesn't like this line which uses a path to a file within the
// same NX project. It wants me to use relative pathing, which I
// don't want to use
import { fooHandler } from '#handlers/foo';
Had to look through the npm package, but found it by searching for the error text. You can disable it like this from inside of your .eslintrc.json settings:
{
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {
"#nrwl/nx/enforce-module-boundaries": [
"error",
// This is the part you need to add
{ "allowCircularSelfDependency": true }
]
}
}
]
}
For those who are coming here without this getting resolved. (nx monorepo usage)
For lint error:
Projects should use relative imports to import from other files within the same project - eslint rule #nrwl/nx/enforce-module-boundaries fails
Add "allowCircularSelfDependency": true.
"#nrwl/nx/enforce-module-boundaries": [
"error",
{
"allowCircularSelfDependency": true, -> This may solve the lint error.
"allow": ["#account/**"], -> // White list the lint error.
...
}
Whitelist the folders: Add "allow": [#foldername]
"#nrwl/nx/enforce-module-boundaries": [
"error",
{
"allow": ["#account/**"], -> // White list the lint error.
...
}
That should fix it.

Typescript and Subpath Imports

I am trying to get Node subpath imports and typescript to work. My IDE has no problem resolving the imports, but Typescript is never happy.
Github repo with code: https://github.com/doronrosenberg/ts-subpath-imports.
package.json:
"imports": {
"#internal/*": "./internal/*.ts",
"#internal2": "./internal"
}
tsconfig.json:
"paths": {
"#internal/*": "./internal/*.ts",
"#internal2": ["./internal"]
}
and the code:
import { foo } from "#internal/index";
import { bar } from "#internal2";
No matter how I set things up, I always get:
src/test.ts:1:21 - error TS2307: Cannot find module '#internal/index' or its corresponding type declarations.
1 import { foo } from "#internal/index";
~~~~~~~~~~~~~~~~~
src/test.ts:2:21 - error TS2307: Cannot find module '#internal2' or its corresponding type declarations.
2 import { bar } from "#internal2";
~~~~~~~~~~~~
Any ideas?
After hacking around with Typescript for a few weeks, I got a working solution.
Let's say I have a package called #kodadot1/metasquid with multiple submodules (consolidator and entity).
In my package.json I declare imports
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./consolidator": {
"types": "./dist/consolidator.d.ts",
"import": "./dist/consolidator.mjs",
"require": "./dist/consolidator.cjs"
},
"./entity": {
"types": "./dist/entity.d.ts",
"import": "./dist/entity.mjs",
"require": "./dist/entity.cjs"
}
}
The trick is to create a .d.ts file for each submodule in the project's root.
So for submodule entity I will make a file called entity.d.ts that contains
export * from './dist/entity'
Now to publish it correctly in npmjs extend your package.json like:
"files": [
"dist",
"*.d.ts"
]
Now just publish, and you can enjoy subpath imports:
import { get } from '#kodadot1/metasquid/entity'
Whole code is available here
The support of subpath exports requires newer module resolutions such as Node16 and NodeNext:
{
"compilerOptions": {
"moduleResolution": "Node16" // or `"NodeNext"`
}
}

How can I step into library code using the VS Code debugger in a Typescript/Node.js project?

I have a Node.js project written in Typescript with the following dependency:
"dependencies": {
...
"#uniswap/smart-order-router": "^2.5.15",
From this library package I import some stuff in my project:
import { AlphaRouter, ... } from '#uniswap/smart-order-router'
And then use it like this:
const routeToRatioResponse: SwapToRatioResponse = await router.routeToRatio(
token0Balance,
token1Balance,
p,
{
ratioErrorTolerance: new Fraction(5, 100),
maxIterations: 1,
},
{
swapOptions: {
recipient: wallet.address,
slippageTolerance: new Percent(5, 100),
deadline: deadlineValue
},
addLiquidityOptions: {
recipient: wallet.address
}
}
)
I have a breakpoint set on that first line above, at the call to router.routeToRatio(). When using the VS Code debugger, execution stops correctly at that line. But then when I click 'Step Into', I do not step into this function at all but instead go to the line after this whole function call.
The library project is written in Typescript. The code is here: https://github.com/Uniswap/smart-order-router. Note that the tsconfig.json for it has inlineSourceMap as true here: https://github.com/Uniswap/smart-order-router/blob/main/tsconfig.json#L9.
I don't seem to have the TS source for the library project in my node_modules dir. When I Ctrl-click on the function name, VS Code takes me to ./node_modules/#uniswap/smart-order-router/build/main/src/routers/alpha-router/alpha-router.d.ts (which has no implementation code, only a class declaration), not to a file called alpha-router.ts. Digging around under node_modules I seem not to have that file.
This answered question mentions the library project should have the sourceRoot set in the tsconfig.json, which it does not. I do not own the library project though, so I can't change anything there.
(Edit 1) Here's my launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "foo",
"type": "node",
"program": "${workspaceFolder}/foo/src/index.ts",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"preLaunchTask": "tsc: build - foo/tsconfig.json",
"outFiles": [
"${workspaceFolder}/**/*.js"
],
"cwd": "${workspaceFolder}/foo"
}
]
}
(Edit 2): Per the comments so far, I now have the dependencies I'm interested in debugging installed (in the npm install sense) as local folders. package.json looks like this:
"dependencies": {
...
"#uniswap/smart-order-router": "file:../smart-order-router",
...
tsconfig.json has "allowJs" missing. I had to install some of the dependency's dependencies directly in my package.json. The code now builds with tsc without errors (without having to change any paths to imports in the TS sources), but now the debugger is completely broken.
The debugger stops at a breakpoint on the very first line of my index.ts and will step over lines ok for a bit but then execution stops here without any error: node_modules/antlr4ts/index.js
The only thing on the debug console in VSC is:
/home/e/.nvm/versions/node/v14.15.4/bin/node ./node_modules/antlr4ts/index.js

How to add subdirectory module aliases in tsconfig?

I can set module aliases with no issue:
"baseUrl": "./app",
"paths": {
"assets/*": ["assets/*"],
"components/*": ["components/*"],
...
},
This works. However, I (actually my client, who wants to extract some parts of the project as a module in the future) want to create subdirectories as aliases to different paths (assume that all the directories as values exist, and I cannot change the actual directory structure):
"paths": {
"assets/*": ["assets/*"],
"components/*": ["components/*"],
"#myapp/api/*": ["services/myapp/*"],
"#myapp/state/*": ["state/*"],
},
Putting aside whether this is a good pattern/practice or not (as I'm asked to do it this way), is this technically possible without touching the physical directory structure (and without the use of 3rd party dependencies)? (I'm using Typescript 3.4.3 and Vscode 1.33.1)
"baseUrl": "./",
"paths": {
"#myapp/environment": [ "./src/environments/environment" ],
"#myapp/extensions": [ "./src/extensions" ],
"#myapp/testing": [ "./src/testing" ],
"#myapp/constants": [ "./src/app/shared/constants" ],
"#myapp/data": [ "./src/app/data" ],
"#myapp/shared": [ "./src/app/shared" ],
"#myapp/core/*": [ "./src/app/core/*" ],
"#myapp/*": [ "./src/app/*" ]
}
this works like a charm on my project

Resources