{"version":3,"file":"generations.mjs","names":["customEmitter: EventfulEmitter<Events>","res","res: EventfulPromise<Data, Events>","createEventfulPromise","generation: Omit<Generation, 'task'>"],"sources":["../../src/lib/promises.ts","../../src/helpers/generations/index.ts"],"sourcesContent":["// oxlint-disable-next-line prefer-node-protocol\nimport { EventEmitter } from 'native-events';\n\n// oxlint-disable-next-line no-explicit-any\ntype EventMap = Record<string, any[]>;\n\ninterface EventfulListener<Events extends EventMap> {\n  on: <Name extends keyof Events>(\n    eventName: Name,\n    listener: (...args: Events[Name]) => void\n  ) => this;\n  once: <Name extends keyof Events>(\n    eventName: Name,\n    listener: (...args: Events[Name]) => void\n  ) => this;\n  off: <Name extends keyof Events>(\n    eventName: Name,\n    listener: (...args: Events[Name]) => void\n  ) => this;\n}\ninterface EventfulEmitter<Events extends EventMap> {\n  emit: <Name extends keyof Events>(\n    eventName: Name,\n    ...args: Events[Name]\n  ) => this;\n}\n\nexport type EventfulPromise<Data, Events extends EventMap> = Promise<Data> &\n  EventfulListener<Events>;\n\n/**\n * Attach a `EventEmitter` to a `Promise` returned by the `executor`\n *\n * @param executor Executor returning the promise. The `emitter` is passed to the executor as param.\n * @param emitter `EventEmitter` attached. By default it's a new instance.\n *\n * @returns The EventfulPromise\n */\nconst createEventfulPromise = <Data, Events extends EventMap = EventMap>(\n  executor: (\n    emitter: EventfulEmitter<Events>,\n    resolve: (value: Data) => void\n  ) => Promise<Data | void>,\n  // oxlint-disable-next-line unicorn/prefer-event-target\n  emitter = new EventEmitter()\n): EventfulPromise<Data, Events> => {\n  const customEmitter: EventfulEmitter<Events> = {\n    emit: (eventName, ...args) => {\n      emitter.emit(eventName.toString(), ...args);\n      return customEmitter;\n    },\n  };\n\n  // oxlint-disable-next-line promise/avoid-new\n  const promise = new Promise<Data>((resolve, reject) => {\n    executor(customEmitter, resolve)\n      // oxlint-disable-next-line prefer-await-to-then\n      .then((res) => res && resolve(res))\n      // oxlint-disable-next-line prefer-await-to-then\n      .catch(reject);\n  });\n\n  const res: EventfulPromise<Data, Events> = Object.assign<\n    Promise<Data>,\n    EventfulListener<Events>\n  >(promise, {\n    on: (eventName, listener) => {\n      emitter.on(eventName.toString(), (...params) =>\n        // oxlint-disable-next-line no-explicit-any\n        listener(...(params as any))\n      );\n      return res;\n    },\n    once: (eventName, listener) => {\n      emitter.once(eventName.toString(), (...params) =>\n        // oxlint-disable-next-line no-explicit-any\n        listener(...(params as any))\n      );\n      return res;\n    },\n    off: (eventName, listener) => {\n      emitter.off(eventName.toString(), (...params) =>\n        // oxlint-disable-next-line no-explicit-any\n        listener(...(params as any))\n      );\n      return res;\n    },\n  });\n  return res;\n};\n\nexport default createEventfulPromise;\n","import { client } from '~/lib/fetch';\nimport createEventfulPromise, { type EventfulPromise } from '~/lib/promises';\n\nimport {\n  assignDependencies,\n  assignPermission,\n} from '~/helpers/permissions/decorator';\n\nimport { generateReportOfTask, getFileAsJson } from '~/modules/reports/methods';\nimport type { ReportResult } from '~/modules/reports/types';\nimport { getTask } from '~/modules/tasks/methods';\nimport type { Task } from '~/modules/tasks/types';\nimport { transformGeneration } from '~/modules/generations/methods';\nimport type {\n  GenerationStatus,\n  Generation,\n  RawGeneration,\n} from '~/modules/generations/types';\n\nexport interface GenerationStartedEvent {\n  id: string;\n}\n\nexport type GenerationProgressEvent = Omit<Generation, 'task'>;\n\n// oxlint-disable-next-line no-explicit-any\ninterface GenerationEvents extends Record<string, any[]> {\n  started: [GenerationStartedEvent];\n  progress: [GenerationProgressEvent];\n}\n\nconst GEN_END_STATES = new Set<GenerationStatus>([\n  'SUCCESS',\n  'ERROR',\n  'ABORTED',\n]);\n\nexport const isGenerationEnded = (gen: Generation): boolean =>\n  GEN_END_STATES.has(gen.status);\n\ntype ReportGenerationPromise = EventfulPromise<ReportResult, GenerationEvents>;\n\n/**\n * Start generation of a report and track progress\n *\n * @param taskOrId Task or Task's id\n * @param targets Override targets, also enable first level of debugging\n *\n * @fires #started When generation started. See `GenerationStartedEvent`.\n * @fires #progress When generation progress. See `GenerationProgressEvent`. Job's progress is\n * between 0 and 1\n *\n * @throws If job's fails. **Not if generation fails !**\n *\n * @returns When the report is ready, returns the report result\n */\nexport const generateAndListenReportOfTask = (\n  taskOrId: Omit<Task, 'template'> | string,\n  period?: { start: Date; end: Date },\n  targets?: string[]\n): ReportGenerationPromise =>\n  createEventfulPromise<ReportResult, GenerationEvents>(\n    async (events, resolve) => {\n      const task = await getTask(taskOrId);\n      const websocket = client.socket('/generations', [task.namespaceId]);\n      if (!websocket) {\n        throw new Error('Unable to get socket');\n      }\n\n      websocket.on(\n        'generation:updated',\n        function onGenerationUpdated(gen: Omit<RawGeneration, 'task'>) {\n          const generation: Omit<Generation, 'task'> = transformGeneration(gen);\n          // Notify progress if it's the correct task\n          if (generation.taskId !== task.id) {\n            return;\n          }\n          events.emit('progress', generation);\n\n          // If generation ended, stop listening\n          if (!isGenerationEnded(generation)) {\n            return;\n          }\n          websocket.off('generation:updated', onGenerationUpdated);\n\n          // And resolve result\n          getFileAsJson(taskOrId, `${generation.reportId}.det.json`)\n            // oxlint-disable-next-line prefer-await-to-then\n            .then((result) => resolve(result))\n            // oxlint-disable-next-line prefer-await-to-then\n            .catch((_err) => {\n              /** */\n            });\n        }\n      );\n\n      // Once events are registered, start generation\n      const { id } = await generateReportOfTask(taskOrId, period, targets);\n      events.emit('started', { id });\n    }\n  );\nassignDependencies(generateAndListenReportOfTask, [\n  getTask,\n  generateReportOfTask,\n  getFileAsJson,\n]);\n\n/**\n * Listen to all generations\n *\n * @param onUpdate Function to call when a generation is updated\n * @param namespaces Namespaces to listen to\n *\n * @returns Function to remove listener\n */\nexport function listenAllGenerations(\n  onUpdate: (generation: Omit<Generation, 'task'>) => void,\n  namespaces?: string[]\n): { stop: () => void } {\n  const websocket = client.socket('/generations', namespaces);\n  if (!websocket) {\n    throw new Error('Unable to get socket');\n  }\n\n  const updated = (gen: Omit<RawGeneration, 'task'>): void =>\n    onUpdate(transformGeneration(gen));\n\n  websocket.on('generation:updated', updated);\n\n  return {\n    stop: (): void => {\n      websocket.off('generation:updated', updated);\n    },\n  };\n}\n// Applies same permissions as `GET /generations/:id`\nassignPermission(listenAllGenerations, 'GET /generations/:id', true);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAsCA,MAAM,yBACJ,UAKA,UAAU,IAAI,cAAc,KACM;CAClC,MAAMA,gBAAyC,EAC7C,OAAO,WAAW,GAAG,SAAS;AAC5B,UAAQ,KAAK,UAAU,UAAU,EAAE,GAAG,KAAK;AAC3C,SAAO;IAEV;CAGD,MAAM,UAAU,IAAI,SAAe,SAAS,WAAW;AACrD,WAAS,eAAe,QAAQ,CAE7B,MAAM,UAAQC,SAAO,QAAQA,MAAI,CAAC,CAElC,MAAM,OAAO;GAChB;CAEF,MAAMC,MAAqC,OAAO,OAGhD,SAAS;EACT,KAAK,WAAW,aAAa;AAC3B,WAAQ,GAAG,UAAU,UAAU,GAAG,GAAG,WAEnC,SAAS,GAAI,OAAe,CAC7B;AACD,UAAO;;EAET,OAAO,WAAW,aAAa;AAC7B,WAAQ,KAAK,UAAU,UAAU,GAAG,GAAG,WAErC,SAAS,GAAI,OAAe,CAC7B;AACD,UAAO;;EAET,MAAM,WAAW,aAAa;AAC5B,WAAQ,IAAI,UAAU,UAAU,GAAG,GAAG,WAEpC,SAAS,GAAI,OAAe,CAC7B;AACD,UAAO;;EAEV,CAAC;AACF,QAAO;;AAGT,uBAAe;;;;AC5Df,MAAM,iBAAiB,IAAI,IAAsB;CAC/C;CACA;CACA;CACD,CAAC;AAEF,MAAa,qBAAqB,QAChC,eAAe,IAAI,IAAI,OAAO;;;;;;;;;;;;;;;AAkBhC,MAAa,iCACX,UACA,QACA,YAEAC;yCACS,QAAQ,SAAY;EACzB,MAAM,aAAa,QAAQ,SAAS;EACpC,MAAM,YAAY,OAAO,OAAO,gBAAgB,CAAC,KAAK,YAAY,CAAC;AACnE,MAAI,CAAC,UACH,OAAM,IAAI,MAAM,uBAAuB;AAGzC,YAAU,GACR,sBACA,SAAS,oBAAoB,KAAkC;GAC7D,MAAMC,aAAuC,oBAAoB,IAAI;AAErE,OAAI,WAAW,WAAW,KAAK,GAC7B;AAEF,UAAO,KAAK,YAAY,WAAW;AAGnC,OAAI,CAAC,kBAAkB,WAAW,CAChC;AAEF,aAAU,IAAI,sBAAsB,oBAAoB;AAGxD,iBAAc,UAAU,GAAG,WAAW,SAAS,WAAW,CAEvD,MAAM,WAAW,QAAQ,OAAO,CAAC,CAEjC,OAAO,SAAS;;KAEf;IAEP;EAGD,MAAM,EAAE,aAAa,qBAAqB,UAAU,QAAQ,QAAQ;AACpE,SAAO,KAAK,WAAW,EAAE,IAAI,CAAC;;iBApCzB,IAAQ;;;IAsChB;AACH,mBAAmB,+BAA+B;CAChD;CACA;CACA;CACD,CAAC;;;;;;;;;AAUF,SAAgB,qBACd,UACA,YACsB;CACtB,MAAM,YAAY,OAAO,OAAO,gBAAgB,WAAW;AAC3D,KAAI,CAAC,UACH,OAAM,IAAI,MAAM,uBAAuB;CAGzC,MAAM,WAAW,QACf,SAAS,oBAAoB,IAAI,CAAC;AAEpC,WAAU,GAAG,sBAAsB,QAAQ;AAE3C,QAAO,EACL,YAAkB;AAChB,YAAU,IAAI,sBAAsB,QAAQ;IAE/C;;AAGH,iBAAiB,sBAAsB,wBAAwB,KAAK"}