Setting up Typescript with expressjs import error - node.js

I have a folder structure as following
src
--/lib
----/errors
------/notFound.ts
in notFound.ts, I'm exporting this class
export abstract class HttpError extends Error {
abstract statusCode: number;
constructor(message: string) {
super(message);
Object.setPrototypeOf(this, HttpError.prototype);
}
abstract serializeErrors(): { message: string; field?: string }[];
}
export class NotFoundError extends HttpError {
statusCode = 404;
constructor() {
super('Route not found');
Object.setPrototypeOf(this, NotFoundError.prototype);
}
serializeErrors() {
return [{ message: 'The requested route is not Found' }];
}
}
Then in TSconfig.json, I have the path parameter set like this
"paths": {
"#/lib/*" : [
"src/lib/*"
],
"#/routes/*": [
"src/routes/*"
],
"*": [
"node_modules/*"
]
},
When i Import NotFoundError as follows, it results in error
import { NotFoundError } from '#/lib/errors/notFound';
Here's the error.
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:889:15)
at Function.Module._load (internal/modules/cjs/loader.js:745:27)
at Module.require (internal/modules/cjs/loader.js:961:19)
at require (internal/modules/cjs/helpers.js:92:18)
at Object.<anonymous> (/home/tuser/Projects/tpro/src/server/express.ts:5:1)
at Module._compile (internal/modules/cjs/loader.js:1072:14)
at Module._compile (/home/tuser/Projects/tpro/node_modules/source-map-support/source-map-support.js:568:25)
at Module.m._compile (/tmp/ts-node-dev-hook-07042914060113459.js:69:33)
at Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
at require.extensions..jsx.require.extensions..js (/tmp/ts-node-dev-hook-07042914060113459.js:114:20)
[ERROR] 16:40:04 Error: Cannot find module '#/lib/errors/notFound'
I have also tried imports like these
const { NotFoundError } = require('#/lib/errors/notFound')
const NotFoundError = require('#/lib/errors/notFound')
Both result in same error
What am i missing ?

Sorry, I initially wanted to post a comment but I don't have enough rep; instead, I've expanded what I know into a full answer in hopes it helps.
I've recently gone about with setting up Node + TypeScript + Express. The repo I made and was playing around with initially is here, but note that it's undocumented and the auxiliary configs aren't necessarily up to scratch. Also, apologies if the formatting of this answer is really unorthodox, and I hope linking to personal repos is not looked down on.
I'm uncertain if the paths in the tsconfig.json have anything to do with your issue; I've never used them, so I don't know. I would remove them for now.
As a preface, this is an imperfect solution.
For my Node/TypeScript/Express setup I had to do the following:
Set "type": "module" in package.json
Install required packages: > npm install ts-node ts-loader (I'm unsure if both are necessary, I believe they are though)
Add node --es-module-specifier-resolution=node --loader ts-node/esm ./src/server/express.ts (Presuming that express.ts is your entrypoint) as a command to your package.json and check if it works.
With what I understand, this works by specifically invoking ts-node with esm support, and it seems to work on Node 14 LTS and v16.9.1.
The command is rather hacky and will give you warnings about it being an experimental feature. I couldn't find any other solution for myself when (very stubbornly) using ESModules.
I've also used this command to use Webpack with TypeScript and ESM (that is, having a webpack.ts file with ESM imports) to compile TypeScript src files with ESM, as below (in package.json, from here):
"webpack-examples": "node --es-module-specifier-resolution=node --loader ts-node/esm node_modules/webpack-cli/bin/cli.js --config webpack.examples.ts --mode production",

expressjs doesnt support import statements yet. use require for eg const http = require("http");

Related

Nuxt - Node error when I want to import some packages

I use Nuxt, and sometimes, when I want to use some npm packages, I have this error:
SyntaxError
Unexpected token '<'
The stack:
vm.js:102:7
new Script
internal/modules/cjs/loader.js:1114:10
Module._extensions..js
internal/modules/cjs/loader.js:950:32
Module.load
internal/modules/cjs/loader.js:790:14
Module._load
internal/modules/cjs/loader.js:974:19
Module.require
webpack:/external "vue-typeahead-bootstrap":1:
Object.vue-typeahead-bootstrap
webpack/bootstrap:25:
__webpack_require__
pages/account/tabs/addresses.js:693:81
Module../node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./components/address/form/country.vue?vue&type=script&lang=js&
webpack/bootstrap:25:
I have this error for example on this package: vue-typeahead-bootstrap
If I import the package:
import VueTypeaheadBootstrap from ['vue-typeahead-bootstrap'](https://github.com/mattzollinhofer/vue-typeahead-bootstrap)
export default {
components: { VueTypeaheadBootstrap },
}
It throws the error.
Is it because the package is not supported or something ?
You may try to transpile it. https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-build#transpile
Add the package name like this
{
build: {
transpile: [
({ isServer }) => 'vue-typeahead-bootstrap'
]
}
}
As answered here: https://github.com/mattzollinhofer/vue-typeahead-bootstrap/issues/19#issuecomment-645510809

Why node throws the error: Cannot find module * imported from * using type="module" in package.json?

Using svelte-kit generator for the first time today generated a package.json with a "type": "module" in it.
Now I wanna call a postbuild script with:
"scripts": {
"postbuild": "node ./postbuild/index.js",
}
which contains:
const { tailwindExtractor } = require("tailwindcss/lib/lib/purgeUnusedStyles");
...
Because of the new error require is not defined I changed the ./postbuild/index.js file to this:
import { tailwindExtractor } from "tailwindcss/lib/lib/purgeUnusedStyles";
...
but I'm still getting an error calling that file from node:
internal/process/esm_loader.js:74
internalBinding('errors').triggerUncaughtException(
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'C:\kit\node_modules\tailwindcss\lib\lib\purgeUnusedStyles' imported from C:\kit\tools\postbuild\index.js
Did you mean to import tailwindcss/lib/lib/purgeUnusedStyles.js?
at finalizeResolution (internal/modules/esm/resolve.js:276:11)
at moduleResolve (internal/modules/esm/resolve.js:699:10)
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:810:11)
at Loader.resolve (internal/modules/esm/loader.js:86:40)
at Loader.getModuleJob (internal/modules/esm/loader.js:230:28)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:56:40)
at link (internal/modules/esm/module_job.js:55:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
What the heck is going on?
I'm using npm 7.8.0 and node v14.16.0.
I tried also with --experimental-modules: I get the same error!
This is the file I need to import: https://github.com/tailwindlabs/tailwindcss/blob/master/src/lib/purgeUnusedStyles.js

Enabling ECMAScript modules in Node.js [duplicate]

This question already has answers here:
Node.js - SyntaxError: Unexpected token import
(16 answers)
Closed 3 years ago.
I'm experimenting with ECMAScript modules in Node.js 12 but I'm struggling with. Following the official docs just by adding the top-level field "type" with a value of "module" it should be enough to keep using the extension .js in this Node.js version but I can not find why is not working as expected. Am I missing something?
$ node --version
v12.14.1
$ cat package.json
{
"type": "module",
"scripts": {
"start": "node test.js"
}
}
$ npm start
> app# start /usr/src/app
> node test.js
/usr/src/app/test.js:1
import { myFunction } from './module.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Module._compile (internal/modules/cjs/loader.js:891:18)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
at Module.load (internal/modules/cjs/loader.js:811:32)
at Function.Module._load (internal/modules/cjs/loader.js:723:14)
at Function.Module.runMain (internal/modules/cjs/loader.js:1043:10)
at internal/main/run_main_module.js:17:11
$ cat test.js
import { myFunction } from './module.js';
myFunction();
$ cat module.js
function myFunction() {
console.log('hello from module');
}
export { myFunction };
https://nodejs.org/docs/latest-v12.x/api/esm.html#esm_code_import_code_statements
Version 12 docs for that import statement show that you can only import the default export via import ... from ...
So import myFunction from './module.js'; would work if you exported myFunction as export default myFunction;

Cannot find module when importing pure Typescript package

I am trying to import a Typescript class from one of my Node packages and I am getting the following error:
module.js:549
throw err;
^
Error: Cannot find module '#sap/api'
at Function.Module._resolveFilename (module.js:547:15)
at Function.Module._load (module.js:474:25)
In this file:
import { Plugin } from "#sap/api";
new Plugin();
Which imports from this index.ts file:
export { Plugin } from "./src/plugin";
Which refers to "src/plugin.ts":
export class Plugin {
constructor() {}
onLoad() {}
onUnload() {}
onReload() {}
}
When I shift click on the import in VSCode it takes me to the correct file.
What am I doing wrong? I am new to Typescript, so sorry if it is a nooby mistake.

Register Node Module Manually

Question:
I have a project in TypeScript that uses several APIs I don't have access to on my computer (they exist on the web). The code will compile fine locally since I have all the APIs in foo.d.ts files, and so the system knows they exist somewhere.
However, I want to unit test parts of the code with a NodeJS app. I can import the code into node just fine, but whenever I reach code that imports a module from a definition file, I get the following error:
Error: Cannot find module 'messages'
at Function.Module._resolveFilename (module.js:527:15)
at Function.Module._load (module.js:476:23)
at Module.require (module.js:568:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (~/dev/repos/sample_typescript_fail/App.js:3:18)
at Module._compile (module.js:624:30)
at Object.Module._extensions..js (module.js:635:10)
at Module.load (module.js:545:32)
at tryModuleLoad (module.js:508:12)
at Function.Module._load (module.js:500:3)
...
This makes sense, since that code is just defined locally, and does not exist.
Can I manually register modules to NodeJS, like
Registry.register('messages', () => {...});
so that I can compile and test with polyfills?
Here's an example app
package.json
{
"name": "sample_typescript_declare_issue",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"scripts": {
"start": "ts-node index.ts"
},
"author": "",
"license": "MIT"
}
index.ts
import {App} from "./App";
console.log("Starting program");
// How do I fake "import {MessageSender} from "messages";"
// here so that I can run this node app as a test?
let app: App = new App();
console.log("Ending program");
App.ts
import {MessageSender} from "messages";
export class App {
constructor() {
let messageSender: MessageSender = new MessageSender();
messageSender.sendMessage("foo!");
}
}
node_modules/#types/messages/index.d.ts
export = Messages;
export as namespace Messages;
declare module Messages {
class MessageSender {
constructor();
sendMessage(message: any): void;
}
}
Running Example App
Running with npm start gives the error message above.
Running tsc *.tsc compiles just fine.
Other things I've tried
Updating package.json to include a bin:
{
"name": "sample_typescript_declare_issue",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"scripts": {
"start": "ts-node index.ts"
},
"author": "",
"license": "MIT",
"bin": {
"messages": "./polyfills/messages/index.ts"
}
}
As you mentioned, compiling works fine - this is just a question of availability of .d.ts files.
What you want to do is alter module import at runtime, in other words alter the behaviour of the nodejs require function since
import {MessageSender} from "messages";
will be transpiled in javascript (ES6) to something like
const messages_1 = require("messages");
...
messages_1.MessageSender
To modify that behaviour, the first thing that springs to mind is to use the deprecated - but still available - require.extensions object.
When running locally you must first inject something like
require.extensions['.js'] = (module, filename) => {
if (filename === 'messages') {
// then load mock module/polyfill using the passed module object
// see (https://nodejs.org/api/modules.html#modules_the_module_object)
}
};
The doc says there are better alternatives but fails to clearly mention any.
Another possibility is to look at projects like sandboxed-module which should help (I have not tested it)

Resources