Home

Awesome

cycle-electron-driver

The cycle-electron-driver module provides Cycle.js drivers for building Electron apps.

API mappings

If you are already familiar with the electron API, here's a map of its interface to drivers:

Drivers

AppConfigDriver

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)
});

source

The source for the driver is an object with the following structure.

sink

The sink for the driver is an observable of objects describing the configuration settings to change. The following structure is supported:

AppEventsDriver

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:

AppLifecycleDriver

AppLifecycleDriver provides visibility into application lifecycle events & the ability to affect the app lifecycle.

Sources

The source object has the following properties:

Sink

The sink for AppLifecycleDriver should provide objects describing the desired lifecycle state & behavior of the app. The following properties are supported:

PropertyDefaultDescription
state'started'Set to 'quitting' to initiate a quit event, 'exiting' to force an exit
exitCode0If state is set to 'exiting', sends this as the exit code
isQuittingEnabledtrueIf false, before-quit events will be cancelled
isAutoExitEnabledtrueIf false, will-quit events will be cancelled

AppMetadataDriver

AppMetadataDriver provides a source observable of objects describing the app. The objects have the following properties:

AppVisibilityDriver

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

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:

Sink objects must be provided for each source event and must have the following properties:

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

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:

Sink objects should have these properties:

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

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:

Sink objects must be provided for each source event and must contain the following properties:

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

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:

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)
});

Main process driver

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)
});

Options

When constructing the main process driver, an optional second argument can provide the following options:

Sources

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$
platformInfo

The platformInfo object provides the following information about the runtime platform:

events

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.

events.extraLaunch$

When the isSingleInstance option is true, this observable indicates when blocked additional launches are attempted. Values are objects with the following properties:

badgeLabel$

This Observable gives the current and future badge labels of the OS X dock icon.

Sinks

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$
pathUpdates

Provide one of the following sinks to change the file path used by electron:

newChromiumParam$

The newChromiumParam$ sink should produce objects with the following properties:

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.

dock

The dock property is a container for multiple OSX-specific sinks.

bounce

The bounce property of dock has the following observable properties:

visibility$

This Observable should contain boolean values; true values will cause the dock icon to show, false to hide.

badgeLabel$

This sink causes the OS X badge label to be updated.

menu$

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.

icon$

This sink sets the icon in the OS X dock. Values should be
NativeImage objects.

ntlmAllowedOverride$

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.

appUserModelId$

This causes the Windows Application User Model ID to change to the values of the Observable.