{"version":3,"file":"diagnostic.mjs","sources":["../../src/utils/diagnostic.ts"],"sourcesContent":["import { EventEmitter } from 'events';\n\nexport interface IDiagnosticReporterOptions {\n  stackSize?: number;\n}\n\nexport type GenericDiagnostic<K extends DiagnosticKind, T = unknown> = {\n  kind: K;\n  details: {\n    message: string;\n    createdAt: Date;\n  } & T;\n};\n\nexport type DiagnosticKind = 'error' | 'warning' | 'info';\n\nexport type DiagnosticListener<T extends DiagnosticKind = DiagnosticKind> = (\n  diagnostic: { kind: T } & Diagnostic extends infer U ? U : never\n) => void | Promise<void>;\n\nexport type DiagnosticEvent = 'diagnostic' | `diagnostic.${DiagnosticKind}`;\n\nexport type GetEventListener<E extends DiagnosticEvent> = E extends 'diagnostic'\n  ? DiagnosticListener\n  : E extends `diagnostic.${infer K}`\n    ? K extends DiagnosticKind\n      ? DiagnosticListener<K>\n      : never\n    : never;\n\nexport type Diagnostic = ErrorDiagnostic | WarningDiagnostic | InfoDiagnostic;\n\nexport type ErrorDiagnosticSeverity = 'fatal' | 'error' | 'silly';\n\nexport type ErrorDiagnostic = GenericDiagnostic<\n  'error',\n  {\n    name: string;\n    severity: ErrorDiagnosticSeverity;\n    error: Error;\n  }\n>;\n\nexport type WarningDiagnostic = GenericDiagnostic<\n  'warning',\n  {\n    origin?: string;\n  }\n>;\n\nexport type InfoDiagnostic<T = unknown> = GenericDiagnostic<\n  'info',\n  {\n    origin?: string;\n    params?: T;\n  }\n>;\n\nexport interface IDiagnosticReporter {\n  stack: {\n    readonly size: number;\n    readonly items: Diagnostic[];\n  };\n\n  report(diagnostic: Diagnostic): IDiagnosticReporter;\n  onDiagnostic(listener: DiagnosticListener): IDiagnosticReporter;\n  on<T extends DiagnosticKind>(kind: T, listener: DiagnosticListener<T>): IDiagnosticReporter;\n}\n\nconst createDiagnosticReporter = (\n  options: IDiagnosticReporterOptions = {}\n): IDiagnosticReporter => {\n  const { stackSize = -1 } = options;\n\n  const emitter = new EventEmitter();\n  const stack: Diagnostic[] = [];\n\n  const addListener = <T extends DiagnosticEvent>(event: T, listener: GetEventListener<T>) => {\n    emitter.on(event, listener);\n  };\n\n  const isDiagnosticValid = (diagnostic: Diagnostic) => {\n    if (!diagnostic.kind || !diagnostic.details || !diagnostic.details.message) {\n      return false;\n    }\n    return true;\n  };\n\n  return {\n    stack: {\n      get size() {\n        return stack.length;\n      },\n\n      get items() {\n        return stack;\n      },\n    },\n\n    report(diagnostic: Diagnostic) {\n      if (!isDiagnosticValid(diagnostic)) {\n        return this;\n      }\n\n      emitter.emit('diagnostic', diagnostic);\n      emitter.emit(`diagnostic.${diagnostic.kind}`, diagnostic);\n\n      if (stackSize !== -1 && stack.length >= stackSize) {\n        stack.shift();\n      }\n\n      stack.push(diagnostic);\n\n      return this;\n    },\n\n    onDiagnostic(listener: DiagnosticListener) {\n      addListener('diagnostic', listener);\n\n      return this;\n    },\n\n    on<T extends DiagnosticKind>(kind: T, listener: DiagnosticListener<T>) {\n      addListener(`diagnostic.${kind}`, listener as never);\n\n      return this;\n    },\n  };\n};\n\nexport { createDiagnosticReporter };\n"],"names":["createDiagnosticReporter","options","stackSize","emitter","EventEmitter","stack","addListener","event","listener","on","isDiagnosticValid","diagnostic","kind","details","message","size","length","items","report","emit","shift","push","onDiagnostic"],"mappings":";;AAqEA,MAAMA,wBAA2B,GAAA,CAC/BC,OAAsC,GAAA,EAAE,GAAA;AAExC,IAAA,MAAM,EAAEC,SAAAA,GAAY,CAAC,CAAC,EAAE,GAAGD,OAAAA;AAE3B,IAAA,MAAME,UAAU,IAAIC,YAAAA,EAAAA;AACpB,IAAA,MAAMC,QAAsB,EAAE;IAE9B,MAAMC,WAAAA,GAAc,CAA4BC,KAAUC,EAAAA,QAAAA,GAAAA;QACxDL,OAAQM,CAAAA,EAAE,CAACF,KAAOC,EAAAA,QAAAA,CAAAA;AACpB,KAAA;AAEA,IAAA,MAAME,oBAAoB,CAACC,UAAAA,GAAAA;AACzB,QAAA,IAAI,CAACA,UAAAA,CAAWC,IAAI,IAAI,CAACD,UAAAA,CAAWE,OAAO,IAAI,CAACF,UAAAA,CAAWE,OAAO,CAACC,OAAO,EAAE;YAC1E,OAAO,KAAA;AACT;QACA,OAAO,IAAA;AACT,KAAA;IAEA,OAAO;QACLT,KAAO,EAAA;AACL,YAAA,IAAIU,IAAO,CAAA,GAAA;AACT,gBAAA,OAAOV,MAAMW,MAAM;AACrB,aAAA;AAEA,YAAA,IAAIC,KAAQ,CAAA,GAAA;gBACV,OAAOZ,KAAAA;AACT;AACF,SAAA;AAEAa,QAAAA,MAAAA,CAAAA,CAAOP,UAAsB,EAAA;YAC3B,IAAI,CAACD,kBAAkBC,UAAa,CAAA,EAAA;AAClC,gBAAA,OAAO,IAAI;AACb;YAEAR,OAAQgB,CAAAA,IAAI,CAAC,YAAcR,EAAAA,UAAAA,CAAAA;YAC3BR,OAAQgB,CAAAA,IAAI,CAAC,CAAC,WAAW,EAAER,UAAWC,CAAAA,IAAI,CAAC,CAAC,EAAED,UAAAA,CAAAA;AAE9C,YAAA,IAAIT,cAAc,CAAC,CAAA,IAAKG,KAAMW,CAAAA,MAAM,IAAId,SAAW,EAAA;AACjDG,gBAAAA,KAAAA,CAAMe,KAAK,EAAA;AACb;AAEAf,YAAAA,KAAAA,CAAMgB,IAAI,CAACV,UAAAA,CAAAA;AAEX,YAAA,OAAO,IAAI;AACb,SAAA;AAEAW,QAAAA,YAAAA,CAAAA,CAAad,QAA4B,EAAA;AACvCF,YAAAA,WAAAA,CAAY,YAAcE,EAAAA,QAAAA,CAAAA;AAE1B,YAAA,OAAO,IAAI;AACb,SAAA;QAEAC,EAA6BG,CAAAA,CAAAA,IAAO,EAAEJ,QAA+B,EAAA;AACnEF,YAAAA,WAAAA,CAAY,CAAC,WAAW,EAAEM,IAAAA,CAAK,CAAC,EAAEJ,QAAAA,CAAAA;AAElC,YAAA,OAAO,IAAI;AACb;AACF,KAAA;AACF;;;;"}