Electron: Load a file with `executeJavaScript` - javascript

I need to inject an NPM package into a BrowserView by using executeJavaScript. The package is Web3 and here is what I've tried so far.
import Web3 from 'web3'
const web3 = '' + Web3; // stringify the Web3 class
view.webContents.executeJavaScript(`
const provider = // ... provider got injected successfully because it doesn't have dependencies.
const web3 = new ${web3}(provider);
`)
But this throws the following error.
Uncaught ReferenceError: core is not defined
at new Web3 (<anonymous>:45:5)
at <anonymous>:41:16
Web3 is trying to load its core dependency which unfortunately did not get stringified.
So my question is, how can I load this whole package into the BrowserView? Aka how can you load npm package in the browser, if you do not have control over <script /> tags (at least I wouldn't know how to inject those in Electron)?
Update:
Because of what OJ Kwon suggested in the comments, I tried bundling Web3 with Browserify by running
browserify packages/web3/src/index.js -o web3-bundle.js
. It seemed to have worked, because at the very end of the bundled file (web3-bundle.js) it says:
// ... 50k+ lines long file
var version = require('../package.json').version;
var core = require('web3-core');
var Eth = require('web3-eth');
var Net = require('web3-net');
var Personal = require('web3-eth-personal');
var Shh = require('web3-shh');
var Bzz = require('web3-bzz');
var utils = require('web3-utils');
var Web3 = function Web3() {
var _this = this;
// sets _requestmanager etc
core.packageInit(this, arguments);
this.version = version;
this.utils = utils;
this.eth = new Eth(this);
this.shh = new Shh(this);
this.bzz = new Bzz(this);
// overwrite package setProvider
var setProvider = this.setProvider;
this.setProvider = function (provider, net) {
setProvider.apply(_this, arguments);
this.eth.setProvider(provider, net);
this.shh.setProvider(provider, net);
this.bzz.setProvider(provider);
return true;
};
};
Web3.version = version;
Web3.utils = utils;
Web3.modules = {
Eth: Eth,
Net: Net,
Personal: Personal,
Shh: Shh,
Bzz: Bzz
};
core.addProviders(Web3);
module.exports = Web3;
Now, I'm trying to import and include it like this:
const Web3 = require('./web3-bundle.js');
which doesn't work. It says undefined is not a constructor.
const Web3 = require('./web3-bundle.js').Web3;
and
const Web3 = require('./web3-bundle.js').default;
both didn't work, either. How should one do this?
Update 2:
Inspecting the bundle further, it has uses exports. and module.exports =. My editor only suggests methods and objects exported with exports. as importable 🤔

I suggest you to use this boilerplate or a boilerplate including a good webpack configuration (suggested boilerplate).
Follow these steps:
Clone the repository
Run yarn install
Run yarn add web3
Add import Web3 from 'web3'; into the app/containers/HomePage.js file (react render view).
Enjoy

Related

Issue installing #tensorflow-models/knn-classifier with npm

I installed #tensorflow-models/knn-classifier with npm, but when i run it i get an error "Cannot find module '#tensorflow-models/knn-classifier'".
I can see the module under node modules but still i get this error. Other models like #tensorflow-models/mobilenet, #tensorflow-models/universal-sentence-encoder are resolved but not the knn-classifier. Is there something additional needed for this model?
import * as tf from '#tensorflow/tfjs';
import * as knnClassifier from '#tensorflow-models/knn-classifier';
const classifier = knnClassifier.create();
const trainData = getTrainingData();
for(const td of trainData) {
classifier.addExample(td.xs, td.label);
}
For now the package is missing index.js. Here is the fix
const tf = require('#tensorflow/tfjs');
const knnClassifier = require('./node_modules/#tensorflow-models/knn-classifier/dist/knn-classifier');
const classifier = knnClassifier.create();
console.log('classifier', classifier)

module.exports won't export object with function

I've made a ModulesManager to manage all my modules, so I don't have a huge list of requirements in the top of my "server.js", but every time I'm trying to access the manager's methods, my server crash and throw an error which is saying that my manager method isn't a function.
TypeError: moduleManager.sqlString is not a function
I'm not really sure what I'm doing wrong here, this might be a stupid error, I've tried to look online for an answer but everyone is saying something different and nothing work.
Modules Manager (manager.js):
const sqlSetup = require("./sqlSetup.js");
const sqlSafeString = require("./sqlString.js");
function Manager(){
this.sqlString = function(query){
return sqlSafeString.getSqlSafeString(query);
},
this.sql = function(){
return sqlSetup;
}
}
module.exports = Manager;
Module SQL (sqlSetup.js):
const SqlString = require('sqlstring');
function getSqlSafeString(query){
//format query to fit in MySQL
var format = SqlString.escape(query);
return format;
}
module.exports = getSqlSafeString;
This is a test for my Travis build that I'm trying to make, the module manager path is good, the problem is really in the "ModuleManager.js" which I don't understand...
require('dotenv').config();
const Discord = require("discord.js");
const client = new Discord.Client();
const token = process.env.MOISTY;
const moduleManager = require("../modules/manager.js");
const assert = require("assert");
console.log("MAKE SURE MOISTY IS OFFLINE!");
client.login(token);
client.on('ready', () => {
//confirm login
console.log("MOISTY:200");
//Assert
assert.deepEqual(moduleManager.sqlString("sample text"), "sample test");
//terminate the session
process.exit();
});
I'm not very used to module exports, so this might be an easy question...
There are multiple mistakes in your code.
module.exports = getSqlSafeString; sets the export to getSqlSafeString.
When you do require("./sqlString.js") you will get the value that was assigned to the exports so in your case the getSqlSafeString.
So if you want to access that function you would write:
const getSqlSafeString = require("./sqlString.js");
//...
return getSqlSafeString(query);`
module.exports = Manager; exports the function Manager but not an object of the type Manager, so moduleManager.sqlString would be equal to Manager.sqlString. If you only want to group the functions in one object, then using a constructor would not make much sense here anyway, so you should write it that way:
module.exports = {
sqlString : function(query){
return sqlSafeString.getSqlSafeString(query)
},
sql : function(){
return sqlSetup
}
};
If you really want to do create on Object of the type Manager then you need to write:
module.exports = new Manager
For you to be able to require something from module A at module B, you have to export that something at module A. You export it assigning it to module.exports.
Yout problem is you didn't export the Manager at the Manager module.
You could simple export Manager, but, because you seem to be using an instance of Manager:
const moduleManager = require("../modules/manager.js");
...
moduleManager.sqlString("sample text")
Then you must export an instance. Add to manager.js:
module.exports = new Manager();
You are putting the functions on an instance, ie this.sqlString is a property named sqlString on an instance of Manager. But you are not using Manager as a constructor, ie not doing new Manager() or in your case new moduleManager()
You can change your import code to like below
const moduleManager = new require("../modules/manager.js")();
Or change the export to:
module.exports = new Manager();
Then moduleManager will be an instance of Manager and will be able to use moduleManager.sqlString

How can I automatically update my javascript file to import newly detected files?

I tagged watchman as it MIGHT be the solution I'm looking for, but I don't quite know how to use it in this way!
I have a directory
/imgs
/icons
/bird.png
/cat.png
/dog.png
/pig.png
and I have a file
/imgs/index.js
My index.js is responsible for importing all of the images and then exporting a single object for the rest of my project to use.
const bird = require('./icons/bird.png');
const cat = require('./icons/cat.png');
const dog = require('./icons/dog.png');
const pig = require('./icons/pig.png');
const Icons = { bird, cat, dog, pig };
export default Icons;
What I want to do is watch my imgs folder for new additions, and automatically update my index.js to import these new files and add them to my object. I need to import them with Common.js and export them with ES6.
Does anyone know a good solution to this problem?
A potential solution is to write a JavaScript script that generates your index.js like so:
'use strict';
const fs = require('fs');
const DIR = __dirname + '/imgs/icons';
const output = __dirname + '/imgs/index.js';
return fs.readdir(DIR, (err, files) => {
let result = '';
let references = [];
files.forEach(item => {
// assuming item has the format animal.png
let newReference = item.split('.')[0];
references.push(newReference);
result += `const ${newReference} = require('./icons/${item}');\n`;
});
result += `\nconst Icons = { ${references} };\n\nexport default Icons;`;
fs.writeFile(output, result, err => {
if (err) throw err;
console.log(output + ' updated');
});
});
Place that file (let's call it watcher.js for this purpose) in imgs's parent directory and make watchman run it whenever changes in your icons directory are detected:
watchman imgs/icons "node watcher.js"
Notice that if a new file gets put into the watched directory, the index.js-creating script will not re-run. Only if it gets altered again (even if just gets saved again with the same data), the index.js will reflect that change.
You can simply test that by running touch imgs/icons/crabigator.png twice and look at the watchman log and/or content of index.js.

Importing JavaScript Library into NativeScript

I am learning NativeScript. I have a basic app working. I am now trying to import a JavaScript library that I've used in the past. I'm importing the library by using:
npm install git://github.com/my-company/my-project.git --save
I've confirmed that the package is being installed. In my view model, I then add the following:
var MyLibrary = require('MyLibrary');
That line alone causes the app to crash. Basically, NativeScript cannot seem to find it (or load it). I looked, and I can see the "MyLibrary" directory in the "node_modules" directory. The directory structure looks like this:
.
node_modules
MyLibrary
dist
MyLibrary.min.js
src
MyLibrary.js
package.json
The MyLibrary.js file looks like this:
class MyLibrary {
process(vals) {
let result = 0;
if (vals) {
vals.forEach(function(val) {
result = result + val;
});
}
return result;
}
}
module.exports = MyLibrary;
The "MyLibrary.min.js" file is the result of running it through Babel and converting it to ES5. What am I doing wrong? I'm just trying to get the following code into my view model:
var MyLibrary = require('MyLibrary');
var library = new MyLibrary();
var result = library.process([1, 2, 3, 4]);
In your package.json, add a property like this :
{
"main": "./dist/MyLibrary.min.js"
}
In your code, use your module like this :
var MyLibraryModule = require('MyLibrary');
var library = new MyLibraryModule.MyLibrary();
var result = library.process([1, 2, 3, 4]);

Common logging for node, express application -- best practice?

I'm working on an node.js application with several dozen modules and using bunyan for logging (JSON output, multiple configurable streams). I've been looking for good examples of how to implement a instance across all the modules, but haven't seen what appears to be a really clean example I can learn from.
Below illustrates an approach that works, but seems quite inelegant (ugly) to me. I'm new to node & commonjs javascript in general, so looking for recommendations on how to improve it.
module: ./lib/logger
// load config file (would like this to be passed in to the constructor)
nconf.file({ file: fileConfig});
var logSetting = nconf.get('log');
// instantiate the logger
var Bunyan = require('bunyan');
var log = new Bunyan({
name: logSetting.name,
streams : [
{ stream : process.stdout,
level : logSetting.stdoutLevel},
{ path : logSetting.logfile,
level : logSetting.logfileLevel}
],
serializers : Bunyan.stdSerializers
});
function Logger() {
};
Logger.prototype.info = function info(e) { log.info(e) };
Logger.prototype.debug = function debug(e) { log.debug(e) };
Logger.prototype.trace = function trace(e) { log.trace(e) };
Logger.prototype.error = function error(e) { log.error(e) };
Logger.prototype.warn = function warn(e) { log.warn(e) };
module.exports = Logger;
module: main app
// create the logger
var logger = require('./lib/logger)
var log = new logger();
// note: would like to pass in options --> new logger(options)
module: any project module using logger
// open the logger (new, rely on singleton...)
var logger = require('./lib/logger');
var log = new logger();
or view the gist
any recommendations?
EDIT:
I've modified the constructor, making the singleton pattern explicit (rather than implicit as part of the 'require' behaviour.
var log = null;
function Logger(option) {
// make the singleton pattern explicit
if (!Logger.log) {
Logger.log = this;
}
return Logger.log;
};
and then changed the initialization to take an options parameter
// initialize the logger
Logger.prototype.init = function init(options) {
log = new Bunyan({
name: options.name,
streams : [
{ stream : process.stdout,
level : options.stdoutLevel},
{ path : options.logfile,
level : options.logfileLevel}
],
serializers : Bunyan.stdSerializers
});
};
Singleton pattern in nodejs - is it needed?
Actually, singleton is perhaps not needed in Node's environment. All you need to do is to create a logger in a separate file say, logger.js:
var bunyan = require("bunyan"); // Bunyan dependency
var logger = bunyan.createLogger({name: "myLogger"});
module.exports = logger;
Then, retrieve this logger from another module:
var logger = require("./logger");
logger.info("Anything you like");
if you are using express with node.js then you can try this.
By default, logging is disabled in Express. You have to do certain stuff to get logs working for your app. For access logs, we need to use the Logger middleware; for error logs we will use Forever.Hope it will help you..
Here is a good example How to Logging Access and Errors in node.js

Categories