{"version":3,"file":"data.mjs","names":[],"sources":["../../../../src/batteries/media/engines/data.ts"],"sourcesContent":["/**\n * The deterministic text/data {@link @nhtio/adk/batteries/media/contracts!MediaEngine}:\n * seeds and conversions for the text-shaped family (txt/md/json/yaml/csv/html).\n *\n * @module @nhtio/adk/batteries/media/engines/data\n *\n * @remarks\n * The smallest engine in the fleet, and deliberately so: text-family media generation is a\n * literal (`''`, `'{}'`, a minimal HTML shell) and text-family conversion is a parse and a\n * re-serialize. Everything here is deterministic — same inputs, same bytes — and cross-env\n * (no `node:*` anywhere).\n *\n * Capabilities:\n *\n * - **generate**: `EMPTY_MIME` → txt, md, json, yaml, csv, html.\n * - **convert**: json ⇄ yaml (js-yaml), json ⇄ csv (papaparse), json → txt (pretty print).\n *\n * `papaparse` is an optional peer (lazily imported only for the csv edges); `js-yaml` is a\n * regular dependency of the library.\n */\n\nimport { MIME } from '../formats'\nimport { EMPTY_MIME } from '../contracts'\nimport { isError } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type * as PapaNS from 'papaparse'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\ntype PapaModule = typeof PapaNS\n\n/** Options for {@link dataEngine}. */\nexport interface DataEngineOptions {\n  /** Override the papaparse resolution (tests / custom builds). Default: `import('papaparse')`. */\n  papaparse?: () => PapaModule | Promise<PapaModule>\n}\n\n/** Literal seeds per generation target. */\nconst SEEDS: Record<string, { content: string; mimeType: string }> = {\n  txt: { content: '', mimeType: MIME.TXT },\n  md: { content: '', mimeType: MIME.MD },\n  json: { content: '{}', mimeType: MIME.JSON },\n  yaml: { content: '', mimeType: MIME.YAML },\n  csv: { content: '', mimeType: MIME.CSV },\n  html: {\n    content:\n      '<!doctype html>\\n<html>\\n<head><meta charset=\"utf-8\"></head>\\n<body></body>\\n</html>\\n',\n    mimeType: MIME.HTML,\n  },\n}\n\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder()\n\n/**\n * Construct the deterministic text/data engine.\n *\n * @param options - Optional module resolver override.\n * @returns The engine.\n */\nexport const dataEngine = (options: DataEngineOptions = {}): MediaEngine => {\n  let papaPromise: Promise<PapaModule> | undefined\n  const getPapa = (): Promise<PapaModule> => {\n    papaPromise ??= Promise.resolve(\n      options.papaparse\n        ? options.papaparse()\n        : import('papaparse').then((m) => ('default' in m ? m.default : m) as PapaModule)\n    ).catch((err) => {\n      const detail = isError(err) ? err.message : String(err)\n      throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n        `the data engine could not load its peer dependency \"papaparse\" (needed for csv conversion): ${detail} — install it (pnpm add papaparse)`,\n      ])\n    })\n    return papaPromise\n  }\n\n  const generate = async (request: ConvertRequest): Promise<ConvertResult> => {\n    const seed = SEEDS[request.to]\n    if (!seed) {\n      throw new Error(\n        `the data engine generates ${Object.keys(SEEDS).join(', ')}; requested \"${request.to}\"`\n      )\n    }\n    return {\n      outputs: [{ bytes: encoder.encode(seed.content), mimeType: seed.mimeType }],\n    }\n  }\n\n  const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n    const mime = request.mimeType.toLowerCase().split(';')[0].trim()\n    const text = decoder.decode(request.bytes)\n\n    if (mime === MIME.JSON && request.to === 'yaml') {\n      const { dump } = await import('js-yaml')\n      const value: unknown = JSON.parse(text)\n      return {\n        outputs: [{ bytes: encoder.encode(dump(value)), mimeType: MIME.YAML }],\n      }\n    }\n    if (mime === MIME.JSON && request.to === 'txt') {\n      const value: unknown = JSON.parse(text)\n      return {\n        outputs: [{ bytes: encoder.encode(JSON.stringify(value, null, 2)), mimeType: MIME.TXT }],\n      }\n    }\n    if (mime === MIME.JSON && request.to === 'csv') {\n      const Papa = await getPapa()\n      const value: unknown = JSON.parse(text)\n      if (!Array.isArray(value)) {\n        throw new Error(\n          'json → csv expects a JSON array (of arrays, or of flat objects) at the top level'\n        )\n      }\n      const csv = Papa.unparse(value as unknown[])\n      return { outputs: [{ bytes: encoder.encode(csv), mimeType: MIME.CSV }] }\n    }\n    if (mime === MIME.YAML && request.to === 'json') {\n      const { load } = await import('js-yaml')\n      const value = load(text)\n      return {\n        outputs: [{ bytes: encoder.encode(JSON.stringify(value ?? null)), mimeType: MIME.JSON }],\n      }\n    }\n    if (mime === MIME.CSV && request.to === 'json') {\n      const Papa = await getPapa()\n      const parsed = Papa.parse<string[]>(text.replace(/\\r\\n/g, '\\n').replace(/\\n+$/, ''), {\n        skipEmptyLines: true,\n      })\n      if (parsed.errors.length > 0) {\n        throw new Error(`csv parse failed: ${parsed.errors[0].message}`)\n      }\n      // Array-of-arrays, matching the battery's json table shape (soffice/sheetjs emit it too).\n      return {\n        outputs: [{ bytes: encoder.encode(JSON.stringify(parsed.data)), mimeType: MIME.JSON }],\n      }\n    }\n    throw new Error(`the data engine cannot convert ${request.mimeType} to \"${request.to}\"`)\n  }\n\n  return {\n    id: 'data',\n    converts: [\n      { from: [EMPTY_MIME], to: Object.keys(SEEDS), convert: generate },\n      { from: [MIME.JSON], to: ['yaml', 'txt', 'csv'], convert },\n      { from: [MIME.YAML], to: ['json'], convert },\n      { from: [MIME.CSV], to: ['json'], convert },\n    ],\n  }\n}\n"],"mappings":"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"}