export {}; /** * @module diffusion */ /// /** * The top-level Diffusion API. * * Provides access to Session connections and global namespaces. */ /** * The version of this client library in the form major.minor.patch */ export declare const version: string; /** * The build version of this client library */ export declare const build: string; /** * Set the level of logging used by Diffusion. This will default to silent. * Log levels are strings that represent different degrees of information to * be logged. Available options are: * * * silent * * error * * warn * * info * * debug * * trace * * @param level the log level to use */ export declare function log(level: LogLevel | keyof typeof LogLevel): void; /** * Connect to a specified Diffusion server. This will return a {@link * Promise} that will complete successfully if a session can be connected, or * fail if an error was encountered. * * If the result is successful, the fulfilled handler will be called with a * {@link Session} instance. This session will be in a connected state and * may be used for subsequent API calls. * * If the result fails, the rejected handler will be called with an error * reason. * * If `sessionName` and `workerJs` is supplied, then the call will create a * shared session inside a shared WebWorker. If a shared session with that name * already exists, this function will return an instance of the existing * session. Shared sessions can only be created when running in a browser * environment that supports the SharedWorker. For more information regarding * shared sessions, see {@link connectShared}. * * **Example:** * ``` * diffusion.connect('example.server.com').then((session) => { * // Connected with a session * console.log('Connected!', session); * }).catch((error) => { * // Connection failed * console.log('Failed to connect', error); * }); * ``` * * @param options the options to construct the session with. If a string is * supplied, it will be interpreted as the `host` option. * @param sessionName the name of the shared session * @param workerJs the location of the diffusion worker script * @returns a {@link Promise} for this operation * * @throws a {@link NullValueError} if only one of `sessionName` or `workerJs` is `undefined` * or if `options` is `undefined` * @throws an {@link IllegalArgumentError} if the options are invalid. */ export declare function connect(options: Options | string, sessionName?: string, workerJs?: string): Promise; /** * Connect to a specified Diffusion server using a shared WebWorker session. * This will return a {@link Promise} that will complete successfully if a * session can be connected, or fail if an error was encountered. Shared * sessions can only be created when running in a browser environment that * supports the SharedWorker. * * Shared sessions are identified by a name. If a shared session with that name * already exists, this function will return an instance of the existing * session. Otherwise the call will fail. Sessions can only be shared across * scripts originating from a single domain. Otherwise the browser will create * independent shared workers resulting in one shared session for each domain. * * The shared session will stay alive as long as there is an open browser tab * that initiated a connection through the shared session. When the last tab is * closed the shared worker holding the shared session will be terminated. The * shared session is also expected to be terminated when the only tab holding a * reference to the session is reloaded or experiences a page navigation. The * exact behavior may be browser dependent. * * The `workerJs` argument must be set to the URL of the `diffusion-worker.js` * supplied with the JavaScript distribution. The same-origin policy of * the shared worker requires the calling script and the `diffusion-worker.js` * to reside on the same domain. * * If the result is successful, the fulfilled handler will be called with a * {@link Session} instance. This session will be in a connected state and * may be used for subsequent API calls. * * If the result fails, the rejected handler will be called with an error * reason. * * **Example:** * ``` * const options = { * host : 'localhost', * port : '8080', * principal : 'admin', * credentials : 'password' * }; * * diffusion.connect(options, 'some-session', 'diffusion-worker.js').then((session) => { * console.log('Connected creating new shared session', session); * }).catch((error) => { * console.log('Failed to connect', error); * }); * * diffusion.connectShared('some-session', 'diffusion-worker.js').then((session) => { * console.log('Connected to existing shared session', session); * }.catch((error) => { * console.log('Failed to connect shared', error); * }); * ``` * * @param sessionName the name of the shared session * @param workerJs the location of the diffusion worker script * @returns a {@link Promise} for this operation * @throws an {@link IllegalArgumentError} if the options are invalid. */ export declare function connectShared(sessionName: string, workerJs: string): Promise; /** * Escapes special characters in a string that is to be used within a topic * property or a session filter. *

* This is a convenience method which inserts an escape character '\' before * any of the special characters ' " or \. * * @param s the string to be escaped * @returns the string value with escape characters inserted as appropriate * * @since 6.1 */ export declare function escape(s: string): string; /** * Utility method which converts a string of the format required by the * {@link PropertyKeys.ROLES $Roles} session property into a mutable set of * strings. * * @param s the string with quoted roles separated by whitespace or * commas * * @return set of roles * @throws an error if the argument is `null` or `undefined` * @throws an {@link IllegalArgumentError} if the input is not correctly quoted * * @since 6.2 */ export declare function stringToRoles(s: string): Set; /** * Utility method which converts a set of authorisation roles to the string * format required by the {@link PropertyKeys.ROLES $Roles} session property. * * @param roles a set of roles * @return a string representing the supplied roles, formatted as * required by the {@link PropertyKeys.ROLES $Roles} session * property * * @since 6.2 */ export declare function rolesToString(roles: Set | string[]): string; /** * Returns an update constraint factory. * * @function diffusion#updateConstraints * @return {diffusion.topicUpdate.UpdateConstraintFactory} update constraint * factory * @since 6.2 */ export declare function updateConstraints(): UpdateConstraintFactory; /** * Create a new {@link BranchMappingTableBuilder}. * * @since 6.7 * @see SessionTrees */ export declare function newBranchMappingTableBuilder(): BranchMappingTableBuilder; /** * Create a new {@link SessionMetricCollectorBuilder}. * * @since 6.7 */ export declare function newSessionMetricCollectorBuilder(): SessionMetricCollectorBuilder; /** * Create a new {@link TopicMetricCollectorBuilder}. * * @since 6.7 */ export declare function newTopicMetricCollectorBuilder(): TopicMetricCollectorBuilder; /** * Access to the selectors namespace */ export declare const selectors: TopicSelectors; export declare function newRemoteServerBuilder(): RemoteServerBuilder; export declare function newRemoteServerBuilder(type: RemoteServerType.PRIMARY_INITIATOR): PrimaryInitiatorBuilder; export declare function newRemoteServerBuilder(type: RemoteServerType.SECONDARY_ACCEPTOR): SecondaryAcceptorBuilder; export declare function newRemoteServerBuilder(type: RemoteServerType.SECONDARY_INITIATOR): SecondaryInitiatorBuilder; export declare function newRemoteServerBuilder(type?: RemoteServerType): RemoteServerBuilder | PrimaryInitiatorBuilder | SecondaryAcceptorBuilder | SecondaryInitiatorBuilder; /** * Create a new {@link SessionEventParametersBuilder}. * * @return the builder * * @since 6.11 */ export declare function newSessionEventParametersBuilder(): SessionEventParametersBuilder; /** * Access to the datatypes namespace */ export declare const datatypes: DataTypes; /** * Access to the topics namespace */ export declare const topics: TopicsNamespace; /** * Access to the topicUpdate namespace */ export declare const topicUpdate: TopicUpdateNamespace; /** * The ErrorReason enum */ export declare const errors: { [key: string]: ErrorReasonType; }; /** * Access to PropertyKeys */ export declare const clients: ClientControlOptionsNamespace; /** * Access to the locks namespace */ export declare const locks: SessionLockOptionsNamespace; /** * Access to the Buffer API that is packaged with diffusion. * * This can be used in browsers that don't have a native Buffer class. It allows * the creation of buffers for use with {@link BinaryDataType binary} datatypes. * * @example * ``` * const buf = diffusion.buffer.from('Hello World', 'utf8') * ``` * * @deprecated since version 6.11. Buffer has been replaced by Uint8Array.This * will be removed in a future release. */ export declare const buffer: { prototype: Buffer; poolSize: number; new (str: string, encoding?: string | undefined): Buffer; new (size: number): Buffer; new (array: Uint8Array): Buffer; new (arrayBuffer: ArrayBuffer): Buffer; new (array: any[]): Buffer; new (buffer: Buffer): Buffer; from(arrayBuffer: ArrayBuffer, byteOffset?: number | undefined, length?: number | undefined): Buffer; from(data: string | any[] | ArrayBuffer | Buffer): Buffer; from(str: string, encoding?: string | undefined): Buffer; isBuffer(obj: any): obj is Buffer; isEncoding(encoding: string): boolean; byteLength(string: string | DataView | ArrayBuffer | Buffer, encoding?: string | undefined): number; concat(list: Buffer[], totalLength?: number | undefined): Buffer; compare(buf1: Buffer, buf2: Buffer): number; alloc(size: number, fill?: string | number | Buffer | undefined, encoding?: string | undefined): Buffer; allocUnsafe(size: number): Buffer; allocUnsafeSlow(size: number): Buffer; }; /** * @module diffusion.errors */ /** * An ErrorReport from the server. */ export interface ErrorReport { /** * The error message */ message: string; /** * The line at which the problem was found */ line: number; /** * The column at which the problem was found */ column: number; } /** * @module Session */ /** * A typed array that can be passed as credentials */ export declare type TypedArray = Int8Array | Int16Array | Int32Array | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | Float32Array | Float64Array; /** * A reconnection strategy */ export declare type ReconnectStrategy = (reconnect: () => void, abort: () => void) => void; /** * Defines a retry strategy. * * A retry strategy will be applied when an initial to attempt to open a session * fails with a transient session establishment exception. * * A retry strategy will be applied when recovering by a * {@link RecoverableUpdateStream} following a recoverable exception. * * The strategy is defined in terms of the number of milliseconds between * retries and the maximum number of retries to attempt. * * If no properties are defined, it means that no retries will be attempted. * * If `interval` is defined but `attempts` is not, it means that unlimited retries * will be attempted. * * @since 6.10 */ export interface RetryStrategy { /** * The number of milliseconds before the first retry and between subsequent retries */ interval?: number; /** * The number of retry attempts */ attempts?: number; } /** * Additional options that can be passed to the {@link connect} function affecting * the underlying TLS configuratio. These options are passed directly to * `tls.createSecureContext()`. For more information, see the documentation for * the `tls.createSecureContext()` function in the Node.js documentation. */ export interface ExtraTlsOptions { /** * Optionally override the trusted CA certificates. */ ca?: string | Uint8Array | Array | undefined; /** * Cert chains in PEM format. */ cert?: string | Uint8Array | Array | undefined; /** * Cipher suite specification, replacing the default. */ ciphers?: string | undefined; /** * Name of an OpenSSL engine which can provide the client certificate. */ clientCertEngine?: string | undefined; /** * PEM formatted CRLs (Certificate Revocation Lists). */ crl?: string | Uint8Array | Array | undefined; /** * Diffie Hellman parameters, required for Perfect Forward Secrecy. */ dhparam?: string | Uint8Array | undefined; /** * A string describing a named curve or a colon separated list of curve * NIDs or names, for example P-521:P-384:P-256, to use for ECDH key * agreement. */ ecdhCurve?: string | undefined; /** * Attempt to use the server's cipher suite preferences instead of the * client's. */ honorCipherOrder?: boolean | undefined; /** * Private keys in PEM format. */ key?: string | Uint8Array | Uint8Array[] | undefined; /** * Shared passphrase used for a single private key and/or a PFX. */ passphrase?: string | undefined; /** * PFX or PKCS12 encoded private key and certificate chain. */ pfx?: string | Uint8Array | Array | undefined; /** * Optionally affect the OpenSSL protocol behavior, which is not * usually necessary. */ secureOptions?: number | undefined; /** * Legacy mechanism to select the TLS protocol version to use. */ secureProtocol?: string | undefined; /** * Opaque identifier used by servers to ensure session state is not * shared between applications. */ sessionIdContext?: string | undefined; /** * If true the server will reject any connection which is not * authorized with the list of supplied CAs. */ rejectUnauthorized?: boolean | undefined; } /** * Provide Session configuration options. * *

Connection:
* There are several option values that can be configured to change how * Diffusion establishes a connection. These options are used to derive a * connection URL in the format: {protocol}://{host}:{port}/{path}. * The protocol used is determined by the chosen transports and whether secure * connections are enabled. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OptionDefault valueDescription
hostlocalhostThe hostname to connect to.
port80 or 443The port to connect to. The default value is the default secure port if * secure connections are enabled, otherwise the default value is the default * insecure port. *

* In case the client is being run in a page served via https * (http), the default secure (insecure) port is the port of the * URI of the current page, otherwise the default secure (insecure) port is * 443 (80). *

path/diffusionThe URL path to apply after the hostname/port. This allows additional context to be provided, such as might be * used by load balancers.
securetrueDetermines if secure transports will be used. If the port is not * explicitly specified this value defaults to true. If the port is * explicitly specified the default value is true only if the port is * equal to the default secure port, otherwise false. *

* In case the client is being run in a page served via https, the * default secure port is the port of the URI of the current page, otherwise the * default secure port is 443.

* *
Reconnection:
* * Reconnection is enabled by default. The reconnect key accepts several different option values. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Option typeDefault valueDescription
booleantrueEnables or disables reconnection. If set to true, reconnection will be enabled using the default * timeout value and a periodic back-off strategy.
number60000Passing a number will enable reconnection with the default strategy and the reconnection timeout set to the * specified value. The reconnection timeout determines how long, in milliseconds, the client will remain in a * disconnected state before the client is closed.
function
 * function(reconnect, abort) {
 *     setTimeout(reconnect, 5000);
 * }
A strategy function that will be called when the client enters a disconnected state, and * subsequently if attempts to reconnect fail. Two arguments are provided, reconnect and abort * - these are functions to be called within the strategy. The reconnect argument will initiate a * reconnect attempt. abort may be called to abort reconnection, in which case the client will be closed. *
 * {
 *     timeout : <number>,
 *     strategy : <function>
 * }
 * {
 *     timeout : 60000,
 *     strategy : function(reconnect, abort) {
 *         setTimeout(reconnect, 5000);
 *     }
 * }
An object containing both the timeout and strategy options as specified above, allowing both to be set together. *
* *
Transports:
* * The transports property configures how the session should connect. It can be set to either a * string, or an array of strings to provide a transport cascading capability. * * * * * * * * * * * * * * * * * * *
Transport keyDescription
ws, WS, WEBSOCKETThe WebSocket transport. A single, long-lived WebSocket connection will be used to send and receive data.
xhr, XHR, HTTP_POLLINGAn XHR-based polling transport. Data will be queued on the client and server, and sent in batches.
* The client will use the transports in the order provided, for example: * transports: ['WS', 'XHR'] indicates that the client will attempt to connect with the WebSocket * transport, and if the connection fails, the client will attempt to connect with the HTTP Polling transport. When no * transports value is provided the client will default to using the WebSocket transport. Any string values * that do not have an associated transport will be ignored. * * When the diffusion client is run in a browser environment, `transports` will * default to `['WEBSOCKET', 'XHR']`. When run in Node, `transports` will * default to `['WEBSOCKET']`. * *
Properties:
* * Supplied session properties will be provided to the server when a session * is created using this session factory. The supplied properties will be * validated during authentication and may be discarded or changed. * * The specified properties will be added to any existing properties set for * this session factory. If any of the keys have been previously declared * then they will be overwritten with the new values. * * For details of how session properties are used see {@link Session}. */ export interface Options { /** * The hostname to connect to (default `'localhost'`) */ host?: string; /** * The port to connect to (default `443`) */ port?: number | string; /** * The request path used for connections (default `/diffusion`) */ path?: string; /** * Whether to use secure connections. */ secure?: boolean; /** * The principal name this session should connect with. Used for authentication. */ principal?: string; /** * A password string to authenticate with, a buffer containing custom * credentials in binary format, a typed array, or a regular * array of octets. */ credentials?: string | TypedArray | number[]; /** * The timeout in milliseconds used when connecting to the server. (default `10000`) */ connectionTimeout?: number; /** * A retry strategy that defines the behaviour for the initial connection * attempt. * * The default connection strategy will attempt each transport once before * cascading to the next transport. */ retry?: RetryStrategy; /** * Reconnection options. (default `true`) */ reconnect?: boolean | number | ReconnectStrategy | { timeout?: number; strategy?: ReconnectStrategy; }; /** * The transports to be used for connection establishment. (default `"WEBSOCKET"`) */ transports?: string | string[]; /** * The maximum size of messages that may be received from the server. (default `2147483647`) */ maxMessageSize?: number; /** * An object of key-value pairs that define the user-defined session properties. * * Property values will be sent as `string` values. Non-string properties must * implement the `toString()` method to allow conversion. * * For details of how session properties are used see {@link Session}. */ properties?: { [key: string]: any; }; /** * An optional HTTP/HTTPS proxy agent. (default `undefined`) * * If this is set, then the client will attempt to connect to the Diffusion * server via a proxy server. * * The proxy agent will be passed to the WebSocket constructor as the * `agent` option. See https://www.npmjs.com/package/https-proxy-agent for * an example of a proxy agent. * * This option is used for web socket connections and is intended for Node * based clients only. Browser based clients will automatically use the * browser's proxy settings. * * **Example:** * ``` * const HttpsProxyAgent = require('https-proxy-agent'); * const url = require('url'); * const diffusion = require('diffusion'); * * const agent = new HttpsProxyAgent(url.parse('https://proxy.example.com:80')); * * diffusion.connect({ * host: 'https://diffusion.foo.com', * httpProxyAgent: agent * }).then((session) => { * // connected through proxy server * }); * ``` */ httpProxyAgent?: any; /** * An optional TLS options object. (default `undefined`) * This option is used for secure web socket connections and is intended for * Node based clients only. Browser based clients will automatically use the * browser's TLS settings. * * See https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions for * more information. */ tlsOptions?: ExtraTlsOptions; } /** * Alias for the Options interface to keep compatibility with old TypeScript definitions */ export declare type SessionOptions = Options; /** * @module Session */ /** * A session ID */ export interface SessionId { /** * Convert the session ID to a string * * @return a string representation of the session ID */ toString(): string; } /** * A client session to a server or cluster of servers. * * A new session can be created by connecting to a server using * {@link connect diffusion.connect}, specifying the server URL. The session * factory can be configured to control the behavior the session. * * The session provides a variety of operations to the application. These are * grouped into feature interfaces, such as {@link Topics} and * {@link Messages}, exposed to the application through properties on the Session * object. * *

Session lifecycle

* * Each session is managed by a server. The server assigns the session a * {@link Session.sessionId unique identity}, and manages the session's topic * subscriptions, security details, and session * properties. * * A session can be terminated using {@link close}. A session may also be * terminated by the server because of an error, a time out, or because it's * authentication has expired. It can also be terminated by other privileged * sessions using the {@link ClientControl} feature. * * A client can become disconnected from the server, and reconnect to the server * without loss of the session. Reconnection can be configured using * {@link Options.reconnect the session options}. The server * must be configured to allow reconnection. * * If a session is connected to a server that belongs to a cluster with session * replication enabled, and then becomes disconnected, it will attempt to * reconnect to the original server. A properly configured load balancer can * detect that the original server is unavailable and re-route the reconnection * request to a second server in the cluster. The second server can recover * session data and continue the session. This process is known as "fail over". * Unlike reconnection, in-flight messages can be lost during failover, and the * application will be unsubscribed and re-subscribed to topics. * * The current state of the session can be retrieved with {@link isClosed} and * {@link isConnected}. Listeners can be registered with {@link on} which will be * notified when the session state changes. * *

Session properties

* * For each session, the server stores a set of session properties that describe * various attributes of the session. * * There are two types of session property. Fixed properties are assigned by the * server. User-defined properties are proposed by the application, but may * be changed during authentication. * * Many operations use session filter expressions (see section Session Filters) * that use session properties to select sessions. * * A session may obtain its own session properties using * {@link Session.getSessionProperties}. * * A privileged client can monitor other sessions, including changes to their * session properties, using a {@link ClientControl.addSessionEventListener * session event listener}. When registering to receive session properties, * special key values of {@link PropertyKeys.ALL_FIXED_PROPERTIES * ALL_FIXED_PROPERTIES} and {@link PropertyKeys.ALL_USER_PROPERTIES * ALL_USER_PROPERTIES} can be used. * * Each property is identified by a key. Most properties have a single string * value. The exception is the $Roles fixed property which has a set of string * values. * * Fixed properties are identified by keys with a '$' prefix. The available * fixed session properties are: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
KeyDescription
$ClientIPThe Internet address of the client in string format.
$ClientTypeThe client type of the session. One of ANDROID, C, * DOTNET, IOS, JAVA, JAVASCRIPT_BROWSER, * MQTT, PYTHON, or OTHER.
$ConnectorThe configuration name of the server connector that the client connected * to.
$CountryThe country code for the country where the client's Internet address was * allocated (for example, NZ for New Zealand). If the country code could not * be determined, this will be a zero length string.
$EnvironmentThe environment in which the client is running. For possible values see the user manual. * The browser name and version are determined by the UA-Parser library.
$ExpiryTimeThe time at which the session is due to expire, specified in milliseconds * since the epoch. This may be set by authenticators. If not present, the * session will not expire.
$GatewayTypeGateway client type. Only set for gateway client sessions. * If present it indicates the type of gateway client (e.g. Kafka).
$GatewayIdThe identity of a gateway client session. * Only present if the $GatewayType session property is present.
$LanguageThe language code for the official language of the country where the * client's Internet address was allocated (for example, en for English). If * the language could not be determined or is not applicable, this will be a * zero length string.
$LatitudeThe client's latitude, if available. This will be the string * representation of a floating point number and will be NaN if not * available.
$LongitudeThe client's longitude, if available. This will be the string * representation of a floating point number and will be NaN if not * available.
$MQTTClientIdThe MQTT client identifier. Only set for MQTT sessions. If * present, the value of the $ClientType session property will be * MQTT.
$PrincipalThe security principal associated with the client session.
$RolesAuthorisation roles assigned to the session. This is a set of roles * represented as quoted strings (for example, `"role1","role2"`). The * utility method {@link stringToRoles} can be used to parse * the string value into a set of roles.
$ServerNameThe name of the server to which the session is connected.
$SessionIdThe session identifier. Equivalent to {@link Session.sessionId}.
$StartTimeThe session's start time in milliseconds since the epoch.
$TransportThe session transport type. One of WEBSOCKET, * HTTP_LONG_POLL, TCP, or OTHER.
* * All user-defined property keys are non-empty strings and are case-sensitve. * The characters ' ', '\t', '\r', '\n', '"', ''', '(', ')' are not allowed. * * Session properties are initially associated with a session as follows:
* * 1. When a client starts a new session or {@link Security.reauthenticate * re-authenticates}, it can optionally propose * user-defined session properties (see {@link Options}.properties). * Session properties proposed in this way must be accepted by the * authenticator. This safeguard prevents abuse by a rogue, unprivileged client. * 2. The server allocates all fixed property values. * 3. The new session is authenticated by registered authenticators. An * authenticator that accepts a session can veto or change the user-defined * session properties and add new user-defined session properties. The * authenticator can also change certain fixed properties, such as the * expiry time (`EXPIRY_TIME`). * * Once a session is established, its user-defined session properties can be * modified by clients with `VIEW_SESSION` and `MODIFY_SESSION` * permissions using {@link ClientControl.setSessionProperties}. * A privileged client can also modify its own session properties. * * If a session re-authenticates (see {@link Security.reauthenticate * reauthenticate}), the authenticator that allows the re-authentication can * modify the user-defined session properties and a subset of the fixed * properties as mentioned above. * *

Session filters

* * Session filters are a mechanism of addressing a set of sessions by the values * of their session properties. * * Session filters are specified using a Domain Specific Language (DSL). For a full and * detailed description of the session filters DSL see the * * user manual. * *

Events

* *

disconnect

* * Emitted when a connected session has lost connection to the server, and * {@link Options} `reconnect` is enabled. The provided reason will * contain the specific cause of the session disconnect. * * **Parameters:** * * `reason`: {@link CloseReason} - the cause of the session disconnect * *

reconnect

* * Emitted when a disconnected session has successfully reconnected. * *

close

* * Emitted when a session is closed. This can occur because it was closed by the * user, closed by the server, failed to connect, or the session encountered an * error. The provided close reason will contain the specific cause of the * session close. * * **Parameters:** * * `reason`: {@link CloseReason} - the cause of the session close * *

error

* * Emitted when a session error has occurred. A session error occurs when the * client cannot parse communication from the server. This occurs if a component * between the two - for example, a proxy or load balancer - alters the * communication. * * **Parameters:** * * `error`: any - the error that occurred */ export interface Session extends Stream, Topics, Ping { /** * The unique id assigned to this session by the server. */ readonly sessionId: SessionId; /** * The connection options used to establish this session */ readonly options: Options; /** * Exposes remote servers capabilities via {@link Session.remoteServers} */ readonly remoteServers: RemoteServers; /** * Exposes system authentication capabilities via a {@link Session.security} */ readonly security: Security; /** * Exposes session trees capabilities via {@link Session.sessionTrees} */ readonly sessionTrees: SessionTrees; /** * Exposes topic control capabilities via {@link Session.topics} */ readonly topics: TopicControl; /** * Exposes topic update capabilities via {@link Session.topicUpdate} */ readonly topicUpdate: TopicUpdate; /** * Exposes topic views capabilities via {@link Session.topicViews} */ readonly topicViews: TopicViews; /** * Exposes time series capabilities via {@link Session.timeseries} */ readonly timeseries: TimeSeries; /** * Exposes messaging capabilities via {@link Session.messages} */ readonly messages: Messages; /** * Exposes topic notification capabilities via {@link Session.notifications} */ readonly notifications: TopicNotifications; /** * Exposes client control capabilities via {@link ClientControl} */ readonly clients: ClientControl; /** * Exposes metric collector management capabilities via {@link Metrics} */ readonly metrics: Metrics; /** * Close this session's connection to the server. * * Calling this repeatedly will have no effect. * * @return this session */ close(): Session; /** * Close this session's connection to the server and return a {@link Promise} * that will completes when the session is closed. * * @return a {@link Promise} that completes with the close reason returned * by the server. Only the {@link Promise} of the first call to * `closeSession` is guaranteed to complete. The {@link Promise} * will not resolve if the session is already closed. */ closeSession(): Promise; /** * Indicates if this session is currently closed, or in the process of * closing. * * This will not return `true` if the session is disconnected * but attempting to reconnect. * * @return whether the session is currently closed. */ isClosed(): boolean; /** * Indicates if this session is currently connected. * * This is orthogonal to {@link Session.isClosed}, as a session may * be disconnected and attempting to reconnect. * * @return whether the session is currently connected or not. */ isConnected(): boolean; /** * Returns the principal name that this session is associated with. * * @return the principal for this session */ getPrincipal(): string; /** * Returns the values of the session's fixed session properties. * * All current fixed property values are returned, except the value of the * `ROLES` property. User-defined session properties are not returned. * * @return a Promise that resolves when a response is received * from the server. *

* If the Promise completes normally, the current * session properties will be returned (excluding the value of the * `ROLES` property). *

* Otherwise, the Promise will be rejected. Common reasons for failure include: * *

    *
  • the session is closed. *
* @since 6.12 */ getSessionProperties(): Promise; /** * Attempt to acquire a {@link SessionLock session lock}. * * This method returns a Promise that will resolve normally if * the server assigns the requested lock to the session. Otherwise, the * Promise will fail with an error indicating why the lock could not * be acquired. * * @param lockName the name of the session lock * @param scope preferred scope, defaults to * `UNLOCK_ON_SESSION_LOSS` . The scope of a lock controls * when it will be released automatically. If a session * makes multiple requests for a lock using different * scopes, and the server assigns the lock to the session * fulfilling the requests, the lock will be given the * weakest scope (`UNLOCK_ON_SESSION_LOSS` ). * @return a Promise that resolves when a response is received * from the server. *

* If this session has successfully acquired the session * lock, or this session already owns the session lock, the * Promise will resolve normally with a SessionLock result. *

* If the Promise resolves with an error, this session does * not own the session lock. * * @since 6.2 */ lock(lockName: string, scope?: SessionLockScope): Promise; /** * Updates the session with missing features that may have been loaded * asynchronously. This method only has an effect when running the client * as a modular client in the browser. */ updateFeatures(): void; } /** * @module diffusion.clients */ /** * A type containing information about the reason for a session being closed * * Documentation of the CloseReason values can be found under {@link CloseReasonEnum}. */ export interface CloseReason { /** * The close reason's id * * @deprecated since 6.8 *

* This member is deprecated and will be removed in the future. */ id: number; /** * The close reason's description * * @deprecated since 6.8 *

* This member is deprecated and will be removed in the future. */ message: string; } /** * Enum representing the reason that the session has been closed. * * **Example:** * ``` * diffusion.connect({...}).then(function(session) {...}, function(err) { * switch(err) { * case diffusion.clients.CloseReason.CLOSED_BY_CLIENT: * // Do something * case diffusion.clients.CloseReason.ACCESS_DENIED: * // Do something else * ... * } * }); * ``` * */ export declare const CloseReasonEnum: { [key: string]: CloseReason; }; /** * The server's view of why a client session was closed. */ export declare enum ClientCloseReason { /** * The connection to the client was lost - possibly dropped by the client. * Recoverable. * * A client may be closed for may reasons that are presented as * CONNECTION_LOST. * * During connection the connection can be lost. The server might have * received a connection or reconnection request from a client already * connected. The server might have received a reconnection request without * a client ID. The connection may not have been authorised because the * credentials are wrong. The maximum number of clients might already be * connected. * * Once connected the connection can be lost for different reasons. If the * client closes its connection while the server is writing a message to the * client. With the chunked encoding based connection the HTTP response is * completed by the server. If the client does not open a new request within * a timeout the client will be closed. If a poll request times out and the * server finds that the connection has already been closed by the client. */ CONNECTION_LOST = 0, /** * An unexpected IO Exception occurred. Recoverable. * * While trying to perform an I/O operation an exception was generated. This * often means that Diffusion attempted to read from a closed TCP * connection. * * When Diffusion is handling SSL connections if there is a problem * encrypting or decrypting a message the client will be closed for this * reason. */ IO_EXCEPTION = 1, /** * The client had become unresponsive. Recoverable. * * The client has either failed to respond to a ping message in a timely * manner or the client has failed to open an HTTP poll for messages. The * client does not appear to be receiving messages. */ CLIENT_UNRESPONSIVE = 2, /** * The maximum outbound queue size was reached for the client. Not * recoverable. * * Messages sent to the client are placed in a queue. This queue has a * maximum allowed size. If the queue limit is reached the client is closed * and the queue discarded. The queue is intended to protect against slow * patches, reaching the queue limit is taken to mean that the client cannot * keep up with the number of messages sent to it. */ MESSAGE_QUEUE_LIMIT_REACHED = 3, /** * The client requested close. Not recoverable (unless TEST_RECONNECT is * true). */ CLOSED_BY_CLIENT = 4, /** * The client sent a message that exceeded the maximum message size. * * The server has a maximum message size. If a client sends a message larger * than this the server is unable to process it. When this happens the * message is discarded and the client is closed. */ MESSAGE_TOO_LARGE = 5, /** * An internal error occurred. */ INTERNAL_ERROR = 6, /** * An inbound message with an invalid format was received. * * A message received by the server is not a valid Diffusion message. The * server is unable to process this and closes the client that sent it. */ INVALID_INBOUND_MESSAGE = 7, /** * The client connection was aborted by the server, possibly because the * connection was disallowed. * * This may be because the connection was disallowed. Abort messages are * also sent to clients that have unrecognised client IDs. This may be * because the server closed the client previously but the client is unaware * of this and tried to continue interacting with the server. */ ABORTED = 8, /** * Loss of messages from the client has been detected. For example, whilst * waiting for the arrival of missing messages in a sequence of messages a * timeout has occurred. * * HTTP based transports use multiple TCP connections. This can cause the * messages to be received out of order. To reorder the messages those sent * to the server may contain a sequence number indicating the correct order. * * If a message is received out of order there is a short time for the * earlier messages to be received. If the messages are not received in this * time the client is closed. * * Missing, invalid or duplicate sequence numbers will also close the client * for this reason. * * This cannot be recovered from as the client and the server are in * inconsistent states. */ LOST_MESSAGES = 9, /** * A control session initiated the client close. */ CLOSED_BY_CONTROLLER = 11, /** * The client has failed over to a different server. *

* The session is still open but is now connected to a different Diffusion * server. This server has evicted its view of the client from its set of * local clients. */ FAILED_OVER = 12, /** * The session had an {@link EXPIRY_TIME} specified which * expired before the session {@link Security.reauthenticate * re-authenticated}. * * @since 6.12 */ EXPIRED = 13, /** * The session's authentication was revoked by a privileged user. * * @since 6.12 */ REVOKED = 14, /** * The session has been closed to make way for a new session. * * This is used by MQTT. See MQTT-3.1.4-3. * * @since 6.12 */ SESSION_TAKEN_OVER = 15 } /** * @module diffusion.datatypes */ /// /** * Read-only interface for values that are internally represented as binary * data. * * This interface provides access to copies of the binary data, making instances * effectively immutable. Methods of derived interfaces and classes that relax * this restriction and expose access to the internal data should be clearly * documented. * * @since 5.7 */ export interface Bytes { /** * Get the number of bytes * * @return The length of the data in bytes */ length(): number; /** * Get a copy of the buffer containing this value. * * @return This value in binary form * * @deprecated since version 6.11. Buffer has been replaced by Uint8Array. This * will be removed in a future release. */ asBuffer(): Buffer; /** * Get a copy of the array containing this value. * * @return This value in binary form */ asArray(): Uint8Array; /** * Copy the binary data to a provided buffer. * * @param target the buffer to copy data to * @param offset the position in the target buffer at which data will be copied */ copyTo(target: Uint8Array, offset?: number): void; } /** * @module diffusion.datatypes */ /// /** * A data type is specified for a particular value type. It provides methods to * convert values to and from binary. Diffusion provides several {@link DataType} * implementations. * * A data type can optionally support incremental changes to values, represented * by one or more types of delta. A delta is the difference between two * values. For large or composite values that change in small steps, it is more * efficient to transmit an initial value followed by a delta for each change * than to transmit a complete value for each change. The data type provides an * implementation of {@link DeltaType} for each type of delta it * supports via {@link DataType.deltaType}. * * @since 5.7 * * @param the value type of the data type * @param the type(s) from which a value can be constructed * @param the binary type containing the CBOR data */ export interface DataType { /** * The external type identifier. * * @return the name of this datatype */ name(): string; /** * Parse a value from binary. * * @param input the binary data * @param offset the offset to start reading from the provided buffer (default = `0`) * @param length the length of the data to read (default = `input.length`) * @returns an instance of this data type value * @throws an {@link InvalidDataError} error if the data is invalid for this type */ readValue(input: Uint8Array, offset?: number, length?: number): ValueType | null; readValue(input: CBORType): ValueType | null; /** * Serialise a value to binary * * @param value the value to serialise. For primitive and JSON datatypes * the value can be `undefined` or `null`. In this case a * `null` value will be serialised. * @returns the serialised value as a buffer * @throws an {@link IllegalArgumentError} if the value cannot be serialised * * @deprecated since version 6.11. Buffer has been replaced by Uint8Array. * Use writeValueToArray instead. This will be removed * in a future release. */ writeValue(value: SourceType | undefined | null): Buffer; /** * Serialise a value to binary * * @param value the value to serialise. For primitive and JSON datatypes * the value can be `undefined` or `null`. In this case a * `null` value will be serialised. * @returns the serialised value as a buffer * @throws an {@link IllegalArgumentError} if the value cannot be serialised */ writeValueToArray(value: SourceType | undefined | null): Uint8Array; /** * Test whether this data type is compatible with `valueType`. Compatibility * with a `valueType` means than any valid binary representation of a * `value` can be {@link DataType.readAs read as} an * instance of `valueType`. * * Every data type should be compatible with the following: * * * `Value Type` – the class corresponding to the data type's value * type. * * For a data type with a value type of `X`, `readAs(X, buffer)` is * equivalent to `readValue(buffer)`. * * @param valueType the type to check * @return `true` if a binary representation created by this data * type can read as an instance * of `valueType` * @since 6.0 */ canReadAs(valueType: new (...args: any[]) => any): boolean; /** * Create a value of a compatible class from binary. * * @param valueType the type of the result * @param buffer the binary data * @param offset the offset to start reading from the provided buffer (default = `0`) * @param length the length of the data to read (default = `input.length`) * @return the value in the form of the specified type * @throws an {@link InvalidDataError} if `valueType` is incompatible with this data * type, or `buffer` does not represent a valid value. * @since 6.0 */ readAs(valueType: new (...args: any[]) => T, buffer: Uint8Array, offset?: number, length?: number): T | null; readAs(valueType: new (...args: any[]) => T, buffer: CBORType): T | null; /** * Obtain a {@link DeltaType} by name or delta type. * * **Example:** * ``` * // Get by name * var deltas = datatype.deltaType("binary"); * ``` * * **Example:** * ``` * // Get by type * var deltas = datatype.deltaType(delta); * ``` * * @param name the name, as returned by {@link DeltaType.name} * @returns the delta type */ deltaType(name?: string): DeltaType; } /** * A placeholder data type that can represent any of the other datatypes. * * The sole purpose of this data type is to allow creating polymorphic streams * that can accept any data type. * * **Example:** * ``` * // Get the Any datatype and create a stream * var anyType = diffusion.datatypes.any(); * var stream = session.addStream('some_topic', anyType); * ``` */ export interface AnyDataType { /** * The external type identifier. * * @return the name of this datatype */ name(): string; } /** * @module diffusion.datatypes */ /** * Diffusion datatype implementations. * * Datatypes are accessed via the `diffusion` singleton. * * **Example:** * ``` * // Get the JSON datatype * var json = diffusion.datatypes.json(); * ``` * * **Example:** * ``` * // Get a datatype via name * var json = diffusion.datatypes.get('json'); * ``` * @namespace diffusion.datatypes * @since 5.7 */ export interface DataTypes { /** * Get the binary data type * * @return the Binary data type */ binary(): BinaryDataType; /** * Get the JSON data type * * @return the JSON data type */ json(): JSONDataType; /** * Get the Int64 data type * * @return the Int64 data type */ int64(): Int64DataType; /** * Get the string data type * * @return the String data type */ string(): StringDataType; /** * Get the double data type * * @return the Double data type */ double(): DoubleDataType; /** * Get the record V2 data type * * @return the RecordV2 data type */ recordv2(): RecordV2DataType; /** * Get the Any data type * * @return the Any data type */ any(): AnyDataType; /** * Get the timeseries data type * * @param valueType the value type of the timeseries data type * @return a timeseries data type */ timeseries(valueType: DataType): DataType, Event, Bytes>; /** * Obtain a {@link DataType} implementation by type * name, topic type, or value class * * @param name the type name as returned by {@link DataType.name}, the value * or a topic type. * @return the data type or `null` if no datatype was found */ get(name: any): DataType | null; /** * Obtain a {@link DataType} implementation by value class. * * For {@link DoubleDataType}, the associated value class is `Number`. * * @param valueClass the class * @return the data type * @throws an {@link IllegalArgumentError} if there is no data type for provided class */ getByClass(valueClass: new (...args: any[]) => any): DataType; } /** * @module diffusion.datatypes */ /// /** * Optional extension provided by {@link DataType} implementations that support * incremental changes to values. * * A data type can optionally support incremental changes to values, represented * by one or more types of delta. A delta is the difference between two values. * For large or composite values that change in small steps, it is more * efficient to transmit an initial value followed by a delta for each change * than to transmit a complete value for each change. * * Each implementation specifies a `value` type and a `delta` type. * Two values, oldValue and new Value, can be compared to produce a delta using * {@link DeltaType.diff}. The delta can be separately applied to oldValue to * create newValue using {@link DeltaType.apply}. * *

Deferred parsing
* Implementations can choose not to fully validate values when they are read, * but instead defer parsing until it is required. Consequently, all methods * that accept values may throw an error. * * @param the value type of the data type * @param the type(s) from which a value can be constructed * @param the binary type containing the CBOR data * * @since 5.7 */ export interface DeltaType { /** * The name of this delta type * * @returns the name */ name(): string; /** * Create a delta from two values. * * If there are many differences between oldValue and newValue, the result * might require more bytes to transmit than the new value, or be * computationally expensive to apply. In this case, it is better to discard * oldValue and publish newValue in its place. This can be checked using * {@link DeltaType.isValueCheaper}. * * The implementation can return the special constant {@link DeltaType.noChange} * to indicate the old value and new value are equivalent and there is no change * to publish. * * @param oldValue the old value * @param newValue the new value * @return the delta between values */ diff(oldValue: SourceType, newValue: SourceType): BinaryDelta; /** * Apply a delta to a value. * * @param old the old value * @param delta the delta to apply * @return the new value generated applying the delta to the old value * @throws an {@link InvalidDataError} if the value or delta is invalid */ apply(oldValue: SourceType, delta: BinaryDelta): ValueType | null; /** * Parse a delta from binary. * * @param binary the binary data * @param offset the offset from which to start reading from the buffer * @param length the length of data to read from the buffer * @return the delta * @throws an error if the binary is invalid */ readDelta(buffer: Uint8Array, offset?: number, length?: number): BinaryDelta; /** * Serialise a delta to binary. * * @param delta the delta to serialise * @return the serialised form of the delta * @throws an error if the delta cannot be serialised * * @deprecated since version 6.11. Buffer has been replaced by Uint8Array. * Use writeDeltaToArray instead. This will be removed * in a future release. */ writeDelta(delta: BinaryDelta): Buffer; /** * Serialise a delta to binary. * * @param delta the delta to serialise * @return the serialised form of the delta * @throws an error if the delta cannot be serialised */ writeDeltaToArray(delta: BinaryDelta): Uint8Array; /** * Constant returned by {@link DeltaType.diff} to * indicate that both values are equivalent. * * @return unique object representing no change in value */ noChange(): BinaryDelta; /** * Calculate if `value` is cheaper than the `delta`. The * result is typically determined by the length of the serialised form, but may * also consider the complexity of the delta. * * @param value the value to compare * @param delta the delta to compare * @return `true` if the value is considered cheaper than the delta * @throws an error if the value or delta is invalid */ isValueCheaper(value: SourceType, delta: BinaryDelta): boolean; } /** * @module diffusion.errors */ /** * A type containing information about the reason that an error occured */ export interface ErrorReasonType { /** * The error reason's id * * @deprecated since 6.8 *

* This member is deprecated and will be removed in the future. */ id: number; /** * The error reason's description * * @deprecated since 6.8 *

* This member is deprecated and will be removed in the future. */ reason: string; } /** * Enum containing reason codes used to report error conditions. *

* Some common ErrorReason values are defined as global constants. More specific reasons may be defined by * individual features. * * **Example:** * ``` * // Handle an error from the server * session.addStream('foo', diffusion.datatypes.string()).on('error', function(e) { * if (e == diffusion.errors.ACCESS_DENIED) { * // Handle authorisation error * } else { * // Log the problem * console.log(e); * } * }); * ``` */ export declare const ErrorReason: { [key: string]: ErrorReasonType; }; /** * Base class for all errors thrown by the diffusion client */ export interface DiffusionError { getType(): string; } /** * An error that signals that a `null` or `undefined` value was encountered. */ export declare class NullValueError extends Error implements DiffusionError { /** * The `null_value_error` error type */ static readonly type = "null_value_error"; /** * The constructor creates NullValueError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that signals a runtime error. */ export declare class RuntimeError extends Error implements DiffusionError { /** * The `runtime_error` error type */ static readonly type = "runtime_error"; /** * The cause of the error */ readonly cause?: Error | ErrorReasonType; /** * The constructor creates RuntimeError objects. * @param message The error message */ constructor(message: string, cause?: Error | ErrorReasonType); /** * Get the error type */ getType(): string; } /** * An error that is not expected to occur. */ export declare class AssertionError extends Error implements DiffusionError { /** * The `assertion_error` error type */ static readonly type = "assertion_error"; /** * The constructor creates RuntimeError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that signals that invalid data was encountered. */ export declare class InvalidDataError extends Error implements DiffusionError { /** * The `invalid_data_error` error type */ static readonly type = "invalid_data_error"; /** * The constructor creates InvalidDataError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that signals that an I/O error has occurred. */ export declare class IOError extends Error implements DiffusionError { /** * The `io_error` error type */ static readonly type = "io_error"; /** * The constructor creates IOError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that is reported from a service call. */ export declare class SessionError extends Error implements DiffusionError { /** * The `session_error` error type */ static readonly type = "session_error"; /** * The cause of the error */ readonly cause?: Error; /** * The constructor creates SessionError objects. * @param message The error message */ constructor(message: string, cause?: Error); /** * Get the error type */ getType(): string; } /** * An error that indicates that a function has been called with an illegal or * inappropriate argument. */ export declare class IllegalArgumentError extends Error implements DiffusionError { /** * The `illegal_argument_error` error type */ static readonly type = "illegal_argument_error"; /** * The constructor creates IllegalArgumentError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that indicates that the requested index is out of bounds. */ export declare class OutOfBoundsError extends Error implements DiffusionError { /** * The `out_of_bounds_error` error type */ static readonly type = "out_of_bounds_error"; /** * The constructor creates OutOfBoundsError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that indicates that a filter expression is invalid. */ export declare class InvalidFilterError extends Error implements DiffusionError { /** * The `invalid_filter_error` error type */ static readonly type = "invalid_filter_error"; /** * The list of errors that caused the filter to be invalid */ readonly errors: ErrorReport[]; /** * The constructor creates InvalidFilterError objects. * @param message The error message */ constructor(message: string, errors: ErrorReport[]); /** * Get the error type */ getType(): string; } /** * An error that indicates that a script is invalid. */ export declare class InvalidScriptError extends Error implements DiffusionError { /** * The `invalid_script_error` error type */ static readonly type = "invalid_script_error"; /** * The list of errors that caused the script to be invalid */ readonly errors: ErrorReport[]; /** * The constructor creates InvalidScriptError objects. * @param message The error message */ constructor(message: string, errors: ErrorReport[]); /** * Get the error type */ getType(): string; } /** * Indicates a problem that has occurred when building a schema. */ export declare class SchemaViolationError extends Error implements DiffusionError { /** * The `schema_violation_error` error type */ static readonly type = "schema_violation_error"; /** * The constructor creates SchemaViolationError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * Indicates a problem that has occurred when parsing a schema. */ export declare class SchemaParseError extends Error implements DiffusionError { /** * The `schema_parse_error` error type */ static readonly type = "schema_parse_error"; /** * The constructor creates SchemaParseError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that indicates that a retry limit has been reached. */ export declare class RetryLimitError extends Error implements DiffusionError { /** * The `retry_limit_error` error type */ static readonly type = "retry_limit_error"; /** * The constructor creates RetryLimitError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that indicates that a method has been called at an illegal or * inappropriate time. */ export declare class IllegalStateError extends Error implements DiffusionError { /** * The `illegal_state_error` error type */ static readonly type = "illegal_state_error"; /** * The constructor creates IllegalStateError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * An error that indicates an error that is internal to the diffusion client. */ export declare class InternalError extends Error implements DiffusionError { /** * The `internal_error` error type */ static readonly type = "internal_error"; /** * The constructor creates InternalError objects. * @param message The error message */ constructor(message: string); /** * Get the error type */ getType(): string; } /** * A reference to a registered handler. * * Such a handler reference is provided whenever a handler with a server side * presence is registered. */ export interface Registration { /** * Request that the handler is unregistered from the server. * * After the handler is unregistered, the handler's `onClose` method * will be called. * * A handler can only be unregistered once. A given instance will return the * same Promise if this method is called more than once. * * @returns a {@link Promise} that completes when a response is received from * the server */ close(): Promise; } /** * @module diffusion.events */ /** * An error callback */ export declare type Callback = (error: any) => U; /** * A Result represents a promise for the result of an async operation. * * It implements the full ES6 Promise specification and is in all respects equivalent to a Promise. * * @deprecated since 6.12 *

* Use the native Promise type instead */ export declare type Result = Promise; /** * @module diffusion.events * * @brief A module containing event streams * * @preferred */ /** * A callback function type for {@link Stream}s */ export declare type StreamCallback = (...args: any[]) => void; /** * A type mapping event names to callback functions */ export interface CallbackMap { [event: string]: StreamCallback; } /** * A {@link Stream} provides a series of events that may be consumed by * arbitrary listeners. The events emitted by a stream are defined by the * operation that created the stream and can carry event-specific arguments. * * A stream is created in an open state, and may immediately emit events. When a * Stream is closed it will emit a `close`. A closed stream will not * emit any further events, and will remain closed permanently. * * It is possible for a stream to encounter an error. In this case, an `error` event will be emitted, and * then the stream will be closed. * * This is a primitive class that is used to provide common event binding methods to other API components. * * @fires [error](../globals.html#error) * @fires {@link close} */ export interface Stream { /** * Register listeners against events. * * A single listener may be bound to an event by passing the event name and * listener function. * * Multiple listeners may be bound by passing in a {@link CallbackMap}, * mapping event names to listener functions. * * **Example:** * ``` * // Bind a single listener to the 'foo' event * stream.on('foo', function(arg1, arg2) { * console.log("Called for 'foo' event", arg1, arg2); * }); * ``` * * **Example:** * ``` * // Bind multiple listeners * stream.on({ * foo : function() { ... }, * bar : function() { ... }, * baz : function() { ... } * }); * ``` * * It is possible to bind multiple listeners to the same event. In this case, * the listeners will be called in the order they were bound. * * @param events the event name or {@link CallbackMap} mapping event names * to listeners * @param listener the listener to bind to the event, if passed as string. * This argument is ignored if the first argument is a * {@link CallbackMap}. * @return this stream. */ on(events: string | CallbackMap, listener?: StreamCallback): Stream; /** * Remove a listener from a specified event. * * **Example:** * ``` * // Bind a single listener to the 'foo' event and then deregister it * var listener = function() {}; * stream.on('foo', listener); * stream.off('foo', listener); * ``` * * **Example:** * ``` * // Bind a listener to the 'foo' event and deregister all listeners * var listener = function() {}; * stream.on('foo', listener); * stream.off('foo'); * ``` * * @param event the event name to remove or {@link CallbackMap} mapping * event names to listeners which will be removed * @param listener the listener to remove. All listeners for the event are * removed if this is not specified. This argument is * ignored if the first argument is a {@link CallbackMap}. * @return this stream. */ off(events: string | CallbackMap, listener?: StreamCallback): Stream; /** * Close the stream. This will emit a 'close' event to any assigned listeners. * No further events will be emitted. */ close(): void; } /** * Emitted when an error occurs in the {@link Stream} or in any of its listeners. * No further events will be emitted after this. * * @param error the error that occurred * * @event */ export declare type error = (err: Error) => void; /** * Emitted when the {@link Stream} has been closed through completion or the underlying session has been closed. * No further events will be emitted after this. * * @param error the reason why the stream was closed * * @event */ export declare type close = (reason?: string) => void; /** * @module diffusion.events */ /** * A subscription event */ export interface SubscriptionEvent { /** * The topic to which the subscription applies */ topic: string; /** * Instance that contains details about the topic */ specification: TopicSpecification; } /** * An unsubscription event */ export interface UnsubscriptionEvent { /** * The topic to which the unsubscription applies */ topic: string; /** * Instance that contains details about the topic */ specification: TopicSpecification; } /** * Provides a stream of topic events, specific to the topic selector that this ValueStream was created for, with * topic values provided as instances of the associated {@link DataType}. * * ValueStream inherits all functions defined on {@link Stream}. * * **Example:** * ``` * // Create a value stream for topic 'foo' * session.addStream('foo', datatype).on('value', function(topic, specification, newValue, oldValue) { * // Receive updates for the topic 'foo' * }); * * // Then subscribe to topic 'foo' * session.select('foo'); * ``` * * **Example:** * ``` * // Attach multiple listeners for events * session.addStream('foo', datatype).on({ * subscribe : function(topic, specification) { * // Subscribed to a particular topic * }, * unsubscribe : function(topic, specification, reason) { * // Unsubscribed from a particular topic * }, * value : function(topic, specification, newValue, oldValue) { * // Value from a topic * } * }); * ``` * *

Events

* *

open

* * Emitted when the subscription is initially opened, passing a reference to the * subscription itself. This will only be fired once. * *

subscribe

* * Emitted when a topic that is selected by this ValueStream's topic selector is * subscribed to by this session. Once subscribed, value update * events may be received for this topic. The specification is a {@link * TopicSpecification} instance that contains details about the topic. * * **Parameters:** * * `topic`: string - The topic to which the subscription applies * * `specification`: {@link TopicSpecification} - Instance that contains details about the topic * *

unsubscribe

* * Emitted when a topic that was previously subscribed, has been unsubscribed. * No further update events will be received from this topic until subscribed * again. Unsubscriptions may occur due to the topic being removed, or through * calling {@link Session.unsubscribe} - an object containing the reason is * provided. * * **Parameters:** * * `topic`: string - The topic to which the unsubscription applies * * `specification`: {@link TopicSpecification} - Instance that contains details about the topic * * `reason`: {@link UnsubscribeReason} - the reason for the unsubscription * *

value

* * Emitted when an update has been received for a topic's value. Values will be * provided as instances appropriate for the associated {@link DataType} this * subscription was created for. Both the previous value and the new value are * provided. * * **Parameters:** * * `topic`: string - The topic to which the update applies * * `specification`: {@link TopicSpecification} - Instance that contains details about the topic * * `newValue`: any - the new value of the topic * * `oldValue`: any - the old value of the topic * *

close

* * Emitted when the subscription has been closed using {@link ValueStream.close}. * *

error

* * Emitted when the subscription request fails. No further events will be emitted after this. * * **Parameters:** * * `error`: {@link ErrorReason} - the error the subscription request failed with */ export interface ValueStream extends Stream { /** * A static reference to the selector this Subscription was created for. */ readonly selector: TopicSelector; /** * Close the stream. No further events will be emitted. * * This does not unsubscribe the topic. Other streams may still receive * updates for the same topic selector. To unsubscribe, use {@link * Session.unsubscribe} */ close(): void; } /** * @module diffusion.clients */ /** * Dictionary containing standard session property keys */ export interface PropertyKeys { ALL_FIXED_PROPERTIES: string[]; ALL_USER_PROPERTIES: string[]; ALL_PROPERTIES: string[]; SESSION_ID: string; PRINCIPAL: string; CONNECTOR: string; TRANSPORT: string; CLIENT_TYPE: string; COUNTRY: string; LANGUAGE: string; SERVER_NAME: string; CLIENT_IP: string; LATITUDE: string; LONGITUDE: string; START_TIME: string; EXPIRY_TIME: string; ROLES: string; MQTT_CLIENT_ID: string; GATEWAY_TYPE: string; GATEWAY_ID: string; ENVIRONMENT: string; } /** * @hidden */ export interface ClientControlOptionsNamespace { PropertyKeys: PropertyKeys; ANONYMOUS: string; CloseReason: typeof CloseReasonEnum; SessionEventStreamEventType: typeof SessionEventStreamEventType; SessionState: typeof SessionState; } export declare const ClientControlOptions: ClientControlOptionsNamespace; /** * @module Session.clients */ /// /** * An object containing session properties */ export interface SessionProperties { [key: string]: string | null; } /** * Event types used within {@link SessionPropertiesListener.onSessionEvent}. * * **Example:** * ``` * session.clients.setSessionPropertiesListener(props, { * // ... * * onSessionEvent : function(sessionID, event, properties, previous) { * switch (event) { * case session.clients.SessionEventType.DISCONNECTED : * console.log(sessionID + " has disconnected"); * break; * case session.clients.SessionEventType.RECONNECTED : * console.log(sessionID + " has reconnected"); * break; * } * } * * // ... * }); * ``` * * @deprecated since 6.11 *

* This type is required for the deprecated {@link SessionPropertiesListener} * which is used with the deprecated {@link ClientControl.setSessionPropertiesListener}. *

* Use the new {@link ClientControl.addSessionEventListener}, * which provides greater functionality and reports sessions at * all cluster members. This interface will be removed in a * future release. */ export declare enum SessionEventType { /** * One or more relevant session properties have been updated. */ UPDATED = 0, /** * A session has reconnected. */ RECONNECTED = 1, /** * A session has failed over from one server to another in a cluster. */ FAILED_OVER = 2, /** * A session has disconnected. */ DISCONNECTED = 3 } /** * This feature provides the ability for a client session to control other * client sessions. * * It allows for notifications of client session events as well as the ability * to manage client sessions (forcibly closing them etc). * * It also provides the ability to monitor session locks. * * This feature also provides the ability to query the topic selections of * another session. * *

Access control

* * A session must have * {@link GlobalPermission.VIEW_SESSION VIEW_SESSION} permission to be able to * listen for notifications using {@link ClientControl.addSessionEventListener} or * {@link ClientControl.setSessionPropertiesListener}, or * {@link ClientControl.getSessionProperties get properties} of sessions. * * In addition, {@link GlobalPermission.REGISTER_HANDLER REGISTER_HANDLER} * permission is required to add a session event listener, a session property * listener, or queue event handler. * * In order to perform operations that change a specific session's state (such * as conflating, closing sessions, or changing roles), * {@link GlobalPermission.MODIFY_SESSION MODIFY_SESSION} permission is * required. * * To directly subscribe other sessions to topics, a session must have * {@link GlobalPermission.MODIFY_SESSION MODIFY_SESSION} permission, and * {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} permission for the * the topic selector used for subscription. The subscribed sessions * will only be subscribed to matching topics for which they have * {@link PathPermission.READ_TOPIC READ_TOPIC} permission. * * To directly unsubscribe other sessions, a session must have * {@link GlobalPermission.MODIFY_SESSION MODIFY_SESSION} permission, and * {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} permission for the topic * selector used for unsubscription. * * Getting the topic selections for a specified session requires * {@link GlobalPermission.VIEW_SESSION VIEW_SESSION} permission. * *

Accessing the feature

* * This feature may be obtained from a {@link Session session} as follows: * * ``` * var clients = session.clients; * ``` */ export interface ClientControl { /** * Event types used within {@link SessionPropertiesListener.onSessionEvent} * * @deprecated since 6.11 * This property is required for the deprecated {@link SessionPropertiesListener} * which is used with the deprecated {@link ClientControl.setSessionPropertiesListener}. *

* Use the new {@link ClientControl.addSessionEventListener}, * which provides greater functionality and reports sessions at * all cluster members. This interface will be removed in a * future release. */ readonly SessionEventType: typeof SessionEventType; /** * Register a listener that will be notified of * {@link SessionEvent client session events}. * * These events may occur when a client session is opened, becomes * disconnected, reconnects, fails over, or is closed. Events may also occur * if any of the session properties of the client session change as a result * of a call to {@link ClientControl.setSessionProperties}. * * When a listener is first added, by default, it will be called with * {@link SessionEventStreamEventType.STATE STATE} events * for all currently open sessions. The amount of data transferred from the * server is proportional to the number of connected clients and is * potentially large, especially if session properties are requested. To * mitigate this the caller can choose to only receive events for sessions * started after a specified time (e.g. from now), in which case events will * only be received for sessions that start after that time. * * A control session can register any number of listeners with different * parameters, but the cost in network traffic should be carefully * considered. * * When a listener is no longer required, it may be closed using the * {@link Registration} provided by the Promise result. * * The `parameters` parameter is used to define the level of event * detail required. * * @param listener the listener to be called with session event * notifications * * @param parameters a {@link SessionEventParameters} object defining the * level of event detail required. * * @return a Promise that completes when the listener has been * registered, returning a {@link Registration} which can be used to * unregister the listener. *

* Otherwise, an error will be returned. Common reasons for * failure include: *

*

    *
  • the session is closed; *
  • the session filter specified in the `parameters` was invalid; *
  • the session does not have * {@link GlobalPermission.REGISTER_HANDLER REGISTER_HANDLER} * and {@link GlobalPermission.VIEW_SESSION VIEW_SESSION} permissions. *
* * @since 6.11 */ addSessionEventListener(listener: SessionEventStream, parameters: SessionEventParameters): Promise; /** * Close one or more client sessions. * * **Example:** * ``` * session.clients.close(otherSessionID).then(function() { * // Other session has been closed * }, function(err) { * // There was an error when trying to close the other session * }); * ``` * * @param sessions Either a {@link SessionId} that identifies a single * client session, or a filter that identifies the set * of client sessions for which the change will be * applied. If a string is passed and is a parsable * `SessionId`, it is treated as a `SessionId`, otherwise * it assumed to be a filter. * @return a Promise that resolves to the number of affected * sessions *

* If unsuccessful, the promise will be rejected. Common reasons * for failure include: *

    *
  • {@link NullValueError} – if the session id is `null` or `undefined` */ close(sessions: string | SessionId): Promise; /** * Subscribe one or more client sessions to topics. * * To subscribe a single known session (anywhere in a cluster), a session id may be provided; * alternatively, a Session Filter may be used, in which case all sessions (anywhere in a cluster) * that satisfy the filter will be subscribed. * * New subscriptions will be established for existing topics that match the * provided topic selector and for which the subscribed session has * {@code READ_TOPIC} permission. The topic selector will be added to the * topic selections of the subscribed session, and re-evaluated when new * topics are added or the session's security roles change. * * A session that does not have {@code SELECT_TOPIC} permission for a topic * cannot subscribe directly, but can be subscribed indirectly using this * method. * * The second argument of this function can be a string, a {@link * TopicSelector}, or a non-empty of strings and {@link TopicSelector}s. * * **Example:** * ``` * // Subscribe a single session via SessionID * session.clients.subscribe(otherSessionID, ">foo").then(function() { * // Subscribed 'otherSession' to topic "foo" * }, function(err) { * // Subscription failed * console.log("Failed to subscribe session", err); * }); * ``` * * **Example:** * ``` * // Subscribe multiple sessions via a Session Filter * session.clients.subscribe("$ClientType IS 'JAVA'", ">foo").then(function(selected) { * console.log("Subscribed " + selected + " sessions to topic 'foo'"); * }, function(err) { * // Subscription failed * console.log("Failed to subscribe sessions", err); * }); * ``` * * @param session Either a {@link SessionId} that identifies a single * client session, or a filter that identifies the set * of client sessions for which the change will be * applied. If a string is passed and is a parsable * `SessionId`, it is treated as a `SessionId`, otherwise * it assumed to be a filter. * @param selector the Topic Selector(s) to subscribe to * @param scope (optional) specifies the scope of the selection. See {@link Topics * Topic Selection Scopes}. Defaults to {@link * Topics.DEFAULT_SELECTION_SCOPE DEFAULT_SELECTION_SCOPE}. * @return a Promise for this operation. If * subscribing with a session filter, the success callback * will be given the number of sessions selected by the * filter. *

    * If unsuccessful, the promise will be rejected. Common reasons * for failure include: *

      *
    • {@link IllegalArgumentError} – if the selector could not be parsed *
    • {@link NullValueError} – if any of the arguments are `null` or `undefined` */ subscribe(session: string | SessionId, selector: string | TopicSelector | Array, scope?: string): Promise; /** * Unsubscribe one or more client sessions from topics. * * To unsubscribe a single known session (anywhere in a cluster), a session id may be provided; * alternatively, a Session Filter may be used, in which case all sessions (anywhere in a cluster) * that satisfy the filter will be unsubscribed. * * The second argument of this function can be a string, a {@link * TopicSelector}, or a non-empty of strings and {@link TopicSelector}s. * * **Example:** * ``` * // Unsubscribe a single session via SessionID * session.clients.unsubscribe(otherSessionID, ">foo").then(function() { * // Unsubscribed 'otherSession' from topic "foo" * }, function(err) { * // Unsubscription failed * console.log("Failed to unsubscribe session", err); * }); * ``` * * **Example:** * ``` * // Unsubscribe multiple sessions via a Session Filter * session.clients.unsubscribe("$ClientType IS 'JAVA'", ">foo").then(function(selected) { * console.log("Unsubscribed " + selected + " sessions from topic 'foo'"); * }, function(err) { * // Unsubscription failed * console.log("Failed to unsubscribe sessions", err); * }); * ``` * * @param session Either a {@link SessionId} that identifies a single * client session, or a filter that identifies the set * of client sessions for which the change will be * applied. If a string is passed and is a parsable * `SessionId`, it is treated as a `SessionId`, otherwise * it assumed to be a filter. * @param selector the Topic Selector to unsubscribe from * @param scope (optional) specifies the scope of the selection. See {@link Topics * Topic Selection Scopes}. Defaults to {@link * Topics.DEFAULT_SELECTION_SCOPE DEFAULT_SELECTION_SCOPE}. * @return a Promise for this operation. If * unsubscribing with a session filter, the success * callback will be given the number of sessions selected * by the filter *

      * If unsuccessful, the promise will be rejected. Common reasons * for failure include: *

        *
      • {@link IllegalArgumentError} – if the selector could not be parsed *
      • {@link NullValueError} – if any of the arguments are `null` or `undefined` */ unsubscribe(session: string | SessionId, selector: string | TopicSelector | Array, scope?: string): Promise; /** * Unsubscribe topics from all topic selection scopes. * * This can be used at any time whilst connected to reduce the set of topics * to which the session is subscribed or negate earlier subscription * requests and will apply to all scopes in use. * * @param session Either a {@link SessionId} that identifies a single * client session, or a filter that identifies the set * of client sessions for which the change will be * applied. If a string is passed and is a parsable * `SessionId`, it is treated as a `SessionId`, otherwise * it assumed to be a filter. * * @param topics the Topic Selector to unsubscribe from * * @return a Promise for this operation. If * unsubscribing with a session filter, the success * callback will be given the number of sessions selected * by the filter *

        * If unsuccessful, the promise will be rejected. Common reasons * for failure include: *

          *
        • {@link IllegalArgumentError} – if the selector could not be parsed *
        • {@link NullValueError} – if any of the arguments are `null` or `undefined` * * @since 6.12 */ unsubscribeAllScopes(session: string | SessionId, topics: string | TopicSelector | Array): Promise; /** * Returns a map of the current topic selection state for a specified * session, keyed on topic selection scope. *

          * Each scope will have an ordered list of selections and/or deselections. *

          * The server conflates selections, so if there has been a selection that is * later rendered redundant by a deselection it will not be present. A scope * that has been used but fully deselected will therefore not be present in * the map and therefore no entry will have an empty list. *

          * If the session has no current selections the map will be empty. * * @param sessionId identifies the session to return topic selections for * * @return a Promise that completes when a response is received * from the server with the results of the operation. *

          * If the task completes successfully, the Promise result * will be a map of an ordered list of * {@link TopicSelection}s keyed on scope. If the default scope is * in use the key will be {@link Topics.DEFAULT_SELECTION_SCOPE}. * If unsuccessful, the promise will be rejected. Common reasons * for failure include: *

            *
          • {@link IllegalArgumentError} – if the selector could not be parsed *
          • {@link NullValueError} – if any of the arguments are `null` or `undefined` *
          * * @since 6.12 */ getTopicSelections(session: SessionId): Promise<{ [key: string]: TopicSelection[]; }>; /** * Query the server for property values of a specified client session. * * See {@link PropertyKeys} for a list of the available * fixed property keys. * * To request all fixed properties {@link * PropertyKeys.ALL_FIXED_PROPERTIES ALL_FIXED_PROPERTIES} * may be included as the key. * * To request all user properties {@link * PropertyKeys.ALL_USER_PROPERTIES ALL_USER_PROPERTIES} * may be included as the key. * * **Example:** * ``` * // Get values of all fixed properties for client whose session id is 'id'. * session.clients.getSessionProperties(id, PropertyKeys.ALL_FIXED_PROPERTIES); * ``` * * **Example:** * ``` * // Get values of the 'FOO' and 'BAR' properties for client whose session id is 'id'. * session.clients.getSessionProperties(id, ['FOO', 'BAR']).then(function(properties) { * console.log('Received properties for session', properties); * }, function(err) { * console.log('Unable to receive properties: ', err); * }); * ``` * * @param sessionID identifies the client session. * @param properties specifies the keys of the property values required. * @returns a Promise for this operation *

          * If unsuccessful, the promise will be rejected. Common reasons * for failure include: *

            *
          • {@link IllegalArgumentError} – if the session id is invalid */ getSessionProperties(session: string | SessionId, properties?: string[]): Promise; /** * Send a request to the server to change the user-defined session * properties for a session. * * It is also permissible to change the values of the following fixed * session properties :- * * $Country - will be normalised to upper case * $Language - will be normalised to lower case * $Latitude - Invalid value will be set to "NaN" * $Longitude - Invalid value will be set to "NaN" * * If values are provided for any other fixed session properties they will * be ignored. * * **Example:** * ``` * // Add a new session property for client whose session id is 'id'. * session.clients.setSessionProperties(id, { 'foo': 'bar' }); * * // Remove a session property for client whose session id is 'id'. * session.clients.setSessionProperties(id, { 'foo': null }).then(function(properties) { * console.log('Properties changed ', properties); * }, function(err) { * console.log('Unable to change properties: ', err); * }); * ``` * * @param session identifies the client session * @param properties the properties to change. Each entry in the map is a * property name and the new value. If the value is * `null` , any existing property with that * name will be removed (unless it is a fixed property). * Otherwise if the property name does not match any existing * property, that entry will be added as a new property * (although properties starting $ will be ignored). * @returns a Promise for this operation. If the session properties * were updated, the result type is a map of properties that * changed with their previous values. If no properties were * changed, the map will be empty. If any new properties were * added, the values in the map will be `null` to indicate that * they do not have an old value. *

            * Otherwise, an error will be returned. Common reasons for * failure include: *

            *

              *
            • {@link ErrorReason.ACCESS_DENIED} if the calling session * does not have sufficient permission. *
            • {@link ErrorReason.NO_SUCH_SESSION} if the calling session * is closed before the response was delivered. *
            • {@link ErrorReason.SESSION_CLOSED} if the calling session * is closed. *
            • {@link NullValueError} – if any of the arguments are `null` or `undefined` * */ setSessionProperties(session: string | SessionId, properties: SessionProperties | Map): Promise; /** * Send a request to the server to set all sessions that satisfy a session * filter with the new user-defined session properties. * * It is also permissible to change the values of the following fixed * session properties :- * * $Country - will be normalised to upper case * $Language - will be normalised to lower case * $Latitude - Invalid value will be set to "NaN" * $Longitude - Invalid value will be set to "NaN" * * If values are provided for any other fixed session properties they will * be ignored. * * **Example:** * ``` * // Remove session property {job=employee} * session.clients.setSessionPropertiesByFilter("job is 'employee'", { 'job': null }).then(function () { * // All sessions satisfied the filter have updated their properties * }, function (err) { * console.log("Failed to update properties ", err); * }); * ``` * @param filter session filter * @param properties the properties to change. Each entry in the map is a * property name and the new value. If the value is * `null` , any existing property with that * name will be removed (unless it is a fixed property). * Otherwise if the property name does not match any existing * property, that entry will be added as a new property * (although properties starting $ will be ignored). * * @returns a Promise that resolves when session properties have been changed. *

              * If successful, the result resolves with an integer value which * represents a number of sessions that have matched the filter and * for which the specified properties changes have been applied. *

              The operation can fail, * common reasons for failure include: *

                *
              • {@link ErrorReason.ACCESS_DENIED} if the calling session * does not have sufficient permission.
              • *
              • {@link ErrorReason.NO_SUCH_SESSION} if the calling * session is closed before the response was delivered. *
              • {@link ErrorReason.SESSION_CLOSED} if the calling * session is closed. *
              • a filter string was supplied that could not be parsed *
              • {@link NullValueError} – if any of the arguments are `null` or `undefined` *
              */ setSessionPropertiesByFilter(filter: string, properties: SessionProperties | Map): Promise; /** * Register a listener that will be notified when client sessions are * opened, disconnected, reconnected, closed or when selected session * property values are updated. * * This only notifies sessions connecting to the same server as the current * session and therefore if the Diffusion system is operating as a cluster * then the only way to receive notifications for sessions at all cluster * members would be to connect separate sessions (and listeners) to each * cluster member. When connecting to a cluster it is recommended that the * {@link ClientControl.addSessionEventListener addSessionEventListener} * method is used instead. * * When a listener is first set, it will be called with the required * properties of all currently open client sessions. The amount of data * transferred from the server is proportional to the number of connected * clients and is potentially large. The amount of data can be reduced * using the requiredProperties parameter. * * The requested property set controls the level of detail provided and * whether the listener is called for updates to sessions. If no * properties are requested then the listener is not called when session * properties are updated. * * To request all fixed properties {@link * PropertyKeys.ALL_FIXED_PROPERTIES ALL_FIXED_PROPERTIES} * should be included as a key and any other fixed property keys would be * ignored. To request all user properties {@link * PropertyKeys.ALL_USER_PROPERTIES ALL_USER_PROPERTIES} * should be included as a key and any other user property keys supplied * would be ignored. * * **Example:** * ``` * // Specify desired properties to listen to * var props = diffusion.clients.PropertyKeys.ALL_FIXED_PROPERTIES; * * // Create the listener * var listener = { * onActive : function(deregister) { * // Listener is active * }, * onSessionOpen : function(sessionID, properties) { * // A session has been opened * }, * onSessionEvent : function(sessionID, event, properties, previous) { * // A session's properties have changed (specified by 'event') * }, * onSessionClose : function(sessionID, properties, reason) { * // A session has closed * }, * onClose : function() { * // Listener is closed * } * } * session.clients.setSessionPropertiesListener(props, listener).then(function() { * // Registration was succesful * }, function(err) { * // There was an error registering the session listener * }); * ``` * * @param properties a set of required property keys. * @param listener the listener to register * @returns a Promise for this operation. * * @deprecated since 6.11 *

              * Use the new {@link ClientControl.addSessionEventListener addSessionEventListener}, * which provides greater functionality and reports on sessions at * all cluster members. This method will be removed in a future release. */ setSessionPropertiesListener(properties: string[], listener: SessionPropertiesListener): Promise; /** * Changes the assigned roles of one or more sessions. * * Initially a session has a set of roles assigned during authentication. * The set of assigned roles can be obtained from the session's `$Roles` * {@link Session session} property. * * When a session's assigned roles change, its `$Roles` property changes * accordingly. Changing the assigned roles can change the `READ_TOPIC` * permissions granted to the session. The session's subscriptions will be * updated accordingly. * * The same role must not occur in both `rolesToRemove` and * `rolesToAdd` sets. Either set can be an empty set but not both. * * @param sessions Either a {@link SessionId} that identifies a single * client session, or a filter that identifies the set * of client sessions for which the change will be * applied. If a string is passed and is a parsable * `SessionId`, it is treated as a `SessionId`, otherwise * it assumed to be a filter. * @param rolesToRemove a set of roles to be removed from the session. If * one or more roles from the list are not currently * assigned, they are ignored. * @param rolesToAdd a set of roles to be added to the session. If one or * more roles from the list are already assigned, they * are ignored. * @return a Promise that resolves when session roles have been changed. *

              * If successful, the result resolves with an integer value which * represents a number of sessions that have matched the filter and * for which the specified role changes have been applied. *

              * Otherwise, the Promise fails with an Error. Common reasons for * failure include: *

                *
              • the calling session does not have `MODIFY_SESSION` permission; *
              • a `SessionId` was supplied and there is no session with * the given `sessionId`; *
              • a filter string was supplied that could not be parsed *
              • the calling session is closed. *
              • {@link IllegalArgumentError} – if both `rolesToRemove` and `rolesToAdd` * are empty sets. *
              • {@link NullValueError} – if sessions `null` or `undefined` *
              * * @since 6.3 */ changeRoles(sessions: SessionId | string, rolesToRemove: string[] | Set, rolesToAdd: string[] | Set): Promise; /** * Returns details of the session (if any) that holds a named session lock. * * @param lockName the lock name * * @return a Promise that resolves with details of the named lock. *

              * If the Promise resolves normally then it returns the * details of the session that currently holds the lock, or null if * no session holds the named lock. *

              * Otherwise, the Promise will reject with * a {@link CompletionException}. Common reasons for failure, listed * by the exception reported as the * {@link CompletionException#getCause() cause}, include: *

                *
              • {@link PermissionsException} – if the calling session * does not have {@code VIEW_SERVER} permissions; *
              • {@link SessionClosedException} – if the calling session * is closed. *
              * @since 6.12 */ getSessionLock(lockName: string): Promise; /** * Returns details of all session locks currently held. * * @return a Promise that resolves with details of all session locks that are * currently held. *

              * If the Promise resolves normally then it returns a map * of session locks keyed on the lock name where the value * identifies the session currently holding the lock. If there are * no session locks currently held by anybody this will return an * empty map. *

              * Otherwise, the Promise will reject with * a {@link CompletionException}. Common reasons for failure, listed * by the exception reported as the * {@link CompletionException#getCause() cause}, include: *

                *
              • {@link PermissionsException} – if the calling session * does not have {@code VIEW_SERVER} permissions; *
              • {@link SessionClosedException} – if the calling session * is closed. *
              * @since 6.12 */ getSessionLocks(): Promise<{ [key: string]: SessionLockDetails; }>; /** * Control client queue conflation. * * Each session begins with conflation enabled or disabled based on the * queue configuration of the connector it is using. This method allows * conflation to be enabled or disabled for specific sessions at runtime. * * Conflation is the process of merging or discarding topic updates queued * for a session to reduce the server memory footprint and network data. * Conflation needs to be enabled for a session and a policy configured for * the topic to have an effect. Policies are configured on a per-topic * basis using the {@link CONFLATION topic property CONFLATION}. * * @param sessions Either a {@link SessionId} that identifies a single * client session, or a filter that identifies the set * of client sessions for which the change will be * applied. If a string is passed and is a parsable * `SessionId`, it is treated as a `SessionId`, otherwise * it assumed to be a filter. * * @param conflate `true` to enable conflation, `false` to disable conflation * * @return a Promise that resolves to the number of affected * sessions *

              * If the conflation policy was updated for the identified session, * the Promise will resolve successfully. *

              * Otherwise, the Promise fails with an Error. Common reasons for * failure include: *

                *
              • the identified session was closed before the response was * delivered; *
              • the calling session does not have `MODIFY_SESSION` permission; *
              • the calling session is closed. *
              • {@link NullValueError} – if sessions is `null` or `undefined` *
              * * @since 6.5 */ setConflated(sessions: SessionId | string, conflated: boolean): Promise; } /** * The Session Properties Listener interface for receiving session property * events. This interface must be implemented by the user, to be registered via * {@link ClientControl.setSessionPropertiesListener}. * * A session properties listener has a lifecycle that reflects the registration * state on the server. This is expressed through the callback methods. Once * {@link SessionPropertiesListener.onClose onClose} has been * called, no further interactions will occur. * * @deprecated since 6.11 *

              * Use the new {@link ClientControl.addSessionEventListener}, * which provides greater functionality and reports sessions at * all cluster members. This interface will be removed in a * future release. */ export interface SessionPropertiesListener { /** * Called when the listener has been registered at the server and is now * active. * * @param deregister a function to call that will deregister and close this * handler. The function will resolve when the handler * has been deregistered. */ onActive(deregister: () => Promise): void; /** * Called when the listener is deregistered, or the session is closed. */ onClose(): void; /** * Notification of a contextual error related to this handler. This is * analogous to an unchecked exception being raised. Situations in which * onError is called include the session being closed before the * handler is registered, a communication timeout, or a problem with the * provided parameters. No further calls will be made to this handler. * * @param error the error * * @since 5.9 */ onError(error: any): void; /** * Notification that a new client session has been opened. * * When the listener is registered, this will be called for all existing * sessions. It will then be called for every client session that opens * whilst the listener is registered. * * This will be called for client session regardless of requested session * properties. * * @param session the session identifier * @param properties the map of requested session property values. */ onSessionOpen(session: SessionId, properties: SessionProperties): void; /** * Notification of a session event that can result in a change of properties. * * @param session the session identifier * @param type the type of event * @param properties the map of requested property values * @param previous a map of previous values for keys that have changed. * This will only contain changed values and not the * whole required property set. */ onSessionEvent(session: SessionId, type: SessionEventType, properties: SessionProperties, previous: SessionProperties): void; /** * Notification that a client session has closed. * * This will be called for every client that closes whilst the listener is * registered, regardless of requested session properties. * * @param session the session identifier * @param properties the map of requested property values * @param reason the reason why the session was closed */ onSessionClose(session: SessionId, properties: SessionProperties, reason: ClientCloseReason): void; } /** * The stream to receive for session event listener notifications. * * This is used along with {@link ClientControl.addSessionEventListener * addSessionEventListener} to obtain notifications for client sessions. * * @since 6.11 */ export interface SessionEventStream { /** * Notification of a session event. * * @param event the session event */ onSessionEvent(event: SessionEvent): void; /** * Notification that a stream context was closed normally. * * No further calls will be made for the stream context. */ onClose(): void; /** * Notification of a contextual error related to this callback. This is * analogous to an exception being raised. Situations in which * `onError` is called include the session being closed, a * communication timeout, or a problem with the provided parameters. No * further calls will be made to this callback for the call context. * * @param errorReason a value representing the error; this can be one of * constants defined in {@link ErrorReason}, or a feature-specific * reason */ onError(errorReason: ErrorReasonType): void; } /** * The type of a {@link SessionEvent}. */ export declare enum SessionEventStreamEventType { /** * The event indicates a change of state of the identified * session, including the opening of a new session. */ STATE = 0, /** * The event indicates a change to the session properties of the * identified session. */ PROPERTIES = 1 } /** * The session state as given by a {@link SessionEvent}. */ export declare enum SessionState { /** * The session is connected and active. */ ACTIVE = 0, /** * The session is disconnected. */ DISCONNECTED = 1, /** * The session has reconnected to the same server after a * disconnection. */ RECONNECTED = 2, /** * The session has failed over to a different server in the * cluster after a disconnection. */ FAILED_OVER = 3, /** * The session has closed. */ CLOSED = 4 } /** * The interface for an event delivered by a {@link SessionEventStream}. */ export interface SessionEvent { /** * Provides the session identifier of the client session that the * event relates to. * * @return the client session id */ readonly sessionId: SessionId; /** * Provides the event type. * * @return the event type */ readonly type: SessionEventStreamEventType; /** * Provides the current state of the session. * * @return the session state */ readonly state: SessionState; /** * Provides the session's properties. * * Only those properties requested when registering the listener * will be present in the map. * * If no properties were requested or {@link SessionEvent.state} is * {@link SessionState.CLOSED CLOSED} the map will be empty. * * @return the map of session properties */ readonly properties: SessionProperties; /** * Provides a map of the previous values of session properties that * have changed. * * This map will be empty if no session properties were requested or * the event did not result in a change of any properties. * * This map will only be populated if {@link SessionEvent.type} is * {@link SessionEventStreamEventType.PROPERTIES PROPERTIES} or {@link SessionEvent.state} is * {@link SessionState.RECONNECTED RECONNECTED}, {@link SessionState.FAILED_OVER * FAILED_OVER}, or {@link SessionState.DISCONNECTED DISCONNECTED}. * * This will only contain keys that have changed and not the whole * required property set. * * When a new property is added the value in this map will be * `null`. * * When a property is removed there will be a value in this map but * not in {@link SessionEvent.properties}. * * @return the changed session properties */ readonly changedProperties: SessionProperties; /** * Provides the reason a session was closed. * * If {@link SessionEvent.state} is {@link SessionState.CLOSED CLOSED} this contains the * reason the session was closed. * * @return the reason for session closure or null if {@link SessionEvent.state} * is not {@link SessionState.CLOSED CLOSED}. */ readonly closeReason?: ClientCloseReason; /** * Convenience method to determine whether the event notifies the * opening of a new session. * * This is equivalent to: * * * event.type == Type.STATE && event.state == State.ACTIVE * * * @return true if the type is `STATE` and the state is `ACTIVE`, * otherwise false */ isOpenEvent(): boolean; } /** * A builder for {@link SessionEventParameters}. * * An instance of such a builder is created using {@link newSessionEventParametersBuilder}. */ export interface SessionEventParametersBuilder { /** * Sets a session filter which will determine which sessions events * will be notified for. * * See {@link Session} for a full description of how to specify * session filters. * * If no filter is specified then notifications will be provided for * all sessions that satisfy any other specified requirements. * * Specifying `null` will remove any current filter from the * builder. * * @param filter the session filter * * @return this builder */ filter(filter: string): SessionEventParametersBuilder; /** * Specifies the session property keys of all session properties to * be returned with events. * * See {@link Session} for a full list of available fixed property * keys. * * To request all fixed properties include * {@link PropertyKeys.ALL_FIXED_PROPERTIES} as a key. In this case any * other fixed property keys would be ignored. * * To request all user properties include * {@link PropertyKeys.ALL_USER_PROPERTIES} as a key. In this case any * other user properties are ignored. *

              * If this is not specified (or no property keys are provided) then * no session property values will be returned with the events and * events of type * {@link SessionEventStreamEventType.PROPERTIES * PROPERTIES} will not be notified. * * @param properties a list of required property keys * * @return this builder */ properties(properties: string[]): SessionEventParametersBuilder; properties(...properties: string[]): SessionEventParametersBuilder; /** * Used to indicate that events are only to be reported for sessions * that start after a specified time. * * If this is not set, the default is to notify events for all * current sessions, even if they started before registration of the * listener. This could potentially result in a large number of * events for all current sessions. * * If the user is only interested in new sessions * `after(Date.now())` could be used. * * @param time only sessions starting after the specified time will * be notified. Specifying null will remove any previously * specified time from the builder. The time can be specified * as a Unix timestamp in milliseconds or as a Date object. * * @return this builder */ after(time: number | Date): SessionEventParametersBuilder; /** * Builds a new {@link SessionEventParameters} instance with the current settings of the * builder. * * @return a new {@link SessionEventParameters} instance */ build(): SessionEventParameters; } /** * Provides parameters which specify the level of detail required by a * {@link SessionEventStream} registered using * {@link ClientControl.addSessionEventListener addSessionEventListener}. * * Parameters may be built using the {@link SessionEventParametersBuilder}. * * @since 6.11 */ export interface SessionEventParameters { /** * Indicates the session filter or `undefined` if one has not been set */ readonly filter?: string; /** * Indicates the requested properties or `undefined` if none have been set */ readonly properties?: Set; /** * Indicates a session start time after which session events should be * notified or `undefined` if one has not been set. */ readonly after?: number; } /** * Provides details of a session lock. * * @since 6.12 */ export interface SessionLockDetails { /** * Returns the name of the server that the session holding the lock is * connected to. * * @return the server name */ readonly serverName: string; /** * Returns the session identifier of the session that holds the lock. * * @return the session holding the lock */ readonly sessionId: SessionId; /** * Returns the lock sequence number. * * @return lock sequence number */ readonly sequence: Long; } /** * @module Session.messages */ /** * Messages Feature. * * This feature provides a client session with request-response messaging * capabilities that can be used to implement application services. * * Request-response messaging allows a session to send requests to other * sessions. Each receiving session provides a corresponding response, which is * returned to the sending session. Each request and response carries an * application provided value. * * The method used to send a request determines which sessions will receive it. * Each request is routed using the provided *message path* – an application * provided string. Two addressing schemes are provided: *unaddressed requests* * and *addressed requests*. * * ### Unaddressed requests * * A session can provide an application service by implementing a handler and * registering it with the server. This is somewhat similar to implementing a * REST service, except that interactions between the sender and receiver are * asynchronous. * * Unaddressed requests sent using {@link Messages.sendRequest sendRequest} are * routed by the server to a handler that has been pre-registered by another * session, and matches the message path. * * Handlers are registered with {@link Messages.addRequestHandler}. Each session * may register at most one handler for a given message path. Optionally, one or * more session property names can be provided (see {@link Session} for a full * description of session properties), in which case the values of the session * properties for each recipient session will be returned along with its * response. To add a request handler, the control client session must have * {@link GlobalPermission.REGISTER_HANDLER REGISTER_HANDLER} permission. If * registering to receive session property values, the session must also have * {@link GlobalPermission.VIEW_SESSION VIEW_SESSION} permission. * * Routing works as follows: * *

                *
              1. The session {@link Messages.sendRequest sends} the request, providing the * message path, the request value and data type, and the expected response * type. *
              2. The server uses the message path to apply access control. The sender must * have the {@link PathPermission.SEND_TO_MESSAGE_HANDLER * SEND_TO_MESSAGE_HANDLER} path permission for the message path, or the request * will be rejected. *
              3. The server uses the message path to select a pre-registered handler and * route the request to the appropriate recipient session. The server will * consider all registered handlers and select one registered for the most * specific path. If multiple sessions have registered a handler registered for * a path, one will be chosen arbitrarily. If there is no registered handler * matching the message path, the request will be rejected. *
              4. Otherwise, the server forwards the request to one of the sessions * registered to handle the message path. The message path is also passed to the * recipient session, providing a hierarchical context. *
              5. The recipient session processes the request and returns a response to the * server, which forwards the response to the sending session. *
              * * Registration works across a cluster of servers. If no matching handler is * registered on the server to which the sending session is connected, the * request will be routed to another server in the cluster that has one. * * ### Addressed requests * * Addressed requests provide a way to perform actions on a group of sessions, * or to notify sessions of one-off events (for repeating streams of events, use * a topic instead). * * An addressed request can be sent to a set of sessions using {@link * Messages.sendRequestToFilter sendRequestToFilter}. For the details of session * filters, see {@link Session}. Sending a request to a filter will match zero * or more sessions. Each response received will be passed to the provided * {@link FilteredResponseHandler callback}. As a convenience, an addressed * request can be sent a specific session using the overloaded variant of {@link * Messages.sendRequest sendRequest} that accepts a session id. * * Sending an addressed request requires {@link PathPermission.SEND_TO_SESSION * SEND_TO_SESSION} permission. * * If the sending session is connected to a server belonging to a cluster, the * recipient sessions can be connected to other servers in the cluster. The * filter will be evaluated against all sessions hosted by the cluster. * * To receive addressed requests, a session must set up a local request stream * to handle the specific message path, using {@link Messages.setRequestStream * setRequestStream}. When a request is received for the message path, the * {@link RequestStream.onRequest onRequest} method on the stream is triggered. * The session should respond using the provided {@link Responder * responder}. Streams receive an {@link RequestStream.onClose onClose} callback when * unregistered and an {@link RequestStream.onError onError} callback if the session is * closed. * * If a request is sent to a session that does not have a matching stream for * the message path, an error will be returned to the sending session. * * ### Accessing the feature * * Obtain this feature from a {@link Session session} as follows: * * **Example:** * ``` * // Get a reference to messaging feature * var messages = session.messages; * ``` */ export interface Messages { /** * Register a request handler to handle requests from other client sessions * for a branch of the message path hierarchy. * * Each control session may register a single handler for a branch. When the * handler is no longer required, it may be closed using the {@link * Registration} provided by the result. To change the handler for a * particular branch the previous handler must first be closed. * * **Example:** * ``` * // Create a request handler that handles strings * var handler = { * onRequest: function(request, context, responder) { * console.log(request); // Log the request * responder.respond('something'); * }, * onError: function() {}, * onClose: function() {} * }; * * // Register the handler * control.messages.addRequestHandler('test/path', handler).then(function() { * // Registration happened successfully * }, function(error) { * // Registration failed * }); * ``` * * @param path the request path to handle * @param handler request handler to be registered at the server * @param sessionProperties an optional array of keys of session properties * that should be supplied with each request. See {@link Session} for * a full list of available fixed property keys. To request all fixed * properties include {@link PropertyKeys.ALL_FIXED_PROPERTIES} as a * key. In this case any other fixed property keys would be ignored. * To request all user properties include {@link * PropertyKeys.ALL_USER_PROPERTIES} as a key. In this case any other * user properties are ignored. * @param requestType an optional request data type * @returns the registration {@link Promise} that resolves * when the handler has been registered, returning a {@link * Registration} which can be used to unregister the handler. *

              * Otherwise, the Promise will fail with an error. Common reasons for * failure include: *

                *
              • the session is closed; *
              • the session has already registered a handler for this message * path; *
              • the session does not have `REGISTER_HANDLER` permission to * register a request handler on the server; *
              • the session does not have `VIEW_SESSION` permission to access * the client's session properties. *
              • {@link NullValueError} – if any of the required arguments are * `null` or `undefined` *
              */ addRequestHandler(path: string, handler: RequestHandler, sessionProperties?: string[], requestType?: DataType): Promise; /** * Send a request. If a `target` is supplied, the request will be sent to * the target session only. * * A response is returned when the {Promise} is complete. * * **Example:** * ``` * // Send a string request to be received by the server and passed to a * // {Session.messages.RequestHandler} registered on the supplied path * session.messages.sendRequest('test/path', 'string request'); * ``` * * **Example:** * ``` * // Send a JSON request to be received by the server and passed to a * // {Session.messages.RequestHandler} registered on the supplied path * session.messages.sendRequest('test/path', diffusion.datatypes.json() * .from({ 'foo': 'bar'}), diffusion.datatypes.json()); * ``` * * **Example:** * ``` * // Send an implicit JSON request to be received by the server and passed to a * // {Session.messages.RequestHandler} registered on the supplied path * session.messages.sendRequest('test/path', { * dwarfs: ['sneezy', 'sleepy','dopey', * 'doc', 'happy', 'bashful', * 'grumpy'] * }); * ``` * * @param path the path to send the request to * @param request the request to send * @param target the target recipient's session ID (as a string or Session ID object) * @param requestType an optional request {@link DataType DataType} * @param responseType an optional response {@link DataType DataType} * @return A {@link Promise} that resolves with the response when a response * has been received by the session if the task completes * successfully. *

              * Otherwise, the Promise will fail with an Error. Common reasons for * failure include: *

                *
              • the session does not exist on the server; *
              • the recipient session does not have a local request stream * registered for this path; *
              • the request is not compatible with the datatype bound to the * handler's message path; *
              • the response is not compatible with the specified response * type; *
              • the request has been rejected by the recipient session * calling `Responder.reject(message)`; *
              • the session is closed; *
              • the session does not have `SEND_TO_SESSION` permission; *
              • {@link IllegalArgumentError} – the request could not be parsed by * the calling client; *
              • {@link InvalidDataError} – the response could not be parsed; *
              • {@link NullValueError} – if any of the required arguments are * `null` or `undefined` *
              */ sendRequest(path: string, request: any, target: SessionId | string, requestType?: DataType | TopicType | (new (...args: any[]) => any) | string, responseType?: DataType | TopicType | (new (...args: any[]) => any) | string): Promise; sendRequest(path: string, request: any, requestType?: DataType | TopicType | (new (...args: any[]) => any) | string, responseType?: DataType | TopicType | (new (...args: any[]) => any) | string): Promise; /** * Send a request to all sessions that satisfy a given session filter. * * **Example:** * ``` * // Send a string request to be received by the server and passed to sessions matching the filter. * session.messages.sendRequestToFilter('$Principal NE 'control'', 'test/path', 'string request', * { * onResponse: (sessionID, response) => { * console.log(response); // Log the response * }, * onResponseError : () => {} * }); * ``` * * **Example:** * ``` * // Send a JSON request to be received by the server and passed to sessions matching the filter. * session.messages.sendRequestToFilter('$Principal NE 'control'', 'test/path', * { dwarfs: ['sneezy', 'sleepy','dopey' ] }, * { * onResponse: (sessionID, response) => { * console.log(response.get()); // Log the response * }, * onResponseError: () => {} * }, diffusion.datatypes.json(), diffusion.datatypes.json()); * ``` * * @param filter the session filter expression. See {@link Session} * for a full description of filter expressions. * @param path message path used by the recipient to select an * appropriate handler * @param request the request to send * @param callback the handler to receive notification of responses * (or errors) from sessions * @param requestType an optional request {@link DataType DataType} * @param responseType an optional response {@link DataType DataType} * @return a Promise that resolves when the server has dispatched all the * requests. *

              * If the server successfully evaluated the filter, the result of * this contains the number of sessions the request was sent to. * Failure to send a request to a particular matching session is * reported to the `callback`. *

              * Otherwise, the Promise will fail with an Error. Common reasons for * failure include: *

                *
              • the `filter` parameter could not be parsed; *
              • the calling session does not have `SEND_TO_SESSION` permission; *
              • the calling session is closed. *
              • {@link IllegalArgumentError} – the request could not be parsed by * the calling client; *
              • {@link NullValueError} – if any of the required arguments are * `null` or `undefined` *
              */ sendRequestToFilter(filter: string, path: string, request: any, callback: FilteredResponseHandler, requestType?: DataType | TopicType | (new (...args: any[]) => any), responseType?: DataType | TopicType | (new (...args: any[]) => any)): Promise; /** * Set a request stream to handle requests to a specified path. * * **Example:** * ``` * // Set a request stream handler to handle string requests to 'test/path' * var handler = { * onRequest: function (path, request, responder) { * console.log(request); * responder.respond('hello'); * }, * onError: function() {} * }; * * control.messages.setRequestStream('test/path', handler, * diffusion.datatypes.string(), diffusion.datatypes.string()); * ``` * * @param path the path to receive request on * @param stream the request stream to handle requests to this path * @param requestType an optional request {@link DataType DataType} * @param responseType an optional response {@link DataType DataType} * @returns `undefined` if the request stream is the first stream * to be set to the path, otherwise this method will * return the previously set request stream. */ setRequestStream(path: string, stream: RequestStream, requestType?: DataType | TopicType | (new (...args: any[]) => any), responseType?: DataType | TopicType | (new (...args: any[]) => any)): RequestStream | undefined; /** * Remove the request stream at a particular path. * * @param path the path at which to remove the request stream * @returns the request stream that was removed from the path. If * the path does not have a request stream assigned (or the * path does not exist), `undefined` will be returned instead. */ removeRequestStream(path: string): RequestStream | undefined; } /** * Interface which specifies a request stream to receive request notifications. */ export interface RequestStream { /** * Called to indicate a request has been received. * * @param path the path the request was sent on * @param request the request that was received * @param responder the responder to dispatch a response back to the requester */ onRequest(path: string, request: any, responder: Responder): void; /** * Notification of a contextual error related to this stream. This is * analogous to an Error being thrown. Situations in which * `onError` is called include being unable to parse the request * with the data type the stream was registered with. No further calls will * be made to this stream. * * @param error the error */ onError(error: ErrorReasonType): void; /** * Called when the request stream is removed, or the session is closed. */ onClose(): void; } /** * Interface which specifies a request handler to receive request notifications. * * @class Session.messages.RequestHandler */ export interface RequestHandler { /** * Called to indicate a request has been received. * * @param {Object} request - The request that was received * @param {Session.messages.RequestContext} context - Context object that provides the session id * (session that sent the request), path and session properties * @param {Session.messages.Responder} responder - The responder to dispatch a response back to the requester * @function Session.messages.RequestHandler.onRequest */ onRequest(request: any, context: RequestContext, responder: Responder): void; /** * Notification of a contextual error related to this handler. This is * analogous to an Error being thrown. Situations in which * `onError` is called include the session being closed before the * handler is registered, a communication timeout, or a problem with the * provided parameters. No further calls will be made to this handler. * * @param error the error */ onError(error: any): void; /** * Called when the request handler is unregistered, or the session is closed. */ onClose(): void; } /** * Interface which specifies a response handler for requests dispatched through * a filter. */ export interface FilteredResponseHandler { /** * Called to indicate a response has been received. * * @param sessionId session ID of the session that sent the response * @param response response object * @function Session.messages.FilteredResponseHandler.onResponse */ onResponse(sessionId: SessionId, response: any): void; /** * Called when a response from a session results in an error. * * @param sessionId sessionID of the session in error * @param errorReason the error reason */ onResponseError(sessionId: SessionId, error: Error): void; } /** * Responder interface to dispatch responses to requests. */ export interface Responder { /** * Dispatch a response to a request. * * @param response the response to send * @param dataType the datatype of the response * @throws an {@link IllegalArgumentError} if the response cannot be serialised */ respond(response: any, dataType?: DataType | TopicType | (new (...args: any[]) => any)): void; /** * Reject a message * * @param message the message indicating the failure */ reject(message: string): void; } /** * A message request context */ export interface RequestContext { /** * SessionId of the session that sent the request */ sessionId: SessionId; /** * The message path of the request */ path: string; /** * The session properties */ properties: { [key: string]: string; }; } /** * This feature allows a client to configure metric collectors. * * Diffusion servers provide metrics which are made available in several ways: *
                *
              • Java Management Extensions (JMX) MBeans. *
              • Through the Diffusion Management Console. *
              • As endpoints for Prometheus. *
              * * Metric collectors allow custom aggregation of metrics that are relevant to * your application. There are no default metric collectors, only the ones that * you create. * * There are two types of metric collector: Session Metric Collectors and Topic * Metric Collectors. * * For full details regarding the configuration and operation of metric * collectors see the user manual. * *

              Session Metric Collectors.

              * * These can be configured to record metric data for a subset of all sessions, * specified with a session filter. * * The set of metrics recorded by each session metric collector is the same as * those recorded for the whole server. For full details of session metrics, see * the table in the user manual. * * If the session filters of two different session metric collectors select the * same session, both will record metrics for that session. It is only valid to * add the metrics of different session metric collectors if their session * filters select distinct sets of sessions. * * You can optionally group the sessions within a collector by session * properties. * *

              Topic Metric Collectors

              * * These can be configured to record metric data for a subset of all topics, * specified with a topic selector. * * You can optionally group the topics within a collector by topic type. * * The set of metrics recorded by each topic metric collector is the same as * those recorded for the whole server. For full details of topic metrics, see * the table in the user manual. * * If the topic selectors of two different topic metric collectors select the * same topic, both will record metrics for that topic. It is only valid to add * the metrics of different topic metric collectors if their topic selectors * select distinct sets of topics. * *

              Access control

              * * The following access control restrictions are applied: *
                *
              • To {@link Metrics.putSessionMetricCollector put} or * {@link Metrics.removeSessionMetricCollector remove} a session metric collector, a * session needs the {@link GlobalPermission.CONTROL_SERVER CONTROL_SERVER} * global permission. *
              • To {@link Metrics.putTopicMetricCollector put} or * {@link Metrics.removeTopicMetricCollector remove} a topic metric collector, a * session needs the {@link GlobalPermission.CONTROL_SERVER CONTROL_SERVER} * global permission. *
              • To list {@link Metrics.listSessionMetricCollectors session metric collectors} or * {@link Metrics.listTopicMetricCollectors topic metric collectors}, a session needs * the {@link GlobalPermission.VIEW_SERVER VIEW_SERVER} global permission. *
              * *

              Accessing the feature

              * * This feature may be obtained from a {@link Session session} as follows: * *
               * const metrics = session.metrics;
               * 
              * * @author DiffusionData Limited * * @since 6.7 */ export interface Metrics { /** * Add a session metric collector, replacing any with the same name. * * A {@link SessionMetricCollector} instance can be created using * {@link newSessionMetricCollectorBuilder}. * * @param collector the session metric collector * * @return a Promise that resolves when a response is received * from the server. *

              * If the task completes successfully, the result will be null. The * result type is `any` rather than `void` to provide forward * compatibility with future iterations of this API that may provide * a non-null result with a more specific result type. *

              * Otherwise, the Promise will reject with an Error. Common reasons * for failure include: *

                *
              • if the metric collector session filter is invalid; *
              • if the calling session does not have {@link * GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission; *
              • if the operation failed due to a transient cluster error; *
              • if the session is closed. *
              • {@link NullValueError} – if the collector is `null` or `undefined` *
              */ putSessionMetricCollector(collector: SessionMetricCollector): Promise; /** * Retrieves the current session metric collectors. * * @return a Promise that completes when a response is received * from the server. *

              * If the task completes successfully, the result will be a list of * current session metric collectors. *

              * Otherwise, the Promise will reject with an Error. Common reasons * for failure include: *

                *
              • if the calling session does not have {@link * GlobalPermission.VIEW_SERVER VIEW_SERVER} permission; *
              • if the session is closed. *
              */ listSessionMetricCollectors(): Promise; /** * Removes any session metric collector with the given name, if it exists. * * @param name the session metric collector name * * @return a Promise that resolves when a response is received * from the server. *

              * If the task completes successfully, the result will be null. The * result type is `any` rather than `void` to provide forward * compatibility with future iterations of this API that may provide * a non-null result with a more specific result type. *

              * Otherwise, the Promise will reject with an Error. Common reasons * for failure include: *

                *
              • if the calling session does not have {@link * GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission; *
              • if the operation failed due to a transient cluster error; *
              • if the session is closed. *
              • {@link NullValueError} – if the name is `null` or `undefined` *
              */ removeSessionMetricCollector(name: string): Promise; /** * Add a topic metric collector, replacing any with the same name. * * A {@link TopicMetricCollector} instance can be created using * {@link newTopicMetricCollectorBuilder}. * * @param collector the topic metric collector * * @return a Promise that resolves when a response is received from the * server. *

              * If the task completes successfully, the result will be null. The * result type is `any` rather than `void` to provide forward * compatibility with future iterations of this API that may provide * a non-null result with a more specific result type. *

              * Otherwise, the Promise will reject with an Error. Common reasons * for failure include: *

                *
              • if the metric collector session filter is invalid; *
              • if the calling session does not have {@link * GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission; *
              • if the operation failed due to a transient cluster error; *
              • if the session is closed. *
              • {@link NullValueError} – if the collector is `null` or `undefined` *
              */ putTopicMetricCollector(collector: TopicMetricCollector): Promise; /** * Retrieves the current topic metric collectors. * * @return a Promise that completes when a response is received * from the server. *

              * If the task completes successfully, the result will be a list of * current topic metric collectors. *

              * Otherwise, the Promise will reject with an Error. Common reasons * for failure include: *

                *
              • if the calling session does not have {@link * GlobalPermission.VIEW_SERVER VIEW_SERVER} permission; *
              • if the session is closed. *
              */ listTopicMetricCollectors(): Promise; /** * Removes any topic metric collector with the given name, if it exists. * * @param name the topic metric collector name * * @return a Promise that resolves when a response is received from the * server. *

              * If the task completes successfully, the result will be null. The * result type is `any` rather than `void` to provide forward * compatibility with future iterations of this API that may provide * a non-null result with a more specific result type. *

              * Otherwise, the Promise will reject with an Error. Common reasons * for failure include: *

                *
              • if the calling session does not have {@link * GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission; *
              • if the operation failed due to a transient cluster error; *
              • if the session is closed. *
              • {@link NullValueError} – if the collector is `null` or `undefined` *
              */ removeTopicMetricCollector(name: string): Promise; /** * Creates an unconfigured {@link MetricsRequest}. The request can be invoked using * {@link MetricsRequest.fetch} to retrieve metrics for the server or cluster. *

              * See {@link MetricsRequest} for more information. * * @return a new {@link MetricsRequest} * * @since 6.10 */ metricsRequest(): MetricsRequest; /** * Set or update a metric alert with a given name and specification. * * This method creates or updates a metric alert. If an alert with the * specified name already exists, it will be overwritten with the new * specification. * * @param name the name of the metric alert. This name is used to uniquely * identify the alert. * @param specification the specification * of the metric alert. This defines the conditions under which the * alert is triggered and the actions to be taken. * @return a Promise that resolves when a response is received * from the server. If the operation is successful, the Promise * resolves normally. * * If the task fails, the Promise will reject with an Error. Common * reasons for failure, listed by the exception, include: * *

                *
              • {@link ScriptException} – if {@code specification} is * invalid; *
              • {@link ClusterRoutingException} – if the operation * failed due to a transient cluster error; *
              • {@link PermissionsException} – if the calling session * does not have CONTROL_SERVER permission; *
              • {@link SessionClosedException} – if the session is * closed; *
              * * @since 6.12 */ setMetricAlert(name: string, specification: string): Promise; /** * List all metric alerts that have been created. * * @return a Promise that resolves when a response is received * from the server, returning a list of metric alerts sorted by their * creation order. * * If the task fails, the Promise will reject with an Error. Common * reasons for failure, listed by the exception, include: * *
                *
              • {@link ClusterRoutingException} – if the operation * failed due to a transient cluster error; *
              • {@link PermissionsException} – if the calling session * does not have CONTROL_SERVER permission; *
              • {@link SessionClosedException} – if the session is * closed. *
              * * @since 6.12 */ listMetricAlerts(): Promise; /** * Remove a named metric alert if it exists. * * If the named alert does not exist, the Promise will complete * successfully. * * @param name the name of the metric alert * @return a Promise that resolves when a response is received * from the server. * * If the task fails, the Promise will reject with an Error. Common * reasons for failure, listed by the exception, include: * *
                *
              • {@link ClusterRoutingException} – if the operation * failed due to a transient cluster error; *
              • {@link PermissionsException} – if the calling session * does not have CONTROL_SERVER permission; *
              • {@link SessionClosedException} – if the session is * closed. *
              * * @since 6.12 */ removeMetricAlert(name: string): Promise; } /** * A list of session metric collectors */ export interface SessionMetricCollectorList { /** * The collectors. */ readonly collectors: SessionMetricCollector[]; } /** * A list of session metric collectors */ export interface TopicMetricCollectorList { /** * The collectors. */ readonly collectors: TopicMetricCollector[]; } /** * The common base interface for metric collectors. */ export interface MetricCollector { /** * the name of the metric collector */ readonly name: string; /** * Indicates whether the metric collector exports to Prometheus. */ readonly exportToPrometheus: boolean; /** * Limit on the number of groups maintained by this metric collector. * * Session metric collectors can * {@link SessionMetricCollector.groupByProperties group metrics by * property}. Topic metric collectors can * {@link TopicMetricCollector.groupByTopicType group metrics by * topic type}. This property places an upper limit on the number of * groups that will be maintained for the metric collector. * * For example, if a session metric collector groups by `$SessionId` and * maximumGroups is 10, then metrics will only be collected for the * first 10 sessions. * * @since 6.8 */ readonly maximumGroups: number; } /** * The definition of a session metric collector. * * These can be configured to record metric data for a subset of all * sessions, specified with a session filter. */ export interface SessionMetricCollector extends MetricCollector { /** * the session filter */ readonly sessionFilter: string; /** * list of properties to group by */ readonly groupByProperties: string[]; /** * Indicates whether metrics with no matches should be removed. */ readonly removeMetricsWithNoMatches: boolean; } /** * A session metric collector builder. * * A builder of this type may be created using * {@link newSessionMetricCollectorBuilder} and used to create instances of * {@link SessionMetricCollector} that can be supplied to * {@link Metrics.putSessionMetricCollector putSessionMetricCollector}. */ export interface SessionMetricCollectorBuilder { /** * Specifies whether the metric collector should export metrics to * Prometheus or not. * * The default is that metrics are not exported to Prometheus. * * @param export true to export metrics to Prometheus * * @return this builder */ exportToPrometheus(exportMetrics: boolean): SessionMetricCollectorBuilder; /** * Set the maximum number of groups maintained by the metric collector. * * By default, the number of groups is not limited. * * @param limit a positive integer * @see {@link MetricCollector.maximumGroups} */ maximumGroups(limit: number): SessionMetricCollectorBuilder; /** * Adds the name of a session property to group by to the list known * to this builder. * * By default a builder will initially have no session properties to * group by set. * * @param propertyName the name of the session property. See * {@link Session} for details of session properties * * @return this builder * @throws a {@link NullValueError} if the propertyName is `null` or `undefined` */ groupByProperty(propertyName: string): SessionMetricCollectorBuilder; /** * Specifies a list of session property names to group by, replacing * any current list known to this builder. * * @param propertyNames a list of session property names. See * {@link Session} for details of session properties * * @return this builder * @throws a {@link NullValueError} if propertyNames is `null` or `undefined` */ groupByProperties(propertyNames: string[]): SessionMetricCollectorBuilder; /** * Specifies whether the metric collector should remove any metrics * that have no matches. *

              * The default is that the metric collector will not remove metrics * with no matches. * * @param remove true to indicate that metrics with no matches * should be removed * * @return this builder */ removeMetricsWithNoMatches(remove: boolean): SessionMetricCollectorBuilder; /** * Reset the builder. * * @return this Builder */ reset(): SessionMetricCollectorBuilder; /** * Create a new {@link SessionMetricCollector} using the values * currently known to this builder. * * @param name the name of the {@link SessionMetricCollector} * * @param sessionFilter the session filter indicating the sessions * this collector should apply to. The format of a session * property filter is documented in {@link Session} * * @return a new {@link SessionMetricCollector} with all of the * current settings of this builder * @throws an {@link IllegalArgumentError} if the name is empty or * the maximum number of groups is not positive * @throws a {@link NullValueError} if name or sessionFilter is `null` or `undefined` */ create(name: string, sessionFilter: string): SessionMetricCollector; } /** * The definition of a topic metric collector. * * These can be configured to record metric data for a subset of all topics, * specified with a topic selector. */ export interface TopicMetricCollector extends MetricCollector { /** * the topic selector */ readonly topicSelector: string; /** * Indicates whether the collector groups by topic type. */ readonly groupByTopicType: boolean; /** * Indicates whether the collector groups by topic view. * * @since 6.9 */ readonly groupByTopicView: boolean; /** * The number of leading parts of the topic path to group by, or * 0 if the collector does not group by path prefix * * @since 6.8 */ readonly groupByPathPrefixParts: number; } /** * A topic metric collector builder. * * A builder of this type may be created using * {@link newTopicMetricCollectorBuilder} and * used to create instances of {@link TopicMetricCollector} that can be supplied * to {@link Metrics.putTopicMetricCollector putTopicMetricCollector}. */ export interface TopicMetricCollectorBuilder { /** * Specifies whether the metric collector should export metrics to * Prometheus or not. * * The default is that metrics are not exported to Prometheus. * * @param export true to export metrics to Prometheus * * @return this builder */ exportToPrometheus(exportMetrics: boolean): TopicMetricCollectorBuilder; /** * Set the maximum number of groups maintained by the metric collector. * * By default, the number of groups is not limited. * * @param limit a positive integer * @see {@link MetricCollector.maximumGroups} */ maximumGroups(limit: number): TopicMetricCollectorBuilder; /** * Specifies whether the metric collector should group by topic * type. * * By default a topic metric collector does not group by topic type. * * @param groupByTopicType true to indicate that the collector * should group by topic type * * @return this builder */ groupByTopicType(groupByTopicType: boolean): TopicMetricCollectorBuilder; /** * Specifies whether the metric collector should group by topic * view. * * By default a topic metric collector does not group by topic view. * * @param groupByTopicView true to indicate that the collector * should group by topic view. * * @return this builder. */ groupByTopicView(groupByTopicView: boolean): TopicMetricCollectorBuilder; /** * Specifies the number of leading parts of the topic path the * metric collector should use to group results. * * By default a topic metric collector does not group by the topic * path prefix. If a positive number of parts is specified, it * will enable grouping. * * @param parts the number of leading parts of the topic path to * group by; set to 0 to disable grouping by path * @return this builder * @since 6.8 */ groupByPathPrefixParts(parts: number): TopicMetricCollectorBuilder; /** * Reset the builder. * * @return this Builder */ reset(): TopicMetricCollectorBuilder; /** * Create a new {@link TopicMetricCollector} using the values * currently known to this builder. * * @param name the name of the {@link TopicMetricCollector} * * @param topicSelector the selector pattern that specifies the * topics for which metrics are to be collected * * @return a new {@link TopicMetricCollector} with all of the * current settings of this builder * @throws an {@link IllegalArgumentError} if the name is empty or * the maximum number of groups is not positive * @throws a {@link NullValueError} if name or topicSelector is `null` or `undefined` */ create(name: string, topicSelector: string | TopicSelector): TopicMetricCollector; } /** * A parameterized query that can be used to fetch metrics from the server. * * A new request can be created with {@link Metrics.metricsRequest}}. * Requests are immutable. The {@link MetricsRequest.server}, {@link * MetricsRequest.currentServer} and {@link MetricsRequest.filter} methods * can be used to create a configured request that either limits the * metrics to a specific server or filters the metrics returned. * * By default, the request will fetch metrics from all servers and will * not filter the metrics. * * The metrics are the same as those exposed by the Prometheus endpoint * when requesting metrics in the OpenMetrics format. * * @since 6.10 */ export interface MetricsRequest { /** * Allows specifying a set of filters to limit the metrics returned. * * The filter may not be null. If the filter is empty then all metrics are returned. * * The filter is a set of strings. The filter matches a String if the String equals * any member of the filter. * * Metrics are included only if: *

                *
              • * The filter matches a {@link MetricSampleCollection} name, in which case the entire collection * and its samples are returned. *
              • *
              • * The filter doesn't match a {@link MetricSampleCollection} name but matches at least one of its * {@link MetricSample} children. In this case, the {@link MetricSampleCollection} is * returned with only the matching child {@link MetricSample}s. *
              • *
              * * @param filters the set of filters to use * @return a new request derived from this fetch request but with the specified filters * @throws a {@link NullValueError} if the filter is null */ filter(filters: string[] | Set): MetricsRequest; /** * Allows specifying a regular expression to filter the metrics returned. * * The filter may not be null. * * Similarly to calling {@link MetricsRequest.filter filter} with a set, metrics are included only if: *
                *
              • * The regular expression matches a {@link MetricSampleCollection} name, in which case the * entire collection and its samples are returned. *
              • *
              • * The regular expression doesn't match a {@link MetricSampleCollection} name but matches at * least one of its {@link MetricSample} children. In this case, the {@link MetricSampleCollection} is * returned with only the matching child {@link MetricSample}s. *
              • *
              * * Only the last filter set by this method will be applied. * * @param filter a regular expression to use to filter the metrics. When using a string to * specify a regular expression, the string should not contain the surrounding slashes * nor any flags. * @return a new request derived from this fetch request but with the specified filter * @throws a {@link NullValueError} if the filter is null */ filter(filter: string | RegExp): MetricsRequest; /** * Specifies the name of the server to fetch metrics from. This is the configured server name. * * @param server the name of the server to fetch metrics from * @return a new request derived from this fetch request but with the specified server * @throws an {@link IllegalArgumentError} if the server name is empty * @throws a {@link NullValueError} if the filter is null */ server(server: string): MetricsRequest; /** * Specifies that metrics should be fetched from the server to which the current * session is connected. * * @return a new request derived from this fetch request but which will collect * metrics from the current server */ currentServer(): MetricsRequest; /** * Fetches the metrics from the server. * * If the fetch operation completes successfully, the Promise result * will contain a {@link MetricsResult} that can be used to access the metrics. * * Otherwise, the Promise will reject with an error. Common reasons for failure * include: * *
                *
              • the calling session does not have * {@link GlobalPermission.VIEW_SERVER} permission; *
              • the operation failed due to a transient cluster error; *
              • the session is closed. *
              * * If all metrics for a server are filtered out then the result will still contain * an empty entry for that server. * * If either {@link MetricsRequest.server} or {@link MetricsRequest.currentServer} * has been called then the result will contain an entry for that server only. * Otherwise, it will contain an entry for each server in the cluster. * * @return a Promise that will complete with the metrics */ fetch(): Promise; } /** * The result of a fetch metrics operation, initiated by a {@link MetricsRequest}. * * @since 6.10 */ export interface MetricsResult { /** * Returns a list of server names for which the result has metrics. * The names may be used with {@link MetricsResult.getMetrics}. * * @return a set of server names */ getServerNames(): Set; /** * Returns the metrics for a server. * * @param serverName the name of the server * @return the metrics for the server */ getMetrics(serverName: string): MetricSampleCollection[]; } /** * Represents a collection of metric samples. * @since 6.10 */ export interface MetricSampleCollection { /** * the name of the metric sample collection */ readonly name: string; /** * the MetricType for the samples in the collection */ readonly type: MetricType; /** * the unit of measurement for the metric samples */ readonly unit: string; /** * the list of metric samples */ samples: MetricSample[]; } /** * Enumeration defining the metric types available. These match the types defined in the * * OpenMetrics specification. * * * @since 6.10 */ export declare enum MetricType { /** * Counters measure discrete events. Common examples are the number of HTTP requests received, CPU seconds * spent, or bytes sent. Counters are always monotonic, and are typically used to count events. */ COUNTER = 0, /** * Gauges are current measurements, such as bytes of memory currently used or the number of items in a queue. */ GAUGE = 1, /** * Info metrics are used to expose textual information which SHOULD NOT change during process lifetime. * Common examples are an application's version, revision control commit, and the version of a compiler. */ INFO = 2, /** * Histograms measure distributions of discrete events. Common examples are the latency of HTTP requests, * function runtimes, or I/O request sizes. */ HISTOGRAM = 3, /** * GaugeHistograms measure current distributions. Common examples are how long items have been waiting in a * queue, or size of the requests in a queue. */ GAUGE_HISTOGRAM = 4, /** * StateSets represent a series of related boolean values, also called a bitset. */ STATE_SET = 5, /** * Like Histograms, Summaries measure distributions of discrete events and MAY be used when * Histograms are too expensive and/or an average event size is sufficient. */ SUMMARY = 6, /** * An unknown metric type. */ UNKNOWN = 7 } /** * Represents a single metric sample. * @since 6.10 */ export interface MetricSample { /** * the name of the metric sample */ readonly name: string; /** * the list of label names */ readonly labelNames: string[]; /** * the list of label values for the metric sample. The nth label value corresponds to the nth label * name. */ readonly labelValues: string[]; /** * optional timestamp for the metric sample if present */ readonly timestamp?: Long; /** * the value of the metric sample */ readonly value: number; } /** * Description of a metric alert. * * @since 6.12 */ export interface MetricAlert { /** * The name of the metric alert. */ name: string; /** * The specification * of the metric alert. */ specification: string; /** * The principal associated with the metric alert. */ principal: string; } /** * This feature provides a client session with the ability to test its * connection to the server. * * The main purpose of a ping is to test, at a very basic level, the current * network conditions that exist between the client session and the server * it is connected to. The ping response includes the time taken to make a * round-trip call to the server. * * There are no permission requirements associated with this feature. */ export interface Ping { /** * Send a ping request to the server. * * **Example:** * ``` * session.pingServer().then(function(pingDetails) { * console.log("Round-trip call to server took: " + pingDetails.rtt + " milliseconds"); * }); * ``` * * @return a result that completes when a response is received from the server. */ pingServer(): Promise; } /** * Details of a successful ping response */ export interface PingDetails { /** * The timestamp when the ping was sent, represented as milliseconds since * epoch */ readonly timestamp: number; /** * The round-trip time in milliseconds from when the ping was sent to the * time the response was received */ readonly rtt: number; } /** * @module Session.remoteServers */ /** * Connection options for use with {@link SecondaryServer}s. */ export declare enum ConnectionOption { /** * Specifies the connection timeout session attribute value (in milliseconds). * * If a value is not specified the session's default connection timeout is used. */ CONNECTION_TIMEOUT = 1, /** * Specifies the input buffer size session attribute. * * This is the size of the input buffer to use for the connection with the remote server. * It is used to receive messages from the remote server. * This should be set to the same size as the output buffer used at the remote server. * * If not specified, a default of 1024k is used. */ INPUT_BUFFER_SIZE = 2, /** * Specifies the maximum queue size session attribute. * * This is the maximum number of messages that can be queued to send to the remote server. * If this number is exceeded, the connection will be closed. * This must be sufficient to cater for messages that may be queued whilst disconnected (awaiting reconnect). * * The default value is 10,000 messages. */ MAXIMUM_QUEUE_SIZE = 3, /** * Specifies the output buffer size session attribute. * * This is the size of the output buffer to use for the connection with the remote server. * It is used to send messages to the remote server. * This should be set to the same size as the input buffer used by the remote server. * * If not specified, a default of 1024k is used. */ OUTPUT_BUFFER_SIZE = 4, /** * Specifies the reconnection timeout session attribute. * * This is the total time in milliseconds that will be allowed to reconnect a failed connection. * * For reconnection to work the remote server connector must have been configured to support reconnection. * * If a value is not specified the session's default reconnection timeout is used. * * This value cannot be supplied for a * {@link RemoteServerType.SECONDARY_ACCEPTOR SECONDARY_ACCEPTOR} server. */ RECONNECTION_TIMEOUT = 5, /** * Specifies the recovery buffer size session attribute. * * If the remote server is configured to support reconnection, a session established with a non-zero * reconnect-timeout retains a buffer of sent messages. * If the session disconnects and reconnects, this buffer is used to re-send messages that the server * has not received. * * The default value is 10,000 messages. If reconnect-timeout is 0 then this value is ignored. * * This value cannot be supplied for a * {@link RemoteServerType.SECONDARY_ACCEPTOR SECONDARY_ACCEPTOR} server. */ RECOVERY_BUFFER_SIZE = 6, /** * Specifies the delay after losing a connection before attempting a reconnection. * * The value is specified in milliseconds. Default 1000 (1 second). * * This value cannot be supplied for a * {@link RemoteServerType.SECONDARY_ACCEPTOR SECONDARY_ACCEPTOR} server. */ RETRY_DELAY = 7, /** * Specifies the write timeout session attribute value (in milliseconds). * * If a value is not specified the session's default write timeout is used. */ WRITE_TIMEOUT = 8 } /** * Represents the current connection state of a remote server. */ export declare enum ConnectionState { /** * The connection is inactive. * * This means that the remote server can successfully connect but a * physical connection is not being maintained as there are no * components that require the remote server. * * If in an inactive or failed state, a test connection will have * been tried to check that the connection can be made and the * connection will then have been closed. */ INACTIVE = 1, /** * The remote server is connected and actively in use by components * that require it. */ CONNECTED = 2, /** * The connection has failed but a retry is scheduled. * * In this case {@link RemoteServerStatus.failureMessage} * will provide details of the failure that resulted in a retry. */ RETRYING = 3, /** * The connection failed to establish. * * If the connection was in an inactive or failed state, a * test connection was tried and failed. * * In this case {@link RemoteServerStatus.failureMessage} * will provide more detail. */ FAILED = 4, /** * The named remote server did not exist. */ MISSING = 5 } /** * A complete map of {@link ConnectionOption ConnectionOption}s to values. */ export declare type ConnectionOptions = { [key in ConnectionOption]: string; }; /** * The remote server type. */ export declare enum RemoteServerType { /** * Secondary initiator remote server. * * Defined on secondary servers. * * This type will initiate connection from a secondary server * (cluster) to a primary server (cluster member). */ SECONDARY_INITIATOR = 1, /** * Primary initiator. * * Defined on primary servers. * * This type will connect to an inbound remote server of the same * name configured at the secondary server (cluster). */ PRIMARY_INITIATOR = 2, /** * Secondary acceptor remote server. * * Defined on secondary servers. * * This type will accept a primary remote server connection and * support remote topic views. */ SECONDARY_ACCEPTOR = 3 } /** * Base interface for a remote server definition. * * @since 6.5 */ export interface RemoteServer { /** * The remote server type. * * A {@link RemoteServer} can be cast to the corresponding sub-type to * access all methods, as follows: * * * * * * * * * * * * * * * * * * *
              TypeType class
              {@link RemoteServerType.SECONDARY_INITIATOR * SECONDARY_INITIATOR}{@link SecondaryInitiator}
              {@link RemoteServerType.PRIMARY_INITIATOR * PRIMARY_INITIATOR}{@link PrimaryInitiator}
              {@link RemoteServerType.SECONDARY_ACCEPTOR * SECONDARY_ACCEPTOR}{@link SecondaryAcceptor}
              */ readonly type: RemoteServerType; /** * The name of the remote server. */ readonly name: string; /** * The url used for connection to the remote server. * * @deprecated since 6.9 *

              * For backwards compatibility this property is retained for * secondary initiator compatibility but will be removed at * a future release. */ readonly url: string; /** * The principal used for connection to the remote server. * * @deprecated since 6.9 *

              * For backwards compatibility this property is retained for * secondary initiator compatibility but will be removed at * a future release. */ readonly principal: string; /** * Options used for connection to the remote server. * * @deprecated since 6.9 *

              * For backwards compatibility this property is retained for * secondary initiator compatibility but will be removed at * a future release. */ readonly connectionOptions: ConnectionOptions; /** * The missing topic notification filter expression or `undefined` if one * has not been specified. * * @deprecated since 6.9 *

              * For backwards compatibility this property is retained for * secondary initiator compatibility but will be removed at * a future release. */ readonly missingTopicNotificationFilter?: string; } /** * The base class for remote server definitions. */ export interface RemoteServerDefinitionBase { /** * The name of the remote server. */ readonly name: string; } /** * A primary initiator definition. * * This type makes a connection from a primary server (cluster) to a * secondary server (or all secondary cluster members) with a * {@link SecondaryAcceptor} of the same name. * * Use a {@link PrimaryInitiatorBuilder} to create an instance of this type. */ export interface PrimaryInitiatorDefinition extends RemoteServerDefinitionBase { /** * The urls for connection to secondary servers. */ readonly urls: string[]; /** * The connector that the primary initiator will use to * establish a connection between the secondary server and the primary * server. */ readonly connector?: string; /** * The interval in milliseconds between connection retries. * * If a primary initiator cannot connect to a secondary server, or loses * the connection, this is the amount of time before it will try to * connect again. */ readonly retryDelay: number; } /** * Base interface for a secondary remote server definition. */ export interface SecondaryServerDefinition extends RemoteServerDefinitionBase { /** * The principal used for connection. */ readonly principal: string; /** * The remote server connection options. */ readonly connectionOptions: Partial; /** * The missing topic notification filter expression. */ readonly missingTopicNotificationFilter?: string; } /** * Definition of a secondary remote server that accepts a connection from * a primary server. * * This type accepts a connection from a {@link PrimaryInitiator} with the * same name configured at the primary server (cluster). * * Use a {@link SecondaryAcceptorBuilder} to create an instance of this * type. */ export interface SecondaryAcceptorDefinition extends SecondaryServerDefinition { /** * The hostname of the expected primary server, for secure WebSocket validation. */ readonly primaryHostName: string; } /** * Definition of a secondary remote server that initiates a connection to * a primary server. * * This type makes a connection from a secondary server (or each secondary * cluster member) to a primary server. No remote server definition is * required at the primary server. * * Use a {@link SecondaryInitiatorBuilder} to create an instance of this * type. */ export interface SecondaryInitiatorDefinition extends SecondaryServerDefinition { /** * The url used for connection to the primary server. */ readonly url: string; } /** * Definition of a remote server that should be created. * * @since 6.7 */ export interface RemoteServerDefinition extends PrimaryInitiatorDefinition, SecondaryInitiatorDefinition, SecondaryAcceptorDefinition { /** * The credentials used for connection to the remote server. */ readonly credentials: Credentials; } /** * The base interface for all remote server builders. * * A builder of this type cannot be instantiated. * * @param the remote server type. */ export interface RemoteServerBuilderBase { /** * Reset the builder to its default values. * * @return this Builder */ reset(): B; } /** * A remote server builder. * * A builder of this type may be created using {@link newRemoteServerBuilder} * and used to create instances of {@link RemoteServer} that can be supplied * to {@link RemoteServers.createRemoteServer createRemoteServer(RemoteServer)}. * * @since 6.7 * * @deprecated since 6.9 *

              * This builder is retained for backwards compatibility * only. It can only be used to create a secondary * initiator. {@link SecondaryInitiatorBuilder} * should be used in preference. This builder will be * removed in a future release. */ export interface RemoteServerBuilder { /** * Specifies the name of a principal used by the remote server to * connect to the primary server. * * The default, if not specified, is the anonymous principal. * * @param principal principal name or a zero length string to * indicate an anonymous connection * * @return this builder * @throws a {@link NullValueError} if the principal is null */ principal(principal: string): RemoteServerBuilder; /** * Specifies the credentials to use when connecting to the primary * server. * * The default, if not specified, is `undefined`. * * @param credentials the credentials to use * * @return this builder */ credentials(credentials: Credentials): RemoteServerBuilder; /** * Specifies a map of {@link ConnectionOption} settings. * * This will replace any options currently set for the builder. * * Any options not supplied will take their default values. * * If no connection options are specified, either using this method * or {@link RemoteServerBuilder.connectionOption connectionOption} * then all options will take their default value. * * @param connectionOptions map of options * * @return this builder * * @throws a {@link NullValueError} if the connectionOptions are null */ connectionOptions(connectionOptions: Partial): RemoteServerBuilder; /** * Specifies a single connection option. * * This will add to the options currently specified to the builder, * or replace a value if it has already been specified. * * @param connectionOption the connection option * * @param value the connection option value. If argument is omitted or `null` * the option is removed * * @return this builder * * @throws a {@link NullValueError} if the connectionOption is null */ connectionOption(connectionOption: ConnectionOption, value?: string | null): RemoteServerBuilder; /** * Specifies a topic selector expression which will filter missing * topic notifications propagated from secondary to primary server. * * {@link MissingTopicNotification}s are notified when a client * subscribes using a topic selector that matches no existing * topics. By specifying a missing topic notification filter all * notifications that match the filter on the secondary server will * be propagated to the primary server. * * A match occurs if the path prefix of the subscription selector * matches the path prefix of the specified selector. If the * selector is a {@link Prefix.SELECTOR_SET selector * set} then the notification will be propagated if it matches any * selector in the set. * * If no filter is specified then no missing topic notifications * will be propagated. * * The special selector expression "*.*" may be used to indicate * that all missing topic notifications should be propagated. * * Only the path prefix of the specified selector(s) is considered * when matching therefore any use of regular expressions would be * ignored. * * @param filter a topic selector expression specifying the filter * to apply or null to remove any existing filter * * @return this builder * * @throws an {@link IllegalArgumentError} if the filter is not a valid topic selector */ missingTopicNotificationFilter(filter: string | null): RemoteServerBuilder; /** * Reset the builder. * * @return this Builder */ reset(): RemoteServerBuilder; /** * Creates a remote server object using the current values known to * this builder. * * @param name the name of the remote server * * @param url the URL to use to connect to the primary server * * @return a new remote server instance * * @throws an {@link IllegalArgumentError} if the name or URL is empty * @throws a {@link NullValueError} if the name or URL is null */ create(name: string, url: string): RemoteServerDefinition; } /** * A primary initiator. * * This type makes a connection from a primary server (cluster) to a * secondary server (or all secondary cluster members) with a * {@link SecondaryAcceptor} of the same name. * * Use a {@link PrimaryInitiatorBuilder} to create an instance of this type. */ export interface PrimaryInitiator extends RemoteServer { /** * The urls for connection to secondary servers. */ readonly urls: string[]; /** * The connector that the primary initiator will use to * establish a connection between the secondary server and the primary * server. */ readonly connector?: string; /** * Gets the interval in milliseconds between connection retries. * * If a primary initiator cannot connect to a secondary server, or loses * the connection, this is the amount of time before it will try to * connect again. */ getRetryDelay(): number; } /** * Builder for a {@link PrimaryInitiator}. * * A builder of this type may be created using * {@link newRemoteServerBuilder} specifying * {@code RemoteServerType.PRIMARY_INITIATOR} as the parameter. */ export interface PrimaryInitiatorBuilder extends RemoteServerBuilderBase { /** * Specifies the delay after losing a connection before attempting a * reconnection. *

              * The value is specified in milliseconds. Default 1000 (1 second). * * @throws an {@link IllegalArgumentError} if the delay is less than 0 * @throws a {@link NullValueError} if the delay is null */ retryDelay(delay: number): PrimaryInitiatorBuilder; /** * Builds a primary initiator using the current values known to this * builder. * * @param name the name of a primary initiator which must * correspond too the name of a {@link SecondaryAcceptor} * defined on the secondary server. * * @param urls the list of URLs to use to initiate connections to * the secondary servers. * * @param connector the name of the connector used to establish the * connection with the secondary server. * * @return a new primary initiator instance. * * @throws an {@link IllegalArgumentError} if the name, urls, or connector is empty or the * urls are invalid * @throws a {@link NullValueError} if any of the arguments are null */ build(name: string, urls: string[], connector: string): RemoteServerDefinition; } /** * Base interface for a secondary remote server. */ export interface SecondaryServer extends RemoteServer { /** * The principal used for connection. */ readonly principal: string; /** * The remote server connection options. */ readonly connectionOptions: ConnectionOptions; /** * The missing topic notification filter expression. */ readonly missingTopicNotificationFilter?: string; } /** * Base builder interface for {@link SecondaryServer}. * * A builder of this type cannot be instantiated. * * @param the builder type. */ export interface SecondaryBuilder extends RemoteServerBuilderBase { /** * Specifies the name of a principal to use for the connection. * * This specifies the principal for the connection to the primary * server and is authenticated at the primary server. * * The default, if not specified is the anonymous principal. * * @param principal principal name or a zero length string to * indicate an anonymous connection. * * @return this builder. */ principal(principal: string): B; /** * Specifies the credentials to use to authenticate the connection. * * The default, if not specified, is `null`. * * This is used along with the specified principal. * * @param credentials the credentials to use. * * @return this builder. */ credentials(credentials: Credentials): B; /** * Specifies a map of {@link ConnectionOption} settings. * * This will replace any options currently set for the builder. * * Any options not supplied will take their default values. * * If no connection options are specified, either using this method * or {@link SecondaryBuilder.connectionOption} then all options will take their * default value. * * Not all remote server types support all options. See * {@link ConnectionOption} for details. * * @param connectionOptions map of options. * * @return this builder. * * @throws an {@link IllegalArgumentError} if any of the connectionOptions are invalid */ connectionOptions(connectionOptions: Partial): B; /** * Specifies a single connection option. *

              * This will add to the options currently specified to the builder, * or replace a value if it has already been specified. *

              * Not all remote server types support all options. See * {@link ConnectionOption} for details. * * @param connectionOption the connection option * * @param value the connection option value or null to remove the * option * * @return this builder * * @throws an {@link IllegalArgumentError} if the connectionOption is invalid * @throws a {@link NullValueError} if the connectionOption is null */ connectionOption(connectionOption: ConnectionOption, value?: string): B; /** * Specifies a topic selector expression which will filter missing * topic notifications propagated from secondary to primary server. * * {@link MissingTopicNotification}s are notified when a client * subscribes using a topic selector that matches no existing * topics. By specifying a missing topic notification filter all * notifications that match the filter on the secondary server will * be propagated to the primary server. * * A match occurs if the path prefix of the subscription selector * matches the path prefix of the specified selector. If the * selector is a {@link Prefix.SELECTOR_SET selector * set} then the notification will be propagated if it matches any * selector in the set. * * If no filter is specified then no missing topic notifications * will be propagated. * * The special selector expression "*.*" may be used to indicate * that all missing topic notifications should be propagated. * * Only the path prefix of the specified selector(s) is considered * when matching therefore any use of regular expressions would be * ignored. * * @param filter a topic selector expression specifying the filter * to apply or null to remove any existing filter * * @return this builder * * @throws an {@link IllegalArgumentError} if the filter is not a valid topic selector */ missingTopicNotificationFilter(filter?: string): B; } /** * Secondary remote server that initiates a connection to a primary server. * * This type makes a connection from a secondary server (or each secondary * cluster member) to a primary server. No remote server definition is * required at the primary server. * * Use a {@link SecondaryInitiatorBuilder} to create an instance of this * type. */ export interface SecondaryInitiator extends SecondaryServer { /** * The url used for connection to the primary server. */ readonly url: string; } /** * Builder for a {@link SecondaryInitiator}. * * A builder of this type may be created using * {@link newRemoteServerBuilder} specifying * {@code RemoteServerType.SECONDARY_INITIATOR} as the parameter. */ export interface SecondaryInitiatorBuilder extends SecondaryBuilder { /** * Builds a secondary initiator instance using the current values * known to this builder. * * @param name the remote server name. This is the name that will be * specified in topic views * * @param url the URL to use to connect to the primary server * * @return a new secondary initiator instance * @throws an {@link IllegalArgumentError} if the name or URL is empty or cannot be parsed * @throws a {@link NullValueError} if the name or URL is null */ build(name: string, url: string): RemoteServerDefinition; } /** * Secondary remote server that accepts a connection from a primary server. *

              * This type accepts a connection from a {@link PrimaryInitiator} with the * same name configured at the primary server (cluster). *

              * Use a {@link SecondaryAcceptorBuilder} to create an instance of this * type. */ export interface SecondaryAcceptor extends SecondaryServer { /** * The hostname of the expected primary server, for secure WebSocket validation. */ readonly primaryHostName: string; } /** * Builder for a {@link SecondaryAcceptor}. *

              * A builder of this type may be created using * {@link newRemoteServerBuilder} specifying * {@code RemoteServerType.SECONDARY_ACCEPTOR} as the parameter. */ export interface SecondaryAcceptorBuilder extends SecondaryBuilder { /** * Builds a secondary acceptor using the current values known to * this builder. * * @param name the remote server name. A primary initiator of the * same name will be able to connect to this acceptor. This * is the name that will be specified in topic views * * @param primaryHostName the hostname of the the primary server. This will * be used for secure WebSocket validation purposes * * @return a new secondary acceptor instance * * @throws an {@link IllegalArgumentError} if the name is empty * @throws a {@link NullValueError} if any of the arguments are null */ build(name: string, primaryHostName: string): RemoteServerDefinition; } /** * Promise returned from a {@link RemoteServers.checkRemoteServer} invocation. */ export interface RemoteServerStatus { /** * The connection state of the remote server. */ readonly connectionState: ConnectionState; /** * The failure message, if there is one, otherwise an empty string */ readonly failureMessage: string; } /** * This feature allows a client session to manage remote servers. * * This feature provides the ability to configure the various modes of operation * for the use of remote topic views. This is the ability for a topic view * specification to indicate that the source topics for the view are to come * from another server in a different Diffusion cluster. The server where the * topic views are configured is referred to as the 'secondary server' and the * server where the actual topics are is referred to as the 'primary server'. * *

              Outbound Connection from the Secondary Server

              * * The typical configuration for a remote server is that there is only * configuration at the secondary server (the configuration is automatically * distributed to all members of the secondary cluster). In this case, each * secondary server connects to a server in the primary cluster (typically via a * load-balancer). * * Remote topic views can specify the use of such remote servers by name. The * connection and disconnection is handled automatically by the server (or * servers in the same cluster) where the remote servers are defined. * * A component can specify a remote server by name even if it does not exist * (has not yet been created) and when the remote server is created the * connection will take place automatically. * * If a remote server is removed and there are topic views that depend upon it, * those topic views will be disabled. * * This form of connection is provided by a {@link RemoteServer} of type * {@link RemoteServerType.SECONDARY_INITIATOR SECONDARY_INITIATOR} and * represented by the sub-type {@link SecondaryInitiator}. * * Such a remote server can be built using a * {@link SecondaryInitiatorBuilder} created using * {@link newRemoteServerBuilder}. It may then be added to the * server (cluster) using {@link createRemoteServer}. * * In this mode a connection from secondary to primary server is only maintained * when there is a topic view that depends upon it. There will be no connections * if there are no topic views that specify the remote server. * *

              Outbound Connection from the Primary Server

              * * In some cases it may be preferred that the connection is initiated by the * primary server, connecting to the secondary server cluster. In this case a * single primary server will connect to all members of the secondary cluster. * * This form of connection is provided by a {@link RemoteServer} of type * {@link RemoteServerType.PRIMARY_INITIATOR PRIMARY_INITIATOR} and represented * by the sub-type {@link PrimaryInitiator}. This * can be built using a * {@link PrimaryInitiatorBuilder} created using * {@link newRemoteServerBuilder}. It may then be added to the * primary server (cluster) using {@link createRemoteServer}. Secondly a * {@link RemoteServer} of type {@link RemoteServerType.SECONDARY_ACCEPTOR * SECONDARY_ACCEPTOR} and represented by the sub-type * {@link SecondaryAcceptor} should be created * in the secondary server (cluster) with the same name as the primary * initiator. Such a remote server can be built using a * {@link SecondaryAcceptorBuilder} created using * {@link newRemoteServerBuilder}. It may then be added to the * secondary server (cluster) using {@link createRemoteServer}. * * Unlike the secondary initiator mode, this mode of connection will establish * connections even if there are no topic views in the secondary server * (cluster) that name the remote server. If the connection is lost any topic * views that depend upon it will be disabled and the primary initiator will * attempt to re-establish the connection(s). Topic views depending upon the * remote server will only be enabled when the connection is re-established. * *

              Remote Server persistence and replication

              * * Remote server configurations created through this feature are replicated * across a cluster and persisted to disk. * *

              Access control

              * * The following access control restrictions are applied: * *
                *
              • To {@link RemoteServers.createRemoteServer create}, * {@link RemoteServers.removeRemoteServer remove} * or {@link RemoteServers.checkRemoteServer check} a remote server, a session needs the * {@link GlobalPermission.CONTROL_SERVER CONTROL_SERVER} global permission. To * {@link RemoteServers.listRemoteServers list} remote servers, a session needs the * {@link GlobalPermission.VIEW_SERVER VIEW_SERVER} global permission. * *
              * *

              Accessing the feature

              * * This feature may be obtained from a {@link Session session} as follows: * *
               * RemoteServers remoteServers = session.feature(RemoteServers.class);
               * 
              * * @since 6.5 */ export interface RemoteServers { /** * Create a new remote server instance at the server. * * If a remote server with the same name already exists an error will be * returned. * * @param remoteServer a remote server definition created using the * appropriate sub-type of {@link RemoteServerBuilder}. * * @return a Promise that completes when a response is received from the * server, returning the definition of the remote server created by * the operation. *

              * If the task fails, the Promise will resolve with an error. Common * reasons for failure include: *

                *
              • a remote server with the given name already exists; *
              • one or more connection options are invalid; *
              • the operation failed due to a transient cluster error; *
              • the calling session does not have CONTROL_SERVER permission; *
              • the session is closed; *
              • the feature is not licensed. *
              • {@link NullValueError} – if any of the required arguments are * `null` or `undefined` *
              */ createRemoteServer(remoteServer: RemoteServerDefinition): Promise; /** * Check the current state of a named remote server. * * This will report back the current state of the remote server, but also can be used to forcibly retry a failed * remote server connection. * * Currently this only reports the state of the remote server at the server * the session is connected to. In a cluster the state of the remote * server on other cluster members is not reported. * * @param name the name of the remote server * * @return a Promise that completes when a response is received from the server, returning details of the remote * server state. *

              * If the task fails, the Promise will resolve with an error. Common reasons for failure include: *

                *
              • the calling session does not have CONTROL_SERVER permission; *
              • the session is closed. *
              */ checkRemoteServer(name: string): Promise; /** * List all the remote servers that have been created. * * @return a Promise that resolves when a response is received from the * server, returning a list of remote servers. *

              * If the task fails, the Promise will resolve with an Error. Common * reasons for failure include: *

                *
              • the calling session does not have CONTROL_SERVER permission; *
              • the session is closed. *
              */ listRemoteServers(): Promise; /** * Remove a named remote server if it exists. * * When a named remote server is removed, any topic views that specify it * would be disabled. * * If the named remote server does not exist the completable future will * complete successfully. * * * @param name the name of the remote server * @return a Promise that resolves when a response is received from the * server. *

              * If the task fails, the Promise will resolve with an Error. Common * reasons for failure include: *

                *
              • the cluster was repartitioning; *
              • the calling session does not have CONTROL_SERVER permission; *
              • the session is closed. *
              */ removeRemoteServer(name: string): Promise; } /** * @module Session.security * * Access to the [[Security]] feature * @preferred */ /** * Permissions that are applied globally */ export declare enum GlobalPermission { /** * Add an authentication handler */ AUTHENTICATE = "AUTHENTICATE", /** * List or listen to client sessions */ VIEW_SESSION = "VIEW_SESSION", /** * Alter a client session */ MODIFY_SESSION = "MODIFY_SESSION", /** * Required to register any server-side handler */ REGISTER_HANDLER = "REGISTER_HANDLER", /** * View the server's runtime state */ VIEW_SERVER = "VIEW_SERVER", /** * Change the server's runtime state */ CONTROL_SERVER = "CONTROL_SERVER", /** * Read the security configuration */ VIEW_SECURITY = "VIEW_SECURITY", /** * Change the security configuration */ MODIFY_SECURITY = "MODIFY_SECURITY", /** * A permission that is unsupported by the session */ UNKNOWN_GLOBAL_PERMISSION = "UNKNOWN_GLOBAL_PERMISSION", /** * List topic views */ READ_TOPIC_VIEWS = "READ_TOPIC_VIEWS", /** * Modify topic views */ MODIFY_TOPIC_VIEWS = "MODIFY_TOPIC_VIEWS" } /** * Permissions that are applied on a path */ export declare enum PathPermission { /** * Required to receive information from a topic. * * If a session does not have read_path permission for a topic, the topic * will be excluded from the results of subscription or fetch operations for * the session, and the topic's details cannot be retrieved by the session. */ READ_TOPIC = "READ_TOPIC", /** * Update topics */ UPDATE_TOPIC = "UPDATE_TOPIC", /** * Add or remove topics */ MODIFY_TOPIC = "MODIFY_TOPIC", /** * Send a message to a handler registered with the server */ SEND_TO_MESSAGE_HANDLER = "SEND_TO_MESSAGE_HANDLER", /** * Send a message another session */ SEND_TO_SESSION = "SEND_TO_SESSION", /** * Use a topic selector that selects a topic path. * * To fetch or subscribe using a topic selector, a session must have * SELECT_TOPIC permission for each individual path that the selector may * match. This allows SELECT_TOPIC to be granted to a branch of the topic * tree and explicitly revoked for specific sub-branches. * * For full path pattern topic selectors, the model is even more * restrictive: SELECT_TOPIC permission is required for all paths, at and * below the path prefix of the selector. This is necessary to prevent * circumvention using advanced regular expressions. * * When the subscription or fetch request completes, the resulting topics * are further filtered based on the {@link PathPermission.READ_TOPIC} permission. * * A session that has `READ_TOPIC` but not `SELECT_TOPIC` for a * particular topic path cannot subscribe directly to topics belonging to * the path. However, the session can be independently subscribed by a * control session that has {@link GlobalPermission.MODIFY_SESSION} * permission in addition to the appropriate `SELECT_TOPIC` * permission. * * @since 5.7 */ SELECT_TOPIC = "SELECT_TOPIC", /** * Evaluate queries that return a non-current view of a time series topic. * *

              * The `READ_TOPIC` permission is required to evaluate any type of * `Query` for a time series topic. This permission is additionally * required for queries that potentially return a non-current view of all or * part of a time series. Such queries include value range queries that * specify an edit range, and all types of edit range query. */ QUERY_OBSOLETE_TIME_SERIES_EVENTS = "QUERY_OBSOLETE_TIME_SERIES_EVENTS", EDIT_TIME_SERIES_EVENTS = "EDIT_TIME_SERIES_EVENTS", /** * Submit edits to time series topic events which have an author which is * the same as the principal of the calling session. * *

              This permission is a more restrictive alternative to * `EDIT_TIME_SERIES_EVENTS`. * *

              * The `UPDATE_TOPIC` permission is required to update a time series * topic. This permission is additionally required to submit * edits to a time series topic where the event * author is the same as the principal of the calling session. */ EDIT_OWN_TIME_SERIES_EVENTS = "EDIT_OWN_TIME_SERIES_EVENTS", /** * Acquire a session lock. */ ACQUIRE_LOCK = "ACQUIRE_LOCK", /** * Expose a branch of the topic tree as a virtual session tree. * * The `EXPOSE_BRANCH` path permission is powerful since it allows a * session to expose a whole branch of the topic tree under a different set * of path permissions. * * A session granted `EXPOSE_BRANCH` for a particular path effectively * has the permission for all descendant paths. From a security perspective, * if a role grants `EXPOSE_BRANCH` at branch `X` it is * ineffectual for it also to deny `EXPOSE_BRANCH` at a child branch * `X/Y` because a branch mapping to `X` can still expose paths * below `X/Y`. */ EXPOSE_BRANCH = "EXPOSE_BRANCH", /** * A permission that is unsupported by the session */ UNKNOWN_PATH_PERMISSION = "UNKNOWN_PATH_PERMISSION" } /** * The credentials that a session uses to authenticate itself. */ export declare type Credentials = string | Uint8Array | null | undefined; /** * Details for the permissions contained by a single role. */ export interface Role { /** * The name of the role */ readonly name: string; /** * The list of global permissions */ readonly global: GlobalPermission[]; /** * The list of default path permissions */ readonly default: PathPermission[]; /** * The map of paths to sets of Path * permissions */ readonly topic: { [key: string]: PathPermission[]; }; /** * Additional roles */ readonly roles: string[]; /** * If the role is locked this will contain the name of the principal that * can update the role. * * @since 6.4 */ readonly lockingPrincipal?: string; } /** * A snapshot of information from the security store */ export interface SecurityConfiguration { /** * The list of default roles for named sessions */ readonly named: string[]; /** * The list of default roles for anonymous sessions */ readonly anonymous: string[]; /** * The list of all defined roles */ readonly roles: Role[]; /** * The list of isolated paths */ readonly isolatedPaths: string[]; } /** * A principal in the system authentication store. */ export interface SystemPrincipal { /** * The principal name */ readonly name: string; /** * The principal's assigned roles */ readonly roles: string[]; /** * If the principal is locked this will contain the name of the principal that * can update the role. * * @since 6.4 */ readonly lockingPrincipal?: string; } /** * Type of a SessionPropertyValidation for a correspondent client proposed property. */ export declare enum ValidationType { REGEX = 0, VALUES = 1 } /** * Defines the validation for a trusted client proposed session property. * The subtypes define specific types of validation. * * @since 6.5 */ export interface SessionPropertyValidation { /** * Subtype of property validation */ readonly type: ValidationType; } /** * Defines regular expression based validation for a trusted client proposed session property. * Such validation defines a * regular expression which supplied values must match against. * * @since 6.5 */ export interface MatchesSessionPropertyValidation { /** * The regular expression */ readonly regex: string; } /** * Defines values based validation for a trusted client proposed session property. * Such validation defines a set of values to which the supplied session property value must belong. * * @since 6.5 */ export interface ValuesSessionPropertyValidation { /** * The sef of permitted values */ readonly values: string[]; } /** * Action to be taken by the system authentication handler for connection * attempts that do not provide a principal name and credentials. */ export declare type AnonymousConnectionAction = 'deny' | 'allow' | 'abstain'; /** * Configuration for anonymous connections */ export interface SystemAuthenticationAnonymousConfiguration { /** * The action to take for anonymous connection attempts. * * May be one of: * * * `deny` - Deny anonymous connection attempts. * * `allow` - Accept anonymous connection attempts. * * `abstain` - Defer authentication for anonymous connection * attempts to subsequent authentication handlers * */ readonly action: AnonymousConnectionAction; /** * The roles the system authentication handler will assign to * anonymous sessions. Applicable only if anonymous connections are * {@link AnonymousConnectionAction allowed}. */ readonly roles: string[]; } /** * A snapshot of information from the system authentication store. */ export interface SystemAuthenticationConfiguration { /** * The system principals stored on the server. */ readonly principals: SystemPrincipal[]; /** * The configuration that is applied for anonymous connections */ readonly anonymous: SystemAuthenticationAnonymousConfiguration; /** * The map of trusted client proposed properties, * where the key is the permitted property name and the value * defines the validation applied to the property. */ readonly trustedClientProposedProperties: { [key: string]: SessionPropertyValidation; }; } /** * A builder that can be used to create scripts for use with * {@link Security.updateSecurityStore updateSecurityStore}. * * Facilitates producing scripts that control the assignment of permissions to * roles. * From Diffusion 6.5, script builders are no longer immutable. Each builder * operation mutates this script builder and returns it. */ export interface SecurityScriptBuilder { /** * Create the script string. * * @return the script */ build(): string; /** * Sets the roles to be assigned by default to all anonymous sessions. * * @param (roles?: string[]): SecurityScriptBuilder;the roles to be * assigned. An empty array (the default), or no argument, * will result in anonymous sessions being assigned no roles * by default. * @return the builder to allow chaining * @throws a {@link NullValueError} if roles is null or undefined */ setRolesForAnonymousSessions(roles?: string[]): SecurityScriptBuilder; /** * Sets the roles to be assigned by default to all sessions that authenticate with a principal. * * @param roles the roles to be assigned. Any empty array (the default), or * no argument, will result in named sessions being assigned * no roles by default. * * @return the builder to allow chaining * @throws a {@link NullValueError} if roles is null or undefined */ setRolesForNamedSessions(roles?: string[]): SecurityScriptBuilder; /** * Set the global permissions assigned to a particular role. * * @param role the role to set global permissions for. * @param permissions the permissions to assign globally for a role, * default `= []`. * * @return the builder to allow chaining * @throws a {@link NullValueError} if any of the arguments are null or undefined */ setGlobalPermissions(role: string, permissions?: string[]): SecurityScriptBuilder; /** * Set the default permissions that a particular role will have for paths. * * @param role the role to set path permissions for. * @param permissions the path permissions to assign for the role, * default `= []`. * * @return the builder to allow chaining * @throws a {@link NullValueError} if any of the arguments are null or undefined */ setDefaultPathPermissions(role: string, permissions?: string[]): SecurityScriptBuilder; /** * Remove any previously assigned permissions from a particular path for a * given role. * * This is different from setting no permissions to a path. By removing * permissions set for a path, permissions will be inherited from the * nearest set of permissions that have been assigned higher in the * path hierarchy or from the default path permissions if no more specific * permissions are found. * * @param role the role to remove path permissions from. * @param path the path path to remove permissions from. * * @return the builder to allow chaining * @throws a {@link NullValueError} if any of the arguments are null or undefined */ removePathPermissions(role: string, path: string): SecurityScriptBuilder; /** * Sets specific path permissions for a named role. * * When permissions are assigned to a role for a path they will apply * to the path and any paths below the specified path. Path-scoped * permissions are assigned to roles for specific paths. The * permission assignment applies to all descendant paths, unless there is a * more specific assignment. * * To evaluate whether a session has permission for a path, the server * starts at that path and searches up the tree to find the nearest * permissions assignment. The first assignment is the only one considered, * even if the session has roles involved in assignments further up the * hierarchy. * * @param role the role to assign permissions for. * @param path the path to assign permissions. * @param permissions the permissions to assign to the role for the * specified path. Any empty array (the default) or no * argument would specify that the role has no * permissions at this path, which differs from there * being no permissions assigned for that path (see * {@link * SecurityScriptBuilder.removePathPermissions}). * * @return the builder to allow chaining * @throws a {@link NullValueError} if any of the arguments are null or undefined */ setPathPermissions(role: string, path: string, permissions?: string[]): SecurityScriptBuilder; /** * Set a path not to inherit path permissions from its parent paths or * the default path permissions. * * * By default, a path without specific * {@link SecurityScriptBuilder.setPathPermissions} path permission * assignments inherits the permission assignments from the first * parent path that has them. If neither the path nor any of its parent * paths have permission assignments, the * {@link SecurityScriptBuilder.setDefaultPathPermissions default path permissions} * are used. * * @param path the path * * @return this builder, modified to isolate the given path * in the path hierarchy * @throws a {@link NullValueError} if path is null or undefined * * @since 6.5 */ isolatePath(path: string): SecurityScriptBuilder; /** * Re-instate inheritance of path permission assignments from parents of * the given path. * * @param path the path * * @return this builder, modified to re-instate the * inheritance of path permission assignments from parents of * the given path * @throws a {@link NullValueError} if path is null or undefined * @see {@link SecurityScriptBuilder.isolatePath} * @since 6.5 */ deisolatePath(path: string): SecurityScriptBuilder; /** * Specify a set of a roles that another role should inherit permissions from. * * @param role the role * @param roles the set of roles to inherit from. * * @return the builder to allow chaining * @throws a {@link NullValueError} if any of the arguments are null or undefined */ setRoleIncludes(role: string, roles: string[]): SecurityScriptBuilder; /** * Restrict a role so it can only be edited by a specific principal. * * @param role the role * @param lockingPrincipal the locking principal * * @return this builder, modified to lock a role to a single * principal that can edit it * @throws a {@link NullValueError} if any of the arguments are null or undefined * * @since 6.4 */ setRoleLockedByPrincipal(role: string, lockingPrincipal: string): SecurityScriptBuilder; } /** * A builder that can be used to create scripts for use with {@link * Security.updateAuthenticationStore updateAuthenticationStore}. * * Facilitates producing scripts that contain the mapping of roles to specific * principals/passwords. * From Diffusion 6.5, script builders are no longer immutable. Each builder * operation mutates this script builder and returns it. */ export interface SystemAuthenticationScriptBuilder { /** * Create the script string. * * @return the script */ build(): string; /** * Change a principal's assigned roles. * * @param principal the principal name. * @param roles an array of roles * @return this builder, modified to contain the changed roles * @throws a {@link NullValueError} if any of the arguments are null or undefined */ assignRoles(principal: string, roles: string[]): SystemAuthenticationScriptBuilder; /** * Add a principal. * * If `lockingPrincipal` is defined, the new principal can only be edited * by the principal defined in the lock. * * The script will fail if the principal is already defined at the server. * * @param principal the principal name * @param password the principal's password * @param roles the assigned roles for the principal, default `= []` * @param lockingPrincipal the name of the principal that can edit this * principal * @return this builder, modified to contain the new principal * @throws a {@link NullValueError} if any of the arguments are null or undefined */ addPrincipal(principal: string, password: string, roles?: string[], lockingPrincipal?: string): SystemAuthenticationScriptBuilder; /** * Set a principal's password. * * @param principal the principal name * @param password the principal's password * @return this builder, modified to contain the changed password * @throws a {@link NullValueError} if any of the arguments are null or undefined */ setPassword(principal: string, password: string): SystemAuthenticationScriptBuilder; /** * Assert that a principal's password is `password`. * * This command doesn't update the store. It can be used in conjunction with * {@link SystemAuthenticationScriptBuilder.setPassword setPassword} to * create a script that updates a password only if the previous password is * supplied. * * @param principal the principal name * @param password the principal's password * @return this builder, modified to verify the password * @throws a {@link NullValueError} if any of the arguments are null or undefined */ verifyPassword(principal: string, password: string): SystemAuthenticationScriptBuilder; /** * Remove a principal. * * @param principal the principal name * @return this builder, modified to remove the principal * @throws a {@link NullValueError} if principal is null or undefined */ removePrincipal(principal: string): SystemAuthenticationScriptBuilder; /** * Instruct the system authentication to allow anonymous connections. * * @param roles the roles to assign to anonymous sessions, default `= []` * @return this builder, modified to contain the allow anonymous connections * command. * @throws a {@link NullValueError} if roles is null or undefined */ allowAnonymousConnections(roles?: string[]): SystemAuthenticationScriptBuilder; /** * Instruct the system authentication to deny anonymous connections. * * @return this builder, modified to contain the deny anonymous connections command. */ denyAnonymousConnections(): SystemAuthenticationScriptBuilder; /** * Instruct the system authentication handler to defer authentication * decisions for anonymous connections to subsequent handlers. * * @return this builder, modified to contain the abstain anonymous connections * command. */ abstainAnonymousConnections(): SystemAuthenticationScriptBuilder; /** * Specifies the name of a client proposed session property that should be * allowed by the system authenticator along with a set of permissible values. * The property will only be allowed if the supplied value matches one of those * in the set of values specified. * * @param propertyName specifies the name of the client proposed property to be allowed * @param allowedValues specifies a set of allowed values for the client proposed property * * @return this builder, modified to allow the specified client * proposed property if its value matches one of those supplied * @throws a {@link NullValueError} if any of the arguments are null or undefined * * @since 6.5 */ trustClientProposedPropertyIn(propertyName: string, allowedValues: string[]): SystemAuthenticationScriptBuilder; /** * Specifies the name of a client proposed session property that should be * allowed by the system authenticator along with a regular expression to * validate the property value. * The property will only be allowed if the supplied value matches with the regular expression. * * @param propertyName specifies the name of the client proposed property to be allowed * @param regex * regular expression which will be matched against * supplied values to determine whether they are valid * * @return this builder, modified to allow the specified client * proposed property if its value matches the given regular expression * @throws a {@link NullValueError} if any of the arguments are null or undefined * * @since 6.5 */ trustClientProposedPropertyMatches(propertyName: string, regex: string): SystemAuthenticationScriptBuilder; /** * Specifies the name of a client proposed session property that should * now be ignored by the system authenticator. * * This removes the effect of a previous request to trust the named property. * * @param propertyName specifies the name of the client proposed property to be ignored * * @return this builder, modified to ignore the specified client proposed property * @throws a {@link NullValueError} if propertyName is null or undefined * * @since 6.5 */ ignoreClientProposedProperty(propertyName: string): SystemAuthenticationScriptBuilder; } /** * Single-use callback provided to the {@link Authenticator.authenticate * authenticate} call. */ export interface AuthenticatorCallback { /** * Authentication passed - allow the authentication request with * modifications to the session properties. * * @param properties this can include all allowed user-defined session * properties, as well as a subset of fixed session * properties see {@link Authenticator.authenticate * authenticate}. * @throws an error if another method has already been * invoked on this callback */ allow(properties: SessionProperties): void; /** * Authentication passed - allow the authentication request with fixed * properties as supplied but no user-defined properties. * * @throws an error if another method has already been * invoked on this callback */ allow(): void; /** * The authentication has neither passed nor failed. * * @throws an error if another method has already been * invoked on this callback */ abstain(): void; /** * Authentication failed - deny the authentication request. * * @throws an error if another method has already been * invoked on this callback */ deny(): void; } /** * An authentication handler that processes authentication requests from the * server. * * Instances can be registered with the server using the * {@link Security.setAuthenticator AuthenticationControl} feature. * * The server calls an authentication handler when a client application creates * a session, or changes the principal associated with a session, allowing the * handler to veto individual requests. * * Authentication handlers are configured in precedence order. Authentication * will succeed if a handler responds by calling {@link * AuthenticatorCallback.allow allow()} or {@link AuthenticatorCallback.allow * allow(map)} and handlers with higher precedence respond by calling {@link * AuthenticatorCallback.abstain abstain()}. * * Authentication will fail if a handler responds by calling {@link * AuthenticatorCallback.deny deny()} and all higher precedence handlers respond * by calling {@link AuthenticatorCallback.abstain abstain()}. * * If all authentication handlers respond by calling {@link * AuthenticatorCallback.abstain abstain()}, the request will be denied. Once * the outcome is known, the server may choose not to call any remaining * authentication handlers. * * @since 6.3 */ export interface Authenticator { /** * Processes an authentication request. * * This method will be called to authenticate new sessions, and when a * session requests that the session principal is changed (for example, * using {@link Security.changePrincipal changePrincipal}). * * For each call to `authenticate`, the handler should respond by calling * one of the methods of the provided {@link AuthenticatorCallback * callback}. The handler may return immediately and process the * authentication request asynchronously. The authentication will not * proceed until a callback method is called. * * The content of the `sessionProperties` parameter depends upon * whether the authentication handler is being called on initial * authentication of a session or as a result of a session re-authenticating * using {@link Security.changePrincipal changePrincipal}, as shown * below: * * * * * * * * * * * * * * * * * *
              Initial AuthenticationchangePrincipal
              Fixed Properties * A full set of fixed session properties as defined in {@link Session}. *

              * $Principal will be the same as the supplied * principal. *

              * $Roles will contain the configured default roles for the * principal. *

              * A full set of fixed session properties as defined in {@link Session}. *

              * $Principal will be the principal from the previously * authenticated session which may differ from the supplied * principal. *

              * $Roles will contain the configured default roles for the new * principal.

              User-defined PropertiesNoneExisting user-defined properties
              * * On initial authentication the `proposedProperties` parameter will * provide any user-defined properties that the client supplied when opening * the client session, but on re-authentication it will be empty * * The handler can choose to call {@link AuthenticatorCallback.allow * allow()} to accept the authentication request with default behavior or * {@link AuthenticatorCallback.allow allow(map)} to accept the * authentication request with modifications to the session properties. * Alternatively it may call {@link AuthenticatorCallback.deny deny()} to * deny the request or {@link AuthenticatorCallback.abstain abstain()} to * abstain from authentication, in which case the request will be passed on * to the next configured authentication handler. * * If the handler calls {@link AuthenticatorCallback.allow allow()} then the * resulting session properties for the session will be as follows: * * * * * * * * * * * * * * * * * *
              Initial AuthenticationchangePrincipal
              Fixed PropertiesAs supplied plus those assigned by the server on connection.As supplied but with $Principal replaced by the supplied * principal.
              User-defined PropertiesNoneNone
              * * If the handler calls {@link AuthenticatorCallback.allow allow(map)} then the map * may contain values for any fixed properties that can be changed/supplied * (see below) and/or all user-defined properties to assign to the session. * The user-defined properties may be those proposed by the client or they * can be any set of user-defined properties that the handler chooses. * *

              Permitted fixed property adjustments

              * * An authentication handler can set values for any of the following fixed * properties to {@link AuthenticatorCallback.allow allow(map)}: * * * {@link PropertyKeys.COUNTRY $Country} * * {@link PropertyKeys.LANGUAGE $Language} * * {@link PropertyKeys.LATITUDE $Latitude} * * {@link PropertyKeys.LONGITUDE $Longitude} * * {@link PropertyKeys.PRINCIPAL $Principal} * * {@link PropertyKeys.ROLES $Roles} * * An authentication handler can only set values of these fixed properties. * Other fixed properties provided by the handler will be ignored. If the * handler does not set a fixed property, the value will be as supplied, or * as assigned by the server. * *

              Handling the $Roles property

              * * The $Roles property is formatted as a quoted list of * strings. To make the handling of this property value easier there are * methods in the global `diffusion` namespace. Using these methods an * authenticator can adjust roles as follows: * * ``` * const roles = diffusion.stringToRoles( * sessionProperties.get(diffusion.clients.PropertyKeys.ROLES)); * * ... changes roles are required ... * * sessionProperties.put(diffusion.clients.PropertyKeys.ROLES, * diffusion.rolesToString(roles)); * callback.allow(sessionProperties); * ``` * * @param principal the name of the proposed principal, or * {@link ClientControlOptions.ANONYMOUS ANONYMOUS} * if none was supplied * @param credentials authenticating the principal; for example, a password * @param sessionProperties supplies the currently known session properties * for the client. On initial authentication this * will be the known fixed property values. If the * session is re-authenticating using {@link * Security.changePrincipal changePrincipal}, this * will be the full set of fixed property values * plus any user-defined properties from the * existing session. * @param proposedProperties provides any user-defined properties proposed * by the client. The handler may choose to pass * on these properties as they are, veto some * properties, or add more properties before * passing them to the result. The client can * provide arbitrary keys and values. Supplied * properties should be checked and * filtered/constrained to ensure they do not * affect the integrity of the application. * Authentication handlers should not blindly pass * proposed properties to {@link * AuthenticatorCallback.allow allow}. * @param callback single use callback */ authenticate(principal: string, credentials: Credentials, sessionProperties: SessionProperties, proposedProperties: SessionProperties, callback: AuthenticatorCallback): void; /** * Notification that the authenticator was closed normally. * * No further calls to this authenticator will be made. */ onClose(): void; /** * Notification of an error * * No further calls to this authenticator will be made. * * @param error the error that occurred */ onError(error: any): void; } /** * This feature allows a client session to query and update the security store * and to authenticate the credentials of other sessions. * *

              Authentication Control

              * * Sessions are authenticated by a chain of authenticators. A client session can * participate in the authentication process by creating an authenticator and * registering it with the server. * * Each authenticator is registered under a particular authenticator name. For * registration to succeed, the server's security configuration must include a * matching `control-authentication-handler` entry for the name, otherwise * registration will fail and the authenticator will be closed immediately. * * Each client session can register a single authenticator for a given * authenticator name. * * For each authentication event, the server will use its configuration to * determine the authenticator priority order. The server may call * authenticators in serial or parallel. The server may stop the authentication * process as soon as it has an allow or deny response from an authenticator and * all higher priority authenticators have abstained. * * For a configured control authenticator, the server will select a single * authenticator from those registered for the authenticator name. If no * authenticators are currently registered, the server will consult the next * configured authenticator in priority order. * *
              Access control
              * * In order to register an authenticator a session needs both * {@link GlobalPermission.REGISTER_HANDLER REGISTER_HANDLER} and * {@link GlobalPermission.AUTHENTICATE AUTHENTICATE} permissions. *

              * In order to revoke a session's authentication a session needs both * {@link GlobalPermission.MODIFY_SESSION MODIFY_SESSION} and * {@link GlobalPermission.AUTHENTICATE AUTHENTICATE} permissions. * *

              Security Control

              * * The security store is a persistent database maintained by the server * containing authorisation rules that control what sessions can do. * * Access rights to read and write data and to perform actions on the server are * controlled by a fixed set of permissions. When a session is opened, the * server assigns it a set of roles based on the principal used to authenticate. * The rules in the security store assign each role to a set of permissions. * Each role can be assigned zero, one, or many permissions. The same permission * can be assigned to multiple roles. Roles can also include other roles to form * a role hierarchy, and so inherit permissions from the other roles. Roles are * defined implicitly by specifying them in permission assignments or inclusion * relationships; there is no need to explicitly create roles in the security * store. * * Permissions either have 'path' or 'global' scope. {@link GlobalPermission * Global permissions} apply to actions that are server-wide and not specific to * a particular path. {@link PathPermission Path permissions} apply to * hierarchical context, such as a branch of the topic tree or a branch of the * message path hierarchy. * *

              Evaluation of global permissions

              * * A session has a global permission if any of its roles are assigned the * permission. * *

              Evaluation of path permissions

              * * A session has a permission for a path if any of its roles have the permission * for the path. * * {@link SecurityScriptBuilder.setPathPermissions Path permissions} can be assigned to * a role for a path. The permissions are inherited by all descendant paths for * the role, except paths that have a separate permission assignment for the * role or that are {@link SecurityScriptBuilder.isolatePath isolated} and their * descendant paths. * *

              * {@link SecurityScriptBuilder.setDefaultPathPermissions Default path permissions} can * be assigned to a role to set permissions at the root of the path hierarchy. A * default permission assignment applies to all paths without direct or * inherited path permission assignments, except paths that are * {@link SecurityScriptBuilder.isolatePath isolated} and their descendant * paths. * * The permissions a session has for a path are determined as follows: * *

                *
              1. If the path has permission assignments for one or more of the sessions * roles, the applicable permissions are the union of all of the assigned * permissions. *
              2. Otherwise, if the path is not isolated, and its parent path has * permission assignments for one or more of the sessions roles, the applicable * permissions are the union of all of the permissions assigned to the parent * path. This rule is applied recursively, for each remaining parent path. *
              3. Otherwise, if the neither the path nor any of its parent paths have * permission assignments for one of the sessions role or are isolated, the * applicable permissions are the union of the default permissions assigned to * each role. *
              4. If no applicable permissions are found, the session has no permissions * for that path. *
              * *

              Access control

              * * To query the store the session needs {@link GlobalPermission.VIEW_SECURITY * VIEW_SECURITY} permission and to update the store it needs * {@link GlobalPermission.MODIFY_SECURITY MODIFY_SECURITY} permission. * * In order to register an authentication handler a session needs both * {@link GlobalPermission.REGISTER_HANDLER REGISTER_HANDLER} and * {@link GlobalPermission.AUTHENTICATE AUTHENTICATE} permissions. * *

              Accessing the feature

              * * This feature can be obtained from a {@link Session session} as follows: * * **Example:** * ``` * // Get a reference to the security feature * var security = session.security; * ``` * */ export interface Security { /** * The global permission enum */ readonly GlobalPermission: typeof GlobalPermission; /** * The path permission enum */ readonly PathPermission: typeof PathPermission; /** * Get the principal that the session is currently authenticated as. * * @returns the session's principal */ getPrincipal(): string; /** * Re-authenticate the session. * * This may be used to change the principal for the session, or to * re-authenticate the session before it expires. * * A session may determine when it is due to expire by querying the value of * the `EXPIRY_TIME` session property using * {@link Session.getSessionProperties}. If this property is not present * the session will not expire and there is no need to re-authenticate * unless the principal in use is to be changed. * * @param principal the principal name. This may be the same principal as * supplied when the session was originally opened, or it may be an * entirely different principal. * * @param credentials the credentials authenticating the principal * * @param properties a map of the proposed user session properties. The * supplied properties will be validated during authentication and * may be discarded or changed. If no user properties are required, * an empty object should be supplied. * * @return a Promise that resolves when a response is received * from the server. *

              * If authentication succeeded, the Promise will resolve with `true`. *

              * If authentication failed because the {@code principal} was * unknown or the {@code credentials} were invalid, the session will * not have been re-authenticated and the Promise will resolve * with `false`. *

              * Otherwise, the Promise will be rejected with an error. *

              * Common reasons for failure include: *

                *
              • the session is closed. *
              * * @since 6.12 */ reauthenticate(principal: string, credentials: Credentials, properties: SessionProperties): Promise; /** * Change the principal associated with this session. * * Allows a session to authenticate as a different principal. If the * authentication fails, the current principal remains valid. * * @param principal the new principal to use. * @param credentials credentials to authenticate the principal with. * @returns a {@link Promise} * * **Example:** * ``` * session.security.changePrincipal('foo', 'password'); * ``` * * @deprecated since 6.12 * Use the new {@link Security.reauthenticate reauthenticate} * in preference, which allows user proposed session properties * to be supplied. This method will be removed in a future release. */ changePrincipal(principal: string, credentials: string): Promise; /** * Obtain the current contents of the server's security store. * * If the request is successful, the result will complete with a {@link SecurityConfiguration}. * * **Example:** * ``` * session.security.getSecurityConfiguration().then(function(configuration) { * console.log('Got security configuration', configuration); * }, function(err) { * console.log('Error getting security configuration', err); * }); * ``` * * @returns a {@link Promise} that completes with the security configuration * */ getSecurityConfiguration(): Promise; /** * Obtain the current contents of the server's authentication store. * * If the request is successful, the success callback will be called with a * {@link SystemAuthenticationConfiguration} object. * * **Example:** * ``` * session.security.getSystemAuthenticationConfiguration().then(function(configuration) { * // Display principals/roles * configuration.principals.forEach(function(principal) { * console.log(principal.name, principal.roles); * }); * * // Check the authentication action applied to anonymous connections * console.log(configuration.anonymous.action); * * // Check the default roles assigned to anonymous connections * console.log(configuration.anonymous.roles); * }, function(err) { * // Error retrieving configuration * console.log(err); * }); * ``` * * @returns a {@link Promise} that completes with the server's authentication store * */ getSystemAuthenticationConfiguration(): Promise; /** * Send a command script to the server to update the security store. The * script may be produced by the builder {@link SecurityScriptBuilder}. * * If the script is applied without error to the server, the operation * result will complete successfully. * * If any command in the script fails, none of the changes will be applied, * and the result will be failed with an error object. * * If the server is configured for path replication then the changes will * be replicated to all members of the cluster. * * **Example:** * ``` * session.security.updateSecurityStore(script).then(function() { * console.log('Security configuration updated'); * }, function(err) { * console.log('Failed to update security configuration', err); * }); * ``` * * @param script the command script * @returns a {@link Promise} */ updateSecurityStore(script: string): Promise; /** * Send a command script to the server to update the authentication store. * The script may be produced by the builder {@link * SystemAuthenticationScriptBuilder}. * * If the script is applied without error to the server, the operation * result will complete successfully. * * If any command in the script fails, none of the changes will be applied, * and the result will be failed with an error object. * * If the server is configured for path replication then the changes will * be replicated to all members of the cluster. * * **Example:** * ``` * session.security.updateAuthenticationStore(script).then(function() { * console.log('Authentication configuration updated'); * }, function(err) { * console.log('Failed to update security configuration', err); * }); * ``` * * @param script the command script * @returns a {@link Promise} */ updateAuthenticationStore(script: string): Promise; /** * Returns a {@link SecurityScriptBuilder} that can be used to modify the * server's {@link SecurityConfiguration}. * * @return a script builder */ securityScriptBuilder(): SecurityScriptBuilder; /** * Returns a {@link SystemAuthenticationScriptBuilder} that can be used to * modify the server's {@link SystemAuthenticationConfiguration}. * * @return a script builder */ authenticationScriptBuilder(): SystemAuthenticationScriptBuilder; /** * Register an authenticator for client authentication events. * * @param handlerName the handler name which must match an entry in the * server's security configuration * @param authenticator specifies the authentication handler * @return a {@link Promise} that completes when the authentication * handler has been registered, returning a {@link Registration} * which can be used to unregister the authentication handler. *

              * Otherwise, the Promise will resolve with an error. Common reasons * for failure include: *

                *
              • the session is closed; *
              • the session does not have `REGISTER_HANDLER` or `AUTHENTICATE` * permission; *
              • the server configuration does not contain a * `control-authentication-handler` element with the given name. *
              • {@link NullValueError} – if any of the arguments are * `null` or `undefined` *
              * * @since 6.3 */ setAuthenticator(handlerName: string, authenticator: Authenticator): Promise; /** * Returns the set of global permissions assigned to the role. * * @return the set of global permissions. This may be empty indicating * that the role has no global permissions assigned. * * @since 6.3 */ getGlobalPermissions(): Promise; /** * Returns a list of path permissions assigned to the calling session on a given * path. * * @param path the path to query for permissions * @return a {@link Promise} which completes when the response is received * from the server. *

              * If the request was successful, the {@link Promise} will * complete successfully with a list of {@link PathPermission}. * * @since 6.5 */ getPathPermissions(path: string): Promise; /** * Revokes a session's authentication. * * This will immediately close the specified client session. * * @param sessionId identifies the client session to revoke * * @return a {@link Promise} which completes when the response is received * from the server. * * @since 6.12 */ revokeAuthentication(sessionId: SessionId): Promise; } /** * @module diffusion.locks * * Provide access to {@link SessionLockScope} * * **Example:** * ``` * // Get a reference to the security feature * var locks = diffusion.locks; * ``` */ /** * Enum containing scope parameter of {@link Session.lock} * * **Example:** * ``` * // Get the ALL_FIXED_PROPERTIES key * var scope = diffusion.locks.SessionLockScope.UNLOCK_ON_SESSION_LOSS; * ``` * * @since 6.2 */ export declare enum SessionLockScope { /** * The lock will be released when the acquiring session is closed. */ UNLOCK_ON_SESSION_LOSS = 0, /** * The lock will be released when the acquiring session loses its * current connection to the server. */ UNLOCK_ON_CONNECTION_LOSS = 1 } /** * @hidden */ export interface SessionLockOptionsNamespace { SessionLockScope: typeof SessionLockScope; } export declare const SessionLockOptions: SessionLockOptionsNamespace; /** * @module Session.lock */ /// /** * A session lock is a server-managed resource that can be used to * coordinate exclusive access to shared resources across sessions. For * example, to ensure a single session has the right to update a topic; to * ensure at most one session responds to an event; or to select a single * session to perform a housekeeping task. Session locks support general * collaborative locking schemes. The application architect is responsible * for designing a suitable locking scheme and for ensuring each application * component follows the scheme appropriately. * * Session locks are identified by a lock name. Lock names are arbitrary and * chosen at will to suit the application. Each lock is owned by at most one * session. Locks are established on demand; there is no separate operation * to create or destroy a lock. * * A session lock is acquired using the {@link Session.lock} method. * If no other session owns the lock, the server will assign the lock to the * calling session immediately. Otherwise, the server will record that the * session is waiting to acquire the lock. A session can call `lock` * more than once for a given session lock – if the lock is acquired, * all calls will complete successfully with equal SessionLocks. * * If a session closes, the session locks it owns are automatically * released. A session can also {@link SessionLock.unlock release a lock}. * When a session lock is released and other sessions are waiting to acquire * the lock, the server will arbitrarily select one of the waiting sessions * and notify it that it has acquired the lock. All of the newly selected * session's pending `lock` calls will complete normally. Other * sessions will continue to wait. * * The {@link Session.lock} method takes an optional scope parameter that * provides the further option of automatically releasing the lock when the * session loses its connection to the server. * *

              Race conditions

              * * This session lock API has inherent race conditions. Even if an * application is coded correctly to protect a shared resource using session * locks, there may be a period where two or more sessions concurrently * access the resource. The races arise for several reasons including * * * due to the check-then-act approach of polling * {@link isOwned}, the lock can be lost after the check has succeeded but * before the resource is accessed; * * the server can detect a session is disconnected and assign the lock * to another session before the original session has detected the * disconnection. * * Despite this imprecision, session locks provide a useful way to * coordinate session actions. * */ export interface SessionLock { /** * Get the name of the lock * @return the name of the session lock */ getName(): string; /** * A value that identifies the acquisition of the lock with the * given {@link getName name}. SessionLocks that are acquired * later are guaranteed to have bigger sequence values, allowing the * sequence number to be used as a fencing token. * * @return a value that identifies the acquisition of this lock */ getSequence(): Long; /** * Test whether the session lock is still owned. * * @return `true` if the session lock is still owned by the session */ isOwned(): boolean; /** * The scope of the lock. * * The scope determines when the lock will be released automatically. * * If a session makes multiple * {@link Session.lock requests for a lock} * using different scopes, and the server assigns the lock to the session * fulfilling the requests, the lock will be given the weakest scope * (`UNLOCK_ON_CONNECTION_LOSS`). Consequently, an individual request can * complete with a lock that has a different scope to that requested. * * @return the lock scope * * @see {@link Session.lock} */ getScope(): SessionLockScope; /** * Release a session lock, if owned. * * @return a Promise that resolves when a response is received * from the server. *

              * On completion, this session will no longer own the named session * lock. If Promise completes normally, a true value indicates this * session previously owned the lock and a false value indicates * it did not. *

              * If the Promise resolves with an error, this session * does not own the session lock. * * @see {@link Session.lock} */ unlock(): Promise; } /** * A session tree branch mapping. * * Branch mappings belong to {@link BranchMappingTable branch mapping tables}. * Each branch mapping is a pair of a {@link Session session filter} and the * topic tree branch that applies to sessions matching the filter. * * @author DiffusionData Limited * @since 6.7 * @see SessionTrees */ export interface BranchMapping { /** * the session filter */ readonly sessionFilter: string; /** * the topic tree branch in the topic tree for sessions matching the session * filter */ readonly topicTreeBranch: string; } /** * A session tree branch mapping table. * * A branch mapping table is a list of {@link BranchMapping branch mappings} * assigned to a session tree branch. * * To create a branch mapping table, obtain a new builder instance using * {@link newBranchMappingTableBuilder}, call * {@link BranchMappingTableBuilder.addBranchMapping} for each branch mapping, * then {@link BranchMappingTableBuilder.create}. The result can then be sent to the * server using {@link SessionTrees.putBranchMappingTable}. * * @author DiffusionData Limited * @since 6.7 * @see SessionTrees */ export interface BranchMappingTable { /** * @return the branch of the session tree to which this table is bound */ getSessionTreeBranch(): string; /** * @return the branch mappings */ getBranchMappings(): BranchMapping[]; } /** * Builder for {@link BranchMappingTable} instances. * * @author DiffusionData Limited * @since 6.7 * @see SessionTrees * @see Diffusion.newBranchMappingTableBuilder() */ export interface BranchMappingTableBuilder { /** * Reset the builder. * * @return this Builder */ reset(): BranchMappingTableBuilder; /** * Add a new branch mapping. * * @return this Builder */ addBranchMapping(sessionFilter: string, topicTreeBranch: string): BranchMappingTableBuilder; /** * Create a new BranchMappingTable. * * @param sessionTreeBranch the session tree branch */ create(sessionTreeBranch: string): BranchMappingTable; } /** * This feature allows a client session to configure session trees. * * A session tree is a virtual view of the topic tree presented to a session by * fetch and subscription operations. Custom session trees for different * sessions can be configured using declarative rules maintained by the server * to meet data security, data optimisation, or personalisation and localisation * requirements. Each session can be presented with a unique session tree based * on its session properties. * * A session tree is produced by applying branch mappings to the topic * tree. Branch mappings are organised into branch mapping tables. Each * branch mapping table is assigned to a unique path – the session tree * branch. * * A session tree is composed of session paths. Each session path is * mapped via the branch mapping tables to a unique topic path. * * A branch mapping table is an ordered list of (session filter, topic tree * branch) pairs. For example, the branch mapping table for the session tree * branch `market/prices` might be: * *

               * Session filter                           Topic tree branch
               * =========                                =============
               * USER_TIER is '1' or $Country is 'DE'     backend/discounted_prices
               * USER_TIER is '2'                         backend/standard_prices
               * $Principal is ''                         backend/delayed_prices
               * 
              * * With this configuration, if an unauthenticated session (one that matches the * `$Principal is ''` session filter) subscribes to the session path * `market/prices/X`, and there is a topic bound to the topic path * `backend/delayed_prices/X`, the subscription will complete. The session * will receive a subscription notification under the session path * `market/prices/X`, together with the topic properties and the value of * the topic. The session is unaware that the data originates from a topic bound * to a different topic path. If no topic is bound to * `backend/delayed_prices/X`, the subscription will not resolve and the * session will receive no data, even if there is a topic bound to * `market/prices/X`. * * Session trees complement the data transformation capabilities of * {@link TopicViews topic views}. In our example, the time delayed time feed at * `backend/delayed_prices` could be maintained by a topic view using the * delay by clause. * * Branch mappings are persisted by the server and shared across a cluster, in a * similar manner to topic views, security stores, and metric collectors. Branch * mappings are editable using this feature, and via the management console. * * For a given session and session path, at most one branch mapping applies. The * applicable branch mapping is chosen as follows: *
                *
              • Each branch mapping table with session tree branch that is a prefix of the * session path is considered. For a given table, the first branch mapping with * a condition that matches the session's properties is the one that applies. A * branch mapping table may have no applicable branch mappings for a session. *
              • If there are several such branch mapping tables with a branch mapping * that for the session, the one with the longest prefix of the session path * applies. *
              • If no branch mapping table has a branch mapping for the session, the * session path is translated to the identical topic path. *
              * *

              Access control

              * * To subscribe to or fetch from a session path, a session must be granted the * appropriate path permission to the session path for the operation * ({@link PathPermission.SELECT_TOPIC SELECT_TOPIC}, or * {@link PathPermission.READ_TOPIC READ_TOPIC}). The session doesn't require * any permissions to the topic path of the topic providing the data. * * To create or replace branch mappings, a session needs the * {@link PathPermission.MODIFY_TOPIC MODIFY_TOPIC} path permission for the * session tree branch of the branch mapping table, * {@link PathPermission.EXPOSE_BRANCH EXPOSE_BRANCH} path permission for the * topic tree branch of each branch mapping, and (if an existing table with the same * session tree branch is being replaced) {@link PathPermission.EXPOSE_BRANCH * EXPOSE_BRANCH} permission for each branch mapping of existing table. * * To retrieve a branch mapping table, a session needs the * {@link PathPermission.READ_TOPIC READ_TOPIC} path permission for its session tree * branch. * *

              Accessing the feature

              * * This feature may be obtained from a {@link Session session} as follows: * *
               * const sessionTrees = session.sessionTrees;
               * 
              * * @author DiffusionData Limited * * @since 6.7 */ export interface SessionTrees { /** * Create or replace a branch mapping table. * * The server ensures that a session tree branch has at most one branch mapping * table. Putting a new branch mapping table will replace any previous * branch mapping table with the same session tree branch. To remove all branch * mappings for a session tree branch, put an empty branch mapping table. * * @param branchMappingTable the new table * * @return a Promise that resolves when a response is received * from the server. *

              * If the task completes successfully, the CompletableFuture result * will be null. The result type is `any` rather than `void` to provide * forward compatibility with future iterations of this API that may * provide a non-null result with a more specific result type. *

              * Otherwise, the Promise will be rejected with an error. Common * reasons for failure include: *

                *
              • the branchMappingTable or one of its branch mappings is * invalid; *
              • the calling session does not have the {@link * PathPermission.MODIFY_TOPIC MODIFY_TOPIC} permission for the * session tree branch of the branch mapping table, {@link * PathPermission.EXPOSE_BRANCH EXPOSE_BRANCH} permission for each * branch mapping of branchMappingTable, and (if there is an * existing table for the session tree branch) {@link * PathPermission.EXPOSE_BRANCH EXPOSE_BRANCH} permission for each * branch mapping of existing table; *
              • the operation failed due to a transient cluster error; *
              • the session is closed. *
              • {@link NullValueError} – if branchMappingTable is `null` or `undefined` *
              */ putBranchMappingTable(branchMappingTable: BranchMappingTable): Promise; /** * Retrieve the session tree branches of the server's branch mapping tables. The * results will only include the session tree branches of branch mapping tables * that have at last one branch mapping and for which the calling session * has {@link PathPermission.READ_TOPIC READ_TOPIC} path permission for * the session tree branch. * * Individual branch mapping tables can be retrieved using * {@link getBranchMappingTable}. * * @return a Promise that resolves when a response is received * from the server, returning a list of session tree branches in path * order. *

              * If the task fails, the the Promise will be rejected with an error. * Common reasons for failure include: *

                *
              • the session is closed. *
              */ getSessionTreeBranchesWithMappings(): Promise; /** * Retrieve a branch mapping table from the server. * * If there is no branch mapping table at the given session tree branch, this * method will return an empty branch mapping table. * * @param sessionTreeBranch the session tree branch that identifies the branch mapping * table * * @return a Promise that resolves when a response is received * from the server, returning the branch mapping table for * sessionTreeBranch. *

              * If the task fails, the Promise will be rejected with an error. Common * reasons for failure include: *

                *
              • the calling session does not have the {@link * PathPermission.READ_TOPIC READ_TOPIC} permission for * sessionTreeBranch; *
              • the session is closed. *
              • {@link NullValueError} – if sessionTreeBranch `null` or `undefined` *
              */ getBranchMappingTable(sessionTreeBranch: string): Promise; } /** * @module diffusion.timeseries */ /** * Time series event metadata. */ export interface EventMetadata { /** * Sequence number identifying this event within its time series. * Assigned by the server when the event is created. * * Sequence numbers are unique within a time series. Each event appended * to a time series is assigned a sequence number that is is equal to * the sequence number of the preceding event plus one. */ readonly sequence: number; /** * Event timestamp. Assigned by the server when the event is created. * * Events do not have unique timestamps. Events with different sequence * numbers may have the same timestamp. * * Subsequent events in a time series usually have timestamps that are * greater or equal to the timestamps of earlier events, but this is not * guaranteed due to changes to the time source used by the server. * * Timestamps represent the difference, measured in milliseconds, between * the time the server added the event to the time series and midnight, * January 1, 1970 UTC */ readonly timestamp: number; /** * Server-authenticated identity of the session that created the event. * * If the session that created the event was not authenticated, the author * will be an empty string. */ readonly author: string; /** * Check if the EventMetadata is equal to another object * * @return `true` if the two objects are equal */ equals(other: any): boolean; } /** * An event in a time series. * * Two instances are {@link Event.equals equal} if and only if they have identical * attributes. Typically, two Event instances that have the same sequence number will * be equal, but this may not be true if the event has changed on the server – * see Changes to a time series made outside the API in the * {@link Session.timeseries TimeSeries} documentation. */ export interface Event extends EventMetadata { /** * The value associated with the event. */ readonly value: V; /** * If this is an edit event, returns the metadata of the original event that this * event replaces; otherwise returns this event. * * The result is always the metadata of an original event, never that of an edit event. */ readonly originalEvent: EventMetadata; /** * Flag indicating whether this is an edit event. * * `x.isEditEvent` is equivalent to `x.originalEvent != x`. */ readonly isEditEvent: boolean; } /** * @module Session.timeseries */ /// /** * Timeseries stream structure */ export interface StreamStructure { /** * The id of the stream structure */ readonly id: number; /** * The name of the stream structure */ readonly name: string; /** * Convert object to string * * @return a string representation of the CloseClientRequest */ toString(): string; } /** * This feature allows a session to update and query time series topics. * *

              Time series topics

              * * A time series is a sequence of events. Each event contains a value * and has server-assigned metadata comprised of a sequence number, timestamp, * and author. Events in a time series are ordered by increasing sequence * number. Sequence numbers have values between `0` and * `Number.MAX_INTEGER` and are contiguous: an event with sequence number * `n` will be followed by one with sequence number `n + 1` . Two * events with the same sequence number will be equal – having the same * timestamp, author, and value. * * A time series topic allows sessions to access a time series that is * maintained by the server. A time series topic has an associated {@link * DataType event data type}, such as `Binary` , `String` , * or `JSON` , that determines the type of value associated with each event. * * This feature provides a historic query API for time series topics, allowing a * session to query arbitrary sub-sequences of a time series. The {@link * Session.topics} and {@link Session.addStream} features complete the API, * providing ways to create and subscribe to a time series topic. * * The API presents a time series as an append-only data structure of immutable * events that is only changed by adding new events. * *

              Edit events

              * * Although a time series is append-only, an event can be overridden by * appending an edit event. An edit event is a special type of event * that overrides an earlier event in the time series (referred to as the * original event) with a new value. When an edit event is added to a * time series, the server retains both the original event and the edit event, * allowing subscription and query results to reflect the edit. * * For example, suppose a time series has two events with the values `A` * and `B` , and the first event has been overridden by a later edit event * that provides a new value of `X` . The server has the following * information about the time series. * * Sequence | Value | Type * --------- | ------- | ------- * 0 | A | *original event* * 1 | B | *original event* * 2 | X | *edit of sequence 0* * * The current value of the event with sequence number 0 is `X` . * * If an original event has several edit events, the latest edit event (the one * with the highest sequence number) determines its current value. Each edit * event refers to an original event, never to another edit event. * * Extending the example by appending a further edit event to the time series: * * Sequence | Value | Type * --------- | ------- | ------- * 3 | Y | *second edit of sequence 0* * * The current value of the event with sequence number 0 is now `Y` . * *

              Retained range

              * * A time series topic retains a range of the most recent events. When a new * event is added to the time series, older events that fall outside of the * range are discarded. By default, this range includes the ten most recent * events. A different range can be configured by setting the * {@link TopicSpecification.TIME_SERIES_RETAINED_RANGE * TIME_SERIES_RETAINED_RANGE} property. * *

              Subscribing to a time series topic

              * * A session can {@link Session.select select} a time series topic and {@link * Session.addStream add a value stream} to receive updates about events * appended to the time series. Events are represented by {@link Event} * instances. Each event has a value and {@link EventMetadata metadata}. An edit * event has two sets of metadata – its own metadata and that of the * original event that it replaces. * *

              Subscription range

              * * New subscribers are sent a range of events from the end of the time series. * This is known as the subscription range. Configuring a subscription * range is a convenient way to provide new subscribers with an appropriate * subset of the latest events. * * The default subscription range depends on whether the topic is configured to * publish delta streams. If delta streams are enabled, new subscribers are sent * the latest event if one exists. If delta streams are disabled, new * subscribers are sent no events. Delta streams are enabled by default and can * be disabled by setting the {@link TopicSpecification.PUBLISH_VALUES_ONLY * PUBLISH_VALUES_ONLY} property to `true`. * * A larger subscription range can be configured by setting the * {@link TopicSpecification.TIME_SERIES_SUBSCRIPTION_RANGE * TIME_SERIES_SUBSCRIPTION_RANGE} property. Regardless of the * `TIME_SERIES_SUBSCRIPTION_RANGE` property, if delta streams are * enabled, new subscribers will be sent at least the latest event if one * exists. * * If the range of events is insufficient, the subscribing session can use a * {@link TimeSeries.rangeQuery range query} to retrieve older events. * * When configuring a non-default subscription range for a time series topic, * register value streams before subscribing to the topic. The session only * maintains a local cache if the latest value received for a topic, not the * full subscription range. If a value stream is added after a session has * subscribed to a matching time series topic, the new stream will only be * notified of the latest value. * *

              Updating a time series topic

              * * A session can use {@link TimeSeries.append append} to submit a value * to be added to a time series. The server will add an event to the end of the * time series based on the supplied value, with a new sequence number, * timestamp, and the author set to the authenticated principal of the session. * * Providing a number as fourth argument to {@link TimeSeries.append append} * allows a session to submit a value and supplied time. This provides control * over the timestamp of the event. The supplied instant must not be before the * latest event stored by the time series topic. There are no other restrictions. * * A session can use {@link TimeSeries.edit edit} to submit an edit to * an original time series event, identified by its sequence number. The server * will add an edit event to the end of the time series based on the supplied * value, with a new sequence number, timestamp, and the author set to the * authenticated principal of the session. * * Time series topics can also be updated using the functionality provided by * the {@link TopicUpdate} feature. This includes {@link TopicUpdate.set set} * {@link UpdateStream}s. This usage performs an append operation with the added * benefits of {@link UpdateConstraint}s, topic creation when updating (upsert), * and delta streams. When using methods from {@link TopicUpdate} the sequence * number, timestamp and author metadata will be generated using the same rules * as {@link TimeSeries.append} but the associated {@link EventMetadata} will * not be returned to the caller. * *

              Querying a time series topic

              * * A {@link RangeQuery} is a configured query that can be evaluated for a time * series topic using {@link RangeQuery.selectFrom selectFrom(topicPath)}. * Results are provided as streams of {@link Event Event} instances. * * {@link RangeQuery} is a builder for configuring a Query that selects a range * of a time series. There are two types of range query that differ in how edits * are processed – value range queries and edit range queries. * *

              Value range queries

              * * A value range query returns a merged view of part of a time series. This is * the most common time series query and appropriate for most applications. * * The result of a value range query reflects the latest available edits and the * {@link QueryResult query result} is ordered by the original event sequence * number, presenting edit events instead of the original events they replace. * Original events that have no edit events are included verbatim. Original * events that have edit events are replaced by the latest edit event. * * A value range query of the example time series, with no range constraints so * the entire time series is selected, returns two events: * * ``` * sequence=3, value=Y; original event sequence=0 * sequence=1, value=B * ``` * * The original value of the first event is not provided. It's apparent that the * first event is an edit event because it provides the metadata of the original * event it replaces. * *

              Edit range queries

              * * Applications with auditing and other administrative requirements can access * original event values using an edit range query. An edit range query returns * an unmerged view of a time series that can include both original events and * the edit events that replace them. Edit range queries are rarely needed * – value range queries satisfy most use cases. * * Edit range queries provide a detailed view of a time series. Because this is * potentially sensitive information, an edit range query can only be performed * by a session that has the `QUERY_OBSOLETE_TIME_SERIES_EVENTS` * permission for the target topic. * * There are two sub-types of edit range query. * * A full audit trail of edit events can be obtained using an all edits * edit range query. The result contains all original events selected by the * query, together with all subsequent edit events that affect the original * events. The query result stream provides events in time series order. An all * edits query of the example time series, with no range constraints so the * entire time series is selected, returns four events: * * ``` * sequence=0; value=A * sequence=1; value=B * sequence=2; value=X; original event sequence=0 * sequence=3; value=Y; original event sequence=0 * ``` * * A latest edits edit range query returns a query result stream in * time series order that contains all original events selected by the query, * together with the latest edit events that affect the original events. A * latest edits query of the example time series, with no range constraints so * the entire time series is selected, returns three events: * * ``` * sequence=0; value=A * sequence=1; value=B * sequence=3; value=Y; original event sequence=0 * ``` * * The initial range of events delivered for a subscription to a time series * topic is derived from a latest edits edit range query. See * Subscription Range. * * When evaluated for a time series that has no edit events, an edit range query * will return the same results as a similarly configured value range query. * *

              Changes to a time series made outside the API

              * * The API presents a time series as an append-only data structure of immutable * events that is only changed by adding new events. The API does not allow * events to be deleted or edited. * * There are circumstances in which events can be removed from a time series by * server operations outside the API. For example, a time series topic can be * configured to discard or archive older events to save storage space; or the * time series may be held in memory and lost if the server restarts. Subscribed * sessions are not notified when events are removed in this way, but a session * can infer the removal of events that are no longer included in query results. * Similarly, an event's value can be changed on the server. For example, if an * administrator changes its value to redact sensitive data. Again, subscribed * sessions are not notified when events are modified, but a session can infer * this has happened from query results. * * Whether such changes can happen for a particular time series topic depends on * the topic specification, and the administrative actions that are allowed. To * write a robust application, do not rely on two Event instances with the same * sequence number but obtained though different API calls, being equal; nor * that there are no sequence number gaps between events in query results. * *

              Access control

              * * The session must have the {@link PathPermission.READ_TOPIC READ_TOPIC} * permission for a topic to query a time series topic. The * {@link PathPermission.QUERY_OBSOLETE_TIME_SERIES_EVENTS * QUERY_OBSOLETE_TIME_SERIES_EVENTS} permission is additionally required * to evaluate an {@link RangeQuery.forEdits edit range} query, or a * {@link RangeQuery.forValues value range query} with an * {@link RangeQuery.editRange edit range}. * * The session must have the {@link PathPermission.UPDATE_TOPIC UPDATE_TOPIC} * path permission for a topic to {@link TimeSeries.append append} a new event * to a time series topic. The {@link PathPermission.EDIT_TIME_SERIES_EVENTS * EDIT_TIME_SERIES_EVENTS} permission is additionally required to {@link * TimeSeries.edit submit an edit} to any time series event. The more * restrictive {@link PathPermission.EDIT_OWN_TIME_SERIES_EVENTS * EDIT_OWN_TIME_SERIES_EVENTS} permission allows a session to submit * edits to time series topic events that are authored by the principal of the * calling session. * * @since 6.0 */ export interface TimeSeries { /** * Update a time series topic by appending a new value. * * The server will add an event to the end of the time series based on the * supplied value, with a new sequence number, timestamp, and the author set * to the authenticated principal of the session. * * @param topicPath the path of the time series topic to update * @param value the event value * @param valueType the type of the supplied value. This must match the value * type of the {@link DataType} configured as the time * series topic's {@link * TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE event * value type}. By default will be inferred from the * provided value. * @param timestamp an optional timestamp. The timestamp must be greater or * equal to that of the most recent event appended to the * topic * @return a result that completes when a response is received from the * server. *

              * If the update was successful, the Promise will complete * successfully and provide the {@link EventMetadata} of the new * event. *

              * Otherwise, the Promise will fail with an Error. Common reasons for * failure include: *

                *
              • {@link IllegalArgumentError} – the request could not be parsed by * the calling client; *
              • {@link NullValueError} – any of the required arguments are null * or undefined; *
              */ append(topicPath: string, value: any, valueType?: DataType | (new (...args: any[]) => any), timestamp?: number | Long): Promise; /** * Update a time series topic by appending a new value that overrides the * value of an existing event. * * The existing event is identified by its sequence number and must be an * original event. * * The server will add an edit event to the end of the time series based on * the supplied value, with a new sequence number, timestamp, and the author * set to the authenticated principal of the session. * * @param topicPath the path of the time series topic to update * @param originalSequence the sequence number of the original event to edit * @param value the event value * @param valueType the type of the supplied value. This must match * the value type of the {@link DataType} * configured as the time series topic's {@link * TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE * event value type}. By default will be inferred * from the provided value. * * @return a result that completes when a response is received from the server. *

              * If the update was successful, the CompletableFuture will complete * successfully and provide the {@link EventMetadata} of the new * event. *

              * Otherwise, the Promise will fail with an Error. Common reasons for * failure include: *

                *
              • {@link IllegalArgumentError} – the request could not be parsed by * the calling client; *
              • {@link NullValueError} – any of the required arguments are null * or undefined; *
              */ edit(topicPath: string, originalSequence: number | Long, value: any, valueType?: DataType): Promise; /** * Return a default range query that performs a value range query of an * entire time series. * * Further queries with different parameters can be configured using the * {@link RangeQuery} methods. * * The result provides {@link Bytes} values, making it * compatible with any event data type supported by time series topics. A * query with a more specific value type can be configured using {@link * RangeQuery.as}. * * A RangeQuery equal to the one returned by this method can be created from * an arbitrary RangeQuery as follows. * * ``` * defaults = anyRangeQuery.forValues() * .fromStart() * .untilLast(0) * .limit(Number.MAX_INTEGER) * .as(Uint8Array); * ``` * * @return a RangeQuery with default settings */ rangeQuery(): RangeQuery; } /** * Builder for queries that select a range of events from a time series. * * See {@link Session.timeseries} for an overview of the various types of range * query: * * * value range queries, * * latest edits edit range queries, and * * all edits edit range queries. * * {@link TimeSeries.rangeQuery rangeQuery} returns a default * RangeQuery. Further queries with different parameters can be configured * using the methods of this interface. {@link RangeQuery} instances are * immutable. Each method returns a copy of this query with a modified * setting. Method calls can be chained together in a fluent manner to create a * query. For example: * * ``` * var defaultQuery = session.timeseries.rangeQuery(); * * // A value range query that selects up to 100 original events from the * // start of a time series. * first100 = defaultQuery.forValues().fromStart().next(100); * ``` * *

              Creating value range queries

              * * A value range query returns a merged view of part of a time series. This is * the most common time series query and appropriate for most applications. A * value range query begins with the {@link RangeQuery.forValues forValues} * operator, followed by the view range. The view range determines the * range of original events the time series that are of interest. See Range * expressions below for the various ways to specify `RANGE` . * * The events returned by the query are constrained by an optional edit * range, introduced by the {@link RangeQuery.editRange editRange} * operator. An event will only be included in the result if it is in the edit * range. Let's consider some examples to see how the view range and the edit * range interact. * * * * * * * * * * * * * * * * * * *
              QueryMeaning
              rangeQuery().forValues();For each original event in the time series, either return the latest * edit event or if it has no edit events, return the original event.
              rangeQuery().forValues().from(100).to(150);For each original event with a sequence number between 100 and 150 * (inclusive), either return the latest edit event or if it has no edit * events, return the original event.
              * rangeQuery().forValues().from(100).to(150).editRange().from(400); * For each original event with a sequence number between 100 and 150 * (inclusive), return the latest edit event with a sequence number greater * than or equal to 400. *

              * The result of this query will not include any original events because * there is no overlap between the view range and the edit range.

              * * Value range queries can be further refined using the {@link RangeQuery.limit * limit()} and {@link RangeQuery.as as()} operators. * *

              Creating edit range queries

              * * An edit range query returns an unmerged view of a time series than can * include both original events and the edit events that replace them. Edit * range queries are rarely needed – value range queries satisfy most * use cases. * * An edit range query begins with the {@link RangeQuery.forEdits forEdits} * operator, followed by the view range. The view range determines the * range of original events the time series that are of interest. The result * will only contain original events that are in the view range, and edit events * for original events in the view range. See Range expressions below * for the various ways to specify `RANGE` . * * The events returned by the query are constrained by an optional edit * range, introduced by the {@link RangeQuery.latestEdits latestEdits} or * {@link RangeQuery.allEdits allEdits} operators. An event will only be * included in the result if it is in the edit range. Let's consider some * example edit range queries. * * * * * * * * * * * * * * * * * * * * * * *
              QueryMeaning
              rangeQuery().forEdits();Return all events in a time series.
              rangeQuery().forEdits().from(100).to(150);Return the original events with a sequence number between 100 and 150 * (inclusive) and all edit events in the time series that refer to the * original events.
              rangeQuery().forEdits().from(100).to(150).latestEdits();Return the original events with a sequence number between 100 and 150 * (inclusive) and the latest edit events in the time series that refer to * the original events.
              * rangeQuery().forEdits().from(100).to(150).allEdits().from(400); * For each original event with a sequence number between 100 and 150, * (inclusive) return all edit events with a sequence number greater than or * equal to 400. *

              * The result of this query will not include any original events because * there is no overlap between the view range and the edit range.

              * * Edit range queries can be further refined using the {@link RangeQuery.limit * limit()} and {@link RangeQuery.as as()} operators. * *

              Range expressions

              * * Range expressions are used to specify the view and edit ranges in value * range and edit range queries. Each range expression has an * anchor that determines where to start, and a span that * determines where the range ends. Both anchor and span are * inclusive – if an anchor or span falls on an event, the * event is included in the result. * * Both anchor and the span are optional. If the anchor is unspecified, the * range begins at the start of the time series. If the span is unspecified, * the range continues until the end of the time series. * *

              Anchors

              * * * There are five ways to specify an anchor. * * * * * * * * * * * * * * * * * * * * * * * * * * *
              AnchorMeaning
              {@link RangeQuery.from from(Number)}Sets the anchor at an absolute sequence number.
              {@link RangeQuery.from from(Date)}Sets the anchor at an absolute time.
              {@link RangeQuery.fromStart fromStart}Sets the anchor at the start of the time series.
              {@link RangeQuery.fromLast fromLast(Number)}Sets the anchor at a relative offset before the end of the time * series. For value range queries, count is the number of original * events. For edit range queries, count is the number of events of * any type.
              {@link RangeQuery.fromLast fromLast(Date}
              * {@link RangeQuery.fromLastMillis fromLastMillis}
              Sets the anchor at a relative time before the timestamp of the last * event of the time series.
              * * An anchor point can be before the start or after the end of the time * series. * *

              Spans

              * * There are nine ways to specify a span. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
              SpanMeaning
              {@link RangeQuery.to to(Number)}The range ends at an absolute sequence number. The sequence * argument may be before or after the anchor.
              {@link RangeQuery.toStart toStart}The range ends at the start of the time series.
              {@link RangeQuery.to to(Date)}The range ends at an absolute time. The date argument may * be before or after the anchor.
              {@link RangeQuery.next next(Number)}The range ends at an event that is a relative number of events after * the anchor. For value range queries, count is the number of * original events. For edit range queries, count is the number of * events of any type.
              {@link RangeQuery.next next(Date)}
              * {@link RangeQuery.nextMillis nextMillis}
              The range ends at an event that is a relative time after the * anchor.
              {@link RangeQuery.previous previous(Number)}The range ends at an event that is a relative number of events before * the anchor. For value range queries, count is the number of * original events. For edit range queries, count is the number of * events of any type.
              {@link RangeQuery.previous previous(Date)}
              * {@link RangeQuery.previousMillis previousMillis}
              The range ends at an event that is a relative time before the * anchor.
              {@link RangeQuery.untilLast untilLast(Number}The range ends at an event that is a relative number of events before * the end of the time series. For value range queries, count is the * number of original events. For edit range queries, count is the * number of events of any type.
              {@link RangeQuery.untilLast untilLast(Date)}
              * {@link RangeQuery.untilLastMillis untilLastMillis}
              The range ends at an event that is a relative time before the * timestamp of the last event of the time series.
              * * A span can specify an end point that is before the start or after the end * of the time series. * * If the span specifies an end point after the anchor, the range includes * the first event at or following the anchor and ends at the last event at * or preceding the end point. If the span specifies an end point before the * anchor, the range includes the first event at or preceding the anchor and * ends at the last event at or after the end point. * *

              Using the builder methods

              * * Although the natural order of operators in a query is as shown in the * syntax diagrams above, RangeQuery builder methods – those that * return another RangeQuery – can be applied in any order with the * following exceptions: * * * {@link RangeQuery.editRange} only applies to value range queries, so cannot * follow `forEdits()` without an intervening `forValues();` * * {@link RangeQuery.latestEdits} and {@link RangeQuery.allEdits} only apply * to edit range queries, so cannot follow `forValues()` without an * intervening `forEdits()`. * * Each method overrides some configuration of the RangeQuery to which it is * applied, as summarized in the following table. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
              Builder methodOperator typeOverridden configuration
              forValues()Value rangeOverrides the existing query type to create a new value range query. * Overrides the existing view range with a new view range that selects the * entire time series. The existing edit range is copied unchanged.
              forEdits()Value rangeOverrides the existing query type to create a new edit range query * that includes all edits. Overrides the existing view range with a new * view range that selects the entire time series. The existing edit range * is copied unchanged.
              editRange() * Edit rangeOverrides the existing edit range with a new edit range that selects * the entire time series. The existing view range is copied unchanged.
              * Throws IllegalStateException if this is not a value range * query.
              latestEdits()
              * allEdits()
              Edit rangeOverrides the existing edit range with a new edit range that selects * the entire time series. The existing view range is copied unchanged. *
              * Throws Error if this is not an edit range query.
              from()
              * fromStart()
              * fromLast()
              AnchorOverrides the anchor of the current range.
              to()
              * toStart()
              * next()
              * previous()
              * untilLast()
              SpanOverrides the span of the current range.
              limit()LimitOverrides the limit.
              as()Query value typeOverrides the query value type.
              * * @see Session.timeseries.rangeQuery */ export interface RangeQuery { /** * Return a copy of this RangeQuery configured to perform a value range * query within the view range set to the entire time series. * * **Operator type:** value range * * @return a copy of this range query configured to perform a view range * query within a new view range that selects the time time series. */ forValues(): RangeQuery; /** * Return a copy of this RangeQuery configured to perform an edit range * query within the view range set to the entire time series. * * **Operator type:** value range * * @return a copy of this range query configured to perform an edit range * query with a new view range that selects the entire time series */ forEdits(): RangeQuery; /** * Return a copy of this RangeQuery configured to perform a value range * query with the edit range set to the entire time series. * * This operator can only be applied to value range queries. The default * query returned by {@link TimeSeries.rangeQuery rangeQuery()} is a * value range query. The {@link RangeQuery.forValues} operator can be used * to create a value range query from an edit range query. * * **Operator type:** edit range * * @return a copy of this range query configured to perform a view range * query with a new edit range that selects the entire time series * @throws an {@link IllegalStateError} if this is not a value range query */ editRange(): RangeQuery; /** * Return a copy of this RangeQuery configured to perform an edit range * query with the edit range that selects all edits in the entire time * series. * * This operator can only be applied to edit range queries. The default * query returned by {@link TimeSeries.rangeQuery rangeQuery()} is a * value range query. The {@link RangeQuery.forEdits} operator can be used * to create an edit range query form a value range query. * * **Operator type:** edit range * * @return a copy of this range query configured to perform an edit range * query with a new edit range that selects all edits in the entire * time series * @throws an {@link IllegalStateError} if this is not an edit range query */ allEdits(): RangeQuery; /** * Return a copy of this RangeQuery configured to perform an edit range * query with the edit range that selects latest edits in the entire * time series. * * This operator can only be applied to edit range queries. The default * query returned by {@link TimeSeries.rangeQuery rangeQuery()} is a * value range query. The {@link RangeQuery.forEdits forEdits()} operator * can be used to create an edit range query from a value range query. * * **Operator type:** edit range * * @return a copy of this range query configured to perform an edit range * query with a new edit range that selects the latest edits in the * entire time series * @throws an {@link IllegalStateError} if this is not an edit range query */ latestEdits(): RangeQuery; /** * Return a copy of this RangeQuery with the anchor of the current range * configured to be either an absolute sequence number, or a Date instance. * * **Operator type:** anchor * * @param sequence absolute sequence number or Date specifying the anchor of * the returned range * @return a copy of this range query with a new anchor * @throws an {@link IllegalArgumentError} if sequence is negative * @throws a {@link NullValueError} if sequence is null or undefined */ from(sequence: number | Date): RangeQuery; /** * Return a copy of this RangeQuery with the anchor of the current range * configured to be the start of the time series. * * There is a difference between fromStart( and `from(0)` * if the range also ends before the first event of the time series. For * example, `fromStart().toStart()` is always empty, but * `from(0).toStart()` includes the event with sequence number * `0` . * * **Operator type:** anchor * * @return a copy of this range query with a new anchor */ fromStart(): RangeQuery; /** * Return a copy of this RangeQuery with the anchor of the current range * configured to be a relative offset before the end of the time series. * * **Operator type:** anchor * * @param count specifies the anchor as a number of events before the * end of the time series. For value range queries, count is * the number of original events. For edit range queries, * count is the number of events of any type. * @return a copy of this range query with a new anchor * @throws an {@link IllegalArgumentError} if count is negative * @throws a {@link NullValueError} if count is null or undefined */ fromLast(count: number): RangeQuery; /** * Return a copy of this RangeQuery with the anchor of the current range * configured to be a relative time from the timestamp of the last event * in the time series. * * **Operator type:** anchor * * @param timeSpan specifies anchor as a number of milliseconds relative * to the timestamp of the latest event in the time series * @return a copy of this range query with a new anchor * @throws an {@link IllegalArgumentError} if timeSpan is negative * @throws a {@link NullValueError} if timeSpan is null or undefined */ fromLastMillis(timeSpan: number): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to end at an absolute sequence number or Date instance. * * **Operator type:** span * * @param sequence absolute sequence number or Date instance specifying the * end of the returned range * @return a copy of this range query with a new span * @throws an {@link IllegalArgumentError} if sequence is negative * @throws a {@link NullValueError} if sequence is null or undefined */ to(sequence: number | Date): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to end at the start of the time series. * * There is a difference between `toStart()` and `to(0)` if * the range also starts before the first event of the time series. For * example, `fromStart().toStart()` is always empty, but * `fromStart().to(0)` includes the event with sequence number * `0` . * * **Operator type:** span * * @return a copy of this range query with a new span */ toStart(): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to select a range of events following the anchor. * * **Operator type:** span * * @param count specifies the end of the range of events to select * following the anchor. For value range queries, count is the * number of original events. For edit range queries, count is * the number of events of any type. * @return a copy of this range query with a new span * @throws an {@link IllegalArgumentError} if count is negative * @throws a {@link NullValueError} if count is null or undefined */ next(count: number): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to select a temporal range of events following the anchor. * * **Operator type:** span * * @param timeSpan the time span in milliseconds of events following the * anchor to select * @return a copy of this range query with a new span * @throws an {@link IllegalArgumentError} if timeSpan is negative * @throws a {@link NullValueError} if timeSpan is null or undefined */ nextMillis(timeSpan: number): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to select a range of events preceding the anchor. * * **Operator type:** span * * @param count specifies the end of the range of events to select * preceding the anchor. For value range queries, count is the * number of original events. For edit range queries, count is * the number of events of any type. * @return a copy of this range query with a new span * @throws an {@link IllegalArgumentError} if count is negative */ previous(count: number): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to select a temporal range of events preceding the anchor. * * **Operator type:** span * * @param timeSpan the time span in milliseconds of events preceding the * anchor to select * @return a copy of this range query with a new span * @throws an {@link IllegalArgumentError} if timeSpan is negative */ previousMillis(timeSpan: number): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to end a number of events before the end of the time * series. * * **Operator type:** span * * @param count specifies the end of the range of events to select as a * number of events before the end of the time series. For * value range queries, count is the number of original * events. For edit range queries, count is the number of * events of any type. * @return a copy of this range query with a new span * @throws an {@link IllegalArgumentError} if count is negative * @throws a {@link NullValueError} if count is null or undefined */ untilLast(count: number): RangeQuery; /** * Return a copy of this RangeQuery with the span of the current range * configured to end at a relative time from the timestamp of the last * event in the time series. * * **Operator type:** span * * @param timeSpan specifies the end of the range of events to select as * a number of milliseconds relative to the timestamp of * the latest event in the time series * @return a copy of this range query with a new span * @throws an {@link IllegalArgumentError} if timeSpan is negative * @throws a {@link NullValueError} if timeSpan is null or undefined */ untilLastMillis(timeSpan: number): RangeQuery; /** * Return a copy of this RangeQuery that returns at most count events. * * If the query would otherwise select more than count events, only the * latest count values (those with the highest sequence numbers) are * returned. * * This is most useful when a temporal span has been configured with * {@link RangeQuery.nextMillis} or {@link RangeQuery.previousMillis}, * where the potential number of returned events is unknown. * * {@link QueryResult.isComplete isComplete()} can be used to determine * whether a query has returned an incomplete result. * * **Operator type:** limit * * @param count the maximum number of events to return * @return a copy of this range query with a new limit * @throws an {@link IllegalArgumentError} if count is negative */ limit(count: number): RangeQuery; /** * Return a copy of this RangeQuery with a different query value type. * * A query can only be evaluated successfully against time series topics * with a compatible event data type. If a query method is called for a * time series topic with an incompatible event data type, the query * will complete exceptionally. * * If the event data type of the time series topic is known, * compatibility of a particular `valueClass` can be checked using * {@link DataType.canReadAs canReadAs}. The * {@link TimeSeries.rangeQuery default range query} has a query value * type of {@link Bytes}, which is compatible with all time series value * data types. * * **Operator type:** query value type * * @param valueClass the value class or data type to read event values as * @return a copy of this range query with a new query value type * @throws an {@link IllegalArgumentError} if valueClass cannot be read as a data type * @throws a {@link NullValueError} if valueClass is null or undefined */ as(valueClass: DataType | (new (...args: any[]) => any)): RangeQuery; /** * Evaluate this query for a time series topic. * * The session must have the `READ_TOPIC` path permission for `topicPath` * to evaluate a query. The `QUERY_OBSOLETE_TIME_SERIES_EVENTS` topic * permission is also required if this is an {@link RangeQuery.forEdits edit * range} query, or a {@link RangeQuery.forValues value range query} with an * {@link RangeQuery.editRange edit range}. * * @param topicPath the path of the time series topic to query * * @return a result that completes when a response is * received from the server. *

              * If the query returned results, the result will * complete successfully and provide an {@link QueryResult}. *

              * Otherwise, the result will complete exceptionally * with an {@link ErrorReason}. */ selectFrom(topicPath: string): Promise; } /** * Query result providing a {@link Stream} of events. */ export interface QueryResult { /** * The number of events selected by the query. * * This number may be greater than `events.length` due to a * policy of the time series topic to limit the number of returned * results, or the use of {@link RangeQuery.limit}. */ readonly selectedCount: number; /** * The timeseries events returned */ readonly events: Array>; /** * `true` if this result includes all events selected by the query. */ readonly isComplete: boolean; /** * A description of the structure of the result stream. */ readonly streamStructure: StreamStructure; /** * Merge this result with `other` , combining original events and * edit events, to produce a new {@link QueryResult}. * * The following rules are applied to calculate the result: * * * If this result and `other` have an event with equal * sequence numbers, the event from `other` is selected. * * An edit event is selected in place of its original event. * * If there are multiple edit events of an original edit, the one * with the highest sequence is selected. * * The returned result implements {@link QueryResult.isComplete} to be true * and {@link QueryResult.selectedCount} to contain the count of events in * the `events` array, regardless of whether this result is complete. * * @param other the other query result to merge * @return the merged result */ merge(other: QueryResult): QueryResult; } /** * @module Session.topics */ /** * This feature allows a session to manage topics. It provides the following * capabilities: * * 1) Adding and removing topics.
              * 2) Missing topic notifications — listening for requests to subscribe to * topics that do not exist thus allowing dynamic topic creation on demand.
              * 3) Topic event listeners — listening for topic events, such as the number of * subscribers to a topic changing from zero to greater than zero or from * greater than zero to zero. * *

              Topics

              * * The Diffusion server stores data in topics. Each topic is bound to a topic * path in the topic tree, and may have a current value. Sessions can subscribe * to topics. Updates to topic values are broadcast to subscribing sessions. * There are several types of topic. The {@link TopicType topic type} determines * the type of the data values a topic publishes to subscribers. * *

              Adding topics

              * *

              Creating topics

              * * The simplest way to create a topic is to call * {@link TopicControl.add}, supplying a topic type. For example, to * create a {@link TopicType.JSON JSON} topic bound to the topic path * foo: * *
               * const result = session.topic.add("foo", diffusion.TopicType.JSON);
               * 
              * * Success or failure is reported asynchronously through the CompletableFuture * result. * * The nature of a topic depends primarily on its topic type, but can be * customized using topic properties. Some types of topic cannot be created * without supplying mandatory topic properties. Topic properties can be * supplied in a {@link TopicSpecification topic specification} using * {@link TopicControl.add add(topicPath: string, specification: TopicSpecification)}. * Topic specifications can be created using * {@link TopicSpecification new TopicSpecification(...)} and further customized * with builder methods. For example, to create a {@link TopicType.JSON JSON} * topic bound to the topic path foo with the * {@link TopicSpecification.VALIDATE_VALUES VALIDATE_VALUES} property set to * true: * * ``` * // Create specification for JSON topics which validate update values on the server * const TopicSpecification = diffusion.topics.TopicSpecification; * * var specification = new TopicSpecification(diffusion.topics.TopicType.JSON) * .withProperty(TopicSpecification.VALIDATE_VALUES, "true"); * ``` * * See {@link TopicSpecification} for details of the available topic properties * and their effects on the different types of topic. * * Topic creation is idempotent. If {@link TopicControl.add addTopic(path, * specification)} is called and there is already a topic bound to `path` with a * topic specification equal to `specification`, the call will complete normally * with an {@link TopicAddResult} result that indicates that no topic has been * added. However, if there is a topic bound to `path` with a different topic * specification, the call will fail. * *

              Removing topics

              * * Topics can be removed using {@link TopicControl.remove}. Only those * selected topics for which the caller has {@link PathPermission.MODIFY_TOPIC * MODIFY_TOPIC} permission will be removed, any others will remain. * * Topics can also be automatically removed according to a removal criteria * specified using the {@link TopicSpecification.REMOVAL REMOVAL} topic * property. * *

              Managing topic tree hierarchies

              * * A topic can be bound to any path in the topic tree namespace. The only * restriction is that two topics cannot have the same path. * In the following example a topic can be created with the path A/B/foo * even though there are no topics with path A or A/B: * *
               * topicControl.addTopic("A/B/foo", TopicType.JSON);
               * 
              * * Topics bound to the paths A or A/B can be created later. * * Topics can be removed without affecting the topics subordinate to them in the * topic tree using {@link TopicControl.remove} providing a path topic selector. By using * the // topic selector qualifier it is possible to remove a topic and * all of its descendant topics, that is to remove whole topic tree branches. * *

              Access control

              * * To add or remove a topic, a session needs {@link PathPermission.MODIFY_TOPIC * MODIFY_TOPIC} permission for the topic path. When removing topics with a * topic selector that matches more than one topic, only topics with paths for * which the session has MODIFY_TOPIC permission will be removed. * * To register a * {@link TopicControl.addMissingTopicHandler missing topic handler} the session * needs {@link GlobalPermission.REGISTER_HANDLER REGISTER_HANDLER} permission. * *

              Accessing the feature

              * * This feature may be obtained from a {@link Session session} as follows: * * **Example:** * ``` * // Get a reference to topic control feature * var topics = session.topics; * ``` */ export interface TopicControl { /** * Add a topic to the server at a specific path. This returns a {@link Promise}. * * The path should be a string. To express hierarchies, `/` can * be used as a delimiter. This allows topics to be nested and grouped below * each other. For example, `session.topics.add('foo/bar');` * creates the topic `bar` . A topic is not created at `foo` * by this method. * * Each topic has a particular {@link TopicType type}, which constrains the * kind of values that the topic will allow. This type can either be * explicitly provided, or included as part of a {@link TopicSpecification * TopicSpecification}. * *
              Adding from topic type
              * * To directly specify the type of topic to create, provide a string path * and a {@link TopicType}. Topics specified in this way * are created with default topic properties, as described in {@link TopicSpecification}. * *
              Adding from topic specification
              * * {@link TopicSpecification TopicSpecifications} allows * the creation of topics of a particular type, along with additional * properties that determine how the topic operates. For instance, you may * wish to specify that a topic will validate values before publishing, or * that it will only publish values instead of deltas. * *
              Operation results
              * * If the topic was added, or a topic already exists with the same path and * specification, the operation will succeed. If there is a problem with * adding the topic then the result will be rejected with an error. * * If any sessions have already subscribed to the same path that a topic is * created for, they will receive a `subscription` event once the topic is * added, and a `value` event with the initial value (if supplied). * * If the session is closed when calling this method, the returned result * will be rejected. * *
              Failure
              * * If the operation fails a {@link TopicAddFailReason} is * provided. Adding a topic may fail because the session has insufficient * permissions; a topic already exists at the specified path; or certain * mandatory {@link TopicSpecification TopicSpecification} * properties were missing * * **Example:** * ``` * // Create a topic with a Topic Type * session.topics.add('foo/binary', diffusion.topics.TopicType.BINARY); * ``` * * **Example:** * ``` * // Create a topic with a TopicSpecification * const TopicSpecification = diffusion.topics.TopicSpecification; * var specification = new TopicSpecification(diffusion.topics.TopicType.JSON, { * TopicSpecification.VALIDATE_VALUES : "true" * }); * * session.topics.add('foo/json', specification); * ``` * * **Example:** * ``` * // Handle the add topic result * session.topics.add('foo/bob', diffusion.topics.TopicType.JSON).then(function(result) { * if (result.added) { * console.log('Topic added'); * } else { * console.log('A compatible topic already exists'); * } * }, function(error) { * console.log('Topic add failed: ', error); * }); * ``` * * @param topicPath the topic path to create. * @param specification the topic type/specification * @returns a {@link Promise} for this operation */ add(topicPath: string, specification: TopicType | TopicSpecification): Promise; /** * Remove one or more topics at the server. * * The topics to remove will depend upon the nature of the topic selector * specified. If the selector does not have {@link TopicSelector descendant * pattern qualifiers} (i.e. / or //), only those topics that exist at paths * indicated by the selector will be removed and not their descendants. If a * single / qualifier is specified, all descendants of the matching topic * paths will be removed. If // is specified, all branches of the topic tree * that match the selector (i.e topics at the selected paths and all * descendants of the selected paths) will be removed. * * This function can take any number of arguments. Each argument can be a string * or a {@link TopicSelector}. Alternatively, an array of strings and * {@link TopicSelector}s can be passed as a single argument. At least one * valid selector has to be specified. * * **Example:** * ``` * // Remove the topic at 'foo/bar', leaving descendants * session.topics.remove('>foo/bar'); * ``` * * **Example:** * ``` * // Remove the topic at 'foo/bar' and all descendants * session.topics.remove('?foo/bar//'); * ``` * * @param selector the selector specifying the topics to remove * @returns a {@link Promise} resolving to a {@link * TopicRemovalResult} * @throws an {@link IllegalArgumentError} if the selector could not be parsed */ remove(selector: Array): Promise; remove(...selector: Array): Promise; /** * Register a {@link MissingTopicHandler} to handle requests for a branch of * the topic tree. * * The provided handler is called when a client subscribes using a topic * selector that matches no existing topics. This allows a control client * session to be notified when another session requests a topic that does * not exist. * * A control client can register multiple handlers, but may only register a * single handler for a given topic path. See {@link * MissingTopicHandler.onRegister}. A handler will only be called for topic * selectors with a {@link TopicSelector.prefix path prefix} that starts * with or is equal to `topicPath` . If the path prefix matches multiple * handlers, the one registered for the most specific (longest) topic path * will be called. * * If the session is closed or the handler could not be registered, the * returned {@link Promise} will call its failure callback, and the handler's * {@link MissingTopicHandler.onClose} or {@link * MissingTopicHandler.onError} method will be called. * * @param topicPath identifies a branch in the topic tree * @param handler specifies the handler for the specified branch (unless * overridden by a handler registered against a more * specific branch) * * @returns a {@link Promise} for this registration */ addMissingTopicHandler(path: string, updateHandler: MissingTopicHandler): Promise; } /** * Handler called when a client session subscribes using a topic * selector that matches no topics. This interface must be implemented by the user. *

              * Handler instances can be registered using * {@link TopicControl.addMissingTopicHandler addMissingTopicHandler}. * * @class MissingTopicHandler */ export interface MissingTopicHandler { /** * Called when a client session subscribes to a topic selector that selects * no topics, and the topic path belongs to part of the topic tree for which * this handler was registered. * * @param notification the missing topic notification */ onMissingTopic(notification: MissingTopicNotification): void; /** * Called when the handler has been successfully registered with the server. * * A session can register a single handler for a given branch of the topic * tree. If there is already a handler registered for the topic path the * operation will fail and {@link MissingTopicHandler.onClose onClose} will * be called. * * To deregister the handler, call the `deregister` function * supplied. * * @param path the registration path * @param deregister a function that may be called to deregister this handler. * The function will resolve when the handler has been * deregistered. */ onRegister(path: string, deregister: () => Promise): void; /** * Called when the handler is closed. The handler will be closed if the * session is closed, or if the handler is unregistered. * * Once closed, no further calls will be made for the handler. * * @param path the registration path */ onClose(path: string): void; /** * Notification of a contextual error related to this handler. This is * analogous to an unchecked exception being raised. Situations in which * `onError` is called include the session being closed before the * handler is registered, a communication timeout, or a problem with the * provided parameters. No further calls will be made to this handler. * * @param path the registration path * @param error the error */ onError(path: string, error: any): void; } /** * Notification that a session has made a request using a selector that does * not match any topics. */ export interface MissingTopicNotification { /** * The common root topic path derived from the requested topic selector */ path: string; /** * The topic selector that triggered this notification */ selector: TopicSelector; /** * Session ID of the client session that triggered this notification */ sessionID: SessionId; /** * The session properties of the session that made the request * * @since 6.7 */ sessionProperties: SessionProperties; /** * A list of the names of the servers through which the notification has * been routed. * * The first name in the list will be the name of the server to which * the originating session was connected. If the notification was routed * through remote server connections before reaching the recipient then * those servers will also be listed in the order that the notification * passed through them. * * @since 6.7 */ serverNames: string[]; } /** * A result returned when a request to add a topic completes */ export interface TopicAddResult { /** * Whether the Topic was added or not */ added: boolean; /** * The topic path that was used */ topic: string; } /** * Reports the number of topics removed by a call to {@link TopicControl.remove}. * * @since 6.6 */ export interface TopicRemovalResult { /** * The integer represents the number of topics removed by the * operation. This does not include any derived topics created by a * topic view which were removed as a side effect of this action. * * @return the count of topics removed */ removedCount: number; } /** * @module Session.notifications */ /** * The type of topic notification that has been received. */ export declare enum TopicNotificationType { /** * The topic was added. */ ADDED = 0, /** * The topic existed at the time of the selector registration. */ SELECTED = 1, /** * The topic was removed. */ REMOVED = 2, /** * The topic was deselected. */ DESELECTED = 3 } /** * This feature allows a client session to receive notifications about changes * to selected topics. * *

              Notifications

              * * Sessions receive notifications via {@link TopicNotificationListener}s. The * listener will be provided with the {@link TopicSpecification specifications} * for all topics bound to paths that match registered selectors, and any * subsequent notifications for the selected topics on those paths, via {@link * TopicNotificationListener.onTopicNotification onTopicNotificaion}. * Notifications will only be emitted for paths where a topic is bound. * * For example, with a registered selector "?a//" , if a topic is * added at path a/b/c/d with no topics bound to paths higher in * the hierarchy {@link TopicNotificationListener.onTopicNotification * onTopicNotification} will be called once with a topic path of "a/b/c/d" * , a notification type of {@link TopicNotificationType.ADDED ADDED}, * and the topic's associated {@link TopicSpecification}. * * The nature of the notification is provided by the * {@link TopicNotificationType} enum. {@link TopicNotificationType.ADDED ADDED} * and {@link TopicNotificationType.REMOVED REMOVED} represent structural * changes to the topic tree; {@link TopicNotificationType.SELECTED SELECTED} * indicates that a pre-existing topic has been selected by a new registered * selector, and similarly {@link TopicNotificationType.DESELECTED DESELECTED} * indicates that a topic is no longer selected because of changes to the set of * registered selectors for the listener. * *

              Selection and deselection

              * * Registered {@link TopicNotificationListener TopicNotificationListeners} will * receive notifications for all topics matching registered selections. * Selection of topics using {@link TopicSelector} expressions is provided via * the {@link TopicNotificationRegistration} associated for a specific listener. * * A session can request selections at any time, even if the topics do not exist * at the server. Selections are stored on the server and any subsequently added * topics that match registered selectors will generate notifications. * *

              Immediate descendant notifications

              * * Listeners will be informed about the presence or absence of unselected * immediate descendants via {@link * TopicNotificationListener.onDescendantNotification onDescendantNotification}. * This allows listeners to determine whether to select deeper topic paths in * order to walk the topic tree. An immediate descendant is defined as the first * bound topic on any branch below a given topic path. * * For example, for topics at "a/b", "a/c", "a/c/d", "a/e/f/g" , * the immediate descendants of "a"} would be "a/b", "a/c", * "a/e/f/g" . * * Immediate descendant notifications provide a {@link TopicNotificationType} to * indicate the reason for the notification in the same manner as {@link * TopicNotificationListener.onTopicNotification onTopicNotification}. *

              * For example, with a registered selector ">a" , if a topic is * added at path a/b then {@link * TopicNotificationListener.onDescendantNotification onDescendantNotification} * will be called with a topic path of "a/b" and a notification * type of {@link TopicNotificationType.ADDED ADDED}. If a topic was * subsequently added at path a/b/c , no further notifications will * be received until {@link TopicNotificationRegistration.select} was used to * select the deeper topic path ">a/b" . * *

              Access control

              * * A listener will only be notified about topics for * which the session has {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} and * {@link PathPermission.READ_TOPIC READ_TOPIC} permissions. * {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} determines which selectors * a listener may register; {@link PathPermission.READ_TOPIC READ_TOPIC} * determines which selected topics the client may receive notifications for. * *

              Accessing the feature

              * * This feature may be obtained from a {@link Session session} as follows: * * ``` * const notifications = session.notifications; * ``` */ export interface TopicNotifications { /** * The topic notification type enum */ TopicNotificationType: typeof TopicNotificationType; /** * Register a {@link TopicNotificationListener} to receive topic notifications. * * @param listener the listener to receive topic notifications * @returns a {@link Promise} for this operation */ addListener(listener: TopicNotificationListener): Promise; } /** * Listener for topic notifications. */ export interface TopicNotificationListener { /** * Notification for an immediate descendant of a selected topic path. This * notifies the presence or absence of a descendant topic that may * subsequently be explicitly selected. * * @param path the path of the selected immediate descendant * @param type the type of notification */ onDescendantNotification(path: string, type: TopicNotificationType): void; /** * A notification for a selected topic. * * @param path the path of the selected topic * @param specification the specification of the topic that this * notification is for * @param type the type of notification */ onTopicNotification(path: string, specification: TopicSpecification, type: TopicNotificationType): void; /** * Called when the listener is closed. The listener will be closed if the * session is closed, or if the listener is closed by the {@link * TopicNotificationRegistration} * * Once closed, no further calls will be made to the listener. */ onClose(): void; /** * Notification of a contextual error related to this listener. This is * analogous to an Error being thrown. Situations in which * `onError` is called include the session being closed before the * listener is registered, a communication timeout, or a problem with the * provided parameters. No further calls will be made to this listener. * * @param {Object} error - The error */ onError(error: any): void; } /** * The TopicNotificationRegistration represents the registration state of the * associated listener on the server. * * The TopicNotificationRegistration provides operations to control which topic * paths the listener will receive notifications for. It can also close the * listener and remove it from the server. */ export interface TopicNotificationRegistration { /** * Request to receive notifications for all topics matched by the provided * topic selector. * * This function can take any number of arguments. Each argument can be a string * or a {@link TopicSelector}. Alternatively, an array of strings and * {@link TopicSelector}s can be passed as a single argument. At least one * valid selector has to be specified. * * @param selector the selector to register * @returns a {@link Promise} for this operation * @throws an {@link IllegalArgumentError} if the selector could not be parsed * @throws a {@link NullValueError} if the selector is `null` or `undefined` */ select(selector: Array): Promise; select(...selector: Array): Promise; /** * Request to stop receiving notifications for all topics matched by the * given selector. * * This function can take any number of arguments. Each argument can be a * string or a {@link TopicSelector}. Alternatively, an array of strings and * {@link TopicSelector}s can be passed as a single argument. At least one * valid selector has to be specified. * * @param selector the selector to register * @returns a {@link Promise} for this operation */ deselect(selector: Array): Promise; deselect(...selector: Array): Promise; /** * Request that the listener is unregistered from the server. */ close(err?: any): void; } /** * @module Session.topicUpdate */ /** * Options for creating a topic update stream or for setting a value using the * topicUpdate feature. */ export interface TopicUpdateOptions { /** * an optional constraint that must be satisfied for the topic to be * updated. */ constraint?: UpdateConstraint; /** * an optional specification of the topic. If this is specified and the * topic does not exist at the `path` , one will be created using * `specification` . If a topic does exist, its specification must match * `specification` , otherwise the operation will fail with an `Error` . */ specification?: TopicSpecification; } /** * Promise of {@link TopicUpdate.applyJsonPatch applyJsonPatch}. Check {@link * JsonPatchResult.failedOperation failedOperation} to determine whether any of * the operations failed. * * @since 6.4 */ export interface JsonPatchResult { /** * If present, this contains the index of the first operation which failed. */ failedOperation?: number; } /** * * This feature provides a client session with the ability to update topics. * * Topics can be set to new values using stateless {@link TopicUpdate.set set} * operations or an {@link UpdateStream UpdateStream}. Both ensure that new * values are applied safely to appropriate topics. * * Additionally, JSON topics can be updated with a * {@link TopicUpdate.applyJsonPatch JSON Patch}. A patch is a list of * operations that modifies a JSON value, removing the need to supply a complete * new value. This is useful if the source of the updates doesn't provide * values. For one-off, small changes to large JSON values, it can be * significantly cheaper to apply a patch than to use `set` to provide the * complete value. * *

              Update streams

              * * An update stream is created for a specific topic. An * UpdateStreamBuilder can be obtained using {@link TopicUpdate.newUpdateStreamBuilder}. * The type of the topic must * match the type of values passed to the update stream. An update stream can be * used to send any number of updates. It sends a sequence of updates for a * specific topic to the server. If supported by the data type, updates will be * sent to the server as a stream of binary deltas. * * Update streams have additional ways of failing compared to stateless set * operations but when used repeatedly have lower overheads. This is because * update streams maintain a small amount of state that reduces the overhead of * operations but can become invalid for example, if the topic is deleted, or * some other session updates the topic value. * * By default, update streams use a form of optimistic locking. An update stream * can update its topic incrementally as long as nothing else updates the topic. * If the topic is updated independently (for example, by another session, or by * the current session via set or a different update stream), then the next * update performed by the update stream will result in an error. * * Applications can choose to use collaborative locking to coordinate exclusive * access to a topic. To follow this pattern acquire a {@link SessionLock * session lock}, and use it with a * {@link UpdateConstraintFactory.locked lock constraint}. The application is * responsible for designing a locking scheme which determines which lock is * required to access a particular topic, and for ensuring that all parts of the * application that update the topic follow this scheme. Lock constraints and an * application locking scheme can also ensure a sequence of set operations has * exclusive access to the topic. * *

              Removing values

              * * When a {@link TopicType.STRING string}, {@link TopicType.INT64 int64}, or * {@link TopicType.DOUBLE double} topic is set to `null`, the topic will be * updated to have no value. If a previous value was present subscribers will * receive a notification that the new value is `null`. New subscribers will not * receive a value notification. Attempting to set any other type of topic to * `null` will cause an error to be thrown. * *

              Adding topics

              * * When setting a value using either stateless operations or update streams it * is possible to add a topic if one is not present. This is done by providing a * topic specification when calling {@link TopicUpdate.set set} or when creating * the update stream. If a topic exists these methods will update the existing * topic. * *

              Time series topics

              * * All methods provided by this feature are compatible with time series topics * except for {@link TopicUpdate.applyJsonPatch}. The {@link TimeSeries} feature * can be used to update time series topics with custom metadata and provides * query capabilities. * *

              Access control

              * * To update a topic a session needs {@link PathPermission.UPDATE_TOPIC * UPDATE_TOPIC} permission for the topic path. To create a topic a session * needs {@link PathPermission.MODIFY_TOPIC MODIFY_TOPIC} permission for the * topic path. Requests that combine adding a topic and setting the value * require both permissions. * *

              Accessing the feature

              * * This feature may be obtained from a {@link Session session} as follows: * * ``` * var topicUpdate = session.topicUpdate; * ``` * * @since 6.2 */ export interface TopicUpdate { /** * Sets the topic to a specified value. * * `null` or `undefined` can only be passed to the * `value` parameter when updating * {@link TopicType.STRING STRING}, * {@link TopicType.INT64 INT64} or * {@link TopicType.DOUBLE DOUBLE} topics. * * When a topic of type {@link TopicType.STRING STRING}, * {@link TopicType.INT64 INT64} or * {@link TopicType.DOUBLE DOUBLE} is set * to `null` or `undefined` , the topic will be updated * to have no value. If a previous value was present subscribers will * receive a notification that the new value is `undefined` . New * subscribers will not receive a value notification. * * **Example:** * ``` * session.topicUpdate.set('my_topic', diffusion.datatypes.string(), 'hello'); * ``` * * @param path the path of the topic * @param dataType the type of the values * @param value the value. String, int64, and double topics accept * `null` or `undefined` , as described above. * Using `null` or `undefined` with other * topic types is an error and will throw an `Error` . * @param options optional options object * @return a Promise that resolves when a response is received * from the server. If a topic specification is provided * in the options, the Promise will resolve with a * {@link TopicCreationResult} that contains the * specification of the topic that was created. *

              * If the task fails, the Promise will resolve with an * `Error`. * * @throws an {@link IllegalArgumentError} if a topic specification was provided * and the value type does not match the topic type */ set(path: string, dataType: DataType, value: any, options?: TopicUpdateOptions): Promise; /** * Creates an {@link UpdateStream update stream} to * use for updating a specific topic. * * The type of the topic being updated must match the type derived from the * `dataType` parameter. * * Update streams send a sequence of updates for a specific topic. They can * result in more efficient use of the network as only the differences * between the current value and the updated value are transmitted. They do * not provide exclusive access to the topic. If exclusive access is * required update streams should be used with {@link SessionLock session * locks} as constraints. * * Streams are validated lazily when the first * {@link UpdateStream.set set} or * {@link UpdateStream.validate validate} operation is * completed. Once validated a stream can be invalidated, after which it * rejects future updates. * * **Example:** * ``` * const stream = session.topicUpdate.createUpdateStream('my_topic', diffusion.datatypes.string()); * stream.set('hello'); * ``` * * @param path the path of the topic * @param dataType the type of the values expected by the update stream * @param options optional options object * @return an update stream * @throws an {@link IllegalArgumentError} if the topic type is not compatible with the * `dataType` parameter * * @deprecated since 6.9, use {@link TopicUpdate.newUpdateStreamBuilder} */ createUpdateStream(path: string, dataType: DataType, options?: TopicUpdateOptions): UpdateStream; /** * Creates an update stream builder to use for creating * update streams. * * @return an update stream builder */ newUpdateStreamBuilder(): UpdateStreamBuilder; /** * Applies a JSON Patch to a JSON topic. * * The `patch` argument should be formatted according to the JSON * Patch standard (RFC 6902). * * Patches are a sequence of JSON Patch operations contained in an array. * The following patch will insert a number at a specific key and then test * that it was added: * * ``` * [{"op":"add", "path":"/price", "value" : 41}, * {"op":"test", "path":"/price", "value": 41}] * ``` * * The available operations are: * * * Add: `{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }` * * Remove: `{ "op": "remove", "path": "/a/b/c" }` * * Replace: `{ "op": "replace", "path": "/a/b/c", "value": 43 }` * * Move: `{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" }` * * Copy: `{ "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }` * * Test: `{ "op": "test", "path": "/a/b/c", "value": "foo" }` * * The test operation checks that the CBOR representation of the value of a * topic is identical to value provided in the patch after converting it to * CBOR. If the value is represented differently as CBOR, commonly due to * different key ordering, then the patch will fail with an error. E.g the * values `{"foo": "bar", "count": 43}` and `{"count": 43, "foo": "bar"}` * are unequal despite semantic equality due to the differences in a byte * for byte comparison. * * @param path the path of the topic to patch * @param patch the JSON Patch * @param constraint optional constraint that must be satisfied for the patch to * be applied * @return a {@link Promise} that resolves when a response is received from * the server. *

              * If the task fails, the Promise will reject with an error. Common reasons * for failure include: *

              *

                *
              • the patch is not a valid JSON Patch; *
              • applying the patch fails; *
              • there is no topic bound to path; *
              • the patch cannot be applied to the topic, for example if the * topic type is not {@link DataTypes.json}. *
              • updates cannot be applied to the topic because an exclusive * update source is registered for its path; *
              • the topic is managed by a component (such as fan-out) that * prohibits updates from the caller; *
              • the cluster was repartitioning; *
              • the calling session does not have the {@link * PathPermission.UPDATE_TOPIC UPDATE_TOPIC} permission for `path`; *
              • the session is closed. *
              * * @see * JavaScript Object Notation (JSON) Patch * * @since 6.4 */ applyJsonPatch(path: string, patch: string | Array<{ [key: string]: any; }>, constraint?: UpdateConstraint): Promise; } /** * Description of a topic view that has been created. * * @since 6.3 */ export interface TopicView { /** * The name of the topic view. * If the name is empty, the operation will fail. */ readonly name: string; /** * The specification of the topic view. * * See the view * specification for the description of the DSL for more * information. */ readonly specification: string; /** * The roles used by the view when evaluating permissions. */ readonly roles: Set; } /** *

              Topic view feature.

              * * This feature allows a client session to manage topic views. * * A topic view maps one part of a server's topic tree to another. It * dynamically creates a set of reference topics from a set of * source topics, based on a declarative topic view * specification. The capabilities of topic views range from simple * mirroring of topics within the topic tree to advanced capabilities including * publication of partial values, expanding a single topic value into many * topics, changing topic values, inserting values from other topics, throttling * the rate of publication, and applying a fixed delay to the publication. * * A topic view can also map topics from another server (in a different * cluster). This capability is referred to as 'remote topic views'. The view * can specify the server that the source topics are hosted on in terms * of a remote server (see {@link RemoteServers} for details of how to * create and maintain remote servers). * * Each reference topic has a single source topic and has the same topic type as * its source topic. Reference topics are read-only (they cannot be updated), * nor can they be created or removed directly. Otherwise, they behave just like * standard topics. A client session can subscribe to a reference topic, and can * fetch the reference topic's current value if it has one. * * The source topics of a topic view are defined by a topic selector. One or * more reference topics are created for each source topic, according to the * topic view. If a source topic is removed, reference topics that are derived * from it will automatically be removed. If a topic is added that matches the * source topic selector of a topic view, corresponding reference topics will be * created. Removing a topic view will remove all of its reference topics. * *

              Topic view specifications

              * * Topic views are specified using a Domain Specific Language (DSL) which * provides many powerful features for manipulating topic data. For a full and * detailed description of the topic views DSL see the user * manual. * * The following is a simple topic view specification that mirrors all topics * below the path a to reference topics below the path * b. * *
               * map ?a// to b/<path(1)>
               * 
              * * A topic view with this specification will map a source topic at the path * a/x/y/z to a reference topic at the path b/x/y/z. * The specification is simple, so the reference topic will exactly mirror the * source topic. Other topic views features allow a single topic to be mapped to * many reference topics and have the data transformed in the process. * *

              Topic view persistence and replication

              * * Reference topics are neither replicated nor persisted. They are created and * removed based on their source topics. However, topic views are replicated and * persisted. A server that restarts will restore topic views during recovery. * Each topic view will then create reference topics based on the source topics * that have been recovered. * * The server records all changes to topic views in a persistent store. Topic * views are restored if the server is started. * * If a server belongs to a cluster, topic views (and remote servers) will be * replicated to each server in the cluster. Topic views are evaluated locally * within a server. Replicated topic views that select non-replicated source * topics can create different reference topics on each server in the cluster. * When remote topic views are in use, each server in the cluster will make a * connection to the specified remote server and will separately manage their * remote topic views. * * A view with a delay clause uses temporary storage to record delayed events. * If there is a high volume of updates, temporary per-server disk files will be * used to save server memory. The storage is per-server, and does not survive * server restart. When a server is started, no data will be published by a view * with a delay clause until the delay time has expired. * *

              Access control

              * * The following access control restrictions are applied: * *
                *
              • To {@link listTopicViews list the topic views}, a session needs the * {@link GlobalPermission.READ_TOPIC_VIEWS READ_TOPIC_VIEWS} global permission. * *
              • To {@link createTopicView create, replace}, or * {@link removeTopicView remove} a topic view, a session needs the * {@link GlobalPermission.MODIFY_TOPIC_VIEWS MODIFY_TOPIC_VIEWS} global * permission and {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} permission * for the path prefix of the source topic selector. * *
              • Each topic view records the principal and security roles of the session * that created it as the topic view security context. When a topic * view is evaluated, this security context is used to constrain the creation of * reference topics. A reference topic will only be created if the security * context has {@link PathPermission.READ_TOPIC READ_TOPIC} permission for the * source topic path, and {@link PathPermission.MODIFY_TOPIC MODIFY_TOPIC} * permission for the reference topic path. The topic view security context is * copied from the creating session at the time the topic view is created or * replaced, and is persisted with the topic view. The topic view security * context is not updated if the roles associated with the session are changed. * *
              * *

              Accessing the feature

              * * This feature may be obtained from a {@link Session session} as follows: * *
               * const topicViews = session.topicViews;
               * 
              * * @since 6.3 * */ export interface TopicViews { /** * Create a new named topic view. * * If a view with the same name already exists the new view will update * the existing view. * * @param name the name of the view * @param specification the specification of the view using the DSL * @return a Promise that completes when a response is received * from the server, returning the topic view created by the * operation. *

              * If the task fails, the Promise will resolve with an error. Common reasons * for failure, include: *

                *
              • the `specification` is invalid; *
              • the cluster was repartitioning; *
              • the calling session does not have MODIFY_TOPIC_VIEW * permission or appropriate path prefix permissions; *
              • the session is closed. *
              • {@link IllegalArgumentError} if the name is empty *
              • {@link NullValueError} – if any of the arguments are `null` or `undefined` *
              */ createTopicView(name: string, specification: string): Promise; /** * List all the topic views that have been created. * * @return a Promise that resolves when a response is received from the * server, returning a list of views sorted by their creation * order. *

              * If the task fails, the Promise will resolve with an Error. Common * reasons for failure include: *

                *
              • the cluster was repartitioning; *
              • the calling session does not have READ_TOPIC_VIEW permission * or appropriate path prefix permissions; *
              • the session is closed. *
              */ listTopicViews(): Promise; /** * Get a named Topic View. * * If the named view does not exist the Promise will resolve with null result. * * @param name the name of the view * @return a Promise that resolves when a response is received from the server, * returning a named view if it exists *

              * If the task fails, the Promise will resolve with an Error. Common * reasons for failure include: *

                *
              • the operation failed due to a transient cluster error; *
              • the calling session does not have READ_TOPIC_VIEW permission or * appropriate path prefix permissions; *
              • the session is closed. *
              • {@link NullValueError} – if the name is null` or `undefined` *
              */ getTopicView(name: string): Promise; /** * Remove a named topic view if it exists. * * If the named view does not exist the completable future will complete * successfully. * * @param name the name of the view * @return a Promise that resolves when a response is received from the * server. *

              * If the task fails, the Promise will resolve with an Error. Common * reasons for failure include: *

                *
              • the cluster was repartitioning; *
              • the calling session does not have MODIFY_TOPIC_VIEW * permission or appropriate path prefix permissions; *
              • the session is closed. *
              • {@link NullValueError} – if the name is null` or `undefined` *
              */ removeTopicView(name: string): Promise; } /** * @module Session */ /** * This feature allows a client session to subscribe to topics to receive * streamed topic updates, fetch the state of topics and/or update topics with * new values. * * Specifically, the feature provides the ability to: *
                *
              • Subscribe to topics and specify streams to receive updates; *
              • Fetch the current state of topics (even if not subscribed); *
              • By extending the {@link TopicUpdate topic update feature}, update topics * with new values; *
              • By extending the {@link TopicViews topic views feature}, manage topic * views. *
              *

              Subscription and unsubscription

              * * A session can issue requests to subscribe to topics at any time, even if the * topics do not exist at the server. Each subscription request provides a * {@link TopicSelector topic selector} that is evaluated by the server to * select matching topics. The session will be subscribed to any topics that * match the selector unless they are already subscribed, or the session has * insufficient permission. The subscription request is also retained at the * server and the session will be automatically subscribed to newly created * topics that match the selector (unless a subsequent unsubscription cancels * the request). * * Sessions receive notifications from topics that they are subscribed to via * subscription streams (see below). When a session is subscribed to a * topic, all matching streams will first receive a subscription notification * that provides details about the topic. If the server has a value for the * topic, the value will be delivered to the streams before any other * notifications. * * A session can unsubscribe from topics at any time. This is also specified * using a topic selector. On unsubscription, matching streams are notified via * the `on('unsubscribe')` notification. This notification will give the * reason for unsubscription (for example, by request of the session, request of * the server, or topic removal). * * Subscriptions and unsubscriptions can occur for reasons other than requests * from the session. A session can be subscribed to or unsubscribed from a topic * by another session using the {@link ClientControl} feature. The removal * of a topic also automatically causes unsubscription for subscribed sessions. * * Subscription requests are subject to authorisation checks. The session must * have {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} permission for the * topic selector used to subscribe. Matching topics will be further filtered to * those for which the session has {@link PathPermission.READ_TOPIC READ_TOPIC} * permission. * *

              Topic selection scopes

              * * Topic selection scopes allow an application with multiple components to use a * single Diffusion session. An application component can use a topic selection * scope to manage a set of selectors that is unaffected by unsubscriptions * performed by other application components. The session will be subscribed to * all topics with paths matching a selector in any scope. The unsubscribe * operation removes a selector from specific scopes. * * A scope may be specified to a {@link Topics.select select} or * {@link Topics.unsubscribe unsubscribe} method, indicating that the * selection only applies to that scope. The server manages scopes to ensure * that unsubscriptions applied to one scope do not affect another. * * Scope names are case sensitive. A scope name may not begin with the character * $ as this is reserved for internal use. * * Unsubscription using a wildcard selector that indicates all topics (such as * "?.*//") effectively removes the scope. * * An application can request unsubscription from all scopes using * {@link Topics.unsubscribeAllScopes unsubscribeAllScopes}. *

              * The {@link Topics.DEFAULT_SELECTION_SCOPE default selection scope} is used for all * methods that do not explicitly specify a scope. * *

              Subscription streams

              * * A session can listen to subscription events and updates for a selection of * topics by adding one or more streams. A stream is registered using a topic * selector which specifies the topics that the stream applies to. When an * update is received for a topic then it will be routed to every stream that * matches both the topic selector and the stream's value type. If more than one * stream matches, all will receive the update; the order in which they are * notified is not defined. * * A stream can be added several times for different selectors. The mapping of * topic selectors to streams is maintained locally in the client process. * * It is also possible to add one or more fallback streams which will * receive updates that do not match any stream registered with a selector. This * is useful for default processing or simply to catch unprocessed updates. A * fallback stream can be added using {@link Topics.addFallbackStream * addFallbackStream}. Zero, one, or more fallback streams may be assigned. If * no fallback stream is specified, any updates that are not routed to any other * stream will simply be discarded. * * If the session is already subscribed to a topic when a matching stream is * added, the stream will immediately receive a subscription notification. For * most topic types, the latest value is locally cached and will be provided to * the stream following the subscription notification. * * A stream will receive a {@link Stream.on close} callback when unregistered * and an {@link Stream.on error(SESSION_CLOSED)} callback if the session is * closed. * *

              Value streams

              * * A {@link ValueStream ValueStream} receives values for matching topics as and * when updates are received from the server. Delta updates received from the * server are automatically applied to locally cached values so that the stream * always receives full values for each update. * * Value streams are typed to a specified value class and only updates for * compatible topics will be routed to the stream. The following table shows how * the value class maps to compatible topic types that will be routed to the * stream: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
              Value ClassCompatible Topic Types
              {@link JSONDataType JSON}{@link TopicType.JSON JSON} {@link TopicType.STRING STRING} * {@link TopicType.INT64 INT64} {@link TopicType.DOUBLE DOUBLE} *
              {@link StringDataType String}{@link TopicType.STRING STRING}
              {@link Int64DataType Int64}{@link TopicType.INT64 INT64}
              {@link DoubleDataType Double}{@link TopicType.DOUBLE DOUBLE}
              {@link BinaryDataType Binary}{@link TopicType.BINARY BINARY}
              {@link Bytes}{@link TopicType.JSON JSON} {@link TopicType.STRING STRING} * {@link TopicType.INT64 INT64} {@link TopicType.DOUBLE DOUBLE} * {@link TopicType.BINARY BINARY} {@link TopicType.RECORD_V2 RECORD_V2}
              {@link RecordV2}{@link TopicType.RECORD_V2 RECORD_V2}
              * * Value stream implementations can be added using * {@link Topics.addStream addStream}. A value stream can be also added to * received updates from {@link TimeSeries time series topics}. The following * table shows how the value class specified when adding the stream maps to the * event value class of time series topics that will be routed to the stream: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
              Event Value ClassTime Series Event Value Class
              {@link JSONDataType JSON}{@link TopicType.JSON JSON} {@link TopicType.STRING STRING} * {@link TopicType.INT64 INT64} {@link TopicType.DOUBLE DOUBLE} *
              {@link StringDataType String}{@link TopicType.STRING STRING}
              {@link Int64DataType Int64}{@link TopicType.INT64 INT64}
              {@link DoubleDataType Double}{@link TopicType.DOUBLE DOUBLE}
              {@link BinaryDataType Binary}{@link TopicType.BINARY BINARY}
              {@link Bytes}{@link TopicType.JSON JSON} {@link TopicType.STRING STRING} * {@link TopicType.INT64 INT64} {@link TopicType.DOUBLE DOUBLE} * {@link TopicType.BINARY BINARY} {@link TopicType.RECORD_V2 RECORD_V2}
              {@link RecordV2}{@link TopicType.RECORD_V2 RECORD_V2}
              * *

              Fetch

              * * A session can issue a request to fetch details of a topic or topics (subject * to authorization) at any time. The topics required are specified using a * topic selector. * * The results of a fetch will return the topic path and type of each selected * topic. The results may also optionally return the topic values and/or * properties. * * A new request can be created using {@link Topics.fetchRequest} and modified to * specify additional requirements of the fetch operation. The request is issued * to the server using the {@link FetchRequest.fetch fetch} * method on the request. This will return the results via a Promise. * * *

              Access control

              * * A session must have {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} * permission for the topic selector used to * {@link Topics.select subscribe} or {@link Topics.fetchRequest fetch}. * The topics that result from a subscription or fetch request are further * filtered using the {@link PathPermission.READ_TOPIC READ_TOPIC} permission. * * No access control restrictions are applied to * {@link Topics.unsubscribe unsubscription}. * *

              Accessing the feature

              * * This feature is directly available on a {@link Session session} object: * * @example *
               * session.select('foo/bar);
               * 
              * * @author DiffusionData Limited * @since 5.0 */ export interface Topics { /** * The default topic selection scope. * * This is used by {@link Topics.select select} and * {@link Topics.unsubscribe unsubscribe} methods that do not explicitly * specify a topic selection scope. * * @see Topics Topic Selection Scopes */ readonly DEFAULT_SELECTION_SCOPE: string; /** * Unsubscribe the client from a given topic selector with the {@link * Topics.DEFAULT_SELECTION_SCOPE default selection scope}. * * This is equivalent to calling {@link Topics.unsubscribeWithScope} with * the {@link Topics.DEFAULT_SELECTION_SCOPE default selection scope}. * * **Example:** * ``` * // Unsubscribe from a single topic * session.unsubscribe('foo'); * ``` * * **Example:** * ``` * // Unsubscribe from multiple topics * session.unsubscribe('?foo/.*'); * ``` * * @param selector the topic selector to unsubscribe from. * @returns a Promise for this operation * @throws an {@link IllegalArgumentError} if the selector could not be parsed */ unsubscribe(selector: Array): Promise; unsubscribe(...selector: Array): Promise; /** * Unsubscribe the client from a given topic selector. * * No more updates will be received from the server for any topics matched * by the selector. If no topics exist that match the selector, the server * will do nothing. * * Each topic that this session is unsubscribed from will cause an * `unsubscribe` event. Any {@link ValueStream} objects produced from {@link * Session.addStream} will remain open, and will continue to emit updates * for topics that the session has not been unsubscribed from. * * The returned result will resolve normally when the session has been * unsubscribed. It will resolve with an error if the session is unable to * unsubscribe, for instance due to security constraints. * * This function can take any number of arguments. Each argument can be a * string or a {@link TopicSelector}. Alternatively, an array of strings and * {@link TopicSelector}s can be passed as a single argument. At least one * valid selector has to be specified. * * **Example:** * ``` * // Unsubscribe from a single topic * session.unsubscribe('foo'); * ``` * * **Example:** * ``` * // Unsubscribe from multiple topics * session.unsubscribe('?foo/.*'); * ``` * * @param selector the topic selector to unsubscribe from. * @param scope (optional) specifies the scope of the selection. See {@link Topics * Topic Selection Scopes}. Defaults to {@link * Topics.DEFAULT_SELECTION_SCOPE DEFAULT_SELECTION_SCOPE}. * @returns a Promise for this operation * @throws an {@link IllegalArgumentError} if the selector could not be parsed */ unsubscribeWithScope(selector: string | TopicSelector | Array, scope?: string): Promise; /** * Unsubscribe topics from all topic selection scopes. * * This can be used at any time whilst connected to reduce the set of topics * to which the session is subscribed or negate earlier subscription * requests and will apply to all scopes in use. * * @param topics the topics to unsubscribe from * * @throws IllegalArgumentException if topics is an invalid topic selector * expression * * @param selector the topic selector to unsubscribe from. * @param scope (optional) specifies the scope of the selection. See {@link Topics * Topic Selection Scopes}. Defaults to {@link * Topics.DEFAULT_SELECTION_SCOPE DEFAULT_SELECTION_SCOPE}. * @returns a Promise for this operation * @throws an {@link IllegalArgumentError} if the selector could not be parsed * * @since 6.12 */ unsubscribeAllScopes(selector: string | TopicSelector | Array): Promise; /** * Creates an unconfigured fetch request. * * The returned request can be invoked with * {@link FetchRequest.fetch fetch}. The server will evaluate * the query and return a fetch result that provides the paths and types of * the matching topics which the session has permission to read. * * You will usually want to restrict the query to a subset of the topic * tree, and to retrieve the topic values and/or properties. This is * achieved by applying one or more of the fluent builder methods provided * by {@link FetchRequest} to produce more refined requests. * * **Example:** * ``` * // Create and send a fetch request. Then pass the results to a resultHandler * session.fetchRequest() * .withValues(diffusion.datatypes.StringDataType) * .fetch("*A/B//") * .then(resultHandler); * ``` * * @see diffusion.topics.FetchRequest * * @returns a new unconfigured fetch request * * @since 6.2 */ fetchRequest(): FetchRequest; /** * Request subscription to topics. * * The session will become subscribed to each existing topic matching the * selector unless the session is already subscribed to the topic, or the * session does not have {@link PathPermission.READ_TOPIC READ_TOPIC} * permission for the topic path. For each topic to which the session * becomes subscribed, a subscription notification and initial value (if * any) will be delivered to registered value streams before the returned * CompletableFuture completes. * * The subscription request is also retained at the server and the session * will be automatically subscribed to newly created topics that match the * selector (unless a subsequent unsubscription cancels the request). * * @param topics specifies the topics to request subscription to * * @param scope (optional) specifies the scope of the selection. See {@link Topics * Topic Selection Scopes}. If not specified, the {@link Topics.DEFAULT_SELECTION_SCOPE * default selection scope} will be used. * * @returns a result that completes when this operation succeeds * @throws an {@link IllegalArgumentError} if the selector could not be parsed * @since 6.12 */ selectWithScope(selector: string | TopicSelector | Array, scope?: string): Promise; /** * Subscribe the session to a topic selector with the the {@link * Topics.DEFAULT_SELECTION_SCOPE default selection scope} in order to receive updates and * subscription events. * * Subscription causes the server to establish a subscription for this * session to any topic that matches the specified selector, including topics * that are added after the initial call to {@link Session.select}. * * If the provided selector string does not begin with one of the prefixes * defined by {@link TopicSelectors}, it will be treated as a direct topic * path. * * This function can take any number of arguments. Each argument can be a string * or a {@link TopicSelector}. Alternatively, an array of strings and * {@link TopicSelector}s can be passed as a single argument. At least one * valid selector has to be specified. * * The session will become subscribed to each existing topic * matching the selector unless the session is already subscribed * to the topic, or the session does not have {@link PathPermission.READ_TOPIC READ_TOPIC} * permission for the topic path. For each topic to which the * session becomes subscribed, a subscription notification and * initial value (if any) will be delivered to registered value * streams before the returned promise completes. * * The subscription request is also retained at the server and the * session will be automatically subscribed to newly created * topics that match the selector (unless a subsequent * unsubscription cancels the request). * * **Example:** * ``` * // Subscribe to a topic foo * session.select("foo").then(function() { * // Successfully subscribed * }, function(err) { * // There was an error with subscribing to topic "foo" * }); * ``` * * @param selector the topic selector to subscribe to. * @returns a result that completes when this operation succeeds * @throws an {@link IllegalArgumentError} if the selector could not be parsed */ select(selector: Array): Promise; select(...selector: Array): Promise; /** * Create a {@link ValueStream} to receive updates from topics that match * the provided topic selector. * * This method will not cause the server to send any topic updates unless * already subscribed. This allows the registration of listeners prior to * subscribing via {@link Session.select}, or to add/remove listeners * independently of subscriptions on the server. * * The values as specific types, use the Streams will only receive values * from topics for which the specified {@link DataTypes Data Type} * is compatible. Passing {@link AnyDataType} as second argument will create * a polymorphic value stream that receives all data types. It is then up to * the value handler to interpret the incoming data. * * The first argument of this function can be a string, a {@link * TopicSelector}, or a non-empty array of strings and {@link TopicSelector}s. * * **Example:** * ``` * // Produce a value stream for receiving JSON values. * var json = diffusion.datatypes.json(); * * session.addStream(topic, json).on('value', function(topic, specification, newValue, oldValue) { * console.log('New value ', newValue.get()); * }); * ``` * * @param selector the topic selector to receive updates for * @param datatype the data type to produce a stream for. * @returns a new {@link ValueStream} for the provided data type * @throws an {@link IllegalArgumentError} if dataType is not a valid data type * or if the selector could not be parsed */ addStream(selector: string | TopicSelector | Array, dataType: DataType | AnyDataType): ValueStream; /** * This adds a value stream for a given {@link DataTypes Data * Type} without a selector which will be a fallback stream to receive all * events that do not have a stream registered. * * **Example:** * ``` * // Produce a fallback value stream for receiving JSON values. * var json = diffusion.datatypes.json(); * * session.addFallbackStream(json).on('value', function(topic, specification, newValue, oldValue) { * console.log('New value ', newValue.get()); * }); * ``` * * @param datatype the data type to produce a stream for. * @returns a fallback stream * @throws an {@link IllegalArgumentError} if dataType is not a valid data type */ addFallbackStream(dataType: DataType): ValueStream; } /** * @module diffusion.selectors */ /** * A `TopicSelector` is a value that identifies one or more topics. * * Depending on where it is used, a selector may be evaluated by either the * server or the client library. For example, the server evaluates the selector * used to subscribe to a topic. In contrast, the selector used to register a * topic handler is evaluated by the client. Applications do not normally need * to evaluate selectors, but may do so using {@link TopicSelector.selects selects}. *

              * A client may receive a selector providing the context for certain operations. * For example, to allow it to veto subscriptions. Limited ability to query the * selector's {@link TopicSelector.type} and associated {@link TopicSelector.expression * expression} is provided. * * Selectors may be created using {@link TopicSelectors}. */ export interface TopicSelector { /** * The type of this selector */ readonly type: Type; /** * The maximum topic path prefix from this selector */ readonly prefix: string; /** * The original expression of this selector */ readonly expression: string; /** * Evaluate this selector against a topic path * * @param topicPath the topic path * @returns if this selector selects the topic path */ selects(topicPath: string): boolean; /** * Convert the topic selector to a string * * @return the original expression of the selector */ toString(): string; } /** * A Topic Selector Prefix */ export declare enum Prefix { /** Prefix used for {@link Type.PATH} expressions. */ PATH = ">", /** Prefix used for {@link Type.SPLIT_PATH_PATTERN} expressions. */ SPLIT_PATH_PATTERN = "?", /** Prefix used for {@link Type.FULL_PATH_PATTERN} expressions. */ FULL_PATH_PATTERN = "*", /** Prefix used for {@link Type.SELECTOR_SET} expressions. */ SELECTOR_SET = "#" } /** * Topic Selector type. */ export declare enum Type { /** A selector that selects a single topic. */ PATH = ">", /** A selector that is a split-path pattern. */ SPLIT_PATH_PATTERN = "?", /** A selector that is a full-path pattern. */ FULL_PATH_PATTERN = "*", /** A composite of multiple selectors. */ SELECTOR_SET = "#" } /** * @module diffusion.selectors */ /** * Create {@link TopicSelector} instances for use with other API methods. * * Selectors are evaluated against topic paths. A topic path is a '/' * separated string of parts, which map to the topic tree. Each part is * formed of one or more UTF characters, except '/'. Topic paths are absolute, * and evaluated from the root of the topic tree. * * **Example:** * ``` * // Create a topic selector * var selector = diffusion.selectors.parse('?foo/bar/.*'); * ``` */ export declare class TopicSelectors { /** * The Prefix enum */ readonly Prefix: typeof Prefix; /** * The Type enum */ readonly Type: typeof Type; /** * Parse an expression to create a selector. * * The following types of expression are supported. The type is determined * by the first character of the expression. * *

              *
              Path *
              Path expressions begin with the character >. The remainder of * the expression must be a valid topic path. A topic path is a '/' * separated string of parts. Each part is formed of one or more UTF * characters, except '/'. *

              * A {@link Type.PATH PATH} selector is returned that only * selects the topic with the given path. *

              *

              * The initial > can be omitted if the path begins with a character * other than one of #, ?, >, * *, $, %, &, or * <. This abbreviated syntax allows most * topic paths to be used directly as selector expressions which appears * more natural. Abbreviated path expressions are converted to standard path * expressions by prepending the > character. Thus * a/b is interpreted as >a/b. *

              * Diffusion.topicSelectors().parse("a/b").getExpression() will * return ">a/b". * *

              Split-path pattern *
              Split-path pattern expressions begin with the character ?. * The remainder of the expression is split into a list of regular * expressions using the / character as a separator. * *

              * A {@link Type.SPLIT_PATH_PATTERN SPLIT_PATH_PATTERN} * selector is returned that selects topics for which each regular * expression matches each part of the topic path at the corresponding * level. *

              * *
              Full-path pattern *
              Full-path pattern expressions begin with the character *. * The remainder of the pattern is a regular expression. * *

              * A {@link Type.FULL_PATH_PATTERN FULL_PATH_PATTERN} selector * is returned that selects topics for which the regular expression matches * the complete topic path. *

              * *

              * Full-path patterns provide a lot of expressive power but should be used * sparingly since the server can evaluate split-path patterns more * efficiently. * *

              * Selector sets are the preferred way to combine expressions. * anyOf("a", "b") is equivalent to the full-path expression " * * /a|/b", but can be evaluated more efficiently by the * server. * *

              Selector set *
              Selector set expressions begin with the character #. The * remainder of the expression is a list of contained selectors, formatted * as described below. * * A {@link Type.SELECTOR_SET SELECTOR_SET} selector is * returned that selects topics that match any of the contained selectors. * * The contained selectors are formatted as follows. First, any selector sets * are expanded to produce a full list of non-selector set expressions. Then * the selector expressions are concatenated, separated by the separator * ////. This separator has been chosen as it is not valid in a * path, and is not a useful sequence in a pattern. *
              * *

              Descendant pattern qualifiers

              * * Split-path and full-path pattern expressions can be further modified by * appending / or //. These control the behavior of the * selector with respect to the descendants of the topics that match the * pattern. * *
                * *
              • If the expression does not end with / or //, it * selects only the topics that match the pattern.
              • * *
              • If the expression ends with /, it selects only the * descendants of the matching topics, excluding the matching topics.
              • * *
              • If the expression ends with //, it selects the matching * topics and all of their descendants.
              • *
              * *

              Regular expressions

              * *

              * Any Java-style regular expression can be used in * split-path and full-path patterns, with the following restrictions: * *

                *
              • A regular expression may not be empty. *
              • A regular expression used in split-path patterns may not contain the * path separator /. *
              • A regular expression used in full-path patterns may not contain the * selector set separator //// . *
              * *

              * Regular expressions that break any of these restrictions would never * match a topic path, so they make no practical difference. *

              * * *

              Examples

              * *

              Path expressions

              * * Path | Matches `alpha/beta`? | Matches `alpha/beta/gamma`? * ------------- | ---------------------- | --------------------------- * `>alpha/beta` | yes | no * `alpha/beta` | yes | no * `>alpha/beta/gamma` | no | yes * `alpha/beta/gamma` | no | yes * `>beta` | no | no * `beta` | no | no * `>.*``/.*` | no | no * `>/alpha/beta/` | yes | no * `/alpha/beta/` | yes | no * *

              Split-path pattern expressions

              * * Path | Matches `alpha/beta`? | Matches `alpha/beta/gamma`? * ------------- | ---------------------- | --------------------------- * `?alpha/beta` | yes | no * `?alpha/beta/gamma` | no | yes * `?beta` | no | no * `?.*` | no | no * `?.*``/.*` | yes | no * `?alpha/beta/` | no | yes * `?alpha/beta//` | yes | yes * `?alpha/.*``//` | yes | yes * *

              Full-path pattern expressions

              * * Path | Matches `alpha/beta`? | Matches `alpha/beta/gamma`? * ------------- | ---------------------- | --------------------------- * `*alpha/beta` | yes | no * `*alpha/beta/gamma` | no | yes * `*beta` | no | no * `*.*beta` | yes | no * `*.*` | yes | yes * `*alpha/beta/` | no | yes * `*alpha/beta//` | yes | yes * * **Example:** * ``` * // Simple selector * var selector = diffusion.selectors.parse(">a/b"); * ``` * * **Example:** * ``` * // Creating a selector set * var selectorSet = diffusion.selectors.parse(">a", ">b"); * ``` * * @param expression the pattern expression(s). At least one * valid selector has to be specified. * @param args additional pattern expressions * @return the topic selector. If multiple expressions are provided, * this will return a `SELECTOR_SET` that will match if * any of the * provided `selectors` match. * @throws an {@link IllegalArgumentError} if the expression could not be parsed */ parse(expression: string | TopicSelector | Array, ...args: Array): TopicSelector; } /** * Provide access to * {@link UpdateConstraint UpdateConstraint}, * {@link UpdateConstraintFactory UpdateConstraintFactory}, * {@link PartialJSON PartialJSON}, * {@link TopicCreationResult TopicCreationResult}, and * {@link UpdateStream UpdateStream}. * * @module diffusion.topicUpdate */ /** * Promise indicating whether the operation caused a topic to be created or if * it already existed. * * @since 6.2 */ export declare enum TopicCreationResult { /** * A new topic was created. */ CREATED = 1, /** * A topic with the same specification already exists. */ EXISTS = 2 } export interface TopicUpdateNamespace { TopicCreationResult: typeof TopicCreationResult; UpdateConstraintOperator: typeof UpdateConstraintOperator; } export declare const TopicUpdateNamespace: TopicUpdateNamespace; /** * @module diffusion.topicUpdate */ /** * A constraint to be applied to an update operation or the creation of an * update stream. * * Constraints describe a condition that must be satisfied for an operation to * succeed. Constraints can be applied to the setting of a value or creation * of an update stream. Constraints are only evaluated on the server. * * The constraints are evaluated using the: * * * active session locks * * existence of the topic * * current value of the topic * * The value of a topic can be described in several ways. The value can be * described as an exact value, a partial value or an unset value. * * Constraints can be composed with one another. It is only possible to * construct logical ANDs of constraints. Constraints can only be composed if * the resulting constraint is satisfiable. Multiple session locks can be held * but a topic can only have a single value. Constraints specifying multiple * topic values cannot be constructed. * * Constraints can be created using a * {@link UpdateConstraintFactory}, an * instance of which can be obtained using * {@link updateConstraints}. * For example: * * ``` * const factory = diffusion.updateConstraints(); * const constraint = factory.locked(lock).and(factory.value(UpdateConstraintOperator.EQ, expectedValue)); * ``` * * @since 6.2 */ export interface UpdateConstraint { /** * Returns a composed constraint that represents a logical AND of this * constraint and another. * * @param other a constraint that will be logically-ANDed with this constraint * @return a composed constraint that represents a logical AND of this * constraint and the `other` constraint * * @throws an {@link IllegalArgumentError} if the composed constraint would be * unsatisfiable */ and(other: UpdateConstraint): UpdateConstraint; /** * Returns a composed constraint that represents a logical OR of this * constraint and another. * * @param other a constraint that will be logically-ORed with this constraint * @return a composed constraint that represents a logical OR of this * constraint and the `other` constraint * * @throws an {@link IllegalArgumentError} if the composed constraint would be * unsatisfiable */ or(other: UpdateConstraint): UpdateConstraint; } /** * An operator used in a constraint comparison. * * Accessible through `diffusion.topicUpdate.UpdateConstraintOperator` * * @since 6.10 */ export declare enum UpdateConstraintOperator { /** * Strict binary equality. * * This operator requires that the binary topic value is exactly * equivalent to the value supplied for comparison. */ IS = 1, /** * Lenient equals. * * This operator requires that the topic value is logically equal to the * supplied value. * * If the supplied value is a string the string representation of the * specified topic value is compared for string equality. * * If the supplied value is a number ({@link DataTypes.int64 Int64} or {@link DataTypes.double Double}) * the corresponding topic value may be a number or a string containing * a parseable number and will be compared for numeric equality. * * If the supplied value is null the condition will be satisfied if the * value at a specified pointer is JSON null. */ EQ = 2, /** * Lenient not equals. * * This operator requires that the topic value is logically not equal to * the supplied value. * * If the supplied value is a string the string representation of the * specified topic value is compared for string equality. * * If the supplied value is a number ({@link DataTypes.int64 Int64} or {@link DataTypes.double Double}) * the corresponding topic value may be a number or a string containing * a parseable number and will be compared for numeric equality. * * If the supplied value is null the condition will be satisfied if the * value at a specified pointer not JSON null. */ NE = 3, /** * Lenient greater than. * * This operator requires that the topic value is greater than the * supplied value. * * The supplied value must be a number ({@link DataTypes.int64 Int64} or {@link DataTypes.double Double}). * The corresponding topic value may be a number or a string containing * a parseable number and the condition will be satisfied if the topic * value is greater than the supplied value. */ GT = 4, /** * Lenient greater than or equals. * * This operator requires that the topic value is greater than or equal * to the supplied value. * * The supplied value must be a number ({@link DataTypes.int64 Int64} or {@link DataTypes.double Double}). * The corresponding topic value may be a number or a string containing * a parseable number and the condition will be satisfied if the topic * value is greater than or equal to the supplied value. */ GE = 5, /** * Lenient less than. * * This operator requires that the topic value is less than the supplied * value. * * The supplied value must be a number ({@link DataTypes.int64 Int64} or {@link DataTypes.double Double}). * The corresponding topic value may be a number or a string containing * a parseable number and the condition will be satisfied if the topic * value is less than the supplied value. */ LT = 6, /** * Lenient less than or equals. * * This operator requires that the topic value is less than or equal to * the supplied value. * * The supplied value must be a number ({@link DataTypes.int64 Int64} or {@link DataTypes.double Double}). * The corresponding topic value may be a number or a string containing * a parseable number and the condition will be satisfied if the topic * value is less than or equal to the supplied value. */ LE = 7 } /** * A constraint requiring the current value of the * {@link TopicType.JSON JSON} topic to match the partially described value. * * The code: * * ``` * const factory = diffusion.updateConstraints(); * const constraint = factory.jsonValue().with('/id', idValue).without('/cancellation'); * ``` * * creates a constraint for a JSON object with a specific ID value and no * value for a 'cancellation' property. * * Missing keys are matched differently to keys that are present with null values. * * @since 6.2 */ export interface PartialJSON extends UpdateConstraint { /** * Require a value at a specific position in the JSON object. * * This is equivalent to calling {@link PartialJSON.with with(String, Operator, Object)} * with an operator of {@link UpdateConstraintOperator.IS IS}. * * @deprecated since 6.10 * * Rather use the {@link PartialJSON.with with(String, Operator, Object)} * method with the {@link UpdateConstraintOperator.IS IS} operator. * * @param pointer the pointer expression * @param value the value * @param dataType the optional type of the value * @return a new constraint * @throws an {@link IllegalArgumentError} if pointer is an invalid JSON Pointer expression * or value cannot be serialised * @throws a {@link NullValueError} if any of the required arguments are null */ with(pointer: string, value: any, dataType?: DataType): PartialJSON; /** * Compares a location within the JSON topic value to a specified value. * * If there is no value found at the specified pointer position, the * constraint will be unsatisfied. * * If a {@link DataTypes.string String} value is supplied and the operator is * {@link UpdateConstraintOperator.EQ EQ} or {@link UpdateConstraintOperator.NE NE}, the string * representation of the topic value at the given pointer will be * compared to the supplied value. If the value at the pointer position * is not a string or number the constraint will be unsatisfied. Other * operators (other than {@link UpdateConstraintOperator.IS IS}) are not permitted with * String values. * * If a number value ({@link DataTypes.int64 Int64} or {@link DataTypes.double Double}) * is supplied the value will be compared with the number value at the * topic location. This will work with JSON string or number values * only. JSON strings can only be compared if they contain a value that * can be parsed as a number. If a string value at the location cannot * be parsed as a number, the constraint will be unsatisfied. Any of the * operators (other than {@link UpdateConstraintOperator.IS IS}) can be used with such * number comparisons. Decimal numbers can be compared with integral * numbers so {@code 1} is equal to {@code 1.0}, {@code "1"}, or * {@code "1.0"}. * * If a {@code null} value is supplied and the operator is * {@link UpdateConstraintOperator.EQ EQ} or {@link UpdateConstraintOperator.NE NE}, the topic value at * the given pointer will be compared to JSON null. Other operators * (other than {@link UpdateConstraintOperator.IS IS}) are not permitted with a * {@code null} value. * * If a `boolean` value is supplied and the operator is * {@link UpdateConstraintOperator.EQ EQ}, the topic value at the given pointer will be * compared to the boolean value. Other operators are not permitted with * a boolean value. * * If the {@link UpdateConstraintOperator.IS IS} operator is specified the supplied * value will be compared to the topic value for strict binary equality. * In this case the value must be of type {@link DataTypes.string String}, * {@link DataTypes.int64 Int64}, {@link DataTypes.double Double}, {@link Bytes}, or * {@code null}. This is slightly more efficient than the lenient * comparisons described above. * * @param pointer a JSON * Pointer specifying the location of the {@code value} in * the JSON object. * * @param value the value * @param operator the operator that determines the type of comparison * @return a new constraint * @throws an {@link IllegalArgumentError} if pointer is an invalid JSON Pointer expression, * the value cannot be serialised or the operator is invalid for the value type * @throws a {@link NullValueError} if any of the required arguments are null * * @since 6.10 */ with(pointer: string, value: any, operator: UpdateConstraintOperator, dataType?: DataType): PartialJSON; /** * Require a specific position in the JSON object to be empty. * * The `pointer` is a * JSON Pointer syntax * reference that should have no value in the JSON object. If the * `pointer` parameter cannot be parsed as a JSON pointer an * `Error` is thrown. * * The function returns a new {@link PartialJSON PartialJSON} * object. The original object remains unmodified. * * @param pointer the pointer expression * @return a new constraint * @throws an {@link IllegalArgumentError} if pointer is an invalid JSON Pointer expression * @throws a {@link NullValueError} if the pointer argument is null */ without(pointer: string): PartialJSON; } /** * Factory for the constraint types. * * An instance can be obtained by calling {@link updateConstraints * diffusion.updateConstraints()}. * * @since 6.2 */ export interface UpdateConstraintFactory { /** * Create a constraint requiring a lock to be held by the session. * * This can be used to coordinate operations between multiple * sessions. * * @param lock the lock * @return the constraint */ locked(lock: SessionLock): UpdateConstraint; /** * Create a constraint requiring the current value of the topic to exactly * match the supplied value. * * This is exactly equivalent to calling * {@link UpdateConstraintFactory.value value(UpdateConstraint.Operator, Object)} specifying the * {@link UpdateConstraintOperator.IS IS} operator. * * @param value the value * @param dataType the optional type of the values * @return the constraint * @throws an {@link IllegalArgumentError} if the value cannot be serialised * @throws a {@link NullValueError} if the value argument is null */ value(value: any, dataType?: DataType): UpdateConstraint; /** * Create a constraint comparing the current value of a topic to a * supplied value. * * If a {@link DataTypes.string String} value is supplied and the operator is * {@link UpdateConstraintOperator.EQ EQ} or * {@link UpdateConstraintOperator.NE NE}, the string representation of * the topic will be compared to the supplied value. This can only be * used with primitive topic types (or {@link TopicType.TIME_SERIES * TIME_SERIES} topics with a primitive event type). Other operators * (other than {@link UpdateConstraintOperator.IS IS}) are not * permitted with String values. *

              * If a number value is supplied ({@link DataTypes.int64 Int64} or * {@link DataTypes.double Double}) the value will be compared with the number value of * the topic. This will work with {@link TopicType.STRING STRING}, * {@link TopicType.INT64 INT64} or {@link TopicType.DOUBLE DOUBLE} * topics (or {@link TopicType.TIME_SERIES TIME_SERIES} topics with a * primitive event type) only. {@link TopicType.STRING STRING} topics * can only be compared if they contain a value that can be parsed as a * number. If the value of a {@link TopicType.STRING STRING} topic * cannot be parsed as a number, or the topic is of any other non-number * type the constraint will be unsatisfied. Any of the operators (other * than {@link UpdateConstraintOperator.IS IS}) can be used with such * number comparisons. Decimal numbers can be compared with integral * numbers so {@code 1} is equal to {@code 1.0}, {@code "1"}, or * {@code "1.0"}. *

              * If the {@link UpdateConstraintOperator.IS IS} operator is specified * the specified value will be compared to the topic value for strict * binary equality. The value type can be any value type supported by * {@link DataTypes} or any {@link Bytes} value and can be used to compare * against any topic type. *

              * When a {@link TopicType.STRING STRING}, {@link TopicType.INT64 INT64} * or {@link TopicType.DOUBLE DOUBLE} topic is updated to a {@code null} * value, the topic is set to have no value. Use the {@link UpdateConstraintFactory.noValue noValue()} * constraint to check if the topic has no value. *

              * This constraint is useful when changing the value of a topic. This * constraint is unsatisfied if no topic is present at the path, making * it unsuitable for operations that try to add topics. * * @param operator the operator that determines the type of comparison * * @param value the value * * @return the constraint * @throws an {@link IllegalArgumentError} if the value cannot be serialised or the operator is invalid * for the value type * @throws a {@link NullValueError} if any of the required arguments are null * * @since 6.10 */ value(operator: UpdateConstraintOperator, value: any, dataType?: DataType): UpdateConstraint; /** * Create a constraint requiring the topic to have no value. * * This is useful when setting the first value of a topic. This * constraint is unsatisfied if no topic is present at the path, making * it unsuitable for operations that try to add topics. * * @return the constraint */ noValue(): UpdateConstraint; /** * Create a constraint requiring the path to have no topic. * * This is useful when setting the first value of a topic being added using * an {@link UpdateStream} without changing the value if the topic already * exists. This constraint is unsatisfied if a topic is present at the path, * making it unsuitable for operations that try to set topics without adding * them. * * @return the constraint */ noTopic(): UpdateConstraint; /** * Create a constraint that partially matches the current topic value. * * The topic must be a {@link TopicType.JSON JSON} topic (or a * {@link TopicType.TIME_SERIES TIME_SERIES} topic with a json event * type). The {@link PartialJSON} partially describes the structure of a * {@link JSON} value. The * {@link PartialJSON.with with} or {@link PartialJSON.without without} methods must be used to * fully qualify the constraint. * * This constraint is useful when changing the value of a topic. The * constraint is unsatisfied if no topic is present at the path, making * it unsuitable for operations that try to add topics. * * @return {diffusion.topicUpdate.PartialJSON} the constraint */ jsonValue(): PartialJSON; } /** * @module diffusion.topicUpdate */ /** * An update stream provides a method for updating a specific topic. * * An update stream is associated with a specific topic. The type of the topic * must match the type of values passed to the update stream. It can be created * with an optional {@link UpdateConstraint constraint}. * The existence of the topic, its type and the constraint are validated lazily * by the first {@link set} or {@link validate} operation. Subsequent operations * issued before the first operation completes will be deferred until the * completion of the first operation. * * An update stream can be used to send any number of updates. It sends a * sequence of updates for a specific topic to the server. If supported by the * data type, updates will be sent to the server as a stream of binary deltas. * An update stream does not prevent other sessions from updating the topic. If * exclusive access is required update streams should be used with * {@link SessionLock session locks} as constraints. * * Once validated an update stream can be invalidated. An invalidated * update stream rejects the operations applied to it. The update stream * will be invalidated if: * * * the topic is removed * * another update stream is created for the same topic * * the topic is updated to a new value by anything other than the stream * * the session does not have the * {@link PathPermission.UPDATE_TOPIC update permission} * * an operation fails because of cluster repartitioning * * UpdateStreams are created using the {@link TopicUpdate} feature. * * @since 6.2 */ export interface UpdateStream { /** * Sets the topic to a specified value. * * `null` or `undefined` can only be passed to the * `value` parameter when updating {@link TopicType.STRING string}, * {@link TopicType.INT64 int64} or {@link TopicType.DOUBLE double} topics. * * When a topic of type {@link TopicType.STRING string}, * {@link TopicType.INT64 int64} or {@link TopicType.DOUBLE double} is set * to `null` or `undefined` , the topic will be updated * to have no value. If a previous value was present subscribers will * receive a notification that the new value is `undefined` . New * subscribers will not receive a value notification. * * If this method fails once, all subsequent calls to {@link UpdateStream.set} or * {@link UpdateStream.validate} will also fail. * * @param value the value. Update streams for string, int64, and double * topics accept `null` or `undefined`, as described above. * Using null with other topic types is an error and will * result in an `Error` . * @return a Promise that completes when a response is received from the * server. *

              * The first set operation will return a {@link * TopicCreationResult} indicating whether a new topic was created * or it already exists. *

              * If the task fails, the Promise will resolve with an * `Error` . */ set(value: any): Promise; /** * Return the latest value of the topic set using this update stream. * * The returned value reflects the last value that has been set, before it * is sent to the server. * * If the server rejects a set operation, the topic value will not change * and this update stream will be invalidated. * * This method will throw an `Error` if called before the first * call to {@link set} * * @return the cached value of the topic */ get(): any; /** * Validates the update stream. * * Update streams are validated lazily when {@link set setting the value}. * This method allows the stream to be validated before a value needs to be * set. * * If the update stream has not been validated yet, calling this method * checks the topic exists, the topic type is correct, the constraint is * satisfied and the session has permission to update the topic. Once * it has been validated calling this method checks the topic has not been * removed, no other stream has been created for the topic, the value * of the topic has not been changed by anything else and the session * still has permission to update the topic. If validation fails, the Promise * will resolve with an `Error`. * * If this method fails all subsequent calls to {@link set} or * {@link validate} will resolve with an `Error`. * * @return a Promise that completes when a response is received from the server. */ validate(): Promise; } /** * An extension to {@link UpdateStream} that includes recovery functionality. * * A recoverable update stream wraps an {@link UpdateStream}, tracking topic * updates and associated Promisess. * * In the event that a {@link RecoverableUpdateStream} returns a Promise * that rejects, calling {@link RecoverableUpdateStream.isRecoverable} * returns `true` recovery is possible. * * Call {@link RecoverableUpdateStream.recover} to re-establish the update * stream and re-play incomplete topic updates before resuming. * * Construct a RecoverableUpdateStream by passing a {@link RetryStrategy} to * {@link UpdateStreamBuilder.build} * *

              Example feature use

              * * This example demonstrates use of a RecoverableUpdateStream to update topic * my/topic with 1000 unique values, after which it checks for * failure in any of them. If any topic updates complete exceptionally and the * exception is recoverable, the code recovers - reestablishing an UpdateStream * and delivering the failed topic updates. * *
               * const topicSpec = new TopicSpecification(TopicType.STRING);
               *
               * const updateStream =
               *     session.topics
               *         .newUpdateStreamBuilder()
               *         .specification(topicSpec)
               *         .build(
               *             'my/topic',
               *             datatypes.string(),
               *             { interval: 1000, attempts: 10 }
               *         );
               *
               * const promises = [ ...Array(1000).keys() ]
               *     .map((i) => updateStream.set(`Value of ${i}`));
               *
               * try {
               *     await Promise.all(promises);
               * } catch (err) {
               *     if (updateStream.isRecoverable()) {
               *         updateStream.recover();
               *     } else {
               *         console.error("Cannot recover", err);
               *     }
               * }
               * 
              * * @since 6.10 */ export interface RecoverableUpdateStream extends UpdateStream { /** * Check if recovery is possible following an rejected Promise returned from * {@link RecoverableUpdateStream}. * * Must be used prior to calling {@link RecoverableUpdateStream.recover}. * * @return true if recovery is possible. */ isRecoverable(): boolean; /** * Reestablish the inner recovery stream. Deliver pending topic updates. * * If recoverable exceptions occur during recovery then pause and retry, * where the pause duration and the maximum number of retries is governed by * the {@link RetryStrategy} supplied to builder function * {@link UpdateStreamBuilder.build}. * * If non-recoverable errors occur during recovery then recovery is aborted. * * If recovery fails for any reason then further recovery attempts will fail. * * @throws an Error if recovery is not possible with the limits of the retry strategy. */ recover(): Promise; } /** * Builder for {@link UpdateStream update stream} to use for updating a * specific topic. A builder is created using * {@link TopicUpdate.newUpdateStreamBuilder}. * * The type of the topic being updated must match the type derived from the * {@code dataType} parameter. * * @since 6.9 */ export interface UpdateStreamBuilder { /** * Specifies a TopicSpecification for this update stream. * * If a topic does not exist at the {@code path} one will be created using * the {@code topicSpecification} when the update stream is validated. If a * topic does exist, its specification must match {@code topicSpecification}, * otherwise the operation will fail with an error. * * Specification is undefined by default. Calling this method with a null or undefined parameter * removes the specification for this builder. * * @param topicSpecification the required specification of the topic * @return this builder */ specification(topicSpecification?: TopicSpecification | TopicType): UpdateStreamBuilder; /** * Specifies an update constraint for this update stream. * * Constraints can be created using {@link updateConstraints}}. * * Constraints can be applied to the setting of a value and creation of an * update stream. Constraints describe a condition that must be satisfied for * the operation to succeed. The constraints are evaluated on the server. The * available constraints are: an active session lock, the absence of a topic, * the current value of the topic being updated, and a part of the current * value of the topic being updated. * * Constraint is Unconstrained by default. Calling this method with a null or undefined parameter * resets the constraint for this builder. * * @param updateConstraint the constraint that must be satisfied for the update * stream to be validated * @return this builder */ constraint(updateConstraint: UpdateConstraint): UpdateStreamBuilder; /** * Specifies if delta compression should be disabled for this update stream. * * This is {@code false} by default, i.e. delta compression is enabled. * * Disabling delta compression can reduce the CPU workload at the client * at the cost of increased bandwidth and possible additional CPU load on * the server (if the topic publishes deltas). This may be particularly * useful for topics that have PUBLISH_VALUES_ONLY set. * * @param suppressDeltas the boolean value to set the suppression of delta compression. * @return this builder * @since 6.11 */ suppressDeltas(suppressDeltas: boolean): UpdateStreamBuilder; /** * Resets the builder to its default parameters. * * @return this builder */ reset(): UpdateStreamBuilder; /** * Creates an {@link UpdateStream} to use for updating a * specific topic. * * The type of the topic being updated must match the type derived from the * {@code dataType} parameter. * * Update streams send a sequence of updates for a specific topic. The * updates may be delivered to the server as binary deltas. They do not * provide exclusive access to the topic. If exclusive access is required * update streams should be used with * {@link SessionLock session locks} as constraints. * * Streams are validated lazily when the first {@link UpdateStream.set} or * {@link UpdateStream.validate} operation is completed. Once validated a * stream can be invalidated, after which it rejects future * updates. * * Takes an optional retry strategy that governs recovery attempts following a * recoverable exception. * * @param path the path of the topic * @param dataType the type of the values expected by the update stream * * @return an update stream * @throws a {@link NullValueError} if the path or dataType is null or undefined */ build(path: string, dataType: DataType): UpdateStream; /** * Creates a {@link RecoverableUpdateStream} to use for updating a * specific topic. * * Takes a retry strategy that governs recovery attempts following a * recoverable exception. * * In other respects this method works in the same way as calling * {@link UpdateStreamBuilder.build} without retry strategy. * * @param path the path of the topic * @param dataType the type of the values expected by the update stream * @param retryStrategy an optional retry strategy * * @return a recoverable update stream * @throws a {@link NullValueError} if any of the required arguments null or undefined */ build(path: string, dataType: DataType, retryStrategy?: RetryStrategy): RecoverableUpdateStream; } /** * @module diffusion.topics */ /// /** * A parameterised query that can be used to search the topic tree. * * A new request can be created using the {@link Session.fetchRequest fetchRequest} * method and modified to specify a range of topics and/or * various levels of detail. The request can then be issued to the server * using the {@link FetchRequest.fetch fetch} method * supplying a topic selector which specifies the selection of topics. * The results are returned via a {@link Promise}. * * As a minimum, the path and type of each selected topic will be returned. * It is also possible to request that the topic {@link withValues values} * and/or {@link withProperties properties} are returned. * * If values are selected then the topic types selected are naturally * constrained by the provided `dataType` argument. So if * {@link DataTypes.string} is specified, only {@link TopicType.STRING * STRING} topics will be selected. However, if {@link DataTypes.json} is * specified, all types compatible with {@link JSON} will be selected * including {@link TopicType.STRING STRING}, {@link TopicType.INT64 INT64} * and {@link TopicType.DOUBLE DOUBLE}. See * {@link DataType.canReadAs} for the class hierarchy of types. * * To select topic types when * values are not required, or to further constrain the selection when * values are required, it is also possible to specify exactly which * {@link TopicType topic types} to select. * * The topics selected by the topic selector can be further restricted by * range. A range is defined by a start path and an end path, and contains * all paths in-between in path order. Given a topic tree containing the * topics: * * ``` * a, a/b, a/c, a/c/x, a/c/y, a/d, a/e, b, b/a/x, b/b/x, c * ``` * * The range from `a/c/y` to `b/a/x` includes the topics with paths: * * ``` * a/c/x, a/c/y, a/d, a/e, b, b/a/x * ``` * * The start point of a range can be specified using {@link from} or * {@link after} and an end point using {@link to} or * {@link before}. {@link from} and {@link to} include any * topic with the specified path in the selection, whereas {@link after} * and {@link before} are non-inclusive and useful for paging * through a potentially large range of topics. If no start point is * specified, the start point is assumed to be the first topic of the topic * tree, ordered by path name. Similarly, if no end point is specified, the * end point is the last topic of the topic tree. * * A limit on the number of results returned can be specified using * {@link first}. This is advisable if the result set could * potentially be large. The number of results returned is also limited by * the session's maximum message size – see {@link maximumResultSize}. The * result indicates whether the results have been limited via the * {@link FetchResult.hasMore hasMore} method. If `hasMore()` * returns `true`, further results can be retrieved by modifying the original * query to request results {@link after} the last path received. * * By default, results are returned in path order, earliest path first, * starting from the beginning of any range specified. It is also possible * to request results from the end of the range indicated by specifying a * limit to the number of results using {@link last}. This method * complements {@link first}, returning up to the specified number of * results from the end of the range, but in reverse path order. This is * useful for paging backwards through a range of topics. * * It can be useful to explore an unknown topic tree in a breadth-first * manner rather than the path order. This can be achieved using * {@link limitDeepBranches}. * * FetchRequest instances are immutable and can be safely shared and reused. * * @since 6.2 */ export declare abstract class FetchRequest { /** * Specifies a logical start point within the topic tree. * * If specified, only results for topics with a path that is lexically equal * to or 'after' the specified path will be returned. * * This is the inclusive equivalent of {@link after} and if used will * override any previous {@link after} or {@link from} * constraint. * * @param topicPath the topic path from which results are to be returned * * @return a new fetch request derived from this fetch request but * selecting only topics from the specified path onwards * (inclusive) */ abstract from(topicPath: string): FetchRequest; /** * Specifies a logical start point within the topic tree. * * If specified, only results for topics with a path that is lexically * 'after' the specified path will be returned. * * This is the non inclusive equivalent of {@link from} and if used * will override any previous {@link from} or {@link after} * constraint. * * @param topicPath the topic path after which results are to be returned * @return a new fetch request derived from this fetch * request but selecting only topics after the specified path (not * inclusive) */ abstract after(topicPath: string): FetchRequest; /** * Specifies a logical end point within the topic tree. * * If specified, only results for topics with a path that is lexically equal * to or 'before' the specified path will be returned. * * This is the inclusive equivalent of {@link before} and if used * will override any previous {@link before} or {@link to} * constraint. * * @param topicPath the topic path to which results are to be returned * @return a new fetch request derived from this fetch request but * selecting only topics including and before the specified path * (inclusive) */ abstract to(topicPath: string): FetchRequest; /** * Specifies a logical end point within the topic tree. * * If specified, only results for topics with a path that is lexically * 'before' the specified path will be returned. * * This is the non inclusive equivalent of {@link to} and if used * will override any previous {@link to } or {@link before} * constraint. * * @param topicPath the topic path before which results are to be * returned * * @return a new fetch request derived from this fetch * request but selecting only topics before the specified path (not * inclusive) */ abstract before(topicPath: string): FetchRequest; /** * Specifies that only topics of the specified topic types should be * returned. * * If this is not specified, {@link getAllTypes all * types} will be returned (unless constrained by {@link withValues}). * * This may be used instead to further constrain the results when using * {@link withValues}. For example, you can specify * {diffusion.datatypes.DataType.json} to {@link withValues} then specify * {@link TopicType.JSON JSON} here to ensure that only * JSON topics are returned and not those topics that are logically value * subtypes of JSON (e.g. {@link TopicType.STRING STRING}). * * If {@link withValues} has been specified then the types specified here * must be compatible with the value class specified. * * @param topicTypes topic types to be selected * * @return a new fetch request derived from this fetch request but * specifying that only topics of the specified topic types should * be returned. * * @throws an {@link IllegalArgumentError} if invalid topic types are specified */ abstract topicTypes(topicTypes: TopicType[] | Set): FetchRequest; /** * Specifies that values should be returned for selected topics, * constraining the selection to only those topics with a data type * compatible with the specified {@link DataType * DataType}. * * The specified value constrains the topic types. So, any topic types * specified in a previous call to {@link topicTypes} that * cannot be read as the specified class will be removed from the list * of topic types. * * @param dataType the type of values. If no value is specified this will * cancel any previous call (topic types will remain * unchanged). * * @return a new fetch request derived from this fetch * request but specifying that only topics compatible with the * specified class should be returned with values. * * @throws an {@link IllegalArgumentError} if the data type is not compatible with any * topic types. */ abstract withValues(dataType?: DataType | AnyDataType): FetchRequest; /** * Specifies that all properties associated with each topic's {@link * TopicSpecification specification} should be returned. * * @return a new fetch request derived from this fetch request but * specifying that topic specification properties should be * returned. */ abstract withProperties(): FetchRequest; /** * Specifies that topic sizes should be returned. * * For time series topics this will fetch the size (in bytes) of * the last event, the number of events, and the total size of all events. * * For all other topics this will fetch the size (in bytes) of the * topic value, or 0 if the topic has no value. * * @return a new fetch request derived from this fetch request but * specifying that topic sizes should be returned. * * @since 6.11 */ abstract withSizes(): FetchRequest; /** * Specifies a maximum number of topic results to be returned from the start * of the required range. * * If this is not specified, the number of results returned will only be * limited by other constraints of the request. * * This should be used to retrieve results in manageable batches and prevent * very large result sets. * * If there are potentially more results that would satisfy the other * constraints then the fetch result will indicate so via the {@link * FetchResult.hasMore hasMore} method. * * If the count is set to zero, no results will be returned. In this case, * {@link FetchResult.hasMore hasMore} can be used to check the existence of * any topics matching the criteria without retrieving topic details. * * Either this or {@link last} may be specified. This will therefore * override any previous {@link last} or {@link first} * constraint. * * @param count the non-negative maximum number of results to return from the * start of the range * * @return a new fetch request derived from this fetch * request but selecting only the number of topics specified from * the start of the range * * @throws an {@link IllegalArgumentError} if the count is negative */ abstract first(count: number): FetchRequest; /** * Specifies a maximum number of topic results to be returned from the end * of the required range. * * This is similar to {@link first} except that the specified number * of results are returned from the end of the range. This is useful for * paging backwards through a range of topics. Results are always returned * in topic path order (not reverse order). * * Either this or {@link first} may be specified. This will therefore * override any previous {@link first} or {@link last} * constraint. * * @param count the non-negative maximum number of results to return from the * end of the range * * @return a new fetch request derived from this fetch * request but selecting only the number of topics specified from * the end of the range * * @throws an {@link IllegalArgumentError} if the count is negative */ abstract last(count: number): FetchRequest; /** * Specifies the maximum data size of the result set. *

              * This may be used to constrain the size of the result. If not specified * then by default the maximum message size for the session (as specified by * {@link Options.maxMessageSize} is used. * * @param maximumSize the maximum size of the result set in bytes. * If a value greater than the session's maximum message * size is specified, the maximum message size will be * used. * * @return a new fetch request derived from this fetch * request but constraining the size of the result to the specified * maximum * * @throws an {@link IllegalArgumentError} if the maximum size is negative */ abstract maximumResultSize(maximumSize: number): FetchRequest; /** * Specifies a limit on the number of results returned for each deep * branch. * * A deep branch has a root path that has a number of parts equal to the * `deepBranchDepth` parameter. The `deepBranchLimit` * specifies the maximum number of results for each deep branch. * * This method is particularly useful for incrementally exploring a * topic tree from the root, allowing a breadth-first search strategy. * * For example, given a topic tree containing the topics with the * following paths: * * ``` * x/0 * x/x/1 * x/x/x/2 * y/y/y/y/3 * y/y/y/4 * z/5 * z/z/6 * ``` * * Then * * ``` * session.fetchRequest().limitDeepBranches(1, 1).fetch("?.//"); * ``` * * will return results with the paths `x/0`, `y/y/y/y/3`, * and `z/5`. The application can then determine the roots of the * tree are `x`, `y`, and `z`. * * The `deepBranchLimit` parameter can usefully be set to * `0`. For example, given the same example topic tree, * * ``` * session.fetchRequest().limitDeepBranches(3, 0).fetch("?.//"); * ``` * * will only return results having paths with fewer than three parts; * namely `x/0`, and `z/5`. * * The fetch result does not indicate whether this option caused some * results to be filtered from deep branches. It has no affect on the * {@link FetchResult.hasMore hasMore()} result. If the result set * contains `deepBranchLimit` results for a particular deep * branch, some topics from that branch may have been filtered. * * @param deepBranchDepth the number of parts in the root path of a * branch for it to be considered deep * @param deepBranchLimit the maximum number of results to return for * each deep branch * @return a new fetch request derived from this fetch request but * restricting the number of results for deep branches * @throws an {@link IllegalArgumentError} if either parameter is negative * * @since 6.4 */ abstract limitDeepBranches(deepBranchDepth: number, deepBranchLimit: number): FetchRequest; /** * Include the details of reference topics that are not yet published. * * {@link TopicViews Topic views} that use the `delay by` clause * create reference topics in an unpublished state. The topics are * published once the delay time has expired. A topic in the * unpublished state prevents a lower priority topic view from creating * a reference topic with the same path. * * A reference topic in the unpublished state which matches the query * will only be included in the fetch results if the session has * {@link PathPermission.READ_TOPIC READ_TOPIC} permission for the * reference's source topic as well as `READ_TOPIC` permission for * the reference topic. Requiring `READ_TOPIC` permission for the * source topic ensures less privileged sessions cannot derive * information from the existence of the reference topic before the * delay time has expired. * * @return a new fetch request derived from this fetch request, * additionally specifying that unpublished reference topics * should be included in the results * @since 6.5 */ abstract withUnpublishedDelayedTopics(): FetchRequest; /** * Sends a fetch request to the server. * * Results are returned for all topics matching the selector that satisfy * the request constraints within any range defined by {@link from}/{@link * after} and/or {@link to}/{@link before}. * * This function can take any number of arguments. Each argument can be a string * or a {@link TopicSelector}. Alternatively, an array of strings and * {@link TopicSelector}s can be passed as a single argument. At least one * valid selector has to be specified. * * @param topics specifies a topic selector which selects the topics to be * fetched * * @return a Promise that resolves with a {@link FetchResult * FetchResult} when a response is received from the server with * the results of the fetch operation. *

              * If the task completes successfully, the FetchResult returned by * the Promise will be an object encapsulating all of the results. *

              * Otherwise, the Promise will resolve with an Error. Common reasons for * failure, listed by the error type, include: *

                *
              • {@link InvalidDataError} – if topic values were returned but could not * be read. *
              * * @throws an {@link IllegalArgumentError} if the selector could not be parsed */ abstract fetch(topics: Array): Promise>; abstract fetch(...topics: Array): Promise>; /** * Return a set of all topic types that can be fetched. * * @returns the topic types that can be fetched by a FetchRequest */ static getAllTypes(): Set; } /** * Encapsulates the results from a fetch operation issued to the server. * * A fetch operation is issued using a {@link FetchRequest * fetch request} which will return a result of this type via a {@link Promise}. * * @param V the result value type. This will be any type unless the request * indicated that {@link FetchRequest.withValues * values} are to be returned, in which case this will be the data * type requested. * * @since 6.2 */ export interface FetchResult { /** * Returns the results from the fetch operation. * * Results are always returned in path order. * * @return a list of {@link TopicResult TopicResult}s, * each representing a result single topic selected by the fetch * operation. */ results(): Array>; /** * Indicates whether the fetch could have returned more results if it had not * been constrained by the {@link FetchRequest.first first}, {@link * FetchRequest.last last} or {@link FetchRequest.maximumResultSize * maximumResultSize} * limits. * * @return `true` if more results could have been returned, * otherwise false */ hasMore(): boolean; /** * The number of elements in the fetch result. * * @return the size of the results list * @since 6.3 */ size(): number; /** * Returns `true` if the result contains zero elements. * * @return true if result list is empty * @since 6.3 */ isEmpty(): boolean; } /** * Encapsulates the result of a {@link FetchRequest.fetch * fetch} invocation for a single selected topic. * * @param V the result value type. This will be any type unless the request * indicated that {@link FetchRequest.withValues values} * are to be returned, in which case this will be the data type * requested. * * @since 6.2 */ export interface TopicResult { /** * Returns the topic path. * * @return the topic path */ path(): string; /** * Returns the topic type. * * @return the topic type */ type(): TopicType; /** * Returns the topic value. * * This will only return a value if the fetch request specified {@link * FetchRequest.withValues withValues} and the topic actually had a value. * For topics that have no value this will return undefined. * * @return the topic value or undefined if none available */ value(): V; /** * Returns the topic specification. * * If the request specified {@link FetchRequest.withProperties * withProperties}, the result reflect the topic's specification and can be * used to create an identical topic. If the request did not specify {@link * FetchRequest.withProperties withProperties}, the specification's property * map will be empty. * * @return {TopicSpecification} the topic specification */ specification(): TopicSpecification; /** * Returns the size of the topic’s value (in bytes) or 0 if the topic * has no value. * * For time series topics this will be the size of the last event. * * @return the value size */ valueSize(): number; /** * Returns the number of values that the topic has. For a topic with no * value this will return 0. * * For a non times series topic with a value this will return 1. For a * time series topic this will return the number of events. * * @return the value count */ valueCount(): number; /** * Return the total value size of a topic. * * For a non time series topic this will be the same as `valueSize()`. * For a time series topic this will be the total size of all events (in bytes). */ valueTotalSize(): Long; } /** * Topic selector type. */ export declare enum TopicSelectionType { /** * Represents selection of topics (i.e. subscription). */ SELECT = 0, /** * Represents deselection of topics (i.e. unsubscription). */ DESELECT = 1 } /** * A topic selection that represents either a subscription (selection) or an * unsubscription (deselection). * * @since 6.12 */ export interface TopicSelection { /** * The topic selector */ readonly selector: TopicSelector; /** * The selection type */ readonly selectionType: TopicSelectionType; } /** * @module diffusion.topics */ /** * Topic specifications provide the information required to create a topic. * Topics can be created from a topic specification using * {@link TopicControl.add}. * * Topic specifications allow an application to introspect the type and * capabilities of a topic. Topic specifications are provided to * {@link ValueStream ValueStreams} and {@link TopicNotificationListener topic * notification listeners}. * * A topic is specified in terms of its {@link TopicType type} * and a map of optional property settings which can alter the default behavior * of the topic. * * A topic specification has a {@link TopicType topic type} and a map of property settings * which define the behavior of the topic. A default topic specification for a topic * type can be created using `new diffusion.topics.TopicSpecification(TopicType)`. Topic * specifications with different properties can be derived from a default instance * using the {@link TopicSpecification.withProperties} and * {@link TopicSpecification.withProperty} builder methods. * *

              Topic Properties

              * * Depending on the topic type, some properties must be included in the * specification when creating a topic and some properties have no effect. All * topic specification property values must be supplied as strings. * * The required and optional properties for each topic type are set out in the following table. * Properties unsupported by the topic type are ignored. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
              Default when optional{@link TopicType.STRING STRING}
              * {@link TopicType.JSON JSON}
              * {@link TopicType.BINARY BINARY}
              *
              {@link TopicType.DOUBLE DOUBLE}
              * {@link TopicType.INT64 INT64}
              {@link TopicType.RECORD_V2 RECORD_V2}{@link TopicType.TIME_SERIES TIME_SERIES}
              {@link TopicSpecification.COMPRESSION COMPRESSION}lowOptional-OptionalOptional
              {@link TopicSpecification.CONFLATION CONFLATION}conflateOptionalOptionalOptionalOptional
              {@link TopicSpecification.DONT_RETAIN_VALUE DONT_RETAIN_VALUE}falseOptionalOptionalOptional-
              {@link TopicSpecification.OWNER OWNER}OptionalOptionalOptionalOptional
              {@link TopicSpecification.PERSISTENT PERSISTENT}trueOptionalOptionalOptionalOptional
              {@link TopicSpecification.PRIORITY PRIORITY}defaultOptionalOptionalOptionalOptional
              {@link TopicSpecification.PUBLISH_VALUES_ONLY PUBLISH_VALUES_ONLY}falseOptional-OptionalOptional
              {@link TopicSpecification.REMOVAL REMOVAL}OptionalOptionalOptionalOptional
              {@link TopicSpecification.SCHEMA SCHEMA}--Optional-
              {@link TopicSpecification.TIDY_ON_UNSUBSCRIBE TIDY_ON_UNSUBSCRIBE}falseOptionalOptionalOptionalOptional
              {@link TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE TIME_SERIES_EVENT_VALUE_TYPE}---Required
              {@link TopicSpecification.TIME_SERIES_RETAINED_RANGE TIME_SERIES_RETAINED_RANGE}limit 10---Optional
              {@link TopicSpecification.TIME_SERIES_SUBSCRIPTION_RANGE TIME_SERIES_SUBSCRIPTION_RANGE}as documented---Optional
              {@link TopicSpecification.VALIDATE_VALUES VALIDATE_VALUES}falseOptionalOptionalOptionalOptional
              * * `TIME_SERIES` topics have restricted values for the * `CONFLATION` property. They are only allowed to have the values * `off` or `unsubscribe`. */ export declare class TopicSpecification { /** * Key of the topic property that specifies whether a topic should publish * only values. * * By default, a topic that supports delta streams will publish the * difference between two values (a delta) when doing so is more efficient * than publishing the complete new value. Subscribing sessions can use a * {@link ValueStream} to automatically apply the delta to a local copy of * the topic value to calculate the new value. * * Setting PUBLISH_VALUES_ONLY to `true` disables this behavior so that * deltas are never published. Doing so is usually not recommended because * it will result in more data being transmitted, less efficient use of * network resources, and increased transmission latency. On the other hand, * calculating deltas can require significant CPU from the server or, if * update streams are used, from the updating client. The CPU cost will be * higher if there are many differences between successive values, in which * case delta streams confer fewer benefits. If successive values are * unrelated to each other, consider setting PUBLISH_VALUES_ONLY to `true`. * Also consider setting PUBLISH_VALUES_ONLY to `true` if the network * capacity is high and the bandwidth savings of deltas are not required. * * @see {@link TopicSpecification.DONT_RETAIN_VALUE} */ static readonly PUBLISH_VALUES_ONLY = "PUBLISH_VALUES_ONLY"; /** * Key of the topic property that specifies whether a topic should validate * inbound values. * * By default, the server does not validate received values before sending * them on to client sessions. Invalid or corrupt values will be stored in * the topic and passed on to sessions. If this property is set to `true`, * the server will perform additional validation on values to check that * they are valid instances of the data type, and if it is not then it will * return an error to the updater and not update the topic. * * If this value is not set (or set to something other than `true`), no * server validation of inbound values is performed. This is the recommended * setting as there is a performance overhead to validation and values * produced through the {@link DataTypes data type} API will not * be invalid anyway. */ static readonly VALIDATE_VALUES = "VALIDATE_VALUES"; /** * Key of the topic property that specifies the 'tidy on unsubscribe' option * for a topic. * * By default, if a session unsubscribes from a topic, it will receive any * updates for that topic that were previously queued but not sent. * * If this property is set to `true`, when a session unsubscribes from the * topic, any updates for the topic that are still queued for the session * are removed. There is a performance overhead to using this option as the * client queue must be scanned to find topic updates to remove, however it * may prove useful for preventing unwanted data being sent to sessions. * * @since 6.0 */ static readonly TIDY_ON_UNSUBSCRIBE = "TIDY_ON_UNSUBSCRIBE"; /** * Key of the topic property that specifies the event data type for a time * series topic. * * The value is the {@link DataType.name type name} of a * data type. * * @since 6.0 */ static readonly TIME_SERIES_EVENT_VALUE_TYPE = "TIME_SERIES_EVENT_VALUE_TYPE"; /** * Key of the topic property that specifies the range of events retained by * a time series topic. * * When a new event is added to the time series, older events that fall * outside of the range are discarded. * * If the property is not specified, a time series topic will retain the ten * most recent events. * *

              Time series range expressions

              * * The property value is a time series range expression string * composed of one or more constraint clauses. Constraints are combined to * provide a range of events from the end of the time series. * *
              *
              limit constraint *
              A limit constraint specifies the maximum number of events from the * end of the time series. *
              last clause *
              A last constraint specifies the maximum duration of events from the * end of the time series. The duration is expressed as an integer followed * by one of the following time units.
              *
              * MS – milliseconds;
              * S – seconds;
              * H – hours. *
              * * If a range expression contains multiple constraints, the constraint that * selects the smallest range is used. * * Property value | Meaning * --------------- | --------- * `limit 5` | The five most recent events * `last 10s` | All events that are no more than ten seconds older than the latest event * `last 10s limit 5` | The five most recent events that are no more than ten seconds older than the latest event * * Range expressions are not case sensitive: `limit 5 last 10s` is * equivalent to `LIMIT 5 LAST 10S`. * * @since 6.0 */ static readonly TIME_SERIES_RETAINED_RANGE = "TIME_SERIES_RETAINED_RANGE"; /** * Key of the topic property that specifies the range of time series topic * events to send to new subscribers. * * The property value is a time series range expression, following the * format used for {@link TopicSpecification.TIME_SERIES_RETAINED_RANGE * TIME_SERIES_RETAINED_RANGE}. * * If the property is not specified, new subscribers will be sent the latest * event if delta streams are enabled and no events if delta streams are * disabled. See the description of Subscription range in the * {@link TimeSeries time series feature} documentation. * * @since 6.0 */ static readonly TIME_SERIES_SUBSCRIPTION_RANGE = "TIME_SERIES_SUBSCRIPTION_RANGE"; /** * Key of the topic property that specifies a schema which constrains topic * values. * * This property is only used by {@link TopicType.RECORD_V2 * RECORD_V2} topics. The property value can be generated using * the {@link Schema.asJSON} method of a {@link Schema} created using a * {@link SchemaBuilder}. * * @since 6.0 */ static readonly SCHEMA = "SCHEMA"; /** * Key of the topic property that specifies a topic should not retain its * last value. * * By default, a topic will retain its latest value. The latest value will * be sent to new subscribers. Setting this property to `true` disables * this behavior. New subscribers will not be sent an initial value. No * value will be returned for fetch operations that select the topic. This * is useful for data streams where the values are only transiently valid. * * Setting DONT_RETAIN_VALUE to `true` also disables delta streams, * regardless of the {@link TopicSpecification.PUBLISH_VALUES_ONLY * PUBLISH_VALUES_ONLY} value. If subsequent values are likely to be * related, delta streams usually provide performance benefits (see {@link * TopicSpecification.PUBLISH_VALUES_ONLY PUBLISH_VALUES_ONLY}). Consider * leaving DONT_RETAIN_VALUE set to `false` to benefit from delta streams, * even if there is no other requirement to retain the last value. * * Bearing in mind the performance trade-offs of disabling delta streams, * there are two reasons to consider setting DONT_RETAIN_VALUE to `true`. * First, it stops the server and each subscribed client from keeping a copy * of the value, reducing their memory requirements. Second, when a topic * has a high update rate and is replicated across a cluster, it can * significantly improve throughput because the values need not be persisted * to the cluster. * * Time series topics ignore this property and always retain the latest * value. * * @since 6.0 */ static readonly DONT_RETAIN_VALUE = "DONT_RETAIN_VALUE"; /** * Key of the topic property that can be used to prevent a topic from being * persisted when the server is configured to enable persistence. * * By default, a topic will be persisted if persistence is enabled at the * server and the topic type supports persistence. * * Setting PERSISTENT to `false` will prevent the topic from being * persisted. * * @since 6.1 */ static readonly PERSISTENT = "PERSISTENT"; /** * Key of the topic property that specifies a removal policy for automatic * removal of the topic (and/or other topics). * * This property is specified as an expression which defines one or more * conditions that are to be satisfied before automatic removal occurs. * * The expression takes the form: * * * when conditions [remove 'selector'] * * * At least one condition must be supplied. If more than one is supplied, * they must be separated by logical operators (`and` or `or`). * The natural evaluation order of the operators may be changed by * surrounding with parentheses (e.g. (condition `and` * condition)). * * The `remove` clause is optional. It provides a {@link TopicSelector} * expression representing the topics to be removed. If a `remove` clause is * specified, the topic with the removal policy will only be removed if its * path matches the selector expression. The selector must be surrounded by * either double or single quotes. * * When many topics have the same removal policy, it is better to * set the `REMOVAL` property for one of them, using a `remove` * clause that selects all of the topics. This is more efficient because it * allows the server to avoid evaluating the same condition many times. * * The permissions that are applied at the time of removal are those defined * by the roles of the principal that created the topic at the time of * creation. The roles of that principal may therefore change before the * removal with no effect, but if the permissions given to the roles change * it may have an effect upon the final removal. * * Only one occurrence of each of the following condition types may be * included within the expression: * * * * * * * * * * * * * * * * * * * * * *
              Condition TypeFormatUsage
              time aftertime after absoluteTimeRemoval should occur after a specified absolute time. Absolute time * may be specified as a number of milliseconds since the epoch (00:00:00 on * 1 January 1970) or as a quoted date and time formatted in RFC_1123 * date time format. Either single or double quotes may be used.
              subscriptions less than[local] subscriptions < n for forPeriod [after afterPeriod]Removal should occur when the topic has had less than the specified * number (n) of subscriptions for a given period (forPeriod) * of time. Optionally, an initial period (afterPeriod) may be * specified by which to delay the initial checking of this condition. See * below for period formats. *

              The optional local keyword restricts evaluation to only count * subscriptions from sessions belonging to the local server or cluster, * ignoring subscriptions from sessions belonging to downstream remote servers that * host fanout replicas of the topic.

              no updates forno updates for forPeriod [after afterPeriod]Removal should occur when the topic has had no updates for a given * period (forPeriod) of time. Optionally, an initial period * (afterPeriod) may be specified by which to delay the initial * checking of this condition. See below for period formats.
              * * Multiple occurrences of the following condition types may be * included within the expression: * * * * * * * * * * * * * * * * *
              Condition TypeFormatUsage
              no session hasno [local] session has 'criteria' [for forPeriod] [after afterPeriod]Removal should occur when no sessions satisfy certain criteria. * Optionally the criteria can be required to be satisfied for a period of time * (forPeriod). Optionally, an initial period (afterPeriod) can * be specified to delay the initial check of the criteria. Session selection * criteria are specified as defined in {@link Session session filters} and * must be surrounded by single or double quotes. See below for period formats. *

              The optional local keyword restricts evaluation to sessions * belonging to the local server or cluster, ignoring sessions belonging to * downstream remote servers that host fanout replicas of the topic.

              this session closesThis is a shorthand form of `no local session has` that may be used to * indicate that the topic is to be removed when the session that created it * closes.
              * * Time periods are specified as a number followed (with no intermediate * space) by a single letter representing the time unit. The time unit may * be `s` (seconds), `m` (minutes), `h` (hours) or `d` (days). For example, * 10 minutes would be specified as 10m. * * If quotes or backslashes (`\`) are required within quoted values such as * selectors or session criteria then they may be escaped by preceding with * `\`. The convenience method {@link escape} is provided to escape such * characters in a value. The expression is validated only by the server and * therefore if an invalid expression is specified it will be reported as an * Error. * * **Examples:** * * ``` * when time after 1518780068112 * ``` * * The topic will be removed when the date and time indicated by the * specified number of milliseconds since the epoch has passed. * * ``` * when time after 'Tue, 3 Jun 2018 11:05:30 GMT' * ``` * * The topic will be removed when the specified date and time has passed. * * ``` * when time after 'Tue, 3 Jun 2018 11:05:30 GMT' remove '*alpha/beta//' * ``` * * The topic alpha/beta and all topics subordinate to it will be removed * when the specified date and time has passed. * * ``` * when subscriptions < 1 for 20m * ``` * * The topic will be removed when it has had no subscriptions for a * continuous period of 20 minutes. * * ``` * when subscriptions < 2 for 20m after 1h * ``` * * The topic will be removed when it has had less than 2 subscriptions for a * continuous period of 20 minutes after one hour has passed since its * creation. * * ``` * when no updates for 3h * ``` * * The topic will be removed when it has had no updates for a continuous * period of 3 hours. * * ``` * when no updates for 15m after 1d * ``` * * The topic will be removed when it has had no updates for a continuous * period of 15 minutes after one day has passed since its creation. * * ``` * when this session closes * ``` * * The topic will be removed when the session that created it closes. * * ``` * when no session has '$Principal is "Alice"' * ``` * * The topic will be removed when there is no session with the principal 'Alice'. * * ``` * when no session has '$Principal is "Alice"' for 10m * ``` * * The topic will be removed when there are no sessions with the principal * 'Alice' for a continuous period of 10 minutes. * * ``` * when no session has 'Department is "Accounts"' for 30m after 2h * ``` * * The topic will be removed when there have been no sessions from the Account * department for a continuous period of 30 minutes after 2 hours have passed * since its creation. * * ``` * when time after "Tue, 3 Jun 2018 11:05:30 GMT" and subscriptions < 1 for 30m * ``` * * The topic will be removed when the specified date and time has passed and * the topic has had no subscriptions for a continuous period of 30 minutes * after that time. * * ``` * when time after "Tue, 3 Jun 2018 11:05:30 GMT" and subscriptions < 2 for 10m after 1h * ``` * * The topic will be removed when the specified date and time has passed and * the topic has had less than 2 subscriptions for a continuous period of 10 * minutes after that time plus one hour. * * ``` * when time after "Tue, 3 Jun 2018 11:05:30 GMT" or subscriptions < 2 for 10m after 1h * ``` * * The topic will be removed when the specified date and time has passed or * the topic has had less than 2 subscriptions for a continuous period of 10 * minutes after one hour from its creation. * * ``` * when time after "Tue, 3 Jun 2018 11:05:30 GMT" and (subscriptions < 2 for 10m after 1h or no updates for 20m) * ``` * * The topic will be removed when the specified date and time has passed and * either the topic has had less than 2 subscriptions for a continuous * period of 10 minutes after that time plus one hour or it has had no * updates for a continuous period of 20 minutes. Note that the parentheses * are significant here as without them the topic would be removed if it had * had no updates for 20 minutes regardless of the time and subscriptions * clause. * * **Notes and restrictions on use** * * The `after` time periods refer to the period since the topic was * created or restored from persistence store after a server is restarted. * They are designed as a 'grace' period after the topic comes into * existence before the related conditions starts to be evaluated. When not * specified the conditions start to be evaluated as soon as the topic is * created or restored. * * The server will evaluate conditions on a periodic basis (every few * seconds) so the exact removal time will not be precise for low periodic * granularity. * * The meaning of the `for` period in a `no session has` condition is subtly * different from its use in other conditions. It does not guarantee that * there has been no session satisfying the condition at some point between * evaluations, only that when evaluated the given period of time has passed * since it was last evaluated and found to have no matching sessions. * * Subscriptions is the number of subscriptions to a topic. * * Automatic topic removal is supported for a topic that is replicated * across the local cluster, and for a topic with with fanout replicas on * downstream remote servers. A `subscriptions less than` condition will be evaluated * against the total number of subscriptions across the cluster and on all * fanout replicas on downstream remote servers. A `no session has` * condition will consider all sessions hosted across the cluster and all * sessions hosted by downstream remote servers that have a fanout replica * of the topic. The `local` keyword can be used to restrict evaluation to * the local cluster, ignoring fanout replicas. * * @since 6.1 */ static readonly REMOVAL = "REMOVAL"; /** * Key of the topic property that specifies the conflation policy of the * topic. The policy specifies how the server manages queued topic updates. * Conflation is applied individually to each session queue. * * Conflation is the process of merging or discarding topic updates queued * for a session to reduce the server memory footprint and network data. The * server will conflate sessions that have a large number of queued messages * to meet configured queue size targets. The sessions with the largest * queues are typically slow consumers or have been disconnected - both will * benefit from conflation. This property allows conflation behavior to be * tuned on a topic-by-topic basis. * * The supported policies are: * * * `off` * * `conflate` * * `unsubscribe` * * `always` * * The default policy used when the property is not specified and the topic * type is not time series is `conflate`. The default policy used when the * property is not specified and the topic type is time series is `off`. * * The policy `off` disables conflation for the topic. This policy * disables all conflation for the topic, so topic updates will never be * merged or discarded. * * The policy `conflate` automatically conflates topic updates when * back pressure is detected by the server. * * The policy `unsubscribe` automatically unsubscribes the topic when * back pressure is detected by the server. The unsubscription is not * persisted to the cluster. If a session fails over to a different server * it will be resubscribed to the topic. * * The policy `always` automatically conflates topic updates as they * are queued for the session. This is an eager policy that ensures only the * latest update is queued for the topic, minimising the server memory and * network bandwidth used by the session. * * The `conflate` and `unsubscribe` policies are applied when * the server detects back pressure for a session. The server configuration * places limits on the data queued for each session. If these limits are * breached, the server will conflate the session queue to attempt to reduce * its size. If the session queue still exceeds the limits after conflation, * the session will be terminated. * * Conflation can be disabled on a session-by-session basis. If conflation is * disabled for a session the policy will not be applied to topic updates * queued for the session but will be for other sessions that have conflation * enabled. * * The policies `conflate` and `always` are not supported for * time series topics as they would cause missing events. Attempts to enable * these policies with time series topics will cause the creation of the * topic to fail, reporting that the specification is invalid. * * @since 6.2 */ static readonly CONFLATION = "CONFLATION"; /** * Key of the topic property that allows the creator of a topic to extend * READ_TOPIC, MODIFY_TOPIC, and UPDATE_TOPIC permissions to a specific * principal, in addition to the permissions granted by the authorisation * rules in the security store. * * A session that has authenticated using the principal can update and * remove the topic, so the principal can be considered the topic owner. To * fetch or subscribe to the topic, the principal must also be granted * the SELECT_TOPIC permission by the security store rules. * * This may be used in the following cases: * 1) A session creates a topic and makes its own principal the owner. * 2) A session creates a topic and makes another principal the owner. * * The format of the property value is: * * `$Principal is "name"` * * where name is the name of the principal. Single quotes may be used * instead of double quotes and special characters can be escaped using * {@link escape} if required. * * The purpose of this property is to allow a client to create topics on * behalf of other users. This can be used in conjunction with the * {@link REMOVAL} property so that such topics are removed when there are * no longer any sessions for the named principal. * * **Example:** * ``` * specification.withProperty(diffusion.topics.TopicSpecification.OWNER, * "$Principal is 'myPrincipal'") * .withProperty(diffusion.topics.TopicSpecification.REMOVAL, * "when no session has '$Principal is \"myPrincipal\"' for 5s"); * ``` * * @since 6.1 */ static readonly OWNER = "OWNER"; /** * Key of the topic property that allows the compression policy to be set * on a per-topic basis. * * Compression reduces the bandwidth required to broadcast topic updates to * subscribed sessions, at the cost of increased server CPU. * * Changes to a topic's value are published to each subscribed session as a * sequence of topic messages. A topic message can carry the latest value or * the difference between the latest value and the previous value (a delta). * The compression policy determines if and how published topic messages * are compressed. Topic messages are not exposed through the client API; * the client library handles decompression and decodes deltas * automatically, passing reconstructed values to the application. * * The compression policy for a topic is specified by setting this property * to one of several values: * * * `off` * * `low` * * `medium` * * `high` * * The policies are listed in the order of increasing compression and * increasing CPU cost. `off` disables compression completely for the * topic and requires no additional CPU; `high` compresses the topic * messages to the smallest number of bytes, but has the highest CPU cost. * Generally some compression is beneficial, so the default value for this * property is `low`. * * Prior to version 6.4, only two values were allowed: `true` * (equivalent to `medium`, and the previous default policy) and * `false` (equivalent to `off`). These values are still * supported. * * This property is only one factor that determines whether a topic message * will be compressed. Other factors include: * * * Compression must be enabled in the server configuration. * * * The client library must support the server's compression * scheme. In this release, the server supports zlib * compression, and also allows compression to be disabled on a * per-connector basis. From 6.4, all client libraries are * capable of zlib compression. A JavaScript client may or may * not support zlib compression, depending on whether the zlib * library can be loaded. The zlib library is packaged * separately to reduce the download size of the core library. * * @since 6.2 */ static readonly COMPRESSION = "COMPRESSION"; /** * Key of the topic property that specifies the topic delivery priority. * * The supported delivery priorities are: * * * `low` * * `default` * * `high` * * The delivery priority affects the order of topic updates sent to a * subscribed client session. When there are multiple topic updates for * topics with different priorities in a session's outbound queue, updates * for `high` priority topics will be delivered first, followed by * updates for `default` priority topics, followed by updates for * `low` priority topics. Topic subscription and unsubscription * notifications are also delivered according to the topic delivery * priority. * * Using different delivery priorities is most beneficial when there is a * large backlog of queued updates to deliver to a client session. On * lightly loaded systems, updates typically remain in the outbound queue * for a few milliseconds and so there is a lower chance of topic updates * being reordered based on their priority. The backlog will be larger if * the topic update rate is higher; the server or the client are more * heavily loaded; the client session becomes temporarily disconnected; or * if there is poor network connectivity between the server and the client. * * Messages from the server to the client that are not topic updates, for * example ping requests and responses, are queued with the * `default` delivery priority. * * @since 6.4 */ static readonly PRIORITY = "PRIORITY"; /** * The topic type. */ type: TopicType; /** * A map of the topic properties. */ properties: { [key: string]: string; }; /** * Create a new TopicSpecification * * @param type the topic type for this specification. * @param properties the properties to use for this specification. * @since 5.9 * * **Example:** * * Properties can be set when creating the specification by passing an object * ``` * // Create specification for JSON topics which validate update values on the server * const TopicSpecification = diffusion.topics.TopicSpecification; * * var specification = new TopicSpecification(diffusion.topics.TopicType.JSON, { * "VALIDATE_VALUES" : "true" * }); * ``` * * **Example:** New specifications can be created with additional properties * ``` * // Create specification for JSON topics which validate update values on the server * const TopicSpecification = diffusion.topics.TopicSpecification; * * var specification = new TopicSpecification(diffusion.topics.TopicType.JSON) * .withProperty(TopicSpecification.VALIDATE_VALUES, "true"); * ``` */ constructor(type: TopicType, properties?: { [key: string]: string; }); /** * Returns a new TopicSpecification with the specified property set to the supplied value. * @param key the new property key * @param value the new property value * @returns a new TopicSpecification with the specified property set. * * @throws an {@link IllegalArgumentError} if the key is not a valid property key. */ withProperty(key: string, value: string): TopicSpecification; /** * Returns a new TopicSpecification with the specified property set to the supplied value. * @param key the new property key * @param value the new property value * @returns a new TopicSpecification with the specified property set. * * @throws an {@link IllegalArgumentError} if the key is not a valid property key. */ withProperties(properties: { [key: string]: string; }): TopicSpecification; } /** * @module diffusion.topics */ /** * Enum containing possible Topic Types. * * **Example:** * ``` * // Get a topic type for adding topics * var topicType = diffusion.topics.TopicType.JSON; * * session.topics.add("foo", topicType); * ``` */ export declare enum TopicType { /** * Binary Topic. * * This is a stateful topic that handles data in Binary format. * @since 5.7 */ BINARY = 14, /** * JSON (JavaScript Object Notation) Topic. * * This is a stateful topic that handles data in JSON representation. * @since 5.7 */ JSON = 15, /** * Topic that stores and publishes String values. Based on the {@link string string data type}. * * Supports null String values. * * Supports delta-streams. * * @since 6.0 */ STRING = 17, /** * Topic that stores and publishes 64-bit integer values. Based on the * {@link int64 int64 data type}. Values are of the type * {@link Int64}. * * Supports null int64 values. * * Does not support delta-streams - only complete values are transmitted. * * @since 6.0 */ INT64 = 18, /** * Topic that stores and publishes IEEE 754 double-precision floating point * numbers (i.e native JavaScript Numbers). Based on the {@link double double data type}. * * Supports null Double values. * * The topic does not support delta-streams - only complete values are transmitted. * * @since 6.0 */ DOUBLE = 19, /** * Time Series Topic. * * A time series is a sequence of events. Each event contains a * value and has server-assigned metadata comprised of a sequence number, * timestamp, and author. * * A time series topic allows sessions to access a time series that is * maintained by the server. A time series topic has an associated * {@link DataType event data type}, such as `Binary`, `String`, * or `JSON`, that determines the type of value associated with each * event. * *

              Retained range

              * * The {@link TopicSpecification.TIME_SERIES_SUBSCRIPTION_RANGE * TIME_SERIES_SUBSCRIPTION_RANGE} property configures the range of historic * events retained by a time series topic. If the property is not specified, * a time series topic will retain the ten most recent events. * *

              Subscription range

              * * The {@link TopicSpecification.TIME_SERIES_SUBSCRIPTION_RANGE * TIME_SERIES_SUBSCRIPTION_RANGE} property configures a time series topic * to send a range of historic events from the end of the time series to new * subscribers. This is a convenient way to synchronize new subscribers * without requiring the use of a {@link TimeSeries.rangeQuery range query}. * * By default, new subscribers will be sent the latest event if delta * streams are enabled and no events if delta streams are disabled. See the * description of Subscription range in the {@link * Session.timeseries} time series feature} documentation. * * *

              Mandatory properties

              * * The {@link TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE * TIME_SERIES_EVENT_VALUE_TYPE} property must be provided when creating a * time series topic. * * * @since 6.0 * @see diffusion.datatypes.TimeSeriesDataType */ TIME_SERIES = 16, /** * Topic that stores and publishes data in the form of records and fields. * Based on the {@link RecordV2DataType RecordV2 data type}. * * Supports delta-streams. * * @since 6.0 */ RECORD_V2 = 20, /** * A topic type that is unsupported by the session. * * @since 6.3 */ UNKNOWN_TOPIC_TYPE = 21 } /** * Provide access to {@link TopicType TopicType}, * {@link TopicSpecification TopicSpecification}, and * {@link UnsubscribeReason UnsubscribeReason} * @namespace diffusion.topics * * @module diffusion.topics */ /** * A type containing information about the reason for an unsubscription */ export declare class UnsubscribeReason { /** * The unsubscribe reason's id * * @deprecated since 6.8 *

              * This member is deprecated and will be removed in the future. */ readonly id?: number; /** * The unsubscribe reason's description * * @deprecated since 6.8 *

              * This member is deprecated and will be removed in the future. */ readonly reason: string; /** * Create a `UnsubscribeReason` * * @param id the unsubscribe reason's id * @param reason the unsubscribe reason's description */ constructor(id: number | undefined, reason: string); } /** * Enum containing reasons that an unsubscription occurred. * * **Example:** * ``` * // Use UnsubscribeReason to validate unsubscription notifications * session.addStream('>foo', diffusion.datatypes.string()) * .on('unsubscribe', function(topic, specification, reason) { * switch (reason) { * case diffusion.topics.UnsubscribeReason.REMOVED : * // Do something if the topic was removed * default : * // Do something else if the client was explicitly unsubscribed * } * }); * ``` */ export declare const UnsubscribeReasonEnum: { [key: string]: UnsubscribeReason; }; /** * A type containing information about the reason for failure of an update */ export declare class UpdateFailReason { /** * The update fail reason's id * * @deprecated since 6.8 *

              * This member is deprecated and will be removed in the future. */ readonly id?: number; /** * The update fail reason's description * * @deprecated since 6.8 *

              * This member is deprecated and will be removed in the future. */ readonly reason: string; /** * Create a `UpdateFailReason` * * @param id the update fail reason's id * @param reason the update fail reason's description */ constructor(id: number | undefined, reason: string); } /** * The reason that a topic could not be updated. * * **Example:** * ``` * session.topics.update('foo', 'bar').then(function() { ... }, function(err) { * switch (err) { * case diffusion.topics.UpdateFailReason.MISSING_TOPIC: * ... * case diffusion.topics.UpdateFailReason.EXCLUSIVE_UPDATER_CONFLICT: * ... * } * }); * ``` */ export declare const UpdateFailReasonEnum: { [key: string]: UpdateFailReason; }; /** * A type containing information about the reason for failure of adding a topic */ export declare class TopicAddFailReason { /** * The topic add failure reason's id * * @deprecated since 6.8 *

              * This member is deprecated and will be removed in the future. */ readonly id?: number; /** * The topic add failure reason's description * * @deprecated since 6.8 *

              * This member is deprecated and will be removed in the future. */ readonly reason: string; /** * Create a `TopicAddFailReason` * * @param id the topic add failure reason's id * @param reason the topic add failure reason's description */ constructor(id: number | undefined, reason: string); } /** * The reason that a topic could not be added. * * **Example:** * ``` * session.topics.add('foo').then(function() { ... }, function(err) { * switch (err) { * case diffusion.topics.TopicAddFailReason.EXISTS: * ... * case diffusion.topics.TopicAddFailReason.INVALID_NAME: * ... * } * }); * ``` * */ export declare const TopicAddFailReasonEnum: { [key: string]: TopicAddFailReason; }; export interface TopicsNamespace { FetchRequest: typeof FetchRequest; TopicType: typeof TopicType; TopicSpecification: typeof TopicSpecification; UnsubscribeReason: typeof UnsubscribeReasonEnum; UpdateFailReason: typeof UpdateFailReasonEnum; TopicAddFailReason: typeof TopicAddFailReasonEnum; } export declare const topicsNamespace: TopicsNamespace; /** * @module diffusion */ /** * An enum for the available log levels * * Accessible through `diffusion.LogLevel`. */ export declare enum LogLevel { trace = "trace", debug = "debug", info = "info", warn = "warn", error = "error", silent = "silent" } /** * @module diffusion.datatypes */ /** * Binary data type. * * Accessed via: * `diffusion.datatypes.binary();` * * The implementation provides support for binary deltas. * * {@link Binary} values can be used to store and transmit arbitrary * information. The responsibility for formatting and interpreting the * information belongs solely to the application. Before using Binary for a * topic, consider other data types such as {@link JSON JSON} or * single value topic types; these may provide a simpler interface for * your application. * * The implementation provides support for {@link BinaryDelta binary deltas}. * * {@link Binary} values are created by passing a `Uint8Array` object to {@link * BinaryDataType.from}. When running the Diffusion Client in a browser context, * access to the `Uint8Array` api is made available through * [diffusion.buffer](../globals.html#buffer). * * @since 5.7 */ export interface BinaryDataType extends DataType { /** * The Binary data type value class */ Binary: new (value: Uint8Array) => Binary; /** * Returns a new {@link Binary} instance from a buffer. * * @param buffer The binary data * @return A Binary data-type instance * @throws an {@link IllegalArgumentError} if the data is not a valid Binary */ from(buffer: Uint8Array): Binary; } /** * @module diffusion.datatypes */ /** * Delta that represents the difference between two binary values. * * {@link DataType} implementations that support binary deltas by returning a * delta type implementation as the result of a diff operation * {@link Binary.diff diff}. Two values of such a data type can be diffed to * create a binary delta. The binary delta can later be applied to the first * value to calculate the second value. * * @since 5.7 */ export interface BinaryDelta { /** * Whether this delta contains any changes. * * @returns if the delta contains changes */ hasChanges(): boolean; } /** * @module diffusion.datatypes */ /// /** * A read-only binary value with support for binary deltas. * * Values are effectively immutable. Instances can be backed by * {@link BinaryDataType.from user-supplied buffers}. * Once a Binary has been constructed around a buffer, care must * be taken not to modify the data in the buffer because doing * so would violate immutability. * * @since 5.7 */ export interface Binary extends Bytes { /** * Get the value as a Buffer. * * @return the buffer value * * @deprecated since version 6.11. Buffer has been replaced by Uint8Array. * Use getArray instead. This will be removed * in a future release. */ get(): Buffer; /** * Get the value as a Uint8Array. * * @return the array value */ getArray(): Uint8Array; /** * Compare this Binary value with an earlier version to create a delta. * * Convenient equivalent to: * `diffusion.datatypes.binary().deltaSupport(type).diff(original, this);` * * Buffers stored in a `Uint8Array` may also be provided as the value to diff instead of a * {@link Binary} instance. * * **Example:** * * Node.js: * ``` * const delta = binaryValue.diff(Buffer.from('Hello world')); * ``` * * Browser: * ``` * const delta = binaryValue.diff(new TextEncoder().encode('Hello World')); * ``` * * @param original the value to diff against this * @param type the type of delta to generate (default: `binary`); * @return a delta representing the difference between this and the provided value */ diff(original: Binary | Uint8Array, type?: string): BinaryDelta; /** * Apply a delta to this Binary value to create a new value. * * Convenient equivalent to: * `diffusion.datatypes.binary().deltaSupport(delta).apply(this, delta);` * * @param delta the binary delta to apply to this value * @return a new instance derived from applying the delta to this value * @throws an {@link InvalidDataError} if the delta is invalid */ apply(delta: BinaryDelta): Binary; } /** * @module diffusion.datatypes */ /** * JSON data type. * * Accessed via: * `diffusion.datatypes.json();` * * The JSON Data Type provides {@link JSON} values, which * are a wrapper around native JSON objects. * * For efficiency, the JSON value is serialized in binary form following * the CBOR specification. * * The implementation provides support for binary deltas. * * JSON instances defer parsing of underlying binary data until required. If the * data is not valid, an Error may be thrown when {@link JSON.get} is called. * * @since 5.7 */ export interface JSONDataType extends DataType { /** * The JSON data type value class */ JSON: new (value: any) => JSON; /** * Returns a new {@link JSON} instance from a native JS object. * * Passing a string will produce a JSON instance encoding a single string * token. To produce a JSON datatype instance from a JSON string, use {@link * JSONDataType.fromJsonString} instead. * * This is useful in cases where providing the raw value may be ambiguous * for SDK methods that infer the datatype from provided arguments, such as * {@link Messages.sendRequest}. * * **Example:** * ``` * // Value from object * var value = jsondatatype.from({ * foo : "bar", * baz : [1, 2, 3] * }); * ``` * * **Example:** * ``` * // Datatype instance from string * var value = jsondatatype.from("this is a simple string"); * ``` * * @param object the object data * @return a JSON data-type instance */ from(object: any): JSON; /** * Returns a new {@link JSON} instance from a JSON * string. * * Precision for numeric types is lost in the translation to the internal * CBOR binary form and non-significant white space is not preserved. * * **Example:** * ``` * // Datatype instance from a JSON string. * var value = jsondatatype.fromJsonString("{\"foo\" : \"bar\"}"); * * // The value contains the parsed object representation * value.get(); // => { foo : "bar" } * ``` * * @param json the JSON string * @return a JSON data-type instance * * @since 5.9 */ fromJsonString(json: string): JSON; } /** * Alias for the JSONDataType interface to keep compatibility with old TypeScript definitions */ export declare type JsonDataType = JSONDataType; /** * @module diffusion.datatypes */ /** * An unmodifiable map describing the changes to a JSON value. * * The {@link JSONDelta.inserted} method returns a * {@link ChangeMap ChangeMap} describing the parts * of the second JSON value not found in the first JSON value. Similarly, * {@link JSONDelta.removed} * returns a `ChangeMap` describing the parts of the first JSON value * not found in the second JSON value. * * The map contains an entry for each change, as follows: * * The key is a JSON * Pointer syntax reference locating the change in the complete value. * Since a JSON value is a list of zero or more data items, the reference * always begins with an array index. For example, the first part is * identified by the JSON Pointer `/0`. * * The value is part of the complete value. It is returned as a parsed * value. * * An error will be thrown if an invalid JSON pointer expression is passed to * {@link ChangeMap.get get}, * {@link ChangeMap.containsKey containsKey}, * {@link ChangeMap.descendants descendants}, or * {@link ChangeMap.intersection intersection}. This only * occurs if the expression does not start with `/` and is not empty. */ export interface ChangeMap { /** * Retrieve a value from this change map, identified by a JSON Pointer. * * @param pointer the JSON Pointer expression * @returns the change map value, if it exists, otherwise null * @throws an {@link IllegalArgumentError} if pointer is an invalid JSON Pointer expression */ get(pointer: string): any; /** * Determines if this change map contains an entry for a given JSON Pointer * * @param pointer the JSON Pointer expression * @returns `true` if an entry exists, false if not * @throws an {@link IllegalArgumentError} if pointer is an invalid JSON Pointer expression */ containsKey(pointer: string): boolean; /** * Returns an array of map entries. Each entry is in the form of a key/value object pair. * * The key is a JSON Pointer expression, in string form. The value will be parsed from the * underlying {@link JSON} object. * * @returns the entry array * * **Example:** * ``` * changeMap.entrySet().forEach(function(entry) { * console.log(entry.key, entry.value); * }); * ``` */ entrySet(): Array<{ key: string; value: string; }>; /** * Returns a view of the portion of this map whose keys are descendants * of `pointer`. If `pointer` is contained in this map, it * will be included in the result. * * @param pointer the json pointer expression to derive descendants for * @returns changemap of descendant changes * @throws an {@link IllegalArgumentError} if pointer is an invalid JSON Pointer expression */ descendants(pointer: string): ChangeMap; /** * Returns a view of the portion of this map whose keys are descendants * or parents of `pointer`. If `pointer` is contained in * this map, it will be included in the result. * * This method can be used to determine whether a structural * delta affects a particular part of a JSON value. For example: * * ``` * if (structuralDelta.removed().intersection("/contact/address").length) { * // The structural delta removes elements that affect '/contact/address'. * } * if (structuralDelta.inserted().intersection("/contact/address").length) { * // The structural delta inserts elements that affect '/contact/address'. * } * ``` * * @param pointer the json pointer expression to derive intersection for * @returns changemap of intersection changes * @throws an {@link IllegalArgumentError} if pointer is an invalid JSON Pointer expression */ intersection(pointer: string): ChangeMap; } /** * Structural delta type for {@link JSON}. * * A JSONDelta describes the differences between two JSON values. Unlike a * {@link BinaryDelta binary delta}, a * structural delta can be queried to determine its effect. The * {@link JSONDelta.removed removed} and * {@link JSONDelta.inserted inserted} methods provide full * details of the differences between the two values. *

              * An instance can be created from two JSON values using * {@link JSON.jsonDiff}. * * JSONDeltas are useful for identifying small changes to complex JSON values. * Here's an example of how to use this class to filter interesting changes in * a ValueStream. * * ``` * const valueStream = session.addStream('foo/bar', diffusion.datatypes.json()); * valueStream.on('value', (topicPath, oldValue, newValue) => { * const delta = newValue.diff(oldValue); * * if (!delta.removed().intersection('/address').isEmpty() || * !delta.inserted().intersection('/address').isEmpty()) { * * // The 'address' field has changed. * processAddress(newValue); * } * } * * // ... * } * ``` * * @author DiffusionData Limited * @since 5.9 */ export interface JSONDelta { /** * Returns the parts of the first JSON value not found in the second JSON * value. * * @return the removed parts. The JSON Pointer references used for the * keys are relative to first JSON value. */ removed(): ChangeMap; /** * Returns the parts of the second JSON value not found in the first JSON * value. * * @return the removed parts. The JSON Pointer references used for * the keys are relative to second JSON value. */ inserted(): ChangeMap; /** * Returns whether the two JSON values used to create this instance are * different. * * @return `true` if this delta has an effect */ hasChanges(): boolean; } /** * @module diffusion.datatypes */ /** * Immutable JSON data. The value is stored internally as a buffer. * * JSON is "JavaScript Object Notation", a lightweight data-interchange format. * See www.json.org. * * To create an instance from an object, obtain a {@link JSONDataType} * implementation from `diffusion.datatypes.json()` and call {@link * JSONDataType.from}. * * The encapsulated value can be accessed by calling {@link JSON.get}. * *

              CBOR representation

              * * Internally the value is stored and transmitted not as a JSON string, but in * CBOR format to reduce memory and network overhead. CBOR (Concise Binary * Object Representation) is a standardized format for binary representation of * structured data defined by RFC * 7049. See www.cbor.io. * * Rather than working with JSON strings it is possible, and usually preferable, * for applications to work directly with the underlying CBOR-format binary * representation. This avoids creating intermediate JSON strings, and allows * access to CBOR features such as the byte string data type. * * Each JSON value is represented as a single CBOR data item. CBOR supports * composite data types just like JSON, so this data item can be an array or a * map of other data items. The JSON `null` value is represented by the * CBOR `null` value. * * A particular advantage of working directly with the CBOR-format data is that * binary data can be written to the value as a data item using the CBOR byte * string type. The data item will be stored as part of the JSON value in binary * form and transmitted without further conversion. * * @since 5.7 */ export interface JSON extends Bytes { /** * Get this instance's value. Use this method to access the provided data when a * {@link JSON} instance is received through the API. * * **Example:** * ``` * session.addStream('foo', diffusion.datatypes.json()) * .on('value', function(path, spec, value) { * // Get the actual value from the JSON instance * const data = value.get(); * }); * ``` * * @return the JSON value * @throws an {@link InvalidDataError} if the value cannot be read */ get(): any; /** * Compare this JSON value with an earlier version to create a delta. * * Convenient equivalent to: * `diffusion.datatypes.json().deltaType(type).diff(original, this);` * * Standard JSON objects may also be provided as the value to diff instead * of a {@link JSON} instance. * * **Example:** * ``` * const binaryDelta = jsonValue.diff({ foo : 'bar' }); * ``` * * **Example:** * ``` * const jsonDelta = jsonValue.diff({ foo : 'bar' }, 'json'); * ``` * * @param original the value to diff against this * @param type the type of delta to generate (default = 'binary') * @return a delta representing the difference between this and the provided value * @throws an {@link InvalidDataError} if the type is `json` but the diff could not be parsed */ diff(original: any, type?: string): BinaryDelta | JSONDelta; /** * Compare this JSON value with an earlier version to create a structural * {@link JSONDelta json delta}. * * Convenient equivalent to: * `this.diff(original, 'json');` * * Standard JSON objects may also be provided as the value to diff instead * of a {@link JSON} instance. * * **Example:** * ``` * const delta = jsonValue.jsonDiff({ foo : 'bar' }); * ``` * * @param original the value to diff against this * @return a delta representing the difference between this and * the provided value */ jsonDiff(original: any): JSONDelta; /** * Apply a delta to this JSON value to create a new value. * * Convenient equivalent to: * `diffusion.datatypes.JSON().deltaType(delta).apply(this, delta);` * * @param delta the binary delta to apply to this value * @return a new instance derived from applying the delta to this value * @throws an {@link InvalidDataError} if the delta is invalid */ apply(delta: BinaryDelta): JSON; } /** * Alias for the JSON interface to keep compatibility with old TypeScript definitions */ export declare type Json = JSON; /** * @module diffusion.datatypes */ /** * Double data type. * * Accessed via: * `diffusion.datatypes.double();` * * Provides a data type implementation which supports double float (native * JavaScript Number) values. The double value is serialized in CBOR-format * binary. * * This data type supports null double values. * * @since 6.0 */ export interface DoubleDataType extends DataType { } /** * @module diffusion.datatypes */ /** * A type that can be converted to an int64 */ export declare type Int64SourceType = string | number | Uint8Array | Int64; /** * Int64 data type. * * Accessed via: * `diffusion.datatypes.int64();` * * Provides a data type implementation which supports {@link Int64 64-bit signed * integer} values. The Int64 value is serialized in CBOR-format binary. * * This data type supports null Int64 values. * * @since 6.0 */ export interface Int64DataType extends DataType { /** * The Int64 data type value class */ Int64: new (value: string | number | Uint8Array, radix?: number) => Int64; } /** * @module diffusion.datatypes */ /** * Signed 64-bit integer. Provides a means to read integer values larger than * supported natively by JavaScript. * * Used as the value type of the Int64 data type: * ``` * var datatype = diffusion.datatypes.int64(); * var value = new datatype.Int64("9223372036854775807"); * ``` * * @since 6.0 */ export interface Int64 { /** * Read this value as a string. * * @param radix the radix to use. Defaults to base `10`. * @return the string representation of the int64 value. */ toString(radix?: number): string; /** * Read this value as a number. The validity of the returned number can only be guaranteed for values up to * `Math.pow(2, 53) - 1` due to underlying platform limitations of JavaScript. * * @return the numerical value of this int64, as a 53-bit integer. */ toNumber(): number; } /** * @module diffusion.datatypes */ /** * A type that can be converted to a string */ export declare type StringSourceType = string | { toString: () => string; }; /** * String data type. * * Accessed via: * `diffusion.datatypes.string();` * * Provides a data type implementation which supports string values. The string value is serialized in CBOR-format * binary. * * This data type supports null string instances. * * @since 6.0 */ export interface StringDataType extends DataType { } /** * @module diffusion.datatypes.RecordV2 */ /** * This is a mutable data model of {@link RecordV2} data * based upon a {@link Schema}. * * An initial version of such a model can be created from a schema using the * {@link Schema.createMutableModel} method. A * model created in this way will have all mandatory fields set to default * values. * * The model may then be updated as required and then at any time a {@link * RecordV2} object can be generated from the current state using the {@link * MutableRecordModel.asValue asValue} method. The {@link RecordV2} object may * then be used to update a topic. * * When values for integer or decimal type fields are supplied the values are * validated and normalized. All number values will have any insignificant * leading zeroes removed. A decimal value will also be rounded to its specified * scale. * * All mutator methods return the model so that calls can be chained. * * @since 6.0 */ export interface MutableRecordModel extends RecordModel { /** * Set a field value. * * This allows an item to be addressed using a key of the form * `recordName(recordIndex).fieldName(fieldIndex)`. Indexes may be omitted * in which case `0` is assumed. * * **Example:** * ``` * // Get field value with record & field names and indices * var value = model.set("record", 0, "field", 0, "foo"); * ``` * * @param recordName the name of the record * @param recordIndex the index of the record * @param fieldName the name of the field * @param fieldIndex the index of the field * @param value the value to be set * @return this model * * @throws an {@link IllegalArgumentError} if `recordName` is invalid * @throws an {@link OutOfBoundsError} if `recordIndex` or `fieldIndex` is out of range * @throws an {@link SchemaViolationError} if a record or field was requested that * does not exist in the schema */ set(recordName: string, recordIndex: number, fieldName: string, fieldIndex: number, value: string): MutableRecordModel; set(recordName: string, fieldName: string, value: string): MutableRecordModel; set(recordName: string, value: string): MutableRecordModel; /** * Adds new values to the end of a variable length field list. * * This can only be used for a variable multiplicity field which can only be * the last field in a record and therefore the field does not need to be * named. * * If the record name and index are not supplied, this will add values to the last * record in the model. If the model's schema does not specify a variable last field * or record, an error will be thrown. * * @param recordName the name of the record * @param recordIndex the index identifying the occurrence of the record * @param values the values to add * @return this model * * @throws a {@link SchemaViolationError} if adding the values would violate the schema */ add(recordName: string, recordIndex: number, ...values: string[]): MutableRecordModel; add(recordName: string, ...values: string[]): MutableRecordModel; /** * Adds a new initialized record occurrence to the end of a variable * multiplicity record list. * * As the only variable multiplicity record can be the last one there is no * need to name the record. This method will add to the list of occurrences * of the last defined record. The record will be initialized with default * values appropriate to the schema definition and may then have individual * field items set separately. * * @return this model * @throws a {@link SchemaViolationError} if adding a record would violate the schema */ addRecord(): MutableRecordModel; /** * Removes the specified occurrence of a variable multiplicity record. * * A variable multiplicity record must be the last or only record within a * schema and therefore the record name is not required. * * @param index the index of the record to remove * @return this model * * @throws an {@link IllegalArgumentError} if the index is out of range * @throws a {@link SchemaViolationError} if removing the record would violate the schema */ removeRecord(index: number): MutableRecordModel; /** * Removes the specified occurrence of a variable multiplicity field. * * A variable multiplicity field must be the last or only field within a * record and therefore the field name is not required. * * @param recordName the name of the record * @param recordIndex the record index * @param fieldIndex the index of the field to remove * @return this model * * @throws an {@link IllegalArgumentError} if one of the indices is out of range * @throws a {@link OutOfBoundsError} if `recordIndex` or `fieldIndex` is out of range * @throws a {@link SchemaViolationError} if removing the field would violate the schema */ removeField(recordName: string, recordIndex: number, fieldIndex: number): MutableRecordModel; } /** * @module diffusion.datatypes.RecordV2 */ /** * Builds free format {@link RecordV2 RecordV2 value}. * * This type of builder may be used to generate free format {@link RecordV2} * data which is not constrained by a {@link Schema}. * * A builder can be created using {@link RecordV2DataType.valueBuilder}. * * @since 6.0 */ export interface RecordV2Builder { /** * Adds one or more field values. * * If there is a current record, this adds the fields to the end of the * current record. * * @param values field values * @return this builder */ addFields(fields: string[]): RecordV2Builder; addFields(...fields: string[]): RecordV2Builder; /** * Adds a new record comprising the specified field values. * * @param fields the fields within the new record. If no fields are * supplied, an empty record will be added. * @return this builder */ addRecord(fields: string[]): RecordV2Builder; addRecord(...fields: string[]): RecordV2Builder; /** * Clears all current values from the builder allowing it to be reused to * generate new data. * * @return this builder */ clear(): void; /** * Builds a {@link RecordV2} object from the current * builder state. * * @return a new {@link RecordV2} object */ build(): RecordV2; } /** * @module diffusion.datatypes.RecordV2 */ /** * Record-based data type. * * This provides the ability to handle data in Diffusion proprietary 'record' * format. This format allows string data to be organized into 'records' which * in turn are made up of 'fields'. Each field is a string but may be handled as * either an integer or a decimal field if required. * * This format is compatible with legacy RECORD topics (removed in release 6.2) * and therefore can be used to migrate client applications from using such * topics with minimal change to the application. * * The data can either be free format or constrained by a {@link Schema}. * * In free format mode, no schema is associated with the data and the data will * contain zero or more records, each comprising zero or more fields. In this * mode the meaning of each field is entirely up to the application and no * validation will be performed by Diffusion, either in the client library, or * at the server. To write free format records, a {@link RecordV2Builder} can be * used to create a [RecordV2](recordv2.html) object. Such a builder may be * created using the {@link RecordV2DataType.valueBuilder} method. * * When using a {@link Schema} then the permitted records and fields are defined * by the schema. The schema names the records and the fields within them and * provides a mechanism for direct access to the fields. The schema is also used * to validate the data to ensure it complies with the schema definition. * * In schema mode, data can be created and updated using a {@link * MutableRecordModel} which allows records and fields to be conveniently set * and updated by name. A base model can be created from a schema using the * {@link Schema.createMutableModel} method. The model can at any time be used * to create a new [RecordV2](recordv2.html) object. A consumer of a * [RecordV2](recordv2.html) value can read it as a {@link RecordModel} by * simply using the {@link RecordV2.asModel} method to produce an immutable * representation of the data. When creating the data using a {@link * MutableRecordModel} then the model ensures that the data is valid and * therefore there is no need for the server or the consuming client to validate * the data. * * Schemas can be parsed from JSON strings or more simply using a {@link * SchemaBuilder} obtained using the {@link RecordV2DataType.schemaBuilder} * method. A schema can be bound to a [RecordV2](recordv2.html) data type * instance using the method {@link RecordV2DataType.withSchema}. This method * will return a new RecordV2DataType instance with the schema bound to it for * validation. * * A [RecordV2](recordv2.html) object can only be validated within the context * of a {@link Schema}. * * Accessed via: * `diffusion.datatypes.recordv2();` * * @since 6.0 */ export interface RecordV2DataType extends DataType { /** * The RecordV2 data type value class */ RecordV2: new (...args: any[]) => RecordV2; /** * Bind a specific schema to a {@link RecordV2DataType} * instance. * * @param schema schema to bind to the data type * @return a {@link RecordV2DataType} bound to a * specific schema */ withSchema(schema: Schema): RecordV2DataType; /** * Parse a schema from a JSON string. * * @param json json string containing a schema definition * @return the schema */ parseSchema(json: string): Schema; /** * Creates a new {@link RecordV2Builder}. * * Such a builder may be used to generate a free format [RecordV2](recordv2.html) * format value that is not constrained by a {@link Schema}. * * @return a new records builder */ valueBuilder(): RecordV2Builder; /** * Creates a new schema builder. * * @return a new schema builder */ schemaBuilder(): SchemaBuilder; } /** * @module diffusion.datatypes.RecordV2 */ /** * Represents a single change to a Record value. */ export interface Change { /** * The name of the affected record */ readonly recordName: string; /** * The index of the affected record */ readonly recordIndex: number; /** * The name of the affected field */ readonly fieldName: string; /** * The index of the affected field */ readonly fieldIndex: number; /** * Returns the string key representation of the affected item in * the form `recordName(recordIndex).fieldName(fieldIndex)`. */ readonly key: string; /** * String denoting the type of change that this represents */ readonly type: string; } /** * {@link RecordV2} structural delta. * * A RecordV2Delta describes the differences between two {@link RecordV2} * values. Unlike a {@link BinaryDelta binary delta}, a structural delta * can be queried to determine its effect. The * {@link RecordV2Delta.changes} method provides details of which values * have changed. * * An instance can be created from two RecordV2 values using * {@link RecordV2.diff}. * * RecordV2Deltas are useful for identifying small changes to complex RecordV2 * values. Here is an example of how to use this class to filter interesting * changes from a value stream. * * **Example:** * ``` * var datatype = diffusion.datatypes.recordv2(); * * session.addStream("topic", datatype).on('value', (path, spec, newValue, oldValue) => { * var schema = datatype.parseSchema(spec.properties.SCHEMA); * * newValue.diff(oldValue).changes(schema).forEach((change) => { * if (change.fieldName === "address") { * // Do something with the changed address * console.log(newValue.getFields()); * } * }); * }); * ``` * * @author DiffusionData Limited * @since 6.0 * @see diffusion.datatypes.RecordV2.diff */ export interface RecordV2Delta extends Bytes { /** * Returns a list of the changes represented by the delta with reference to * a specified schema. * * The schema supplied must comply with the data format of the delta. No * validation takes place, so if the schema does not match the data then the * results may be unpredictable. * * @param schema the schema * @return the list of changes * @throws an {@link SchemaViolationError} if the schema is not compatible with the delta */ changes(schema: Schema): Change[]; } /** * @module diffusion.datatypes.RecordV2 */ /** * {@link RecordV2} data model. * * A read only model can be created from any {@link RecordV2} object using the * {@link RecordV2.asModel asModel} method. The model then provides direct * access to the fields within the data. Fields may be accessed either by * explicitly specifying the record and field occurrence or by specifying a key * of the form: * * ``` * recordName(recordIndex).fieldName(fieldIndex) * ``` * * Indexes start from 0 and if omitted then 0 is assumed. The record name may * also be omitted, in which case the first record definition is accessed. This * form of addressing is useful when there is only one record definition. * * So valid keys are: * * Key | Description * ---------------------------| -------------------- * `Address(4).AddressLine(3)`| The 4th `AddressLine` occurrence within the 5th `Address` record * `Address.Name` | The first (or only) `Name` field within the first (or only) `Address` record * `AddressLine(1)` | The 2nd `AddressLine` field within the first (or only) record * `Name` | The first (or only) `Name` field within the first (or only) record * * The {@link RecordModel.recordCount} and * {@link RecordModel.fieldCount} methods are useful for * determining the actual number of occurrences of variable multiplicity items. * * @since 6.0 */ export interface RecordModel { /** * Get a field value. * * This allows an item to be addressed using a key of the form * recordName(recordIndex).fieldName(fieldIndex). Indexes may be omitted in * which case `0` is assumed. * * **Example:** * ``` * // Get field value with record & field names and indices * const value = model.get("record", 0, "field", 0); * * // Get field value with key * const value = model.get("Address.Name"); * ``` * * @param recordKey the key addressing the record * @param recordName the name of the record * @param recordIndex the index of the record * @param fieldName the name of the field * @param fieldIndex the index of the field * @return the field value * * @throws an {@link IllegalArgumentError} if `recordName` can not be parsed * @throws an {@link OutOfBoundsError} if `recordIndex` or `fieldIndex` is out of range * @throws an {@link SchemaViolationError} if a record or field was requested that * does not exist in the schema */ get(recordName: string, recordIndex: number, fieldName: string, fieldIndex?: number): string | null; get(recordName: string, fieldName: string, fieldIndex?: number): string | null; get(recordKey: string): string | null; /** * Creates an immutable {@link RecordV2} object * generated from the model. * * @return a new immutable instance */ asValue(): RecordV2; /** * Returns the actual number of occurrences of a named field within a * specified record. * * For all but variable fields this simply returns the schema defined number * of occurrences of the field. * * @param recordName the record name * @param recordIndex the record index * @param fieldName the field name * @return the actual number of occurrences of the field * * @throws an {@link SchemaViolationError} if a record or field was requested that * does not exist in the schema */ fieldCount(recordName: string, recordIndex?: number, fieldName?: string): number; /** * Returns the actual number of occurrences of a named record. * * If the record is not variable, this is the same as the defined number of * occurrences in the schema * * @param recordName the record name * @return the actual number of occurrences of the record */ recordCount(recordName: string): number; } /** * @module diffusion.datatypes.RecordV2 */ /** * An immutable value representing a list of records. * * See {@link RecordV2DataType} for details * * @since 6.0 */ export interface RecordV2 extends Bytes { /** * Compare this value with an earlier version to calculate a structural * delta. * * @param original the original value to compare with this value * @return a structural delta representing the difference between * the original and this value */ diff(original: RecordV2): RecordV2Delta; /** * Parses the content into a model based upon a specified schema. * * This assumes that data is compatible with the schema and does not do any * validation. There is no need to validate the data if this has been done * on entry or at the server. However, if the data is invalid then issues * may occur when attempting to access it. * * If it is not certain that the data is valid then the {@link * asValidatedModel} method may be used instead. * * @param schema the schema to use for parsing the data * @return an immutable model derived from the data content */ asModel(schema: Schema): RecordModel; /** * Parses the content into a model based upon a specified schema. * * The data is validated against the schema * * @param schema the schema to use for parsing the data * @return an immutable model derived from the data content * * @throws an {@link InvalidDataError} if the model data is found to be invalid when validated against the schema */ asValidatedModel(schema: Schema): RecordModel; /** * Returns the data content as an Array of Arrays of strings. * * **Example:** * ``` * // Iterate across each record's fields * value.asRecords().forEach((record) => { * record.forEach((field) => { * console.log("Field value: " + field); * }); * }); * ``` * * @return a new mutable list where each entry represents a record within the data */ asRecords(): string[][]; /** * Returns the data content as a list of fields. * * This disregards record boundaries. If there is more than one record, they * are concatenated to produce a list of all of the fields. * * This method would normally only be used when it is known that there is * only one record. * * @return a new mutable list of all the fields */ asFields(): string[]; } /** * @module diffusion.datatypes.RecordV2 */ /** * Used to build an immutable {@link Schema}. * * A schema defines the records and fields that may occur in a {@link RecordV2} topic * value. * * The schema must declare at least one record type and every record must have * at least one field type declared. * * Every record type and field type has a 'multiplicity' which defines the * number of times that the record or field may occur within the data. * Multiplicity is specified as a 'minimum' and 'maximum' number of occurrences * or where the minimum and maximum are the same (fixed multiplicity) then the * multiplicity may be specified as a single 'occurs' value. If the minimum and * maximum are different, this is referred to a 'variable' multiplicity. Only * the last record declared or the last field within a record may have variable * multiplicity. The maximum value may be declared as -1 to indicate that the * record or field can have an unlimited number of occurrences. * * The builder is used to add a record definition followed by the fields within * it. After all fields have been added to a record another may then be added, * and so on, and then finally {@link SchemaBuilder.build build()} is called to create * an immutable schema object. * * Every call returns the builder instance allowing calls to be chained, for * example: * * ``` * const schema = builder.record('R1').string('S1').string('S2', 1, 5) * .record('R2', 0, -1).decimal('D', 5).build(); * ``` * * A builder is obtained using the {@link RecordV2DataType.schemaBuilder} * method. * * @since 6.0 */ export interface SchemaBuilder { /** * Add a new record to the schema * * The record added must not have the same name as a previously added record. * * A record may not be added after a record that has variable multiplicity (min != max) * * A record may not be added directly after another record which has had no fields added. * * @param name record name. This must not the same as any record already added * @param min=1 the minimum number of times the record should occur within the schema * @param max=1 the maximum number of times the record should occur within the schema. * May be either `-1` (indicating no upper limit) or a * positive value that is not less than * `min` * @return the builder instance * * @throws a {@link SchemaViolationError} if the record name or multiplicity is invalid */ record(name: string, min?: number, max?: number): SchemaBuilder; /** * Add a string field to the current record. * * A field may not be added after a field that has variable multiplicity (min != max) * * @param name field name. This must not the same as any field already added * @param min=1 the minimum number of times the field should occur within the record * @param max=1 the maximum number of times the field should occur within the record. * May be either `-1` (indicating no upper limit) or a * positive value that is not less than * `min` * * @throws a {@link SchemaViolationError} if the field name or multiplicity is invalid * */ string(name: string, min?: number, max?: number): SchemaBuilder; /** * Add an integer field to the current record. * * A field may not be added after a field that has variable multiplicity (min != max) * * @param name field name. This must not the same as any field already added * @param min=1 the minimum number of times the field should occur within the record * @param max=1 the maximum number of times the field should occur within the record. * May be either `-1` (indicating no upper limit) or a * positive value that is not less than * `min` * * @throws a {@link SchemaViolationError} if the field name or multiplicity is invalid */ integer(name: string, min?: number, max?: number): SchemaBuilder; /** * Add a decimal field to the current record. * * A field may not be added after a field that has variable multiplicity (min != max) * * @param name field name. This must not the same as any field already added * @param scale the scale of the field (number of decimal places). This must be strictly positive. * @param min=1 the minimum number of times the field should occur within the record * @param max=1 the maximum number of times the field should occur within the record. * May be either `-1` (indicating no upper limit) or a * positive value that is not less than * `min` * * @throws a {@link SchemaViolationError} if the field name or multiplicity is invalid */ decimal(name: string, scale: number, min?: number, max?: number): SchemaBuilder; /** * Build an immutable Schema. * * At least one record with at least one field must have been added to the * builder. * * @return a new immutable schema object representing the current state of * the builder * * @throws a {@link SchemaViolationError} if no records have been added to the schema. */ build(): Schema; } /** * @module diffusion.datatypes.RecordV2 */ /** * A Node in the schema definition */ export interface Node { /** * The node name */ name: string; /** * The minimum number of occurrences of the node within its parent */ min: number; /** * The maximum number of occurrences of the node within its parent */ max: number; /** * Flag that indicates if the node has variable multiplicity, or has fixed * multiplicity */ isVariable: boolean; } /** * A field node in the schema definition */ export interface Field extends Node { /** * An optional scale definition for decimal field types */ scale?: number; } /** * A record node in the schema definition */ export interface Record extends Node { /** * A list of the field definitions. There will be at least one */ fields: Field[]; } /** * A {@link RecordV2} schema. * * A schema describes data value format in terms of one or more record definitions. * A record definition describes the layout of a record and comprises one or more * field definitions. * * Within the data value there can be multiple occurrences of a record or * field described by a single definition. The defined (or allowed, when * describing variable numbers) number of occurrences of each definition is * referred to as its 'multiplicity'. The multiplicity can be fixed (the item * occurs a fixed number of times), or variable (the item occurs from a minimum * number of times to a maximum number of times). If a variable field is used it * must be the last in a record definition and if a variable record is used it * must be the last in the schema definition. * * A field may be defined as of type 'string', 'integer' or 'decimal'. A decimal * type has a further property of 'scale' which defines the number of digits to * the right of the decimal point. * * A schema can be obtained from {@link RecordV2DataType.parseSchema} or from a * {@link SchemaBuilder} * * @since 6.0 */ export interface Schema { /** * Returns an immutable, ordered list of record definitions. * * There will be at least one. * * @return a list of the record definitions in the schema */ getRecords(): Record[]; /** * Returns the schema in a JSON format * * @return schema in JSON format */ asJSON(): any; /** * Create a mutable model based upon the schema. * * The model will be created with all mandatory record occurrences and all * mandatory field occurrences initialized to default values. * * Such a model may be mutated and used to generate updated * {@link RecordV2} occurrences for updating purposes. * * @return a new initialized model */ createMutableModel(): MutableRecordModel; } export as namespace diffusion;