@json-to-office/jto 1.2.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/cli.js +178 -31
  2. package/dist/cli.js.map +1 -1
  3. package/dist/client/assets/{HomePage-jkIz_s7u.js → HomePage-CeUQIXch.js} +44 -44
  4. package/dist/client/assets/HomePage-CeUQIXch.js.map +1 -0
  5. package/dist/client/assets/{JsonEditorPage-DR8UoROz.js → JsonEditorPage-4LrF2fB9.js} +3 -3
  6. package/dist/client/assets/{JsonEditorPage-DR8UoROz.js.map → JsonEditorPage-4LrF2fB9.js.map} +1 -1
  7. package/dist/client/assets/{MonacoPluginProvider-CE5NPGwN.js → MonacoPluginProvider-Bx_V_FaE.js} +3 -3
  8. package/dist/client/assets/MonacoPluginProvider-Bx_V_FaE.js.map +1 -0
  9. package/dist/client/assets/editor-D-REaAU9.js +9 -0
  10. package/dist/client/assets/editor-D-REaAU9.js.map +1 -0
  11. package/dist/client/assets/editor-monaco-json-BgziSLMV.js +24 -0
  12. package/dist/client/assets/editor-monaco-json-BgziSLMV.js.map +1 -0
  13. package/dist/client/assets/editor-refs-store-vzLK2-Zo.js +2 -0
  14. package/dist/client/assets/{editor-refs-store-DKOJcTAk.js.map → editor-refs-store-vzLK2-Zo.js.map} +1 -1
  15. package/dist/client/assets/index-B7bDnXoC.js +5 -0
  16. package/dist/client/assets/index-B7bDnXoC.js.map +1 -0
  17. package/dist/client/assets/index-CrzIwHLS.css +1 -0
  18. package/dist/client/assets/preview-BGqIip90.js +2 -0
  19. package/dist/client/assets/preview-BGqIip90.js.map +1 -0
  20. package/dist/client/assets/{ui-vendor-DpjQWJgX.js → ui-vendor-Bq4-oNFL.js} +92 -57
  21. package/dist/client/assets/ui-vendor-Bq4-oNFL.js.map +1 -0
  22. package/dist/client/assets/useQualityAnalysis-CowAaoA9.js +6 -0
  23. package/dist/client/assets/useQualityAnalysis-CowAaoA9.js.map +1 -0
  24. package/dist/client/index.html +3 -3
  25. package/dist/client/templates/data-report-presentation.pptx.json +22 -22
  26. package/dist/client/templates/media/vermilion-annual-report/fonts/ClashDisplay-Bold.otf +0 -0
  27. package/dist/client/templates/media/vermilion-annual-report/fonts/ClashDisplay-Light.otf +0 -0
  28. package/dist/client/templates/media/vermilion-annual-report/fonts/ClashDisplay-Medium.otf +0 -0
  29. package/dist/client/templates/media/vermilion-annual-report/fonts/ClashDisplay-Regular.otf +0 -0
  30. package/dist/client/templates/media/vermilion-annual-report/fonts/ClashDisplay-Semibold.otf +0 -0
  31. package/dist/client/templates/media/vermilion-annual-report/fonts/FFL.txt +132 -0
  32. package/dist/client/templates/minimalist-pitch-deck.pptx.json +52 -52
  33. package/dist/client/templates/modern-annual-report-1.docx.json +2 -2
  34. package/dist/client/templates/modern-annual-report-2.docx.json +2 -2
  35. package/dist/client/templates/modern-annual-report-3.docx.json +1 -1
  36. package/dist/client/templates/tech-report.docx.json +8 -8
  37. package/dist/client/templates/themes/corporate.pptx.theme.json +12 -2
  38. package/dist/client/templates/themes/minimal.pptx.theme.json +12 -2
  39. package/dist/client/templates/themes/vibrant.pptx.theme.json +12 -2
  40. package/dist/client/templates/vermilion-annual-report.docx.json +10541 -0
  41. package/package.json +8 -7
  42. package/dist/client/assets/HomePage-jkIz_s7u.js.map +0 -1
  43. package/dist/client/assets/MonacoPluginProvider-CE5NPGwN.js.map +0 -1
  44. package/dist/client/assets/editor-edmvhW9F.js +0 -9
  45. package/dist/client/assets/editor-edmvhW9F.js.map +0 -1
  46. package/dist/client/assets/editor-monaco-json-CAlvfPc7.js +0 -24
  47. package/dist/client/assets/editor-monaco-json-CAlvfPc7.js.map +0 -1
  48. package/dist/client/assets/editor-refs-store-DKOJcTAk.js +0 -2
  49. package/dist/client/assets/index-CNvLzaJ7.css +0 -1
  50. package/dist/client/assets/index-DLlW4q4v.js +0 -5
  51. package/dist/client/assets/index-DLlW4q4v.js.map +0 -1
  52. package/dist/client/assets/preview-zo-CHAU0.js +0 -2
  53. package/dist/client/assets/preview-zo-CHAU0.js.map +0 -1
  54. package/dist/client/assets/ui-vendor-DpjQWJgX.js.map +0 -1
  55. package/dist/client/templates/Alternative deck 16_9.pptx.json +0 -3103
  56. package/dist/client/templates/Brand template 16_9.pptx.json +0 -2013
  57. package/dist/client/templates/Company deck 16_9.pptx.json +0 -6384
  58. package/dist/client/templates/Company deck 4_3.pptx.json +0 -5426
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.0_jiti@2.6.1_postcss@8.5.6_tsx@4.20.3_typescript@5.3.3_yaml@2.8.3/node_modules/tsup/assets/esm_shims.js","../src/server/config/index.ts","../src/server/config/api-info.ts","../src/server/utils/logger.ts","../src/server/services/generator.ts","../src/server/services/cache.ts","../src/server/services/libreoffice-converter.ts","../src/server/container/index.ts","../src/server/routes/health.ts","../src/server/schemas/loose.ts","../src/server/lib/typebox-validator.ts","../src/server/middleware/hono/rate-limit.ts","../src/server/security/outbound-source-policy.ts","../src/server/rasterize-route.ts","../src/server/services/template-media-inliner.ts","../src/server/routes/format.ts","../src/server/routes/discovery.ts","../src/server/services/ai-schema.ts","../src/server/services/prompt-loader.ts","../src/server/routes/ai.ts","../src/server/routes/fonts.ts","../src/server/middleware/hono/request-id.ts","../src/server/middleware/hono/auth.ts","../src/server/middleware/hono/error-handler.ts","../src/server/middleware/hono/security.ts","../src/server/middleware/hono/error-recovery.ts","../src/server/middleware/hono/request-logger.ts","../src/server/middleware/hono/concurrency-limit.ts","../src/server/app.ts","../src/server/unified-server.ts","../src/cli.ts","../src/commands/dev.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import dotenv from 'dotenv';\n\ndotenv.config();\n\nexport type ApiAuthMode = 'auto' | 'required' | 'disabled';\nexport type OutboundSourceMode = 'development' | 'safe';\n\nfunction positiveInteger(value: string | undefined, fallback: number): number {\n const parsed = Number.parseInt(value ?? '', 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n}\n\nfunction parseAuthMode(\n value: string | undefined,\n nodeEnv: 'development' | 'production' | 'test'\n): ApiAuthMode {\n if (value === 'auto' || value === 'required' || value === 'disabled') {\n return value;\n }\n // Public production APIs must opt out explicitly. Local playgrounds remain\n // zero-config; supplying a key there preserves the historical auto-enable.\n return nodeEnv === 'production' ? 'required' : 'auto';\n}\n\nfunction parseOutboundSourceMode(\n value: string | undefined,\n nodeEnv: 'development' | 'production' | 'test'\n): OutboundSourceMode {\n if (value === 'development' || value === 'safe') return value;\n return nodeEnv === 'production' ? 'safe' : 'development';\n}\n\n/**\n * Only the two explicitly local environments keep permissive defaults. Every\n * other value — `staging`, `prod`, a typo — gets production-grade hardening, so\n * a mislabelled deployment cannot silently disable auth, rate limits, or the\n * outbound-source (SSRF) checks.\n */\nfunction normalizeNodeEnv(\n value: string | undefined\n): 'development' | 'production' | 'test' {\n return value === 'development' || value === 'test' ? value : 'production';\n}\n\nfunction parseEnv(env: NodeJS.ProcessEnv) {\n const nodeEnv = normalizeNodeEnv(env.NODE_ENV || 'development');\n return {\n NODE_ENV: nodeEnv,\n // No PORT here: the listener is opened by the dev server from the CLI\n // config (`-p` > `server.port` > `PORT` env > format default), so a second\n // copy of it in this module would be silently ignored.\n CORS_ORIGIN: env.CORS_ORIGIN || '*',\n API_KEY: env.API_KEY,\n API_KEY_HEADER: env.API_KEY_HEADER || 'x-api-key',\n API_AUTH_MODE: parseAuthMode(env.API_AUTH_MODE, nodeEnv),\n RATE_LIMIT_WINDOW_MS: positiveInteger(env.RATE_LIMIT_WINDOW_MS, 900_000),\n RATE_LIMIT_MAX: positiveInteger(\n env.RATE_LIMIT_MAX,\n nodeEnv === 'production' ? 100 : 1000\n ),\n TRUST_PROXY_HEADERS: env.TRUST_PROXY_HEADERS === 'true',\n MAX_FILE_SIZE: positiveInteger(env.MAX_FILE_SIZE, 10 * 1024 * 1024),\n MAX_REQUEST_BODY_SIZE: positiveInteger(\n env.MAX_REQUEST_BODY_SIZE,\n 32 * 1024 * 1024\n ),\n MAX_CONCURRENT_REQUESTS: positiveInteger(\n env.MAX_CONCURRENT_REQUESTS,\n nodeEnv === 'production' ? 8 : 64\n ),\n OUTBOUND_SOURCE_MODE: parseOutboundSourceMode(\n env.OUTBOUND_SOURCE_MODE,\n nodeEnv\n ),\n OUTBOUND_HOST_ALLOWLIST: (env.OUTBOUND_HOST_ALLOWLIST || '')\n .split(',')\n .map((host) => host.trim().toLowerCase())\n .filter(Boolean),\n LIBREOFFICE_PATH: env.LIBREOFFICE_PATH,\n LIBREOFFICE_TIMEOUT_MS: env.LIBREOFFICE_TIMEOUT_MS\n ? positiveInteger(env.LIBREOFFICE_TIMEOUT_MS, 30000)\n : 30000,\n LOG_LEVEL: (env.LOG_LEVEL || 'info') as 'error' | 'warn' | 'info' | 'debug',\n CACHE_ENABLED: env.CACHE_ENABLED !== 'false',\n CACHE_MAX_SIZE_MB: positiveInteger(env.CACHE_MAX_SIZE_MB, 100),\n CACHE_TTL_SECONDS: positiveInteger(env.CACHE_TTL_SECONDS, 3600),\n CACHE_MAX_ITEMS: positiveInteger(env.CACHE_MAX_ITEMS, 1000),\n };\n}\n\nconst parsedEnv = parseEnv(process.env);\n\nexport const config = {\n ...parsedEnv,\n\n isDevelopment: parsedEnv.NODE_ENV === 'development',\n isProduction: parsedEnv.NODE_ENV === 'production',\n isTest: parsedEnv.NODE_ENV === 'test',\n\n features: {\n apiKey: parsedEnv.API_AUTH_MODE !== 'disabled',\n cache: parsedEnv.CACHE_ENABLED,\n },\n\n cors: {\n origin:\n parsedEnv.CORS_ORIGIN === '*'\n ? parsedEnv.CORS_ORIGIN\n : parsedEnv.CORS_ORIGIN.split(',').map((o) => o.trim()),\n credentials: true,\n },\n\n rateLimit: {\n windowMs: parsedEnv.RATE_LIMIT_WINDOW_MS,\n max: parsedEnv.RATE_LIMIT_MAX,\n trustProxy: parsedEnv.TRUST_PROXY_HEADERS,\n },\n\n requestLimits: {\n maxBodySize: parsedEnv.MAX_REQUEST_BODY_SIZE,\n maxConcurrent: parsedEnv.MAX_CONCURRENT_REQUESTS,\n maxFileSize: parsedEnv.MAX_FILE_SIZE,\n },\n\n outboundSources: {\n mode: parsedEnv.OUTBOUND_SOURCE_MODE,\n allowedHosts: parsedEnv.OUTBOUND_HOST_ALLOWLIST,\n },\n\n cache: {\n enabled: parsedEnv.CACHE_ENABLED,\n maxSizeMB: parsedEnv.CACHE_MAX_SIZE_MB,\n ttlSeconds: parsedEnv.CACHE_TTL_SECONDS,\n maxItems: parsedEnv.CACHE_MAX_ITEMS,\n },\n} as const;\n\nexport type ServerConfig = typeof config;\n","import { config } from './index.js';\n\nexport async function getApiInfo() {\n return {\n name: 'JSON to Office API',\n version: '1.0.0',\n description: 'Generate DOCX and PPTX documents from JSON definitions',\n environment: config.NODE_ENV,\n endpoints: {\n health: '/health',\n api: '/api',\n generate: '/api/{format}/generate',\n validate: '/api/{format}/validate',\n discovery: '/api/discovery',\n },\n };\n}\n","import { config } from '../config/index.js';\n\ntype LogLevel = 'error' | 'warn' | 'info' | 'debug';\n\ninterface LogContext {\n [key: string]: unknown;\n}\n\nclass Logger {\n private level: LogLevel;\n\n constructor(level: LogLevel = 'info') {\n this.level = level;\n }\n\n private shouldLog(level: LogLevel): boolean {\n const levels: LogLevel[] = ['error', 'warn', 'info', 'debug'];\n return levels.indexOf(level) <= levels.indexOf(this.level);\n }\n\n private formatMessage(level: LogLevel, message: string, context?: LogContext): string {\n const timestamp = new Date().toISOString();\n const contextStr = context\n ? ` ${JSON.stringify(context, this.errorReplacer)}`\n : '';\n return `[${timestamp}] [${level.toUpperCase()}] ${message}${contextStr}`;\n }\n\n private errorReplacer(_key: string, value: unknown): unknown {\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n stack: value.stack,\n };\n }\n return value;\n }\n\n private log(level: LogLevel, message: string, context?: LogContext): void {\n if (!this.shouldLog(level)) return;\n const formatted = this.formatMessage(level, message, context);\n switch (level) {\n case 'error': console.error(formatted); break;\n case 'warn': console.warn(formatted); break;\n case 'info': console.info(formatted); break;\n case 'debug': console.debug(formatted); break;\n }\n }\n\n error(message: string, context?: LogContext): void { this.log('error', message, context); }\n warn(message: string, context?: LogContext): void { this.log('warn', message, context); }\n info(message: string, context?: LogContext): void { this.log('info', message, context); }\n debug(message: string, context?: LogContext): void { this.log('debug', message, context); }\n}\n\nexport const logger = new Logger(config.LOG_LEVEL);\n","import {\n type FormatAdapter,\n cacheEvents,\n PluginRegistry,\n} from '@json-to-office/jto-cli';\nimport { CacheService } from './cache.js';\nimport { logger } from '../utils/logger.js';\nimport {\n collectFontNamesFromDocx,\n collectFontNamesFromPptx,\n POPULAR_GOOGLE_FONTS,\n getUpstreamOverride,\n isSafeFont,\n documentFontRegistry,\n themeFontRegistry,\n type FontRegistryEntry,\n type ResolvedFont,\n type GenerationWarning,\n} from '@json-to-office/shared';\n\n/**\n * Playground-only convenience: scan the document for font names that match\n * a POPULAR_GOOGLE_FONTS family and auto-build `fonts.extraEntries` so the\n * LibreOffice preview stager can materialise the bytes for PDF conversion.\n * The final .docx/.pptx does not embed them — substitution is the default\n * export mode.\n */\nexport function collectReferencedNames(\n config: unknown,\n customThemes: Record<string, unknown> | undefined,\n adapterName: 'docx' | 'pptx'\n): Set<string> {\n const collect =\n adapterName === 'docx'\n ? collectFontNamesFromDocx\n : collectFontNamesFromPptx;\n // Walk the doc AND every supplied custom theme — themes defined in a\n // separate .theme.json file contain font references the doc only names\n // indirectly (via `theme: \"myTheme\"`).\n const names = new Set<string>();\n for (const n of collect(config)) names.add(n);\n for (const theme of Object.values(customThemes ?? {})) {\n for (const n of collect(theme)) names.add(n);\n }\n return names;\n}\n\n/**\n * Walk the doc tree + custom themes for `fontWeight` numeric values. Used\n * to narrow `autoGoogleFontEntries` so cold-cache runs fetch only the\n * weights the doc actually needs instead of 18 faces per Google family.\n */\nexport function collectReferencedWeights(\n config: unknown,\n customThemes: Record<string, unknown> | undefined\n): Set<number> {\n const weights = new Set<number>();\n const visit = (node: unknown): void => {\n if (node == null) return;\n if (Array.isArray(node)) {\n for (const item of node) visit(item);\n return;\n }\n if (typeof node === 'object') {\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (\n k === 'fontWeight' &&\n typeof v === 'number' &&\n v >= 100 &&\n v <= 900\n ) {\n weights.add(v);\n } else {\n visit(v);\n }\n }\n }\n };\n visit(config);\n for (const theme of Object.values(customThemes ?? {})) visit(theme);\n return weights;\n}\n\n/**\n * Walk the doc tree + themes for any `italic: true`. Lets the override\n * variant filter drop italic faces entirely when the doc never uses them\n * (Inter's override is 18 variants — dropping italic halves the instancer\n * cost for upright-only docs).\n */\nexport function collectReferencedItalic(\n config: unknown,\n customThemes: Record<string, unknown> | undefined\n): boolean {\n let found = false;\n const visit = (node: unknown): void => {\n if (found || node == null) return;\n if (Array.isArray(node)) {\n for (const item of node) visit(item);\n return;\n }\n if (typeof node === 'object') {\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (k === 'italic' && v === true) {\n found = true;\n return;\n }\n visit(v);\n }\n }\n };\n visit(config);\n if (!found) {\n for (const theme of Object.values(customThemes ?? {})) {\n visit(theme);\n if (found) break;\n }\n }\n return found;\n}\n\n/**\n * A service-local warning carrying its OWN code. This used to be a bare\n * string and the code was hardcoded at the mapping site, so every message in\n * the array — including `FONT_WEIGHT_NOT_IN_OVERRIDE` — was published to\n * clients as `context.code === 'FONT_OVERRIDE_LOCAL'`, and any client\n * filtering on the code misclassified it.\n */\nexport interface SupplementalFontWarning {\n code: string;\n message: string;\n}\n\n/**\n * Turn service-local font warnings into the client-facing shape, preserving\n * each entry's own code. Informational: unlike core's `FONT_UNRESOLVED`,\n * none of these mean the document failed to resolve something.\n */\nexport function toSupplementalWarnings(\n warnings: readonly SupplementalFontWarning[]\n): GenerationWarning[] {\n return warnings.map(({ code, message }) => ({\n component: 'fontRegistry',\n message,\n severity: 'info' as const,\n context: { code },\n }));\n}\n\nexport function autoGoogleFontEntries(\n names: Set<string>,\n skipFamilies: Set<string>,\n referencedWeights?: Set<number>,\n referencedItalic?: boolean,\n warnings?: SupplementalFontWarning[]\n): FontRegistryEntry[] {\n const googleByLower = new Map(\n POPULAR_GOOGLE_FONTS.map((f) => [f.family.toLowerCase(), f])\n );\n const entries: FontRegistryEntry[] = [];\n for (const name of names) {\n if (isSafeFont(name)) continue;\n if (skipFamilies.has(name.toLowerCase())) continue;\n const match = googleByLower.get(name.toLowerCase());\n if (!match) continue;\n // Prefer an upstream override when one exists — bypasses Google's\n // redistribution for families with known metadata defects (Inter today).\n // Falls back to the Google Fonts CSS endpoint otherwise.\n // Narrow the fetched weight set to what the doc actually references.\n // Cold-cache fetches 1 file per (weight × italic) serially — Inter has\n // 18 faces advertised — so docs that only use 400/700 shouldn't pay\n // for all nine. When the doc references no explicit weights, fall\n // back to 400/700 (Regular + Bold). When it does, fetch those\n // weights (intersected with what the family advertises).\n const wanted = (() => {\n if (!referencedWeights || referencedWeights.size === 0) {\n const filtered = match.weights.filter((w) => w === 400 || w === 700);\n // Pathological catalog entries that advertise neither 400 nor\n // 700 would otherwise return []; fall back to the family's\n // lightest advertised weight (deterministic regardless of\n // catalog ordering) so the Google fetcher gets something\n // reproducible to work with.\n if (filtered.length > 0) return filtered;\n return match.weights.length > 0 ? [Math.min(...match.weights)] : [400];\n }\n const want = new Set<number>([400, ...referencedWeights]);\n const filtered = match.weights.filter((w) => want.has(w));\n return filtered.length > 0 ? filtered : [400];\n })();\n const override = getUpstreamOverride(match.family);\n if (override) {\n // Each override variant is already schema-shaped (kind: 'url' | 'variable'\n // with the right field set). Forward them straight through — the\n // registry's materializeSource switch handles both. Filter by the\n // narrowed weight set so instancing/fetching cost scales with doc\n // usage, not the full 9-weight catalog.\n //\n // The override is the source of truth for which weights exist, NOT\n // the catalog. Rebuild the wanted set from doc-referenced weights\n // directly so a narrow catalog (e.g. advertising only {400,700})\n // doesn't prune out valid override variants (e.g. weight 300).\n const overrideWantedSet = (() => {\n if (!referencedWeights || referencedWeights.size === 0) {\n return new Set<number>([400, 700]);\n }\n return new Set<number>([400, ...referencedWeights]);\n })();\n // Drop italic variants when the doc never requests italic. Halves the\n // instancer/fetch cost for upright-only docs (Inter's override ships 9\n // upright + 9 italic variants).\n const keepItalic = referencedItalic !== false;\n const variants = override.variants.filter(\n (v) => overrideWantedSet.has(v.weight) && (keepItalic || !v.italic)\n );\n let selected = variants;\n if (selected.length === 0) {\n // Referenced weights are all outside this override's advertised\n // variants. Fetching every variant is the legacy fallback; warn\n // so a typo (e.g. `fontWeight: 250`) surfaces instead of silently\n // inflating cold-cache cost.\n const missing = [...overrideWantedSet]\n .filter((w) => !override.variants.some((v) => v.weight === w))\n .sort((a, b) => a - b);\n warnings?.push({\n code: 'FONT_WEIGHT_NOT_IN_OVERRIDE',\n message: `FONT_WEIGHT_NOT_IN_OVERRIDE: family \"${match.family}\" — referenced weight(s) ${missing.join(', ')} not in upstream override (has ${override.variants\n .map((v) => v.weight)\n .filter((w, i, a) => a.indexOf(w) === i)\n .sort((a, b) => a - b)\n .join(', ')}). Fetching all override variants as a fallback.`,\n });\n selected = override.variants;\n }\n entries.push({\n id: match.family,\n family: match.family,\n sources: selected.map((v) =>\n v.kind === 'variable'\n ? {\n kind: 'variable' as const,\n url: v.url,\n weight: v.weight,\n italic: v.italic ?? false,\n ...(v.axes ? { axes: v.axes } : {}),\n }\n : {\n kind: 'url' as const,\n url: v.url,\n weight: v.weight,\n italic: v.italic ?? false,\n }\n ),\n });\n continue;\n }\n entries.push({\n id: match.family,\n family: match.family,\n sources: [\n {\n kind: 'google',\n family: match.family,\n weights: wanted,\n // Only request italics when the catalog advertises them. Requesting\n // italics for a family without italic variants (e.g. Inter) makes\n // Google return 404s that surface as `FONT_WEIGHT_UNAVAILABLE`\n // warnings and confuse diagnostics.\n italics: match.hasItalic,\n },\n ],\n });\n }\n return entries;\n}\n\nexport class GeneratorService {\n private adapter: FormatAdapter;\n private cacheService: CacheService;\n private cacheInvalidationHandler: (() => void) | null = null;\n\n constructor(adapter: FormatAdapter, cacheService: CacheService) {\n this.adapter = adapter;\n this.cacheService = cacheService;\n\n this.cacheInvalidationHandler = () => this.cacheService.clear();\n cacheEvents.on('generator:invalidate', this.cacheInvalidationHandler);\n }\n\n async generate(request: {\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: Record<string, unknown>;\n }): Promise<{\n filename: string;\n fileId?: string;\n buffer: Buffer;\n cached?: boolean;\n warnings?: GenerationWarning[] | null;\n resolvedFonts?: ResolvedFont[];\n }> {\n const { jsonDefinition, customThemes, options } = request;\n const config =\n typeof jsonDefinition === 'string'\n ? JSON.parse(jsonDefinition)\n : jsonDefinition;\n\n const referencedNames = collectReferencedNames(\n config,\n customThemes,\n this.adapter.name as 'docx' | 'pptx'\n );\n const referencedWeights = collectReferencedWeights(config, customThemes);\n const referencedItalic = collectReferencedItalic(config, customThemes);\n // Caller-supplied extraEntries (e.g. playground user uploads) win over the\n // auto-Google path. Build a skip-set of their family names so\n // `autoGoogleFontEntries` doesn't queue a parallel Google fetch for the\n // same family — which would race the local registration and, in the worst\n // case, override the caller's chosen bytes.\n const callerFonts = (options as { fonts?: Record<string, unknown> })?.fonts;\n const callerExtraEntriesRaw = (callerFonts as { extraEntries?: unknown })\n ?.extraEntries;\n const callerExtraEntries: FontRegistryEntry[] = Array.isArray(\n callerExtraEntriesRaw\n )\n ? (callerExtraEntriesRaw as FontRegistryEntry[])\n : [];\n const callerStrict =\n typeof (callerFonts as { strict?: unknown })?.strict === 'boolean'\n ? (callerFonts as { strict: boolean }).strict\n : undefined;\n const rawMode = callerFonts?.mode;\n const fontMode: 'substitute' | 'custom' | undefined =\n rawMode === 'substitute' || rawMode === 'custom' ? rawMode : undefined;\n const rawSub = callerFonts?.substitution;\n const fontSubstitution =\n rawSub && typeof rawSub === 'object' && !Array.isArray(rawSub)\n ? (rawSub as Record<string, string>)\n : undefined;\n // Families already declared by the caller, the document, or a theme. Any\n // of them outranks an auto-Google fetch, and `extraEntries` — where the\n // auto entries land — is the HIGHEST precedence group in the merge, so\n // omitting the document/theme families here would let Google's bytes\n // silently replace the ones the document ships with.\n const declaredFamilies = [\n ...callerExtraEntries,\n ...documentFontRegistry(config),\n ...Object.values(customThemes ?? {}).flatMap((t) => themeFontRegistry(t)),\n ];\n const callerFamilies = new Set(\n declaredFamilies.map((e) => e.family.toLowerCase())\n );\n // In substitute mode the doc's non-safe families are rewritten to safe\n // equivalents before font resolution runs, so an auto-Google fetch for\n // them is wasted work and — via `bypassCache` below — would disable the\n // server buffer cache for no benefit. Skip it.\n const overrideWarnings: SupplementalFontWarning[] = [];\n const autoEntries =\n fontMode === 'substitute'\n ? []\n : autoGoogleFontEntries(\n referencedNames,\n callerFamilies,\n referencedWeights,\n referencedItalic,\n overrideWarnings\n );\n const extraEntries = [...callerExtraEntries, ...autoEntries];\n // Surface the override so the caller can see their local file won vs a\n // would-be Google fetch. Collected later into the `warnings` array.\n if (callerExtraEntries.length > 0) {\n const googleFamiliesLower = new Set(\n POPULAR_GOOGLE_FONTS.map((f) => f.family.toLowerCase())\n );\n for (const e of callerExtraEntries) {\n const lower = e.family.toLowerCase();\n if (googleFamiliesLower.has(lower) && referencedNames.has(e.family)) {\n overrideWarnings.push({\n code: 'FONT_OVERRIDE_LOCAL',\n message: `[FONT_OVERRIDE_LOCAL] ${e.family}: caller-supplied source used; Google Fonts auto-fetch skipped for this family.`,\n });\n }\n }\n }\n // A document- or theme-declared registry is the third thing that makes\n // font resolution meaningful, alongside caller entries and the export-mode\n // selectors. Computed here rather than next to `fontOpts` because\n // `bypassCache` below has to see it.\n const declaresRegistry =\n documentFontRegistry(config).length > 0 ||\n Object.values(customThemes ?? {}).some(\n (t) => themeFontRegistry(t).length > 0\n );\n // Font resolution produces a side-channel (`resolvedFonts`) consumed by the\n // LibreOffice preview stager. The byte-cache can't round-trip that, so skip\n // the cache when auto-font resolution is needed — otherwise a cached buffer\n // returns without the TTFs the previewer needs. A declared registry counts:\n // its bytes are exactly what the stager would otherwise be missing.\n const bypassCache =\n options?.bypassCache === true ||\n extraEntries.length > 0 ||\n declaresRegistry;\n // Include font runtime selectors in the cache key so substitute vs\n // custom runs (same config+themes) don't collide on a single buffer\n // slot. `extraEntries` already forces bypassCache, so only need\n // mode/substitution/strict in the key for the non-bypass path.\n const baseDir =\n typeof (options as { baseDir?: unknown } | undefined)?.baseDir ===\n 'string'\n ? (options as { baseDir: string }).baseDir\n : undefined;\n // The backend is chosen per request, not per server: the playground's\n // point is comparing two of them on the same document.\n const renderer =\n typeof (options as { renderer?: unknown } | undefined)?.renderer ===\n 'string'\n ? (options as { renderer: string }).renderer\n : undefined;\n const cacheKeyData = {\n config,\n customThemes:\n customThemes && Object.keys(customThemes).length > 0\n ? customThemes\n : null,\n fontMode: fontMode ?? null,\n fontSubstitution: fontSubstitution ?? null,\n fontStrict: callerStrict ?? null,\n // Same definition, different source directory → different local assets.\n baseDir: baseDir ?? null,\n // Same document, different backend → different bytes. Without this,\n // switching backends would serve the other one's cached buffer.\n renderer: renderer ?? null,\n };\n const cacheKey = this.cacheService.generateCacheKey(cacheKeyData);\n const hasDynamicContent = this.cacheService.hasDynamicContent(config);\n\n // Try cache\n if (!bypassCache && !hasDynamicContent) {\n const cached = this.cacheService.get(cacheKey);\n if (cached) {\n logger.info('Served from cache', { title: config.metadata?.title });\n return {\n filename: `${config.metadata?.title || this.adapter.label}${this.adapter.extension}`,\n fileId: Date.now().toString(),\n buffer: cached.buffer,\n // Warnings ride along with the bytes: a cache hit describes the same\n // document, so it must report the same font problems.\n cached: true,\n warnings: cached.warnings,\n };\n }\n }\n\n // Generate — use plugin-aware generator when plugins are loaded\n logger.info(`Generating ${this.adapter.label}`, {\n title: config.metadata?.title,\n });\n const registry = PluginRegistry.getInstance();\n let buffer: Buffer;\n\n const resolvedFonts: ResolvedFont[] = [];\n // Forward fonts.mode + fonts.substitution + fonts.strict from the\n // request body so API consumers can opt into substitution, custom\n // (as-is), or strict-validation behaviour. Embedding is no longer\n // supported. `extraEntries` is authoritative in this flow:\n // caller-supplied entries were merged with auto-Google entries above\n // and are passed down unified here.\n // `declaresRegistry` (computed above, next to `bypassCache`) is what keeps\n // a document-declared registry from falling through every branch here:\n // without it the preview's `onResolved` listener is never registered,\n // `resolveDocumentFonts` short-circuits, and an uploaded font is validated\n // but never materialized — the preview then uses a host fallback.\n const needsFontOpts =\n extraEntries.length > 0 ||\n declaresRegistry ||\n fontMode !== undefined ||\n fontSubstitution !== undefined ||\n callerStrict !== undefined;\n const fontOpts = needsFontOpts\n ? {\n ...(extraEntries.length > 0 && { extraEntries }),\n ...(fontMode && { mode: fontMode }),\n ...(fontSubstitution && { substitution: fontSubstitution }),\n ...(callerStrict !== undefined && { strict: callerStrict }),\n onResolved: (r: ResolvedFont[]) => {\n resolvedFonts.push(...r);\n },\n }\n : undefined;\n\n // Per-request sink for core warnings. `createGenerator` is invoked per\n // request just below, so one generator never accumulates another\n // request's warnings.\n const coreWarnings: GenerationWarning[] = [];\n\n if (registry.hasPlugins()) {\n const plugins = registry.getPlugins();\n const generator = await this.adapter.createGenerator(plugins, {\n customThemes,\n fonts: fontOpts,\n baseDir,\n renderer,\n warnings: coreWarnings,\n });\n buffer = await generator.generateBuffer(config);\n } else {\n buffer = await this.adapter.generateBuffer(config, {\n customThemes,\n fonts: fontOpts,\n baseDir,\n renderer,\n warnings: coreWarnings,\n });\n }\n\n // Surface non-canonical fontWeight values (e.g. 450, 550) — the render\n // path silently coerces these to Regular/Bold via a bold-fallback, so\n // without a warning an author writing `fontWeight: 450` has no way to\n // know their intermediate weight was rounded away.\n const CANONICAL_WEIGHTS = new Set([\n 100, 200, 300, 400, 500, 600, 700, 800, 900,\n ]);\n const nonCanonical = [...referencedWeights].filter(\n (w) => !CANONICAL_WEIGHTS.has(w)\n );\n // Each entry keeps its own code: this array mixes FONT_OVERRIDE_LOCAL and\n // FONT_WEIGHT_NOT_IN_OVERRIDE, and clients filter on `context.code`.\n const extraWarnings: GenerationWarning[] =\n toSupplementalWarnings(overrideWarnings);\n for (const w of nonCanonical) {\n extraWarnings.push({\n component: 'fontRegistry',\n message: `[FONT_NONCANONICAL_WEIGHT] fontWeight ${w} is not one of 100/200/.../900; render path rounds to Regular or Bold via bold-only fallback.`,\n severity: 'info' as const,\n context: { code: 'FONT_NONCANONICAL_WEIGHT' },\n });\n }\n\n // Core first: FONT_UNRESOLVED is actionable and should read above the\n // informational FONT_OVERRIDE_LOCAL / FONT_NONCANONICAL_WEIGHT entries.\n const allWarnings = [...coreWarnings, ...extraWarnings];\n\n // Store in cache — buffer and warnings together, so a later HIT is not a\n // silent render. `resolvedFonts` deliberately stays out: it is a TTF byte\n // side-channel, and its only consumer passes `bypassCache: true`.\n this.cacheService.set(\n cacheKey,\n { buffer, warnings: allWarnings.length > 0 ? allWarnings : null },\n config,\n { bypassCache: bypassCache || hasDynamicContent }\n );\n\n return {\n filename: `${config.metadata?.title || this.adapter.label}${this.adapter.extension}`,\n fileId: Date.now().toString(),\n buffer,\n cached: false,\n warnings: allWarnings.length > 0 ? allWarnings : null,\n resolvedFonts,\n };\n }\n\n async validate(\n jsonDefinition: any\n ): Promise<{ valid: boolean; errors?: string[] }> {\n const config =\n typeof jsonDefinition === 'string'\n ? JSON.parse(jsonDefinition)\n : jsonDefinition;\n\n return this.adapter.validateDocument(config);\n }\n\n destroy(): void {\n if (this.cacheInvalidationHandler) {\n cacheEvents.off('generator:invalidate', this.cacheInvalidationHandler);\n this.cacheInvalidationHandler = null;\n }\n this.cacheService.clear();\n }\n}\n","import { LRUCache } from 'lru-cache';\nimport crypto from 'crypto';\nimport { logger } from '../utils/logger.js';\nimport { config } from '../config/index.js';\nimport { cacheEvents } from '@json-to-office/jto-cli';\nimport type { GenerationWarning } from '@json-to-office/shared';\n\n/**\n * A cached generation: the bytes plus the warnings that produced them.\n * Storing bare Buffers meant a cache HIT reported no warnings at all, so the\n * second render of a document with an unresolvable font went silent.\n */\nexport interface CachedGeneration {\n buffer: Buffer;\n warnings: GenerationWarning[] | null;\n}\n\nexport interface CacheStats {\n hits: number;\n misses: number;\n evictions: number;\n size: number;\n itemCount: number;\n}\n\nexport class CacheService {\n private cache: LRUCache<string, CachedGeneration>;\n private stats: CacheStats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n size: 0,\n itemCount: 0,\n };\n private cacheInvalidationHandler: (() => void) | null = null;\n\n constructor() {\n const maxSizeBytes = config.cache.maxSizeMB * 1024 * 1024;\n\n this.cache = new LRUCache<string, CachedGeneration>({\n max: config.cache.maxItems,\n maxSize: maxSizeBytes,\n // Must stay the buffer's byte length: lru-cache rejects a zero or\n // undefined size when `maxSize` is set.\n sizeCalculation: (value: CachedGeneration) => value.buffer.length,\n ttl: config.cache.ttlSeconds * 1000,\n dispose: (\n _value: CachedGeneration,\n _key: string,\n reason: LRUCache.DisposeReason\n ) => {\n if (reason === 'evict' || reason === 'delete') {\n this.stats.evictions++;\n }\n },\n updateAgeOnGet: true,\n updateAgeOnHas: false,\n });\n\n this.cacheInvalidationHandler = () => this.clear();\n cacheEvents.on('cache:invalidate', this.cacheInvalidationHandler);\n }\n\n generateCacheKey(data: unknown): string {\n const normalized = JSON.stringify(data, this.sortKeysReplacer);\n return crypto.createHash('sha256').update(normalized).digest('hex');\n }\n\n private sortKeysReplacer(_key: string, value: unknown): unknown {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return Object.keys(value)\n .sort()\n .reduce((sorted: Record<string, unknown>, key) => {\n sorted[key] = (value as Record<string, unknown>)[key];\n return sorted;\n }, {});\n }\n return value;\n }\n\n hasDynamicContent(data: unknown): boolean {\n const str = JSON.stringify(data);\n const patterns = [\n /\\{\\{now\\}\\}/i,\n /\\{\\{date\\}\\}/i,\n /\\{\\{time\\}\\}/i,\n /\\{\\{timestamp\\}\\}/i,\n /\\{\\{random\\}\\}/i,\n /\\{\\{uuid\\}\\}/i,\n ];\n return patterns.some((p) => p.test(str));\n }\n\n get(key: string): CachedGeneration | null {\n if (!config.features.cache) return null;\n const value = this.cache.get(key);\n if (value) {\n this.stats.hits++;\n this.updateStats();\n return value;\n }\n this.stats.misses++;\n return null;\n }\n\n set(\n key: string,\n value: CachedGeneration,\n documentConfig: unknown,\n options?: { bypassCache?: boolean }\n ): void {\n if (\n !config.features.cache ||\n options?.bypassCache ||\n this.hasDynamicContent(documentConfig)\n )\n return;\n this.cache.set(key, value);\n this.updateStats();\n }\n\n clear(): void {\n this.cache.clear();\n this.stats = { hits: 0, misses: 0, evictions: 0, size: 0, itemCount: 0 };\n logger.info('Cache cleared');\n }\n\n getStats(): CacheStats & { enabled: boolean; hitRate: number } {\n const total = this.stats.hits + this.stats.misses;\n return {\n ...this.stats,\n enabled: config.features.cache,\n hitRate:\n total > 0 ? Math.round((this.stats.hits / total) * 100) / 100 : 0,\n };\n }\n\n private updateStats(): void {\n this.stats.size = this.cache.calculatedSize || 0;\n this.stats.itemCount = this.cache.size;\n }\n\n destroy(): void {\n if (this.cacheInvalidationHandler) {\n cacheEvents.off('cache:invalidate', this.cacheInvalidationHandler);\n this.cacheInvalidationHandler = null;\n }\n }\n}\n","import { execFile } from 'node:child_process';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport { config } from '../config/index.js';\nimport { getFontStager } from '@json-to-office/jto-cli';\n\nconst DEFAULT_CONVERSION_TIMEOUT_MS = 30000;\nconst BINARY_PROBE_TIMEOUT_MS = 5000;\nconst MAX_EXEC_BUFFER_BYTES = 20 * 1024 * 1024;\n\ntype ExecError = NodeJS.ErrnoException & {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n};\n\nfunction executeFile(\n binary: string,\n args: string[],\n timeoutMs: number,\n envOverrides?: Record<string, string>\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n execFile(\n binary,\n args,\n {\n timeout: timeoutMs,\n maxBuffer: MAX_EXEC_BUFFER_BYTES,\n windowsHide: true,\n env: envOverrides ? { ...process.env, ...envOverrides } : process.env,\n },\n (error, stdout, stderr) => {\n if (error) {\n const execError = error as ExecError;\n execError.stdout = stdout;\n execError.stderr = stderr;\n reject(execError);\n return;\n }\n resolve({ stdout: stdout ?? '', stderr: stderr ?? '' });\n }\n );\n });\n}\n\nfunction toErrorText(value: unknown): string {\n if (!value) return '';\n if (Buffer.isBuffer(value)) return value.toString('utf8');\n if (typeof value === 'string') return value;\n return String(value);\n}\n\nfunction sanitizeBaseName(originalName?: string): string {\n const parsed = path.parse(originalName || 'document');\n return (\n (parsed.name || 'document').replace(/[^a-zA-Z0-9._-]/g, '_') || 'document'\n );\n}\n\nexport class LibreOfficeError extends Error {\n readonly code:\n | 'BINARY_NOT_FOUND'\n | 'CONVERSION_TIMEOUT'\n | 'CONVERSION_FAILED'\n | 'OUTPUT_NOT_FOUND';\n constructor(code: LibreOfficeError['code'], message: string) {\n super(message);\n this.name = 'LibreOfficeError';\n this.code = code;\n }\n}\n\nexport class LibreOfficeBinaryNotFoundError extends LibreOfficeError {\n readonly candidates: string[];\n constructor(candidates: string[]) {\n super(\n 'BINARY_NOT_FOUND',\n 'LibreOffice binary not found. Install LibreOffice locally or set LIBREOFFICE_PATH.'\n );\n this.name = 'LibreOfficeBinaryNotFoundError';\n this.candidates = candidates;\n }\n}\n\nexport class LibreOfficeTimeoutError extends LibreOfficeError {\n readonly timeoutMs: number;\n constructor(timeoutMs: number) {\n super(\n 'CONVERSION_TIMEOUT',\n `LibreOffice conversion timed out after ${timeoutMs}ms`\n );\n this.name = 'LibreOfficeTimeoutError';\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class LibreOfficeConversionError extends LibreOfficeError {\n readonly details?: string;\n constructor(message: string, details?: string) {\n super('CONVERSION_FAILED', message);\n this.name = 'LibreOfficeConversionError';\n this.details = details;\n }\n}\n\nexport class LibreOfficeOutputNotFoundError extends LibreOfficeError {\n readonly outputPath: string;\n constructor(outputPath: string) {\n super(\n 'OUTPUT_NOT_FOUND',\n 'LibreOffice conversion completed but PDF output was not produced'\n );\n this.name = 'LibreOfficeOutputNotFoundError';\n this.outputPath = outputPath;\n }\n}\n\nexport class LibreOfficeConverterService {\n private readonly timeoutMs: number;\n private readonly format: 'docx' | 'pptx';\n\n constructor(format: 'docx' | 'pptx', timeoutMs?: number) {\n this.format = format;\n this.timeoutMs =\n timeoutMs ||\n config.LIBREOFFICE_TIMEOUT_MS ||\n DEFAULT_CONVERSION_TIMEOUT_MS;\n }\n\n async convertToPdf(\n input: Buffer,\n originalName: string = 'document',\n resolvedFonts?: ResolvedFont[]\n ): Promise<Buffer> {\n if (!input || input.length === 0) {\n throw new LibreOfficeConversionError('Input file is empty');\n }\n\n const binaryPath = await this.resolveBinaryPath();\n const tempDir = await fs.mkdtemp(\n path.join(os.tmpdir(), 'jto-libreoffice-')\n );\n const outputBaseName = sanitizeBaseName(originalName);\n const ext = this.format === 'pptx' ? '.pptx' : '.docx';\n const inputPath = path.join(tempDir, `${outputBaseName}${ext}`);\n const pdfPath = path.join(tempDir, `${outputBaseName}.pdf`);\n\n // Stage fonts before spawning soffice so the child process picks them up\n // at startup. Handle is closed in the finally block regardless of outcome.\n const stager = getFontStager();\n const fontsToStage = (resolvedFonts ?? []).filter(\n (r) => r.sources.length > 0\n );\n const stageHandle =\n fontsToStage.length > 0\n ? await stager.stage(fontsToStage, tempDir)\n : null;\n\n try {\n await fs.writeFile(inputPath, input);\n\n const filterName =\n this.format === 'pptx' ? 'impress_pdf_Export' : 'writer_pdf_Export';\n await this.runConversion(\n binaryPath,\n inputPath,\n tempDir,\n filterName,\n stageHandle?.envOverrides\n );\n\n try {\n return await fs.readFile(pdfPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new LibreOfficeOutputNotFoundError(pdfPath);\n }\n throw error;\n }\n } finally {\n if (stageHandle) {\n await stageHandle.cleanup().catch(() => {});\n }\n await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n }\n\n private getBinaryCandidates(): string[] {\n const candidates: string[] = [];\n const configured = config.LIBREOFFICE_PATH?.trim();\n if (configured) candidates.push(configured);\n if (process.platform === 'darwin') {\n candidates.push('/Applications/LibreOffice.app/Contents/MacOS/soffice');\n } else if (process.platform === 'win32') {\n candidates.push('C:\\\\Program Files\\\\LibreOffice\\\\program\\\\soffice.exe');\n candidates.push(\n 'C:\\\\Program Files (x86)\\\\LibreOffice\\\\program\\\\soffice.exe'\n );\n }\n candidates.push('soffice', 'libreoffice');\n return [...new Set(candidates)];\n }\n\n private async resolveBinaryPath(): Promise<string> {\n const candidates = this.getBinaryCandidates();\n for (const candidate of candidates) {\n if (await this.isBinaryAvailable(candidate)) return candidate;\n }\n throw new LibreOfficeBinaryNotFoundError(candidates);\n }\n\n private async isBinaryAvailable(binaryPath: string): Promise<boolean> {\n if (binaryPath.includes(path.sep)) {\n try {\n await fs.access(binaryPath);\n } catch {\n return false;\n }\n }\n try {\n await executeFile(binaryPath, ['--version'], BINARY_PROBE_TIMEOUT_MS);\n return true;\n } catch (error) {\n const code = (error as ExecError).code;\n return code !== 'ENOENT' && code !== 'EACCES';\n }\n }\n\n private async runConversion(\n binaryPath: string,\n inputPath: string,\n outputDir: string,\n filterName: string,\n envOverrides?: Record<string, string>\n ): Promise<void> {\n const userProfilePath = path\n .join(outputDir, 'user-profile')\n .replace(/\\\\/g, '/');\n const userInstallation = `file:///${userProfilePath.replace(/^\\//, '')}`;\n const args = [\n '--headless',\n '--norestore',\n '--nolockcheck',\n '--nodefault',\n `-env:UserInstallation=${userInstallation}`,\n '--convert-to',\n `pdf:${filterName}`,\n '--outdir',\n outputDir,\n inputPath,\n ];\n\n if (process.env.JTO_DEBUG_FONTS === '1') {\n // eslint-disable-next-line no-console\n console.log(\n '[jto libreoffice-converter] spawning soffice with env overrides: ' +\n JSON.stringify(\n envOverrides\n ? Object.fromEntries(\n Object.entries(envOverrides).map(([k, v]) => [\n k,\n k === 'JTO_FONT_PATHS'\n ? `<${v.split(':').length} paths>`\n : v,\n ])\n )\n : {}\n )\n );\n }\n try {\n const result = await executeFile(\n binaryPath,\n args,\n this.timeoutMs,\n envOverrides\n );\n // Surface the soffice stderr stream for debugging — that's where the\n // [jto-font-register] macro writes its confirmation. Empty output\n // on macOS indicates the macro never fired (macro-security block,\n // missing Python, XCU parse error, …) and LibreOffice rendered\n // against fallback fonts. Gated behind a flag so prod logs stay clean.\n if (process.env.JTO_DEBUG_FONTS === '1') {\n const stderr = result.stderr?.trim();\n // eslint-disable-next-line no-console\n console.log(\n '[jto libreoffice-converter] conversion ok; stderr len=' +\n (stderr?.length ?? 0) +\n (stderr ? '\\n' + stderr : ' (empty)')\n );\n }\n } catch (error) {\n const execError = error as ExecError;\n if (execError.code === 'ETIMEDOUT')\n throw new LibreOfficeTimeoutError(this.timeoutMs);\n if (execError.code === 'ENOENT')\n throw new LibreOfficeBinaryNotFoundError(this.getBinaryCandidates());\n const details = [\n toErrorText(execError.stderr),\n toErrorText(execError.stdout),\n ]\n .filter(Boolean)\n .join('\\n')\n .trim();\n throw new LibreOfficeConversionError(\n 'LibreOffice failed to convert to PDF',\n details || execError.message\n );\n }\n }\n}\n","import type { FormatAdapter } from '@json-to-office/jto-cli';\nimport { GeneratorService } from '../services/generator.js';\nimport { CacheService } from '../services/cache.js';\nimport { LibreOfficeConverterService } from '../services/libreoffice-converter.js';\n\ntype ServiceMap = {\n generatorService: GeneratorService;\n cacheService: CacheService;\n libreOfficeConverterService: LibreOfficeConverterService;\n};\n\nexport class Container {\n private static instance: Container;\n private services: Map<keyof ServiceMap, ServiceMap[keyof ServiceMap]> =\n new Map();\n private adapter: FormatAdapter;\n\n private constructor(adapter: FormatAdapter) {\n this.adapter = adapter;\n const cacheService = new CacheService();\n const generatorService = new GeneratorService(adapter, cacheService);\n const libreOfficeConverterService = new LibreOfficeConverterService(\n adapter.name as 'docx' | 'pptx'\n );\n\n this.services.set('cacheService', cacheService);\n this.services.set('generatorService', generatorService);\n this.services.set(\n 'libreOfficeConverterService',\n libreOfficeConverterService\n );\n }\n\n public static initialize(adapter: FormatAdapter): Container {\n Container.instance = new Container(adapter);\n return Container.instance;\n }\n\n public static getInstance(): Container {\n if (!Container.instance) {\n throw new Error(\n 'Container not initialized. Call Container.initialize(adapter) first.'\n );\n }\n return Container.instance;\n }\n\n public static getAdapter(): FormatAdapter {\n return Container.getInstance().adapter;\n }\n\n public get<K extends keyof ServiceMap>(serviceName: K): ServiceMap[K] {\n const service = this.services.get(serviceName);\n if (!service) {\n throw new Error(`Service ${serviceName} not found`);\n }\n return service as ServiceMap[K];\n }\n}\n\nexport const getContainer = () => Container.getInstance();\n","import { Hono } from 'hono';\nimport { config } from '../config/index.js';\nimport { getContainer } from '../container/index.js';\nimport { AppEnv } from '../types/hono.js';\n\nexport const healthRouter = new Hono<AppEnv>();\n\nhealthRouter.get('/', (c) => {\n const memoryUsage = process.memoryUsage();\n const uptime = process.uptime();\n\n let cacheStats: any;\n try {\n const cacheService = getContainer().get('cacheService');\n cacheStats = cacheService.getStats();\n } catch {\n cacheStats = { enabled: false, hits: 0, misses: 0, hitRate: 0, evictions: 0, size: 0, itemCount: 0 };\n }\n\n return c.json({\n status: 'ok',\n timestamp: new Date().toISOString(),\n environment: config.NODE_ENV,\n version: '1.0.0',\n framework: 'Hono',\n uptime: Math.floor(uptime),\n memory: {\n rss: `${Math.round(memoryUsage.rss / 1024 / 1024)} MB`,\n heapTotal: `${Math.round(memoryUsage.heapTotal / 1024 / 1024)} MB`,\n heapUsed: `${Math.round(memoryUsage.heapUsed / 1024 / 1024)} MB`,\n },\n cache: {\n enabled: cacheStats.enabled,\n hits: cacheStats.hits,\n misses: cacheStats.misses,\n hitRate: `${(cacheStats.hitRate * 100).toFixed(1)}%`,\n itemCount: cacheStats.itemCount,\n },\n });\n});\n\nhealthRouter.get('/ready', (c) => c.json({ status: 'ready' }));\nhealthRouter.get('/live', (c) => c.json({ status: 'alive' }));\n","/**\n * Loose schemas for initial request validation before plugin-aware validation.\n * These schemas allow unknown types that will be validated by plugin-aware validators.\n */\n\nimport { Type } from '@sinclair/typebox';\n\n/**\n * Loose presentation generation request schema that allows plugin component names.\n * The strict validation is performed later with plugin-aware validators.\n */\n/**\n * Font options accepted over the wire. Caps prevent client-supplied\n * substitution maps from landing unbounded strings into the tree walker.\n */\nconst FontOptionsSchema = Type.Object(\n {\n mode: Type.Optional(\n Type.Union([Type.Literal('substitute'), Type.Literal('custom')])\n ),\n substitution: Type.Optional(\n Type.Record(\n Type.String({ maxLength: 128 }),\n Type.String({ maxLength: 128 }),\n { maxProperties: 256 }\n )\n ),\n strict: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false }\n);\n\nexport const LooseDocumentGenerationRequestSchema = Type.Object(\n {\n jsonDefinition: Type.Union([\n Type.String(), // Allow JSON string\n Type.Object({}, { additionalProperties: true }), // Allow any object\n ]),\n customThemes: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n options: Type.Optional(\n Type.Object(\n {\n bypassCache: Type.Optional(Type.Boolean()),\n returnUrl: Type.Optional(Type.Boolean()),\n fonts: Type.Optional(FontOptionsSchema),\n // Backend to render with. Left as a bounded string rather than an\n // enum: the registry owns the list, answers an unknown id with the\n // ids that exist, and the route turns that into a 400.\n renderer: Type.Optional(Type.String({ maxLength: 64 })),\n // Name of the discovered document this definition came from; the\n // server maps it to that document's directory so relative asset\n // paths resolve against it (#142). Names, never paths — a client\n // cannot point the server at an arbitrary directory.\n sourceName: Type.Optional(Type.String()),\n },\n { additionalProperties: true }\n )\n ),\n },\n { additionalProperties: true }\n);\n\n/**\n * Loose document validation request schema that allows plugin component names.\n */\nexport const LooseDocumentValidationRequestSchema = Type.Object(\n {\n jsonDefinition: Type.Union([\n Type.String(), // Allow JSON string\n Type.Object({}, { additionalProperties: true }), // Allow any object\n ]),\n },\n { additionalProperties: true }\n);\n\n/**\n * Diff request: two DOCX definitions to compare into a tracked-change\n * redline. Strict validation of both documents happens in the handler.\n */\nexport const LooseDocumentDiffRequestSchema = Type.Object(\n {\n oldDefinition: Type.Union([\n Type.String(),\n Type.Object({}, { additionalProperties: true }),\n ]),\n newDefinition: Type.Union([\n Type.String(),\n Type.Object({}, { additionalProperties: true }),\n ]),\n options: Type.Optional(\n Type.Object(\n {\n author: Type.Optional(Type.String({ maxLength: 128 })),\n date: Type.Optional(Type.String({ maxLength: 64 })),\n },\n { additionalProperties: false }\n )\n ),\n },\n { additionalProperties: true }\n);\n","import { TSchema } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport { Context, Env, ValidationTargets, MiddlewareHandler } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\n\n/**\n * Auto-detect raw document JSON (has `name` + `children` but no `jsonDefinition`)\n * and wrap it so callers can POST the document tree directly.\n */\nfunction autoWrapDocumentBody(value: unknown): unknown {\n if (\n typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'children' in value &&\n !('jsonDefinition' in value)\n ) {\n return { jsonDefinition: value };\n }\n return value;\n}\n\nexport function tbValidator<\n T extends TSchema,\n E extends Env = Env,\n P extends string = string,\n>(schema: T) {\n return (async (c: Context<E, P>, next: () => Promise<void>) => {\n let value: unknown;\n\n try {\n value = await c.req.json();\n } catch {\n throw new HTTPException(400, {\n message: 'Invalid JSON in request body',\n });\n }\n\n value = autoWrapDocumentBody(value);\n\n const isValid = Value.Check(schema, value);\n\n if (isValid) {\n (c.req as { validatedData?: Record<string, unknown> }).validatedData = {\n json: value,\n };\n await next();\n } else {\n const errors = [...Value.Errors(schema, value)].map((error) => ({\n path: error.path,\n message: error.message,\n value: error.value,\n }));\n\n const errorMessages = errors.map((e) => `${e.path || '/'}: ${e.message}`);\n\n throw new HTTPException(400, {\n message:\n errorMessages.length === 1\n ? errorMessages[0]\n : `Validation failed:\\n${errorMessages.join('\\n')}`,\n cause: { errors },\n });\n }\n }) as MiddlewareHandler<E, P, Record<string, unknown>>;\n}\n\nexport function getValidated<T>(\n c: Context,\n target: keyof ValidationTargets\n): T {\n const validatedData = (c.req as { validatedData?: Record<string, unknown> })\n .validatedData;\n if (!validatedData || !validatedData[target]) {\n throw new Error(`No validated data found for target: ${target}`);\n }\n return validatedData[target] as T;\n}\n","import { MiddlewareHandler } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\n\nexport interface RateLimitOptions {\n limit: number;\n window: number; // milliseconds\n keyGenerator?: (c: any) => string;\n namespace?: string | ((c: any) => string);\n maxEntries?: number;\n trustProxy?: boolean;\n}\n\nfunction clientAddress(c: any, trustProxy: boolean): string {\n if (trustProxy) {\n const forwarded =\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',')[0]?.trim();\n if (forwarded) return forwarded;\n }\n const incoming = c.env?.incoming || c.env?.req;\n return incoming?.socket?.remoteAddress || 'anonymous';\n}\n\n/**\n * Bounded, process-local rate limiting. Distributed deployments should put a\n * shared limiter at the edge too; this remains the last line of defence for a\n * single worker and never grows without bound.\n */\nexport const rateLimiter = (options: RateLimitOptions): MiddlewareHandler => {\n const { limit, window, keyGenerator } = options;\n const maxEntries = options.maxEntries ?? 10_000;\n const rateLimitStore = new Map<\n string,\n { count: number; resetTime: number }\n >();\n let lastCleanup = 0;\n\n return async (c, next) => {\n const clientKey = keyGenerator\n ? keyGenerator(c)\n : clientAddress(c, options.trustProxy === true);\n const namespace =\n typeof options.namespace === 'function'\n ? options.namespace(c)\n : options.namespace || `${c.req.method}:${c.req.path}`;\n const key = `${namespace}:${String(clientKey).slice(0, 256)}`;\n const now = Date.now();\n\n // Amortize cleanup; scanning an attacker-filled map on every request would\n // turn the protection itself into a CPU denial of service.\n if (now - lastCleanup >= Math.min(window, 60_000)) {\n for (const [storedKey, value] of rateLimitStore.entries()) {\n if (value.resetTime <= now) rateLimitStore.delete(storedKey);\n }\n lastCleanup = now;\n }\n\n const record = rateLimitStore.get(key);\n\n if (!record) {\n if (rateLimitStore.size >= maxEntries) {\n const oldestKey = rateLimitStore.keys().next().value as\n | string\n | undefined;\n if (oldestKey) rateLimitStore.delete(oldestKey);\n }\n rateLimitStore.set(key, {\n count: 1,\n resetTime: now + window,\n });\n } else if (record.resetTime <= now) {\n // Window expired, reset\n record.count = 1;\n record.resetTime = now + window;\n } else if (record.count >= limit) {\n // Rate limit exceeded\n const retryAfter = Math.ceil((record.resetTime - now) / 1000);\n\n c.header('X-RateLimit-Limit', String(limit));\n c.header('X-RateLimit-Remaining', '0');\n c.header('X-RateLimit-Reset', String(record.resetTime));\n c.header('Retry-After', String(retryAfter));\n\n throw new HTTPException(429, {\n message: 'Too many requests, please try again later',\n });\n } else {\n // Increment count\n record.count++;\n }\n\n // Add rate limit headers\n const currentRecord = rateLimitStore.get(key)!;\n c.header('X-RateLimit-Limit', String(limit));\n c.header(\n 'X-RateLimit-Remaining',\n String(Math.max(0, limit - currentRecord.count))\n );\n c.header('X-RateLimit-Reset', String(currentRecord.resetTime));\n\n await next();\n };\n};\n","import type { OutboundSourceMode } from '../config/index.js';\n\nexport interface OutboundSourcePolicy {\n mode: OutboundSourceMode;\n allowedHosts: readonly string[];\n}\n\nexport class UnsafeOutboundSourceError extends Error {\n constructor(\n readonly path: string,\n reason: string\n ) {\n super(`Unsafe outbound source at ${path}: ${reason}`);\n this.name = 'UnsafeOutboundSourceError';\n }\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nconst DANGEROUS_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\nconst COMPONENT_SOURCE_NAMES = new Set(['image']);\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hostMatches(host: string, pattern: string): boolean {\n const normalized = pattern.toLowerCase().replace(/\\.$/, '');\n if (normalized.startsWith('*.')) {\n const suffix = normalized.slice(1);\n return host.endsWith(suffix) && host.length > suffix.length;\n }\n return host === normalized;\n}\n\nfunction isPrivateIpv4(host: string): boolean {\n const parts = host.split('.');\n if (parts.length !== 4) return false;\n const octets = parts.map(Number);\n if (\n octets.some(\n (part, index) =>\n !Number.isInteger(part) ||\n part < 0 ||\n part > 255 ||\n String(part) !== parts[index]\n )\n ) {\n return false;\n }\n const [a, b] = octets;\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 100 && b >= 64 && b <= 127) ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && (b === 0 || b === 168)) ||\n (a === 198 && (b === 18 || b === 19)) ||\n a >= 224\n );\n}\n\nfunction isPrivateHost(host: string): boolean {\n const normalized = host\n .toLowerCase()\n .replace(/^\\[|\\]$/g, '')\n .replace(/\\.$/, '');\n if (\n normalized === 'localhost' ||\n normalized.endsWith('.localhost') ||\n normalized === '::' ||\n normalized === '::1'\n ) {\n return true;\n }\n if (isPrivateIpv4(normalized)) return true;\n if (normalized.startsWith('::ffff:')) {\n const mapped = normalized.slice('::ffff:'.length);\n if (isPrivateIpv4(mapped)) return true;\n const groups = mapped.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);\n if (groups) {\n const value =\n Number.parseInt(groups[1], 16) * 0x1_0000 +\n Number.parseInt(groups[2], 16);\n return isPrivateIpv4(\n [\n value >>> 24,\n (value >>> 16) & 255,\n (value >>> 8) & 255,\n value & 255,\n ].join('.')\n );\n }\n }\n const firstIpv6Group = Number.parseInt(normalized.split(':')[0] || '0', 16);\n return (\n (firstIpv6Group >= 0xfc00 && firstIpv6Group <= 0xfdff) ||\n (firstIpv6Group >= 0xfe80 && firstIpv6Group <= 0xfebf)\n );\n}\n\nfunction assertAllowedUrl(\n source: string,\n path: string,\n allowedHosts: readonly string[]\n): void {\n if (source.startsWith('data:')) return;\n\n let url: URL;\n try {\n url = new URL(source);\n } catch {\n throw new UnsafeOutboundSourceError(\n path,\n 'local and relative file paths are disabled for HTTP requests'\n );\n }\n\n if (url.protocol !== 'https:') {\n throw new UnsafeOutboundSourceError(path, 'only HTTPS URLs are allowed');\n }\n if (url.username || url.password) {\n throw new UnsafeOutboundSourceError(\n path,\n 'URLs containing credentials are not allowed'\n );\n }\n\n const host = url.hostname.toLowerCase().replace(/\\.$/, '');\n if (isPrivateHost(host)) {\n throw new UnsafeOutboundSourceError(\n path,\n `private or local host \"${host}\" is not allowed`\n );\n }\n if (!allowedHosts.some((pattern) => hostMatches(host, pattern))) {\n throw new UnsafeOutboundSourceError(\n path,\n `host \"${host}\" is not in OUTBOUND_HOST_ALLOWLIST`\n );\n }\n}\n\nfunction extractCssReferences(input: string): string[] {\n const references: string[] = [];\n const urlPattern = /url\\(\\s*(['\"]?)([^)'\"\\s]+)\\1\\s*\\)/gi;\n const importPattern = /@import\\s+(?:url\\(\\s*)?(['\"])([^'\"]+)\\1/gi;\n for (const pattern of [urlPattern, importPattern]) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(input))) references.push(match[2]);\n }\n return references;\n}\n\nfunction extractAbsoluteUrls(input: string): string[] {\n return input.match(/(?:https?|file):\\/\\/[^\\s'\"<>)}\\]]+/gi) ?? [];\n}\n\nfunction assertSafeSvg(\n svg: string,\n path: string,\n allowedHosts: readonly string[]\n): void {\n if (\n /<\\s*script\\b/i.test(svg) ||\n /<\\s*(?:foreignObject|iframe|object|embed)\\b/i.test(svg) ||\n /\\bon[a-z]+\\s*=/i.test(svg)\n ) {\n throw new UnsafeOutboundSourceError(path, 'active SVG content is disabled');\n }\n if (/<!\\s*(?:DOCTYPE|ENTITY)\\b/i.test(svg)) {\n throw new UnsafeOutboundSourceError(\n path,\n 'SVG document types and entities are disabled'\n );\n }\n\n const refPattern = /\\b(?:href|src)\\s*=\\s*(['\"])(.*?)\\1/gi;\n let match: RegExpExecArray | null;\n while ((match = refPattern.exec(svg))) {\n const ref = match[2].trim();\n if (!ref || ref.startsWith('#') || ref.startsWith('data:')) continue;\n assertAllowedUrl(ref, path, allowedHosts);\n }\n for (const ref of extractCssReferences(svg)) {\n if (ref.startsWith('#') || ref.startsWith('data:')) continue;\n assertAllowedUrl(ref, path, allowedHosts);\n }\n}\n\nfunction assertSafeEncodedImage(\n source: string,\n path: string,\n allowedHosts: readonly string[]\n): void {\n let candidate = source.trim();\n let declaredSvg = false;\n\n if (candidate.startsWith('data:')) {\n const comma = candidate.indexOf(',');\n if (comma < 0) {\n throw new UnsafeOutboundSourceError(path, 'malformed image data URL');\n }\n const metadata = candidate.slice(5, comma);\n declaredSvg = metadata.split(';')[0].toLowerCase() === 'image/svg+xml';\n if (!declaredSvg) return;\n const payload = candidate.slice(comma + 1);\n try {\n candidate = /(?:^|;)base64(?:;|$)/i.test(metadata)\n ? Buffer.from(payload, 'base64').toString('utf8')\n : decodeURIComponent(payload);\n } catch {\n throw new UnsafeOutboundSourceError(path, 'malformed SVG data URL');\n }\n } else if (!/<\\s*svg\\b/i.test(candidate)) {\n // The documented `base64` shape is a data URL, but inspect raw base64 too\n // so a migration client cannot smuggle active SVG through the same field.\n candidate = Buffer.from(candidate, 'base64').toString('utf8');\n }\n\n const svgStart = candidate.search(/<\\s*svg\\b/i);\n if (svgStart < 0) {\n if (declaredSvg) {\n throw new UnsafeOutboundSourceError(path, 'malformed SVG image data');\n }\n return;\n }\n assertSafeSvg(candidate, path, allowedHosts);\n}\n\nfunction assertSafeResources(\n resources: JsonRecord,\n path: string,\n allowedHosts: readonly string[]\n): void {\n if (typeof resources.js === 'string' && resources.js.trim()) {\n throw new UnsafeOutboundSourceError(\n `${path}.js`,\n 'remote renderer JavaScript resources are disabled'\n );\n }\n if (typeof resources.css === 'string') {\n for (const ref of extractCssReferences(resources.css)) {\n if (ref.startsWith('data:')) continue;\n assertAllowedUrl(ref, `${path}.css`, allowedHosts);\n }\n }\n // Highcharts loads `resources.files` as JavaScript. Allowlisting a host for\n // fonts or stylesheets must not also grant it script execution inside the\n // renderer, so reject the field outright rather than URL-checking it.\n if (Array.isArray(resources.files) && resources.files.length > 0) {\n throw new UnsafeOutboundSourceError(\n `${path}.files`,\n 'remote renderer JavaScript resources are disabled'\n );\n }\n}\n\nfunction assertNoRemoteReferences(\n value: unknown,\n path: string,\n allowedHosts: readonly string[],\n seen: WeakSet<object>\n): void {\n if (typeof value === 'string') {\n if (\n /\\b(?:fetch|XMLHttpRequest|WebSocket|EventSource)\\s*\\(/i.test(value) ||\n /\\b(?:javascript|file):/i.test(value)\n ) {\n throw new UnsafeOutboundSourceError(\n path,\n 'network-capable JavaScript and file URLs are disabled'\n );\n }\n for (const url of [\n ...extractAbsoluteUrls(value),\n ...extractCssReferences(value),\n ]) {\n if (url.startsWith('data:')) continue;\n assertAllowedUrl(url, path, allowedHosts);\n }\n if (/^\\/\\//.test(value.trim())) {\n throw new UnsafeOutboundSourceError(\n path,\n 'protocol-relative URLs are disabled'\n );\n }\n return;\n }\n if (!value || typeof value !== 'object' || seen.has(value)) return;\n seen.add(value);\n if (Array.isArray(value)) {\n value.forEach((entry, index) =>\n assertNoRemoteReferences(entry, `${path}[${index}]`, allowedHosts, seen)\n );\n return;\n }\n for (const [key, child] of Object.entries(value as JsonRecord)) {\n assertNoRemoteReferences(child, `${path}.${key}`, allowedHosts, seen);\n }\n}\n\nfunction visit(\n value: unknown,\n path: string,\n containerKey: string | undefined,\n allowedHosts: readonly string[],\n seen: WeakSet<object>\n): void {\n if (!value || typeof value !== 'object' || seen.has(value)) return;\n seen.add(value);\n\n if (Array.isArray(value)) {\n value.forEach((entry, index) =>\n visit(entry, `${path}[${index}]`, containerKey, allowedHosts, seen)\n );\n return;\n }\n\n const record = value as JsonRecord;\n for (const key of Object.keys(record)) {\n if (DANGEROUS_KEYS.has(key)) {\n throw new UnsafeOutboundSourceError(\n `${path}.${key}`,\n 'prototype mutation keys are disabled'\n );\n }\n }\n\n const kind = typeof record.kind === 'string' ? record.kind : undefined;\n if (kind === 'file' && typeof record.path === 'string') {\n throw new UnsafeOutboundSourceError(\n `${path}.path`,\n 'local file sources are disabled for HTTP requests'\n );\n }\n if (\n (kind === 'url' || kind === 'variable') &&\n typeof record.url === 'string'\n ) {\n assertAllowedUrl(record.url, `${path}.url`, allowedHosts);\n }\n\n const componentName =\n typeof record.name === 'string' ? record.name.toLowerCase() : undefined;\n const props = isRecord(record.props) ? record.props : undefined;\n if (componentName && props) {\n if (\n COMPONENT_SOURCE_NAMES.has(componentName) &&\n typeof props.path === 'string'\n ) {\n assertAllowedUrl(props.path, `${path}.props.path`, allowedHosts);\n assertSafeEncodedImage(props.path, `${path}.props.path`, allowedHosts);\n }\n if (\n COMPONENT_SOURCE_NAMES.has(componentName) &&\n typeof props.base64 === 'string'\n ) {\n assertSafeEncodedImage(\n props.base64,\n `${path}.props.base64`,\n allowedHosts\n );\n }\n if (\n (componentName === 'highcharts' || componentName === 'visual') &&\n typeof props.serverUrl === 'string'\n ) {\n assertAllowedUrl(\n props.serverUrl,\n `${path}.props.serverUrl`,\n allowedHosts\n );\n }\n if (componentName === 'highcharts') {\n if (isRecord(props.resources)) {\n assertSafeResources(\n props.resources,\n `${path}.props.resources`,\n allowedHosts\n );\n }\n assertNoRemoteReferences(\n props.options,\n `${path}.props.options`,\n allowedHosts,\n new WeakSet()\n );\n }\n }\n\n // Slide/template/visual canvas backgrounds store an image source in a plain\n // `{ image: { path } }` object rather than an image component.\n if (containerKey === 'image' && typeof record.path === 'string') {\n assertAllowedUrl(record.path, `${path}.path`, allowedHosts);\n assertSafeEncodedImage(record.path, `${path}.path`, allowedHosts);\n }\n if (typeof record.svg === 'string') {\n assertSafeSvg(record.svg, `${path}.svg`, allowedHosts);\n }\n if (containerKey === 'resources') {\n assertSafeResources(record, path, allowedHosts);\n }\n\n for (const [key, child] of Object.entries(record)) {\n visit(child, `${path}.${key}`, key, allowedHosts, seen);\n }\n}\n\n/**\n * Reject request-controlled sources capable of making the server read local\n * files or reach arbitrary network hosts. Development mode intentionally\n * preserves local playground workflows.\n */\nexport function assertSafeOutboundSources(\n value: unknown,\n policy: OutboundSourcePolicy,\n rootPath = 'request'\n): void {\n if (policy.mode === 'development') return;\n\n let parsed = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value);\n } catch {\n // Structural validation owns malformed JSON reporting.\n return;\n }\n }\n visit(parsed, rootPath, undefined, policy.allowedHosts, new WeakSet());\n}\n\n/** Extra checks for payloads executed by the Chromium-based chart renderer. */\nexport function assertSafeRendererPayload(\n value: unknown,\n policy: OutboundSourcePolicy\n): void {\n assertSafeOutboundSources(value, policy, 'export');\n if (policy.mode === 'development' || !isRecord(value)) return;\n assertNoRemoteReferences(\n value.infile,\n 'export.infile',\n policy.allowedHosts,\n new WeakSet()\n );\n}\n","/**\n * Shared POST /rasterize + /rasterize/batch routes — validated handlers\n * mounted on BOTH the playground format router and the standalone\n * jto-render-server, so the public and in-app rasterize surfaces can't drift\n * in validation, limits, or error mapping.\n *\n * /rasterize renders one single-slide pptx presentation to a PNG.\n * /rasterize/batch (#153) renders many independent single-slide presentations\n * in one request — one LibreOffice launch instead of one per visual — and\n * returns index-aligned per-slide results (200 with item errors rather than\n * all-or-nothing).\n */\n\nimport path from 'node:path';\nimport type { Hono, MiddlewareHandler } from 'hono';\nimport { Type } from '@sinclair/typebox';\nimport { bodyLimit } from 'hono/body-limit';\nimport { HTTPException } from 'hono/http-exception';\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n MIN_VISUAL_DPI,\n MAX_VISUAL_DPI,\n MAX_RASTERIZE_BATCH_SLIDES,\n MAX_RASTERIZE_FONTS,\n MAX_RASTERIZE_FONT_BYTES,\n type PptxRasterizer,\n type PptxBatchRasterizer,\n type RasterizeFontFace,\n} from '@json-to-office/shared';\nimport {\n createLibreOfficePptxRasterizer,\n createLibreOfficePptxBatchRasterizer,\n} from '@json-to-office/jto-cli';\nimport { config } from './config/index.js';\nimport { tbValidator, getValidated } from './lib/typebox-validator.js';\nimport {\n assertSafeOutboundSources,\n type OutboundSourcePolicy,\n UnsafeOutboundSourceError,\n} from './security/outbound-source-policy.js';\n\n/**\n * Strict standard-alphabet base64: whole quadruplets with correct padding,\n * nothing else. `Buffer.from(s, 'base64')` is lenient — it silently skips\n * whitespace, newlines, invalid characters, and everything up to (and\n * including) a `data:image/...;base64,` prefix — so an unconstrained string\n * decodes to garbage that gets written to disk and handed to LibreOffice.\n * Rejecting at the boundary turns that into a 400.\n *\n * Linear-time by construction: one unambiguous fixed-width repetition\n * followed by a fixed-width optional tail, so there is no backtracking\n * blowup on a multi-megabyte string.\n */\nconst BASE64_PATTERN =\n '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$';\n\n/**\n * One font face the caller wants staged for this render's LibreOffice\n * launch. `data` is base64 of the raw font file (no `data:` prefix).\n */\nconst RasterizeFontFaceSchema = Type.Object(\n {\n family: Type.String({ minLength: 1, maxLength: 128 }),\n weight: Type.Integer({ minimum: 1, maximum: 1000 }),\n italic: Type.Boolean(),\n data: Type.String({\n minLength: 1,\n maxLength: 4 * 1024 * 1024,\n pattern: BASE64_PATTERN,\n }),\n format: Type.Optional(\n Type.Union([\n Type.Literal('ttf'),\n Type.Literal('otf'),\n Type.Literal('woff'),\n Type.Literal('woff2'),\n ])\n ),\n },\n { additionalProperties: false }\n);\nconst FontsSchema = Type.Optional(\n Type.Array(RasterizeFontFaceSchema, { maxItems: MAX_RASTERIZE_FONTS })\n);\n\n/** Body for POST /rasterize: a single-slide pptx presentation + optional dpi. */\nexport const RasterizeRequestSchema = Type.Object(\n {\n presentation: Type.Object({}, { additionalProperties: true }),\n dpi: Type.Optional(\n Type.Number({ minimum: MIN_VISUAL_DPI, maximum: MAX_VISUAL_DPI })\n ),\n baseDir: Type.Optional(Type.String()),\n fonts: FontsSchema,\n },\n { additionalProperties: false }\n);\n\n/** Body for POST /rasterize/batch: independent slides + shared baseDir. */\nexport const RasterizeBatchRequestSchema = Type.Object(\n {\n slides: Type.Array(\n Type.Object(\n {\n presentation: Type.Object({}, { additionalProperties: true }),\n dpi: Type.Optional(\n Type.Number({ minimum: MIN_VISUAL_DPI, maximum: MAX_VISUAL_DPI })\n ),\n },\n { additionalProperties: false }\n ),\n { minItems: 1, maxItems: MAX_RASTERIZE_BATCH_SLIDES }\n ),\n baseDir: Type.Optional(Type.String()),\n // Request-level, shared by every slide, exactly like `baseDir`. NOT\n // inside the per-slide object above, whose `additionalProperties: false`\n // must keep rejecting per-slide fonts: a uniform slide shape is what\n // lets batch dedupe and the disk-cache key stay identical to the\n // single-slide path.\n fonts: FontsSchema,\n },\n { additionalProperties: false }\n);\n\n// One rasterizer per process — shares the on-disk content-addressed cache\n// across every /rasterize surface in the process. Single and batch factories\n// use the same default cache directory, so the two routes share hits too.\nlet sharedRasterizer: PptxRasterizer | undefined;\nexport function getSharedRasterizer(): PptxRasterizer {\n if (!sharedRasterizer) {\n sharedRasterizer = createLibreOfficePptxRasterizer();\n }\n return sharedRasterizer;\n}\n\nlet sharedBatchRasterizer: PptxBatchRasterizer | undefined;\nexport function getSharedBatchRasterizer(): PptxBatchRasterizer {\n if (!sharedBatchRasterizer) {\n sharedBatchRasterizer = createLibreOfficePptxBatchRasterizer();\n }\n return sharedBatchRasterizer;\n}\n\nconst jsonOnly: MiddlewareHandler = async (c, next) => {\n const contentType = c.req.header('content-type');\n if (!contentType || !contentType.includes('application/json')) {\n throw new HTTPException(400, {\n message: 'Content-Type must be application/json',\n });\n }\n await next();\n};\n\n// Raster size budget. Slide dimensions are author-controlled inches and the\n// schema does not bound them, so an oversized canvas × dpi could demand an\n// enormous bitmap; with batching that multiplies by slide count. Budgets are\n// estimated up front from the declared slide size (default pptx 16:9 when\n// absent) — same philosophy as the /export pixel budget.\nconst DEFAULT_SLIDE_WIDTH_IN = 13.34;\nconst DEFAULT_SLIDE_HEIGHT_IN = 7.5;\nconst MAX_SLIDE_PIXELS = 64_000_000;\nconst MAX_BATCH_PIXELS = 256_000_000;\n\nfunction estimateSlidePixels(presentation: unknown, dpi: number): number {\n const props = (presentation as { props?: Record<string, unknown> } | null)\n ?.props;\n const dim = (value: unknown, fallback: number): number =>\n typeof value === 'number' && Number.isFinite(value) && value > 0\n ? value\n : fallback;\n const widthIn = dim(props?.slideWidth, DEFAULT_SLIDE_WIDTH_IN);\n const heightIn = dim(props?.slideHeight, DEFAULT_SLIDE_HEIGHT_IN);\n return widthIn * dpi * (heightIn * dpi);\n}\n\nfunction assertPixelBudget(\n slides: Array<{ presentation: unknown; dpi: number }>\n): void {\n let total = 0;\n for (const slide of slides) {\n const pixels = estimateSlidePixels(slide.presentation, slide.dpi);\n if (pixels > MAX_SLIDE_PIXELS) {\n throw new HTTPException(400, {\n message: 'Requested slide dimensions are too large',\n });\n }\n total += pixels;\n }\n if (total > MAX_BATCH_PIXELS) {\n throw new HTTPException(400, {\n message: 'Requested batch raster size is too large',\n });\n }\n}\n\n/**\n * Bound the decoded font payload. The per-face `maxLength` and\n * `MAX_RASTERIZE_FONTS` alone would admit far more than the body limit\n * allows, and staging writes every face to disk before soffice starts.\n */\nfunction assertFontBudget(fonts: RasterizeFontFace[] | undefined): void {\n if (!fonts?.length) return;\n // base64 → bytes ≈ len × 3/4. A cheap upper bound; no decode needed.\n const bytes = fonts.reduce(\n (sum, f) => sum + Math.ceil(f.data.length * 0.75),\n 0\n );\n if (bytes > MAX_RASTERIZE_FONT_BYTES) {\n throw new HTTPException(400, {\n message: 'Requested font payload is too large',\n });\n }\n}\n\n/**\n * `baseDir` selects the directory local media paths resolve against. An\n * unrestricted value would let any HTTP caller point the rasterizer at\n * arbitrary server directories and exfiltrate readable files as rendered\n * pixels, so it must stay inside the server's own working tree. Callers\n * rendering documents that live elsewhere should run the server from that\n * tree (or use an in-process rasterizer).\n */\nfunction resolveSafeBaseDir(baseDir: string | undefined): string | undefined {\n if (baseDir === undefined) return undefined;\n const resolved = path.resolve(baseDir);\n const cwd = process.cwd();\n if (resolved !== cwd && !resolved.startsWith(cwd + path.sep)) {\n throw new HTTPException(400, {\n message: 'baseDir must be inside the server working directory',\n });\n }\n return resolved;\n}\n\n/** Map rasterization failures onto stable 400/503/500 responses. */\nfunction toHttpException(error: unknown): HTTPException {\n if (error instanceof HTTPException) return error;\n if (error instanceof UnsafeOutboundSourceError) {\n return new HTTPException(400, { message: error.message });\n }\n const msg =\n error instanceof Error ? error.message.toLowerCase() : String(error);\n if (msg.includes('not found') || msg.includes('rasterization needs')) {\n return new HTTPException(503, { message: (error as Error).message });\n }\n if (msg.includes('invalid') || msg.includes('validation')) {\n return new HTTPException(400, { message: (error as Error).message });\n }\n return new HTTPException(500, {\n message: 'Internal server error during rasterization',\n });\n}\n\n/**\n * Hard ceiling for the rasterize body limit, whatever an operator configures.\n * The schema's own worst case (MAX_RASTERIZE_FONTS × 4 MiB of base64 = 128\n * MiB) must never be reachable, and a body this large is already far past the\n * MAX_RASTERIZE_FONT_BYTES working budget.\n */\nconst MAX_RASTERIZE_BODY_CEILING = 64 * 1024 * 1024;\n\n/**\n * Resolve the rasterize body limit. Precedence, most specific first:\n *\n * 1. an explicit `options.maxBodyBytes` from the mounting server,\n * 2. `MAX_RASTERIZE_BODY_SIZE` — the route's own operator knob, also read\n * by the standalone render server for its outer limit,\n * 3. `config.requestLimits.maxBodySize` (`MAX_REQUEST_BODY_SIZE`), the\n * process-wide configured ceiling,\n *\n * clamped to {@link MAX_RASTERIZE_BODY_CEILING}. Previously this was a\n * hardcoded 32 MiB, which silently discarded any configured value above it.\n * Resolved lazily (at route registration) so dotenv has certainly run.\n */\nexport function resolveMaxBodyBytes(explicit?: number): number {\n const fromEnv = Number.parseInt(\n process.env.MAX_RASTERIZE_BODY_SIZE ?? '',\n 10\n );\n const configured =\n explicit ??\n (Number.isFinite(fromEnv) && fromEnv > 0\n ? fromEnv\n : config.requestLimits.maxBodySize);\n return Math.min(configured, MAX_RASTERIZE_BODY_CEILING);\n}\n\nexport interface RasterizeRouteOptions {\n getRasterizer?: () => PptxRasterizer;\n getBatchRasterizer?: () => PptxBatchRasterizer;\n preMiddleware?: MiddlewareHandler[];\n sourcePolicy?: OutboundSourcePolicy;\n onError?: (error: unknown) => void;\n /**\n * Body-size limit for both rasterize routes. Defaults to the configured\n * server limit (see {@link resolveMaxBodyBytes}); always clamped to\n * {@link MAX_RASTERIZE_BODY_CEILING}.\n */\n maxBodyBytes?: number;\n}\n\n/**\n * Register `POST /rasterize` and `POST /rasterize/batch` on a Hono router\n * with body-size limits, content-type + schema validation (dpi clamped to\n * [MIN,MAX]_VISUAL_DPI, batch capped at MAX_RASTERIZE_BATCH_SLIDES), the\n * shared rasterizers, and structured 400/413/503/500 error mapping. Both\n * routes share `preMiddleware` instances (e.g. one rate limiter), so a batch\n * and its per-visual fallback draw from the same budget.\n *\n * @param options.preMiddleware - extra middleware (e.g. a rate limiter) run first.\n * @param options.maxBodyBytes - body-size limit; defaults to the configured\n * server limit rather than a hardcoded one (see {@link resolveMaxBodyBytes}).\n */\nexport function registerRasterizeRoute(\n router: Hono<any>,\n options: RasterizeRouteOptions = {}\n): void {\n const getRasterizer = options.getRasterizer ?? getSharedRasterizer;\n const getBatchRasterizer =\n options.getBatchRasterizer ?? getSharedBatchRasterizer;\n\n // The body now also carries base64 font faces. The schema alone would admit\n // MAX_RASTERIZE_FONTS × 4 MiB = 128 MiB; this limit is what actually bounds\n // it, and it rejects with 413 BEFORE parsing, which is the order we want.\n // MAX_RASTERIZE_FONT_BYTES (8 MiB decoded ≈ 10.7 MiB base64) is the\n // intended working ceiling for fonts within that budget.\n const maxBodyBytes = resolveMaxBodyBytes(options.maxBodyBytes);\n\n const shared: MiddlewareHandler[] = [\n ...(options.preMiddleware ?? []),\n bodyLimit({\n maxSize: maxBodyBytes,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n jsonOnly,\n ];\n\n const guard = async <T>(run: () => Promise<T>): Promise<T> => {\n try {\n return await run();\n } catch (error) {\n options.onError?.(error);\n throw toHttpException(error);\n }\n };\n\n router.post(\n '/rasterize',\n ...shared,\n tbValidator(RasterizeRequestSchema),\n async (c) => {\n const { presentation, dpi, baseDir, fonts } = getValidated<{\n presentation: unknown;\n dpi?: number;\n baseDir?: string;\n fonts?: RasterizeFontFace[];\n }>(c, 'json');\n const safeBaseDir = resolveSafeBaseDir(baseDir);\n\n const effectiveDpi = clampVisualDpi(dpi ?? DEFAULT_VISUAL_DPI);\n assertPixelBudget([{ presentation, dpi: effectiveDpi }]);\n assertFontBudget(fonts);\n\n const result = await guard(async () => {\n if (options.sourcePolicy) {\n // Scoped to `presentation` only. Font faces are inert base64 with\n // no URL-shaped keys, and walking multi-MB strings per request\n // would be pure cost.\n assertSafeOutboundSources(\n presentation,\n options.sourcePolicy,\n 'presentation'\n );\n }\n return getRasterizer()({\n presentation,\n dpi: effectiveDpi,\n baseDir: safeBaseDir,\n // Conditional so a fontless request reaches the engine with no\n // `fonts` key at all — an `undefined` would still be an absent\n // digest, but keeping the object identical to the pre-change shape\n // makes the cache-key equivalence obvious.\n ...(fonts?.length && { fonts }),\n });\n });\n return c.json(result);\n }\n );\n\n router.post(\n '/rasterize/batch',\n ...shared,\n tbValidator(RasterizeBatchRequestSchema),\n async (c) => {\n const { slides, baseDir, fonts } = getValidated<{\n slides: Array<{ presentation: unknown; dpi?: number }>;\n baseDir?: string;\n fonts?: RasterizeFontFace[];\n }>(c, 'json');\n const safeBaseDir = resolveSafeBaseDir(baseDir);\n const effectiveSlides = slides.map((slide) => ({\n presentation: slide.presentation,\n dpi: clampVisualDpi(slide.dpi ?? DEFAULT_VISUAL_DPI),\n }));\n assertPixelBudget(effectiveSlides);\n assertFontBudget(fonts);\n\n const result = await guard(async () => {\n if (options.sourcePolicy) {\n // Scoped to each slide's `presentation` only — see /rasterize.\n slides.forEach((slide, index) =>\n assertSafeOutboundSources(\n slide.presentation,\n options.sourcePolicy!,\n `slides[${index}].presentation`\n )\n );\n }\n return getBatchRasterizer()({\n slides: effectiveSlides,\n baseDir: safeBaseDir,\n ...(fonts?.length && { fonts }),\n });\n });\n\n // Per-slide errors from `build` are caused by the slide's own JSON and\n // are the caller's actionable feedback; `convert`/`rasterize` failures\n // carry raw tool output (host paths, temp dirs), which the single route\n // never exposes — log them, return a generic message (C2 parity with\n // /rasterize's 500 mapping).\n return c.json({\n results: result.results.map((slide) => {\n if (slide.ok) return slide;\n options.onError?.(new Error(slide.error));\n return slide.stage === 'build'\n ? { ok: false as const, error: slide.error, stage: slide.stage }\n : {\n ok: false as const,\n error: 'Slide rasterization failed',\n stage: slide.stage,\n };\n }),\n });\n }\n );\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Inline relative media references of a server-discovered document as data\n * URLs, so bundled templates survive safe-mode outbound-source validation and\n * remote rasterization (which runs on a host without the template's files).\n *\n * Only relative paths that canonicalize inside `baseDir` are inlined; anything\n * else (absolute paths, URLs, data URLs, `..` escapes, missing or oversized\n * files) is left untouched for the outbound-source policy to judge.\n */\n\nconst MIME_BY_EXTENSION: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.bmp': 'image/bmp',\n '.tiff': 'image/tiff',\n '.tif': 'image/tiff',\n};\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isInlineCandidate(source: string): boolean {\n if (!source || source.includes('\\0')) return false;\n if (source.startsWith('data:')) return false;\n if (path.isAbsolute(source)) return false;\n try {\n new URL(source);\n return false; // absolute URL — policy handles it\n } catch {\n return true;\n }\n}\n\nexport interface InlineTemplateMediaOptions {\n /** Per-file size cap in bytes; larger files are left as-is. */\n maxFileBytes?: number;\n /** Total inlined bytes cap; once exceeded, remaining files are left as-is. */\n maxTotalBytes?: number;\n}\n\ninterface InlineState {\n baseDirReal: string;\n maxFileBytes: number;\n totalBudget: number;\n cache: Map<string, string | null>;\n}\n\nasync function toDataUrl(\n source: string,\n baseDir: string,\n state: InlineState\n): Promise<string | null> {\n // Key the cache by canonical path so equivalent spellings of the same file\n // (`media/logo.png` vs `media/./logo.png`) share one budget charge.\n let cacheKey = source;\n let result: string | null = null;\n try {\n const resolved = await fs.realpath(path.resolve(baseDir, source));\n cacheKey = resolved;\n const cached = state.cache.get(cacheKey);\n if (cached !== undefined) return cached;\n const contained =\n resolved === state.baseDirReal ||\n resolved.startsWith(state.baseDirReal + path.sep);\n if (contained) {\n const mime = MIME_BY_EXTENSION[path.extname(resolved).toLowerCase()];\n if (mime) {\n const stat = await fs.stat(resolved);\n if (\n stat.isFile() &&\n stat.size <= state.maxFileBytes &&\n stat.size <= state.totalBudget\n ) {\n const buffer = await fs.readFile(resolved);\n state.totalBudget -= buffer.length;\n result = `data:${mime};base64,${buffer.toString('base64')}`;\n }\n }\n }\n } catch {\n // Missing or unreadable file: leave the reference for the policy layer,\n // whose error message names the offending JSON path.\n }\n state.cache.set(cacheKey, result);\n return result;\n}\n\nasync function visit(\n value: unknown,\n containerKey: string | undefined,\n baseDir: string,\n state: InlineState,\n seen: WeakSet<object>\n): Promise<void> {\n if (!value || typeof value !== 'object' || seen.has(value)) return;\n seen.add(value);\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n await visit(entry, containerKey, baseDir, state, seen);\n }\n return;\n }\n\n const record = value as JsonRecord;\n\n // Image components: { name: 'image', props: { path } }.\n const componentName =\n typeof record.name === 'string' ? record.name.toLowerCase() : undefined;\n const props = isRecord(record.props) ? record.props : undefined;\n if (\n componentName === 'image' &&\n props &&\n typeof props.path === 'string' &&\n isInlineCandidate(props.path)\n ) {\n const inlined = await toDataUrl(props.path, baseDir, state);\n if (inlined !== null) props.path = inlined;\n }\n\n // Canvas/slide backgrounds: plain { image: { path } } objects.\n if (\n containerKey === 'image' &&\n typeof record.path === 'string' &&\n isInlineCandidate(record.path)\n ) {\n const inlined = await toDataUrl(record.path, baseDir, state);\n if (inlined !== null) record.path = inlined;\n }\n\n for (const [key, child] of Object.entries(record)) {\n await visit(child, key, baseDir, state, seen);\n }\n}\n\nexport async function inlineTemplateMedia(\n jsonDefinition: unknown,\n baseDir: string,\n options: InlineTemplateMediaOptions = {}\n): Promise<unknown> {\n // The generation schema also accepts a JSON string definition; parse it so\n // its media inlines too (the generator accepts either form downstream).\n if (typeof jsonDefinition === 'string') {\n try {\n jsonDefinition = JSON.parse(jsonDefinition);\n } catch {\n // Structural validation owns malformed JSON reporting.\n return jsonDefinition;\n }\n }\n if (!jsonDefinition || typeof jsonDefinition !== 'object') {\n return jsonDefinition;\n }\n\n let baseDirReal: string;\n try {\n baseDirReal = await fs.realpath(baseDir);\n } catch {\n return jsonDefinition;\n }\n\n const clone = structuredClone(jsonDefinition);\n const state: InlineState = {\n baseDirReal,\n maxFileBytes: options.maxFileBytes ?? 10 * 1024 * 1024,\n totalBudget: options.maxTotalBytes ?? 32 * 1024 * 1024,\n cache: new Map(),\n };\n await visit(clone, undefined, baseDir, state, new WeakSet());\n return clone;\n}\n","import { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport { bodyLimit } from 'hono/body-limit';\nimport { getContainer } from '../container/index.js';\nimport {\n LooseDocumentGenerationRequestSchema,\n LooseDocumentValidationRequestSchema,\n LooseDocumentDiffRequestSchema,\n} from '../schemas/loose.js';\nimport { tbValidator, getValidated } from '../lib/typebox-validator.js';\nimport { logger } from '../utils/logger.js';\nimport { rateLimiter } from '../middleware/hono/rate-limit.js';\nimport { AppEnv } from '../types/hono.js';\nimport {\n type FormatAdapter,\n PluginRegistry,\n PluginDiscoveryService,\n} from '@json-to-office/jto-cli';\nimport { dirname } from 'node:path';\nimport { registerRasterizeRoute } from '../rasterize-route.js';\nimport { config } from '../config/index.js';\nimport {\n assertSafeOutboundSources,\n UnsafeOutboundSourceError,\n} from '../security/outbound-source-policy.js';\nimport {\n LibreOfficeBinaryNotFoundError,\n LibreOfficeConversionError,\n LibreOfficeOutputNotFoundError,\n LibreOfficeTimeoutError,\n} from '../services/libreoffice-converter.js';\nimport { inlineTemplateMedia } from '../services/template-media-inliner.js';\n\n/**\n * Re-throw as a 400 when the failure is the document's fault, not the server's.\n *\n * Two kinds qualify. A backend refusing a feature, or the compiler meeting a\n * component it does not lower, both carry a code and a message naming what was\n * missing and where — matched on the code rather than the text, because these\n * cross a dynamic-import boundary where `instanceof` is unreliable and because\n * the wording is not an API. Everything else is matched on the message, which\n * is older and less precise but covers validation failures that predate codes.\n *\n * Returns normally when the error is not a client error, leaving the caller to\n * decide what its own 500 says.\n */\nfunction throwIfClientError(error: unknown): void {\n const code = (error as { code?: unknown } | undefined)?.code;\n if (\n code === 'UNSUPPORTED_RENDERER_FEATURE' ||\n code === 'UNCOMPILED_COMPONENT' ||\n // An id nobody registered is the caller naming a backend that does not\n // exist. The message already lists the ones that do.\n code === 'UNKNOWN_RENDERER'\n ) {\n throw new HTTPException(400, { message: (error as Error).message });\n }\n if (!(error instanceof Error)) return;\n const message = error.message.toLowerCase();\n if (\n message.includes('invalid') ||\n message.includes('validation') ||\n message.includes('missing required') ||\n message.includes('unknown component')\n ) {\n throw new HTTPException(400, { message: error.message });\n }\n}\n\nexport function createFormatRouter(adapter: FormatAdapter) {\n const router = new Hono<AppEnv>();\n const assertRequestSources = (value: unknown, path: string) => {\n try {\n assertSafeOutboundSources(value, config.outboundSources, path);\n } catch (error) {\n if (error instanceof UnsafeOutboundSourceError) {\n throw new HTTPException(400, { message: error.message });\n }\n throw error;\n }\n };\n\n // Map a discovered-document name to its directory so relative asset paths\n // resolve against the document's own location (#142). Only names are\n // accepted from clients; unknown names fall back to cwd-relative resolution.\n const resolveSourceBaseDir = async (\n options: unknown\n ): Promise<string | undefined> => {\n const sourceName = (options as { sourceName?: unknown } | undefined)\n ?.sourceName;\n if (typeof sourceName !== 'string' || sourceName.length === 0) {\n return undefined;\n }\n try {\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const documents = await discovery.discoverDocuments(\n adapter.name as 'docx' | 'pptx'\n );\n const match = documents.find((doc) => doc.name === sourceName);\n return match ? dirname(match.path) : undefined;\n } catch {\n // Discovery is best-effort here; generation proceeds cwd-relative.\n return undefined;\n }\n };\n\n // In safe mode, relative media of a server-discovered document is inlined\n // as data URLs so bundled templates pass source validation and survive the\n // trip to the remote rasterizer. Development mode keeps filesystem\n // resolution (and the path-keyed visual cache) untouched.\n const inlineDiscoveredMedia = async (\n jsonDefinition: unknown,\n baseDir: string | undefined\n ): Promise<unknown> => {\n if (\n baseDir === undefined ||\n config.outboundSources.mode === 'development'\n ) {\n return jsonDefinition;\n }\n return inlineTemplateMedia(jsonDefinition, baseDir, {\n maxFileBytes: config.requestLimits.maxFileSize,\n maxTotalBytes: config.requestLimits.maxBodySize,\n });\n };\n\n const contentTypeMw = async (c: any, next: () => Promise<void>) => {\n const contentType = c.req.header('content-type');\n if (!contentType || !contentType.includes('application/json')) {\n throw new HTTPException(400, {\n message: 'Content-Type must be application/json',\n });\n }\n await next();\n };\n\n // POST /generate\n router.post(\n '/generate',\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 10 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n contentTypeMw,\n tbValidator(LooseDocumentGenerationRequestSchema),\n async (c) => {\n const generatorService = getContainer().get('generatorService');\n const { jsonDefinition, customThemes, options } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: { bypassCache?: boolean; returnUrl?: boolean };\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n try {\n // Resolve the trusted sourceName -> baseDir mapping first so bundled\n // template media can be inlined as data URLs before safe-mode source\n // validation (which rejects relative paths from HTTP clients).\n const baseDir = await resolveSourceBaseDir(options);\n const effectiveDefinition = await inlineDiscoveredMedia(\n jsonDefinition,\n baseDir\n );\n\n assertRequestSources(effectiveDefinition, 'jsonDefinition');\n assertRequestSources(customThemes, 'customThemes');\n assertRequestSources(options, 'options');\n\n const bypassCache =\n c.req.header('X-Bypass-Cache') === 'true' ||\n c.req.query('bypass-cache') === 'true' ||\n options?.bypassCache === true;\n\n // Drop `fonts.strict` from untrusted client input: a toggle that\n // throws on unresolved refs is only meaningful for programmatic\n // callers. Honouring it from an HTTP client would turn any\n // non-safe font reference into a predictable 500 — DoS-adjacent\n // and no useful UX behind it. Advisory only. Build a fresh\n // object rather than mutating the validated request payload.\n let sanitizedFonts: Record<string, unknown> | undefined;\n const rawFonts = (\n options as { fonts?: Record<string, unknown> } | undefined\n )?.fonts;\n if (rawFonts && 'strict' in rawFonts) {\n sanitizedFonts = { ...rawFonts };\n delete sanitizedFonts.strict;\n } else if (rawFonts) {\n sanitizedFonts = rawFonts;\n }\n\n // `baseDir` selects the directory local media paths resolve against —\n // never accept it from the HTTP client. Only the server-side\n // sourceName mapping above may set it.\n const clientOptions = { ...(options as Record<string, unknown>) };\n delete clientOptions.baseDir;\n\n const result = await generatorService.generate({\n jsonDefinition: effectiveDefinition,\n customThemes,\n options: {\n ...clientOptions,\n ...(sanitizedFonts !== undefined && { fonts: sanitizedFonts }),\n ...(baseDir !== undefined && { baseDir }),\n bypassCache,\n },\n });\n\n const cacheService = getContainer().get('cacheService');\n const cacheStats = cacheService.getStats();\n\n const contentType =\n adapter.name === 'pptx'\n ? 'application/vnd.openxmlformats-officedocument.presentationml.presentation'\n : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';\n\n return c.json({\n success: true,\n data: {\n document: result.buffer.toString('base64'),\n filename: result.filename,\n fileId: result.fileId || null,\n contentType,\n },\n cache: {\n status: result.cached ? 'HIT' : 'MISS',\n hitRate: `${(cacheStats.hitRate * 100).toFixed(1)}%`,\n },\n warnings: result.warnings || [],\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n logger.error(`${adapter.label} generation failed`, {\n error,\n requestId,\n });\n\n throwIfClientError(error);\n if (error instanceof HTTPException) throw error;\n throw new HTTPException(500, {\n message: `Internal server error during ${adapter.label} generation`,\n });\n }\n }\n );\n\n // POST /validate\n router.post(\n '/validate',\n contentTypeMw,\n tbValidator(LooseDocumentValidationRequestSchema),\n async (c) => {\n const generatorService = getContainer().get('generatorService');\n const { jsonDefinition } = getValidated<{ jsonDefinition: any }>(\n c,\n 'json'\n );\n const requestId = c.get('requestId');\n\n try {\n const result = await generatorService.validate(jsonDefinition);\n return c.json({\n success: result.valid,\n data: result,\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n logger.error('Validation failed', { error, requestId });\n throw error;\n }\n }\n );\n\n // POST /diff (DOCX only)\n //\n // Compare two document definitions into a tracked-change redline: returns\n // the renderable redline JSON plus a summary. The client previews and\n // downloads the redline through the normal generate/preview pipeline.\n if (adapter.name === 'docx') {\n router.post(\n '/diff',\n bodyLimit({\n // Two full documents per request — same cap rationale as\n // /preview/libreoffice-from-json, doubled.\n maxSize: 32 * 1024 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 30 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n contentTypeMw,\n tbValidator(LooseDocumentDiffRequestSchema),\n async (c) => {\n const { oldDefinition, newDefinition, options } = getValidated<{\n oldDefinition: string | object;\n newDefinition: string | object;\n options?: { author?: string; date?: string };\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n const parseDef = (label: string, def: string | object): object => {\n if (typeof def !== 'string') return def;\n try {\n return JSON.parse(def);\n } catch {\n throw new HTTPException(400, {\n message: `${label} document is not valid JSON`,\n });\n }\n };\n\n try {\n const oldDoc = parseDef('Old', oldDefinition);\n const newDoc = parseDef('New', newDefinition);\n\n // Use the canonical shared-docx validator (same as the CLI).\n const sharedDocx = await import('@json-to-office/shared-docx');\n for (const [label, doc] of [\n ['Old', oldDoc],\n ['New', newDoc],\n ] as const) {\n const result = sharedDocx.validate.jsonDocument(\n JSON.stringify(doc)\n );\n if (!result.valid) {\n return c.json(\n {\n success: false,\n error: `${label} document failed validation`,\n errors: (result.errors || []).slice(0, 20),\n meta: { timestamp: new Date().toISOString(), requestId },\n },\n 400\n );\n }\n }\n\n // Validate and canonicalize the revision date (invalid values\n // would fail RevisionSchema and OOXML ST_DateTime downstream)\n const revisionDate = options?.date\n ? new Date(options.date)\n : new Date();\n if (isNaN(revisionDate.getTime())) {\n throw new HTTPException(400, {\n message: `Invalid date: \"${options?.date}\" (expected ISO 8601)`,\n });\n }\n\n const { diffDocuments } = sharedDocx;\n const { document, summary } = diffDocuments(\n oldDoc as Parameters<typeof diffDocuments>[0],\n newDoc as Parameters<typeof diffDocuments>[1],\n {\n author: options?.author || 'playground',\n date: revisionDate.toISOString(),\n }\n );\n\n return c.json({\n success: true,\n data: { document, summary },\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n logger.error('Document diff failed', { error, requestId });\n if (\n error instanceof Error &&\n error.message.includes('top-level component')\n ) {\n throw new HTTPException(400, { message: error.message });\n }\n throw new HTTPException(500, {\n message: 'Internal server error during document diff',\n });\n }\n }\n );\n }\n\n // POST /preview/libreoffice\n router.post(\n '/preview/libreoffice',\n bodyLimit({\n // Multipart framing adds a small amount around the configured file cap.\n maxSize: config.requestLimits.maxFileSize + 64 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n async (c) => {\n const requestId = c.get('requestId');\n const libreOfficeService = getContainer().get(\n 'libreOfficeConverterService'\n );\n\n try {\n const body = await c.req.parseBody();\n const file = body.file;\n\n if (!file || typeof file === 'string') {\n throw new HTTPException(400, {\n message: `No ${adapter.name.toUpperCase()} file provided`,\n });\n }\n if ((file as File).size === 0) {\n throw new HTTPException(400, {\n message: `${adapter.name.toUpperCase()} file is empty`,\n });\n }\n if ((file as File).size > config.requestLimits.maxFileSize) {\n throw new HTTPException(413, {\n message: `File exceeds ${config.requestLimits.maxFileSize} bytes`,\n });\n }\n\n const expectedExtension = `.${adapter.name}`;\n const originalName =\n (file as File).name || `preview${expectedExtension}`;\n if (!originalName.toLowerCase().endsWith(expectedExtension)) {\n throw new HTTPException(400, {\n message: `Expected a ${adapter.name.toUpperCase()} file`,\n });\n }\n\n const arrayBuffer = await (file as File).arrayBuffer();\n const inputBuffer = Buffer.from(arrayBuffer);\n if (\n inputBuffer.length < 4 ||\n inputBuffer[0] !== 0x50 ||\n inputBuffer[1] !== 0x4b\n ) {\n throw new HTTPException(400, {\n message: `Invalid ${adapter.name.toUpperCase()} file`,\n });\n }\n const pdfBuffer = await libreOfficeService.convertToPdf(\n inputBuffer,\n originalName\n );\n\n const pdfName =\n originalName\n .replace(/\\.[^.]+$/i, '')\n .replace(/[^a-zA-Z0-9._-]/g, '_') + '.pdf';\n c.header('Content-Type', 'application/pdf');\n c.header('Content-Disposition', `inline; filename=\"${pdfName}\"`);\n c.header('Content-Length', String(pdfBuffer.length));\n\n return c.body(pdfBuffer);\n } catch (error) {\n logger.error('LibreOffice preview conversion failed', {\n error,\n requestId,\n });\n if (error instanceof HTTPException) throw error;\n if (error instanceof LibreOfficeBinaryNotFoundError) {\n throw new HTTPException(503, {\n message:\n 'LibreOffice is not available. Install LibreOffice or set LIBREOFFICE_PATH.',\n });\n }\n if (\n error instanceof LibreOfficeTimeoutError ||\n error instanceof LibreOfficeConversionError ||\n error instanceof LibreOfficeOutputNotFoundError\n ) {\n throw new HTTPException(500, {\n message: 'LibreOffice preview conversion failed.',\n });\n }\n throw new HTTPException(500, {\n message: 'Internal server error during preview conversion',\n });\n }\n }\n );\n\n // POST /preview/libreoffice-from-json\n //\n // Generate the document server-side and convert to PDF in one step so\n // resolved fonts flow straight into the LibreOffice font-staging pipeline.\n // The client sends the JSON doc instead of re-uploading the generated file.\n router.post(\n '/preview/libreoffice-from-json',\n bodyLimit({\n // Doc JSON + custom themes. 16 MB accommodates real-world docs that\n // inline base64 image assets (logos, screenshots, chart images); the\n // earlier 2 MB cap rejected legitimate payloads with 413.\n maxSize: 16 * 1024 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n contentTypeMw,\n tbValidator(LooseDocumentGenerationRequestSchema),\n async (c) => {\n const requestId = c.get('requestId');\n const generatorService = getContainer().get('generatorService');\n const libreOfficeService = getContainer().get(\n 'libreOfficeConverterService'\n );\n const { jsonDefinition, customThemes, options } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: { sourceName?: string; renderer?: string };\n }>(c, 'json');\n\n try {\n // Same server-side sourceName -> baseDir mapping as /generate, so\n // previews resolve relative asset paths the way downloads do (#142).\n const baseDir = await resolveSourceBaseDir(options);\n const effectiveDefinition = await inlineDiscoveredMedia(\n jsonDefinition,\n baseDir\n );\n\n assertRequestSources(effectiveDefinition, 'jsonDefinition');\n assertRequestSources(customThemes, 'customThemes');\n assertRequestSources(options, 'options');\n\n const generated = await generatorService.generate({\n jsonDefinition: effectiveDefinition,\n customThemes,\n options: {\n bypassCache: true,\n ...(baseDir !== undefined && { baseDir }),\n // The preview has to come from the backend the caller picked.\n // Regenerating with the default made the picker lie: the PDF on\n // screen and the bytes on download came from different renderers,\n // and a capability refusal was invisible until you downloaded\n // (#255).\n ...(options?.renderer !== undefined && {\n renderer: options.renderer,\n }),\n },\n });\n\n const pdfBuffer = await libreOfficeService.convertToPdf(\n generated.buffer,\n generated.filename,\n generated.resolvedFonts\n );\n\n const pdfName = generated.filename.replace(/\\.[^.]+$/i, '') + '.pdf';\n c.header('Content-Type', 'application/pdf');\n c.header('Content-Disposition', `inline; filename=\"${pdfName}\"`);\n c.header('Content-Length', String(pdfBuffer.length));\n return c.body(pdfBuffer);\n } catch (error) {\n logger.error('LibreOffice (JSON) preview failed', {\n error,\n requestId,\n });\n if (error instanceof HTTPException) throw error;\n // Generation runs inside this route now, so the same document faults\n // the download reports — an unknown backend, a feature it cannot\n // express — have to reach the previewer with the same status.\n throwIfClientError(error);\n if (error instanceof LibreOfficeBinaryNotFoundError) {\n throw new HTTPException(503, {\n message:\n 'LibreOffice is not available. Install LibreOffice or set LIBREOFFICE_PATH.',\n });\n }\n if (\n error instanceof LibreOfficeTimeoutError ||\n error instanceof LibreOfficeConversionError ||\n error instanceof LibreOfficeOutputNotFoundError\n ) {\n throw new HTTPException(500, {\n message: 'LibreOffice preview conversion failed.',\n });\n }\n throw new HTTPException(500, {\n message: 'Internal server error during preview conversion',\n });\n }\n }\n );\n\n // POST /standard-components\n router.post(\n '/standard-components',\n contentTypeMw,\n tbValidator(LooseDocumentGenerationRequestSchema),\n async (c) => {\n const { jsonDefinition, customThemes, options } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: { sourceName?: string };\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n try {\n // Same prologue as /generate: inline a discovered document's bundled\n // media before safe-mode source validation, otherwise templates that\n // reference relative media paths 400 here while rendering fine there.\n const baseDir = await resolveSourceBaseDir(options);\n const effectiveDefinition = await inlineDiscoveredMedia(\n jsonDefinition,\n baseDir\n );\n\n assertRequestSources(effectiveDefinition, 'jsonDefinition');\n assertRequestSources(customThemes, 'customThemes');\n\n let config: unknown;\n try {\n config =\n typeof effectiveDefinition === 'string'\n ? JSON.parse(effectiveDefinition)\n : effectiveDefinition;\n } catch {\n throw new HTTPException(400, {\n message: 'jsonDefinition is not valid JSON',\n });\n }\n\n // If plugins are loaded, use plugin-aware generator to resolve custom components\n const registry = PluginRegistry.getInstance();\n if (registry.hasPlugins()) {\n const plugins = registry.getPlugins();\n const generatorResult = await adapter.createGenerator(plugins, {\n customThemes,\n baseDir,\n });\n\n // Expansion-only path: resolves custom components to the standard\n // tree without fonts/layout/rendering (#155) — the old deprecated\n // wrapper ran a full generation, LibreOffice rasterization included.\n if (generatorResult.getStandardDefinition) {\n const standardComponents =\n await generatorResult.getStandardDefinition(config);\n return c.json({\n success: true,\n data: standardComponents,\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n }\n }\n\n // No plugins — config is already standard components\n return c.json({\n success: true,\n data: config,\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n logger.error('Failed to get standard components definition', {\n error,\n requestId,\n });\n if (error instanceof HTTPException) throw error;\n throwIfClientError(error);\n throw new HTTPException(500, {\n message: 'Failed to get standard components definition',\n });\n }\n }\n );\n\n // GET /renderers — the backends this format registers, defaults first.\n router.get('/renderers', async (c) => {\n try {\n const ids = await adapter.rendererIds();\n return c.json({\n success: true,\n data: { ids, default: ids[0] ?? null },\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to list renderers', { error });\n throw new HTTPException(500, { message: 'Failed to list renderers' });\n }\n });\n\n // GET /cache-stats\n router.get('/cache-stats', async (c) => {\n try {\n const cacheService = getContainer().get('cacheService');\n const stats = cacheService.getStats();\n // Rasterizer cache observability (#156): the disk cache and the batch\n // dedupe are where `visual` caching lives. There is no component render\n // cache to report any more — compiling a document to an IR is cheap and\n // holds no cross-document state.\n const rasterizer = await (async () => {\n try {\n const cli = await import('@json-to-office/jto-cli');\n const engine = await cli.getRasterizerCacheStats?.();\n if (!engine) return null;\n const prepass = (await adapter.getVisualPrepassStats?.()) ?? null;\n return { ...engine, ...(prepass ? { prepass } : {}) };\n } catch {\n return null;\n }\n })();\n return c.json({\n success: true,\n data: {\n document: {\n hits: stats.hits,\n misses: stats.misses,\n hitRate: stats.hitRate,\n size: stats.size,\n itemCount: stats.itemCount,\n enabled: stats.enabled,\n },\n ...(rasterizer ? { rasterizer } : {}),\n },\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to get cache statistics', { error });\n throw new HTTPException(500, {\n message: 'Failed to get cache statistics',\n });\n }\n });\n\n // DELETE /cache\n router.delete('/cache', async (c) => {\n try {\n const cacheService = getContainer().get('cacheService');\n cacheService.clear();\n const cli = await import('@json-to-office/jto-cli');\n cli.invalidateAllCaches();\n // \"Clear all caches\" means all of them: the rasterizer's PNG disk cache\n // used to survive this call (#156).\n await adapter.resetCacheStats?.();\n await cli.clearRasterizerCache?.();\n return c.json({\n success: true,\n data: { message: 'Cache cleared successfully' },\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to clear cache', { error });\n throw new HTTPException(500, { message: 'Failed to clear cache' });\n }\n });\n\n // POST /rasterize — render a single-slide pptx presentation to a PNG.\n // Backs the docx `visual` component when it is configured with\n // `services.pptx.serverUrl`. Shares the validated handler + limits with the\n // standalone jto-render-server (see rasterize-route.ts).\n registerRasterizeRoute(router, {\n preMiddleware: [\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 10 : 1000,\n window: 15 * 60 * 1000,\n // One bucket for /rasterize AND /rasterize/batch — without a shared\n // namespace the default per-path key would double the budget.\n namespace: 'rasterize',\n trustProxy: config.rateLimit.trustProxy,\n }),\n ],\n sourcePolicy: config.outboundSources,\n onError: (error) => logger.error('Visual rasterization failed', { error }),\n });\n\n return router;\n}\n","import { Hono } from 'hono';\nimport {\n PluginDiscoveryService,\n PluginRegistry,\n} from '@json-to-office/jto-cli';\nimport { latestVersion } from '@json-to-office/shared';\nimport { logger } from '../utils/logger.js';\nimport { AppEnv } from '../types/hono.js';\nimport { Container } from '../container/index.js';\n\nexport const discoveryRouter = new Hono<AppEnv>();\n\n// ---------------------------------------------------------------------------\n// Schema generation helpers (mirrors client-side json-schema-generator.ts)\n// ---------------------------------------------------------------------------\n\nfunction cleanupTypeBoxIds(schema: any): void {\n if (typeof schema !== 'object' || schema === null) return;\n if (schema.$id && /^T\\d+$/.test(schema.$id)) delete schema.$id;\n if (schema.$ref && /^T\\d+$/.test(schema.$ref))\n schema.$ref = '#/definitions/ComponentDefinition';\n if (Array.isArray(schema)) {\n schema.forEach(cleanupTypeBoxIds);\n return;\n }\n Object.keys(schema).forEach((key) => {\n if (typeof schema[key] === 'object' && schema[key] !== null)\n cleanupTypeBoxIds(schema[key]);\n });\n}\n\n/**\n * Schema generation must not depend on the client having POSTed\n * `/load-plugins` first. The playground fires that bootstrap POST and the\n * first schema fetch in parallel on page load; when the schema request won\n * the race (or the POST failed), the registry was empty, the requested\n * plugins were silently dropped, and Monaco kept a plugin-less schema —\n * enabled components neither completed nor validated until a toggle forced a\n * refetch. Requests that need plugins now load them on demand; the registry\n * coalesces concurrent loads and its load fingerprint makes repeats a no-op.\n *\n * Dev-playground affordance only: in production, plugin loading stays behind\n * the authenticated POST /load-plugins (same policy check as that route), so\n * an unauthenticated schema request cannot trigger discovery — generation\n * falls back to whatever is already registered.\n */\nasync function ensurePluginsRegistered(\n format: 'docx' | 'pptx',\n pluginNames?: string[]\n): Promise<void> {\n if (process.env.NODE_ENV === 'production') return;\n\n const registry = PluginRegistry.getInstance();\n const satisfied = pluginNames\n ? pluginNames.every((name) => registry.getPlugin(name))\n : registry.hasPlugins();\n if (satisfied) return;\n\n registry.setFormat(format);\n try {\n await registry.discoverAndLoad();\n } catch (error: any) {\n // Schema generation falls back to standard components only.\n logger.warn('On-demand plugin load for schema generation failed', {\n error: error?.message,\n });\n }\n}\n\nfunction getSelectedPlugins(pluginNames?: string[]) {\n const registry = PluginRegistry.getInstance();\n if (!registry.hasPlugins()) return [];\n\n // An explicit array is an exact selection — [] means \"no plugins\", so a\n // playground with every plugin toggled off gets the plugin-free schema.\n // Only an absent selection falls back to every registered plugin.\n const plugins = pluginNames\n ? pluginNames.map((n) => registry.getPlugin(n)).filter(Boolean)\n : registry.getPlugins();\n\n return plugins.map((plugin) => {\n const versions = (plugin as any).versions || {};\n const versionKeys = Object.keys(versions);\n const latest =\n versionKeys.length > 0 ? latestVersion(versionKeys) : undefined;\n const latestEntry = latest ? versions[latest] : undefined;\n\n return { name: plugin!.name, versions, versionKeys, latest, latestEntry };\n });\n}\n\nasync function generateDocumentSchema(\n format: string,\n pluginNames?: string[]\n): Promise<any> {\n await ensurePluginsRegistered(format as 'docx' | 'pptx', pluginNames);\n const selected = getSelectedPlugins(pluginNames);\n\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n const customComponents = selected\n .filter((p) => p.latestEntry?.propsSchema)\n .map((p) => {\n const info: any = {\n name: p.name,\n propsSchema: p.latestEntry!.propsSchema,\n hasChildren: p.latestEntry?.hasChildren,\n description: p.latestEntry?.description,\n };\n if (p.versionKeys.length > 1) {\n info.versionedProps = p.versionKeys.map((v) => ({\n version: v,\n propsSchema: p.versions[v].propsSchema,\n description: p.versions[v].description,\n hasChildren: p.versions[v].hasChildren,\n }));\n }\n return info;\n });\n const unified = shared.generateUnifiedDocumentSchema({ customComponents });\n return shared.convertToJsonSchema(unified, {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://json-to-office.dev/schema/document/v1.0.0',\n title: 'JSON to DOCX Document Definition',\n description: 'Schema for JSON to DOCX JSON document definitions',\n });\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n const customComponents = selected.map((p) => ({\n name: p.name,\n versions: p.versionKeys.map((v) => ({\n version: v,\n propsSchema: p.versions[v].propsSchema,\n hasChildren: p.versions[v].hasChildren,\n description: p.versions[v].description,\n })),\n }));\n const unified = shared.generateUnifiedDocumentSchema({ customComponents });\n return shared.convertToJsonSchema(unified, {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://json-to-office.dev/schema/presentation/v1.0.0',\n title: 'JSON to PPTX Presentation Definition',\n description: 'Schema for JSON to PPTX JSON presentation definitions',\n });\n }\n}\n\nasync function generateThemeSchema(format: string): Promise<any> {\n let source: any;\n let label: string;\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n source = shared.ThemeConfigSchema;\n label = 'DOCX';\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n source = shared.ThemeConfigSchema;\n label = 'PPTX';\n }\n const schema = JSON.parse(JSON.stringify(source));\n cleanupTypeBoxIds(schema);\n return {\n ...schema,\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://json-to-office.dev/schemas/theme/v1.0.0',\n title: `JSON to ${label} Theme`,\n description: `Theme definition for JSON to ${label} ${format === 'docx' ? 'documents' : 'presentations'}`,\n };\n}\n\ndiscoveryRouter.get('/all', async (c) => {\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const [plugins, documents, themes] = await Promise.all([\n discovery.discoverPlugins(format),\n discovery.discoverDocuments(format),\n discovery.discoverThemes(format),\n ]);\n const results = { plugins, documents, themes };\n return c.json({\n success: true,\n data: results,\n counts: {\n plugins: results.plugins.length,\n documents: results.documents.length,\n themes: results.themes.length,\n },\n });\n } catch (error: any) {\n logger.error('Discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/plugins', async (c) => {\n try {\n const includeSchemas = c.req.query('schemas') === 'true';\n const includeExamples = c.req.query('examples') === 'true';\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const plugins = await discovery.discoverPlugins(format);\n const processed = plugins.map((plugin) => {\n const result: any = { ...plugin };\n if (!includeSchemas && result.schema) {\n delete result.schema.raw;\n delete result.schema.jsonSchema;\n }\n if (!includeExamples) delete result.examples;\n return result;\n });\n return c.json({ success: true, data: processed, count: plugins.length });\n } catch (error: any) {\n logger.error('Plugin discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/documents', async (c) => {\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const documents = await discovery.discoverDocuments(format);\n return c.json({ success: true, data: documents, count: documents.length });\n } catch (error: any) {\n logger.error('Document discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/themes', async (c) => {\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const themes = await discovery.discoverThemes(format);\n return c.json({ success: true, data: themes, count: themes.length });\n } catch (error: any) {\n logger.error('Theme discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/plugin/:name', async (c) => {\n try {\n const pluginName = c.req.param('name');\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const plugins = await discovery.discoverPlugins(format);\n const plugin = plugins.find((p) => p.name === pluginName);\n if (!plugin)\n return c.json(\n { success: false, error: `Plugin '${pluginName}' not found` },\n 404\n );\n return c.json({ success: true, data: plugin });\n } catch (error: any) {\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.post('/load-plugins', async (c) => {\n // Require API key for plugin loading regardless of global auth setting\n const apiKey = c.req.header('X-API-Key') || c.req.header('Authorization');\n if (!apiKey && process.env.NODE_ENV === 'production') {\n return c.json({ success: false, error: 'Authentication required' }, 401);\n }\n\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const registry = PluginRegistry.getInstance();\n registry.setFormat(format);\n const result = await registry.discoverAndLoad();\n return c.json({ success: true, data: result });\n } catch (error: any) {\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/documents/:name/content', async (c) => {\n try {\n const name = c.req.param('name');\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const content = await discovery.getDocumentContent(name, format);\n return c.text(content);\n } catch (error: any) {\n const status = error.message.includes('not found') ? 404 : 500;\n return c.json({ success: false, error: error.message }, status);\n }\n});\n\ndiscoveryRouter.get('/themes/:name/content', async (c) => {\n try {\n const name = c.req.param('name');\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const content = await discovery.getThemeContent(name, format);\n return c.text(content);\n } catch (error: any) {\n const status = error.message.includes('not found') ? 404 : 500;\n return c.json({ success: false, error: error.message }, status);\n }\n});\n\ndiscoveryRouter.get('/schemas/document', async (c) => {\n try {\n const adapter = Container.getAdapter();\n const pluginsParam = c.req.query('plugins');\n // `?plugins=` (empty) is an explicit \"no plugins\"; only a missing param\n // means \"all registered plugins\".\n const pluginNames =\n pluginsParam !== undefined\n ? pluginsParam.split(',').filter(Boolean)\n : undefined;\n const schema = await generateDocumentSchema(adapter.name, pluginNames);\n return c.json({ success: true, data: schema });\n } catch (error: any) {\n logger.error('Document schema generation failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/schemas/theme', async (c) => {\n try {\n const adapter = Container.getAdapter();\n const schema = await generateThemeSchema(adapter.name);\n return c.json({ success: true, data: schema });\n } catch (error: any) {\n logger.error('Theme schema generation failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n","/**\n * Builds and caches the full JSON schema per format for AI structured output.\n */\nimport { Container } from '../container/index.js';\n\nconst schemaCache = new Map<string, any>();\n\nfunction cleanupTypeBoxIds(schema: any): void {\n if (typeof schema !== 'object' || schema === null) return;\n if (schema.$id && /^T\\d+$/.test(schema.$id)) delete schema.$id;\n if (schema.$ref && /^T\\d+$/.test(schema.$ref))\n schema.$ref = '#/definitions/ComponentDefinition';\n if (Array.isArray(schema)) {\n schema.forEach(cleanupTypeBoxIds);\n return;\n }\n Object.keys(schema).forEach((key) => {\n if (typeof schema[key] === 'object' && schema[key] !== null)\n cleanupTypeBoxIds(schema[key]);\n });\n}\n\nexport async function getDocumentSchema(format: string): Promise<any> {\n const cacheKey = `${format}:document`;\n if (schemaCache.has(cacheKey)) return schemaCache.get(cacheKey);\n\n let schema: any;\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n const unified = shared.generateUnifiedDocumentSchema({\n customComponents: [],\n });\n schema = shared.convertToJsonSchema(unified, {\n title: 'JSON to DOCX Document',\n description: 'Schema for JSON to DOCX document definitions',\n });\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n const unified = shared.generateUnifiedDocumentSchema({\n customComponents: [],\n });\n schema = shared.convertToJsonSchema(unified, {\n title: 'JSON to PPTX Presentation',\n description: 'Schema for JSON to PPTX presentation definitions',\n });\n }\n\n // Remove $schema URI — not needed for AI context\n delete schema.$schema;\n delete schema.$id;\n cleanupTypeBoxIds(schema);\n\n schemaCache.set(cacheKey, schema);\n return schema;\n}\n\nexport async function getThemeSchema(format: string): Promise<any> {\n const cacheKey = `${format}:theme`;\n if (schemaCache.has(cacheKey)) return schemaCache.get(cacheKey);\n\n let schema: any;\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n schema = shared.convertToJsonSchema(shared.ThemeConfigSchema, {\n title: 'JSON to DOCX Theme',\n description: 'Schema for DOCX theme configuration',\n });\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n schema = shared.convertToJsonSchema(shared.ThemeConfigSchema, {\n title: 'JSON to PPTX Theme',\n description: 'Schema for PPTX theme configuration',\n });\n }\n\n delete schema.$schema;\n delete schema.$id;\n cleanupTypeBoxIds(schema);\n\n schemaCache.set(cacheKey, schema);\n return schema;\n}\n\nexport async function getSchemaString(format: string, docType: 'document' | 'theme'): Promise<string> {\n const schema = docType === 'theme'\n ? await getThemeSchema(format)\n : await getDocumentSchema(format);\n return JSON.stringify(schema, null, 2);\n}\n\nexport function getDocumentSchemaString(format: string): Promise<string> {\n return getSchemaString(format, 'document');\n}\n\nexport function getFormatFromContainer(): string {\n return Container.getAdapter().name;\n}\n","/**\n * Reads .md prompt files from the prompts/ directory and interpolates {{var}} placeholders.\n */\nimport { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// In dev (tsx): __dirname = src/server/services → ../prompts\n// In prod (tsup): __dirname = dist → look for prompts in src/server/prompts (fallback)\nfunction resolvePromptsDir(): string {\n const candidates = [\n join(__dirname, '..', 'prompts'), // dev: src/server/prompts\n join(__dirname, 'prompts'), // bundled: dist/prompts\n join(__dirname, '..', 'src', 'server', 'prompts'), // prod from dist/\n ];\n for (const dir of candidates) {\n if (existsSync(dir)) return dir;\n }\n return candidates[0]; // fallback — will error on read if missing\n}\n\nconst PROMPTS_DIR = resolvePromptsDir();\n\nconst cache = new Map<string, string>();\n\nfunction readPromptFile(name: string): string {\n if (cache.has(name)) return cache.get(name)!;\n const filePath = join(PROMPTS_DIR, name);\n const content = readFileSync(filePath, 'utf-8');\n cache.set(name, content);\n return content;\n}\n\nexport function loadPrompt(\n name: string,\n vars: Record<string, string> = {}\n): string {\n let content = readPromptFile(name);\n for (const [key, value] of Object.entries(vars)) {\n content = content.replaceAll(`{{${key}}}`, value);\n }\n return content;\n}\n","import { Hono } from 'hono';\nimport { streamText, convertToModelMessages, type ModelMessage } from 'ai';\nimport { claudeCode } from 'ai-sdk-provider-claude-code';\nimport { extractText as extractPdfText } from 'unpdf';\nimport { AppEnv } from '../types/hono.js';\nimport {\n getSchemaString,\n getFormatFromContainer,\n} from '../services/ai-schema.js';\nimport { loadPrompt } from '../services/prompt-loader.js';\nimport { logger } from '../utils/logger.js';\nimport { rateLimiter } from '../middleware/hono/rate-limit.js';\nimport { config } from '../config/index.js';\n\nfunction sanitizeFilename(name: string): string {\n return name.replace(/[[\\]\\n\\r]/g, '_');\n}\n\n/**\n * Convert data: URL file parts to inline base64 so providers that\n * reject data: URLs (e.g. claude-code) can consume them.\n */\nfunction fixDataUrlFileParts(messages: ModelMessage[]): ModelMessage[] {\n for (const msg of messages) {\n if (msg.role !== 'user' || typeof msg.content === 'string') continue;\n for (const part of msg.content) {\n if (part.type !== 'file') continue;\n const data = part.data;\n if (data instanceof URL && data.protocol === 'data:') {\n const str = data.toString();\n const commaIdx = str.indexOf(',');\n if (commaIdx !== -1) {\n const isBase64 = str.slice(0, commaIdx).includes(';base64');\n const payload = str.slice(commaIdx + 1);\n const decoded = Buffer.from(\n decodeURIComponent(payload),\n 'utf-8'\n ).toString('base64');\n part.data = isBase64 ? payload : decoded;\n }\n } else if (typeof data === 'string' && data.startsWith('data:')) {\n const commaIdx = data.indexOf(',');\n if (commaIdx !== -1) {\n const isBase64 = data.slice(0, commaIdx).includes(';base64');\n const payload = data.slice(commaIdx + 1);\n const decoded = Buffer.from(\n decodeURIComponent(payload),\n 'utf-8'\n ).toString('base64');\n part.data = isBase64 ? payload : decoded;\n }\n }\n }\n }\n return messages;\n}\n\nconst TEXT_MIME_TYPES = new Set([\n 'text/plain',\n 'text/markdown',\n 'text/csv',\n 'text/html',\n]);\n\nfunction toBuffer(data: string | Uint8Array | ArrayBuffer | URL): Buffer {\n if (data instanceof ArrayBuffer) return Buffer.from(new Uint8Array(data));\n if (data instanceof Uint8Array) return Buffer.from(data);\n if (data instanceof URL) {\n const str = data.toString();\n const commaIdx = str.indexOf(',');\n if (commaIdx === -1) return Buffer.from(str, 'base64');\n const isBase64 = str.slice(0, commaIdx).includes(';base64');\n const payload = str.slice(commaIdx + 1);\n return isBase64\n ? Buffer.from(payload, 'base64')\n : Buffer.from(decodeURIComponent(payload), 'utf-8');\n }\n // base64 string (or raw data: string already stripped by fixDataUrlFileParts)\n return Buffer.from(data, 'base64');\n}\n\nasync function extractFileText(\n mimeType: string,\n data: string | Uint8Array | ArrayBuffer | URL\n): Promise<string> {\n const buf = toBuffer(data);\n if (mimeType === 'application/pdf') {\n const { text } = await extractPdfText(new Uint8Array(buf));\n return Array.isArray(text) ? text.join('\\n') : String(text);\n }\n // text/* types\n return buf.toString('utf-8');\n}\n\nasync function extractNonImageFileParts(\n messages: ModelMessage[]\n): Promise<ModelMessage[]> {\n for (const msg of messages) {\n if (msg.role !== 'user' || typeof msg.content === 'string') continue;\n const newContent: typeof msg.content = [];\n for (const part of msg.content) {\n if (part.type !== 'file') {\n newContent.push(part);\n continue;\n }\n const mime = part.mediaType ?? '';\n // Images pass through — the provider handles them\n if (mime.startsWith('image/')) {\n newContent.push(part);\n continue;\n }\n // Non-image file: extract text\n if (mime === 'application/pdf' || TEXT_MIME_TYPES.has(mime)) {\n const filename = sanitizeFilename((part as any).filename || 'file');\n try {\n const text = await extractFileText(mime, part.data);\n newContent.push({\n type: 'text' as const,\n text: `[Attached file: ${filename}]\\n${text}`,\n });\n } catch (err: any) {\n logger.warn('Failed to extract file content', {\n filename,\n mime,\n error: err.message,\n });\n newContent.push({\n type: 'text' as const,\n text: `[Attached file: ${filename} — could not extract content]`,\n });\n }\n } else {\n // Unknown MIME — mention it but don't crash\n const filename = sanitizeFilename((part as any).filename || 'file');\n newContent.push({\n type: 'text' as const,\n text: `[Attached file: ${filename} — unsupported format: ${mime}]`,\n });\n }\n }\n msg.content = newContent;\n }\n return messages;\n}\n\nexport function createAiRouter() {\n const router = new Hono<AppEnv>();\n\n router.post(\n '/chat',\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 30 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n async (c) => {\n try {\n const body = await c.req.json();\n const {\n messages,\n context,\n format: clientFormat,\n activeDocument,\n documentType,\n scope,\n model: requestedModel,\n } = body;\n const VALID_MODELS = ['opus', 'sonnet', 'haiku'] as const;\n const model = VALID_MODELS.includes(requestedModel)\n ? requestedModel\n : 'opus';\n\n const format = clientFormat || getFormatFromContainer();\n const isTheme = documentType === 'application/json+theme';\n const schemaStr = await getSchemaString(\n format,\n isTheme ? 'theme' : 'document'\n );\n const contentLabel = isTheme ? 'Theme' : 'Document';\n\n // === Prompt assembly: base → format → format+design → mode ===\n\n // Layer 1: Base\n let systemPrompt = loadPrompt(\n isTheme ? 'system-theme.md' : 'system.md',\n {\n format,\n schema: schemaStr,\n }\n );\n\n // Layer 2: Format-specific core (always loaded)\n if (!isTheme) {\n if (format === 'pptx') {\n systemPrompt += '\\n\\n' + loadPrompt('pptx-core.md');\n } else if (format === 'docx') {\n systemPrompt += '\\n\\n' + loadPrompt('instructions-docx.md');\n }\n }\n\n // Determine mode: selection-edit, edit-document, or generate\n const hasSelection =\n context && context.length > 0 && context[0]?.selectedText;\n const hasActiveDoc = !hasSelection && activeDocument?.text;\n const isGenerate = !hasSelection && !hasActiveDoc;\n\n // Layer 3: Format+design (generate and edit-document only, not selection-edit)\n if (!isTheme && format === 'pptx' && !hasSelection) {\n systemPrompt += '\\n\\n' + loadPrompt('pptx-design.md');\n }\n\n // Layer 4: Mode-specific instructions\n if (hasSelection) {\n const ctx = context[0];\n // Use pptx-aware selection editing for pptx, generic for others\n const editFile =\n format === 'pptx' && !isTheme\n ? 'instructions-edit-pptx.md'\n : 'instructions-edit.md';\n systemPrompt +=\n '\\n\\n' +\n loadPrompt(editFile, {\n documentName: ctx.documentName || 'unknown',\n jsonPath: ctx.jsonPath || '',\n selectedText: ctx.selectedText,\n });\n } else if (hasActiveDoc) {\n const pptxScope =\n format === 'pptx' &&\n !isTheme &&\n (scope === 'slides' || scope === 'templates');\n\n let parsedDoc: any = null;\n if (pptxScope) {\n try {\n parsedDoc = JSON.parse(activeDocument.text);\n } catch {\n /* fall through to global */\n }\n }\n\n if (pptxScope && parsedDoc) {\n const doc = parsedDoc;\n\n if (scope === 'slides') {\n const templatesSummary = (doc.props?.templates || [])\n .map((m: any) => {\n const phs = (m.placeholders || [])\n .map((p: any) => {\n const d = p.defaults\n ? ` → defaults: ${JSON.stringify(p.defaults)}`\n : '';\n return ` - \\`${p.name}\\`${d}`;\n })\n .join('\\n');\n return `**${m.name}**\\n${phs}`;\n })\n .join('\\n\\n');\n const slidesText = JSON.stringify(doc.children || [], null, 2);\n systemPrompt +=\n '\\n\\n' +\n loadPrompt('instructions-edit-document-pptx-slides.md', {\n documentName: activeDocument.name || 'untitled',\n templatesSummary,\n slidesText,\n });\n } else {\n const templatesText = JSON.stringify(\n doc.props?.templates || [],\n null,\n 2\n );\n const slidesSummary = (doc.children || [])\n .map((s: any, i: number) => {\n const template = s.props?.template || '(none)';\n const phs = Object.keys(s.props?.placeholders || {}).join(\n ', '\n );\n return ` ${i}: template=${template}, placeholders=[${phs}]`;\n })\n .join('\\n');\n systemPrompt +=\n '\\n\\n' +\n loadPrompt('instructions-edit-document-pptx-templates.md', {\n documentName: activeDocument.name || 'untitled',\n templatesText,\n slidesSummary,\n });\n }\n } else {\n const editDocFiles: Record<string, string> = {\n pptx: 'instructions-edit-document-pptx.md',\n docx: 'instructions-edit-document-docx.md',\n };\n const editDocFile = isTheme\n ? 'instructions-edit-document.md'\n : editDocFiles[format] ?? 'instructions-edit-document.md';\n systemPrompt +=\n '\\n\\n' +\n loadPrompt(editDocFile, {\n contentLabel,\n contentLabelLower: contentLabel.toLowerCase(),\n documentName: activeDocument.name || 'untitled',\n documentText: activeDocument.text,\n });\n }\n } else if (isGenerate) {\n const generateFiles: Record<string, string> = {\n pptx: 'instructions-generate-pptx.md',\n docx: 'instructions-generate-docx.md',\n };\n const generateFile = isTheme\n ? 'instructions-generate.md'\n : generateFiles[format] ?? 'instructions-generate.md';\n systemPrompt +=\n '\\n\\n' +\n loadPrompt(generateFile, {\n contentType: isTheme ? 'theme' : 'document',\n });\n }\n\n // If context is provided (selection from editor), prepend as a user message\n const allMessages = [...messages];\n if (context && context.length > 0) {\n const contextParts = context.map((ctx: any) => {\n const parts: string[] = [];\n if (ctx.documentName) parts.push(`Document: ${ctx.documentName}`);\n if (ctx.jsonPath) parts.push(`JSON Path: ${ctx.jsonPath}`);\n if (ctx.selectedText)\n parts.push(`Selected:\\n\\`\\`\\`json\\n${ctx.selectedText}\\n\\`\\`\\``);\n return parts.join('\\n');\n });\n\n // Insert context as a system-style user message before the last user message\n const lastMsg = allMessages[allMessages.length - 1];\n if (lastMsg && lastMsg.role === 'user') {\n const contextPrefix = `[Editor Context]\\n${contextParts.join('\\n---\\n')}\\n\\n`;\n // Prepend context to the last user message text\n if (typeof lastMsg.content === 'string') {\n lastMsg.content = contextPrefix + lastMsg.content;\n } else if (Array.isArray(lastMsg.parts)) {\n lastMsg.parts = [\n { type: 'text', text: contextPrefix },\n ...lastMsg.parts,\n ];\n }\n }\n }\n\n const modelMessages = await extractNonImageFileParts(\n fixDataUrlFileParts(await convertToModelMessages(allMessages))\n );\n\n const result = streamText({\n model: claudeCode(model, {\n streamingInput: 'always',\n disallowedTools: [\n 'Read',\n 'Write',\n 'Edit',\n 'Glob',\n 'Grep',\n 'Bash',\n 'Agent',\n ],\n persistSession: false,\n }),\n system: systemPrompt,\n messages: modelMessages,\n });\n\n return result.toUIMessageStreamResponse();\n } catch (error: any) {\n const message = error.message || 'Unknown error';\n const status = error.status || error.statusCode || 500;\n\n if (status === 429 || message.includes('rate')) {\n logger.warn('AI rate limit hit', { error: message });\n return c.json(\n {\n error:\n 'Rate limit exceeded. Please wait before sending another message.',\n },\n 429\n );\n }\n if (\n status === 413 ||\n message.includes('too large') ||\n message.includes('too long') ||\n message.includes('exceeds maximum')\n ) {\n logger.warn('AI request too large', { error: message });\n return c.json(\n {\n error:\n 'Request too large for the AI model. Try selecting a smaller portion of the document.',\n },\n 413\n );\n }\n if (error.name === 'AbortError' || message.includes('abort')) {\n logger.info('AI request aborted');\n return c.json({ error: 'Request was cancelled.' }, 400);\n }\n\n logger.error('AI chat error', { error: message, stack: error.stack });\n return c.json(\n {\n error:\n process.env.NODE_ENV === 'production'\n ? 'Something went wrong. Please try again.'\n : message,\n },\n 500\n );\n }\n }\n );\n\n return router;\n}\n","/**\n * Font catalog + Google Fonts materialization endpoints for the playground.\n *\n * GET /catalog — safe + popular Google fonts (static; cached)\n * POST /materialize — server-side Google Fonts fetch; returns base64 sources\n * so the client can insert `kind: \"data\"` entries into the\n * document JSON (self-contained, survives export/reimport).\n */\n\nimport { createHash } from 'node:crypto';\nimport { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport { bodyLimit } from 'hono/body-limit';\nimport {\n SAFE_FONTS,\n POPULAR_GOOGLE_FONTS,\n fetchGoogleFontSources,\n} from '@json-to-office/shared';\nimport { rateLimiter } from '../middleware/hono/rate-limit.js';\nimport type { AppEnv } from '../types/hono.js';\nimport { config } from '../config/index.js';\n\nexport const fontsRouter = new Hono<AppEnv>();\n\nconst MATERIALIZE_FAMILY_MAX = 64;\nconst MATERIALIZE_WEIGHTS_MAX = 9;\n\n// Precomputed body + ETag for /catalog. SAFE_FONTS and POPULAR_GOOGLE_FONTS\n// are module-level constants, so the payload only changes on deploy. Hashing\n// once at import lets every request answer with a 304 when the client\n// already has the current catalog.\nconst CATALOG_BODY = JSON.stringify({\n safe: SAFE_FONTS,\n google: POPULAR_GOOGLE_FONTS,\n});\nconst CATALOG_ETAG = `\"${createHash('sha256')\n .update(CATALOG_BODY)\n .digest('base64')\n .slice(0, 24)}\"`;\n\nfontsRouter.get('/catalog', (c) => {\n const ifNoneMatch = c.req.header('If-None-Match');\n if (ifNoneMatch && ifNoneMatch === CATALOG_ETAG) {\n c.header('ETag', CATALOG_ETAG);\n c.header('Cache-Control', 'public, max-age=86400');\n return c.body(null, 304);\n }\n c.header('Content-Type', 'application/json');\n c.header('ETag', CATALOG_ETAG);\n c.header('Cache-Control', 'public, max-age=86400');\n return c.body(CATALOG_BODY, 200);\n});\n\ninterface MaterializeBody {\n family?: string;\n weights?: number[];\n italics?: boolean;\n}\n\nfontsRouter.post(\n '/materialize',\n bodyLimit({\n // Body is just {family, weights, italics} — 16 KB is generous.\n maxSize: 16 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n async (c) => {\n let body: MaterializeBody;\n try {\n body = (await c.req.json()) as MaterializeBody;\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n\n const family = body.family?.trim();\n if (!family) {\n return c.json({ error: 'Missing required field: family' }, 400);\n }\n if (family.length > MATERIALIZE_FAMILY_MAX) {\n return c.json(\n { error: `family exceeds ${MATERIALIZE_FAMILY_MAX} characters` },\n 400\n );\n }\n // Dedup + cap weights so a crafted request can't fan out to thousands of\n // upstream Google fetches. 9 canonical weights (100..900) is the ceiling.\n const weights =\n Array.isArray(body.weights) && body.weights.length > 0\n ? Array.from(\n new Set(\n body.weights.filter(\n (w) => typeof w === 'number' && w >= 100 && w <= 900\n )\n )\n ).slice(0, MATERIALIZE_WEIGHTS_MAX)\n : [400, 700];\n const italics = Boolean(body.italics);\n\n try {\n const { sources, warnings } = await fetchGoogleFontSources({\n family,\n weights,\n italics,\n });\n return c.json({\n family,\n sources: sources.map((s) => ({\n weight: s.weight,\n italic: s.italic,\n format: s.format,\n data: s.data.toString('base64'),\n })),\n warnings,\n });\n } catch (err) {\n return c.json(\n {\n error: `Google Fonts materialize failed: ${(err as Error).message}`,\n },\n 502\n );\n }\n }\n);\n","import { MiddlewareHandler } from 'hono';\nimport { randomUUID } from 'crypto';\n\n/**\n * Request ID middleware for Hono\n * Generates a unique ID for each request for tracing\n */\nexport const requestIdMiddleware: MiddlewareHandler = async (c, next) => {\n const requestId = c.req.header('X-Request-Id') || randomUUID();\n\n // Set request ID in context\n c.set('requestId', requestId);\n\n // Add to response headers\n c.header('X-Request-Id', requestId);\n\n await next();\n};\n","import { createHash, timingSafeEqual } from 'node:crypto';\nimport { MiddlewareHandler } from 'hono';\nimport { config } from '../../config';\nimport type { ApiAuthMode } from '../../config';\n\nexport interface ApiKeyAuthOptions {\n mode: ApiAuthMode;\n apiKey?: string;\n headerName?: string;\n}\n\nfunction keysEqual(received: string, expected: string): boolean {\n const receivedDigest = createHash('sha256').update(received).digest();\n const expectedDigest = createHash('sha256').update(expected).digest();\n return timingSafeEqual(receivedDigest, expectedDigest);\n}\n\nfunction readCredential(\n headers: Headers,\n headerName: string\n): string | undefined {\n const direct = headers.get(headerName)?.trim();\n if (direct) {\n if (\n headerName.toLowerCase() === 'authorization' &&\n direct.toLowerCase().startsWith('bearer ')\n ) {\n return direct.slice(7).trim() || undefined;\n }\n return direct;\n }\n\n const authorization = headers.get('authorization')?.trim();\n if (authorization?.toLowerCase().startsWith('bearer ')) {\n return authorization.slice(7).trim() || undefined;\n }\n return undefined;\n}\n\n/**\n * API Key authentication middleware for Hono\n */\nexport function createApiKeyAuthMiddleware(\n options: ApiKeyAuthOptions\n): MiddlewareHandler {\n const headerName = options.headerName || 'x-api-key';\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS' || options.mode === 'disabled') {\n return next();\n }\n\n if (!options.apiKey) {\n if (options.mode === 'auto') return next();\n return c.json(\n {\n success: false,\n error: 'API authentication is not configured',\n code: 'AUTH_CONFIGURATION_ERROR',\n },\n 503\n );\n }\n\n const apiKey = readCredential(c.req.raw.headers, headerName);\n\n if (!apiKey) {\n return c.json(\n {\n success: false,\n error: 'API key required',\n code: 'UNAUTHORIZED',\n },\n 401\n );\n }\n\n if (!keysEqual(apiKey, options.apiKey)) {\n return c.json(\n {\n success: false,\n error: 'Invalid API key',\n code: 'UNAUTHORIZED',\n },\n 401\n );\n }\n\n await next();\n };\n}\n\nexport const apiKeyAuthMiddleware = createApiKeyAuthMiddleware({\n mode: config.API_AUTH_MODE,\n apiKey: config.API_KEY,\n headerName: config.API_KEY_HEADER,\n});\n","import { ErrorHandler } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport { logger } from '../../utils/logger';\nimport { config } from '../../config';\n\n/**\n * Global error handler for Hono\n */\nexport const errorHandler: ErrorHandler = (err, c) => {\n const requestId = c.get('requestId') || 'unknown';\n\n // Handle Hono HTTPException\n if (err instanceof HTTPException) {\n return c.json(\n {\n success: false,\n error: err.message,\n code: err.status >= 500 ? 'INTERNAL_ERROR' : 'CLIENT_ERROR',\n requestId,\n },\n err.status\n );\n }\n\n // Log unexpected errors\n logger.error('Unhandled error', {\n error: err.message,\n stack: err.stack,\n requestId,\n path: c.req.path,\n method: c.req.method,\n });\n\n // Handle validation errors (TypeBox format)\n if (err.name === 'ValidationError' && 'errors' in err) {\n return c.json(\n {\n success: false,\n error: 'Validation failed',\n errors: (err as any).errors,\n code: 'VALIDATION_ERROR',\n requestId,\n },\n 400\n );\n }\n\n // Default error response\n return c.json(\n {\n success: false,\n error: config.isDevelopment ? err.message : 'Internal server error',\n code: 'INTERNAL_ERROR',\n requestId,\n },\n 500\n );\n};\n","import { MiddlewareHandler } from 'hono';\n\n/**\n * Security middleware for Hono\n * Adds additional security headers and input sanitization\n */\nexport const securityMiddleware: MiddlewareHandler = async (c, next) => {\n // Add security headers\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('X-Frame-Options', 'DENY');\n c.header('Referrer-Policy', 'strict-origin-when-cross-origin');\n c.header('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');\n\n // Remove sensitive headers\n c.header('X-Powered-By', '');\n\n await next();\n};\n","import { MiddlewareHandler } from 'hono';\n// import { HTTPException } from 'hono/http-exception';\nimport { logger } from '../../utils/logger';\n\n/**\n * Error recovery middleware for Hono\n * Handles specific error types with appropriate recovery strategies\n */\nexport const errorRecoveryMiddleware: MiddlewareHandler = async (c, next) => {\n try {\n await next();\n } catch (err: any) {\n const requestId = c.get('requestId') || 'unknown';\n\n logger.error('Error recovery triggered', {\n error: err.message,\n name: err.name,\n path: c.req.path,\n method: c.req.method,\n requestId,\n });\n\n // Handle payload too large errors\n if (err.name === 'PayloadTooLargeError' || err.status === 413) {\n return c.json(\n {\n success: false,\n error: 'Payload too large',\n message: 'The request body exceeds the maximum allowed size',\n code: 'PAYLOAD_TOO_LARGE',\n requestId,\n },\n 413\n );\n }\n\n // Handle JSON syntax errors\n if (\n (err.name === 'SyntaxError' && err.message.includes('JSON')) ||\n (err.status === 400 && err.message.includes('JSON'))\n ) {\n return c.json(\n {\n success: false,\n error: 'Invalid JSON',\n message: 'The request body contains invalid JSON',\n code: 'INVALID_JSON',\n requestId,\n },\n 400\n );\n }\n\n // Handle timeout errors\n if (err.name === 'TimeoutError' || err.code === 'ETIMEDOUT') {\n return c.json(\n {\n success: false,\n error: 'Request timeout',\n message: 'The request took too long to process',\n code: 'TIMEOUT',\n requestId,\n },\n 408\n );\n }\n\n // Re-throw the error to be handled by the global error handler\n throw err;\n }\n};\n","import { MiddlewareHandler } from 'hono';\nimport { logger } from '../../utils/logger';\n\n/**\n * Request logger middleware for Hono\n * Logs incoming requests and their responses\n */\nexport const requestLoggerMiddleware: MiddlewareHandler = async (c, next) => {\n const startTime = Date.now();\n const requestId = c.get('requestId');\n\n // Log incoming request\n logger.info('Incoming request', {\n requestId,\n method: c.req.method,\n url: c.req.url,\n path: c.req.path,\n ip:\n c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown',\n userAgent: c.req.header('user-agent'),\n });\n\n try {\n // Process the request\n await next();\n\n // Log response\n const duration = Date.now() - startTime;\n const status = c.res.status;\n\n logger.info('Request completed', {\n requestId,\n method: c.req.method,\n path: c.req.path,\n status,\n duration,\n responseTime: `${duration}ms`,\n });\n\n // Add response time header\n c.header('X-Response-Time', `${duration}ms`);\n } catch (error) {\n // Log error response\n const duration = Date.now() - startTime;\n\n logger.error('Request failed', {\n requestId,\n method: c.req.method,\n path: c.req.path,\n duration,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Re-throw the error\n throw error;\n }\n};\n","import type { MiddlewareHandler } from 'hono';\n\nexport interface ConcurrencyLimitOptions {\n limit: number;\n retryAfterSeconds?: number;\n}\n\n/**\n * Process-local admission control for expensive generation/rendering work.\n * It rejects excess work instead of queueing unbounded request bodies in RAM.\n */\nexport function concurrencyLimiter(\n options: ConcurrencyLimitOptions\n): MiddlewareHandler {\n const limit = Math.max(1, Math.floor(options.limit));\n const retryAfterSeconds = options.retryAfterSeconds ?? 1;\n let active = 0;\n\n return async (c, next) => {\n c.header('X-Concurrency-Limit', String(limit));\n if (active >= limit) {\n c.header('Retry-After', String(retryAfterSeconds));\n return c.json(\n {\n success: false,\n error: 'Server is at capacity',\n code: 'CONCURRENCY_LIMIT_EXCEEDED',\n },\n 503\n );\n }\n\n active += 1;\n c.header('X-Concurrency-Remaining', String(Math.max(0, limit - active)));\n try {\n await next();\n } finally {\n active -= 1;\n }\n };\n}\n","import { Hono } from 'hono';\n\nimport { cors } from 'hono/cors';\nimport { secureHeaders } from 'hono/secure-headers';\nimport { logger as honoLogger } from 'hono/logger';\nimport { timing } from 'hono/timing';\nimport { bodyLimit } from 'hono/body-limit';\nimport { HTTPException } from 'hono/http-exception';\nimport { config } from './config/index.js';\nimport { getApiInfo } from './config/api-info.js';\nimport type { FormatAdapter } from '@json-to-office/jto-cli';\n\nimport { healthRouter } from './routes/health.js';\nimport { createFormatRouter } from './routes/format.js';\nimport { discoveryRouter } from './routes/discovery.js';\nimport { createAiRouter } from './routes/ai.js';\nimport { fontsRouter } from './routes/fonts.js';\n\nimport { requestIdMiddleware } from './middleware/hono/request-id.js';\nimport { apiKeyAuthMiddleware } from './middleware/hono/auth.js';\nimport { errorHandler } from './middleware/hono/error-handler.js';\nimport { securityMiddleware } from './middleware/hono/security.js';\nimport { errorRecoveryMiddleware } from './middleware/hono/error-recovery.js';\nimport { requestLoggerMiddleware } from './middleware/hono/request-logger.js';\nimport { rateLimiter } from './middleware/hono/rate-limit.js';\nimport { concurrencyLimiter } from './middleware/hono/concurrency-limit.js';\n\nimport { AppEnv } from './types/hono.js';\nimport { Container } from './container/index.js';\n\nexport function createAPIApp(adapter: FormatAdapter) {\n // Initialize DI container with the adapter\n Container.initialize(adapter);\n\n const honoApp = new Hono<AppEnv>();\n\n // Built-in middleware\n honoApp.use('*', timing());\n honoApp.use('*', honoLogger());\n\n // CORS\n honoApp.use(\n '*',\n cors({\n origin: config.cors.origin,\n credentials: config.cors.origin === '*' ? false : config.cors.credentials,\n allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization', config.API_KEY_HEADER],\n exposeHeaders: ['X-Request-Id', 'X-File-Id'],\n maxAge: 86400,\n })\n );\n\n honoApp.use('*', secureHeaders());\n\n // Custom middleware\n honoApp.use('*', requestIdMiddleware);\n honoApp.use('*', errorRecoveryMiddleware);\n honoApp.use('*', requestLoggerMiddleware);\n honoApp.use('*', securityMiddleware);\n\n // Uniform admission controls cover every API surface. Individual expensive\n // routes retain tighter limits below this process-wide ceiling.\n //\n // These run BEFORE authentication on purpose: Hono executes middleware in\n // registration order, so an auth check registered first would return 401\n // without ever reaching the limiter, leaving API-key guessing unbounded.\n honoApp.use(\n '/api/*',\n bodyLimit({\n maxSize: config.requestLimits.maxBodySize,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n })\n );\n honoApp.use(\n '/api/*',\n rateLimiter({\n limit: config.rateLimit.max,\n window: config.rateLimit.windowMs,\n namespace: (c) => `${c.req.method}:${c.req.path}`,\n trustProxy: config.rateLimit.trustProxy,\n })\n );\n honoApp.use(\n '/api/*',\n concurrencyLimiter({ limit: config.requestLimits.maxConcurrent })\n );\n\n // API key auth (if enabled)\n if (config.features.apiKey) {\n honoApp.use('/api/*', apiKeyAuthMiddleware);\n }\n\n // Mount routes\n honoApp.route('/health', healthRouter);\n\n // Format-specific routes at /api/{format}/*\n const formatRouter = createFormatRouter(adapter);\n honoApp.route(`/api/${adapter.name}`, formatRouter);\n\n // Also mount at /api/documents or /api/presentations for backward compat\n const legacyPath =\n adapter.name === 'docx' ? '/api/documents' : '/api/presentations';\n honoApp.route(legacyPath, formatRouter);\n\n // Discovery routes\n honoApp.route('/api/discovery', discoveryRouter);\n\n // Font catalog + Google Fonts materialization\n honoApp.route('/api/fonts', fontsRouter);\n\n // AI chat routes (disabled via AI_ENABLED=false)\n if (process.env.AI_ENABLED !== 'false') {\n honoApp.route('/api/ai', createAiRouter());\n }\n\n // Root endpoint\n honoApp.get('/', async (c) => {\n const apiInfo = await getApiInfo();\n return c.json(apiInfo);\n });\n\n honoApp.get('/api', async (c) => {\n const apiInfo = await getApiInfo();\n return c.json(apiInfo);\n });\n\n // 404 handler\n honoApp.notFound((c) => {\n return c.json(\n {\n success: false,\n error: 'Not found',\n path: c.req.path,\n method: c.req.method,\n requestId: c.get('requestId'),\n },\n 404\n );\n });\n\n honoApp.onError(errorHandler);\n\n return honoApp;\n}\n","import { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport { logger } from 'hono/logger';\nimport { compress } from 'hono/compress';\nimport { createAPIApp } from './app.js';\nimport type { Config, FormatAdapter } from '@json-to-office/jto-cli';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { logger as serverLogger } from './utils/logger.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport class UnifiedServer {\n private app: Hono;\n private config: Config;\n private adapter: FormatAdapter;\n private server: ReturnType<typeof serve> | null = null;\n private viteServer: any | null = null;\n\n constructor(adapter: FormatAdapter, config: Config) {\n this.adapter = adapter;\n this.config = config;\n this.app = new Hono();\n }\n\n async initialize() {\n await this.setupMiddleware();\n await this.setupRoutes();\n }\n\n private async setupMiddleware() {\n this.app.use('*', logger());\n this.app.use('*', compress());\n }\n\n private async setupRoutes() {\n // Health check (fast path)\n this.app.get('/health', (c) =>\n c.json({\n status: 'ok',\n timestamp: Date.now(),\n version: '1.0.0',\n mode: this.config.mode,\n format: this.adapter.name,\n })\n );\n\n // Mount API routes FIRST\n const apiApp = createAPIApp(this.adapter);\n\n this.app.get('/api', async (c) => {\n return await apiApp.fetch(c.req.raw, c.env as any);\n });\n\n this.app.use('*', async (c, next) => {\n const path = c.req.path;\n\n if (path.startsWith('/api')) {\n // Allow Vite module requests to fall through\n if (/\\.(ts|tsx|js|jsx|css|map)$/.test(path)) {\n return next();\n }\n const response = await apiApp.fetch(c.req.raw, c.env as any);\n if (response.status !== 404) {\n return response;\n }\n }\n\n return next();\n });\n\n // Client serving\n if (this.config.mode === 'development') {\n await this.setupDevClient();\n } else {\n await this.setupProdClient();\n }\n }\n\n private async setupDevClient() {\n const { existsSync } = await import('fs');\n const format = this.adapter.name.replace(/[^a-zA-Z0-9]/g, '');\n\n const formatPlugin = {\n name: 'jto-format-inject',\n transformIndexHtml(html: string) {\n return html.replace(\n '</head>',\n `<script>window.__JTO_FORMAT__ = '${format}';</script>\\n</head>`\n );\n },\n };\n\n const isBundled =\n __filename.endsWith('.cjs') ||\n __filename.endsWith('.mjs') ||\n __dirname.includes('node_modules') ||\n __dirname.endsWith('dist');\n\n let clientPath: string | null = null;\n\n // Check env var\n if (process.env.JTO_CLIENT_PATH) {\n const envClientPath = process.env.JTO_CLIENT_PATH;\n if (\n existsSync(envClientPath) &&\n existsSync(resolve(envClientPath, 'index.html'))\n ) {\n clientPath = envClientPath;\n serverLogger.debug('[Dev Server] Using client from JTO_CLIENT_PATH', {\n path: clientPath,\n });\n }\n } else if (isBundled) {\n const bundledClientPath = resolve(__dirname, 'client');\n if (\n existsSync(bundledClientPath) &&\n existsSync(resolve(bundledClientPath, 'index.html'))\n ) {\n clientPath = bundledClientPath;\n serverLogger.debug('[Dev Server] Using bundled client at', {\n path: clientPath,\n });\n }\n } else {\n const possiblePaths = [\n resolve(__dirname, '../client'),\n resolve(__dirname, '../../dist/client'),\n ];\n\n for (const p of possiblePaths) {\n if (existsSync(p)) {\n if (p.replace(/\\\\/g, '/').includes('/src/client')) {\n serverLogger.debug('[Dev Server] Using Vite dev server for', {\n path: p,\n });\n try {\n const { createServer: createViteServer } = await import('vite');\n this.viteServer = await createViteServer({\n root: p,\n plugins: [formatPlugin],\n server: {\n middlewareMode: true,\n hmr: { port: this.config.development.hmrPort || 5173 },\n },\n });\n } catch (err) {\n serverLogger.warn('[Dev Server] Vite not available for dev mode');\n }\n break;\n } else if (existsSync(resolve(p, 'index.html'))) {\n clientPath = p;\n serverLogger.debug('[Dev Server] Using pre-built client at', {\n path: clientPath,\n });\n break;\n }\n }\n }\n }\n\n if (clientPath) {\n return this.setupBuiltClient(clientPath);\n }\n\n if (!this.viteServer && !isBundled) {\n const sourceClientPath = resolve(__dirname, '../client');\n try {\n const { createServer: createViteServer } = await import('vite');\n this.viteServer = await createViteServer({\n root: sourceClientPath,\n plugins: [formatPlugin],\n server: {\n middlewareMode: true,\n hmr: { port: this.config.development.hmrPort || 5173 },\n },\n });\n } catch {\n serverLogger.warn('[Dev Server] Vite not available');\n }\n }\n\n if (this.viteServer) {\n this.app.use('*', async (c, next) => {\n const path = c.req.path;\n\n if (\n (path.startsWith('/api') || path === '/health') &&\n !/\\.(ts|tsx|js|jsx|css|map)$/.test(path)\n ) {\n return next();\n }\n\n const env = c.env as Record<string, unknown>;\n const req = env.incoming || env.req;\n const res = env.outgoing || env.res;\n\n if (req && res && this.viteServer) {\n return new Promise((resolve) => {\n this.viteServer!.middlewares.handle(req as any, res as any, () => {\n resolve(next());\n });\n });\n }\n\n return next();\n });\n }\n }\n\n private async setupBuiltClient(clientPath: string) {\n const { serveStatic } = await import('@hono/node-server/serve-static');\n const fs = await import('fs');\n const { extname } = await import('path');\n const mime = await import('mime-types');\n\n const format = this.adapter.name.replace(/[^a-zA-Z0-9]/g, '');\n\n // Serve static assets\n this.app.use(\n '/assets/*',\n serveStatic({\n root: clientPath,\n rewriteRequestPath: (path) => path.replace(/^\\/assets/, '/assets'),\n })\n );\n\n // Handle file requests\n this.app.use('/*', async (c, next) => {\n const reqPath = c.req.path;\n if (reqPath.startsWith('/api') || reqPath === '/health') return next();\n\n const ext = extname(reqPath);\n if (ext) {\n const filePath = resolve(clientPath, reqPath.slice(1));\n if (fs.existsSync(filePath)) {\n const mimeType = mime.lookup(filePath) || 'application/octet-stream';\n const content = fs.readFileSync(filePath);\n c.header('Content-Type', mimeType);\n return c.body(content);\n }\n }\n\n return next();\n });\n\n // SPA fallback - inject format into HTML\n this.app.get('*', async (c) => {\n const reqPath = c.req.path;\n if (reqPath.startsWith('/api') || reqPath === '/health')\n return c.notFound();\n\n const indexPath = resolve(clientPath, 'index.html');\n if (fs.existsSync(indexPath)) {\n let html = fs.readFileSync(indexPath, 'utf-8');\n // Inject format configuration\n html = html.replace(\n '</head>',\n `<script>window.__JTO_FORMAT__ = '${format}';</script>\\n</head>`\n );\n return c.html(html);\n }\n\n return c.notFound();\n });\n }\n\n private async setupProdClient() {\n const clientPath = resolve(__dirname, 'client');\n return this.setupBuiltClient(clientPath);\n }\n\n async start(): Promise<void> {\n await this.initialize();\n\n return new Promise((resolve) => {\n this.server = serve(\n {\n fetch: this.app.fetch,\n port: this.config.server.port,\n hostname: this.config.server.host,\n },\n () => {\n resolve();\n }\n );\n });\n }\n\n async stop(): Promise<void> {\n if (this.viteServer) await this.viteServer.close();\n if (this.server) {\n return new Promise((resolve) => {\n this.server?.close(() => resolve());\n });\n }\n }\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { registerCoreCommands, renderLines } from '@json-to-office/jto-cli';\nimport { createDevCommand } from './commands/dev.js';\n\ndeclare const __PACKAGE_VERSION__: string | undefined;\nconst PACKAGE_VERSION =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : 'dev-mode';\n\nconst program = new Command();\n\nprogram\n .name('jto')\n .description('JSON to Office CLI - Generate .docx and .pptx from JSON')\n .version(PACKAGE_VERSION);\n\nregisterCoreCommands(program, {\n extraCommands: (adapter) => [createDevCommand(adapter)],\n});\n\nprogram.addHelpText(\n 'after',\n `\n${chalk.gray('Examples:')}\n $ jto docx generate doc.json ${chalk.dim('# Generate DOCX from JSON')}\n $ jto pptx generate slides.json ${chalk.dim('# Generate PPTX from JSON')}\n $ jto docx dev ${chalk.dim('# Start DOCX dev server')}\n $ jto pptx validate slides.json ${chalk.dim('# Validate PPTX JSON')}\n $ jto docx schemas ${chalk.dim('# Export DOCX JSON schemas')}\n $ jto pptx discover ${chalk.dim('# Discover PPTX plugins')}\n $ jto docx fonts install Inter ${chalk.dim('# Download a Google Font into ./fonts')}\n`\n);\n\nprogram.exitOverride();\n\n(async () => {\n try {\n await program.parseAsync(process.argv);\n } catch (error: any) {\n if (\n error.code === 'commander.version' ||\n error.code === 'commander.help' ||\n error.code === 'commander.helpDisplayed'\n ) {\n process.exit(0);\n }\n if (error.code === 'commander.executeSubCommandAsync') {\n process.exit(error.exitCode);\n }\n await renderLines(\n [{ text: `Error: ${error.message}`, tone: 'error' }],\n process.stderr\n );\n process.exit(1);\n }\n})();\n","import { Command } from 'commander';\nimport {\n type FormatAdapter,\n loadConfig,\n parsePort,\n formatError,\n renderLines,\n runTask,\n EXIT_CODES,\n} from '@json-to-office/jto-cli';\n\ninterface DevOptions {\n port?: string;\n host?: string;\n open?: boolean;\n config?: string;\n}\n\ninterface StoppableServer {\n stop(): Promise<void>;\n}\n\nfunction installShutdownHandlers(server: StoppableServer): void {\n let shutdownPromise: Promise<void> | undefined;\n\n const removeHandlers = () => {\n process.off('SIGINT', handleShutdown);\n process.off('SIGTERM', handleShutdown);\n };\n const handleShutdown = () => {\n shutdownPromise ??= (async () => {\n let exitCode: number = EXIT_CODES.OK;\n try {\n await runTask('Shutting down...', () => server.stop(), {\n success: 'Server stopped',\n failure: 'Failed to stop server',\n });\n } catch (error) {\n exitCode = EXIT_CODES.FAIL;\n await formatError(error);\n } finally {\n removeHandlers();\n }\n process.exit(exitCode);\n })();\n };\n\n process.once('SIGINT', handleShutdown);\n process.once('SIGTERM', handleShutdown);\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const { execFile } = await import('node:child_process');\n const [command, args] =\n process.platform === 'darwin'\n ? ['open', [url]]\n : process.platform === 'win32'\n ? ['cmd', ['/c', 'start', '', url]]\n : ['xdg-open', [url]];\n\n await new Promise<void>((resolve, reject) => {\n execFile(command, args, (error) => (error ? reject(error) : resolve()));\n });\n}\n\nexport function createDevCommand(adapter: FormatAdapter): Command {\n const dev = new Command('dev');\n return dev\n .description('Start development server with web UI')\n .option(\n '-p, --port <port>',\n 'Port to run server on',\n String(adapter.defaultPort)\n )\n .option('-H, --host <host>', 'Host to bind to', 'localhost')\n .option('-o, --open', 'Open browser automatically')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (options: DevOptions) => {\n try {\n const { server, url } = await runTask(\n `Starting ${adapter.name.toUpperCase()} dev server...`,\n async () => {\n // The adapter default goes in as the loader's fallback so an\n // explicit port equal to it stays explicit — no sentinel value.\n const config = await loadConfig(options.config, {\n defaultPort: adapter.defaultPort,\n });\n\n // CLI flag > config file > PORT > adapter default\n const portSource = dev.getOptionValueSource('port');\n const hostSource = dev.getOptionValueSource('host');\n if (portSource === 'cli') {\n // Same strict parser as PORT: `parseInt` would read \"8080x\" as\n // 8080 and bind a port the user never asked for.\n const port = parsePort(options.port);\n if (port === undefined) {\n throw new Error(\n `Invalid --port \"${options.port}\": expected an integer between 0 and 65535`\n );\n }\n config.server.port = port;\n }\n if (hostSource === 'cli') {\n config.server.host = options.host!;\n }\n\n const { UnifiedServer } = await import(\n '../server/unified-server.js'\n );\n const server = new UnifiedServer(adapter, config);\n await server.start();\n\n return {\n server,\n url: `http://${config.server.host}:${config.server.port}`,\n };\n },\n { success: 'Server ready', failure: 'Failed to start dev server' }\n );\n\n installShutdownHandlers(server);\n await renderLines([\n {\n text: `${adapter.name.toUpperCase()} Dev Server`,\n tone: 'success',\n },\n { text: `Local: ${url}` },\n { text: `API: ${url}/api/${adapter.name}/generate` },\n { text: `Health: ${url}/health` },\n { text: 'Press Ctrl+C to stop', tone: 'muted' },\n ]);\n\n // Open browser if requested\n if (options.open) {\n try {\n await openBrowser(url);\n } catch (error) {\n await renderLines([\n {\n text: `Could not open browser: ${\n error instanceof Error ? error.message : String(error)\n }`,\n tone: 'warning',\n },\n ]);\n }\n }\n } catch (error) {\n await formatError(error);\n process.exit(EXIT_CODES.FAIL);\n }\n });\n}\n"],"mappings":"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","names":["config","visit","filtered","cacheEvents","path","resolve","HTTPException","path","path","Type","HTTPException","fs","path","isRecord","visit","Hono","HTTPException","bodyLimit","PluginRegistry","path","config","Hono","PluginDiscoveryService","PluginRegistry","cleanupTypeBoxIds","dirname","fileURLToPath","__dirname","Hono","Hono","HTTPException","bodyLimit","POPULAR_GOOGLE_FONTS","createHash","HTTPException","Hono","bodyLimit","HTTPException","Hono","logger","dirname","fileURLToPath","__filename","__dirname","config","path","existsSync","resolve","fs","Command","renderLines","execFile","resolve","config","UnifiedServer","server","Command","renderLines"]}
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.0_jiti@2.6.1_postcss@8.5.6_tsx@4.20.3_typescript@5.3.3_yaml@2.8.3/node_modules/tsup/assets/esm_shims.js","../src/server/config/index.ts","../src/server/config/api-info.ts","../src/server/utils/logger.ts","../src/server/services/generator.ts","../src/server/services/cache.ts","../src/server/services/libreoffice-converter.ts","../src/server/container/index.ts","../src/server/routes/health.ts","../src/server/schemas/loose.ts","../src/server/lib/typebox-validator.ts","../src/server/middleware/hono/rate-limit.ts","../src/server/security/outbound-source-policy.ts","../src/server/rasterize-route.ts","../src/server/services/template-media-inliner.ts","../src/server/routes/format.ts","../src/server/routes/discovery.ts","../src/server/services/ai-schema.ts","../src/server/services/prompt-loader.ts","../src/server/routes/ai.ts","../src/server/routes/fonts.ts","../src/server/middleware/hono/request-id.ts","../src/server/middleware/hono/auth.ts","../src/server/middleware/hono/error-handler.ts","../src/server/middleware/hono/security.ts","../src/server/middleware/hono/error-recovery.ts","../src/server/middleware/hono/request-logger.ts","../src/server/middleware/hono/concurrency-limit.ts","../src/server/app.ts","../src/server/unified-server.ts","../src/cli.ts","../src/commands/dev.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import dotenv from 'dotenv';\n\ndotenv.config();\n\nexport type ApiAuthMode = 'auto' | 'required' | 'disabled';\nexport type OutboundSourceMode = 'development' | 'safe';\n\nfunction positiveInteger(value: string | undefined, fallback: number): number {\n const parsed = Number.parseInt(value ?? '', 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;\n}\n\nfunction parseAuthMode(\n value: string | undefined,\n nodeEnv: 'development' | 'production' | 'test'\n): ApiAuthMode {\n if (value === 'auto' || value === 'required' || value === 'disabled') {\n return value;\n }\n // Public production APIs must opt out explicitly. Local playgrounds remain\n // zero-config; supplying a key there preserves the historical auto-enable.\n return nodeEnv === 'production' ? 'required' : 'auto';\n}\n\nfunction parseOutboundSourceMode(\n value: string | undefined,\n nodeEnv: 'development' | 'production' | 'test'\n): OutboundSourceMode {\n if (value === 'development' || value === 'safe') return value;\n return nodeEnv === 'production' ? 'safe' : 'development';\n}\n\n/**\n * Only the two explicitly local environments keep permissive defaults. Every\n * other value — `staging`, `prod`, a typo — gets production-grade hardening, so\n * a mislabelled deployment cannot silently disable auth, rate limits, or the\n * outbound-source (SSRF) checks.\n */\nfunction normalizeNodeEnv(\n value: string | undefined\n): 'development' | 'production' | 'test' {\n return value === 'development' || value === 'test' ? value : 'production';\n}\n\nfunction parseEnv(env: NodeJS.ProcessEnv) {\n const nodeEnv = normalizeNodeEnv(env.NODE_ENV || 'development');\n return {\n NODE_ENV: nodeEnv,\n // No PORT here: the listener is opened by the dev server from the CLI\n // config (`-p` > `server.port` > `PORT` env > format default), so a second\n // copy of it in this module would be silently ignored.\n CORS_ORIGIN: env.CORS_ORIGIN || '*',\n API_KEY: env.API_KEY,\n API_KEY_HEADER: env.API_KEY_HEADER || 'x-api-key',\n API_AUTH_MODE: parseAuthMode(env.API_AUTH_MODE, nodeEnv),\n RATE_LIMIT_WINDOW_MS: positiveInteger(env.RATE_LIMIT_WINDOW_MS, 900_000),\n RATE_LIMIT_MAX: positiveInteger(\n env.RATE_LIMIT_MAX,\n nodeEnv === 'production' ? 100 : 1000\n ),\n TRUST_PROXY_HEADERS: env.TRUST_PROXY_HEADERS === 'true',\n MAX_FILE_SIZE: positiveInteger(env.MAX_FILE_SIZE, 10 * 1024 * 1024),\n MAX_REQUEST_BODY_SIZE: positiveInteger(\n env.MAX_REQUEST_BODY_SIZE,\n 32 * 1024 * 1024\n ),\n MAX_CONCURRENT_REQUESTS: positiveInteger(\n env.MAX_CONCURRENT_REQUESTS,\n nodeEnv === 'production' ? 8 : 64\n ),\n OUTBOUND_SOURCE_MODE: parseOutboundSourceMode(\n env.OUTBOUND_SOURCE_MODE,\n nodeEnv\n ),\n OUTBOUND_HOST_ALLOWLIST: (env.OUTBOUND_HOST_ALLOWLIST || '')\n .split(',')\n .map((host) => host.trim().toLowerCase())\n .filter(Boolean),\n LIBREOFFICE_PATH: env.LIBREOFFICE_PATH,\n LIBREOFFICE_TIMEOUT_MS: env.LIBREOFFICE_TIMEOUT_MS\n ? positiveInteger(env.LIBREOFFICE_TIMEOUT_MS, 30000)\n : 30000,\n LOG_LEVEL: (env.LOG_LEVEL || 'info') as 'error' | 'warn' | 'info' | 'debug',\n CACHE_ENABLED: env.CACHE_ENABLED !== 'false',\n CACHE_MAX_SIZE_MB: positiveInteger(env.CACHE_MAX_SIZE_MB, 100),\n CACHE_TTL_SECONDS: positiveInteger(env.CACHE_TTL_SECONDS, 3600),\n CACHE_MAX_ITEMS: positiveInteger(env.CACHE_MAX_ITEMS, 1000),\n };\n}\n\nconst parsedEnv = parseEnv(process.env);\n\nexport const config = {\n ...parsedEnv,\n\n isDevelopment: parsedEnv.NODE_ENV === 'development',\n isProduction: parsedEnv.NODE_ENV === 'production',\n isTest: parsedEnv.NODE_ENV === 'test',\n\n features: {\n apiKey: parsedEnv.API_AUTH_MODE !== 'disabled',\n cache: parsedEnv.CACHE_ENABLED,\n },\n\n cors: {\n origin:\n parsedEnv.CORS_ORIGIN === '*'\n ? parsedEnv.CORS_ORIGIN\n : parsedEnv.CORS_ORIGIN.split(',').map((o) => o.trim()),\n credentials: true,\n },\n\n rateLimit: {\n windowMs: parsedEnv.RATE_LIMIT_WINDOW_MS,\n max: parsedEnv.RATE_LIMIT_MAX,\n trustProxy: parsedEnv.TRUST_PROXY_HEADERS,\n },\n\n requestLimits: {\n maxBodySize: parsedEnv.MAX_REQUEST_BODY_SIZE,\n maxConcurrent: parsedEnv.MAX_CONCURRENT_REQUESTS,\n maxFileSize: parsedEnv.MAX_FILE_SIZE,\n },\n\n outboundSources: {\n mode: parsedEnv.OUTBOUND_SOURCE_MODE,\n allowedHosts: parsedEnv.OUTBOUND_HOST_ALLOWLIST,\n },\n\n cache: {\n enabled: parsedEnv.CACHE_ENABLED,\n maxSizeMB: parsedEnv.CACHE_MAX_SIZE_MB,\n ttlSeconds: parsedEnv.CACHE_TTL_SECONDS,\n maxItems: parsedEnv.CACHE_MAX_ITEMS,\n },\n} as const;\n\nexport type ServerConfig = typeof config;\n","import { config } from './index.js';\n\nexport async function getApiInfo() {\n return {\n name: 'JSON to Office API',\n version: '1.0.0',\n description: 'Generate DOCX and PPTX documents from JSON definitions',\n environment: config.NODE_ENV,\n endpoints: {\n health: '/health',\n api: '/api',\n generate: '/api/{format}/generate',\n validate: '/api/{format}/validate',\n discovery: '/api/discovery',\n },\n };\n}\n","import { config } from '../config/index.js';\n\ntype LogLevel = 'error' | 'warn' | 'info' | 'debug';\n\ninterface LogContext {\n [key: string]: unknown;\n}\n\nclass Logger {\n private level: LogLevel;\n\n constructor(level: LogLevel = 'info') {\n this.level = level;\n }\n\n private shouldLog(level: LogLevel): boolean {\n const levels: LogLevel[] = ['error', 'warn', 'info', 'debug'];\n return levels.indexOf(level) <= levels.indexOf(this.level);\n }\n\n private formatMessage(\n level: LogLevel,\n message: string,\n context?: LogContext\n ): string {\n const timestamp = new Date().toISOString();\n const contextStr = context\n ? ` ${JSON.stringify(context, this.errorReplacer)}`\n : '';\n return `[${timestamp}] [${level.toUpperCase()}] ${message}${contextStr}`;\n }\n\n private errorReplacer(_key: string, value: unknown): unknown {\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n stack: value.stack,\n };\n }\n return value;\n }\n\n private log(level: LogLevel, message: string, context?: LogContext): void {\n if (!this.shouldLog(level)) return;\n const formatted = this.formatMessage(level, message, context);\n switch (level) {\n case 'error':\n console.error(formatted);\n break;\n case 'warn':\n console.warn(formatted);\n break;\n case 'info':\n console.info(formatted);\n break;\n case 'debug':\n console.debug(formatted);\n break;\n }\n }\n\n error(message: string, context?: LogContext): void {\n this.log('error', message, context);\n }\n warn(message: string, context?: LogContext): void {\n this.log('warn', message, context);\n }\n info(message: string, context?: LogContext): void {\n this.log('info', message, context);\n }\n debug(message: string, context?: LogContext): void {\n this.log('debug', message, context);\n }\n}\n\nexport const logger = new Logger(config.LOG_LEVEL);\n","import {\n type FormatAdapter,\n type GeneratorOptions,\n cacheEvents,\n PluginRegistry,\n} from '@json-to-office/jto-cli';\nimport { CacheService } from './cache.js';\nimport { logger } from '../utils/logger.js';\nimport {\n collectFontNamesFromDocx,\n collectFontNamesFromPptx,\n POPULAR_GOOGLE_FONTS,\n getUpstreamOverride,\n isSafeFont,\n documentFontRegistry,\n themeFontRegistry,\n type FontRegistryEntry,\n type ResolvedFont,\n type GenerationWarning,\n} from '@json-to-office/shared';\nimport {\n QualityGateError,\n type QualityAnalysis,\n type QualityDiagnostic,\n} from '@json-to-office/quality';\n\nfunction toQualityWarnings(\n diagnostics: readonly QualityDiagnostic[]\n): GenerationWarning[] {\n return diagnostics.map((finding) => ({\n component: 'quality',\n message: `[${finding.code}] ${finding.message}`,\n severity: finding.severity === 'info' ? 'info' : 'warning',\n context: {\n ...(finding.context ?? {}),\n code: finding.code,\n path: finding.path,\n originalSeverity: finding.severity,\n ...(finding.ruleId && { ruleId: finding.ruleId }),\n ...(finding.category && { category: finding.category }),\n ...(finding.certainty && { certainty: finding.certainty }),\n blocking: finding.blocking,\n ...(finding.suggestion && { suggestion: finding.suggestion }),\n ...(finding.relatedPaths && { relatedPaths: finding.relatedPaths }),\n ...(finding.evidence && { evidence: finding.evidence }),\n ...(finding.fixes && { fixes: finding.fixes }),\n },\n }));\n}\n\n/**\n * Playground-only convenience: scan the document for font names that match\n * a POPULAR_GOOGLE_FONTS family and auto-build `fonts.extraEntries` so the\n * LibreOffice preview stager can materialise the bytes for PDF conversion.\n * The final .docx/.pptx does not embed them — substitution is the default\n * export mode.\n */\nexport function collectReferencedNames(\n config: unknown,\n customThemes: Record<string, unknown> | undefined,\n adapterName: 'docx' | 'pptx'\n): Set<string> {\n const collect =\n adapterName === 'docx'\n ? collectFontNamesFromDocx\n : collectFontNamesFromPptx;\n // Walk the doc AND every supplied custom theme — themes defined in a\n // separate .theme.json file contain font references the doc only names\n // indirectly (via `theme: \"myTheme\"`).\n const names = new Set<string>();\n for (const n of collect(config)) names.add(n);\n for (const theme of Object.values(customThemes ?? {})) {\n for (const n of collect(theme)) names.add(n);\n }\n return names;\n}\n\n/**\n * Walk the doc tree + custom themes for `fontWeight` numeric values. Used\n * to narrow `autoGoogleFontEntries` so cold-cache runs fetch only the\n * weights the doc actually needs instead of 18 faces per Google family.\n */\nexport function collectReferencedWeights(\n config: unknown,\n customThemes: Record<string, unknown> | undefined\n): Set<number> {\n const weights = new Set<number>();\n const visit = (node: unknown): void => {\n if (node == null) return;\n if (Array.isArray(node)) {\n for (const item of node) visit(item);\n return;\n }\n if (typeof node === 'object') {\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (\n k === 'fontWeight' &&\n typeof v === 'number' &&\n v >= 100 &&\n v <= 900\n ) {\n weights.add(v);\n } else {\n visit(v);\n }\n }\n }\n };\n visit(config);\n for (const theme of Object.values(customThemes ?? {})) visit(theme);\n return weights;\n}\n\n/**\n * Walk the doc tree + themes for any `italic: true`. Lets the override\n * variant filter drop italic faces entirely when the doc never uses them\n * (Inter's override is 18 variants — dropping italic halves the instancer\n * cost for upright-only docs).\n */\nexport function collectReferencedItalic(\n config: unknown,\n customThemes: Record<string, unknown> | undefined\n): boolean {\n let found = false;\n const visit = (node: unknown): void => {\n if (found || node == null) return;\n if (Array.isArray(node)) {\n for (const item of node) visit(item);\n return;\n }\n if (typeof node === 'object') {\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (k === 'italic' && v === true) {\n found = true;\n return;\n }\n visit(v);\n }\n }\n };\n visit(config);\n if (!found) {\n for (const theme of Object.values(customThemes ?? {})) {\n visit(theme);\n if (found) break;\n }\n }\n return found;\n}\n\n/**\n * A service-local warning carrying its OWN code. This used to be a bare\n * string and the code was hardcoded at the mapping site, so every message in\n * the array — including `FONT_WEIGHT_NOT_IN_OVERRIDE` — was published to\n * clients as `context.code === 'FONT_OVERRIDE_LOCAL'`, and any client\n * filtering on the code misclassified it.\n */\nexport interface SupplementalFontWarning {\n code: string;\n message: string;\n}\n\n/**\n * Turn service-local font warnings into the client-facing shape, preserving\n * each entry's own code. Informational: unlike core's `FONT_UNRESOLVED`,\n * none of these mean the document failed to resolve something.\n */\nexport function toSupplementalWarnings(\n warnings: readonly SupplementalFontWarning[]\n): GenerationWarning[] {\n return warnings.map(({ code, message }) => ({\n component: 'fontRegistry',\n message,\n severity: 'info' as const,\n context: { code },\n }));\n}\n\nexport function autoGoogleFontEntries(\n names: Set<string>,\n skipFamilies: Set<string>,\n referencedWeights?: Set<number>,\n referencedItalic?: boolean,\n warnings?: SupplementalFontWarning[]\n): FontRegistryEntry[] {\n const googleByLower = new Map(\n POPULAR_GOOGLE_FONTS.map((f) => [f.family.toLowerCase(), f])\n );\n const entries: FontRegistryEntry[] = [];\n for (const name of names) {\n if (isSafeFont(name)) continue;\n if (skipFamilies.has(name.toLowerCase())) continue;\n const match = googleByLower.get(name.toLowerCase());\n if (!match) continue;\n // Prefer an upstream override when one exists — bypasses Google's\n // redistribution for families with known metadata defects (Inter today).\n // Falls back to the Google Fonts CSS endpoint otherwise.\n // Narrow the fetched weight set to what the doc actually references.\n // Cold-cache fetches 1 file per (weight × italic) serially — Inter has\n // 18 faces advertised — so docs that only use 400/700 shouldn't pay\n // for all nine. When the doc references no explicit weights, fall\n // back to 400/700 (Regular + Bold). When it does, fetch those\n // weights (intersected with what the family advertises).\n const wanted = (() => {\n if (!referencedWeights || referencedWeights.size === 0) {\n const filtered = match.weights.filter((w) => w === 400 || w === 700);\n // Pathological catalog entries that advertise neither 400 nor\n // 700 would otherwise return []; fall back to the family's\n // lightest advertised weight (deterministic regardless of\n // catalog ordering) so the Google fetcher gets something\n // reproducible to work with.\n if (filtered.length > 0) return filtered;\n return match.weights.length > 0 ? [Math.min(...match.weights)] : [400];\n }\n const want = new Set<number>([400, ...referencedWeights]);\n const filtered = match.weights.filter((w) => want.has(w));\n return filtered.length > 0 ? filtered : [400];\n })();\n const override = getUpstreamOverride(match.family);\n if (override) {\n // Each override variant is already schema-shaped (kind: 'url' | 'variable'\n // with the right field set). Forward them straight through — the\n // registry's materializeSource switch handles both. Filter by the\n // narrowed weight set so instancing/fetching cost scales with doc\n // usage, not the full 9-weight catalog.\n //\n // The override is the source of truth for which weights exist, NOT\n // the catalog. Rebuild the wanted set from doc-referenced weights\n // directly so a narrow catalog (e.g. advertising only {400,700})\n // doesn't prune out valid override variants (e.g. weight 300).\n const overrideWantedSet = (() => {\n if (!referencedWeights || referencedWeights.size === 0) {\n return new Set<number>([400, 700]);\n }\n return new Set<number>([400, ...referencedWeights]);\n })();\n // Drop italic variants when the doc never requests italic. Halves the\n // instancer/fetch cost for upright-only docs (Inter's override ships 9\n // upright + 9 italic variants).\n const keepItalic = referencedItalic !== false;\n const variants = override.variants.filter(\n (v) => overrideWantedSet.has(v.weight) && (keepItalic || !v.italic)\n );\n let selected = variants;\n if (selected.length === 0) {\n // Referenced weights are all outside this override's advertised\n // variants. Fetching every variant is the legacy fallback; warn\n // so a typo (e.g. `fontWeight: 250`) surfaces instead of silently\n // inflating cold-cache cost.\n const missing = [...overrideWantedSet]\n .filter((w) => !override.variants.some((v) => v.weight === w))\n .sort((a, b) => a - b);\n warnings?.push({\n code: 'FONT_WEIGHT_NOT_IN_OVERRIDE',\n message: `FONT_WEIGHT_NOT_IN_OVERRIDE: family \"${match.family}\" — referenced weight(s) ${missing.join(', ')} not in upstream override (has ${override.variants\n .map((v) => v.weight)\n .filter((w, i, a) => a.indexOf(w) === i)\n .sort((a, b) => a - b)\n .join(', ')}). Fetching all override variants as a fallback.`,\n });\n selected = override.variants;\n }\n entries.push({\n id: match.family,\n family: match.family,\n sources: selected.map((v) =>\n v.kind === 'variable'\n ? {\n kind: 'variable' as const,\n url: v.url,\n weight: v.weight,\n italic: v.italic ?? false,\n ...(v.axes ? { axes: v.axes } : {}),\n }\n : {\n kind: 'url' as const,\n url: v.url,\n weight: v.weight,\n italic: v.italic ?? false,\n }\n ),\n });\n continue;\n }\n entries.push({\n id: match.family,\n family: match.family,\n sources: [\n {\n kind: 'google',\n family: match.family,\n weights: wanted,\n // Only request italics when the catalog advertises them. Requesting\n // italics for a family without italic variants (e.g. Inter) makes\n // Google return 404s that surface as `FONT_WEIGHT_UNAVAILABLE`\n // warnings and confuse diagnostics.\n italics: match.hasItalic,\n },\n ],\n });\n }\n return entries;\n}\n\nexport class GeneratorService {\n private adapter: FormatAdapter;\n private cacheService: CacheService;\n private cacheInvalidationHandler: (() => void) | null = null;\n\n constructor(adapter: FormatAdapter, cacheService: CacheService) {\n this.adapter = adapter;\n this.cacheService = cacheService;\n\n this.cacheInvalidationHandler = () => this.cacheService.clear();\n cacheEvents.on('generator:invalidate', this.cacheInvalidationHandler);\n }\n\n async generate(request: {\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: Record<string, unknown>;\n }): Promise<{\n filename: string;\n fileId?: string;\n buffer: Buffer;\n cached?: boolean;\n warnings?: GenerationWarning[] | null;\n resolvedFonts?: ResolvedFont[];\n }> {\n const { jsonDefinition, customThemes, options } = request;\n const config =\n typeof jsonDefinition === 'string'\n ? JSON.parse(jsonDefinition)\n : jsonDefinition;\n\n const referencedNames = collectReferencedNames(\n config,\n customThemes,\n this.adapter.name as 'docx' | 'pptx'\n );\n const referencedWeights = collectReferencedWeights(config, customThemes);\n const referencedItalic = collectReferencedItalic(config, customThemes);\n // Caller-supplied extraEntries (e.g. playground user uploads) win over the\n // auto-Google path. Build a skip-set of their family names so\n // `autoGoogleFontEntries` doesn't queue a parallel Google fetch for the\n // same family — which would race the local registration and, in the worst\n // case, override the caller's chosen bytes.\n const callerFonts = (options as { fonts?: Record<string, unknown> })?.fonts;\n const callerExtraEntriesRaw = (callerFonts as { extraEntries?: unknown })\n ?.extraEntries;\n const callerExtraEntries: FontRegistryEntry[] = Array.isArray(\n callerExtraEntriesRaw\n )\n ? (callerExtraEntriesRaw as FontRegistryEntry[])\n : [];\n const callerStrict =\n typeof (callerFonts as { strict?: unknown })?.strict === 'boolean'\n ? (callerFonts as { strict: boolean }).strict\n : undefined;\n const rawMode = callerFonts?.mode;\n const fontMode: 'substitute' | 'custom' | undefined =\n rawMode === 'substitute' || rawMode === 'custom' ? rawMode : undefined;\n const rawSub = callerFonts?.substitution;\n const fontSubstitution =\n rawSub && typeof rawSub === 'object' && !Array.isArray(rawSub)\n ? (rawSub as Record<string, string>)\n : undefined;\n // Families already declared by the caller, the document, or a theme. Any\n // of them outranks an auto-Google fetch, and `extraEntries` — where the\n // auto entries land — is the HIGHEST precedence group in the merge, so\n // omitting the document/theme families here would let Google's bytes\n // silently replace the ones the document ships with.\n const declaredFamilies = [\n ...callerExtraEntries,\n ...documentFontRegistry(config),\n ...Object.values(customThemes ?? {}).flatMap((t) => themeFontRegistry(t)),\n ];\n const callerFamilies = new Set(\n declaredFamilies.map((e) => e.family.toLowerCase())\n );\n // In substitute mode the doc's non-safe families are rewritten to safe\n // equivalents before font resolution runs, so an auto-Google fetch for\n // them is wasted work and — via `bypassCache` below — would disable the\n // server buffer cache for no benefit. Skip it.\n const overrideWarnings: SupplementalFontWarning[] = [];\n const autoEntries =\n fontMode === 'substitute'\n ? []\n : autoGoogleFontEntries(\n referencedNames,\n callerFamilies,\n referencedWeights,\n referencedItalic,\n overrideWarnings\n );\n const extraEntries = [...callerExtraEntries, ...autoEntries];\n // Surface the override so the caller can see their local file won vs a\n // would-be Google fetch. Collected later into the `warnings` array.\n if (callerExtraEntries.length > 0) {\n const googleFamiliesLower = new Set(\n POPULAR_GOOGLE_FONTS.map((f) => f.family.toLowerCase())\n );\n for (const e of callerExtraEntries) {\n const lower = e.family.toLowerCase();\n if (googleFamiliesLower.has(lower) && referencedNames.has(e.family)) {\n overrideWarnings.push({\n code: 'FONT_OVERRIDE_LOCAL',\n message: `[FONT_OVERRIDE_LOCAL] ${e.family}: caller-supplied source used; Google Fonts auto-fetch skipped for this family.`,\n });\n }\n }\n }\n // A document- or theme-declared registry is the third thing that makes\n // font resolution meaningful, alongside caller entries and the export-mode\n // selectors. Computed here rather than next to `fontOpts` because\n // `bypassCache` below has to see it.\n const declaresRegistry =\n documentFontRegistry(config).length > 0 ||\n Object.values(customThemes ?? {}).some(\n (t) => themeFontRegistry(t).length > 0\n );\n // Font resolution produces a side-channel (`resolvedFonts`) consumed by the\n // LibreOffice preview stager. The byte-cache can't round-trip that, so skip\n // the cache when auto-font resolution is needed — otherwise a cached buffer\n // returns without the TTFs the previewer needs. A declared registry counts:\n // its bytes are exactly what the stager would otherwise be missing.\n const bypassCache =\n options?.bypassCache === true ||\n extraEntries.length > 0 ||\n declaresRegistry;\n // Include font runtime selectors in the cache key so substitute vs\n // custom runs (same config+themes) don't collide on a single buffer\n // slot. `extraEntries` already forces bypassCache, so only need\n // mode/substitution/strict in the key for the non-bypass path.\n const baseDir =\n typeof (options as { baseDir?: unknown } | undefined)?.baseDir ===\n 'string'\n ? (options as { baseDir: string }).baseDir\n : undefined;\n // The backend is chosen per request, not per server: the playground's\n // point is comparing two of them on the same document.\n const renderer =\n typeof (options as { renderer?: unknown } | undefined)?.renderer ===\n 'string'\n ? (options as { renderer: string }).renderer\n : undefined;\n const resolvedFonts: ResolvedFont[] = [];\n const coreWarnings: GenerationWarning[] = [];\n const needsFontOpts =\n extraEntries.length > 0 ||\n declaresRegistry ||\n fontMode !== undefined ||\n fontSubstitution !== undefined ||\n callerStrict !== undefined;\n const fontOpts = needsFontOpts\n ? {\n ...(extraEntries.length > 0 && { extraEntries }),\n ...(fontMode && { mode: fontMode }),\n ...(fontSubstitution && { substitution: fontSubstitution }),\n ...(callerStrict !== undefined && { strict: callerStrict }),\n onResolved: (resolved: ResolvedFont[]) => {\n resolvedFonts.push(...resolved);\n },\n }\n : undefined;\n const registry = PluginRegistry.getInstance();\n const quality = (options as { quality?: GeneratorOptions['quality'] })\n ?.quality;\n const prepared =\n !registry.hasPlugins() &&\n this.adapter.prepareDocument &&\n this.adapter.validateDocument(config).valid\n ? await this.adapter.prepareDocument(config, {\n customThemes,\n fonts: fontOpts,\n baseDir,\n renderer,\n warnings: coreWarnings,\n })\n : undefined;\n const qualityOptions: GeneratorOptions = {\n customThemes,\n fonts: fontOpts,\n baseDir,\n renderer,\n quality,\n prepared,\n };\n let qualityWarnings: GenerationWarning[] = [];\n try {\n if (this.adapter.analyzeQuality) {\n const analysis = await this.adapter.analyzeQuality(\n config,\n qualityOptions\n );\n if (analysis.blocked) throw new QualityGateError(analysis);\n qualityWarnings = toQualityWarnings(analysis.diagnostics);\n }\n } catch (error) {\n const errorCode = (error as { code?: unknown } | undefined)?.code;\n if (\n errorCode === 'QUALITY_GATE_FAILED' ||\n errorCode === 'QUALITY_PROFILE_INCOMPATIBLE' ||\n // An unusable policy is the caller's configuration, not a hiccup.\n errorCode === 'QUALITY_POLICY_INVALID' ||\n quality?.policy?.onRuleError === 'throw' ||\n // A caller who asked for a gate must not receive an ungated document:\n // if the analysis failed, the gate never ran. Only the advisory case\n // (no gate requested) degrades to a warning.\n (quality?.policy?.gate && quality.policy.gate !== 'none')\n ) {\n throw error;\n }\n logger.warn('Quality analysis failed', { error });\n }\n const cacheKeyData = {\n config,\n customThemes:\n customThemes && Object.keys(customThemes).length > 0\n ? customThemes\n : null,\n fontMode: fontMode ?? null,\n fontSubstitution: fontSubstitution ?? null,\n fontStrict: callerStrict ?? null,\n // Same definition, different source directory → different local assets.\n baseDir: baseDir ?? null,\n // Same document, different backend → different bytes. Without this,\n // switching backends would serve the other one's cached buffer.\n renderer: renderer ?? null,\n };\n const cacheKey = this.cacheService.generateCacheKey(cacheKeyData);\n const hasDynamicContent = this.cacheService.hasDynamicContent(config);\n\n // Try cache\n if (!bypassCache && !hasDynamicContent) {\n const cached = this.cacheService.get(cacheKey);\n if (cached) {\n logger.info('Served from cache', { title: config.metadata?.title });\n return {\n filename: `${config.metadata?.title || this.adapter.label}${this.adapter.extension}`,\n fileId: Date.now().toString(),\n buffer: cached.buffer,\n // Render warnings ride with bytes. Quality is request policy, so it\n // is recomputed and merged even when the rendered artifact is cached.\n cached: true,\n warnings:\n cached.warnings || qualityWarnings.length > 0\n ? [...(cached.warnings ?? []), ...qualityWarnings]\n : null,\n };\n }\n }\n\n // Generate — use plugin-aware generator when plugins are loaded\n logger.info(`Generating ${this.adapter.label}`, {\n title: config.metadata?.title,\n });\n let buffer: Buffer;\n\n if (registry.hasPlugins()) {\n const plugins = registry.getPlugins();\n const generator = await this.adapter.createGenerator(plugins, {\n customThemes,\n fonts: fontOpts,\n baseDir,\n renderer,\n warnings: coreWarnings,\n quality,\n });\n buffer = await generator.generateBuffer(config);\n } else {\n buffer = await this.adapter.generateBuffer(config, {\n customThemes,\n fonts: fontOpts,\n baseDir,\n renderer,\n warnings: coreWarnings,\n quality,\n prepared,\n });\n }\n\n // Surface non-canonical fontWeight values (e.g. 450, 550) — the render\n // path silently coerces these to Regular/Bold via a bold-fallback, so\n // without a warning an author writing `fontWeight: 450` has no way to\n // know their intermediate weight was rounded away.\n const CANONICAL_WEIGHTS = new Set([\n 100, 200, 300, 400, 500, 600, 700, 800, 900,\n ]);\n const nonCanonical = [...referencedWeights].filter(\n (w) => !CANONICAL_WEIGHTS.has(w)\n );\n // Each entry keeps its own code: this array mixes FONT_OVERRIDE_LOCAL and\n // FONT_WEIGHT_NOT_IN_OVERRIDE, and clients filter on `context.code`.\n const extraWarnings: GenerationWarning[] =\n toSupplementalWarnings(overrideWarnings);\n for (const w of nonCanonical) {\n extraWarnings.push({\n component: 'fontRegistry',\n message: `[FONT_NONCANONICAL_WEIGHT] fontWeight ${w} is not one of 100/200/.../900; render path rounds to Regular or Bold via bold-only fallback.`,\n severity: 'info' as const,\n context: { code: 'FONT_NONCANONICAL_WEIGHT' },\n });\n }\n\n // Core first: FONT_UNRESOLVED is actionable and should read above the\n // informational FONT_OVERRIDE_LOCAL / FONT_NONCANONICAL_WEIGHT entries.\n const renderWarnings = [...coreWarnings, ...extraWarnings];\n const allWarnings = [...renderWarnings, ...qualityWarnings];\n\n // Cache renderer output only. Quality depends on request policy/profile\n // and is recomputed before every HIT. `resolvedFonts` stays out: it is a\n // TTF byte side-channel whose consumer passes `bypassCache: true`.\n this.cacheService.set(\n cacheKey,\n {\n buffer,\n warnings: renderWarnings.length > 0 ? renderWarnings : null,\n },\n config,\n { bypassCache: bypassCache || hasDynamicContent }\n );\n\n return {\n filename: `${config.metadata?.title || this.adapter.label}${this.adapter.extension}`,\n fileId: Date.now().toString(),\n buffer,\n cached: false,\n warnings: allWarnings.length > 0 ? allWarnings : null,\n resolvedFonts,\n };\n }\n\n async validate(\n jsonDefinition: any,\n options: GeneratorOptions = {}\n ): Promise<{\n valid: boolean;\n errors?: any[];\n qualityAnalysis?: QualityAnalysis;\n }> {\n const config =\n typeof jsonDefinition === 'string'\n ? JSON.parse(jsonDefinition)\n : jsonDefinition;\n\n const result = this.adapter.validateDocument(config);\n if (!result.valid) return result;\n if (this.adapter.analyzeQuality) {\n try {\n const prepared = this.adapter.prepareDocument\n ? await this.adapter.prepareDocument(config, options)\n : undefined;\n const qualityAnalysis = await this.adapter.analyzeQuality(\n config,\n prepared ? { ...options, prepared } : options\n );\n return {\n ...result,\n valid: result.valid && !qualityAnalysis.blocked,\n qualityAnalysis,\n };\n } catch (error) {\n const errorCode = (error as { code?: unknown } | undefined)?.code;\n const quality = options.quality;\n if (\n errorCode === 'QUALITY_GATE_FAILED' ||\n errorCode === 'QUALITY_PROFILE_INCOMPATIBLE' ||\n errorCode === 'QUALITY_POLICY_INVALID' ||\n quality?.policy?.onRuleError === 'throw' ||\n // Same rule `generate` applies: an analysis that never ran leaves a\n // requested gate unevaluated, and answering `valid: true` there would\n // promise a generation this service would then refuse.\n (quality?.policy?.gate && quality.policy.gate !== 'none')\n ) {\n throw error;\n }\n // Reporting a malformed document is what this endpoint is for: a\n // preparation that chokes on it must degrade to \"no quality\n // analysis\", not bury the schema errors under a 500.\n logger.warn('Quality analysis failed', { error });\n }\n }\n return result;\n }\n\n destroy(): void {\n if (this.cacheInvalidationHandler) {\n cacheEvents.off('generator:invalidate', this.cacheInvalidationHandler);\n this.cacheInvalidationHandler = null;\n }\n this.cacheService.clear();\n }\n}\n","import { LRUCache } from 'lru-cache';\nimport crypto from 'crypto';\nimport { logger } from '../utils/logger.js';\nimport { config } from '../config/index.js';\nimport { cacheEvents } from '@json-to-office/jto-cli';\nimport type { GenerationWarning } from '@json-to-office/shared';\n\n/**\n * Render bytes plus render-time warnings. Request-specific quality diagnostics\n * are recomputed and merged on every hit; caching them would leak one policy's\n * verdict into another request.\n */\nexport interface CachedGeneration {\n buffer: Buffer;\n warnings: GenerationWarning[] | null;\n}\n\nexport interface CacheStats {\n hits: number;\n misses: number;\n evictions: number;\n size: number;\n itemCount: number;\n}\n\nexport class CacheService {\n private cache: LRUCache<string, CachedGeneration>;\n private stats: CacheStats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n size: 0,\n itemCount: 0,\n };\n private cacheInvalidationHandler: (() => void) | null = null;\n\n constructor() {\n const maxSizeBytes = config.cache.maxSizeMB * 1024 * 1024;\n\n this.cache = new LRUCache<string, CachedGeneration>({\n max: config.cache.maxItems,\n maxSize: maxSizeBytes,\n // Must stay the buffer's byte length: lru-cache rejects a zero or\n // undefined size when `maxSize` is set.\n sizeCalculation: (value: CachedGeneration) => value.buffer.length,\n ttl: config.cache.ttlSeconds * 1000,\n dispose: (\n _value: CachedGeneration,\n _key: string,\n reason: LRUCache.DisposeReason\n ) => {\n if (reason === 'evict' || reason === 'delete') {\n this.stats.evictions++;\n }\n },\n updateAgeOnGet: true,\n updateAgeOnHas: false,\n });\n\n this.cacheInvalidationHandler = () => this.clear();\n cacheEvents.on('cache:invalidate', this.cacheInvalidationHandler);\n }\n\n generateCacheKey(data: unknown): string {\n const normalized = JSON.stringify(data, this.sortKeysReplacer);\n return crypto.createHash('sha256').update(normalized).digest('hex');\n }\n\n private sortKeysReplacer(_key: string, value: unknown): unknown {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return Object.keys(value)\n .sort()\n .reduce((sorted: Record<string, unknown>, key) => {\n sorted[key] = (value as Record<string, unknown>)[key];\n return sorted;\n }, {});\n }\n return value;\n }\n\n hasDynamicContent(data: unknown): boolean {\n const str = JSON.stringify(data);\n const patterns = [\n /\\{\\{now\\}\\}/i,\n /\\{\\{date\\}\\}/i,\n /\\{\\{time\\}\\}/i,\n /\\{\\{timestamp\\}\\}/i,\n /\\{\\{random\\}\\}/i,\n /\\{\\{uuid\\}\\}/i,\n ];\n return patterns.some((p) => p.test(str));\n }\n\n get(key: string): CachedGeneration | null {\n if (!config.features.cache) return null;\n const value = this.cache.get(key);\n if (value) {\n this.stats.hits++;\n this.updateStats();\n return value;\n }\n this.stats.misses++;\n return null;\n }\n\n set(\n key: string,\n value: CachedGeneration,\n documentConfig: unknown,\n options?: { bypassCache?: boolean }\n ): void {\n if (\n !config.features.cache ||\n options?.bypassCache ||\n this.hasDynamicContent(documentConfig)\n )\n return;\n this.cache.set(key, value);\n this.updateStats();\n }\n\n clear(): void {\n this.cache.clear();\n this.stats = { hits: 0, misses: 0, evictions: 0, size: 0, itemCount: 0 };\n logger.info('Cache cleared');\n }\n\n getStats(): CacheStats & { enabled: boolean; hitRate: number } {\n const total = this.stats.hits + this.stats.misses;\n return {\n ...this.stats,\n enabled: config.features.cache,\n hitRate:\n total > 0 ? Math.round((this.stats.hits / total) * 100) / 100 : 0,\n };\n }\n\n private updateStats(): void {\n this.stats.size = this.cache.calculatedSize || 0;\n this.stats.itemCount = this.cache.size;\n }\n\n destroy(): void {\n if (this.cacheInvalidationHandler) {\n cacheEvents.off('cache:invalidate', this.cacheInvalidationHandler);\n this.cacheInvalidationHandler = null;\n }\n }\n}\n","import { execFile } from 'node:child_process';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport { config } from '../config/index.js';\nimport { getFontStager } from '@json-to-office/jto-cli';\n\nconst DEFAULT_CONVERSION_TIMEOUT_MS = 30000;\nconst BINARY_PROBE_TIMEOUT_MS = 5000;\nconst MAX_EXEC_BUFFER_BYTES = 20 * 1024 * 1024;\n\ntype ExecError = NodeJS.ErrnoException & {\n stdout?: string | Buffer;\n stderr?: string | Buffer;\n};\n\nfunction executeFile(\n binary: string,\n args: string[],\n timeoutMs: number,\n envOverrides?: Record<string, string>\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n execFile(\n binary,\n args,\n {\n timeout: timeoutMs,\n maxBuffer: MAX_EXEC_BUFFER_BYTES,\n windowsHide: true,\n env: envOverrides ? { ...process.env, ...envOverrides } : process.env,\n },\n (error, stdout, stderr) => {\n if (error) {\n const execError = error as ExecError;\n execError.stdout = stdout;\n execError.stderr = stderr;\n reject(execError);\n return;\n }\n resolve({ stdout: stdout ?? '', stderr: stderr ?? '' });\n }\n );\n });\n}\n\nfunction toErrorText(value: unknown): string {\n if (!value) return '';\n if (Buffer.isBuffer(value)) return value.toString('utf8');\n if (typeof value === 'string') return value;\n return String(value);\n}\n\nfunction sanitizeBaseName(originalName?: string): string {\n const parsed = path.parse(originalName || 'document');\n return (\n (parsed.name || 'document').replace(/[^a-zA-Z0-9._-]/g, '_') || 'document'\n );\n}\n\nexport class LibreOfficeError extends Error {\n readonly code:\n | 'BINARY_NOT_FOUND'\n | 'CONVERSION_TIMEOUT'\n | 'CONVERSION_FAILED'\n | 'OUTPUT_NOT_FOUND';\n constructor(code: LibreOfficeError['code'], message: string) {\n super(message);\n this.name = 'LibreOfficeError';\n this.code = code;\n }\n}\n\nexport class LibreOfficeBinaryNotFoundError extends LibreOfficeError {\n readonly candidates: string[];\n constructor(candidates: string[]) {\n super(\n 'BINARY_NOT_FOUND',\n 'LibreOffice binary not found. Install LibreOffice locally or set LIBREOFFICE_PATH.'\n );\n this.name = 'LibreOfficeBinaryNotFoundError';\n this.candidates = candidates;\n }\n}\n\nexport class LibreOfficeTimeoutError extends LibreOfficeError {\n readonly timeoutMs: number;\n constructor(timeoutMs: number) {\n super(\n 'CONVERSION_TIMEOUT',\n `LibreOffice conversion timed out after ${timeoutMs}ms`\n );\n this.name = 'LibreOfficeTimeoutError';\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class LibreOfficeConversionError extends LibreOfficeError {\n readonly details?: string;\n constructor(message: string, details?: string) {\n super('CONVERSION_FAILED', message);\n this.name = 'LibreOfficeConversionError';\n this.details = details;\n }\n}\n\nexport class LibreOfficeOutputNotFoundError extends LibreOfficeError {\n readonly outputPath: string;\n constructor(outputPath: string) {\n super(\n 'OUTPUT_NOT_FOUND',\n 'LibreOffice conversion completed but PDF output was not produced'\n );\n this.name = 'LibreOfficeOutputNotFoundError';\n this.outputPath = outputPath;\n }\n}\n\nexport class LibreOfficeConverterService {\n private readonly timeoutMs: number;\n private readonly format: 'docx' | 'pptx';\n\n constructor(format: 'docx' | 'pptx', timeoutMs?: number) {\n this.format = format;\n this.timeoutMs =\n timeoutMs ||\n config.LIBREOFFICE_TIMEOUT_MS ||\n DEFAULT_CONVERSION_TIMEOUT_MS;\n }\n\n async convertToPdf(\n input: Buffer,\n originalName: string = 'document',\n resolvedFonts?: ResolvedFont[]\n ): Promise<Buffer> {\n if (!input || input.length === 0) {\n throw new LibreOfficeConversionError('Input file is empty');\n }\n\n const binaryPath = await this.resolveBinaryPath();\n const tempDir = await fs.mkdtemp(\n path.join(os.tmpdir(), 'jto-libreoffice-')\n );\n const outputBaseName = sanitizeBaseName(originalName);\n const ext = this.format === 'pptx' ? '.pptx' : '.docx';\n const inputPath = path.join(tempDir, `${outputBaseName}${ext}`);\n const pdfPath = path.join(tempDir, `${outputBaseName}.pdf`);\n\n // Stage fonts before spawning soffice so the child process picks them up\n // at startup. Handle is closed in the finally block regardless of outcome.\n const stager = getFontStager();\n const fontsToStage = (resolvedFonts ?? []).filter(\n (r) => r.sources.length > 0\n );\n const stageHandle =\n fontsToStage.length > 0\n ? await stager.stage(fontsToStage, tempDir)\n : null;\n\n try {\n await fs.writeFile(inputPath, input);\n\n const filterName =\n this.format === 'pptx' ? 'impress_pdf_Export' : 'writer_pdf_Export';\n await this.runConversion(\n binaryPath,\n inputPath,\n tempDir,\n filterName,\n stageHandle?.envOverrides\n );\n\n try {\n return await fs.readFile(pdfPath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new LibreOfficeOutputNotFoundError(pdfPath);\n }\n throw error;\n }\n } finally {\n if (stageHandle) {\n await stageHandle.cleanup().catch(() => {});\n }\n await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});\n }\n }\n\n private getBinaryCandidates(): string[] {\n const candidates: string[] = [];\n const configured = config.LIBREOFFICE_PATH?.trim();\n if (configured) candidates.push(configured);\n if (process.platform === 'darwin') {\n candidates.push('/Applications/LibreOffice.app/Contents/MacOS/soffice');\n } else if (process.platform === 'win32') {\n candidates.push('C:\\\\Program Files\\\\LibreOffice\\\\program\\\\soffice.exe');\n candidates.push(\n 'C:\\\\Program Files (x86)\\\\LibreOffice\\\\program\\\\soffice.exe'\n );\n }\n candidates.push('soffice', 'libreoffice');\n return [...new Set(candidates)];\n }\n\n private async resolveBinaryPath(): Promise<string> {\n const candidates = this.getBinaryCandidates();\n for (const candidate of candidates) {\n if (await this.isBinaryAvailable(candidate)) return candidate;\n }\n throw new LibreOfficeBinaryNotFoundError(candidates);\n }\n\n private async isBinaryAvailable(binaryPath: string): Promise<boolean> {\n if (binaryPath.includes(path.sep)) {\n try {\n await fs.access(binaryPath);\n } catch {\n return false;\n }\n }\n try {\n await executeFile(binaryPath, ['--version'], BINARY_PROBE_TIMEOUT_MS);\n return true;\n } catch (error) {\n const code = (error as ExecError).code;\n return code !== 'ENOENT' && code !== 'EACCES';\n }\n }\n\n private async runConversion(\n binaryPath: string,\n inputPath: string,\n outputDir: string,\n filterName: string,\n envOverrides?: Record<string, string>\n ): Promise<void> {\n const userProfilePath = path\n .join(outputDir, 'user-profile')\n .replace(/\\\\/g, '/');\n const userInstallation = `file:///${userProfilePath.replace(/^\\//, '')}`;\n const args = [\n '--headless',\n '--norestore',\n '--nolockcheck',\n '--nodefault',\n `-env:UserInstallation=${userInstallation}`,\n '--convert-to',\n `pdf:${filterName}`,\n '--outdir',\n outputDir,\n inputPath,\n ];\n\n if (process.env.JTO_DEBUG_FONTS === '1') {\n // eslint-disable-next-line no-console\n console.log(\n '[jto libreoffice-converter] spawning soffice with env overrides: ' +\n JSON.stringify(\n envOverrides\n ? Object.fromEntries(\n Object.entries(envOverrides).map(([k, v]) => [\n k,\n k === 'JTO_FONT_PATHS'\n ? `<${v.split(':').length} paths>`\n : v,\n ])\n )\n : {}\n )\n );\n }\n try {\n const result = await executeFile(\n binaryPath,\n args,\n this.timeoutMs,\n envOverrides\n );\n // Surface the soffice stderr stream for debugging — that's where the\n // [jto-font-register] macro writes its confirmation. Empty output\n // on macOS indicates the macro never fired (macro-security block,\n // missing Python, XCU parse error, …) and LibreOffice rendered\n // against fallback fonts. Gated behind a flag so prod logs stay clean.\n if (process.env.JTO_DEBUG_FONTS === '1') {\n const stderr = result.stderr?.trim();\n // eslint-disable-next-line no-console\n console.log(\n '[jto libreoffice-converter] conversion ok; stderr len=' +\n (stderr?.length ?? 0) +\n (stderr ? '\\n' + stderr : ' (empty)')\n );\n }\n } catch (error) {\n const execError = error as ExecError;\n if (execError.code === 'ETIMEDOUT')\n throw new LibreOfficeTimeoutError(this.timeoutMs);\n if (execError.code === 'ENOENT')\n throw new LibreOfficeBinaryNotFoundError(this.getBinaryCandidates());\n const details = [\n toErrorText(execError.stderr),\n toErrorText(execError.stdout),\n ]\n .filter(Boolean)\n .join('\\n')\n .trim();\n throw new LibreOfficeConversionError(\n 'LibreOffice failed to convert to PDF',\n details || execError.message\n );\n }\n }\n}\n","import type { FormatAdapter } from '@json-to-office/jto-cli';\nimport { GeneratorService } from '../services/generator.js';\nimport { CacheService } from '../services/cache.js';\nimport { LibreOfficeConverterService } from '../services/libreoffice-converter.js';\n\ntype ServiceMap = {\n generatorService: GeneratorService;\n cacheService: CacheService;\n libreOfficeConverterService: LibreOfficeConverterService;\n};\n\nexport class Container {\n private static instance: Container;\n private services: Map<keyof ServiceMap, ServiceMap[keyof ServiceMap]> =\n new Map();\n private adapter: FormatAdapter;\n\n private constructor(adapter: FormatAdapter) {\n this.adapter = adapter;\n const cacheService = new CacheService();\n const generatorService = new GeneratorService(adapter, cacheService);\n const libreOfficeConverterService = new LibreOfficeConverterService(\n adapter.name as 'docx' | 'pptx'\n );\n\n this.services.set('cacheService', cacheService);\n this.services.set('generatorService', generatorService);\n this.services.set(\n 'libreOfficeConverterService',\n libreOfficeConverterService\n );\n }\n\n public static initialize(adapter: FormatAdapter): Container {\n Container.instance = new Container(adapter);\n return Container.instance;\n }\n\n public static getInstance(): Container {\n if (!Container.instance) {\n throw new Error(\n 'Container not initialized. Call Container.initialize(adapter) first.'\n );\n }\n return Container.instance;\n }\n\n public static getAdapter(): FormatAdapter {\n return Container.getInstance().adapter;\n }\n\n public get<K extends keyof ServiceMap>(serviceName: K): ServiceMap[K] {\n const service = this.services.get(serviceName);\n if (!service) {\n throw new Error(`Service ${serviceName} not found`);\n }\n return service as ServiceMap[K];\n }\n}\n\nexport const getContainer = () => Container.getInstance();\n","import { Hono } from 'hono';\nimport { config } from '../config/index.js';\nimport { getContainer } from '../container/index.js';\nimport { AppEnv } from '../types/hono.js';\n\nexport const healthRouter = new Hono<AppEnv>();\n\nhealthRouter.get('/', (c) => {\n const memoryUsage = process.memoryUsage();\n const uptime = process.uptime();\n\n let cacheStats: any;\n try {\n const cacheService = getContainer().get('cacheService');\n cacheStats = cacheService.getStats();\n } catch {\n cacheStats = {\n enabled: false,\n hits: 0,\n misses: 0,\n hitRate: 0,\n evictions: 0,\n size: 0,\n itemCount: 0,\n };\n }\n\n return c.json({\n status: 'ok',\n timestamp: new Date().toISOString(),\n environment: config.NODE_ENV,\n version: '1.0.0',\n framework: 'Hono',\n uptime: Math.floor(uptime),\n memory: {\n rss: `${Math.round(memoryUsage.rss / 1024 / 1024)} MB`,\n heapTotal: `${Math.round(memoryUsage.heapTotal / 1024 / 1024)} MB`,\n heapUsed: `${Math.round(memoryUsage.heapUsed / 1024 / 1024)} MB`,\n },\n cache: {\n enabled: cacheStats.enabled,\n hits: cacheStats.hits,\n misses: cacheStats.misses,\n hitRate: `${(cacheStats.hitRate * 100).toFixed(1)}%`,\n itemCount: cacheStats.itemCount,\n },\n });\n});\n\nhealthRouter.get('/ready', (c) => c.json({ status: 'ready' }));\nhealthRouter.get('/live', (c) => c.json({ status: 'alive' }));\n","/**\n * Loose schemas for initial request validation before plugin-aware validation.\n * These schemas allow unknown types that will be validated by plugin-aware validators.\n */\n\nimport { Type } from '@sinclair/typebox';\n\n/**\n * Loose presentation generation request schema that allows plugin component names.\n * The strict validation is performed later with plugin-aware validators.\n */\n/**\n * Font options accepted over the wire. Caps prevent client-supplied\n * substitution maps from landing unbounded strings into the tree walker.\n */\nconst FontOptionsSchema = Type.Object(\n {\n mode: Type.Optional(\n Type.Union([Type.Literal('substitute'), Type.Literal('custom')])\n ),\n substitution: Type.Optional(\n Type.Record(\n Type.String({ maxLength: 128 }),\n Type.String({ maxLength: 128 }),\n { maxProperties: 256 }\n )\n ),\n strict: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false }\n);\n\nconst QualityOptionsSchema = Type.Object(\n {\n profile: Type.Optional(\n Type.Object(\n { id: Type.String({ minLength: 1, maxLength: 128 }) },\n { additionalProperties: true }\n )\n ),\n policy: Type.Optional(Type.Object({}, { additionalProperties: true })),\n },\n { additionalProperties: false }\n);\n\nexport const LooseDocumentGenerationRequestSchema = Type.Object(\n {\n jsonDefinition: Type.Union([\n Type.String(), // Allow JSON string\n Type.Object({}, { additionalProperties: true }), // Allow any object\n ]),\n customThemes: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n options: Type.Optional(\n Type.Object(\n {\n bypassCache: Type.Optional(Type.Boolean()),\n returnUrl: Type.Optional(Type.Boolean()),\n fonts: Type.Optional(FontOptionsSchema),\n // Backend to render with. Left as a bounded string rather than an\n // enum: the registry owns the list, answers an unknown id with the\n // ids that exist, and the route turns that into a 400.\n renderer: Type.Optional(Type.String({ maxLength: 64 })),\n quality: Type.Optional(QualityOptionsSchema),\n // Name of the discovered document this definition came from; the\n // server maps it to that document's directory so relative asset\n // paths resolve against it (#142). Names, never paths — a client\n // cannot point the server at an arbitrary directory.\n sourceName: Type.Optional(Type.String()),\n },\n { additionalProperties: true }\n )\n ),\n },\n { additionalProperties: true }\n);\n\n/**\n * Loose document validation request schema that allows plugin component names.\n */\nexport const LooseDocumentValidationRequestSchema = Type.Object(\n {\n jsonDefinition: Type.Union([\n Type.String(), // Allow JSON string\n Type.Object({}, { additionalProperties: true }), // Allow any object\n ]),\n options: Type.Optional(\n Type.Object(\n {\n renderer: Type.Optional(Type.String({ maxLength: 64 })),\n quality: Type.Optional(QualityOptionsSchema),\n },\n { additionalProperties: false }\n )\n ),\n },\n { additionalProperties: true }\n);\n\n/**\n * Diff request: two DOCX definitions to compare into a tracked-change\n * redline. Strict validation of both documents happens in the handler.\n */\nexport const LooseDocumentDiffRequestSchema = Type.Object(\n {\n oldDefinition: Type.Union([\n Type.String(),\n Type.Object({}, { additionalProperties: true }),\n ]),\n newDefinition: Type.Union([\n Type.String(),\n Type.Object({}, { additionalProperties: true }),\n ]),\n options: Type.Optional(\n Type.Object(\n {\n author: Type.Optional(Type.String({ maxLength: 128 })),\n date: Type.Optional(Type.String({ maxLength: 64 })),\n },\n { additionalProperties: false }\n )\n ),\n },\n { additionalProperties: true }\n);\n","import { TSchema } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport { Context, Env, ValidationTargets, MiddlewareHandler } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\n\n/**\n * Auto-detect raw document JSON (has `name` + `children` but no `jsonDefinition`)\n * and wrap it so callers can POST the document tree directly.\n */\nfunction autoWrapDocumentBody(value: unknown): unknown {\n if (\n typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'children' in value &&\n !('jsonDefinition' in value)\n ) {\n return { jsonDefinition: value };\n }\n return value;\n}\n\nexport function tbValidator<\n T extends TSchema,\n E extends Env = Env,\n P extends string = string,\n>(schema: T) {\n return (async (c: Context<E, P>, next: () => Promise<void>) => {\n let value: unknown;\n\n try {\n value = await c.req.json();\n } catch {\n throw new HTTPException(400, {\n message: 'Invalid JSON in request body',\n });\n }\n\n value = autoWrapDocumentBody(value);\n\n const isValid = Value.Check(schema, value);\n\n if (isValid) {\n (c.req as { validatedData?: Record<string, unknown> }).validatedData = {\n json: value,\n };\n await next();\n } else {\n const errors = [...Value.Errors(schema, value)].map((error) => ({\n path: error.path,\n message: error.message,\n value: error.value,\n }));\n\n const errorMessages = errors.map((e) => `${e.path || '/'}: ${e.message}`);\n\n throw new HTTPException(400, {\n message:\n errorMessages.length === 1\n ? errorMessages[0]\n : `Validation failed:\\n${errorMessages.join('\\n')}`,\n cause: { errors },\n });\n }\n }) as MiddlewareHandler<E, P, Record<string, unknown>>;\n}\n\nexport function getValidated<T>(\n c: Context,\n target: keyof ValidationTargets\n): T {\n const validatedData = (c.req as { validatedData?: Record<string, unknown> })\n .validatedData;\n if (!validatedData || !validatedData[target]) {\n throw new Error(`No validated data found for target: ${target}`);\n }\n return validatedData[target] as T;\n}\n","import { MiddlewareHandler } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\n\nexport interface RateLimitOptions {\n limit: number;\n window: number; // milliseconds\n keyGenerator?: (c: any) => string;\n namespace?: string | ((c: any) => string);\n maxEntries?: number;\n trustProxy?: boolean;\n}\n\nfunction clientAddress(c: any, trustProxy: boolean): string {\n if (trustProxy) {\n const forwarded =\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',')[0]?.trim();\n if (forwarded) return forwarded;\n }\n const incoming = c.env?.incoming || c.env?.req;\n return incoming?.socket?.remoteAddress || 'anonymous';\n}\n\n/**\n * Bounded, process-local rate limiting. Distributed deployments should put a\n * shared limiter at the edge too; this remains the last line of defence for a\n * single worker and never grows without bound.\n */\nexport const rateLimiter = (options: RateLimitOptions): MiddlewareHandler => {\n const { limit, window, keyGenerator } = options;\n const maxEntries = options.maxEntries ?? 10_000;\n const rateLimitStore = new Map<\n string,\n { count: number; resetTime: number }\n >();\n let lastCleanup = 0;\n\n return async (c, next) => {\n const clientKey = keyGenerator\n ? keyGenerator(c)\n : clientAddress(c, options.trustProxy === true);\n const namespace =\n typeof options.namespace === 'function'\n ? options.namespace(c)\n : options.namespace || `${c.req.method}:${c.req.path}`;\n const key = `${namespace}:${String(clientKey).slice(0, 256)}`;\n const now = Date.now();\n\n // Amortize cleanup; scanning an attacker-filled map on every request would\n // turn the protection itself into a CPU denial of service.\n if (now - lastCleanup >= Math.min(window, 60_000)) {\n for (const [storedKey, value] of rateLimitStore.entries()) {\n if (value.resetTime <= now) rateLimitStore.delete(storedKey);\n }\n lastCleanup = now;\n }\n\n const record = rateLimitStore.get(key);\n\n if (!record) {\n if (rateLimitStore.size >= maxEntries) {\n const oldestKey = rateLimitStore.keys().next().value as\n | string\n | undefined;\n if (oldestKey) rateLimitStore.delete(oldestKey);\n }\n rateLimitStore.set(key, {\n count: 1,\n resetTime: now + window,\n });\n } else if (record.resetTime <= now) {\n // Window expired, reset\n record.count = 1;\n record.resetTime = now + window;\n } else if (record.count >= limit) {\n // Rate limit exceeded\n const retryAfter = Math.ceil((record.resetTime - now) / 1000);\n\n c.header('X-RateLimit-Limit', String(limit));\n c.header('X-RateLimit-Remaining', '0');\n c.header('X-RateLimit-Reset', String(record.resetTime));\n c.header('Retry-After', String(retryAfter));\n\n throw new HTTPException(429, {\n message: 'Too many requests, please try again later',\n });\n } else {\n // Increment count\n record.count++;\n }\n\n // Add rate limit headers\n const currentRecord = rateLimitStore.get(key)!;\n c.header('X-RateLimit-Limit', String(limit));\n c.header(\n 'X-RateLimit-Remaining',\n String(Math.max(0, limit - currentRecord.count))\n );\n c.header('X-RateLimit-Reset', String(currentRecord.resetTime));\n\n await next();\n };\n};\n","import type { OutboundSourceMode } from '../config/index.js';\n\nexport interface OutboundSourcePolicy {\n mode: OutboundSourceMode;\n allowedHosts: readonly string[];\n}\n\nexport class UnsafeOutboundSourceError extends Error {\n constructor(\n readonly path: string,\n reason: string\n ) {\n super(`Unsafe outbound source at ${path}: ${reason}`);\n this.name = 'UnsafeOutboundSourceError';\n }\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nconst DANGEROUS_KEYS = new Set(['__proto__', 'prototype', 'constructor']);\nconst COMPONENT_SOURCE_NAMES = new Set(['image']);\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hostMatches(host: string, pattern: string): boolean {\n const normalized = pattern.toLowerCase().replace(/\\.$/, '');\n if (normalized.startsWith('*.')) {\n const suffix = normalized.slice(1);\n return host.endsWith(suffix) && host.length > suffix.length;\n }\n return host === normalized;\n}\n\nfunction isPrivateIpv4(host: string): boolean {\n const parts = host.split('.');\n if (parts.length !== 4) return false;\n const octets = parts.map(Number);\n if (\n octets.some(\n (part, index) =>\n !Number.isInteger(part) ||\n part < 0 ||\n part > 255 ||\n String(part) !== parts[index]\n )\n ) {\n return false;\n }\n const [a, b] = octets;\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 100 && b >= 64 && b <= 127) ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && (b === 0 || b === 168)) ||\n (a === 198 && (b === 18 || b === 19)) ||\n a >= 224\n );\n}\n\nfunction isPrivateHost(host: string): boolean {\n const normalized = host\n .toLowerCase()\n .replace(/^\\[|\\]$/g, '')\n .replace(/\\.$/, '');\n if (\n normalized === 'localhost' ||\n normalized.endsWith('.localhost') ||\n normalized === '::' ||\n normalized === '::1'\n ) {\n return true;\n }\n if (isPrivateIpv4(normalized)) return true;\n if (normalized.startsWith('::ffff:')) {\n const mapped = normalized.slice('::ffff:'.length);\n if (isPrivateIpv4(mapped)) return true;\n const groups = mapped.match(/^([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);\n if (groups) {\n const value =\n Number.parseInt(groups[1], 16) * 0x1_0000 +\n Number.parseInt(groups[2], 16);\n return isPrivateIpv4(\n [\n value >>> 24,\n (value >>> 16) & 255,\n (value >>> 8) & 255,\n value & 255,\n ].join('.')\n );\n }\n }\n const firstIpv6Group = Number.parseInt(normalized.split(':')[0] || '0', 16);\n return (\n (firstIpv6Group >= 0xfc00 && firstIpv6Group <= 0xfdff) ||\n (firstIpv6Group >= 0xfe80 && firstIpv6Group <= 0xfebf)\n );\n}\n\nfunction assertAllowedUrl(\n source: string,\n path: string,\n allowedHosts: readonly string[]\n): void {\n if (source.startsWith('data:')) return;\n\n let url: URL;\n try {\n url = new URL(source);\n } catch {\n throw new UnsafeOutboundSourceError(\n path,\n 'local and relative file paths are disabled for HTTP requests'\n );\n }\n\n if (url.protocol !== 'https:') {\n throw new UnsafeOutboundSourceError(path, 'only HTTPS URLs are allowed');\n }\n if (url.username || url.password) {\n throw new UnsafeOutboundSourceError(\n path,\n 'URLs containing credentials are not allowed'\n );\n }\n\n const host = url.hostname.toLowerCase().replace(/\\.$/, '');\n if (isPrivateHost(host)) {\n throw new UnsafeOutboundSourceError(\n path,\n `private or local host \"${host}\" is not allowed`\n );\n }\n if (!allowedHosts.some((pattern) => hostMatches(host, pattern))) {\n throw new UnsafeOutboundSourceError(\n path,\n `host \"${host}\" is not in OUTBOUND_HOST_ALLOWLIST`\n );\n }\n}\n\nfunction extractCssReferences(input: string): string[] {\n const references: string[] = [];\n const urlPattern = /url\\(\\s*(['\"]?)([^)'\"\\s]+)\\1\\s*\\)/gi;\n const importPattern = /@import\\s+(?:url\\(\\s*)?(['\"])([^'\"]+)\\1/gi;\n for (const pattern of [urlPattern, importPattern]) {\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(input))) references.push(match[2]);\n }\n return references;\n}\n\nfunction extractAbsoluteUrls(input: string): string[] {\n return input.match(/(?:https?|file):\\/\\/[^\\s'\"<>)}\\]]+/gi) ?? [];\n}\n\nfunction assertSafeSvg(\n svg: string,\n path: string,\n allowedHosts: readonly string[]\n): void {\n if (\n /<\\s*script\\b/i.test(svg) ||\n /<\\s*(?:foreignObject|iframe|object|embed)\\b/i.test(svg) ||\n /\\bon[a-z]+\\s*=/i.test(svg)\n ) {\n throw new UnsafeOutboundSourceError(path, 'active SVG content is disabled');\n }\n if (/<!\\s*(?:DOCTYPE|ENTITY)\\b/i.test(svg)) {\n throw new UnsafeOutboundSourceError(\n path,\n 'SVG document types and entities are disabled'\n );\n }\n\n const refPattern = /\\b(?:href|src)\\s*=\\s*(['\"])(.*?)\\1/gi;\n let match: RegExpExecArray | null;\n while ((match = refPattern.exec(svg))) {\n const ref = match[2].trim();\n if (!ref || ref.startsWith('#') || ref.startsWith('data:')) continue;\n assertAllowedUrl(ref, path, allowedHosts);\n }\n for (const ref of extractCssReferences(svg)) {\n if (ref.startsWith('#') || ref.startsWith('data:')) continue;\n assertAllowedUrl(ref, path, allowedHosts);\n }\n}\n\nfunction assertSafeEncodedImage(\n source: string,\n path: string,\n allowedHosts: readonly string[]\n): void {\n let candidate = source.trim();\n let declaredSvg = false;\n\n if (candidate.startsWith('data:')) {\n const comma = candidate.indexOf(',');\n if (comma < 0) {\n throw new UnsafeOutboundSourceError(path, 'malformed image data URL');\n }\n const metadata = candidate.slice(5, comma);\n declaredSvg = metadata.split(';')[0].toLowerCase() === 'image/svg+xml';\n if (!declaredSvg) return;\n const payload = candidate.slice(comma + 1);\n try {\n candidate = /(?:^|;)base64(?:;|$)/i.test(metadata)\n ? Buffer.from(payload, 'base64').toString('utf8')\n : decodeURIComponent(payload);\n } catch {\n throw new UnsafeOutboundSourceError(path, 'malformed SVG data URL');\n }\n } else if (!/<\\s*svg\\b/i.test(candidate)) {\n // The documented `base64` shape is a data URL, but inspect raw base64 too\n // so a migration client cannot smuggle active SVG through the same field.\n candidate = Buffer.from(candidate, 'base64').toString('utf8');\n }\n\n const svgStart = candidate.search(/<\\s*svg\\b/i);\n if (svgStart < 0) {\n if (declaredSvg) {\n throw new UnsafeOutboundSourceError(path, 'malformed SVG image data');\n }\n return;\n }\n assertSafeSvg(candidate, path, allowedHosts);\n}\n\nfunction assertSafeResources(\n resources: JsonRecord,\n path: string,\n allowedHosts: readonly string[]\n): void {\n if (typeof resources.js === 'string' && resources.js.trim()) {\n throw new UnsafeOutboundSourceError(\n `${path}.js`,\n 'remote renderer JavaScript resources are disabled'\n );\n }\n if (typeof resources.css === 'string') {\n for (const ref of extractCssReferences(resources.css)) {\n if (ref.startsWith('data:')) continue;\n assertAllowedUrl(ref, `${path}.css`, allowedHosts);\n }\n }\n // Highcharts loads `resources.files` as JavaScript. Allowlisting a host for\n // fonts or stylesheets must not also grant it script execution inside the\n // renderer, so reject the field outright rather than URL-checking it.\n if (Array.isArray(resources.files) && resources.files.length > 0) {\n throw new UnsafeOutboundSourceError(\n `${path}.files`,\n 'remote renderer JavaScript resources are disabled'\n );\n }\n}\n\nfunction assertNoRemoteReferences(\n value: unknown,\n path: string,\n allowedHosts: readonly string[],\n seen: WeakSet<object>\n): void {\n if (typeof value === 'string') {\n if (\n /\\b(?:fetch|XMLHttpRequest|WebSocket|EventSource)\\s*\\(/i.test(value) ||\n /\\b(?:javascript|file):/i.test(value)\n ) {\n throw new UnsafeOutboundSourceError(\n path,\n 'network-capable JavaScript and file URLs are disabled'\n );\n }\n for (const url of [\n ...extractAbsoluteUrls(value),\n ...extractCssReferences(value),\n ]) {\n if (url.startsWith('data:')) continue;\n assertAllowedUrl(url, path, allowedHosts);\n }\n if (/^\\/\\//.test(value.trim())) {\n throw new UnsafeOutboundSourceError(\n path,\n 'protocol-relative URLs are disabled'\n );\n }\n return;\n }\n if (!value || typeof value !== 'object' || seen.has(value)) return;\n seen.add(value);\n if (Array.isArray(value)) {\n value.forEach((entry, index) =>\n assertNoRemoteReferences(entry, `${path}[${index}]`, allowedHosts, seen)\n );\n return;\n }\n for (const [key, child] of Object.entries(value as JsonRecord)) {\n assertNoRemoteReferences(child, `${path}.${key}`, allowedHosts, seen);\n }\n}\n\nfunction visit(\n value: unknown,\n path: string,\n containerKey: string | undefined,\n allowedHosts: readonly string[],\n seen: WeakSet<object>\n): void {\n if (!value || typeof value !== 'object' || seen.has(value)) return;\n seen.add(value);\n\n if (Array.isArray(value)) {\n value.forEach((entry, index) =>\n visit(entry, `${path}[${index}]`, containerKey, allowedHosts, seen)\n );\n return;\n }\n\n const record = value as JsonRecord;\n for (const key of Object.keys(record)) {\n if (DANGEROUS_KEYS.has(key)) {\n throw new UnsafeOutboundSourceError(\n `${path}.${key}`,\n 'prototype mutation keys are disabled'\n );\n }\n }\n\n const kind = typeof record.kind === 'string' ? record.kind : undefined;\n if (kind === 'file' && typeof record.path === 'string') {\n throw new UnsafeOutboundSourceError(\n `${path}.path`,\n 'local file sources are disabled for HTTP requests'\n );\n }\n if (\n (kind === 'url' || kind === 'variable') &&\n typeof record.url === 'string'\n ) {\n assertAllowedUrl(record.url, `${path}.url`, allowedHosts);\n }\n\n const componentName =\n typeof record.name === 'string' ? record.name.toLowerCase() : undefined;\n const props = isRecord(record.props) ? record.props : undefined;\n if (componentName && props) {\n if (\n COMPONENT_SOURCE_NAMES.has(componentName) &&\n typeof props.path === 'string'\n ) {\n assertAllowedUrl(props.path, `${path}.props.path`, allowedHosts);\n assertSafeEncodedImage(props.path, `${path}.props.path`, allowedHosts);\n }\n if (\n COMPONENT_SOURCE_NAMES.has(componentName) &&\n typeof props.base64 === 'string'\n ) {\n assertSafeEncodedImage(\n props.base64,\n `${path}.props.base64`,\n allowedHosts\n );\n }\n if (\n (componentName === 'highcharts' || componentName === 'visual') &&\n typeof props.serverUrl === 'string'\n ) {\n assertAllowedUrl(\n props.serverUrl,\n `${path}.props.serverUrl`,\n allowedHosts\n );\n }\n if (componentName === 'highcharts') {\n if (isRecord(props.resources)) {\n assertSafeResources(\n props.resources,\n `${path}.props.resources`,\n allowedHosts\n );\n }\n assertNoRemoteReferences(\n props.options,\n `${path}.props.options`,\n allowedHosts,\n new WeakSet()\n );\n }\n }\n\n // Slide/template/visual canvas backgrounds store an image source in a plain\n // `{ image: { path } }` object rather than an image component.\n if (containerKey === 'image' && typeof record.path === 'string') {\n assertAllowedUrl(record.path, `${path}.path`, allowedHosts);\n assertSafeEncodedImage(record.path, `${path}.path`, allowedHosts);\n }\n if (typeof record.svg === 'string') {\n assertSafeSvg(record.svg, `${path}.svg`, allowedHosts);\n }\n if (containerKey === 'resources') {\n assertSafeResources(record, path, allowedHosts);\n }\n\n for (const [key, child] of Object.entries(record)) {\n visit(child, `${path}.${key}`, key, allowedHosts, seen);\n }\n}\n\n/**\n * Reject request-controlled sources capable of making the server read local\n * files or reach arbitrary network hosts. Development mode intentionally\n * preserves local playground workflows.\n */\nexport function assertSafeOutboundSources(\n value: unknown,\n policy: OutboundSourcePolicy,\n rootPath = 'request'\n): void {\n if (policy.mode === 'development') return;\n\n let parsed = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value);\n } catch {\n // Structural validation owns malformed JSON reporting.\n return;\n }\n }\n visit(parsed, rootPath, undefined, policy.allowedHosts, new WeakSet());\n}\n\n/** Extra checks for payloads executed by the Chromium-based chart renderer. */\nexport function assertSafeRendererPayload(\n value: unknown,\n policy: OutboundSourcePolicy\n): void {\n assertSafeOutboundSources(value, policy, 'export');\n if (policy.mode === 'development' || !isRecord(value)) return;\n assertNoRemoteReferences(\n value.infile,\n 'export.infile',\n policy.allowedHosts,\n new WeakSet()\n );\n}\n","/**\n * Shared POST /rasterize + /rasterize/batch routes — validated handlers\n * mounted on BOTH the playground format router and the standalone\n * jto-render-server, so the public and in-app rasterize surfaces can't drift\n * in validation, limits, or error mapping.\n *\n * /rasterize renders one single-slide pptx presentation to a PNG.\n * /rasterize/batch (#153) renders many independent single-slide presentations\n * in one request — one LibreOffice launch instead of one per visual — and\n * returns index-aligned per-slide results (200 with item errors rather than\n * all-or-nothing).\n */\n\nimport path from 'node:path';\nimport type { Hono, MiddlewareHandler } from 'hono';\nimport { Type } from '@sinclair/typebox';\nimport { bodyLimit } from 'hono/body-limit';\nimport { HTTPException } from 'hono/http-exception';\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n MIN_VISUAL_DPI,\n MAX_VISUAL_DPI,\n MAX_RASTERIZE_BATCH_SLIDES,\n MAX_RASTERIZE_FONTS,\n MAX_RASTERIZE_FONT_BYTES,\n type PptxRasterizer,\n type PptxBatchRasterizer,\n type RasterizeFontFace,\n} from '@json-to-office/shared';\nimport {\n createLibreOfficePptxRasterizer,\n createLibreOfficePptxBatchRasterizer,\n} from '@json-to-office/jto-cli';\nimport { config } from './config/index.js';\nimport { tbValidator, getValidated } from './lib/typebox-validator.js';\nimport {\n assertSafeOutboundSources,\n type OutboundSourcePolicy,\n UnsafeOutboundSourceError,\n} from './security/outbound-source-policy.js';\n\n/**\n * Strict standard-alphabet base64: whole quadruplets with correct padding,\n * nothing else. `Buffer.from(s, 'base64')` is lenient — it silently skips\n * whitespace, newlines, invalid characters, and everything up to (and\n * including) a `data:image/...;base64,` prefix — so an unconstrained string\n * decodes to garbage that gets written to disk and handed to LibreOffice.\n * Rejecting at the boundary turns that into a 400.\n *\n * Linear-time by construction: one unambiguous fixed-width repetition\n * followed by a fixed-width optional tail, so there is no backtracking\n * blowup on a multi-megabyte string.\n */\nconst BASE64_PATTERN =\n '^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$';\n\n/**\n * One font face the caller wants staged for this render's LibreOffice\n * launch. `data` is base64 of the raw font file (no `data:` prefix).\n */\nconst RasterizeFontFaceSchema = Type.Object(\n {\n family: Type.String({ minLength: 1, maxLength: 128 }),\n weight: Type.Integer({ minimum: 1, maximum: 1000 }),\n italic: Type.Boolean(),\n data: Type.String({\n minLength: 1,\n maxLength: 4 * 1024 * 1024,\n pattern: BASE64_PATTERN,\n }),\n format: Type.Optional(\n Type.Union([\n Type.Literal('ttf'),\n Type.Literal('otf'),\n Type.Literal('woff'),\n Type.Literal('woff2'),\n ])\n ),\n },\n { additionalProperties: false }\n);\nconst FontsSchema = Type.Optional(\n Type.Array(RasterizeFontFaceSchema, { maxItems: MAX_RASTERIZE_FONTS })\n);\n\n/** Body for POST /rasterize: a single-slide pptx presentation + optional dpi. */\nexport const RasterizeRequestSchema = Type.Object(\n {\n presentation: Type.Object({}, { additionalProperties: true }),\n dpi: Type.Optional(\n Type.Number({ minimum: MIN_VISUAL_DPI, maximum: MAX_VISUAL_DPI })\n ),\n baseDir: Type.Optional(Type.String()),\n fonts: FontsSchema,\n },\n { additionalProperties: false }\n);\n\n/** Body for POST /rasterize/batch: independent slides + shared baseDir. */\nexport const RasterizeBatchRequestSchema = Type.Object(\n {\n slides: Type.Array(\n Type.Object(\n {\n presentation: Type.Object({}, { additionalProperties: true }),\n dpi: Type.Optional(\n Type.Number({ minimum: MIN_VISUAL_DPI, maximum: MAX_VISUAL_DPI })\n ),\n },\n { additionalProperties: false }\n ),\n { minItems: 1, maxItems: MAX_RASTERIZE_BATCH_SLIDES }\n ),\n baseDir: Type.Optional(Type.String()),\n // Request-level, shared by every slide, exactly like `baseDir`. NOT\n // inside the per-slide object above, whose `additionalProperties: false`\n // must keep rejecting per-slide fonts: a uniform slide shape is what\n // lets batch dedupe and the disk-cache key stay identical to the\n // single-slide path.\n fonts: FontsSchema,\n },\n { additionalProperties: false }\n);\n\n// One rasterizer per process — shares the on-disk content-addressed cache\n// across every /rasterize surface in the process. Single and batch factories\n// use the same default cache directory, so the two routes share hits too.\nlet sharedRasterizer: PptxRasterizer | undefined;\nexport function getSharedRasterizer(): PptxRasterizer {\n if (!sharedRasterizer) {\n sharedRasterizer = createLibreOfficePptxRasterizer();\n }\n return sharedRasterizer;\n}\n\nlet sharedBatchRasterizer: PptxBatchRasterizer | undefined;\nexport function getSharedBatchRasterizer(): PptxBatchRasterizer {\n if (!sharedBatchRasterizer) {\n sharedBatchRasterizer = createLibreOfficePptxBatchRasterizer();\n }\n return sharedBatchRasterizer;\n}\n\nconst jsonOnly: MiddlewareHandler = async (c, next) => {\n const contentType = c.req.header('content-type');\n if (!contentType || !contentType.includes('application/json')) {\n throw new HTTPException(400, {\n message: 'Content-Type must be application/json',\n });\n }\n await next();\n};\n\n// Raster size budget. Slide dimensions are author-controlled inches and the\n// schema does not bound them, so an oversized canvas × dpi could demand an\n// enormous bitmap; with batching that multiplies by slide count. Budgets are\n// estimated up front from the declared slide size (default pptx 16:9 when\n// absent) — same philosophy as the /export pixel budget.\nconst DEFAULT_SLIDE_WIDTH_IN = 13.34;\nconst DEFAULT_SLIDE_HEIGHT_IN = 7.5;\nconst MAX_SLIDE_PIXELS = 64_000_000;\nconst MAX_BATCH_PIXELS = 256_000_000;\n\nfunction estimateSlidePixels(presentation: unknown, dpi: number): number {\n const props = (presentation as { props?: Record<string, unknown> } | null)\n ?.props;\n const dim = (value: unknown, fallback: number): number =>\n typeof value === 'number' && Number.isFinite(value) && value > 0\n ? value\n : fallback;\n const widthIn = dim(props?.slideWidth, DEFAULT_SLIDE_WIDTH_IN);\n const heightIn = dim(props?.slideHeight, DEFAULT_SLIDE_HEIGHT_IN);\n return widthIn * dpi * (heightIn * dpi);\n}\n\nfunction assertPixelBudget(\n slides: Array<{ presentation: unknown; dpi: number }>\n): void {\n let total = 0;\n for (const slide of slides) {\n const pixels = estimateSlidePixels(slide.presentation, slide.dpi);\n if (pixels > MAX_SLIDE_PIXELS) {\n throw new HTTPException(400, {\n message: 'Requested slide dimensions are too large',\n });\n }\n total += pixels;\n }\n if (total > MAX_BATCH_PIXELS) {\n throw new HTTPException(400, {\n message: 'Requested batch raster size is too large',\n });\n }\n}\n\n/**\n * Bound the decoded font payload. The per-face `maxLength` and\n * `MAX_RASTERIZE_FONTS` alone would admit far more than the body limit\n * allows, and staging writes every face to disk before soffice starts.\n */\nfunction assertFontBudget(fonts: RasterizeFontFace[] | undefined): void {\n if (!fonts?.length) return;\n // base64 → bytes ≈ len × 3/4. A cheap upper bound; no decode needed.\n const bytes = fonts.reduce(\n (sum, f) => sum + Math.ceil(f.data.length * 0.75),\n 0\n );\n if (bytes > MAX_RASTERIZE_FONT_BYTES) {\n throw new HTTPException(400, {\n message: 'Requested font payload is too large',\n });\n }\n}\n\n/**\n * `baseDir` selects the directory local media paths resolve against. An\n * unrestricted value would let any HTTP caller point the rasterizer at\n * arbitrary server directories and exfiltrate readable files as rendered\n * pixels, so it must stay inside the server's own working tree. Callers\n * rendering documents that live elsewhere should run the server from that\n * tree (or use an in-process rasterizer).\n */\nfunction resolveSafeBaseDir(baseDir: string | undefined): string | undefined {\n if (baseDir === undefined) return undefined;\n const resolved = path.resolve(baseDir);\n const cwd = process.cwd();\n if (resolved !== cwd && !resolved.startsWith(cwd + path.sep)) {\n throw new HTTPException(400, {\n message: 'baseDir must be inside the server working directory',\n });\n }\n return resolved;\n}\n\n/** Map rasterization failures onto stable 400/503/500 responses. */\nfunction toHttpException(error: unknown): HTTPException {\n if (error instanceof HTTPException) return error;\n if (error instanceof UnsafeOutboundSourceError) {\n return new HTTPException(400, { message: error.message });\n }\n const msg =\n error instanceof Error ? error.message.toLowerCase() : String(error);\n if (msg.includes('not found') || msg.includes('rasterization needs')) {\n return new HTTPException(503, { message: (error as Error).message });\n }\n if (msg.includes('invalid') || msg.includes('validation')) {\n return new HTTPException(400, { message: (error as Error).message });\n }\n return new HTTPException(500, {\n message: 'Internal server error during rasterization',\n });\n}\n\n/**\n * Hard ceiling for the rasterize body limit, whatever an operator configures.\n * The schema's own worst case (MAX_RASTERIZE_FONTS × 4 MiB of base64 = 128\n * MiB) must never be reachable, and a body this large is already far past the\n * MAX_RASTERIZE_FONT_BYTES working budget.\n */\nconst MAX_RASTERIZE_BODY_CEILING = 64 * 1024 * 1024;\n\n/**\n * Resolve the rasterize body limit. Precedence, most specific first:\n *\n * 1. an explicit `options.maxBodyBytes` from the mounting server,\n * 2. `MAX_RASTERIZE_BODY_SIZE` — the route's own operator knob, also read\n * by the standalone render server for its outer limit,\n * 3. `config.requestLimits.maxBodySize` (`MAX_REQUEST_BODY_SIZE`), the\n * process-wide configured ceiling,\n *\n * clamped to {@link MAX_RASTERIZE_BODY_CEILING}. Previously this was a\n * hardcoded 32 MiB, which silently discarded any configured value above it.\n * Resolved lazily (at route registration) so dotenv has certainly run.\n */\nexport function resolveMaxBodyBytes(explicit?: number): number {\n const fromEnv = Number.parseInt(\n process.env.MAX_RASTERIZE_BODY_SIZE ?? '',\n 10\n );\n const configured =\n explicit ??\n (Number.isFinite(fromEnv) && fromEnv > 0\n ? fromEnv\n : config.requestLimits.maxBodySize);\n return Math.min(configured, MAX_RASTERIZE_BODY_CEILING);\n}\n\nexport interface RasterizeRouteOptions {\n getRasterizer?: () => PptxRasterizer;\n getBatchRasterizer?: () => PptxBatchRasterizer;\n preMiddleware?: MiddlewareHandler[];\n sourcePolicy?: OutboundSourcePolicy;\n onError?: (error: unknown) => void;\n /**\n * Body-size limit for both rasterize routes. Defaults to the configured\n * server limit (see {@link resolveMaxBodyBytes}); always clamped to\n * {@link MAX_RASTERIZE_BODY_CEILING}.\n */\n maxBodyBytes?: number;\n}\n\n/**\n * Register `POST /rasterize` and `POST /rasterize/batch` on a Hono router\n * with body-size limits, content-type + schema validation (dpi clamped to\n * [MIN,MAX]_VISUAL_DPI, batch capped at MAX_RASTERIZE_BATCH_SLIDES), the\n * shared rasterizers, and structured 400/413/503/500 error mapping. Both\n * routes share `preMiddleware` instances (e.g. one rate limiter), so a batch\n * and its per-visual fallback draw from the same budget.\n *\n * @param options.preMiddleware - extra middleware (e.g. a rate limiter) run first.\n * @param options.maxBodyBytes - body-size limit; defaults to the configured\n * server limit rather than a hardcoded one (see {@link resolveMaxBodyBytes}).\n */\nexport function registerRasterizeRoute(\n router: Hono<any>,\n options: RasterizeRouteOptions = {}\n): void {\n const getRasterizer = options.getRasterizer ?? getSharedRasterizer;\n const getBatchRasterizer =\n options.getBatchRasterizer ?? getSharedBatchRasterizer;\n\n // The body now also carries base64 font faces. The schema alone would admit\n // MAX_RASTERIZE_FONTS × 4 MiB = 128 MiB; this limit is what actually bounds\n // it, and it rejects with 413 BEFORE parsing, which is the order we want.\n // MAX_RASTERIZE_FONT_BYTES (8 MiB decoded ≈ 10.7 MiB base64) is the\n // intended working ceiling for fonts within that budget.\n const maxBodyBytes = resolveMaxBodyBytes(options.maxBodyBytes);\n\n const shared: MiddlewareHandler[] = [\n ...(options.preMiddleware ?? []),\n bodyLimit({\n maxSize: maxBodyBytes,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n jsonOnly,\n ];\n\n const guard = async <T>(run: () => Promise<T>): Promise<T> => {\n try {\n return await run();\n } catch (error) {\n options.onError?.(error);\n throw toHttpException(error);\n }\n };\n\n router.post(\n '/rasterize',\n ...shared,\n tbValidator(RasterizeRequestSchema),\n async (c) => {\n const { presentation, dpi, baseDir, fonts } = getValidated<{\n presentation: unknown;\n dpi?: number;\n baseDir?: string;\n fonts?: RasterizeFontFace[];\n }>(c, 'json');\n const safeBaseDir = resolveSafeBaseDir(baseDir);\n\n const effectiveDpi = clampVisualDpi(dpi ?? DEFAULT_VISUAL_DPI);\n assertPixelBudget([{ presentation, dpi: effectiveDpi }]);\n assertFontBudget(fonts);\n\n const result = await guard(async () => {\n if (options.sourcePolicy) {\n // Scoped to `presentation` only. Font faces are inert base64 with\n // no URL-shaped keys, and walking multi-MB strings per request\n // would be pure cost.\n assertSafeOutboundSources(\n presentation,\n options.sourcePolicy,\n 'presentation'\n );\n }\n return getRasterizer()({\n presentation,\n dpi: effectiveDpi,\n baseDir: safeBaseDir,\n // Conditional so a fontless request reaches the engine with no\n // `fonts` key at all — an `undefined` would still be an absent\n // digest, but keeping the object identical to the pre-change shape\n // makes the cache-key equivalence obvious.\n ...(fonts?.length && { fonts }),\n });\n });\n return c.json(result);\n }\n );\n\n router.post(\n '/rasterize/batch',\n ...shared,\n tbValidator(RasterizeBatchRequestSchema),\n async (c) => {\n const { slides, baseDir, fonts } = getValidated<{\n slides: Array<{ presentation: unknown; dpi?: number }>;\n baseDir?: string;\n fonts?: RasterizeFontFace[];\n }>(c, 'json');\n const safeBaseDir = resolveSafeBaseDir(baseDir);\n const effectiveSlides = slides.map((slide) => ({\n presentation: slide.presentation,\n dpi: clampVisualDpi(slide.dpi ?? DEFAULT_VISUAL_DPI),\n }));\n assertPixelBudget(effectiveSlides);\n assertFontBudget(fonts);\n\n const result = await guard(async () => {\n if (options.sourcePolicy) {\n // Scoped to each slide's `presentation` only — see /rasterize.\n slides.forEach((slide, index) =>\n assertSafeOutboundSources(\n slide.presentation,\n options.sourcePolicy!,\n `slides[${index}].presentation`\n )\n );\n }\n return getBatchRasterizer()({\n slides: effectiveSlides,\n baseDir: safeBaseDir,\n ...(fonts?.length && { fonts }),\n });\n });\n\n // Per-slide errors from `build` are caused by the slide's own JSON and\n // are the caller's actionable feedback; `convert`/`rasterize` failures\n // carry raw tool output (host paths, temp dirs), which the single route\n // never exposes — log them, return a generic message (C2 parity with\n // /rasterize's 500 mapping).\n return c.json({\n results: result.results.map((slide) => {\n if (slide.ok) return slide;\n options.onError?.(new Error(slide.error));\n return slide.stage === 'build'\n ? { ok: false as const, error: slide.error, stage: slide.stage }\n : {\n ok: false as const,\n error: 'Slide rasterization failed',\n stage: slide.stage,\n };\n }),\n });\n }\n );\n}\n","import { promises as fs } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Inline relative media references of a server-discovered document as data\n * URLs, so bundled templates survive safe-mode outbound-source validation and\n * remote rasterization (which runs on a host without the template's files).\n *\n * Only relative paths that canonicalize inside `baseDir` are inlined; anything\n * else (absolute paths, URLs, data URLs, `..` escapes, missing or oversized\n * files) is left untouched for the outbound-source policy to judge.\n */\n\nconst MIME_BY_EXTENSION: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.bmp': 'image/bmp',\n '.tiff': 'image/tiff',\n '.tif': 'image/tiff',\n};\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is JsonRecord {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isInlineCandidate(source: string): boolean {\n if (!source || source.includes('\\0')) return false;\n if (source.startsWith('data:')) return false;\n if (path.isAbsolute(source)) return false;\n try {\n new URL(source);\n return false; // absolute URL — policy handles it\n } catch {\n return true;\n }\n}\n\nexport interface InlineTemplateMediaOptions {\n /** Per-file size cap in bytes; larger files are left as-is. */\n maxFileBytes?: number;\n /** Total inlined bytes cap; once exceeded, remaining files are left as-is. */\n maxTotalBytes?: number;\n}\n\ninterface InlineState {\n baseDirReal: string;\n maxFileBytes: number;\n totalBudget: number;\n cache: Map<string, string | null>;\n}\n\nasync function toDataUrl(\n source: string,\n baseDir: string,\n state: InlineState\n): Promise<string | null> {\n // Key the cache by canonical path so equivalent spellings of the same file\n // (`media/logo.png` vs `media/./logo.png`) share one budget charge.\n let cacheKey = source;\n let result: string | null = null;\n try {\n const resolved = await fs.realpath(path.resolve(baseDir, source));\n cacheKey = resolved;\n const cached = state.cache.get(cacheKey);\n if (cached !== undefined) return cached;\n const contained =\n resolved === state.baseDirReal ||\n resolved.startsWith(state.baseDirReal + path.sep);\n if (contained) {\n const mime = MIME_BY_EXTENSION[path.extname(resolved).toLowerCase()];\n if (mime) {\n const stat = await fs.stat(resolved);\n if (\n stat.isFile() &&\n stat.size <= state.maxFileBytes &&\n stat.size <= state.totalBudget\n ) {\n const buffer = await fs.readFile(resolved);\n state.totalBudget -= buffer.length;\n result = `data:${mime};base64,${buffer.toString('base64')}`;\n }\n }\n }\n } catch {\n // Missing or unreadable file: leave the reference for the policy layer,\n // whose error message names the offending JSON path.\n }\n state.cache.set(cacheKey, result);\n return result;\n}\n\nasync function visit(\n value: unknown,\n containerKey: string | undefined,\n baseDir: string,\n state: InlineState,\n seen: WeakSet<object>\n): Promise<void> {\n if (!value || typeof value !== 'object' || seen.has(value)) return;\n seen.add(value);\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n await visit(entry, containerKey, baseDir, state, seen);\n }\n return;\n }\n\n const record = value as JsonRecord;\n\n // Image components: { name: 'image', props: { path } }.\n const componentName =\n typeof record.name === 'string' ? record.name.toLowerCase() : undefined;\n const props = isRecord(record.props) ? record.props : undefined;\n if (\n componentName === 'image' &&\n props &&\n typeof props.path === 'string' &&\n isInlineCandidate(props.path)\n ) {\n const inlined = await toDataUrl(props.path, baseDir, state);\n if (inlined !== null) props.path = inlined;\n }\n\n // Canvas/slide backgrounds: plain { image: { path } } objects.\n if (\n containerKey === 'image' &&\n typeof record.path === 'string' &&\n isInlineCandidate(record.path)\n ) {\n const inlined = await toDataUrl(record.path, baseDir, state);\n if (inlined !== null) record.path = inlined;\n }\n\n for (const [key, child] of Object.entries(record)) {\n await visit(child, key, baseDir, state, seen);\n }\n}\n\nexport async function inlineTemplateMedia(\n jsonDefinition: unknown,\n baseDir: string,\n options: InlineTemplateMediaOptions = {}\n): Promise<unknown> {\n // The generation schema also accepts a JSON string definition; parse it so\n // its media inlines too (the generator accepts either form downstream).\n if (typeof jsonDefinition === 'string') {\n try {\n jsonDefinition = JSON.parse(jsonDefinition);\n } catch {\n // Structural validation owns malformed JSON reporting.\n return jsonDefinition;\n }\n }\n if (!jsonDefinition || typeof jsonDefinition !== 'object') {\n return jsonDefinition;\n }\n\n let baseDirReal: string;\n try {\n baseDirReal = await fs.realpath(baseDir);\n } catch {\n return jsonDefinition;\n }\n\n const clone = structuredClone(jsonDefinition);\n const state: InlineState = {\n baseDirReal,\n maxFileBytes: options.maxFileBytes ?? 10 * 1024 * 1024,\n totalBudget: options.maxTotalBytes ?? 32 * 1024 * 1024,\n cache: new Map(),\n };\n await visit(clone, undefined, baseDir, state, new WeakSet());\n return clone;\n}\n","import { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport { bodyLimit } from 'hono/body-limit';\nimport { getContainer } from '../container/index.js';\nimport {\n LooseDocumentGenerationRequestSchema,\n LooseDocumentValidationRequestSchema,\n LooseDocumentDiffRequestSchema,\n} from '../schemas/loose.js';\nimport { tbValidator, getValidated } from '../lib/typebox-validator.js';\nimport { logger } from '../utils/logger.js';\nimport { rateLimiter } from '../middleware/hono/rate-limit.js';\nimport { AppEnv } from '../types/hono.js';\nimport {\n type FormatAdapter,\n type GeneratorOptions,\n PluginRegistry,\n PluginDiscoveryService,\n} from '@json-to-office/jto-cli';\nimport { dirname } from 'node:path';\nimport { registerRasterizeRoute } from '../rasterize-route.js';\nimport { config } from '../config/index.js';\nimport {\n assertSafeOutboundSources,\n UnsafeOutboundSourceError,\n} from '../security/outbound-source-policy.js';\nimport {\n LibreOfficeBinaryNotFoundError,\n LibreOfficeConversionError,\n LibreOfficeOutputNotFoundError,\n LibreOfficeTimeoutError,\n} from '../services/libreoffice-converter.js';\nimport { inlineTemplateMedia } from '../services/template-media-inliner.js';\n\n/**\n * Re-throw as a 400 when the failure is the document's fault, not the server's.\n *\n * Two kinds qualify. A backend refusing a feature, or the compiler meeting a\n * component it does not lower, both carry a code and a message naming what was\n * missing and where — matched on the code rather than the text, because these\n * cross a dynamic-import boundary where `instanceof` is unreliable and because\n * the wording is not an API. Everything else is matched on the message, which\n * is older and less precise but covers validation failures that predate codes.\n *\n * Returns normally when the error is not a client error, leaving the caller to\n * decide what its own 500 says.\n */\nfunction throwIfClientError(error: unknown): void {\n const code = (error as { code?: unknown } | undefined)?.code;\n if (code === 'QUALITY_GATE_FAILED') {\n throw new HTTPException(400, {\n message: (error as Error).message,\n cause: error,\n });\n }\n if (\n code === 'QUALITY_PROFILE_INCOMPATIBLE' ||\n // A gate or severity the policy parser cannot read came in on the\n // request, so the request is what is at fault.\n code === 'QUALITY_POLICY_INVALID'\n ) {\n throw new HTTPException(400, { message: (error as Error).message });\n }\n if (\n code === 'UNSUPPORTED_RENDERER_FEATURE' ||\n code === 'UNCOMPILED_COMPONENT' ||\n // An id nobody registered is the caller naming a backend that does not\n // exist. The message already lists the ones that do.\n code === 'UNKNOWN_RENDERER'\n ) {\n throw new HTTPException(400, { message: (error as Error).message });\n }\n if (!(error instanceof Error)) return;\n const message = error.message.toLowerCase();\n if (\n message.includes('invalid') ||\n message.includes('validation') ||\n message.includes('missing required') ||\n message.includes('unknown component')\n ) {\n throw new HTTPException(400, { message: error.message });\n }\n}\n\nexport function createFormatRouter(adapter: FormatAdapter) {\n const router = new Hono<AppEnv>();\n const assertRequestSources = (value: unknown, path: string) => {\n try {\n assertSafeOutboundSources(value, config.outboundSources, path);\n } catch (error) {\n if (error instanceof UnsafeOutboundSourceError) {\n throw new HTTPException(400, { message: error.message });\n }\n throw error;\n }\n };\n\n // Map a discovered-document name to its directory so relative asset paths\n // resolve against the document's own location (#142). Only names are\n // accepted from clients; unknown names fall back to cwd-relative resolution.\n const resolveSourceBaseDir = async (\n options: unknown\n ): Promise<string | undefined> => {\n const sourceName = (options as { sourceName?: unknown } | undefined)\n ?.sourceName;\n if (typeof sourceName !== 'string' || sourceName.length === 0) {\n return undefined;\n }\n try {\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const documents = await discovery.discoverDocuments(\n adapter.name as 'docx' | 'pptx'\n );\n const match = documents.find((doc) => doc.name === sourceName);\n return match ? dirname(match.path) : undefined;\n } catch {\n // Discovery is best-effort here; generation proceeds cwd-relative.\n return undefined;\n }\n };\n\n // In safe mode, relative media of a server-discovered document is inlined\n // as data URLs so bundled templates pass source validation and survive the\n // trip to the remote rasterizer. Development mode keeps filesystem\n // resolution (and the path-keyed visual cache) untouched.\n const inlineDiscoveredMedia = async (\n jsonDefinition: unknown,\n baseDir: string | undefined\n ): Promise<unknown> => {\n if (\n baseDir === undefined ||\n config.outboundSources.mode === 'development'\n ) {\n return jsonDefinition;\n }\n return inlineTemplateMedia(jsonDefinition, baseDir, {\n maxFileBytes: config.requestLimits.maxFileSize,\n maxTotalBytes: config.requestLimits.maxBodySize,\n });\n };\n\n const contentTypeMw = async (c: any, next: () => Promise<void>) => {\n const contentType = c.req.header('content-type');\n if (!contentType || !contentType.includes('application/json')) {\n throw new HTTPException(400, {\n message: 'Content-Type must be application/json',\n });\n }\n await next();\n };\n\n // POST /generate\n router.post(\n '/generate',\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 10 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n contentTypeMw,\n tbValidator(LooseDocumentGenerationRequestSchema),\n async (c) => {\n const generatorService = getContainer().get('generatorService');\n const { jsonDefinition, customThemes, options } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: { bypassCache?: boolean; returnUrl?: boolean };\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n try {\n // Resolve the trusted sourceName -> baseDir mapping first so bundled\n // template media can be inlined as data URLs before safe-mode source\n // validation (which rejects relative paths from HTTP clients).\n const baseDir = await resolveSourceBaseDir(options);\n const effectiveDefinition = await inlineDiscoveredMedia(\n jsonDefinition,\n baseDir\n );\n\n assertRequestSources(effectiveDefinition, 'jsonDefinition');\n assertRequestSources(customThemes, 'customThemes');\n assertRequestSources(options, 'options');\n\n const bypassCache =\n c.req.header('X-Bypass-Cache') === 'true' ||\n c.req.query('bypass-cache') === 'true' ||\n options?.bypassCache === true;\n\n // Drop `fonts.strict` from untrusted client input: a toggle that\n // throws on unresolved refs is only meaningful for programmatic\n // callers. Honouring it from an HTTP client would turn any\n // non-safe font reference into a predictable 500 — DoS-adjacent\n // and no useful UX behind it. Advisory only. Build a fresh\n // object rather than mutating the validated request payload.\n let sanitizedFonts: Record<string, unknown> | undefined;\n const rawFonts = (\n options as { fonts?: Record<string, unknown> } | undefined\n )?.fonts;\n if (rawFonts && 'strict' in rawFonts) {\n sanitizedFonts = { ...rawFonts };\n delete sanitizedFonts.strict;\n } else if (rawFonts) {\n sanitizedFonts = rawFonts;\n }\n\n // `baseDir` selects the directory local media paths resolve against —\n // never accept it from the HTTP client. Only the server-side\n // sourceName mapping above may set it.\n const clientOptions = { ...(options as Record<string, unknown>) };\n delete clientOptions.baseDir;\n delete clientOptions.prepared;\n\n const result = await generatorService.generate({\n jsonDefinition: effectiveDefinition,\n customThemes,\n options: {\n ...clientOptions,\n ...(sanitizedFonts !== undefined && { fonts: sanitizedFonts }),\n ...(baseDir !== undefined && { baseDir }),\n bypassCache,\n },\n });\n\n const cacheService = getContainer().get('cacheService');\n const cacheStats = cacheService.getStats();\n\n const contentType =\n adapter.name === 'pptx'\n ? 'application/vnd.openxmlformats-officedocument.presentationml.presentation'\n : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';\n\n return c.json({\n success: true,\n data: {\n document: result.buffer.toString('base64'),\n filename: result.filename,\n fileId: result.fileId || null,\n contentType,\n },\n cache: {\n status: result.cached ? 'HIT' : 'MISS',\n hitRate: `${(cacheStats.hitRate * 100).toFixed(1)}%`,\n },\n warnings: result.warnings || [],\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n logger.error(`${adapter.label} generation failed`, {\n error,\n requestId,\n });\n\n throwIfClientError(error);\n if (error instanceof HTTPException) throw error;\n throw new HTTPException(500, {\n message: `Internal server error during ${adapter.label} generation`,\n });\n }\n }\n );\n\n // POST /validate\n router.post(\n '/validate',\n contentTypeMw,\n tbValidator(LooseDocumentValidationRequestSchema),\n async (c) => {\n const generatorService = getContainer().get('generatorService');\n const { jsonDefinition, options } = getValidated<{\n jsonDefinition: any;\n options?: GeneratorOptions;\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n try {\n const result = await generatorService.validate(jsonDefinition, options);\n return c.json({\n success: result.valid,\n data: result,\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n logger.error('Validation failed', { error, requestId });\n throwIfClientError(error);\n throw error;\n }\n }\n );\n\n // POST /diff (DOCX only)\n //\n // Compare two document definitions into a tracked-change redline: returns\n // the renderable redline JSON plus a summary. The client previews and\n // downloads the redline through the normal generate/preview pipeline.\n if (adapter.name === 'docx') {\n router.post(\n '/diff',\n bodyLimit({\n // Two full documents per request — same cap rationale as\n // /preview/libreoffice-from-json, doubled.\n maxSize: 32 * 1024 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 30 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n contentTypeMw,\n tbValidator(LooseDocumentDiffRequestSchema),\n async (c) => {\n const { oldDefinition, newDefinition, options } = getValidated<{\n oldDefinition: string | object;\n newDefinition: string | object;\n options?: { author?: string; date?: string };\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n const parseDef = (label: string, def: string | object): object => {\n if (typeof def !== 'string') return def;\n try {\n return JSON.parse(def);\n } catch {\n throw new HTTPException(400, {\n message: `${label} document is not valid JSON`,\n });\n }\n };\n\n try {\n const oldDoc = parseDef('Old', oldDefinition);\n const newDoc = parseDef('New', newDefinition);\n\n // Use the canonical shared-docx validator (same as the CLI).\n const sharedDocx = await import('@json-to-office/shared-docx');\n for (const [label, doc] of [\n ['Old', oldDoc],\n ['New', newDoc],\n ] as const) {\n const result = sharedDocx.validate.jsonDocument(\n JSON.stringify(doc)\n );\n if (!result.valid) {\n return c.json(\n {\n success: false,\n error: `${label} document failed validation`,\n errors: (result.errors || []).slice(0, 20),\n meta: { timestamp: new Date().toISOString(), requestId },\n },\n 400\n );\n }\n }\n\n // Validate and canonicalize the revision date (invalid values\n // would fail RevisionSchema and OOXML ST_DateTime downstream)\n const revisionDate = options?.date\n ? new Date(options.date)\n : new Date();\n if (isNaN(revisionDate.getTime())) {\n throw new HTTPException(400, {\n message: `Invalid date: \"${options?.date}\" (expected ISO 8601)`,\n });\n }\n\n const { diffDocuments } = sharedDocx;\n const { document, summary } = diffDocuments(\n oldDoc as Parameters<typeof diffDocuments>[0],\n newDoc as Parameters<typeof diffDocuments>[1],\n {\n author: options?.author || 'playground',\n date: revisionDate.toISOString(),\n }\n );\n\n return c.json({\n success: true,\n data: { document, summary },\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n if (error instanceof HTTPException) throw error;\n logger.error('Document diff failed', { error, requestId });\n if (\n error instanceof Error &&\n error.message.includes('top-level component')\n ) {\n throw new HTTPException(400, { message: error.message });\n }\n throw new HTTPException(500, {\n message: 'Internal server error during document diff',\n });\n }\n }\n );\n }\n\n // POST /preview/libreoffice\n router.post(\n '/preview/libreoffice',\n bodyLimit({\n // Multipart framing adds a small amount around the configured file cap.\n maxSize: config.requestLimits.maxFileSize + 64 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n async (c) => {\n const requestId = c.get('requestId');\n const libreOfficeService = getContainer().get(\n 'libreOfficeConverterService'\n );\n\n try {\n const body = await c.req.parseBody();\n const file = body.file;\n\n if (!file || typeof file === 'string') {\n throw new HTTPException(400, {\n message: `No ${adapter.name.toUpperCase()} file provided`,\n });\n }\n if ((file as File).size === 0) {\n throw new HTTPException(400, {\n message: `${adapter.name.toUpperCase()} file is empty`,\n });\n }\n if ((file as File).size > config.requestLimits.maxFileSize) {\n throw new HTTPException(413, {\n message: `File exceeds ${config.requestLimits.maxFileSize} bytes`,\n });\n }\n\n const expectedExtension = `.${adapter.name}`;\n const originalName =\n (file as File).name || `preview${expectedExtension}`;\n if (!originalName.toLowerCase().endsWith(expectedExtension)) {\n throw new HTTPException(400, {\n message: `Expected a ${adapter.name.toUpperCase()} file`,\n });\n }\n\n const arrayBuffer = await (file as File).arrayBuffer();\n const inputBuffer = Buffer.from(arrayBuffer);\n if (\n inputBuffer.length < 4 ||\n inputBuffer[0] !== 0x50 ||\n inputBuffer[1] !== 0x4b\n ) {\n throw new HTTPException(400, {\n message: `Invalid ${adapter.name.toUpperCase()} file`,\n });\n }\n const pdfBuffer = await libreOfficeService.convertToPdf(\n inputBuffer,\n originalName\n );\n\n const pdfName =\n originalName\n .replace(/\\.[^.]+$/i, '')\n .replace(/[^a-zA-Z0-9._-]/g, '_') + '.pdf';\n c.header('Content-Type', 'application/pdf');\n c.header('Content-Disposition', `inline; filename=\"${pdfName}\"`);\n c.header('Content-Length', String(pdfBuffer.length));\n\n return c.body(pdfBuffer);\n } catch (error) {\n logger.error('LibreOffice preview conversion failed', {\n error,\n requestId,\n });\n if (error instanceof HTTPException) throw error;\n if (error instanceof LibreOfficeBinaryNotFoundError) {\n throw new HTTPException(503, {\n message:\n 'LibreOffice is not available. Install LibreOffice or set LIBREOFFICE_PATH.',\n });\n }\n if (\n error instanceof LibreOfficeTimeoutError ||\n error instanceof LibreOfficeConversionError ||\n error instanceof LibreOfficeOutputNotFoundError\n ) {\n throw new HTTPException(500, {\n message: 'LibreOffice preview conversion failed.',\n });\n }\n throw new HTTPException(500, {\n message: 'Internal server error during preview conversion',\n });\n }\n }\n );\n\n // POST /preview/libreoffice-from-json\n //\n // Generate the document server-side and convert to PDF in one step so\n // resolved fonts flow straight into the LibreOffice font-staging pipeline.\n // The client sends the JSON doc instead of re-uploading the generated file.\n router.post(\n '/preview/libreoffice-from-json',\n bodyLimit({\n // Doc JSON + custom themes. 16 MB accommodates real-world docs that\n // inline base64 image assets (logos, screenshots, chart images); the\n // earlier 2 MB cap rejected legitimate payloads with 413.\n maxSize: 16 * 1024 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n contentTypeMw,\n tbValidator(LooseDocumentGenerationRequestSchema),\n async (c) => {\n const requestId = c.get('requestId');\n const generatorService = getContainer().get('generatorService');\n const libreOfficeService = getContainer().get(\n 'libreOfficeConverterService'\n );\n const { jsonDefinition, customThemes, options } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: { sourceName?: string; renderer?: string };\n }>(c, 'json');\n\n try {\n // Same server-side sourceName -> baseDir mapping as /generate, so\n // previews resolve relative asset paths the way downloads do (#142).\n const baseDir = await resolveSourceBaseDir(options);\n const effectiveDefinition = await inlineDiscoveredMedia(\n jsonDefinition,\n baseDir\n );\n\n assertRequestSources(effectiveDefinition, 'jsonDefinition');\n assertRequestSources(customThemes, 'customThemes');\n assertRequestSources(options, 'options');\n\n const generated = await generatorService.generate({\n jsonDefinition: effectiveDefinition,\n customThemes,\n options: {\n bypassCache: true,\n ...(baseDir !== undefined && { baseDir }),\n // The preview has to come from the backend the caller picked.\n // Regenerating with the default made the picker lie: the PDF on\n // screen and the bytes on download came from different renderers,\n // and a capability refusal was invisible until you downloaded\n // (#255).\n ...(options?.renderer !== undefined && {\n renderer: options.renderer,\n }),\n },\n });\n\n const pdfBuffer = await libreOfficeService.convertToPdf(\n generated.buffer,\n generated.filename,\n generated.resolvedFonts\n );\n\n const pdfName = generated.filename.replace(/\\.[^.]+$/i, '') + '.pdf';\n c.header('Content-Type', 'application/pdf');\n c.header('Content-Disposition', `inline; filename=\"${pdfName}\"`);\n c.header('Content-Length', String(pdfBuffer.length));\n return c.body(pdfBuffer);\n } catch (error) {\n logger.error('LibreOffice (JSON) preview failed', {\n error,\n requestId,\n });\n if (error instanceof HTTPException) throw error;\n // Generation runs inside this route now, so the same document faults\n // the download reports — an unknown backend, a feature it cannot\n // express — have to reach the previewer with the same status.\n throwIfClientError(error);\n if (error instanceof LibreOfficeBinaryNotFoundError) {\n throw new HTTPException(503, {\n message:\n 'LibreOffice is not available. Install LibreOffice or set LIBREOFFICE_PATH.',\n });\n }\n if (\n error instanceof LibreOfficeTimeoutError ||\n error instanceof LibreOfficeConversionError ||\n error instanceof LibreOfficeOutputNotFoundError\n ) {\n throw new HTTPException(500, {\n message: 'LibreOffice preview conversion failed.',\n });\n }\n throw new HTTPException(500, {\n message: 'Internal server error during preview conversion',\n });\n }\n }\n );\n\n // POST /standard-components\n router.post(\n '/standard-components',\n contentTypeMw,\n tbValidator(LooseDocumentGenerationRequestSchema),\n async (c) => {\n const { jsonDefinition, customThemes, options } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n options?: { sourceName?: string };\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n try {\n // Same prologue as /generate: inline a discovered document's bundled\n // media before safe-mode source validation, otherwise templates that\n // reference relative media paths 400 here while rendering fine there.\n const baseDir = await resolveSourceBaseDir(options);\n const effectiveDefinition = await inlineDiscoveredMedia(\n jsonDefinition,\n baseDir\n );\n\n assertRequestSources(effectiveDefinition, 'jsonDefinition');\n assertRequestSources(customThemes, 'customThemes');\n\n let config: unknown;\n try {\n config =\n typeof effectiveDefinition === 'string'\n ? JSON.parse(effectiveDefinition)\n : effectiveDefinition;\n } catch {\n throw new HTTPException(400, {\n message: 'jsonDefinition is not valid JSON',\n });\n }\n\n // If plugins are loaded, use plugin-aware generator to resolve custom components\n const registry = PluginRegistry.getInstance();\n if (registry.hasPlugins()) {\n const plugins = registry.getPlugins();\n const generatorResult = await adapter.createGenerator(plugins, {\n customThemes,\n baseDir,\n });\n\n // Expansion-only path: resolves custom components to the standard\n // tree without fonts/layout/rendering (#155) — the old deprecated\n // wrapper ran a full generation, LibreOffice rasterization included.\n if (generatorResult.getStandardDefinition) {\n const standardComponents =\n await generatorResult.getStandardDefinition(config);\n return c.json({\n success: true,\n data: standardComponents,\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n }\n }\n\n // No plugins — config is already standard components\n return c.json({\n success: true,\n data: config,\n meta: { timestamp: new Date().toISOString(), requestId },\n });\n } catch (error) {\n logger.error('Failed to get standard components definition', {\n error,\n requestId,\n });\n if (error instanceof HTTPException) throw error;\n throwIfClientError(error);\n throw new HTTPException(500, {\n message: 'Failed to get standard components definition',\n });\n }\n }\n );\n\n // GET /renderers — the backends this format registers, defaults first.\n router.get('/renderers', async (c) => {\n try {\n const ids = await adapter.rendererIds();\n return c.json({\n success: true,\n data: { ids, default: ids[0] ?? null },\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to list renderers', { error });\n throw new HTTPException(500, { message: 'Failed to list renderers' });\n }\n });\n\n // GET /cache-stats\n router.get('/cache-stats', async (c) => {\n try {\n const cacheService = getContainer().get('cacheService');\n const stats = cacheService.getStats();\n // Rasterizer cache observability (#156): the disk cache and the batch\n // dedupe are where `visual` caching lives. There is no component render\n // cache to report any more — compiling a document to an IR is cheap and\n // holds no cross-document state.\n const rasterizer = await (async () => {\n try {\n const cli = await import('@json-to-office/jto-cli');\n const engine = await cli.getRasterizerCacheStats?.();\n if (!engine) return null;\n const prepass = (await adapter.getVisualPrepassStats?.()) ?? null;\n return { ...engine, ...(prepass ? { prepass } : {}) };\n } catch {\n return null;\n }\n })();\n return c.json({\n success: true,\n data: {\n document: {\n hits: stats.hits,\n misses: stats.misses,\n hitRate: stats.hitRate,\n size: stats.size,\n itemCount: stats.itemCount,\n enabled: stats.enabled,\n },\n ...(rasterizer ? { rasterizer } : {}),\n },\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to get cache statistics', { error });\n throw new HTTPException(500, {\n message: 'Failed to get cache statistics',\n });\n }\n });\n\n // DELETE /cache\n router.delete('/cache', async (c) => {\n try {\n const cacheService = getContainer().get('cacheService');\n cacheService.clear();\n const cli = await import('@json-to-office/jto-cli');\n cli.invalidateAllCaches();\n // \"Clear all caches\" means all of them: the rasterizer's PNG disk cache\n // used to survive this call (#156).\n await adapter.resetCacheStats?.();\n await cli.clearRasterizerCache?.();\n return c.json({\n success: true,\n data: { message: 'Cache cleared successfully' },\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to clear cache', { error });\n throw new HTTPException(500, { message: 'Failed to clear cache' });\n }\n });\n\n // POST /rasterize — render a single-slide pptx presentation to a PNG.\n // Backs the docx `visual` component when it is configured with\n // `services.pptx.serverUrl`. Shares the validated handler + limits with the\n // standalone jto-render-server (see rasterize-route.ts).\n registerRasterizeRoute(router, {\n preMiddleware: [\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 10 : 1000,\n window: 15 * 60 * 1000,\n // One bucket for /rasterize AND /rasterize/batch — without a shared\n // namespace the default per-path key would double the budget.\n namespace: 'rasterize',\n trustProxy: config.rateLimit.trustProxy,\n }),\n ],\n sourcePolicy: config.outboundSources,\n onError: (error) => logger.error('Visual rasterization failed', { error }),\n });\n\n return router;\n}\n","import { Hono } from 'hono';\nimport {\n PluginDiscoveryService,\n PluginRegistry,\n} from '@json-to-office/jto-cli';\nimport { latestVersion } from '@json-to-office/shared';\nimport { logger } from '../utils/logger.js';\nimport { AppEnv } from '../types/hono.js';\nimport { Container } from '../container/index.js';\n\nexport const discoveryRouter = new Hono<AppEnv>();\n\n// ---------------------------------------------------------------------------\n// Schema generation helpers (mirrors client-side json-schema-generator.ts)\n// ---------------------------------------------------------------------------\n\nfunction cleanupTypeBoxIds(schema: any): void {\n if (typeof schema !== 'object' || schema === null) return;\n if (schema.$id && /^T\\d+$/.test(schema.$id)) delete schema.$id;\n if (schema.$ref && /^T\\d+$/.test(schema.$ref))\n schema.$ref = '#/definitions/ComponentDefinition';\n if (Array.isArray(schema)) {\n schema.forEach(cleanupTypeBoxIds);\n return;\n }\n Object.keys(schema).forEach((key) => {\n if (typeof schema[key] === 'object' && schema[key] !== null)\n cleanupTypeBoxIds(schema[key]);\n });\n}\n\n/**\n * Schema generation must not depend on the client having POSTed\n * `/load-plugins` first. The playground fires that bootstrap POST and the\n * first schema fetch in parallel on page load; when the schema request won\n * the race (or the POST failed), the registry was empty, the requested\n * plugins were silently dropped, and Monaco kept a plugin-less schema —\n * enabled components neither completed nor validated until a toggle forced a\n * refetch. Requests that need plugins now load them on demand; the registry\n * coalesces concurrent loads and its load fingerprint makes repeats a no-op.\n *\n * Dev-playground affordance only: in production, plugin loading stays behind\n * the authenticated POST /load-plugins (same policy check as that route), so\n * an unauthenticated schema request cannot trigger discovery — generation\n * falls back to whatever is already registered.\n */\nasync function ensurePluginsRegistered(\n format: 'docx' | 'pptx',\n pluginNames?: string[]\n): Promise<void> {\n if (process.env.NODE_ENV === 'production') return;\n\n const registry = PluginRegistry.getInstance();\n const satisfied = pluginNames\n ? pluginNames.every((name) => registry.getPlugin(name))\n : registry.hasPlugins();\n if (satisfied) return;\n\n registry.setFormat(format);\n try {\n await registry.discoverAndLoad();\n } catch (error: any) {\n // Schema generation falls back to standard components only.\n logger.warn('On-demand plugin load for schema generation failed', {\n error: error?.message,\n });\n }\n}\n\nfunction getSelectedPlugins(pluginNames?: string[]) {\n const registry = PluginRegistry.getInstance();\n if (!registry.hasPlugins()) return [];\n\n // An explicit array is an exact selection — [] means \"no plugins\", so a\n // playground with every plugin toggled off gets the plugin-free schema.\n // Only an absent selection falls back to every registered plugin.\n const plugins = pluginNames\n ? pluginNames.map((n) => registry.getPlugin(n)).filter(Boolean)\n : registry.getPlugins();\n\n return plugins.map((plugin) => {\n const versions = (plugin as any).versions || {};\n const versionKeys = Object.keys(versions);\n const latest =\n versionKeys.length > 0 ? latestVersion(versionKeys) : undefined;\n const latestEntry = latest ? versions[latest] : undefined;\n\n return { name: plugin!.name, versions, versionKeys, latest, latestEntry };\n });\n}\n\nasync function generateDocumentSchema(\n format: string,\n pluginNames?: string[]\n): Promise<any> {\n await ensurePluginsRegistered(format as 'docx' | 'pptx', pluginNames);\n const selected = getSelectedPlugins(pluginNames);\n\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n const customComponents = selected\n .filter((p) => p.latestEntry?.propsSchema)\n .map((p) => {\n const info: any = {\n name: p.name,\n propsSchema: p.latestEntry!.propsSchema,\n hasChildren: p.latestEntry?.hasChildren,\n description: p.latestEntry?.description,\n };\n if (p.versionKeys.length > 1) {\n info.versionedProps = p.versionKeys.map((v) => ({\n version: v,\n propsSchema: p.versions[v].propsSchema,\n description: p.versions[v].description,\n hasChildren: p.versions[v].hasChildren,\n }));\n }\n return info;\n });\n const unified = shared.generateUnifiedDocumentSchema({ customComponents });\n return shared.convertToJsonSchema(unified, {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://json-to-office.dev/schema/document/v1.0.0',\n title: 'JSON to DOCX Document Definition',\n description: 'Schema for JSON to DOCX JSON document definitions',\n });\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n const customComponents = selected.map((p) => ({\n name: p.name,\n versions: p.versionKeys.map((v) => ({\n version: v,\n propsSchema: p.versions[v].propsSchema,\n hasChildren: p.versions[v].hasChildren,\n description: p.versions[v].description,\n })),\n }));\n const unified = shared.generateUnifiedDocumentSchema({ customComponents });\n return shared.convertToJsonSchema(unified, {\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://json-to-office.dev/schema/presentation/v1.0.0',\n title: 'JSON to PPTX Presentation Definition',\n description: 'Schema for JSON to PPTX JSON presentation definitions',\n });\n }\n}\n\nasync function generateThemeSchema(format: string): Promise<any> {\n let source: any;\n let label: string;\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n source = shared.ThemeConfigSchema;\n label = 'DOCX';\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n source = shared.ThemeConfigSchema;\n label = 'PPTX';\n }\n const schema = JSON.parse(JSON.stringify(source));\n cleanupTypeBoxIds(schema);\n return {\n ...schema,\n $schema: 'http://json-schema.org/draft-07/schema#',\n $id: 'https://json-to-office.dev/schemas/theme/v1.0.0',\n title: `JSON to ${label} Theme`,\n description: `Theme definition for JSON to ${label} ${format === 'docx' ? 'documents' : 'presentations'}`,\n };\n}\n\ndiscoveryRouter.get('/all', async (c) => {\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const [plugins, documents, themes] = await Promise.all([\n discovery.discoverPlugins(format),\n discovery.discoverDocuments(format),\n discovery.discoverThemes(format),\n ]);\n const results = { plugins, documents, themes };\n return c.json({\n success: true,\n data: results,\n counts: {\n plugins: results.plugins.length,\n documents: results.documents.length,\n themes: results.themes.length,\n },\n });\n } catch (error: any) {\n logger.error('Discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/plugins', async (c) => {\n try {\n const includeSchemas = c.req.query('schemas') === 'true';\n const includeExamples = c.req.query('examples') === 'true';\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const plugins = await discovery.discoverPlugins(format);\n const processed = plugins.map((plugin) => {\n const result: any = { ...plugin };\n if (!includeSchemas && result.schema) {\n delete result.schema.raw;\n delete result.schema.jsonSchema;\n }\n if (!includeExamples) delete result.examples;\n return result;\n });\n return c.json({ success: true, data: processed, count: plugins.length });\n } catch (error: any) {\n logger.error('Plugin discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/documents', async (c) => {\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const documents = await discovery.discoverDocuments(format);\n return c.json({ success: true, data: documents, count: documents.length });\n } catch (error: any) {\n logger.error('Document discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/themes', async (c) => {\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const themes = await discovery.discoverThemes(format);\n return c.json({ success: true, data: themes, count: themes.length });\n } catch (error: any) {\n logger.error('Theme discovery failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/plugin/:name', async (c) => {\n try {\n const pluginName = c.req.param('name');\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const plugins = await discovery.discoverPlugins(format);\n const plugin = plugins.find((p) => p.name === pluginName);\n if (!plugin)\n return c.json(\n { success: false, error: `Plugin '${pluginName}' not found` },\n 404\n );\n return c.json({ success: true, data: plugin });\n } catch (error: any) {\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.post('/load-plugins', async (c) => {\n // Require API key for plugin loading regardless of global auth setting\n const apiKey = c.req.header('X-API-Key') || c.req.header('Authorization');\n if (!apiKey && process.env.NODE_ENV === 'production') {\n return c.json({ success: false, error: 'Authentication required' }, 401);\n }\n\n try {\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const registry = PluginRegistry.getInstance();\n registry.setFormat(format);\n const result = await registry.discoverAndLoad();\n return c.json({ success: true, data: result });\n } catch (error: any) {\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/documents/:name/content', async (c) => {\n try {\n const name = c.req.param('name');\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const content = await discovery.getDocumentContent(name, format);\n return c.text(content);\n } catch (error: any) {\n const status = error.message.includes('not found') ? 404 : 500;\n return c.json({ success: false, error: error.message }, status);\n }\n});\n\ndiscoveryRouter.get('/themes/:name/content', async (c) => {\n try {\n const name = c.req.param('name');\n const format = Container.getAdapter().name as 'docx' | 'pptx';\n const discovery = new PluginDiscoveryService({\n maxDepth: 10,\n includeNodeModules: false,\n verbose: false,\n });\n const content = await discovery.getThemeContent(name, format);\n return c.text(content);\n } catch (error: any) {\n const status = error.message.includes('not found') ? 404 : 500;\n return c.json({ success: false, error: error.message }, status);\n }\n});\n\ndiscoveryRouter.get('/schemas/document', async (c) => {\n try {\n const adapter = Container.getAdapter();\n const pluginsParam = c.req.query('plugins');\n // `?plugins=` (empty) is an explicit \"no plugins\"; only a missing param\n // means \"all registered plugins\".\n const pluginNames =\n pluginsParam !== undefined\n ? pluginsParam.split(',').filter(Boolean)\n : undefined;\n const schema = await generateDocumentSchema(adapter.name, pluginNames);\n return c.json({ success: true, data: schema });\n } catch (error: any) {\n logger.error('Document schema generation failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n\ndiscoveryRouter.get('/schemas/theme', async (c) => {\n try {\n const adapter = Container.getAdapter();\n const schema = await generateThemeSchema(adapter.name);\n return c.json({ success: true, data: schema });\n } catch (error: any) {\n logger.error('Theme schema generation failed', { error: error.message });\n return c.json({ success: false, error: error.message }, 500);\n }\n});\n","/**\n * Builds and caches the full JSON schema per format for AI structured output.\n */\nimport { Container } from '../container/index.js';\n\nconst schemaCache = new Map<string, any>();\n\nfunction cleanupTypeBoxIds(schema: any): void {\n if (typeof schema !== 'object' || schema === null) return;\n if (schema.$id && /^T\\d+$/.test(schema.$id)) delete schema.$id;\n if (schema.$ref && /^T\\d+$/.test(schema.$ref))\n schema.$ref = '#/definitions/ComponentDefinition';\n if (Array.isArray(schema)) {\n schema.forEach(cleanupTypeBoxIds);\n return;\n }\n Object.keys(schema).forEach((key) => {\n if (typeof schema[key] === 'object' && schema[key] !== null)\n cleanupTypeBoxIds(schema[key]);\n });\n}\n\nexport async function getDocumentSchema(format: string): Promise<any> {\n const cacheKey = `${format}:document`;\n if (schemaCache.has(cacheKey)) return schemaCache.get(cacheKey);\n\n let schema: any;\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n const unified = shared.generateUnifiedDocumentSchema({\n customComponents: [],\n });\n schema = shared.convertToJsonSchema(unified, {\n title: 'JSON to DOCX Document',\n description: 'Schema for JSON to DOCX document definitions',\n });\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n const unified = shared.generateUnifiedDocumentSchema({\n customComponents: [],\n });\n schema = shared.convertToJsonSchema(unified, {\n title: 'JSON to PPTX Presentation',\n description: 'Schema for JSON to PPTX presentation definitions',\n });\n }\n\n // Remove $schema URI — not needed for AI context\n delete schema.$schema;\n delete schema.$id;\n cleanupTypeBoxIds(schema);\n\n schemaCache.set(cacheKey, schema);\n return schema;\n}\n\nexport async function getThemeSchema(format: string): Promise<any> {\n const cacheKey = `${format}:theme`;\n if (schemaCache.has(cacheKey)) return schemaCache.get(cacheKey);\n\n let schema: any;\n if (format === 'docx') {\n const shared = await import('@json-to-office/shared-docx');\n schema = shared.convertToJsonSchema(shared.ThemeConfigSchema, {\n title: 'JSON to DOCX Theme',\n description: 'Schema for DOCX theme configuration',\n });\n } else {\n const shared = await import('@json-to-office/shared-pptx');\n schema = shared.convertToJsonSchema(shared.ThemeConfigSchema, {\n title: 'JSON to PPTX Theme',\n description: 'Schema for PPTX theme configuration',\n });\n }\n\n delete schema.$schema;\n delete schema.$id;\n cleanupTypeBoxIds(schema);\n\n schemaCache.set(cacheKey, schema);\n return schema;\n}\n\nexport async function getSchemaString(\n format: string,\n docType: 'document' | 'theme'\n): Promise<string> {\n const schema =\n docType === 'theme'\n ? await getThemeSchema(format)\n : await getDocumentSchema(format);\n return JSON.stringify(schema, null, 2);\n}\n\nexport function getDocumentSchemaString(format: string): Promise<string> {\n return getSchemaString(format, 'document');\n}\n\nexport function getFormatFromContainer(): string {\n return Container.getAdapter().name;\n}\n","/**\n * Reads .md prompt files from the prompts/ directory and interpolates {{var}} placeholders.\n */\nimport { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// In dev (tsx): __dirname = src/server/services → ../prompts\n// In prod (tsup): __dirname = dist → look for prompts in src/server/prompts (fallback)\nfunction resolvePromptsDir(): string {\n const candidates = [\n join(__dirname, '..', 'prompts'), // dev: src/server/prompts\n join(__dirname, 'prompts'), // bundled: dist/prompts\n join(__dirname, '..', 'src', 'server', 'prompts'), // prod from dist/\n ];\n for (const dir of candidates) {\n if (existsSync(dir)) return dir;\n }\n return candidates[0]; // fallback — will error on read if missing\n}\n\nconst PROMPTS_DIR = resolvePromptsDir();\n\nconst cache = new Map<string, string>();\n\nfunction readPromptFile(name: string): string {\n if (cache.has(name)) return cache.get(name)!;\n const filePath = join(PROMPTS_DIR, name);\n const content = readFileSync(filePath, 'utf-8');\n cache.set(name, content);\n return content;\n}\n\nexport function loadPrompt(\n name: string,\n vars: Record<string, string> = {}\n): string {\n let content = readPromptFile(name);\n for (const [key, value] of Object.entries(vars)) {\n content = content.replaceAll(`{{${key}}}`, value);\n }\n return content;\n}\n","import { Hono } from 'hono';\nimport { streamText, convertToModelMessages, type ModelMessage } from 'ai';\nimport { claudeCode } from 'ai-sdk-provider-claude-code';\nimport { extractText as extractPdfText } from 'unpdf';\nimport { AppEnv } from '../types/hono.js';\nimport {\n getSchemaString,\n getFormatFromContainer,\n} from '../services/ai-schema.js';\nimport { loadPrompt } from '../services/prompt-loader.js';\nimport { logger } from '../utils/logger.js';\nimport { rateLimiter } from '../middleware/hono/rate-limit.js';\nimport { config } from '../config/index.js';\n\nfunction sanitizeFilename(name: string): string {\n return name.replace(/[[\\]\\n\\r]/g, '_');\n}\n\n/**\n * Convert data: URL file parts to inline base64 so providers that\n * reject data: URLs (e.g. claude-code) can consume them.\n */\nfunction fixDataUrlFileParts(messages: ModelMessage[]): ModelMessage[] {\n for (const msg of messages) {\n if (msg.role !== 'user' || typeof msg.content === 'string') continue;\n for (const part of msg.content) {\n if (part.type !== 'file') continue;\n const data = part.data;\n if (data instanceof URL && data.protocol === 'data:') {\n const str = data.toString();\n const commaIdx = str.indexOf(',');\n if (commaIdx !== -1) {\n const isBase64 = str.slice(0, commaIdx).includes(';base64');\n const payload = str.slice(commaIdx + 1);\n const decoded = Buffer.from(\n decodeURIComponent(payload),\n 'utf-8'\n ).toString('base64');\n part.data = isBase64 ? payload : decoded;\n }\n } else if (typeof data === 'string' && data.startsWith('data:')) {\n const commaIdx = data.indexOf(',');\n if (commaIdx !== -1) {\n const isBase64 = data.slice(0, commaIdx).includes(';base64');\n const payload = data.slice(commaIdx + 1);\n const decoded = Buffer.from(\n decodeURIComponent(payload),\n 'utf-8'\n ).toString('base64');\n part.data = isBase64 ? payload : decoded;\n }\n }\n }\n }\n return messages;\n}\n\nconst TEXT_MIME_TYPES = new Set([\n 'text/plain',\n 'text/markdown',\n 'text/csv',\n 'text/html',\n]);\n\nfunction toBuffer(data: string | Uint8Array | ArrayBuffer | URL): Buffer {\n if (data instanceof ArrayBuffer) return Buffer.from(new Uint8Array(data));\n if (data instanceof Uint8Array) return Buffer.from(data);\n if (data instanceof URL) {\n const str = data.toString();\n const commaIdx = str.indexOf(',');\n if (commaIdx === -1) return Buffer.from(str, 'base64');\n const isBase64 = str.slice(0, commaIdx).includes(';base64');\n const payload = str.slice(commaIdx + 1);\n return isBase64\n ? Buffer.from(payload, 'base64')\n : Buffer.from(decodeURIComponent(payload), 'utf-8');\n }\n // base64 string (or raw data: string already stripped by fixDataUrlFileParts)\n return Buffer.from(data, 'base64');\n}\n\nasync function extractFileText(\n mimeType: string,\n data: string | Uint8Array | ArrayBuffer | URL\n): Promise<string> {\n const buf = toBuffer(data);\n if (mimeType === 'application/pdf') {\n const { text } = await extractPdfText(new Uint8Array(buf));\n return Array.isArray(text) ? text.join('\\n') : String(text);\n }\n // text/* types\n return buf.toString('utf-8');\n}\n\nasync function extractNonImageFileParts(\n messages: ModelMessage[]\n): Promise<ModelMessage[]> {\n for (const msg of messages) {\n if (msg.role !== 'user' || typeof msg.content === 'string') continue;\n const newContent: typeof msg.content = [];\n for (const part of msg.content) {\n if (part.type !== 'file') {\n newContent.push(part);\n continue;\n }\n const mime = part.mediaType ?? '';\n // Images pass through — the provider handles them\n if (mime.startsWith('image/')) {\n newContent.push(part);\n continue;\n }\n // Non-image file: extract text\n if (mime === 'application/pdf' || TEXT_MIME_TYPES.has(mime)) {\n const filename = sanitizeFilename((part as any).filename || 'file');\n try {\n const text = await extractFileText(mime, part.data);\n newContent.push({\n type: 'text' as const,\n text: `[Attached file: ${filename}]\\n${text}`,\n });\n } catch (err: any) {\n logger.warn('Failed to extract file content', {\n filename,\n mime,\n error: err.message,\n });\n newContent.push({\n type: 'text' as const,\n text: `[Attached file: ${filename} — could not extract content]`,\n });\n }\n } else {\n // Unknown MIME — mention it but don't crash\n const filename = sanitizeFilename((part as any).filename || 'file');\n newContent.push({\n type: 'text' as const,\n text: `[Attached file: ${filename} — unsupported format: ${mime}]`,\n });\n }\n }\n msg.content = newContent;\n }\n return messages;\n}\n\nexport function createAiRouter() {\n const router = new Hono<AppEnv>();\n\n router.post(\n '/chat',\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 30 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n async (c) => {\n try {\n const body = await c.req.json();\n const {\n messages,\n context,\n format: clientFormat,\n activeDocument,\n documentType,\n scope,\n model: requestedModel,\n } = body;\n const VALID_MODELS = ['opus', 'sonnet', 'haiku'] as const;\n const model = VALID_MODELS.includes(requestedModel)\n ? requestedModel\n : 'opus';\n\n const format = clientFormat || getFormatFromContainer();\n const isTheme = documentType === 'application/json+theme';\n const schemaStr = await getSchemaString(\n format,\n isTheme ? 'theme' : 'document'\n );\n const contentLabel = isTheme ? 'Theme' : 'Document';\n\n // === Prompt assembly: base → format → format+design → mode ===\n\n // Layer 1: Base\n let systemPrompt = loadPrompt(\n isTheme ? 'system-theme.md' : 'system.md',\n {\n format,\n schema: schemaStr,\n }\n );\n\n // Layer 2: Format-specific core (always loaded)\n if (!isTheme) {\n if (format === 'pptx') {\n systemPrompt += '\\n\\n' + loadPrompt('pptx-core.md');\n } else if (format === 'docx') {\n systemPrompt += '\\n\\n' + loadPrompt('instructions-docx.md');\n }\n }\n\n // Determine mode: selection-edit, edit-document, or generate\n const hasSelection =\n context && context.length > 0 && context[0]?.selectedText;\n const hasActiveDoc = !hasSelection && activeDocument?.text;\n const isGenerate = !hasSelection && !hasActiveDoc;\n\n // Layer 3: Format+design (generate and edit-document only, not selection-edit)\n if (!isTheme && format === 'pptx' && !hasSelection) {\n systemPrompt += '\\n\\n' + loadPrompt('pptx-design.md');\n }\n\n // Layer 4: Mode-specific instructions\n if (hasSelection) {\n const ctx = context[0];\n // Use pptx-aware selection editing for pptx, generic for others\n const editFile =\n format === 'pptx' && !isTheme\n ? 'instructions-edit-pptx.md'\n : 'instructions-edit.md';\n systemPrompt +=\n '\\n\\n' +\n loadPrompt(editFile, {\n documentName: ctx.documentName || 'unknown',\n jsonPath: ctx.jsonPath || '',\n selectedText: ctx.selectedText,\n });\n } else if (hasActiveDoc) {\n const pptxScope =\n format === 'pptx' &&\n !isTheme &&\n (scope === 'slides' || scope === 'templates');\n\n let parsedDoc: any = null;\n if (pptxScope) {\n try {\n parsedDoc = JSON.parse(activeDocument.text);\n } catch {\n /* fall through to global */\n }\n }\n\n if (pptxScope && parsedDoc) {\n const doc = parsedDoc;\n\n if (scope === 'slides') {\n const templatesSummary = (doc.props?.templates || [])\n .map((m: any) => {\n const phs = (m.placeholders || [])\n .map((p: any) => {\n const d = p.defaults\n ? ` → defaults: ${JSON.stringify(p.defaults)}`\n : '';\n return ` - \\`${p.name}\\`${d}`;\n })\n .join('\\n');\n return `**${m.name}**\\n${phs}`;\n })\n .join('\\n\\n');\n const slidesText = JSON.stringify(doc.children || [], null, 2);\n systemPrompt +=\n '\\n\\n' +\n loadPrompt('instructions-edit-document-pptx-slides.md', {\n documentName: activeDocument.name || 'untitled',\n templatesSummary,\n slidesText,\n });\n } else {\n const templatesText = JSON.stringify(\n doc.props?.templates || [],\n null,\n 2\n );\n const slidesSummary = (doc.children || [])\n .map((s: any, i: number) => {\n const template = s.props?.template || '(none)';\n const phs = Object.keys(s.props?.placeholders || {}).join(\n ', '\n );\n return ` ${i}: template=${template}, placeholders=[${phs}]`;\n })\n .join('\\n');\n systemPrompt +=\n '\\n\\n' +\n loadPrompt('instructions-edit-document-pptx-templates.md', {\n documentName: activeDocument.name || 'untitled',\n templatesText,\n slidesSummary,\n });\n }\n } else {\n const editDocFiles: Record<string, string> = {\n pptx: 'instructions-edit-document-pptx.md',\n docx: 'instructions-edit-document-docx.md',\n };\n const editDocFile = isTheme\n ? 'instructions-edit-document.md'\n : editDocFiles[format] ?? 'instructions-edit-document.md';\n systemPrompt +=\n '\\n\\n' +\n loadPrompt(editDocFile, {\n contentLabel,\n contentLabelLower: contentLabel.toLowerCase(),\n documentName: activeDocument.name || 'untitled',\n documentText: activeDocument.text,\n });\n }\n } else if (isGenerate) {\n const generateFiles: Record<string, string> = {\n pptx: 'instructions-generate-pptx.md',\n docx: 'instructions-generate-docx.md',\n };\n const generateFile = isTheme\n ? 'instructions-generate.md'\n : generateFiles[format] ?? 'instructions-generate.md';\n systemPrompt +=\n '\\n\\n' +\n loadPrompt(generateFile, {\n contentType: isTheme ? 'theme' : 'document',\n });\n }\n\n // If context is provided (selection from editor), prepend as a user message\n const allMessages = [...messages];\n if (context && context.length > 0) {\n const contextParts = context.map((ctx: any) => {\n const parts: string[] = [];\n if (ctx.documentName) parts.push(`Document: ${ctx.documentName}`);\n if (ctx.jsonPath) parts.push(`JSON Path: ${ctx.jsonPath}`);\n if (ctx.selectedText)\n parts.push(`Selected:\\n\\`\\`\\`json\\n${ctx.selectedText}\\n\\`\\`\\``);\n return parts.join('\\n');\n });\n\n // Insert context as a system-style user message before the last user message\n const lastMsg = allMessages[allMessages.length - 1];\n if (lastMsg && lastMsg.role === 'user') {\n const contextPrefix = `[Editor Context]\\n${contextParts.join('\\n---\\n')}\\n\\n`;\n // Prepend context to the last user message text\n if (typeof lastMsg.content === 'string') {\n lastMsg.content = contextPrefix + lastMsg.content;\n } else if (Array.isArray(lastMsg.parts)) {\n lastMsg.parts = [\n { type: 'text', text: contextPrefix },\n ...lastMsg.parts,\n ];\n }\n }\n }\n\n const modelMessages = await extractNonImageFileParts(\n fixDataUrlFileParts(await convertToModelMessages(allMessages))\n );\n\n const result = streamText({\n model: claudeCode(model, {\n streamingInput: 'always',\n disallowedTools: [\n 'Read',\n 'Write',\n 'Edit',\n 'Glob',\n 'Grep',\n 'Bash',\n 'Agent',\n ],\n persistSession: false,\n }),\n system: systemPrompt,\n messages: modelMessages,\n });\n\n return result.toUIMessageStreamResponse();\n } catch (error: any) {\n const message = error.message || 'Unknown error';\n const status = error.status || error.statusCode || 500;\n\n if (status === 429 || message.includes('rate')) {\n logger.warn('AI rate limit hit', { error: message });\n return c.json(\n {\n error:\n 'Rate limit exceeded. Please wait before sending another message.',\n },\n 429\n );\n }\n if (\n status === 413 ||\n message.includes('too large') ||\n message.includes('too long') ||\n message.includes('exceeds maximum')\n ) {\n logger.warn('AI request too large', { error: message });\n return c.json(\n {\n error:\n 'Request too large for the AI model. Try selecting a smaller portion of the document.',\n },\n 413\n );\n }\n if (error.name === 'AbortError' || message.includes('abort')) {\n logger.info('AI request aborted');\n return c.json({ error: 'Request was cancelled.' }, 400);\n }\n\n logger.error('AI chat error', { error: message, stack: error.stack });\n return c.json(\n {\n error:\n process.env.NODE_ENV === 'production'\n ? 'Something went wrong. Please try again.'\n : message,\n },\n 500\n );\n }\n }\n );\n\n return router;\n}\n","/**\n * Font catalog + Google Fonts materialization endpoints for the playground.\n *\n * GET /catalog — safe + popular Google fonts (static; cached)\n * POST /materialize — server-side Google Fonts fetch; returns base64 sources\n * so the client can insert `kind: \"data\"` entries into the\n * document JSON (self-contained, survives export/reimport).\n */\n\nimport { createHash } from 'node:crypto';\nimport { Hono } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport { bodyLimit } from 'hono/body-limit';\nimport {\n SAFE_FONTS,\n POPULAR_GOOGLE_FONTS,\n fetchGoogleFontSources,\n} from '@json-to-office/shared';\nimport { rateLimiter } from '../middleware/hono/rate-limit.js';\nimport type { AppEnv } from '../types/hono.js';\nimport { config } from '../config/index.js';\n\nexport const fontsRouter = new Hono<AppEnv>();\n\nconst MATERIALIZE_FAMILY_MAX = 64;\nconst MATERIALIZE_WEIGHTS_MAX = 9;\n\n// Precomputed body + ETag for /catalog. SAFE_FONTS and POPULAR_GOOGLE_FONTS\n// are module-level constants, so the payload only changes on deploy. Hashing\n// once at import lets every request answer with a 304 when the client\n// already has the current catalog.\nconst CATALOG_BODY = JSON.stringify({\n safe: SAFE_FONTS,\n google: POPULAR_GOOGLE_FONTS,\n});\nconst CATALOG_ETAG = `\"${createHash('sha256')\n .update(CATALOG_BODY)\n .digest('base64')\n .slice(0, 24)}\"`;\n\nfontsRouter.get('/catalog', (c) => {\n const ifNoneMatch = c.req.header('If-None-Match');\n if (ifNoneMatch && ifNoneMatch === CATALOG_ETAG) {\n c.header('ETag', CATALOG_ETAG);\n c.header('Cache-Control', 'public, max-age=86400');\n return c.body(null, 304);\n }\n c.header('Content-Type', 'application/json');\n c.header('ETag', CATALOG_ETAG);\n c.header('Cache-Control', 'public, max-age=86400');\n return c.body(CATALOG_BODY, 200);\n});\n\ninterface MaterializeBody {\n family?: string;\n weights?: number[];\n italics?: boolean;\n}\n\nfontsRouter.post(\n '/materialize',\n bodyLimit({\n // Body is just {family, weights, italics} — 16 KB is generous.\n maxSize: 16 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n trustProxy: config.rateLimit.trustProxy,\n }),\n async (c) => {\n let body: MaterializeBody;\n try {\n body = (await c.req.json()) as MaterializeBody;\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n\n const family = body.family?.trim();\n if (!family) {\n return c.json({ error: 'Missing required field: family' }, 400);\n }\n if (family.length > MATERIALIZE_FAMILY_MAX) {\n return c.json(\n { error: `family exceeds ${MATERIALIZE_FAMILY_MAX} characters` },\n 400\n );\n }\n // Dedup + cap weights so a crafted request can't fan out to thousands of\n // upstream Google fetches. 9 canonical weights (100..900) is the ceiling.\n const weights =\n Array.isArray(body.weights) && body.weights.length > 0\n ? Array.from(\n new Set(\n body.weights.filter(\n (w) => typeof w === 'number' && w >= 100 && w <= 900\n )\n )\n ).slice(0, MATERIALIZE_WEIGHTS_MAX)\n : [400, 700];\n const italics = Boolean(body.italics);\n\n try {\n const { sources, warnings } = await fetchGoogleFontSources({\n family,\n weights,\n italics,\n });\n return c.json({\n family,\n sources: sources.map((s) => ({\n weight: s.weight,\n italic: s.italic,\n format: s.format,\n data: s.data.toString('base64'),\n })),\n warnings,\n });\n } catch (err) {\n return c.json(\n {\n error: `Google Fonts materialize failed: ${(err as Error).message}`,\n },\n 502\n );\n }\n }\n);\n","import { MiddlewareHandler } from 'hono';\nimport { randomUUID } from 'crypto';\n\n/**\n * Request ID middleware for Hono\n * Generates a unique ID for each request for tracing\n */\nexport const requestIdMiddleware: MiddlewareHandler = async (c, next) => {\n const requestId = c.req.header('X-Request-Id') || randomUUID();\n\n // Set request ID in context\n c.set('requestId', requestId);\n\n // Add to response headers\n c.header('X-Request-Id', requestId);\n\n await next();\n};\n","import { createHash, timingSafeEqual } from 'node:crypto';\nimport { MiddlewareHandler } from 'hono';\nimport { config } from '../../config';\nimport type { ApiAuthMode } from '../../config';\n\nexport interface ApiKeyAuthOptions {\n mode: ApiAuthMode;\n apiKey?: string;\n headerName?: string;\n}\n\nfunction keysEqual(received: string, expected: string): boolean {\n const receivedDigest = createHash('sha256').update(received).digest();\n const expectedDigest = createHash('sha256').update(expected).digest();\n return timingSafeEqual(receivedDigest, expectedDigest);\n}\n\nfunction readCredential(\n headers: Headers,\n headerName: string\n): string | undefined {\n const direct = headers.get(headerName)?.trim();\n if (direct) {\n if (\n headerName.toLowerCase() === 'authorization' &&\n direct.toLowerCase().startsWith('bearer ')\n ) {\n return direct.slice(7).trim() || undefined;\n }\n return direct;\n }\n\n const authorization = headers.get('authorization')?.trim();\n if (authorization?.toLowerCase().startsWith('bearer ')) {\n return authorization.slice(7).trim() || undefined;\n }\n return undefined;\n}\n\n/**\n * API Key authentication middleware for Hono\n */\nexport function createApiKeyAuthMiddleware(\n options: ApiKeyAuthOptions\n): MiddlewareHandler {\n const headerName = options.headerName || 'x-api-key';\n\n return async (c, next) => {\n if (c.req.method === 'OPTIONS' || options.mode === 'disabled') {\n return next();\n }\n\n if (!options.apiKey) {\n if (options.mode === 'auto') return next();\n return c.json(\n {\n success: false,\n error: 'API authentication is not configured',\n code: 'AUTH_CONFIGURATION_ERROR',\n },\n 503\n );\n }\n\n const apiKey = readCredential(c.req.raw.headers, headerName);\n\n if (!apiKey) {\n return c.json(\n {\n success: false,\n error: 'API key required',\n code: 'UNAUTHORIZED',\n },\n 401\n );\n }\n\n if (!keysEqual(apiKey, options.apiKey)) {\n return c.json(\n {\n success: false,\n error: 'Invalid API key',\n code: 'UNAUTHORIZED',\n },\n 401\n );\n }\n\n await next();\n };\n}\n\nexport const apiKeyAuthMiddleware = createApiKeyAuthMiddleware({\n mode: config.API_AUTH_MODE,\n apiKey: config.API_KEY,\n headerName: config.API_KEY_HEADER,\n});\n","import { ErrorHandler } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport { logger } from '../../utils/logger';\nimport { config } from '../../config';\n\n/**\n * Global error handler for Hono\n */\nexport const errorHandler: ErrorHandler = (err, c) => {\n const requestId = c.get('requestId') || 'unknown';\n\n // Handle Hono HTTPException\n if (err instanceof HTTPException) {\n const cause = (err as Error & { cause?: unknown }).cause as\n | { code?: unknown; analysis?: unknown }\n | undefined;\n if (cause?.code === 'QUALITY_GATE_FAILED') {\n return c.json(\n {\n success: false,\n error: err.message,\n code: cause.code,\n quality: cause.analysis,\n requestId,\n },\n 400\n );\n }\n return c.json(\n {\n success: false,\n error: err.message,\n code: err.status >= 500 ? 'INTERNAL_ERROR' : 'CLIENT_ERROR',\n requestId,\n },\n err.status\n );\n }\n\n // Log unexpected errors\n logger.error('Unhandled error', {\n error: err.message,\n stack: err.stack,\n requestId,\n path: c.req.path,\n method: c.req.method,\n });\n\n // Handle validation errors (TypeBox format)\n if (err.name === 'ValidationError' && 'errors' in err) {\n return c.json(\n {\n success: false,\n error: 'Validation failed',\n errors: (err as any).errors,\n code: 'VALIDATION_ERROR',\n requestId,\n },\n 400\n );\n }\n\n // Default error response\n return c.json(\n {\n success: false,\n error: config.isDevelopment ? err.message : 'Internal server error',\n code: 'INTERNAL_ERROR',\n requestId,\n },\n 500\n );\n};\n","import { MiddlewareHandler } from 'hono';\n\n/**\n * Security middleware for Hono\n * Adds additional security headers and input sanitization\n */\nexport const securityMiddleware: MiddlewareHandler = async (c, next) => {\n // Add security headers\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('X-Frame-Options', 'DENY');\n c.header('Referrer-Policy', 'strict-origin-when-cross-origin');\n c.header('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');\n\n // Remove sensitive headers\n c.header('X-Powered-By', '');\n\n await next();\n};\n","import { MiddlewareHandler } from 'hono';\n// import { HTTPException } from 'hono/http-exception';\nimport { logger } from '../../utils/logger';\n\n/**\n * Error recovery middleware for Hono\n * Handles specific error types with appropriate recovery strategies\n */\nexport const errorRecoveryMiddleware: MiddlewareHandler = async (c, next) => {\n try {\n await next();\n } catch (err: any) {\n const requestId = c.get('requestId') || 'unknown';\n\n logger.error('Error recovery triggered', {\n error: err.message,\n name: err.name,\n path: c.req.path,\n method: c.req.method,\n requestId,\n });\n\n // Handle payload too large errors\n if (err.name === 'PayloadTooLargeError' || err.status === 413) {\n return c.json(\n {\n success: false,\n error: 'Payload too large',\n message: 'The request body exceeds the maximum allowed size',\n code: 'PAYLOAD_TOO_LARGE',\n requestId,\n },\n 413\n );\n }\n\n // Handle JSON syntax errors\n if (\n (err.name === 'SyntaxError' && err.message.includes('JSON')) ||\n (err.status === 400 && err.message.includes('JSON'))\n ) {\n return c.json(\n {\n success: false,\n error: 'Invalid JSON',\n message: 'The request body contains invalid JSON',\n code: 'INVALID_JSON',\n requestId,\n },\n 400\n );\n }\n\n // Handle timeout errors\n if (err.name === 'TimeoutError' || err.code === 'ETIMEDOUT') {\n return c.json(\n {\n success: false,\n error: 'Request timeout',\n message: 'The request took too long to process',\n code: 'TIMEOUT',\n requestId,\n },\n 408\n );\n }\n\n // Re-throw the error to be handled by the global error handler\n throw err;\n }\n};\n","import { MiddlewareHandler } from 'hono';\nimport { logger } from '../../utils/logger';\n\n/**\n * Request logger middleware for Hono\n * Logs incoming requests and their responses\n */\nexport const requestLoggerMiddleware: MiddlewareHandler = async (c, next) => {\n const startTime = Date.now();\n const requestId = c.get('requestId');\n\n // Log incoming request\n logger.info('Incoming request', {\n requestId,\n method: c.req.method,\n url: c.req.url,\n path: c.req.path,\n ip:\n c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown',\n userAgent: c.req.header('user-agent'),\n });\n\n try {\n // Process the request\n await next();\n\n // Log response\n const duration = Date.now() - startTime;\n const status = c.res.status;\n\n logger.info('Request completed', {\n requestId,\n method: c.req.method,\n path: c.req.path,\n status,\n duration,\n responseTime: `${duration}ms`,\n });\n\n // Add response time header\n c.header('X-Response-Time', `${duration}ms`);\n } catch (error) {\n // Log error response\n const duration = Date.now() - startTime;\n\n logger.error('Request failed', {\n requestId,\n method: c.req.method,\n path: c.req.path,\n duration,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Re-throw the error\n throw error;\n }\n};\n","import type { MiddlewareHandler } from 'hono';\n\nexport interface ConcurrencyLimitOptions {\n limit: number;\n retryAfterSeconds?: number;\n}\n\n/**\n * Process-local admission control for expensive generation/rendering work.\n * It rejects excess work instead of queueing unbounded request bodies in RAM.\n */\nexport function concurrencyLimiter(\n options: ConcurrencyLimitOptions\n): MiddlewareHandler {\n const limit = Math.max(1, Math.floor(options.limit));\n const retryAfterSeconds = options.retryAfterSeconds ?? 1;\n let active = 0;\n\n return async (c, next) => {\n c.header('X-Concurrency-Limit', String(limit));\n if (active >= limit) {\n c.header('Retry-After', String(retryAfterSeconds));\n return c.json(\n {\n success: false,\n error: 'Server is at capacity',\n code: 'CONCURRENCY_LIMIT_EXCEEDED',\n },\n 503\n );\n }\n\n active += 1;\n c.header('X-Concurrency-Remaining', String(Math.max(0, limit - active)));\n try {\n await next();\n } finally {\n active -= 1;\n }\n };\n}\n","import { Hono } from 'hono';\n\nimport { cors } from 'hono/cors';\nimport { secureHeaders } from 'hono/secure-headers';\nimport { logger as honoLogger } from 'hono/logger';\nimport { timing } from 'hono/timing';\nimport { bodyLimit } from 'hono/body-limit';\nimport { HTTPException } from 'hono/http-exception';\nimport { config } from './config/index.js';\nimport { getApiInfo } from './config/api-info.js';\nimport type { FormatAdapter } from '@json-to-office/jto-cli';\n\nimport { healthRouter } from './routes/health.js';\nimport { createFormatRouter } from './routes/format.js';\nimport { discoveryRouter } from './routes/discovery.js';\nimport { createAiRouter } from './routes/ai.js';\nimport { fontsRouter } from './routes/fonts.js';\n\nimport { requestIdMiddleware } from './middleware/hono/request-id.js';\nimport { apiKeyAuthMiddleware } from './middleware/hono/auth.js';\nimport { errorHandler } from './middleware/hono/error-handler.js';\nimport { securityMiddleware } from './middleware/hono/security.js';\nimport { errorRecoveryMiddleware } from './middleware/hono/error-recovery.js';\nimport { requestLoggerMiddleware } from './middleware/hono/request-logger.js';\nimport { rateLimiter } from './middleware/hono/rate-limit.js';\nimport { concurrencyLimiter } from './middleware/hono/concurrency-limit.js';\n\nimport { AppEnv } from './types/hono.js';\nimport { Container } from './container/index.js';\n\nexport function createAPIApp(adapter: FormatAdapter) {\n // Initialize DI container with the adapter\n Container.initialize(adapter);\n\n const honoApp = new Hono<AppEnv>();\n\n // Built-in middleware\n honoApp.use('*', timing());\n honoApp.use('*', honoLogger());\n\n // CORS\n honoApp.use(\n '*',\n cors({\n origin: config.cors.origin,\n credentials: config.cors.origin === '*' ? false : config.cors.credentials,\n allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowHeaders: ['Content-Type', 'Authorization', config.API_KEY_HEADER],\n exposeHeaders: ['X-Request-Id', 'X-File-Id'],\n maxAge: 86400,\n })\n );\n\n honoApp.use('*', secureHeaders());\n\n // Custom middleware\n honoApp.use('*', requestIdMiddleware);\n honoApp.use('*', errorRecoveryMiddleware);\n honoApp.use('*', requestLoggerMiddleware);\n honoApp.use('*', securityMiddleware);\n\n // Uniform admission controls cover every API surface. Individual expensive\n // routes retain tighter limits below this process-wide ceiling.\n //\n // These run BEFORE authentication on purpose: Hono executes middleware in\n // registration order, so an auth check registered first would return 401\n // without ever reaching the limiter, leaving API-key guessing unbounded.\n honoApp.use(\n '/api/*',\n bodyLimit({\n maxSize: config.requestLimits.maxBodySize,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n })\n );\n honoApp.use(\n '/api/*',\n rateLimiter({\n limit: config.rateLimit.max,\n window: config.rateLimit.windowMs,\n namespace: (c) => `${c.req.method}:${c.req.path}`,\n trustProxy: config.rateLimit.trustProxy,\n })\n );\n honoApp.use(\n '/api/*',\n concurrencyLimiter({ limit: config.requestLimits.maxConcurrent })\n );\n\n // API key auth (if enabled)\n if (config.features.apiKey) {\n honoApp.use('/api/*', apiKeyAuthMiddleware);\n }\n\n // Mount routes\n honoApp.route('/health', healthRouter);\n\n // Format-specific routes at /api/{format}/*\n const formatRouter = createFormatRouter(adapter);\n honoApp.route(`/api/${adapter.name}`, formatRouter);\n\n // Also mount at /api/documents or /api/presentations for backward compat\n const legacyPath =\n adapter.name === 'docx' ? '/api/documents' : '/api/presentations';\n honoApp.route(legacyPath, formatRouter);\n\n // Discovery routes\n honoApp.route('/api/discovery', discoveryRouter);\n\n // Font catalog + Google Fonts materialization\n honoApp.route('/api/fonts', fontsRouter);\n\n // AI chat routes (disabled via AI_ENABLED=false)\n if (process.env.AI_ENABLED !== 'false') {\n honoApp.route('/api/ai', createAiRouter());\n }\n\n // Root endpoint\n honoApp.get('/', async (c) => {\n const apiInfo = await getApiInfo();\n return c.json(apiInfo);\n });\n\n honoApp.get('/api', async (c) => {\n const apiInfo = await getApiInfo();\n return c.json(apiInfo);\n });\n\n // 404 handler\n honoApp.notFound((c) => {\n return c.json(\n {\n success: false,\n error: 'Not found',\n path: c.req.path,\n method: c.req.method,\n requestId: c.get('requestId'),\n },\n 404\n );\n });\n\n honoApp.onError(errorHandler);\n\n return honoApp;\n}\n","import { Hono } from 'hono';\nimport { serve } from '@hono/node-server';\nimport { logger } from 'hono/logger';\nimport { compress } from 'hono/compress';\nimport { createAPIApp } from './app.js';\nimport type { Config, FormatAdapter } from '@json-to-office/jto-cli';\nimport { resolve, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { logger as serverLogger } from './utils/logger.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport class UnifiedServer {\n private app: Hono;\n private config: Config;\n private adapter: FormatAdapter;\n private server: ReturnType<typeof serve> | null = null;\n private viteServer: any | null = null;\n\n constructor(adapter: FormatAdapter, config: Config) {\n this.adapter = adapter;\n this.config = config;\n this.app = new Hono();\n }\n\n async initialize() {\n await this.setupMiddleware();\n await this.setupRoutes();\n }\n\n private async setupMiddleware() {\n this.app.use('*', logger());\n this.app.use('*', compress());\n }\n\n private async setupRoutes() {\n // Health check (fast path)\n this.app.get('/health', (c) =>\n c.json({\n status: 'ok',\n timestamp: Date.now(),\n version: '1.0.0',\n mode: this.config.mode,\n format: this.adapter.name,\n })\n );\n\n // Mount API routes FIRST\n const apiApp = createAPIApp(this.adapter);\n\n this.app.get('/api', async (c) => {\n return await apiApp.fetch(c.req.raw, c.env as any);\n });\n\n this.app.use('*', async (c, next) => {\n const path = c.req.path;\n\n if (path.startsWith('/api')) {\n // Allow Vite module requests to fall through\n if (/\\.(ts|tsx|js|jsx|css|map)$/.test(path)) {\n return next();\n }\n const response = await apiApp.fetch(c.req.raw, c.env as any);\n if (response.status !== 404) {\n return response;\n }\n }\n\n return next();\n });\n\n // Client serving\n if (this.config.mode === 'development') {\n await this.setupDevClient();\n } else {\n await this.setupProdClient();\n }\n }\n\n private async setupDevClient() {\n const { existsSync } = await import('fs');\n const format = this.adapter.name.replace(/[^a-zA-Z0-9]/g, '');\n\n const formatPlugin = {\n name: 'jto-format-inject',\n transformIndexHtml(html: string) {\n return html.replace(\n '</head>',\n `<script>window.__JTO_FORMAT__ = '${format}';</script>\\n</head>`\n );\n },\n };\n\n const isBundled =\n __filename.endsWith('.cjs') ||\n __filename.endsWith('.mjs') ||\n __dirname.includes('node_modules') ||\n __dirname.endsWith('dist');\n\n let clientPath: string | null = null;\n\n // Check env var\n if (process.env.JTO_CLIENT_PATH) {\n const envClientPath = process.env.JTO_CLIENT_PATH;\n if (\n existsSync(envClientPath) &&\n existsSync(resolve(envClientPath, 'index.html'))\n ) {\n clientPath = envClientPath;\n serverLogger.debug('[Dev Server] Using client from JTO_CLIENT_PATH', {\n path: clientPath,\n });\n }\n } else if (isBundled) {\n const bundledClientPath = resolve(__dirname, 'client');\n if (\n existsSync(bundledClientPath) &&\n existsSync(resolve(bundledClientPath, 'index.html'))\n ) {\n clientPath = bundledClientPath;\n serverLogger.debug('[Dev Server] Using bundled client at', {\n path: clientPath,\n });\n }\n } else {\n const possiblePaths = [\n resolve(__dirname, '../client'),\n resolve(__dirname, '../../dist/client'),\n ];\n\n for (const p of possiblePaths) {\n if (existsSync(p)) {\n if (p.replace(/\\\\/g, '/').includes('/src/client')) {\n serverLogger.debug('[Dev Server] Using Vite dev server for', {\n path: p,\n });\n try {\n const { createServer: createViteServer } = await import('vite');\n this.viteServer = await createViteServer({\n root: p,\n plugins: [formatPlugin],\n server: {\n middlewareMode: true,\n hmr: { port: this.config.development.hmrPort || 5173 },\n },\n });\n } catch (err) {\n serverLogger.warn('[Dev Server] Vite not available for dev mode');\n }\n break;\n } else if (existsSync(resolve(p, 'index.html'))) {\n clientPath = p;\n serverLogger.debug('[Dev Server] Using pre-built client at', {\n path: clientPath,\n });\n break;\n }\n }\n }\n }\n\n if (clientPath) {\n return this.setupBuiltClient(clientPath);\n }\n\n if (!this.viteServer && !isBundled) {\n const sourceClientPath = resolve(__dirname, '../client');\n try {\n const { createServer: createViteServer } = await import('vite');\n this.viteServer = await createViteServer({\n root: sourceClientPath,\n plugins: [formatPlugin],\n server: {\n middlewareMode: true,\n hmr: { port: this.config.development.hmrPort || 5173 },\n },\n });\n } catch {\n serverLogger.warn('[Dev Server] Vite not available');\n }\n }\n\n if (this.viteServer) {\n this.app.use('*', async (c, next) => {\n const path = c.req.path;\n\n if (\n (path.startsWith('/api') || path === '/health') &&\n !/\\.(ts|tsx|js|jsx|css|map)$/.test(path)\n ) {\n return next();\n }\n\n const env = c.env as Record<string, unknown>;\n const req = env.incoming || env.req;\n const res = env.outgoing || env.res;\n\n if (req && res && this.viteServer) {\n return new Promise((resolve) => {\n this.viteServer!.middlewares.handle(req as any, res as any, () => {\n resolve(next());\n });\n });\n }\n\n return next();\n });\n }\n }\n\n private async setupBuiltClient(clientPath: string) {\n const { serveStatic } = await import('@hono/node-server/serve-static');\n const fs = await import('fs');\n const { extname } = await import('path');\n const mime = await import('mime-types');\n\n const format = this.adapter.name.replace(/[^a-zA-Z0-9]/g, '');\n\n // Serve static assets\n this.app.use(\n '/assets/*',\n serveStatic({\n root: clientPath,\n rewriteRequestPath: (path) => path.replace(/^\\/assets/, '/assets'),\n })\n );\n\n // Handle file requests\n this.app.use('/*', async (c, next) => {\n const reqPath = c.req.path;\n if (reqPath.startsWith('/api') || reqPath === '/health') return next();\n\n const ext = extname(reqPath);\n if (ext) {\n const filePath = resolve(clientPath, reqPath.slice(1));\n if (fs.existsSync(filePath)) {\n const mimeType = mime.lookup(filePath) || 'application/octet-stream';\n const content = fs.readFileSync(filePath);\n c.header('Content-Type', mimeType);\n return c.body(content);\n }\n }\n\n return next();\n });\n\n // SPA fallback - inject format into HTML\n this.app.get('*', async (c) => {\n const reqPath = c.req.path;\n if (reqPath.startsWith('/api') || reqPath === '/health')\n return c.notFound();\n\n const indexPath = resolve(clientPath, 'index.html');\n if (fs.existsSync(indexPath)) {\n let html = fs.readFileSync(indexPath, 'utf-8');\n // Inject format configuration\n html = html.replace(\n '</head>',\n `<script>window.__JTO_FORMAT__ = '${format}';</script>\\n</head>`\n );\n return c.html(html);\n }\n\n return c.notFound();\n });\n }\n\n private async setupProdClient() {\n const clientPath = resolve(__dirname, 'client');\n return this.setupBuiltClient(clientPath);\n }\n\n async start(): Promise<void> {\n await this.initialize();\n\n return new Promise((resolve) => {\n this.server = serve(\n {\n fetch: this.app.fetch,\n port: this.config.server.port,\n hostname: this.config.server.host,\n },\n () => {\n resolve();\n }\n );\n });\n }\n\n async stop(): Promise<void> {\n if (this.viteServer) await this.viteServer.close();\n if (this.server) {\n return new Promise((resolve) => {\n this.server?.close(() => resolve());\n });\n }\n }\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { registerCoreCommands, renderLines } from '@json-to-office/jto-cli';\nimport { createDevCommand } from './commands/dev.js';\n\ndeclare const __PACKAGE_VERSION__: string | undefined;\nconst PACKAGE_VERSION =\n typeof __PACKAGE_VERSION__ !== 'undefined' ? __PACKAGE_VERSION__ : 'dev-mode';\n\nconst program = new Command();\n\nprogram\n .name('jto')\n .description('JSON to Office CLI - Generate .docx and .pptx from JSON')\n .version(PACKAGE_VERSION);\n\nregisterCoreCommands(program, {\n extraCommands: (adapter) => [createDevCommand(adapter)],\n});\n\nprogram.addHelpText(\n 'after',\n `\n${chalk.gray('Examples:')}\n $ jto docx generate doc.json ${chalk.dim('# Generate DOCX from JSON')}\n $ jto pptx generate slides.json ${chalk.dim('# Generate PPTX from JSON')}\n $ jto docx dev ${chalk.dim('# Start DOCX dev server')}\n $ jto pptx validate slides.json ${chalk.dim('# Validate PPTX JSON')}\n $ jto docx schemas ${chalk.dim('# Export DOCX JSON schemas')}\n $ jto pptx discover ${chalk.dim('# Discover PPTX plugins')}\n $ jto docx fonts install Inter ${chalk.dim('# Download a Google Font into ./fonts')}\n`\n);\n\nprogram.exitOverride();\n\n(async () => {\n try {\n await program.parseAsync(process.argv);\n } catch (error: any) {\n if (\n error.code === 'commander.version' ||\n error.code === 'commander.help' ||\n error.code === 'commander.helpDisplayed'\n ) {\n process.exit(0);\n }\n if (error.code === 'commander.executeSubCommandAsync') {\n process.exit(error.exitCode);\n }\n await renderLines(\n [{ text: `Error: ${error.message}`, tone: 'error' }],\n process.stderr\n );\n process.exit(1);\n }\n})();\n","import { Command } from 'commander';\nimport {\n type FormatAdapter,\n loadConfig,\n parsePort,\n formatError,\n renderLines,\n runTask,\n EXIT_CODES,\n} from '@json-to-office/jto-cli';\n\ninterface DevOptions {\n port?: string;\n host?: string;\n open?: boolean;\n config?: string;\n}\n\ninterface StoppableServer {\n stop(): Promise<void>;\n}\n\nfunction installShutdownHandlers(server: StoppableServer): void {\n let shutdownPromise: Promise<void> | undefined;\n\n const removeHandlers = () => {\n process.off('SIGINT', handleShutdown);\n process.off('SIGTERM', handleShutdown);\n };\n const handleShutdown = () => {\n shutdownPromise ??= (async () => {\n let exitCode: number = EXIT_CODES.OK;\n try {\n await runTask('Shutting down...', () => server.stop(), {\n success: 'Server stopped',\n failure: 'Failed to stop server',\n });\n } catch (error) {\n exitCode = EXIT_CODES.FAIL;\n await formatError(error);\n } finally {\n removeHandlers();\n }\n process.exit(exitCode);\n })();\n };\n\n process.once('SIGINT', handleShutdown);\n process.once('SIGTERM', handleShutdown);\n}\n\nasync function openBrowser(url: string): Promise<void> {\n const { execFile } = await import('node:child_process');\n const [command, args] =\n process.platform === 'darwin'\n ? ['open', [url]]\n : process.platform === 'win32'\n ? ['cmd', ['/c', 'start', '', url]]\n : ['xdg-open', [url]];\n\n await new Promise<void>((resolve, reject) => {\n execFile(command, args, (error) => (error ? reject(error) : resolve()));\n });\n}\n\nexport function createDevCommand(adapter: FormatAdapter): Command {\n const dev = new Command('dev');\n return dev\n .description('Start development server with web UI')\n .option(\n '-p, --port <port>',\n 'Port to run server on',\n String(adapter.defaultPort)\n )\n .option('-H, --host <host>', 'Host to bind to', 'localhost')\n .option('-o, --open', 'Open browser automatically')\n .option('-c, --config <path>', 'Path to config file')\n .action(async (options: DevOptions) => {\n try {\n const { server, url } = await runTask(\n `Starting ${adapter.name.toUpperCase()} dev server...`,\n async () => {\n // The adapter default goes in as the loader's fallback so an\n // explicit port equal to it stays explicit — no sentinel value.\n const config = await loadConfig(options.config, {\n defaultPort: adapter.defaultPort,\n });\n\n // CLI flag > config file > PORT > adapter default\n const portSource = dev.getOptionValueSource('port');\n const hostSource = dev.getOptionValueSource('host');\n if (portSource === 'cli') {\n // Same strict parser as PORT: `parseInt` would read \"8080x\" as\n // 8080 and bind a port the user never asked for.\n const port = parsePort(options.port);\n if (port === undefined) {\n throw new Error(\n `Invalid --port \"${options.port}\": expected an integer between 0 and 65535`\n );\n }\n config.server.port = port;\n }\n if (hostSource === 'cli') {\n config.server.host = options.host!;\n }\n\n const { UnifiedServer } = await import(\n '../server/unified-server.js'\n );\n const server = new UnifiedServer(adapter, config);\n await server.start();\n\n return {\n server,\n url: `http://${config.server.host}:${config.server.port}`,\n };\n },\n { success: 'Server ready', failure: 'Failed to start dev server' }\n );\n\n installShutdownHandlers(server);\n await renderLines([\n {\n text: `${adapter.name.toUpperCase()} Dev Server`,\n tone: 'success',\n },\n { text: `Local: ${url}` },\n { text: `API: ${url}/api/${adapter.name}/generate` },\n { text: `Health: ${url}/health` },\n { text: 'Press Ctrl+C to stop', tone: 'muted' },\n ]);\n\n // Open browser if requested\n if (options.open) {\n try {\n await openBrowser(url);\n } catch (error) {\n await renderLines([\n {\n text: `Could not open browser: ${\n error instanceof Error ? error.message : String(error)\n }`,\n tone: 'warning',\n },\n ]);\n }\n }\n } catch (error) {\n await formatError(error);\n process.exit(EXIT_CODES.FAIL);\n }\n });\n}\n"],"mappings":"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","names":["config","visit","filtered","cacheEvents","path","resolve","HTTPException","path","path","Type","HTTPException","fs","path","isRecord","visit","Hono","HTTPException","bodyLimit","PluginRegistry","path","config","Hono","PluginDiscoveryService","PluginRegistry","cleanupTypeBoxIds","dirname","fileURLToPath","__dirname","Hono","Hono","HTTPException","bodyLimit","POPULAR_GOOGLE_FONTS","createHash","HTTPException","Hono","bodyLimit","HTTPException","Hono","logger","dirname","fileURLToPath","__filename","__dirname","config","path","existsSync","resolve","fs","Command","renderLines","execFile","resolve","config","UnifiedServer","server","Command","renderLines"]}