{"version":3,"file":"hook.mjs","names":[],"sources":["../../src/assembly/hook.ts"],"sourcesContent":["import { combine } from '../util/mergeInto'\n\n/**\n * A typed publish/subscribe hook used to assemble SDK events.\n *\n * Multiple callbacks can be registered. When `trigger` is called, each callback receives the same\n * `params` and may return:\n * - A `Result` value — merged with the other callbacks' results via `combine`.\n * - `SKIPPED` — this callback contributes nothing; processing continues.\n * - `DISCARDED` — the entire event is dropped; no further callbacks are invoked.\n *\n * @typeParam Params - The input passed to every registered callback.\n * @typeParam Result - The type of the assembled output value.\n */\nexport interface Hook<Params, Result> {\n  /** Registers a callback and returns a handle to unregister it. */\n  register(this: void, callback: (params: Params) => Result | DISCARDED | SKIPPED): { unregister: () => void }\n  /**\n   * Invokes all registered callbacks with `params` and deep-merges their results.\n   * Returns `DISCARDED` if any callback discards the event, or `undefined` if no callback\n   * returns a result.\n   */\n  trigger(this: void, params: Params): Result | DISCARDED | undefined\n}\n\n/**\n * Creates a new `Hook` instance with no registered callbacks.\n *\n * @typeParam Params - The input type passed to registered callbacks.\n * @typeParam Result - The return type that callbacks contribute to.\n */\nexport function createHook<Params, Result>(): Hook<Params, Result> {\n  type Callback = (params: Params) => Result | DISCARDED | SKIPPED\n  let callbacks: Callback[] = []\n\n  return {\n    register(callback) {\n      callbacks.push(callback)\n      return {\n        unregister() {\n          callbacks = callbacks.filter((cb) => cb !== callback)\n        },\n      }\n    },\n    trigger(params) {\n      const results: Result[] = []\n      for (const callback of callbacks) {\n        const result = callback(params)\n        if (result === DISCARDED) {\n          return DISCARDED\n        }\n        if (result === SKIPPED) {\n          continue\n        }\n        results.push(result)\n      }\n      return combine(...(results as [unknown, unknown])) as Result\n    },\n  }\n}\n\n/** Sentinel returned by a hook callback to discard the entire event (no further callbacks are invoked). */\nexport const DISCARDED = 'DISCARDED'\n/** Sentinel returned by a hook callback to opt out of contributing a result (other callbacks still run). */\nexport const SKIPPED = 'SKIPPED'\n\nexport type DISCARDED = typeof DISCARDED\nexport type SKIPPED = typeof SKIPPED\n"],"mappings":";;;;;;;;AA+BA,SAAgB,aAAmD;CAEjE,IAAI,YAAwB,CAAC;CAE7B,OAAO;EACL,SAAS,UAAU;GACjB,UAAU,KAAK,QAAQ;GACvB,OAAO,EACL,aAAa;IACX,YAAY,UAAU,QAAQ,OAAO,OAAO,QAAQ;GACtD,EACF;EACF;EACA,QAAQ,QAAQ;GACd,MAAM,UAAoB,CAAC;GAC3B,KAAK,MAAM,YAAY,WAAW;IAChC,MAAM,SAAS,SAAS,MAAM;IAC9B,IAAI,WAAA,aACF,OAAO;IAET,IAAI,WAAA,WACF;IAEF,QAAQ,KAAK,MAAM;GACrB;GACA,OAAO,QAAQ,GAAI,OAA8B;EACnD;CACF;AACF;;AAGA,MAAa,YAAY;;AAEzB,MAAa,UAAU"}