{"version":3,"file":"graph-reports-B6yoYbPq.mjs","names":[],"sources":["../src/mcp/graph-reports.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { chmod, mkdir, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport * as z from 'zod'\nimport { normalizeGraphPayload } from '../viz/graph-normalizer.js'\nimport { workspaceOutputPaths } from '../workspace/output-root.js'\n\nconst GraphReportInputSchema = z.object({\n  schema: z.literal('chain-insights.graph.v1'),\n  nodes: z.array(z.unknown()),\n  edges: z.array(z.unknown()),\n  flows: z.array(z.unknown()).optional(),\n  edge_anchors: z.array(z.unknown()).optional(),\n}).passthrough()\n\nexport type GraphReportRef = {\n  schema: 'chain-insights.graph.v1'\n  filename: string\n  url: string\n  path: string\n}\n\nexport type WriteGraphReportOptions = {\n  serverPort: number\n  slug: string\n}\n\nfunction graphPayloadSchema(graphData: unknown): string {\n  return typeof graphData === 'object' && graphData !== null && 'schema' in graphData\n    ? String(graphData.schema)\n    : 'unknown'\n}\n\nfunction sanitizeSlug(slug: string): string {\n  const sanitized = slug\n    .toLowerCase()\n    .replace(/[^a-z0-9._-]+/g, '-')\n    .replace(/-+/g, '-')\n    .replace(/^[._-]+|[._-]+$/g, '')\n  return sanitized || 'graph'\n}\n\nfunction timestampSegment(date = new Date()): string {\n  return date.toISOString().replace(/[-:.]/g, '')\n}\n\nfunction uniqueFilename(slug: string): string {\n  const suffix = randomUUID().replace(/-/g, '').slice(0, 12)\n  return `${timestampSegment()}-${sanitizeSlug(slug)}-${suffix}.graph.json`\n}\n\nasync function ensurePrivateDirectory(dir: string): Promise<void> {\n  await mkdir(dir, { recursive: true, mode: 0o700 })\n  await chmod(dir, 0o700)\n}\n\nexport async function writeGraphReport(\n  graphData: unknown,\n  options: WriteGraphReportOptions,\n): Promise<GraphReportRef> {\n  const parsed = GraphReportInputSchema.safeParse(graphData)\n  if (!parsed.success) {\n    const schema = graphPayloadSchema(graphData)\n    if (schema !== 'chain-insights.graph.v1') {\n      throw new Error(`Unsupported graph payload schema: ${schema}`)\n    }\n\n    throw new Error('Invalid graph payload: nodes and edges must be arrays; flows and edge_anchors must be arrays when present')\n  }\n\n  const normalized = normalizeGraphPayload({\n    ...parsed.data,\n    flows: parsed.data.flows ?? [],\n    edge_anchors: parsed.data.edge_anchors ?? [],\n  })\n  const paths = workspaceOutputPaths()\n  const filename = uniqueFilename(options.slug)\n  const filePath = path.join(paths.reportGraphsRoot, filename)\n\n  await ensurePrivateDirectory(paths.reportsRoot)\n  await ensurePrivateDirectory(paths.reportGraphsRoot)\n  await writeFile(filePath, JSON.stringify(normalized, null, 2) + '\\n', { mode: 0o600 })\n\n  return {\n    schema: normalized.schema,\n    filename,\n    path: filePath,\n    url: `http://127.0.0.1:${options.serverPort}/graph-reports/${filename}`,\n  }\n}\n"],"mappings":";;;;;;;AAOA,MAAM,yBAAyB,EAAE,OAAO;CACtC,QAAQ,EAAE,QAAQ,yBAAyB;CAC3C,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC;CAC1B,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC;CAC1B,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS;CACrC,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS;AAC9C,CAAC,CAAC,CAAC,YAAY;AAcf,SAAS,mBAAmB,WAA4B;CACtD,OAAO,OAAO,cAAc,YAAY,cAAc,QAAQ,YAAY,YACtE,OAAO,UAAU,MAAM,IACvB;AACN;AAEA,SAAS,aAAa,MAAsB;CAM1C,OALkB,KACf,YAAY,CAAC,CACb,QAAQ,kBAAkB,GAAG,CAAC,CAC9B,QAAQ,OAAO,GAAG,CAAC,CACnB,QAAQ,oBAAoB,EAChB,KAAK;AACtB;AAEA,SAAS,iBAAiB,uBAAO,IAAI,KAAK,GAAW;CACnD,OAAO,KAAK,YAAY,CAAC,CAAC,QAAQ,UAAU,EAAE;AAChD;AAEA,SAAS,eAAe,MAAsB;CAC5C,MAAM,SAAS,WAAW,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,EAAE;CACzD,OAAO,GAAG,iBAAiB,EAAE,GAAG,aAAa,IAAI,EAAE,GAAG,OAAO;AAC/D;AAEA,eAAe,uBAAuB,KAA4B;CAChE,MAAM,MAAM,KAAK;EAAE,WAAW;EAAM,MAAM;CAAM,CAAC;CACjD,MAAM,MAAM,KAAK,GAAK;AACxB;AAEA,eAAsB,iBACpB,WACA,SACyB;CACzB,MAAM,SAAS,uBAAuB,UAAU,SAAS;CACzD,IAAI,CAAC,OAAO,SAAS;EACnB,MAAM,SAAS,mBAAmB,SAAS;EAC3C,IAAI,WAAW,2BACb,MAAM,IAAI,MAAM,qCAAqC,QAAQ;EAG/D,MAAM,IAAI,MAAM,2GAA2G;CAC7H;CAEA,MAAM,aAAa,sBAAsB;EACvC,GAAG,OAAO;EACV,OAAO,OAAO,KAAK,SAAS,CAAC;EAC7B,cAAc,OAAO,KAAK,gBAAgB,CAAC;CAC7C,CAAC;CACD,MAAM,QAAQ,qBAAqB;CACnC,MAAM,WAAW,eAAe,QAAQ,IAAI;CAC5C,MAAM,WAAW,KAAK,KAAK,MAAM,kBAAkB,QAAQ;CAE3D,MAAM,uBAAuB,MAAM,WAAW;CAC9C,MAAM,uBAAuB,MAAM,gBAAgB;CACnD,MAAM,UAAU,UAAU,KAAK,UAAU,YAAY,MAAM,CAAC,IAAI,MAAM,EAAE,MAAM,IAAM,CAAC;CAErF,OAAO;EACL,QAAQ,WAAW;EACnB;EACA,MAAM;EACN,KAAK,oBAAoB,QAAQ,WAAW,iBAAiB;CAC/D;AACF"}