@adonisjs/events 8.4.9-0 → 8.4.9-2

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/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # The MIT License
2
2
 
3
- Copyright (c) 2023 AdonisJS Framework
3
+ Copyright (c) 2023 Harminder Virk
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
@@ -3,3 +3,4 @@ import { Emitter } from '../src/emitter.js';
3
3
  export declare class EmitterFactory {
4
4
  create(app: Application<any>): Emitter<Record<string | number | symbol, any>>;
5
5
  }
6
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../factories/emitter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAM3C,qBAAa,cAAc;IAIzB,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC;CAG7B"}
@@ -1 +1,2 @@
1
1
  export { EmitterFactory } from './emitter.js';
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../factories/main.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
package/build/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { Emitter } from './src/emitter.js';
2
2
  export { BaseEvent } from './src/base_event.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA"}
@@ -1,7 +1,8 @@
1
- import { Emitter } from './emitter.js';
1
+ import type { Emitter } from './emitter.js';
2
2
  export declare class BaseEvent {
3
3
  constructor(..._: any[]);
4
4
  static emitter?: Emitter<any>;
5
5
  static useEmitter(emitter: Emitter<any>): void;
6
6
  static dispatch<T extends typeof BaseEvent>(this: T, ...args: ConstructorParameters<T>): Promise<void>;
7
7
  }
8
+ //# sourceMappingURL=base_event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base_event.d.ts","sourceRoot":"","sources":["../../src/base_event.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAM3C,qBAAa,SAAS;gBACR,GAAG,CAAC,EAAE,GAAG,EAAE;IAKvB,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IAK7B,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC;WAQ1B,QAAQ,CAAC,CAAC,SAAS,OAAO,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC;CAS7F"}
@@ -7,7 +7,7 @@ export class BaseEvent {
7
7
  }
8
8
  static async dispatch(...args) {
9
9
  if (!this.emitter) {
10
- throw new RuntimeException(`Cannot dispatch "${this.name}" event. Make sure to pass emitter to the base event for dispatch method to work`);
10
+ throw new RuntimeException(`Cannot dispatch "${this.name}" event. Make sure to pass emitter to the "BaseEvent" class for dispatch method to work`);
11
11
  }
12
12
  return this.emitter.emit(this, new this(...args));
13
13
  }
@@ -1,3 +1,4 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  declare const _default: import("util").DebugLogger;
3
3
  export default _default;
4
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/debug.ts"],"names":[],"mappings":";;AAUA,wBAA0C"}
@@ -8,10 +8,10 @@ export declare class Emitter<EventsList extends Record<string | symbol | number,
8
8
  constructor(app: Application<any>);
9
9
  onError(callback: (event: keyof EventsList | Constructor<any>, error: any, data: any) => void): this;
10
10
  listen<Event extends Constructor<any>>(event: Event, listeners: (ListenerClassWithHandleMethod<InstanceType<Event>> | LazyImport<ListenerClassWithHandleMethod<InstanceType<Event>>>)[]): void;
11
- on<Event extends Constructor<any>, ListenerClass extends Constructor<any>>(event: Event, listener: Listener<InstanceType<Event>, ListenerClass>): UnsubscribeFunction;
12
- on<Name extends keyof EventsList, ListenerClass extends Constructor<any>>(event: Name, listener: Listener<EventsList[Name], ListenerClass>): UnsubscribeFunction;
13
- once<Event extends Constructor<any>, ListenerClass extends Constructor<any>>(event: Event, listener: Listener<InstanceType<Event>, ListenerClass>): void;
14
- once<Name extends keyof EventsList, ListenerClass extends Constructor<any>>(event: Name, listener: Listener<EventsList[Name], ListenerClass>): void;
11
+ on<Event extends Constructor, ListenerClass extends Constructor>(event: Event, listener: Listener<InstanceType<Event>, ListenerClass>): UnsubscribeFunction;
12
+ on<Name extends keyof EventsList, ListenerClass extends Constructor>(event: Name, listener: Listener<EventsList[Name], ListenerClass>): UnsubscribeFunction;
13
+ once<Event extends Constructor, ListenerClass extends Constructor>(event: Event, listener: Listener<InstanceType<Event>, ListenerClass>): void;
14
+ once<Name extends keyof EventsList, ListenerClass extends Constructor>(event: Name, listener: Listener<EventsList[Name], ListenerClass>): void;
15
15
  onAny(listener: (event: AllowedEventTypes, data: any) => any | Promise<any>): UnsubscribeFunction;
16
16
  emit<Event extends Constructor<any>>(event: Event, data: InstanceType<Event>): Promise<void>;
17
17
  emit<Name extends keyof EventsList>(event: Name, data: EventsList[Name]): Promise<void>;
@@ -25,3 +25,4 @@ export declare class Emitter<EventsList extends Record<string | symbol | number,
25
25
  fake(events?: (keyof EventsList | Constructor<any>)[]): EventsBuffer<EventsList>;
26
26
  restore(): void;
27
27
  }
28
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/emitter.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAI7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,6BAA6B,EAC9B,MAAM,YAAY,CAAA;AAMnB,qBAAa,OAAO,CAAC,UAAU,SAAS,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC;;IAmD3E,IAAI,eAAe,sFAElB;gBAEW,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC;IA6FjC,OAAO,CACL,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,GACpF,IAAI;IAUP,MAAM,CAAC,KAAK,SAAS,WAAW,CAAC,GAAG,CAAC,EACnC,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,CACP,6BAA6B,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GAClD,UAAU,CAAC,6BAA6B,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CACjE,EAAE;IAQL,EAAE,CAAC,KAAK,SAAS,WAAW,EAAE,aAAa,SAAS,WAAW,EAC7D,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,GACrD,mBAAmB;IACtB,EAAE,CAAC,IAAI,SAAS,MAAM,UAAU,EAAE,aAAa,SAAS,WAAW,EACjE,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,GAClD,mBAAmB;IAmBtB,IAAI,CAAC,KAAK,SAAS,WAAW,EAAE,aAAa,SAAS,WAAW,EAC/D,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,GACrD,IAAI;IACP,IAAI,CAAC,IAAI,SAAS,MAAM,UAAU,EAAE,aAAa,SAAS,WAAW,EACnE,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,GAClD,IAAI;IA2BP,KAAK,CACH,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GACpE,mBAAmB;IAUhB,IAAI,CAAC,KAAK,SAAS,WAAW,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5F,IAAI,CAAC,IAAI,SAAS,MAAM,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B7F,GAAG,CAAC,KAAK,EAAE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI;IAoBhG,MAAM,CACJ,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GACtF,IAAI;IAUP,aAAa,CACX,KAAK,EAAE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,EAC1C,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,GACxC,IAAI;IAOP,cAAc,CAAC,KAAK,EAAE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC;IASzD,iBAAiB;IASjB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,MAAM;IAOlE,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,OAAO;IAclE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,YAAY,CAAC,UAAU,CAAC;IAkBhF,OAAO;CAMR"}
@@ -4,8 +4,12 @@ export declare class EventsBuffer<EventsList extends Record<string | symbol | nu
4
4
  add<Name extends AllowedEventTypes>(event: Name, data: any): void;
5
5
  all(): BufferedEventsList<EventsList>[];
6
6
  size(): number;
7
- exists<Event extends keyof EventsList | Constructor<any>>(finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)): boolean;
8
- filter(finder: keyof EventsList | Constructor<any> | ((event: BufferedEventsList<EventsList>) => boolean)): BufferedEventsList<EventsList>[];
9
- find<Event extends keyof EventsList | Constructor<any>>(finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)): (Event extends keyof EventsList ? BufferedEvent<Event, EventsList[Event]> : Event extends Constructor<infer A> ? BufferedEvent<Event, A> : BufferedEventsList<EventsList>) | null;
7
+ exists<Event extends keyof EventsList | Constructor>(finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)): boolean;
8
+ filter(finder: keyof EventsList | Constructor | ((event: BufferedEventsList<EventsList>) => boolean)): BufferedEventsList<EventsList>[];
9
+ find<Event extends keyof EventsList | Constructor>(finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)): (Event extends keyof EventsList ? BufferedEvent<Event, EventsList[Event]> : Event extends Constructor<infer A> ? BufferedEvent<Event, A> : BufferedEventsList<EventsList>) | null;
10
+ assertEmitted<Event extends keyof EventsList | Constructor>(finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)): void;
11
+ assertNotEmitted<Event extends keyof EventsList | Constructor<any>>(finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)): void;
12
+ assertNoneEmitted(): void;
10
13
  flush(): void;
11
14
  }
15
+ //# sourceMappingURL=events_buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events_buffer.d.ts","sourceRoot":"","sources":["../../src/events_buffer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAKnG,qBAAa,YAAY,CAAC,UAAU,SAAS,MAAM,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC;;IAShF,GAAG,CAAC,IAAI,SAAS,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IAOjE,GAAG;IAOH,IAAI;IAOJ,MAAM,CAAC,KAAK,SAAS,MAAM,UAAU,GAAG,WAAW,EACjD,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,GACnE,OAAO;IAOV,MAAM,CACJ,MAAM,EAAE,MAAM,UAAU,GAAG,WAAW,GAAG,CAAC,CAAC,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,GAC5F,kBAAkB,CAAC,UAAU,CAAC,EAAE;IAWnC,IAAI,CAAC,KAAK,SAAS,MAAM,UAAU,GAAG,WAAW,EAC/C,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,GAElE,CAAC,KAAK,SAAS,MAAM,UAAU,GAC3B,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,GACvC,KAAK,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC,GAClC,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,GACvB,kBAAkB,CAAC,UAAU,CAAC,CAAC,GACnC,IAAI;IAWR,aAAa,CAAC,KAAK,SAAS,MAAM,UAAU,GAAG,WAAW,EACxD,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,GACnE,IAAI;IAyBP,gBAAgB,CAAC,KAAK,SAAS,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,EAChE,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,GACnE,IAAI;IAyBP,iBAAiB,IAAI,IAAI;IAuBzB,KAAK;CAGN"}
@@ -1,4 +1,5 @@
1
1
  import is from '@sindresorhus/is';
2
+ import { AssertionError } from 'node:assert';
2
3
  export class EventsBuffer {
3
4
  #events = [];
4
5
  add(event, data) {
@@ -25,6 +26,56 @@ export class EventsBuffer {
25
26
  }
26
27
  return (this.#events.find((event) => event.event === finder) || null);
27
28
  }
29
+ assertEmitted(finder) {
30
+ const hasEvent = this.exists(finder);
31
+ if (!hasEvent) {
32
+ const isClass = is.class_(finder);
33
+ const message = typeof finder === 'function' && !isClass
34
+ ? `Expected callback to find an emitted event`
35
+ : isClass
36
+ ? `Expected "${finder.name}" event to be emitted`
37
+ : `Expected "${String(finder)}" event to be emitted`;
38
+ throw new AssertionError({
39
+ message: message,
40
+ expected: true,
41
+ actual: false,
42
+ operator: 'strictEqual',
43
+ stackStartFn: this.assertEmitted,
44
+ });
45
+ }
46
+ }
47
+ assertNotEmitted(finder) {
48
+ const hasEvent = this.exists(finder);
49
+ if (hasEvent) {
50
+ const isClass = is.class_(finder);
51
+ const message = typeof finder === 'function' && !isClass
52
+ ? `Expected callback to not find any event`
53
+ : isClass
54
+ ? `Expected "${finder.name}" event to be not emitted`
55
+ : `Expected "${String(finder)}" event to be not emitted`;
56
+ throw new AssertionError({
57
+ message: message,
58
+ expected: false,
59
+ actual: true,
60
+ operator: 'strictEqual',
61
+ stackStartFn: this.assertNotEmitted,
62
+ });
63
+ }
64
+ }
65
+ assertNoneEmitted() {
66
+ const eventsSize = this.size();
67
+ if (eventsSize > 0) {
68
+ throw new AssertionError(Object.assign({
69
+ message: `Expected zero events to be emitted. Instead received "${eventsSize}" event(s)`,
70
+ expected: 0,
71
+ actual: eventsSize,
72
+ operator: 'strictEqual',
73
+ stackStartFn: this.assertNoneEmitted,
74
+ }, {
75
+ showDiff: true,
76
+ }));
77
+ }
78
+ }
28
79
  flush() {
29
80
  this.#events = [];
30
81
  }
@@ -1,5 +1,5 @@
1
- export type AllowedEventTypes = string | symbol | number | Constructor<any>;
2
- export type Constructor<T> = new (...args: any[]) => T;
1
+ export type AllowedEventTypes = string | symbol | number | Constructor;
2
+ export type Constructor<T = unknown> = new (...args: any[]) => T;
3
3
  export type LazyImport<DefaultExport> = () => Promise<{
4
4
  default: DefaultExport;
5
5
  }>;
@@ -18,4 +18,5 @@ export type GetListenersMethods<Listener extends Constructor<any>, Data> = {
18
18
  export type ListenerClassWithHandleMethod<Data> = Constructor<{
19
19
  handle: ListenerMethod<Data>;
20
20
  }>;
21
- export type Listener<Data, ListenerClass extends Constructor<any>> = ListenerFn<Data> | string | [LazyImport<ListenerClass> | ListenerClass, GetListenersMethods<ListenerClass, Data>?];
21
+ export type Listener<Data, ListenerClass extends Constructor> = ListenerFn<Data> | string | [LazyImport<ListenerClass> | ListenerClass, GetListenersMethods<ListenerClass, Data>?];
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,CAAA;AAKtE,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,OAAO,IAAI,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;AAKhE,MAAM,MAAM,UAAU,CAAC,aAAa,IAAI,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,CAAA;CAAE,CAAC,CAAA;AAKjF,MAAM,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,IAAI;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAA;AAKrE,MAAM,MAAM,kBAAkB,CAAC,UAAU,IACrC;KACG,IAAI,IAAI,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;CAClE,CAAC,MAAM,UAAU,CAAC,GACnB,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAA;AAOxC,MAAM,MAAM,cAAc,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;AAKrF,MAAM,MAAM,UAAU,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;AAMjE,MAAM,MAAM,mBAAmB,CAAC,QAAQ,SAAS,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI;KACxE,CAAC,IAAI,MAAM,YAAY,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,cAAc,CAAC,IAAI,CAAC,GACvF,CAAC,GACD,KAAK;CACV,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;AAK/B,MAAM,MAAM,6BAA6B,CAAC,IAAI,IAAI,WAAW,CAAC;IAC5D,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,CAAA;CAC7B,CAAC,CAAA;AAMF,MAAM,MAAM,QAAQ,CAAC,IAAI,EAAE,aAAa,SAAS,WAAW,IACxD,UAAU,CAAC,IAAI,CAAC,GAChB,MAAM,GACN,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,aAAa,EAAE,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,24 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import type { Application } from '@adonisjs/application'
11
+ import { Emitter } from '../src/emitter.js'
12
+
13
+ /**
14
+ * Emitter factory is used to create an instance of emitter
15
+ * for testing
16
+ */
17
+ export class EmitterFactory {
18
+ /**
19
+ * Create emitter instance
20
+ */
21
+ create(app: Application<any>) {
22
+ return new Emitter(app)
23
+ }
24
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ export { EmitterFactory } from './emitter.js'
package/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ export { Emitter } from './src/emitter.js'
11
+ export { BaseEvent } from './src/base_event.js'
package/package.json CHANGED
@@ -1,13 +1,17 @@
1
1
  {
2
2
  "name": "@adonisjs/events",
3
- "version": "8.4.9-0",
3
+ "version": "8.4.9-2",
4
4
  "description": "An implementation of the event emitter built on top of emittery",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
7
7
  "files": [
8
+ "src",
9
+ "factories",
10
+ "index.ts",
8
11
  "build/src",
9
- "build/test_factories",
12
+ "build/factories",
10
13
  "build/index.d.ts",
14
+ "build/index.d.ts.map",
11
15
  "build/index.js"
12
16
  ],
13
17
  "imports": {
@@ -15,7 +19,7 @@
15
19
  },
16
20
  "exports": {
17
21
  ".": "./build/index.js",
18
- "./factories": "./build/test_factories/main.js",
22
+ "./factories": "./build/factories/main.js",
19
23
  "./types": "./build/src/types.js"
20
24
  },
21
25
  "scripts": {
@@ -39,12 +43,9 @@
39
43
  "author": "virk,adonisjs",
40
44
  "license": "MIT",
41
45
  "devDependencies": {
42
- "@adonisjs/application": "^7.1.2-0",
43
- "@adonisjs/config": "^4.2.1-0",
44
- "@adonisjs/env": "^4.2.0-0",
45
- "@adonisjs/fold": "^9.9.3-0",
46
- "@adonisjs/logger": "^5.4.2-0",
47
- "@commitlint/cli": "^17.4.4",
46
+ "@adonisjs/application": "^7.1.2-3",
47
+ "@adonisjs/fold": "^9.9.3-4",
48
+ "@commitlint/cli": "^17.5.0",
48
49
  "@commitlint/config-conventional": "^17.4.4",
49
50
  "@japa/assert": "^1.4.1",
50
51
  "@japa/expect-type": "^1.0.3",
@@ -52,30 +53,30 @@
52
53
  "@japa/run-failed-tests": "^1.1.1",
53
54
  "@japa/runner": "^2.5.1",
54
55
  "@japa/spec-reporter": "^1.3.3",
55
- "@poppinss/dev-utils": "^2.0.1",
56
- "@swc/core": "^1.3.37",
57
- "@types/node": "^18.14.6",
56
+ "@swc/core": "^1.3.42",
57
+ "@types/node": "^18.15.9",
58
58
  "c8": "^7.13.0",
59
59
  "cross-env": "^7.0.3",
60
60
  "del-cli": "^5.0.0",
61
- "eslint": "^8.35.0",
62
- "eslint-config-prettier": "^8.6.0",
61
+ "eslint": "^8.36.0",
62
+ "eslint-config-prettier": "^8.8.0",
63
63
  "eslint-plugin-adonis": "^3.0.3",
64
64
  "eslint-plugin-prettier": "^4.2.1",
65
- "github-label-sync": "^2.0.1",
65
+ "github-label-sync": "^2.3.1",
66
66
  "husky": "^8.0.3",
67
- "np": "^7.6.3",
68
- "prettier": "^2.8.4",
67
+ "np": "^7.6.4",
68
+ "prettier": "^2.8.7",
69
69
  "ts-node": "^10.9.1",
70
- "typescript": "^4.9.5"
70
+ "typescript": "^5.0.2"
71
71
  },
72
72
  "dependencies": {
73
+ "@poppinss/utils": "^6.5.0-1",
73
74
  "@sindresorhus/is": "^5.3.0",
74
75
  "emittery": "^1.0.1"
75
76
  },
76
77
  "peerDependencies": {
77
- "@adonisjs/application": "^7.1.2-0",
78
- "@adonisjs/fold": "^9.9.3-0"
78
+ "@adonisjs/application": "^7.1.2-3",
79
+ "@adonisjs/fold": "^9.9.3-4"
79
80
  },
80
81
  "repository": {
81
82
  "type": "git",
@@ -0,0 +1,45 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { RuntimeException } from '@poppinss/utils'
11
+ import type { Emitter } from './emitter.js'
12
+
13
+ /**
14
+ * Base event adds ability to a class to act as an event. You can emit the
15
+ * event by calling "Event.dispatch" method.
16
+ */
17
+ export class BaseEvent {
18
+ constructor(..._: any[]) {}
19
+
20
+ /**
21
+ * The emitter to use for dispatching events
22
+ */
23
+ static emitter?: Emitter<any>
24
+
25
+ /**
26
+ * Specify the emitter instance to use for dispatching events
27
+ */
28
+ static useEmitter(emitter: Emitter<any>) {
29
+ this.emitter = emitter
30
+ }
31
+
32
+ /**
33
+ * Dispatch the current class as an event. The method takes the arguments
34
+ * accepted by the class constructor.
35
+ */
36
+ static async dispatch<T extends typeof BaseEvent>(this: T, ...args: ConstructorParameters<T>) {
37
+ if (!this.emitter) {
38
+ throw new RuntimeException(
39
+ `Cannot dispatch "${this.name}" event. Make sure to pass emitter to the "BaseEvent" class for dispatch method to work`
40
+ )
41
+ }
42
+
43
+ return this.emitter.emit<T>(this, new this(...args) as InstanceType<T>)
44
+ }
45
+ }
package/src/debug.ts ADDED
@@ -0,0 +1,11 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { debuglog } from 'node:util'
11
+ export default debuglog('adonisjs:events')
package/src/emitter.ts ADDED
@@ -0,0 +1,407 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import is from '@sindresorhus/is'
11
+ import type { Application } from '@adonisjs/application'
12
+ import Emittery, { type UnsubscribeFunction } from 'emittery'
13
+ import { moduleExpression, moduleCaller, moduleImporter } from '@adonisjs/fold'
14
+
15
+ import debug from './debug.js'
16
+ import { EventsBuffer } from './events_buffer.js'
17
+ import type {
18
+ Listener,
19
+ LazyImport,
20
+ Constructor,
21
+ ListenerMethod,
22
+ AllowedEventTypes,
23
+ ListenerClassWithHandleMethod,
24
+ } from './types.js'
25
+
26
+ /**
27
+ * Event emitter is built on top of emittery with support class based
28
+ * events and listeners
29
+ */
30
+ export class Emitter<EventsList extends Record<string | symbol | number, any>> {
31
+ /**
32
+ * Event classes to symbols mapping. We need symbols as emittery
33
+ * does not support class based event names
34
+ */
35
+ #eventsClassSymbols: Map<Constructor<any>, symbol> = new Map()
36
+
37
+ /**
38
+ * A collection of events and their listeners. We do not track listeners
39
+ * listening for events only once
40
+ */
41
+ #eventsListeners: Map<
42
+ AllowedEventTypes,
43
+ Map<Listener<any, Constructor<any>>, ListenerMethod<any>>
44
+ > = new Map()
45
+
46
+ /**
47
+ * Underlying transport to emit events
48
+ */
49
+ #transport = new Emittery()
50
+
51
+ /**
52
+ * Events buffer. The events are collected inside an in-memory
53
+ * buffer during fakes
54
+ */
55
+ #eventsBuffer?: EventsBuffer<EventsList>
56
+
57
+ /**
58
+ * A set of events to fake
59
+ */
60
+ #eventsToFake: Set<AllowedEventTypes | '*'> = new Set()
61
+
62
+ /**
63
+ * Error handler to catch all errors thrown by listeners
64
+ */
65
+ #errorHandler?: (event: keyof EventsList | Constructor<any>, error: any, data: any) => void
66
+
67
+ /**
68
+ * Reference to AdonisJS application, we need the application root
69
+ * and container reference from it.
70
+ */
71
+ #app: Application<any>
72
+
73
+ /**
74
+ * Returns a map of events and their registered listeners. The
75
+ * map key is the event name and the value is another map
76
+ * of listeners.
77
+ *
78
+ * The listeners map key is the original binding listener
79
+ * and the value is a callback function.
80
+ */
81
+ get eventsListeners() {
82
+ return this.#eventsListeners
83
+ }
84
+
85
+ constructor(app: Application<any>) {
86
+ this.#app = app
87
+ }
88
+
89
+ /**
90
+ * Returns the symbol for a class based event.
91
+ */
92
+ #getEventClassSymbol(event: Constructor<any>): symbol {
93
+ if (!this.#eventsClassSymbols.has(event)) {
94
+ this.#eventsClassSymbols.set(event, Symbol(event.name))
95
+ }
96
+
97
+ return this.#eventsClassSymbols.get(event)!
98
+ }
99
+
100
+ /**
101
+ * Normalizes the event to emittery supported data types. The class
102
+ * constructors are cached against a unique symbol.
103
+ */
104
+ #resolveEvent(event: AllowedEventTypes): string | symbol | number {
105
+ if (is.class_(event)) {
106
+ return this.#getEventClassSymbol(event)
107
+ }
108
+
109
+ return event
110
+ }
111
+
112
+ /**
113
+ * Returns the event listeners map
114
+ */
115
+ #getEventListeners(event: AllowedEventTypes) {
116
+ if (!this.#eventsListeners.has(event)) {
117
+ this.#eventsListeners.set(event, new Map())
118
+ }
119
+
120
+ return this.#eventsListeners.get(event)!
121
+ }
122
+
123
+ /**
124
+ * Normalizes the event listener to a function that can be passed to
125
+ * emittery.
126
+ */
127
+ #normalizeEventListener(listener: Listener<any, Constructor>): ListenerMethod<any> {
128
+ /**
129
+ * Parse string based listener
130
+ */
131
+ if (typeof listener === 'string') {
132
+ return moduleExpression(listener, this.#app.appRoot).toCallable(this.#app.container)
133
+ }
134
+
135
+ /**
136
+ * Parse array based listener with the listener reference
137
+ * or lazily imported listener class
138
+ */
139
+ if (Array.isArray(listener)) {
140
+ const listenerModule = listener[0]
141
+ const method = listener[1] || 'handle'
142
+
143
+ /**
144
+ * Class reference
145
+ */
146
+ if (is.class_(listenerModule)) {
147
+ return moduleCaller(listenerModule, method).toCallable(this.#app.container)
148
+ }
149
+
150
+ /**
151
+ * Lazily loaded module
152
+ */
153
+ return moduleImporter(listenerModule, method).toCallable(this.#app.container)
154
+ }
155
+
156
+ return listener
157
+ }
158
+
159
+ /**
160
+ * Resolves the event listener either from the cache or normalizes
161
+ * it and stores it inside the cache
162
+ */
163
+ #resolveEventListener(
164
+ event: AllowedEventTypes,
165
+ listener: Listener<any, Constructor>
166
+ ): ListenerMethod<any> {
167
+ const eventListeners = this.#getEventListeners(event)
168
+ if (!eventListeners.has(listener)) {
169
+ eventListeners.set(listener, this.#normalizeEventListener(listener))
170
+ }
171
+
172
+ return eventListeners.get(listener)!
173
+ }
174
+
175
+ /**
176
+ * Register a global error handler
177
+ */
178
+ onError(
179
+ callback: (event: keyof EventsList | Constructor<any>, error: any, data: any) => void
180
+ ): this {
181
+ this.#errorHandler = callback
182
+ return this
183
+ }
184
+
185
+ /**
186
+ * Bind multiple listeners to listen for a single event. The listen
187
+ * method is a convenience helper to be used with class based
188
+ * events and listeners.
189
+ */
190
+ listen<Event extends Constructor<any>>(
191
+ event: Event,
192
+ listeners: (
193
+ | ListenerClassWithHandleMethod<InstanceType<Event>>
194
+ | LazyImport<ListenerClassWithHandleMethod<InstanceType<Event>>>
195
+ )[]
196
+ ) {
197
+ listeners.forEach((listener) => this.on(event, [listener, 'handle']))
198
+ }
199
+
200
+ /**
201
+ * Listen for an event. The method returns the unsubscribe function.
202
+ */
203
+ on<Event extends Constructor, ListenerClass extends Constructor>(
204
+ event: Event,
205
+ listener: Listener<InstanceType<Event>, ListenerClass>
206
+ ): UnsubscribeFunction
207
+ on<Name extends keyof EventsList, ListenerClass extends Constructor>(
208
+ event: Name,
209
+ listener: Listener<EventsList[Name], ListenerClass>
210
+ ): UnsubscribeFunction
211
+ on<Event extends AllowedEventTypes>(
212
+ event: Event,
213
+ listener: Listener<any, Constructor>
214
+ ): UnsubscribeFunction {
215
+ if (debug.enabled) {
216
+ debug('registering event listener, event: %O, listener: %O', event, listener)
217
+ }
218
+
219
+ const normalizedEvent = this.#resolveEvent(event)
220
+ const normalizedListener = this.#resolveEventListener(event, listener)
221
+
222
+ this.#transport.on(normalizedEvent, normalizedListener)
223
+ return () => this.off(event, listener)
224
+ }
225
+
226
+ /**
227
+ * Listen for an event only once
228
+ */
229
+ once<Event extends Constructor, ListenerClass extends Constructor>(
230
+ event: Event,
231
+ listener: Listener<InstanceType<Event>, ListenerClass>
232
+ ): void
233
+ once<Name extends keyof EventsList, ListenerClass extends Constructor>(
234
+ event: Name,
235
+ listener: Listener<EventsList[Name], ListenerClass>
236
+ ): void
237
+ once<Event extends AllowedEventTypes>(event: Event, listener: Listener<any, Constructor>): void {
238
+ if (debug.enabled) {
239
+ debug('registering one time event listener, event: %O, listener: %O', event, listener)
240
+ }
241
+
242
+ const normalizedEvent = this.#resolveEvent(event)
243
+ const normalizedListener = this.#normalizeEventListener(listener)
244
+
245
+ /**
246
+ * Listening for an event and unsubscribing right after the event is emitted.
247
+ * Internally emittery does the same thing, but they do not await the
248
+ * handler. Therefore, the "once" listeners will finish after the
249
+ * "emit" call. This behavior is not inline with the "on" event
250
+ * listeners.
251
+ */
252
+ const off = this.#transport.on(normalizedEvent, async (data) => {
253
+ off()
254
+ debug('removing one time event listener, event: %O', event)
255
+ await normalizedListener(data)
256
+ })
257
+ }
258
+
259
+ /**
260
+ * Attach a listener to listen for all the events. Wildcard listeners
261
+ * can only be defined as inline callbacks.
262
+ */
263
+ onAny(
264
+ listener: (event: AllowedEventTypes, data: any) => any | Promise<any>
265
+ ): UnsubscribeFunction {
266
+ return this.#transport.onAny(listener)
267
+ }
268
+
269
+ /**
270
+ * Emit event. The event listeners will be called asynchronously
271
+ * in parallel.
272
+ *
273
+ * You can await this method to wait for events listeners to finish
274
+ */
275
+ async emit<Event extends Constructor<any>>(event: Event, data: InstanceType<Event>): Promise<void>
276
+ async emit<Name extends keyof EventsList>(event: Name, data: EventsList[Name]): Promise<void>
277
+ async emit<Event extends AllowedEventTypes>(event: Event, data: any): Promise<void> {
278
+ /**
279
+ * Entertain fakes if exists
280
+ */
281
+ if (this.#eventsToFake.has(event) || this.#eventsToFake.has('*')) {
282
+ debug('faking emit. event: %O, data: %O', event, data)
283
+ this.#eventsBuffer!.add(event, data)
284
+ return
285
+ }
286
+
287
+ try {
288
+ const normalizedEvent = this.#resolveEvent(event)
289
+ await this.#transport.emit(normalizedEvent, data)
290
+ } catch (error) {
291
+ if (this.#errorHandler) {
292
+ this.#errorHandler(event, error, data)
293
+ } else {
294
+ throw error
295
+ }
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Remove a specific listener for an event
301
+ */
302
+ off(event: keyof EventsList | Constructor<any>, listener: Listener<any, Constructor<any>>): void {
303
+ if (debug.enabled) {
304
+ debug('removing listener, event: %O, listener: %O', event, listener)
305
+ }
306
+
307
+ const normalizedEvent = this.#resolveEvent(event)
308
+ const listeners = this.#getEventListeners(event)
309
+ const normalizedListener = listeners.get(listener)
310
+
311
+ if (!normalizedListener) {
312
+ return
313
+ }
314
+
315
+ listeners.delete(listener)
316
+ this.#transport.off(normalizedEvent, normalizedListener)
317
+ }
318
+
319
+ /**
320
+ * Remove a specific listener listening for all the events
321
+ */
322
+ offAny(
323
+ listener: (event: keyof EventsList | Constructor<any>, data: any) => any | Promise<any>
324
+ ): this {
325
+ this.#transport.offAny(listener)
326
+ return this
327
+ }
328
+
329
+ /**
330
+ * Remove a specific listener for an event
331
+ *
332
+ * @alias "off"
333
+ */
334
+ clearListener(
335
+ event: keyof EventsList | Constructor<any>,
336
+ listener: Listener<any, Constructor<any>>
337
+ ): void {
338
+ return this.off(event, listener)
339
+ }
340
+
341
+ /**
342
+ * Clear all listeners for a specific event
343
+ */
344
+ clearListeners(event: keyof EventsList | Constructor<any>) {
345
+ debug('clearing all listeners for event %O', event)
346
+ this.#transport.clearListeners(this.#resolveEvent(event))
347
+ this.#eventsListeners.delete(event)
348
+ }
349
+
350
+ /**
351
+ * Clear all listeners for all the events
352
+ */
353
+ clearAllListeners() {
354
+ debug('clearing all event listeners')
355
+ this.#transport.clearListeners()
356
+ this.#eventsListeners.clear()
357
+ }
358
+
359
+ /**
360
+ * Get count of listeners for a given event or all the events
361
+ */
362
+ listenerCount(event?: keyof EventsList | Constructor<any>): number {
363
+ return this.#transport.listenerCount(event ? this.#resolveEvent(event) : undefined)
364
+ }
365
+
366
+ /**
367
+ * Find if an event has one or more listeners
368
+ */
369
+ hasListeners(event?: keyof EventsList | Constructor<any>): boolean {
370
+ return this.listenerCount(event) > 0
371
+ }
372
+
373
+ /**
374
+ * Fake one or more events. The listeners for faked events will
375
+ * not be invoked.
376
+ *
377
+ * The return value is an events buffer that collects all the
378
+ * events within memory.
379
+ *
380
+ * Calling this method one than once drops the existing fakes and
381
+ * creates new one.
382
+ */
383
+ fake(events?: (keyof EventsList | Constructor<any>)[]): EventsBuffer<EventsList> {
384
+ this.restore()
385
+ this.#eventsBuffer = new EventsBuffer<EventsList>()
386
+
387
+ if (!events) {
388
+ debug('faking all events')
389
+ this.#eventsToFake.add('*')
390
+ } else {
391
+ debug('faking events: %O', events)
392
+ events.forEach((event) => this.#eventsToFake.add(event))
393
+ }
394
+
395
+ return this.#eventsBuffer
396
+ }
397
+
398
+ /**
399
+ * Restore fakes
400
+ */
401
+ restore() {
402
+ debug('restoring existing fakes')
403
+ this.#eventsToFake.clear()
404
+ this.#eventsBuffer?.flush()
405
+ this.#eventsBuffer = undefined
406
+ }
407
+ }
@@ -0,0 +1,168 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import is from '@sindresorhus/is'
11
+ import { AssertionError } from 'node:assert'
12
+ import type { AllowedEventTypes, BufferedEvent, BufferedEventsList, Constructor } from './types.js'
13
+
14
+ /**
15
+ * Exposes API to filter, find events from the events buffer.
16
+ */
17
+ export class EventsBuffer<EventsList extends Record<string | symbol | number, any>> {
18
+ /**
19
+ * Buffered events
20
+ */
21
+ #events: BufferedEventsList<EventsList>[] = []
22
+
23
+ /**
24
+ * Track emitted event
25
+ */
26
+ add<Name extends AllowedEventTypes>(event: Name, data: any): void {
27
+ this.#events.push({ event: event as any, data })
28
+ }
29
+
30
+ /**
31
+ * Get all the emitted events
32
+ */
33
+ all() {
34
+ return this.#events
35
+ }
36
+
37
+ /**
38
+ * Returns the size of captured events
39
+ */
40
+ size() {
41
+ return this.#events.length
42
+ }
43
+
44
+ /**
45
+ * Find if an event was emitted
46
+ */
47
+ exists<Event extends keyof EventsList | Constructor>(
48
+ finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)
49
+ ): boolean {
50
+ return !!this.find(finder)
51
+ }
52
+
53
+ /**
54
+ * Get selected events
55
+ */
56
+ filter(
57
+ finder: keyof EventsList | Constructor | ((event: BufferedEventsList<EventsList>) => boolean)
58
+ ): BufferedEventsList<EventsList>[] {
59
+ if (typeof finder === 'function' && !is.class_(finder)) {
60
+ return this.#events.filter(finder)
61
+ }
62
+
63
+ return this.#events.filter((event) => event.event === finder)
64
+ }
65
+
66
+ /**
67
+ * Find a specific event
68
+ */
69
+ find<Event extends keyof EventsList | Constructor>(
70
+ finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)
71
+ ):
72
+ | (Event extends keyof EventsList
73
+ ? BufferedEvent<Event, EventsList[Event]>
74
+ : Event extends Constructor<infer A>
75
+ ? BufferedEvent<Event, A>
76
+ : BufferedEventsList<EventsList>)
77
+ | null {
78
+ if (typeof finder === 'function' && !is.class_(finder)) {
79
+ return (this.#events.find(finder) || null) as any
80
+ }
81
+
82
+ return (this.#events.find((event) => event.event === finder) || null) as any
83
+ }
84
+
85
+ /**
86
+ * Assert a given event has been emitted
87
+ */
88
+ assertEmitted<Event extends keyof EventsList | Constructor>(
89
+ finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)
90
+ ): void {
91
+ const hasEvent = this.exists(finder)
92
+
93
+ if (!hasEvent) {
94
+ const isClass = is.class_(finder)
95
+ const message =
96
+ typeof finder === 'function' && !isClass
97
+ ? `Expected callback to find an emitted event`
98
+ : isClass
99
+ ? `Expected "${finder.name}" event to be emitted`
100
+ : `Expected "${String(finder)}" event to be emitted`
101
+
102
+ throw new AssertionError({
103
+ message: message,
104
+ expected: true,
105
+ actual: false,
106
+ operator: 'strictEqual',
107
+ stackStartFn: this.assertEmitted,
108
+ })
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Assert a given event has been not been emitted
114
+ */
115
+ assertNotEmitted<Event extends keyof EventsList | Constructor<any>>(
116
+ finder: Event | ((event: BufferedEventsList<EventsList>) => boolean)
117
+ ): void {
118
+ const hasEvent = this.exists(finder)
119
+
120
+ if (hasEvent) {
121
+ const isClass = is.class_(finder)
122
+ const message =
123
+ typeof finder === 'function' && !isClass
124
+ ? `Expected callback to not find any event`
125
+ : isClass
126
+ ? `Expected "${finder.name}" event to be not emitted`
127
+ : `Expected "${String(finder)}" event to be not emitted`
128
+
129
+ throw new AssertionError({
130
+ message: message,
131
+ expected: false,
132
+ actual: true,
133
+ operator: 'strictEqual',
134
+ stackStartFn: this.assertNotEmitted,
135
+ })
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Assert a given event has been not been emitted
141
+ */
142
+ assertNoneEmitted(): void {
143
+ const eventsSize = this.size()
144
+ if (eventsSize > 0) {
145
+ throw new AssertionError(
146
+ Object.assign(
147
+ {
148
+ message: `Expected zero events to be emitted. Instead received "${eventsSize}" event(s)`,
149
+ expected: 0,
150
+ actual: eventsSize,
151
+ operator: 'strictEqual',
152
+ stackStartFn: this.assertNoneEmitted,
153
+ },
154
+ {
155
+ showDiff: true,
156
+ }
157
+ )
158
+ )
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Flush events collected within memory
164
+ */
165
+ flush() {
166
+ this.#events = []
167
+ }
168
+ }
package/src/types.ts ADDED
@@ -0,0 +1,75 @@
1
+ /*
2
+ * @adonisjs/events
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ /**
11
+ * Data types for event name
12
+ */
13
+ export type AllowedEventTypes = string | symbol | number | Constructor
14
+
15
+ /**
16
+ * Class constructor type
17
+ */
18
+ export type Constructor<T = unknown> = new (...args: any[]) => T
19
+
20
+ /**
21
+ * A function that lazily imports a middleware
22
+ */
23
+ export type LazyImport<DefaultExport> = () => Promise<{ default: DefaultExport }>
24
+
25
+ /**
26
+ * Data structure for a buffered event
27
+ */
28
+ export type BufferedEvent<Event, Data> = { event: Event; data: Data }
29
+
30
+ /**
31
+ * Event list item inside bufferred items
32
+ */
33
+ export type BufferedEventsList<EventsList> =
34
+ | {
35
+ [Name in keyof EventsList]: BufferedEvent<Name, EventsList[Name]>
36
+ }[keyof EventsList]
37
+ | BufferedEvent<Constructor<any>, any>
38
+
39
+ /**
40
+ * Representation of listener method on the listener class. The
41
+ * spread args can type hint dependencies and container will
42
+ * resolve them
43
+ */
44
+ export type ListenerMethod<Data> = (data: Data, ...args: any[]) => any | Promise<any>
45
+
46
+ /**
47
+ * The event listener defined as an inline callback
48
+ */
49
+ export type ListenerFn<Data> = (data: Data) => any | Promise<any>
50
+
51
+ /**
52
+ * Returns a union of methods from a listener that accepts
53
+ * the event data as the first argument.
54
+ */
55
+ export type GetListenersMethods<Listener extends Constructor<any>, Data> = {
56
+ [K in keyof InstanceType<Listener>]: InstanceType<Listener>[K] extends ListenerMethod<Data>
57
+ ? K
58
+ : never
59
+ }[keyof InstanceType<Listener>]
60
+
61
+ /**
62
+ * Representation of listener class with handle method
63
+ */
64
+ export type ListenerClassWithHandleMethod<Data> = Constructor<{
65
+ handle: ListenerMethod<Data>
66
+ }>
67
+
68
+ /**
69
+ * The event listener defined as an inline callback, string
70
+ * listener class reference or a lazily imported listener
71
+ */
72
+ export type Listener<Data, ListenerClass extends Constructor> =
73
+ | ListenerFn<Data>
74
+ | string
75
+ | [LazyImport<ListenerClass> | ListenerClass, GetListenersMethods<ListenerClass, Data>?]
File without changes
File without changes