Cannot resolve “node:http” when using libp2p with create-react-app - javascript

I am new to libp2p, so please excuse me if this is something that’s been asked/discussed elsewhere. I am trying to set up in a newly created project made with create-react-app. The app currently has one component with the following:
import React, {Component} from 'react';
import mplex from 'libp2p-mplex';
import Noise from 'libp2p-noise';
import Libp2p from 'libp2p';
class Connector extends Component {
constructor (props)
{
super(props);
this.state = {};
}
componentDidMount(){
node = Libp2p.create({
addresses:{
isten: [
'/dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star',
'/dns4/wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star'
]
},
modules:{
connEncryption:[Noise],
streamMuxer:[mplex],
transport:[WebSockets]
}
})
console.log(node);
}
render(){
return (<div>The connector component</div>);
}
}
export default Connector;
I know this alone is not enough to connect to anything, but it doesn’t even compile. I get the following error message when I run this:
Module not found: Can’t resolve ‘node:http’ in ‘/Users/myuser/projects/p2p-browser/node_modules/node-fetch/src’
I looked into the source code of the node-fetch module referenced and found that, indeed, it is requiring node:http. I also found that the node: prefix is to get node to include always node’s native http module. Since this is a react-app, which runs on the browser, I see no reason at all to use node-fetch, which leads me to think that either libp2p is not compatible with the browser, or somehow I am using the node.js version of libp2p instead of the “browser version”, though so far, I haven’t found any documentation to suggest there is a “browser version”, the examples I’ve seen use parcel and include the same npm modules. So, am I missing something, or is libp2p simply incompatible with create-react-app and needs to be compiled for the browser with parceljs?
Any help will be greatly appreciated. Thank you.

Related

How to get values from the context of a node_modules folder component into another react app

I want to be able to access a value from a npm package library context.
I've tried that this way:
import { DocViewerContext } from '#cyntler/react-doc-viewer/dist/esm/store/DocViewerProvider'
const test = useContext(DocViewerContext)
console.log({ test })
But unfortunatelly I cannot see the data being changed when I do some stuff in that component.
To tell you the truth I think I am not doing the right thing
I tried to do some research and I've found the following question here: Providing React Context to an imported node module

Circular dependency (?) in library & nodejs library code - Object prototype may only be an Object or null: undefined

I'm using filestack-js in a Rails project which is bundled with Vite. Everything works as expected until I include the ESM module for the filestack-js library, in this case in a StimulusJS controller:
import { Controller } from "stimulus";
import * as filestack from "filestack-js";
export default class extends Controller {
// some irrelevant implementation code that calls filestack.init(...)
}
Loading the above controller file in the browser causes an error:
tslib.es6.js:25 Uncaught TypeError: Object prototype may only be an Object or null: undefined
at setPrototypeOf (<anonymous>)
at __extends (tslib.es6.js:25)
at http.ts:43
at node_modules/filestack-js/build/module/lib/request/adapters/http.js (http.ts:64)
at __init (chunk-IHTDASF6.js?v=1616a449:14)
at request_adapter.node.ts:17
This is an error produced by the browser while working in a development environment, using Vite to build and serve ES modules to the browser directly. It handles Typescript compilation. Removing the import * as filestack bit makes the error go away (but obviously breaks the class' functionality).
My google searches seem to suggest that this might be a circular dependency problem. The browser stack trace points towards a file in the filestack-js library:
// src/lib/request/adapters/http.ts
import * as url from 'url';
import * as zlib from 'zlib';
import Debug from 'debug';
import { AdapterInterface } from './interface';
import { getVersion } from '../../utils';
import * as Stream from 'stream'; // <---------- Stream imported here
import { FsRequestOptions, FsResponse } from '../types';
import * as utils from '../utils';
import { prepareData, parseResponse, combineURL, set as setHeader, normalizeHeaders } from './../helpers';
import { FsRequestErrorCode, FsRequestError } from '../error';
import { FsHttpMethod } from './../types';
const HTTPS_REGEXP = /https:?/;
const HTTP_CHUNK_SIZE = 16 * 1024;
const MAX_REDIRECTS = 10;
const CANCEL_CLEAR = `FsCleanMemory`;
const debug = Debug('fs:request:http');
class HttpWritableStream extends Stream.Writable {
// omitted class definition
}
Where Stream.Writable is actually undefined due to a circular dependency problem. I have no idea how that would happen or seem to only affect me.
This is not an issue that has been reported on the filestack-js issue tracker.
Debugging in the browser and cloning/linking the repository locally have confirmed that Stream.Writable is returning undefined, but I don't know enough about JS to understand why. Supposedly this typically happens due to a circular dependency, but I'm not sure how the nodejs Stream module would have circular dependencies on a random library like filestack-js. I am also inexperienced enough in the JS world to understand exactly what it means to be using a nodeJS library like Stream in a browser module - filestack-js has both browser modules and commonJS/nodeJS modules so I'm not sure how/if they relate or interact.
Here's what the Stream object looks like when logged to a browser console. Clearly something has been imported but Writable is not a property of what was imported:
FWIW this happens on Chrome and Firefox, latest versions of each.
I also tried using dpdm to analyze the filestack-js project for circular dependencies. It did find some but it doesn't appear as if they are causing errors, and it does seem to explicitly be excluding node libraries and other dependency libraries.
Ok I think I've solved my issue but I'm not an expert so I'll try to explain what the problem was. Feel free to chime in with clarification if you know better.
This was caused by filestack-js's heavy usage of nodejs libraries. Historically, Webpack v4 has polyfilled a lot of common NodeJS libraries for usage in-browser, entirely transparent to most developers. This worked great but was complete magic.
Rollup, and incidentally, Webpack v5, do not do this polyfilling, so any nodeJS libraries used by "ESM" libraries from NPM that aren't directly compatible with modern browsers will just break. In order to polyfill this manually I had to instruct Vite & Rollup to alias the name of the nodejs stream module to something that is directly compatible with browsers, and install that. To do that, I:
yarn add --dev stream-browserify
And added the following to my vite.config.js:
// ...
resolve: {
alias: {
stream: "stream-browserify",
},
},
// ...
There should be a very similar (but different) way of telling Rollup to do this, because here I do it though the Vite configuration.
For extra context, here is the GitHub issue I opened on the filestack-js repo: https://github.com/filestack/filestack-js/issues/458
Imported it directly as recommended in the link Taylor recommended.
import * as filestack from 'filestack-js/build/browser/filestack.esm';
https://github.com/filestack/filestack-js/issues/458#issuecomment-927373100

How to test typescript function locally manually in React app?

sorry a rookie question, I am using react and typescript (via create-react-app) and if I have some totally non-UI javascript code (a module I am working on to work with some REST api), something along the lines like this:
src/lib/rest.tsx
export const getUser = async function (
username: string,
) {
let response = await fetch(`http://localhost:3000/api/auth/`, {
username
});
return response;
};
I am wondering how can I test this function locally in a REPL or browsers's dev tools, before putting it into real use. I think I have two difficulties right now:
webpack seems not even packaing this module into the code now, if I open Chrom's dev tools I can see other tsx files but not this one, simply becasue I am not importing this module anywhere I think.
even if it is packaged I dont know how to import this module in a REPL or the dev tool console because first I dont know what is the correct syntax here, Would it be import src/lib/rest.tsx? Also seems I cannot import any module in a REPL because import can only happen inside a module.
The workflow here is just I have written some simple typescript function and I want to run them in a REPL like enviorment so I can make sure they are working before using it anywhere or starting to write unit/integration tests against them.
Thanks!
1 is correct, your new module is not imported and thus not bundled by webpack.
I don't think you could use import syntax in console atm. But there are 2 ways you could try.
Just import your code in one of the bundled file, if you are using dev server, change will be reflected to browser automatically:
import { getUser } from '../../lib/rest';
getUser().then(console.log);
Or attach it to window so you could play with it in console:
import { getUser } from '../../lib/rest';
if (typeof window !== 'undefined') {
window.getUser = getUser;
}

Using Vue Design System in Nuxt is throwing errors about export in system.js

I am trying to get the components imported into a Nuxt project, following the steps here:
https://github.com/viljamis/vue-design-system/wiki/getting-started#using-design-system-as-an-npm-module
Nuxt does not have a main.js (everything is plugin based), so what I have done is create a "plugin" and then do the import code in there like so (Nuxt recommends this for other libraries too and works fine):
vue-design-system.js
import Vue from 'vue'
import system from 'fp-design-system'
import 'fp-design-system/dist/system/system.css'
Vue.use(system)
Then in my config I do (removed other code in config):
nuxt.config.js
module.exports = {
css: [
{ src: 'fp-design-system/dist/system/system.css', lang: 'css' }
],
plugins: [
{ src: '~plugins/vue-design-system', ssr: true }
]
}
When I run npm run dev in my theme, it builds, but I get a warning:
WARNING Compiled with 1 warnings warning in
./plugins/vue-design-system.js 7:8-14 "export 'default' (imported as
'system') was not found in 'fp-design-system'
Seems to have an issue with the generated system.js regarding the export (the command npm run build:system).
In my page on screen I get the following error when trying to use a component in the design system:
NuxtServerError Cannot find module
'fp-design-system/src/elements/TextStyle' from
'/Users/paranoidandroid/Documents/websites/Nuxt-SSR'
If I hard refresh the page, I then get another message:
NuxtServerError render function or template not defined in component:
anonymous
Any idea what's happening here? It would be really great to get this working somehow.
At this current time, I'm not sure if it's a Nuxt issue or a Vue Design System issue. I think the latter, just because the Nuxt setup I have right now is very bare-bones...so it's not something else causing this.
Thanks.
Repository on GitHub:
Here is the repo for my "theme", but in order to get this going, you will need to create a design system separate from this with the same name and follow the steps to use the design system as a local (file) NPM module.
https://github.com/michaelpumo/Nuxt-SSR
console.log of system (from the JS import statement)
As for your first error (""export 'default' (imported as 'system') was not found in 'fp-design-system'"), the UMD built JS from vue-design-system does not export a "default" object. But you can simply workaround the issue by importing it as:
import * as system from 'fp-design-system'
instead of:
import system from 'fp-design-system'
Then another issue comes quickly as you noticed in your comments: "window is not defined", due again to the UMD built JS that expects window to be globally available, instead of the usual trick to use this (which equals window in a browser). Therefore as it is, the build is not comptible with SSR.
You could however slightly rework the built JS by replacing the first occurrence of window by this, but I am not sure if the result will still work.
Most probably you should better keep this module for client rendering only.
It seems Vue is looking for the ES6 pattern for importing module, which you should use for external javascript modules/files.
in ES6 it is
export default myModule
in ES5 it was
module.exports = myModule
Hope it will help.

Import external Javascript libraries installed via npm in Meteor 1.3

I want to use the OpenSeadragon library in my Meteor app. As Meteor 1.3 provides support for npm modules, I have installed it via npm using meteor npm install openseadragon.
But now I am not sure how to user it. The OpenSeadragon docs only provides an example using the script tag.
The meteor docs tell us to use import like import moment from 'moment';. But how do I import openseadragon as I am pretty sure it doesn't use ES6 modules and doesn't export anything.
How can I use it using the npm import without loading the openseadragon.js as global for whole app?
The project's (poorly documented) API page states that
OpenSeadragon will also return an AMD module when required with a loader like Require.js.
Therefore, inside a client script, you can simply
import 'openseadragon'; // load globally
and it should give you the module constructor
Now, depending on what you are using, you may initialize your container from that constructor. For React container, this would look something like this :
import React, { Component } from 'react';
import { Random } from 'meteor/random';
import 'openseadragon'; // OpenSeadragon on global scope
export default class OpenSeedragonComponent extends Component {
constructor(props) {
super(props);
this.state = {
options: {
id: Random.id(), // container unique name
// other options here...
}
};
}
componentDidMount() {
this.initialiseWidgets();
}
componentDidUpdate() {
this.initialiseWidgets();
}
initialiseWidgets() {
this.viewer = OpenSeadragon(this.state.options);
}
render() {
return (
<div id={ this.state.options.id }
width={ this.props.width || '800px' }
height={ this.props.height || '600px' }
>
</div>
);
}
};
Note: at the moment of this writing, you will get an error when loading the .map file. Just ignore it, or open an issue with the project maintainer so he properly integrate the project with Meteor. Perhaps someone will write a react / meteor package wrapper for it...
A JS lib doesn't have to specifically use ES6 export keyword to expose symbols, as a matter of fact npm modules are still using CommonJS module.exports in their vast majority because even though package authors write their code in ES6 they publish them to npm using Babel.
In this specific case, you need to globally import the OpenSeadragon lib using import 'openseadragon'; somewhere in your client/ folder.
Then it will be available on window.OpenSeadragon.
Since the nice Yanick Rochon's answer does not seem to work in your case, note that you should still be able to load your library the "old fashion" way, using the [project_root]/client/compatibility/ special folder.
Any library in that folder will not be loaded in an independent scope by Meteor, but rather loaded "as is" like if it were through a classic <script> tag.
Then your OpenSeadragon object should become available on global scope.
As a side note, if you need simple image navigation and not the OpenSeadragon advanced features, you might be interested in trying Leaflet. It is lighter-weight but very stable and well maintained.

Categories

Resources