bubus 1.8.1 → 2.2.1

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.
Files changed (67) hide show
  1. package/README.md +510 -75
  2. package/dist/esm/async_context.js +39 -0
  3. package/dist/esm/async_context.js.map +7 -0
  4. package/dist/esm/base_event.js +825 -0
  5. package/dist/esm/base_event.js.map +7 -0
  6. package/dist/esm/bridge_jsonl.js +150 -0
  7. package/dist/esm/bridge_jsonl.js.map +7 -0
  8. package/dist/esm/bridge_nats.js +88 -0
  9. package/dist/esm/bridge_nats.js.map +7 -0
  10. package/dist/esm/bridge_postgres.js +231 -0
  11. package/dist/esm/bridge_postgres.js.map +7 -0
  12. package/dist/esm/bridge_redis.js +155 -0
  13. package/dist/esm/bridge_redis.js.map +7 -0
  14. package/dist/esm/bridge_sqlite.js +235 -0
  15. package/dist/esm/bridge_sqlite.js.map +7 -0
  16. package/dist/esm/bridges.js +306 -0
  17. package/dist/esm/bridges.js.map +7 -0
  18. package/dist/esm/event_bus.js +1046 -0
  19. package/dist/esm/event_bus.js.map +7 -0
  20. package/dist/esm/event_handler.js +279 -0
  21. package/dist/esm/event_handler.js.map +7 -0
  22. package/dist/esm/event_history.js +172 -0
  23. package/dist/esm/event_history.js.map +7 -0
  24. package/dist/esm/event_result.js +426 -0
  25. package/dist/esm/event_result.js.map +7 -0
  26. package/dist/esm/events_suck.js +39 -0
  27. package/dist/esm/events_suck.js.map +7 -0
  28. package/dist/esm/helpers.js +64 -0
  29. package/dist/esm/helpers.js.map +7 -0
  30. package/dist/esm/index.js +32 -16559
  31. package/dist/esm/index.js.map +4 -4
  32. package/dist/esm/lock_manager.js +323 -0
  33. package/dist/esm/lock_manager.js.map +7 -0
  34. package/dist/esm/logging.js +196 -0
  35. package/dist/esm/logging.js.map +7 -0
  36. package/dist/esm/middlewares.js +1 -0
  37. package/dist/esm/middlewares.js.map +7 -0
  38. package/dist/esm/optional_deps.js +34 -0
  39. package/dist/esm/optional_deps.js.map +7 -0
  40. package/dist/esm/retry.js +237 -0
  41. package/dist/esm/retry.js.map +7 -0
  42. package/dist/esm/timing.js +56 -0
  43. package/dist/esm/timing.js.map +7 -0
  44. package/dist/esm/types.js +84 -0
  45. package/dist/esm/types.js.map +7 -0
  46. package/dist/types/async_context.d.ts +1 -1
  47. package/dist/types/base_event.d.ts +96 -79
  48. package/dist/types/bridge_jsonl.d.ts +26 -0
  49. package/dist/types/bridge_nats.d.ts +20 -0
  50. package/dist/types/bridge_postgres.d.ts +31 -0
  51. package/dist/types/bridge_redis.d.ts +34 -0
  52. package/dist/types/bridge_sqlite.d.ts +30 -0
  53. package/dist/types/bridges.d.ts +49 -0
  54. package/dist/types/event_bus.d.ts +88 -41
  55. package/dist/types/event_handler.d.ts +47 -18
  56. package/dist/types/event_history.d.ts +45 -0
  57. package/dist/types/event_result.d.ts +37 -33
  58. package/dist/types/events_suck.d.ts +40 -0
  59. package/dist/types/helpers.d.ts +1 -0
  60. package/dist/types/index.d.ts +10 -1
  61. package/dist/types/lock_manager.d.ts +27 -18
  62. package/dist/types/logging.d.ts +4 -1
  63. package/dist/types/middlewares.d.ts +13 -0
  64. package/dist/types/optional_deps.d.ts +3 -0
  65. package/dist/types/timing.d.ts +3 -0
  66. package/dist/types/types.d.ts +18 -7
  67. package/package.json +25 -11
@@ -1,63 +1,92 @@
1
1
  import { z } from 'zod';
2
- import type { EventHandlerFunction, EventKey } from './types.js';
2
+ import { type EventHandlerCallable, type EventPattern } from './types.js';
3
3
  import { BaseEvent } from './base_event.js';
4
4
  import type { EventResult } from './event_result.js';
5
5
  export type EphemeralFindEventHandler = {
6
- event_key: EventKey;
6
+ event_pattern: string | '*';
7
7
  matches: (event: BaseEvent) => boolean;
8
8
  resolve: (event: BaseEvent) => void;
9
9
  timeout_id?: ReturnType<typeof setTimeout>;
10
10
  };
11
+ export declare const FindWaiterJSONSchema: z.ZodObject<{
12
+ event_pattern: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"*">]>;
13
+ has_timeout: z.ZodBoolean;
14
+ }, z.core.$strict>;
15
+ export type FindWaiterJSON = z.infer<typeof FindWaiterJSONSchema>;
16
+ export declare class FindWaiter {
17
+ static toJSON(waiter: EphemeralFindEventHandler): FindWaiterJSON;
18
+ static fromJSON(data: unknown, overrides?: {
19
+ matches?: (event: BaseEvent) => boolean;
20
+ resolve?: (event: BaseEvent) => void;
21
+ }): EphemeralFindEventHandler;
22
+ static toJSONArray(waiters: Iterable<EphemeralFindEventHandler>): FindWaiterJSON[];
23
+ static fromJSONArray(data: unknown, overrides?: {
24
+ matches?: (event: BaseEvent) => boolean;
25
+ resolve?: (event: BaseEvent) => void;
26
+ }): EphemeralFindEventHandler[];
27
+ }
11
28
  export declare const EventHandlerJSONSchema: z.ZodObject<{
12
29
  id: z.ZodString;
13
30
  eventbus_name: z.ZodString;
14
31
  eventbus_id: z.ZodString;
15
- event_key: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"*">]>;
32
+ event_pattern: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"*">]>;
16
33
  handler_name: z.ZodString;
17
- handler_file_path: z.ZodOptional<z.ZodString>;
34
+ handler_file_path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
35
  handler_timeout: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
19
36
  handler_slow_timeout: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
20
37
  handler_registered_at: z.ZodString;
21
- handler_registered_ts: z.ZodNumber;
22
38
  }, z.core.$strict>;
23
39
  export type EventHandlerJSON = z.infer<typeof EventHandlerJSONSchema>;
24
40
  export declare class EventHandler {
25
41
  id: string;
26
- handler: EventHandlerFunction;
42
+ handler: EventHandlerCallable;
27
43
  handler_name: string;
28
- handler_file_path?: string;
44
+ handler_file_path: string | null;
29
45
  handler_timeout?: number | null;
30
46
  handler_slow_timeout?: number | null;
31
47
  handler_registered_at: string;
32
- handler_registered_ts: number;
33
- event_key: string | '*';
48
+ event_pattern: string | '*';
34
49
  eventbus_name: string;
35
50
  eventbus_id: string;
36
51
  constructor(params: {
37
52
  id?: string;
38
- handler: EventHandlerFunction;
53
+ handler: EventHandlerCallable;
39
54
  handler_name: string;
40
- handler_file_path?: string;
55
+ handler_file_path?: string | null;
41
56
  handler_timeout?: number | null;
42
57
  handler_slow_timeout?: number | null;
43
58
  handler_registered_at: string;
44
- handler_registered_ts: number;
45
- event_key: string | '*';
59
+ event_pattern: string | '*';
46
60
  eventbus_name: string;
47
61
  eventbus_id: string;
48
62
  });
63
+ get _handler_async(): EventHandlerCallable;
49
64
  static computeHandlerId(params: {
50
65
  eventbus_id: string;
51
66
  handler_name: string;
52
- handler_file_path?: string;
67
+ handler_file_path?: string | null;
53
68
  handler_registered_at: string;
54
- handler_registered_ts: number;
55
- event_key: string | '*';
69
+ event_pattern: string | '*';
56
70
  }): string;
71
+ static fromCallable<TEvent extends BaseEvent = BaseEvent>(params: {
72
+ handler: EventHandlerCallable<TEvent>;
73
+ event_pattern: EventPattern | '*';
74
+ eventbus_name: string;
75
+ eventbus_id: string;
76
+ detect_handler_file_path?: boolean;
77
+ id?: string;
78
+ handler_file_path?: string | null;
79
+ handler_timeout?: number | null;
80
+ handler_slow_timeout?: number | null;
81
+ handler_registered_at?: string;
82
+ }): EventHandler;
57
83
  toString(): string;
58
- detectHandlerFilePath(): void;
84
+ _detectHandlerFilePath(): void;
59
85
  toJSON(): EventHandlerJSON;
60
- static fromJSON(data: unknown, handler?: EventHandlerFunction): EventHandler;
86
+ static fromJSON(data: unknown, handler?: EventHandlerCallable): EventHandler;
87
+ static toJSONArray(handlers: Iterable<EventHandler>): EventHandlerJSON[];
88
+ static fromJSONArray(data: unknown, handler?: EventHandlerCallable): EventHandler[];
89
+ get eventbus_label(): string;
61
90
  }
62
91
  export declare class TimeoutError extends Error {
63
92
  constructor(message: string);
@@ -0,0 +1,45 @@
1
+ import { BaseEvent } from './base_event.js';
2
+ import type { EventPattern, FindWindow } from './types.js';
3
+ export type EventHistoryFindOptions = {
4
+ past?: FindWindow;
5
+ future?: FindWindow;
6
+ child_of?: BaseEvent | null;
7
+ event_is_child_of?: (event: BaseEvent, ancestor: BaseEvent) => boolean;
8
+ wait_for_future_match?: (event_pattern: string | '*', matches: (event: BaseEvent) => boolean, future: FindWindow) => Promise<BaseEvent | null>;
9
+ } & Record<string, unknown>;
10
+ export type EventHistoryTrimOptions<TEvent extends BaseEvent = BaseEvent> = {
11
+ is_event_complete?: (event: TEvent) => boolean;
12
+ on_remove?: (event: TEvent) => void;
13
+ owner_label?: string;
14
+ max_history_size?: number | null;
15
+ max_history_drop?: boolean;
16
+ };
17
+ export declare class EventHistory<TEvent extends BaseEvent = BaseEvent> implements Iterable<[string, TEvent]> {
18
+ max_history_size: number | null;
19
+ max_history_drop: boolean;
20
+ private _events;
21
+ private _warned_about_dropping_uncompleted_events;
22
+ constructor(options?: {
23
+ max_history_size?: number | null;
24
+ max_history_drop?: boolean;
25
+ });
26
+ get size(): number;
27
+ [Symbol.iterator](): Iterator<[string, TEvent]>;
28
+ entries(): IterableIterator<[string, TEvent]>;
29
+ keys(): IterableIterator<string>;
30
+ values(): IterableIterator<TEvent>;
31
+ clear(): void;
32
+ get(event_id: string): TEvent | undefined;
33
+ set(event_id: string, event: TEvent): this;
34
+ has(event_id: string): boolean;
35
+ delete(event_id: string): boolean;
36
+ addEvent(event: TEvent): void;
37
+ getEvent(event_id: string): TEvent | undefined;
38
+ removeEvent(event_id: string): boolean;
39
+ hasEvent(event_id: string): boolean;
40
+ static normalizeEventPattern(event_pattern: EventPattern | '*'): string | '*';
41
+ find(event_pattern: '*', where?: (event: TEvent) => boolean, options?: EventHistoryFindOptions): Promise<TEvent | null>;
42
+ find<TMatch extends TEvent>(event_pattern: EventPattern<TMatch>, where?: (event: TMatch) => boolean, options?: EventHistoryFindOptions): Promise<TMatch | null>;
43
+ trimEventHistory(options?: EventHistoryTrimOptions<TEvent>): number;
44
+ private eventIsChildOf;
45
+ }
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import { BaseEvent } from './base_event.js';
3
3
  import type { EventBus } from './event_bus.js';
4
4
  import { EventHandler } from './event_handler.js';
5
- import { HandlerLock } from './lock_manager.js';
5
+ import { type HandlerLock } from './lock_manager.js';
6
6
  import type { Deferred } from './lock_manager.js';
7
7
  import type { EventResultType } from './types.js';
8
8
  export type EventResultStatus = 'pending' | 'started' | 'completed' | 'error';
@@ -15,25 +15,20 @@ export declare const EventResultJSONSchema: z.ZodObject<{
15
15
  error: "error";
16
16
  }>;
17
17
  event_id: z.ZodString;
18
- handler: z.ZodObject<{
19
- id: z.ZodString;
20
- eventbus_name: z.ZodString;
21
- eventbus_id: z.ZodString;
22
- event_key: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"*">]>;
23
- handler_name: z.ZodString;
24
- handler_file_path: z.ZodOptional<z.ZodString>;
25
- handler_timeout: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
26
- handler_slow_timeout: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
27
- handler_registered_at: z.ZodString;
28
- handler_registered_ts: z.ZodNumber;
29
- }, z.core.$strict>;
30
- started_at: z.ZodOptional<z.ZodString>;
31
- started_ts: z.ZodOptional<z.ZodNumber>;
32
- completed_at: z.ZodOptional<z.ZodString>;
33
- completed_ts: z.ZodOptional<z.ZodNumber>;
18
+ handler_id: z.ZodString;
19
+ handler_name: z.ZodString;
20
+ handler_file_path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
21
+ handler_timeout: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
22
+ handler_slow_timeout: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
23
+ handler_registered_at: z.ZodOptional<z.ZodString>;
24
+ handler_event_pattern: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"*">]>>;
25
+ eventbus_name: z.ZodString;
26
+ eventbus_id: z.ZodString;
27
+ started_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
28
+ completed_at: z.ZodOptional<z.ZodNullable<z.ZodString>>;
34
29
  result: z.ZodOptional<z.ZodUnknown>;
35
30
  error: z.ZodOptional<z.ZodUnknown>;
36
- event_children: z.ZodOptional<z.ZodArray<z.ZodString>>;
31
+ event_children: z.ZodArray<z.ZodString>;
37
32
  }, z.core.$strict>;
38
33
  export type EventResultJSON = z.infer<typeof EventResultJSONSchema>;
39
34
  export declare class EventResult<TEvent extends BaseEvent = BaseEvent> {
@@ -41,13 +36,11 @@ export declare class EventResult<TEvent extends BaseEvent = BaseEvent> {
41
36
  status: EventResultStatus;
42
37
  event: TEvent;
43
38
  handler: EventHandler;
44
- started_at?: string;
45
- started_ts?: number;
46
- completed_at?: string;
47
- completed_ts?: number;
39
+ started_at: string | null;
40
+ completed_at: string | null;
48
41
  result?: EventResultType<TEvent>;
49
42
  error?: unknown;
50
- event_children: BaseEvent[] | undefined;
43
+ event_children: BaseEvent[];
51
44
  _abort: Deferred<never> | null;
52
45
  _lock: HandlerLock | null;
53
46
  _queue_jump_pause_releases: Map<EventBus, () => void> | null;
@@ -60,23 +53,34 @@ export declare class EventResult<TEvent extends BaseEvent = BaseEvent> {
60
53
  get bus(): EventBus;
61
54
  get handler_id(): string;
62
55
  get handler_name(): string;
63
- get handler_file_path(): string | undefined;
56
+ get handler_file_path(): string | null;
64
57
  get eventbus_name(): string;
65
58
  get eventbus_id(): string;
66
59
  get eventbus_label(): string;
60
+ private getHookBus;
61
+ private _notifyStatusHook;
67
62
  get value(): EventResultType<TEvent> | undefined;
68
- linkEmittedChildEvent(child_event: BaseEvent): void;
63
+ get result_type(): TEvent['event_result_type'];
64
+ _linkEmittedChildEvent(child_event: BaseEvent): void;
69
65
  get raw_value(): EventResultType<TEvent> | undefined;
70
66
  get handler_timeout(): number | null;
71
67
  get handler_slow_timeout(): number | null;
72
- createSlowHandlerWarningTimer(effective_timeout: number | null): ReturnType<typeof setTimeout> | null;
73
- ensureQueueJumpPause(bus: EventBus): void;
74
- releaseQueueJumpPauses(): void;
75
- runHandler(): Promise<void>;
76
- signalAbort(error: Error): void;
77
- markStarted(): Promise<never>;
78
- markCompleted(result: EventResultType<TEvent> | undefined): void;
79
- markError(error: unknown): void;
68
+ _createSlowHandlerWarningTimer(effective_timeout: number | null): ReturnType<typeof setTimeout> | null;
69
+ _ensureQueueJumpPause(bus: EventBus): void;
70
+ _releaseQueueJumpPauses(): void;
71
+ update(params: {
72
+ status?: EventResultStatus;
73
+ result?: EventResultType<TEvent> | BaseEvent | undefined;
74
+ error?: unknown;
75
+ }): this;
76
+ private _createHandlerTimeoutError;
77
+ private _handleHandlerError;
78
+ private _onHandlerExit;
79
+ runHandler(handler_lock: HandlerLock | null): Promise<void>;
80
+ _signalAbort(error: Error): void;
81
+ _markStarted(notify_hook?: boolean): Promise<never>;
82
+ _markCompleted(result: EventResultType<TEvent> | BaseEvent | undefined, notify_hook?: boolean): void;
83
+ _markError(error: unknown, notify_hook?: boolean): void;
80
84
  toJSON(): EventResultJSON;
81
85
  static fromJSON<TEvent extends BaseEvent>(event: TEvent, data: unknown): EventResult<TEvent>;
82
86
  }
@@ -0,0 +1,40 @@
1
+ import { EventBus } from './event_bus.js';
2
+ import { BaseEvent } from './base_event.js';
3
+ import type { EventClass, EventResultType } from './types.js';
4
+ type EventMap = Record<string, EventClass<BaseEvent>>;
5
+ type AnyFn = (...args: any[]) => any;
6
+ type FunctionMap = Record<string, AnyFn>;
7
+ type ExtraDict = Record<string, unknown>;
8
+ type EventFieldsFromFn<TFunc extends AnyFn> = Parameters<TFunc> extends [infer TArg] ? (TArg extends Record<string, unknown> ? TArg : ExtraDict) : ExtraDict;
9
+ type GeneratedEvent<TFunc extends AnyFn> = {
10
+ (data: EventFieldsFromFn<TFunc> & ExtraDict): BaseEvent & EventFieldsFromFn<TFunc> & {
11
+ __event_result_type__?: Awaited<ReturnType<TFunc>>;
12
+ };
13
+ new (data: EventFieldsFromFn<TFunc> & ExtraDict): BaseEvent & EventFieldsFromFn<TFunc> & {
14
+ __event_result_type__?: Awaited<ReturnType<TFunc>>;
15
+ };
16
+ event_type?: string;
17
+ };
18
+ export type GeneratedEvents<TEvents extends FunctionMap> = {
19
+ by_name: {
20
+ [K in keyof TEvents]: GeneratedEvent<TEvents[K]>;
21
+ };
22
+ } & {
23
+ [K in keyof TEvents]: GeneratedEvent<TEvents[K]>;
24
+ };
25
+ type EventInit<TEventClass extends EventClass<BaseEvent>> = ConstructorParameters<TEventClass> extends [infer TInit, ...unknown[]] ? TInit : never;
26
+ type EventMethodArgs<TEventClass extends EventClass<BaseEvent>> = {} extends EventInit<TEventClass> ? [init?: EventInit<TEventClass>, extra?: Record<string, unknown>] : [init: EventInit<TEventClass>, extra?: Record<string, unknown>];
27
+ type EventMethodResult<TEventClass extends EventClass<BaseEvent>> = EventResultType<InstanceType<TEventClass>> | undefined;
28
+ export type EventsSuckClient<TEvents extends EventMap> = {
29
+ bus: EventBus;
30
+ } & {
31
+ [K in keyof TEvents]: (...args: EventMethodArgs<TEvents[K]>) => Promise<EventMethodResult<TEvents[K]>>;
32
+ };
33
+ export type EventsSuckClientClass<TEvents extends EventMap> = new (bus?: EventBus) => EventsSuckClient<TEvents>;
34
+ export declare const make_events: <TEvents extends FunctionMap>(events: TEvents) => GeneratedEvents<TEvents>;
35
+ export declare const wrap: <TEvents extends EventMap>(class_name: string, methods: TEvents) => EventsSuckClientClass<TEvents>;
36
+ export declare const events_suck: {
37
+ readonly make_events: <TEvents extends FunctionMap>(events: TEvents) => GeneratedEvents<TEvents>;
38
+ readonly wrap: <TEvents extends EventMap>(class_name: string, methods: TEvents) => EventsSuckClientClass<TEvents>;
39
+ };
40
+ export {};
@@ -0,0 +1 @@
1
+ export declare function monotonicDatetime(isostring?: string): string;
@@ -1,8 +1,17 @@
1
1
  export { BaseEvent, BaseEventSchema } from './base_event.js';
2
+ export { EventHistory } from './event_history.js';
3
+ export type { EventHistoryFindOptions, EventHistoryTrimOptions } from './event_history.js';
2
4
  export { EventResult } from './event_result.js';
3
5
  export { EventBus } from './event_bus.js';
6
+ export type { EventBusJSON, EventBusOptions } from './event_bus.js';
7
+ export { monotonicDatetime } from './helpers.js';
8
+ export type { EventBusMiddleware, EventBusMiddlewareCtor, EventBusMiddlewareInput } from './middlewares.js';
4
9
  export { EventHandlerTimeoutError, EventHandlerCancelledError, EventHandlerAbortedError, EventHandlerResultSchemaError, } from './event_handler.js';
5
10
  export type { EventConcurrencyMode, EventHandlerConcurrencyMode, EventHandlerCompletionMode, EventBusInterfaceForLockManager, } from './lock_manager.js';
6
- export type { EventClass, EventHandlerFunction as EventHandler, EventKey, EventStatus, FindOptions, FindWindow } from './types.js';
11
+ export type { EventClass, EventHandlerCallable as EventHandler, EventPattern, EventStatus, FindOptions, FindWindow } from './types.js';
7
12
  export { retry, clearSemaphoreRegistry, RetryTimeoutError, SemaphoreTimeoutError } from './retry.js';
8
13
  export type { RetryOptions } from './retry.js';
14
+ export { HTTPEventBridge, SocketEventBridge, NATSEventBridge, RedisEventBridge, PostgresEventBridge, JSONLEventBridge, SQLiteEventBridge, } from './bridges.js';
15
+ export type { HTTPEventBridgeOptions } from './bridges.js';
16
+ export { events_suck } from './events_suck.js';
17
+ export type { EventsSuckClient, EventsSuckClientClass, GeneratedEvents } from './events_suck.js';
@@ -12,7 +12,7 @@ export declare const EVENT_HANDLER_CONCURRENCY_MODES: readonly ["serial", "paral
12
12
  export type EventHandlerConcurrencyMode = (typeof EVENT_HANDLER_CONCURRENCY_MODES)[number];
13
13
  export declare const EVENT_HANDLER_COMPLETION_MODES: readonly ["all", "first"];
14
14
  export type EventHandlerCompletionMode = (typeof EVENT_HANDLER_COMPLETION_MODES)[number];
15
- export declare class AsyncSemaphore {
15
+ export declare class AsyncLock {
16
16
  size: number;
17
17
  in_use: number;
18
18
  waiters: Array<() => void>;
@@ -20,12 +20,12 @@ export declare class AsyncSemaphore {
20
20
  acquire(): Promise<void>;
21
21
  release(): void;
22
22
  }
23
- export declare const runWithSemaphore: <T>(semaphore: AsyncSemaphore | null, fn: () => Promise<T>) => Promise<T>;
23
+ export declare const runWithLock: <T>(lock: AsyncLock | null, fn: () => Promise<T>) => Promise<T>;
24
24
  export type HandlerExecutionState = 'held' | 'yielded' | 'closed';
25
25
  export declare class HandlerLock {
26
- private semaphore;
26
+ private lock;
27
27
  private state;
28
- constructor(semaphore: AsyncSemaphore | null);
28
+ constructor(lock: AsyncLock | null);
29
29
  yieldHandlerLockForChildRun(): boolean;
30
30
  reclaimHandlerLockIfRunning(): Promise<boolean>;
31
31
  exitHandlerRun(): void;
@@ -33,29 +33,38 @@ export declare class HandlerLock {
33
33
  }
34
34
  export type EventBusInterfaceForLockManager = {
35
35
  isIdleAndQueueEmpty: () => boolean;
36
- event_concurrency_default: EventConcurrencyMode;
36
+ event_concurrency: EventConcurrencyMode;
37
+ _lock_for_event_global_serial: AsyncLock;
38
+ };
39
+ export type LockManagerOptions = {
40
+ auto_schedule_idle_checks?: boolean;
37
41
  };
38
42
  export declare class LockManager {
39
43
  private bus;
40
- static global_event_semaphore: AsyncSemaphore;
41
- readonly bus_event_semaphore: AsyncSemaphore;
44
+ private auto_schedule_idle_checks;
45
+ readonly bus_event_lock: AsyncLock;
42
46
  private pause_depth;
43
47
  private pause_waiters;
44
48
  private active_handler_results;
45
49
  private idle_waiters;
46
50
  private idle_check_pending;
47
51
  private idle_check_streak;
48
- constructor(bus: EventBusInterfaceForLockManager);
49
- requestRunloopPause(): () => void;
50
- waitUntilRunloopResumed(): Promise<void>;
51
- isPaused(): boolean;
52
- enterActiveHandlerContext(result: EventResult): void;
53
- exitActiveHandlerContext(result: EventResult): void;
54
- getActiveHandlerResult(): EventResult | undefined;
55
- isAnyHandlerActive(): boolean;
56
- waitForIdle(): Promise<void>;
57
- notifyIdleListeners(): void;
58
- getSemaphoreForEvent(event: BaseEvent): AsyncSemaphore | null;
52
+ constructor(bus: EventBusInterfaceForLockManager, options?: LockManagerOptions);
53
+ _requestRunloopPause(): () => void;
54
+ _waitUntilRunloopResumed(): Promise<void>;
55
+ _isPaused(): boolean;
56
+ _runWithHandlerDispatchContext<T>(result: EventResult, fn: () => Promise<T>): Promise<T>;
57
+ _getActiveHandlerResult(): EventResult | undefined;
58
+ _getActiveHandlerResults(): EventResult[];
59
+ _isAnyHandlerActive(): boolean;
60
+ waitForIdle(timeout_seconds?: number | null): Promise<boolean>;
61
+ _notifyIdleListeners(): void;
62
+ getLockForEvent(event: BaseEvent): AsyncLock | null;
63
+ _runWithEventLock<T>(event: BaseEvent, fn: () => Promise<T>, options?: {
64
+ bypass_event_locks?: boolean;
65
+ pre_acquired_lock?: AsyncLock | null;
66
+ }): Promise<T>;
67
+ _runWithHandlerLock<T>(event: BaseEvent, default_handler_concurrency: EventHandlerConcurrencyMode | undefined, fn: (lock: HandlerLock | null) => Promise<T>): Promise<T>;
59
68
  private scheduleIdleCheck;
60
69
  clear(): void;
61
70
  }
@@ -2,7 +2,10 @@ import { BaseEvent } from './base_event.js';
2
2
  import { EventResult } from './event_result.js';
3
3
  type LogTreeBus = {
4
4
  name: string;
5
- event_history: Map<string, BaseEvent>;
5
+ event_history: {
6
+ values(): IterableIterator<BaseEvent>;
7
+ has(event_id: string): boolean;
8
+ };
6
9
  toString?: () => string;
7
10
  };
8
11
  export declare const logTree: (bus: LogTreeBus) => string;
@@ -0,0 +1,13 @@
1
+ import type { BaseEvent } from './base_event.js';
2
+ import type { EventBus } from './event_bus.js';
3
+ import type { EventHandler } from './event_handler.js';
4
+ import type { EventResult } from './event_result.js';
5
+ import type { EventStatus } from './types.js';
6
+ export type { EventStatus } from './types.js';
7
+ export interface EventBusMiddleware {
8
+ onEventChange?(eventbus: EventBus, event: BaseEvent, status: EventStatus): void | Promise<void>;
9
+ onEventResultChange?(eventbus: EventBus, event: BaseEvent, event_result: EventResult, status: EventStatus): void | Promise<void>;
10
+ onBusHandlersChange?(eventbus: EventBus, handler: EventHandler, registered: boolean): void | Promise<void>;
11
+ }
12
+ export type EventBusMiddlewareCtor = new () => EventBusMiddleware;
13
+ export type EventBusMiddlewareInput = EventBusMiddleware | EventBusMiddlewareCtor;
@@ -0,0 +1,3 @@
1
+ export declare const isNodeRuntime: () => boolean;
2
+ export declare const assertOptionalDependencyAvailable: (bridge_name: string, package_name: string) => void;
3
+ export declare const importOptionalDependency: (bridge_name: string, package_name: string) => Promise<any>;
@@ -0,0 +1,3 @@
1
+ export declare function _runWithTimeout<T>(timeout_seconds: number | null, on_timeout: () => Error, fn: () => Promise<T>): Promise<T>;
2
+ export declare function _runWithSlowMonitor<T>(slow_timer: ReturnType<typeof setTimeout> | null, fn: () => Promise<T>): Promise<T>;
3
+ export declare function _runWithAbortMonitor<T>(fn: () => T | Promise<T>, abort_signal: Promise<never>): Promise<T>;
@@ -4,22 +4,33 @@ export type EventStatus = 'pending' | 'started' | 'completed';
4
4
  export type EventClass<T extends BaseEvent = BaseEvent> = {
5
5
  event_type?: string;
6
6
  } & (new (...args: any[]) => T);
7
- export type EventKey<T extends BaseEvent = BaseEvent> = string | EventClass<T>;
8
- export type EventWithResult<TResult> = BaseEvent & {
7
+ export type EventPattern<T extends BaseEvent = BaseEvent> = string | EventClass<T>;
8
+ export type EventWithResultSchema<TResult> = BaseEvent & {
9
9
  __event_result_type__?: TResult;
10
10
  };
11
11
  export type EventResultType<TEvent extends BaseEvent> = TEvent extends {
12
12
  __event_result_type__?: infer TResult;
13
13
  } ? TResult : unknown;
14
- export type EventHandlerFunction<T extends BaseEvent = BaseEvent> = (event: T) => void | EventResultType<T> | Promise<void | EventResultType<T>>;
15
- export type UntypedEventHandlerFunction<T extends BaseEvent = BaseEvent> = (event: T) => void | unknown | Promise<void | unknown>;
14
+ export type EventResultTypeConstructor = StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor;
15
+ export type EventResultTypeInput = z.ZodTypeAny | EventResultTypeConstructor | unknown;
16
+ export type EventHandlerReturn<T extends BaseEvent = BaseEvent> = EventResultType<T> | BaseEvent | null | void;
17
+ export type EventHandlerCallable<T extends BaseEvent = BaseEvent> = (event: T) => EventHandlerReturn<T> | Promise<EventHandlerReturn<T>>;
18
+ export type UntypedEventHandlerFunction<T extends BaseEvent = BaseEvent> = (event: T) => EventHandlerReturn<T> | unknown | Promise<EventHandlerReturn<T> | unknown>;
16
19
  export type FindWindow = boolean | number;
17
- export type FindOptions = {
20
+ type FindReservedOptionKeys = 'past' | 'future' | 'child_of';
21
+ type EventFilterFields<T extends BaseEvent> = {
22
+ [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K extends FindReservedOptionKeys ? never : T[K] extends (...args: any[]) => any ? never : K]?: T[K];
23
+ };
24
+ export type FindOptions<T extends BaseEvent = BaseEvent> = {
18
25
  past?: FindWindow;
19
26
  future?: FindWindow;
20
27
  child_of?: BaseEvent | null;
21
- };
28
+ } & EventFilterFields<T> & Record<string, unknown>;
29
+ export declare const normalizeEventPattern: (event_pattern: EventPattern | "*") => string | "*";
22
30
  export declare const isZodSchema: (value: unknown) => value is z.ZodTypeAny;
31
+ export declare const eventResultTypeFromConstructor: (value: unknown) => z.ZodTypeAny | undefined;
23
32
  export declare const extractZodShape: (raw: Record<string, unknown>) => z.ZodRawShape;
24
33
  export declare const toJsonSchema: (schema: unknown) => unknown;
25
- export declare const getStringTypeName: (schema?: z.ZodTypeAny) => string | undefined;
34
+ export declare const fromJsonSchema: (schema: unknown) => z.ZodTypeAny;
35
+ export declare const normalizeEventResultType: (value: EventResultTypeInput) => z.ZodTypeAny | undefined;
36
+ export {};
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "bubus",
3
- "version": "1.8.1",
3
+ "version": "2.2.1",
4
4
  "description": "Event bus library for browsers and ESM Node.js",
5
5
  "type": "module",
6
+ "sideEffects": false,
6
7
  "main": "./dist/esm/index.js",
7
8
  "module": "./dist/esm/index.js",
8
9
  "types": "./dist/types/index.d.ts",
@@ -11,6 +12,11 @@
11
12
  "types": "./dist/types/index.d.ts",
12
13
  "import": "./dist/esm/index.js",
13
14
  "default": "./dist/esm/index.js"
15
+ },
16
+ "./*": {
17
+ "types": "./dist/types/*.d.ts",
18
+ "import": "./dist/esm/*.js",
19
+ "default": "./dist/esm/*.js"
14
20
  }
15
21
  },
16
22
  "files": [
@@ -25,12 +31,14 @@
25
31
  "zod": "^4.3.6"
26
32
  },
27
33
  "devDependencies": {
28
- "@typescript-eslint/eslint-plugin": "^8.46.0",
29
- "@typescript-eslint/parser": "^8.46.0",
30
- "esbuild": "^0.27.2",
34
+ "@types/node": "^25.2.3",
35
+ "@typescript-eslint/eslint-plugin": "^8.55.0",
36
+ "@typescript-eslint/parser": "^8.55.0",
37
+ "esbuild": "^0.27.3",
31
38
  "eslint": "^9.39.2",
32
39
  "prettier": "^3.8.1",
33
- "tsx": "^4.20.6",
40
+ "tsc-files": "^1.1.4",
41
+ "tsx": "^4.21.0",
34
42
  "typescript": "^5.9.3"
35
43
  },
36
44
  "repository": {
@@ -46,22 +54,28 @@
46
54
  "access": "public",
47
55
  "registry": "https://registry.npmjs.org/"
48
56
  },
57
+ "optionalDependencies": {
58
+ "ioredis": "^5.9.3",
59
+ "nats": "^2.29.3",
60
+ "pg": "^8.18.0"
61
+ },
49
62
  "scripts": {
50
63
  "build": "pnpm run build:esm && pnpm run build:types",
51
- "build:esm": "esbuild src/index.ts --bundle --format=esm --platform=neutral --target=es2022 --sourcemap --outdir=dist/esm",
64
+ "build:esm": "node ./scripts/build_esm.mjs",
52
65
  "build:types": "tsc -p tsconfig.json --emitDeclarationOnly",
53
- "typecheck": "tsc -p tsconfig.json --noEmit",
54
- "lint": "pnpm run prettier && eslint . && pnpm run typecheck",
66
+ "typecheck": "tsc -p tsconfig.typecheck.json",
55
67
  "prettier": "prettier --write .",
56
- "test": "NODE_OPTIONS='--expose-gc' node --expose-gc --test --import tsx tests/**/*.test.ts",
68
+ "eslint": "eslint .",
69
+ "lint": "pnpm run prettier && pnpm run eslint && pnpm run typecheck",
70
+ "test": "NODE_OPTIONS='--expose-gc' node --expose-gc --test --import tsx \"tests/**/*.test.ts\"",
57
71
  "perf": "pnpm run perf:node && pnpm run perf:bun && pnpm run perf:deno && pnpm run perf:browser",
58
72
  "debug:node": "NODE_OPTIONS='--expose-gc' node --expose-gc --import tsx",
59
73
  "debug:bun": "bun --expose-gc run",
60
- "debug:deno": "deno run --v8-flags=--expose-gc",
74
+ "debug:deno": "deno run --sloppy-imports --v8-flags=--expose-gc",
61
75
  "perf:node": "pnpm run build && pnpm run debug:node -- tests/performance.runtime.ts --scenario 50k-events && pnpm run debug:node -- tests/performance.runtime.ts --scenario 500-buses-x-100-events && pnpm run debug:node -- tests/performance.runtime.ts --scenario 1-event-x-50k-parallel-handlers && pnpm run debug:node -- tests/performance.runtime.ts --scenario 50k-one-off-handlers && pnpm run debug:node -- tests/performance.runtime.ts --scenario worst-case-forwarding-timeouts && pnpm run debug:node -- tests/performance.runtime.ts --scenario cleanup-equivalence",
62
76
  "perf:bun": "pnpm run build && pnpm run debug:bun -- tests/performance.runtime.ts --scenario 50k-events && pnpm run debug:bun -- tests/performance.runtime.ts --scenario 500-buses-x-100-events && pnpm run debug:bun -- tests/performance.runtime.ts --scenario 1-event-x-50k-parallel-handlers && pnpm run debug:bun -- tests/performance.runtime.ts --scenario 50k-one-off-handlers && pnpm run debug:bun -- tests/performance.runtime.ts --scenario worst-case-forwarding-timeouts && pnpm run debug:bun -- tests/performance.runtime.ts --scenario cleanup-equivalence",
63
77
  "perf:deno": "pnpm run build && pnpm run debug:deno -- tests/performance.runtime.ts --scenario 50k-events && pnpm run debug:deno -- tests/performance.runtime.ts --scenario 500-buses-x-100-events && pnpm run debug:deno -- tests/performance.runtime.ts --scenario 1-event-x-50k-parallel-handlers && pnpm run debug:deno -- tests/performance.runtime.ts --scenario 50k-one-off-handlers && pnpm run debug:deno -- tests/performance.runtime.ts --scenario worst-case-forwarding-timeouts && pnpm run debug:deno -- tests/performance.runtime.ts --scenario cleanup-equivalence",
64
- "perf:browser": "pnpm run build && npx --yes --package=playwright -c 'PW_BIN=\"$(command -v playwright)\"; PW_NODE_MODULES=\"$(cd \"$(dirname \"$PW_BIN\")/..\" && pwd)\"; NODE_PATH=\"$PW_NODE_MODULES\" playwright test tests/performance.browser.spec.cjs --browser=chromium --workers=1 --reporter=line --output=/tmp/bubus-playwright-results'",
78
+ "perf:browser": "pnpm run build && bash ./scripts/run_browser_perf.sh",
65
79
  "release:dry-run": "pnpm publish --access public --dry-run --no-git-checks",
66
80
  "release:check": "pnpm run typecheck && pnpm test && pnpm run build"
67
81
  }