Electron contextBridge works on desktop but not on web - web

My stack consist of Electron, React, FastAPI. I created a contextBridge in the preload.js file. Everything is working fine on the desktop application however when I am on the web, I get the following error below. If anyone knows what might be the cause of this please let me know where to start looking! I don't fully understand why it's a type error. Thank you!
preload.js
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("api", {
rollDice: async () => {
return await ipcRenderer.invoke("roll-dice");
},
});
error in the browser console
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'rollDice')
You can recreate the bug by following this:
npx create-react-app my-app --template electron-python-fastapi
cd my-app
python -m pip install virtualenv
python -m virtualenv venv
.\venv\Scripts\activate
python -m pip install -r requirements.txt
npm start
Edit: in my App.js file window.api seems to be undefined. Any reason that might be the case for Web but not Desktop?
Edit: I added console.log("running preload"); at the end of my preload.js file and seems like it doesn't preload the file when running on the browser(web).
electron.js
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
preload: path.join(__dirname, "preload.js"),
},
});

Related

vscode extension using execa returns EPERM

Currently writing a vscode extension and testing on mac osx. Need to automate some npm commands using execa. After the recent round of vscode updates we are no longer able to run our existing commands.
async runScript(script: string, cwd?: string) {
const scriptStdOut = execa.command(script, {
shell: true,
cwd: cwd,
windowsVerbatimArguments: true,
})
let out = await scriptStdOut
return out
}
Error: failed with exit code 1 (EPERM): npx ng update #angular/cli #angular/core

Requiring node modules in ionic + electron (5.0.0) desktop application

I'm building a desktop application using ionic and electron.
I started using electron v4.1.3 and i was able to require node modules in the "ionic part" of the application, for example in the home.ts file by using:
import { Component } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
ngOnInit () {
console.log ((<any> window).require ("fs"));
}
}
and this is what i get:
As you can see i can access all fs methods, so i can read, write, copy files and whatever else.
Now i have installed electron v5.0.0, i created the same application but i get an error when i try to require fs module in the ngOnInit method:
window.require is not a function
How can i fix this? If you need more details on installation or envinronment just tell me, thank you!
nodeIntegration is now disabled by default in 5.0.0 as per breaking changes document.
https://github.com/electron/electron/blob/master/docs/api/breaking-changes.md#planned-breaking-api-changes-50
and the release notes
https://github.com/electron/electron/releases/tag/v5.0.0
So you need to enable it :
const mainWindow = new BrowserWindow({
webPreferences: { nodeIntegration: true }
});

Electron - "Cannot read property 'on' of undefined"; tried reinstalling,

I'm testing an electron app but I'm getting this pernicious error:
"TypeError: Cannot read property 'on' of undefined"
The research I've done pointed to either a botched module install, a syntax issue, or passing in an undefined variable to the app.on, and I suspect the issue may be Electron being pointed to incorrectly (now it's being pointed to the folder ending in electron\dist\electron.exe, which I've heard might not the right location), but I'm unsure.
Despite checking the require command, syntax, rechecking, uninstalling, and reinstalling node, I can't seem to make this darn error go away. What could be causing this?
const electron = require('electron');
const os = require('os');
const fs = require('fs');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
var Mousetrap = require('mousetrap');
const path = require('path');
const url = require('url');
const ipc = electron.ipcMain;
let mainWindow;
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
/* More code in this and sub functions*/
}))
}
})
const preferencesManager = require('./preferencesManager');
/******
Send data to database given constructor created in preferencesManager
******/
// First instantiate the class because we want to turn the class into an object to be able to use.
const store = new Store({ //create a new getting and setting logic
//We'll call our data file 'user-preferences'
configName: 'user-preferences',
defaults: {
//800 x 600 is the default size of our window
windowBounds: { width: 800, height: 600}
}
});
// When our app is ready, we'll create our BrowserWindow
app.on('ready',function(){
//Set up a listener for what I've done in keycapture (in the renderer process)
//???
ipc.on('invokeAction', function(event, args){
/* Do some action */
});
});
You are probably trying to run your application like a node app with:
$ node index.js
The electron file is a binary file, not a JavaScript file, when you require it an run with node there will be no object to call electron.app, so it parses for null and cannot have an property. As in the getting started documento of Electron.JS you must run the application like this:
Change your package.json script session adding start:
{
"scripts": {
"start": "electron ."
}
}
Now run:
$ npm start
The code you posted has an error, witch may be an edition error while coping and pasting but it should loose some parenthesis and curly brackets:
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
/* More code in this and sub functions*/
}))
}
The application should now run correctly. I tested you exact code, removing the libs I did not have and it loaded with no errors.

Import libraries in Angular-Electron project

I'm developing a web application using Angular 5.
I have wrapped it inside Electron because of I need to use the filesystem.
In order to use the node features I set the main.js file as follows:
mainWindow = new BrowserWindow({
width: 1280,
height: 800,
backgroundColor: '#ffffff',
webPreferences: {
nodeIntegration: true
}
})
As you can see nodeIntegration is set to true.
With this configuration everything works well but I noticed that when I import some library in the .angular-cli.json file that libraries are not imported.
For example I import toastr as follows: (.angular-cli.json file)
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
"../node_modules/toastr/build/toastr.min.js"
],
On the browser it works like a sharm, but in Electron I get this error:
Uncaught (in promise): ReferenceError: toastr is not defined
ReferenceError: toastr is not defined ...
How should I import an external library in order to make it works in Electron && Browser?
Thanks a lot

Durandal optimization with Gulp and Gulp-Durandal not working

We are building an application with Durandal which is quite big at the moment and we currently looking into bundling all JS files located in the App folder into a main-built.js file. Pretty basic and usual stuff I guess.
I'm using Gulp with the Gulp-Durandal extension. Here our gulpfile :
var gulp = require('gulp');
var durandal = require('gulp-durandal');
gulp.task('build-portal', function () {
durandal({
baseDir: 'app',
main: 'main.js',
output: 'main-built.js',
almond: false,
minify: false
}).pipe(gulp.dest('app'));
});
And here's a snippet of our main.js file
require.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'transitions': '../Scripts/durandal/transitions'
},
shim: {
},
waitSeconds: 0
});
define('jquery', [], function () { return jQuery; });
define('knockout', [], function () { return ko; });
define('ga', function () { return ga; });
define(
["require", "exports", "durandal/app", "durandal/viewLocator", "durandal/system", "plugins/router", "services/logger", "modules/knockout.extensions", "modules/knockout.validation.custom"],
function (require, exports, __app__, __viewLocator__, __system__, __router__, __logger__, __koExtensions__, __koValidationCustom__) {
var app = __app__;
var viewLocator = __viewLocator__;
var system = __system__;
var router = __router__;
As you can see in the gulpfile, we do not want to use Almond but RequireJs instead, for some reasons almond isn't workin with our project and anyhow, we prefer RequireJs whether its bigger than almond at the end. That's where it look to brake. Running the command to build the main-built.js file took sometime but at the end I get the file built with everything in it.
The problem is that when I try to load the application, it is stuck to the loading screen. It doesn't go any further and there's no errors at all in the browser console.
I created a new project on the side to test if our code was somewhat faulty and found that it might not. You can found that project here :
https://github.com/maroy1986/DurandalGulpBundling
If I build that project with almond option to true, everything works fine but if I switch almound off to tell gulp to use RequireJs, I got the same behavior as our app. You got stuck at the loading screen, without any errors.
So here I am, I do read a lot on the subject but didn't found anything to solve this. Hope someone here already encounter these behavior and have a solution to share.
Thanks!
I had the same requirement and issue. It seems require.js wasn't calling the main module which will startup the Durandal app, that's why it's stuck in the loading screen. I was able to resolve it by implicitly calling the main module:
gulp.task("durandal", function() {
return durandal({
baseDir: "app",
main: "main.js",
output: "main-built.js",
almond: false,
minify: true,
rjsConfigAdapter: function(config) {
//Tell requirejs to load the "main" module
config.insertRequire = ["main"];
return config;
}
})
.pipe(gulp.dest("dist"));
});
I downloaded your project and tried building it with the latest versions of gulp and durandal. Initially it didn't build and gave me the following error:
TypeError: Cannot read property 'normalize' of undefined
This is a problem with the text-plugin of rjs and you can solve this by adding the following to your gulp-file (next to the almond, minify, output... properties):
rjsConfigAdapter : function(rjsConfig){
rjsConfig.deps = ['text'];
return rjsConfig;
}
Once I did that, the build finished and I could build with or without minify, almond and require and the application works fine.

Resources