;
/**
* 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;
/**
* Create a new {@link BranchMappingTableBuilder}.
*
* @since 6.7
* @see SessionTrees
*/
export declare function newBranchMappingTableBuilder(): BranchMappingTableBuilder;
/**
* Create a new {@link SessionMetricCollectorBuilder}.
*
* @since 6.7
*/
export declare function newSessionMetricCollectorBuilder(): SessionMetricCollectorBuilder;
/**
* Create a new {@link TopicMetricCollectorBuilder}.
*
* @since 6.7
*/
export declare function newTopicMetricCollectorBuilder(): TopicMetricCollectorBuilder;
/**
* Access to the selectors namespace
*/
export declare const selectors: TopicSelectors;
/**
* Create a new {@link RemoteServerBuilder}.
*
* @since 6.7
*/
export declare function newRemoteServerBuilder(): RemoteServerBuilder;
/**
* Access to the datatypes namespace
*/
export declare const datatypes: DataTypes;
/**
* Access to the topics namespace
*/
export declare const topics: TopicsNamespace;
/**
* Access to the topicUpdate namespace
*/
export declare const topicUpdate: TopicUpdateNamespace;
/**
* The ErrorReason enum
*/
export declare const errors: {
[key: string]: ErrorReasonType;
};
/**
* Access to PropertyKeys
*/
export declare const clients: ClientControlOptionsNamespace;
/**
* Access to the locks namespace
*/
export declare const locks: SessionLockOptionsNamespace;
/**
* Permissions that are applied on a path
* @deprecated since 6.5
* Replaced by {@link PathPermission}
*/ export declare const TopicPermission: typeof PathPermission;
/**
* Access to the Buffer API that is packaged with diffusion.
*
* This can be used in browsers that don't have a native Buffer class. It allows
* the creation of buffers for use with {@link BinaryDataType binary} datatypes.
*
* @example
* ```
* const buf = diffusion.buffer.from('Hello World', 'utf8')
* ```
*/
export declare const buffer: {
prototype: Buffer;
poolSize: number;
new (str: string, encoding?: string | undefined): Buffer;
new (size: number): Buffer;
new (array: Uint8Array): Buffer;
new (arrayBuffer: ArrayBuffer): Buffer;
new (array: any[]): Buffer;
new (buffer: Buffer): Buffer;
from(arrayBuffer: ArrayBuffer, byteOffset?: number | undefined, length?: number | undefined): Buffer;
from(data: string | any[] | ArrayBuffer | Buffer): Buffer;
from(str: string, encoding?: string | undefined): Buffer;
isBuffer(obj: any): obj is Buffer;
isEncoding(encoding: string): boolean;
byteLength(string: string | DataView | ArrayBuffer | Buffer, encoding?: string | undefined): number;
concat(list: Buffer[], totalLength?: number | undefined): Buffer;
compare(buf1: Buffer, buf2: Buffer): number;
alloc(size: number, fill?: string | number | Buffer | undefined, encoding?: string | undefined): Buffer;
allocUnsafe(size: number): Buffer;
allocUnsafeSlow(size: number): Buffer;
};
/**
* @module diffusion.errors
*/
/**
* An ErrorReport from the server.
*/
export interface ErrorReport {
/**
* The error message
*/
message: string;
/**
* The line at which the problem was found
*/
line: number;
/**
* The column at which the problem was found
*/
column: number;
}
/**
* @module Session
*/
///
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.
*
*
*
*
* Option |
* Default value |
* Description |
*
*
*
*
* host |
* localhost |
* The hostname to connect to. |
*
*
* port |
* 80 or 443 |
* The 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 |
* /diffusion |
* The URL path to apply after the hostname/port. This allows additional context to be provided, such as might be
* used by load balancers. |
*
*
* secure |
* true |
* Determines 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 type |
* Default value |
* Description |
*
*
*
*
* boolean |
* true |
* Enables or disables reconnection. If set to true , reconnection will be enabled using the default
* timeout value and a periodic back-off strategy. |
*
*
* number |
* 60000 |
* Passing 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 key |
* Description |
*
*
*
*
* ws , WS , WEBSOCKET |
* The WebSocket transport. A single, long-lived WebSocket connection will be used to send and receive data. |
*
*
* xhr , XHR , HTTP_POLLING |
* An XHR-based polling transport. Data will be queued on the client and server, and sent in batches. |
*
*
*
* The client will use the transports in the order provided, for example:
* transports: ['WS', 'XHR']
indicates that the client will attempt to connect with the WebSocket
* transport, and if the connection fails, the client will attempt to connect with the HTTP Polling transport. When no
* transports
value is provided the client will default to using the WebSocket transport. Any string values
* that do not have an associated transport will be ignored.
*
* When the diffusion client is run in a browser environment, `transports` will
* default to `['WEBSOCKET', 'XHR']`. When run in Node, `transports` will
* default to `['WEBSOCKET']`.
*
* Properties:
*
* Supplied session properties will be provided to the server when a session
* is created using this session factory. The supplied properties will be
* validated during authentication and may be discarded or changed.
*
* The specified properties will be added to any existing properties set for
* this session factory. If any of the keys have been previously declared
* then they will be overwritten with the new values.
*
* For details of how session properties are used see {@link Session}.
*/
export interface Options {
/**
* The hostname to connect to (default `'localhost'`)
*/
host?: string;
/**
* The port to connect to (default `443`)
*/
port?: number | string;
/**
* The request path used for connections (default `/diffusion`)
*/
path?: string;
/**
* Whether to use secure connections.
*/
secure?: boolean;
/**
* The principal name this session should connect with. Used for authentication.
*/
principal?: string;
/**
* A password string to authenticate with, a buffer containing custom
* credentials in binary format, a typed array, or a regular
* array of octets.
*/
credentials?: string | Buffer | TypedArray | number[];
/**
* The timeout in milliseconds used when connecting to the server. (default `10000`)
*/
connectionTimeout?: 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.
*
* Property values will be sent as `string` values. Non-string properties must
* implement the `toString()` method to allow conversion.
*
* For details of how session properties are used see {@link Session}.
*/
properties?: {
[key: string]: any;
};
/**
* An optional HTTP/HTTPS proxy agent. (default `undefined`)
*
* If this is set, then the client will attempt to connect to the Diffusion
* server via a proxy server.
*
* The proxy agent will be passed to the WebSocket constructor as the
* `agent` option. See https://www.npmjs.com/package/https-proxy-agent for
* an example of a proxy agent.
*
* This option is used for web socket connections and is intended for Node
* based clients only. Browser based clients will automatically use the
* browser's proxy settings.
*
* **Example:**
* ```
* const HttpsProxyAgent = require('https-proxy-agent');
* const url = require('url');
* const diffusion = require('diffusion');
*
* const agent = new HttpsProxyAgent(url.parse('https://proxy.example.com:80'));
*
* diffusion.connect({
* host: 'https://diffusion.foo.com',
* httpProxyAgent: agent
* }).then((session) => {
* // connected through proxy server
* });
* ```
*/
httpProxyAgent?: any;
}
/**
* 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:
*
*
*
* Key |
* Description |
*
*
* `$ClientIP` |
* The Internet address of the client in string format. |
*
*
* `$ClientType` |
* The client type of the session. One of `ANDROID`, `C`, `DOTNET`, `IOS`,
* `JAVA`, `JAVASCRIPT_BROWSER`, `MQTT`, `PYTHON`, or `OTHER`. |
*
*
* `$Connector` |
* The configuration name of the server connector that the client connected
* to. |
*
*
* `$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. |
*
*
* `$GatewayType` |
* Gateway client type. Only set for gateway client sessions.
* If present it indicates the type of gateway client (e.g. Kafka). |
*
*
* `$GatewayId` |
* The identity of a gateway client session.
* Only present if the $GatewayType session property is present. |
*
*
* `$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. |
*
*
* `$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. |
*
*
* `$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. |
*
* `$MQTTClientId` |
* The MQTT client identifier. Only set for MQTT sessions. If
* present, the value of the `$ClientType` session property will be
* `MQTT`. |
*
*
* `$Principal` |
* The security principal associated with the client session. |
*
*
* `$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. |
*
*
* `$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`, `TCP`, or `OTHER`. |
*
*
*
* All user-defined property keys are non-empty strings and are case-sensitve.
* The characters ' ', '\t', '\r', '\n', '"', ''', '(', ')' are not allowed.
*
* Session properties are initially associated with a session as follows:
*
* 1. When a client starts a new session, 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.
*
* The `all` operator matches all sessions.
*
* The `has` operator checks if a property is present. This is useful for determining
* whether a user-defined property or an optional fixed property has been set for a
* session.
*
* `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 `in` operator allows for the querying of a specific session property
* to see if it exists in a defined set. An example of this would to be filter all
* sessions from a set of countries, say Germany, France, and the UK. The query would be
* `$Country in 'UK','DE','FR'`.
*
* The lists provided to `in` and `hasRoles` can optionally use square brackets and commas as delimiters.
* For example `$Country in ['UK','DE','FR']`.
*
* 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"]}`
* * `hasRoles "operator"}`
* * `$Transport is "wss" and hasRoles ["accountancy" "administrator"]`
* * `hasRoles ["operator"] and not hasRoles ["administrator"]`
* * `$Version in {"6","7","8"}`
* * `$Country in ['UK','DE','FR']`
* * `has Department`
* * `all`
*
* **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.
*
* @deprecated since 6.5
* replaced by {@link Session.sessionId sessionId}
*/
readonly sessionID: string;
/**
* The unique id assigned to this session by the server.
*/
readonly sessionId: SessionId;
/**
* The connection options used to establish this session
*/
readonly options: Options;
/**
* Exposes remote servers capabilities via {@link Session.remoteServers}
*/
readonly remoteServers: RemoteServers;
/**
* Exposes system authentication capabilities via a {@link Session.security}
*/
readonly security: Security;
/**
* Exposes session trees capabilities via {@link Session.sessionTrees}
*/
readonly sessionTrees: SessionTrees;
/**
* Exposes topic control capabilities via {@link Session.topics}
*/
readonly topics: TopicControl;
/**
* Exposes topic update capabilities via {@link Session.topicUpdate}
*/
readonly topicUpdate: TopicUpdate;
/**
* Exposes topic views capabilities via {@link Session.topicViews}
*/
readonly topicViews: TopicViews;
/**
* Exposes time series capabilities via {@link Session.timeseries}
*/
readonly timeseries: TimeSeries;
/**
* Exposes messaging capabilities via {@link Session.messages}
*/
readonly messages: Messages;
/**
* Exposes topic notification capabilities via {@link Session.notifications}
*/
readonly notifications: TopicNotifications;
/**
* Exposes client control capabilities via {@link ClientControl}
*/
readonly clients: ClientControl;
/**
* Exposes metric collector management capabilities via {@link Metrics}
*/
readonly metrics: Metrics;
/**
* Close this session's connection to the server.
*
* Calling this repeatedly will have no effect.
*
* @return this session
*/
close(): Session;
/**
* Close this session's connection to the server and return a {@link 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;
/**
* Updates the session with missing features that may have been loaded
* asynchronously. This method only has an effect when running the client
* as a modular client in the browser.
*/
updateFeatures(): void;
}
/**
* @module diffusion.clients
*/
/**
* A type containing information about the reason for a session being closed
*
* Documentation of the CloseReason values can be found under {@link CloseReasonEnum}.
*/
export interface CloseReason {
/**
* The close reason's id
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
id: number;
/**
* The close reason's description
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
message: string;
}
/**
* Enum representing the reason that the session has been closed.
*
* **Example:**
* ```
* diffusion.connect({...}).then(function(session) {...}, function(err) {
* switch(err) {
* case diffusion.clients.CloseReason.CLOSED_BY_CLIENT:
* // Do something
* case diffusion.clients.CloseReason.ACCESS_DENIED:
* // Do something else
* ...
* }
* });
* ```
*
*/ export declare const CloseReasonEnum: {
[key: string]: CloseReason;
};
/**
* @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.
*
* When running the Diffusion Client in a browser context, access to the
* `Buffer` api is made available through {@link diffusion.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.
*
* When running the Diffusion Client in a browser context, access to the
* `Buffer` api is made available through {@link diffusion.buffer}.
*
* @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
*
* When running the Diffusion Client in a browser context, access to the
* `Buffer` api is made available through {@link diffusion.buffer}.
*
* @param value the value to serialise. For primitive and JSON datatypes
* the value can be `undefined` or `null`. In this case a
* `null` value will be serialised.
* @returns the serialised value as a buffer
* @throws an error if the value can not be serialised
*/
writeValue(value: SourceType | undefined | null): 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[]) => T, buffer: Buffer, offset?: number, length?: number): T | null;
readAs(valueType: new (...args: any[]) => T, buffer: CBORType): T | null;
/**
* Obtain a {@link DeltaType} by name or delta type.
*
* **Example:**
* ```
* // Get by name
* var deltas = datatype.deltaType("binary");
* ```
*
* **Example:**
* ```
* // Get by type
* var deltas = datatype.deltaType(delta);
* ```
*
* @param name the name, as returned by {@link DeltaType.name}
* @returns the delta type
*/
deltaType(name?: string): DeltaType;
}
/**
* A placeholder data type that can represent any of the other datatypes.
*
* The sole purpose of this data type is to allow creating polymorphic streams
* that can accept any data type.
*
* **Example:**
* ```
* // Get the Any datatype and create a stream
* var anyType = diffusion.datatypes.any();
* var stream = session.addStream('some_topic', anyType);
* ```
*/
export interface AnyDataType {
/**
* The external type identifier.
*
* @return the name of this datatype
*/
name(): string;
}
/**
* @module diffusion.datatypes
*/
/**
* Diffusion datatype implementations.
*
* Datatypes are accessed via the `diffusion` singleton.
*
* **Example:**
* ```
* // Get the JSON datatype
* var json = diffusion.datatypes.json();
* ```
*
* **Example:**
* ```
* // Get a datatype via name
* var json = diffusion.datatypes.get('json');
* ```
* @namespace diffusion.datatypes
* @since 5.7
*/
export interface DataTypes {
/**
* Get the binary data type
*
* @return the Binary data type
*/
binary(): BinaryDataType;
/**
* Get the JSON data type
*
* @return the JSON data type
*/
json(): JSONDataType;
/**
* Get the Int64 data type
*
* @return the Int64 data type
*/
int64(): Int64DataType;
/**
* Get the string data type
*
* @return the String data type
*/
string(): StringDataType;
/**
* Get the double data type
*
* @return the Double data type
*/
double(): DoubleDataType;
/**
* Get the record V2 data type
*
* @return the RecordV2 data type
*/
recordv2(): RecordV2DataType;
/**
* Get the Any data type
*
* @return the Any data type
*/
any(): AnyDataType;
/**
* Get the timeseries data type
*
* @param valueType the value type of the timeseries data type
* @return a timeseries data type
*/
timeseries(valueType: DataType): DataType, Event, Bytes>;
/**
* Obtain a {@link DataType} implementation by type
* name, topic type, or value class
*
* @param name the type name as returned by {@link DataType.name}, the value
* or a topic type.
* @return the data type or `null` if no datatype was found
*/
get(name: any): DataType | null;
/**
* Obtain a {@link DataType} implementation by value class.
*
* For {@link DoubleDataType}, the associated value class is `Number`.
*
* @param valueClass the class
* @return the data type
* @throws an 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.
*
* When running the Diffusion Client in a browser context, access to the
* `Buffer` api is made available through {@link diffusion.buffer}.
*
* @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;
}
/**
* @module diffusion.errors
*/
/**
* A type containing information about the reason that an error occured
*/
export interface ErrorReasonType {
/**
* The error reason's id
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
id: number;
/**
* The error reason's description
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
reason: string;
}
/**
* Enum containing reason codes used to report error conditions.
*
* Some common ErrorReason values are defined as global constants. More specific reasons may be defined by
* individual features.
*
* **Example:**
* ```
* // Handle an error from the server
* session.addStream('foo', diffusion.datatypes.string()).on('error', function(e) {
* if (e == diffusion.errors.ACCESS_DENIED) {
* // Handle authorisation error
* } else {
* // Log the problem
* console.log(e);
* }
* });
* ```
*/ export declare const ErrorReason: {
[key: string]: ErrorReasonType;
};
/**
* @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;
MQTT_CLIENT_ID: string;
GATEWAY_TYPE: string;
GATEWAY_ID: string;
}
/**
* @hidden
*/
export interface ClientControlOptionsNamespace {
PropertyKeys: PropertyKeys;
ANONYMOUS: string;
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 one or more client sessions.
*
* **Example:**
* ```
* session.clients.close(otherSessionID).then(function() {
* // Other session has been closed
* }, function(err) {
* // There was an error when trying to close the other session
* });
* ```
*
* @param sessions Either a {@link SessionId} that identifies a single
* client session, or a filter that identifies the set
* of client sessions for which the change will be
* applied. If a string is passed and is a parsable
* `SessionId`, it is treated as a `SessionId`, otherwise
* it assumed to be a filter.
* @return a {@link Result} that resolves to the number of affected
* sessions
*/
close(sessions: 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 Either a {@link SessionId} that identifies a single
* client session, or a filter that identifies the set
* of client sessions for which the change will be
* applied. If a string is passed and is a parsable
* `SessionId`, it is treated as a `SessionId`, otherwise
* it assumed to be a filter.
* @param selector the Topic Selector to 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 Either a {@link SessionId} that identifies a single
* client session, or a filter that identifies the set
* of client sessions for which the change will be
* applied. If a string is passed and is a parsable
* `SessionId`, it is treated as a `SessionId`, otherwise
* it assumed to be a filter.
* @param selector the Topic Selector to unsubscribe from
* @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.
*
* It is also permissible to change the values of the following fixed
* session properties :-
*
* $Country - will be normalised to upper case
* $Language - will be normalised to lower case
* $Latitude - Invalid value will be set to "NaN"
* $Longitude - Invalid value will be set to "NaN"
*
* If values are provided for any other fixed session properties they will
* be ignored.
*
* **Example:**
* ```
* // Add a new session property for client whose session id is 'id'.
* session.clients.setSessionProperties(id, { 'foo': 'bar' });
*
* // Remove a session property for client whose session id is 'id'.
* session.clients.setSessionProperties(id, { 'foo': null }).then(function(properties) {
* console.log('Properties changed ', properties);
* }, function(err) {
* console.log('Unable to change properties: ', err);
* });
* ```
*
* @param session identifies the client session
* @param properties the properties to change. Each entry in the map is a
* property name and the new value. If the value is
* `null` , any existing property with that
* name will be removed (unless it is a fixed property).
* Otherwise if the property name does not match any existing
* property, that entry will be added as a new property
* (although properties starting $ will be ignored).
* @returns a {@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.
*
* It is also permissible to change the values of the following fixed
* session properties :-
*
* $Country - will be normalised to upper case
* $Language - will be normalised to lower case
* $Latitude - Invalid value will be set to "NaN"
* $Longitude - Invalid value will be set to "NaN"
*
* If values are provided for any other fixed session properties they will
* be ignored.
*
* **Example:**
* ```
* // Remove session property {job=employee}
* session.clients.setSessionPropertiesByFilter("job is 'employee'", { 'job': null }).then(function () {
* // All sessions satisfied the filter have updated their properties
* }, function (err) {
* console.log("Failed to update properties ", err);
* });
* ```
* @param filter session filter
* @param properties the properties to change. Each entry in the map is a
* property name and the new value. If the value is
* `null` , any existing property with that
* name will be removed (unless it is a fixed property).
* Otherwise if the property name does not match any existing
* property, that entry will be added as a new property
* (although properties starting $ will be ignored).
*
* @returns a Result that resolves when session properties have been changed.
*
* If successful, the result resolves with an integer value which
* represents a number of sessions that have matched the filter and
* for which the specified properties changes have been applied.
*
The operation can fail,
* common reasons for failure include:
*
* - {@link ErrorReason.ACCESS_DENIED} if the calling session
* does not have sufficient permission.
* - {@link ErrorReason.NO_SUCH_SESSION} if the calling
* session is closed before the response was delivered.
*
- {@link ErrorReason.SESSION_CLOSED} if the calling
* session is closed.
*
- a filter string was supplied that could not be parsed
*
*/
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. If a string is passed and is a parsable
* `SessionId`, it is treated as a `SessionId`, otherwise
* it assumed to be a filter.
* @param rolesToRemove a set of roles to be removed from the session. If
* one or more roles from the list are not currently
* assigned, they are ignored.
* @param rolesToAdd a set of roles to be added to the session. If one or
* more roles from the list are already assigned, they
* are ignored.
* @return a 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;
/**
* Control client queue conflation.
*
* Each session begins with conflation enabled or disabled based on the
* queue configuration of the connector it is using. This method allows
* conflation to be enabled or disabled for specific sessions at runtime.
*
* Conflation is the process of merging or discarding topic updates queued
* for a session to reduce the server memory footprint and network data.
* Conflation needs to be enabled for a session and a policy configured for
* the topic to have an effect. Policies are configured on a per-topic
* basis using the {@link CONFLATION topic property CONFLATION}.
*
* @param sessions Either a {@link SessionId} that identifies a single
* client session, or a filter that identifies the set
* of client sessions for which the change will be
* applied. If a string is passed and is a parsable
* `SessionId`, it is treated as a `SessionId`, otherwise
* it assumed to be a filter.
*
* @param conflate `true` to enable conflation, `false` to disable conflation
*
* @return a {@link Result} that resolves to the number of affected
* sessions
*
* If the conflation policy was updated for the identified session,
* the Result will resolve successfully.
*
* Otherwise, the Result fails with an Error. Common reasons for
* failure include:
*
* - the identified session was closed before the response was
* delivered;
*
- the calling session does not have `MODIFY_SESSION` and
* `VIEW_SESSION` permissions;
*
- the calling session is closed.
*
*
* @since 6.5
*/
setConflated(sessions: SessionId | string, conflated: boolean): 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. The function will resolve when the handler
* has been deregistered.
*/
onActive(deregister: () => Promise): void;
/**
* Called when the listener is deregistered, or the session is closed.
*/
onClose(): void;
/**
* Notification of a contextual error related to this handler. This is
* analogous to an unchecked exception being raised. Situations in which
* onError is called include the session being closed before the
* handler is registered, a communication timeout, or a problem with the
* provided parameters. No further calls will be made to this handler.
*
* @param error the error
*
* @since 5.9
*/
onError(error: any): void;
/**
* Notification that a new client session has been opened.
*
* When the listener is registered, this will be called for all existing
* sessions. It will then be called for every client session that opens
* whilst the listener is registered.
*
* This will be called for client session regardless of requested session
* properties.
*
* @param session the session identifier
* @param properties the map of requested session property values.
*/
onSessionOpen(session: SessionId, properties: SessionProperties): void;
/**
* Notification of a session event that can result in a change of properties.
*
* @param session the session identifier
* @param type the type of event
* @param properties the map of requested property values
* @param previous a map of previous values for keys that have changed.
* This will only contain changed values and not the
* whole required property set.
*/
onSessionEvent(session: SessionId, type: SessionEventType, properties: SessionProperties, previous: SessionProperties): void;
/**
* Notification that a client session has closed.
*
* This will be called for every client that closes whilst the listener is
* registered, regardless of requested session properties.
*
* @param session the session identifier
* @param properties the map of requested property values
* @param reason the reason why the session was closed
*/
onSessionClose(session: SessionId, properties: SessionProperties, reason: {}): void;
}
/**
* @module Session.messages
*/
/**
* Messages Feature.
*
* This feature provides a client session with request-response messaging
* capabilities that can be used to implement application services.
*
* Request-response messaging allows a session to send requests to other
* sessions. Each receiving session provides a corresponding response, which is
* returned to the sending session. Each request and response carries an
* application provided value.
*
* The method used to send a request determines which sessions will receive it.
* Each request is routed using the provided *message path* – an application
* provided string. Two addressing schemes are provided: *unaddressed requests*
* and *addressed requests*.
*
* ### Unaddressed requests
*
* A session can provide an application service by implementing a handler and
* registering it with the server. This is somewhat similar to implementing a
* REST service, except that interactions between the sender and receiver are
* asynchronous.
*
* Unaddressed requests sent using {@link Messages.sendRequest sendRequest} are
* routed by the server to a handler that has been pre-registered by another
* session, and matches the message path.
*
* Handlers are registered with {@link Messages.addRequestHandler}. Each session
* may register at most one handler for a given message path. Optionally, one or
* more session property names can be provided (see {@link Session} for a full
* description of session properties), in which case the values of the session
* properties for each recipient session will be returned along with its
* response. To add a request handler, the control client session must have
* {@link GlobalPermission.REGISTER_HANDLER REGISTER_HANDLER} permission. If
* registering to receive session property values, the session must also have
* {@link GlobalPermission.VIEW_SESSION VIEW_SESSION} permission.
*
* Routing works as follows:
*
*
* - The session {@link Messages.sendRequest sends} the request, providing the
* message path, the request value and data type, and the expected response
* type.
*
- The server uses the message path to apply access control. The sender must
* have the {@link PathPermission.SEND_TO_MESSAGE_HANDLER
* SEND_TO_MESSAGE_HANDLER} path permission for the message path, or the request
* will be rejected.
*
- The server uses the message path to select a pre-registered handler and
* route the request to the appropriate recipient session. The server will
* consider all registered handlers and select one registered for the most
* specific path. If multiple sessions have registered a handler registered for
* a path, one will be chosen arbitrarily. If there is no registered handler
* matching the message path, the request will be rejected.
*
- Otherwise, the server forwards the request to one of the sessions
* registered to handle the message path. The message path is also passed to the
* recipient session, providing a hierarchical context.
*
- The recipient session processes the request and returns a response to the
* server, which forwards the response to the sending session.
*
*
* Registration works across a cluster of servers. If no matching handler is
* registered on the server to which the sending session is connected, the
* request will be routed to another server in the cluster that has one.
*
* ### Addressed requests
*
* Addressed requests provide a way to perform actions on a group of sessions,
* or to notify sessions of one-off events (for repeating streams of events, use
* a topic instead).
*
* An addressed request can be sent to a set of sessions using {@link
* Messages.sendRequestToFilter sendRequestToFilter}. For the details of session
* filters, see {@link Session}. Sending a request to a filter will match zero
* or more sessions. Each response received will be passed to the provided
* {@link FilteredResponseHandler callback}. As a convenience, an addressed
* request can be sent a specific session using the overloaded variant of {@link
* Messages.sendRequest sendRequest} that accepts a session id.
*
* Sending an addressed request requires {@link PathPermission.SEND_TO_SESSION
* SEND_TO_SESSION} permission.
*
* If the sending session is connected to a server belonging to a cluster, the
* recipient sessions can be connected to other servers in the cluster. The
* filter will be evaluated against all sessions hosted by the cluster.
*
* To receive addressed requests, a session must set up a local request stream
* to handle the specific message path, using {@link Messages.setRequestStream
* setRequestStream}. When a request is received for the message path, the
* {@link RequestStream.onRequest onRequest} method on the stream is triggered.
* The session should respond using the provided {@link Responder
* responder}. Streams receive an {@link RequestStream.onClose onClose} callback when
* unregistered and an {@link RequestStream.onError onError} callback if the session is
* closed.
*
* If a request is sent to a session that does not have a matching stream for
* the message path, an error will be returned to the sending session.
*
* ### Accessing the feature
*
* Obtain this feature from a {@link Session session} as follows:
*
* **Example:**
* ```
* // Get a reference to messaging feature
* var messages = session.messages;
* ```
*/
export interface Messages {
/**
* Register a request handler to handle requests from other client sessions
* for a branch of the message path hierarchy.
*
* Each control session may register a single handler for a branch. When the
* handler is no longer required, it may be closed using the {@link
* Registration} provided by the result. To change the handler for a
* particular branch the previous handler must first be closed.
*
* **Example:**
* ```
* // Create a request handler that handles strings
* var handler = {
* onRequest: function(request, context, responder) {
* console.log(request); // Log the request
* responder.respond('something');
* },
* onError: function() {},
* onClose: function() {}
* };
*
* // Register the handler
* control.messages.addRequestHandler('test/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 of keys of session properties
* that should be supplied with each request. See {@link Session} for
* a full list of available fixed property keys. To request all fixed
* properties include {@link PropertyKeys.ALL_FIXED_PROPERTIES} as a
* key. In this case any other fixed property keys would be ignored.
* To request all user properties include {@link
* PropertyKeys.ALL_USER_PROPERTIES} as a key. In this case any other
* user properties are ignored.
* @param requestType an optional request data type
* @returns the registration {@link Result} that resolves
* when the handler has been registered, returning a {@link
* Registration} which can be used to unregister the handler.
*
* Otherwise, the Result will fail with an error. Common reasons for
* failure include:
*
* - the session is closed;
*
- the session has already registered a handler for this message
* path;
*
- the session does not have `REGISTER_HANDLER` permission to
* register a request handler on the server;
*
- the session does not have `VIEW_SESSION` permission to access
* the client's session properties.
*
*/
addRequestHandler(path: string, handler: RequestHandler, sessionProperties?: string[], requestType?: DataType): Result;
/**
* Send a request. If a `target` is supplied, the request will be sent to
* the target session only.
*
* 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}
* @return A {@link Result} that resolves with the response when a response
* has been received by the session if the task completes
* successfully.
*
* Otherwise, the Result will fail with an Error. Common reasons for
* failure include:
*
* - the session does not exist on the server;
*
- the recipient session does not have a local request stream
* registered for this path;
*
- the request is not compatible with the datatype bound to the
* handler's message path;
*
- the response is not compatible with the specified response
* type;
*
- the request has been rejected by the recipient session
* calling `Responder.reject(message)`;
*
- the session is closed;
*
- the session does not have `SEND_TO_SESSION` permission;
*
*/
sendRequest(path: string, request: any, target: SessionId | string, requestType?: DataType | TopicType | (new (...args: any[]) => any) | string, responseType?: DataType | TopicType | (new (...args: any[]) => any) | string): Result;
sendRequest(path: string, request: any, requestType?: DataType | TopicType | (new (...args: any[]) => any) | string, responseType?: DataType | TopicType | (new (...args: any[]) => any) | 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. See {@link Session}
* for a full description of filter expressions.
* @param path message path used by the recipient to select an
* appropriate handler
* @param request the request to send
* @param callback the handler to receive notification of responses
* (or errors) from sessions
* @param requestType] an optional request {@link DataType DataType}
* @param responseType an optional response {@link DataType DataType}
* @return a Result that resolves when the server has dispatched all the
* requests.
*
* If the server successfully evaluated the filter, the result of
* this contains the number of sessions the request was sent to.
* Failure to send a request to a particular matching session is
* reported to the `callback`.
*
* Otherwise, the Result will fail with an Error. Common reasons for
* failure include:
*
* - the `filter` parameter could not be parsed;
*
- the calling session does not have `SEND_TO_SESSION` and
* `VIEW_SESSION` permissions;
*
- the calling session is closed.
*
*/
sendRequestToFilter(filter: string, path: string, request: any, callback: FilteredResponseHandler, reqType?: DataType | TopicType | (new (...args: any[]) => any), respType?: DataType | TopicType | (new (...args: any[]) => any)): 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 | TopicType | (new (...args: any[]) => any), resType?: DataType | TopicType | (new (...args: any[]) => any)): RequestStream | undefined;
/**
* Remove the request stream at a particular path.
*
* @param path the path at which to remove the request stream
* @returns the request stream that was removed from the path. If
* the path does not have a request stream assigned (or the
* path does not exist), `undefined` will be returned instead.
*/
removeRequestStream(path: string): RequestStream | undefined;
}
/**
* Interface which specifies a request stream to receive request notifications.
*/
export interface RequestStream {
/**
* Called to indicate a request has been received.
*
* @param path the path the request was sent on
* @param request the request that was received
* @param responder the responder to dispatch a response back to the requester
*/
onRequest(path: string, request: any, responder: Responder): void;
/**
* Notification of a contextual error related to this stream. This is
* analogous to an Error being thrown. Situations in which
* `onError` is called include being unable to parse the request
* with the data type the stream was registered with. No further calls will
* be made to this stream.
*
* @param error the error
*/
onError(error: ErrorReasonType): void;
/**
* Called when the request stream is removed, or the session is closed.
*/
onClose(): void;
}
/**
* Interface which specifies a request handler to receive request notifications.
*
* @class Session.messages.RequestHandler
*/
export interface RequestHandler {
/**
* Called to indicate a request has been received.
*
* @param {Object} request - The request that was received
* @param {Session.messages.RequestContext} context - Context object that provides the session id
* (session that sent the request), path and session properties
* @param {Session.messages.Responder} responder - The responder to dispatch a response back to the requester
* @function Session.messages.RequestHandler.onRequest
*/
onRequest(request: any, context: RequestContext, responder: Responder): void;
/**
* Notification of a contextual error related to this handler. This is
* analogous to an Error being thrown. Situations in which
* `onError` is called include the session being closed before the
* handler is registered, a communication timeout, or a problem with the
* provided parameters. No further calls will be made to this handler.
*
* @param error the error
*/
onError(error: any): void;
/**
* Called when the request handler is unregistered, or the session is closed.
*/
onClose(): void;
}
/**
* Interface which specifies a response handler for requests dispatched through
* a filter.
*/
export interface FilteredResponseHandler {
/**
* Called to indicate a response has been received.
*
* @param sessionId session ID of the session that sent the response
* @param response response object
* @function Session.messages.FilteredResponseHandler.onResponse
*/
onResponse(sessionId: SessionId, response: any): void;
/**
* Called when a response from a session results in an error.
*
* @param sessionId sessionID of the session in error
* @param errorReason the error reason
*/
onResponseError(sessionId: SessionId, error: Error): void;
/**
* 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
*
* @deprecated since 6.6 this method is no longer called and will be removed
* in a future release
*/
onError?(error: Error): void;
/**
* @deprecated since 6.6 this method is not called and will be removed in a
* future release
*/
onClose?(): void;
}
/**
* Responder interface to dispatch responses to requests.
*/
export interface Responder {
/**
* Dispatch a response to a request.
*
* @param response the response to send
* @param dataType the datatype of the response
*/
respond(response: any, dataType?: DataType | TopicType | (new (...args: any[]) => any)): void;
/**
* Reject a message
*
* @param message the message indicating the failure
*/
reject(message: string): void;
}
/**
* A message request context
*/
export interface RequestContext {
/**
* SessionId of the session that sent the request
*/
sessionId: SessionId;
/**
* The message path of the request
*/
path: string;
/**
* The session properties
*/
properties: {
[key: string]: string;
};
}
/**
* This feature allows a client to configure metric collectors.
*
* Diffusion servers provide metrics which are made available in several ways:
*
* - Java Management Extensions (JMX) MBeans.
*
- Through the Diffusion Management Console.
*
- As endpoints for Prometheus.
*
*
* Metric collectors allow custom aggregation of metrics that are relevant to
* your application. There are no default metric collectors, only the ones that
* you create.
*
* There are two types of metric collector: Session Metric Collectors and Topic
* Metric Collectors.
*
* For full details regarding the configuration and operation of metric
* collectors see the user manual.
*
* Session Metric Collectors.
*
* These can be configured to record metric data for a subset of all sessions,
* specified with a session filter.
*
* The set of metrics recorded by each session metric collector is the same as
* those recorded for the whole server. For full details of session metrics, see
* the table in the user manual.
*
* If the session filters of two different session metric collectors select the
* same session, both will record metrics for that session. It is only valid to
* add the metrics of different session metric collectors if their session
* filters select distinct sets of sessions.
*
* You can optionally group the sessions within a collector by session
* properties.
*
* Topic Metric Collectors
*
* These can be configured to record metric data for a subset of all topics,
* specified with a topic selector.
*
* You can optionally group the topics within a collector by topic type.
*
* The set of metrics recorded by each topic metric collector is the same as
* those recorded for the whole server. For full details of topic metrics, see
* the table in the user manual.
*
* If the topic selectors of two different topic metric collectors select the
* same topic, both will record metrics for that topic. It is only valid to add
* the metrics of different topic metric collectors if their topic selectors
* select distinct sets of topics.
*
* Access control
*
* The following access control restrictions are applied:
*
* - To {@link Metrics.putSessionMetricCollector put} or
* {@link Metrics.removeSessionMetricCollector remove} a session metric collector, a
* session needs the {@link GlobalPermission.CONTROL_SERVER CONTROL_SERVER}
* global permission.
*
- To {@link Metrics.putTopicMetricCollector put} or
* {@link Metrics.removeTopicMetricCollector remove} a topic metric collector, a
* session needs the {@link GlobalPermission.CONTROL_SERVER CONTROL_SERVER}
* global permission.
*
- To list {@link Metrics.listSessionMetricCollectors session metric collectors} or
* {@link Metrics.listTopicMetricCollectors topic metric collectors}, a session needs
* the {@link GlobalPermission.VIEW_SERVER VIEW_SERVER} global permission.
*
*
* Accessing the feature
*
* This feature may be obtained from a {@link Session session} as follows:
*
*
* const metrics = session.metrics;
*
*
* @author Push Technology Limited
*
* @since 6.7
*/
export interface Metrics {
/**
* Add a session metric collector, replacing any with the same name.
*
* A {@link SessionMetricCollector} instance can be created using
* {@link Diffusion.newSessionMetricCollectorBuilder
* newSessionMetricCollectorBuilder}.
*
* @param collector the session metric collector
*
* @return a Result that resolves when a response is received
* from the server.
*
* If the task completes successfully, the result will be null. The
* result type is `any` rather than `void` to provide forward
* compatibility with future iterations of this API that may provide
* a non-null result with a more specific result type.
*
* Otherwise, the Result will reject with an Error. Common reasons
* for failure include:
*
* - if the metric collector session filter is invalid;
*
- if the calling session does not have {@link
* GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission;
*
- if the operation failed due to a transient cluster error;
*
- if the session is closed.
*
*/
putSessionMetricCollector(collector: SessionMetricCollector): Result;
/**
* Retrieves the current session metric collectors.
*
* @return a Result that completes when a response is received
* from the server.
*
* If the task completes successfully, the result will be a list of
* current session metric collectors.
*
* Otherwise, the Result will reject with an Error. Common reasons
* for failure include:
*
* - if the calling session does not have {@link
* GlobalPermission.VIEW_SERVER VIEW_SERVER} permission;
*
- if the session is closed.
*
*/
listSessionMetricCollectors(): Result;
/**
* Removes any session metric collector with the given name, if it exists.
*
* @param name the session metric collector name
*
* @return a Result that resolves when a response is received
* from the server.
*
* If the task completes successfully, the result will be null. The
* result type is `any` rather than `void` to provide forward
* compatibility with future iterations of this API that may provide
* a non-null result with a more specific result type.
*
* Otherwise, the Result will reject with an Error. Common reasons
* for failure include:
*
* - if the calling session does not have {@link
* GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission;
*
- if the operation failed due to a transient cluster error;
*
- if the session is closed.
*
*/
removeSessionMetricCollector(name: string): Result;
/**
* Add a topic metric collector, replacing any with the same name.
*
* A {@link TopicMetricCollector} instance can be created using
* {@link Diffusion.newTopicMetricCollectorBuilder
* newTopicMetricCollectorBuilder}.
*
* @param collector the topic metric collector
*
* @return a Result that resolves when a response is received from the
* server.
*
* If the task completes successfully, the result will be null. The
* result type is `any` rather than `void` to provide forward
* compatibility with future iterations of this API that may provide
* a non-null result with a more specific result type.
*
* Otherwise, the Result will reject with an Error. Common reasons
* for failure include:
*
* - if the metric collector session filter is invalid;
*
- if the calling session does not have {@link
* GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission;
*
- if the operation failed due to a transient cluster error;
*
- if the session is closed.
*
*/
putTopicMetricCollector(collector: TopicMetricCollector): Result;
/**
* Retrieves the current topic metric collectors.
*
* @return a Result that completes when a response is received
* from the server.
*
* If the task completes successfully, the result will be a list of
* current topic metric collectors.
*
* Otherwise, the Result will reject with an Error. Common reasons
* for failure include:
*
* - if the calling session does not have {@link
* GlobalPermission.VIEW_SERVER VIEW_SERVER} permission;
*
- if the session is closed.
*
*/
listTopicMetricCollectors(): Result;
/**
* Removes any topic metric collector with the given name, if it exists.
*
* @param name the topic metric collector name
*
* @return a Result that resolves when a response is received from the
* server.
*
* If the task completes successfully, the result will be null. The
* result type is `any` rather than `void` to provide forward
* compatibility with future iterations of this API that may provide
* a non-null result with a more specific result type.
*
* Otherwise, the Result will reject with an Error. Common reasons
* for failure include:
*
* - if the calling session does not have {@link
* GlobalPermission.CONTROL_SERVER CONTROL_SERVER} permission;
*
- if the operation failed due to a transient cluster error;
*
- if the session is closed.
*
*/
removeTopicMetricCollector(name: string): Result;
}
/**
* A list of session metric collectors
*/
export interface SessionMetricCollectorList {
/**
* The collectors.
*/
readonly collectors: SessionMetricCollector[];
}
/**
* A list of session metric collectors
*/
export interface TopicMetricCollectorList {
/**
* The collectors.
*/
readonly collectors: TopicMetricCollector[];
}
/**
* The common base interface for metric collectors.
*/
export interface MetricCollector {
/**
* the name of the metric collector
*/
readonly name: string;
/**
* Indicates whether the metric collector exports to Prometheus.
*/
readonly exportToPrometheus: boolean;
/**
* Limit on the number of groups maintained by this metric collector.
*
* Session metric collectors can
* {@link SessionMetricCollector.getGroupByProperties group metrics by
* property}. Topic metric collectors can
* {@link TopicMetricCollector#groupsByTopicType group metrics by
* topic type}. This property places an upper limit on the number of
* groups that will be maintained for the metric collector.
*
* For example, if a session metric collector groups by `$SessionId` and
* maximumGroups is 10, then metrics will only be collected for the
* first 10 sessions.
*
* @since 6.8
*/
readonly maximumGroups: number;
}
/**
* The definition of a session metric collector.
*
* These can be configured to record metric data for a subset of all
* sessions, specified with a session filter.
*/
export interface SessionMetricCollector extends MetricCollector {
/**
* the session filter
*/
readonly sessionFilter: string;
/**
* list of properties to group by
*/
readonly groupByProperties: string[];
/**
* Indicates whether metrics with no matches should be removed.
*/
readonly removeMetricsWithNoMatches: boolean;
}
/**
* A session metric collector builder.
*
* A builder of this type may be created using
* {@link Diffusion.newSessionMetricCollectorBuilder
* newSessionMetricCollectorBuilder} and used to create instances of
* {@link SessionMetricCollector} that can be supplied to
* {@link Metrics.putSessionMetricCollector putSessionMetricCollector}.
*/
export interface SessionMetricCollectorBuilder {
/**
* Specifies whether the metric collector should export metrics to
* Prometheus or not.
*
* The default is that metrics are not exported to Prometheus.
*
* @param export true to export metrics to Prometheus
*
* @return this builder
*/
exportToPrometheus(exportMetrics: boolean): SessionMetricCollectorBuilder;
/**
* Set the maximum number of groups maintained by the metric collector.
*
* By default, the number of groups is not limited.
*
* @param limit a positive integer
* @see {@link MetricCollector.maximumGroups}
*/
maximumGroups(limit: number): SessionMetricCollectorBuilder;
/**
* Adds the name of a session property to group by to the list known
* to this builder.
*
* By default a builder will initially have no session properties to
* group by set.
*
* @param propertyName the name of the session property. See
* {@link Session} for details of session properties
*
* @return this builder
*/
groupByProperty(propertyName: string): SessionMetricCollectorBuilder;
/**
* Specifies a list of session property names to group by, replacing
* any current list known to this builder.
*
* @param propertyNames a list of session property names. See
* {@link Session} for details of session properties
*
* @return this builder
*/
groupByProperties(propertyNames: string[]): SessionMetricCollectorBuilder;
/**
* Specifies whether the metric collector should remove any metrics
* that have no matches.
*
* The default is that the metric collector will not remove metrics
* with no matches.
*
* @param remove true to indicate that metrics with no matches
* should be removed
*
* @return this builder
*/
removeMetricsWithNoMatches(remove: boolean): SessionMetricCollectorBuilder;
/**
* Reset the builder.
*
* @return this Builder
*/
reset(): SessionMetricCollectorBuilder;
/**
* Create a new {@link SessionMetricCollector} using the values
* currently known to this builder.
*
* @param name the name of the {@link SessionMetricCollector}
*
* @param sessionFilter the session filter indicating the sessions
* this collector should apply to. The format of a session
* property filter is documented in {@link Session}
*
* @return a new {@link SessionMetricCollector} with all of the
* current settings of this builder
*/
create(name: string, sessionFilter: string): SessionMetricCollector;
}
/**
* The definition of a topic metric collector.
*
* These can be configured to record metric data for a subset of all topics,
* specified with a topic selector.
*/
export interface TopicMetricCollector extends MetricCollector {
/**
* the topic selector
*/
readonly topicSelector: string;
/**
* Indicates whether the collector groups by topic type.
*/
readonly groupByTopicType: boolean;
/**
* The number of leading parts of the topic path to group by, or
* 0 if the collector does not group by path prefix
*
* @since 6.8
*/
readonly groupByPathPrefixParts: number;
}
/**
* A topic metric collector builder.
*
* A builder of this type may be created using {@link
* Diffusion.newTopicMetricCollectorBuilder newTopicMetricCollectorBuilder} and
* used to create instances of {@link TopicMetricCollector} that can be supplied
* to {@link Metrics.putTopicMetricCollector putTopicMetricCollector}.
*/
export interface TopicMetricCollectorBuilder {
/**
* Specifies whether the metric collector should export metrics to
* Prometheus or not.
*
* The default is that metrics are not exported to Prometheus.
*
* @param export true to export metrics to Prometheus
*
* @return this builder
*/
exportToPrometheus(exportMetrics: boolean): TopicMetricCollectorBuilder;
/**
* Set the maximum number of groups maintained by the metric collector.
*
* By default, the number of groups is not limited.
*
* @param limit a positive integer
* @see {@link MetricCollector.maximumGroups}
*/
maximumGroups(limit: number): TopicMetricCollectorBuilder;
/**
* Specifies whether the metric collector should group by topic
* type.
*
* By default a topic metric collector does not group by topic type.
*
* @param groupByTopicType true to indicate that the collector
* should group by topic type
*
* @return this builder
*/
groupByTopicType(groupByTopicType: boolean): TopicMetricCollectorBuilder;
/**
* Specifies the number of leading parts of the topic path the
* metric collector should use to group results.
*
* By default a topic metric collector does not group by the topic
* path prefix. If a positive number of parts is specified, it
* will enable grouping.
*
* @param parts the number of leading parts of the topic path to
* group by; set to 0 to disable grouping by path
* @return this builder
* @since 6.8
*/
groupByPathPrefixParts(parts: number): TopicMetricCollectorBuilder;
/**
* Reset the builder.
*
* @return this Builder
*/
reset(): TopicMetricCollectorBuilder;
/**
* Create a new {@link TopicMetricCollector} using the values
* currently known to this builder.
*
* @param name the name of the {@link TopicMetricCollector}
*
* @param topicSelector the selector pattern that specifies the
* topics for which metrics are to be collected
*
* @return a new {@link TopicMetricCollector} with all of the
* current settings of this builder
*/
create(name: string, topicSelector: string | TopicSelector): TopicMetricCollector;
}
/**
* @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.remoteServers
*/
/**
* Connection option key.
*/
export declare enum ConnectionOption {
/**
* Specifies the connection timeout session attribute value (in milliseconds).
*
* If a value is not specified the session's default connection timeout is used.
*/
CONNECTION_TIMEOUT = 1,
/**
* Specifies the input buffer size session attribute.
*
* This is the size of the input buffer to use for the connection with the remote server.
* It is used to receive messages from the remote server.
* This should be set to the same size as the output buffer used at the remote server.
*
* If not specified, a default of 1024k is used.
*/
INPUT_BUFFER_SIZE = 2,
/**
* Specifies the maximum queue size session attribute.
*
* This is the maximum number of messages that can be queued to send to the remote server.
* If this number is exceeded, the connection will be closed.
* This must be sufficient to cater for messages that may be queued whilst disconnected (awaiting reconnect).
*
* The default value is 10,000 messages.
*/
MAXIMUM_QUEUE_SIZE = 3,
/**
* Specifies the output buffer size session attribute.
*
* This is the size of the output buffer to use for the connection with the remote server.
* It is used to send messages to the remote server.
* This should be set to the same size as the input buffer used by the remote server.
*
* If not specified, a default of 1024k is used.
*/
OUTPUT_BUFFER_SIZE = 4,
/**
* Specifies the reconnection timeout session attribute.
*
* This is the total time in milliseconds that will be allowed to reconnect a failed connectionto the
* remote server.
*
* For reconnection to work the remote server connector must have been configured to support reconnection.
*
* If a value is not specified the session's default reconnection timeout is used.
*/
RECONNECTION_TIMEOUT = 5,
/**
* Specifies the recovery buffer size session attribute.
*
* If the remote server is configured to support reconnection, a session established with a non-zero
* reconnect-timeout retains a buffer of sent messages.
* If the session disconnects and reconnects, this buffer is used to re-send messages that the server
* has not received.
*
* The default value is 10,000 messages. If reconnect-timeout is 0 then this value is ignored.
*/
RECOVERY_BUFFER_SIZE = 6,
/**
* Specifies the delay after losing a connection before attempting a reconnection.
*
* The value is specified in milliseconds. Default 1000 (1 second).
*/
RETRY_DELAY = 7,
/**
* Specifies the write timeout session attribute value (in milliseconds).
*
* If a value is not specified the session's default write timeout is used.
*/
WRITE_TIMEOUT = 8
}
/**
* Represents the current connection state of a remote server.
*/
export declare enum ConnectionState {
/**
* The connection is inactive.
*
* This means that the remote server can successfully connect but a
* physical connection is not being maintained as there are no
* components that require the remote server.
*
* If in an inactive or failed state, a test connection will have
* been tried to check that the connection can be made and the
* connection will then have been closed.
*/
INACTIVE = 1,
/**
* The remote server is connected and actively in use by components
* that require it.
*/
CONNECTED = 2,
/**
* The connection has failed but a retry is scheduled.
*
* In this case {@link RemoteServerStatus.failureMessage}
* will provide details of the failure that resulted in a retry.
*/
RETRYING = 3,
/**
* The connection failed to establish.
*
* If the connection was in an inactive or failed state state, a
* test connection was tried and failed.
*
* In this case {@link RemoteServerStatus.failureMessage}
* will provide more detail.
*/
FAILED = 4,
/**
* The named remote server did not exist.
*/
MISSING = 5
}
/**
* A complete map of {@link ConnectionOption ConnectionOption}s to values.
*/
export declare type ConnectionOptions = {
[key in ConnectionOption]: string;
};
/**
* Description of a remote server that has been created.
*
* @since 6.5
*/
export interface RemoteServer {
/**
* The name of the remote server.
*/
readonly name: string;
/**
* The url used for connection to the remote server.
*/
readonly url: string;
/**
* The principal used for connection to the remote server.
*/
readonly principal: string;
/**
* Options used for connection to the remote server.
*/
readonly connectionOptions: ConnectionOptions;
/**
* The missing topic notification filter expression or `undefined` if one
* has not been specified.
*/
readonly missingTopicNotificationFilter?: string;
}
/**
* Definition of a remote server that should be created.
*
* @since 6.7
*/
export interface RemoteServerDefinition {
/**
* The name of the remote server.
*/
readonly name: string;
/**
* The url used for connection to the remote server.
*/
readonly url: string;
/**
* The principal used for connection to the remote server.
*/
readonly principal: string;
/**
* The credentials used for connection to the remote server.
*/
readonly credentials: Credentials;
/**
* Options used for connection to the remote server.
*/
readonly connectionOptions: Partial;
/**
* The missing topic notification filter expression or `undefined` if one
* has not been specified.
*/
readonly missingTopicNotificationFilter?: string;
}
/**
* A remote server builder.
*
* A builder of this type may be created using {@link
* diffusion.newRemoteServerBuilder newRemoteServerBuilder} and used to create
* instances of {@link RemoteServer} that can be supplied to {@link
* RemoteServers.createRemoteServer(RemoteServer)
* createRemoteServer(RemoteServer)}.
*
* @since 6.7
*/
export interface RemoteServerBuilder {
/**
* Specifies the name of a principal used by the remote server to
* connect to the primary server.
*
* The default, if not specified, is the anonymous principal.
*
* @param principal principal name or a zero length string to
* indicate an anonymous connection
*
* @return this builder
*/
principal(principal: string): RemoteServerBuilder;
/**
* Specifies the credentials to use when connecting to the primary
* server.
*
* The default, if not specified, is `undefined`.
*
* @param credentials the credentials to use
*
* @return this builder
*/
credentials(credentials: Credentials): RemoteServerBuilder;
/**
* Specifies a map of {@link ConnectionOption} settings.
*
* This will replace any options currently set for the builder.
*
* Any options not supplied will take their default values.
*
* If no connection options are specified, either using this method
* or {@link #connectionOption} then all options will take their
* default value.
*
* @param connectionOptions map of options
*
* @return this builder
*/
connectionOptions(connectionOptions: Partial): RemoteServerBuilder;
/**
* Specifies a single connection option.
*
* This will add to the options currently specified to the builder,
* or replace a value if it has already been specified.
*
* @param connectionOption the connection option
*
* @param value the connection option value. If argument is omitted or `null`
* the option is removed
*
* @return this builder
*/
connectionOption(connectionOption: ConnectionOption, value?: string | null): RemoteServerBuilder;
/**
* Specifies a topic selector expression which will filter missing
* topic notifications propagated from secondary to primary server.
*
* {@link MissingTopicNotification}s are notified when a client
* subscribes using a topic selector that matches no existing
* topics. By specifying a missing topic notification filter all
* notifications that match the filter on the secondary server will
* be propagated to the primary server.
*
* A match occurs if the path prefix of the subscription selector
* matches the path prefix of the specified selector. If the
* selector is a {@link TopicSelector#SELECTOR_SET_PREFIX selector
* set} then the notification will be propagated if it matches any
* selector in the set.
*
* If no filter is specified then no missing topic notifications
* will be propagated.
*
* The special selector expression "*.*" may be used to indicate
* that all missing topic notifications should be propagated.
*
* Only the path prefix of the specified selector(s) is considered
* when matching therefore any use of regular expressions would be
* ignored.
*
* @param filter a topic selector expression specifying the filter
* to apply or null to remove any existing filter
*
* @return this builder
*/
missingTopicNotificationFilter(filter: string | null): RemoteServerBuilder;
/**
* Reset the builder.
*
* @return this Builder
*/
reset(): RemoteServerBuilder;
/**
* Creates a remote server object using the current values known to
* this builder.
*
* @param name the name of the remote server
*
* @param url the URL to use to connect to the primary server
*
* @return a new remote server instance
*/
create(name: string, url: string): RemoteServerDefinition;
}
/**
* Result returned from a {@link RemoteServers.checkRemoteServer} invocation.
*/
export interface RemoteServerStatus {
/**
* The connection state of the remote server.
*/
readonly connectionState: ConnectionState;
/**
* The failure message, if there is one, otherwise an empty string
*/
readonly failureMessage: string;
}
/**
* This feature allows a client session to manage remote servers.
*
* A remote server provides the configuration to connect to a Diffusion server belonging to a different cluster.
* Each server in the local cluster will establish a session with each remote server.
*
* Higher level components, such as remote topic views, can specify the use of such remote servers by name.
* The connecting and disconnecting is handled automatically by the server (or servers in the same cluster) where
* the remote servers are defined.
*
* A component can specify a remote server by name even if it does not exist (has not yet been created) and when
* the remote server is created the connection will take place automatically.
*
* If a remote server is removed and there are components that depend upon it, those components will be disabled.
*
* An example of the use of remote servers is within remote topic views (those that indicate that their source
* topics are to be taken from a different server) where the name of such a server can be specified.
*
*
Remote Server persistence and replication
*
* Remote server configurations created through this feature are replicated across a cluster and persisted to disk.
*
* Access control
*
* The following access control restrictions are applied:
*
*
* - To {@link createRemoteServer create}, {@link removeRemoteServer remove}
* or {@link checkRemoteServer check} a remote server, a session needs the
* {@link GlobalPermission.CONTROL_SERVER CONTROL_SERVER} global permission.
*
- To {@link listRemoteServers list} remote servers, a session needs the
* {@link GlobalPermission.VIEW_SERVER VIEW_SERVER} global permission.
*
*
* Accessing the feature
*
* This feature may be obtained from a {@link Session session} as follows:
*
*
* const remoteServers = session.remoteServers;
*
*
* @since 6.5
*/
export interface RemoteServers {
/**
* Create a new remote server instance at the server.
*
* If a remote server with the same name already exists an error will be
* returned.
*
* @param remoteServer a remote server definition created using a
* {@link RemoteServerBuilder remote server builder}.
*
* @return a Result that completes when a response is received from the
* server, returning the definition of the remote server created by
* the operation.
*
* If the task fails, the Result will resolve with an error. Common
* reasons for failure include:
*
* - a remote server with the given name already exists;
*
- one or more connection options are invalid;
*
- the operation failed due to a transient cluster error;
*
- the calling session does not have CONTROL_SERVER permission;
*
- the session is closed;
*
- the feature is not licensed.
*
*
* @since 6.7
*/
createRemoteServer(remoteServer: RemoteServerDefinition): Promise;
/**
* Create a new remote server instance with default connection options.
*
* If a remote server with the same name already exists an error will be returned.
*
* @param name the name of the remote server
* @param url the URL to use to connect to the primary server
* @param principal the name of a principal used by the remote server to connect
* to the primary server. A zero length string may be supplied to indicate an anonymous
* connection
* @param credentials to use for connecting to the primary server
* @param connectionOptions (optional) a map of connection option settings. Any options not supplied will take
* their default values
* @return a Result that completes when a response is received from the
* server, returning the definition of the remote server created by
* the operation.
*
* If the task fails, the Result will resolve with an error. Common
* reasons for failure include:
*
* - a remote server with the given name already exists;
*
- one or more connection options are invalid;
*
- the operation failed due to a transient cluster error;
*
- the calling session does not have CONTROL_SERVER permission;
*
- the session is closed.
*
*
* @deprecated since 6.7
*
* Use {@link RemoteServers.createRemoteServer(RemoteServer)} in
* preference. This method will be removed in a future release.
*/
createRemoteServer(name: string, url: string, principal: string, credentials: Credentials, connectionOptions?: Partial): Result;
/**
* Check the current state of a named remote server.
*
* This will report back the current state of the remote server, but also can be used to forcibly retry a failed
* remote server connection.
*
* @param name the name of the remote server
*
* @return a Result that completes when a response is received from the server, returning details of the remote
* server state.
*
* If the task fails, the Result will resolve with an error. Common reasons for failure include:
*
* - the calling session does not have CONTROL_SERVER permission;
*
- the session is closed.
*
*/
checkRemoteServer(name: string): Result;
/**
* List all the remote servers that have been created.
*
* @return a Result that resolves when a response is received from the
* server, returning a list of remote servers.
*
* If the task fails, the Result will resolve with an Error. Common
* reasons for failure include:
*
* - the calling session does not have CONTROL_SERVER permission;
*
- the session is closed.
*
*/
listRemoteServers(): Result;
/**
* Remove a named remote server if it exists.
*
* When a named remote server is removed, any components that specify it
* would be disabled.
*
* If the named remote server does not exist the completable future will
* complete successfully.
*
*
* @param name the name of the remote server
* @return a 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 CONTROL_SERVER permission;
*
- the session is closed.
*
*/
removeRemoteServer(name: string): Result;
}
/**
* @module Session.security
*
* Access to the [[Security]] feature
* @preferred
*/
///
/**
* Permissions that are applied globally
*/
export declare enum GlobalPermission {
/**
* Add an authentication handler
*/
AUTHENTICATE = "AUTHENTICATE",
/**
* List or listen to client sessions
*/
VIEW_SESSION = "VIEW_SESSION",
/**
* Alter a client session
*/
MODIFY_SESSION = "MODIFY_SESSION",
/**
* Required to register any server-side handler
*/
REGISTER_HANDLER = "REGISTER_HANDLER",
/**
* View the server's runtime state
*/
VIEW_SERVER = "VIEW_SERVER",
/**
* Change the server's runtime state
*/
CONTROL_SERVER = "CONTROL_SERVER",
/**
* Read the security configuration
*/
VIEW_SECURITY = "VIEW_SECURITY",
/**
* Change the security configuration
*/
MODIFY_SECURITY = "MODIFY_SECURITY",
/**
* A permission that is unsupported by the session
*/
UNKNOWN_GLOBAL_PERMISSION = "UNKNOWN_GLOBAL_PERMISSION",
/**
* List topic views
*/
READ_TOPIC_VIEWS = "READ_TOPIC_VIEWS",
/**
* Modify topic views
*/
MODIFY_TOPIC_VIEWS = "MODIFY_TOPIC_VIEWS"
}
/**
* Permissions that are applied on a path
*/
export declare enum PathPermission {
/**
* Required to receive information from a topic.
*
* If a session does not have read_path permission for a topic, the topic
* will be excluded from the results of subscription or fetch operations for
* the session, and the topic's details cannot be retrieved by the session.
*/
READ_TOPIC = "READ_TOPIC",
/**
* Update topics
*/
UPDATE_TOPIC = "UPDATE_TOPIC",
/**
* Add or remove topics
*/
MODIFY_TOPIC = "MODIFY_TOPIC",
/**
* Send a message to a handler registered with the server
*/
SEND_TO_MESSAGE_HANDLER = "SEND_TO_MESSAGE_HANDLER",
/**
* Send a message another session
*/
SEND_TO_SESSION = "SEND_TO_SESSION",
/**
* Use a topic selector that selects 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.
*
* A session granted `SELECT_TOPIC` for a particular path effectively
* has the permission for all descendant paths. From a security perspective,
* if a role grants `SELECT_TOPIC` at branch `X` it is
* ineffectual for it also to deny `SELECT_TOPIC` at a child branch
* `X/Y` because a a topic selector with a path prefix of `X`
* can still select paths below `X/Y`.
*/
SELECT_TOPIC = "SELECT_TOPIC",
/**
* Evaluate queries that return a non-current view of a time series topic.
*
*
* The `READ_TOPIC` permission is required to evaluate any type of
* `Query` for a time series topic. This permission is additionally
* required for queries that potentially return a non-current view of all or
* part of a time series. Such queries include value range queries that
* specify an edit range, and all types of edit range query.
*/
QUERY_OBSOLETE_TIME_SERIES_EVENTS = "QUERY_OBSOLETE_TIME_SERIES_EVENTS",
EDIT_TIME_SERIES_EVENTS = "EDIT_TIME_SERIES_EVENTS",
/**
* Submit edits to time series topic events which have an author which is
* the same as the principal of the calling session.
*
*
This permission is a more restrictive alternative to
* `EDIT_TIME_SERIES_EVENTS`.
*
*
* The `UPDATE_TOPIC` permission is required to update a time series
* topic. This permission is additionally required to submit
* edits to a time series topic where the event
* author is the same as the principal of the calling session.
*/
EDIT_OWN_TIME_SERIES_EVENTS = "EDIT_OWN_TIME_SERIES_EVENTS",
/**
* Acquire a session lock.
*/
ACQUIRE_LOCK = "ACQUIRE_LOCK",
/**
* Expose a branch of the topic tree as a virtual session tree.
*
* The `EXPOSE_BRANCH` path permission is powerful since it allows a
* session to expose a whole branch of the topic tree under a different set
* of path permissions.
*
* A session granted `EXPOSE_BRANCH` for a particular path effectively
* has the permission for all descendant paths. From a security perspective,
* if a role grants `EXPOSE_BRANCH` at branch `X` it is
* ineffectual for it also to deny `EXPOSE_BRANCH` at a child branch
* `X/Y` because a branch mapping to `X` can still expose paths
* below `X/Y`.
*/
EXPOSE_BRANCH = "EXPOSE_BRANCH",
/**
* A permission that is unsupported by the session
*/
UNKNOWN_PATH_PERMISSION = "UNKNOWN_PATH_PERMISSION",
/**
* A permission that is unsupported by the session
* @deprecated since 6.5
*/
UNKNOWN_TOPIC_PERMISSION = "UNKNOWN_TOPIC_PERMISSION"
}
/**
* Permissions that are applied on a path
* @deprecated since 6.5
* Replaced by {@link PathPermission}
*/
export declare type TopicPermission = PathPermission;
/**
* The credentials that a session uses to authenticate itself.
*
* When running the Diffusion Client in a browser context, access to the
* `Buffer` api is made available through {@link diffusion.buffer}.
*
*/
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 path permissions
*/
readonly default: PathPermission[];
/**
* The map of paths to sets of Path
* permissions
*/
readonly topic: {
[key: string]: PathPermission[];
};
/**
* Additional roles
*/
readonly roles: string[];
/**
* If the role is locked this will contain the name of the principal that
* can update the role.
*
* @since 6.4
*/
readonly lockingPrincipal?: string;
}
/**
* A snapshot of information from the security store
*/
export interface SecurityConfiguration {
/**
* The list of default roles for named sessions
*/
readonly named: string[];
/**
* The list of default roles for anonymous sessions
*/
readonly anonymous: string[];
/**
* The list of all defined roles
*/
readonly roles: Role[];
/**
* The list of isolated paths
*/
readonly isolatedPaths: string[];
}
/**
* A principal in the system authentication store.
*/
export interface SystemPrincipal {
/**
* The principal name
*/
readonly name: string;
/**
* The principal's assigned roles
*/
readonly roles: string[];
/**
* If the principal is locked this will contain the name of the principal that
* can update the role.
*
* @since 6.4
*/
readonly lockingPrincipal?: string;
}
/**
* Type of a SessionPropertyValidation for a correspondent client proposed property.
*/
export declare enum ValidationType {
REGEX = 0,
VALUES = 1
}
/**
* Defines the validation for a trusted client proposed session property.
* The subtypes define specific types of validation.
*
* @since 6.5
*/
export interface SessionPropertyValidation {
/**
* Subtype of property validation
*/
readonly type: ValidationType;
}
/**
* Defines regular expression based validation for a trusted client proposed session property.
* Such validation defines a
* regular expression which supplied values must match against.
*
* @since 6.5
*/
export interface MatchesSessionPropertyValidation {
/**
* The regular expression
*/
readonly regex: string;
}
/**
* Defines values based validation for a trusted client proposed session property.
* Such validation defines a set of values to which the supplied session property value must belong.
*
* @since 6.5
*/
export interface ValuesSessionPropertyValidation {
/**
* The sef of permitted values
*/
readonly values: string[];
}
/**
* Action to be taken by the system authentication handler for connection
* attempts that do not provide a principal name and credentials.
*/
export declare type AnonymousConnectionAction = 'deny' | 'allow' | 'abstain';
/**
* Configuration for anonymous connections
*/
export interface SystemAuthenticationAnonymousConfiguration {
/**
* The action to take for anonymous connection attempts.
*
* May be one of:
*
* * `deny` - Deny anonymous connection attempts.
* * `allow` - Accept anonymous connection attempts.
* * `abstain` - Defer authentication for anonymous connection
* attempts to subsequent authentication handlers
*
*/
readonly action: AnonymousConnectionAction;
/**
* The roles the system authentication handler will assign to
* anonymous sessions. Applicable only if anonymous connections are
* {@link AnonymousConnectionAction allowed}.
*/
readonly roles: string[];
}
/**
* A snapshot of information from the system authentication store.
*/
export interface SystemAuthenticationConfiguration {
/**
* The system principals stored on the server.
*/
readonly principals: SystemPrincipal[];
/**
* The configuration that is applied for anonymous connections
*/
readonly anonymous: SystemAuthenticationAnonymousConfiguration;
/**
* The map of trusted client proposed properties,
* where the key is the permitted property name and the value
* defines the validation applied to the property.
*/
readonly trustedClientProposedProperties: {
[key: string]: SessionPropertyValidation;
};
}
/**
* A builder that can be used to create scripts for use with
* {@link Security.updateSecurityStore updateSecurityStore}.
*
* Facilitates producing scripts that control the assignment of permissions to
* roles.
* From Diffusion 6.5, script builders are no longer immutable. Each builder
* operation mutates this script builder and returns it.
*/
export interface SecurityScriptBuilder {
/**
* Create the script string.
*
* @return the script
*/
build(): string;
/**
* Sets the roles to be assigned by default to all anonymous sessions.
*
* @param (roles?: string[]): SecurityScriptBuilder;the roles to be
* assigned. An empty array (the default), or no argument,
* will result in anonymous sessions being assigned no roles
* by default.
* @return the builder to allow chaining
*/
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.
*
* @param role the role to set path permissions for.
* @param permissions the path permissions to assign for the role,
* default `= []`.
*
* @return the builder to allow chaining
*
* @deprecated since 6.5
* Replaced with setDefaultPathPermissions
*/
setDefaultTopicPermissions(role: string, permissions?: string[]): SecurityScriptBuilder;
/**
* Remove any previously assigned permissions from a particular path for a
* given role.
*
* This is different from setting no permissions to a path. By removing
* permissions set for a path, permissions will be inherited from the
* nearest set of permissions that have been assigned higher in the
* path hierarchy or from the default path permissions if no more specific
* permissions are found.
*
* @param role the role to remove path permissions from.
* @param path the path path to remove permissions from.
*
* @return the builder to allow chaining
*
* @deprecated since 6.5
* Replaced with removePathPermissions
*
*/
removeTopicPermissions(role: string, path: string): SecurityScriptBuilder;
/**
* Set the default permissions that a particular role will have for paths.
*
* @param role the role to set path permissions for.
* @param permissions the path permissions to assign for the role,
* default `= []`.
*
* @return the builder to allow chaining
*/
setDefaultPathPermissions(role: string, permissions?: string[]): SecurityScriptBuilder;
/**
* Remove any previously assigned permissions from a particular path for a
* given role.
*
* This is different from setting no permissions to a path. By removing
* permissions set for a path, permissions will be inherited from the
* nearest set of permissions that have been assigned higher in the
* path hierarchy or from the default path permissions if no more specific
* permissions are found.
*
* @param role the role to remove path permissions from.
* @param path the path path to remove permissions from.
*
* @return the builder to allow chaining
*/
removePathPermissions(role: string, path: string): SecurityScriptBuilder;
/**
* Sets specific path permissions for a named role.
*
* When permissions are assigned to a role for a path they will apply
* to the path and any paths below the specified path. Path-scoped
* permissions are assigned to roles for specific paths. The
* permission assignment applies to all descendant paths, unless there is a
* more specific assignment.
*
* To evaluate whether a session has permission for a path, the server
* starts at that path and searches up the tree to find the nearest
* permissions assignment. The first assignment is the only one considered,
* even if the session has roles involved in assignments further up the
* hierarchy.
*
* @param role the role to assign permissions for.
* @param path the path to assign permissions.
* @param permissions the permissions to assign to the role for the
* specified path. Any empty array (the default) or no
* argument would specify that the role has no
* permissions at this path, which differs from there
* being no permissions assigned for that path (see
* {@link
* SecurityScriptBuilder.removeTopicPermissions}).
*
* @return the builder to allow chaining
*
* @deprecated since 6.5
* Replaced with setPathPermissions
*
*/
setTopicPermissions(role: string, path: string, permissions?: string[]): SecurityScriptBuilder;
/**
* Sets specific path permissions for a named role.
*
* When permissions are assigned to a role for a path they will apply
* to the path and any paths below the specified path. Path-scoped
* permissions are assigned to roles for specific paths. The
* permission assignment applies to all descendant paths, unless there is a
* more specific assignment.
*
* To evaluate whether a session has permission for a path, the server
* starts at that path and searches up the tree to find the nearest
* permissions assignment. The first assignment is the only one considered,
* even if the session has roles involved in assignments further up the
* hierarchy.
*
* @param role the role to assign permissions for.
* @param path the path to assign permissions.
* @param permissions the permissions to assign to the role for the
* specified path. Any empty array (the default) or no
* argument would specify that the role has no
* permissions at this path, which differs from there
* being no permissions assigned for that path (see
* {@link
* SecurityScriptBuilder.removePathPermissions}).
*
* @return the builder to allow chaining
*/
setPathPermissions(role: string, path: string, permissions?: string[]): SecurityScriptBuilder;
/**
* Set a path not to inherit path permissions from its parent paths or
* the default path permissions.
*
*
* By default, a path without specific
* {@link SecurityScriptBuilder.setPathPermissions} path permission
* assignments inherits the permission assignments from the first
* parent path that has them. If neither the path nor any of its parent
* paths have permission assignments, the
* {@link SecurityScriptBuilder.setDefaultPathPermissions default path permissions}
* are used.
*
* @param path the path
*
* @return this builder, modified to isolate the given path
* in the path hierarchy
* @since 6.5
*/
isolatePath(path: string): SecurityScriptBuilder;
/**
* Re-instate inheritance of path permission assignments from parents of
* the given path.
*
* @param path the path
*
* @return this builder, modified to re-instate the
* inheritance of path permission assignments from parents of
* the given path
* @see {@link SecurityScriptBuilder.isolatePath}
* @since 6.5
*/
deisolatePath(path: string): SecurityScriptBuilder;
/**
* Specify a set of a roles that another role should inherit permissions from.
*
* @param role the role
* @param roles the set of roles to inherit from.
*
* @return the builder to allow chaining
*/
setRoleIncludes(role: string, roles: string[]): SecurityScriptBuilder;
/**
* Restrict a role so it can only be edited by a specific principal.
*
* @param role the role
* @param lockingPrincipal the locking principal
*
* @return this builder, modified to lock a role to a single
* principal that can edit it
*
* @since 6.4
*/
setRoleLockedByPrincipal(role: string, lockingPrincipal: string): SecurityScriptBuilder;
}
/**
* A builder that can be used to create scripts for use with {@link
* Security.updateAuthenticationStore updateAuthenticationStore}.
*
* Facilitates producing scripts that contain the mapping of roles to specific
* principals/passwords.
* From Diffusion 6.5, script builders are no longer immutable. Each builder
* operation mutates this script builder and returns it.
*/
export interface SystemAuthenticationScriptBuilder {
/**
* Create the script string.
*
* @return the script
*/
build(): string;
/**
* Change a principal's assigned roles.
*
* @param principal the principal name.
* @param roles an array of roles
* @return this builder, modified to contain the changed roles
*/
assignRoles(principal: string, roles: string[]): SystemAuthenticationScriptBuilder;
/**
* Add a principal.
*
* If `lockingPrincipal` is defined, the new principal can only be edited
* by the principal defined in the lock.
*
* The script will fail if the principal is already defined at the server.
*
* @param principal the principal name
* @param password the principal's password
* @param roles the assigned roles for the principal, default `= []`
* @param lockingPrincipal the name of the principal that can edit this
* principal
* @return this builder, modified to contain the new principal
*/
addPrincipal(principal: string, password: string, roles?: string[], lockingPrincipal?: string): SystemAuthenticationScriptBuilder;
/**
* Set a principal's password.
*
* @param principal the principal name
* @param password the principal's password
* @return this builder, modified to contain the changed password
*/
setPassword(principal: string, password: string): SystemAuthenticationScriptBuilder;
/**
* Assert that a principal's password is `password`.
*
* This command doesn't update the store. It can be used in conjunction with
* {@link SystemAuthenticationScriptBuilder.setPassword setPassword} to
* create a script that updates a password only if the previous password is
* supplied.
*
* @param principal the principal name
* @param password the principal's password
* @return this builder, modified to verify the password
*/
verifyPassword(principal: string, password: string): SystemAuthenticationScriptBuilder;
/**
* Remove a principal.
*
* @param principal the principal name
* @return this builder, modified to remove the principal
*/
removePrincipal(principal: string): SystemAuthenticationScriptBuilder;
/**
* Instruct the system authentication to allow anonymous connections.
*
* @param roles the roles to assign to anonymous sessions, default `= []`
* @return this builder, modified to contain the allow anonymous connections
* command.
*/
allowAnonymousConnections(roles?: string[]): SystemAuthenticationScriptBuilder;
/**
* Instruct the system authentication to deny anonymous connections.
*
* @return this builder, modified to contain the deny anonymous connections command.
*/
denyAnonymousConnections(): SystemAuthenticationScriptBuilder;
/**
* Instruct the system authentication handler to defer authentication
* decisions for anonymous connections to subsequent handlers.
*
* @return this builder, modified to contain the abstain anonymous connections
* command.
*/
abstainAnonymousConnections(): SystemAuthenticationScriptBuilder;
/**
* Specifies the name of a client proposed session property that should be
* allowed by the system authenticator along with a set of permissible values.
* The property will only be allowed if the supplied value matches one of those
* in the set of values specified.
*
* @param propertyName specifies the name of the client proposed property to be allowed
* @param allowedValues specifies a set of allowed values for the client proposed property
*
* @return this builder, modified to allow the specified client
* proposed property if its value matches one of those supplied
*
* @since 6.5
*/
trustClientProposedPropertyIn(propertyName: string, allowedValues: string[]): SystemAuthenticationScriptBuilder;
/**
* Specifies the name of a client proposed session property that should be
* allowed by the system authenticator along with a regular expression to
* validate the property value.
* The property will only be allowed if the supplied value matches with the regular expression.
*
* @param propertyName specifies the name of the client proposed property to be allowed
* @param regex
* regular expression which will be matched against
* supplied values to determine whether they are valid
*
* @return this builder, modified to allow the specified client
* proposed property if its value matches the given regular expression
*
* @since 6.5
*/
trustClientProposedPropertyMatches(propertyName: string, regex: string): SystemAuthenticationScriptBuilder;
/**
* Specifies the name of a client proposed session property that should
* now be ignored by the system authenticator.
*
* This removes the effect of a previous request to trust the named property.
*
* @param propertyName specifies the name of the client proposed property to be ignored
*
* @return this builder, modified to ignore the specified client proposed property
*
* @since 6.5
*/
ignoreClientProposedProperty(propertyName: string): SystemAuthenticationScriptBuilder;
}
/**
* Single-use callback provided to the {@link Authenticator.authenticate
* authenticate} call.
*/
export interface AuthenticatorCallback {
/**
* Authentication passed - allow the authentication request with
* modifications to the session properties.
*
* @param properties this can include all allowed user-defined session
* properties, as well as a subset of fixed session
* properties see {@link Authenticator.authenticate
* authenticate}.
* @throws an error if another method has already been
* invoked on this callback
*/
allow(properties: SessionProperties): void;
/**
* Authentication passed - allow the authentication request with fixed
* properties as supplied but no user-defined properties.
*
* @throws an error if another method has already been
* invoked on this callback
*/
allow(): void;
/**
* The authentication has neither passed nor failed.
*
* @throws an error if another method has already been
* invoked on this callback
*/
abstain(): void;
/**
* Authentication failed - deny the authentication request.
*
* @throws an error if another method has already been
* invoked on this callback
*/
deny(): void;
}
/**
* An authentication handler that processes authentication requests from the
* server.
*
* Instances can be registered with the server using the
* {@link Security.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 Authentication |
* changePrincipal |
*
*
* 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 Properties |
* None |
* Existing 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 Authentication |
* changePrincipal |
*
*
* Fixed Properties |
* As supplied plus those assigned by the server on connection. |
* As supplied but with $Principal replaced by the supplied
* principal . |
*
*
* User-defined Properties |
* None |
* None |
*
*
*
* 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
* @deprecated since 6.5
* Replaced with PathPermission
*/ readonly TopicPermission: typeof PathPermission;
/**
* The path permission enum
*/ readonly PathPermission: typeof PathPermission;
/**
* Get the principal that the session is currently authenticated as.
*
* @returns the session's principal
*/
getPrincipal(): string;
/**
* 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 path replication then the changes will
* be replicated to all members of the cluster.
*
* **Example:**
* ```
* session.security.updateSecurityStore(script).then(function() {
* console.log('Security configuration updated');
* }, function(err) {
* console.log('Failed to update security configuration', err);
* });
* ```
*
* @param script the command script
* @returns a {@link 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 path replication then the changes will
* be replicated to all members of the cluster.
*
* **Example:**
* ```
* session.security.updateAuthenticationStore(script).then(function() {
* console.log('Authentication configuration updated');
* }, function(err) {
* console.log('Failed to update security configuration', err);
* });
* ```
*
* @param script the command script
* @returns a {@link 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 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;
/**
* Returns the set of global permissions assigned to the role.
*
* @return the set of global permissions. This may be empty indicating
* that the role has no global permissions assigned.
*
* @since 6.3
*/
getGlobalPermissions(): Result;
/**
* Returns a list of path permissions assigned to the calling session on a given
* path.
*
* @param path the path to query for permissions
* @return a {@link 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 PathPermission}.
*
* @since 6.5
*/
getPathPermissions(path: string): Result;
/**
* Returns a list of topic permissions assigned to the calling session on a given
* path.
*
* @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}.
*
* @deprecated since 6.5. Use {@link #getPathPermissions()} instead.
*/
getTopicPermissions(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 Session.topicViews
*/
/**
* A session tree branch mapping.
*
* Branch mappings belong to {@link BranchMappingTable branch mapping tables}.
* Each branch mapping is a pair of a {@link Session session filter} and the
* topic tree branch that applies to sessions matching the filter.
*
* @author Push Technology Limited
* @since 6.7
* @see SessionTrees
*/
export interface BranchMapping {
/**
* the session filter
*/
readonly sessionFilter: string;
/**
* the topic tree branch in the topic tree for sessions matching the session
* filter
*/
readonly topicTreeBranch: string;
}
/**
* A session tree branch mapping table.
*
* A branch mapping table is a list of {@link BranchMapping branch mappings}
* assigned to a session tree branch.
*
* To create a branch mapping table, obtain a new builder instance using
* {@link Diffusion.newBranchMappingTableBuilder}, call
* {@link Builder.addBranchMapping} for each branch mapping,
* then {@link Builder.create}. The result can then be sent to the
* server using {@link SessionTrees.putBranchMappingTable}.
*
* @author Push Technology Limited
* @since 6.7
* @see SessionTrees
*/
export interface BranchMappingTable {
/**
* @return the branch of the session tree to which this table is bound
*/
getSessionTreeBranch(): string;
/**
* @return the branch mappings
*/
getBranchMappings(): BranchMapping[];
}
/**
* Builder for {@link BranchMappingTable} instances.
*
* @author Push Technology Limited
* @since 6.7
* @see SessionTrees
* @see Diffusion.newBranchMappingTableBuilder()
*/
export interface BranchMappingTableBuilder {
/**
* Reset the builder.
*
* @return this Builder
*/
reset(): BranchMappingTableBuilder;
/**
* Add a new branch mapping.
*
* @return this Builder
*/
addBranchMapping(sessionFilter: string, topicTreeBranch: string): BranchMappingTableBuilder;
/**
* Create a new BranchMappingTable.
*
* @param sessionTreeBranch the session tree branch
*/
create(sessionTreeBranch: string): BranchMappingTable;
}
/**
* This feature allows a client session to configure session trees.
*
* A session tree is a virtual view of the topic tree presented to a session by
* fetch and subscription operations. Custom session trees for different
* sessions can be configured using declarative rules maintained by the server
* to meet data security, data optimisation, or personalisation and localisation
* requirements. Each session can be presented with a unique session tree based
* on its session properties.
*
* A session tree is produced by applying branch mappings to the topic
* tree. Branch mappings are organised into branch mapping tables. Each
* branch mapping table is assigned to a unique path – the session tree
* branch.
*
* A session tree is composed of session paths. Each session path is
* mapped via the branch mapping tables to a unique topic path.
*
* A branch mapping table is an ordered list of (session filter, topic tree
* branch) pairs. For example, the branch mapping table for the session tree
* branch `market/prices` might be:
*
*
* Session filter Topic tree branch
* ========= =============
* USER_TIER is '1' or $Country is 'DE' backend/discounted_prices
* USER_TIER is '2' backend/standard_prices
* $Principal is '' backend/delayed_prices
*
*
* With this configuration, if an unauthenticated session (one that matches the
* `$Principal is ''` session filter) subscribes to the session path
* `market/prices/X`, and there is a topic bound to the topic path
* `backend/delayed_prices/X`, the subscription will complete. The session
* will receive a subscription notification under the session path
* `market/prices/X`, together with the topic properties and the value of
* the topic. The session is unaware that the data originates from a topic bound
* to a different topic path. If no topic is bound to
* `backend/delayed_prices/X`, the subscription will not resolve and the
* session will receive no data, even if there is a topic bound to
* `market/prices/X`.
*
* Session trees complement the data transformation capabilities of
* {@link TopicViews topic views}. In our example, the time delayed time feed at
* `backend/delayed_prices` could be maintained by a topic view using the
* delay by clause.
*
* Branch mappings are persisted by the server and shared across a cluster, in a
* similar manner to topic views, security stores, and metric collectors. Branch
* mappings are editable using this feature, and via the management console.
*
* For a given session and session path, at most one branch mapping applies. The
* applicable branch mapping is chosen as follows:
*
* - Each branch mapping table with session tree branch that is a prefix of the
* session path is considered. For a given table, the first branch mapping with
* a condition that matches the session's properties is the one that applies. A
* branch mapping table may have no applicable branch mappings for a session.
*
- If there are several such branch mapping tables with a branch mapping
* that for the session, the one with the longest prefix of the session path
* applies.
*
- If no branch mapping table has a branch mapping for the session, the
* session path is translated to the identical topic path.
*
*
* Access control
*
* To subscribe to or fetch from a session path, a session must be granted the
* appropriate path permission to the session path for the operation
* ({@link PathPermission.SELECT_TOPIC SELECT_TOPIC}, or
* {@link PathPermission.READ_TOPIC READ_TOPIC}). The session doesn't require
* any permissions to the topic path of the topic providing the data.
*
* To create or replace branch mappings, a session needs the
* {@link PathPermission.MODIFY_TOPIC MODIFY_TOPIC} path permission for the
* session tree branch of the branch mapping table,
* {@link PathPermission.EXPOSE_BRANCH EXPOSE_BRANCH} path permission for the
* topic tree branch of each branch mapping, and (if an existing table with the same
* session tree branch is being replaced) {@link PathPermission.EXPOSE_BRANCH
* EXPOSE_BRANCH} permission for each branch mapping of existing table.
*
* To retrieve a branch mapping table, a session needs the
* {@link PathPermission.READ_TOPIC READ_TOPIC} path permission for its session tree
* branch.
*
* Accessing the feature
*
* This feature may be obtained from a {@link Session session} as follows:
*
*
* const sessionTrees = session.sessionTrees;
*
*
* @author Push Technology Limited
*
* @since 6.7
*/
export interface SessionTrees {
/**
* Create or replace a branch mapping table.
*
* The server ensures that a session tree branch has at most one branch mapping
* table. Putting a new branch mapping table will replace any previous
* branch mapping table with the same session tree branch. To remove all branch
* mappings for a session tree branch, put an empty branch mapping table.
*
* @param branchMappingTable the new table
*
* @return a Result that resolves when a response is received
* from the server.
*
* If the task completes successfully, the CompletableFuture result
* will be null. The result type is `any` rather than `void` to provide
* forward compatibility with future iterations of this API that may
* provide a non-null result with a more specific result type.
*
* Otherwise, the Result will be rejected with an error. Common
* reasons for failure include:
*
* - the branchMappingTable or one of its branch mappings is
* invalid;
*
- the calling session does not have the {@link
* PathPermission.MODIFY_TOPIC MODIFY_TOPIC} permission for the
* session tree branch of the branch mapping table, {@link
* PathPermission.EXPOSE_BRANCH EXPOSE_BRANCH} permission for each
* branch mapping of branchMappingTable, and (if there is an
* existing table for the session tree branch) {@link
* PathPermission.EXPOSE_BRANCH EXPOSE_BRANCH} permission for each
* branch mapping of existing table;
*
- the operation failed due to a transient cluster error;
*
- the session is closed.
*
*/
putBranchMappingTable(branchMappingTable: BranchMappingTable): Result;
/**
* Retrieve the session tree branches of the server's branch mapping tables. The
* results will only include the session tree branches of branch mapping tables
* that have at last one branch mapping and for which the calling session
* has {@link PathPermission.READ_TOPIC READ_TOPIC} path permission for
* the session tree branch.
*
* Individual branch mapping tables can be retrieved using
* {@link getBranchMappingTable}.
*
* @return a Result that resolves when a response is received
* from the server, returning a list of session tree branches in path
* order.
*
* If the task fails, the the Result will be rejected with an error.
* Common reasons for failure include:
*
* - the session is closed.
*
*/
getSessionTreeBranchesWithMappings(): Result;
/**
* Retrieve a branch mapping table from the server.
*
* If there is no branch mapping table at the given session tree branch, this
* method will return an empty branch mapping table.
*
* @param sessionTreeBranch the session tree branch that identifies the branch mapping
* table
*
* @return a Result that resolves when a response is received
* from the server, returning the branch mapping table for
* sessionTreeBranch.
*
* If the task fails, the Result will be rejected with an error. Common
* reasons for failure include:
*
* - the calling session does not have the {@link
* PathPermission.READ_TOPIC READ_TOPIC} permission for
* sessionTreeBranch;
*
- the session is closed.
*
*/
getBranchMappingTable(sessionTreeBranch: string): 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.
*
* Providing a number as fourth argument to {@link TimeSeries.append append}
* allows a session to submit a value and supplied time. This provides control
* over the timestamp of the event. The supplied instant must be synchronous to
* or more recent than the latest event stored by the time series topic. There
* are no other restrictions.
*
* A session can use {@link TimeSeries.edit edit} to submit an edit to
* an original time series event, identified by its sequence number. The server
* will add an edit event to the end of the time series based on the supplied
* value, with a new sequence number, timestamp, and the author set to the
* authenticated principal of the session.
*
* Time series topics can also be updated using the functionality provided by
* the {@link TopicUpdate} feature. This includes {@link TopicUpdate.set set}
* {@link UpdateStream}s. This usage performs an append operation with the added
* benefits of {@link UpdateConstraint}s, topic creation when updating (upsert),
* and delta streams. When using methods from {@link TopicUpdate} the sequence
* number, timestamp and author metadata will be generated using the same rules
* as {@link TimeSeries.append} but the associated {@link EventMetadata} will
* not be returned to the caller.
*
* Querying a time series topic
*
* A {@link RangeQuery} is a configured query that can be evaluated for a time
* series topic using {@link RangeQuery.selectFrom selectFrom(topicPath)}.
* Results are provided as streams of {@link Event Event} instances.
*
* {@link RangeQuery} is a builder for configuring a Query that selects a range
* of a time series. There are two types of range query that differ in how edits
* are processed – value range queries and edit range queries.
*
* Value range queries
*
* A value range query returns a merged view of part of a time series. This is
* the most common time series query and appropriate for most applications.
*
* The result of a value range query reflects the latest available edits and the
* {@link QueryResult query result} is ordered by the original event sequence
* number, presenting edit events instead of the original events they replace.
* Original events that have no edit events are included verbatim. Original
* events that have edit events are replaced by the latest edit event.
*
* A value range query of the example time series, with no range constraints so
* the entire time series is selected, returns two events:
*
* ```
* sequence=3, value=Y; original event sequence=0
* sequence=1, value=B
* ```
*
* The original value of the first event is not provided. It's apparent that the
* first event is an edit event because it provides the metadata of the original
* event it replaces.
*
* Edit range queries
*
* Applications with auditing and other administrative requirements can access
* original event values using an edit range query. An edit range query returns
* an unmerged view of a time series that can include both original events and
* the edit events that replace them. Edit range queries are rarely needed
* – value range queries satisfy most use cases.
*
* Edit range queries provide a detailed view of a time series. Because this is
* potentially sensitive information, an edit range query can only be performed
* by a session that has the `QUERY_OBSOLETE_TIME_SERIES_EVENTS`
* permission for the target topic.
*
* There are two sub-types of edit range query.
*
* A full audit trail of edit events can be obtained using an all edits
* edit range query. The result contains all original events selected by the
* query, together with all subsequent edit events that affect the original
* events. The query result stream provides events in time series order. An all
* edits query of the example time series, with no range constraints so the
* entire time series is selected, returns four events:
*
* ```
* sequence=0; value=A
* sequence=1; value=B
* sequence=2; value=X; original event sequence=0
* sequence=3; value=Y; original event sequence=0
* ```
*
* A latest edits edit range query returns a query result stream in
* time series order that contains all original events selected by the query,
* together with the latest edit events that affect the original events. A
* latest edits query of the example time series, with no range constraints so
* the entire time series is selected, returns three events:
*
* ```
* sequence=0; value=A
* sequence=1; value=B
* sequence=3; value=Y; original event sequence=0
* ```
*
* The initial range of events delivered for a subscription to a time series
* topic is derived from a latest edits edit range query. See
* Subscription Range.
*
* When evaluated for a time series that has no edit events, an edit range query
* will return the same results as a similarly configured value range query.
*
* Changes to a time series made outside the API
*
* The API presents a time series as an append-only data structure of immutable
* events that is only changed by adding new events. The API does not allow
* events to be deleted or edited.
*
* There are circumstances in which events can be removed from a time series by
* server operations outside the API. For example, a time series topic can be
* configured to discard or archive older events to save storage space; or the
* time series may be held in memory and lost if the server restarts. Subscribed
* sessions are not notified when events are removed in this way, but a session
* can infer the removal of events that are no longer included in query results.
* Similarly, an event's value can be changed on the server. For example, if an
* administrator changes its value to redact sensitive data. Again, subscribed
* sessions are not notified when events are modified, but a session can infer
* this has happened from query results.
*
* Whether such changes can happen for a particular time series topic depends on
* the topic specification, and the administrative actions that are allowed. To
* write a robust application, do not rely on two Event instances with the same
* sequence number but obtained though different API calls, being equal; nor
* that there are no sequence number gaps between events in query results.
*
* Access control
*
* The session must have the {@link PathPermission.READ_TOPIC READ_TOPIC} topic
* permission for a topic to query a time series topic. The
* {@link PathPermission.QUERY_OBSOLETE_TIME_SERIES_EVENTS
* QUERY_OBSOLETE_TIME_SERIES_EVENTS} path permission is additionally required
* to evaluate an {@link RangeQuery.forEdits edit range} query, or a
* {@link RangeQuery.forValues value range query} with an
* {@link RangeQuery.editRange edit range}.
*
* The session must have the {@link PathPermission.UPDATE_TOPIC UPDATE_TOPIC}
* path permission for a topic to {@link TimeSeries.append append} a new event
* to a time series topic. The {@link PathPermission.EDIT_TIME_SERIES_EVENTS
* EDIT_TIME_SERIES_EVENTS} path permission is additionally required to {@link
* TimeSeries.edit submit an edit} to any time series event. The more
* restrictive {@link PathPermission.EDIT_OWN_TIME_SERIES_EVENTS
* EDIT_OWN_TIME_SERIES_EVENTS} path permission allows a session to submit
* edits to time series topic events that are authored by the principal of the
* calling session.
*
* @since 6.0
*/
export interface TimeSeries {
/**
* Update a time series topic by appending a new value.
*
* The server will add an event to the end of the time series based on the
* supplied value, with a new sequence number, timestamp, and the author set
* to the authenticated principal of the session.
*
* @param topicPath the path of the time series topic to update
* @param value the event value
* @param valueType the type of the supplied value. This must match the value
* type of the {@link DataType} configured as the time
* series topic's {@link
* TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE event
* value type}. By default will be inferred from the
* provided value.
* @param timestamp an optional timestamp. The timestamp must be greater or
* equal to that of the most recent event appended to the
* topic
* @return a result that completes when a response is received from the
* server.
*/
append(topicPath: string, value: any, valueType?: DataType | (new (...args: any[]) => any), timestamp?: number | Long): 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.
*
*
*
* Query |
* Meaning |
*
*
* 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.
*
*
*
* Query |
* Meaning |
*
*
* 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.
*
*
*
* Anchor |
* Meaning |
*
*
* {@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.
*
*
*
* Span |
* Meaning |
*
*
* {@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 method |
* Operator type |
* Overridden configuration |
*
*
* forValues() |
* Value range |
* Overrides 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 range |
* Overrides 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 range |
* Overrides 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 range |
* Overrides 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() |
* Anchor |
* Overrides the anchor of the current range. |
*
*
* to()
* toStart()
* next()
* previous()
* untilLast() |
* Span |
* Overrides the span of the current range. |
*
*
* limit() |
* Limit |
* Overrides the limit. |
*
*
* as() |
* Query value type |
* Overrides 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` path permission for `topicPath`
* to evaluate a query. The `QUERY_OBSOLETE_TIME_SERIES_EVENTS` topic
* permission is also required if this is an {@link RangeQuery.forEdits edit
* range} query, or a {@link RangeQuery.forValues value range query} with an
* {@link RangeQuery.editRange edit range}.
*
* @param topicPath the path of the time series topic to query
*
* @return a result that completes when a response is
* received from the server.
*
* If the query returned results, the result will
* complete successfully and provide an {@link QueryResult}.
*
* Otherwise, the result will complete exceptionally
* with an {@link ErrorReason}.
*/
selectFrom(topicPath: string): Result;
}
/**
* Query result providing a {@link Stream} of events.
*/
export interface QueryResult {
/**
* The number of events selected by the query.
*
* This number may be greater than `events.length` due to a
* policy of the time series topic to limit the number of returned
* results, or the use of {@link RangeQuery.limit}.
*/
readonly selectedCount: number;
/**
* The timeseries events returned
*/
readonly events: Array>;
/**
* `true` if this result includes all events selected by the query.
*/
readonly isComplete: boolean;
/**
* A description of the structure of the result stream.
*/
readonly streamStructure: StreamStructure;
/**
* Merge this result with `other` , combining original events and
* edit events, to produce a new {@link QueryResult}.
*
* The following rules are applied to calculate the result:
*
* * If this result and `other` have an event with equal
* sequence numbers, the event from `other` is selected.
* * An edit event is selected in place of its original event.
* * If there are multiple edit events of an original edit, the one
* with the highest sequence is selected.
*
* The returned result implements {@link QueryResult.isComplete} to be true
* and {@link QueryResult.selectedCount} to contain the count of events in
* the `events` array, regardless of whether this result is complete.
*
* @param other the other query result to merge
* @return the merged result
*/
merge(other: QueryResult): QueryResult;
}
/**
* @module Session.topics
*/
/**
* 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} resolving to a {@link
* TopicRemovalResult}
*/
remove(selector: Array): Result;
remove(...selector: Array): Result;
/**
* Register a {@link MissingTopicHandler} to handle requests for a branch of
* the topic tree.
*
* The provided handler is called when a client subscribes using a topic
* selector that matches no existing topics. This allows a control client
* session to be notified when another session requests a topic that does
* not exist.
*
* A control client can register multiple handlers, but may only register a
* single handler for a given topic path. See {@link
* MissingTopicHandler.onRegister}. A handler will only be called for topic
* selectors with a {@link TopicSelector.prefix path prefix} that starts
* with or is equal to `topicPath` . If the path prefix matches multiple
* handlers, the one registered for the most specific (longest) topic path
* will be called.
*
* If the session is closed or the handler could not be registered, the
* returned {@link 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 using a topic
* selector that matches no topics. This interface must be implemented by the user.
*
* Handler instances can be registered using
* {@link TopicControl.addMissingTopicHandler addMissingTopicHandler}.
*
* @class MissingTopicHandler
*/
export interface MissingTopicHandler {
/**
* Called when a client session subscribes to a topic selector that selects
* no topics, and the topic path belongs to part of the topic tree for which
* this handler was registered.
*
* @param notification the missing topic notification
*/
onMissingTopic(notification: MissingTopicNotification): void;
/**
* Called when the handler has been successfully registered with the server.
*
* A session can register a single handler for a given branch of the topic
* tree. If there is already a handler registered for the topic path the
* operation will fail and {@link MissingTopicHandler.onClose onClose} will
* be called.
*
* To deregister the handler, call the `deregister` function
* supplied.
*
* @param path the registration path
* @param deregister a function that may be called to deregister this handler.
* The function will resolve when the handler has been
* deregistered.
*/
onRegister(path: string, deregister: () => Promise): void;
/**
* Called when the handler is closed. The handler will be closed if the
* session is closed, or if the handler is unregistered.
*
* Once closed, no further calls will be made for the handler.
*
* @param path the registration path
*/
onClose(path: string): void;
/**
* Notification of a contextual error related to this handler. This is
* analogous to an unchecked exception being raised. Situations in which
* `onError` is called include the session being closed before the
* handler is registered, a communication timeout, or a problem with the
* provided parameters. No further calls will be made to this handler.
*
* @param path the registration path
* @param error the error
*/
onError(path: string, error: any): void;
}
/**
* Notification that a session has made a request using a selector that does
* not match any topics.
*/
export interface MissingTopicNotification {
/**
* The common root topic path derived from the requested topic selector
*/
path: string;
/**
* The topic selector that triggered this notification
*/
selector: TopicSelector;
/**
* Session ID of the client session that triggered this notification
*/
sessionID: SessionId;
/**
* The session properties of the session that made the request
*
* @since 6.7
*/
sessionProperties: SessionProperties;
/**
* A list of the names of the servers through which the notification has
* been routed.
*
* The first name in the list will be the name of the server to which
* the originating session was connected. If the notification was routed
* through remote server connections before reaching the recipient then
* those servers will also be listed in the order that the notification
* passed through them.
*
* @since 6.7
*/
serverNames: string[];
/**
* This method has no effect.
*
* @deprecated since 6.6
*
* This method is a no-op. In previous releases this would
* cause the selector to be added to the session's
* selections and the selection to be re-evaluated. Since
* 6.6 the selector is always added to the session's
* selections before this notification is issued.
*/
proceed(): void;
/**
* This method has no effect.
*
* @deprecated since 6.4
*
* This method is a no-op. In previous releases this would
* prevent the selector from being added to the session's
* selections. Since 6.6 the selector is always added to the
* session's selections before this notification is issued
* regardless.
*/
cancel(): void;
}
/**
* A result returned when a request to add a topic completes
*/
export interface TopicAddResult {
/**
* Whether the Topic was added or not
*/
added: boolean;
/**
* The topic path that was used
*/
topic: string;
}
/**
* Reports the number of topics removed by a call to {@link TopicControl.remove}.
*
* @since 6.6
*/
export interface TopicRemovalResult {
/**
* The integer represents the number of topics removed by the
* operation. This does not include any derived topics created by a
* topic view which were removed as a side effect of this action.
*
* @return the count of topics removed
*/
removedCount: number;
}
/**
* @module Session.notifications
*/
/**
* The type of topic notification that has been received.
*/
export declare enum TopicNotificationType {
/**
* The topic was added.
*/
ADDED = 0,
/**
* The topic existed at the time of the selector registration.
*/
SELECTED = 1,
/**
* The topic was removed.
*/
REMOVED = 2,
/**
* The topic was deselected.
*/
DESELECTED = 3
}
/**
* 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 PathPermission.UPDATE_TOPIC
* update topic} permission covering the topic. To create any topic a session
* needs {@link PathPermission.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 PathPermission.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.
*
* **Example:**
* ```
* session.topicUpdate.set('my_topic', diffusion.datatypes.string(), 'hello');
* ```
*
* @param path the path of the topic
* @param dataType the type of the values
* @param value the value. String, int64, and double topics accept
* `null` or `undefined` , as described above.
* Using `null` or `undefined` with other
* topic types is an error and will throw an `Error` .
* @param options optional options object
* @return a 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.
*
* **Example:**
* ```
* const stream = session.topicUpdate.createUpdateStream('my_topic', diffusion.datatypes.string());
* stream.set('hello');
* ```
*
* @param path the path of the topic
* @param dataType the type of the values expected by the update stream
* @param options optional options object
* @return an update stream
*/
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
* PathPermission.UPDATE_TOPIC UPDATE_TOPIC} permission for `path`;
*
- the session is closed.
*
*
* @see
* JavaScript Object Notation (JSON) Patch
*
* @since 6.4
*/
applyJsonPatch(path: string, patch: string | Array<{
[key: string]: any;
}>, constraint?: UpdateConstraint): 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.
* If the name is empty, the operation will fail.
*/
readonly name: string;
/**
* The specification of the topic view.
*
* See the view
* specification for the description of the DSL for more
* information.
*/
readonly specification: string;
/**
* The roles used by the view when evaluating permissions.
*/
readonly roles: Set;
}
/**
* Topic view feature.
*
* This feature provides a client session with the ability to manage topic
* views.
*
* A topic view maps one part of a server's topic tree to another. It
* dynamically creates a set of reference topics from a set of
* source topics, based on a declarative topic view
* specification. The capabilities of topic views range from simple
* mirroring of topics within the topic tree to advanced capabilities including
* publication of partial values, expanding a single topic value into many
* topics, changing topic values, inserting values from other topics, throttling
* the rate of publication, and applying a fixed delay to the publication.
*
* A topic view can also map topics from another server (in a different
* cluster). This capability is referred to as 'remote topic views'. The view
* can specify the server that the source topics are hosted on in terms
* of a remote server (see {@link RemoteServers} for details of how to
* create and maintain remote servers).
*
* Each reference topic has a single source topic and has the same topic type as
* its source topic. Reference topics are read-only (they cannot be updated),
* nor can they be created or removed directly. Otherwise, they behave just like
* standard topics. A client session can subscribe to a reference topic, and can
* fetch the reference topic's current value if it has one.
*
* The source topics of a topic view are defined by a topic selector. One or
* more reference topics are created for each source topic, according to the
* topic view. If a source topic is removed, reference topics that are derived
* from it will automatically be removed. If a topic is added that matches the
* source topic selector of a topic view, corresponding reference topics will be
* created. Removing a topic view will remove all of its reference topics.
*
* Topic view specifications
*
* 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 topic view specification comprises three main parts:
*
* - The mapping part which specifies the source topics to map from
* and the mappings to target reference topics.
*
- Optional transformations which transform the topic value in some
* way.
*
- Optional options which specify other changes that the view may
* apply.
*
*
* Mapping comprises:
*
*
* - The source topic clause identifying the source topics that the
* view can apply to.
*
- The optional from clause which may identify a remote server that
* hosts the source topics.
*
- The path mapping clause which 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.
*
* Transformations can be:
*
* - patch transformation(s) specifying that a JSON patch is applied
* to the reference topic value.
*
- process transformations that allow conditional processing and/or
* calculations to be applied to the reference topic value.
*
- insert transformation(s) specifying that values from other
* topics are inserted into the reference topic value.
*
* Options can be:
*
* - The topic property mapping clause determines how reference topic
* properties are derived from source topic properties.
*
- The value mapping clause determines how reference topic values
* are derived from source topic or expanded values.
*
- The throttle clause constrains the rate at which each reference
* topic is updated when its source topic is updated.
*
- The delay by clause causes a change to a view's source topic to
* be delayed by a fixed time before it is reflected in reference topics.
*
- The separator clause can define a replacement path separator for
* values extracted using the scalar or expand directives.
*
- The type clause can specify that the reference topic that is
* created is of a different {@link TopicType} from the selected source topic.
*
*
* Mapping
* 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, all topics in the topic tree that match the
* source topic selector are considered (excluding {@link TopicTypeEnum.ROUTING
* ROUTING} topics). However, if a view specification uses some feature that can
* only be applied to JSON topics then only JSON topics will be selected.
*
* 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 source topic of a routing topic subscription.
*
* From clause
*
* The 'from' clause optionally follows the source topic clause. It begins with
* the `from` keyword and is followed by a remote server name. The name
* refers to a remote server created using the {@link RemoteServers} feature.
*
* The presence of the clause indicates that the source topics will be selected
* from the specified server and not from the local server.
*
* Further details regarding the processing of remote topic views are given
* below.
*
* Path mapping clause
*
* The paths of reference topics are derived from the source topic according to
* the path mapping clause. 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 or {@link TIME_SERIES} source topics with a JSON event type;
* if the path mapping contains a source value directive, topics with other topic
* types 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 current) 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 current)
* 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. Use the separator directive to replace path separators with an
* alternative string.
*
* 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.
*
*
* Transformations
*
* Transformations are specified after the mapping and before any options.
* Transformations can only be applied to JSON topics.
*
* Transformations are applied to the value extracted from the source topic in
* the order specified. There can be any number of transformations interspersed
* with one another and the value from one will be that which is input to the
* next. The only restriction is that all insert transformations must
* occur at the end, after any others.
*
* A transformation is applied to the current value within a view processing
* chain, so if a transformation occurs after an expand then it will be applied
* to each expanded value.
*
* Process transformations
*
* Process transformations may be used to apply conditional processing to a
* value (optionally determining whether a reference topic is created) and/or
* change the value in some way (for example, by applying some calculation to a
* field within the value).
*
* The format of a process transformation is:-
*
*
* process {statement}
*
*
* Where the statement can be:-
*
* - Operation(s).
* One or more operations separated by ';'.
* - A conditional statement.
* Comprising one or more conditions with operations to perform if they are
* satisfied.
*
*
* For example, the following topic view specification could be used to write a
* field into the value of the reference topic :
*
*
* map ?a// to b/<path(1)> process {set(/Name, 'John')};
*
*
* The following example shows a simple conditional statement which would only
* generate reference topics if the value of field /Price
was
* greater than 50 :
*
*
* map ?a// to b/<path(1)> process {if '/Price gt 50' continue};
*
*
* And the following shows a more complex statement which would set a field
* according to the value of the input field /Price
:
*
*
* map ?a// to b/<path(1)> process {if '/Price lt 50' set(/Tier, 1) elseif '/Price gt 50' set(/Tier, 2)};
*
*
*
* - Process operations
* -
*
* The following operations are supported :
*
*
* Operation |
* Description |
*
*
*
* set(pointer,
* value) |
* Sets the field indicated by the JSON
* pointer to an absolute value. If the field does not exist it
* will be created. The value can be an integer (e.g. 123), a String
* (e.g. "XYZ"), or a boolean (e.g. true or false).
*
* For example :
*
*
* set(/Name, "John")
*
*
* If a hierarchic pointer is specified, the parent object or array must
* exist. |
*
*
* set(pointer, calc
* calculation) |
* Sets the field indicated by the JSON
* pointer to a value which is the result of the specified
* calculation. If the field does not exist it will be created. The
* calculation can include fields within the input value. The calculation is
* specified as a quoted string. See below for a detailed description of
* calculations.
*
* For example :
*
*
* set(/DoubleValue, calc "/Value * 2")
*
*
* If a hierarchic pointer is specified, the parent object or array must
* exist. |
*
*
* remove(pointer) |
* Removes the json item at the specified
* pointer. Unlike JSON patch, if the item does not exist the operation
* does not fail. |
*
*
* continue |
* This is a special operation that indicates that
* the topic view evaluation should continue with the value as it is. This is
* only for use with conditional statements as the default behavior of a
* conditional statement is not to proceed if no condition is satisifed. |
*
*
* Operations can be chained by separating them with a ';' as shown in the
* example below:-
*
*
* set(/Amount, calc "/Value * /Number"); remove(/Value); remove (/Number)
*
*
* In this case the operations are all performed on the original value, creating
* a chain of deltas which are only applied to the original value at the end. If
* the 'set' operation fails no reference topic would be generated, however,
* processing will continue if the fields specified in the 'remove's are not
* present.
*
*
*
* - Process calculations
* -
*
* A calculation may be specified as the value of a set operation. A
* calculation is a simple arithmetic calculation upon integer fields. If
* applied to a non integer field the evaluation will not proceed. Floating
* point calculations are not supported.
*
* Arithmetic operators supported are
+
, -
,
* *
and /
.
*
* Examples of calculations are:-
*
*
* set(/Value, calc "/Value * 2")
* set(/Result, calc "/Value / 2")
* set(/Bonus, calc "/Salary + 1000")
* set(/Bonus, calc "/Salary + 1000 + /Age * 10")
*
*
* Standard operator precedence is applied, so in the last example above we have
* (/Salary + 1000 + (/Age * 10))
not
* ((/Salary + 1000 + /Age) * 10)
. Brackets may be used to override
* this.
*
*
* - Process conditional statements
* -
*
* A conditional statement is made up of an if clause, optionally
* followed by one or more elseif clauses and an optional final else
* clause.
*
* The if clause takes the form :
*
*
* if condition operation(s)
*
*
* Where the condition is a quoted string as described in detail below
* and the operation(s) is as described previously. If the condition is
* satisfied, the operations are applied to the value and the process is
* complete. If the condition is not satisfied, processing moves on to any
* elseif or else clauses that follow, but if there are none, the
* topic view evaluation does not proceed and no reference topic is created.
*
* An elseif (else if) clause takes the form :
*
*
* elseif condition operation(s)
*
*
* If the condition is satisfied, the operations are applied to the value and
* the process is complete. If the condition is not satisfied, processing moves
* on to any elseif or else clauses that follow, but if there are
* none, the topic view evaluation does not proceed and no reference topic is
* created. Note that elseif can be abbreviated to elsf.
*
* An else clause takes the form :
*
*
* else operation(s)
*
*
* And will only be reached if no previous if or elseif conditions
* were satisfied. If reached then the operations are applied to the value and
* the topic view evaluation proceeds. The continue operation may be used
* to proceed with an unchanged value.
*
*
* - Process conditions
* -
*
* A condition is of the form:
*
*
* pointer operator [constant/pointer]
*
*
* Where pointer is a JSON pointer, operator is a relational
* operator and constant is a string, integer, or boolean value.
*
* for example:-
*
*
* /Age > 40
* /Name = "Bill"
* /Age > /RetirementAge
* /Manager eq true
*
*
* Operators allowed are:
*
*
* Operator |
* Variant |
* Description |
* Supported JSON types |
*
*
*
* = |
* eq |
* Equals |
* All |
*
*
* > |
* gt |
* Greater than |
* Integer only |
*
*
* < |
* lt |
* Less than |
* Integer only |
*
*
* != |
* ne |
* Not equals |
* All |
*
*
* >= |
* ge |
* Greater than or equal |
* Integer only |
*
*
* <= |
* le |
* Less than or equal |
* Integer only |
*
*
*
* Compound conditions are supported by means of boolean operators:
*
* |
or or
* &
or and
*
* For example:
*
*
* /Age = 50 or /Age > 80
* /Age gt 50 & /Department eq "Accounts"
*
*
* Normal boolean precedence applies but brackets can be used to control
* precedence. For example:
*
*
* (/Age > 50 or /Department eq "Accounts") and /Band > 3
*
*
* Boolean 'not' is also allowed :
*
*
* not (/Age < 65 or /Retired eq false)
*
*
*
*
*
* Patch transformations
*
* Patch transformations indicate that a JSON patch is to be applied to the
* value.
*
* The format of a patch transformation is
*
*
* patch 'patch string'
*
* The patch string should be formatted according to the JSON Patch standard
* (see RFC 6902: JavaScript
* Object Notation (JSON) Patch).
*
* Patches are a sequence of JSON Patch operations contained in an array. They
* are applied as an atomic update to the previous value if the resulting update
* is successfully calculated. The following patch will check the value at a
* specific key and update if the expected value is correct:
*
*
* [{"op":"test", "path":"/price", "value" : 22}, {"op":"add", "path":"/price", "value": 23}]
*
*
* 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 the 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 return the index of the failed
* operation. 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.
*
* The following patch clause would add the 'price' field and remove the 'name'
* field from an input JSON object.
*
*
* patch '[{"op":"add", "path":"/price", "value" : 22}, {"op":"remove", "path":"/name"}]'
*
*
* Patches can only be applied to JSON arrays or objects and if they fail to
* apply, no resulting reference topic will be created by the view. If an update
* patch fails, any previously created reference topic would be removed.
*
* Insert transformations
*
* Insert transformations are used to insert a value from another topic into the
* current value.
*
* The name of the topic to insert from can be specified in a similar way to the
* path mapping in that constants, path directives, and scalar directives (but
* not expand directives) may be used.
*
* The value from the insertion topic (if found) is inserted into the 'current'
* value at a specified key position. The current value may be the source topic
* value, the value output from expand directives (in which case the insertion
* applies to each value), or the value from a previous transformation.
* Insertion topics may be {@link TopicTypeEnum.JSON JSON}, {@link TopicTypeEnum.STRING
* STRING}, {@link TopicTypeEnum.INT64 INT64}, or {@link TopicTypeEnum.DOUBLE DOUBLE}.
*
* If, when evaluating a topic view, the insertion topic is not found (or the
* specified key within it is not found), or it is of an unsupported topic type,
* an optional default value may be inserted, but if no default is specified
* then no insertion takes place and the value is passed to the derived
* reference topic unchanged.
*
* The values of the insertion topics are only taken at the point when the
* source topic is evaluated against the topic view (i.e. when the source topic
* is updated). Changes to the value of the insertion topic that occur in the
* interim are not applied to the derived reference topics.
*
* The format of an insert transformation is
*
*
* insert path [key fromKey] at insertionKey
* [default defaultValue]
*
*
* The path is specified in exactly the same way as for the path mapping
* clause, except it may not contain expand directives. path directives
* operate on the path of the source topic, whereas scalar directives
* operate on the 'current' value as defined previously.
*
* key is optional and can specify a fromKey which is a JSON
* pointer indicating the data within the insertion topic that is to be
* inserted. If no key is specified then the whole of the insertion topic value
* is inserted.
*
* at specifies the insertionKey which is a JSON pointer
* indicating where to insert the insertion topic value. If a value already
* exists at the specified key then it is replaced otherwise it is inserted.
* Insertion can only occur if the parent of the key exists in the value and is
* of a compatible type. Array pointers may only be used to replace existing
* entries or append one greater than the last entry. The special pointer value
* /-
may be used to append to the end of an existing array.
*
* default is optional and may be used to specify a string
* defaultValue to be inserted if the insertion topic does not exist, it
* is of an unsupported topic type, or the specified key within it could not be
* found.
*
* The following insert transformation would cause the whole value of the topic
* named AnyTopic to be inserted into the current value at key /T, assuming that
* the current value is an object.
*
*
* insert AnyTopic at /T
*
*
* The following insert transformation would cause the whole value of the topic
* named AnyTopic to be inserted into the current value at key /T/MyKey,
* assuming that an object with the key T exists in the current value.
*
*
* insert AnyTopic at /T/MyKey
*
*
* The following insert transformation would cause the whole value of the topic
* named AnyTopic to be appended to the array at the key T in the current value.
*
*
* insert AnyTopic at /T/-
*
*
* The following insert transformation would cause the value at the key name
* within the topic named AnyTopic to be appended to the array at the key T in
* the current value.
*
*
* insert AnyTopic key /name at /T/-
*
*
* In the above examples no insertion would take place if the insertion value
* was not found, but a default value can be specified to insert into the
* current value in this case.
*
*
* insert AnyTopic at /T/- default "unknown"
*
*
* The path of the topic to insert from can be built from parts of the source
* topic path and/or scalar values within the current value. For example:
*
*
* insert AC/<path(1,1)>/<scalar(/myval)> at /T
*
*
* Any number of insert clauses may be chained together. For example:
*
*
* insert AnyTopic at /T/- default "unknown" insert AnotherTopic at /X/Another
*
*
* Options
*
* Options are specified after the mapping and any transformations. Any number
* of options may be specified but any particular option may only be specified
* once.
* Topic property mapping
*
* 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 topic property mapping option.
* The following table describes the behavior for each topic property.
*
*
*
*
*
* Source topic property |
* Reference topic specification default |
* Can be set by topic property mapping? |
* Notes |
*
*
*
* {@link TopicSpecification.COMPRESSION COMPRESSION} |
* Copied from source topic specification |
* Yes |
* |
*
*
* {@link TopicSpecification.CONFLATION CONFLATION} |
* Copied from source topic specification |
* Yes |
* |
*
*
* {@link TopicSpecification.DONT_RETAIN_VALUE
* DONT_RETAIN_VALUE} |
* Copied from source topic specification |
* Yes |
* |
*
*
* {@link TopicSpecification.OWNER OWNER} |
* Not set |
* No |
* |
*
*
* {@link TopicSpecification.PERSISTENT PERSISTENT} |
* Not set |
* No |
* Reference 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 specification |
* Yes |
* |
*
*
* {@link TopicSpecification.PUBLISH_VALUES_ONLY PUBLISH_VALUES_ONLY} |
* Copied from source topic specification |
* Yes |
* |
*
*
* {@link TopicSpecification.REMOVAL REMOVAL} |
* Not set |
* No |
* Reference topics cannot be removed directly. |
*
*
* {@link TopicSpecification.SCHEMA SCHEMA}
* |
* Copied from source topic specification |
* No |
* A {@link RECORD_V2 RECORD_V2} reference topic has the same
* schema as its source topic. |
*
*
* {@link TopicSpecification.TIDY_ON_UNSUBSCRIBE TIDY_ON_UNSUBSCRIBE} |
* Copied from source topic specification |
* Yes |
* |
*
*
*
* {@link TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE TIME_SERIES_EVENT_VALUE_TYPE} |
* Copied from source topic specification |
* No |
* A {@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 specification |
* Yes, with restrictions |
* A 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 specification |
* Yes |
* |
*
*
*
* {@link TopicSpecification.VALIDATE_VALUES VALIDATE_VALUES} |
* Not set |
* No |
* A reference topic reflects updates to its source topic. It cannot reject
* updates. |
*
*
*
* A topic property option 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 option
*
* 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 and/or
* modified by transformations. For {@link TopicTypeEnum.JSON JSON} source topics or
* {@link TopicTypeEnum.TIME_SERIES TIME_SERIES} topics with a `JSON` event
* type, the value option can be applied to extract part of the resulting value
* (the latest value in the case of TIME_SERIES topics).
*
* A topic value option begins with 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 current value to
* copy.
*
* For example, given a current value of
*
*
* {
* "account" : "1234",
* "balance" : { "amount" : 12.57, "currency" : "USD" }
* }
*
*
* and the value option `as `, the reference topic value
* will be
*
*
* {
* "amount" : 12.57,
* "currency" : "USD"
* }
*
*
* Value mappings that follow expand directives and/or transformations apply to
* the current derived 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 option
*
* The throttle option 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 option 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 option 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 throttle option 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, the throttle option provides topic-scoped
* conflation.
*
* The throttle option 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.
*
* Delay option
*
* The delay option causes a change to a view's source topic to be delayed by a
* fixed time before it is reflected in reference topics. Topic additions,
* updates, and removals are all delayed. Delays can range from one second to
* many days​.
*
* Such a publication delay is a useful way to devalue topic data so it can be
* given away to non-paying users.
*
* The delay option has the form delay by duration
, where
* duration 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 changes to a source
* topic are delayed by five minutes before they are reflected in the
* corresponding reference topic.
*
*
* map ?a// to b/<path(1)> delay by 5 minutes
*
*
* Views with the delay option specified initially create reference topics in an
* unpublished state. The topics are published once the delay time has expired.
* A topic in the unpublished state prevents a lower priority topic view from
* creating a reference topic with the same path. Sessions with the rights to
* read the source topic can browse unpublished topics using the
* {@link FetchRequest.withUnpublishedDelayedTopics withUnpublishedDelayedTopics}
* fetch request option.
*
* Separator option
*
* Views can use the scalar and expand directives in path mappings to extract
* text from the source value. By default, any `/` characters in the text
* are interpreted as path separators and will introduce extra levels in
* reference topic paths. If this is undesirable, the separator option
* can be used to replace any `/` characters produced by the scalar and
* expand directives with a constant string. The replacement can contain path
* separators but must have no empty path segments (`//`).
*
* Here is an example replacing all path separators with an alternate character:
*
*
* map ?a/path/ to b/<scalar(/x/y)> separator '%'
*
*
* If the value at '/x/y' in the source topic was foo/bar, this would cause the
* reference topic to be created at `/b/foo%bar` instead of `/b/foo/bar`.
*
* Preserve topics option
*
* The default behavior for a topic view is that only the reference topics
* that can be derived from the current value of the source topic are
* maintained. This applies to views using directives that derive the path of
* the reference topic(s) from a value within the source topic (e.g. scalar or
* expand). For example if a view uses a scalar directive to determine the path
* of the reference topic and the source topic is updated such that the selected
* scalar value changes then the previously created reference topic will be
* removed and a new one created. Similarly an expand directive may create many
* reference topics from the source value but if the source is updated then only
* those reference topics that still have a corresponding value within the
* source value will be updated (or new ones added if not in the previous
* value), whilst others will be removed.
*
* There are situations where an application may not want reference topics to be
* removed because of source value changes. In such cases the 'preserve
* topics' option may be used to indicate that all reference topics created by a
* view should be retained (and updated by later updates that apply to it) until
* either the source topic or the creating view are removed.
*
* For example:
*
* map ?a/path/ to b/<expand()> preserve topics
*
*
* Topic type option
*
* The 'type' option can be used to specify the {@link TopicType} of the target
* reference topic. If the current source value of type indicated by the source
* topic's type can be converted to the target type, a reference topic of the
* specified type will be created.
*
* For example:
*
*
* map ?a/ to b/<path(1)> type STRING
*
*
* The specified type must be one of the supported target types
* ({@link TopicTypeEnum.STRING STRING}, {@link TopicTypeEnum.INT64 INT64},
* {@link TopicTypeEnum.DOUBLE DOUBLE}, {@link TopicTypeEnum.JSON JSON},
* {@link TopicTypeEnum.TIME_SERIES TIME_SERIES}, or {@link TopicTypeEnum.BINARY
* BINARY}), case insensitive.
*
* The following table describes the supported conversions from the source topic
* type (the left column) to the supported target types. The number in brackets
* indicates a note at the foot of the table describing exactly how the
* conversion is processed. Where there is no number, no conversion is necessary
* and the derived source value is simply mapped to the target reference topic
* as if the 'type' option was not specified. Where there is no entry for the
* source topic type in the left column, no conversion is supported and topics
* of unsupported types will not be processed by the topic view. An 'x'
* indicates that the conversion is not supported.
*
* In all cases the value being processed will be the 'current' value as derived
* from other mappings within the topic view (e.g. expand) which is not
* necessarily the value of the source topic.
*
*
*
* Source topic |
* {@link TopicTypeEnum.STRING STRING} |
* {@link TopicTypeEnum.INT64 INT64} |
* {@link TopicTypeEnum.DOUBLE DOUBLE} |
* {@link TopicTypeEnum.JSON JSON} |
* {@link TopicTypeEnum.TIME_SERIES
* TIME_SERIES} |
* {@link TopicTypeEnum.BINARY BINARY} |
*
*
* {@link TopicTypeEnum.STRING STRING} |
* |
* (1) |
* (1) |
* (2) |
* (3) |
* x |
*
*
* {@link TopicTypeEnum.INT64 INT64} |
* (4) |
* |
* (5) |
* (2) |
* (3) |
* x |
*
*
* {@link TopicTypeEnum.DOUBLE DOUBLE} |
* (4) |
* (6) |
* |
* (2) |
* (3) |
* x |
*
*
* {@link TopicTypeEnum.JSON JSON} |
* (7) |
* (7) |
* (7) |
* |
* (3) |
* x |
*
*
* {@link TopicTypeEnum.TIME_SERIES TIME_SERIES} |
* (8) |
* (8) |
* (8) |
* (8) |
* |
* (9) |
*
*
* {@link TopicTypeEnum.BINARY BINARY} |
* x |
* x |
* x |
* x |
* (9) |
* |
*
*
*
* Conversion notes:-
*
*
* - {@link TopicTypeEnum.STRING STRING} to number conversions will only occur if
* the value of the string can be converted to the target number type. If the
* string cannot be converted then no reference topic will be created.
* - Primitive types to {@link TopicTypeEnum.JSON JSON} will result in a JSON
* topic containing just the scalar value.
* - Conversions to {@link TopicTypeEnum.TIME_SERIES TIME_SERIES} will result in a
* time series topic with an event type matching the source topic. Every update
* to the source topic will result in a new value being appended to the
* reference time series topic. It is not possible to convert to a time series
* topic with a different event type from the source topic.
* - Conversions from number types to {@link TopicTypeEnum.STRING STRING} will
* result in a simple string representation of the number in the reference topic
* value.
* - {@link TopicTypeEnum.INT64 INT64} to {@link TopicTypeEnum.DOUBLE DOUBLE}
* conversions perform a simple conversion. For example, 123 becomes 123.0.
* - {@link TopicTypeEnum.DOUBLE DOUBLE} to {@link TopicTypeEnum.INT64 INT64}
* conversions perform rounding to the nearest integer value. For example 12.51
* becomes 13.
* - {@link TopicTypeEnum.JSON JSON} to primitive type conversions only occur if
* the JSON value is a scalar which can be read as a string and converted to the
* target type. Currently, only string and integer scalar values can be read as
* a string (i.e. not doubles). The string representation of the value will be
* converted in the same way as specified for {@link TopicTypeEnum.STRING STRING} to
* other primitive types. If the JSON value is a structure or cannot be
* converted then no conversion takes place and no reference topic will be
* created.
* - The conversion of {@link TopicTypeEnum.TIME_SERIES TIME_SERIES} to other
* types follows the same rules as for conversion from the source topic type
* that matches the source time series topic's event value type. So if the time
* series event type is 'double' then the conversion rules from source topic type
* {@link TopicTypeEnum.DOUBLE DOUBLE} to the target type will apply. Each value
* appended to the source time series topic will result in an update to the
* reference topic. If a failure to convert occurs at any point then the
* reference topic would be removed and only recreated if a value is appended
* that can be converted.
* - {@link TopicTypeEnum.BINARY BINARY} to {@link TopicTypeEnum.TIME_SERIES
* TIME_SERIES}, and vice-versa is supported in the same way as for other time
* series conversions.
*
*
* 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.
*
* Remote topic views
*
* A remote topic view is one that specifies another server as the location of
* the source topics using the from clause as shown in the example
* below:
*
* ```
* map ?a// from server1 to b/
* ```
* The server name (`server1` in this example) refers to the name of a
* remote server created using the {@link RemoteServers} feature.
*
* In this case, upon establishing a successful connection with the remote
* server indicated the topic view will create reference topics locally based
* upon the topics selected by the topic view's selector at the remote server.
* match it at the remote server and not on the local server and there is no
* reason why there could not be a source topic at the remote server that has
* the same path as an entirely different topic on the local server.
*
* More than one topic view can specify the same remote server.
*
* A remote server only makes a physical connection when it is in use, therefore
* the first topic view that specifies a remote server will cause it to
* establish a connection. Similarly, if the last topic view that uses a remote
* server is removed then the connection will be closed.
*
* It is not necessary for the named remote server definition to exist before
* creating the topic view, as if it does not then the topic view will simply
* remain dormant until the remote server is created and a successful connection
* to the server specified in its URL is established. Similarly, if a remote
* server that is in use by remote topic views is removed then all of the
* reference topics created by the topic views will be removed and the topic
* views will become dormant until the named remote server is created again or
* the views are changed to name a different remote server.
*
* If a remote topic view selects a {@link TopicTypeEnum.ROUTING ROUTING} topic at
* the remote server then local mappings will only be performed if the routing
* topic mapping at the remote server is able to establish a mapping for the
* remote server connection. The mapping will be done as if from the resolved
* routing topic.
*
* The rules of precedence for remote topic views are the same as for other
* topic views. If the remote server for a remote topic view does not exist or
* does not have an established connection then the remote topic view is not
* evaluated (i.e. it is as if the source topics for the view did not exist),
* but if the remote server later connects then the view will be evaluated and
* rules of precedence will determine whether reference topic will replace those
* created by earlier views.
*
* Topic view persistence and replication
*
* Reference topics are neither replicated nor persisted. They are created and
* removed based on their source topics. However, topic views are replicated and
* persisted. A server that restarts will restore topic views during recovery.
* Each topic view will then create reference topics based on the source topics
* that have been recovered.
*
* The server records all changes to topic views in a persistent store. Topic
* views are restored if the server is started.
*
* If a server belongs to a cluster, topic views (and remote servers) will be
* replicated to each server in the cluster. Topic views are evaluated locally
* within a server. Replicated topic views that select non-replicated source
* topics can create different reference topics on each server in the cluster.
* When remote topic views are in use, each server in the cluster will make a
* connection to the specified remote server and will separately manage their
* remote topic views.
*
* A view with a delay clause uses temporary storage to record delayed events.
* If there is a high volume of updates, temporary per-server disk files will be
* used to save server memory. The storage is per-server, and does not survive
* server restart. When a server is started, no data will be published by a view
* with a delay clause until the delay time has expired.
*
* Access control
*
* The following access control restrictions are applied:
*
*
* - To {@link listTopicViews list the topic views}, a session needs the
* {@link GlobalPermission.READ_TOPIC_VIEWS READ_TOPIC_VIEWS} global permission.
*
*
- To {@link createTopicView create, replace}, or
* {@link removeTopicView remove} a topic view, a session needs the
* {@link GlobalPermission.MODIFY_TOPIC_VIEWS MODIFY_TOPIC_VIEWS} global
* permission and {@link PathPermission.SELECT_TOPIC SELECT_TOPIC} permission
* for the path prefix of the source topic selector.
*
*
- Each topic view records the principal and security roles of the session
* that created it as the topic view security context. When a topic
* view is evaluated, this security context is used to constrain the creation of
* reference topics. A reference topic will only be created if the security
* context has {@link PathPermission.READ_TOPIC READ_TOPIC} permission for the
* source topic path, and {@link PathPermission.MODIFY_TOPIC MODIFY_TOPIC}
* permission for the reference topic path. The topic view security context is
* copied from the creating session at the time the topic view is created or
* replaced, and is persisted with the topic view. The topic view security
* context is not updated if the roles associated with the session are changed.
*
*
*
* Accessing the feature
*
* This feature may be obtained from a {@link Session session} as follows:
*
*
* const topicViews = session.topicViews;
*
*
* @since 6.3
*
*/
export interface TopicViews {
/**
* Create a new named topic view.
*
* If a view with the same name already exists the new view will update
* the existing view.
*
* @param name the name of the view
* @param specification the specification of the view using the DSL
* @return a 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;
/**
* Get a named Topic View.
*
* If the named view does not exist the Result will resolve with null result.
*
* @param name the name of the view
* @return a Result that resolves when a response is received from the server,
* returning a named view if it exists
*
* If the task fails, the Result will resolve with an Error. Common
* reasons for failure include:
*
* - the operation failed due to a transient cluster error;
*
- the calling session does not have READ_TOPIC_VIEW permission or
* appropriate path prefix permissions;
*
- the session is closed.
*
*/
getTopicView(name: string): 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;
/**
* 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. Passing {@link AnyDataType} as second argument will create
* a polymorphic value stream that receives all data types. It is then up to
* the value handler to interpret the incoming data.
*
* The first argument of this function can be a string, a {@link
* TopicSelector}, or a non-empty array of strings and {@link TopicSelector}s.
*
* **Example:**
* ```
* // Produce a value stream for receiving JSON values.
* var json = diffusion.datatypes.json();
*
* session.addStream(topic, json).on('value', function(topic, specification, newValue, oldValue) {
* console.log('New value ', newValue.get());
* });
* ```
*
* @param selector the topic selector to receive updates for
* @param datatype the data type to produce a stream for.
* @returns a new {@link ValueStream} for the provided data type
*/
addStream(selector: string | TopicSelector | Array, dataType: DataType | AnyDataType): ValueStream;
/**
* This adds a value stream for a given {@link DataTypes Data
* Type} without a selector which will be a fallback stream to receive all
* events that do not have a stream registered.
*
* **Example:**
* ```
* // Produce a fallback value stream for receiving JSON values.
* var json = diffusion.datatypes.json();
*
* session.addFallbackStream(json).on('value', function(topic, specification, newValue, oldValue) {
* console.log('New value ', newValue.get());
* });
* ```
*
* @param datatype the data type to produce a stream for.
* @returns a fallback stream
*/
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 = "#"
}
/**
* @module diffusion.selectors
*/
/**
* Create {@link TopicSelector} instances for use with other API methods.
*
* Selectors are evaluated against topic paths. A topic path is a '/'
* separated string of parts, which map to the topic 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 value the value
* @param dataType the optional type of the value
* @return a new constraint
*/
with(pointer: string, value: any, dataType?: DataType): PartialJSON;
/**
* Require a specific position in the JSON object to be empty.
*
* The `pointer` is a
* JSON Pointer syntax
* reference that should have no value in the JSON object. If the
* `pointer` parameter cannot be parsed as a JSON pointer an
* `Error` is thrown.
*
* The function returns a new {@link PartialJSON PartialJSON}
* object. The original object remains unmodified.
*
* @param pointer the pointer expression
* @return a new constraint
*/
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.
*
* The first set operation will return a {@link
* TopicCreationResult} indicating whether a new topic was created
* or it already exists.
*
* If the task fails, the 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;
}
/**
* @module diffusion.topics
*/
/**
* A parameterised query that can be used to search the topic tree.
*
* A new request can be created using the {@link Session.fetchRequest fetchRequest}
* method and modified to specify a range of topics and/or
* various levels of detail. The request can then be issued to the server
* using the {@link FetchRequest.fetch fetch} method
* supplying a topic selector which specifies the selection of topics.
* The results are returned via a {@link 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.ROUTING Routing} topics are deprecated and 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.
*
* {@link TopicTypeEnum.ROUTING ROUTING} may be specified.
*
* @param topicTypes topic types to be selected
*
* @return a new fetch request derived from this fetch request but
* specifying that only topics of the specified topic types should
* be returned.
*
* @throws an Error if invalid topic types are specified
*/
abstract topicTypes(topicTypes: TopicType[] | Set): FetchRequest;
/**
* Specifies that values should be returned for selected topics,
* constraining the selection to only those topics with a data type
* compatible with the specified {@link DataType
* DataType}.
*
* The specified value constrains the topic types. So, any topic types
* specified in a previous call to {@link topicTypes} that
* cannot be read as the specified class will be removed from the list
* of topic types.
*
* @param dataType the type of values. If no value is specified this will
* cancel any previous call (topic types will remain
* unchanged).
*
* @return a new fetch request derived from this fetch
* request but specifying that only topics compatible with the
* specified class should be returned with values.
*
* @throws an Error if the class is not compatible with any topic types.
*/
abstract withValues(dataType?: DataType | AnyDataType): FetchRequest;
/**
* Specifies that all properties associated with each topic's {@link
* TopicSpecification specification} should be returned.
*
* @return a new fetch request derived from this fetch request but
* specifying that topic specification properties should be
* returned.
*/
abstract withProperties(): FetchRequest;
/**
* Specifies 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;
/**
* Include the details of reference topics that are not yet published.
*
* {@link TopicViews Topic views} that use the `delay by` clause
* create reference topics in an unpublished state. The topics are
* published once the delay time has expired. A topic in the
* unpublished state prevents a lower priority topic view from creating
* a reference topic with the same path.
*
* A reference topic in the unpublished state which matches the query
* will only be included in the fetch results if the session has
* {@link PathPermission.READ_TOPIC READ_TOPIC} permission for the
* reference's source topic as well as `READ_TOPIC` permission for
* the reference topic. Requiring `READ_TOPIC` permission for the
* source topic ensures less privileged sessions cannot derive
* information from the existence of the reference topic before the
* delay time has expired.
*
* @return a new fetch request derived from this fetch request,
* additionally specifying that unpublished reference topics
* should be included in the results
* @since 6.5
*/
abstract withUnpublishedDelayedTopics(): FetchRequest;
/**
* Sends a fetch request to the server.
*
* Results are returned for all topics matching the selector that satisfy
* the request constraints within any range defined by {@link from}/{@link
* after} and/or {@link to}/{@link before}.
*
* This function can take any number of arguments. Each argument can be a string
* or a {@link TopicSelector}. Alternatively, an array of strings and
* {@link TopicSelector}s can be passed as a single argument. At least one
* valid selector has to be specified.
*
* @param topics specifies a topic selector which selects the topics to be
* fetched
*
* @return a 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} (deprecated)
* | {@link TopicTypeEnum.TIME_SERIES TIME_SERIES} |
* {@link TopicTypeEnum.RECORD_V2 RECORD_V2} |
*
*
* {@link TopicSpecification.COMPRESSION COMPRESSION} |
* Optional |
* - |
* Optional |
* Optional |
* Optional |
*
*
* {@link TopicSpecification.CONFLATION CONFLATION} |
* Optional |
* Optional |
* Optional |
* Optional |
* Optional |
*
*
* {@link TopicSpecification.DONT_RETAIN_VALUE DONT_RETAIN_VALUE} |
* Optional |
* Optional |
* - |
* - |
* Optional |
*
*
* {@link TopicSpecification.PUBLISH_VALUES_ONLY PUBLISH_VALUES_ONLY} |
* Optional |
* - |
* - |
* Optional |
* Optional |
*
*
* {@link TopicSpecification.SCHEMA SCHEMA} |
* - |
* - |
* - |
* - |
* Optional |
*
*
* {@link TopicSpecification.TIDY_ON_UNSUBSCRIBE TIDY_ON_UNSUBSCRIBE} |
* Optional |
* Optional |
* Optional |
* Optional |
* Optional |
*
*
* {@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} |
* Optional |
* Optional |
* - |
* Optional |
* Optional |
*
*
* {@link TopicSpecification.PERSISTENT PERSISTENT} |
* Optional |
* Optional |
* Optional |
* Optional |
* Optional |
*
*
* {@link TopicSpecification.PRIORITY PRIORITY} |
* Optional |
* Optional |
* Optional |
* Optional |
* Optional |
*
*
* {@link TopicSpecification.REMOVAL REMOVAL} |
* Optional |
* Optional |
* Optional |
* Optional |
* Optional |
*
*
* {@link TopicSpecification.OWNER OWNER} |
* Optional |
* Optional |
* Optional |
* Optional |
* Optional |
*
*
*
* `TIME_SERIES` topics have restricted values for the
* `CONFLATION` property. They are only allowed to have the values
* `off` or `unsubscribe`.
*
* `ROUTING` topics (deprecated) 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 publishing the complete new value. Subscribing sessions can use a
* {@link ValueStream} to automatically apply the delta to a local copy of
* the topic value to calculate the new value.
*
* Setting PUBLISH_VALUES_ONLY to `true` disables this behavior so that
* deltas are never published. Doing so is usually not recommended because
* it will result in more data being transmitted, less efficient use of
* network resources, and increased transmission latency. On the other hand,
* calculating deltas can require significant CPU from the server or, if
* update streams are used, from the updating client. The CPU cost will be
* higher if there are many differences between successive values, in which
* case delta streams confer fewer benefits. If successive values are
* unrelated to each other, consider setting PUBLISH_VALUES_ONLY to `true`.
* Also consider setting PUBLISH_VALUES_ONLY to `true` if the network
* capacity is high and the bandwidth savings of deltas are not required.
*
* @see {@link TopicSpecification.DONT_RETAIN_VALUE}
*/
static readonly PUBLISH_VALUES_ONLY = "PUBLISH_VALUES_ONLY";
/**
* Key of the topic property 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 = "VALIDATE_VALUES";
/**
* Key of the topic property that specifies the 'tidy on unsubscribe' option
* for a topic.
*
* By default, if a session unsubscribes from a topic, it will receive any
* updates for that topic that were previously queued but not sent.
*
* If this property is set to `true`, when a session unsubscribes from the
* topic, any updates for the topic that are still queued for the session
* are removed. There is a performance overhead to using this option as the
* client queue must be scanned to find topic updates to remove, however it
* may prove useful for preventing unwanted data being sent to sessions.
*
* @since 6.0
*/
static readonly TIDY_ON_UNSUBSCRIBE = "TIDY_ON_UNSUBSCRIBE";
/**
* Key of the topic property that specifies the event data type for a time
* series topic.
*
* The value is the {@link DataType.name type name} of a
* data type.
*
* @since 6.0
*/
static readonly TIME_SERIES_EVENT_VALUE_TYPE = "TIME_SERIES_EVENT_VALUE_TYPE";
/**
* Key of the topic property that specifies the range of events retained by
* a time series topic.
*
* When a new event is added to the time series, older events that fall
* outside of the range are discarded.
*
* If the property is not specified, a time series topic will retain the ten
* most recent events.
*
* Time series range expressions
*
* The property value is a time series range expression string
* composed of one or more constraint clauses. Constraints are combined to
* provide a range of events from the end of the time series.
*
*
* - limit constraint
*
- A limit constraint specifies the maximum number of events from the
* end of the time series.
*
- last clause
*
- A last constraint specifies the maximum duration of events from the
* end of the time series. The duration is expressed as an integer followed
* by one of the following time units.
*
* MS
– milliseconds;
* S
– seconds;
* H
– hours.
*
*
* If a range expression contains multiple constraints, the constraint that
* selects the smallest range is used.
*
* Property value | Meaning
* --------------- | ---------
* `limit 5` | The five most recent events
* `last 10s` | All events that are no more than ten seconds older than the latest event
* `last 10s limit 5` | The five most recent events that are no more than ten seconds older than the latest event
*
* Range expressions are not case sensitive: `limit 5 last 10s` is
* equivalent to `LIMIT 5 LAST 10S`.
*
* @since 6.0
*/
static readonly TIME_SERIES_RETAINED_RANGE = "TIME_SERIES_RETAINED_RANGE";
/**
* Key of the topic property that specifies the range of time series topic
* events to send to new subscribers.
*
* The property value is a time series range expression, following the
* format used for {@link TopicSpecification.TIME_SERIES_RETAINED_RANGE
* TIME_SERIES_RETAINED_RANGE}.
*
* If the property is not specified, new subscribers will be sent the latest
* event if delta streams are enabled and no events if delta streams are
* disabled. See the description of Subscription range in the
* {@link TimeSeries time series feature} documentation.
*
* @since 6.0
*/
static readonly TIME_SERIES_SUBSCRIPTION_RANGE = "TIME_SERIES_SUBSCRIPTION_RANGE";
/**
* Key of the topic property that specifies a schema which constrains topic
* values.
*
* This property is only used by {@link 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 = "SCHEMA";
/**
* Key of the topic property that specifies a topic should not retain its
* last value.
*
* By default, a topic (other than a `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` also disables delta streams,
* regardless of the {@link TopicSpecification.PUBLISH_VALUES_ONLY
* PUBLISH_VALUES_ONLY} value. If subsequent values are likely to be
* related, delta streams usually provide performance benefits (see {@link
* TopicSpecification.PUBLISH_VALUES_ONLY PUBLISH_VALUES_ONLY}). Consider
* leaving DONT_RETAIN_VALUE set to `false` to benefit from delta streams,
* even if there is no other requirement to retain the last value.
*
* Bearing in mind the performance trade-offs of disabling delta streams,
* there are two reasons to consider setting DONT_RETAIN_VALUE to `true`.
* First, it stops the server and each subscribed client from keeping a copy
* of the value, reducing their memory requirements. Second, when a topic
* has a high update rate and is replicated across a cluster, it can
* significantly improve throughput because the values need not be persisted
* to the cluster.
*
* Time series topics ignore this property and always retain the latest
* value.
*
* @since 6.0
*/
static readonly DONT_RETAIN_VALUE = "DONT_RETAIN_VALUE";
/**
* Key of the topic property that can be used to prevent a topic from being
* persisted when the server is configured to enable persistence.
*
* By default, a topic will be persisted if persistence is enabled at the
* server and the topic type supports persistence.
*
* Setting PERSISTENT to `false` will prevent the topic from being
* persisted.
*
* @since 6.1
*/
static readonly PERSISTENT = "PERSISTENT";
/**
* Key of the topic property that specifies a removal policy for automatic
* removal of the topic (and/or other topics).
*
* This property is specified as an expression which defines one or more
* conditions that are to be satisfied before automatic removal occurs.
*
* The expression takes the form:
*
*
* when conditions [remove 'selector']
*
*
* At least one condition must be supplied. If more than one is supplied,
* they must be separated by logical operators (`and` or `or`).
* The natural evaluation order of the operators may be changed by
* surrounding with parentheses (e.g. (condition `and`
* condition)).
*
* The `remove` clause is optional. It provides a {@link TopicSelector}
* expression representing the topics to be removed. If a `remove` clause is
* specified, the topic with the removal policy will only be removed if its
* path matches the selector expression. The selector must be surrounded by
* either double or single quotes.
*
* When many topics have the same removal policy, it is better to
* set the `REMOVAL` property for one of them, using a `remove`
* clause that selects all of the topics. This is more efficient because it
* allows the server to avoid evaluating the same condition many times.
*
* The permissions that are applied at the time of removal are those defined
* by the roles of the principal that created the topic at the time of
* creation. The roles of that principal may therefore change before the
* removal with no effect, but if the permissions given to the roles change
* it may have an effect upon the final removal.
*
* Only one occurrence of each of the following condition types may be
* included within the expression:
*
*
* Condition Type |
* Format |
* Usage |
*
*
* time after |
* time after absoluteTime |
* Removal should occur after a specified absolute time. Absolute time
* may be specified as a number of milliseconds since the epoch (00:00:00 on
* 1 January 1970) or as a quoted date and time formatted in RFC_1123
* date time format. Either single or double quotes may be used. |
*
*
* subscriptions less than |
* [local] subscriptions < n for forPeriod [after afterPeriod] |
* Removal should occur when the topic has had less than the specified
* number (n) of subscriptions for a given period (forPeriod)
* of time. Optionally, an initial period (afterPeriod) may be
* specified by which to delay the initial checking of this condition. See
* below for period formats.
* The optional local keyword restricts evaluation to only count
* subscriptions from sessions belonging to the local server or cluster,
* ignoring subscriptions from sessions belonging to downstream remote servers that
* host fanout replicas of the topic. |
*
*
* no updates for |
* no updates for forPeriod [after afterPeriod] |
* Removal should occur when the topic has had no updates for a given
* period (forPeriod) of time. Optionally, an initial period
* (afterPeriod) may be specified by which to delay the initial
* checking of this condition. See below for period formats. |
*
*
*
* Multiple occurrences of the following condition types may be
* included within the expression:
*
*
* Condition Type |
* Format |
* Usage |
*
*
* no session has |
* no [local] session has 'criteria' [for forPeriod] [after afterPeriod] |
* Removal should occur when no sessions satisfy certain criteria.
* Optionally the criteria can be required to be satisfied for a period of time
* (forPeriod). Optionally, an initial period (afterPeriod) can
* be specified to delay the initial check of the criteria. Session selection
* criteria are specified as defined in {@link Session session filters} and
* must be surrounded by single or double quotes. See below for period formats.
* The optional local keyword restricts evaluation to sessions
* belonging to the local server or cluster, ignoring sessions belonging to
* downstream remote servers that host fanout replicas of the topic. |
*
*
* |
* this session closes |
* This is a shorthand form of `no local session has` that may be used to
* indicate that the topic is to be removed when the session that created it
* closes. |
*
*
*
* Time periods are specified as a number followed (with no intermediate
* space) by a single letter representing the time unit. The time unit may
* be `s` (seconds), `m` (minutes), `h` (hours) or `d` (days). For example,
* 10 minutes would be specified as 10m.
*
* If quotes or backslashes (`\`) are required within quoted values such as
* selectors or session criteria then they may be escaped by preceding with
* `\`. The convenience method {@link escape} is provided to escape such
* characters in a value. The expression is validated only by the server and
* therefore if an invalid expression is specified it will be reported as an
* Error.
*
* **Examples:**
*
* ```
* when time after 1518780068112
* ```
*
* The topic will be removed when the date and time indicated by the
* specified number of milliseconds since the epoch has passed.
*
* ```
* when time after 'Tue, 3 Jun 2018 11:05:30 GMT'
* ```
*
* The topic will be removed when the specified date and time has passed.
*
* ```
* when time after 'Tue, 3 Jun 2018 11:05:30 GMT' remove '*alpha/beta//'
* ```
*
* The topic alpha/beta and all topics subordinate to it will be removed
* when the specified date and time has passed.
*
* ```
* when subscriptions < 1 for 20m
* ```
*
* The topic will be removed when it has had no subscriptions for a
* continuous period of 20 minutes.
*
* ```
* when subscriptions < 2 for 20m after 1h
* ```
*
* The topic will be removed when it has had less than 2 subscriptions for a
* continuous period of 20 minutes after one hour has passed since its
* creation.
*
* ```
* when no updates for 3h
* ```
*
* The topic will be removed when it has had no updates for a continuous
* period of 3 hours.
*
* ```
* when no updates for 15m after 1d
* ```
*
* The topic will be removed when it has had no updates for a continuous
* period of 15 minutes after one day has passed since its creation.
*
* ```
* when this session closes
* ```
*
* The topic will be removed when the session that created it closes.
*
* ```
* when no session has '$Principal is "Alice"'
* ```
*
* The topic will be removed when there is no session with the principal 'Alice'.
*
* ```
* when no session has '$Principal is "Alice"' for 10m
* ```
*
* The topic will be removed when there 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 in a `no session has` condition is subtly
* different from its use in other conditions. It does not guarantee that
* there has been no session satisfying the condition at some point between
* evaluations, only that when evaluated the given period of time has passed
* since it was last evaluated and found to have no matching sessions.
*
* Automatic topic removal is supported for a topic that is replicated
* across the local cluster, and for a topic with with fanout replicas on
* downstream remote servers. A `subscriptions less than` condition will be evaluated
* against the total number of subscriptions across the cluster and on all
* fanout replicas on downstream remote servers. A `no session has`
* condition will consider all sessions hosted across the cluster and all
* sessions hosted by downstream remote servers that have a fanout replica
* of the topic. The `local` keyword can be used to restrict evaluation to
* the local cluster, ignoring fanout replicas.
*
* @since 6.1
*/
static readonly REMOVAL = "REMOVAL";
/**
* Key of the topic property that specifies the conflation policy of the
* topic. The policy specifies how the server manages queued topic updates.
* Conflation is applied individually to each session queue.
*
* Conflation is the process of merging or discarding topic updates queued
* for a session to reduce the server memory footprint and network data. The
* server will conflate sessions that have a large number of queued messages
* to meet configured queue size targets. The sessions with the largest
* queues are typically slow consumers or have been disconnected - both will
* benefit from conflation. This property allows conflation behavior to be
* tuned on a topic-by-topic basis.
*
* The supported policies are:
*
* * `off`
* * `conflate`
* * `unsubscribe`
* * `always`
*
* The default policy used when the property is not specified and the topic
* type is not time series is `conflate`. The default policy used when the
* property is not specified and the topic type is time series is `off`.
*
* The policy `off` disables conflation for the topic. This policy
* disables all conflation for the topic, so topic updates will never be
* merged or discarded.
*
* The policy `conflate` automatically conflates topic updates when
* back pressure is detected by the server.
*
* The policy `unsubscribe` automatically unsubscribes the topic when
* back pressure is detected by the server. The unsubscription is not
* persisted to the cluster. If a session fails over to a different server
* it will be resubscribed to the topic.
*
* The policy `always` automatically conflates topic updates as they
* are queued for the session. This is an eager policy that ensures only the
* latest update is queued for the topic, minimising the server memory and
* network bandwidth used by the session.
*
* The `conflate` and `unsubscribe` policies are applied when
* the server detects back pressure for a session. The server configuration
* places limits on the data queued for each session. If these limits are
* breached, the server will conflate the session queue to attempt to reduce
* its size. If the session queue still exceeds the limits after conflation,
* the session will be terminated.
*
* Conflation can be disabled on a session-by-session basis. If conflation is
* disabled for a session the policy will not be applied to topic updates
* queued for the session but will be for other sessions that have conflation
* enabled.
*
* The policies `conflate` and `always` are not supported for
* time series topics as they would cause missing events. Attempts to enable
* these policies with time series topics will cause the creation of the
* topic to fail, reporting that the specification is invalid.
*
* @since 6.2
*/
static readonly CONFLATION = "CONFLATION";
/**
* Key of the topic property that allows the creator of a topic to extend
* READ_TOPIC, MODIFY_TOPIC, and UPDATE_TOPIC permissions to a specific
* principal, in addition to the permissions granted by the authorisation
* rules in the security store.
*
* A session that has authenticated using the principal can update and
* remove the topic, so the principal can be considered the topic owner. To
* fetch or subscribe to the topic, the principal must also be granted
* the SELECT_TOPIC permission by the security store rules.
*
* This may be used in the following cases:
* 1) A session creates a topic and makes its own principal the owner.
* 2) A session creates a topic and makes another principal the owner.
*
* The format of the property value is:
*
* `$Principal is "name"`
*
* where name is the name of the principal. Single quotes may be used
* instead of double quotes and special characters can be escaped using
* {@link escape} if required.
*
* The purpose of this property is to allow a client to create topics on
* behalf of other users. This can be used in conjunction with the
* {@link REMOVAL} property so that such topics are removed when there are
* no longer any sessions for the named principal.
*
* **Example:**
* ```
* specification.withProperty(diffusion.topics.TopicSpecification.OWNER,
* "$Principal is 'myPrincipal'")
* .withProperty(diffusion.topics.TopicSpecification.REMOVAL,
* "when no session has '$Principal is \"myPrincipal\"' for 5s");
* ```
*
* @since 6.1
*/
static readonly OWNER = "OWNER";
/**
* Key of the topic property that allows the compression policy to be set
* on a per-topic basis.
*
* Compression reduces the bandwidth required to broadcast topic updates to
* subscribed sessions, at the cost of increased server CPU.
*
* Changes to a topic's value are published to each subscribed session as a
* sequence of topic messages. A topic message can carry the latest value or
* the difference between the latest value and the previous value (a delta).
* The compression policy determines if and how published topic messages
* are compressed. Topic messages are not exposed through the client API;
* the client library handles decompression and decodes deltas
* automatically, passing reconstructed values to the application.
*
* The compression policy for a topic is specified by setting this property
* to one of several values:
*
* * `off`
* * `low`
* * `medium`
* * `high`
*
* The policies are listed in the order of increasing compression and
* increasing CPU cost. `off` disables compression completely for the
* topic and requires no additional CPU; `high` compresses the topic
* messages to the smallest number of bytes, but has the highest CPU cost.
* Generally some compression is beneficial, so the default value for this
* property is `low`.
*
* Prior to version 6.4, only two values were allowed: `true`
* (equivalent to `medium`, and the previous default policy) and
* `false` (equivalent to `off`). These values are still
* supported.
*
* This property is only one factor that determines whether a topic message
* will be compressed. Other factors include:
*
* * Compression must be enabled in the server configuration.
*
* * The client library must support the server's compression
* scheme. In this release, the server supports zlib
* compression, and also allows compression to be disabled on a
* per-connector basis. From 6.4, all client libraries are
* capable of zlib compression. A JavaScript client may or may
* not support zlib compression, depending on whether the zlib
* library can be loaded. The zlib library is packaged
* separately to reduce the download size of the core library.
*
* @since 6.2
*/
static readonly COMPRESSION = "COMPRESSION";
/**
* Key of the topic property that specifies the topic delivery priority.
*
* The supported delivery priorities are:
*
* * `low`
* * `default`
* * `high`
*
* The delivery priority affects the order of topic updates sent to a
* subscribed client session. When there are multiple topic updates for
* topics with different priorities in a session's outbound queue, updates
* for `high` priority topics will be delivered first, followed by
* updates for `default` priority topics, followed by updates for
* `low` priority topics. Topic subscription and unsubscription
* notifications are also delivered according to the topic delivery
* priority.
*
* Using different delivery priorities is most beneficial when there is a
* large backlog of queued updates to deliver to a client session. On
* lightly loaded systems, updates typically remain in the outbound queue
* for a few milliseconds and so there is a lower chance of topic updates
* being reordered based on their priority. The backlog will be larger if
* the topic update rate is higher; the server or the client are more
* heavily loaded; the client session becomes temporarily disconnected; or
* if there is poor network connectivity between the server and the client.
*
* Messages from the server to the client that are not topic updates, for
* example ping requests and responses, are queued with the
* `default` delivery priority.
*
* @since 6.4
*/
static readonly PRIORITY = "PRIORITY";
/**
* The topic type.
*/
type: TopicType;
/**
* A map of the topic properties.
*/
properties: {
[key: string]: string;
};
/**
* Create a new TopicSpecification
*
* @param type the topic type for this specification.
* @param properties the properties to use for this specification.
* @since 5.9
*
* **Example:**
*
* Properties can be set when creating the specification by passing an object
* ```
* // Create specification for JSON topics which validate update values on the server
* const TopicSpecification = diffusion.topics.TopicSpecification;
*
* var specification = new TopicSpecification(diffusion.topics.TopicType.JSON, {
* "VALIDATE_VALUES" : "true"
* });
* ```
*
* **Example:** New specifications can be created with additional properties
* ```
* // Create specification for JSON topics which validate update values on the server
* const TopicSpecification = diffusion.topics.TopicSpecification;
*
* var specification = new TopicSpecification(diffusion.topics.TopicType.JSON)
* .withProperty(TopicSpecification.VALIDATE_VALUES, "true");
* ```
*/
constructor(type: TopicType, properties?: {
[key: string]: string;
});
/**
* Returns a new TopicSpecification with the specified property set to the supplied value.
* @param key the new property key
* @param value the new property value
* @returns a new TopicSpecification with the specified property set.
*/
withProperty(key: string, value: string): TopicSpecification;
}
/**
* @module diffusion.topics
*/
/**
* A topic type
*
* Documentation of the TopicType values can be found under {@link TopicTypeEnum}.
*/
export declare class TopicType {
/**
* The topic type ID
*
* @deprecated since 6.5
*
* This property is deprecated and will be removed in the future.
*/
readonly id: number;
/**
* A flag indicating whether the topic type is stateful
*
* @deprecated since 6.5
*
* This flag is deprecated and will be removed in the future.
*/
readonly stateful: boolean;
/**
* A flag indicating whether the topic type is functional
*
* @deprecated since 6.5
*
* This flag is deprecated and will be removed in the future.
*/
readonly functional: boolean;
/**
* Create a new TopicType instance
*
* @deprecated since 6.5
*
* In the future, TopicType objects will be replaced by a string
* constants.
*
* @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;
};
/**
* Provide access to {@link TopicType TopicType},
* {@link TopicSpecification TopicSpecification}, and
* {@link UnsubscribeReason UnsubscribeReason}
* @namespace diffusion.topics
*
* @module diffusion.topics
*/
/**
* A type containing information about the reason for an unsubscription
*/
export declare class UnsubscribeReason {
/**
* The unsubscribe reason's id
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
readonly id?: number;
/**
* The unsubscribe reason's description
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
readonly reason: string;
/**
* Create a `UnsubscribeReason`
*
* @param id the unsubscribe reason's id
* @param reason the unsubscribe reason's description
*/
constructor(id: number | undefined, reason: string);
}
/**
* Enum containing reasons that an unsubscription occurred.
*
* **Example:**
* ```
* // Use UnsubscribeReason to validate unsubscription notifications
* session.addStream('>foo', diffusion.datatypes.string())
* .on('unsubscribe', function(topic, specification, reason) {
* switch (reason) {
* case diffusion.topics.UnsubscribeReason.REMOVED :
* // Do something if the topic was removed
* default :
* // Do something else if the client was explicitly unsubscribed
* }
* });
* ```
*/ export declare const UnsubscribeReasonEnum: {
[key: string]: UnsubscribeReason;
};
/**
* A type containing information about the reason for failure of an update
*/
export declare class UpdateFailReason {
/**
* The update fail reason's id
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
readonly id?: number;
/**
* The update fail reason's description
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
readonly reason: string;
/**
* Create a `UpdateFailReason`
*
* @param id the update fail reason's id
* @param reason the update fail reason's description
*/
constructor(id: number | undefined, reason: string);
}
/**
* The reason that a topic could not be updated.
*
* **Example:**
* ```
* session.topics.update('foo', 'bar').then(function() { ... }, function(err) {
* switch (err) {
* case diffusion.topics.UpdateFailReason.MISSING_TOPIC:
* ...
* case diffusion.topics.UpdateFailReason.EXCLUSIVE_UPDATER_CONFLICT:
* ...
* }
* });
* ```
*/ export declare const UpdateFailReasonEnum: {
[key: string]: UpdateFailReason;
};
/**
* A type containing information about the reason for failure of adding a topic
*/
export declare class TopicAddFailReason {
/**
* The topic add failure reason's id
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
readonly id?: number;
/**
* The topic add failure reason's description
*
* @deprecated since 6.8
*
* This member is deprecated and will be removed in the future.
*/
readonly reason: string;
/**
* Create a `TopicAddFailReason`
*
* @param id the topic add failure reason's id
* @param reason the topic add failure reason's description
*/
constructor(id: number | undefined, reason: string);
}
/**
* The reason that a topic could not be added.
*
* **Example:**
* ```
* session.topics.add('foo').then(function() { ... }, function(err) {
* switch (err) {
* case diffusion.topics.TopicAddFailReason.EXISTS:
* ...
* case diffusion.topics.TopicAddFailReason.INVALID_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.
*
* {@link Binary} values are created by passing a `Buffer` object to {@link
* Binary.from()}. When running the Diffusion Client in a browser context,
* access to the `Buffer` api is made available through {@link
* diffusion.buffer}.
*
* @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.
*
* When running the Diffusion Client in a browser context, access to the
* `Buffer` api is made available through {@link diffusion.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. When running the Diffusion Client in a browser context,
* access to the `Buffer` api is made available through {@link
* diffusion.buffer}.
*
* **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("9223372036854775807");
* ```
*
* @since 6.0
*/
export interface Int64 {
/**
* Read this value as a string.
*
* @param radix the radix to use. Defaults to base `10`.
* @return the string representation of the int64 value.
*/
toString(radix?: number): string;
/**
* Read this value as a number. The validity of the returned number can only be guaranteed for values up to
* `Math.pow(2, 53) - 1` due to underlying platform limitations of JavaScript.
*
* @return the numerical value of this int64, as a 53-bit integer.
*/
toNumber(): number;
}
/**
* @module diffusion.datatypes
*/
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
* const value = model.get("record", 0, "field", 0);
*
* // Get field value with key
* const value = model.get("Address.Name");
* ```
*
* @param recordKey the key addressing the record
* @param recordName the name of the record
* @param recordIndex the index of the record
* @param fieldName the name of the field
* @param fieldIndex the index of the field
* @return the field value
*/
get(recordName: string, recordIndex: number, fieldName: string, fieldIndex?: number): string | null;
get(recordName: string, fieldName: string, fieldIndex?: number): string | null;
get(recordKey: string): string | null;
/**
* Creates an immutable {@link RecordV2} object
* generated from the model.
*
* @return a new immutable instance
*/
asValue(): RecordV2;
/**
* Returns the actual number of occurrences of a named field within a
* specified record.
*
* For all but variable fields this simply returns the schema defined number
* of occurrences of the field.
*
* @param recordName the record name
* @param recordIndex the record index
* @param fieldName the field name
* @return the actual number of occurrences of the field
*/
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;