abxbus 2.4.29 → 2.4.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -1
- package/dist/cjs/EventBus.d.ts +5 -1
- package/dist/cjs/EventBus.js +20 -7
- package/dist/cjs/EventBus.js.map +2 -2
- package/dist/cjs/EventHistory.d.ts +5 -0
- package/dist/cjs/EventHistory.js +32 -5
- package/dist/cjs/EventHistory.js.map +2 -2
- package/dist/cjs/TachyonEventBridge.d.ts +25 -0
- package/dist/cjs/TachyonEventBridge.js +427 -0
- package/dist/cjs/TachyonEventBridge.js.map +7 -0
- package/dist/cjs/base_event.d.ts +2 -2
- package/dist/cjs/bridges.d.ts +1 -0
- package/dist/cjs/bridges.js +3 -1
- package/dist/cjs/bridges.js.map +2 -2
- package/dist/cjs/event_handler.d.ts +0 -1
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/types.d.ts +3 -0
- package/dist/cjs/types.js.map +2 -2
- package/dist/esm/EventBus.js +20 -7
- package/dist/esm/EventBus.js.map +2 -2
- package/dist/esm/EventHistory.js +32 -5
- package/dist/esm/EventHistory.js.map +2 -2
- package/dist/esm/TachyonEventBridge.js +406 -0
- package/dist/esm/TachyonEventBridge.js.map +7 -0
- package/dist/esm/bridges.js +3 -1
- package/dist/esm/bridges.js.map +2 -2
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/types.js.map +2 -2
- package/dist/types/EventBus.d.ts +5 -1
- package/dist/types/EventHistory.d.ts +5 -0
- package/dist/types/TachyonEventBridge.d.ts +25 -0
- package/dist/types/base_event.d.ts +2 -2
- package/dist/types/bridges.d.ts +1 -0
- package/dist/types/event_handler.d.ts +0 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types.d.ts +3 -0
- package/package.json +26 -20
- package/src/EventBus.ts +38 -10
- package/src/EventHistory.ts +47 -4
- package/src/TachyonEventBridge.ts +498 -0
- package/src/bridges.ts +1 -0
- package/src/index.ts +10 -2
- package/src/types.ts +2 -0
- package/dist/cjs/bridge_ipc.d.ts +0 -45
- package/dist/cjs/middleware_otel_tracing.d.ts +0 -49
- package/dist/types/bridge_ipc.d.ts +0 -45
- package/dist/types/middleware_otel_tracing.d.ts +0 -49
package/dist/types/EventBus.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { EventResult } from './EventResult.js';
|
|
|
4
4
|
import { AsyncLock, type EventConcurrencyMode, type EventHandlerConcurrencyMode, type EventHandlerCompletionMode, LockManager } from './LockManager.js';
|
|
5
5
|
import { EventHandler, type EphemeralFindEventHandler, type EventHandlerJSON } from './EventHandler.js';
|
|
6
6
|
import type { EventBusMiddleware, EventBusMiddlewareInput } from './EventBusMiddleware.js';
|
|
7
|
-
import type { EventClass, EventHandlerCallable, EventPattern, FindOptions, UntypedEventHandlerFunction } from './types.js';
|
|
7
|
+
import type { EventClass, EventHandlerCallable, EventPattern, FilterOptions, FindOptions, UntypedEventHandlerFunction } from './types.js';
|
|
8
8
|
export type EventBusOptions = {
|
|
9
9
|
id?: string;
|
|
10
10
|
max_history_size?: number | null;
|
|
@@ -104,6 +104,10 @@ export declare class EventBus {
|
|
|
104
104
|
find(event_pattern: '*', where: (event: BaseEvent) => boolean, options?: FindOptions<BaseEvent>): Promise<BaseEvent | null>;
|
|
105
105
|
find<T extends BaseEvent>(event_pattern: EventPattern<T>, options?: FindOptions<T>): Promise<T | null>;
|
|
106
106
|
find<T extends BaseEvent>(event_pattern: EventPattern<T>, where: (event: T) => boolean, options?: FindOptions<T>): Promise<T | null>;
|
|
107
|
+
filter(event_pattern: '*', options?: FilterOptions<BaseEvent>): Promise<BaseEvent[]>;
|
|
108
|
+
filter(event_pattern: '*', where: (event: BaseEvent) => boolean, options?: FilterOptions<BaseEvent>): Promise<BaseEvent[]>;
|
|
109
|
+
filter<T extends BaseEvent>(event_pattern: EventPattern<T>, options?: FilterOptions<T>): Promise<T[]>;
|
|
110
|
+
filter<T extends BaseEvent>(event_pattern: EventPattern<T>, where: (event: T) => boolean, options?: FilterOptions<T>): Promise<T[]>;
|
|
107
111
|
private _waitForFutureMatch;
|
|
108
112
|
waitUntilIdle(timeout?: number | null): Promise<boolean>;
|
|
109
113
|
isIdle(): boolean;
|
|
@@ -7,6 +7,9 @@ export type EventHistoryFindOptions = {
|
|
|
7
7
|
event_is_child_of?: (event: BaseEvent, ancestor: BaseEvent) => boolean;
|
|
8
8
|
wait_for_future_match?: (event_pattern: string | '*', matches: (event: BaseEvent) => boolean, future: FindWindow) => Promise<BaseEvent | null>;
|
|
9
9
|
} & Record<string, unknown>;
|
|
10
|
+
export type EventHistoryFilterOptions = EventHistoryFindOptions & {
|
|
11
|
+
limit?: number | null;
|
|
12
|
+
};
|
|
10
13
|
export type EventHistoryTrimOptions<TEvent extends BaseEvent = BaseEvent> = {
|
|
11
14
|
is_event_complete?: (event: TEvent) => boolean;
|
|
12
15
|
on_remove?: (event: TEvent) => void;
|
|
@@ -40,6 +43,8 @@ export declare class EventHistory<TEvent extends BaseEvent = BaseEvent> implemen
|
|
|
40
43
|
static normalizeEventPattern(event_pattern: EventPattern | '*'): string | '*';
|
|
41
44
|
find(event_pattern: '*', where?: (event: TEvent) => boolean, options?: EventHistoryFindOptions): Promise<TEvent | null>;
|
|
42
45
|
find<TMatch extends TEvent>(event_pattern: EventPattern<TMatch>, where?: (event: TMatch) => boolean, options?: EventHistoryFindOptions): Promise<TMatch | null>;
|
|
46
|
+
filter(event_pattern: '*', where?: (event: TEvent) => boolean, options?: EventHistoryFilterOptions): Promise<TEvent[]>;
|
|
47
|
+
filter<TMatch extends TEvent>(event_pattern: EventPattern<TMatch>, where?: (event: TMatch) => boolean, options?: EventHistoryFilterOptions): Promise<TMatch[]>;
|
|
43
48
|
trimEventHistory(options?: EventHistoryTrimOptions<TEvent>): number;
|
|
44
49
|
private eventIsChildOf;
|
|
45
50
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BaseEvent } from './BaseEvent.js';
|
|
2
|
+
import type { EventClass, EventHandlerCallable, UntypedEventHandlerFunction } from './types.js';
|
|
3
|
+
export declare class TachyonEventBridge {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly capacity: number;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
private readonly inbound_bus;
|
|
8
|
+
private listener_worker;
|
|
9
|
+
private acted_as_listener;
|
|
10
|
+
private listener_startup_error;
|
|
11
|
+
private sender_worker;
|
|
12
|
+
private sender_ready_promise;
|
|
13
|
+
private send_seq;
|
|
14
|
+
private pending_sends;
|
|
15
|
+
private closed;
|
|
16
|
+
constructor(path: string, capacity?: number, name?: string);
|
|
17
|
+
on<T extends BaseEvent>(event_pattern: EventClass<T>, handler: EventHandlerCallable<T>): void;
|
|
18
|
+
on<T extends BaseEvent>(event_pattern: string | '*', handler: UntypedEventHandlerFunction<T>): void;
|
|
19
|
+
emit<T extends BaseEvent>(event: T): Promise<void>;
|
|
20
|
+
dispatch<T extends BaseEvent>(event: T): Promise<void>;
|
|
21
|
+
start(): Promise<void>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
private ensureListenerStarted;
|
|
24
|
+
private ensureSenderConnected;
|
|
25
|
+
}
|
|
@@ -27,7 +27,7 @@ export declare const BaseEventSchema: z.ZodObject<{
|
|
|
27
27
|
}>>;
|
|
28
28
|
event_started_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
29
29
|
event_completed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
30
|
-
event_results: z.ZodOptional<z.
|
|
30
|
+
event_results: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
31
31
|
event_concurrency: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
32
32
|
"global-serial": "global-serial";
|
|
33
33
|
"bus-serial": "bus-serial";
|
|
@@ -133,7 +133,7 @@ export declare class BaseEvent {
|
|
|
133
133
|
}>>;
|
|
134
134
|
event_started_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
135
135
|
event_completed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
136
|
-
event_results: z.ZodOptional<z.
|
|
136
|
+
event_results: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
137
137
|
event_concurrency: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
138
138
|
"global-serial": "global-serial";
|
|
139
139
|
"bus-serial": "bus-serial";
|
package/dist/types/bridges.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export { SQLiteEventBridge } from './SQLiteEventBridge.js';
|
|
|
7
7
|
export { NATSEventBridge } from './NATSEventBridge.js';
|
|
8
8
|
export { RedisEventBridge } from './RedisEventBridge.js';
|
|
9
9
|
export { PostgresEventBridge } from './PostgresEventBridge.js';
|
|
10
|
+
export { TachyonEventBridge } from './TachyonEventBridge.js';
|
|
@@ -61,7 +61,6 @@ export declare class EventHandler {
|
|
|
61
61
|
eventbus_id: string;
|
|
62
62
|
});
|
|
63
63
|
get _handler_async(): EventHandlerCallable;
|
|
64
|
-
static handlerNameFromCallable(handler: EventHandlerCallable): string;
|
|
65
64
|
static computeHandlerId(params: {
|
|
66
65
|
eventbus_id: string;
|
|
67
66
|
handler_name: string;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { BaseEvent, BaseEventSchema } from './BaseEvent.js';
|
|
2
2
|
export { EventHistory } from './EventHistory.js';
|
|
3
|
-
export type { EventHistoryFindOptions, EventHistoryTrimOptions } from './EventHistory.js';
|
|
3
|
+
export type { EventHistoryFilterOptions, EventHistoryFindOptions, EventHistoryTrimOptions } from './EventHistory.js';
|
|
4
4
|
export { EventResult } from './EventResult.js';
|
|
5
5
|
export { EventBus } from './EventBus.js';
|
|
6
6
|
export type { EventBusJSON, EventBusOptions } from './EventBus.js';
|
|
@@ -14,7 +14,7 @@ export type { EventBusMiddleware, EventBusMiddlewareCtor, EventBusMiddlewareInpu
|
|
|
14
14
|
export { monotonicDatetime } from './helpers.js';
|
|
15
15
|
export { EventHandlerTimeoutError, EventHandlerCancelledError, EventHandlerAbortedError, EventHandlerResultSchemaError, } from './EventHandler.js';
|
|
16
16
|
export type { EventConcurrencyMode, EventHandlerConcurrencyMode, EventHandlerCompletionMode, EventBusInterfaceForLockManager, } from './LockManager.js';
|
|
17
|
-
export type { EventClass, EventHandlerCallable as EventHandler, EventPattern, EventStatus, FindOptions, FindWindow } from './types.js';
|
|
17
|
+
export type { EventClass, EventHandlerCallable as EventHandler, EventPattern, EventStatus, FilterOptions, FindOptions, FindWindow, } from './types.js';
|
|
18
18
|
export { retry, clearSemaphoreRegistry, RetryTimeoutError, SemaphoreTimeoutError } from './retry.js';
|
|
19
19
|
export type { RetryOptions } from './retry.js';
|
|
20
20
|
export { events_suck } from './events_suck.js';
|
package/dist/types/types.d.ts
CHANGED
|
@@ -26,6 +26,9 @@ export type FindOptions<T extends BaseEvent = BaseEvent> = {
|
|
|
26
26
|
future?: FindWindow;
|
|
27
27
|
child_of?: BaseEvent | null;
|
|
28
28
|
} & EventFilterFields<T> & Record<string, unknown>;
|
|
29
|
+
export type FilterOptions<T extends BaseEvent = BaseEvent> = FindOptions<T> & {
|
|
30
|
+
limit?: number | null;
|
|
31
|
+
};
|
|
29
32
|
export declare const normalizeEventPattern: (event_pattern: EventPattern | "*") => string | "*";
|
|
30
33
|
export declare const isZodSchema: (value: unknown) => value is z.ZodTypeAny;
|
|
31
34
|
export declare const eventResultTypeFromConstructor: (value: unknown) => z.ZodTypeAny | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abxbus",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.30",
|
|
4
4
|
"description": "Event bus library for browsers and ESM Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -46,35 +46,38 @@
|
|
|
46
46
|
"author": "",
|
|
47
47
|
"license": "MIT",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"uuid": "^
|
|
50
|
-
"zod": "^4.3
|
|
49
|
+
"uuid": "^14.0.0",
|
|
50
|
+
"zod": "^4.4.3"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@opentelemetry/api": "^1.9.1",
|
|
54
|
-
"@opentelemetry/exporter-trace-otlp-http": "^0.
|
|
55
|
-
"@opentelemetry/resources": "^2.7.
|
|
56
|
-
"@opentelemetry/sdk-trace-base": "^2.7.
|
|
57
|
-
"@
|
|
58
|
-
"@
|
|
59
|
-
"@typescript-eslint/
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
54
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.217.0",
|
|
55
|
+
"@opentelemetry/resources": "^2.7.1",
|
|
56
|
+
"@opentelemetry/sdk-trace-base": "^2.7.1",
|
|
57
|
+
"@tachyon-ipc/core": "^0.5.0",
|
|
58
|
+
"@types/node": "^25.6.1",
|
|
59
|
+
"@typescript-eslint/eslint-plugin": "^8.59.2",
|
|
60
|
+
"@typescript-eslint/parser": "^8.59.2",
|
|
61
|
+
"cmake-js": "^8.0.0",
|
|
62
|
+
"esbuild": "^0.28.0",
|
|
63
|
+
"eslint": "^10.3.0",
|
|
64
|
+
"ioredis": "^5.10.1",
|
|
63
65
|
"nats": "^2.29.3",
|
|
64
|
-
"pg": "^8.
|
|
65
|
-
"prettier": "^3.8.
|
|
66
|
+
"pg": "^8.20.0",
|
|
67
|
+
"prettier": "^3.8.3",
|
|
66
68
|
"tsc-files": "^1.1.4",
|
|
67
69
|
"tsx": "^4.21.0",
|
|
68
|
-
"typescript": "^
|
|
70
|
+
"typescript": "^6.0.3"
|
|
69
71
|
},
|
|
70
72
|
"peerDependencies": {
|
|
71
73
|
"@opentelemetry/api": "^1.9.1",
|
|
72
|
-
"@opentelemetry/exporter-trace-otlp-http": "^0.
|
|
73
|
-
"@opentelemetry/resources": "^2.7.
|
|
74
|
-
"@opentelemetry/sdk-trace-base": "^2.7.
|
|
75
|
-
"
|
|
74
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.217.0",
|
|
75
|
+
"@opentelemetry/resources": "^2.7.1",
|
|
76
|
+
"@opentelemetry/sdk-trace-base": "^2.7.1",
|
|
77
|
+
"@tachyon-ipc/core": "^0.5.0",
|
|
78
|
+
"ioredis": "^5.10.1",
|
|
76
79
|
"nats": "^2.29.3",
|
|
77
|
-
"pg": "^8.
|
|
80
|
+
"pg": "^8.20.0"
|
|
78
81
|
},
|
|
79
82
|
"peerDependenciesMeta": {
|
|
80
83
|
"@opentelemetry/api": {
|
|
@@ -89,6 +92,9 @@
|
|
|
89
92
|
"@opentelemetry/sdk-trace-base": {
|
|
90
93
|
"optional": true
|
|
91
94
|
},
|
|
95
|
+
"@tachyon-ipc/core": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
92
98
|
"ioredis": {
|
|
93
99
|
"optional": true
|
|
94
100
|
},
|
package/src/EventBus.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { v7 as uuidv7 } from 'uuid'
|
|
|
24
24
|
import { monotonicDatetime } from './helpers.js'
|
|
25
25
|
|
|
26
26
|
import { normalizeEventPattern } from './types.js'
|
|
27
|
-
import type { EventClass, EventHandlerCallable, EventPattern, FindOptions, UntypedEventHandlerFunction } from './types.js'
|
|
27
|
+
import type { EventClass, EventHandlerCallable, EventPattern, FilterOptions, FindOptions, UntypedEventHandlerFunction } from './types.js'
|
|
28
28
|
|
|
29
29
|
export type EventBusOptions = {
|
|
30
30
|
id?: string
|
|
@@ -782,16 +782,39 @@ export class EventBus {
|
|
|
782
782
|
): Promise<T | null> {
|
|
783
783
|
const where = typeof where_or_options === 'function' ? where_or_options : () => true
|
|
784
784
|
const options = typeof where_or_options === 'function' ? maybe_options : where_or_options
|
|
785
|
-
|
|
785
|
+
// `limit` field-equality filter would collide with filter()'s cap arg; route it through `where`.
|
|
786
|
+
let effective_where = where
|
|
787
|
+
let effective_options: FindOptions<T> = options
|
|
788
|
+
if (Object.prototype.hasOwnProperty.call(options, 'limit')) {
|
|
789
|
+
const { limit: limit_field_value, ...rest } = options as FindOptions<T> & { limit: unknown }
|
|
790
|
+
const inner_where = where
|
|
791
|
+
effective_where = (event: T) => (event as unknown as Record<string, unknown>).limit === limit_field_value && inner_where(event)
|
|
792
|
+
effective_options = rest as unknown as FindOptions<T>
|
|
793
|
+
}
|
|
794
|
+
const results = await this.filter(event_pattern as EventPattern<T> | '*', effective_where, { ...effective_options, limit: 1 })
|
|
795
|
+
return results.length > 0 ? results[0] : null
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// same as find() but returns the list of all matching events (newest to oldest)
|
|
799
|
+
// optional `limit` arg caps the number of results returned
|
|
800
|
+
filter(event_pattern: '*', options?: FilterOptions<BaseEvent>): Promise<BaseEvent[]>
|
|
801
|
+
filter(event_pattern: '*', where: (event: BaseEvent) => boolean, options?: FilterOptions<BaseEvent>): Promise<BaseEvent[]>
|
|
802
|
+
filter<T extends BaseEvent>(event_pattern: EventPattern<T>, options?: FilterOptions<T>): Promise<T[]>
|
|
803
|
+
filter<T extends BaseEvent>(event_pattern: EventPattern<T>, where: (event: T) => boolean, options?: FilterOptions<T>): Promise<T[]>
|
|
804
|
+
async filter<T extends BaseEvent>(
|
|
805
|
+
event_pattern: EventPattern<T> | '*',
|
|
806
|
+
where_or_options: ((event: T) => boolean) | FilterOptions<T> = {},
|
|
807
|
+
maybe_options: FilterOptions<T> = {}
|
|
808
|
+
): Promise<T[]> {
|
|
809
|
+
const where = typeof where_or_options === 'function' ? where_or_options : () => true
|
|
810
|
+
const options = typeof where_or_options === 'function' ? maybe_options : where_or_options
|
|
811
|
+
const matches = await this.event_history.filter(event_pattern as EventPattern<T> | '*', where, {
|
|
786
812
|
...options,
|
|
787
813
|
event_is_child_of: (event, ancestor) => this.eventIsChildOf(event, ancestor),
|
|
788
|
-
wait_for_future_match: (normalized_event_pattern,
|
|
789
|
-
this._waitForFutureMatch(normalized_event_pattern,
|
|
814
|
+
wait_for_future_match: (normalized_event_pattern, matches_fn, future) =>
|
|
815
|
+
this._waitForFutureMatch(normalized_event_pattern, matches_fn, future),
|
|
790
816
|
})
|
|
791
|
-
|
|
792
|
-
return null
|
|
793
|
-
}
|
|
794
|
-
return this._getEventProxyScopedToThisBus(match) as T
|
|
817
|
+
return matches.map((match) => this._getEventProxyScopedToThisBus(match) as T)
|
|
795
818
|
}
|
|
796
819
|
|
|
797
820
|
private async _waitForFutureMatch(
|
|
@@ -1000,8 +1023,13 @@ export class EventBus {
|
|
|
1000
1023
|
original_event.event_blocks_parent_completion = true
|
|
1001
1024
|
}
|
|
1002
1025
|
|
|
1003
|
-
//
|
|
1004
|
-
|
|
1026
|
+
// Serial event modes need the runloop paused while the queue-jumped child
|
|
1027
|
+
// runs so queued siblings cannot overshoot the suspended parent handler.
|
|
1028
|
+
// Parallel events have no event lock, so pausing here would incorrectly
|
|
1029
|
+
// block later parallel work emitted by the same parent.
|
|
1030
|
+
if (this.locks.getLockForEvent(original_event) !== null) {
|
|
1031
|
+
currently_active_event_result._ensureQueueJumpPause(this)
|
|
1032
|
+
}
|
|
1005
1033
|
if (original_event.event_status === 'completed') {
|
|
1006
1034
|
return event
|
|
1007
1035
|
}
|
package/src/EventHistory.ts
CHANGED
|
@@ -15,6 +15,8 @@ export type EventHistoryFindOptions = {
|
|
|
15
15
|
) => Promise<BaseEvent | null>
|
|
16
16
|
} & Record<string, unknown>
|
|
17
17
|
|
|
18
|
+
export type EventHistoryFilterOptions = EventHistoryFindOptions & { limit?: number | null }
|
|
19
|
+
|
|
18
20
|
export type EventHistoryTrimOptions<TEvent extends BaseEvent = BaseEvent> = {
|
|
19
21
|
is_event_complete?: (event: TEvent) => boolean
|
|
20
22
|
on_remove?: (event: TEvent) => void
|
|
@@ -109,13 +111,45 @@ export class EventHistory<TEvent extends BaseEvent = BaseEvent> implements Itera
|
|
|
109
111
|
where: (event: TEvent) => boolean = () => true,
|
|
110
112
|
options: EventHistoryFindOptions = {}
|
|
111
113
|
): Promise<TEvent | null> {
|
|
114
|
+
// `limit` field-equality filter would collide with filter()'s cap arg; route it through `where`.
|
|
115
|
+
let effective_where = where
|
|
116
|
+
let effective_options: EventHistoryFindOptions = options
|
|
117
|
+
if (Object.prototype.hasOwnProperty.call(options, 'limit')) {
|
|
118
|
+
const { limit: limit_field_value, ...rest } = options as EventHistoryFindOptions & { limit: unknown }
|
|
119
|
+
const inner_where = where
|
|
120
|
+
effective_where = (event: TEvent) => (event as unknown as Record<string, unknown>).limit === limit_field_value && inner_where(event)
|
|
121
|
+
effective_options = rest as EventHistoryFindOptions
|
|
122
|
+
}
|
|
123
|
+
const results = await this.filter(event_pattern as EventPattern<TEvent> | '*', effective_where, {
|
|
124
|
+
...effective_options,
|
|
125
|
+
limit: 1,
|
|
126
|
+
})
|
|
127
|
+
return results.length > 0 ? results[0] : null
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
filter(event_pattern: '*', where?: (event: TEvent) => boolean, options?: EventHistoryFilterOptions): Promise<TEvent[]>
|
|
131
|
+
filter<TMatch extends TEvent>(
|
|
132
|
+
event_pattern: EventPattern<TMatch>,
|
|
133
|
+
where?: (event: TMatch) => boolean,
|
|
134
|
+
options?: EventHistoryFilterOptions
|
|
135
|
+
): Promise<TMatch[]>
|
|
136
|
+
async filter(
|
|
137
|
+
event_pattern: EventPattern<TEvent> | '*',
|
|
138
|
+
where: (event: TEvent) => boolean = () => true,
|
|
139
|
+
options: EventHistoryFilterOptions = {}
|
|
140
|
+
): Promise<TEvent[]> {
|
|
112
141
|
const past = options.past ?? true
|
|
113
142
|
const future = options.future ?? false
|
|
114
143
|
const child_of = options.child_of ?? null
|
|
115
144
|
const eventIsChildOf = options.event_is_child_of ?? ((event: BaseEvent, ancestor: BaseEvent) => this.eventIsChildOf(event, ancestor))
|
|
116
145
|
const waitForFutureMatch = options.wait_for_future_match
|
|
146
|
+
const limit = options.limit ?? null
|
|
117
147
|
if (past === false && future === false) {
|
|
118
|
-
return
|
|
148
|
+
return []
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (limit !== null && limit <= 0) {
|
|
152
|
+
return []
|
|
119
153
|
}
|
|
120
154
|
|
|
121
155
|
const event_key = EventHistory.normalizeEventPattern(event_pattern)
|
|
@@ -128,6 +162,7 @@ export class EventHistory<TEvent extends BaseEvent = BaseEvent> implements Itera
|
|
|
128
162
|
key !== 'child_of' &&
|
|
129
163
|
key !== 'event_is_child_of' &&
|
|
130
164
|
key !== 'wait_for_future_match' &&
|
|
165
|
+
key !== 'limit' &&
|
|
131
166
|
value !== undefined
|
|
132
167
|
)
|
|
133
168
|
|
|
@@ -137,6 +172,7 @@ export class EventHistory<TEvent extends BaseEvent = BaseEvent> implements Itera
|
|
|
137
172
|
event_field_filters.every(([field_name, expected]) => (event as unknown as Record<string, unknown>)[field_name] === expected) &&
|
|
138
173
|
where(event as TEvent)
|
|
139
174
|
|
|
175
|
+
const results: TEvent[] = []
|
|
140
176
|
if (past !== false) {
|
|
141
177
|
const history_values = Array.from(this._events.values())
|
|
142
178
|
for (let i = history_values.length - 1; i >= 0; i -= 1) {
|
|
@@ -145,16 +181,23 @@ export class EventHistory<TEvent extends BaseEvent = BaseEvent> implements Itera
|
|
|
145
181
|
continue
|
|
146
182
|
}
|
|
147
183
|
if (matches(event)) {
|
|
148
|
-
|
|
184
|
+
results.push(event)
|
|
185
|
+
if (limit !== null && results.length >= limit) {
|
|
186
|
+
return results
|
|
187
|
+
}
|
|
149
188
|
}
|
|
150
189
|
}
|
|
151
190
|
}
|
|
152
191
|
|
|
153
192
|
if (future === false || !waitForFutureMatch) {
|
|
154
|
-
return
|
|
193
|
+
return results
|
|
155
194
|
}
|
|
156
195
|
|
|
157
|
-
|
|
196
|
+
const future_match = (await waitForFutureMatch(event_key, matches, future)) as TEvent | null
|
|
197
|
+
if (future_match !== null) {
|
|
198
|
+
results.push(future_match)
|
|
199
|
+
}
|
|
200
|
+
return results
|
|
158
201
|
}
|
|
159
202
|
|
|
160
203
|
trimEventHistory(options: EventHistoryTrimOptions<TEvent> = {}): number {
|