enigma.js

v2.7.2

JavaScript library for consuming Qlik backend services

Function used to create a QIX session.

Parameters

config

The enigma.js configuration object.

Returns

The QIX Engine session object

Example minimal session creation

const enigma = require('enigma.js');
const schema = require('enigma.js/schemas/12.20.0.json');
const WebSocket = require('ws');
const config = {
  schema,
  url: 'ws://localhost:9076/app/engineData',
  createSocket: url => new WebSocket(url),
};
const session = enigma.create(config);

Function used to build an URL.

Parameters

urlConfig

This object describes the configuration that is sent into buildUrl(config).

Returns

string

Returns the websocket URL.

Example of building and using a Qlik Sense-compatible WebSocket URL

const enigma = require('enigma.js');
const schema = require('enigma.js/schemas/12.20.0.json');
const SenseUtilities = require('enigma.js/sense-utilities');
const url = SenseUtilities.buildUrl({ host: 'my-sense-host', appId: 'some-app' });
const session = enigma.create({ schema, url });

This is a list of error codes that can be thrown from enigma.js API calls.

Properties

NOT_CONNECTED
default=-1
number

You're trying to send data on a socket that's not connected

OBJECT_NOT_FOUND
default=-2
number

The object you're trying to fetch does not exist

EXPECTED_ARRAY_OF_PATCHES
default=-3
number

Unexpected RPC response, expected array of patches

PATCH_HAS_NO_PARENT
default=-4
number

Patchee is not an object we can patch

ENTRY_ALREADY_DEFINED
default=-5
number

This entry is already defined with another key

NO_CONFIG_SUPPLIED
default=-6
number

You need to supply a configuration

PROMISE_REQUIRED
default=-7
number

There's no promise object available (polyfill required?)

SCHEMA_STRUCT_TYPE_NOT_FOUND
default=-8
number

The schema struct type you requested does not exist

SCHEMA_MIXIN_CANT_OVERRIDE_FUNCTION
default=-9
number

Can't override this function

SCHEMA_MIXIN_EXTEND_NOT_ALLOWED
default=-10
number

Extend is not allowed for this mixin

SESSION_SUSPENDED
default=-11
number

Session suspended - no interaction allowed

SESSION_NOT_ATTACHED
default=-12
number

onlyIfAttached supplied, but you got SESSION_CREATED

Handling an enigma.js error

const { NOT_CONNECTED } = require('enigma.js/error-codes');
try {
  const layout = await model.getLayout();
} catch (err) {
  if (err.code === NOT_CONNECTED) {
    console.log('Tried to communicate on a session that is closed');
  }
}

API

interface

The API for generated APIs depends on the QIX Engine schema you pass into your Configuration, and on what QIX struct the API has.

All API calls made using the generated APIs will return promises which are either resolved or rejected depending on how the QIX Engine responds.

Properties

id
string

Contains the unique identifier for this API.

type
string

Contains the schema class name for this API.

genericType
string

Corresponds to the qInfo.qType property on the generic object's properties object.

session

The QIX Engine session object

handle
number

Contains the handle QIX Engine assigned to the API. Used interally in enigma.js for caches and JSON-RPC requests.

Example using `global` and `generic object` struct APIs

global.openDoc('my-document.qvf').then((doc) => {
  doc.createObject({ qInfo: { qType: 'my-object' } }).then(api => { });
  doc.getObject('object-id').then(api => { });
  doc.getBookmark('bookmark-id').then(api => { });
});

Handle changes on the API. The changed event is triggered whenever enigma.js or QIX Engine has identified potential changes on the underlying properties or hypercubes and you should re-fetch your data.

Bind the `changed` event

api.on('changed', () => {
  api.getLayout().then(layout => { });
});

Handle closed API. The closed event is triggered whenever QIX Engine considers an API closed. It usually means that it no longer exist in the QIX Engine document or session.

Bind the `closed` event

api.on('closed', () => {
  console.log(api.id, 'was closed');
});

Handle JSON-RPC requests/responses for this API. Generally used in debugging purposes. traffic:* will handle all websocket messages, traffic:sent will handle outgoing messages and traffic:received will handle incoming messages.

Bind the traffic events

// bind both in- and outbound traffic to console.log:
api.on('traffic:*', console.log);
// bind outbound traffic to console.log:
api.on('traffic:sent', console.log);
// bind inbound traffic to console.log:
api.on('traffic:received', console.log);

Configuration

interface

The enigma.js configuration object.

Properties

schema
Object

Object containing the specification for the API to generate. Corresponds to a specific version of the QIX Engine API.

url
string

String containing a proper websocket URL to QIX Engine.

Promise
optional
Object

ES6-compatible Promise library.

suspendOnClose
optional
boolean

Set to true if the session should be suspended instead of closed when the websocket is closed.

mixins
optional, default=[]

Mixins to extend/augment the QIX Engine API. Mixins are applied in the array order.

requestInterceptors
optional, default=[]
Array

Interceptors for augmenting requests before they are sent to QIX Engine. Interceptors are applied in the array order.

responseInterceptors
optional, default=[]
Array

Interceptors for augmenting responses before they are passed into mixins and end-users. Interceptors are applied in the array order.

protocol
optional, default={}

An object containing additional JSON-RPC request parameters.

Example defining a configuration object

const enigma = require('enigma.js');
const WebSocket = require('ws');
const bluebird = require('bluebird');
const schema = require('enigma.js/schemas/12.20.0.json');

const config = {
 schema,
 url: 'ws://localhost:4848/app/engineData',
 createSocket: url => new WebSocket(url),
 Promise: bluebird,
 suspendOnClose: true,
 mixins: [{ types: ['Global'], init: () => console.log('Mixin ran') }],
 protocol: { delta: false },
};

enigma.create(config).open().then((global) => {
  // global === QIX global interface
  process.exit(0);
});

A function to use when instantiating the WebSocket, mandatory for Node.js.

extendsError

Error containing a custom error code.

Properties

code
number

The error code as defined by errorCodes

enigmaError
default=true
boolean

No description

Interceptor

interface

Interceptors is a concept similar to mixins, but run on a lower level. The interceptor concept can augment either the requests (i.e. before sent to QIX Engine), or the responses (i.e. after QIX Engine has sent a response). The interceptor promises runs in parallel to the regular promises used in enigma.js, which means that it can be really useful when you want to normalize behaviors in your application.

Implement a request interceptor

const enigma = require('enigma.js');
const WebSocket = require('ws');
const schema = require('enigma.js/schemas/12.20.0.json');

const session = enigma.create({
  schema,
  url: 'ws://localhost:9076/app/engineData',
  createSocket: (url) => new WebSocket(url),
  requestInterceptors: [{
    onFulfilled: function logRequest(sessionReference, request) {
      console.log('Request being sent', request);
      return request;
    }
  },
});

This method is invoked when a request is about to be sent to QIX Engine.

Parameters

session

The QIX Engine session object

request
Object

The JSON-RPC request that will be sent.

Implement a request interceptor

const enigma = require('enigma.js');
const WebSocket = require('ws');
const schema = require('enigma.js/schemas/12.20.0.json');

const session = enigma.create({
  schema,
  url: 'ws://localhost:9076/app/engineData',
  createSocket: (url) => new WebSocket(url),
  responseInterceptors: [{
    onRejected: function logError(sessionReference, request, error) {
      console.log('Error returned from QIX engine', error, 'Originating request:', request);
      // throw error so it's continued to be rejected:
      throw error;
    }
  },
});

This method is invoked when a promise has been successfully resolved, use this to modify the result or reject the promise chain before it is sent to mixins.

Parameters

session

The QIX Engine session object

request
Object

The JSON-RPC request resulting in this response.

result
Object

Whatever the previous interceptor is resolved with.

This method is invoked when a previous interceptor has rejected the promise, use this to handle for example errors before they are sent into mixins.

Parameters

session

The QIX Engine session object

request
Object

The JSON-RPC request resulting in this error.

error
Object

Whatever the previous interceptor is rejected with.

Mixin

interface

The mixin concept allows you to add or override QIX Engine API functionality. A mixin is basically a JavaScript object describing which types it modifies, and a list of functions for extending and overriding the API for those types.

QIX Engine types like for example GenericObject, Doc, GenericBookmark, are supported but also custom GenericObject types such as barchart, story and myCustomType. An API will get both their generic type as well as custom type mixins applied.

Mixins that are bound to several different types can find the current API type in the genericType or type members. this.type would for instance return GenericObject and this.genericType would return barchart.

See the Mixins examples on how to use it, below is an outline of what the mixin API consists of.

Properties

types
string | Array<string>

String or array of strings containing the API-types that will be mixed in.

extend
optional
Object

Object literal containing the methods that will be extended on the specified API.

override
optional
Object

Object literal containing the methods to override existing methods.

Mixininit

function

Init function that, if defined, will run when an API is instantiated. It runs with Promise and API object as parameters

This object describes the configuration that is sent into buildUrl(config).

Properties

appId
optional
string

The app id. If omitted, only the global object is returned. Otherwise both global and app object are returned.

noData
optional
boolean

Whether to open the app without data.

secure
optional, default=true
boolean

Set to false if an unsecure WebSocket should be used.

host
optional
string

Host address.

port
optional
number

Port to connect to.

prefix
optional, default='"/"'
string

The absolute base path to use when connecting. Used for proxy prefixes.

subpath
optional, default='""'
string

The subpath.

route
optional, default='""'
string

Used to instruct Proxy to route to the correct receiver.

identity
optional, default='""'
string

Identity to use.

urlParams
optional, default={}
Object

Used to add parameters to the WebSocket URL.

ttl
optional
number

A value in seconds that QIX Engine should keep the session alive after socket disconnect (only works if QIX Engine supports it).

The QIX Engine session object

Handle closed state. This event is triggered when the underlying websocket is closed and config.suspendOnClose is false.

Handling session closed

session.on('closed', () => {
  console.log('Session was closed, clean up!');
});

Handle all JSON-RPC notification event, 'notification:*. Or handle a specific JSON-RPC notification event, 'notification:OnConnected'. These events depend on the product you use QIX Engine from.

Bind the notification events

// bind all notifications to console.log:
session.on('notification:*', console.log);
// bind a specific notification to console.log:
session.on('notification:OnConnected', console.log);

Handle opened state. This event is triggered whenever the websocket is connected and ready for communication.

Bind the session opened event

session.on('opened', () => {
  console.log('Session was opened');
});

Handle resumed state. This event is triggered when the session was properly resumed. It is useful in scenarios where you for example can close blocking modal dialogs and allow the user to interact with your application again.

Handling session resumed

session.on('resumed', () => {
  console.log('Session was resumed, we can close that "reconnecting" dialog now');
});

Handle suspended state. This event is triggered in two cases (listed below). It is useful in scenarios where you for example want to block interaction in your application until you are resumed again. If config.suspendOnClose is true and there was a network disconnect (socked closed) or if you ran session.suspend().

Parameters

evt

Event object.

Handling session suspended

session.on('suspended', () => {
  console.log('Session was suspended, retrying...');
  session.resume();
});

Handle websocket messages. Generally used in debugging purposes. traffic:* will handle all websocket messages, traffic:sent will handle outgoing messages and traffic:received will handle incoming messages.

Bind the traffic events

// bind both in- and outbound traffic to console.log:
session.on('traffic:*', console.log);
// bind outbound traffic to console.log:
session.on('traffic:sent', console.log);
// bind inbound traffic to console.log:
session.on('traffic:received', console.log);
emitsclosed

Closes the websocket and cleans up internal caches, also triggers the closed event on all generated APIs. Note that you have to manually invoke this when you want to close a session and config.suspendOnClose is true.

Parameters

code
optional, default=1000
number

The reason code for closing the connection.

reason
optional, default='""'
string

The human readable string describing why the connection is closed.

Returns

Promise<Object>

Eventually resolved when the websocket has been closed.

Closing a session

session.close().then(() => {
  console.log('Session was closed');
});
emitsopened

Establishes the websocket against the configured URL and returns the Global instance.

Returns

Promise<Object>

Eventually resolved if the connection was successful.

Opening a sesssion

session.open().then(() => {
  console.log('Session was opened');
});
emitsresumed

Resumes a previously suspended enigma.js session by re-creating the websocket and, if possible, re-open the document as well as refreshing the internal cashes. If successful, changed events will be triggered on all generated APIs, and on the ones it was unable to restore, the closed event will be triggered.

Parameters

onlyIfAttached
boolean

If true, resume only if the session was re-attached properly.

Returns

Promise<Object>

Eventually resolved when the websocket (and potentially the previously opened document, and generated APIs) has been restored, rejected when it fails any of those steps, or when onlyIfAttached is true and a new session was created.

Resuming a session

session.resume(true).then(() => {
  console.log('Session was resumed by re-attaching');
});

Function used to send data on the RPC socket.

Parameters

request
Object

The request to be sent. (data and some meta info)

Returns

Object

Returns a promise instance.

Suspends the enigma.js session by closing the websocket and rejecting all method calls until is has been resumed again.

Parameters

code
optional, default=4000
number

The reason code for suspending the connection.

reason
optional, default='""'
string

The human readable string describing why the connection is suspended.

Returns

Promise<Object>

Eventually resolved when the websocket has been closed.

Suspending a session

session.suspend().then(() => {
  console.log('Session was suspended');
});