UNPKG

@actyx/sdk

Version:
1,225 lines (1,130 loc) 46.7 kB
import { Ord } from 'fp-ts/lib/Ord'; import * as t from 'io-ts'; declare type ActiveRequest = { serviceId: string; payload?: unknown; time: Date; }; declare type ActiveRequestGlobals = { all: () => ActiveRequest[]; [GlobalInternalSymbol]: { register: (sym: symbol, activeRequest: ActiveRequest) => unknown; unregister: (sym: symbol) => unknown; }; }; /** * Global object for accessing currently active requests * @public */ declare const activeRequests: ActiveRequestGlobals; /** Access all sorts of functionality related to the Actyx system! * @public */ export declare type Actyx = EventFns & { /** Id of the Actyx node this interface is connected to. */ readonly nodeId: NodeId; /** Fish snapshot store for the Pond * @beta */ readonly snapshotStore: SnapshotStore; /** Dispose of this Actyx connector, cancelling all ongoing subscriptions and freeing all underlying ressources. * @public */ dispose: () => void; /** Wait for the connected node to be in sync with the swarm. This is on a * best-effort basis and waits at most 30 seconds after the point in time the * node has been started. This can be used in order to reduce stale state * inside the application when started together with an Actyx node. * @public */ waitForSync: () => Promise<void>; /** * Obtain information on the Actyx node. In order to save some cycles, and because the information * doesn’t change all that quickly, please provide a time parameter that matches your app’s * freshness requirements — for human consumption a couple hundred milliseconds is good enough. * * The underlying API endpoint has been added in Actyx 2.5.0, earlier versions report dummy data. * * Starting with Actyx 2.15.0 the returned data also contains the swarm status as seen by this node. * * @public */ nodeInfo: (maxAgeMillis: number) => Promise<NodeInfo>; }; /** Function for creating `Actyx` instances. * @public */ export declare const Actyx: { /** Create an `Actyx` instance that talks to a running `Actyx` system. * @public */ of: (manifest: AppManifest, opts?: ActyxOpts) => Promise<Actyx>; /** * Create an `Actyx` instance that mocks all APIs within TypeScript. Useful for unit-tests. * Will not talk to other nodes, but rather that can be simulated via `directlyPushEvents`. * @public */ test: (opts?: ActyxTestOpts) => TestActyx; }; /** An event with its metadata. * @public */ export declare type ActyxEvent<E = unknown> = { meta: Metadata; payload: E; }; /** Things related to ActyxEvent. * @public */ export declare const ActyxEvent: { ord: Ord<ActyxEvent<unknown>>; }; /** Options used when creating a new `Actyx` instance. * @public */ export declare type ActyxOpts = { /** Host of the Actxy service. This defaults to localhost and should stay localhost in almost all cases. */ actyxHost?: string; /** API port of the Actyx service. Defaults to 4454. */ actyxPort?: number; /** Hook, when the connection to the store is closed */ onConnectionLost?: () => void; /** * Hook, when the connection to the store has been established. */ onConnectionEstablished?: () => void; }; /** Options used when creating a new TEST `Actyx` instance. * @public */ export declare type ActyxTestOpts = { /** Local node id to use * @public */ nodeId?: NodeId; /** Install the given time source for test purposes * @beta */ timeInjector?: TimeInjector; }; /** * A `Where` expression that selects all events. * @public */ export declare const allEvents: Tags<unknown>; /** * An Actyx app id. * @public */ export declare type AppId = string; /** * `AppId` associated functions. * @public */ export declare const AppId: { /** * Creates a AppId from a string */ of: (text: string) => AppId; }; /** Manifest describing an Actyx application. Used for authorizing API access. * @public */ export declare type AppManifest = { /** * Structured application id. * For testing and development purposes, you can always pass 'com.example.somestring' * For production, you will buy a license from Actyx for your specific app id like com.my-company.my-app. */ appId: string; /** Arbitrary string describing the app. */ displayName: string; /** Arbitrary version string */ version: string; /** Manifest signature, if it’s not an example app. */ signature?: string; }; /** AQL diagnostic output describing an error that occured during query evaluation. * @beta */ export declare type AqlDiagnosticMessage = { /** A problem occured */ type: 'diagnostic'; severity: string; message: string; }; /** AQL message conveying a raw event or a record created by mapping an event via SELECT. * @beta */ export declare type AqlEventMessage = { /** A simply-mapped event */ type: 'event'; /** Payload data generated by the AQL query via SELECT statements. */ payload: unknown; /** Metadata of the event that yielded this record. */ meta: Metadata; }; /** Future versions of AQL will know additional response message types. * @beta */ export declare type AqlFutureCompat = { /** Consult AQL documentation to find out about future available types. */ type: Exclude<'event' | 'offsets' | 'diagnostic', string>; payload: unknown; /** Consult AQL documentation to find out about future metadata contents. */ meta: Record<string, unknown>; }; /** AQL message describing the offsets at the current state of the response stream. * @beta */ export declare type AqlOffsetsMsg = { type: 'offsets'; offsets: OffsetMap; }; /** An aql query is either a plain string, or an object containing the string and the desired order. * @beta */ export declare type AqlQuery = string | { /** Query as AQL string */ query: string; /** Desired order of delivery (relative to events). Defaults to 'Asc' */ order?: EventsSortOrder; }; /** Response message returned by running AQL query. * @beta */ export declare type AqlResponse = AqlEventMessage | AqlOffsetsMsg | AqlDiagnosticMessage | AqlFutureCompat; /** Query for a set of events which is automatically capped at the latest available upperBound. * @public */ export declare type AutoCappedQuery = { /** * Starting point for the query. Everything up-to-and-including `lowerBound` will be omitted from the result. * Defaults to empty map, which means no lower bound at all. * Sources not listed in the `lowerBound` will be delivered in full. */ lowerBound?: OffsetMap; /** Statement to select specific events. Defaults to `allEvents`. */ query?: Where<unknown>; /** Desired order of delivery. Defaults to 'Asc' */ order?: EventsSortOrder; /** Earliest event ID to consider in the result */ horizon?: string; }; /** * Cancel an ongoing aggregation (the provided callback will stop being called). * @public */ export declare type CancelSubscription = () => void; /** Query for observeEarliest. * @beta */ export declare type EarliestQuery<E> = { /** Statement to select specific events. */ query: Where<E>; /** * Starting point for the query. Everything up-to-and-including `lowerBound` will be omitted from the result. * Defaults to empty map, which means no lower bound at all. * Sources not listed in the `lowerBound` will be delivered in full. */ lowerBound?: OffsetMap; /** The order to find min/max for. Defaults to `Lamport`. */ eventOrder?: EventOrder; }; declare class EnumType<A> extends t.Type<A> { readonly _tag: 'EnumType'; enumObject: object; constructor(e: object, name?: string); } /** * A chunk of events, with lower and upper bound. * A call to `queryKnownRange` with the included bounds is guaranteed to return exactly the contained set of events. * A call to `subscribe` with the included `lowerBound`, however, may find new events from sources not included in the bounds. * * @public */ export declare type EventChunk = { /** The event data. Sorting depends on the request which produced this chunk. */ events: ActyxEvent[]; /** The lower bound of the event chunk, independent of its sorting in memory. */ lowerBound: OffsetMap; /** The upper bound of the event chunk, independent of its sorting in memory. */ upperBound: OffsetMap; }; /** Functions that operate directly on Events. * @public */ export declare interface EventFns { /** Get the current local 'present' i.e. offsets up to which we can provide events without any gaps. */ present: () => Promise<OffsetMap>; /** Get the present alongside information on how many events are known to be pending replication from peers to us. */ offsets: () => Promise<OffsetsResponse>; /** * Get all known events between the given offsets, in one array. * * @param query - `RangeQuery` object specifying the desired set of events. * * @returns A Promise that resolves to the complete set of queries events. */ queryKnownRange: (query: RangeQuery) => Promise<ActyxEvent[]>; /** * Get all known events between the given offsets, in chunks. * This is helpful if the result set is too large to fit into memory all at once. * The returned `Promise` resolves after all chunks have been delivered. * * @param query - `RangeQuery` object specifying the desired set of events. * @param chunkSize - Maximum size of chunks. Chunks may be smaller than this. * @param onChunk - Callback that will be invoked with every chunk, in sequence. * * @returns A function that can be called in order to cancel the delivery of further chunks. */ queryKnownRangeChunked: (query: RangeQuery, chunkSize: number, onChunk: (chunk: EventChunk) => Promise<void> | void, onComplete?: OnCompleteOrErr) => CancelSubscription; /** * Query all known events that occured after the given `lowerBound`. * * @param query - `OpenEndedQuery` object specifying the desired set of events. * * @returns An `EventChunk` with the result and its bounds. * The contained `upperBound` can be passed as `lowerBound` to a subsequent call of this function to achieve exactly-once delivery of all events. */ queryAllKnown: (query: AutoCappedQuery) => Promise<EventChunk>; /** * Query all known events that occured after the given `lowerBound`, in chunks. * This is useful if the complete result set is potentially too large to fit into memory at once. * * @param query - `OpenEndedQuery` object specifying the desired set of events. * @param chunkSize - Maximum size of chunks. Chunks may be smaller than this. * @param onChunk - Callback that will be invoked for each chunk, in sequence. Second argument is an offset map covering all events passed as first arg. * * @returns A function that can be called in order to cancel the delivery of further chunks. */ queryAllKnownChunked: (query: AutoCappedQuery, chunkSize: number, onChunk: (chunk: EventChunk) => Promise<void> | void, onComplete?: OnCompleteOrErr) => CancelSubscription; /** * Run a custom AQL query and get back the raw responses collected. * * @param query - A plain AQL query string. * * @returns List of all response messages generated by the query. * * @beta */ queryAql: (query: AqlQuery) => Promise<AqlResponse[]>; /** * Run a custom AQL subscription and get back the raw responses collected via a callback. * * @param query - A plain AQL query string. * @param onResponse - Callback that will be invoked for each raw response, in sequence. Even if this is an async function (returning `Promise<void>`), there will be no concurrent invocations of it. * @param onError - Callback that will be invoked in case on a error. * @param lowerBound - Starting point (exclusive) for the query. Everything up-to-and-including `lowerBound` will be omitted from the result. Defaults empty record. * * @returns A `Promise` that resolves to updated offset-map after all chunks have been delivered. * * @beta */ subscribeAql: (query: AqlQuery, onResponse: (r: AqlResponse) => Promise<void> | void, onError?: (err: unknown) => void, lowerBound?: OffsetMap) => CancelSubscription; /** * Run a custom AQL query and get the response messages in chunks. * * @param query - AQL query * @param chunkSize - Desired chunk size * @param onChunk - Callback that will be invoked for each chunk, in sequence. Even if this is an async function (returning `Promise<void>`), there will be no concurrent invocations of it. * * @returns A function that can be called in order to cancel the delivery of further chunks. * * @beta */ queryAqlChunked: (query: AqlQuery, chunkSize: number, onChunk: (chunk: AqlResponse[]) => Promise<void> | void, onCompleteOrError: OnCompleteOrErr) => CancelSubscription; /** * Subscribe to all events fitting the `query` after `lowerBound`. * * The subscription goes on forever, until manually cancelled. * * @param query - `EventSubscription` object specifying the desired set of events. * @param onEvent - Callback that will be invoked for each event, in sequence. * * @returns A function that can be called in order to cancel the subscription. */ subscribe: (query: EventSubscription, onEvent: (e: ActyxEvent) => Promise<void> | void, onError?: (err: unknown) => void) => CancelSubscription; /** * Subscribe to all events fitting the `query` after `lowerBound`. * They will be delivered in chunks of configurable size. * Each chunk is internally sorted in ascending `eventId` order. * The subscription goes on forever, until manually cancelled. * * @param query - `EventSubscription` object specifying the desired set of events. * @param chunkConfig - How event chunks should be built. * @param onChunk - Callback that will be invoked for each chunk, in sequence. Second argument is the updated offset map. * * @returns A function that can be called in order to cancel the subscription. */ subscribeChunked: (query: EventSubscription, chunkConfig: { /** Maximum chunk size. Defaults to 1000. */ maxChunkSize?: number; /** * Maximum duration (in ms) a chunk of events is allowed to grow, before being passed to the callback. * Defaults to 5. */ maxChunkTimeMs?: number; }, onChunk: (chunk: EventChunk) => Promise<void> | void, onError?: (err: unknown) => void) => CancelSubscription; /** * Subscribe to a stream of events until this would go back in time. * Instead of going back in time, receive a TimeTravelMsg and terminate the stream. * * @alpha */ subscribeMonotonic: <E>(query: MonotonicSubscription<E>, callback: (data: EventsOrTimetravel<E>) => Promise<void> | void, onCompleteOrErr?: OnCompleteOrErr) => CancelSubscription; /** * Observe always the **earliest** event matching the given query. * If there is an existing event fitting the query, `onNewEarliest` will be called with that event. * Afterwards, `onNewEarliest` will be called whenever a new event becomes known that is older than the previously passed one. * Note that the 'earliest' event may keep updating as new events become known. * * @param query - Query to select the set of events. * @param onNewEarliest - Callback that will be invoked whenever there is a 'new' earliest event. * * @returns A function that can be called in order to cancel the subscription. * * @beta */ observeEarliest: <E>(query: EarliestQuery<E>, onNewEarliest: (event: E, metadata: Metadata) => void, onError?: (err: unknown) => void) => CancelSubscription; /** * Observe always the **latest** event matching the given query. * If there is an existing event fitting the query, `onNewLatest` will be called with that event. * Afterwards, `onNewLatest` will be called whenever a new event becomes known that is younger than the previously passed one. * * @param query - Query to select the set of events. * @param onNewLatest - Callback that will be invoked for each new latest event. * * @returns A function that can be called in order to cancel the subscription. * * @beta */ observeLatest: <E>(query: EarliestQuery<E>, onNewLatest: (event: E, metadata: Metadata) => void, onError?: (err: unknown) => void) => CancelSubscription; /** * Among all events matching the query, find one that best matches some property. * This is useful for finding the event that has `min` or `max` of something. * E.g. `shouldReplace = (candidate: ActyxEventy<number>, cur: ActyxEventy<number>) => candidate.payload > cur.payload` keeps finding the event with the highest payload value. * Note that there is no guarantee regarding the order in which candidates are passed to the callback! * If `shouldReplace(a, b)` returns true, the reversed call `shouldReplace(b, a)` should return false. Otherwise results may be wild. * * @param query - Query to select the set of `candidate` events. * @param shouldReplace - Should `candidate` replace `cur`? * @param onReplaced - Callback that is evoked whenever replacement happens, i.e. we found a new best match. * * @returns A function that can be called in order to cancel the subscription. */ observeBestMatch: <E>(query: Where<E>, shouldReplace: (candidate: ActyxEvent<E>, cur: ActyxEvent<E>) => boolean, onReplaced: (event: E, metadata: Metadata) => void, onError?: (err: unknown) => void) => CancelSubscription; /** * Apply a `reduce` operation to all events matching `query`, in no specific order. * This is useful for operations that are **commutative**, e.g. `sum` or `product`. * * @param query - Query to select the set of events to pass to the reducer. * @param reduce - Compute a new state `R` by integrating the next event. * @param initial - Initial, neutral state, e.g. `0` for a `sum` operation. * @param onUpdate - Callback that is evoked with updated results. * If a batch of events was applied, `onUpdate` will only be called once, with the final new state. * * @returns A function that can be called in order to cancel the subscription. */ observeUnorderedReduce: <R, E>(query: Where<E>, reduce: (acc: R, event: E, metadata: Metadata) => R, initial: R, onUpdate: (result: R) => void, onError?: (err: unknown) => void) => CancelSubscription; /** * Emit a number of events with tags attached. * * @param events - Events to emit. * * @returns A `PendingEmission` object that can be used to register callbacks with the emission’s completion. * * @deprecated Use `publish` instead, and always await the Promise. */ emit: (events: TaggedEvent[]) => PendingEmission; /** * Publish a number of events with tags attached. * This function is the same as `emit`, only it directly returns the Promise. * * @param events - Events to publish. * * @returns A Promise that resolves to the persisted event’s metadata, in the same order they were passed into the function. */ publish(event: TaggedEvent): Promise<Metadata>; publish(events: TaggedEvent[]): Promise<Metadata[]>; } /** * Triple that Actyx events are sorted and identified by. * * @public */ export declare type EventKey = { lamport: Lamport; offset: Offset; stream: StreamId; }; /** Functions related to EventKey. * @public */ export declare const EventKey: { zero: EventKey; ord: Ord<EventKey>; format: (key: EventKey) => string; }; /** Which clock to compare events by. Defaults to `Lamport`. * @beta */ export declare enum EventOrder { /** * Comparison according to Lamport clock, which is a logical clock, * meaning it preserves causal order even when wall clocks on devices are off. * * On the flip-side, for any two events where neither is a cause of the other, * lamport-order may be different from timestamp-order, if the devices creating the events * where disconnected from each other at the time. */ Lamport = "lamport", /** * Comparison according to wall clock time logged at event creation. * If the system clock on a device is wrong, the event's timestamp will also be wrong. */ Timestamp = "timestamp" } /** Implies consumer should apply the given events to its latest local state. * @alpha */ export declare type EventsMsg<E> = { type: MsgType.events; events: ActyxEvent<E>[]; caughtUp: boolean; }; /** Possible subscribe_monotonic message types. * @alpha */ export declare type EventsOrTimetravel<E> = StateMsg | EventsMsg<E> | TimeTravelMsg<E>; /** * Sort order for persisted events. * @public */ export declare enum EventsSortOrder { /** Strictly ascending, meaning events are strictly ordered by eventId. */ Ascending = "asc", /** Strictly descending, meaning events are strictly ordered by eventId, reverse. */ Descending = "desc", /** Ascending per stream, meaning between different streams there is no specific order guaranteed. */ StreamAscending = "stream-asc" } /** Subscription to a set of events that may still grow. * @public */ export declare type EventSubscription = { /** * Starting point for the query. Everything up-to-and-including `lowerBound` will be omitted from the result. * Defaults to empty map, which means no lower bound at all. * Sources not listed in the `lowerBound` will be delivered in full. */ lowerBound?: OffsetMap; /** Statement to select specific events. Defaults to `allEvents`. */ query?: Where<unknown>; }; /** * Sent by the client to indicate it wants event delivery to start from this point. * Implies that a state was cached in-process by the client and so it does not want to start from a snapshot known to Actyx. * @alpha */ export declare type FixedStart = { from: OffsetMap; latestEventKey: EventKey; horizon?: EventKey; }; declare const GlobalInternalSymbol: unique symbol; declare type GlobalInternalSymbol = typeof GlobalInternalSymbol; declare namespace globals { export { activeRequests } } export { globals } /** Anything with offset on a stream. * @public */ export declare type HasOffsetAndStream = { offset: number; stream: string; }; /** Anything that has tags. @alpha */ export declare type HasTags = { tags: string[]; }; /** The signature of the function to invalidate all stored snapshots. * @beta */ export declare type InvalidateAllSnapshots = () => Promise<void>; /** The signature of the function to invalidate snapshots for a given fish. * @beta */ export declare type InvalidateSnapshots = (semantics: string, name: string, key: EventKey) => Promise<void>; /** * Refinement that checks whether typeof x === 'number' * @public */ export declare const isBoolean: (x: any) => x is boolean; /** * Refinement that checks whether typeof x === 'number' * @public */ export declare const isNumber: (x: any) => x is number; /** * Refinement that checks whether typeof x === 'string' * @public */ export declare const isString: (x: any) => x is string; /** * Lamport timestamp, cf. https://en.wikipedia.org/wiki/Lamport_timestamp * @public */ export declare type Lamport = number; /** @public */ export declare const Lamport: { of: (value: number) => Lamport; zero: number; }; /** Query for observeLatest. * @beta */ export declare type LatestQuery<E> = EarliestQuery<E>; /** A local snapshot of state. * @beta */ export declare type LocalSnapshot<S> = StateWithProvenance<S> & { /** * eventKey of the last event according to event order that went into the state. * This can be used to detect shattering of the state due to time travel. */ eventKey: EventKey; /** * Oldest event key we are interested in. This is defined for a local snapshot * that is based on a semantic snapshot. All events before the semantic snapshot * that the local snapshot is based on are not relevant and can be discarded. * * Not discarding these events will lead to unnecessary shattering. */ horizon: EventKey | undefined; /** * Number of events since the beginning of time or the last semantic snapshot (which is * kind of the same thing as far as the fish is concerned). This can be used as a measure * how useful the snapshot is, and also for count-based snapshot scheduling */ cycle: number; }; /** The format of snapshots coming back from the store. * @beta */ export declare type LocalSnapshotFromIndex = LocalSnapshot<string>; /** Generic Metadata attached to every event. * @public */ export declare type Metadata = { isLocalEvent: boolean; tags: string[]; timestampMicros: Timestamp; timestampAsDate: () => Date; lamport: Lamport; eventId: string; appId: AppId; stream: StreamId; offset: Offset; }; /** Some number of milliseconds. * @public */ export declare type Milliseconds = number; /** Helper functions for making sense of and converting Milliseconds. * @public */ export declare const Milliseconds: { of: (time: number) => Milliseconds; fromDate: (date: Date) => Milliseconds; zero: number; now: (now?: number | undefined) => Milliseconds; toSeconds: (value: Milliseconds) => number; toTimestamp: (value: Milliseconds) => Timestamp; fromSeconds: (value: number) => number; fromMinutes: (value: number) => number; fromAny: (value: number) => Milliseconds; }; /** * Subscribe to a stream of events that will never go backwards in time, but rather terminate with a timetravel-message. * * @alpha */ export declare type MonotonicSubscription<E> = { /** User-chosen session id, used to find cached intermediate states aka local snapshots. */ sessionId: string; /** Statement to select specific events. */ query: Where<E>; /** Sending 'attemptStartFrom' means we DONT want a snapshot sent as initial message. */ attemptStartFrom: FixedStart; }; /** Possible subscribe_monotonic message types. * @alpha */ export declare enum MsgType { state = "state", events = "events", timetravel = "timetravel" } /** * An Actyx source id. * @public */ export declare type NodeId = string; /** * `SourceId` associated functions. * @public */ export declare const NodeId: { /** * Creates a NodeId from a string */ of: (text: string) => NodeId; /** * Creates a random SourceId with the given number of digits */ random: (digits?: number | undefined) => string; streamNo: (nodeId: NodeId, num: number) => string; }; /** * Information about the Actyx node this SDK is connected to. * * Instances are returned by `Pond.nodeInfo()`. * @public */ export declare class NodeInfo { private io; private semver; constructor(io: NodeInfo_2); /** * * @returns the full version string including git hash and CPU architecture */ longVersion(): string; /** * * @returns the semantic version part of the full version string, e.g. `2.6.1` */ semVer(): string; /** * * @param version - The version to compare with, in semantic version format `<major>.<minor>.<patch>` * @returns `true` if the reported Actyx version is greater than or equal to the supplied version */ isAtLeastVersion(version: string): boolean; /** * * @returns the uptime of the Actyx node in milliseconds */ uptimeMillis(): number; /** * * @returns the number of other nodes the Actyx node is currently connected to */ connectedNodes(): number; /** * * @returns information about the perceived connectivity of other nodes */ peersStatus(): Record<string, NodeStatus> | undefined; } declare const NodeInfo_2: t.TypeC<{ connectedNodes: t.NumberC; uptime: t.TypeC<{ secs: t.NumberC; nanos: t.NumberC; }>; version: t.StringC; swarmState: t.UnionC<[t.UndefinedC, t.TypeC<{ peersStatus: t.RecordC<t.Type<string, string, unknown>, EnumType<NodeStatus>>; }>]>; }>; declare type NodeInfo_2 = t.TypeOf<typeof NodeInfo_2>; /** * Status of another node as observed by the local node * @public */ export declare enum NodeStatus { /** * Replicates all streams within at most two gossip cycles */ LowLatency = "LowLatency", /** * Replicates all streams within at most five gossip cycles */ HighLatency = "HighLatency", /** * Replicates at least half of all streams within five gossip cycles */ PartiallyWorking = "PartiallyWorking", /** * Replicates less than half of all streams within five gossip cycles * * This state either means that the node is disconnected from our part of * the network or that it has been shut down or decommissioned. Old streams * will stay in the swarm in this state. */ NotWorking = "NotWorking" } /** Offset within an Actyx event stream. * @public */ export declare type Offset = number; /** Functions related to Offsets. * @public */ export declare const Offset: { of: (n: number) => Offset; zero: number; /** * A value that is below any valid Offset */ min: number; /** * A value that is above any valid Offset */ max: number; }; /** * A offset map stores the high water mark for each source. * * The value in the psn map is the highest psn seen for this source. Since sequence * numbers start with 0, the default value for sources that are not present is -1 * * @public */ export declare type OffsetMap = Record<StreamId, Offset>; /** OffsetMap companion functions. * @public */ export declare const OffsetMap: OffsetMapCompanion; /** * Relatively pointless attempt to distinguish between mutable and immutable psnmap * See https://github.com/Microsoft/TypeScript/issues/13347 for why this does not help much. * @public */ export declare type OffsetMapBuilder = Record<string, Offset>; /** OffsetMap companion functions. * @public */ export declare type OffsetMapCompanion = { empty: OffsetMap; isEmpty: (m: OffsetMap) => boolean; lookup: (m: OffsetMap, s: string) => Offset; lookupOrUndefined: (m: OffsetMap, s: string) => Offset | undefined; update: (m: OffsetMapBuilder, ev: HasOffsetAndStream) => OffsetMapBuilder; }; /** * Response to an offsets() call * @public */ export declare type OffsetsResponse = { /** The current local present, i.e. offsets up to which we can provide events without any gaps. */ present: OffsetMap; /** For each stream we still need to download events from, the number of pending events. */ toReplicate: Record<StreamId, number>; }; /** * Handler for a streaming operation ending, either normally or with an error. * If the `err` argument is defined, the operation completed due to an error. * Otherwise, it completed normally. * @public **/ export declare type OnCompleteOrErr = (err?: unknown) => void; /** * Allows you to register actions for when event emission has completed. * @public */ export declare type PendingEmission = { subscribe: (whenEmitted: (meta: Metadata[]) => void) => void; toPromise: () => Promise<Metadata[]>; }; /** Query for a fixed set of known events. * @public */ export declare type RangeQuery = { /** Statement to select specific events. Defaults to `allEvents`. */ query?: Where<unknown>; /** * Starting point (exclusive) for the query. Everything up-to-and-including `lowerBound` will be omitted from the result. Defaults empty record. * * Events from sources not included in the `lowerBound` will be delivered from start, IF they are included in `upperBound`. * Events from sources missing from both `lowerBound` and `upperBound` will not be delivered at all. */ lowerBound?: OffsetMap; /** * Ending point (inclusive) for the query. Everything covered by `upperBound` (inclusive) will be part of the result. * * If a source is not included in `upperBound`, its events will not be included in the result. **/ upperBound: OffsetMap; /** Desired order of delivery. Defaults to 'Asc' */ order?: EventsSortOrder; /** Earliest event ID to consider in the result */ horizon?: string; }; /** The signature of the function to retrieve a snapshot. * @beta */ export declare type RetrieveSnapshot = (semantics: string, name: string, version: number) => Promise<LocalSnapshotFromIndex | undefined>; /** A local snapshot where the state has already been serialised. * @beta */ export declare type SerializedStateSnap = LocalSnapshot<string>; /** * Interface to the snapshot store. * @beta */ export declare interface SnapshotStore { /** * Store local snapshot (best effort) * * @param version - For each semantics, the store is partitioned into versions corresponding to the snapshot format. * Only the newest known version should be kept. * * @param key - is the EventKey of the event from which the snapshot state was computed. * * @param tag - is a unique identifier for a given semantics, name, and version; it is used to ensure that only * one snapshot is kept for the a given interval (hour, day, month, year) * * @param psnMap - is needed to recognize whether the given snapshot has already been invalidated by the * root updates that have been performed between the one that triggered the snapshot computation and now * * @returns success if the snapshot was accepted, false if it was rejected due to using an old format * * A snapshot is out of date if between the event state it represents (as demonstrated by the given psnMap) * and the current index store state there have been root updates that would have invalidated the snapshot. * * Snapshots will not be validated against events on storage. The only validation that might happen is that * the format version is the latest. */ storeSnapshot: StoreSnapshot; /** * Retrieve local snapshot and its EventKey if it exists; undefined otherwise. * The method also returns the PsnMap from which the snapshot was calculated. * * Most of the time, snapshots returned by this method will be valid, meaning that all stored events with * larger psns than the snapshot also have larger event keys that the snapshot. * * However, this is not guaranteed. In very rare circumstances it is possible that there are stored events with * a psn above the snapshot psnMap, but an eventKey below the snapshot eventKey. In these cases, the snapshot * needs to be discarded, exactly as if there was a realtime event coming in with a smaller eventKey than * the snapshot. * * To be precise, invalid snapshots will happen only if the application crashes between the time events are added * at the store level (e.g. to the recvlog) and the time the events appear in the fishjar, triggering explicit * invalidation. This should be very rare, but still needs to be handled properly. */ retrieveSnapshot: RetrieveSnapshot; /** * Invalidate all snapshots for the fish identified by semantics and name that are at or above the given event key. * * @param semantics - semantics of the fish to invalidate snapshots for * @param name - name of the fish to invalidate snapshots for * @param eventKey - eventKey at or above which to purge snapshots * @returns a void promise that will complete once the snapshot invalidation is done in the persistence layer. */ invalidateSnapshots: InvalidateSnapshots; /** * Invalidate all snapshots * * @returns a void promise that will complete once the snapshot invalidation is done in the persistence layer. */ invalidateAllSnapshots: InvalidateAllSnapshots; } /** Interface to the snapshot store. * @beta */ export declare const SnapshotStore: { noop: SnapshotStore; inMem: () => SnapshotStore; }; /** Implies consumer should apply the given state. * @alpha */ export declare type StateMsg = { type: MsgType.state; snapshot: SerializedStateSnap; }; /** * A state and its corresponding psn map. * @beta */ export declare type StateWithProvenance<S> = { readonly state: S; /** * Minimum psn map that allow to reconstruct the state. * Only contains sources that contain events matching the filter. */ readonly offsets: OffsetMap; }; /** The signature of the function to store a snapshot. * @beta */ export declare type StoreSnapshot = (semantics: string, name: string, key: EventKey, offsets: OffsetMap, horizon: EventKey | undefined, cycle: number, version: number, tag: string, serializedBlob: string) => Promise<boolean>; /** * An Actyx stream id. * @public */ export declare type StreamId = string; /** * `SourceId` associated functions. * @public */ export declare const StreamId: { /** * Creates a StreamId from a string */ of: (text: string) => StreamId; /** * Creates a random StreamId off a random NodeId. */ random: () => string; }; /** * Representation of a single tag. * @public */ export declare interface Tag<E = unknown> extends Tags<E> { /** * Returns two tags: * * - this tag * - this tag suffixed with the given `name`, e.g. `Tag<RobotEvent>('robot').withId('robot500')` * expresses robot events belonging to a *specific* robot. The suffix will be separated * from the base name by a colon `:` like `robot:robot500`. * * The reason for preserving the base tag is to keep a notion of the whole event group, * and enable selection of it all without knowing every individual specific ID. */ withId(name: string): Tags<E>; /** * Returns the ID-specific variant of this particular tag, see also `withId`. * * Use this if you want to tag an event belonging to entity A with a specific identity of entity B. * For example an activity has been started by some user, so you may add * `activityTag.withId(activityId).and(userTag.id(userId))`; this would result in three tags. * * This returns a tag for arbitrary events (type `unknown`) because the base tag is omitted. */ id(name: string): Tags<unknown>; } /** * Create a new tag from the given string. * (Tag factory function. Call WITHOUT new, e.g. `const myTag = Tag<MyType>('my-tag')`) * * @param rawTagString - The raw tag string * @param extractId - If supplied, this function will be used to automatically call `withId` for events this tag is being attached to. * The automatism is disabled if there is a manual `withId` call. * @public */ export declare const Tag: <E = unknown>(rawTagString: string, extractId?: ((e: E) => string) | undefined) => Tag<E>; /** An event with tags attached. * @public */ export declare type TaggedEvent = { tags: string[]; event: unknown; }; /** A typed event with tags attached. * @public */ export declare interface TaggedTypedEvent<E = unknown> extends TaggedEvent { readonly tags: string[]; readonly event: E; withTags<E1>(tags: Tags<E1> & (E extends E1 ? unknown : never)): TaggedTypedEvent<E>; } /** * Selection of events based on required tags. `Tags('a', 'b')` will select all events that have tag 'a' *as well as* tag 'b'. * @public */ export declare interface Tags<E = unknown> extends Where<E> { /** * Add more tags to this requirement. E.g `Tag<FooEvent>('foo').and(Tag<BarEvent>('bar'))` will require both 'foo' and 'bar'. */ and<E1 = unknown>(tag: Tags<E1>): Tags<E1 & E>; /** * Add an additional untyped tag to this requirement. * Since there is no associated type, the overall type cannot be constrained further. */ and(tag: string): Tags<E>; /** * The same requirement, but matching only Events emitted by the very node the code is run on. * E.g. `Tags('my-tag').local()` selects all locally emitted events tagged with 'my-tag'. */ local(): Tags<E>; /** * Apply these tags to an event that they may legally be attached to (according to the tag's type `E`). */ apply(event: E): TaggedEvent; /** * Apply these tags to a list of events that they may legally be attached to. */ apply(...events: E[]): TaggedEvent[]; /** * Apply these tags to a list of events that match their type, and allow further tags to be added. */ applyTyped<E1 extends E>(event: E1): TaggedTypedEvent<E1>; } /** * Declare a set of tags. * This is a generator function to be called WITHOUT new, e.g. `const required = Tags('a', 'b', 'c')` * @public */ export declare const Tags: <E = unknown>(...requiredTags: string[]) => Tags<E>; /** * An instance of `Actyx` that is not talking to any Actyx instance, but mocks all functionality within TypeScript. * Very useful for unit-testing. * * @public */ export declare type TestActyx = TestEventFns & { /** Prented id of the underlying Actyx instance that actually is just simulated. */ readonly nodeId: NodeId; /** Fish snapshot store for the Pond * @beta */ readonly snapshotStore: SnapshotStore; /** For `TestActyx` instances, this method does nothing; it’s just there so all normal `Actyx` functions are provided. * @public */ dispose: () => void; waitForSync: () => Promise<void>; }; /** * A raw Actyx event to be emitted by the TestEventStore, as if it really arrived from the outside. * @public */ export declare type TestEvent = { offset: number; stream: string; timestamp: Timestamp; lamport: Lamport; tags: string[]; payload: unknown; }; /** EventFns for unit-tests. * @public */ export declare type TestEventFns = EventFns & { /** Inject an event as if it arrived from anywhere. * @public */ directlyPushEvents: (events: TestEvent[]) => void; }; /** * Test tool. * @beta */ export declare type TimeInjector = (tags: string[], events: unknown) => Timestamp; /** Timestamp (UNIX epoch), MICROseconds resolution. * @public */ export declare type Timestamp = number; /** Helper functions for making sense of and converting Timestamps. * @public */ export declare const Timestamp: { of: (time: number) => Timestamp; zero: number; maxSafe: number; now: (now?: number | undefined) => number; format: (timestamp: Timestamp) => string; toSeconds: (value: Timestamp) => number; toMilliseconds: (value: Timestamp) => Milliseconds; toDate: (value: Timestamp) => Date; fromDate: (date: Date) => Timestamp; fromDays: (value: number) => number; fromSeconds: (value: number) => number; fromMilliseconds: (value: number) => number; min: (...values: Timestamp[]) => number; max: (values: Timestamp[]) => number; }; /** Implies consumer should re-subscribe starting from `trigger` or earlier. * @alpha */ export declare type TimeTravelMsg<E> = { type: MsgType.timetravel; trigger: EventKey; }; /** * Turn a `Where` into a function that can decide whether a locally emitted event matches the clause. * * We can ignore the 'local' flag since it will never exclude our local events, * and this method is used solely to decide whether locally emitted events are relevant. * * TODO: This will be removed once we support other means of 'I got events up to X' feedback * * @alpha */ export declare const toEventPredicate: (where: Where<unknown>) => (event: HasTags) => boolean; /** * Representation of a union of tag sets. I.e. this is an event selection that combines multiple `Tags` selections. * @public */ export declare interface Where<E> { /** * Add an alternative set we may also match. E.g. tag0.or(tag1.and(tag2)).or(tag1.and(tag3)) will match: * Events with tag0; Events with both tag1 and tag2; Events with both tag1 and tag3. */ or<E1>(tag: Where<E1>): Where<E1 | E>; /** * Type of the Events which may be returned by the contained tags. * Note that this does reflect only locally declared type knowledge; * historic events delivered by the Actyx system may not match these types, and this is not automatically detected. * It is therefore good practice to carefully review changes to the declared type so that they remain * backwards compatible. */ readonly _dataType?: E; /** * Convert to an Actyx Event Service query string. */ toString(): string; } export { }