@json-to-office/jto 0.15.0 → 0.17.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.
- package/dist/cli.js +130 -37
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/{HomePage-BTmw2QAf.js → HomePage-DMh-RgIS.js} +3 -3
- package/dist/client/assets/{HomePage-BTmw2QAf.js.map → HomePage-DMh-RgIS.js.map} +1 -1
- package/dist/client/assets/{JsonEditorPage-CRONWw-J.js → JsonEditorPage-D1guKBA7.js} +3 -3
- package/dist/client/assets/{JsonEditorPage-CRONWw-J.js.map → JsonEditorPage-D1guKBA7.js.map} +1 -1
- package/dist/client/assets/{MonacoPluginProvider-DhOIgTne.js → MonacoPluginProvider-BGk556YV.js} +3 -3
- package/dist/client/assets/{MonacoPluginProvider-DhOIgTne.js.map → MonacoPluginProvider-BGk556YV.js.map} +1 -1
- package/dist/client/assets/{button-ebCBEwlw.js → button-BcpACLlK.js} +2 -2
- package/dist/client/assets/{button-ebCBEwlw.js.map → button-BcpACLlK.js.map} +1 -1
- package/dist/client/assets/{editor-CB9BVJGn.js → editor-DuF2Zy4-.js} +2 -2
- package/dist/client/assets/{editor-CB9BVJGn.js.map → editor-DuF2Zy4-.js.map} +1 -1
- package/dist/client/assets/editor-monaco-json-BmSqeB6D.js +24 -0
- package/dist/client/assets/editor-monaco-json-BmSqeB6D.js.map +1 -0
- package/dist/client/assets/index-Auo5vP51.css +1 -0
- package/dist/client/assets/index-Cx5kWIBL.js +5 -0
- package/dist/client/assets/index-Cx5kWIBL.js.map +1 -0
- package/dist/client/assets/{preview-B4bcm38l.js → preview-WR-KEQG4.js} +2 -2
- package/dist/client/assets/{preview-B4bcm38l.js.map → preview-WR-KEQG4.js.map} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/render-server.d.ts +2 -0
- package/dist/render-server.js +255 -0
- package/dist/render-server.js.map +1 -0
- package/package.json +9 -9
- package/dist/client/assets/editor-monaco-json-DaGk8WIJ.js +0 -6
- package/dist/client/assets/editor-monaco-json-DaGk8WIJ.js.map +0 -1
- package/dist/client/assets/index-Cy63RxyT.js +0 -5
- package/dist/client/assets/index-Cy63RxyT.js.map +0 -1
- package/dist/client/assets/index-DiQf3mCW.css +0 -1
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/font-staging/noop-stager.ts","../src/server/services/font-staging/types.ts","../src/server/services/font-staging/fontconfig-stager.ts","../src/server/services/font-staging/windows-stager.ts","../src/server/services/font-staging/macos-stager.ts","../src/server/services/font-staging/index.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/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/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\nfunction parseEnv(env: NodeJS.ProcessEnv) {\n return {\n NODE_ENV: (env.NODE_ENV || 'development') as 'development' | 'production' | 'test',\n PORT: parseInt(env.PORT || '3003', 10),\n CORS_ORIGIN: env.CORS_ORIGIN || '*',\n API_KEY: env.API_KEY,\n API_KEY_HEADER: env.API_KEY_HEADER || 'x-api-key',\n RATE_LIMIT_WINDOW_MS: parseInt(env.RATE_LIMIT_WINDOW_MS || '900000', 10),\n RATE_LIMIT_MAX: parseInt(env.RATE_LIMIT_MAX || '100', 10),\n MAX_FILE_SIZE: parseInt(env.MAX_FILE_SIZE || '10485760', 10),\n UPLOAD_DIR: env.UPLOAD_DIR || 'uploads',\n LIBREOFFICE_PATH: env.LIBREOFFICE_PATH,\n LIBREOFFICE_TIMEOUT_MS: env.LIBREOFFICE_TIMEOUT_MS\n ? parseInt(env.LIBREOFFICE_TIMEOUT_MS, 10)\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: parseInt(env.CACHE_MAX_SIZE_MB || '100', 10),\n CACHE_TTL_SECONDS: parseInt(env.CACHE_TTL_SECONDS || '3600', 10),\n CACHE_MAX_ITEMS: parseInt(env.CACHE_MAX_ITEMS || '1000', 10),\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: Boolean(parsedEnv.API_KEY),\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 },\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 type FontRegistryEntry,\n type ResolvedFont,\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\nexport function autoGoogleFontEntries(\n names: Set<string>,\n skipFamilies: Set<string>,\n referencedWeights?: Set<number>,\n referencedItalic?: boolean,\n warnings?: string[]\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 `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?: any[] | 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 const callerFamilies = new Set(\n callerExtraEntries.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: string[] = [];\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 `[FONT_OVERRIDE_LOCAL] ${e.family}: caller-supplied source used; Google Fonts auto-fetch skipped for this family.`\n );\n }\n }\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.\n const bypassCache =\n options?.bypassCache === true || extraEntries.length > 0;\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 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 };\n const cacheKey = this.cacheService.generateCacheKey(cacheKeyData);\n const hasDynamicContent = this.cacheService.hasDynamicContent(config);\n\n // Try cache\n if (!bypassCache && !hasDynamicContent) {\n const cachedBuffer = this.cacheService.get(cacheKey);\n if (cachedBuffer) {\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: cachedBuffer,\n cached: true,\n warnings: 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 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 const needsFontOpts =\n extraEntries.length > 0 ||\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 if (registry.hasPlugins()) {\n const plugins = registry.getPlugins();\n const generator = await this.adapter.createGenerator(plugins, {\n customThemes,\n fonts: fontOpts,\n });\n buffer = await generator.generateBuffer(config);\n } else {\n buffer = await this.adapter.generateBuffer(config, {\n customThemes,\n fonts: fontOpts,\n });\n }\n\n // Store in cache\n this.cacheService.set(cacheKey, buffer, config, {\n bypassCache: bypassCache || hasDynamicContent,\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 const extraWarnings = overrideWarnings.map((message) => ({\n component: 'fontRegistry',\n message,\n severity: 'info' as const,\n context: { code: 'FONT_OVERRIDE_LOCAL' },\n }));\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 return {\n filename: `${config.metadata?.title || this.adapter.label}${this.adapter.extension}`,\n fileId: Date.now().toString(),\n buffer,\n cached: false,\n warnings: extraWarnings.length > 0 ? extraWarnings : 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';\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, Buffer>;\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, Buffer>({\n max: config.cache.maxItems,\n maxSize: maxSizeBytes,\n sizeCalculation: (value: Buffer) => value.length,\n ttl: config.cache.ttlSeconds * 1000,\n dispose: (\n _value: Buffer,\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): Buffer | 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: Buffer,\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 type { FontStager, FontStageHandle } from './types';\n\nexport class NoopFontStager implements FontStager {\n async stage(): Promise<FontStageHandle> {\n return {\n envOverrides: {},\n cleanup: async () => {},\n };\n }\n}\n","/**\n * Make resolved fonts visible to the LibreOffice child process for the\n * duration of one PDF conversion, then clean up.\n *\n * Linux/macOS: fontconfig + FONTCONFIG_FILE env var.\n * Windows: GDI session registration via koffi (AddFontResourceW).\n *\n * The converter calls `stage(fonts, tempDir)` before spawning soffice, merges\n * `envOverrides` into the child process env, waits for conversion, then\n * awaits `cleanup()` regardless of success or failure.\n */\n\nimport type { ResolvedFont } from '@json-to-office/shared';\n\nexport interface FontStageHandle {\n /** Merged into the child process env. Empty object if nothing to stage. */\n envOverrides: Record<string, string>;\n /** Always call in a finally block. Safe to call multiple times (idempotent). */\n cleanup(): Promise<void>;\n}\n\nexport interface FontStager {\n stage(fonts: ResolvedFont[], tempDir: string): Promise<FontStageHandle>;\n}\n\n/** Per-process monotonic counter to disambiguate concurrent conversions. */\nlet counter = 0;\nexport function nextStagingId(): string {\n counter += 1;\n return `${process.pid}-${counter}`;\n}\n\n/** Sanitize a font family for use in a filename. */\nexport function safeFilenamePart(s: string): string {\n return s.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 48);\n}\n","/**\n * Linux + macOS: use fontconfig to expose staged TTFs to LibreOffice.\n *\n * Writes each resolved font to `<tempDir>/fonts/` and a minimal\n * fontconfig.xml that includes that dir plus the system font config.\n * LibreOffice honors the per-invocation FONTCONFIG_FILE env var.\n *\n * No cleanup work is needed here — the converter removes the whole tempDir\n * in its own finally block.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport {\n synthesizeFamilyName,\n rewriteFontFamilyName,\n} from '@json-to-office/shared';\nimport type { FontStager, FontStageHandle } from './types';\nimport { nextStagingId, safeFilenamePart } from './types';\n\nconst SYSTEM_FONTS_CONF_CANDIDATES = [\n '/etc/fonts/fonts.conf',\n '/opt/homebrew/etc/fonts/fonts.conf',\n '/usr/local/etc/fonts/fonts.conf',\n];\n\nexport class FontconfigStager implements FontStager {\n async stage(\n fonts: ResolvedFont[],\n tempDir: string\n ): Promise<FontStageHandle> {\n const id = nextStagingId();\n const fontsDir = path.join(tempDir, 'fonts');\n await fs.mkdir(fontsDir, { recursive: true });\n\n let serial = 0;\n for (const r of fonts) {\n if (r.sources.length === 0) continue;\n for (const s of r.sources) {\n serial += 1;\n const suffix = s.italic ? 'i' : 'r';\n // Rewrite `name` table so fontconfig indexes the file under the\n // synthetic sub-family (\"Inter Light\"), matching the doc's\n // `rFonts`/`fontFace` references after synthesizeFamilyName.\n const synth = synthesizeFamilyName(r.family, s.weight, s.italic);\n const data =\n synth.family === r.family\n ? s.data\n : rewriteFontFamilyName(s.data, synth.family);\n const name = `${safeFilenamePart(synth.family)}-${s.weight}${suffix}-${id}-${serial}.ttf`;\n await fs.writeFile(path.join(fontsDir, name), data);\n }\n }\n\n // Freeze the fonts dir read-only after staging so a misbehaving\n // fontconfig run (or a concurrent soffice spawn) can't corrupt the\n // file contents we just wrote. fc-cache writes its own indexes into\n // `cacheDir` (next step), which stays writable. The whole tree gets\n // rm'd by the converter in finally, so mode matters only during the\n // conversion window.\n await fs.chmod(fontsDir, 0o555).catch(() => {\n // Some filesystems (e.g. certain Windows-mounted shares under WSL)\n // refuse chmod — ignore and proceed. The defensive-in-depth case\n // still wins on native Linux/macOS.\n });\n const includeLines = await this.pickSystemIncludes();\n // Redirect fontconfig's scan cache into tempDir. Without this, fontconfig\n // writes cache entries for `fontsDir` into the user's ~/.cache/fontconfig\n // and leaves them behind after tempDir is rm'd. Per-invocation isolation\n // also prevents two concurrent conversions from racing on the same\n // fontconfig cache directory.\n const cacheDir = path.join(tempDir, 'fc-cache');\n await fs.mkdir(cacheDir, { recursive: true });\n const configPath = path.join(tempDir, 'fontconfig.xml');\n const configXml = [\n '<?xml version=\"1.0\"?>',\n '<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">',\n '<fontconfig>',\n ` <dir>${escapeXml(fontsDir)}</dir>`,\n ` <cachedir>${escapeXml(cacheDir)}</cachedir>`,\n ...includeLines,\n '</fontconfig>',\n '',\n ].join('\\n');\n await fs.writeFile(configPath, configXml, 'utf8');\n\n return {\n envOverrides: {\n FONTCONFIG_FILE: configPath,\n XDG_CACHE_HOME: cacheDir,\n },\n cleanup: async () => {\n // Cleanup handled by converter's tempDir rm -rf.\n },\n };\n }\n\n private async pickSystemIncludes(): Promise<string[]> {\n for (const candidate of SYSTEM_FONTS_CONF_CANDIDATES) {\n try {\n await fs.access(candidate);\n return [\n ` <include ignore_missing=\"yes\">${escapeXml(candidate)}</include>`,\n ];\n } catch {\n /* try next */\n }\n }\n // Fall back to the conventional path; fontconfig will fail softly.\n return [` <include ignore_missing=\"yes\">/etc/fonts/fonts.conf</include>`];\n }\n}\n\nfunction escapeXml(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n","/**\n * Windows: register staged TTFs with GDI via AddFontResourceW so the soffice\n * child process finds them at startup. Forces LibreOffice onto the GDI\n * backend via SAL_DISABLE_SKIA=1 — Skia/DirectWrite doesn't reliably pick\n * up GDI-registered fonts on recent LO builds.\n *\n * Registration is process-scoped: Node stays alive for the full conversion,\n * so the fonts persist until cleanup. If Node crashes, GDI releases them on\n * process exit — no logout-scope leaks.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport {\n synthesizeFamilyName,\n rewriteFontFamilyName,\n} from '@json-to-office/shared';\nimport type { FontStager, FontStageHandle } from './types';\nimport { nextStagingId, safeFilenamePart } from './types';\n\ntype KoffiLib = {\n func: (sig: string) => (...args: unknown[]) => number | boolean;\n};\ntype KoffiModule = {\n load: (libName: string) => KoffiLib;\n};\n\n// Lazy-load koffi so Linux/macOS don't incur the FFI init cost.\nlet cachedBindings: {\n addFont: (pathW: string) => number;\n removeFont: (pathW: string) => boolean;\n} | null = null;\n\nasync function getGdiBindings() {\n if (cachedBindings) return cachedBindings;\n const koffi = (await import('koffi')) as unknown as {\n default?: KoffiModule;\n } & KoffiModule;\n const mod = koffi.default ?? koffi;\n const gdi32 = mod.load('gdi32.dll');\n cachedBindings = {\n addFont: gdi32.func('int __stdcall AddFontResourceW(str16)') as (\n path: string\n ) => number,\n removeFont: gdi32.func('bool __stdcall RemoveFontResourceW(str16)') as (\n path: string\n ) => boolean,\n };\n return cachedBindings;\n}\n\nexport class WindowsFontStager implements FontStager {\n async stage(\n fonts: ResolvedFont[],\n tempDir: string\n ): Promise<FontStageHandle> {\n const id = nextStagingId();\n const fontsDir = path.join(tempDir, 'fonts');\n await fs.mkdir(fontsDir, { recursive: true });\n\n const stagedPaths: string[] = [];\n let serial = 0;\n for (const r of fonts) {\n if (r.sources.length === 0) continue;\n for (const s of r.sources) {\n serial += 1;\n const suffix = s.italic ? 'i' : 'r';\n // Rewrite the TTF's internal family name so GDI registers the\n // file under the synthetic sub-family the doc references.\n const synth = synthesizeFamilyName(r.family, s.weight, s.italic);\n const data =\n synth.family === r.family\n ? s.data\n : rewriteFontFamilyName(s.data, synth.family);\n const name = `${safeFilenamePart(synth.family)}-${s.weight}${suffix}-${id}-${serial}.ttf`;\n const fullPath = path.join(fontsDir, name);\n await fs.writeFile(fullPath, data);\n stagedPaths.push(fullPath);\n }\n }\n\n if (stagedPaths.length === 0) {\n return { envOverrides: {}, cleanup: async () => {} };\n }\n\n const { addFont, removeFont } = await getGdiBindings();\n const registered: string[] = [];\n for (const p of stagedPaths) {\n const added = addFont(p);\n if (added > 0) registered.push(p);\n }\n\n let cleaned = false;\n return {\n envOverrides: {\n // Force GDI backend so the freshly-registered fonts are visible.\n // Skia on Windows uses DirectWrite which does not reliably see\n // fonts added via AddFontResourceW.\n SAL_DISABLE_SKIA: '1',\n },\n cleanup: async () => {\n if (cleaned) return;\n cleaned = true;\n for (const p of registered) {\n try {\n removeFont(p);\n } catch {\n // Swallow — GDI will drop it on process exit anyway.\n }\n }\n },\n };\n }\n}\n","/**\n * macOS: make staged fonts visible to the soffice child process by\n * registering them *inside* soffice via a Python macro bound to the\n * `OnStartApp` event.\n *\n * Why this works on macOS 26. Apple tightened `CTFontManagerScopeSession`\n * and `kCTFontManagerScopePersistent` to require signed+notarized callers\n * (unsigned Node processes get `paramErr -50`), and `Process` scope only\n * registers fonts for the calling process — so the Node server can't\n * register fonts the soffice child sees. But Process scope DOES work from\n * inside soffice. LibreOffice for macOS bundles Python 3.12 with `ctypes`,\n * and UNO lets us bind a Python macro to application-start events. We seed\n * a per-invocation UserInstallation profile with:\n *\n * - `user/Scripts/python/JtoFontRegister.py` — a ~20-line macro that\n * reads `JTO_FONT_PATHS` from the process env and calls\n * `CTFontManagerRegisterFontsForURL(url, kScopeProcess, NULL)` via\n * ctypes for each path (Process = 1 in Core Text's scope enum).\n * - `user/registrymodifications.xcu` — binds the macro to `OnStartApp`\n * and sets `MacroSecurityLevel=0` for this ephemeral profile only.\n *\n * SECURITY INVARIANT — macro execution scope. The seeded profile disables\n * soffice's macro-security prompt (`MacroSecurityLevel=0`) so our\n * OnStartApp macro runs without a dialog. This profile MUST ONLY be used\n * to open files this server just generated (i.e., well-formed outputs\n * from `@json-to-office/core-*`). Piping user-supplied .docx/.pptx/.odt\n * through a soffice invocation that uses this stager would execute any\n * embedded VBA/Basic macros silently — an RCE primitive. If a future\n * code path ever converts user-supplied documents (e.g. \"PDF-ify my\n * upload\"), it must build a separate converter that does NOT share this\n * profile, or call soffice with `--safe-mode` / a default profile.\n *\n * Flow: the converter spawns\n * `soffice --headless -env:UserInstallation=file://<tempDir>/user-profile ...`\n * with env `{ JTO_FONT_PATHS: \"<ttf1>:<ttf2>:...\" }`. LO boots, reads our\n * seeded profile, fires `OnStartApp`, runs our macro, registers each\n * staged TTF at Process scope in its own process. Font enumeration then\n * resolves the synthetic family names (`Inter Bold`, `Source Code Pro\n * Medium`, …) against those Process-scope registrations. The PDF export\n * ships the correct glyphs.\n *\n * Elegant side-effects:\n * - Nothing outside the converter's `tempDir` is touched. The user's\n * real `~/Library/Fonts` and `~/Library/Application Support/LibreOffice`\n * stay untouched.\n * - Cleanup is the converter's `fs.rm(tempDir, …)` — no orphan sweep\n * needed. If Node crashes mid-conversion, the per-invocation tempDir\n * is reaped by macOS tmpreaper (or the OS's next boot cleanup).\n * - No DYLD injection, no notarized helper, no filesystem-scan races.\n *\n * Failure mode: if LibreOffice can't run the macro for any reason\n * (macro-security policy applied at bootstrap before our XCU loads,\n * Python not present in a minimal LO build, …) the soffice process still\n * runs and produces a PDF — just with system-fallback fonts, exactly the\n * pre-fix behavior. Non-catastrophic. Diagnose via stderr: the macro\n * writes failures to stderr via `print(..., file=sys.stderr)`.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport {\n synthesizeFamilyName,\n rewriteFontFamilyName,\n} from '@json-to-office/shared';\nimport type { FontStager, FontStageHandle } from './types';\nimport { nextStagingId, safeFilenamePart } from './types';\n\n/**\n * Python macro source. Written verbatim into\n * `<profile>/user/Scripts/python/JtoFontRegister.py`. Kept inline (rather\n * than a separate .py asset) so this TypeScript module is self-contained\n * and survives bundler reshuffles — no runtime file-system lookup for a\n * static asset.\n */\nconst PYTHON_MACRO = `# Auto-generated by @json-to-office/jto. Runs inside soffice on OnStartApp\n# to make staged fonts visible to LibreOffice's font enumeration. macOS 26\n# blocks Session/Persistent CT registration for unsigned callers, but\n# Process scope still works from inside the target process — which is\n# exactly where this macro runs.\nimport os\nimport sys\nimport ctypes\nimport ctypes.util\n\n\ndef _log(msg):\n # soffice swallows Python stdout in headless mode; stderr surfaces to\n # the parent's pipe. The stager doesn't read this today but the\n # converter logs stderr on failure, which is how we'll debug.\n sys.stderr.write(\"[jto-font-register] \" + msg + \"\\\\n\")\n\n\ndef register(*_args):\n paths_env = os.environ.get(\"JTO_FONT_PATHS\", \"\")\n if not paths_env:\n return\n try:\n cf = ctypes.CDLL(ctypes.util.find_library(\"CoreFoundation\"))\n ct = ctypes.CDLL(ctypes.util.find_library(\"CoreText\"))\n except Exception as e:\n _log(\"failed to load CoreFoundation/CoreText: \" + repr(e))\n return\n cf.CFURLCreateFromFileSystemRepresentation.argtypes = [\n ctypes.c_void_p, ctypes.c_char_p, ctypes.c_long, ctypes.c_bool,\n ]\n cf.CFURLCreateFromFileSystemRepresentation.restype = ctypes.c_void_p\n cf.CFRelease.argtypes = [ctypes.c_void_p]\n ct.CTFontManagerRegisterFontsForURL.argtypes = [\n ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p,\n ]\n ct.CTFontManagerRegisterFontsForURL.restype = ctypes.c_bool\n\n kCTFontManagerScopeProcess = 1\n registered = 0\n for p in paths_env.split(os.pathsep):\n if not p:\n continue\n try:\n b = p.encode(\"utf-8\")\n url = cf.CFURLCreateFromFileSystemRepresentation(\n None, b, len(b), False\n )\n if not url:\n _log(\"CFURL failed for \" + p)\n continue\n ok = ct.CTFontManagerRegisterFontsForURL(\n url, kCTFontManagerScopeProcess, None\n )\n cf.CFRelease(url)\n if ok:\n registered += 1\n else:\n _log(\"CT register returned false for \" + p)\n except Exception as e:\n _log(\"exception registering \" + p + \": \" + repr(e))\n _log(\"registered \" + str(registered) + \" font(s) at Process scope\")\n\n\n# Expose under \"register\" (event-binding URL) and module-level run so\n# command-line vnd.sun.star.script invocation works either way.\ng_exportedScripts = (register,)\n`;\n\n/**\n * XCU that LO merges into its Bootstrap registry on startup. Two keys:\n *\n * 1. `/org.openoffice.Office.Events/ApplicationEvents/Bindings/OnStartApp`\n * → fires our Python macro before any document is loaded, so font\n * registration completes before LO enumerates fonts for rendering.\n *\n * 2. `/org.openoffice.Office.Common/Security/Scripting/MacroSecurityLevel`\n * → 0 (allow all). This only applies to the ephemeral UserInstallation\n * profile we create under `<tempDir>/user-profile`; the user's real\n * LibreOffice profile config is untouched. Scope of the security\n * relaxation is bounded by the per-invocation profile's lifetime.\n */\nconst REGISTRY_MOD_XCU = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items xmlns:oor=\"http://openoffice.org/2001/registry\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n <item oor:path=\"/org.openoffice.Office.Events/ApplicationEvents/Bindings\">\n <node oor:name=\"OnStartApp\" oor:op=\"replace\">\n <prop oor:name=\"BindingURL\" oor:type=\"xs:string\">\n <value>vnd.sun.star.script:JtoFontRegister.py$register?language=Python&location=user</value>\n </prop>\n </node>\n </item>\n <item oor:path=\"/org.openoffice.Office.Common/Security/Scripting\">\n <prop oor:name=\"MacroSecurityLevel\" oor:op=\"fuse\">\n <value>0</value>\n </prop>\n </item>\n</oor:items>\n`;\n\nexport class MacOSCoreTextStager implements FontStager {\n async stage(\n fonts: ResolvedFont[],\n tempDir: string\n ): Promise<FontStageHandle> {\n const embeddable = fonts.filter((r) => r.sources.length > 0);\n if (embeddable.length === 0) {\n return { envOverrides: {}, cleanup: async () => {} };\n }\n\n // Fonts go to a subdir of the converter's tempDir. No ~/Library writes.\n const fontsDir = path.join(tempDir, 'fonts');\n await fs.mkdir(fontsDir, { recursive: true });\n\n const id = nextStagingId();\n const fontPaths: string[] = [];\n const staged: {\n family: string;\n weight: number;\n italic: boolean;\n path: string;\n }[] = [];\n let serial = 0;\n for (const r of embeddable) {\n for (const s of r.sources) {\n serial += 1;\n const suffix = s.italic ? 'i' : 'r';\n // Rewrite the TTF's internal family name to match the synthetic\n // sub-family the doc references (e.g. \"Inter Light\"). Without\n // this, Core Text indexes the staged file as \"Inter\" and\n // LibreOffice can't resolve `rFonts w:ascii=\"Inter Light\"`.\n const synth = synthesizeFamilyName(r.family, s.weight, s.italic);\n const data =\n synth.family === r.family\n ? s.data\n : rewriteFontFamilyName(s.data, synth.family);\n const name = `${safeFilenamePart(synth.family)}-${s.weight}${suffix}-${id}-${serial}.ttf`;\n const full = path.join(fontsDir, name);\n await fs.writeFile(full, data);\n fontPaths.push(full);\n staged.push({\n family: synth.family,\n weight: s.weight,\n italic: s.italic,\n path: full,\n });\n }\n }\n\n if (process.env.JTO_DEBUG_FONTS === '1') {\n // eslint-disable-next-line no-console\n console.log(\n '[jto macos-stager] staged ' +\n staged.length +\n ' font(s) for CT Process-scope registration; JTO_FONT_PATHS has ' +\n fontPaths.length +\n ' entries\\n' +\n staged\n .map(\n (s) =>\n ` ${s.family} (w=${s.weight}${s.italic ? ' italic' : ''}) → ${path.basename(s.path)}`\n )\n .join('\\n')\n );\n }\n\n // Seed the per-invocation UserInstallation profile. The converter\n // spawns soffice with `-env:UserInstallation=file://<tempDir>/user-profile`,\n // so LO reads the macro + event binding from these exact paths.\n const profileUser = path.join(tempDir, 'user-profile', 'user');\n const scriptsDir = path.join(profileUser, 'Scripts', 'python');\n await fs.mkdir(scriptsDir, { recursive: true });\n await fs.writeFile(\n path.join(scriptsDir, 'JtoFontRegister.py'),\n PYTHON_MACRO\n );\n await fs.writeFile(\n path.join(profileUser, 'registrymodifications.xcu'),\n REGISTRY_MOD_XCU\n );\n\n return {\n envOverrides: {\n // Colon-separated list of staged TTF paths (`:` matches Python's\n // `os.pathsep` on macOS). The macro reads this at OnStartApp.\n JTO_FONT_PATHS: fontPaths.join(':'),\n // Force LibreOffice's Core Graphics backend. Skia on macOS can\n // skip Core Text's freshly-registered fonts in some builds.\n SAL_DISABLE_SKIA: '1',\n },\n cleanup: async () => {\n // No-op: the converter's `fs.rm(tempDir, { recursive: true })` in\n // its own finally block sweeps everything we wrote here.\n },\n };\n }\n}\n","/**\n * Factory entry point for the font staging pipeline used by the\n * LibreOffice-based PDF preview.\n */\n\nimport type { FontStager } from './types';\nimport { NoopFontStager } from './noop-stager';\nimport { FontconfigStager } from './fontconfig-stager';\nimport { WindowsFontStager } from './windows-stager';\nimport { MacOSCoreTextStager } from './macos-stager';\n\nexport type { FontStager, FontStageHandle } from './types';\n\nconst cached = new Map<NodeJS.Platform, FontStager>();\n\nexport function getFontStager(\n platform: NodeJS.Platform = process.platform\n): FontStager {\n const hit = cached.get(platform);\n if (hit) return hit;\n let stager: FontStager;\n switch (platform) {\n case 'win32':\n stager = new WindowsFontStager();\n break;\n case 'darwin':\n // LibreOffice-for-macOS uses Core Text for font enumeration and does\n // not honor FONTCONFIG_FILE reliably. macOS 26 further blocks\n // Session/Persistent CT registration for unsigned callers, and\n // Process scope only works inside the target process. We register\n // fonts from *inside* soffice via a Python UNO macro bound to\n // OnStartApp, seeded into a per-invocation UserInstallation profile.\n // The user's ~/Library/Fonts is never touched. See macos-stager.ts.\n stager = new MacOSCoreTextStager();\n break;\n case 'linux':\n case 'freebsd':\n case 'openbsd':\n stager = new FontconfigStager();\n break;\n default:\n stager = new NoopFontStager();\n }\n cached.set(platform, stager);\n return stager;\n}\n\nexport {\n NoopFontStager,\n FontconfigStager,\n WindowsFontStager,\n MacOSCoreTextStager,\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 './font-staging/index.js';\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 module types.\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 },\n { additionalProperties: true }\n )\n ),\n },\n { additionalProperties: true }\n);\n\n/**\n * Loose document validation request schema that allows plugin module types.\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\ninterface RateLimitOptions {\n limit: number;\n window: number; // milliseconds\n keyGenerator?: (c: any) => string;\n}\n\n// In-memory store for rate limiting (use Redis in production)\nconst rateLimitStore = new Map<string, { count: number; resetTime: number }>();\n\n/**\n * Rate limiting middleware for Hono\n */\nexport const rateLimiter = (options: RateLimitOptions): MiddlewareHandler => {\n const { limit, window, keyGenerator } = options;\n\n return async (c, next) => {\n const key = keyGenerator\n ? keyGenerator(c)\n : c.req.header('X-Real-IP') || c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() || 'anonymous';\n const now = Date.now();\n\n // Clean up expired entries\n for (const [k, v] of rateLimitStore.entries()) {\n if (v.resetTime < now) {\n rateLimitStore.delete(k);\n }\n }\n\n const record = rateLimitStore.get(key);\n\n if (!record) {\n // First request\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 { 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 { type FormatAdapter, PluginRegistry } from '@json-to-office/jto-cli';\nimport {\n LibreOfficeBinaryNotFoundError,\n LibreOfficeConversionError,\n LibreOfficeOutputNotFoundError,\n LibreOfficeTimeoutError,\n} from '../services/libreoffice-converter.js';\n\nexport function createFormatRouter(adapter: FormatAdapter) {\n const router = new Hono<AppEnv>();\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 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 const result = await generatorService.generate({\n jsonDefinition,\n customThemes,\n options: {\n ...options,\n ...(sanitizedFonts !== undefined && { fonts: sanitizedFonts }),\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 if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n if (\n msg.includes('invalid') ||\n msg.includes('validation') ||\n msg.includes('missing required') ||\n msg.includes('unknown component')\n ) {\n throw new HTTPException(400, { message: error.message });\n }\n }\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 // The adapter's validateDocument is a no-op stub; use the real\n // TypeBox document validation from shared-docx (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 rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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\n const arrayBuffer = await (file as File).arrayBuffer();\n const inputBuffer = Buffer.from(arrayBuffer);\n const pdfBuffer = await libreOfficeService.convertToPdf(\n inputBuffer,\n (file as File).name\n );\n\n const pdfName =\n ((file as File).name || 'preview').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\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n }>(c, 'json');\n\n try {\n const generated = await generatorService.generate({\n jsonDefinition,\n customThemes,\n options: { bypassCache: true },\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 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 } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n try {\n const config =\n typeof jsonDefinition === 'string'\n ? JSON.parse(jsonDefinition)\n : jsonDefinition;\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 theme: customThemes ? Object.values(customThemes)[0] : undefined,\n });\n\n if (generatorResult.getStandardComponentsDefinition) {\n const standardComponents =\n await generatorResult.getStandardComponentsDefinition(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 throw new HTTPException(500, {\n message: 'Failed to get standard components definition',\n });\n }\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 const components = (await adapter.getComponentCacheStats?.()) ?? null;\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 ...(components ? { components } : {}),\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 // GET /cache-analytics\n router.get('/cache-analytics', async (c) => {\n try {\n const analytics = await adapter.getComponentCacheAnalytics?.();\n if (!analytics) {\n return c.json({\n success: true,\n data: null,\n meta: { timestamp: new Date().toISOString() },\n });\n }\n return c.json({\n success: true,\n data: analytics,\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to get cache analytics', { error });\n throw new HTTPException(500, {\n message: 'Failed to get cache analytics',\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 { invalidateAllCaches } = await import('@json-to-office/jto-cli');\n invalidateAllCaches();\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 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\nfunction getSelectedPlugins(pluginNames?: string[]) {\n const registry = PluginRegistry.getInstance();\n if (!registry.hasPlugins()) return [];\n\n const plugins = pluginNames?.length\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 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: 'https://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: 'https://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: 'https://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 const pluginNames = pluginsParam\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';\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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';\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 { MiddlewareHandler } from 'hono';\nimport { config } from '../../config';\n\n/**\n * API Key authentication middleware for Hono\n */\nexport const apiKeyAuthMiddleware: MiddlewareHandler = async (c, next) => {\n // Skip auth if not configured\n if (!config.features.apiKey || !config.API_KEY) {\n return next();\n }\n\n const apiKey = c.req.header(config.API_KEY_HEADER);\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 (apiKey !== config.API_KEY) {\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","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 { 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 { 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';\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.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 // 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);\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);\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 } 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 console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n})();\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport boxen from 'boxen';\nimport {\n type FormatAdapter,\n loadConfig,\n formatError,\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\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 const spinner = ora(\n `Starting ${adapter.name.toUpperCase()} dev server...`\n ).start();\n\n try {\n const config = await loadConfig(options.config);\n\n // CLI flag > adapter default > config file default\n const portSource = dev.getOptionValueSource('port');\n const hostSource = dev.getOptionValueSource('host');\n if (portSource === 'cli') {\n config.server.port = parseInt(options.port!, 10);\n } else if (\n config.server.port === 3003 &&\n adapter.defaultPort !== 3003\n ) {\n config.server.port = adapter.defaultPort;\n }\n if (hostSource === 'cli') {\n config.server.host = options.host!;\n }\n\n const { UnifiedServer } = await import('../server/unified-server.js');\n const server = new UnifiedServer(adapter, config);\n await server.start();\n\n const url = `http://${config.server.host}:${config.server.port}`;\n spinner.succeed('Server ready');\n\n console.log(\n boxen(\n chalk.bold(`${adapter.name.toUpperCase()} Dev Server\\n\\n`) +\n `${chalk.cyan('Local:')} ${chalk.bold(url)}\\n` +\n `${chalk.cyan('API:')} ${url}/api/${adapter.name}/generate\\n` +\n `${chalk.cyan('Health:')} ${url}/health\\n\\n` +\n chalk.gray('Press Ctrl+C to stop'),\n {\n padding: 1,\n borderColor: 'green',\n borderStyle: 'round',\n }\n )\n );\n\n // Open browser if requested\n if (options.open) {\n const { execFile } = await import('child_process');\n const cmd =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n execFile(cmd, [url]);\n }\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log(chalk.yellow('\\nShutting down...'));\n await server.stop();\n process.exit(EXIT_CODES.OK);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n } catch (error: any) {\n spinner.fail('Failed to start dev server');\n formatError(error);\n process.exit(EXIT_CODES.FAIL);\n }\n });\n}\n"],"mappings":"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","names":["config","filtered","cacheEvents","path","fs","path","synthesizeFamilyName","rewriteFontFamilyName","fs","path","synthesizeFamilyName","rewriteFontFamilyName","fs","path","resolve","HTTPException","Hono","HTTPException","PluginRegistry","config","Hono","PluginRegistry","cleanupTypeBoxIds","fileURLToPath","__dirname","Hono","Hono","HTTPException","bodyLimit","POPULAR_GOOGLE_FONTS","HTTPException","Hono","Hono","logger","dirname","fileURLToPath","__filename","__dirname","config","path","existsSync","resolve","fs","Command","chalk","config","UnifiedServer","execFile","Command","chalk"]}
|
|
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/font-staging/noop-stager.ts","../src/server/services/font-staging/types.ts","../src/server/services/font-staging/fontconfig-stager.ts","../src/server/services/font-staging/windows-stager.ts","../src/server/services/font-staging/macos-stager.ts","../src/server/services/font-staging/index.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/rasterize-route.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/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\nfunction parseEnv(env: NodeJS.ProcessEnv) {\n return {\n NODE_ENV: (env.NODE_ENV || 'development') as 'development' | 'production' | 'test',\n PORT: parseInt(env.PORT || '3003', 10),\n CORS_ORIGIN: env.CORS_ORIGIN || '*',\n API_KEY: env.API_KEY,\n API_KEY_HEADER: env.API_KEY_HEADER || 'x-api-key',\n RATE_LIMIT_WINDOW_MS: parseInt(env.RATE_LIMIT_WINDOW_MS || '900000', 10),\n RATE_LIMIT_MAX: parseInt(env.RATE_LIMIT_MAX || '100', 10),\n MAX_FILE_SIZE: parseInt(env.MAX_FILE_SIZE || '10485760', 10),\n UPLOAD_DIR: env.UPLOAD_DIR || 'uploads',\n LIBREOFFICE_PATH: env.LIBREOFFICE_PATH,\n LIBREOFFICE_TIMEOUT_MS: env.LIBREOFFICE_TIMEOUT_MS\n ? parseInt(env.LIBREOFFICE_TIMEOUT_MS, 10)\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: parseInt(env.CACHE_MAX_SIZE_MB || '100', 10),\n CACHE_TTL_SECONDS: parseInt(env.CACHE_TTL_SECONDS || '3600', 10),\n CACHE_MAX_ITEMS: parseInt(env.CACHE_MAX_ITEMS || '1000', 10),\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: Boolean(parsedEnv.API_KEY),\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 },\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 type FontRegistryEntry,\n type ResolvedFont,\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\nexport function autoGoogleFontEntries(\n names: Set<string>,\n skipFamilies: Set<string>,\n referencedWeights?: Set<number>,\n referencedItalic?: boolean,\n warnings?: string[]\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 `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?: any[] | 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 const callerFamilies = new Set(\n callerExtraEntries.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: string[] = [];\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 `[FONT_OVERRIDE_LOCAL] ${e.family}: caller-supplied source used; Google Fonts auto-fetch skipped for this family.`\n );\n }\n }\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.\n const bypassCache =\n options?.bypassCache === true || extraEntries.length > 0;\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 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 };\n const cacheKey = this.cacheService.generateCacheKey(cacheKeyData);\n const hasDynamicContent = this.cacheService.hasDynamicContent(config);\n\n // Try cache\n if (!bypassCache && !hasDynamicContent) {\n const cachedBuffer = this.cacheService.get(cacheKey);\n if (cachedBuffer) {\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: cachedBuffer,\n cached: true,\n warnings: 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 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 const needsFontOpts =\n extraEntries.length > 0 ||\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 if (registry.hasPlugins()) {\n const plugins = registry.getPlugins();\n const generator = await this.adapter.createGenerator(plugins, {\n customThemes,\n fonts: fontOpts,\n });\n buffer = await generator.generateBuffer(config);\n } else {\n buffer = await this.adapter.generateBuffer(config, {\n customThemes,\n fonts: fontOpts,\n });\n }\n\n // Store in cache\n this.cacheService.set(cacheKey, buffer, config, {\n bypassCache: bypassCache || hasDynamicContent,\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 const extraWarnings = overrideWarnings.map((message) => ({\n component: 'fontRegistry',\n message,\n severity: 'info' as const,\n context: { code: 'FONT_OVERRIDE_LOCAL' },\n }));\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 return {\n filename: `${config.metadata?.title || this.adapter.label}${this.adapter.extension}`,\n fileId: Date.now().toString(),\n buffer,\n cached: false,\n warnings: extraWarnings.length > 0 ? extraWarnings : 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';\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, Buffer>;\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, Buffer>({\n max: config.cache.maxItems,\n maxSize: maxSizeBytes,\n sizeCalculation: (value: Buffer) => value.length,\n ttl: config.cache.ttlSeconds * 1000,\n dispose: (\n _value: Buffer,\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): Buffer | 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: Buffer,\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 type { FontStager, FontStageHandle } from './types';\n\nexport class NoopFontStager implements FontStager {\n async stage(): Promise<FontStageHandle> {\n return {\n envOverrides: {},\n cleanup: async () => {},\n };\n }\n}\n","/**\n * Make resolved fonts visible to the LibreOffice child process for the\n * duration of one PDF conversion, then clean up.\n *\n * Linux/macOS: fontconfig + FONTCONFIG_FILE env var.\n * Windows: GDI session registration via koffi (AddFontResourceW).\n *\n * The converter calls `stage(fonts, tempDir)` before spawning soffice, merges\n * `envOverrides` into the child process env, waits for conversion, then\n * awaits `cleanup()` regardless of success or failure.\n */\n\nimport type { ResolvedFont } from '@json-to-office/shared';\n\nexport interface FontStageHandle {\n /** Merged into the child process env. Empty object if nothing to stage. */\n envOverrides: Record<string, string>;\n /** Always call in a finally block. Safe to call multiple times (idempotent). */\n cleanup(): Promise<void>;\n}\n\nexport interface FontStager {\n stage(fonts: ResolvedFont[], tempDir: string): Promise<FontStageHandle>;\n}\n\n/** Per-process monotonic counter to disambiguate concurrent conversions. */\nlet counter = 0;\nexport function nextStagingId(): string {\n counter += 1;\n return `${process.pid}-${counter}`;\n}\n\n/** Sanitize a font family for use in a filename. */\nexport function safeFilenamePart(s: string): string {\n return s.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 48);\n}\n","/**\n * Linux + macOS: use fontconfig to expose staged TTFs to LibreOffice.\n *\n * Writes each resolved font to `<tempDir>/fonts/` and a minimal\n * fontconfig.xml that includes that dir plus the system font config.\n * LibreOffice honors the per-invocation FONTCONFIG_FILE env var.\n *\n * No cleanup work is needed here — the converter removes the whole tempDir\n * in its own finally block.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport {\n synthesizeFamilyName,\n rewriteFontFamilyName,\n} from '@json-to-office/shared';\nimport type { FontStager, FontStageHandle } from './types';\nimport { nextStagingId, safeFilenamePart } from './types';\n\nconst SYSTEM_FONTS_CONF_CANDIDATES = [\n '/etc/fonts/fonts.conf',\n '/opt/homebrew/etc/fonts/fonts.conf',\n '/usr/local/etc/fonts/fonts.conf',\n];\n\nexport class FontconfigStager implements FontStager {\n async stage(\n fonts: ResolvedFont[],\n tempDir: string\n ): Promise<FontStageHandle> {\n const id = nextStagingId();\n const fontsDir = path.join(tempDir, 'fonts');\n await fs.mkdir(fontsDir, { recursive: true });\n\n let serial = 0;\n for (const r of fonts) {\n if (r.sources.length === 0) continue;\n for (const s of r.sources) {\n serial += 1;\n const suffix = s.italic ? 'i' : 'r';\n // Rewrite `name` table so fontconfig indexes the file under the\n // synthetic sub-family (\"Inter Light\"), matching the doc's\n // `rFonts`/`fontFace` references after synthesizeFamilyName.\n const synth = synthesizeFamilyName(r.family, s.weight, s.italic);\n const data =\n synth.family === r.family\n ? s.data\n : rewriteFontFamilyName(s.data, synth.family);\n const name = `${safeFilenamePart(synth.family)}-${s.weight}${suffix}-${id}-${serial}.ttf`;\n await fs.writeFile(path.join(fontsDir, name), data);\n }\n }\n\n // Freeze the fonts dir read-only after staging so a misbehaving\n // fontconfig run (or a concurrent soffice spawn) can't corrupt the\n // file contents we just wrote. fc-cache writes its own indexes into\n // `cacheDir` (next step), which stays writable. The whole tree gets\n // rm'd by the converter in finally, so mode matters only during the\n // conversion window.\n await fs.chmod(fontsDir, 0o555).catch(() => {\n // Some filesystems (e.g. certain Windows-mounted shares under WSL)\n // refuse chmod — ignore and proceed. The defensive-in-depth case\n // still wins on native Linux/macOS.\n });\n const includeLines = await this.pickSystemIncludes();\n // Redirect fontconfig's scan cache into tempDir. Without this, fontconfig\n // writes cache entries for `fontsDir` into the user's ~/.cache/fontconfig\n // and leaves them behind after tempDir is rm'd. Per-invocation isolation\n // also prevents two concurrent conversions from racing on the same\n // fontconfig cache directory.\n const cacheDir = path.join(tempDir, 'fc-cache');\n await fs.mkdir(cacheDir, { recursive: true });\n const configPath = path.join(tempDir, 'fontconfig.xml');\n const configXml = [\n '<?xml version=\"1.0\"?>',\n '<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">',\n '<fontconfig>',\n ` <dir>${escapeXml(fontsDir)}</dir>`,\n ` <cachedir>${escapeXml(cacheDir)}</cachedir>`,\n ...includeLines,\n '</fontconfig>',\n '',\n ].join('\\n');\n await fs.writeFile(configPath, configXml, 'utf8');\n\n return {\n envOverrides: {\n FONTCONFIG_FILE: configPath,\n XDG_CACHE_HOME: cacheDir,\n },\n cleanup: async () => {\n // Cleanup handled by converter's tempDir rm -rf.\n },\n };\n }\n\n private async pickSystemIncludes(): Promise<string[]> {\n for (const candidate of SYSTEM_FONTS_CONF_CANDIDATES) {\n try {\n await fs.access(candidate);\n return [\n ` <include ignore_missing=\"yes\">${escapeXml(candidate)}</include>`,\n ];\n } catch {\n /* try next */\n }\n }\n // Fall back to the conventional path; fontconfig will fail softly.\n return [` <include ignore_missing=\"yes\">/etc/fonts/fonts.conf</include>`];\n }\n}\n\nfunction escapeXml(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n","/**\n * Windows: register staged TTFs with GDI via AddFontResourceW so the soffice\n * child process finds them at startup. Forces LibreOffice onto the GDI\n * backend via SAL_DISABLE_SKIA=1 — Skia/DirectWrite doesn't reliably pick\n * up GDI-registered fonts on recent LO builds.\n *\n * Registration is process-scoped: Node stays alive for the full conversion,\n * so the fonts persist until cleanup. If Node crashes, GDI releases them on\n * process exit — no logout-scope leaks.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport {\n synthesizeFamilyName,\n rewriteFontFamilyName,\n} from '@json-to-office/shared';\nimport type { FontStager, FontStageHandle } from './types';\nimport { nextStagingId, safeFilenamePart } from './types';\n\ntype KoffiLib = {\n func: (sig: string) => (...args: unknown[]) => number | boolean;\n};\ntype KoffiModule = {\n load: (libName: string) => KoffiLib;\n};\n\n// Lazy-load koffi so Linux/macOS don't incur the FFI init cost.\nlet cachedBindings: {\n addFont: (pathW: string) => number;\n removeFont: (pathW: string) => boolean;\n} | null = null;\n\nasync function getGdiBindings() {\n if (cachedBindings) return cachedBindings;\n const koffi = (await import('koffi')) as unknown as {\n default?: KoffiModule;\n } & KoffiModule;\n const mod = koffi.default ?? koffi;\n const gdi32 = mod.load('gdi32.dll');\n cachedBindings = {\n addFont: gdi32.func('int __stdcall AddFontResourceW(str16)') as (\n path: string\n ) => number,\n removeFont: gdi32.func('bool __stdcall RemoveFontResourceW(str16)') as (\n path: string\n ) => boolean,\n };\n return cachedBindings;\n}\n\nexport class WindowsFontStager implements FontStager {\n async stage(\n fonts: ResolvedFont[],\n tempDir: string\n ): Promise<FontStageHandle> {\n const id = nextStagingId();\n const fontsDir = path.join(tempDir, 'fonts');\n await fs.mkdir(fontsDir, { recursive: true });\n\n const stagedPaths: string[] = [];\n let serial = 0;\n for (const r of fonts) {\n if (r.sources.length === 0) continue;\n for (const s of r.sources) {\n serial += 1;\n const suffix = s.italic ? 'i' : 'r';\n // Rewrite the TTF's internal family name so GDI registers the\n // file under the synthetic sub-family the doc references.\n const synth = synthesizeFamilyName(r.family, s.weight, s.italic);\n const data =\n synth.family === r.family\n ? s.data\n : rewriteFontFamilyName(s.data, synth.family);\n const name = `${safeFilenamePart(synth.family)}-${s.weight}${suffix}-${id}-${serial}.ttf`;\n const fullPath = path.join(fontsDir, name);\n await fs.writeFile(fullPath, data);\n stagedPaths.push(fullPath);\n }\n }\n\n if (stagedPaths.length === 0) {\n return { envOverrides: {}, cleanup: async () => {} };\n }\n\n const { addFont, removeFont } = await getGdiBindings();\n const registered: string[] = [];\n for (const p of stagedPaths) {\n const added = addFont(p);\n if (added > 0) registered.push(p);\n }\n\n let cleaned = false;\n return {\n envOverrides: {\n // Force GDI backend so the freshly-registered fonts are visible.\n // Skia on Windows uses DirectWrite which does not reliably see\n // fonts added via AddFontResourceW.\n SAL_DISABLE_SKIA: '1',\n },\n cleanup: async () => {\n if (cleaned) return;\n cleaned = true;\n for (const p of registered) {\n try {\n removeFont(p);\n } catch {\n // Swallow — GDI will drop it on process exit anyway.\n }\n }\n },\n };\n }\n}\n","/**\n * macOS: make staged fonts visible to the soffice child process by\n * registering them *inside* soffice via a Python macro bound to the\n * `OnStartApp` event.\n *\n * Why this works on macOS 26. Apple tightened `CTFontManagerScopeSession`\n * and `kCTFontManagerScopePersistent` to require signed+notarized callers\n * (unsigned Node processes get `paramErr -50`), and `Process` scope only\n * registers fonts for the calling process — so the Node server can't\n * register fonts the soffice child sees. But Process scope DOES work from\n * inside soffice. LibreOffice for macOS bundles Python 3.12 with `ctypes`,\n * and UNO lets us bind a Python macro to application-start events. We seed\n * a per-invocation UserInstallation profile with:\n *\n * - `user/Scripts/python/JtoFontRegister.py` — a ~20-line macro that\n * reads `JTO_FONT_PATHS` from the process env and calls\n * `CTFontManagerRegisterFontsForURL(url, kScopeProcess, NULL)` via\n * ctypes for each path (Process = 1 in Core Text's scope enum).\n * - `user/registrymodifications.xcu` — binds the macro to `OnStartApp`\n * and sets `MacroSecurityLevel=0` for this ephemeral profile only.\n *\n * SECURITY INVARIANT — macro execution scope. The seeded profile disables\n * soffice's macro-security prompt (`MacroSecurityLevel=0`) so our\n * OnStartApp macro runs without a dialog. This profile MUST ONLY be used\n * to open files this server just generated (i.e., well-formed outputs\n * from `@json-to-office/core-*`). Piping user-supplied .docx/.pptx/.odt\n * through a soffice invocation that uses this stager would execute any\n * embedded VBA/Basic macros silently — an RCE primitive. If a future\n * code path ever converts user-supplied documents (e.g. \"PDF-ify my\n * upload\"), it must build a separate converter that does NOT share this\n * profile, or call soffice with `--safe-mode` / a default profile.\n *\n * Flow: the converter spawns\n * `soffice --headless -env:UserInstallation=file://<tempDir>/user-profile ...`\n * with env `{ JTO_FONT_PATHS: \"<ttf1>:<ttf2>:...\" }`. LO boots, reads our\n * seeded profile, fires `OnStartApp`, runs our macro, registers each\n * staged TTF at Process scope in its own process. Font enumeration then\n * resolves the synthetic family names (`Inter Bold`, `Source Code Pro\n * Medium`, …) against those Process-scope registrations. The PDF export\n * ships the correct glyphs.\n *\n * Elegant side-effects:\n * - Nothing outside the converter's `tempDir` is touched. The user's\n * real `~/Library/Fonts` and `~/Library/Application Support/LibreOffice`\n * stay untouched.\n * - Cleanup is the converter's `fs.rm(tempDir, …)` — no orphan sweep\n * needed. If Node crashes mid-conversion, the per-invocation tempDir\n * is reaped by macOS tmpreaper (or the OS's next boot cleanup).\n * - No DYLD injection, no notarized helper, no filesystem-scan races.\n *\n * Failure mode: if LibreOffice can't run the macro for any reason\n * (macro-security policy applied at bootstrap before our XCU loads,\n * Python not present in a minimal LO build, …) the soffice process still\n * runs and produces a PDF — just with system-fallback fonts, exactly the\n * pre-fix behavior. Non-catastrophic. Diagnose via stderr: the macro\n * writes failures to stderr via `print(..., file=sys.stderr)`.\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { ResolvedFont } from '@json-to-office/shared';\nimport {\n synthesizeFamilyName,\n rewriteFontFamilyName,\n} from '@json-to-office/shared';\nimport type { FontStager, FontStageHandle } from './types';\nimport { nextStagingId, safeFilenamePart } from './types';\n\n/**\n * Python macro source. Written verbatim into\n * `<profile>/user/Scripts/python/JtoFontRegister.py`. Kept inline (rather\n * than a separate .py asset) so this TypeScript module is self-contained\n * and survives bundler reshuffles — no runtime file-system lookup for a\n * static asset.\n */\nconst PYTHON_MACRO = `# Auto-generated by @json-to-office/jto. Runs inside soffice on OnStartApp\n# to make staged fonts visible to LibreOffice's font enumeration. macOS 26\n# blocks Session/Persistent CT registration for unsigned callers, but\n# Process scope still works from inside the target process — which is\n# exactly where this macro runs.\nimport os\nimport sys\nimport ctypes\nimport ctypes.util\n\n\ndef _log(msg):\n # soffice swallows Python stdout in headless mode; stderr surfaces to\n # the parent's pipe. The stager doesn't read this today but the\n # converter logs stderr on failure, which is how we'll debug.\n sys.stderr.write(\"[jto-font-register] \" + msg + \"\\\\n\")\n\n\ndef register(*_args):\n paths_env = os.environ.get(\"JTO_FONT_PATHS\", \"\")\n if not paths_env:\n return\n try:\n cf = ctypes.CDLL(ctypes.util.find_library(\"CoreFoundation\"))\n ct = ctypes.CDLL(ctypes.util.find_library(\"CoreText\"))\n except Exception as e:\n _log(\"failed to load CoreFoundation/CoreText: \" + repr(e))\n return\n cf.CFURLCreateFromFileSystemRepresentation.argtypes = [\n ctypes.c_void_p, ctypes.c_char_p, ctypes.c_long, ctypes.c_bool,\n ]\n cf.CFURLCreateFromFileSystemRepresentation.restype = ctypes.c_void_p\n cf.CFRelease.argtypes = [ctypes.c_void_p]\n ct.CTFontManagerRegisterFontsForURL.argtypes = [\n ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p,\n ]\n ct.CTFontManagerRegisterFontsForURL.restype = ctypes.c_bool\n\n kCTFontManagerScopeProcess = 1\n registered = 0\n for p in paths_env.split(os.pathsep):\n if not p:\n continue\n try:\n b = p.encode(\"utf-8\")\n url = cf.CFURLCreateFromFileSystemRepresentation(\n None, b, len(b), False\n )\n if not url:\n _log(\"CFURL failed for \" + p)\n continue\n ok = ct.CTFontManagerRegisterFontsForURL(\n url, kCTFontManagerScopeProcess, None\n )\n cf.CFRelease(url)\n if ok:\n registered += 1\n else:\n _log(\"CT register returned false for \" + p)\n except Exception as e:\n _log(\"exception registering \" + p + \": \" + repr(e))\n _log(\"registered \" + str(registered) + \" font(s) at Process scope\")\n\n\n# Expose under \"register\" (event-binding URL) and module-level run so\n# command-line vnd.sun.star.script invocation works either way.\ng_exportedScripts = (register,)\n`;\n\n/**\n * XCU that LO merges into its Bootstrap registry on startup. Two keys:\n *\n * 1. `/org.openoffice.Office.Events/ApplicationEvents/Bindings/OnStartApp`\n * → fires our Python macro before any document is loaded, so font\n * registration completes before LO enumerates fonts for rendering.\n *\n * 2. `/org.openoffice.Office.Common/Security/Scripting/MacroSecurityLevel`\n * → 0 (allow all). This only applies to the ephemeral UserInstallation\n * profile we create under `<tempDir>/user-profile`; the user's real\n * LibreOffice profile config is untouched. Scope of the security\n * relaxation is bounded by the per-invocation profile's lifetime.\n */\nconst REGISTRY_MOD_XCU = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<oor:items xmlns:oor=\"http://openoffice.org/2001/registry\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n <item oor:path=\"/org.openoffice.Office.Events/ApplicationEvents/Bindings\">\n <node oor:name=\"OnStartApp\" oor:op=\"replace\">\n <prop oor:name=\"BindingURL\" oor:type=\"xs:string\">\n <value>vnd.sun.star.script:JtoFontRegister.py$register?language=Python&location=user</value>\n </prop>\n </node>\n </item>\n <item oor:path=\"/org.openoffice.Office.Common/Security/Scripting\">\n <prop oor:name=\"MacroSecurityLevel\" oor:op=\"fuse\">\n <value>0</value>\n </prop>\n </item>\n</oor:items>\n`;\n\nexport class MacOSCoreTextStager implements FontStager {\n async stage(\n fonts: ResolvedFont[],\n tempDir: string\n ): Promise<FontStageHandle> {\n const embeddable = fonts.filter((r) => r.sources.length > 0);\n if (embeddable.length === 0) {\n return { envOverrides: {}, cleanup: async () => {} };\n }\n\n // Fonts go to a subdir of the converter's tempDir. No ~/Library writes.\n const fontsDir = path.join(tempDir, 'fonts');\n await fs.mkdir(fontsDir, { recursive: true });\n\n const id = nextStagingId();\n const fontPaths: string[] = [];\n const staged: {\n family: string;\n weight: number;\n italic: boolean;\n path: string;\n }[] = [];\n let serial = 0;\n for (const r of embeddable) {\n for (const s of r.sources) {\n serial += 1;\n const suffix = s.italic ? 'i' : 'r';\n // Rewrite the TTF's internal family name to match the synthetic\n // sub-family the doc references (e.g. \"Inter Light\"). Without\n // this, Core Text indexes the staged file as \"Inter\" and\n // LibreOffice can't resolve `rFonts w:ascii=\"Inter Light\"`.\n const synth = synthesizeFamilyName(r.family, s.weight, s.italic);\n const data =\n synth.family === r.family\n ? s.data\n : rewriteFontFamilyName(s.data, synth.family);\n const name = `${safeFilenamePart(synth.family)}-${s.weight}${suffix}-${id}-${serial}.ttf`;\n const full = path.join(fontsDir, name);\n await fs.writeFile(full, data);\n fontPaths.push(full);\n staged.push({\n family: synth.family,\n weight: s.weight,\n italic: s.italic,\n path: full,\n });\n }\n }\n\n if (process.env.JTO_DEBUG_FONTS === '1') {\n // eslint-disable-next-line no-console\n console.log(\n '[jto macos-stager] staged ' +\n staged.length +\n ' font(s) for CT Process-scope registration; JTO_FONT_PATHS has ' +\n fontPaths.length +\n ' entries\\n' +\n staged\n .map(\n (s) =>\n ` ${s.family} (w=${s.weight}${s.italic ? ' italic' : ''}) → ${path.basename(s.path)}`\n )\n .join('\\n')\n );\n }\n\n // Seed the per-invocation UserInstallation profile. The converter\n // spawns soffice with `-env:UserInstallation=file://<tempDir>/user-profile`,\n // so LO reads the macro + event binding from these exact paths.\n const profileUser = path.join(tempDir, 'user-profile', 'user');\n const scriptsDir = path.join(profileUser, 'Scripts', 'python');\n await fs.mkdir(scriptsDir, { recursive: true });\n await fs.writeFile(\n path.join(scriptsDir, 'JtoFontRegister.py'),\n PYTHON_MACRO\n );\n await fs.writeFile(\n path.join(profileUser, 'registrymodifications.xcu'),\n REGISTRY_MOD_XCU\n );\n\n return {\n envOverrides: {\n // Colon-separated list of staged TTF paths (`:` matches Python's\n // `os.pathsep` on macOS). The macro reads this at OnStartApp.\n JTO_FONT_PATHS: fontPaths.join(':'),\n // Force LibreOffice's Core Graphics backend. Skia on macOS can\n // skip Core Text's freshly-registered fonts in some builds.\n SAL_DISABLE_SKIA: '1',\n },\n cleanup: async () => {\n // No-op: the converter's `fs.rm(tempDir, { recursive: true })` in\n // its own finally block sweeps everything we wrote here.\n },\n };\n }\n}\n","/**\n * Factory entry point for the font staging pipeline used by the\n * LibreOffice-based PDF preview.\n */\n\nimport type { FontStager } from './types';\nimport { NoopFontStager } from './noop-stager';\nimport { FontconfigStager } from './fontconfig-stager';\nimport { WindowsFontStager } from './windows-stager';\nimport { MacOSCoreTextStager } from './macos-stager';\n\nexport type { FontStager, FontStageHandle } from './types';\n\nconst cached = new Map<NodeJS.Platform, FontStager>();\n\nexport function getFontStager(\n platform: NodeJS.Platform = process.platform\n): FontStager {\n const hit = cached.get(platform);\n if (hit) return hit;\n let stager: FontStager;\n switch (platform) {\n case 'win32':\n stager = new WindowsFontStager();\n break;\n case 'darwin':\n // LibreOffice-for-macOS uses Core Text for font enumeration and does\n // not honor FONTCONFIG_FILE reliably. macOS 26 further blocks\n // Session/Persistent CT registration for unsigned callers, and\n // Process scope only works inside the target process. We register\n // fonts from *inside* soffice via a Python UNO macro bound to\n // OnStartApp, seeded into a per-invocation UserInstallation profile.\n // The user's ~/Library/Fonts is never touched. See macos-stager.ts.\n stager = new MacOSCoreTextStager();\n break;\n case 'linux':\n case 'freebsd':\n case 'openbsd':\n stager = new FontconfigStager();\n break;\n default:\n stager = new NoopFontStager();\n }\n cached.set(platform, stager);\n return stager;\n}\n\nexport {\n NoopFontStager,\n FontconfigStager,\n WindowsFontStager,\n MacOSCoreTextStager,\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 './font-staging/index.js';\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 module types.\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 },\n { additionalProperties: true }\n )\n ),\n },\n { additionalProperties: true }\n);\n\n/**\n * Loose document validation request schema that allows plugin module types.\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\ninterface RateLimitOptions {\n limit: number;\n window: number; // milliseconds\n keyGenerator?: (c: any) => string;\n}\n\n// In-memory store for rate limiting (use Redis in production)\nconst rateLimitStore = new Map<string, { count: number; resetTime: number }>();\n\n/**\n * Rate limiting middleware for Hono\n */\nexport const rateLimiter = (options: RateLimitOptions): MiddlewareHandler => {\n const { limit, window, keyGenerator } = options;\n\n return async (c, next) => {\n const key = keyGenerator\n ? keyGenerator(c)\n : c.req.header('X-Real-IP') || c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() || 'anonymous';\n const now = Date.now();\n\n // Clean up expired entries\n for (const [k, v] of rateLimitStore.entries()) {\n if (v.resetTime < now) {\n rateLimitStore.delete(k);\n }\n }\n\n const record = rateLimitStore.get(key);\n\n if (!record) {\n // First request\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","/**\n * Shared POST /rasterize route — one validated handler mounted on BOTH the\n * playground format router and the standalone jto-render-server, so the public\n * and in-app rasterize surfaces can't drift in validation, limits, or error\n * mapping. Renders a single-slide pptx presentation to a PNG.\n */\n\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 type PptxRasterizer,\n} from '@json-to-office/shared';\nimport { createLibreOfficePptxRasterizer } from '@json-to-office/jto-cli';\nimport { tbValidator, getValidated } from './lib/typebox-validator.js';\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 },\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.\nlet sharedRasterizer: PptxRasterizer | undefined;\nexport function getSharedRasterizer(): PptxRasterizer {\n if (!sharedRasterizer) {\n sharedRasterizer = createLibreOfficePptxRasterizer();\n }\n return sharedRasterizer;\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/**\n * Register `POST /rasterize` on a Hono router with body-size limit, content-type\n * + schema validation (dpi clamped to [MIN,MAX]_VISUAL_DPI), the shared\n * rasterizer, and structured 400/413/503/500 error mapping.\n *\n * @param preMiddleware - extra middleware (e.g. a rate limiter) run first.\n */\nexport function registerRasterizeRoute(\n router: Hono<any>,\n options: {\n getRasterizer?: () => PptxRasterizer;\n preMiddleware?: MiddlewareHandler[];\n onError?: (error: unknown) => void;\n } = {}\n): void {\n const getRasterizer = options.getRasterizer ?? getSharedRasterizer;\n\n router.post(\n '/rasterize',\n ...(options.preMiddleware ?? []),\n bodyLimit({\n maxSize: 32 * 1024 * 1024,\n onError: () => {\n throw new HTTPException(413, { message: 'Request body too large' });\n },\n }),\n jsonOnly,\n tbValidator(RasterizeRequestSchema),\n async (c) => {\n const { presentation, dpi } = getValidated<{\n presentation: unknown;\n dpi?: number;\n }>(c, 'json');\n\n try {\n const result = await getRasterizer()({\n presentation,\n dpi: clampVisualDpi(dpi ?? DEFAULT_VISUAL_DPI),\n });\n return c.json(result);\n } catch (error) {\n options.onError?.(error);\n if (error instanceof HTTPException) throw error;\n const msg =\n error instanceof Error ? error.message.toLowerCase() : String(error);\n if (msg.includes('not found') || msg.includes('rasterization needs')) {\n throw new HTTPException(503, { message: (error as Error).message });\n }\n if (msg.includes('invalid') || msg.includes('validation')) {\n throw new HTTPException(400, { message: (error as Error).message });\n }\n throw new HTTPException(500, {\n message: 'Internal server error during rasterization',\n });\n }\n }\n );\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 { type FormatAdapter, PluginRegistry } from '@json-to-office/jto-cli';\nimport { registerRasterizeRoute } from '../rasterize-route.js';\nimport {\n LibreOfficeBinaryNotFoundError,\n LibreOfficeConversionError,\n LibreOfficeOutputNotFoundError,\n LibreOfficeTimeoutError,\n} from '../services/libreoffice-converter.js';\n\nexport function createFormatRouter(adapter: FormatAdapter) {\n const router = new Hono<AppEnv>();\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 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 const result = await generatorService.generate({\n jsonDefinition,\n customThemes,\n options: {\n ...options,\n ...(sanitizedFonts !== undefined && { fonts: sanitizedFonts }),\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 if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n if (\n msg.includes('invalid') ||\n msg.includes('validation') ||\n msg.includes('missing required') ||\n msg.includes('unknown component')\n ) {\n throw new HTTPException(400, { message: error.message });\n }\n }\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 // The adapter's validateDocument is a no-op stub; use the real\n // TypeBox document validation from shared-docx (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 rateLimiter({\n limit: process.env.NODE_ENV === 'production' ? 20 : 1000,\n window: 15 * 60 * 1000,\n keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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\n const arrayBuffer = await (file as File).arrayBuffer();\n const inputBuffer = Buffer.from(arrayBuffer);\n const pdfBuffer = await libreOfficeService.convertToPdf(\n inputBuffer,\n (file as File).name\n );\n\n const pdfName =\n ((file as File).name || 'preview').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\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n }>(c, 'json');\n\n try {\n const generated = await generatorService.generate({\n jsonDefinition,\n customThemes,\n options: { bypassCache: true },\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 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 } = getValidated<{\n jsonDefinition: any;\n customThemes?: Record<string, any>;\n }>(c, 'json');\n const requestId = c.get('requestId');\n\n try {\n const config =\n typeof jsonDefinition === 'string'\n ? JSON.parse(jsonDefinition)\n : jsonDefinition;\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 theme: customThemes ? Object.values(customThemes)[0] : undefined,\n });\n\n if (generatorResult.getStandardComponentsDefinition) {\n const standardComponents =\n await generatorResult.getStandardComponentsDefinition(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 throw new HTTPException(500, {\n message: 'Failed to get standard components definition',\n });\n }\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 const components = (await adapter.getComponentCacheStats?.()) ?? null;\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 ...(components ? { components } : {}),\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 // GET /cache-analytics\n router.get('/cache-analytics', async (c) => {\n try {\n const analytics = await adapter.getComponentCacheAnalytics?.();\n if (!analytics) {\n return c.json({\n success: true,\n data: null,\n meta: { timestamp: new Date().toISOString() },\n });\n }\n return c.json({\n success: true,\n data: analytics,\n meta: { timestamp: new Date().toISOString() },\n });\n } catch (error) {\n logger.error('Failed to get cache analytics', { error });\n throw new HTTPException(500, {\n message: 'Failed to get cache analytics',\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 { invalidateAllCaches } = await import('@json-to-office/jto-cli');\n invalidateAllCaches();\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\n }),\n ],\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\nfunction getSelectedPlugins(pluginNames?: string[]) {\n const registry = PluginRegistry.getInstance();\n if (!registry.hasPlugins()) return [];\n\n const plugins = pluginNames?.length\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 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: 'https://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: 'https://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: 'https://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 const pluginNames = pluginsParam\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';\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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';\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 keyGenerator: (c) =>\n c.req.header('X-Real-IP') ||\n c.req.header('X-Forwarded-For')?.split(',').pop()?.trim() ||\n 'anonymous',\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 { MiddlewareHandler } from 'hono';\nimport { config } from '../../config';\n\n/**\n * API Key authentication middleware for Hono\n */\nexport const apiKeyAuthMiddleware: MiddlewareHandler = async (c, next) => {\n // Skip auth if not configured\n if (!config.features.apiKey || !config.API_KEY) {\n return next();\n }\n\n const apiKey = c.req.header(config.API_KEY_HEADER);\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 (apiKey !== config.API_KEY) {\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","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 { 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 { 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';\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.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 // 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);\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);\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 } 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 console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n})();\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport boxen from 'boxen';\nimport {\n type FormatAdapter,\n loadConfig,\n formatError,\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\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 const spinner = ora(\n `Starting ${adapter.name.toUpperCase()} dev server...`\n ).start();\n\n try {\n const config = await loadConfig(options.config);\n\n // CLI flag > adapter default > config file default\n const portSource = dev.getOptionValueSource('port');\n const hostSource = dev.getOptionValueSource('host');\n if (portSource === 'cli') {\n config.server.port = parseInt(options.port!, 10);\n } else if (\n config.server.port === 3003 &&\n adapter.defaultPort !== 3003\n ) {\n config.server.port = adapter.defaultPort;\n }\n if (hostSource === 'cli') {\n config.server.host = options.host!;\n }\n\n const { UnifiedServer } = await import('../server/unified-server.js');\n const server = new UnifiedServer(adapter, config);\n await server.start();\n\n const url = `http://${config.server.host}:${config.server.port}`;\n spinner.succeed('Server ready');\n\n console.log(\n boxen(\n chalk.bold(`${adapter.name.toUpperCase()} Dev Server\\n\\n`) +\n `${chalk.cyan('Local:')} ${chalk.bold(url)}\\n` +\n `${chalk.cyan('API:')} ${url}/api/${adapter.name}/generate\\n` +\n `${chalk.cyan('Health:')} ${url}/health\\n\\n` +\n chalk.gray('Press Ctrl+C to stop'),\n {\n padding: 1,\n borderColor: 'green',\n borderStyle: 'round',\n }\n )\n );\n\n // Open browser if requested\n if (options.open) {\n const { execFile } = await import('child_process');\n const cmd =\n process.platform === 'darwin'\n ? 'open'\n : process.platform === 'win32'\n ? 'start'\n : 'xdg-open';\n execFile(cmd, [url]);\n }\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log(chalk.yellow('\\nShutting down...'));\n await server.stop();\n process.exit(EXIT_CODES.OK);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n } catch (error: any) {\n spinner.fail('Failed to start dev server');\n formatError(error);\n process.exit(EXIT_CODES.FAIL);\n }\n });\n}\n"],"mappings":"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","names":["config","filtered","cacheEvents","path","fs","path","synthesizeFamilyName","rewriteFontFamilyName","fs","path","synthesizeFamilyName","rewriteFontFamilyName","fs","path","resolve","HTTPException","Type","HTTPException","Hono","HTTPException","bodyLimit","PluginRegistry","config","Hono","PluginRegistry","cleanupTypeBoxIds","fileURLToPath","__dirname","Hono","Hono","HTTPException","bodyLimit","POPULAR_GOOGLE_FONTS","HTTPException","Hono","Hono","logger","dirname","fileURLToPath","__filename","__dirname","config","path","existsSync","resolve","fs","Command","chalk","config","UnifiedServer","execFile","Command","chalk"]}
|