The cycle-electron-driver module provides Cycle.js drivers for building Electron apps.
If you are already familiar with the electron API, here's a map of its interface to drivers:
- app
- events
will-finish-launching- AppLifecycleDriverready- AppLifecycleDriverwindow-all-closed- AppLifecycleDriverbefore-quit- AppLifecycleDriverwill-quit- AppLifecycleDriverquit- AppLifecycleDriveropen-file- AppEventsDriveropen-url- AppEventsDriveractivate- AppEventsDriverbrowser-window-blur- AppEventsDriverbrowser-window-focus- AppEventsDriverbrowser-window-created- AppEventsDrivercertificate-error- CertErrorOverrideDriverselect-client-certificate- ClientCertDriverlogin- BasicAuthDrivergpu-process-crashed- AppEventsDriver
- methods
quit- AppLifecycleDriverexit- AppLifecycleDriverhide- AppVisibilityDrivershow- AppVisibilityDrivergetAppPath- AppConfigDrivergetPath- AppConfigDriversetPath- AppConfigDrivergetVersion- AppMetadataDrivergetName- AppMetadataDrivergetLocale- AppMetadataDriveraddRecentDocument- RecentDocsDriverclearRecentDocuments- RecentDocsDriversetUserTasks- AppConfigDriver
- events
AppConfigDriver enables the getting/setting of configuration used by your app.
import { join } from 'path';
import { app } from 'electron';
import { AppPathsDriver } from 'cycle-electron-driver';
Cycle.run(({ config: { appPaths } }) => ({
appPaths: appPaths.appData$.map(dataPath => ({ downloads: join(dataPath, 'downloads') }))
}), {
config: AppConfigDriver(app)
});The source for the driver is an object with the following structure.
allowNTMLForNonIntranet$- Gives the currentallowNTMLForNonIntranetconfig setting.paths- An object with observable properties that match the electron path names with the idiomatic$suffix (e.g.home$,appData$). Additionally, anapp$property gives access to app.getAppPath().task$- An observable ofTaskarrays.
The sink for the driver is an observable of objects describing the configuration settings to change. The following structure is supported:
allowNTMLForNonIntranet- If set totrue, enable NTLM auth for all domains. Otherwise, only intranet sites.paths- An object with properties matching the electron path names. Only the specified paths are changed.tasks: An array ofTaskobjects (Windows only). These have the following properties:program- The application executable; useprocess.execPathto use the currently-executing app executable.arguments- An array of strings to use as program argumentstitle- The title to give the taskdescription- The full description of the taskiconPath- Path to the icon to show for the taskiconIndex- IficonPathcontains multiple icons, the index of the icon to use for the task
AppEventsDriver provides access to electron app events. It provides a source observable containing all events.
To create the driver, simply call the constructor with the electron app:
import Cycle from '@cycle/core';
import { app } from 'electron';
Cycle.run(({ appEvent$ }) => ({
fileOpen$: appEvent$.filter(e => e.type === 'file-open')
}), {
appEvent$: AppEventsDriver(app)
});These events have a type property that matches
the names of the electron events. Additional
event arguments are normalized into the event object properties as follows:
open-file-pathopen-url-urlactivate-hasVisibleWindowsbrowser-window-blur-windowbrowser-window-focus-windowbrowser-window-created-windowcertificate-error-webContents,url,error,certificatelogin-webContents,request,authInfo
AppLifecycleDriver provides visibility into application lifecycle events & the ability to affect the app lifecycle.
The source object has the following properties:
- willFinishLaunching$ - will-finish-launching events
- ready$ - will-finish-launching events
- windowAllClosed$ - window-all-closed events
- beforeQuit$ - before-quit events
- willQuit$ - will-quit events
- quit$ - quit events. These contain an additional
exitCodeproperty.
The sink for AppLifecycleDriver should provide objects describing the desired lifecycle state & behavior of the app.
The following properties are supported:
| Property | Default | Description |
|---|---|---|
state |
'started' |
Set to 'quitting' to initiate a quit event, 'exiting' to force an exit |
exitCode |
0 | If state is set to 'exiting', sends this as the exit code |
isQuittingEnabled |
true |
If false, before-quit events will be cancelled |
isAutoExitEnabled |
true |
If false, will-quit events will be cancelled |
AppMetadataDriver provides a source observable of objects describing the app. The objects have the following
properties:
nameversionlocale
AppVisibilityDriver consumes a sink of boolean values that show/hide the application's windows (OS X only).
import { app } from 'electron';
import { AppVisibilityDriver } from 'cycle-electron-driver';
Cycle.run(() => {
// ...
return {
visibility$: appState$.map(state => state.shouldHide)
};
}, {
visibility$: AppVisibilityDriver(app)
});BasicAuthDriver provides a source of HTTP basic auth prompts and consumes objects that provide the response
credentials.
import { app } from 'electron';
import { BasicAuthDriver } from 'cycle-electron-driver';
Cycle.run(({ login$ }) => ({
login$: login$.map(e => ({
event: e,
username: 'someuser',
password: 's0m3Pa$sw0rd'
}))
}), {
login$: BasicAuthDriver(app)
});Source events are based on electron login events have the following properties:
webContents- The contents of the window that received the promptrequest- Information about the HTTP request that received the promptauthInfo- Information about the auth prompt
Sink objects must be provided for each source event and must have the following properties:
event- The source event that is being responded tousernamepassword
If you do not use this driver, then the auth prompts are automatically cancelled. Use AppEventsDriver
and watch for events of type login if you only want to observe these failed logins.
CertErrorOverrideDriver provides a source observable of events indicating when verification of a server's SSL
certificate has failed, and consumes a sink observable of objects indicating whether the certificate rejection should
be overridden. This driver should only rarely be needed, but it can be helpful for cases such as when you are using
a self-signed certificate during development and want your app to accept that certificate. For example:
import { app } from 'electron';
import { CertErrorOverrideDriver } from 'cycle-electron-driver';
Cycle.run(({ certErr$ }) => ({
certErr$: certErr$.map(e => ({ event: e, allow: e.certificate.issuerName === 'My Test CA' }));
}), {
certErr$: CertErrorOverrideDriver(app);
});The source objects are based on electron certificate-error events and have the following properties:
webContents- The contents of the window that received the errorurl- The URL being requestederror- The error codecertificate.data- A buffer containing the PEM-formatted certificatecertificate.issuerName- The issuer of the certificate
Sink objects should have these properties:
event- The source event representing the certificate errorallow- A booleantrueorfalse. Iftrue, the SSL request will be allowed to continue. Else it will fail.
You must have one object for each source event; otherwise the driver does not know whether the certificate error should
cause the SSL requests to succeed or fail. If you do not want to override any certificate errors, do not use this
driver. If you only want to be notified when these events occur, filter the AppEventsDriver events by type
certificate-error.
ClientCertDriver provides a source observable containing client SSL cert request events and consumes an observable
of client certificate selection objects.
import { app } from 'electron';
import { ClientCertDriver } from 'cycle-electron-driver';
Cycle.run(({ certSelection$ }) => ({
certSelection$: certSelection$.map(e => ({
event: e,
cert: e.certificateList.find(cert => cert.issuerName === 'My Issuer')
}));
}), {
certSelection$: ClientCertDriver(app);
});Source event objects are based on electron select-client-certificate events and have the following properties:
webContents- The contents of the window that received the certificate prompturl- The URL that requested the certificatecertificateList- An array of available certificates, each of which have the following properties:data- PEM-encoded bufferissuerName- Issuer’s Common Name
Sink objects must be provided for each source event and must contain the following properties:
event- The source event representing the certificate promptcert- One of the objects from the source event'scertificateListproperty
Do not use this driver if you want to keep the default electron behavior of always selecting the first client
certificate. If you only wish to be notified when client certificates are being selected with the default behavior,
use the AppEventsDriver and filter where type equals select-client-certificate.
RecentDocsDriver provides a sink for changing the recent documents of the app. Each object in the observable should
contain one or more of the following properties:
clear- If set totrue, the recent documents list for the app is cleared.add- If set to a string, the path to a document to add to the recent documents list.
import Cycle from '@cycle/core';
import { app } from 'electron';
import { RecentDocsDriver } from 'cycle-electron-driver';
Cycle.run(() => {
//...
return {
recentDoc$: model.openedDoc$.map(doc => ({ add: doc }))
}
}), {
recentDoc$: RecentDocsDriver(app)
});To create the driver for the main process, call the MainDriver function with the Electron app:
import Cycle from '@cycle/core';
import { app } from 'electron';
import { MainDriver } from 'cycle-electron-driver';
function main(sources) {
//...
}
Cycle.run(main, {
electron: MainDriver(app)
});When constructing the main process driver, an optional second argument can provide the following options:
isSingleInstance- If set totrue, only one instance of the application can be created. TheextraLaunch$source will emit when additional launches are attempted. This defaults tofalse.
The source object provided by MainDriver contains multiple properties and observables, most of which you will never
need to use. To summarize the overall structure, it looks something like this:
platformInfo:
isAeroGlassEnabled
events() :: String -> Observable
extraLaunch$
beforeAllWindowClose$
beforeExit$
exit$
badgeLabel$
The platformInfo object provides the following information about the runtime platform:
isAeroGlassEnabled- (Windows only) whether DWM composition is enabled
The events source factory creates an Observable for raw
electron app events.
function main({ electron }) {
const readyEvent$ = electron.events('ready');
}Note that events documented with more than one parameter will be truncated; only the Event portion will be received.
It is recommended that you use one of the more normalized event sources listed below if you're handling an event.
When the isSingleInstance option is true, this observable indicates when blocked additional launches are attempted.
Values are objects with the following properties:
argv- Array of command-line arguments used when this was launchedcwd- The working directory of the process that was launched
This Observable gives the current and future badge labels of the OS X dock icon.
The sink for the driver should be an observable that produces an object containing multiple sink observables. Any of these sinks can be omitted if not needed. The object properties can be summarized as follows:
pathUpdates:
appData$
desktop$
documents$
downloads$
exe$
home$
module$
music$
pictures$
temp$
userData$
videos$
newChromiumParam$AppTasksDriver
dock:
bounce:
start$
cancel$
visibility$
badgeLabel$
menu$
icon$
ntlmAllowedOverride$
appUserModelId$
Provide one of the following sinks to change the file path used by electron:
appData$- The directory for application datadesktop$- The directory for the user's desktop filesdocuments$- The directory for the user's documentsdownloads$- The directory for the user's downloaded filesexe$- The path to the application executablehome$- The user's home directorymodule$- The path to thelibchromiumcontentlibrarymusic$- The directory for the user's music filespictures$- The directory for the user's image filestemp$- The directory for storing temporary datauserData$- The directory for storing user-specific application datavideos$- The directory for the user's video files
The newChromiumParam$ sink should produce objects with the following properties:
switches- AnArrayof objects with a requiredswitchand optionalvalueproperty to be appended to the Chromium parametersargs- AnArrayof strings that will be used for additional command-line arguments to Chromium
Note that these are write-only and cannot be undone. In other words, you cannot remove a switch or argument once it has been included.
The dock property is a container for multiple OSX-specific sinks.
The bounce property of dock has the following observable properties:
start$- This should be anObservableof objects with anidandtypeproperty. Thetypeproperty should be a string equalling eithercriticalorinformational.idis an arbitrary string that should be unique and kept track of if you wish to cancel the bounce at a later time. Otherwise, it may be omitted.cancel$- This should be anObservableof string IDs; these IDs should correlate to theidused in thestart$observable objects.
This Observable should contain boolean values; true values will cause the dock icon to show, false to hide.
This sink causes the OS X badge label to be updated.
This sink sets the menu in the OS X dock for the application. See the electron documentation for details on what these values should be.
This sink sets the icon in the OS X dock. Values should be
NativeImage objects.
This sink should be an Observable of boolean values; when true, NTLM authentication is enabled for sites not
recognized as being part of the local intranet.
This causes the Windows
Application User Model ID to change
to the values of the Observable.