Failed to resolve module specifier - javascript

I`m only starting my JS journey and I will be really grateful if you help me to receive data using the JS. I found that info on the alcor exchange site that is the exchange site for wax (gaming crypto currency).
What is on site:
// Code not tested yet, and provided for explanation reason
import fetch from 'node-fetch'
import { Api, JsonRpc, RpcError } from 'eosjs'
const rpc = new JsonRpc('https://wax.greymass.com', { fetch })
// Get buy orderbook from table
const { rows } = await rpc.get_table_rows({
code: 'alcordexmain',
table: 'buyorder',
limit: 1000,
scope: 29, // Market id from /api/markets
key_type: 'i128', // we are using it for getting order sorted by price.
index_position: 2
})
I faced with some trouble because of JSHint version and updated it to 9. But still "await" is red and JSHint is asking for semicolon after it - which causes huge amount of new errors. However the project is opening in the browser with no info of course. But in the console I see an error.
index.html:1 Uncaught TypeError: Failed to resolve module specifier "node-fetch". Relative references must start with either "/", "./", or "../".
P.S. I checked the posts with such error but actually didn't understand what should I do because all of them are proposing some changes for JSON file and I only have index.html and that js. file.

There is a difference between JavaScript in your browser and JavaScript on a server.
JavaScript in a browser is the code that can be injected into HTML (inlined or linked), which is evaluated by the browser.
JavaScript on a server is not related to JavaScript in a browser. The language is the same, but the environment is not. It's like “draw in Paint” and “draw on a real life canvas”. Colors are the same, but everything else is not.
So, what you are trying to do here is to run server-side JavaScript in a browser. That's the real reason you're getting this error.
There are two ways to fix this error.
Probably the one you should go
You should install Node.js, read about npm, init your npm project, put everything into .js file and eval using Node.
In a nutshell, let's say you've already installed Node.js and node -v outputs something in your terminal. Then everything you need to do is:
$ cd path/to/the/directory/you/like
$ npm init -f
$ npm install --save node-fetch eosjs
$ touch index.js
Then edit index.js using your favorite editor, adding there the code you're trying to run.
You may encounter error due to using await on a “top-level”. In this case, put it into an async function:
import fetch from 'node-fetch'
import { Api, JsonRpc, RpcError } from 'eosjs'
const rpc = new JsonRpc('https://wax.greymass.com', { fetch })
(async () => {
const { rows } = await rpc.get_table_rows({
code: 'alcordexmain',
table: 'buyorder',
limit: 1000,
scope: 29, // Market id from /api/markets
key_type: 'i128', // we are using it for getting order sorted by price.
index_position: 2
});
})();
Aaaand, that's it. You do not need to run browser here at all.
Probably the one you should not go, but can
If you need to run your JavaScript in a browser, then you need to either bundle all the deps using a tool like webpack (which still requires you to use Node.js & npm), or you may replace the deps you're trying to use with client-side alternatives.
E.g. instead of requiring node-fetch you may use Fetch API.
What to use instead of eosjs I do not know, but if you decide to use this dependency in a browser, you will at least need to use import maps to tell the browser how to resolve such dependencies. Because, well, the error you've got tells you exactly this: your browser does not know what you're trying to import. Browsers use URLs as import paths, not ids (or “bare names”).

Related

SvelteKit - "ReferenceError: File is not defined"

A quick problem I faced while developing a web-app using SvelteKit (and by extension, Vite):
Inside the <script> tag of my +page.svelte file I tried defining an empty placeholder File object the following way:
let formObject: FormCreationData = {
fileToUpload: new File([], ''),
anotherField: "",
...
};
While it should work in normal JS/TS (and Svelte if you aren't using SvelteKit), it now throws the following error:
ReferenceError: File is not defined
at +page.svelte:13:14
Why is this the case?
Since SvelteKit implements Server-Side Rendering (SSR) - The code that is on the +page.svelte file has to run both on client browsers and the Vite server.
The File class is only available in browsers, so it won't be able to fulfill this requirement (You might know that Node.js offers the fs module in order to allow for file operations instead).
This means that there are two ways to possibly fix this problem:
Disable SSR using the variable ssr in the +page.ts/js file:
export const ssr = false;
Find a way to define the File object at a point where the code runs on the browser (This can be done by checking the browser variable under the $app/environment module, or inside of one of the supported Svelte hooks, such as onMount()).

How to use dynamic import from a dependency in Node.js?

I'm using Node.js (v16) dynamic imports in a project to load plugins using a function loadJsPlugin shown here:
import { pathToFileURL } from 'url';
async function loadJsPlugin(pluginPath) {
const pluginURL = pathToFileURL(pluginPath).toString();
const result = await import(pluginURL);
return result.default;
}
My main program provides absolute paths to the loadJsPlugin function, such as /home/sparky/example/plugins/plugin1.js (Linux) or C:\Users\sparky\example\plugins\plugin1.js (Windows). The pathToFileURL function then converts these absolute paths to URLs like file:///home/sparky/example/plugins/plugin1.js (Linux) or file:///C:/Users/sparky/example/plugins/plugin1.js (Windows).
Loading the plugins this way works fine when the loadJsPlugin function is in the same package as the main program, like this:
import { loadJsPlugin } from './plugin-loader.js';
async function doSomething() {
const plugin = await loadJsPlugin('...'); // works
// use plugin
}
However, if I try to move loadJsPlugin to a separate library and use it from there, it fails with Error: Cannot find module '<url here>'
import { loadJsPlugin } from '#example/plugin-loader';
async function doSomething() {
const plugin = await loadJsPlugin('...'); // error
// use plugin
}
NOTE: the dependency name here is not on NPM, it's on a private repository and there's no problem loading the dependency itself. Also, static ES6 imports in general are working fine in this system.
I looked through Node.js documentation, MDN documentation, and other StackOverflow questions for information about what is allowed or not, or whether dynamic import works differently when in the same package or a dependency, and didn't find anything about this. As far as I can tell, if a relative path or file URL is provided, and the file is found, it should work.
Ruling out file not found:
I can switch back and forth between the two import lines to load the loadJsPlugin function from either ./plugin-loader.js or #example/plugin-loader, give it the same input, and the one in the same package works while the one from the dependency doesn't.
When I test in VS Code, I can hover the mouse over the URL in the Error: Cannot find module 'file:///...' message and the file opens just fine
I can also copy the 'file:///...' URL to a curl command (Linux) or paste it into the address bar of Windows Explorer and it works.
If I try a path that actually doesn't exist, I get a slightly different message Error [ERR_MODULE_NOT_FOUND]: Cannot find module '<path here>', and it shows the absolute path to the file that wasn't found instead of the file URL I provided.
Checking different file locations:
I tried loading plugins that are located in a directory outside the program (the paths shown above like /home/sparky/example/plugins/...); got the results described above
I tried loading plugins that are located in the same directory (or subdirectory) as the main program; same result
I tried loading plugins that are packaged with the dependency in node_modules/#example/plugin-loader; same result (obviously this is not a useful set up but I just wanted to check it)
I'd like to put the plugin loader in a separate library instead of having the same code in every project, but it seems that dynamic import only works from the main package and not from its dependencies.
I'm hoping someone here can explain what is going on, or give me a pointer to what might make this work.

InternalError Metro has encountered an error: While trying to resolve module `child_process`

I am trying to call a function in a python file from a js file, I got this to work through my console, but I am now trying to implement it in a mobile app using expo.
The way I had set this up is, I have the JS file for a certain screen in my app, this then calls a function in a separate JS file, which then calls the function in the python file.
I am using the child_process module to talk to python from JS.
And as I said, this was working before I tried to export the JS function to my screen file.
index.js
export function foo(process, sentence){
const spawn = require("child_process").spawn;
const process = spawn("python3", ["./python.py", sentence]);
...
}
screen.js
*other imports
import { foo } from "./filepath..."
...
But when I run npm start I get the following error:
Failed building JavaScript bundle.
While trying to resolve module `child_process` from file `/Users/mee/Documents/GitHub/project/app/screens/screen.js`, the package `/Users/mee/Documents/GitHub/project/node_modules/child_process/package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`/Users/me/Documents/GitHub/project/node_modules/child_process/app/screens/screen.js`. Indeed, none of these files exist:
How can I fix this?
It won't work for few reasons
child_process is part of the node standard library, it's not available in other environments like react-native or browser
even if above was not true, there is no python3 executable on your phone
python.py file from your local directory wouldn't be even uploaded to the phone because bundler is only uploading one big js file with entire js code combined + assets, python.py is neither of those.
Only solution that make sense it to rewrite that code to javascript.
Technically it's not impossible, there might be a way to do that, by compiling python interpreter for mobile platform, or using some tool that translates python code into js, but it's not something that you should consider.

Single API to load JSON file in Browser and NodeJS?

Is there an existing API or library that can be used to load a JSON file in both the browser and Node?
I'm working on a module that I intend to run both from the command-line in NodeJS, and through the browser. I'm using the latest language features common to both (and don't need to support older browsers), including class keywords and the ES6 import syntax. The class in question needs to load a series of JSON files (where the first file identifies others that need to be loaded), and my preference is to access them as-is (they are externally defined and shared with other tools).
The "import" command looks like it might work for the first JSON file, except that I don't see a way of using that to load a series of files (determined by the first file) into variables.
One option is to pass in a helper function to the class for loading files, which the root script would populate as appropriate for NodeJS or the browser.
Alternatively, my current leading idea, but still not ideal in my mind, is to define a separate module with a "async function loadFile(fn)" function that can be imported, and set the paths such that a different version of that file loads for browser vs NodeJS.
This seems like something that should have a native option, or that somebody else would have already written a module for, but I've yet to find either.
For node, install the node-fetch module from npm.
Note that browser fetch can't talk directly to your filesystem -- it requires an HTTP server on the other side of the request. Node can talk to your filesystem, as well as making HTTP calls to servers.
It sounds like as of now, there is no perfect solution here. The 'fetch' API is the most promising, but only if Node implements it some day.
In the meantime I've settled for a simple solution that works seamlessly with minimal dependencies, requiring only a little magic with my ExpressJS server paths to point the served web instance to a different version of utils.js.
Note: To use the ES-style import syntax for includes in NodeJS (v14+) you must set "type":"module" in your package.json. See https://nodejs.org/api/esm.html#esm_package_json_type_field for details. This is necessary for true shared code bases.
Module Using it (NodeJS + Browser running the same file):
import * as utils from "../utils.js";
...
var data = await utils.loadJSON(filename);
...
utils.js for browser:
async function loadJSON(fn) {
return $.getJSON(fn); // Only because I'm using another JQuery-dependent lib
/* Or natively something like
let response = await fetch(fn);
return response.json();
*/
}
export { loadJSON };
utils.js for nodeJS
import * as fs from 'fs';
async function loadJSON(fn) {
return JSON.parse(await fs.promises.readFile(fn));
}
export { loadJSON };

Reading a file for a npm package

I have created a npm package named test_package_cat, which is supposed to read a json file (info.json) at the beginning.
Thus, index.js (main entry) and info.json are at the same level.
When I run the index.js locally, I can read the file.
either:
fs.readFileSync('info.json')
or
fs.readFileSync(path.resolve(__dirname, 'info.json')
works fine.
However, when I have another program, a React page,that uses the package, it fails to read the json file.
cat = require('test_package_cat')
cat.meow()
When I run index.js locally, if I console.log(__dirname), it gives me C://......../myProject.
However, when running the React app, console.log(__dirname) just prints "/" and when I try to print directories/files, it shows nothing.
How can I make the my npm package to read info.json file?
Edit: After more searching, I managed to get it working by doing:
let info = require('./info.json')
console.log(JSON.stringify(info))
but would still like to know how to do it using "readFile" way.
fs is only available in the Node runtime environment. It isn't available in a browser's JavaScript runtime environment. I'm surprised you haven't encountered an error to that effect.

Categories