Worker threads with ts-node - node.js

I am planning to have worker threads for socket.io rooms. I create a worker thread on the first connection to a room which then sets up firebase listeners.
Unfortunately. I have common imports in the worker file and my main source code.
I followed this article to allow running ts files via worker_threads -> https://wanago.io/2019/05/06/node-js-typescript-12-worker-threads/
Unfortunately, I dont get top-level await and upon starting the worker thread, I get the following error.
error TS2451: Cannot redeclare block-scoped variable 'tslib_1'.\r\n"
Here is my tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"lib": ["esnext"],
"module": "commonjs",
"importHelpers": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"baseUrl": ".",
"sourceMap": true,
"declaration": false,
"noImplicitAny": false,
},
"files": [
"typings.d.ts"
],
}

You haven't provided any info on how you run your application, so I will suppose the following setup:
you run your main application by requiring ts-node on command line:
node -r ts-node/register index.ts
your worker entry point is a .ts file, you instantiate it as follows:
new Worker('./worker.ts')
you have the following code near the top of your worker script:
require('ts-node').register();
Assuming this is your setup, you need to remove the line
require('ts-node').register();
from your worker entry point script. This line is basically causing your TypeScript file to be compiled twice by ts-node, hence the double declaration error for tslib_1.
Registering ts-node manually like above is only necessary, when your main program wan't started with the -r ts-node/register flag. If it was, then ts-node will be automatically required when you instantiate your worker and will compile the requested TS sources on-the-fly.
There are a few other gotchas that you have to keep in mind when using workers:
The new Worker(...) API resolves the requested file relatively to your working directory, if you want to resolve relatively to the current souce file you'll need to do something like this: new Worker(path.resolve(__dirname, './worker.ts')).
If you don't use ts-node in production and instead compile your sources via tsc, you won't be able to load the worker script after your sources are compiled to JS, your worker file will become worker.js (mind the file extension). You'll need to detect this situation and change the path accordingly.

Related

How to stop typescript compiling files *above* `../` the current src dir?

I am developing a package within a larger project, but compiling the package also tries to run all tests from further up the hierarchy. Is there any way to stop this?
app
node_modules
packages/
mypackage/
src/
when I run tsc inside mypackage it will look for files above, all the way to my home directory.
Now, I can compile and build outside my app, and all is good, but for reasons of distribution I wanted to compile things directly inside.
I tried with rootDir and exclude but to no avail.
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"declaration": true,
"outDir": "./dist",
"strict": true,
"rootDir": "./src",
},
"include": [
"./src"
],
"exclude": [
"../../../node_modules",
"node_modules",
"**/node_modules/**",
]
}
the errors look like this:
../../../node_modules/#types/jest/index.d.ts:43:13
43 declare var xit: jest.It;
~~~
'xit' was also declared here.
Found 7 errors in the same file, starting at: ../../../node_modules/#types/mocha/index.d.ts:2642
update found this issue, but not sure if there is a solution. Letting tsc pull in random files from throughout your directory tree, outside the current .src, seems really dangerous behavior to allow TS to do.
https://github.com/microsoft/TypeScript/issues/9858
similar

Typescript/Node Error [ERR_MODULE_NOT_FOUND]: Cannot find module

Converting Project form CJS to ESM
I am attempting to convert my current TypeScript-Node project from ESM to CJS, however, I keep getting the error below
Error [ERR_MODULE_NOT_FOUND]: Cannot find module` 'redacted/dist/config/datadog'
imported from /redacted/dist/app.js
This is what the import looks like in app.ts:
import './config/datadog';
And this is what it looks like for app.js
import './config/datadog';
Here is my datadog.ts document
datadog.ts
import tracer from 'dd-trace';
tracer.init({
logInjection: true,
profiling: true,
appsec: true
});
export default tracer;
Here is the full printout of the error I am recieving when I execute the app via ~/$ node dist/app.js.
> node dist/app.js
node:internal/errors:465
ErrorCaptureStackTrace(err);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'redacted/dist/config/datadog' imported from /redacted/dist/app.js
at new NodeError (node:internal/errors:372:5)
at finalizeResolution (node:internal/modules/esm/resolve:405:11)
at moduleResolve (node:internal/modules/esm/resolve:966:10)
at defaultResolve (node:internal/modules/esm/resolve:1176:11)
at ESMLoader.resolve (node:internal/modules/esm/loader:605:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:318:18)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
at link (node:internal/modules/esm/module_job:78:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
Node.js v18.0.0
Process finished with exit code 1
It works fine When running using ts-node
node --experimental-specifier-resolution=node --loader ts-node/esm app.ts --project tsconfig.json
I have configured my tsconfig.json file like this:
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"lib": ["ES2020"],
"moduleResolution": "node",
"esModuleInterop": true,
"rootDir": "./src",
"outDir": "./dist",
"forceConsistentCasingInFileNames": true,
"strict": true,
}
}
Edit
I've posted the code on GitHub
Your need to use TypeScript v4.7 which is currently the TS-Next Version
Once you upgrade to typescript#next which can be done by executing the command ~/$ npm install -D typescript#next, you will need to make the changes below to your tsconfig.json file.
{
"compilerOptions": {
"lib": [
"ESNext" /* ESNext includes new Level-4 features that were
recently added to the ECMA-262 JS spec */
],
"module": "NodeNext",/* (1 of 2) TS v4.7 settings you need
to change */
"moduleResolution": "NodeNext", /* This is the one that will
specifically solve the error you're
getting. Without the internal changes
made by this, your project will not
resolve modules correctly. */
"esModuleInterop": true, /* This is properly configured. FYI you cannot
change this, it must be set to true. */
/*
THE REST OF THE SETTINGS DO NOT AFFECT THE MODULE TYPE OR HOW TSC
RESOLVES OTHER MODULES */
"target": "ES2021",
"rootDir": "./src",
"outDir": "./dist",
"forceConsistentCasingInFileNames": true,
"strict": true,
}
}
To Summarize
You must set the tsconfig.json keys module and moduleResolution as they are shown below.
`moduleResolution: "NodeNext"
module: "NodeNext"
You will need TypeScript v4.7
Personally I keep a global property, so below I show the command for the global install, but all you really need is to add it to your node_modules dir it as a dependency for your current project.
~$ sudo npm i -g typescript#next // Global Install
~$ npm i -D typescript#next // Add as a Project Dependency
I can't help with ever IDE in existance, but if you use VSCode, use the following configuration so your project uses the ver v4.7.
Then you need to set the following configuration
"typescript.tsdk": "./node_modules/typescript/lib",
package.json
You also need to enable ESM in for Node.. To do this you need to add the following to your package.json
/** #file "package.json" */
{
"type": "module"
}
...OR YOU CAN use the dot MTS (.mts) file extension for all of your files. There are advantages to both, but discussing the advantages is beyond the scope of this answer.
That should be it. It sounds hard but its actually easy once you have done it before.
For another helpful source:
The answer at this LINK covers this same subject with a bit more detail. I really suggest you check it out.

How to specify the distributable directory visible for both NPM and TypeScript? (Multiple files case)

The library written in TypeScript includes three main files for distribution:
NodeJS.js - for, obviously, Node.js runtime.
BroswerJS.js - for, obviously, browser runtime.
index.js - common functionality for both browser and Node.js
There no "main" file in this library so I has not specified this property in package.json.
Planning usage:
import { isUndefined, isNull } from "package-name;
import { delegateClickEventHandling } from "package-name/BrowserJS;
import { NodeJS_Timer } from "package-name/NodeJS;
Currently, the TypeScript with below config compiles files below Source directory to Distributable directory:
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"moduleResolution": "Node",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"removeComments": true,
"outDir": "Distributable/",
"declaration": true
},
"include": [ "Source/**/*" ]
}
If to publish the library such as, TypeScript even will not see it:
import { isUndefined } from "package-name";
TS2307: Cannot find module 'package-name' or its corresponding type declarations.
Because as default TypeScript expecting that .d.ts files will be in root directory of the library. But the distributables are in Distributable directory!
And of course, isUndefined will not be found. I know about "main" property in package.json, but it is for one file case, but what about directory?
I know that multiple distributable files exporting is the supported scenario. For example the mysql2 exporting promise.ts besides index.js:
import MySQL from "mysql2";
import MySQL_Promise from "mysql2/promise";
Update
The NPM part solved - modern solution is exports filed in package.json:
"exports": {
".": "./Distributable/index.js",
"./NodeJS": "./Distributable/NodeJS.js",
"./BrowserJS": "./Distributable/BrowserJS.js"
},
But distribution files are still invisible for TypeScript.
TS2307: Cannot find module 'package-name' or its corresponding type declarations.
I learned about "types" field of package.json. Unfortunately, it could be only a string. It means currently it's impossible to specify multiple files. The issue about making in to array has been declined.
But how to make visible all of "./Distributable/index.js", "./Distributable/NodeJS.js", "./Distributable/BrowserJS.js" for TypeScript?
Please don't suggest me again to make all imports to single entry point. In this question we considering the multiple entry points case.
I am not entirely sure what you are trying to achive, in TS generally when you have single project with 1 configuration file, and you emit multiple files from it, you would not use package name within the same project, use path instead './someFileName'.
If you have multiple projects (tsconfig files) to manage different directories - sort of monorepo thing going on.
Your best options is project references: https://www.typescriptlang.org/docs/handbook/project-references.html
Or if you are doing something else then this may help altho I'd do this as last resort :-)
https://www.typescriptlang.org/tsconfig#paths

Why does `allowJS` cause an unwanted `src` subdirectory in my compiled output?

I'm converting a legacy node/express codebase to TypeScript, following the Microsoft TypeScript starter as a starting reference.
In this reference output is compiled to dist, however when enabling allowJS in tsconfig.json, the output is emitted to dist/src - why is that?
Here is my tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"moduleResolution": "node",
"sourceMap": true,
"rootDir" : "./",
"outDir": "dist",
"baseUrl": ".",
"allowJs": true,
"paths": {
"*": [
"node_modules/*",
"src/types/*"
]
}
},
"include": [
"src/**/*"
]
}
I tried changing rootDir to ./src but it gives an error saying 'node_modules/someModule' is not in the src root.
I tried moving tsconfig.json to src, according to a GitHub issue I saw, but no output was generated.
AllowJS
The output was mapping correctly under /dist until allowJS flag was turned on in tsconfig.json, after which output appeared in /dist/src
There are two things going on here:
Typescript relies on rootDir to decide the directory structure of the output (see this comment from Typescript's bossman).
Only code within the rootDir can be compiled/emitted by tsc.
If you don't set rootDir explicitly, it defaults to ./ (relative to tsconfig)... unless you've included something outside of ./ that needs to be compiled/emitted by tsc, in which case it forces rootDir to automatically get set to the directory that contains all the source.
The allowJS setting tells tsc to treat .js code as source and to also emit it to the outDir.
I suspect that when you enabled allowJS, there was .js code outside of src that tsc now had to emit to outDir, and so it automatically moved rootDir one level up. Since src is now a subdir of the rootDir, this gets mirrored within outDir.
See this answer for a solution that enables you to have src remain a rootDir and also include code from outside of it.
Sounds like your compiler (TSC) config file may be up a level from where you want the transpiler to begin the linking process. Can you try pushing it down a level and let us know what happens?
Hope this helps.

How to debug TypeScript in WebStorm Node.js Remote Debug?

I have a TypeScript Node.js Restify app running inside Docker container. I can connect the WebStorm Node.js Remote Debugger, but I can only debug the compiled JS files and not the TS files.
In the tsconfig.json I have "sourceMap": true set.
Is there anything I am missing?
I have found a solution using ts-node there are a few steps that you should do for doing it.
First, you must add "esModuleInterop": true and "sourceMap": true to your tsconfig.json
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}
After that, you should install the ts-node package.
npm i -D ts-node
The last step is adding to edit the Run/Debug Configurations of the WebStorm.
Go to Run/Debug Configurations window.
Add new Node.js configuration using the +.
Change the Node parameters to --require ts-node/register
Then, change the Javascript file to your Typescript file, for me it is: src/app.ts
Press the OK button.
Run this configuration as dubug.
What run confoguration do you use - Node.js Remote? Remote debugging with sourcemaps only works if sources are inlined (inlineSources=true in tsconfig.json)
I've had a similar issue, #lena answer didn't work for me either, but I solved the problem by adding "inlineSourceMap": true to the compilerOptions of my tsconfig.json.

Resources