/** * 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 * Result} that will complete succesfully if a session can be connected, or * fail if an error was encountered. * * If the result is succesful, 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:** * ``` * diffusion.connect('example.server.com').then(function(session) { * // Connected with a session * console.log('Connected!', session); * }, function(error) { * // Connection failed * console.log('Failed to connect', error); * }); * ``` * * * @param options the options to construct the session with. * @returns a {@link Result} for this operation */ export declare function connect(options: Options): Result; /** * 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 * * @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; /** * Access to the datatypes namespace */ export declare const datatypes: DataTypes; /** * Access to the selectors namespace */ export declare const selectors: TopicSelectors; /** * 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; /** * @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 */ export declare type TypedArray = Int8Array | Int16Array | Int32Array | Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array | Float32Array | Float64Array; export declare type ReconnectStrategy = (reconnect: () => void, abort: () => void) => void; /** * 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. * *
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 | Buffer | TypedArray | number[]; /** * 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. * * For details of how session properties are used see {@link Session}. */ properties?: { [key: string]: string; }; /** * 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; } /** * 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; } /** * Diffusion Session. Handles a connection to Diffusion and exposes API * features. Sessions can subscribe, add, remove and update topics, as well as * perform remote operations on the server. * * A session represents a single connection to a single Diffusion server. A * session begins connected and will remain so until until it is explicitly * closed via {@link Session.close} or there is a connection error. * * When a connected session loses its connection to the server, it will close if * {@link Options} `reconnect` is not enabled. If reconnect is enabled * then the session will enter a `disconnected` state. Once disconnected, any * API methods that involve the server will automatically fail. It is possible * for a session to lose messages while disconnected. * * The session will attempt to reconnect to the server on a regular basis. This * will continue until the server responds; at which point the session will * attempt to recover its previous connection. * * If the reconnection is successful the session will become connected again and * emit a `reconnect` event. Any prior subscriptions will continue to receive * data. * * If the server rejects the reconnection, the session will be closed. * * Sessions emit events to notify listeners of changes in state. Certain events * will provide arguments to any callback functions that have been registered. * *

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 assigned by the application. * * Many operations use session filter expressions (see section Session Filters) * that use session properties to select sessions. * * A privileged client can monitor other sessions, including changes to their * session properties, using a {@link ClientControl.setSessionPropertiesListener * session properties 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
`$ClientIP`The Internet address of the client in string format. See * {@link ClientLocation}.address.
`$ClientType`The client type of the session. One of `ANDROID`, `C`, `DOTNET`, `IOS`, * `JAVA`, `JAVASCRIPT_BROWSER`, or `OTHER`. Equivalent to {@link * ClientSummary}.clientType.
`$Connector`The configuration name of the server connector that the client connected * to. See {@link SessionDetails}.connector.
`$Country`The 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. See {@link * ClientLocation}.details.country.
`$Language`The 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. See {@link ClientLocation}.details.language.
`$Latitude`The client's latitude, if available. This will be the string * representation of a floating point number and will be `NaN` if not * available. See {@link ClientLocation}.coordinates.latitude.
`$Longitude`The client's longitude, if available. This will be the string * representation of a floating point number and will be `NaN` if not * available. See {@link ClientLocation}.coordinates.longitude.
`$Principal`The security principal associated with the client session. Equivalent to * {@link ClientSummary}.principal
`$Roles`Authorisation 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.
`$ServerName`The name of the server to which the session is connected. See * {@link SessionDetails}.server.
`$SessionId`The session identifier. Equivalent to {@link Session.sessionID}.
`$StartTime`The session's start time in milliseconds since the epoch.
`$Transport`The session transport type. One of `WEBSOCKET`, * `HTTP_LONG_POLL`, or `OTHER`. Equivalent to * {@link ClientSummary}.transportType.
* * 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, 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. * * 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.changePrincipal * changePrincipal}), 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 query expressions for session properties. They can be * used to address a set of sessions based on their session properties. For * example, it is possible to send a message to all sessions that satisfy a * specified filter. Session filters are parsed and evaluated at the server. * * A session filter expression consists of either a single clause, or multiple * clauses connected by the binary operators `and` and `or`. The * `and` operator takes precedence over `or` but parentheses can be * used to override the precedence. For example: * * `Department is "Accounts"` * * `hasRoles ["operator" "trading desk"]` * * `Department is "Payroll" and Status is "Closed"}` * * `(Department is "Accounts" or Department is "Payroll") and Status is "Closed"}` * * The boolean not operator may be used to negate the following clause or * an expression within parentheses: * * `not Department is "Payroll"` * * `not (Department is "Payroll" or Department is "Accounts")` * * An equality clause has the form key operator value where * key is the name of a session property and value is the * property value. The supported operators are `is` or `eq`, both of * which mean "equals", and `ne` which means "does not equal". Values are * strings enclosed within single or double quotes. Special characters * (`"`, `'` or `\`) can be included within the value by * preceding with the escape character `\`. The utility method * {@link escape} can be used to insert escape characters into * a value. * * `hasRoles` is a special operator for querying the `$Roles` * session property. A `hasRoles` clause has the form hasRoles * ["role1" "role2" ... "roleN"]. The clause will match sessions that have * all the specified authorisation roles. Each role is a string enclosed within * either single or double quotes. Roles can be space or comma separated. * * The `all` operator matches all sessions. * * The `$Roles` session property can also be queried with an equality * clause, for example, `$Roles eq '"admin","client"'`, but the * `hasRoles` clause is usually more convenient. An equality clause will * match sessions that have exactly the listed roles. In contrast, a * `hasRoles` clause will match any sessions with the listed roles, * regardless of whether they have other roles. The equality clause requires the * value to be in the canonical form produced by the * {@link rolesToString} utility method. * Supported operators are as follows: * * Operator | Description * ---------------- | ----------- * **is** or **eq** | equals * **ne** | not equals * * All operators are case insensitive. * * The following are examples of valid expressions: * * * `$Principal is "Alice"` * * `Department is "Accounts" and $Country ne "US"` * * `$Language EQ "en" and $Country NE "US"` * * `not (Department is "Accounts" or` * * `"Department is "Payroll") and $Country is "FR"` * * `Text is "xyz\"\\"` * * `hasRoles ["operator"]}` * * `$Transport is "wss" and hasRoles ["accountancy" "administrator"]` * * `hasRoles ["operator"] and not hasRoles ["administrator"]` * * **Example:** * ``` * // Establish a session * diffusion.connect('diffusion.example.com').then(function(session) { * // Attach state listeners * session.on({ * disconnect : function() { * console.log('Disconnected!'); * }, * reconnect : function() { * console.log('Phew, reconnected!'); * }, * error : function(error) { * console.log('Session error', error); * }, * close : function(reason) { * console.log('Session closed', reason); * } * }); * * // Do something with session... * }); * ``` * *

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: string; /** * The connection options used to establish this session */ readonly options: Options; /** * Exposes system authentication capabilities via a {@link Session.security} */ readonly security: Security; /** * 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; /** * 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 Result} * that will completes when the session is closed. * * @return a {@link Result} that completes with the close reason returned * by the server. Only the {@link Result} of the first call to * `closeSession` is guaranteed to complete. The {@link Result} * will not resolve if the session is already closed. */ closeSession(): Result; /** * 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; /** * 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): Result; } /** * @module diffusion.clients */ /** * Details relating to the network and geographic location of a client session. */ export interface ClientLocation { /** * the IP address of the client */ address: string; /** * the host name */ hostname: string; /** * the resolved name */ resolved: string; /** * the country details */ details: { /** * the country code for the country where the IP address was allocated */ country: string; /** * the country code for the official language of the country where the * IP address was allocated */ language: string; }; /** * the geographic coordinates of the client if this could be ascertained */ coordinates?: { /** * the latitude */ latitude: number; /** * the longitude */ longitude: number; }; /** * the address type */ type: AddressType; } /** * Enum containing possible Address types. */ export declare enum AddressType { /** * The address is a standard global internet address */ GLOBAL = 1, /** * The address is a site local address. The address is part of the IP subset that is reserved for private networks. */ LOCAL = 2, /** * The address is assigned to the server loopback interface */ LOOPBACK = 3, /** * The address type is unknown */ UNKNOWN = 4, } /** * @module diffusion.clients */ /** * Lightweight summary of a client session. */ export interface ClientSummary { /** * The name of the principal associated with the session */ principal: string; /** * The type of the client */ clientType: ClientType; /** * The transport type */ transportType: TransportType; } /** * Enum containing possible client types. */ export declare enum ClientType { /** * JavaScript client */ JAVASCRIPT_BROWSER = 0, /** * Android client */ ANDROID = 3, /** * iOS client */ IOS = 4, /** * Java client */ JAVA = 8, /** * .NET client */ DOTNET = 9, /** * C */ C = 10, /** * Client type is not known to the local session, possibly because the remote client is using a different version * of Diffusion */ OTHER = 12, } /** * Enum containing possible Transport types. */ export declare enum TransportType { /** * WebSocket protocol */ WEBSOCKET = 0, /** * HTTP long polling transport */ HTTP_LONG_POLL = 1, /** * HTTP long poll, via HTML iFrame elements */ IFRAME_LONG_POLL = 2, /** * HTTP 1.1 chunked transfer via HTML iFrame elements */ IFRAME_STREAMING = 3, /** * Diffusion protocol based on TCP sockets */ DPT = 4, /** * Diffusion protocol based on HTTP 1.1 chunked transfer */ HTTPC = 5, /** * Diffusion protocol based on HTTP 1.1 chunked transfer */ HTTPC_DUPLEX = 6, /** * Transport type is not known to the local session, possible because the remote client is using a different version * of Diffusion */ OTHER = 7, } /** * A type containing information about the reason for a session being closed */ export interface CloseReason { /** * The close reason's id */ id: number; /** * The close reason's description */ 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; }; /** * @module diffusion.clients */ /** * A set of details relating to a client session. */ export interface SessionDetails { /** * available detail types */ available: DetailType[]; /** * the configuration name of the server connector the client is connected to, * or `undefined` if unavailable */ connector?: string; /** * server name or `undefined` if unavailable */ server?: string; /** * client location or `undefined` if unavailable */ location?: ClientLocation; /** * client summary or `undefined` if unavailable */ summary?: ClientSummary; } /** * Enum containing possible Session Detail types. */ export declare enum DetailType { SUMMARY = 0, LOCATION = 1, CONNECTOR_NAME = 2, SERVER_NAME = 3, } /// /** * @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 */ asBuffer(): Buffer; /** * 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: Buffer, 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 error if the data is invalid for this type */ readValue(input: Buffer, offset?: number, length?: number): ValueType | null; readValue(input: CBORType): ValueType | null; /** * Serialise a value to binary * * @param value the value to serialise * @returns the serialised value as a buffer * @throws an error if the value can not be serialised */ writeValue(value: SourceType): Buffer; /** * 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 error if `valueType` is incompatible with this data * type, or `buffer` does not * represent a valid value. * @since 6.0 */ readAs(valueType: new (...args: any[]) => any, buffer: Buffer, offset?: number, length?: number): any | null; readAs(valueType: new (...args: any[]) => any, buffer: CBORType): any | 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; } /** * @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 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 Error 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. * * 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 error 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: Buffer, 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 */ writeDelta(delta: BinaryDelta): Buffer; /** * 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; } /** * A type containing information about the reason that an error occured */ export interface ErrorReasonType { /** * The error reason's id */ id: number; /** * The error reason's description */ 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; }; /** * @module diffusion.events */ /** * Provides a stream of topic values for a given fetch request. * * FetchStream inherits all functions defined on {@link Stream}. * * **Example:** * ``` * // Handle all events from stream * session.fetch("foo").on({ * open : function() { * // Fetch stream has opened, values will be emitted after this event. * }, * value : function(value, topicPath) { * // Received topic value * }, * error : function(err) { * // Encountered an error * }, * close : function() { * // Fetch stream closed; no more values will be received * } * }); * ``` * *

Events

* *

open

* * Emitted when the fetch stream is initially opened. This will only be fired once. * *

value

* * Emitted when a topic that is selected by the fetch request's topic selector * has returned its value. By default, values are provided as * `Buffer` instances. The topic path specifies which topic this * value is for. * * **Parameters:** * * `value`: any - the new value of the topic * * `topicPath`: string - the path to the topic to which the value update applies * *

close

*

error

*/ export interface FetchStream extends Stream { } /** * @module diffusion.events */ /** * 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 Result if this method is called more than once. * * @returns a {@link Result} that completes when a response is received from * the server */ close(): Result; } /** * @module diffusion.events */ 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. * * Adapted from https://www.npmjs.com/package/@types/es6-promise */ 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 {@link 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() { ... } * }); * ``` * * @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 */ export interface SubscriptionEvent { /** * The topic to which the subscription applies */ topic: string; /** * Instance that contains details about the topic */ specification: TopicSpecification; } 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 */ 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; ROLES: string; } /** * @hidden */ export interface ClientControlOptionsNamespace { PropertyKeys: PropertyKeys; ANONYMOUS: string; ClientType: typeof ClientType; TransportType: typeof TransportType; AddressType: typeof AddressType; DetailType: typeof DetailType; CloseReason: typeof CloseReasonEnum; } export declare const ClientControlOptions: ClientControlOptionsNamespace; /** * @module Session.clients */ 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; * } * } * * // ... * }); * ``` */ 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, } /** * Client control feature. * * Provides the ability for a client session to control other client sessions. * * **Example:** * ``` * var clients = session.clients; * ``` */ export interface ClientControl { /** * Event types used within * {@link SessionPropertiesListener.onSessionEvent} */ readonly SessionEventType: typeof SessionEventType; /** * Close a client session. * * **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 sessionId identifies the client session to close * @return a {@link Result} for this operation. */ close(sessionId: string | SessionId): Result; /** * Subscribe one or more client sessions to topics. * * To subscribe a single known session, a session id may be provided; * alternatively, a Session Filter may be used, in which case all sessions * that satisfy the filter will be subscribed. * * 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 sesssions 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 the Session ID or Session Filter * @param selector the Topic Selector to subscribe to * @return a {@link Result} for this operation. If * subscribing with a session filter, the success callback * will be given the number of sessions selected by the * filter */ subscribe(session: string | SessionId, selector: string | TopicSelector | Array): Result; /** * Unsubscribe one or more client sessions from topics. * * To unsubscribe a single known session, a session id may be provided; * alternatively, a Session Filter may be used, in which case all sessions * 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 sesssions 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 the Session ID or Session Filter * @param selector the Topic Selector to unsubscribe from * @return a {@link Result} for this operation. If * unsubscribing with a session filter, the success * callback will be given the number of sessions selected * by the filter */ unsubscribe(session: string | SessionId, selector: string | TopicSelector | Array): Result; /** * 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 {@link Result} for this operation */ getSessionProperties(session: string | SessionId, properties?: string[]): Result; /** * Send a request to the server to change the user-defined session * properties for a session. * * **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. Otherwise if the property name * does not match any existing property, that entry will * be added as a new property. * @returns a {@link Result} 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. * */ setSessionProperties(session: string | SessionId, properties: SessionProperties | Map): Result; /** * Send a request to the server to set all sessions that satisfy a session * filter with the new user-defined session properties. * * **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. Otherwise if the property name does not match * any existing property, that entry will be added as a * new property. * * @returns a {@link Result} for this operation. 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. *
*/ setSessionPropertiesByFilter(filter: string, properties: SessionProperties | Map): Result; /** * Register a listener that will be notified when client sessions are * opened, disconnected, reconnected, closed or when selected session * property values are updated. * * 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 {@link Result} for this operation. */ setSessionPropertiesListener(properties: string[], listener: SessionPropertiesListener): Result; /** * 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 * @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 Result 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 Result fails with an Error. Common reasons for * failure include: *

    *
  • the calling session does not have `MODIFY_SESSION` and * `VIEW_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. *
* * @since 6.3 */ changeRoles(sessions: SessionId | string, rolesToRemove: string[] | Set, rolesToAdd: string[] | Set): Result; } /** * 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. */ 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. */ onActive(deregister: () => void): 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: {}): void; } /// /** * @module Session.messages */ /** * The priority of the message. Higher priorities are delivered faster. * * @deprecated since 6.2 * * This is only used within one-way messaging, which is deprecated * from this release. This enum will be removed in a future * release. */ export declare enum Priority { /** * Indicates that messages should be delivered with normal priority. */ NORMAL = 0, /** * Indicates that messages should be delivered with high priority. */ HIGH = 1, /** * Indicates that messages should be delivered with low priority. */ LOW = 2, } /** * Messages Feature. * * This feature provides a client session with messaging capabilities. Each * message is delivered to a request stream registered with the server. * Additionally, the server and other clients can send messages to be received * using this feature. * * Message requests are sent and received for a particular path. The message * path provides a hierarchical context for the recipient. * * Message paths are distinct from topic paths. A topic with the path need not * exist on the server; if a topic does exist, it is unaffected by messaging. An * application can use the same path to associate messages with topics, or an * arbitrary path can be chosen. * * A message request sent directly to another session is discarded if the * receiving session is no longer connected or does not have a stream that * matches the message path - an error is returned to the sending session in * this case. * * Handlers for receiving messages are registered for a path. Each session may * register at most one handler for a given path. When dispatching a message, * the server will consider all registered handlers and select one registered * for the most specific path. If multiple sessions have registered a handler * for the same path, one will be chosen arbitrarily. * * When registering handlers to receive messages it is also possible to indicate * that certain session properties (see {@link Session} for a full description * of session properties), should be delivered with each message from a client * session. The current values of the named properties for the originating * session will be delivered with the message. * * Messages can also be sent using 'filters', (see {@link Session} for a full * description of session filters), where the message is delivered to all * sessions that satisfy a particular filter expression. * * Messages from other clients are received via {@link RequestStream streams}. * Streams receive an {@link RequestStream.onClose onClose} callback when * unregistered and an {@link RequestStream.onError onError} callback if the * session is closed. * *

Request-Response Messaging

* * Typed request-response messaging allows applications to send requests (of * type T) and receive responses (of type R) in the form of a {@link Result}. * Using Messaging, applications send requests to paths using {@link * Messages.sendRequest sendRequest}. In order to receive requests, applications * must have a local request stream assigned to the specific path, using {@link * Messages.setRequestStream setRequestStream}. When a request is received, the * {@link RequestStream.onRequest onRequest} method on the stream is triggered, * to which a response can be sent using the provided {@link * Responder.respond respond} method call. * *

One-way Messaging (deprecated)

* * One-way messaging allows a client to send an untyped message to be sent to a * path and be notified that the message has been delivered. No response is * possible. * * A client can listen for one-way messages for a selection of paths by {@link * listen adding} one or more {@link MessageStream} implementations. The mapping * of selectors to message streams is maintained locally in the client process. * Any number of message streams for inbound messages can be added on various * selectors. * *

Access control

* * A client session needs {@link TopicPermission.SEND_TO_MESSAGE_HANDLER * SEND_TO_MESSAGE_HANDLER} permission for the message paths to which it sends * messages. If a client sends messages to a message path for which it does not * have permission, the message is discarded by the server. * *

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 { /** * The Priority enum */ readonly Priority: typeof Priority; /** * Send an arbitrary message to either the server or another session, on a * particular path. * * The path does not need to correspond to an existing topic; however the * use of `/` as a hierarchical delimiter allows for other sessions to * listen to messages from specific paths. * * The message content may be of any type that can be used for topic {@link * TopicControl.update updates}. It is up to any receiving session to * de-serialize it as appropriate. * * An optional argument may be provided to target a specific session or a * collection of sessions that satisfy a given filter string. Messages sent * will be received if that session has established a {@link MessageStream} * for the same message path. The ability to send messages to specific * sessions or via a filter is determined by permissions assigned to the * sender. * * If no session ID or filter is given, the message will be sent to the * server and dispatched to a control client that has registered a {@link * MessageHandler} for the same, or higher, path. There is no guarantee that * a MessageHandler will have been established for the path that the message * is sent on. * * If no recipient is specified, a successful result will resolve with a * single object containing the `path` that the message was sent to. * * If a session ID was used as the recipient, then the result will resolve * with an object containing both `path` and `recipient` fields. The result * will only resolve when the message has been successfully received by the * intended recipient. * * If a session filter was used to send the message, then the result will * contain `path`, `recipient`, `sent` and `errors` fields. The `sent` field * specifies the number of sessions that the filter resolved and * successfully sent the message to. The `errors` field contains an array of * errors for any session that could not receive the message. * * **Example:** * ``` * // Send a message to be received by the server and passed to a MessageHandler * session.messages.send('foo', 123); * ``` * * **Example:** * ``` * // Send a message to a specific session * session.messages.send('bar', 'hello', sessionID); * ``` * * **Example:** * ``` * // Send a message with a filter * session.messages.send('baz', 'world', '$Principal is 'john''); * ``` * * @param path the message path * @param message the message value * @param options the optional message send options * @param target the target recipient's session ID (as a string or * ession ID object) or a session property filter string. * @returns the {@link Result} of the send operation * * @deprecated since 6.2 * * One-way messaging is deprecated in favor of request-response * messaging. Use {@link Messages.sendRequest * sendRequest} instead. This method will be removed in a future * release. */ send(path: string, message: any, options: SendOptions, target: string | SessionId): Result; send(path: string, message: any, target: string | SessionId): Result; /** * Listen to a stream of messages sent to this Session for a particular * path. Messages will be received as {@link Message * message} instances. * * The message content is dependent on the sender. Correct parsing of the * message content from a `Buffer` is up to the consuming session. * * Received messages do not indicate which session sent them; if sender * information is required then this should be included within the message * content. * * 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:** * ``` * // Create with a default listener function * session.messages.listen('foo', function(message) { * // Do something with the message * }); * ``` * * **Example:** * ``` * // Create a message stream and consume from it * var stream = session.messages.listen('foo'); * * stream.on('message', function(message) { * // Do something with the message * }); * ``` * * @param path the message path or paths to listen to * @param listener the default listener * @returns a stream providing messages received on the specific path * * @deprecated since 6.2 * * One-way messaging is deprecated in favor of request-response * messaging. See {@link sendRequest} and * {@link sendRequestToFilter}. This method * will be removed in a future release. */ listen(path: string | TopicSelector | Array, listener: (message: Message) => void): MessageStream; /** * Register a {@link MessageHandler MessageHandler} to * receive messages that were sent from other sessions for a particular * path but with no specified recipient. The handler must implement the * {@link MessageHandler MessageHandler} interface. * * The provided handler will be passed messages received on the same path * used for registration, or any lower branches. A session may only register * a single handler for a given path at a time. * * The message content is dependent on the sender. Correct parsing of the * message content from a `Buffer` is up to the consuming handler. * * Unlike {@link Messages.listen}, received messages provide the * sender's SessionId. * * **Example:** * ``` * // Create a message handler * var handler = { * onMessage : function(message) { * console.log(message); // Log the received message * }, * onActive : function(unregister) { * * }, * onClose : function() { * * } * }; * * // Register the handler * session.messages.addHandler('foo/bar', handler).then(function() { * // Registration happened successfully * }, function(error) { * // Registration failed * }); * ``` * * * @param path the message path to handle * @param handler the message handler * @param keys message keys to register for this session * @returns the registration {@link Result} that completes when the * handler has been registered. * * @deprecated since 6.2 * * One-way messaging is deprecated in favor of request-response * messaging. See {@link sendRequest} and * {@link sendRequestToFilter}. This method * will be removed in a future release. */ addHandler(path: string, handler: MessageHandler, keys?: string[]): Result; /** * Register a request handler to handle requests from other client sessions * on a path. * * **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/topic', 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 containing session properties * that should be included with each request * @param requestType an optional request data type * @returns the registration {@link Result} */ addRequestHandler(path: string, handler: RequestHandler, sessionProperties?: string[], requestType?: DataType): Result; /** * Send a request. * * A response is returned when the {Result} is complete. * * **Example:** * ``` * // Send a string request to be received by the server and passed to a * // {Session.messages.RequestHandler} registered on the supplied topic * session.messages.sendRequest('test/topic', 'string request'); * ``` * * **Example:** * ``` * // Send a JSON request to be received by the server and passed to a * // {Session.messages.RequestHandler} registered on the supplied topic * session.messages.sendRequest('test/topic', 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 topic * session.messages.sendRequest('test/topic', { * 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} * @returns a {@link Result} containing the response */ sendRequest(path: string, request: any, target: SessionId | string, requestType?: DataType | string, responseType?: DataType | string): Result; sendRequest(path: string, request: any, requestType?: DataType | string, responseType?: DataType | string): Result; /** * 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/topic', 'string request', { * onResponse : function(sessionID, response) { * console.log(response); // Log the response * }, * onResponseError : function() {}, * onError : function() {}, * onClose : function() {}}); * ``` * * **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/topic', * { dwarfs: ['sneezy', 'sleepy','dopey' ] }, * { * onResponse : function(sessionID, response) { * console.log(response.get()); // Log the response * }, * onResponseError : function() {}, * onError : function() {}, * onClose : function() {}}, diffusion.datatypes.json(), diffusion.datatypes.json()); * ``` * * @param filter the session filter expression * @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} * @returns if the server successfully evaluated the filter, the * result contains the number of sessions the request * was sent to. Failure to send a request to a * particular matching session is reported to the * handler. */ sendRequestToFilter(filter: string, path: string, request: any, callback: FilteredResponseHandler, reqType?: DataType, respType?: DataType): Result; /** * Set a request stream to handle requests to a specified path. * * **Example:** * ``` * // Set a request stream handler to handle string requests to 'test/topic' * var handler = { * onRequest: function (path, request, responder) { * console.log(request); * responder.respond('hello'); * }, * onError: function() {} * }; * * control.messages.setRequestStream('test/topic', 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, reqType?: DataType, resType?: DataType): 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; } /** * A stream of messages sent to this session for a particular path. * *

Events

* *

message

* * Emitted when a message is received * * **Parameters:** * * `message`: {@link Message} - the incoming message * *

close

* * Emitted when the stream is closed * *

error

* * Emitted when an error occurred * * **Parameters:** * * `error`: any - the error * * @deprecated since 6.2 * < * One-way messaging is deprecated in favor of request-response * messaging. See {@link Messages.sendRequest sendRequest} * and {@link Messages.sendRequestToFilter * sendRequestToFilter}. This interface will be removed in a future * release. */ export interface MessageStream extends Stream { } /** * The handler interface for receiving messages sent from sessions to the * server. This interface must be implemented by the user, to be registered via * {@link Messages.addHandler}. * * A message handler has a lifecycle that reflects the registration state on the * server. This is expressed through the callback methods. Once {@link * MessageHandler.onClose onClose} has been closed, no further interactions will * occur. * * {@link SessionMessage Messages} received by a handler * contain the identity of the original sender. * * @deprecated since 6.2 * * One-way messaging is deprecated in favor of request-response * messaging. See {@link Messages.sendRequest sendRequest} * and {@link Messages.sendRequestToFilter * sendRequestToFilter}. This interface will be removed in a future * release. */ export interface MessageHandler { /** * Handle a message that was sent by another session to the server, on a * path that is a descendant of the path which this handler is registered * for. * * @param {Session.messages.SessionMessage} message - The received message * @function Session.messages.MessageHandler.onMessage */ onMessage(message: SessionMessage): void; /** * Called when the handler has been registered at the server and is now * active. * * @param unregister a function to call that will unregister and close this * handler */ onActive(unregister: () => void): void; /** * Called when the handler is unregistered, or the session is closed. */ onClose(): void; } /** * 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; /** * 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: Error): void; /** * Called when the filtered response handler is unregistered, or the session * is closed. */ onClose(): void; } /** * Responder interface to dispatch responses to requests. */ export interface Responder { /** * Dispatch a response to a request. * * @param response the response to send */ respond(response: 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; }; } /** * A message that is received when a session {@link Messages.listen listens} to * incoming messages. * * **Example:** * ``` * // Read message content as a JSON DataType value * var jsonObj = diffusion.datatypes.json().readValue(message.content).get(); * ``` * * @deprecated since 6.2 * * One-way messaging is deprecated in favor of request-response * messaging. See {@link Messages.sendRequest sendRequest} * and {@link Messages.sendRequestToFilter * sendRequestToFilter}. This interface will be removed in a future * release. */ export interface Message { /** * The message path */ readonly path: string; /** * The message payload */ readonly content: Buffer; /** * The send options */ readonly options: SendOptions; } /** * A message received by the {@link MessageHandler} * * @deprecated since 6.2 * * One-way messaging is deprecated in favor of request-response * messaging. See {@link Messages.sendRequest sendRequest} * and {@link Messages.sendRequestToFilter * sendRequestToFilter}. This interface will be removed in a future * release. */ export interface SessionMessage { /** * The path that this message was sent on */ readonly path: string; /** * The message's value as a binary buffer */ readonly content: Buffer; /** * The session that sent this message */ readonly session: string; /** * The options that were set when sending the message */ readonly options: SendOptions; /** * The sender's session properties */ properties?: { [key: string]: string; }; } /** * Options for sending messages * * @deprecated since 6.2 * * This is only used within one-way messaging, which is deprecated * from this release. This interface will be removed in a future * release. */ export interface SendOptions { /** * The message priority */ priority?: Priority; /** * The message headers as an array of strings */ headers?: string[]; } /** * @typedef {Object} Session.messages.MessageSendResult * @property {String} path - topic path * @property {String} recipient - session filter or SessionID of the recipient * @property {Number} [sent] - the number of sessions the message has been sent to using a filter string * @property {Array} [errors] - errors from sending to sessions using a filter string * * @deprecated since 6.2 *

* One-way messaging is deprecated in favor of request-response * messaging. See {@link Messages.sendRequest sendRequest} * and {@link Messages.sendRequestToFilter * sendRequestToFilter}. This interface will be removed in a future * release. */ export interface MessageSendResult { /** * The topic path as specified in the call to {@link Messages.send} */ readonly path: string; /** * The recipient as specified in the call to {@link Messages.send} */ readonly recipient?: string | SessionId; /** * If a filter was passed for the recipient, this contains the number of * sessions the message has been sent to. */ readonly sent?: number; /** * Any errors from sending to sessions using a filter string */ readonly errors?: ErrorReport[]; } /** * Alias for the MessageSendResult interface to keep compatibility with old TypeScript definitions */ export declare type SendResult = MessageSendResult; /** * @module Session */ /** * Ping feature * * 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(): Result; } /** * 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.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 topic path */ export declare enum TopicPermission { /** * Required to receive information from a topic. * * If a session does not have read_topic 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 the topic path * * A session must have this permission for the path prefix of any topic selector * used to subscribe or fetch. * * When the subscription or fetch request completes, the resulting topics * are further filtered based on the `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 the * `MODIFY_SESSION` global permission in addition to the * appropriate `SELECT_TOPIC` permission. */ 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", /** * A permission that is unsupported by the session */ UNKNOWN_TOPIC_PERMISSION = "UNKNOWN_TOPIC_PERMISSION", } /** * The credentials that a session uses to authenticate itself */ export declare type Credentials = string | Buffer | 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 topic permissions */ readonly default: TopicPermission[]; /** * The map of topic paths to sets of Topic * permissions */ readonly topic: { [key: string]: TopicPermission[]; }; /** * 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[]; } /** * 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; } /** * 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. * * @property {Object} anonymous The configuration used for anonymous connections. * @property {String} anonymous.action The default action to apply to anonymous connections. *

* @property {String[]} anonymous.roles - The roles assigned to anonymous connections. */ export interface SystemAuthenticationConfiguration { /** * The system principals stored on the server. */ readonly principals: SystemPrincipal[]; /** * The configuration that is applied for anonymous connections */ readonly anonymous: SystemAuthenticationAnonymousConfiguration; } /** * Additional information supplied to the server upon a successful authentication. * * @deprecated since 6.3 *

* This interface is part of the deprecated {@link * AuthenticationHandler} API. Use the new {@link Authenticator} * API instead. */ export interface AuthenticationResult { /** * Additional roles to be assigned to the authenticated session */ readonly roles: string[]; /** * Additional properties to be assigned to the authenticated session */ readonly properties: SessionProperties; } /** * Single-use callback provided to the {@link * AuthenticationHandler.onAuthenticate onAuthenticate} call. * * The server calls the handlers for each authentication request. Each * handler must respond {@link AuthenticationHandlerCallback.allow allow}, * {@link AuthenticationHandlerCallback.abstain abstain}, * or {@link AuthenticationHandlerCallback.deny deny}. * * The handler may provide additional information to the allow method with a user-supplied * {@link AuthenticationResult} object. * * Authentication handlers are configured in precedence order. * Authentication will succeed if a handler returns 'allow' and all higher * precedence handlers (earlier in the order) return 'abstain'. * Authentication will fail if a handler returns 'deny' and all higher * precedence handlers return 'abstain'. If all authentication handlers * return 'abstain', the request will be denied. Once the outcome is known, * the server may choose not to call the remaining handlers. * * @deprecated since 6.3 *

* This interface is part of the deprecated {@link * AuthenticationHandler} API. Use the new {@link Authenticator} * API instead. */ export interface AuthenticationHandlerCallback { /** * Authentication passed - allow the authentication request * * **Example:** * ``` * // Basic allow * callback.allow(); * * // Allow with AuthenticationResult * callback.allow({ * roles : ['SOME_ROLE'], * properties : { * MyPropertyKey : 'MyPropertyValue' * } * }); * ``` * * @param result optional roles/properties to assign to the authenticated session */ allow(result?: AuthenticationResult): void; /** * Abstain from deciding on the authentication request */ abstain(): void; /** * Authentication failed - deny the authentication request. */ deny(): void; } /** * Handler for session authentication events. Must be implemented by user. * * Authentication handlers implementing this interface can be registered with * the server. The server calls the authentication handlers 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 returns {@link AuthenticationHandlerCallback.allow * allow} and all higher precedence handlers (earlier in the order) return * {@link AuthenticationHandlerCallback.abstain abstain}. Authentication will * fail if a handler returns {@link AuthenticationHandlerCallback.deny deny} and * all higher precedence handlers return 'abstain'. If all authentication * handlers return 'abstain', the request will be denied. Once the outcome is * known, the server may choose not to call the remaining handlers. * * The special variant of {@link AuthenticationHandlerCallback.allow allow} * may be used by the handler to supply the server with additional information that is * used to set up the session. * * @deprecated since 6.3 *

* This interface is part of the deprecated {@link * AuthenticationHandler} API. Use the new {@link Authenticator} * API instead. */ export interface AuthenticationHandler { /** * Request authentication. * * The server calls this to authenticate new sessions, and when a client * requests the session principal is changed (e.g. using * {@link Security.changePrincipal}. * * For each call to `onAuthenticate`, the authentication handler should * respond by calling one of the methods of the provided `callback`. * The handler may return immediately and process the authentication request * asynchronously. The client session will be blocked until a callback * method is called. * * @param principal the requested principal, or '' if none was supplied. * @param credentials credentials authenticating the principal * @param sessionDetails the information the server has about the client * @param callback single use callback */ onAuthenticate(principal: string, credentials: string | Buffer, sessionDetails: SessionDetails, callback: AuthenticationHandlerCallback): void; /** * Called when the handler has been successfully registered with the server. * * A session can register a single handler. If there is already a handler * registered, the operation will fail and {@link * AuthenticationHandler.onClose onClose} will be called. * * To deregister the handler, call the `deregister` function supplied. * * @param deregister a function that may be called to deregister this handler */ onActive(deregister: () => void): 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. */ 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 */ onError(error: Error): void; } /** * 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. */ 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 */ 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 */ 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 */ setGlobalPermissions(role: string, permissions?: string[]): SecurityScriptBuilder; /** * Set the default permissions that a particular role will have for topics. * * @param role the role to set topic permissions for. * @param permissions the topic permissions to assign for the role, * default `= []`. * * @return the builder to allow chaining */ setDefaultTopicPermissions(role: string, permissions?: string[]): SecurityScriptBuilder; /** * Remove any previously assigned permissions from a particular topic for a * given role. * * This is different from setting no permissions to a topic. By removing * permissions set for a topic, permissions will be inherited from the * nearest set of permissions that have been assigned higher in the topic * path hierarchy or from the default topic permissions if no more specific * permissions are found. * * @param role the role to remove topic permissions from. * @param path the topic path to remove permissions from. * * @return the builder to allow chaining */ removeTopicPermissions(role: string, path: string): SecurityScriptBuilder; /** * Sets specific topic permissions for a named role. * * When permissions are assigned to a role for a topic path they will apply * to the topic and any topics below the specified path. Topic-scoped * permissions are assigned to roles for specific topic paths. The * permission assignment applies to all descendant topics, unless there is a * more specific assignment. * * To evaluate whether a session has permission for a topic, the server * starts at that topic 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 topic 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.removeTopicPermissions}). * * @return the builder to allow chaining */ setTopicPermissions(role: string, path: string, permissions?: 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 */ 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 a new builder for scripts that also locks a role to a single * principal that can edit it * * @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. */ 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 a new builder containing the changed roles */ 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 a new builder containing the new principal */ 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 a new builder containing the changed password */ 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 a new builder containing the verification command */ verifyPassword(principal: string, password: string): SystemAuthenticationScriptBuilder; /** * Remove a principal. * * @param principal the principal name * @return a new builder containing the remove command */ removePrincipal(principal: string): SystemAuthenticationScriptBuilder; /** * Instruct the system authentication to allow anonymous connections. * * @param roles the roles to assign to anonymous sessions, default `= []` * @return a new builder containing the allow anonymous connections * command. */ allowAnonymousConnections(roles?: string[]): SystemAuthenticationScriptBuilder; /** * Instruct the system authentication to deny anonymous connections. * * @return a new builder containing the deny anonymous connections command. */ denyAnonymousConnections(): SystemAuthenticationScriptBuilder; /** * Instruct the system authentication handler to defer authentication * decisions for anonymous connections to subsequent handlers. * * @return a new builder containing the abstain anonymous connections * command. */ abstainAnonymousConnections(): 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.setAuthenticationHandler 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; } /** * Security feature. Allows querying and modification of server-side * security and authentication configuration. * * **Example:** * ``` * // Get a reference to the security feature * var security = session.security; * ``` * */ export interface Security { /** * The global permission enum */ readonly GlobalPermission: typeof GlobalPermission; /** * The topic permission enum */ readonly TopicPermission: typeof TopicPermission; /** * Get the principal that the session is currently authenticated as. * * @returns the session's principal */ getPrincipal(): string; /** * 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 Result} * * **Example:** * ``` * session.security.changePrincipal('foo', 'password'); * ``` * */ changePrincipal(principal: string, credentials: string): Result; /** * 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 Result} that completes with the security configuration * */ getSecurityConfiguration(): Result; /** * 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 Result} that completes with the server's authentication store * */ getSystemAuthenticationConfiguration(): Result; /** * 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 topic 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 Result} */ updateSecurityStore(script: string): Result; /** * 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 topic 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 Result} */ updateAuthenticationStore(script: string): Result; /** * 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 a handler for client authentication events. * * Each handler is registered under a particular `handlerName` . For * registration to succeed, the server's security configuration must include * a matching `` entry for the name. * Otherwise registration will fail, the handler will be closed immediately, * and an error will be reported to the session error handler. * * Each control session can register a single handler for a `handlerName` . * See {@link AuthenticationHandler.onActive onActive}. * * It is normal for several or all of the control sessions in a control * group to set a handler for a given name. Registration will fail if a * session in a different control group has registered a handler using the * name. * * For each authentication event, the server will use its configuration to * determine the handler priority order. The server can call authentication * handlers in serial or parallel. The server can stop the authentication * process as soon as it has an allow or deny response from a handler and * all higher priority handlers have abstained. * * For a configured control authentication handler, the server will select a * single handler from those registered for the `handlerName` . If * no handlers are currently registered, the server will consult the next * handler. * * **Example:** * ``` * // Set a simple handler to handle pre-defined principals, otherwise defer to default handling * session.security.setAuthenticationHandler('before-system-handler', [], { * onAuthenticate : function(principal, credentials, details, callback) { * if (principal === 'alice' && credentials === 'hello') { * callback.allow(); * } else if (principal === 'bob') { * callback.deny(); * } else { * callback.abstain(); * } * }, * onActive : function(deregister) { }, * onClose : function() { }, * onError : function() { } * }); * ``` * * **Example:** * ``` * // Set a handler that allocates roles & properties to certain sessions * session.security.setAuthenticationHandler('before-system-handler', [diffusion.clients.DetailType.SUMMARY], { * onAuthenticate : function(principal, credentials, details, callback) { * * if (details.summary.clientType === diffusion.clients.ClientType.IOS && * details.summary.transportType === diffusion.clients.TransportType.WEBSOCKET) { * * // Session will be authenticated with the 'WS_IOS' role, and an assigned session property * callback.allow({ * roles : ['WS_IOS'], * properties : { * PropertyName : 'PropertyValue' * } * }); * } else { * callback.abstain(); * } * }, * onActive : function(deregister) { }, * onClose : function() { }, * onError : function() { } * }); * ``` * * @param handlerName must match an entry in the server's security * configuration for registration to succeed * @param requestedDetails the session details that the server will supply, * if available * @param handler the authentication handler to set * @returns a {@link Result} * * * @deprecated since 6.3 *

* This interface is part of the deprecated {@link * AuthenticationHandler} API. Use the new {@link Authenticator} * API instead. */ setAuthenticationHandler(handlerName: string, requestedDetails: DetailType[], handler: AuthenticationHandler): Result; /** * 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 Result} that completes when the authentication * handler has been registered, returning a {@link Registration} * which can be used to unregister the authentication handler. *

* Otherwise, the Result 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. *
* * @since 6.3 */ setAuthenticator(handlerName: string, authenticator: Authenticator): Result; /** * Query the global permissions assigned to the calling session. * * @return a {@link Result} which completes when the response is received * from the server. *

* If the request was successful, the {@link Result} will * complete successfully with a list of {@link GlobalPermission}. * * @since 6.3 */ getGlobalPermissions(): Result; /** * Query the topic permissions assigned to the calling session on a given * path. * * @param path the path to query for permissions * @return a {@link Result} which completes when the response is received * from the server. *

* If the request was successful, the {@link Result} will * complete successfully with a list of {@link TopicPermission}. * * @since 6.3 */ getPathPermissions(path: string): Result; } /** * @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(): Result; } /** * @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. * * 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. * *

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 TopicPermission.READ_TOPIC READ_TOPIC} topic * permission for a topic to query a time series topic. The * {@link TopicPermission.QUERY_OBSOLETE_TIME_SERIES_EVENTS * QUERY_OBSOLETE_TIME_SERIES_EVENTS} topic 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 TopicPermission.UPDATE_TOPIC UPDATE_TOPIC} * topic permission for a topic to {@link TimeSeries.append append} a new event * to a time series topic. The {@link TopicPermission.EDIT_TIME_SERIES_EVENTS * EDIT_TIME_SERIES_EVENTS} topic permission is additionally required to {@link * TimeSeries.edit submit an edit} to any time series event. The more * restrictive {@link TopicPermission.EDIT_OWN_TIME_SERIES_EVENTS * EDIT_OWN_TIME_SERIES_EVENTS} topic 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. * @return a result that completes when a response is received from the * server. */ append(topicPath: string, value: any, valueType?: DataType): Result; /** * 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. */ edit(topicPath: string, originalSequence: number | Long, value: any, valueType?: DataType): Result; /** * 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(Buffer); * ``` * * @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 {Error} 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 {Error} 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 {Error} 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 {Error} if sequence is negative */ 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 {Error} if count is negative */ 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 {Error} if timeSpan is negative */ 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 {Error} if sequence is negative */ 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. * @throws an {Error} if count is negative * @return a copy of this range query with a new span */ 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 {Error} if timeSpan is negative */ 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 {Error} 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 {Error} 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 {Error} if count is negative */ 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 {Error} if timeSpan is negative */ 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 {Error} 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 */ as(valueClass: DataType | (new (...args: any[]) => any)): RangeQuery; /** * Evaluate this query for a time series topic. * * The session must have the `READ_TOPIC` topic 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): Result; } /** * Query result providing a {@link Stream} of events. */ export interface QueryResult { /** * Returns the number of events selected by the query. * * This number may be greater than `stream().count()` 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>; /** * Returns whether this result includes all events selected by the * query. */ readonly isComplete: boolean; /** * Returns 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 return true and {@link QueryResult.selectedCount} to * return the count of events in the stream, 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 */ /** * Topic control feature. * * Provides methods to change and update the topic tree stored on the server. * * **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 Result}. * * 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 Result} for this operation */ add(topicPath: string, specification: TopicType | TopicSpecification): Result; /** * 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 Result} for this operation */ remove(selector: Array): Result; remove(...selector: Array): Result; /** * Register a deferred action to remove a branch of the topic tree when this * session is closed. * * A removal action can be registered at any point in the topic tree, but * can not be placed above or below existing registrations. An * `error` event will be emitted if the server rejects the * registration. * * When this session is closed, regardless of reason, this topic and all * topics below it will be removed from the topic tree. * * Multiple sessions can request that the same branch be removed. If a branch * has multiple registrations, then the marked topics will not be removed * until all registered sessions have been closed. * * When registration is successful, the {@link Result} will * call the success callback with an object representing the registration * with the property function deregister that can be called at any point to * remove this registered action. The deregistration function returns a new * {@link Result}. * * If the session is closed when calling this method, the returned result * will emit an `error` event. * * @deprecated since 6.1 * * The preferred method for automatic removal of topics is * the {@link TopicSpecification.REMOVAL REMOVAL} topic * property. To achieve the equivalent of this method the * property can be specified as:- * * ``` * when this session closes remove "?topicPath//" * ``` * * To achieve a dependency upon more than one session, a * condition specifying a principal name or some other session * property can be used. * * This method will be removed in a future release. * * **Example:** * ``` * // Remove all topics under 'foo' * session.topics.removeWithSession('foo').then( * function(registration) { * // Registration complete * * // Deregister this action * registration.deregister().then( * function() { * // Deregistration complete * }, * function(err) { * // Failure while deregistering * } * ); * }, * function(err) { * // Could not register * } * ); * ``` * * @param topicPath the path of the topic tree to remove * @returns registration {@link Result}. */ removeWithSession(topicPath: string): Result; /** * Update a topic on the server with a new supplied value. The returned * {@link Result} will complete if the update is successfully applied, and * any sessions subscribed to the same topic will be notified of the new * topic value. * * If the session is closed when calling this method, the returned result * will also emit an `error` event. * *
Failure
* * If the operation fails a {@link UpdateFailReason} is provided. The value * provided must be compatible with the data type of the topic being * updated, or the update will be rejected. Updates will also be rejected if * the session has insufficient permissions, or the topic does not exist. * * Prefer {@link TopicControl.updateValue} when updating a `Double` or * `Int64` topic. This method can infer the wrong data type when updating a * `Double` topic with a value that does not have a fractional component. * * **Example:** * ``` * // Update topic 'foo/bar' with string value. * session.topics.update('foo/bar', 'baz'); * ``` * * **Example:** * ``` * // Update topic with JSON content * var content = diffusion.datatypes.json().from({ "foo" : "bar" }); * * session.topics.update('foo/bar', content); * ``` * * @param path the topic path to update * @param value the value to update the topic with * @returns a {@link Result} that completes with the topic path that has * been updated. * * @deprecated since 6.2 *

* This method is deprecated. Use {@link TopicUpdate.set} * instead. This method will be removed in a future release. */ update(path: string, value: any): Result; /** * This method is similar to {@link TopicControl.update} but takes in a * data type so that the updater can determine which data type to use when * encoding the value. * * Note that if a double value is applied to an `Int64` topic, the * fractional component is ignored. Updating a topic with a different value * type can lead to an unexpected value getting applied to the topic. * * **Example:** * ``` * session.topics.updateValue('foo', 123.45, diffusion.datatypes.double()); * ``` * * @param path the topic path to update * @param value the value to update the topic with * @param datatype the data type to be used for encoding the value * @returns a {@link Result} that completes with the topic path that has * been updated. * * @deprecated since 6.2 *

* This method is deprecated. Use {@link TopicUpdate.set} * instead. This method will be removed in a future release. */ updateValue(path: string, value: any, datatype: DataType): Result; /** * Register a handler to provide exclusive updates for a particular branch * of the topic tree. Once successfully registered, the handler will be * called with lifecycle callbacks. This grants this session sole access to * publish updates to topics at or under the branch used for registration. * * If no other handlers have been registered for the topic path, the handler * will enter the {@link TopicUpdateHandler.onActive active} state. This * provides an {@link Updater updater} which can then be used to publish * updates for topics at or below the registered topic path. * * If there is an existing handler for the topic path, the handler will be * put into the {@link TopicUpdateHandler.onStandBy standby} state. This * indicates that the handler is registered but does not have access to * publish updates. Once all previously registered handlers are closed, this * handler will transition to the {@link TopicUpdateHandler.onActive active} * state. * * The handler will be closed if the session closes or `unregister` is * called. This is a terminal state from which no further state transitions * will occur. When a registered handler is closed, if there is another * handler registered by a different session, this next handler will * transition to an active state. * * Handlers cannot be registered above or below the topic path of any other * registered handlers. Attempting to do so will close the handler. * * **Example:** * ``` * session.topics.registerUpdateSource('foo/bar', { * onRegister : function(topicPath, unregister) { * // The handler has been registered * * // Unregister the handler * unregister(); * }, * onActive : function(topicPath, updater) { * // Now that we're active, we have sole write access for all topics under 'foo/bar' * updater.update('foo/bar/baz', 123).then(function() { * // Updates return a promise just like session.topics.update * }); * }, * onStandby : function(topicPath) { * // The updater is registered, but another updater currently holds the active state. * }, * onClose : function(topicPath) { * // The updater is closed * } * }); * ``` * * **Example:** * ``` * // 'client' is an anonymous session that has insufficient permission to register an update source * client.topics.registerUpdateSource('foo/bar', { * onRegister : function(topicPath, unregister) { * }, * onActive : function(topicPath, updater) { * }, * onStandby : function(topicPath) { * }, * onClose : function(topicPath, error) { * // The updater is closed because the error is diffusion.errors.ACCESS_DENIED * } * }); * ``` * * @param path the topic path to register an update source for. * @param updateHandler handler specifies the handler for the specified * branch (unless overridden by a handler registered * against a more specific branch) * @returns a {@link Result} for this operation * * @deprecated since 6.2 *

* This method is deprecated. Use {@link * TopicUpdate.createUpdateStream} instead. This method will be * removed in a future release. */ registerUpdateSource(path: string, updateHandler: TopicUpdateHandler): Result; /** * Register a {@link MissingTopicHandler} to handle requests for a branch of * the topic tree. * * The provided handler is called when a client subscribes or fetches using * a topic selector that matches no existing topics. This allows a control * client to intercede when another session requests a topic that does not * exist. The control client may {@link TopicControl.add create the * topic}, perform some other action, or do nothing, before allowing the * client operation to proceed by calling {@link * MissingTopicNotification.proceed proceed()}. Alternatively, the control * client can call {@link MissingTopicNotification.cancel cancel()} to * discard the request. * * 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 Result} 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 Result} for this registration */ addMissingTopicHandler(path: string, updateHandler: MissingTopicHandler): Result; } /** * Handler called when a client session subscribes or fetches 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 requests a topic that does not exist, * and the topic path belongs to part of the topic tree for which this * handler was registered. * * Missing topic notifications only occur when using the deprecated * {@link Session.fetch} mechanism. The newer {@link Session.fetchRequest} * mechanism does not generate missing topic notifications. * * The handler implementation should take the appropriate action (for * example, create the topic), and then call * {@link MissingTopicNotification.proceed proceed} on the supplied * `notification` . This allows the client request to continue and * successfully resolve against the topic if it was created. * * Alternatively, the handler can call {@link * MissingTopicNotification.cancel cancel} to discard the request. A * handler should always call `proceed` or `cancel` , otherwise resources * will continue to be reserved on the server until the notification times * out. * * @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 */ onRegister(path: string, deregister: () => void): 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. * * Processing of the initial request will be halted until * {@link MissingTopicNotification.proceed proceed} is called, at which point * the selector will be resolved against the topic tree again. * * If after calling `proceed` the selector still does not * match against any topics, no further notifications will be provided. * * Should {@link MissingTopicNotification.cancel cancel} be called, or the * notification time out, the request will be discarded. The requesting * session will not be notified that their request has been cancelled. */ 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; /** * Instruct the server to complete processing of the session request. * * This may be called after additional operations (such as adding * topics) have been performed, to allow the requested selector to be * resolved against the updated topic tree. * * For subscription requests, the topic selector will be added to the * client's topic selections. This will cause the client session to * become subscribed to topics that match the selector if they are added * later. */ proceed(): void; /** * Cancel the client request on the server. * * Calling this will prevent any further processing of the request. For * subscription requests, the topic selector will be discarded. The * client session will not become subscribed to topics that match the * selector if they are added later. * * @deprecated since 6.4 *

* This is only useful when using the deprecated {@link * Topics.fetch} mechanism. It will be removed when that * mechanism is removed. */ cancel(): void; } /** * The TopicUpdateHandler interface for exclusive updates. This interface must * be implemented by the user, to be registered via {@link * TopicControl.registerUpdateSource}. * * A topic update handler has a lifecycle that reflects the registration state * on the server. This is expressed through the callback methods. Once {@link * TopicUpdateHandler.onClose onClose} has been called, no further interactions * will occur. * * When an update handler is registered it will be notified via the {@link * TopicUpdateHandler.onRegister onRegister} callback. Once registered it may be * in either a `active` state, where it can provide topic updates, or a * `standby` state, where it is still registered but is not allowed to * perform updates. The state may be switched in any order, depending on server * policy. * * @class TopicUpdateHandler * * @deprecated since 6.2 * * This class is deprecated. It is only used in conjunction with * {@link TopicControl.registerUpdateSource}. Use {@link * TopicUpdate.createUpdateStream} instead. This method will be * removed in a future release. */ export interface TopicUpdateHandler { /** * 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 TopicUpdateHandler.onClose onClose} will * be called. * * To deregister the handler, call the `deregister` function supplied. * * @param path the path that the handler is registered for * @param deregister a function that may be called to deregister this handler */ onRegister(path: string, deregister: () => void): void; /** * State notification that this handler is now active for the specified * topic path and is therefore in a valid state to send updates on topic at * or below the registered topic path * * @param path the registration path * @param updater an updater that can be used to update topics */ onActive(path: string, updater: Updater): void; /** * State notification that this handler is not currently allowed to provide * topic updates for the specified topic path. This indicates that another * {@link TopicUpdateHandler} is currently active for the given topic path. * * Server policy will dictate when this handler is set as active. * * If this handler was previously in a `active` state, any {@link Updater} * instances for this topic path will no longer be valid for use. * * @param path the registration path */ onStandBy(path: string): 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 * @param errorReason an optional value representing the error; this can be * one of the constants defined in {@link * ErrorReason}, or a feature-specific reason. It * is absent if the handler was closed because the * session closed. */ onClose(path: string, errorReason?: ErrorReasonType): void; } /** * An updater provides methods to update a topic on the server with a new * supplied value, like {@link TopicControl.update}, but within the context of * an exclusive {@link TopicUpdateHandler} registration. If the update is * successful it will call the result's success callback, and any sessions * subscribed to the same topic will be notified of a topic update. * * An updater may only update topics at or below the registration path of the * {@link TopicUpdateHandler} from which it was produced. * * The result will fail if the update was not successful. It is necessary for * the topic to exist, and that the value type must be valid for the topic, for * example a topic added with {@link TopicTypeEnum.INT64} cannot accept a string * value. Updates will also fail if the {@link TopicUpdateHandler} this updater * was created from is in a `standby` or `closed` state. * * **Example:** * ``` * updater.update('foo/bar', 123).then(function() { * // Update successful * }, function(err) { * // Update failed * }); * ``` * * @deprecated since 6.2 *

* This class is deprecated. It is only used in conjunction with * {@link TopicControl.registerUpdateSource}. Use {@link * TopicUpdate.createUpdateStream} instead. This method will be * removed in a future release. */ export interface Updater { /** * Update a topic * * Prefer {@link updateValue} when updating a `Double` or `Int64` topic. * This method can infer the wrong data type when updating a `Double` topic * with a value that does not have a fractional component. * * @param path the topic to update * @param value the value to update the topic with * @return the {@link Result} that completes when the update succeeded */ update(path: string, value: any): Result; /** * Update a topic with a specified data type * * @param path the topic to update * @param value the value to update the topic with * @param datatype the data type to be used for encoding the value * @return the {@link Result} that completes when the update suceeded */ updateValue(path: string, value: any, datatype: DataType): Result; } /** * 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; } /** * A result that is returned from a {@link TopicControl.removeWithSession} request */ export interface RemoveWithSessionResult { /** * A function to remove this registered action * * @return a result that resolves with the topic path that was removed */ deregister(): Result<{ topic: string; }>; } /** * Alias for the TopicUpdateHandler interface to keep compatibility with old TypeScript definitions */ export declare type UpdateSourceHandler = TopicUpdateHandler; /** * @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, } /** * Topic notifications feature. * * Allows a client session to receive notifications about changes to selected topics. */ 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 Result} for this operation */ addListener(listener: TopicNotificationListener): Result; } /** * 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 * * @function TopicNotificationListener#onError */ 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 Result} for this operation */ select(selector: Array): Result; select(...selector: Array): Result; /** * 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 Result} for this operation */ deselect(selector: Array): Result; deselect(...selector: Array): Result; /** * Request that the listener is unregistered from the server. * @function TopicNotificationRegistration#close */ 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; } /** * Result 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. * * A session does not have to be subscribed to a topic to update it. * * 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 current value of the * topic being updated and a part of the current value of the topic being * updated. * * When a topic of type {@link TopicTypeEnum.STRING STRING}, * {@link TopicTypeEnum.INT64 INT64} or * {@link TopicTypeEnum.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. Attempting to set any other type of topic to `null` * or `undefined` will cause an `Error` to be thrown. * *

Access control

* * To update any topic a session needs {@link TopicPermission.UPDATE_TOPIC * update topic} permission covering the topic. To create any topic a session * needs {@link TopicPermission.MODIFY_TOPIC modify topic} permission covering * the topic. Requests that combine adding a topic and setting the value will * require both permissions for either action to happen. An {@link UpdateStream} * cannot be used to add a topic successfully but fail to set its value because * the {@link TopicPermission.UPDATE_TOPIC update topic} is missing. * *

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 TopicTypeEnum.STRING STRING}, * {@link TopicTypeEnum.INT64 INT64} or * {@link TopicTypeEnum.DOUBLE DOUBLE} topics. * * When a topic of type {@link TopicTypeEnum.STRING STRING}, * {@link TopicTypeEnum.INT64 INT64} or * {@link TopicTypeEnum.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. * * @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 Result that resolves when a response is received * from the server. *

* If the task fails, the Result will resolve with an * `Error` . */ set(path: string, dataType: DataType, value: any, options?: TopicUpdateOptions): Result; /** * 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. * * @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 */ createUpdateStream(path: string, dataType: DataType, options?: TopicUpdateOptions): UpdateStream; /** * 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 Result} that resolves when a response is received from * the server. *

* If the task fails, the Result 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 {@code 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 * TopicPermission.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): Result; } /** * @module Session.topicViews */ /** * Description of a topic view that has been created. * * @since 6.3 */ export interface TopicView { /** * The name of the topic view. */ 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 provides a client session with the ability to manage topic * views. * * A topic view maps one part of the 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 that * include publication of partial values, expanding a single topic value into * many topics and throttling the rate of publication. * * 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

* * 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. * * A general topic view specification comprises several parts: * *
    *
  • The source topic clause identifies the source topics. *
  • The path mapping clause determines how reference topic paths are * derived from the source topic paths, and when expanding to more than one * reference topic, from where the values are obtained. *
  • The optional topic property mapping clause determines how * reference topic properties are derived from source topic properties. *
  • The optional value mapping clause determines how reference topic * values are derived from source topic or expanded values. *
  • The optional throttle clause constrains the rate at which each * reference topic is updated when its source topic is updated. *
* *

Source topic clause

* The source topic clause begins with the map keyword and is followed * by a topic selector. These topic selectors follow the same * {@link TopicSelectors.parse parsing rules} as other topic selectors. * When evaluating a topic view, topics in the topic tree that match the source * topic selector are considered, with the following exceptions: *
    *
  • Topics created through the Publisher API; *
  • {@link ROUTING ROUTING} topics. *
* * Both {@link SLAVE SLAVE} and reference topics are valid source * topics. In particular, chaining of topic views is supported; that is, a * reference topic created by one topic view can be the source topic of another * topic view. Additionally, a reference topic can be the master topic of a * slave topic, or the source topic of a routing topic subscription. * *
Prefer topic views to slave topics which are now * deprecated. Individual topics can be mirrored by creating a slave topic, * but maintaining slave topics for a branch of the topic tree quickly becomes * tedious. A topic view will maintain such a branch automatically, and provides * more sophisticated mapping options.
* *

Path mapping clause

* The paths of reference topics are derived from the source topic according to * the topic view path mapping. The path mapping allows the source topic path * and the value of the source topic to determine the path of the reference * topic. In addition the path mapping can include expand directives * which allow objects and arrays in JSON source topic values to be expanded to * produce many reference topics. * * A path mapping clause begins with the to keyword and is followed by a * path mapping template. A path mapping template is a topic path with embedded * directives. Directives are evaluated when creating the topic * reference and substituted into the topic path. Directives are delimited by * angle brackets (<,>) and consist of the name of the * directive and a list of parameters. The parameter list is comma-separated and * surrounded by parentheses ((, )). * * The following path mapping directives are supported: * *
*
Source path directives
*
Source path directives extract a portion of the source path and are * parameterized by the index of the start part of the source path and the * number of parts to include. The number of parts parameter is optional – if it * is missing, the selection extends to the end of the source path. The syntax * is <path(start, number)>, or * <path(start)> when the number of parts parameter * is omitted. * * For example, given the source path a/b/c/d, the source path directive * <path(1, 2)> is mapped to the reference topic path b/c, and * the source path directive <path(2)> is mapped to the reference topic * path c/d.
* *
Source value ("scalar") directives
*
Source value directives are only applied to {@link JSON} source * topics; if the path mapping contains a source value directive, non-JSON * topics matching the source topic selector are ignored. Source value * directives use the keyword scalar and are parameterized by a * single JSON pointer that * extracts a scalar value from the source (or expanded) value. A scalar value * is a string, a number, true, false, or * null, that is, anything other than an array or a object. If the * JSON pointer does not refer to a scalar value in the source (or expanded) * value, no reference topic will be created. This includes cases where the JSON * pointer refers to an array or an object), or when no part of the source value * is selected. * * Deriving the reference topic paths from part of the source topic value * effectively creates a secondary index on the value. For source value * directives to work efficiently, the selected scalar values should be * relatively stable. If an update to the source topic changes the selected * scalar value, the corresponding reference topic will be removed and a new * reference topic will be created. * * For example, given a source value of * *
 * {
 *   "account" : "1234",
 *   "balance" : { "amount" : 12.57, "currency" : "USD" }
 * }
 * 
* * and the source value directive * currency/<scalar(/balance/currency)>/account/<scalar(/account)>, the * reference topic path will be currency/USD/account/1234. * * If the extracted value is a string, it is copied literally to the reference * topic path. A value that contains path separators (/) will create a * reference topic path with more levels than the path mapping template. * * An extracted value of null will be copied to the reference topic path * as the string "null".
* *
Expand value directives
* *
Expand value directives are only applied to {@link JSON} * source topics; if the path mapping contains an expand value directive, * non-JSON topics matching the source topic selector are ignored. *

* Expand value directives use the keyword expand and are * parameterized by one or two * JSON pointers. *

* The first pointer indicates the element within the value to be expanded, and * if omitted, the value is expanded from the root. Expansion of a source topic * indicates that every direct child of the element pointed to by the expand * pointer will be used to create a new reference topic (or provide input to * later expand or scalar directives). For example <expand()> would * expand every child item in the source value and <expand(/account)> * would expand every child of the account value in the source value. * The specified value could be an object, an array or even a scalar value, but * a scalar value would expand to only a single new value. *

* The optional second parameter of the expand directive specifies a pointer to * a scalar value within the expanded value which will be used to derive the * path fragment of the reference topic path. If the second pointer is not * specified or no scalar value is found for the pointer, the path fragment is * taken from the key (if the child value is an object) or the index (if the * child value is an array). Scalar child values will expand to a reference * topic but will not add anything to the generated path. For example * <expand(,/name)> would expand from the root of the source * value and each child value path fragment would be obtained from the scalar * value with the key name. *

* So if a source topic had a value of * *

 * {
 *     "values": [1, 5, 7]
 * }
 * 
* * a path mapping of
* value<expand(/values)> would expand the value to the * following reference topics:- *

* path value0 with a value of 1
* path value1 with a value of 5
* path value2 with a value of 7
*

* Expand directives can be nested (i.e. there can be more than one expand * directive in a path mapping). In this case a second expand directive will use * the value from the previous expand as its source (root) value and not the * value of the source topic. This also applies to scalar directives that * follow an expand directive. *

* If expansion causes more than one mapping to the same topic path, only the * first encountered will be created and updated. *

* Expanding source topic values effectively creates secondary indices on the * value. For expanded value directives to work efficiently, the value selected * for expansion should be relatively stable in terms of the children it * contains. If an update to the source topic changes the children of the * expanded value, then corresponding reference topics will be removed and * created. Updates should generally be limited to changing values within the * expanded values.

*
* *

Topic property mapping clause

* The {@link TopicSpecification topic specification} of a reference topic is * derived from the topic specification of the source topics. A reference topic * has the same topic type as its source topic. * * The topic properties of a reference topic are derived from the source topic. * Some topic properties can be tuned using the optional topic property mapping * clause. The following table describes the behavior for each topic property. * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Source topic propertyReference topic specification defaultCan be set by topic property mapping?Notes
* {@link TopicSpecification.COMPRESSION COMPRESSION}Copied from source topic specificationYes
{@link TopicSpecification.CONFLATION CONFLATION}Copied from source topic specificationYes
{@link TopicSpecification.DONT_RETAIN_VALUE * DONT_RETAIN_VALUE}Copied from source topic specificationYes
{@link TopicSpecification.OWNER OWNER}Not setNo
{@link TopicSpecification.PERSISTENT PERSISTENT}Not setNoReference topics are not persisted. Topic views are persisted, so a * reference topic will be recreated on server restart if its source is * persistent.
* {@link TopicSpecification.PRIORITY PRIORITY}Copied from source topic specificationYes
{@link TopicSpecification.PUBLISH_VALUES_ONLY PUBLISH_VALUES_ONLY}Copied from source topic specificationYes
{@link TopicSpecification.REMOVAL REMOVAL}Not setNoReference topics cannot be removed directly.
{@link TopicSpecification.SCHEMA SCHEMA} * Copied from source topic specificationNoA {@link RECORD_V2 RECORD_V2} reference topic has the same * schema as its source topic.
{@link TopicSpecification.SLAVE_MASTER_TOPIC SLAVE_MASTER_TOPIC}Not setNoIf a reference topic has a slave topic as its source topic, it indirectly * references the slave's master topic.
{@link TopicSpecification.TIDY_ON_UNSUBSCRIBE TIDY_ON_UNSUBSCRIBE}Copied from source topic specificationYes
* {@link TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE TIME_SERIES_EVENT_VALUE_TYPE}Copied from source topic specificationNoA {@link TIME_SERIES TIME_SERIES} reference topic has the same * value type as its source topic.
* {@link TopicSpecification.TIME_SERIES_RETAINED_RANGE TIME_SERIES_RETAINED_RANGE}Copied from source topic specificationYes, with restrictionsA topic property mapping cannot increase the time series retained range * by overriding the TIME_SERIES_RETAINED_RANGE property. The retained * range of a reference time series topic will be constrained to be no greater * than that of its source topic.
* {@link TopicSpecification.TIME_SERIES_SUBSCRIPTION_RANGE TIME_SERIES_SUBSCRIPTION_RANGE}Copied from source topic specificationYes
* {@link TopicSpecification.VALIDATE_VALUES VALIDATE_VALUES}Not setNoA reference topic reflects updates to its source topic. It cannot reject * updates.
* * A topic property mapping clause begins with the keywords * with properties and consists of a comma-separated list of topic * property keys and values, each separated by a colon. For example, the * following topic view specification maps all topics below the path * a to reference topics below the path b, and * disables both conflation and compression for the reference topics. * *
 * map ?a// to b/<path(1)> with properties 'CONFLATION':'off', 'COMPRESSION':'false'
 * 
* *
* *

Topic value mapping

* * By default, a reference topic's value is a copy of the source topic * value, or part of the source value produced by an expand path * mapping directive. For JSON source topics, the * optional topic value mapping clause can be applied to extract part * of the source value, or to further refine the value produced by the * expand directive. * * A topic value mapping begins the keyword as and is * followed by a value directive. A value directive is delimited by * angle brackets (<, >), and consists * of the value keywords and a single JSON pointer * parameter. The JSON pointer selects the part of the source value to * copy. * * For example, given a source value of * *
 * {
 *   "account" : "1234",
 *   "balance" : { "amount" : 12.57, "currency" : "USD" }
 * }
 * 
* * and the value mapping clause as <value(/balance)>, the * reference topic value will be * *
 * {
 *   "amount" : 12.57,
 *   "currency" : "USD"
 * }
 * 
* * Value mappings that follow expand directives apply to the expanded * value and not the source topic value. * * Topic value mappings only alter the reference topic value; only the * path mapping determines whether a reference topic should exist. If * the topic value mapping's JSON pointer fails to select anything * from the source topic value, the reference topic will have the JSON * value null. * * Topic value mappings are often used with path value mappings to * avoid repeating information in the path and the value. For example: * *
 * map ?accounts// to balances/<scalar(/account)> as <value(/balance)>
 * 
* *
* *

Throttle clause

* The optional throttle clause can be used to constrain the rate at which a * reference topic is updated when its source topic is updated. The primary * application of a throttle clause is to restrict the number of updates sent to * reference topic subscribers, reducing network utilization or the processing * each subscriber must do. Throttling also restricts the rate at which client * sessions can observe changes to reference topic values using the fetch API. * * The throttle clause has the form * throttle to X updates every period, where * X is a positive integer, and period is a positive integer * followed by a time unit which is one of seconds, * minutes, or hours. * * For example, the following topic view specification maps all topics below the * path a to reference topics below the path b, but * updates the value of each reference topic at most twice every five seconds: * *
 * map ?a// to b/<path(1)> throttle to 2 updates every 5 seconds
 * 
* * To improve readability, the throttling clause allows 1 update as * an alternative to 1 updates, and every second as an * alternative to every 1 seconds (and so on, for other time * units). For example, the following topic view specification maps all topics * below the path a to reference topics below the path * b, but updates the value of each reference topic at most once * every hour: * *
 * map ?a// to b/<path(1)> throttle to 1 update every minute
 * 
* * The throttle clause is only applied when a source topic is updated more * frequently than the configured rate. If a source topic is updated less * frequently, updates are passed on unconstrained. If the rate is exceeded, a * reference topic will not be updated again until the configured period has * expired. At this time, the reference topic will be updated based on the * source topic updates that happened in the interim, and a single value will be * published. Thus, a throttle clause provides topic-scoped conflation. * * The throttle clause is ignored for time series topics because time series * updates do not support efficient conflation. Updates to source time series * topics are passed on immediately to the corresponding reference topics, * regardless of any throttle clause. * *

Escaping and quoting special characters

* Each part of a topic view expression has characters with special * significance. Source topic clauses and path mapping clauses are delimited by * white space. Directives in path and topic property mapping clauses are * delimited by the < and > characters, and each directive * parameter is terminated by , or ). Topic property mapping * clauses are delimited by white space, and the : and , * characters. * * Sometimes a topic view must refer to or generate topics with paths that * containing special characters, or use a JSON pointer containing special * characters. The escape sequence \x can be used to literally insert * any character x, with a one exception: \/ cannot be used in * path fragments since the path delimiter / is always significant. * * Here is an example topic view expression containing escape sequences. It maps * the topic path a topic a reference topic with the path * another topic. * *
 * map a\ topic to another\ topic
 * 
* * Here is an example with a source value directive that uses the JSON pointer * /x()/y to extract the target path from the source value. The * ) character in the JSON pointer must be escaped so it is not treated * as the end of the parameter list. * *
 * map ?a// to <scalar(/x(\)/y)>
 * 
* * To insert \, the escape sequence \\ must be used. * * There is no need to escape white space in JSON pointers directive parameters. * However, white space is significant. For example, the following expressions * have different topic value mapping clauses since the JSON pointer in the * second expression is /x ; that is, it has a trailing space: * *
 * map a to b as <value(/x)>
 * map a to b as <value(/x )>
 * 
* * Instead of using escape sequences, white space characters can be included in * source topic clauses and path mapping clauses using quotes. A clause is * quoted by wrapping it in single quote (') or double quote (") * characters. For example: * *
 * map "a topic" to "another topic"
 * 
* * Within a quoted clause, quotes of the same type must be escaped: * *
 * map 'alice\'s topic' to 'bob\'s topic'
 * 
* * For consistency, the values in topic property mapping clauses can be escaped * or quoted. However, there is no need to do so because none of the valid * values for the mappable properties contain special characters. * *

Dealing with topic path conflicts

* * Reference topics have a lower priority than normal topics created through the * API, including replicas of normal topics created by topic replication or * fan-out. A reference topic will only be created if no topic or reference * topic is already bound to its derived topic path. * * Topic views have a precedence based on order of creation. If two topic views * define mappings the same topic path, the earliest-created topic view will * create a reference topic. If a topic view is updated, it retains its original * precedence. * *

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 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. * *

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 TopicPermission.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 TopicPermission.READ_TOPIC READ_TOPIC} permission for the * source topic path, and {@link TopicPermission.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 Result that completes when a response is received * from the server, returning the topic view created by the * operation. *

* If the task fails, the Result 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. *
*/ createTopicView(name: string, specification: string): Result; /** * List all the topic views that have been created. * * @return a Result 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 Result 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(): Result; /** * 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 Result that resolves when a response is received from the * server. *

* If the task fails, the Result 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. *
*/ removeTopicView(name: string): Result; } /** * @module Session */ export interface Topics { /** * 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. * @returns a {@link Result} for this operation */ unsubscribe(selector: Array): Result; unsubscribe(...selector: Array): Result; /** * Fetch the current state of one or more topics. * * Fetching a topic will provide its current value without subscribing this * client to that topic. The returned {@link FetchStream} will emit `value` * events for each topic that is matched for which a fetch request can be * satisfied. Once complete, the {@link FetchStream} will be closed. * * 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:** * ``` * // Fetch a topic's value * session.fetch("foo").on('value', function(value, path) { * console.log("Value for topic '" + path + "' is: " + value); * }); * ``` * * **Example:** * ``` * // Fetch multiple topics, handling possible errors * session.fetch("?foo/bar.*").on({ * value : function(value, path) { ... }, * error : function(error) { ... }, * close : function() { ... } * }); * ``` * * @param selector the topic selector to fetch * @returns a {@link FetchStream} that will emit the fetched values. * * @deprecated since 6.2 *

* Prefer the use of {@link fetchRequest} instead. Unlike * this method fetchRequest supports additional query * constraints, returns type-safe values, and optionally allows * topic properties to be retrieved. This will be removed in a * future release. */ fetch(selector: Array): FetchStream; fetch(...selector: Array): FetchStream; /** * 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; /** * Subscribe the session to a topic selector 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 TopicPermissions.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 */ select(selector: Array): Result; select(...selector: Array): Result; /** * 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. * * 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 */ addStream(selector: string | TopicSelector | Array, dataType: DataType): 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 */ addFallbackStream(dataType: DataType): ValueStream; } /** * @module diffusion.selectors */ /** * A {@link TopicSelector} is a value that identifies one or more topics. */ 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 = "#", } /** * 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 hierarchy. Each part is * formed of one or more UTF characters, except '/'. Topic paths are absolute, * and evaluated from the root of the current domain. * * **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. * * 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. * * 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. * *

Abbreviated Path Expressions

* * In Diffusion 5.2, an alternative syntax for path expressions was added. * An abbreviated path expression is any valid topic path (see * above) that begins with a character other than one of #, * ?, >, *, $, * %, &, or <. * This syntax allows most topic paths to be used directly as selector * expressions which appears more natural. * * This method converts abbreviated path expressions to standard path * expressions by prepending the > character. Thus a/b is * interpreted as >a/b. * * parse("a/b").expression 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. * parse("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 behaviour 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/gamma` | no | yes * `>beta` | no | no * `>.*``/.*` | no | no * `>/alpha/beta/` | yes | no * *

Abbreviated path expressions

* * Path | Matches `alpha/beta`? | Matches `alpha/beta/gamma`? * ------------- | ---------------------- | --------------------------- * `alpha/beta` | yes | no * `alpha/beta/gamma` | no | yes * `beta` | no | 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. */ 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 */ /** * Result 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; } 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(expectedValue)); * ``` * * @since 6.2 */ export interface UpdateConstraint { /** * Returns a composed constraint that represents a logical AND of this * constraint and another. * * If the composed constraint would be unsatisfiable, an `Error` * is thrown. * * @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 */ and(other: UpdateConstraint): UpdateConstraint; } /** * A constraint requiring the current value of the * {@link TopicTypeEnum.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. * * @since 6.2 */ export interface PartialJSON extends UpdateConstraint { /** * Require a value at a specific position in the JSON object. * * The `pointer` is a * JSON Pointer * syntax reference locating the `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 * @param dataType the optional type of the value * @param value the value * @return a new constraint */ with(pointer: string, dataType: DataType, value: any): 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 */ without(pointer: string): PartialJSON; } /** * Factory for the constraint types. * * An instance can be obtained by calling * {@link 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 match * the supplied value. * * If `dataType` is not specified, the data type is inferred * from the `value` parameter. * * This method 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. * * When a {@link TopicTypeEnum.STRING string}, * {@link TopicTypeEnum.INT64 int64} or * {@link TopicTypeEnum.DOUBLE double} topic is updated to a * {@code null} value, the topic is set to have no value. Use the * {@link noValue} constraint to check if the topic has no value. * * @param value the value * @param dataType the optional type of the values * @return the constraint */ value(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 TopicTypeEnum.JSON JSON} topic. The * {@link PartialJSON} partially describes the * structure of a {@link JSON} value. * * @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 TopicPermission.UPDATE_TOPIC update permission} * * an operation fails because of cluster repartitioning * * @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 TopicTypeEnum.STRING string}, * {@link TopicTypeEnum.INT64 int64} or {@link TopicTypeEnum.DOUBLE double} topics. *

* When a topic of type {@link TopicTypeEnum.STRING string}, * {@link TopicTypeEnum.INT64 int64} or {@link TopicTypeEnum.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. * * @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 Result that completes when a response is received from the * server. *

* If the task fails, the Result will resolve with an * `Error` . */ set(value: any): Result; /** * 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 Result * 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 Result that completes when a response is received from the server. */ validate(): Result; } /** * 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 Result}. * * 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 TopicTypeEnum.STRING * STRING} topics will be selected. However, if {@link DataTypes.json} is * specified, all types compatible with {@link JSON} will be selected * including {@link TopicTypeEnum.STRING STRING}, {@link TopicTypeEnum.INT64 INT64} * and {@link TopicTypeEnum.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 TopicTypeEnum 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}. * * {@link TopicTypeEnum.SLAVE Slave} topics are supported, in that if the slave * topic itself is within the requested selector/range and it is currently * linked to a topic that should be selected then a result will be returned * for the slave topic with the type/value/properties of the source topic. * * {@link TopicTypeEnum.ROUTING Routing} topics are not supported, and if * encountered will be ignored (i.e. treated as if they did not exist). * * 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 TopicTypeEnum.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 TopicTypeEnum.STRING STRING}). * * If {@link withValues} has been specified then the types specified here * must be compatible with the value class specified. * * Neither {@link TopicTypeEnum.SLAVE SLAVE} nor {@link * TopicTypeEnum.ROUTING ROUTING} may be specified as only target topic * types may be selected. * * @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 Error if invalid topic types are specified */ abstract topicTypes(topicTypes: TopicType[]): 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 Error if the class is not compatible with any topic types. */ abstract withValues(dataType: DataType): 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 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 */ 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 */ 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 */ 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 * @since 6.4 */ abstract limitDeepBranches(deepBranchDepth: number, deepBranchLimit: number): 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 Result 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 Result will be an object encapsulating all of the results. *

* Otherwise, the Result will resolve with an Error. */ abstract fetch(topics: Array): Result>; abstract fetch(...topics: Array): Result>; /** * 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 Result}. * * @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; } /** * @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. * *

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. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
{@link TopicTypeEnum.STRING STRING}
* {@link TopicTypeEnum.JSON JSON}
* {@link TopicTypeEnum.BINARY BINARY}
*
{@link TopicTypeEnum.DOUBLE DOUBLE}
* {@link TopicTypeEnum.INT64 INT64}
{@link TopicTypeEnum.ROUTING ROUTING}
*
{@link TopicTypeEnum.SLAVE SLAVE}
deprecated
{@link TopicTypeEnum.TIME_SERIES TIME_SERIES}{@link TopicTypeEnum.RECORD_V2 RECORD_V2}
{@link TopicSpecification.COMPRESSION COMPRESSION}Optional-OptionalOptionalOptionalOptional
{@link TopicSpecification.CONFLATION CONFLATION}OptionalOptionalOptionalOptionalOptionalOptional
{@link TopicSpecification.DONT_RETAIN_VALUE DONT_RETAIN_VALUE}OptionalOptionalOptionalOptional
{@link TopicSpecification.PUBLISH_VALUES_ONLY PUBLISH_VALUES_ONLY}OptionalOptionalOptional
{@link TopicSpecification.SCHEMA SCHEMA}Optional
{@link TopicSpecification.SLAVE_MASTER_TOPIC SLAVE_MASTER_TOPIC} (deprecated)Required
{@link TopicSpecification.TIDY_ON_UNSUBSCRIBE TIDY_ON_UNSUBSCRIBE}OptionalOptionalOptionalOptionalOptionalOptional
{@link TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE TIME_SERIES_EVENT_VALUE_TYPE}Required
{@link TopicSpecification.TIME_SERIES_RETAINED_RANGE TIME_SERIES_RETAINED_RANGE}Optional
{@link TopicSpecification.TIME_SERIES_SUBSCRIPTION_RANGE TIME_SERIES_SUBSCRIPTION_RANGE}Optional
{@link TopicSpecification.VALIDATE_VALUES VALIDATE_VALUES}OptionalOptionalOptional
{@link TopicSpecification.PERSISTENT PERSISTENT}OptionalOptionalOptional
{@link TopicSpecification.PRIORITY PRIORITY}Optional-OptionalOptionalOptionalOptional
{@link TopicSpecification.REMOVAL REMOVAL}OptionalOptionalOptional
{@link TopicSpecification.OWNER OWNER}OptionalOptionalOptional
* * `TIME_SERIES` topics have restricted values for the * `CONFLATION` property. They are only allowed to have the values * `off` or `unsubscribe`. * * `ROUTING` and `SLAVE` topics are references to other topics, * and have no value of their own. Instead, they reflect the value of the * appropriate source topic. Observed behavior depends on the values of the * `DONT_RETAIN_VALUE`, `PUBLISH_VALUES_ONLY`, and * `VALIDATE_VALUES` properties that are set on the source topic. * */ 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 to 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 not recommended because it will * result in more data being transmitted and less efficient use of network * resources. Reasons to consider setting the value to 'true' include * compatibility with older client libraries that do not support delta * streams; to simplify applications that use topic streams and do not wish * to deal with the complexities of delta processing (it would be better for * such an application to use a {@link ValueStream}); and to disable * delta streams to investigate their performance benefits. * */ static readonly PUBLISH_VALUES_ONLY: string; /** * Key of the topic property indicating 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: string; /** * Key of the topic property that specifies the master topic path for a * {@link TopicTypeEnum.SLAVE slave} topic. * * When creating a slave topic using a topic specification then this must be * specified. For all other topic types it is ignored. * * @since 6.0 * * * @deprecated Since 6.4 *

* Slave topics are deprecated. This property key will be * removed in a future release. */ static readonly SLAVE_MASTER_TOPIC: string; /** * 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: string; /** * 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: string; /** * 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: string; /** * 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: string; /** * Key of the topic property that specifies a schema which constrains topic * values. * * This property is only used by {@link TopicTypeEnum.RECORD_V2 * RECORD_V2} topics. The value is converted to a Diffusion record schema * using {@link RecordV2DataType.parseSchema}. * * @since 6.0 */ static readonly SCHEMA: string; /** * Key of the topic property that specifies a topic should not retain * its last value. Setting this property to `'true'` allows the topic to behave * like a stateless topic, while retaining other properties such as its data * type. * * By default, a topic (other than a `SLAVE`, or `ROUTING` 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'` 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 can provide a performance benefit. Consider not * setting this property to benefit from delta streams, even if there is no * other requirement to retain the last value. * * Setting this property affects the default subscription range of a time * series topic. If set to `'true'`, the default subscription range will * not provide an initial event to new subscribers. The default * subscription range can be overridden with the {@link TopicSpecification.TIME_SERIES_SUBSCRIPTION_RANGE * TIME_SERIES_SUBSCRIPTION_RANGE} property. Regardless of whether * DONT_RETAIN_VALUE is set, a time series topic will continue to * record events according to the {@link TopicSpecification.TIME_SERIES_RETAINED_RANGE * TIME_SERIES_RETAINED_RANGE} property. * * @since 6.0 */ static readonly DONT_RETAIN_VALUE: string; /** * 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: string; /** * 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. * * 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 thansubscriptions < 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.
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.
no session hasno 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.
`this session closes`This is a shorthand form of 'no 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 have been 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 on `no session has` * conditions is subtly different from on 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. * * Automatic topic removal is supported for both replicated topics and topics * fanned out to secondary servers using the fan-out feature. A * 'subscriptions less than' condition for such topics will be evaluated * against the total number of subscriptions to the topic across the cluster * and on all downstream secondary servers. A 'no session has' condition will * consider all sessions hosted across a cluster and hosted by downstream * secondary servers. * * @since 6.1 */ static readonly REMOVAL: string; /** * 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: string; /** * 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 * SELECT_TOPIC 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: string; /** * 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: string; /** * 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: string; /** * 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. */ withProperty(key: string, value: string): TopicSpecification; } /** * A topic type */ export declare class TopicType { /** * The topic type ID */ readonly id: number; /** * A flag indicating whether the topic type is stateful */ readonly stateful: boolean; /** * A flag indicating whether the topic type is functional */ readonly functional: boolean; /** * Create a new TopicType instance * * @param id the topic type ID * @param stateful a flag indicating whether the topic type is stateful * @param functional a flag indicating whether the topic type is functional */ constructor(id: number, stateful: boolean, functional: boolean); } /** * 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 const TopicTypeEnum: { [key: string]: TopicType; }; /** * A type containing information about the reason for an unsubscription */ export declare class UnsubscribeReason { /** * The unsubscribe reason's id */ readonly id?: number; /** * The unsubscribe reason's description */ 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 */ readonly id?: number; /** * The update fail reason's description */ 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 */ readonly id?: number; /** * The topic add failure reason's description */ 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_PATH: * ... * } * }); * ``` * */ export declare const TopicAddFailReasonEnum: { [key: string]: TopicAddFailReason; }; export interface TopicsNamespace { FetchRequest: typeof FetchRequest; TopicType: typeof TopicTypeEnum; 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. * * @since 5.7 */ export interface BinaryDataType extends DataType { /** * The Binary data type value class */ Binary: new (value: Buffer) => Binary; /** * Returns a new {@link Binary} instance from a buffer. * * @param {Buffer} buffer - The binary data * @return {diffusion.datatypes.Binary} a Binary data-type instance * * @function diffusion.datatypes.BinaryDataType#from */ from(buffer: Buffer): Binary; } /** * @module diffusion.datatypes */ /** * Delta that represents the difference between two binary values. * * @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 */ get(): Buffer; /** * Compare this Binary value with an earlier version to create a delta. * * Convenient equivalent to: * `diffusion.datatypes.binary().deltaSupport(type).diff(original, this);` * * Buffers may also be provided as the value to diff instead of a {@link * Binary} instance. * * **Example:** * ``` * var delta = binaryValue.diff(Buffer.from('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 | Buffer, 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 error 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 error 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 error 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 error 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 error 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}. * * @author Push Technology 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. * * 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 */ 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 */ 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 error 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 */ export declare type Int64SourceType = string | number | Buffer | 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 | Buffer, 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("12498352809328592352350908124"); * ``` * * @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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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. * * 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}. For this reason, if the {@link DataType#validate(Object) * validate} method is called on a dataType that has no bound schema, it will * always succeed. * * 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 Push Technology 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 */ 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 * var value = model.get("record", 0, "field", 0); * ``` * * @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 */ get(recordName: string, recordIndex: number, fieldName: string, fieldIndex?: number): string | null; get(recordName: string, fieldName: string, fieldIndex?: number): 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 */ 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 */ 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 on record-based topic * content. * * 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` */ 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` * */ 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` * */ 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` */ 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 */ 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; } export interface Field extends Node { /** * An optional scale definition for decimal field types */ scale?: number; } 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 content 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 content 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;