I've distilled this issue down to a simple test. I'm using the node "config" module to define configuration values for my app. Pkg doesn't complain on build, but barfs at runtime with the following message. Am I missing something?
jim-macbookpro:~/development/node/pkgtest$ ./pkgtest-macos
pkg/prelude/bootstrap.js:1172
throw error;
^
Error: Cannot find module 'config'
1) If you want to compile the package/file into executable, please pay attention to compilation warnings and specify a literal in 'require' call. 2) If you don't want to compile the package/file into executable and want to 'require' it from filesystem (likely plugin), specify an absolute path in 'require' call using process.cwd() or process.execPath.
at Function.Module._resolveFilename (module.js:540:15)
at Function.Module._resolveFilename (pkg/prelude/bootstrap.js:1269:46)
at Function.Module._load (module.js:470:25)
at Module.require (module.js:583:17)
at Module.require (pkg/prelude/bootstrap.js:1153:31)
at require (internal/module.js:11:18)
at Object.<anonymous> (/snapshot/pkgtest/index.js:1:78)
at Module._compile (pkg/prelude/bootstrap.js:1243:22)
at Object.Module._extensions..js (module.js:650:10)
at Module.load (module.js:558:32)
index.js is simple:
const config = require('config');
console.log('yo:', config.message);
and I have a default.json in the local 'config' directory:
{
"message": "whodapunk?"
}
My package.json, for what it's worth:
{
"name": "pkgtest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"config": "^1.30.0"
},
"bin": "index.js"
}
I had the same issue and it was because my config file was added to .gitignore -- as soon as I removed it from there it worked like a charm!
I just had the same issue. However not a really beautiful solution I managed to find a way to work around it.
When calling pkg I do not set e NODE_ENV. Then in my entry point I check if a NODE_ENV is set. If not I define the variables I need there.
let port = null;
let db = null;
let name = null;
if (process.env.NODE_ENV) {
const config = require('config');
port = config.get('port');
db = config.get('database');
name = config.get('name');
} else {
port = 3000;
db = 'mongodb://localhost:27017/production';
name = 'Server Production';
}
I tried linking directly to the config module but after that it started complaining that it could not find and files in my config folder. This worked for me as a work around.
Related
Pasted below is a node:buffer error that I've received when using a link to a local route in nextjs. Anyone know how to solve this?
I see: https://github.com/vercel/next.js/discussions/33982
thanks!
node:buffer
Module build failed: UnhandledSchemeError: Reading from "node:buffer" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.
So I had this problem too - the discussion above links you to file-type, which is where I actually eventually fell on the answer for this.
First of all, I am now using react-app-rewired - this allows me to change the webpack config without ejecting your project. That's the first thing to install. There are other packages that will do this too and some people are concerned that this rewired package is only 'lightly' maintained by the community.
You then need to create in the root of your project a file called 'config-overrides.js'
This is what I have inside my file. It covers a few things other than node:buffer because I need other things too (like fs and stream). I'm sure you can modify it as you need:
const webpack = require("webpack");
module.exports = function override(config, env) {
config.resolve.fallback = {
url: require.resolve("url"),
fs: require.resolve("graceful-fs"),
buffer: require.resolve("buffer"),
stream: require.resolve("stream-browserify"),
};
config.plugins.push(
new webpack.ProvidePlugin({
process: "process/browser",
Buffer: ["buffer", "Buffer"],
}),
new webpack.NormalModuleReplacementPlugin(/node:/, (resource) => {
const mod = resource.request.replace(/^node:/, "");
switch (mod) {
case "buffer":
resource.request = "buffer";
break;
case "stream":
resource.request = "readable-stream";
break;
default:
throw new Error(`Not found ${mod}`);
}
}),
);
config.ignoreWarnings = [/Failed to parse source map/];
return config;
};
You need to make sure that the packages that you use in that file are installed, e.g.
npm install url graceful-fs buffer stream-browserify --save
After that I changed the 'scripts' area in my package.json to be as follows:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"eject": "react-scripts eject"
}
My package then compiled correctly and ran fine.
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");
Background
I am currently in the process of migrating the backend of my project to ES6 via babel and am running into an error that seems to be related to a short-hand assignment that is not working anymore? I am not familiar with babel. Might be that I am not seeing something super obvious here.
Problem
now when trying to run my app in dev via yarn start I am seeing the following error (simplified example) this did work prior to setting up babel (I am on node.js 13.13.0). Any idea what's going on here?
Codesnippet:
const a = {
hi:1, bye:2, ciao: 3
}
const b = {hi, bye} = a
console.log(b)
Errormessage:
[nodemon] restarting due to changes...
[nodemon] starting `NODE_ENV=development babel-node server.js server.js`
/Users/user/Projects/fb/fb-flow-app/server/config/config.js:21
var b = (_a = a, hi = _a.hi, bye = _a.bye, _a);
^
ReferenceError: hi is not defined
at Object.<anonymous> (/Users/user/Projects/fb/fb-flow-app/server/config/config.js:12:8)
at Module._compile (internal/modules/cjs/loader.js:1123:30)
at Module._compile (/Users/user/Projects/fb/fb-flow-app/server/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:1143:10)
at Object.newLoader [as .js] (/Users/user/Projects/fb/fb-flow-app/server/node_modules/pirates/lib/index.js:104:7)
at Module.load (internal/modules/cjs/loader.js:972:32)
at Function.Module._load (internal/modules/cjs/loader.js:872:14)
at Module.require (internal/modules/cjs/loader.js:1012:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (/Users/user/Projects/fb/fb-flow-app/server/server.js:1:14)
[nodemon] app crashed - waiting for file changes before starting...
High-level project structure:
root
|-frontend
|-server
The frontend is a next.js project and has it's own .babelrc which seems to be working.
Steps taken so far
I've installed a couple of babel-dev-dependencies (in my server folder):
"devDependencies": {
"#babel/cli": "^7.10.1",
"#babel/core": "^7.10.2",
"#babel/node": "^7.10.1",
"#babel/preset-env": "^7.10.2",
...
}
and also tried (with no result)
#babel/plugin-transform-shorthand-properties
#babel/plugin-transform-spread
I've configured my nodemon.json:
{
"watch": ["../server"],
"exec": "NODE_ENV=development babel-node server.js",
"ext": "js"
}
I've set up a .babelrc
{
"presets": ["#babel/preset-env"]
}
And then I am running via:
"scripts": {
"start": "concurrently --prefix none \"cd server && NODE_ENV=development yarn nodemon server.js\" \"cd frontend && yarn dev\""
},
When you do the following:
const a = {
hi:1, bye:2, ciao: 3
}
const b = {hi, bye} = a
Babel sees an assignment to two variables, named hi and bye that don't yet exist. It seems that Babel is operating in strict mode where this is an error. You'll get the same in Node while in strict mode. Solve this by defining them explicitly:
const a = {
hi:1, bye:2, ciao: 3
}
let hi, bye;
const b = {hi, bye} = a
Destructuring does not make an object, despite it looking like an object initialization.
Note how, because of that, the value of b is not an object that looks like {hi:1, bye:2} but a reference to a, just like what would happen if you just do const b = a:
const b = a;
a.hi = 5;
console.log(b.hi); // 5
Other things you can do:
const {hi, bye} = a; to get two const variables named hi and bye (rather than var or let)
const {hi: b, bye: c} = a; to get two variables named b and
c ("renaming")
const {hi, bye} = a; const b = {hi, bye}; to make an object with just those two keys in variable b, but this will also create variables hi and bye.
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)
I'm relatively new to node and am having issues trying to mock request using jest.
If my file to be tested has require('request'), and I try to run npm test, I get this error:
FAIL __tests__/sum-test.js (0.291s)
● sum › it adds 1 + 2 to equal 3
- TypeError: The super constructor to `inherits` must have a prototype.
at Object.exports.inherits (util.js:756:11)
at Object.<anonymous> (node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js:44:6)
at Object.<anonymous> (node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/utils.js:16:18)
Here's my package.json, if that helps:
{
"name": "jesttest",
"version": "1.0.0",
"scripts": {
"test": "jest"
},
"devDependencies": {
"jest-cli": "^12.0.2"
},
"dependencies": {
"request": "^2.72.0"
}
}
Anyone know why this might be happening?
add jest.unmock('request') in your test file.
Jest will mock a fake require object when you require something in your file.In this situation, request is not the real request.So tell jext not mock request.