{"version":3,"file":"file.cjs","names":["EventSubscriber","path"],"sources":["../src/file.ts"],"sourcesContent":["/**\n * File subscriber for autotel.\n *\n * Appends each tracked event to a file as newline-delimited JSON (NDJSON).\n * Useful for AI agents, scripts, evals, and local debugging that want\n * structured events on disk without a hosted backend. Query the file with\n * `jq`, load it into a notebook, or feed it to an agent.\n *\n * @example\n * ```typescript\n * import { Event } from 'autotel/events';\n * import { FileSubscriber } from 'autotel-subscribers/file';\n *\n * const events = new Event('worker', {\n *   subscribers: [new FileSubscriber({ path: './telemetry/events.ndjson' })],\n * });\n * ```\n */\n\nimport { appendFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { EventSubscriber, type EventPayload } from './event-subscriber-base';\n\nexport interface FileSubscriberConfig {\n  /** File path to append newline-delimited JSON events to. */\n  path: string;\n  /** Enable or disable the subscriber. Default `true`. */\n  enabled?: boolean;\n  /** Pretty-print each event as indented JSON instead of one line. Default `false`. */\n  pretty?: boolean;\n  /** Create parent directories if they do not exist. Default `true`. */\n  mkdir?: boolean;\n  /**\n   * Transform a payload before writing. Return `null` to skip the event.\n   * Defaults to writing the normalized payload unchanged.\n   */\n  transform?: (payload: EventPayload) => Record<string, unknown> | null;\n}\n\nexport class FileSubscriber extends EventSubscriber {\n  readonly name = 'FileSubscriber';\n  readonly version = '1.0.0';\n\n  private readonly filePath: string;\n  private readonly pretty: boolean;\n  private readonly ensureDir: boolean;\n  private readonly transform?: (\n    payload: EventPayload,\n  ) => Record<string, unknown> | null;\n\n  /** Serializes writes so concurrent events never interleave on disk. */\n  private writeChain: Promise<void> = Promise.resolve();\n  private dirEnsured = false;\n\n  constructor(config: FileSubscriberConfig) {\n    super();\n    this.filePath = config.path;\n    this.enabled = config.enabled ?? true;\n    this.pretty = config.pretty ?? false;\n    this.ensureDir = config.mkdir ?? true;\n    this.transform = config.transform;\n  }\n\n  protected async sendToDestination(payload: EventPayload): Promise<void> {\n    if (!this.enabled) return;\n\n    const record = this.transform ? this.transform(payload) : payload;\n    if (record === null) return;\n\n    const json = this.pretty\n      ? JSON.stringify(record, null, 2)\n      : JSON.stringify(record);\n    const line = `${json}\\n`;\n\n    const run = this.writeChain.then(() => this.write(line));\n    // Keep the chain ordered and alive even if one write rejects; the failed\n    // write still rejects `run` so the base class can report it.\n    this.writeChain = run.catch(() => {});\n    await run;\n  }\n\n  private async write(line: string): Promise<void> {\n    if (this.ensureDir && !this.dirEnsured) {\n      const dir = path.dirname(this.filePath);\n      if (dir && dir !== '.') {\n        await mkdir(dir, { recursive: true });\n      }\n      this.dirEnsured = true;\n    }\n    await appendFile(this.filePath, line, 'utf8');\n  }\n\n  override async shutdown(): Promise<void> {\n    await this.writeChain;\n    await super.shutdown();\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,IAAa,iBAAb,cAAoCA,8CAAgB;CAClD,AAAS,OAAO;CAChB,AAAS,UAAU;CAEnB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CACjB,AAAiB;;CAKjB,AAAQ,aAA4B,QAAQ,QAAQ;CACpD,AAAQ,aAAa;CAErB,YAAY,QAA8B;EACxC,MAAM;EACN,KAAK,WAAW,OAAO;EACvB,KAAK,UAAU,OAAO,WAAW;EACjC,KAAK,SAAS,OAAO,UAAU;EAC/B,KAAK,YAAY,OAAO,SAAS;EACjC,KAAK,YAAY,OAAO;CAC1B;CAEA,MAAgB,kBAAkB,SAAsC;EACtE,IAAI,CAAC,KAAK,SAAS;EAEnB,MAAM,SAAS,KAAK,YAAY,KAAK,UAAU,OAAO,IAAI;EAC1D,IAAI,WAAW,MAAM;EAKrB,MAAM,OAAO,GAHA,KAAK,SACd,KAAK,UAAU,QAAQ,MAAM,CAAC,IAC9B,KAAK,UAAU,MAAM,EACJ;EAErB,MAAM,MAAM,KAAK,WAAW,WAAW,KAAK,MAAM,IAAI,CAAC;EAGvD,KAAK,aAAa,IAAI,YAAY,CAAC,CAAC;EACpC,MAAM;CACR;CAEA,MAAc,MAAM,MAA6B;EAC/C,IAAI,KAAK,aAAa,CAAC,KAAK,YAAY;GACtC,MAAM,MAAMC,kBAAK,QAAQ,KAAK,QAAQ;GACtC,IAAI,OAAO,QAAQ,KACjB,kCAAY,KAAK,EAAE,WAAW,KAAK,CAAC;GAEtC,KAAK,aAAa;EACpB;EACA,uCAAiB,KAAK,UAAU,MAAM,MAAM;CAC9C;CAEA,MAAe,WAA0B;EACvC,MAAM,KAAK;EACX,MAAM,MAAM,SAAS;CACvB;AACF"}