Error: Cannot find module 'build/addon.node' - node.js

I am trying to import a module using a non-relative import but it's not working:
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"suppressImplicitAnyIndexErrors": true,
"rootDir": ".",
"outDir": "build/js",
"baseUrl": "."
// "paths": {
// "#build/*": ["./build/*"]
// }
},
"exclude": ["node_modules", "build-releases", "addons"]
}
Code:
// const addon = require('../../../build/addon.node');
const addon = require('build/addon.node');
const debug = true;
export { addon, debug };
The commented code works but the non-commented require does not.
This error outputs:
App threw an error during load
Error: Cannot find module 'build/addon.node'
Require stack:
- /Users/name/Desktop/workspace/proj/build/js/vapp/globals.js
Dir structure:
tree build/
build/
├── addon.node
└── js
└── vapp
├── client.js
├── client.js.map
├── globals.js
├── globals.js.map
├── index.js
├── index.js.map
├── utils.js
└── utils.js.map
(build is in CWD)
TypeScript docs say:
A relative import is one that starts with /, ./ or ../.
Any other import is considered non-relative.
Setting baseUrl informs the compiler where to find modules. All module imports with non-relative names are assumed to be relative to the baseUrl.
Question: Is this because TypeScript is not responsible for module resolution with a require? As in, it's a node related things vs. a TypeScript thing?
Edit
I tried running tsc --traceResolution and found no information about my require trying to import addon.node. That made me realize: TypeScript is likely not responsible for module resolution here, NodeJS is. It doesn't look like you can easily change the baseURL dir for NodeJS and I'd have to use something like Webpack if I wanted to transpile with different, aliased paths.

Related

module resolution from 'dist' folder

I'm working on a nodeJs/Typescript app and I would like to be able to launch it from the dist/ folder.
The structure of each src and dist folders is something like that :
server/
|---dist/
| |---server/
| |---src/
| |---index.js
| |---utils/
| |---connection.js
|---src/
| |---index.ts
| |---utils/
| |---connection.ts
|
|---package.json
|---tsconfig.json
This dist folder is the generated code, with this path being configured using outDir inside of my tsconfig.json file.
I have also configured the main property in my package.json to be dist/server/src/index.js and the type property to be module
In this project, I am using Typescript 4.0.5
I have specified paths property in my tsconfig.json to be "utils/*" : ["src/utils/*"], the baseUrl property to be './' and the property moduleResolution strategy to be node
Now this is my issue. I would like to be able to import my modules the same way i do in my source code, but this time directly from the dist folder, like this :
import createConnection from 'utils/connexion';
However, when i hover the import declaration in VScode, it does not seems to resolve the module and i get an error Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'utils' imported from /home/maxime/Dev/JeuxDuPlacard/packages/server/dist/server/src/index.js
When i do the same operation from my Typescript files, it works as expected.
The paths of the files in the dist folder is the same in the Server folder. If the problem comes form the module resolution, Is there a way to persist the paths aliases in the dist folder (without installing a third party library) ?
{
"compilerOptions": {
"esModuleInterop": true,
"target": "es2020",
"moduleResolution": "node",
"sourceMap": true,
"baseUrl": "./",
"outDir": "dist",
"strict": true,
"lib": ["ES2017", "ES2020"],
"types": [
"node"
],
"allowSyntheticDefaultImports": true,
"noImplicitAny": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"incremental": true,
"skipLibCheck": true,
"strictPropertyInitialization": false,
"paths": {
"utils/*": ["src/utils/*"]
}
}
}
Thanks
That's right, because you CAN'T import files from outside your workdir. What you could do, is you could link a local module and access it as you would any other npm package.
npm link (in package dir)
npm link [<#scope>/]<pkg>[#<version>]
alias: npm ln
https://docs.npmjs.com/cli/v6/commands/npm-link

Exporting Global Styles with Font Assets from a TypeScript->CommonJS module

I have a TypeScript React project organized as follows:
tsconfig.json
package.json
yarn.lock
lerna.json
node_modules/
packages/
ui-library/
package.json
tsconfig.json
typings.d.ts
src/
fonts/
myfont.ttf
components/
GlobalStyle.tsx
lib/ <-- `tsc` builds to here
web-app/
package.json
src/
components/
The web-app imports the ui-library as a commonjs module in its package.json. This is managed through Yarn Workspaces, hence node_modules being at the root instead of each folder. At one point, the web-app imports GlobalStyle from the ui-lib, which is where the issue occurs.
Error: Cannot find module '../fonts/myfont.ttf'
Require stack:
- /Users/me/sources/myproject/packages/ui-library/lib/styles/GlobalStyle.js...
Here is the original import statement from ui-library/src/GlobalStyle.tsx that causes the issue:
import myFont from "../fonts/myfont.ttf";
const GlobalStyle = () => (
<style global jsx>{`
#font-face {
font-family: "My font family";
src: url(${myFont}) format("truetype");
}
...</style>);
The issue is the require statement in the emitted GlobalStyle.js code, built when I run tsc in the ui-lib folder:
const MYFONT_ttf_1 = __importDefault(require("./myfont.ttf"));
I googled this issue online, and I found you had to add typings for compiling .ttf and other abnormal imports. So I created a typings.d.ts file with this declaration:
declare module "*.ttf" {
const value: string;
export default value;
}
And I included it on ui-library/tsconfig.json as follows:
{
"extends": "../../tsconfig.json",
"exclude": ["lib"],
"include": ["src"],
"files": ["./typings.d.ts"],
"compilerOptions": {
"baseUrl": "src",
"outDir": "lib",
"declaration": true,
"declarationMap": true,
"noEmit": false
}
}
The tsconfig above extends the root tsconfig:
{
"files": ["./typings.d.ts"],
"compilerOptions": {
"module": "commonjs",
"target": "es2019",
"lib": ["dom", "es2019"],
"strict": true,
"jsx": "react",
"moduleResolution": "node",
"isolatedModules": true,
"esModuleInterop": true,
"noUnusedLocals": false,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true,
"sourceMap": true,
"noEmit": true,
"declaration": false
},
"exclude": ["node_modules"]
}
We are using TypeScript 3.8. Let me know if there is any additional info to provide. My hunch is that I am either using the wrong module/target, or fundamentally misunderstanding some aspect of this.
More Details
I should note the reason we are using CommonJS modules is because ts-node can only work with that. We pull in ts-node when we are doing our gatsby build, following the gist here in gatsby-config.js:
require("ts-node").register();
// Use a TypeScript version of gatsby-config.js.
module.exports = require("./gatsby-config.ts");
Maybe it's an impossible problem to solve, to get fonts imported through ts-node which is a server side environment? Confused on what the right approach is to export a module with fonts. Willing to get rid of ts-node, and leave the Gatsby config files as js.. but mostly just want to be able to import my fonts.
I solved this by just copying the fonts as part of build steps. Basically, fonts have their own pipeline. There may be better ways, but this works well enough.

importing class in Node js with typescript

I would import class in nodejs and use it in app.ts
var nano = require("nano");
import { EnvConfig } from './envConfig.service';
let config = new EnvConfig();
const dbCredentials: any = config.appEnv.getServiceCreds('dataservices');
export const nanodb = nano({
url: dbCredentials.url,
});
export const nanodbCockpitLight = nanodb.use('data');
console.log(dbCredentials);
When I try to compile I get this error.
import { EnvConfig } from './envConfig.service';
^
SyntaxError: Unexpected token {
I have created the tsconfig file :
{
"compilerOptions": {
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"allowSyntheticDefaultImports": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"allowJs": true,
"outDir": "./dist",
//"baseUrl": "src" // Attention !! nécessite l'utilisation d'un loader de module node pour fonctionner sur node
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}
I get this warning
No inputs were found in config file 'c:/Users/EHHD05911.COMMUN/Documents/cockpitLight/DB mananger/tsconfig.json'. Specified 'include' paths were '["src//"]' and 'exclude' paths were '["node_modules","/.spec.ts"]'
You cannot run node app.ts file directly that won't work
You need transpiler like babel js or typescript compiler tsc so first transpile to js file and then run node app.js
You're using .js extension, you need .ts extension, e.g.: app.ts instead of app.js.
Make sure you have typescript either in npm global or in dev dependencies.
I suspect whatever you're importing has typescript syntax (strong typing and such), and so running node directly won't work. You need to run tsc first, which will transpile everything to javascript in a dist folder, and then run node dist/app.js.
This is a bit cumbersome though, which is why there is ts-node. It's exactly what it sounds like, a node REPL for typescript. You should be able to run ts-node src/app.ts.
import { something } is a typescript syntax, it won't work in a .js file. That is a separate language. Try using require instead.
Use babel js which is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.
package.json
"dependencies": {
"#babel/polyfill": "^7.0.0",
}
"babel": {
"presets": [
"#babel/preset-env"
]
},
"scripts": {
"start": "server.js --exec babel-node",
}
https://babeljs.io/docs
This will enable/resolve your import statements.

How do I compile my TypeScript code for Node.js to one file?

I want to compile TypeScript to one file when using with Node.js.
I have tried configuring "tsconfig.json" like this:
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": false,
"sourceMap": false,
"outFile": "./app/index.js",
"pretty": true,
"types": [
"node"
]
}",
...but when I try with module set to "commonjs", I get the error:
error TS6082: Only 'amd' and 'system' modules are supported alongside --outFile.
If I change it to "module": "system", I get this error when running the file in node:
ReferenceError: System is not defined
If I change module to "amd", I get this error when running the file in node:
ReferenceError: define is not defined
It is not possible to bundle Node.js modules into a single file with the TypeScript compiler alone: each file in the CommonJS module system (used by Node.js) is treated as a single module, and cannot be joined together without proper module bundling techniques found in the many JavaScript code bundlers out there (such as Browserify, Webpack, Rollup, Parceljs, ...).
Other module systems such as SystemJS do not have this limitation, and module definitions can be concatenated into a single file using just the TypeScript compiler: tsc ... --outfile bundle.js -module system. However, they are not supported by Node.js on the fly.
For the actual solution, there are two reasonable choices: either configure your project to bundle the solution using a separate tool (Browserify, Webpack, ...), or include an implementation of SystemJS into your Node.js application (instructions here).
I will also end with a side note: consider evaluating whether you really need to bundle your server-sided code. Bundling is typically performed in frontend projects to reduce the size of client-sided resources, although it can be done as well for server applications in resource-efficient scenarios.
#E_net4 is right. Currently, it is not possible to build modules into a single file with the TypeScript compiler alone. This article describes how to do so with webpack where the file structure is:
├── index.js
├── package.json
├── src
│ ├── add-message
│ │ └── index.ts
│ ├── index.ts
│ └── upcase-messages
│ └── index.ts
├── tsconfig.json
└── webpack.config.js
webpack.config.js
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: './src/index.ts',
output: {
filename: 'index.js', // <-- Important
libraryTarget: 'this' // <-- Important
},
target: 'node', // <-- Important
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
transpileOnly: true
}
}
]
},
resolve: {
extensions: [ '.ts', '.tsx', '.js' ]
},
externals: [nodeExternals()] // <-- Important
};
tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "./",
"noImplicitAny": true,
"strictNullChecks": true
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}

How to get VS Code intellisense to search multiple node_modules folders for typescript

I have a node/typescript project structured like so:
- node_modules // => these are loaded npm/package.json
- src
- node_modules // => shared modules for my project, not on npm
- lib.ts
- app.ts
- package.json
I have a secondary node_modules folder for my private packages mainly so I can import them from anywhere in my project and not have to worry about relative paths (as suggested here) on imports.
This works great because instead of import * as lib from '../../lib' or var lib = require('../../lib'), I can import * as lib from 'lib'.
Typescript compiles/loads lib w/o problem, but VS Code intellisense complains that it "cannot find module 'lib'".
FWIW, here is my tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": false,
"emitDecoratorMetadata": false,
"module": "commonjs",
"target": "es2015",
"rootDir": "src"
}
}
I needed to modify the package.json of my lib to include a "typings" property:
{
"name": "lib",
"version": "0.0.1",
"main": "lib.js",
"typings": "lib"
}

Resources