{"version":3,"file":"target.cjs","sources":["../../../../src/mods/target.ts"],"sourcesContent":["import { Pin } from \"@hazae41/box\";\nimport { Future } from \"@hazae41/future\";\nimport { None, Option, Some } from \"@hazae41/option\";\nimport { WeakParameters } from \"libs/parameters/index.js\";\nimport { Awaitable } from \"libs/promises/index.js\";\nimport { Voidable } from \"libs/voidable/index.js\";\n\nexport type SuperEventDescriptor =\n  (...args: any) => any\n\nexport type SuperEventMap =\n  Record<string, SuperEventDescriptor>\n\nexport type SuperEventListener<T extends SuperEventDescriptor> =\n  (...params: WeakParameters<T>) => Awaitable<Voidable<Option<ReturnType<T>>>>\n\nexport type SuperEventWaiter<T extends SuperEventDescriptor, R> =\n  (future: Future<R>, ...params: WeakParameters<T>) => Awaitable<Voidable<Option<ReturnType<T>>>>\n\nexport class SuperEventTarget<M extends SuperEventMap> {\n\n  readonly #listeners = new Map<keyof M, Map<SuperEventListener<any>, AddEventListenerOptions & Disposable>>()\n\n  get listeners() {\n    return this.#listeners\n  }\n\n  /**\n   * Add a listener to an event\n   * @param type Event type //  \"abort\", \"error\", \"message\", \"close\"\n   * @param listener Event listener // (e) => new Some(123)\n   * @param options Options // { passive: true }\n   * @returns \n   */\n  on<K extends keyof M>(type: K, listener: SuperEventListener<M[K]>, options: AddEventListenerOptions = {}) {\n    let listeners = this.#listeners.get(type)\n\n    if (listeners === undefined) {\n      listeners = new Map<SuperEventListener<any>, AddEventListenerOptions & Disposable>()\n      this.#listeners.set(type, listeners)\n    }\n\n    const off = () => this.off(type, listener)\n\n    options.signal?.addEventListener(\"abort\", off, { passive: true })\n    const dispose = () => options.signal?.removeEventListener(\"abort\", off)\n\n    listeners.set(listener, { ...options, [Symbol.dispose]: () => dispose() })\n\n    return off\n  }\n\n  /**\n   * Remove a listener from an event\n   * @param type Event type //  \"abort\", \"error\", \"message\", \"close\"\n   * @param listener Event listener // (e) => console.log(\"hello\")\n   * @param options Just to look like DOM's EventTarget\n   * @returns \n   */\n  off<K extends keyof M>(type: K, listener: SuperEventListener<M[K]>) {\n    const listeners = this.#listeners.get(type)\n\n    if (!listeners)\n      return\n\n    using options = listeners.get(listener)\n\n    if (!options)\n      return\n\n    listeners.delete(listener)\n\n    if (listeners.size > 0)\n      return\n\n    this.#listeners.delete(type)\n  }\n\n  /**\n   * Dispatch an event to its listeners\n   * \n   * - Dispatch to active listeners sequencially\n   * - Return if one of the listeners returned something\n   * - Dispatch to passive listeners concurrently\n   * - Return if one of the listeners returned something\n   * - Return nothing\n   * @param params The object to emit\n   * @returns `Some` if the event \n   */\n  async emit<K extends keyof M>(type: K, ...params: WeakParameters<M[K]>): Promise<Option<ReturnType<M[K]>>> {\n    const listeners = this.#listeners.get(type) as Map<SuperEventListener<M[K]>, AddEventListenerOptions & Disposable> | undefined\n\n    if (!listeners)\n      return new None()\n\n    const promises = new Array<Promise<Voidable<Option<ReturnType<M[K]>>>>>()\n\n    for (const [listener, options] of listeners) {\n      if (options.passive)\n        continue\n      if (options.once)\n        this.off(type, listener)\n\n      const returned = await listener(...params)\n\n      if (returned == null)\n        continue\n      if (returned.isNone())\n        continue\n\n      return new Some(returned.get())\n    }\n\n    for (const [listener, options] of listeners) {\n      if (!options.passive)\n        continue\n      if (options.once)\n        this.off(type, listener)\n\n      const promise = Promise.resolve().then(() => listener(...params))\n\n      promises.push(promise)\n\n      continue\n    }\n\n    const returneds = await Promise.all(promises)\n\n    for (const returned of returneds) {\n      if (returned == null)\n        continue\n      if (returned.isNone())\n        continue\n\n      return new Some(returned.get())\n    }\n\n    return new None()\n  }\n\n  /**\n   * Like `.on`, but instead of returning to the target, capture the returned value in a future, and return nothing to the target\n   * @param type \n   * @param callback \n   * @returns \n   */\n  wait<K extends keyof M, R>(type: K, callback: SuperEventWaiter<M[K], R>) {\n    const future = new Future<R>()\n\n    const dispose = this.on(type, async (...params: WeakParameters<M[K]>) => {\n      return await callback(future, ...params)\n    }, { passive: true })\n\n    return Pin.with(future.promise, dispose)\n  }\n\n}\n"],"names":["None","Some","future","Future","Pin"],"mappings":"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"}