Table of contents
- API documentation
Returns a session.
See Configuration for the configuration options.
Example:
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);
This section describes the configuration object that is sent into enigma.create(config)
.
Property | Type | Optional | Default | Description |
---|---|---|---|---|
schema |
Object | No | Object containing the specification for the API to generate. Corresponds to a specific version of the QIX Engine API. | |
url |
String | No | String containing a proper websocket URL to QIX Engine. | |
createSocket |
Function | In browser | A function to use when instantiating the WebSocket, mandatory for Node.js. | |
Promise |
Promise | Yes | Promise |
ES6-compatible Promise library. |
suspendOnClose |
Boolean | Yes | false |
Set to true if the session should be suspended instead of closed when the websocket is closed. |
mixins |
Array | Yes | [] |
Mixins to extend/augment the QIX Engine API. See Mixins section for more information how each entry in this array should look like. Mixins are applied in the array order. |
requestInterceptors |
Array | Yes | [] |
Interceptors for augmenting requests before they are sent to QIX Engine. See Interceptors section for more information how each entry in this array should look like. Interceptors are applied in the array order. |
responseInterceptors |
Array | Yes | [] |
Interceptors for augmenting responses before they are passed into mixins and end-users. See Interceptors section for more information how each entry in this array should look like. Interceptors are applied in the array order. |
protocol |
Object | Yes | {} |
An object containing additional JSON-RPC request parameters. |
protocol.delta |
Boolean | Yes | true |
Set to false to disable the use of the bandwidth-reducing delta protocol. |
Example:
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);
});
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.
This function will be executed for each generated API.
See below what args
contains.
Property | Type | Description |
---|---|---|
config |
Object | A reference to the enigma.js configuration object, including default values. |
api |
Object | The newly generated API instance. |
mixin.extend
is an object containing methods to extend the generated API with. These method names cannot already exist or
enigma.js will throw an error.
mixin.override
is an object containing methods that overrides existing API methods. These method names needs to exist already* or
engima.js will throw an error. Be careful when overriding, you may break expected behaviors in other mixins or your
application.
base
is a reference to the previous mixin method, can be used to invoke the mixin chain before this mixin method.
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.
See the Interceptor examples on how to use it, below is an outline of what the interceptor API consists of.
This method is invoked when a request is about to be sent to QIX Engine.
session
refers to the session executing the interceptor.
request
is the JSON-RPC request that will be sent.
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.
session
refers to the session executing the interceptor.
request
is the JSON-RPC request resulting in this error. You may use .retry()
to retry sending it to QIX Engine.
error
is whatever the previous interceptor rejected with.
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.
session
refers to the session executing the interceptor.
request
is the JSON-RPC request resulting in this response.
result
is whatever the previous interceptor resolved with.
You retrieve a session by calling enigma.create(config)
.
The session.config
property contains a reference to the configuration object used by the session. Default values for optional parameters will be filled in.
Returns a promise.
Establishes the websocket against the configured URL. Eventually resolved with the QIX global interface when the connection has been established.
Example:
session.open().then((global) => {
global.openDoc('my-document.qvf');
});
Returns a promise.
Closes the websocket and cleans up internal caches, also triggers the closed
event on all generated APIs.
Eventually resolved when the websocket has been closed.
Note: you need to manually invoke this when you want to close a session and
config.suspendOnClose
is true
.
Example:
session.close().then(() => console.log('Session was properly closed'));
Returns a promise.
Suspends the enigma.js session by closing the websocket and rejecting all method calls until it has been resumed again.
Example:
session.suspend().then(() => console.log('We are now suspended'));
Returns a promise.
Resume a previously suspended enigma.js session by re-creating the websocket and,
if possible, re-open the document as well as refreshing the internal caches. 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.
onlyIfAttached
can be used to only allow resuming if the QIX Engine session
was reattached properly.
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 QIX Engine session
was created.
Example:
// assuming suspended state:
doc.on('changed', () => console.log('Document was restored'));
object.on('changed', () => console.log('model1 was restored'));
sessionObject.on('closed', () => console.log('Session object could not be restored (new QIX Engine session)'));
session.resume().then(() => console.log('Session was properly resumed'));
Handle opened state. This event is triggered whenever the websocket is connected and ready for communication.
Example:
session.on('opened', () => console.log('We are connected'));
Handle closed state. This event is triggered when the underlying websocket is closed
and config.suspendOnClose
is false
.
Example:
session.on('closed', () => console.log('The session was closed'));
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
istrue
and there was a network disconnect (socked closed) - If you ran
session.suspend()
Example:
session.on('suspended', (evt) => console.log(evt.initiator));
The evt.initiator
value is a string indicating what triggered the suspended state.
Possible values: network
, manual
.
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.
Example:
session.on('resumed', () => console.log('The session was resumed'));
Handle a specific JSON-RPC notification event. These events depend on the product you use QIX Engine from.
Example:
session.on('notification:OnConnected', (data) => console.log(data));
Read more:
Handle all JSON-RPC notification events.
Example:
session.on('notification:*', (eventName, data) => console.log(eventName, data));
Handle outgoing websocket messages.
Generally used in debugging purposes.
Example:
session.on('traffic:sent', (req) => console.log(req));
Handle incoming websocket messages.
Generally used in debugging purposes.
Example:
session.on('traffic:received', (res) => console.log(res));
Handle all websocket messages.
Generally used in debugging purposes.
Example:
session.on('traffic:*', (direction, msg) => console.log(direction, msg));
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.
Read more: Generic object model
Example:
global.openDoc('my-document.qvf').then((doc) => {
doc.createObject({ qInfo: { qType: 'my-object' } }).then(api => { /* do something with api */ });
doc.getObject('object-id').then(api => { /* do something with api */ });
doc.getBookmark('bookmark-id').then(api => { /* do something with api */ });
});
The requestId
property is injected onto promises that enigma.js returns to give you better
control in scenarios like cancelling heavy calculation requests and the like.
Read more: JSON-RPC protocol
Example of cancelling a request:
const request = doc.evaluate('SUM([myfield]');
global.cancelRequest(request.requestId);
request.catch(() => {
console.log('Evaluation was cancelled.');
});
This property contains the unique identifier for this API.
Example:
doc.getObject('object-id').then((api) => {
// api.id === 'object-id'
});
This property contains the schema class name for this API.
Example:
doc.getObject('object-id').then((api) => {
// api.type === 'GenericObject'
});
Despite the name, this property corresponds to the qInfo.qType
property on your generic object's properties object.
Example:
doc.getObject('object-id').then((api) => {
// api.genericType === 'linechart'
});
This property contains a reference to the session
that this
API belongs to.
Example:
doc.session.suspend();
This property contains the handle QIX Engine assigned to the API. Used internally in enigma.js for caches and JSON-RPC requests.
Example:
doc.getObject('object-id').then((api) => {
// typeof api.handle === 'number'
});
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.
Example:
api.on('changed', () => {
api.getLayout().then(layout => /* do something with the new 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.
Example:
api.on('closed', () => {
/* do something in your application, perhaps route your user to an overview page */
});
Handle outgoing websocket messages for a specific generated API.
Generally used in debugging purposes.
Example:
api.on('traffic:sent', (req) => console.log(req));
Handle incoming websocket messages for a specific generated API.
Generally used in debugging purposes.
Example:
api.on('traffic:received', (res) => console.log(res));
Handle all websocket messages for a specific generated API.
Generally used in debugging purposes.
Example:
api.on('traffic:*', (direction, msg) => console.log(direction, msg));
The Sense Utilities API is a standalone module delivered with enigma.js. It can be used to generate Qlik Sense websocket URLs using a configuration, similar to how enigma.js worked in version 1.
This section describes the configuration object that is sent into SenseUtilities.buildUrl(config)
.
Property | Type | Optional | Default | Description |
---|---|---|---|---|
host |
String | Yes | localhost |
|
port |
Number | Yes | 443 or 80 |
Default depends on secure . |
secure |
Boolean | Yes | true |
Set to false to use an unsecure WebSocket connection (ws:// ). |
urlParams |
Object | Yes | {} |
Additional parameters to be added to WebSocket URL. |
prefix |
String | Yes | Absolute base path to use when connecting, used for proxy prefixes. | |
appId |
String | Yes | The ID of the app intended to be opened in the session. | |
route |
String | Yes | Initial route to open the WebSocket against, default is app/engineData . |
|
subpath |
String | Yes | Subpath to use, used to connect to dataprepservice in a server environment. | |
identity |
String | Yes | Identity (session ID) to use. | |
ttl |
Number | Yes | A value in seconds that QIX Engine should keep the session alive after socket disconnect (only works if QIX Engine supports it). |
Returns a string (websocket URL).
See Configuration for the configuration options.
Example in browser (commonjs syntax):
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 });
There are multiple types of errors that can occur, native WebSocket errors (See CloseEvent),
QIX errors and native enigma.js errors. For the enigma.js errors, you can import enigma.js/error-codes.js
or refer to the list below.
All native enigma.js errors have the property Error.enigmaError = true
. These may occur thrown or in rejected promises.
Property | Code | Description |
---|---|---|
NOT_CONNECTED |
-1 |
You're trying to send data on a socket that's not created |
OBJECT_NOT_FOUND |
-2 |
The object you're trying to fetch does not exist |
EXPECTED_ARRAY_OF_PATCHES |
-3 |
Unexpected RPC response, expected array of patches |
PATCH_HAS_NO_PARENT |
-4 |
Patchee is not an object we can patch |
ENTRY_ALREADY_DEFINED |
-5 |
This entry is already defined with another key |
NO_CONFIG_SUPPLIED |
-6 |
You need to supply a configuration |
PROMISE_REQUIRED |
-7 |
There's no promise object available (polyfill required?) |
SCHEMA_STRUCT_TYPE_NOT_FOUND |
-8 |
The schema struct type you requested does not exist |
SCHEMA_MIXIN_CANT_OVERRIDE_FUNCTION |
-9 |
Can't override this function |
SCHEMA_MIXIN_EXTEND_NOT_ALLOWED |
-10 |
Extend is not allowed for this mixin |
SESSION_SUSPENDED |
-11 |
Session suspended - no interaction allowed |
SESSION_NOT_ATTACHED |
-12 |
onlyIfAttached supplied, but you got SESSION_CREATED |