How should I handle user-facing plugins in Electron? - javascript

I would like to add a plugin system to my Electron application so that my users can add new features to my application. I was originally thinking that I would let my users upload a .zip containing a plugin and then it would extract, and require the plugin to use it within the application. I then ran into problems with the idea.
How should I handle a plugin which has dependencies since I cannot use npm (e.g lodash)?
How can I give the plugin an API to use (e.g getting application theme or resource name)
I am not sure how this could be handled, I've looked around for similar cases but haven't found them. My ultimate goal is to have a system that works in Electron similar to how Wordpress plugins work.

You could use npm as a child process.
You can implement your own:
require('child_process').exec(
'npm ...',
{ maxBuffer: 1024 * 500 },
function (error, stdout, stderr) {
var response = JSON.parse(stdout).dependencies;
...
}
);
or use a library, as an example: https://github.com/getstation/electron-package-manager

Related

Unable to understand the difference between different monaco editor packages integration

I have a react application, and I want to embed Monaco Editor into my application mainly for SQL validation and AutoComplete scenarios. I use neutrinorc.js to configure plugins or direct install using npm install plugin-name in the application.
My webpack.config.js looks like,
// Whilst the configuration object can be modified here, the recommended way of making
// changes is via the presets' options or Neutrino's API in `.neutrinorc.js` instead.
// Neutrino's inspect feature can be used to view/export the generated configuration.
const neutrino = require('neutrino');
module.exports = neutrino().webpack();
I noticed that there is,
https://github.com/react-monaco-editor/react-monaco-editor
https://github.com/jaywcjlove/react-monacoeditor
And Microsoft ones,
https://github.com/microsoft/monaco-editor-webpack-plugin
https://github.com/Microsoft/monaco-editor
I don't understand that if I want to embed a Monaco Editor into my React application which of the above packages do I need and do I need to configure them in neutrinorc.js?
It would be great if someone can explain this in detail.
I don't know neutrinorc.js, but I can explain the other aspects. Integrating Monaco in a React app requires 2 things:
A React wrapper for the Monaco editor. You can either write one yourself or use the react-monaco-editor node module.
You have to configure webpack to load the required files. This is where monaco-editor-webpack-plugin comes in.
Especially the second point is a bit tricky, depending on your app. If you created that using CRA (create-react-app) you will not have access to the webpack config file, unless you "eject" the app. This is usually not desirable, hence add another node module to the mix, called react-app-rewired. This module allows you to add another webpack config file (config-overrides.js) to the root of your project and add configuration data there. Something like:
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const webpack = require("webpack");
module.exports = function override(config, env) {
config.plugins.push(new MonacoWebpackPlugin({
languages: ["typescript", "javascript", "sql", "mysql", "python", "json", "markdown", "ini", "xml"]
})
return config;
}
With that webpack plugin you can decide which language you want to support in Monaco and distribute only those files required by them (especially TS + JS require quite large files to be there).

How to manage releases with ASP.NET pointing to new versions of Webpacked JS files?

I'm working with a client who has a monolithic ASP.NET application as their backend, but also hosts Webpacked JS files for their React.js frontend in the same GIT repo. The obvious problem is that anytime they want to do a frontend release, they have to release and build the entire .NET application along with it, due to the manifest.json that is in the EC2 instance. The idea is that there will also be many versions over many instances, canaried out to different users, going through various levels of post-production testing, etc., standard DevOps CI/CD pipeline with post-production health checks and automated rollbacks. That is the end goal. In the meantime, they need to split their frontend/backend releases apart, which means separate versioning for both. So after much preamble, the question to the community is two-fold:
Has anyone experienced this type of environment and come up with a viable solution?
Does anyone have a good suggestion for how to approach this problem?
Keep in mind that this solution should also expect local development, PR testing, and a blue/green prod setup.
Assuming that you can refactor your project so that the client-side stuff will be a folder of its own, let's call this folder client-{version}, you can create a setting for your project for client-side path, which would be client-v1/ and then, if you need to change v1 -> v2, a command-line command would be needed in order to ensure that this setting can be changed for your project at runtime. So, deploying the client-side would have this algorithm:
deploy the client-side
change the client-{version} to a newer version
trigger command-line command to the project which will ensure that the new client-side path will be used from now on
I have used following solution, (I learned from JSDelivr, UnPkg ..)
Private NPM Repository (ProGet)
Version Table (stores package name and production version to be used)
A controller to download and extract package to a local folder for requested package with version.
Here is how it works,
/// lets assume this will serve JS/image/css everything from
/// from a path /js-pkg/packageName[#version]/....
[RoutePrefix("js-pkg")]
public class JSContent: Controller {
[HttpGet("{packageName}/{*path}")]
public ActionResult Get(
string packageName,
string path) {
string version = null;
string releasedVersion = db.Versions
.Where(x => x.Package == packageName)
.Select(x => x.Version)
.First();
if (packageName.Contains("#")) {
var tokens = packageName.Split("#");
version = tokens[1];
packageName = tokens[0];
}
if (version == null) {
// this is for performance reason...
// explained in next line...
return Redirect($"/js-pkg/{packageName}#{releasedVersion}/{all}");
}
// since all requests will be versioned...
// you don't have to worry about stale cache ...
Response.CacheControl = "public, max-age=36000000";
// you need to setup a file based locking here
string folder = $"d:\\temp\\{packageName}\\{version}";
if (!System.IO.Directory.Exists(folder))
{
DownloadAndExtract(
$"https://proget...../npm/repo/{package}/-/{package}-{version}.tgz",
folder
);
}
string file = $"{folder}//{path}";
if(!System.IO.File.Exists(file)) {
return HttpNotFound();
}
return File(file);
}
}
Now to host file, you can simply put a CSHTML or view with following line
<script src="/js-pgk/packageName/dist/ui/start.packed.js" ></script>
<link rel="stylesheet" href="/js-pgk/packageName/dist/ui/start.css" ></link>
There are multiple advantages to it,
All your JS packages can stay outside the main repository, as most of the time UI becomes more and more complicated, your UI can be divided into multiple packages and they all can exist independently
Multiple teams can independently manage packages, and undoing released package is easy as you can simply go in database and change version.
In debug environment, you can also supply version in querystring or in package name to test different JS package for production/staging backend
Separate Frontend will remove all node related code from backend, backend will not need unnecessary frontend processing.
You will eventually have many small repositories, each independently developed and maintained. Your commits will be smaller and clearer. Single repository for frontend/backend has too many commits for single feature/change.

Attempting to load a JavaScript sdk into an Angular2 application. Can't find all dependencies

I'm attempting to make use of this library: https://github.com/MagicTheGathering/mtg-sdk-javascript in an Angular2 application.
Unfortunately, I've been going in circles trying to load it into my application.
Firstly, on the TypeScript side if I import it using:
import { } from 'mtgsdk';
there are no types to load into the {}.
If I attempt to load it using something similar to:
import * as mtg from 'mtgsdk'
I'm unable to because it says that it's unable to find a module named mtgsdk.
I've installed the module using
npm install --save mtgsdk
Also, npm installs work fine for other modules.
The application compiles fine if I load it in using require via something similar to this:
var mtg = require('mtgsdk');
Taking that approach, I'm able to compile and launch but in the browser I get a number of errors about modules that it can't find. I figure they are prerequisites for the sdk that didn't get loaded so I start bringing them in via package.json.
For every one that I bring in, I then have to go to systemjs.config.js and add an entry pointing to the module's entry point and often have to specify a default extension using blocks like this:
pointer
'mtgsdk': 'npm:mtgsdk/lib/index.js',
'request-promise': 'npm:request-promise/lib/rp.js',
'ramda': 'npm:ramda/dist/ramda.js',
'emitter20': 'npm:emitter20/index.js',
'bluebird': 'npm:bluebird/js/browser/bluebird.js',
'request': 'npm:request/index.js'
default extension
'request-promise':
{
defaultExtension: 'js'
}
I'm not sure if that's the right approach though because the more dependencies I add, the more that I end up requiring. At one point I had literally gotten up to 50 extra dependencies added because every time I launched, the browser console would find more that were needed.
Is there any easier way to load all of these in?
Also, some of them (such as tough-cookie and request-promise-core) were very problematic to load and I couldn't get the browser console to stop complaining about them. Finally, some of them seemed very basic such as url, http, https. Those seem like they should already be present.
Using systemjs was utilized in the previous versions of Angular 2, However Angular 2 has evolved to Angular 4, with super new features like Angular CLI.
I recommend your use Angular CLI, with #angular/cli.
Importing Node modules
Since mtgsdk is a node-module, you can easily import it using
import * as mtg from 'mtgsdk'
However for your program to compile, you must install a type definition for it. or declare one for it in /typings.json or your app might not build.
Importing Client Scripts
For client scripts like firebase.js you won't need to add client scripts as entries in systemjs.config.js again.
Using #angular/cli, you would easily add them in the scripts[] array in your angular-cli.json for automatic compilation.
Then access them like this
declare const firebase: any;
Here is a quickstart tutorial to set up Angular with #angular/cli.

Phonegap Plugin not working (cordova-plugin-purchase)

My first Phonegap App. Everything working well except for plugins. I'm trying to install the cordova-plugin-purchase Plugin.
https://github.com/j3k0/cordova-plugin-purchase
I've followed the instructions. And when I run "phonegap plugins" in the console it shows the plugin as being installed.
According to the documentation, there is suppose to be a "store" object that I can reference. I set up the following code to test if it's working:
try {
store.register({
id: "my.reverse.item.example",
alias: "example name",
type: store.CONSUMABLE
});
} catch(err) {
alert(err);
}
On my real project, I have the real info in when registering the product, but I can't even get that far. In my TryCatch it returns the following alert:
"Can't find variable: store".
So it seems that the plugin isn't even installed correct. I'm not to phonegap plugins, so there's probably something very basic that I'm missing. Do I have to include a link to the plugin JS in my index.html file?
I ended up figuring out the problem. It seems to be that I didn't include the cordova.js file in my index.html. I don't see why I needed to do that since I've read over and over that you don't need to manually add the cordova files to your html files.
So the plugin works now and I can receive the store data that I setup using the cordova-plugin-purchase plugin tutorials.
Another thing to note once you actually have the plugin installed correctly:
The Bundle Identifier in Xcode needs to match the bundle ID for the In App purchases you are trying to connect to.

window.resolveLocalFileSystemURI is not a function

I created a web application that I need to convert to a mobile application, now all I have is html5/js/css files which means I don't have any www foder no platforms folder, not a cordova project ... I started first to build the app using cordova command lines, but I couldn't, I found many problems on that, I used then https://build.phonegap.com/ , and it works fine for me. In order to read the file, I have tried this code :
window.resolveLocalFileSystemURI("file:///android_asset/www/data/User.xml", function () {
alert("Success");
}, function () {
alert(" error ");
});
but, it didn't work. I added a try catch, the exception was :
window.resolveLocalFileSystemURI is not a function
Do i need to add something to my code to make it work ?
You need to install a plugin for this to work.
Basically, run "cordova plugin add org.apache.cordova.file" at your application's root directory.
For detailed instructions see here, under "Accessing the Feature":
http://docs.phonegap.com/en/edge/cordova_file_file.md.html#LocalFileSystem
UPDATE 2019
The correct way to add this plugin is now with this command in your project root:
cordova plugin add cordova-plugin-file
This is a core cordova plugin. Documentation found here on npm

Categories

Resources