lightstreamer-adapter
Version:
This package includes the resources needed to write Data Adapters and Metadata Adapters for Lightstreamer Server in a Node.js environment. The adapters will run in a separate process, communicating with the Server through the Adapter Remoting Infrastructu
336 lines (323 loc) • 19.8 kB
TypeScript
import { Stream } from 'node:stream';
import { EventEmitter } from 'node:events';
export class DataProvider extends EventEmitter {
/**
* Data provider constructor.<br>
* The created object allows you to interact with Lightstreamer Server through
* the Adapter Remoting Infrastructure protocol as a Remote Data Adapter.
* See the ARI Protocol documentation for details on the request and response
* messages.<br>
* This object extends the EventEmitter object and emits the following events:
* <ul>
* <li>init: function(request, response) {}<br/>
* Here, the request object is an associative array with the following content:
* {parameters: {<name 1>: <value 1> ... <name n>: <value n>}}</li>
* <li>subscribe: function(itemName, response) {}</li>
* <li>unsubscribe: function(itemName, response) {}</li>
* </ul>
* The response argument is a DataResponse object and one of its methods, error or success, must be called
* in order to reply to the request bound to the event.
* In case of a subscribe event, after calling the "success" callback, it is possible to invoke "update"
* or other item-related methods, or to predispose for future invocations when data is available.
* Then, upon an unsubscribe event, any existing such predisposition should be deactivated before calling
* the "success" callback.
* @class
* @param {Stream} stream the stream channel to the remote LS Proxy Data Adapter.
* In case of interruption, the 'error' event on the stream may report interruption cause details.
* @param {Function} [isSnapshotAvailable] optional callback that receives an itemName as argument and must return
* a boolean value asserting if the item supports snapshot. The default value is function(itemName) {return false;}
* @param {Object} [credentials] optional credentials to be submitted to the remote LS Proxy Data Adapter.
* The credentials are needed only if the Proxy Adapter is configured to require Remote Adapter authentication.
* If needed, the supplied object should contain both a "user" and a "password" field.
* @param {Number} [keepaliveInterval] optional time in milliseconds between subsequent keepalive packets
* to be sent on the reply stream to prevent LS Proxy Data Adapter and any intermediate nodes
* from closing the connection for inactivity; a value of 0 or negative means no keepalives; the default
* if not supplied is 10000 ms. However, if a stricter interval is requested by the Proxy Adapter
* on startup, it will be obeyed (with a safety minimum of 1 second). This should ensure that the
* Proxy Adapter activity checks will always succeed, but for some old versions of the Proxy Adapter.
* The keepalives can also allow for prompt detection of connection issues.
*/
constructor(stream: Stream, isSnapshotAvailable?: Function, credentials?: object, keepaliveInterval?: number);
/**
* Sends an update for a particular item to the remote LS proxy.
*
* @param {String} itemName the item name
* @param {Boolean} isSnapshot is it a snapshot?
* @param {Object} data an associative array of strings
* that represents the data to be published
*/
update(itemName: string, isSnapshot: boolean, data: object): DataProvider;
/**
* Sends an end of snapshot message for a particular item to the remote LS proxy.
*
* @param {String} itemName the item name
*/
endOfSnapshot(itemName: string): DataProvider;
/**
* Sends a clear snapshot message for a particular item to the remote LS proxy.
*
* @param {String} itemName the item name
*/
clearSnapshot(itemName: string): DataProvider;
/**
* Sends information about "diff" algorithms for some or all fields
* of a particular item. The algorithms suitable for each fields should be expressed
* as an array of string literals representing the actual algorithms in the desired order.
* Omitted fields or null arrays will add no information. On the other hand, an empty array
* can be supplied to mean that no "diff" algorithm is admitted for a field.
*
* @param {String} itemName the item name
* @param {Object} algorithmsMap an associative array of algorithm lists,
* in turn expressed as a (possibly empty) array of string literals.
* Supported literals are:<ul>
* <li>"JSONPATCH": Computes the difference between two values that are valid JSON
* string representations in JSON Patch format.</li>
* <li>"DIFF_MATCH_PATCH": Computes the difference between two values with Google's
* "diff-match-patch" algorithm (the result is then serialized with the custom
* "TLCP-diff" format). This algorithm applies to any strings, only provided that
* their UTF-16 representation doesn't contain surrogate pairs.</li>
* </ul>
*/
declareFieldDiffOrder(itemName: string, algorithmsMap: object): DataProvider;
/**
* Sends a failure message to the remote LS proxy.
*
* @param {String} exception the exception message
*/
failure(exception: string): DataProvider;
/**
* Returns the configured stream.
*
* @return Object the stream
*/
getStream(): Stream;
}
/**
* <p>An instance of this class is passed as argument to an event listener,
* and must be used to respond to the remote adapter request,
* using the success method or the error method.</p>
*/
export class DataResponse {
/**
* Sends a successful response.
*/
success(): void;
/**
* Sends an error response. The optional exception type parameter that can be used
* to issue a proper type of exception depends on the event handled as described in the following table:
* <ul>
* <li>init: "data"</li>
* <li>subscribe: "subscription"</li>
* <li>unsubscribe: "subscription"</li>
* </ul>
*
* @param {String} exceptionMessage exception message
* @param {String} [exceptionType] exception type
*/
error(exceptionMessage: string, exceptionType: string): void;
}
export class MetadataProvider extends EventEmitter {
/**
* Metadata provider constructor.<br>
* The created object allows you to interact with Lightstreamer Server through
* the Adapter Remoting Infrastructure protocol as a Remote Metadata Adapter.
* See the ARI Protocol documentation for details on the request and response
* messages.<br>
* This object extends the EventEmitter object and emits the following events:
* <ul>
* <li>init: function(request, response) {}</li>
* <li>getItemData: function(request, response) {}</li>
* <li>getUserItemData: function(request, response) {}</li>
* <li>getSchema: function(request, response) {}</li>
* <li>getItems: function(request, response) {}</li>
* <li>notifyUser: function(request, response) {}</li>
* <li>notifyUserAuth: function(request, response) {}</li>
* <li>notifyUserMessage: function(request, response) {}</li>
* <li>notifyNewSession: function(request, response) {}</li>
* <li>notifySessionClose: function(request, response) {}</li>
* <li>notifyNewTables: function(request, response) {}</li>
* <li>notifyTablesClose: function(request, response) {}</li>
* <li>notifyMpnDeviceAccess: function(request, response) {}</li>
* <li>notifyMpnSubscriptionActivation: function(request, response) {}</li>
* <li>notifyMpnDeviceTokenChange: function(request, response) {}</li>
* </ul>
* The response argument is a MetadataResponse object and one of its methods,
* error or success, must be called
* in order to reply to the request bound to the event.<br>
* The request object is an associative array containing different data
* according to the specific request:
* <ul>
* <li>init: {parameters: {<name 1>: <value 1> ... <name n>: <value n>}}</li>
* <li>getItemData: {itemNames: [<item name 1> ... <item name n>]}</li>
* <li>getUserItemData: {userName: <username>, itemNames: [<item name 1> ... <item name n>]}</li>
* <li>getSchema: {userName: <username>, groupName: <group name>, schemaName: <schema name>, sessionId: <session id>}</li>
* <li>getItems: {userName: <username>, groupName: <group name>, sessionId: <session id>}</li>
* <li>notifyUser: {userName: <username>, userPassword: <password>,
* headers: {<name 1>: <value 1> ... <name n>: <value n>} }</li>
* <li>notifyUserAuth: {userName: <username>, userPassword: <password>, clientPrincipal: <client principal>,
* headers: {<name 1>: <value 1> ... <name n>: <value n>} }
* <br>NOTE: clientPrincipal is related with TLS/SSL connections, which is an optional feature, available depending on Edition and License Type</li>
* <li>notifyUserMessage: {userName: <username>, sessionId: <session id>, userMessage: <message>}</li>
* <li>notifyNewSession: {userName: <username>, sessionId: <session id>,
* contextProperties: {<name 1>: <val 1> ... <name n>: <value n>}}</li>
* <li>notifySessionClose: {sessionId: <session id>}</li>
* <li>notifyNewTables: {userName: <username>, sessionId: <session id>,
* tableInfos: [{winIndex: <win index>, pubModes: <publish mode>, groupName: <group name>, dataAdapter: <data adapter>,
* schemaName: <schema name>, firstItemIndex: <first index>, lastItemIndex: <last index>,
* selector: <selector>}, ...]}</li>
* <li>notifyTablesClose: {sessionId: <session id>,
* tableInfos: [{winIndex: <win index>, pubModes: <publish mode>, groupName: <group name>, dataAdapter: <data adapter>,
* schemaName: <schema name>, firstItemIndex: <first index>, lastItemIndex: <last index>,
* selector: <selector>}, ...]}</li>
* <li>notifyMpnDeviceAccess: {userName: <username>, sessionId: <session id>,
* device: {mpnPlatformType: <MPN platform type>, applicationId: <application ID>, deviceToken: <device token>}}
* <br>NOTE: Push Notifications is an optional feature, available depending on Edition and License Type</li>
* <li>notifyMpnSubscriptionActivation: {userName: <username>, sessionId: <session id>,
* tableInfo: {winIndex: <win index>, pubModes: <publish mode>, groupName: <group name>, dataAdapter: <data adapter>,
* schemaName: <schema name>, firstItemIndex: <first index>, lastItemIndex: <last index>, selector: <selector>},
* mpnSubscription: {device: {mpnPlatformType: <MPN platform type>, applicationId: <application ID>, deviceToken: <device token>},
* trigger: <trigger expression>, notificationFormat: <notification format descriptor>}<br/>
* The structure of the format descriptor depends on the platform type and it is represented as a json string;
* <br>NOTE: Push Notifications is an optional feature, available depending on Edition and License Type</li>
* <li>notifyMpnDeviceTokenChange: {userName: <username>, sessionId: <session id>,
* device: {mpnPlatformType: <MPN platform type>, applicationId: <application ID>, deviceToken: <device token>},
* newDeviceToken: <new device token>}
* <br>NOTE: Push Notifications is an optional feature, available depending on Edition and License Type</li>
* </ul>
* With reference to the features qualified as optional, to know what features are enabled by your license,
* please see the License tab of the Monitoring Dashboard (by default, available at /dashboard).<br/>
* When the handler for some event is not supplied, a default response is provided;
* some default responses can be configured with the optional constructor parameters.
* The getItems and getSchema events are handler in a way similar to the
* LiteralBasedProvider supplied with the Java in-process Adapter SDK.<br/>
* To resume the default behavior:
* <ul>
* <li>init: does nothing</li>
* <li>getItemData: for each item returns the configured distinctSnapLen, minSourceFreq, and itemAllowedModes</li>
* <li>getUserItemData: for each item returns the configured allowedBufferSize, allowedMaxItemFreq, and userAllowedModes;
* <br>NOTE: A further global frequency limit could also be imposed by the Server, depending on Edition and License Type.</li>
* <li>getSchema: reads the supplied schemaName as a space-separated list of field names and returns an array of such field names</li>
* <li>getItems: reads the supplied groupName as a space-separated list of item names and returns an array of such item names</li>
* <li>notifyUser: returns the configured maxBandwidth and notifyTables (hence accepts the user);
* <br>NOTE: Bandwidth Control is an optional feature, available depending on Edition and License Type</li>
* <li>notifyUserAuth: returns the configured maxBandwidth and notifyTables (hence accepts the user)</li>
* <li>notifyUserMessage: does nothing (hence accepts but ignores the message)</li>
* <li>notifyNewSession: does nothing (hence accepts the session)</li>
* <li>notifySessionClose: does nothing</li>
* <li>notifyNewTables: does nothing (hence accepts the tables)</li>
* <li>notifyTablesClose: does nothing</li>
* <li>notifyMpnDeviceAccess: does nothing (hence allows the access)</li>
* <li>notifyMpnSubscriptionActivation: does nothing (hence accepts the activation)</li>
* <li>notifyMpnDeviceTokenChange: does nothing (hence accepts the change)</li>
* </ul>
*
* @class
* @param {Stream} stream the stream channel to the remote LS Proxy Metadata Adapter.
* In case of interruption, the 'error' event on the stream may report interruption cause details.
* @param {Object} [params] optional parameters used by the default request handlers. By default
* <ul>
* <li>maxBandwidth: 0.0</li>
* <li>notifyTables: false</li>
* <li>minSourceFreq: 0.0</li>
* <li>distinctSnapLen: 0</li>
* <li>itemAllowedModes: {raw: true, merge: true, distinct: true, command: true}</li>
* <li>userAllowedModes: {raw: true, merge: true, distinct: true, command: true}</li>
* <li>allowedMaxItemFreq: 0.0</li>
* <li>allowedBufferSize: 0</li>
* </ul>
* @param {Object} [credentials] optional credentials to be submitted to the remote LS Proxy Metadata Adapter.
* The credentials are needed only if the Proxy Adapter is configured to require Remote Adapter authentication.
* If needed, the supplied object should contain both a "user" and a "password" field.
* @param {Number} [keepaliveInterval] optional time in milliseconds between subsequent keepalive packets
* to be sent on the reply stream to prevent LS Proxy Metadata Adapter and any intermediate nodes from closing
* the connection for inactivity; a value of 0 or negative means no keepalives; the default
* if not supplied is 10000 ms. However, if a stricter interval is requested by the Proxy Adapter
* on startup, it will be obeyed (with a safety minimum of 1 second). This should ensure that the
* Proxy Adapter activity checks will always succeed, but for some old versions of the Proxy Adapter.
* The keepalives can also allow for prompt detection of connection issues.
*/
constructor(stream: Stream, params?: object, credentials?: object, keepaliveInterval?: number);
/**
* Returns the configured stream.
*
* @return Object the stream
*/
getStream(): Stream;
}
/**
* <p>An instance of this class is passed as argument to an event listener,
* and must be used to respond to the remote adapter request,
* using the success method or the error method.</p>
*/
export class MetadataResponse {
/**
* Sends a successful response. Parameters that can be used depends on the event handled
* as described in the following table:
* <ul>
* <li>init: success()</li>
* <li>getItemData: success([{distinctSnapLen: <distinct snapshot length>, minSourceFreq: <min source frequency>,
* allowedModes: {raw: <raw allowed>, merge: <merge allowed>, distinct: <distinct allowed>, command: <command allowed>}}, ...])</li>
* <li>getUserItemData: success([{allowedBufferSize: <allowed buffer size>, allowedMaxItemFreq: <allowed max item frequency>},
* allowedModes: {raw: <raw allowed for user>, merge: <merge allowed for user>, distinct: <distinct allowed for user>, command: <command allowed for user>}}, ...])</li>
* <li>getSchema: success([<field 1>, <field 2>, ...])</li>
* <li>getItems: success([<item 1>, <item 2>, ...])</li>
* <li>notifyUser: success(<allowed max bandwidth>, <wants table notifications>)</li>
* <li>notifyUserAuth: success(<allowed max bandwidth>, <wants table notifications>)</li>
* <li>notifyUserMessage: success()</li>
* <li>notifyNewSession: success()</li>
* <li>notifySessionClose: success()</li>
* <li>notifyNewTables: success()</li>
* <li>notifyTablesClose: success()</li>
* <li>notifyMpnDeviceAccess: success()</li>
* <li>notifyMpnSubscriptionActivation: success()</li>
* <li>notifyMpnDeviceTokenChange: success()</li>
* </ul>
*/
success(): void;
/**
* Sends an error response. The optional exception type parameter that can be used
* to issue a proper type of exception depends on the event handled as described in the following table:
* <ul>
* <li>init: "metadata"</li>
* <li>getItemData: none</li>
* <li>getUserItemData: none</li>
* <li>getSchema: "items" or "schema"</li>
* <li>getItems: "items"</li>
* <li>notifyUser: "access" or "credits"</li>
* <li>notifyUserAuth: "access" or "credits"</li>
* <li>notifyUserMessage: "credits" or "notification"</li>
* <li>notifyNewSession: "credits" or "conflictingSession" or "notification"</li>
* <li>notifySessionClose: "notification"</li>
* <li>notifyNewTables: "credits" or "notification"</li>
* <li>notifyTablesClose: "notification"</li>
* <li>notifyMpnDeviceAccess: "credits" or "notification"</li>
* <li>notifyMpnSubscriptionActivation: "credits" or "notification"</li>
* <li>notifyMpnDeviceTokenChange: "credits" or "notification"</li>
* </ul>
*
* @param {String} exceptionMessage exception message
* @param {String} [exceptionType] exception type
* @param {Object} [exceptionData] extra information required by the exception, to be supplied
* as an associative array. Depending on the exception type; the following cases are possible:
* <ul>
* <li>"credits": extra information is mandatory and should have the form:
* {clientCode: <client code>, clientMessage: <client message>}.</li>
* <li>"conflictingSession": extra information is mandatory and should have the form:
* {clientCode: <client code>, clientMessage: <client message>, conflictingSessionId: <session id>}.</li>
* <li>Others or not specified: no extra information needed.</li>
* </ul>
* Where:
* <ul>
* <li>clientCode is an error code that can be used to distinguish the kind of problem.
* It must be a negative integer, or zero to mean an unspecified problem. </li>
* <li>clientMessage is a detail message to be forwarded to the Client. It can
* be null, in which case an empty string message will be assumed.
* The message is free, but if it is not in simple ASCII or if it is
* multiline, it might be altered in order to be sent to very old
* non-TLCP clients.</li>
* <li>conflictingSessionId is the ID of a Session that can be closed in order to eliminate
* the reported problem.</li>
* </ul>
*/
error(exceptionMessage: string, exceptionType?: string, exceptionData?: object): void;
}