meno-core 1.0.52 → 1.0.53
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/build-astro.ts +183 -13
- package/build-next.ts +1361 -0
- package/build-static.ts +7 -5
- package/dist/bin/cli.js +2 -2
- package/dist/build-static.js +6 -6
- package/dist/chunks/{chunk-HNLUO36W.js → chunk-GZHGVVW3.js} +2 -2
- package/dist/chunks/chunk-GZHGVVW3.js.map +7 -0
- package/dist/chunks/{chunk-LPVETICS.js → chunk-H3GJ4H2U.js} +185 -1
- package/dist/chunks/chunk-H3GJ4H2U.js.map +7 -0
- package/dist/chunks/{chunk-CXCBV2M7.js → chunk-IGYR22T6.js} +76 -270
- package/dist/chunks/chunk-IGYR22T6.js.map +7 -0
- package/dist/chunks/{chunk-LHLHPYSP.js → chunk-JGP5A3Y5.js} +12 -11
- package/dist/chunks/chunk-JGP5A3Y5.js.map +7 -0
- package/dist/chunks/{chunk-7NIC4I3V.js → chunk-JGWFTO6P.js} +167 -21
- package/dist/chunks/chunk-JGWFTO6P.js.map +7 -0
- package/dist/chunks/{chunk-EDQSMAMP.js → chunk-O3NAGJP4.js} +85 -4
- package/dist/chunks/chunk-O3NAGJP4.js.map +7 -0
- package/dist/chunks/{chunk-H4JSCDNW.js → chunk-QB2LNO4W.js} +24 -1
- package/dist/chunks/chunk-QB2LNO4W.js.map +7 -0
- package/dist/chunks/{chunk-A725KYFK.js → chunk-R6XHAFBF.js} +561 -112
- package/dist/chunks/chunk-R6XHAFBF.js.map +7 -0
- package/dist/chunks/{chunk-J23ZX5AP.js → chunk-X754AHS5.js} +277 -1
- package/dist/chunks/chunk-X754AHS5.js.map +7 -0
- package/dist/chunks/{chunk-2QK6U5UK.js → chunk-YBLHKYFF.js} +12 -2
- package/dist/chunks/chunk-YBLHKYFF.js.map +7 -0
- package/dist/chunks/{constants-GWBAD66U.js → constants-STK2YBIW.js} +2 -2
- package/dist/entries/server-router.js +7 -7
- package/dist/lib/client/index.js +354 -59
- package/dist/lib/client/index.js.map +4 -4
- package/dist/lib/server/index.js +1458 -190
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +202 -34
- package/dist/lib/shared/index.js.map +4 -4
- package/dist/lib/test-utils/index.js +1 -1
- package/entries/client-router.tsx +5 -165
- package/lib/client/ErrorBoundary.test.tsx +27 -25
- package/lib/client/ErrorBoundary.tsx +34 -19
- package/lib/client/core/ComponentBuilder.ts +19 -2
- package/lib/client/core/builders/embedBuilder.ts +8 -4
- package/lib/client/core/builders/listBuilder.ts +23 -4
- package/lib/client/fontFamiliesService.test.ts +76 -0
- package/lib/client/fontFamiliesService.ts +69 -0
- package/lib/client/hmrCssReload.ts +160 -0
- package/lib/client/hooks/useColorVariables.ts +2 -0
- package/lib/client/index.ts +4 -0
- package/lib/client/meno-filter/ui.ts +2 -0
- package/lib/client/routing/RouteLoader.test.ts +2 -2
- package/lib/client/routing/RouteLoader.ts +8 -2
- package/lib/client/routing/Router.tsx +81 -15
- package/lib/client/scripts/ScriptExecutor.test.ts +143 -0
- package/lib/client/scripts/ScriptExecutor.ts +56 -2
- package/lib/client/styles/StyleInjector.ts +20 -5
- package/lib/client/styles/UtilityClassCollector.ts +7 -1
- package/lib/client/styles/cspNonce.test.ts +67 -0
- package/lib/client/styles/cspNonce.ts +63 -0
- package/lib/client/templateEngine.test.ts +80 -0
- package/lib/client/templateEngine.ts +5 -0
- package/lib/server/astro/cmsPageEmitter.ts +35 -5
- package/lib/server/astro/componentEmitter.ts +61 -5
- package/lib/server/astro/nodeToAstro.ts +149 -11
- package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +264 -0
- package/lib/server/astro/normalizeOrphanTemplateProps.ts +184 -0
- package/lib/server/createServer.ts +11 -0
- package/lib/server/draftPageStore.ts +49 -0
- package/lib/server/fileWatcher.ts +62 -2
- package/lib/server/index.ts +13 -1
- package/lib/server/providers/fileSystemPageProvider.ts +8 -0
- package/lib/server/routes/api/components.ts +9 -4
- package/lib/server/routes/api/core-routes.ts +2 -2
- package/lib/server/routes/api/pages.ts +14 -22
- package/lib/server/routes/api/shared.ts +56 -0
- package/lib/server/routes/index.ts +90 -0
- package/lib/server/routes/pages.ts +13 -6
- package/lib/server/services/componentService.test.ts +199 -2
- package/lib/server/services/componentService.ts +354 -49
- package/lib/server/services/fileWatcherService.ts +4 -24
- package/lib/server/services/pageService.test.ts +23 -0
- package/lib/server/services/pageService.ts +124 -6
- package/lib/server/ssr/attributeBuilder.ts +8 -2
- package/lib/server/ssr/buildErrorOverlay.ts +1 -1
- package/lib/server/ssr/errorOverlay.test.ts +21 -2
- package/lib/server/ssr/errorOverlay.ts +38 -11
- package/lib/server/ssr/htmlGenerator.test.ts +53 -13
- package/lib/server/ssr/htmlGenerator.ts +71 -27
- package/lib/server/ssr/liveReloadIntegration.test.ts +123 -2
- package/lib/server/ssr/ssrRenderer.test.ts +67 -0
- package/lib/server/ssr/ssrRenderer.ts +94 -9
- package/lib/server/websocketManager.ts +0 -1
- package/lib/shared/componentRefs.ts +45 -0
- package/lib/shared/constants.ts +8 -0
- package/lib/shared/cssGeneration.ts +2 -0
- package/lib/shared/cssProperties.ts +184 -0
- package/lib/shared/expressionEvaluator.ts +54 -0
- package/lib/shared/fontCss.ts +101 -0
- package/lib/shared/fontLoader.ts +8 -86
- package/lib/shared/friendlyError.test.ts +87 -0
- package/lib/shared/friendlyError.ts +121 -0
- package/lib/shared/hrefRefs.test.ts +130 -0
- package/lib/shared/hrefRefs.ts +100 -0
- package/lib/shared/index.ts +52 -0
- package/lib/shared/inlineSvgStyleRules.test.ts +108 -0
- package/lib/shared/inlineSvgStyleRules.ts +134 -0
- package/lib/shared/interfaces/contentProvider.ts +13 -0
- package/lib/shared/itemTemplateUtils.test.ts +14 -0
- package/lib/shared/itemTemplateUtils.ts +4 -1
- package/lib/shared/registry/NodeTypeDefinition.ts +1 -1
- package/lib/shared/registry/nodeTypes/LinkNodeType.ts +1 -1
- package/lib/shared/slugTranslator.test.ts +24 -0
- package/lib/shared/slugTranslator.ts +24 -0
- package/lib/shared/styleNodeUtils.ts +4 -1
- package/lib/shared/tree/PathBuilder.test.ts +128 -1
- package/lib/shared/tree/PathBuilder.ts +83 -31
- package/lib/shared/types/comment.ts +99 -0
- package/lib/shared/types/index.ts +12 -0
- package/lib/shared/types/rendering.ts +8 -0
- package/lib/shared/utilityClassConfig.ts +4 -2
- package/lib/shared/utilityClassMapper.test.ts +24 -0
- package/lib/shared/validation/commentValidators.ts +69 -0
- package/lib/shared/validation/index.ts +1 -0
- package/lib/shared/viewportUnits.integration.test.ts +42 -0
- package/lib/shared/viewportUnits.test.ts +103 -0
- package/lib/shared/viewportUnits.ts +63 -0
- package/lib/test-utils/dom-setup.ts +6 -0
- package/package.json +1 -1
- package/dist/chunks/chunk-2QK6U5UK.js.map +0 -7
- package/dist/chunks/chunk-7NIC4I3V.js.map +0 -7
- package/dist/chunks/chunk-A725KYFK.js.map +0 -7
- package/dist/chunks/chunk-CXCBV2M7.js.map +0 -7
- package/dist/chunks/chunk-EDQSMAMP.js.map +0 -7
- package/dist/chunks/chunk-H4JSCDNW.js.map +0 -7
- package/dist/chunks/chunk-HNLUO36W.js.map +0 -7
- package/dist/chunks/chunk-J23ZX5AP.js.map +0 -7
- package/dist/chunks/chunk-LHLHPYSP.js.map +0 -7
- package/dist/chunks/chunk-LPVETICS.js.map +0 -7
- /package/dist/chunks/{constants-GWBAD66U.js.map → constants-STK2YBIW.js.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../lib/server/pageCache.ts", "../../lib/server/websocketManager.ts", "../../lib/server/utils/jsonLineMapper.ts", "../../lib/server/services/pageService.ts", "../../lib/server/services/componentService.ts", "../../lib/server/services/EnumService.ts", "../../lib/server/fileWatcher.ts", "../../lib/server/services/fileWatcherService.ts", "../../lib/server/middleware/cors.ts", "../../lib/server/middleware/errorHandler.ts", "../../lib/server/middleware/logger.ts", "../../lib/server/routes/api/shared.ts", "../../lib/server/routes/api/cms.ts", "../../lib/server/routes/api/core-routes.ts", "../../lib/server/routes/api/pages.ts", "../../lib/server/routes/api/components.ts", "../../lib/server/routes/api/config.ts", "../../lib/server/routes/api/colors.ts", "../../lib/server/routes/api/variables.ts", "../../lib/server/routes/api/enums.ts", "../../lib/server/routes/api/functions.ts", "../../lib/server/routes/index.ts", "../../lib/server/routes/api/index.ts", "../../lib/server/routes/pages.ts", "../../lib/shared/pathUtils.ts", "../../lib/server/ssr/errorOverlay.ts", "../../lib/server/scriptCache.ts", "../../lib/server/routes/static.ts", "../../lib/server/createServer.ts", "../../lib/server/providers/fileSystemPageProvider.ts", "../../lib/shared/utils/fileUtils.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Page Cache\n * Manages caching of page JSON content with line number tracking\n */\n\nimport type { LineMap, LineRange } from './utils/jsonLineMapper';\n\nexport interface CachedPage {\n content: string;\n lineMap: LineMap;\n}\n\nexport class PageCache {\n private cache = new Map<string, CachedPage>();\n\n /**\n * Store page content and line map in cache\n */\n set(path: string, content: string, lineMap: LineMap): void {\n this.cache.set(path, { content, lineMap });\n }\n\n /**\n * Get cached page data\n */\n get(path: string): CachedPage | undefined {\n return this.cache.get(path);\n }\n\n /**\n * Get page content from cache\n */\n getContent(path: string): string | undefined {\n return this.cache.get(path)?.content;\n }\n\n /**\n * Get line map from cache\n */\n getLineMap(path: string): LineMap | undefined {\n return this.cache.get(path)?.lineMap;\n }\n\n /**\n * Get line range for a specific element path\n */\n getLineRange(pagePath: string, elementPath: string): LineRange | undefined {\n return this.cache.get(pagePath)?.lineMap.get(elementPath);\n }\n\n /**\n * Delete page from cache\n */\n delete(path: string): void {\n this.cache.delete(path);\n }\n\n /**\n * Check if page exists in cache\n */\n has(path: string): boolean {\n return this.cache.has(path);\n }\n\n /**\n * Get all page paths\n */\n keys(): string[] {\n return Array.from(this.cache.keys());\n }\n\n /**\n * Clear all cached pages\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get cache size\n */\n size(): number {\n return this.cache.size;\n }\n\n /**\n * Get all pages content as object (without line maps)\n */\n toObject(): Record<string, string> {\n const obj: Record<string, string> = {};\n this.cache.forEach((value, key) => {\n obj[key] = value.content;\n });\n return obj;\n }\n}\n\n", "/**\n * WebSocket Manager\n * Manages WebSocket connections for HMR\n */\n\nimport type { HMRMessage } from '../shared/types';\nimport { WEBSOCKET_STATES } from '../shared/constants';\nimport type { RuntimeWSClient } from './runtime';\n\nexport class WebSocketManager {\n private clients = new Set<RuntimeWSClient>();\n\n /**\n * Add a WebSocket client\n */\n addClient(ws: RuntimeWSClient): void {\n this.clients.add(ws);\n }\n\n /**\n * Remove a WebSocket client\n */\n removeClient(ws: RuntimeWSClient): void {\n this.clients.delete(ws);\n }\n \n /**\n * Broadcast message to all connected clients\n */\n broadcast(message: HMRMessage | string): void {\n const messageStr = typeof message === 'string' \n ? message \n : JSON.stringify(message);\n \n for (const ws of this.clients) {\n if (ws.readyState === WEBSOCKET_STATES.OPEN) {\n ws.send(messageStr);\n }\n }\n }\n \n /**\n * Broadcast update notification\n */\n broadcastUpdate(path?: string): void {\n this.broadcast({\n type: 'hmr:update',\n path: path || 'all'\n });\n }\n\n /**\n * Broadcast colors/themes update notification\n */\n broadcastColorsUpdate(): void {\n this.broadcast({\n type: 'hmr:colors-update'\n });\n }\n\n /**\n * Broadcast variables update notification\n */\n broadcastVariablesUpdate(): void {\n this.broadcast({\n type: 'hmr:variables-update'\n });\n }\n\n /**\n * Broadcast fonts update notification\n */\n broadcastFontsUpdate(): void {\n this.broadcast({\n type: 'hmr:fonts-update'\n });\n }\n\n /**\n * Broadcast libraries update notification\n */\n broadcastLibrariesUpdate(): void {\n this.broadcast({\n type: 'hmr:libraries-update'\n });\n }\n\n /**\n * Broadcast enums update notification\n */\n broadcastEnumsUpdate(): void {\n this.broadcast({\n type: 'hmr:enums-update'\n });\n }\n\n /**\n * Broadcast CMS content update notification\n */\n broadcastCMSUpdate(collection: string): void {\n this.broadcast({\n type: 'hmr:cms-update',\n collection\n });\n }\n\n /**\n * Broadcast CMS collections-list update notification.\n * Emitted when a template file is added, removed, or its schema changes \u2014\n * tells connected clients to re-fetch the collections list.\n */\n broadcastCollectionsUpdate(): void {\n this.broadcast({\n type: 'hmr:cms-collections-update'\n });\n }\n\n /**\n * Broadcast project.config.json update notification.\n * Emitted when project.config.json changes (e.g. an AI tool adds a new\n * locale) \u2014 tells connected clients to re-fetch config-derived state\n * such as the i18n locale list.\n */\n broadcastConfigUpdate(): void {\n this.broadcast({\n type: 'hmr:config-update'\n });\n }\n\n /**\n * Get number of connected clients\n */\n getClientCount(): number {\n return this.clients.size;\n }\n \n /**\n * Clear all clients\n */\n clear(): void {\n this.clients.clear();\n }\n \n /**\n * Get all clients\n */\n getClients(): Set<RuntimeWSClient> {\n return new Set(this.clients);\n }\n \n /**\n * Check if any clients are connected\n */\n hasClients(): boolean {\n return this.clients.size > 0;\n }\n}\n\n", "/**\n * JSON Line Mapper\n * Parses JSON while tracking line numbers for each element path\n */\n\nexport interface LineRange {\n startLine: number;\n endLine: number;\n}\n\nexport type LineMap = Map<string, LineRange>;\n\n/**\n * Parse JSON text and build a map of path -> line range\n * Path format: \"0\", \"0.1\", \"1.2.3\" (matching pathToString format)\n */\nexport function buildLineMap(jsonText: string): LineMap {\n const lineMap = new Map<string, LineRange>();\n const lines = jsonText.split('\\n');\n\n // Build character offset to line number lookup\n const charToLine: number[] = [];\n let currentLine = 1;\n for (let i = 0; i < jsonText.length; i++) {\n charToLine[i] = currentLine;\n if (jsonText[i] === '\\n') {\n currentLine++;\n }\n }\n\n // Parse JSON and track positions\n let pos = 0;\n\n function skipWhitespace(): void {\n while (pos < jsonText.length && /\\s/.test(jsonText[pos])) {\n pos++;\n }\n }\n\n function parseString(): string {\n if (jsonText[pos] !== '\"') return '';\n pos++; // skip opening \"\n let result = '';\n while (pos < jsonText.length && jsonText[pos] !== '\"') {\n if (jsonText[pos] === '\\\\') {\n pos++; // skip escape\n if (pos < jsonText.length) {\n result += jsonText[pos];\n pos++;\n }\n } else {\n result += jsonText[pos];\n pos++;\n }\n }\n pos++; // skip closing \"\n return result;\n }\n\n function parseNumber(): void {\n while (pos < jsonText.length && /[\\d.eE\\-+]/.test(jsonText[pos])) {\n pos++;\n }\n }\n\n function parseValue(path: number[], trackChildren: boolean): { start: number; end: number } {\n skipWhitespace();\n const startPos = pos;\n\n if (jsonText[pos] === '{') {\n parseObject(path, trackChildren);\n } else if (jsonText[pos] === '[') {\n parseArray(path, trackChildren);\n } else if (jsonText[pos] === '\"') {\n parseString();\n } else if (jsonText[pos] === 't') {\n pos += 4; // true\n } else if (jsonText[pos] === 'f') {\n pos += 5; // false\n } else if (jsonText[pos] === 'n') {\n pos += 4; // null\n } else {\n parseNumber();\n }\n\n return { start: startPos, end: pos };\n }\n\n function recordTrackedRoot(path: number[]): void {\n // Parse the root element of the tracked structure and record its own line range\n // under the empty-string key, so callers can resolve the root selection itself.\n const { start, end } = parseValue(path, true);\n lineMap.set('', {\n startLine: charToLine[start],\n endLine: charToLine[end - 1] || charToLine[start],\n });\n }\n\n function parseObject(path: number[], trackChildren: boolean): void {\n pos++; // skip {\n skipWhitespace();\n\n while (pos < jsonText.length && jsonText[pos] !== '}') {\n skipWhitespace();\n const key = parseString();\n skipWhitespace();\n pos++; // skip :\n skipWhitespace();\n\n if (key === 'root' && path.length === 0) {\n // Page format: track from `root`.\n recordTrackedRoot(path);\n } else if (key === 'component' && path.length === 0) {\n // Component format: descend into the component object looking for `structure`.\n parseComponentWrapper(path);\n } else if (key === 'children' && trackChildren) {\n // Children array \u2014 track each element with indices\n parseValue(path, true);\n } else {\n // Regular property - don't track individual items\n parseValue(path, false);\n }\n\n skipWhitespace();\n if (jsonText[pos] === ',') pos++;\n skipWhitespace();\n }\n pos++; // skip }\n }\n\n function parseComponentWrapper(path: number[]): void {\n // We expect an object value for the `component` key. If it isn't one, just skip it.\n if (jsonText[pos] !== '{') {\n parseValue(path, false);\n return;\n }\n pos++; // skip {\n skipWhitespace();\n while (pos < jsonText.length && jsonText[pos] !== '}') {\n skipWhitespace();\n const key = parseString();\n skipWhitespace();\n pos++; // skip :\n skipWhitespace();\n if (key === 'structure') {\n // The component's structure is the root of what we track \u2014 same as `root` for pages.\n recordTrackedRoot(path);\n } else {\n parseValue(path, false);\n }\n skipWhitespace();\n if (jsonText[pos] === ',') pos++;\n skipWhitespace();\n }\n pos++; // skip }\n }\n\n function parseArray(path: number[], trackChildren: boolean): void {\n pos++; // skip [\n skipWhitespace();\n\n let index = 0;\n while (pos < jsonText.length && jsonText[pos] !== ']') {\n const childPath = [...path, index];\n const { start, end } = parseValue(childPath, trackChildren);\n\n // Record line mapping for this element if we're tracking children\n // Use comma-separated format to match pathToString: [0,1,2] -> \"0,1,2\"\n if (trackChildren) {\n const pathStr = childPath.join(',');\n lineMap.set(pathStr, {\n startLine: charToLine[start],\n endLine: charToLine[end - 1] || charToLine[start]\n });\n }\n\n index++;\n skipWhitespace();\n if (jsonText[pos] === ',') pos++;\n skipWhitespace();\n }\n pos++; // skip ]\n }\n\n // Start parsing from the root\n try {\n skipWhitespace();\n parseValue([], false);\n } catch (e) {\n // If parsing fails, return empty map\n console.error('Failed to build line map:', e);\n }\n\n return lineMap;\n}\n\n/**\n * Convert LineMap to plain object for JSON serialization\n */\nexport function lineMapToObject(lineMap: LineMap): Record<string, LineRange> {\n const obj: Record<string, LineRange> = {};\n lineMap.forEach((value, key) => {\n obj[key] = value;\n });\n return obj;\n}\n", "/**\n * Page Service\n * Handles page loading, caching, and management\n *\n * Provides methods for loading pages from data providers, caching them in memory,\n * and managing page data including saving and deletion.\n */\n\nimport { existsSync, readdirSync, mkdirSync, rmdirSync } from 'fs';\nimport { join } from 'path';\nimport { PageCache } from '../pageCache';\nimport { parseJSON } from '../jsonLoader';\nimport { buildLineMap } from '../utils/jsonLineMapper';\nimport { projectPaths } from '../projectContext';\nimport type { JSONPage } from '../../shared/types';\nimport type { SlugMap } from '../../shared/slugTranslator';\nimport type { PageProvider } from '../../shared/interfaces/contentProvider';\n\nexport class PageService {\n /**\n * Creates a new PageService instance\n *\n * @param pageCache - PageCache instance to use for caching pages\n * @param provider - Optional PageProvider for loading pages (enables DI for testing/CMS)\n */\n constructor(\n private pageCache: PageCache,\n private provider?: PageProvider\n ) {}\n\n /**\n * Set the page provider\n * Allows setting provider after construction for backward compatibility\n *\n * @param provider - PageProvider implementation\n */\n setProvider(provider: PageProvider): void {\n this.provider = provider;\n }\n\n /**\n * Load all pages from the data provider\n *\n * Uses the provider to load pages. If no provider is set, does nothing.\n * Pages are cached in memory for fast access.\n *\n * @returns Promise that resolves when all pages are loaded\n *\n * @example\n * ```typescript\n * await pageService.loadAllPages();\n * const paths = pageService.getAllPagePaths();\n * ```\n */\n async loadAllPages(): Promise<void> {\n if (!this.provider) {\n return;\n }\n\n const pages = await this.provider.loadAll();\n for (const [path, content] of pages) {\n const lineMap = buildLineMap(content);\n this.pageCache.set(path, content, lineMap);\n }\n }\n\n /**\n * Get page content from cache\n *\n * @param path - Page path (e.g., \"/\" or \"/about\")\n * @returns Raw JSON string content, or undefined if page not found\n *\n * @example\n * ```typescript\n * const content = pageService.getPage('/');\n * if (content) {\n * const data = JSON.parse(content);\n * }\n * ```\n */\n getPage(path: string): string | undefined {\n return this.pageCache.getContent(path);\n }\n\n /**\n * Get parsed page data\n *\n * Retrieves page content from cache and parses it as JSON. Returns null if\n * the page doesn't exist or if parsing fails.\n *\n * @param path - Page path (e.g., \"/\" or \"/about\")\n * @returns Parsed JSONPage object, or null if not found or invalid\n *\n * @example\n * ```typescript\n * const pageData = pageService.getPageData('/');\n * if (pageData) {\n * console.log(pageData.meta.title);\n * }\n * ```\n */\n getPageData(path: string): JSONPage | null {\n const content = this.pageCache.getContent(path);\n if (!content) {\n return null;\n }\n\n try {\n return parseJSON<JSONPage>(content);\n } catch {\n return null;\n }\n }\n\n /**\n * Save page content\n *\n * Saves page data via the provider and updates the cache. The page path\n * is converted to a filename (e.g., \"/\" -> \"index.json\", \"/about\" -> \"about.json\").\n *\n * @param path - Page path (e.g., \"/\" or \"/about\")\n * @param data - JSONPage object to save\n * @returns Promise that resolves when the page is saved\n *\n * @throws {Error} If provider is not set or file write fails\n *\n * @example\n * ```typescript\n * await pageService.savePage('/', {\n * meta: { title: 'Home' },\n * root: { type: 'node', tag: 'div', children: [] }\n * });\n * ```\n */\n async savePage(path: string, data: JSONPage): Promise<void> {\n if (!this.provider) {\n throw new Error('PageProvider not set');\n }\n\n // Strip runtime metadata that shouldn't be persisted\n const { _lineMap, ...dataToSave } = data as JSONPage & { _lineMap?: unknown };\n const content = JSON.stringify(dataToSave, null, 2);\n\n await this.provider.save(path, content);\n\n const lineMap = buildLineMap(content);\n this.pageCache.set(path, content, lineMap);\n }\n\n /**\n * Re-read a single page from disk via the provider and refresh the cache.\n *\n * Used by the file watcher for live reload. Provider-based (not a hardcoded\n * JSON read), so it works for any format \u2014 the FileSystem provider returns the\n * raw JSON and the Astro provider returns the parsed model serialized to JSON.\n *\n * @returns true if the cache changed (page updated or confirmed-deleted) and a\n * reload broadcast is warranted; false if the read failed transiently (e.g. a\n * partial mid-write or parse error), in which case the cache is left intact and\n * the next watcher event retries.\n */\n async reloadPageFromDisk(path: string): Promise<boolean> {\n if (!this.provider) return false;\n\n let content: string | null = null;\n try {\n content = await this.provider.get(path);\n } catch {\n // Transient (mid-write / partial .astro parse error) \u2014 keep the cache as-is.\n return false;\n }\n\n if (content) {\n this.pageCache.set(path, content, buildLineMap(content));\n return true;\n }\n\n // No content: only drop from cache if the page is truly gone, not mid-write.\n try {\n if (!(await this.provider.exists(path))) {\n this.pageCache.delete(path);\n return true;\n }\n } catch {\n /* leave cache intact */\n }\n return false;\n }\n\n /**\n * Delete page from cache and optionally from storage\n *\n * Removes a page from the in-memory cache. If provider is set,\n * also deletes from the underlying storage.\n *\n * @param path - Page path to delete\n * @param deleteFromStorage - If true and provider is set, also delete from storage\n *\n * @example\n * ```typescript\n * pageService.deletePage('/old-page');\n * // Or with storage deletion:\n * await pageService.deletePage('/old-page', true);\n * ```\n */\n async deletePage(path: string, deleteFromStorage = false): Promise<void> {\n this.pageCache.delete(path);\n\n if (deleteFromStorage && this.provider) {\n await this.provider.delete(path);\n }\n }\n\n /**\n * Get all page paths\n *\n * Returns an array of all page paths currently in the cache.\n *\n * @returns Array of page paths (e.g., [\"/\", \"/about\", \"/contact\"])\n *\n * @example\n * ```typescript\n * const paths = pageService.getAllPagePaths();\n * console.log(`Loaded ${paths.length} pages`);\n * ```\n */\n getAllPagePaths(): string[] {\n return this.pageCache.keys();\n }\n\n /**\n * Get all pages with their info (including draft status)\n *\n * Returns an array of page info objects including path and draft status.\n *\n * @returns Array of page info objects\n *\n * @example\n * ```typescript\n * const pages = pageService.getAllPagesWithInfo();\n * // [{ path: \"/\", isDraft: false }, { path: \"/about\", isDraft: true }]\n * ```\n */\n getAllPagesWithInfo(): Array<{ path: string; isDraft: boolean; folder?: string }> {\n const paths = this.pageCache.keys().filter(p => !p.startsWith('/_sketch/'));\n return paths.map(path => {\n const pageData = this.getPageData(path);\n // Extract folder from path: /blog/post -> blog, /templates/blog-post -> templates\n // Root-level pages (e.g., /, /about) have no folder\n const pathWithoutSlash = path === '/' ? 'index' : path.substring(1);\n const slashIndex = pathWithoutSlash.lastIndexOf('/');\n const folder = slashIndex > 0 ? pathWithoutSlash.substring(0, slashIndex) : undefined;\n return {\n path,\n isDraft: pageData?.meta?.draft === true,\n ...(folder ? { folder } : {})\n };\n });\n }\n\n /**\n * Get line map for a page\n *\n * Returns the line number mapping for elements in the page JSON.\n *\n * @param path - Page path (e.g., \"/\" or \"/about\")\n * @returns LineMap object or undefined if page not found\n */\n getLineMap(path: string): Map<string, { startLine: number; endLine: number }> | undefined {\n return this.pageCache.getLineMap(path);\n }\n\n /**\n * Pages base directory \u2014 provider-aware (e.g. `src/pages` for astro projects),\n * falling back to `projectPaths.pages()` when the provider doesn't expose\n * `baseDir()` (or no provider is set). Used by the folder/move/rename ops that\n * touch the filesystem directly.\n */\n private pagesBaseDir(): string {\n return this.provider?.baseDir?.() ?? projectPaths.pages();\n }\n\n /** Page file extension (e.g. `.astro` for astro projects), defaulting to `.json`. */\n private pageExt(): string {\n return this.provider?.extension?.() ?? '.json';\n }\n\n /**\n * Get all page folders\n *\n * Scans the pages directory for subdirectories.\n *\n * @returns Sorted array of folder names\n */\n getAllFolders(): string[] {\n const pagesDir = this.pagesBaseDir();\n if (!existsSync(pagesDir)) {\n return [];\n }\n\n const collectFolders = (dir: string, prefix: string): string[] => {\n try {\n const entries = readdirSync(dir, { withFileTypes: true });\n const result: string[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n result.push(relativePath);\n result.push(...collectFolders(join(dir, entry.name), relativePath));\n }\n return result;\n } catch { return []; }\n };\n\n return collectFolders(pagesDir, '').sort();\n }\n\n /**\n * Create a page folder\n *\n * Creates an empty folder in the pages directory.\n *\n * @param folderName - Name of the folder to create\n * @throws {Error} If folder name is invalid or already exists\n */\n async createFolder(folderName: string): Promise<void> {\n if (!folderName || folderName.trim() === '') {\n throw new Error('Folder name cannot be empty');\n }\n\n const trimmed = folderName.trim();\n const segments = trimmed.split('/');\n const segmentRegex = /^[a-z0-9][a-z0-9-_]*$/;\n\n for (const segment of segments) {\n if (!segment) throw new Error('Folder path cannot have empty segments');\n if (!segmentRegex.test(segment)) {\n throw new Error('Each folder segment can only contain lowercase letters, numbers, dashes, and underscores');\n }\n }\n\n const pagesDir = this.pagesBaseDir();\n const folderPath = join(pagesDir, trimmed);\n\n if (existsSync(folderPath)) {\n throw new Error('Folder already exists');\n }\n\n mkdirSync(folderPath, { recursive: true });\n }\n\n /**\n * Move a page to a different folder\n *\n * Moves a page file from its current location to the target folder.\n * If folder is empty string, moves to root pages directory.\n *\n * @param pagePath - Current page path (e.g., \"/blog/post\" or \"/about\")\n * @param newFolder - Target folder name (empty string for root)\n */\n async movePage(pagePath: string, newFolder: string): Promise<void> {\n const { rename } = await import('fs/promises');\n const pagesDir = this.pagesBaseDir();\n const ext = this.pageExt();\n\n // Convert page path to file name: \"/blog/post\" -> \"blog/post\", \"/\" -> \"index\"\n const pageName = pagePath === '/' ? 'index' : pagePath.substring(1);\n // Extract just the filename (without folder): \"blog/post\" -> \"post\", \"about\" -> \"about\"\n const slashIndex = pageName.lastIndexOf('/');\n const baseName = slashIndex >= 0 ? pageName.substring(slashIndex + 1) : pageName;\n\n const sourceFile = join(pagesDir, `${pageName}${ext}`);\n const targetFile = newFolder\n ? join(pagesDir, newFolder, `${baseName}${ext}`)\n : join(pagesDir, `${baseName}${ext}`);\n\n // Create target directory if needed\n if (newFolder) {\n const targetDir = join(pagesDir, newFolder);\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n }\n }\n\n if (!existsSync(sourceFile)) {\n throw new Error(`Page not found: ${pagePath}`);\n }\n\n await rename(sourceFile, targetFile);\n\n // Update cache: remove old path, re-add at new path\n const content = this.pageCache.getContent(pagePath);\n if (content) {\n this.pageCache.delete(pagePath);\n const newPageName = newFolder ? `${newFolder}/${baseName}` : baseName;\n const newPath = newPageName === 'index' ? '/' : `/${newPageName}`;\n const lineMap = buildLineMap(content);\n this.pageCache.set(newPath, content, lineMap);\n }\n\n // Clean up empty source directory\n const sourceDir = slashIndex >= 0\n ? join(pagesDir, pageName.substring(0, slashIndex))\n : null;\n\n if (sourceDir && sourceDir !== pagesDir) {\n try {\n const remaining = readdirSync(sourceDir);\n if (remaining.length === 0) {\n rmdirSync(sourceDir);\n }\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n\n /**\n * Rename a page (file rename + cache update).\n *\n * Renames the underlying .json file from `oldPath`'s filename to `newPath`'s\n * filename, keeping the same folder. Updates the in-memory cache so the\n * page is now keyed at `newPath`. Folder moves stay with `movePage()` \u2014\n * this is purely \"change the URL slug of an existing page\" for\n * single-locale projects.\n *\n * @param oldPath - Current page path (e.g., \"/about\" or \"/blog/post\")\n * @param newPath - New page path with same folder (e.g., \"/about-us\" or \"/blog/new-slug\")\n * @throws {Error} If oldPath doesn't exist, newPath already exists, or paths\n * reference different folders.\n */\n async renamePage(oldPath: string, newPath: string): Promise<void> {\n if (oldPath === newPath) return;\n if (newPath === '/') {\n throw new Error('Cannot rename a page to the index path');\n }\n if (!newPath.startsWith('/')) {\n throw new Error('newPath must start with \"/\"');\n }\n\n const oldName = oldPath === '/' ? 'index' : oldPath.substring(1);\n const newName = newPath.substring(1);\n\n const oldSlash = oldName.lastIndexOf('/');\n const newSlash = newName.lastIndexOf('/');\n const oldFolder = oldSlash >= 0 ? oldName.substring(0, oldSlash) : '';\n const newFolder = newSlash >= 0 ? newName.substring(0, newSlash) : '';\n if (oldFolder !== newFolder) {\n throw new Error('renamePage only changes the filename; use movePage to change folder');\n }\n\n const baseSegment = newSlash >= 0 ? newName.substring(newSlash + 1) : newName;\n if (!/^[a-z0-9][a-z0-9-_]*$/.test(baseSegment)) {\n throw new Error('Page slug can only contain lowercase letters, numbers, dashes, and underscores');\n }\n\n const { rename } = await import('fs/promises');\n const pagesDir = this.pagesBaseDir();\n const ext = this.pageExt();\n const sourceFile = join(pagesDir, `${oldName}${ext}`);\n const targetFile = join(pagesDir, `${newName}${ext}`);\n\n if (!existsSync(sourceFile)) {\n throw new Error(`Page not found: ${oldPath}`);\n }\n if (existsSync(targetFile)) {\n throw new Error(`Page already exists: ${newPath}`);\n }\n\n await rename(sourceFile, targetFile);\n\n const content = this.pageCache.getContent(oldPath);\n if (content) {\n this.pageCache.delete(oldPath);\n const lineMap = buildLineMap(content);\n this.pageCache.set(newPath, content, lineMap);\n }\n }\n\n /**\n * Get slug mappings for all pages\n *\n * Extracts slug translations from all pages' meta.slugs fields.\n * Returns a list of { pageId, slugs } objects for locale-aware routing.\n *\n * @returns Array of SlugMap objects with pageId and translated slugs\n *\n * @example\n * ```typescript\n * const mappings = pageService.getSlugMappings();\n * // [{ pageId: \"about\", slugs: { \"en\": \"about\", \"pl\": \"o-nas\" } }]\n * ```\n */\n getSlugMappings(): SlugMap[] {\n const mappings: SlugMap[] = [];\n const paths = this.pageCache.keys();\n\n for (const path of paths) {\n const pageData = this.getPageData(path);\n if (pageData?.meta?.slugs) {\n // Convert path to pageId (e.g., \"/\" -> \"index\", \"/about\" -> \"about\")\n const pageId = path === '/' ? 'index' : path.substring(1);\n mappings.push({\n pageId,\n slugs: pageData.meta.slugs,\n });\n } else {\n // For pages without explicit slugs, use the path as the slug for all locales\n const pageId = path === '/' ? 'index' : path.substring(1);\n const defaultSlug = path === '/' ? '' : path.substring(1);\n mappings.push({\n pageId,\n slugs: { _default: defaultSlug },\n });\n }\n }\n\n return mappings;\n }\n}\n", "/**\n * Component Service\n * Handles component loading and management\n * \n * Provides methods for loading components from the file system, caching them in memory,\n * and managing component definitions including saving JavaScript and CSS files.\n */\n\nimport { join } from 'path';\nimport { existsSync, mkdirSync, unlinkSync, readdirSync, rmdirSync } from 'fs';\nimport { loadComponentDirectory, loadJSONFile, parseJSON } from '../jsonLoader';\nimport type { ComponentWithCategory, ComponentDirectoryResult, ComponentLoadDiagnostic } from '../jsonLoader';\nimport { projectPaths } from '../projectContext';\nimport type { ComponentDefinition, JSONPage } from '../../shared/types';\nimport { readTextFile, fileExists } from '../runtime';\nimport type { PageService } from './pageService';\nimport { rewriteComponentRefs } from '../../shared/componentRefs';\n\n// Re-export for callers that already imported the helper from this module.\nexport { rewriteComponentRefs };\n\n/**\n * File system interface for dependency injection\n * Allows mocking file operations in tests\n */\nexport interface ComponentServiceFs {\n writeFile(path: string, content: string, encoding: string): Promise<void>;\n readFile?(path: string): Promise<string | null>;\n}\n\n/**\n * Component loader interface for dependency injection\n * Allows mocking component loading in tests\n */\nexport interface ComponentLoader {\n loadDirectory(dir: string): Promise<Map<string, ComponentDefinition>>;\n loadFile(path: string): Promise<string | null>;\n}\n\n/**\n * Component writer interface for dependency injection.\n *\n * This is the WRITE-side mirror of {@link ComponentLoader}. By default (no writer\n * injected) ComponentService keeps its exact JSON behavior \u2014 `.json` definition files\n * plus sibling `.js`/`.css` under `<root>/components/`. Injecting a writer lets a\n * different on-disk format own where and how components are persisted. The astro\n * format (`meno-astro`'s `AstroComponentWriter`) emits a single `.astro` file per\n * component under `src/components/` (structure + JS + CSS + meta folded together).\n *\n * The service still owns category resolution, the in-memory cache, ref-rewriting,\n * and validation; the writer only abstracts the directory + the physical file I/O.\n */\nexport interface ComponentWriter {\n /** Base components directory this writer owns (e.g. `<root>/src/components`). */\n componentsDir(): string;\n\n /**\n * Persist a component definition into `dir` under `name`. For single-file formats\n * (astro) `def` carries everything (structure/interface/js/css/meta); for the JSON\n * writer it is the `.json` payload (js/css live in sibling files written separately).\n */\n writeComponent(dir: string, name: string, def: ComponentDefinition): Promise<void>;\n\n /**\n * Persist the component's JavaScript. `currentDef` is the latest in-memory definition\n * so single-file formats can re-emit the whole `.astro` with the new JS folded in.\n * Multi-file formats (JSON) just write a sibling `<name>.js`.\n */\n writeJavaScript(dir: string, name: string, javascript: string, currentDef?: ComponentDefinition): Promise<void>;\n\n /** Persist the component's CSS. Mirrors {@link writeJavaScript}. */\n writeCSS(dir: string, name: string, css: string, currentDef?: ComponentDefinition): Promise<void>;\n\n /** Delete every on-disk file for `name` in `dir` (definition + any JS/CSS). */\n removeComponent(dir: string, name: string): Promise<void>;\n\n /** Whether any on-disk file for `name` already exists in `dir` (collision check). */\n componentExists(dir: string, name: string): Promise<boolean>;\n\n /** Move every file for `name` from `srcDir` to `dstDir` (category change / rename). */\n moveComponent(srcDir: string, dstDir: string, name: string, dstName?: string): Promise<void>;\n}\n\n/**\n * Component info with category metadata\n */\nexport interface ComponentInfo {\n definition: ComponentDefinition;\n category?: string;\n}\n\nexport class ComponentService {\n private components = new Map<string, ComponentDefinition>();\n private componentCategories = new Map<string, string | undefined>();\n private fs?: ComponentServiceFs;\n private loader?: ComponentLoader;\n private writer?: ComponentWriter;\n private loadErrors = new Map<string, ComponentLoadDiagnostic>();\n private loadWarnings: ComponentLoadDiagnostic[] = [];\n\n /**\n * Creates a new ComponentService instance\n *\n * @param options - Optional configuration for dependency injection\n * @param options.fs - Optional file system interface for testing\n * @param options.loader - Optional component loader interface for testing (READ)\n * @param options.writer - Optional component writer for non-JSON on-disk formats\n * (WRITE). When omitted, the service writes JSON exactly as before \u2014 legacy\n * projects are byte-identical. The astro bootstrap injects an AstroComponentWriter\n * so saves emit `.astro` files under `src/components/`.\n */\n constructor(options?: { fs?: ComponentServiceFs; loader?: ComponentLoader; writer?: ComponentWriter }) {\n this.fs = options?.fs;\n this.loader = options?.loader;\n this.writer = options?.writer;\n }\n\n /**\n * Base components directory \u2014 `<root>/components` for JSON, or whatever the\n * injected writer owns (e.g. `<root>/src/components` for astro). All path\n * resolution (categories, folders, save/move/rename targets) routes through\n * here so a single switch covers every write op.\n * @internal\n */\n private componentsBaseDir(): string {\n return this.writer ? this.writer.componentsDir() : projectPaths.components();\n }\n\n /**\n * Load all components from the components directory\n *\n * Scans the ./components directory recursively and loads all component definitions.\n * Subdirectories are treated as category folders. Clears existing components before loading.\n * Components are loaded from .json files, and associated .js and .css files are\n * automatically loaded if they exist.\n *\n * @returns Promise that resolves when all components are loaded\n *\n * @example\n * ```typescript\n * await componentService.loadAllComponents();\n * const count = Object.keys(componentService.getAllComponents()).length;\n * ```\n */\n async loadAllComponents(): Promise<void> {\n // Build new state locally and swap atomically. Concurrent saves\n // (e.g. ensureAcceptsStyles firing while the file watcher reload runs)\n // must never observe an empty `componentCategories` mid-reload \u2014 that\n // gap was what caused fresh component files to be written at root next\n // to the canonical categorized file.\n const nextComponents = new Map<string, ComponentDefinition>();\n const nextCategories = new Map<string, string | undefined>();\n const nextErrors = new Map<string, ComponentLoadDiagnostic>();\n let nextWarnings: ComponentLoadDiagnostic[] = [];\n\n let loadedComponents: Map<string, ComponentWithCategory>;\n\n if (this.loader) {\n // Legacy loader interface returns plain Map\n loadedComponents = await this.loader.loadDirectory(projectPaths.components()) as Map<string, ComponentWithCategory>;\n } else {\n const result: ComponentDirectoryResult = await loadComponentDirectory(projectPaths.components());\n loadedComponents = result.components;\n\n // Store diagnostics\n nextWarnings = result.warnings;\n for (const error of result.errors) {\n nextErrors.set(error.componentName, error);\n }\n }\n\n loadedComponents.forEach((value, key) => {\n // Extract category from the loaded component (set by recursive loader)\n const componentWithCategory = value as ComponentWithCategory;\n const category = componentWithCategory._category;\n\n nextCategories.set(key, category);\n\n // Remove internal metadata before storing\n const { _category, _relativePath, ...cleanDef } = componentWithCategory;\n nextComponents.set(key, cleanDef as ComponentDefinition);\n });\n\n this.components = nextComponents;\n this.componentCategories = nextCategories;\n this.loadErrors = nextErrors;\n this.loadWarnings = nextWarnings;\n }\n\n /**\n * Get component by name\n * \n * @param name - Component name (without .json extension)\n * @returns ComponentDefinition if found, undefined otherwise\n * \n * @example\n * ```typescript\n * const button = componentService.getComponent('Button');\n * if (button) {\n * console.log(button.component.interface);\n * }\n * ```\n */\n getComponent(name: string): ComponentDefinition | undefined {\n return this.components.get(name);\n }\n\n /**\n * Check if component exists\n * \n * @param name - Component name to check\n * @returns True if component exists in cache, false otherwise\n * \n * @example\n * ```typescript\n * if (componentService.hasComponent('Button')) {\n * // Component is available\n * }\n * ```\n */\n hasComponent(name: string): boolean {\n return this.components.has(name);\n }\n\n /**\n * Get all components as a Record\n *\n * Returns all loaded components as a plain object for easy iteration\n * or serialization.\n *\n * @returns Record mapping component names to ComponentDefinition objects\n *\n * @example\n * ```typescript\n * const allComponents = componentService.getAllComponents();\n * Object.keys(allComponents).forEach(name => {\n * console.log(`Component: ${name}`);\n * });\n * ```\n */\n getAllComponents(): Record<string, ComponentDefinition> {\n const record: Record<string, ComponentDefinition> = {};\n this.components.forEach((value, key) => {\n record[key] = value;\n });\n return record;\n }\n\n /**\n * Get all components with their category information\n *\n * Returns all loaded components with category metadata derived from folder structure.\n *\n * @returns Record mapping component names to ComponentInfo objects (definition + category)\n *\n * @example\n * ```typescript\n * const components = componentService.getAllComponentsWithCategories();\n * Object.entries(components).forEach(([name, info]) => {\n * console.log(`${name}: category=${info.category || 'uncategorized'}`);\n * });\n * ```\n */\n getAllComponentsWithCategories(): Record<string, ComponentInfo> {\n const record: Record<string, ComponentInfo> = {};\n this.components.forEach((value, key) => {\n record[key] = {\n definition: value,\n category: this.componentCategories.get(key)\n };\n });\n return record;\n }\n\n /**\n * Get category for a component\n *\n * @param name - Component name\n * @returns Category string if component is in a category folder, undefined otherwise\n */\n getComponentCategory(name: string): string | undefined {\n return this.componentCategories.get(name);\n }\n\n /**\n * Get load errors keyed by component name\n */\n getLoadErrors(): Map<string, ComponentLoadDiagnostic> {\n return this.loadErrors;\n }\n\n /**\n * Get load warnings\n */\n getLoadWarnings(): ComponentLoadDiagnostic[] {\n return this.loadWarnings;\n }\n\n /**\n * Get all load diagnostics\n */\n getLoadDiagnostics(): { errors: ComponentLoadDiagnostic[]; warnings: ComponentLoadDiagnostic[] } {\n return {\n errors: Array.from(this.loadErrors.values()),\n warnings: this.loadWarnings,\n };\n }\n\n /**\n * Validate that a component has a valid structure\n * \n * @param componentDef - ComponentDefinition to validate\n * @returns true if component has valid structure, false otherwise\n * \n * @example\n * ```typescript\n * const component = componentService.getComponent('Button');\n * if (component && componentService.validateComponentStructure(component)) {\n * // Component has valid structure\n * }\n * ```\n */\n validateComponentStructure(componentDef: ComponentDefinition | undefined): boolean {\n if (!componentDef) {\n return false;\n }\n \n // Handle ComponentDefinition in any format:\n // 1. Legacy: { type: string, component: { structure: {...} } }\n // 2. New: { component: { structure: {...} } }\n // 3. Direct: { component: { structure: {...} } } (already normalized)\n \n // Access component field safely (handle both TypeScript types and runtime data)\n const component = (componentDef as any).component;\n \n if (!component || typeof component !== 'object') {\n return false;\n }\n \n // Check for structure in component\n const structure = component.structure;\n if (!structure) {\n return false;\n }\n \n // Validate structure is a proper object with type property\n if (typeof structure !== 'object' || structure === null || Array.isArray(structure)) {\n return false;\n }\n \n // Structure must have a type property that's a string\n if (!('type' in structure) || typeof structure.type !== 'string') {\n return false;\n }\n \n return true;\n }\n\n /**\n * Get the directory path for a component based on its category\n * @internal\n */\n private getComponentDir(name: string, category?: string): string {\n const componentsDir = this.componentsBaseDir();\n const cat = this.resolveComponentCategory(name, category);\n return cat ? join(componentsDir, cat) : componentsDir;\n }\n\n /**\n * Resolve which category a save should land in. Priority:\n * 1. Explicit caller-supplied category (including '' for root)\n * 2. In-memory categories cache\n * 3. Existing file on disk (defense against a stale/empty cache)\n * Falls back to root only when none of the above resolves. The disk\n * scan in step 3 closes the race where a save fires while\n * loadAllComponents has been called but hasn't rebuilt the cache yet.\n * @internal\n */\n private resolveComponentCategory(name: string, category?: string): string | undefined {\n if (category !== undefined) {\n return category || undefined;\n }\n if (this.componentCategories.has(name)) {\n return this.componentCategories.get(name);\n }\n return this.findComponentCategoryOnDisk(name);\n }\n\n /**\n * Look on disk for an existing `<name>.json` and return its category.\n * Returns undefined for \"exists at root\" or \"not found anywhere\" \u2014 both\n * map to writing at root, which is the right default.\n * @internal\n */\n private findComponentCategoryOnDisk(name: string): string | undefined {\n const componentsDir = this.componentsBaseDir();\n if (!existsSync(componentsDir)) return undefined;\n // File extension is format-specific (.json for JSON, .astro for astro). When a\n // writer is injected we don't know its extension here, so use a synchronous\n // directory scan that matches any `<name>.*` definition file.\n const ext = this.writer ? null : '.json';\n const existsAt = (dir: string): boolean => {\n if (ext) return existsSync(join(dir, `${name}${ext}`));\n try {\n return readdirSync(dir, { withFileTypes: true }).some(\n (e) => e.isFile() && (e.name === `${name}.json` || e.name === `${name}.astro`),\n );\n } catch {\n return false;\n }\n };\n if (existsAt(componentsDir)) return undefined;\n try {\n for (const entry of readdirSync(componentsDir, { withFileTypes: true })) {\n if (entry.isDirectory() && existsAt(join(componentsDir, entry.name))) {\n return entry.name;\n }\n }\n } catch {\n // If the components dir is unreadable, fall through to root.\n }\n return undefined;\n }\n\n /**\n * Get component JavaScript from .js file\n *\n * Loads the JavaScript code for a component from its .js file.\n * Returns null if the file doesn't exist.\n *\n * @param name - Component name (without .js extension)\n * @returns JavaScript code as string, or null if file doesn't exist\n *\n * @example\n * ```typescript\n * const js = await componentService.getComponentJavaScript('Button');\n * if (js) {\n * console.log('Component has JavaScript');\n * }\n * ```\n */\n async getComponentJavaScript(name: string): Promise<string | null> {\n const componentDir = this.getComponentDir(name);\n const jsFilePath = join(componentDir, `${name}.js`);\n try {\n if (await fileExists(jsFilePath)) {\n return await readTextFile(jsFilePath);\n }\n return null;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * Save component definition\n *\n * Saves component definition to a .json file and updates the cache.\n * The javascript field is automatically removed from the saved data\n * (JavaScript should only be in .js files).\n *\n * If category is provided, the component is saved to the category subfolder.\n * If category is undefined and component exists, it stays in its current location.\n * If category is empty string '', component is saved to root (uncategorized).\n *\n * @param name - Component name (without .json extension)\n * @param data - ComponentDefinition object to save\n * @param category - Optional category folder name (empty string for root/uncategorized)\n * @returns Promise that resolves when the component is saved\n *\n * @throws {Error} If file write fails\n *\n * @example\n * ```typescript\n * // Save to root (uncategorized)\n * await componentService.saveComponent('Button', buttonDef);\n *\n * // Save to 'ui' category folder\n * await componentService.saveComponent('Card', cardDef, 'ui');\n * ```\n */\n async saveComponent(name: string, data: ComponentDefinition, category?: string): Promise<void> {\n // Create a copy without the javascript field (JavaScript should only be in .js files)\n const dataWithoutJS = JSON.parse(JSON.stringify(data));\n if (dataWithoutJS?.component?.javascript !== undefined) {\n delete dataWithoutJS.component.javascript;\n }\n\n // Determine target directory. Resolver consults the explicit arg, then\n // the in-memory cache, then disk \u2014 so a save during the file-watcher\n // reload window can't accidentally land at root next to a categorized\n // file.\n const targetCategory = this.resolveComponentCategory(name, category);\n const componentsDir = this.componentsBaseDir();\n const componentDir = targetCategory ? join(componentsDir, targetCategory) : componentsDir;\n\n if (this.writer) {\n // Format-aware write (e.g. emit a `.astro` file). The writer owns directory\n // creation + serialization. The category folder is part of `componentDir`.\n await this.writer.writeComponent(componentDir, name, dataWithoutJS);\n } else {\n // JSON path \u2014 unchanged, byte-identical to legacy behavior.\n const writeFile = this.fs\n ? this.fs.writeFile.bind(this.fs)\n : (await import('fs/promises')).writeFile;\n\n // Create category directory if needed\n if (targetCategory && !existsSync(componentDir)) {\n mkdirSync(componentDir, { recursive: true });\n }\n\n const filePath = join(componentDir, `${name}.json`);\n await writeFile(filePath, JSON.stringify(dataWithoutJS, null, 2), 'utf-8');\n }\n\n // Update in-memory cache\n this.components.set(name, dataWithoutJS);\n this.componentCategories.set(name, targetCategory);\n }\n\n /**\n * Save component JavaScript to .js file\n *\n * Saves JavaScript code to a component's .js file and reloads the component\n * to update the in-memory cache with the new JavaScript.\n *\n * @param name - Component name (without .js extension)\n * @param javascript - JavaScript code to save\n * @returns Promise that resolves when the JavaScript is saved\n *\n * @throws {Error} If file write fails\n *\n * @example\n * ```typescript\n * await componentService.saveComponentJavaScript('Button', 'console.log(\"clicked\");');\n * ```\n */\n async saveComponentJavaScript(name: string, javascript: string): Promise<void> {\n const componentDir = this.getComponentDir(name);\n\n if (this.writer) {\n // Single-file formats (astro) fold JS into the `.astro` file. Re-emit from\n // the latest in-memory definition with the new JS so structure/CSS survive.\n const current = this.components.get(name);\n await this.writer.writeJavaScript(componentDir, name, javascript || '', current);\n const next: ComponentDefinition = current\n ? { ...current, component: { ...current.component, javascript: javascript || '' } }\n : { component: { javascript: javascript || '' } };\n this.components.set(name, next);\n return;\n }\n\n const writeFile = this.fs\n ? this.fs.writeFile.bind(this.fs)\n : (await import('fs/promises')).writeFile;\n const jsFilePath = join(componentDir, `${name}.js`);\n await writeFile(jsFilePath, javascript || '', 'utf-8');\n\n // Reload the component to update the registry with the new JS\n const componentPath = join(componentDir, `${name}.json`);\n const componentData = await loadJSONFile(componentPath);\n if (componentData) {\n const parsed = parseJSON<ComponentDefinition>(componentData);\n try {\n if (await fileExists(jsFilePath)) {\n const jsContent = await readTextFile(jsFilePath);\n if (!parsed.component) {\n parsed.component = {};\n }\n parsed.component.javascript = jsContent;\n }\n } catch (error) {\n // Silently handle JS file read errors\n }\n this.components.set(name, parsed);\n }\n }\n\n /**\n * Save component CSS to .css file\n *\n * Saves CSS code to a component's .css file and reloads the component\n * to update the in-memory cache with the new CSS.\n *\n * @param name - Component name (without .css extension)\n * @param css - CSS code to save\n * @returns Promise that resolves when the CSS is saved\n *\n * @throws {Error} If file write fails\n *\n * @example\n * ```typescript\n * await componentService.saveComponentCSS('Button', '.button { color: blue; }');\n * ```\n */\n async saveComponentCSS(name: string, css: string): Promise<void> {\n const componentDir = this.getComponentDir(name);\n\n if (this.writer) {\n // Single-file formats (astro) fold CSS into the `.astro` file. Re-emit from\n // the latest in-memory definition with the new CSS so structure/JS survive.\n const current = this.components.get(name);\n await this.writer.writeCSS(componentDir, name, css || '', current);\n const next: ComponentDefinition = current\n ? { ...current, component: { ...current.component, css: css || '' } }\n : { component: { css: css || '' } };\n this.components.set(name, next);\n return;\n }\n\n const writeFile = this.fs\n ? this.fs.writeFile.bind(this.fs)\n : (await import('fs/promises')).writeFile;\n const cssFilePath = join(componentDir, `${name}.css`);\n await writeFile(cssFilePath, css || '', 'utf-8');\n\n // Reload the component to update the registry with the new CSS\n const componentPath = join(componentDir, `${name}.json`);\n const componentData = await loadJSONFile(componentPath);\n if (componentData) {\n const parsed = parseJSON<ComponentDefinition>(componentData);\n try {\n if (await fileExists(cssFilePath)) {\n const cssContent = await readTextFile(cssFilePath);\n if (!parsed.component) {\n parsed.component = {};\n }\n parsed.component.css = cssContent;\n }\n } catch (error) {\n // Silently handle CSS file read errors\n }\n this.components.set(name, parsed);\n }\n }\n\n /**\n * Get all component folders (including empty ones)\n *\n * Scans the components directory for subdirectories.\n * Returns all folder names, whether they contain components or not.\n *\n * @returns Array of folder names\n *\n * @example\n * ```typescript\n * const folders = componentService.getAllFolders();\n * // ['ui', 'layout', 'content']\n * ```\n */\n getAllFolders(): string[] {\n const componentsDir = this.componentsBaseDir();\n if (!existsSync(componentsDir)) {\n return [];\n }\n\n try {\n const entries = readdirSync(componentsDir, { withFileTypes: true });\n return entries\n .filter(entry => entry.isDirectory())\n .map(entry => entry.name)\n .sort();\n } catch {\n return [];\n }\n }\n\n /**\n * Create a component folder\n *\n * Creates an empty folder in the components directory.\n * Useful for pre-creating category folders before moving components.\n *\n * @param folderName - Name of the folder to create\n * @returns Promise that resolves when folder is created\n *\n * @throws {Error} If folder creation fails\n *\n * @example\n * ```typescript\n * await componentService.createFolder('ui');\n * ```\n */\n async createFolder(folderName: string): Promise<void> {\n if (!folderName || folderName.trim() === '') {\n throw new Error('Folder name cannot be empty');\n }\n\n // Validate folder name (alphanumeric, dashes, underscores only)\n const sanitized = folderName.trim().toLowerCase().replace(/[^a-z0-9-_]/g, '-');\n if (sanitized !== folderName.trim()) {\n throw new Error('Folder name can only contain lowercase letters, numbers, dashes, and underscores');\n }\n\n const componentsDir = this.componentsBaseDir();\n const folderPath = join(componentsDir, folderName);\n\n if (existsSync(folderPath)) {\n throw new Error('Folder already exists');\n }\n\n mkdirSync(folderPath, { recursive: true });\n }\n\n /**\n * Move component to a different category folder\n *\n * Moves all component files (.json, .js, .css) from current location to new category folder.\n * If newCategory is empty string or undefined, moves to root (uncategorized).\n *\n * @param name - Component name\n * @param newCategory - Target category folder (empty string or undefined for root)\n * @returns Promise that resolves when move is complete\n *\n * @throws {Error} If component doesn't exist or move fails\n *\n * @example\n * ```typescript\n * // Move Button from root to 'ui' category\n * await componentService.moveComponent('Button', 'ui');\n *\n * // Move Card from 'ui' to root (uncategorized)\n * await componentService.moveComponent('Card', '');\n * ```\n */\n async moveComponent(name: string, newCategory: string | undefined): Promise<void> {\n const currentCategory = this.componentCategories.get(name);\n const targetCategory = newCategory || undefined;\n\n // No-op if category unchanged\n if (currentCategory === targetCategory) {\n return;\n }\n\n const componentsDir = this.componentsBaseDir();\n const sourceDir = currentCategory ? join(componentsDir, currentCategory) : componentsDir;\n const targetDir = targetCategory ? join(componentsDir, targetCategory) : componentsDir;\n\n if (this.writer) {\n // Format-aware move (e.g. relocate the single `.astro` file). The writer\n // owns target-dir creation + which files belong to the component.\n await this.writer.moveComponent(sourceDir, targetDir, name);\n } else {\n // Create target directory if needed\n if (targetCategory && !existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n }\n\n // Move all component files (.json, .js, .css)\n const extensions = ['.json', '.js', '.css'];\n const { rename } = await import('fs/promises');\n\n for (const ext of extensions) {\n const sourcePath = join(sourceDir, `${name}${ext}`);\n const targetPath = join(targetDir, `${name}${ext}`);\n\n if (existsSync(sourcePath)) {\n await rename(sourcePath, targetPath);\n }\n }\n }\n\n // Update category mapping\n this.componentCategories.set(name, targetCategory);\n\n // Clean up empty source directory (only if it's a category folder, not root)\n if (currentCategory) {\n try {\n const remaining = readdirSync(sourceDir);\n if (remaining.length === 0) {\n rmdirSync(sourceDir);\n }\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n\n /**\n * Rename a component across the project.\n *\n * Renames the component's `.json`/`.js`/`.css` files on disk (respecting its\n * category folder), updates the in-memory caches, rewrites every\n * `{ type: \"component\", component: \"<oldName>\" }` reference inside other\n * component structures, and \u2014 if `pageService` is provided \u2014 also walks every\n * page/template and rewrites references there, saving any pages that changed.\n *\n * Matching is structural (only `node.component` string equality), not\n * text-based, so it never touches HTML tags, CSS classes, prop values, or\n * embedded markup that happen to contain the name as a substring.\n *\n * @throws {Error} If old/new name is missing, names are identical, new name\n * isn't a valid JS identifier, the source component doesn't exist, or the\n * new name is already taken.\n */\n async renameComponent(\n oldName: string,\n newName: string,\n pageService?: PageService,\n ): Promise<{\n oldName: string;\n newName: string;\n category: string | undefined;\n componentRefs: number;\n pageRefs: number;\n }> {\n if (!oldName || typeof oldName !== 'string') {\n throw new Error('oldName is required');\n }\n if (!newName || typeof newName !== 'string') {\n throw new Error('newName is required');\n }\n const trimmedNew = newName.trim();\n if (oldName === trimmedNew) {\n throw new Error('newName must differ from oldName');\n }\n if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(trimmedNew)) {\n throw new Error('newName must be a valid JavaScript identifier');\n }\n if (!this.components.has(oldName)) {\n throw new Error(`Component \"${oldName}\" not found`);\n }\n if (this.components.has(trimmedNew)) {\n throw new Error(`Component \"${trimmedNew}\" already exists`);\n }\n\n const category = this.componentCategories.get(oldName);\n const componentsDir = this.componentsBaseDir();\n const dir = category ? join(componentsDir, category) : componentsDir;\n\n if (this.writer) {\n // On-disk collision check (format-aware) + move the component's file(s).\n if (await this.writer.componentExists(dir, trimmedNew)) {\n throw new Error(`Component \"${trimmedNew}\" already exists in components/${category ?? ''}`);\n }\n await this.writer.moveComponent(dir, dir, oldName, trimmedNew);\n } else {\n // On-disk collision check \u2014 defends against a stale cache where the file\n // exists but wasn't loaded (e.g. a parse error masked it).\n for (const ext of ['.json', '.js', '.css'] as const) {\n if (existsSync(join(dir, `${trimmedNew}${ext}`))) {\n throw new Error(`File \"${trimmedNew}${ext}\" already exists in components/${category ?? ''}`);\n }\n }\n\n const { rename } = await import('fs/promises');\n for (const ext of ['.json', '.js', '.css'] as const) {\n const src = join(dir, `${oldName}${ext}`);\n const dst = join(dir, `${trimmedNew}${ext}`);\n if (existsSync(src)) {\n await rename(src, dst);\n }\n }\n }\n\n // Move the cache entries to the new key.\n const def = this.components.get(oldName)!;\n this.components.delete(oldName);\n this.componentCategories.delete(oldName);\n this.components.set(trimmedNew, def);\n this.componentCategories.set(trimmedNew, category);\n\n // Rewrite references in every OTHER component's structure and persist\n // each one that actually changed. The owning component's own structure\n // shouldn't reference itself, so we don't bother walking it.\n let componentRefs = 0;\n const writeFile = this.fs\n ? this.fs.writeFile.bind(this.fs)\n : (await import('fs/promises')).writeFile;\n for (const [name, otherDef] of this.components.entries()) {\n if (name === trimmedNew) continue;\n const structure = otherDef.component?.structure;\n if (!structure) continue;\n if (rewriteComponentRefs(structure, oldName, trimmedNew)) {\n const otherCategory = this.componentCategories.get(name);\n const otherDir = otherCategory ? join(componentsDir, otherCategory) : componentsDir;\n // Strip the runtime-only javascript field on save, matching saveComponent.\n const persisted = JSON.parse(JSON.stringify(otherDef));\n if (persisted?.component?.javascript !== undefined) {\n delete persisted.component.javascript;\n }\n if (this.writer) {\n await this.writer.writeComponent(otherDir, name, persisted);\n } else {\n await writeFile(join(otherDir, `${name}.json`), JSON.stringify(persisted, null, 2), 'utf-8');\n }\n componentRefs++;\n }\n }\n\n // Walk every page (and CMS template \u2014 they're loaded under /templates/*)\n // and rewrite refs. Save pages that actually changed.\n let pageRefs = 0;\n if (pageService) {\n const pagePaths = pageService.getAllPagePaths();\n for (const path of pagePaths) {\n const pageData = pageService.getPageData(path);\n if (!pageData || !('root' in pageData) || !pageData.root) continue;\n if (rewriteComponentRefs(pageData.root, oldName, trimmedNew)) {\n await pageService.savePage(path, pageData as JSONPage);\n pageRefs++;\n }\n }\n }\n\n return {\n oldName,\n newName: trimmedNew,\n category,\n componentRefs,\n pageRefs,\n };\n }\n}\n\n", "/**\n * Enum Service\n * Manages loading and caching of project-level enums from enums.json\n */\n\nimport { loadJSONFile, parseJSON } from '../jsonLoader';\nimport { projectPaths } from '../projectContext';\nimport type { EnumsConfig } from '../../shared/types';\nimport { CachedConfigLoader } from './CachedConfigLoader';\nimport { writeFile } from '../runtime';\n\nexport class EnumService extends CachedConfigLoader<EnumsConfig> {\n /**\n * Load enums configuration from enums.json\n */\n async loadConfig(): Promise<EnumsConfig> {\n return this.load();\n }\n\n protected async performLoad(): Promise<EnumsConfig> {\n // Load both files in parallel \u2014 enums.json takes priority over config fallback\n const [enumsContent, configContent] = await Promise.all([\n loadJSONFile(projectPaths.enums()).catch(() => null),\n loadJSONFile(projectPaths.config()).catch(() => null),\n ]);\n\n // Try enums.json first\n if (enumsContent) {\n try {\n const data = parseJSON(enumsContent);\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n return this.validateEnums(data as Record<string, unknown>);\n }\n } catch (error) {\n console.warn('Failed to parse enums.json:', error);\n }\n }\n\n // Fallback: check project.config.json for existing enums (migration support)\n if (configContent) {\n try {\n const configData = parseJSON(configContent);\n if (configData && typeof configData === 'object' && 'enums' in configData) {\n const enums = (configData as Record<string, unknown>).enums;\n if (enums && typeof enums === 'object' && !Array.isArray(enums)) {\n return this.validateEnums(enums as Record<string, unknown>);\n }\n }\n } catch {\n // Ignore errors from config fallback\n }\n }\n\n return this.getDefaultConfig();\n }\n\n private getDefaultConfig(): EnumsConfig {\n return {};\n }\n\n /**\n * Validate that all values are string arrays\n */\n private validateEnums(data: Record<string, unknown>): EnumsConfig {\n const result: Record<string, string[]> = {};\n for (const [key, value] of Object.entries(data)) {\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n result[key] = value;\n }\n }\n return result;\n }\n\n /**\n * Get config with status info (for editor UI)\n */\n async getConfigWithStatus(): Promise<{\n status: 'valid' | 'missing' | 'invalid';\n config: EnumsConfig;\n error?: string;\n filePath: string;\n }> {\n const filePath = projectPaths.enums();\n try {\n const content = await loadJSONFile(filePath);\n if (!content) {\n // File doesn't exist - try migration fallback\n const fallbackConfig = await this.performLoad();\n const hasFallback = Object.keys(fallbackConfig).length > 0;\n return {\n status: hasFallback ? 'valid' : 'missing',\n config: fallbackConfig,\n filePath,\n };\n }\n const data = parseJSON(content);\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n return { status: 'valid', config: this.validateEnums(data as Record<string, unknown>), filePath };\n }\n return { status: 'invalid', config: this.getDefaultConfig(), error: 'Invalid structure: expected Record<string, string[]>', filePath };\n } catch (error) {\n return {\n status: 'invalid',\n config: this.getDefaultConfig(),\n error: error instanceof Error ? error.message : 'Parse error',\n filePath,\n };\n }\n }\n\n /**\n * Save enums configuration to enums.json\n */\n async saveConfig(config: EnumsConfig): Promise<void> {\n const enumsPath = projectPaths.enums();\n const content = JSON.stringify(config, null, 2);\n await writeFile(enumsPath, content);\n this.setCache(config);\n }\n}\n\n// Export singleton instance\nexport const enumService = new EnumService();\n", "/**\n * File Watcher\n * Watches for changes in JSON files and triggers callbacks\n */\n\nimport { watch, existsSync } from 'fs';\nimport { basename, dirname, join } from 'path';\nimport type { FSWatcher } from 'fs';\nimport { mapPageNameToPath } from './jsonLoader';\nimport { projectPaths, getProjectRoot } from './projectContext';\n\n/**\n * Attach a recursive watcher to `dirPath`. If the directory doesn't exist\n * yet, watch the parent directory and defer the attach until the target is\n * created (e.g. a blank project that doesn't ship with `templates/` or `cms/`\n * gets one added later by an external tool).\n *\n * Returns the currently active FSWatcher (which may be the deferred parent\n * watcher until the target appears, then the proper recursive watcher).\n */\nfunction attachWhenDirExists(\n dirPath: string,\n attach: () => FSWatcher | null,\n setWatcher: (w: FSWatcher | null) => void\n): void {\n if (existsSync(dirPath)) {\n setWatcher(attach());\n return;\n }\n\n const parentDir = dirname(dirPath);\n const targetName = basename(dirPath);\n if (!existsSync(parentDir)) {\n // Parent doesn't exist either \u2014 give up; nothing reasonable to watch.\n return;\n }\n\n let parentWatcher: FSWatcher | null = null;\n parentWatcher = watch(parentDir, (_event, filename) => {\n if (filename !== targetName) return;\n if (!existsSync(dirPath)) return;\n // Target exists now \u2014 tear down the parent watcher and attach the real one.\n parentWatcher?.close();\n parentWatcher = null;\n setWatcher(attach());\n });\n setWatcher(parentWatcher);\n}\n\nexport interface FileWatchCallbacks {\n onComponentChange?: () => Promise<void>;\n onPageChange?: (pagePath: string) => Promise<void>;\n onColorsChange?: () => Promise<void>;\n onVariablesChange?: () => Promise<void>;\n onEnumsChange?: () => Promise<void>;\n onCMSChange?: (collection: string) => Promise<void>;\n onImageAdded?: (filename: string) => Promise<void>;\n onLibraryChange?: () => Promise<void>;\n onProjectConfigChange?: () => Promise<void>;\n}\n\nexport class FileWatcher {\n private componentsWatcher: FSWatcher | null = null;\n private pagesWatcher: FSWatcher | null = null;\n private templatesWatcher: FSWatcher | null = null;\n private colorsWatcher: FSWatcher | null = null;\n private variablesWatcher: FSWatcher | null = null;\n private enumsWatcher: FSWatcher | null = null;\n private cmsWatcher: FSWatcher | null = null;\n private imagesWatcher: FSWatcher | null = null;\n private librariesWatcher: FSWatcher | null = null;\n private projectConfigWatcher: FSWatcher | null = null;\n // Astro-format projects keep pages/components/CMS under src/ as .astro/.json.\n private astroPagesWatcher: FSWatcher | null = null;\n private astroComponentsWatcher: FSWatcher | null = null;\n private astroContentWatcher: FSWatcher | null = null;\n\n constructor(private callbacks: FileWatchCallbacks) {}\n \n /**\n * Start watching components directory\n * Watches both .json and .js files to detect component definition and JavaScript changes\n */\n watchComponents(dirPath: string = projectPaths.components()): void {\n if (!existsSync(dirPath)) {\n return;\n }\n \n this.componentsWatcher = watch(\n dirPath,\n { recursive: true },\n async (event, filename) => {\n // Watch .json (component definitions), .js (component JavaScript), and .css (component CSS) files\n if (filename && (filename.endsWith('.json') || filename.endsWith('.js') || filename.endsWith('.css'))) {\n const fileType = filename.endsWith('.js') ? 'JavaScript' : filename.endsWith('.css') ? 'CSS' : 'component';\n \n if (this.callbacks.onComponentChange) {\n await this.callbacks.onComponentChange();\n }\n }\n }\n );\n \n }\n \n /**\n * Start watching pages directory\n */\n watchPages(dirPath: string = projectPaths.pages()): void {\n if (!existsSync(dirPath)) {\n return;\n }\n\n this.pagesWatcher = watch(\n dirPath,\n { recursive: true },\n async (event, filename) => {\n if (filename && filename.endsWith('.json')) {\n const pageName = filename.replace('.json', '');\n const pagePath = mapPageNameToPath(pageName);\n\n if (this.callbacks.onPageChange) {\n await this.callbacks.onPageChange(pagePath);\n }\n }\n }\n );\n\n }\n\n /**\n * Start watching root templates directory for CMS template changes.\n * Falls back to a deferred-attach watcher on the project root when\n * `templates/` doesn't exist yet (blank projects, projects that have never\n * had a CMS collection).\n */\n watchTemplates(dirPath: string = projectPaths.templates()): void {\n attachWhenDirExists(\n dirPath,\n () => watch(\n dirPath,\n { recursive: true },\n async (event, filename) => {\n if (filename && filename.endsWith('.json')) {\n // Prefix with templates/ so the path is /templates/...\n const pageName = `templates/${filename.replace('.json', '')}`;\n const pagePath = mapPageNameToPath(pageName);\n\n if (this.callbacks.onPageChange) {\n await this.callbacks.onPageChange(pagePath);\n }\n }\n }\n ),\n (w) => { this.templatesWatcher = w; }\n );\n }\n \n /**\n * Start watching colors.json file\n */\n watchColors(filePath: string = projectPaths.colors()): void {\n if (!existsSync(filePath)) {\n return;\n }\n\n // Watch the file's directory for changes\n const dirPath = getProjectRoot();\n this.colorsWatcher = watch(\n dirPath,\n { recursive: false },\n async (event, filename) => {\n if (filename === 'colors.json' && this.callbacks.onColorsChange) {\n await this.callbacks.onColorsChange();\n }\n }\n );\n }\n\n /**\n * Start watching variables.json file\n */\n watchVariables(): void {\n const dirPath = getProjectRoot();\n this.variablesWatcher = watch(\n dirPath,\n { recursive: false },\n async (event, filename) => {\n if (filename === 'variables.json' && this.callbacks.onVariablesChange) {\n await this.callbacks.onVariablesChange();\n }\n }\n );\n }\n\n /**\n * Start watching enums.json file\n */\n watchEnums(): void {\n const dirPath = getProjectRoot();\n this.enumsWatcher = watch(\n dirPath,\n { recursive: false },\n async (event, filename) => {\n if (filename === 'enums.json' && this.callbacks.onEnumsChange) {\n await this.callbacks.onEnumsChange();\n }\n }\n );\n }\n\n /**\n * Start watching CMS directory.\n * Watches for changes in CMS content files (cms/{collection}/*.json).\n * Falls back to a deferred-attach watcher when `cms/` doesn't exist yet.\n */\n watchCMS(dirPath: string = projectPaths.cms()): void {\n attachWhenDirExists(\n dirPath,\n () => watch(\n dirPath,\n { recursive: true },\n async (event, filename) => {\n if (filename && filename.endsWith('.json')) {\n // Extract collection from path: \"blog/my-post.json\" -> \"blog\"\n const collection = filename.split('/')[0];\n if (this.callbacks.onCMSChange) {\n await this.callbacks.onCMSChange(collection);\n }\n }\n }\n ),\n (w) => { this.cmsWatcher = w; }\n );\n }\n\n /**\n * Start watching images directory for new source images\n */\n watchImages(dirPath: string = projectPaths.images()): void {\n if (!existsSync(dirPath)) {\n return;\n }\n\n this.imagesWatcher = watch(\n dirPath,\n { recursive: false },\n async (event, filename) => {\n if (event === 'rename' && filename && this.callbacks.onImageAdded) {\n await this.callbacks.onImageAdded(filename);\n }\n }\n );\n }\n\n /**\n * Start watching project.config.json for changes.\n * Picks up edits to i18n locales, breakpoints, libraries, icons, etc. so the\n * studio reflects external writes (e.g. an AI tool adding a new locale) without\n * a dev-server restart.\n */\n watchProjectConfig(): void {\n const dirPath = getProjectRoot();\n this.projectConfigWatcher = watch(\n dirPath,\n { recursive: false },\n async (_event, filename) => {\n if (filename === 'project.config.json' && this.callbacks.onProjectConfigChange) {\n await this.callbacks.onProjectConfigChange();\n }\n }\n );\n }\n\n /**\n * Start watching libraries directory for CSS/JS changes\n */\n watchLibraries(dirPath: string = projectPaths.libraries()): void {\n if (!existsSync(dirPath)) {\n return;\n }\n\n this.librariesWatcher = watch(\n dirPath,\n { recursive: true },\n async (event, filename) => {\n if (filename && (filename.endsWith('.css') || filename.endsWith('.js'))) {\n if (this.callbacks.onLibraryChange) {\n await this.callbacks.onLibraryChange();\n }\n }\n }\n );\n }\n\n /**\n * Astro-format projects keep pages/components/CMS under src/ as .astro/.json.\n * The onPageChange/onComponentChange/onCMSChange callbacks are format-agnostic\n * (reload goes through the active provider), so file\u2192editor live reload works\n * for `.astro` the same way it does for JSON. These are no-ops in JSON projects\n * (the src/ dirs don't exist).\n */\n watchAstroPages(dirPath: string = join(getProjectRoot(), 'src', 'pages')): void {\n if (!existsSync(dirPath)) return;\n this.astroPagesWatcher = watch(dirPath, { recursive: true }, async (_event, filename) => {\n // Skip dynamic CMS routes ([slug].astro) \u2014 those are CMS templates, not pages.\n if (filename && filename.endsWith('.astro') && !filename.includes('[')) {\n const pagePath = mapPageNameToPath(filename.replace(/\\.astro$/, ''));\n if (this.callbacks.onPageChange) await this.callbacks.onPageChange(pagePath);\n }\n });\n }\n\n watchAstroComponents(dirPath: string = join(getProjectRoot(), 'src', 'components')): void {\n if (!existsSync(dirPath)) return;\n this.astroComponentsWatcher = watch(dirPath, { recursive: true }, async (_event, filename) => {\n if (filename && filename.endsWith('.astro') && this.callbacks.onComponentChange) {\n await this.callbacks.onComponentChange();\n }\n });\n }\n\n watchAstroContent(dirPath: string = join(getProjectRoot(), 'src', 'content')): void {\n if (!existsSync(dirPath)) return;\n this.astroContentWatcher = watch(dirPath, { recursive: true }, async (_event, filename) => {\n if (filename && filename.endsWith('.json') && this.callbacks.onCMSChange) {\n const collection = filename.split('/')[0];\n await this.callbacks.onCMSChange(collection);\n }\n });\n }\n\n /**\n * Start watching all directories\n */\n watchAll(): void {\n this.watchComponents();\n this.watchPages();\n this.watchTemplates();\n this.watchColors();\n this.watchVariables();\n this.watchEnums();\n this.watchCMS();\n this.watchImages();\n this.watchLibraries();\n this.watchProjectConfig();\n // Astro-format dirs (no-ops in JSON projects).\n this.watchAstroPages();\n this.watchAstroComponents();\n this.watchAstroContent();\n }\n \n /**\n * Stop watching all directories\n */\n stopAll(): void {\n if (this.componentsWatcher) {\n this.componentsWatcher.close();\n this.componentsWatcher = null;\n }\n\n if (this.pagesWatcher) {\n this.pagesWatcher.close();\n this.pagesWatcher = null;\n }\n\n if (this.templatesWatcher) {\n this.templatesWatcher.close();\n this.templatesWatcher = null;\n }\n\n if (this.colorsWatcher) {\n this.colorsWatcher.close();\n this.colorsWatcher = null;\n }\n\n if (this.variablesWatcher) {\n this.variablesWatcher.close();\n this.variablesWatcher = null;\n }\n\n if (this.enumsWatcher) {\n this.enumsWatcher.close();\n this.enumsWatcher = null;\n }\n\n if (this.cmsWatcher) {\n this.cmsWatcher.close();\n this.cmsWatcher = null;\n }\n\n if (this.imagesWatcher) {\n this.imagesWatcher.close();\n this.imagesWatcher = null;\n }\n\n if (this.librariesWatcher) {\n this.librariesWatcher.close();\n this.librariesWatcher = null;\n }\n\n if (this.projectConfigWatcher) {\n this.projectConfigWatcher.close();\n this.projectConfigWatcher = null;\n }\n\n if (this.astroPagesWatcher) {\n this.astroPagesWatcher.close();\n this.astroPagesWatcher = null;\n }\n\n if (this.astroComponentsWatcher) {\n this.astroComponentsWatcher.close();\n this.astroComponentsWatcher = null;\n }\n\n if (this.astroContentWatcher) {\n this.astroContentWatcher.close();\n this.astroContentWatcher = null;\n }\n }\n\n /**\n * Check if watchers are active\n */\n isWatching(): boolean {\n return this.componentsWatcher !== null || this.pagesWatcher !== null || this.cmsWatcher !== null || this.imagesWatcher !== null;\n }\n}\n\n", "/**\n * File Watcher Service\n * Manages file watching for pages and components\n */\n\nimport { FileWatcher, type FileWatchCallbacks } from '../fileWatcher';\nimport { WebSocketManager } from '../websocketManager';\nimport { ComponentService } from './componentService';\nimport { PageService } from './pageService';\nimport type { CMSService } from './cmsService';\nimport { PageCache } from '../pageCache';\nimport { colorService } from './ColorService';\nimport { variableService } from './VariableService';\nimport { enumService } from './EnumService';\nimport { configService } from './configService';\n\nexport class FileWatcherService {\n private fileWatcher: FileWatcher | null = null;\n /** Timer for debouncing refreshSchemas calls from burst fs.watch events */\n private refreshSchemasTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n private componentService: ComponentService,\n private pageService: PageService,\n private pageCache: PageCache,\n private wsManager: WebSocketManager,\n private cmsService?: CMSService,\n private onImageAdded?: (filename: string) => Promise<void>\n ) {}\n\n /**\n * Initialize file watchers\n */\n initialize(): void {\n this.fileWatcher = new FileWatcher({\n onComponentChange: async () => {\n await this.componentService.loadAllComponents();\n this.wsManager.broadcastUpdate('all');\n },\n onPageChange: async (pagePath: string) => {\n // Provider-based reload so .astro and JSON projects both live-reload. The\n // provider re-reads (and, for astro, re-parses) the file; a transient\n // mid-write returns false and is left for the next watcher event.\n if (await this.pageService.reloadPageFromDisk(pagePath)) {\n this.wsManager.broadcastUpdate(pagePath);\n }\n\n // Refresh CMS schemas when template files change\n // Debounced to coalesce burst fs.watch events (multiple events per write)\n if (pagePath.startsWith('/templates/') && this.cmsService) {\n if (this.refreshSchemasTimer !== null) {\n clearTimeout(this.refreshSchemasTimer);\n }\n const cmsService = this.cmsService;\n const wsManager = this.wsManager;\n this.refreshSchemasTimer = setTimeout(async () => {\n this.refreshSchemasTimer = null;\n await cmsService.refreshSchemas();\n // Tell connected studio clients to re-fetch the collections list.\n // Without this, the CMS panel only refreshes after a dev-server\n // restart even though the server cache is now correct.\n wsManager.broadcastCollectionsUpdate();\n }, 50);\n }\n },\n onColorsChange: async () => {\n // Clear the color service cache so it reloads on next request\n colorService.clearCache();\n // Broadcast to all clients to refresh their color data\n this.wsManager.broadcastColorsUpdate();\n },\n onVariablesChange: async () => {\n // Clear the variable service cache so it reloads on next request\n variableService.clearCache();\n // Broadcast to all clients to refresh their variables data\n this.wsManager.broadcastVariablesUpdate();\n },\n onEnumsChange: async () => {\n // Clear the enum service cache so it reloads on next request\n enumService.clearCache();\n // Broadcast to all clients to refresh their enums data\n this.wsManager.broadcastEnumsUpdate();\n },\n onCMSChange: async (collection: string) => {\n // Drop the items cache for this collection so the next read returns\n // fresh data immediately, not the previous TTL-cached snapshot.\n this.cmsService?.clearItemsCache(collection);\n // Broadcast to all clients to refresh CMS content\n this.wsManager.broadcastCMSUpdate(collection);\n },\n onImageAdded: this.onImageAdded,\n onLibraryChange: async () => {\n this.wsManager.broadcastLibrariesUpdate();\n },\n onProjectConfigChange: async () => {\n // Reset the singleton config cache so the next read pulls the new\n // i18n locales / breakpoints / icons from disk. Without this, the\n // config API would keep serving the stale snapshot.\n configService.reset();\n await configService.load();\n this.wsManager.broadcastConfigUpdate();\n },\n });\n\n this.fileWatcher.watchAll();\n }\n\n /**\n * Stop file watchers\n */\n stop(): void {\n if (this.refreshSchemasTimer !== null) {\n clearTimeout(this.refreshSchemasTimer);\n this.refreshSchemasTimer = null;\n }\n if (this.fileWatcher) {\n this.fileWatcher.stopAll();\n this.fileWatcher = null;\n }\n }\n}\n\n", "/**\n * CORS Middleware\n * Handles Cross-Origin Resource Sharing headers\n */\n\nexport interface CorsOptions {\n origin?: string | string[] | ((origin: string) => boolean);\n methods?: string[];\n allowedHeaders?: string[];\n credentials?: boolean;\n}\n\nconst DEFAULT_OPTIONS: CorsOptions = {\n origin: '*',\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Authorization'],\n credentials: false,\n};\n\n/**\n * Create CORS headers for a response\n */\nexport function createCorsHeaders(options: CorsOptions = {}): Record<string, string> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const headers: Record<string, string> = {};\n\n // Handle origin\n if (opts.origin) {\n if (typeof opts.origin === 'function') {\n // Dynamic origin - would need request origin to evaluate\n headers['Access-Control-Allow-Origin'] = '*';\n } else if (Array.isArray(opts.origin)) {\n headers['Access-Control-Allow-Origin'] = opts.origin.join(', ');\n } else {\n headers['Access-Control-Allow-Origin'] = opts.origin;\n }\n }\n\n // Handle methods\n if (opts.methods && opts.methods.length > 0) {\n headers['Access-Control-Allow-Methods'] = opts.methods.join(', ');\n }\n\n // Handle headers\n if (opts.allowedHeaders && opts.allowedHeaders.length > 0) {\n headers['Access-Control-Allow-Headers'] = opts.allowedHeaders.join(', ');\n }\n\n // Handle credentials\n if (opts.credentials) {\n headers['Access-Control-Allow-Credentials'] = 'true';\n }\n\n return headers;\n}\n\n/**\n * Handle CORS preflight requests\n */\nexport function handleCorsPreflight(req: Request, options: CorsOptions = {}): Response | null {\n if (req.method === 'OPTIONS') {\n return new Response(null, {\n status: 204,\n headers: createCorsHeaders(options),\n });\n }\n return null;\n}\n\n", "/**\n * Error Handler Middleware\n * Centralized error handling for routes\n */\n\nexport interface ErrorResponse {\n error: string;\n message?: string;\n status: number;\n}\n\n/**\n * Create an error response\n */\nexport function createErrorResponse(\n error: unknown,\n status: number = 500,\n message?: string\n): Response {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const response: ErrorResponse = {\n error: errorMessage,\n status,\n };\n\n if (message) {\n response.message = message;\n }\n\n return new Response(JSON.stringify(response), {\n status,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n}\n\n/**\n * Handle errors in async route handlers\n */\nexport async function handleRouteError(\n handler: () => Promise<Response>,\n errorMessage: string = 'Internal server error'\n): Promise<Response> {\n try {\n return await handler();\n } catch (error) {\n return createErrorResponse(error, 500, errorMessage);\n }\n}\n\n/**\n * Wrap a route handler with error handling\n */\nexport function withErrorHandling<T extends unknown[]>(\n handler: (...args: T) => Promise<Response>,\n errorMessage?: string\n): (...args: T) => Promise<Response> {\n return async (...args: T) => {\n return handleRouteError(() => handler(...args), errorMessage);\n };\n}\n\n", "/**\n * Logger Middleware\n * Request logging for development and debugging\n */\n\nexport interface LogOptions {\n logRequests?: boolean;\n logErrors?: boolean;\n logResponseTime?: boolean;\n}\n\nconst DEFAULT_OPTIONS: LogOptions = {\n logRequests: true,\n logErrors: true,\n logResponseTime: true,\n};\n\n/**\n * Log a request\n */\nexport function logRequest(\n req: Request,\n options: LogOptions = {}\n): void {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n \n if (!opts.logRequests) {\n return;\n }\n\n const url = new URL(req.url);\n const timestamp = new Date().toISOString();\n}\n\n/**\n * Log an error\n */\nexport function logError(\n error: unknown,\n context?: string,\n options: LogOptions = {}\n): void {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n \n if (!opts.logErrors) {\n return;\n }\n\n const timestamp = new Date().toISOString();\n const contextStr = context ? ` [${context}]` : '';\n const errorMessage = error instanceof Error ? error.message : String(error);\n \n if (error instanceof Error && error.stack) {\n }\n}\n\n/**\n * Log response time\n */\nexport function logResponseTime(\n startTime: number,\n req: Request,\n options: LogOptions = {}\n): void {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n \n if (!opts.logResponseTime) {\n return;\n }\n\n const url = new URL(req.url);\n const duration = Date.now() - startTime;\n}\n\n/**\n * Wrap a route handler with logging\n */\nexport function withLogging<T extends unknown[]>(\n handler: (...args: T) => Promise<Response>,\n options: LogOptions = {}\n): (...args: T) => Promise<Response> {\n return async (...args: T) => {\n const startTime = Date.now();\n const req = args[0] as Request;\n \n logRequest(req, options);\n \n try {\n const response = await handler(...args);\n logResponseTime(startTime, req, options);\n return response;\n } catch (error) {\n logError(error, req.method, options);\n logResponseTime(startTime, req, options);\n throw error;\n }\n };\n}\n\n", "/**\n * Shared utilities for API routes\n */\n\nimport { createCorsHeaders } from '../../middleware/cors';\n\n/**\n * Helper function for JSON responses with CORS headers\n */\nexport function jsonResponse(data: unknown, options: { status?: number } = {}): Response {\n const corsHeaders = createCorsHeaders();\n\n return new Response(JSON.stringify(data), {\n status: options.status || 200,\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-store, max-age=0',\n 'Pragma': 'no-cache',\n 'Expires': '0',\n ...corsHeaders,\n },\n });\n}\n\n/**\n * Helper function for error responses with CORS headers\n */\nexport function errorResponse(message: string, status: number = 500): Response {\n return jsonResponse({ error: message }, { status });\n}\n\n/**\n * Cheap, fast 32-bit string hash (FNV-1a). Used to build ETag values for\n * read endpoints \u2014 collision chance is tiny and a false match only delays\n * propagation of a change by one revalidation cycle.\n */\nfunction fnv1a(str: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * JSON response variant that lets the browser keep the body cached and\n * revalidates cheaply via `ETag` / `If-None-Match`. Returns 304 with no\n * body when the client already has the same version. Used by the\n * high-frequency read endpoints (`/api/page-content`, `/api/components`)\n * so iframe page navigations don't re-download identical bodies.\n */\nexport function cachedJsonResponse(\n req: Request,\n body: string,\n options: { status?: number; contentType?: string } = {},\n): Response {\n const corsHeaders = createCorsHeaders();\n const contentType = options.contentType ?? 'application/json';\n const etag = `W/\"${fnv1a(body)}\"`;\n const ifNoneMatch = req.headers.get('if-none-match');\n\n // 304 path: identical body, skip transmission and parsing on the client.\n if (ifNoneMatch && ifNoneMatch === etag) {\n return new Response(null, {\n status: 304,\n headers: {\n 'ETag': etag,\n 'Cache-Control': 'no-cache',\n ...corsHeaders,\n },\n });\n }\n\n return new Response(body, {\n status: options.status ?? 200,\n headers: {\n 'Content-Type': contentType,\n 'ETag': etag,\n // `no-cache` (not `no-store`) \u2014 browser may keep the body but must\n // revalidate every time. Pairs with the 304 branch above.\n 'Cache-Control': 'no-cache',\n ...corsHeaders,\n },\n });\n}\n\n", "/**\n * CMS API Routes\n * Handles CMS content CRUD endpoints\n */\n\nimport type { CMSService } from '../../services/cmsService';\nimport type { CMSSchema } from '../../../shared/types';\nimport { jsonResponse, errorResponse } from './shared';\nimport { addItemUrls } from '../../../shared/itemTemplateUtils';\nimport { extractStringValue } from '../../../shared/slugify';\n\n/**\n * GET /api/cms/collections - List all collections with their schemas\n */\nexport function handleCollectionsRoute(cmsService: CMSService): Response {\n const schemas = cmsService.getAllSchemas();\n const collections: CMSSchema[] = [];\n\n for (const [, schemaInfo] of schemas) {\n collections.push(schemaInfo.schema);\n }\n\n return jsonResponse({ collections });\n}\n\n/**\n * GET /api/cms/collections/:collection - Get schema for specific collection\n */\nexport function handleCollectionSchemaRoute(\n collection: string,\n cmsService: CMSService\n): Response {\n const schema = cmsService.getSchema(collection);\n\n if (!schema) {\n return errorResponse('Collection not found', 404);\n }\n\n return jsonResponse({ schema });\n}\n\n// Note: handleCreateCollectionRoute moved to @meno/studio\n\n/**\n * GET /api/cms/:collection - List items in a collection with pagination\n * Query params:\n * - limit: max items to return (default: all)\n * - offset: items to skip (default: 0)\n * - search: filter items by title/slug containing this string\n */\nexport async function handleItemsRoute(\n collection: string,\n cmsService: CMSService,\n searchParams?: URLSearchParams\n): Promise<Response> {\n // Parse pagination params\n const limit = searchParams?.get('limit') ? parseInt(searchParams.get('limit')!, 10) : undefined;\n const offset = searchParams?.get('offset') ? parseInt(searchParams.get('offset')!, 10) : undefined;\n const search = searchParams?.get('search') || undefined;\n\n // Get total count first (without limit/offset)\n const allItems = await cmsService.queryItems({ collection });\n const total = allItems.length;\n\n // Apply search filter if provided\n let filteredItems = allItems;\n if (search) {\n const searchLower = search.toLowerCase();\n const schema = cmsService.getSchema(collection);\n const slugField = schema?.slugField || 'slug';\n\n filteredItems = allItems.filter(item => {\n // Search in title, slug, and filename\n const title = extractStringValue(item.title || '').toLowerCase();\n const slug = extractStringValue(item[slugField] || item._slug || '').toLowerCase();\n const filename = String(item._filename || '').toLowerCase();\n return title.includes(searchLower) || slug.includes(searchLower) || filename.includes(searchLower);\n });\n }\n\n // Apply pagination\n let items = filteredItems;\n if (offset !== undefined && offset > 0) {\n items = items.slice(offset);\n }\n if (limit !== undefined && limit > 0) {\n items = items.slice(0, limit);\n }\n\n // Add computed _url field to items for template access ({{item._url}})\n const schema = cmsService.getSchema(collection);\n const itemsWithUrl = schema ? addItemUrls(items, schema) : items;\n\n return jsonResponse({\n items: itemsWithUrl,\n total: search ? filteredItems.length : total,\n limit,\n offset: offset || 0\n });\n}\n\n/**\n * GET /api/cms/:collection/:slug - Get specific item by slug\n */\nexport async function handleItemRoute(\n collection: string,\n slug: string,\n cmsService: CMSService\n): Promise<Response> {\n const match = await cmsService.matchRoute(\n cmsService.getSchema(collection)?.urlPattern.replace('{{slug}}', slug) || ''\n );\n\n // If no match via route, try direct provider access\n if (!match) {\n // For direct item access, we need to check if item exists\n const items = await cmsService.queryItems({ collection });\n const item = items.find(i => i._slug === slug || i[cmsService.getSchema(collection)?.slugField || 'slug'] === slug);\n\n if (!item) {\n return errorResponse('Item not found', 404);\n }\n\n return jsonResponse({ item });\n }\n\n return jsonResponse({ item: match.item });\n}\n\n// Note: Write handlers (handleCreateItemRoute, handleUpdateItemRoute, handleDeleteItemRoute)\n// moved to @meno/studio\n", "/**\n * Core API Routes (Read-only)\n * These routes are part of meno-core and handle read operations\n */\n\nimport { API_ROUTES } from '../../../shared/constants';\nimport type { PageService } from '../../services/pageService';\nimport type { ComponentService } from '../../services/componentService';\nimport type { CMSService } from '../../services/cmsService';\nimport { configService } from '../../services/configService';\nimport { handleRouteError } from '../../middleware/errorHandler';\nimport { generateFontCSS, loadProjectConfig } from '../../../shared/fontLoader';\n\n// Import route handlers\nimport * as pagesRoutes from './pages';\nimport * as componentsRoutes from './components';\nimport * as configRoutes from './config';\nimport * as colorsRoutes from './colors';\nimport * as variablesRoutes from './variables';\nimport * as enumsRoutes from './enums';\nimport * as cmsRoutes from './cms';\nimport { handleFunctionsRoute, handleFunctionsPreflight } from './functions';\n\n/** Context for core API routes */\nexport interface CoreRouteContext {\n pageService: PageService;\n componentService: ComponentService;\n cmsService?: CMSService;\n}\n\n/**\n * Handle core API routes (read-only operations)\n * Returns undefined if route is not handled\n */\nexport async function handleCoreApiRoutes(\n req: Request,\n url: URL,\n context: CoreRouteContext\n): Promise<Response | undefined> {\n const { pageService, componentService, cmsService } = context;\n\n // Handle CORS preflight for project functions\n const preflightResponse = handleFunctionsPreflight(req, url);\n if (preflightResponse) {\n return preflightResponse;\n }\n\n // Handle project functions (e.g., /api/contact -> functions/api/contact.ts)\n const functionsResponse = await handleFunctionsRoute(req, url);\n if (functionsResponse) {\n return functionsResponse;\n }\n\n // Pages API routes (read-only)\n if (url.pathname === API_ROUTES.PAGES && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(pagesRoutes.handlePagesRoute(pageService)),\n 'Failed to fetch pages list'\n );\n }\n\n if (url.pathname.startsWith(API_ROUTES.PAGE_DATA) && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(pagesRoutes.handlePageDataRoute(url, pageService)),\n 'Failed to fetch page data'\n );\n }\n\n if (url.pathname === API_ROUTES.PAGE_CONTENT && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(pagesRoutes.handlePageContentRoute(req, url, pageService)),\n 'Failed to fetch page content'\n );\n }\n\n // Components API routes (read-only)\n if (url.pathname === API_ROUTES.COMPONENTS && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(componentsRoutes.handleComponentsRoute(req, componentService)),\n 'Failed to fetch components list'\n );\n }\n\n if (url.pathname.startsWith('/api/component-data/') && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(componentsRoutes.handleComponentDataRoute(url, componentService)),\n 'Failed to fetch component data'\n );\n }\n\n if (url.pathname.startsWith('/api/component-js/') && req.method === 'GET') {\n return await handleRouteError(\n () => componentsRoutes.handleComponentJavaScriptRoute(url, componentService),\n 'Failed to fetch component JavaScript'\n );\n }\n\n // Config API routes (read-only)\n if (url.pathname === '/api/config' && req.method === 'GET') {\n return await handleRouteError(\n () => configRoutes.handleConfigRoute(),\n 'Failed to fetch config'\n );\n }\n\n if (url.pathname === '/api/components-config' && req.method === 'GET') {\n return await handleRouteError(\n () => configRoutes.handleComponentsConfigRoute(),\n 'Failed to fetch components config'\n );\n }\n\n // Colors API routes (read-only)\n if (url.pathname === '/api/colors' && req.method === 'GET') {\n return await handleRouteError(\n () => colorsRoutes.handleColorsRoute(url),\n 'Failed to fetch colors'\n );\n }\n\n if (url.pathname === '/api/themes' && req.method === 'GET') {\n return await handleRouteError(\n () => colorsRoutes.handleThemesRoute(),\n 'Failed to fetch themes'\n );\n }\n\n if (url.pathname === '/api/colors-config' && req.method === 'GET') {\n return await handleRouteError(\n () => colorsRoutes.handleColorsConfigRoute(),\n 'Failed to fetch colors config'\n );\n }\n\n if (url.pathname === '/api/colors-status' && req.method === 'GET') {\n return await handleRouteError(\n () => colorsRoutes.handleColorsStatusRoute(),\n 'Failed to fetch colors status'\n );\n }\n\n // Variables API routes (read-only)\n if (url.pathname === '/api/variables-status' && req.method === 'GET') {\n return await handleRouteError(\n () => variablesRoutes.handleVariablesStatusRoute(),\n 'Failed to fetch variables status'\n );\n }\n\n if (url.pathname === '/api/variables-css' && req.method === 'GET') {\n return await handleRouteError(\n () => variablesRoutes.handleVariablesCSSRoute(),\n 'Failed to generate variables CSS'\n );\n }\n\n // Fonts CSS route (read-only)\n if (url.pathname === '/api/fonts-css' && req.method === 'GET') {\n return await handleRouteError(\n async () => {\n await loadProjectConfig();\n const css = generateFontCSS();\n return new Response(css, {\n headers: { 'Content-Type': 'text/css' },\n });\n },\n 'Failed to generate fonts CSS'\n );\n }\n\n // Enums API route (read-only)\n if (url.pathname === '/api/enums' && req.method === 'GET') {\n return await handleRouteError(\n () => enumsRoutes.handleEnumsRoute(),\n 'Failed to fetch enums'\n );\n }\n\n // Usage API route (for license limit checks)\n if (url.pathname === '/api/usage' && req.method === 'GET') {\n return await handleRouteError(\n () => {\n // Count CMS collections\n const cmsCollections = cmsService ? cmsService.getAllSchemas().size : 0;\n\n // Count pages (exclude templates directory)\n const allPages = pageService.getAllPagePaths();\n const pages = allPages.filter(p => !p.includes('/templates/')).length;\n\n // Count locales from config\n const i18n = configService.getI18n();\n const locales = i18n.locales.length;\n\n return Promise.resolve(\n new Response(JSON.stringify({ cmsCollections, pages, locales }), {\n headers: { 'Content-Type': 'application/json' }\n })\n );\n },\n 'Failed to fetch usage stats'\n );\n }\n\n // Component usage API route (read-only)\n if (url.pathname === API_ROUTES.COMPONENT_USAGE && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(componentsRoutes.handleComponentUsageRoute(pageService, componentService)),\n 'Failed to fetch component usage'\n );\n }\n\n // Slug mappings API route (read-only)\n if (url.pathname === '/api/slug-mappings' && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(pagesRoutes.handleSlugMappingsRoute(pageService)),\n 'Failed to fetch slug mappings'\n );\n }\n\n // CMS API routes (read-only - only if CMS service is available)\n if (cmsService && url.pathname.startsWith('/api/cms/')) {\n // GET /api/cms/collections - List all collections\n if (url.pathname === '/api/cms/collections' && req.method === 'GET') {\n return await handleRouteError(\n () => Promise.resolve(cmsRoutes.handleCollectionsRoute(cmsService)),\n 'Failed to fetch CMS collections'\n );\n }\n\n // GET /api/cms/collections/:collection - Get collection schema\n const collectionSchemaMatch = url.pathname.match(/^\\/api\\/cms\\/collections\\/([^/]+)$/);\n if (collectionSchemaMatch && req.method === 'GET') {\n const collection = collectionSchemaMatch[1];\n return await handleRouteError(\n () => Promise.resolve(cmsRoutes.handleCollectionSchemaRoute(collection, cmsService)),\n 'Failed to fetch collection schema'\n );\n }\n\n // Parse collection and slug from path: /api/cms/:collection/:slug?\n const cmsPathMatch = url.pathname.match(/^\\/api\\/cms\\/([^/]+)(?:\\/([^/]+))?$/);\n if (cmsPathMatch) {\n const collection = cmsPathMatch[1];\n const slug = cmsPathMatch[2];\n\n // Skip if this is the 'collections' path (handled above)\n if (collection === 'collections') {\n return undefined;\n }\n\n // GET /api/cms/:collection - List items (supports pagination via query params)\n if (!slug && req.method === 'GET') {\n return await handleRouteError(\n () => cmsRoutes.handleItemsRoute(collection, cmsService, url.searchParams),\n 'Failed to fetch CMS items'\n );\n }\n\n // GET /api/cms/:collection/:slug - Get item\n if (slug && req.method === 'GET') {\n return await handleRouteError(\n () => cmsRoutes.handleItemRoute(collection, slug, cmsService),\n 'Failed to fetch CMS item'\n );\n }\n }\n }\n\n return undefined;\n}\n", "/**\n * Pages API Routes\n * Handles page CRUD endpoints\n */\n\nimport type { PageService } from '../../services/pageService';\nimport { API_ROUTES } from '../../../shared/constants';\nimport { parseJSON } from '../../jsonLoader';\nimport { createCorsHeaders } from '../../middleware/cors';\nimport { jsonResponse, cachedJsonResponse } from './shared';\n\n/**\n * Handle pages API endpoint - GET /api/pages\n * Returns pages with draft status info\n */\nexport function handlePagesRoute(pageService: PageService): Response {\n const pages = pageService.getAllPagesWithInfo();\n return jsonResponse({ pages });\n}\n\n/**\n * Handle page data API endpoint - GET /api/page-data/:path\n */\nexport function handlePageDataRoute(\n url: URL,\n pageService: PageService\n): Response {\n const pagePath = url.pathname.replace(API_ROUTES.PAGE_DATA, '') || '/';\n const content = pageService.getPage(pagePath);\n\n if (content) {\n try {\n const parsedContent = parseJSON(content);\n // Include line map for element line number tracking\n const lineMap = pageService.getLineMap(pagePath);\n const lineMapObj: Record<string, { startLine: number; endLine: number }> = {};\n if (lineMap) {\n lineMap.forEach((value, key) => {\n lineMapObj[key] = value;\n });\n }\n return jsonResponse({ ...(parsedContent as Record<string, unknown>), _lineMap: lineMapObj });\n } catch (error) {\n return jsonResponse({ error: 'Invalid JSON' }, { status: 500 });\n }\n } else {\n return jsonResponse({ error: 'Page not found' }, { status: 404 });\n }\n}\n\n// Note: handleSavePageRoute moved to @meno/studio\n\n/**\n * Handle page content API endpoint - GET /api/page-content?page=...\n * Returns raw JSON text for client routing, prefetching, and studio editor.\n * Uses ETag revalidation so repeat navigations to the same page get a 304\n * instead of re-transmitting an unchanged body.\n */\nexport function handlePageContentRoute(\n req: Request,\n url: URL,\n pageService: PageService\n): Response {\n const page = url.searchParams.get('page') || '/';\n const content = pageService.getPage(page);\n\n if (content) {\n return cachedJsonResponse(req, content);\n }\n const corsHeaders = createCorsHeaders();\n return new Response('Page not found', {\n status: 404,\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-store, max-age=0',\n ...corsHeaders,\n },\n });\n}\n\n/**\n * Handle slug mappings API endpoint - GET /api/slug-mappings\n * Returns all page slug translations for locale switching\n */\nexport function handleSlugMappingsRoute(pageService: PageService): Response {\n const mappings = pageService.getSlugMappings();\n return jsonResponse({ mappings });\n}\n\n", "/**\n * Components API Routes\n * Handles component CRUD endpoints\n */\n\nimport type { ComponentService } from '../../services/componentService';\nimport type { PageService } from '../../services/pageService';\nimport type { ComponentNode } from '../../../shared/types';\nimport { createCorsHeaders } from '../../middleware/cors';\nimport { jsonResponse, cachedJsonResponse } from './shared';\nimport { formatJsonErrorMessage } from '../../../shared/jsonRepair';\n\n/**\n * Handle components API endpoint - GET /api/components\n * Returns components with category metadata derived from folder structure.\n * Uses ETag revalidation so repeat page navigations get a 304 when the\n * registry hasn't changed.\n */\nexport function handleComponentsRoute(\n req: Request,\n componentService: ComponentService,\n): Response {\n const componentsWithCategories = componentService.getAllComponentsWithCategories();\n\n // Transform to API format: { name: { ...definition, _category } }\n const result: Record<string, any> = {};\n for (const [name, info] of Object.entries(componentsWithCategories)) {\n result[name] = {\n ...info.definition,\n _category: info.category\n };\n }\n\n // Include load diagnostics if any\n const diagnostics = componentService.getLoadDiagnostics();\n if (diagnostics.errors.length > 0 || diagnostics.warnings.length > 0) {\n result._diagnostics = diagnostics;\n }\n\n return cachedJsonResponse(req, JSON.stringify(result));\n}\n\n/**\n * Handle component data API endpoint - GET /api/component-data/:name\n * Validates that component has structure before returning\n */\nexport function handleComponentDataRoute(\n url: URL,\n componentService: ComponentService\n): Response {\n const componentName = url.pathname.replace('/api/component-data/', '');\n const componentDef = componentService.getComponent(componentName);\n\n if (!componentDef) {\n // Check if there's a JSON parse error for this component\n const loadErrors = componentService.getLoadErrors();\n const diagnostic = loadErrors.get(componentName);\n if (diagnostic) {\n const message = formatJsonErrorMessage(\n `${diagnostic.componentName}.json`,\n { message: diagnostic.description, line: diagnostic.line, column: diagnostic.column }\n );\n return jsonResponse(\n { error: 'json_parse_error', message, errorCode: 'JSON_PARSE_ERROR' },\n { status: 422 }\n );\n }\n return jsonResponse({ error: 'Component not found' }, { status: 404 });\n }\n\n // Debug: Log what we're about to return\n\n // Validate that component has structure\n if (!componentService.validateComponentStructure(componentDef)) {\n return jsonResponse(\n { \n error: 'Component structure is missing',\n message: `Component \"${componentName}\" does not have a valid structure definition. Please add a structure field to the component definition.`\n }, \n { status: 400 }\n );\n }\n\n return jsonResponse(componentDef);\n}\n\n/**\n * Handle component JavaScript API endpoint - GET /api/component-js/:name\n */\nexport async function handleComponentJavaScriptRoute(\n url: URL,\n componentService: ComponentService\n): Promise<Response> {\n const componentName = url.pathname.replace('/api/component-js/', '');\n const jsContent = await componentService.getComponentJavaScript(componentName);\n const corsHeaders = createCorsHeaders();\n\n return new Response(jsContent || '', {\n headers: {\n 'Content-Type': 'text/javascript',\n ...corsHeaders,\n },\n });\n}\n\n/**\n * Handle component usage API endpoint - GET /api/component-usage\n * Returns how many times each component is used across all pages and other components\n */\nexport function handleComponentUsageRoute(\n pageService: PageService,\n componentService: ComponentService\n): Response {\n const usageMap = new Map<string, { count: number; files: Map<string, { name: string; path: string; type: 'page' | 'component' }> }>();\n\n function walkTree(node: ComponentNode | undefined | null, fileName: string, filePath: string, fileType: 'page' | 'component') {\n if (!node || typeof node !== 'object') return;\n if (node.type === 'component' && 'component' in node && (node as any).component) {\n const compName = (node as any).component as string;\n if (!usageMap.has(compName)) {\n usageMap.set(compName, { count: 0, files: new Map() });\n }\n const entry = usageMap.get(compName)!;\n entry.count++;\n entry.files.set(filePath, { name: fileName, path: filePath, type: fileType });\n }\n if ('children' in node && Array.isArray((node as any).children)) {\n for (const child of (node as any).children) {\n if (child && typeof child === 'object') {\n walkTree(child as ComponentNode, fileName, filePath, fileType);\n }\n }\n }\n }\n\n // Walk all pages\n const pagePaths = pageService.getAllPagePaths();\n for (const path of pagePaths) {\n const pageData = pageService.getPageData(path);\n if (pageData && 'root' in pageData && pageData.root) {\n const name = path === '/' ? 'index' : path.replace(/^\\//, '').replace(/\\//g, '-');\n walkTree(pageData.root, name, path, 'page');\n }\n }\n\n // Walk all component structures\n const allComponents = componentService.getAllComponents();\n for (const [compName, compDef] of Object.entries(allComponents)) {\n if (compDef.component?.structure) {\n walkTree(compDef.component.structure, compName, compName, 'component');\n }\n }\n\n // Convert to plain object\n const result: Record<string, { count: number; files: Array<{ name: string; path: string; type: 'page' | 'component' }> }> = {};\n for (const [name, data] of usageMap) {\n result[name] = {\n count: data.count,\n files: Array.from(data.files.values()),\n };\n }\n\n return jsonResponse(result);\n}\n\n// Note: Write handlers (handleSaveComponentRoute, handleSaveComponentJavaScriptRoute,\n// handleSaveComponentCSSRoute, handleComponentCategoryRoute) moved to @meno/studio\n\n", "/**\n * Config API Routes\n * Handles configuration endpoints\n */\n\nimport { loadJSONFile, parseJSON } from '../../jsonLoader';\nimport { projectPaths } from '../../projectContext';\nimport { jsonResponse, errorResponse } from './shared';\n\n/**\n * Handle config API endpoint - GET /api/config\n */\nexport async function handleConfigRoute(): Promise<Response> {\n try {\n const configContent = await loadJSONFile(projectPaths.config());\n if (configContent) {\n const config = parseJSON(configContent);\n return jsonResponse(config);\n } else {\n return jsonResponse({ editor: { theme: 'dark' } });\n }\n } catch (error) {\n return jsonResponse({ editor: { theme: 'dark' } });\n }\n}\n\n/**\n * Handle components config API endpoint - GET /api/components-config\n */\nexport async function handleComponentsConfigRoute(): Promise<Response> {\n try {\n const configContent = await loadJSONFile(projectPaths.componentsConfig());\n if (configContent) {\n const config = parseJSON(configContent);\n return jsonResponse(config);\n } else {\n // Return empty defaults if file doesn't exist\n return jsonResponse({ componentTypes: [], componentCategories: {} });\n }\n } catch (error) {\n return jsonResponse({ componentTypes: [], componentCategories: {} });\n }\n}\n\n// Note: handleSaveConfigRoute moved to @meno/studio\n// Note: handleSaveComponentsConfigRoute moved to @meno/studio\n\n", "/**\n * Colors API Routes\n * Handles color variables endpoints with theme support\n */\n\nimport { colorService } from '../../services/ColorService';\nimport { jsonResponse } from './shared';\n\n/**\n * Handle colors API endpoint - GET /api/colors?theme=<themeName>\n */\nexport async function handleColorsRoute(url?: URL): Promise<Response> {\n const themeName = url?.searchParams.get('theme') || undefined;\n const colors = await colorService.getThemeColors(themeName);\n return jsonResponse(colors);\n}\n\n/**\n * Handle themes API endpoint - GET /api/themes\n */\nexport async function handleThemesRoute(): Promise<Response> {\n const themes = await colorService.getAvailableThemes();\n const defaultTheme = await colorService.getDefaultTheme();\n return jsonResponse({ themes, default: defaultTheme });\n}\n\n/**\n * Handle full colors config API endpoint - GET /api/colors-config\n */\nexport async function handleColorsConfigRoute(): Promise<Response> {\n const config = await colorService.getFullConfig();\n return jsonResponse(config);\n}\n\n/**\n * Handle colors status API endpoint - GET /api/colors-status\n * Returns status info: whether file exists, is valid, or has errors\n */\nexport async function handleColorsStatusRoute(): Promise<Response> {\n const result = await colorService.getConfigWithStatus();\n return jsonResponse(result);\n}\n\n// Note: handleSaveColorsRoute moved to @meno/studio\n", "/**\n * Variables API Routes (Read-only)\n * Handles CSS variables status and CSS generation endpoints\n */\n\nimport { variableService } from '../../services/VariableService';\nimport { generateVariablesCSS } from '../../cssGenerator';\nimport { loadBreakpointConfig } from '../../jsonLoader';\nimport { configService } from '../../services/configService';\nimport { jsonResponse } from './shared';\n\n/**\n * Handle variables status API endpoint - GET /api/variables-status\n * Returns status info: whether file exists, is valid, or has errors\n */\nexport async function handleVariablesStatusRoute(): Promise<Response> {\n const result = await variableService.getConfigWithStatus();\n return jsonResponse(result);\n}\n\n/**\n * Handle variables CSS API endpoint - GET /api/variables-css\n * Returns generated CSS custom properties from variables.json\n */\nexport async function handleVariablesCSSRoute(): Promise<Response> {\n await configService.load();\n const variablesConfig = await variableService.loadConfig();\n const breakpointConfig = await loadBreakpointConfig();\n const responsiveScalesConfig = configService.getResponsiveScales();\n const css = generateVariablesCSS(variablesConfig, breakpointConfig, responsiveScalesConfig);\n return new Response(css, {\n headers: { 'Content-Type': 'text/css' }\n });\n}\n", "/**\n * Enums API Routes (Read-only)\n * Handles project-level enums endpoint\n */\n\nimport { enumService } from '../../services/EnumService';\nimport { jsonResponse } from './shared';\n\n/**\n * Handle enums API endpoint - GET /api/enums\n * Returns enums config with status info\n */\nexport async function handleEnumsRoute(): Promise<Response> {\n const result = await enumService.getConfigWithStatus();\n return jsonResponse(result);\n}\n", "/**\n * Functions Route Handler (Development)\n * Loads and executes Cloudflare Pages Functions locally for development\n *\n * In production, Cloudflare Pages handles these routes directly.\n * This handler simulates the Cloudflare environment for local dev.\n */\n\nimport { projectPaths } from '../../projectContext';\nimport path from 'path';\nimport { readTextFile, fileExists } from '../../runtime';\n\n/**\n * Mock Cloudflare EventContext for local development\n */\ninterface MockEventContext {\n request: Request;\n env: Record<string, string>;\n params: Record<string, string>;\n waitUntil: (promise: Promise<unknown>) => void;\n passThroughOnException: () => void;\n}\n\n/**\n * Load environment variables from project .env file\n */\nasync function loadProjectEnv(): Promise<Record<string, string>> {\n const envPath = projectPaths.env();\n const env: Record<string, string> = {};\n\n try {\n if (await fileExists(envPath)) {\n const content = await readTextFile(envPath);\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed && !trimmed.startsWith('#')) {\n const [key, ...valueParts] = trimmed.split('=');\n if (key) {\n // Remove quotes from value if present\n let value = valueParts.join('=');\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n env[key.trim()] = value;\n }\n }\n }\n }\n } catch (error) {\n console.warn('Could not load .env file:', error);\n }\n\n return env;\n}\n\n/**\n * Handle API function requests in development\n * Routes like /api/contact are mapped to /functions/api/contact.ts\n */\nexport async function handleFunctionsRoute(\n req: Request,\n url: URL\n): Promise<Response | undefined> {\n // Only handle /api/* routes\n if (!url.pathname.startsWith('/api/')) {\n return undefined;\n }\n\n // Skip /api/editor/* routes - those are handled by the editor API\n if (url.pathname.startsWith('/api/editor/')) {\n return undefined;\n }\n\n // Extract function path from URL\n // /api/contact -> functions/api/contact.ts\n const functionPath = url.pathname.replace('/api/', '');\n const functionFilePath = path.join(\n projectPaths.functions(),\n 'api',\n `${functionPath}.ts`\n );\n\n // Check if function file exists\n if (!(await fileExists(functionFilePath))) {\n // Also try .js extension\n const jsFilePath = functionFilePath.replace('.ts', '.js');\n if (!(await fileExists(jsFilePath))) {\n return undefined; // Let other handlers deal with it\n }\n }\n\n try {\n // Dynamically import the function module\n // Use timestamp to bust cache in development\n const moduleUrl = `${functionFilePath}?t=${Date.now()}`;\n const functionModule = await import(moduleUrl);\n\n // Determine which handler to call based on HTTP method\n const method = req.method.toUpperCase();\n const handlerName = `onRequest${method.charAt(0)}${method.slice(1).toLowerCase()}`;\n\n // Try method-specific handler first, then generic onRequest\n const handler = functionModule[handlerName] || functionModule.onRequest;\n\n if (!handler || typeof handler !== 'function') {\n return new Response(\n JSON.stringify({ error: `No handler found for ${method} request` }),\n { status: 405, headers: { 'Content-Type': 'application/json' } }\n );\n }\n\n // Load environment variables\n const env = await loadProjectEnv();\n\n // Create mock Cloudflare context\n const context: MockEventContext = {\n request: req,\n env,\n params: {}, // Could parse URL params if needed\n waitUntil: () => {}, // No-op in dev\n passThroughOnException: () => {}, // No-op in dev\n };\n\n // Call the handler\n const response = await handler(context);\n\n // Add CORS headers for development\n const headers = new Headers(response.headers);\n headers.set('Access-Control-Allow-Origin', '*');\n headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');\n headers.set('Access-Control-Allow-Headers', 'Content-Type');\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n } catch (error) {\n console.error(`Error executing function ${functionPath}:`, error);\n return new Response(\n JSON.stringify({\n error: 'Function execution error',\n message: error instanceof Error ? error.message : 'Unknown error',\n }),\n { status: 500, headers: { 'Content-Type': 'application/json' } }\n );\n }\n}\n\n/**\n * Handle OPTIONS preflight for CORS\n */\nexport function handleFunctionsPreflight(req: Request, url: URL): Response | undefined {\n if (req.method !== 'OPTIONS' || !url.pathname.startsWith('/api/')) {\n return undefined;\n }\n\n return new Response(null, {\n status: 204,\n headers: {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n 'Access-Control-Max-Age': '86400',\n },\n });\n}\n", "/**\n * Route Registration\n * Centralized route handling with middleware\n */\n\nimport type { PageService } from '../services/pageService';\nimport type { ComponentService } from '../services/componentService';\nimport type { CMSService } from '../services/cmsService';\nimport type { CMSProvider } from '../../shared/interfaces/contentProvider';\nimport type { WebSocketManager } from '../websocketManager';\nimport type { DraftPageStore } from '../draftPageStore';\nimport { HMR_ROUTE } from '../../shared/constants';\nimport { handleCorsPreflight } from '../middleware/cors';\nimport { handleRouteError } from '../middleware/errorHandler';\nimport { logRequest, logResponseTime } from '../middleware/logger';\nimport { handleApiRoutes, type CMSRouteContext } from './api/index';\nimport { handlePageRoute } from './pages';\nimport { handleStaticRoute } from './static';\nimport { getScript } from '../scriptCache';\nimport { loadI18nConfig } from '../jsonLoader';\nimport { parseLocaleFromPath } from '../../shared/i18n';\n\nexport interface RouteContext {\n pageService: PageService;\n componentService: ComponentService;\n cmsService?: CMSService;\n cmsProvider?: CMSProvider;\n /**\n * Inject live reload script for on-demand SSR preview mode.\n * When true, pages include a WebSocket client that reloads on HMR messages.\n */\n injectLiveReload?: boolean;\n /** Whether this is the visual editor (studio). Affects library filtering. */\n isEditor?: boolean;\n /** Actual bound server port, used to connect live reload WS directly to SSR server */\n serverPort?: number;\n /**\n * WebSocket manager for this server. Used by the /__draft-page endpoint\n * to nudge live-reload clients (external browser tabs) to refetch after a\n * draft pageData has been stored on the server.\n */\n wsManager?: WebSocketManager;\n /**\n * In-memory draft page store. When the page route finds a draft for the\n * requested path it renders from that instead of disk, so external\n * browser tabs see the editor's in-flight edits without anything being\n * persisted.\n */\n draftPageStore?: DraftPageStore;\n}\n\n/**\n * Handle all routes with middleware\n */\nexport async function handleRoutes(\n req: Request,\n url: URL,\n server: any,\n context: RouteContext\n): Promise<Response | undefined> {\n const startTime = Date.now();\n const { pageService, componentService, cmsService, cmsProvider } = context;\n\n // Log request\n logRequest(req);\n\n // Handle CORS preflight requests\n const corsResponse = handleCorsPreflight(req);\n if (corsResponse) {\n logResponseTime(startTime, req);\n return corsResponse;\n }\n\n try {\n // WebSocket upgrade is now handled by the HTTP server abstraction\n // (in createServer's fetch handler before calling handleRoutes)\n if (url.pathname === HMR_ROUTE) {\n logResponseTime(startTime, req);\n return undefined;\n }\n\n // Ephemeral draft-page channel for external browser tabs.\n // POST /__draft-page body: { path, content } \u2014 store draft + nudge clients\n // POST /__draft-page/clear body: { path } \u2014 drop draft (e.g. after save)\n // GET /__draft-page/clients \u2014 probe connected-client count\n //\n // The studio fire-and-forgets POSTs here while the user edits. We bail\n // before parsing the body when no external tab is listening, so this\n // path costs ~zero in the common case.\n if (url.pathname === '/__draft-page' && req.method === 'POST') {\n const corsHeaders = { 'Access-Control-Allow-Origin': '*' };\n const store = context.draftPageStore;\n const ws = context.wsManager;\n if (!store || !ws || ws.getClientCount() === 0) {\n logResponseTime(startTime, req);\n return new Response(null, { status: 204, headers: corsHeaders });\n }\n try {\n const body = await req.json() as { path?: string; content?: string };\n if (typeof body.path === 'string' && typeof body.content === 'string' && body.path.startsWith('/')) {\n store.set(body.path, body.content);\n // Nudge connected tabs to refetch. The existing live-reload\n // script does a smart-diff hotReload off this message and will\n // pull the draft-rendered HTML (classes + utility CSS together).\n ws.broadcastUpdate(body.path);\n }\n } catch {\n // Drop silently \u2014 studio retries on next commit.\n }\n logResponseTime(startTime, req);\n return new Response(null, { status: 204, headers: corsHeaders });\n }\n\n if (url.pathname === '/__draft-page/clear' && req.method === 'POST') {\n const corsHeaders = { 'Access-Control-Allow-Origin': '*' };\n const store = context.draftPageStore;\n if (store) {\n try {\n const body = await req.json() as { path?: string };\n if (typeof body.path === 'string') {\n store.clear(body.path);\n // External tabs viewing this path should refetch the disk\n // version now that the draft is gone.\n context.wsManager?.broadcastUpdate(body.path);\n }\n } catch { /* ignore */ }\n }\n logResponseTime(startTime, req);\n return new Response(null, { status: 204, headers: corsHeaders });\n }\n\n if (url.pathname === '/__draft-page/clients' && req.method === 'GET') {\n const count = context.wsManager?.getClientCount() ?? 0;\n logResponseTime(startTime, req);\n return new Response(JSON.stringify({ count }), {\n status: 200,\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-store',\n 'Access-Control-Allow-Origin': '*',\n },\n });\n }\n\n // Build CMS context if CMS service and provider are available\n const cmsContext: CMSRouteContext | undefined =\n cmsService && cmsProvider\n ? { cmsService, cmsProvider }\n : undefined;\n\n // API Routes\n const apiResponse = await handleApiRoutes(\n req,\n url,\n pageService,\n componentService,\n cmsContext\n );\n if (apiResponse) {\n logResponseTime(startTime, req);\n return apiResponse;\n }\n\n // CMS data routes - serve collection items as JSON for client-side filtering\n // Pattern: /data/{collection}/index.json\n if (url.pathname.startsWith('/data/') && url.pathname.endsWith('/index.json') && cmsService) {\n const match = url.pathname.match(/^\\/data\\/([^/]+)\\/index\\.json$/);\n if (match) {\n const collectionId = match[1];\n try {\n // Resolve locale to filter draft items\n const i18nConfig = await loadI18nConfig();\n let refererPath = '/';\n try {\n const referer = req.headers.get('referer');\n if (referer) refererPath = new URL(referer).pathname;\n } catch { /* ignore malformed referer */ }\n const { locale } = parseLocaleFromPath(refererPath, i18nConfig);\n const items = await cmsService.queryItems({ collection: collectionId, excludeDraftLocale: locale });\n logResponseTime(startTime, req);\n return new Response(JSON.stringify(items), {\n headers: {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-cache',\n },\n });\n } catch {\n logResponseTime(startTime, req);\n return new Response('[]', {\n headers: { 'Content-Type': 'application/json' },\n });\n }\n }\n }\n\n // Serve cached scripts (SSR preview mode - same pattern as static build)\n if (url.pathname.startsWith('/_scripts/') && url.pathname.endsWith('.js')) {\n const hash = url.pathname.slice(10, -3); // Extract hash from /_scripts/{hash}.js\n const script = getScript(hash);\n if (script) {\n logResponseTime(startTime, req);\n return new Response(script, {\n headers: {\n 'Content-Type': 'application/javascript',\n 'Cache-Control': 'no-cache',\n },\n });\n }\n }\n\n // Static asset directories - serve before page routes\n if (url.pathname.startsWith('/images/') || url.pathname.startsWith('/videos/') || url.pathname.startsWith('/assets/') || url.pathname.startsWith('/public/') || url.pathname.startsWith('/icons/')) {\n const response = await handleStaticRoute(url, req);\n if (response) {\n logResponseTime(startTime, req);\n return response;\n }\n }\n\n // Unknown /api/* \u2014 return a real 404 instead of falling through to the\n // SPA shell. Without this guard, an /api/foo that no handler claimed gets\n // rendered as a 200 HTML page (the catch-all below), which makes broken\n // route wiring look like a working endpoint to API clients.\n if (url.pathname.startsWith('/api/')) {\n logResponseTime(startTime, req);\n return new Response(\n JSON.stringify({ error: 'Not Found', path: url.pathname }),\n { status: 404, headers: { 'Content-Type': 'application/json' } }\n );\n }\n\n // Page routes (SSR)\n if (url.pathname === '/' || (url.pathname.startsWith('/') && !url.pathname.includes('.'))) {\n const response = await handlePageRoute(url, context, req);\n logResponseTime(startTime, req);\n return response;\n }\n\n // Static files\n const response = await handleStaticRoute(url, req);\n logResponseTime(startTime, req);\n return response;\n } catch (error) {\n logResponseTime(startTime, req);\n return handleRouteError(\n () => Promise.reject(error),\n `Error handling route: ${url.pathname}`\n );\n }\n}\n\n", "/**\n * API Route Registration\n * Centralized API route handling with error handling\n *\n * Core routes are read-only operations. Write operations are in @meno/studio.\n */\n\nimport type { PageService } from '../../services/pageService';\nimport type { ComponentService } from '../../services/componentService';\nimport type { CMSService } from '../../services/cmsService';\nimport type { CMSProvider } from '../../../shared/interfaces/contentProvider';\nimport { handleRouteError } from '../../middleware/errorHandler';\nimport { handleCoreApiRoutes, type CoreRouteContext } from './core-routes';\n\n/** Context for CMS API routes */\nexport interface CMSRouteContext {\n cmsService: CMSService;\n cmsProvider: CMSProvider;\n}\n\n// Re-export route contexts for external use\nexport type { CoreRouteContext };\n\n/**\n * Handle core API routes (read-only operations)\n * Write operations are handled by @meno/studio via additionalRoutes\n */\nexport async function handleApiRoutes(\n req: Request,\n url: URL,\n pageService: PageService,\n componentService: ComponentService,\n cmsContext?: CMSRouteContext\n): Promise<Response | undefined> {\n try {\n const coreContext: CoreRouteContext = {\n pageService,\n componentService,\n cmsService: cmsContext?.cmsService,\n };\n\n return await handleCoreApiRoutes(req, url, coreContext);\n } catch (error) {\n // This catch is a fallback - individual routes should handle their own errors\n return handleRouteError(\n () => Promise.reject(error),\n 'API route error'\n );\n }\n}\n\n/**\n * Handle only core API routes (for meno-core without editor)\n */\nexport async function handleCoreOnlyApiRoutes(\n req: Request,\n url: URL,\n pageService: PageService,\n componentService: ComponentService,\n cmsService?: CMSService\n): Promise<Response | undefined> {\n const context: CoreRouteContext = {\n pageService,\n componentService,\n cmsService,\n };\n\n return handleCoreApiRoutes(req, url, context);\n}\n", "/**\n * Page Route Handler\n * Handles page route requests with SSR, i18n, and CMS support\n */\n\nimport { randomBytes } from 'crypto';\nimport type { RouteContext } from './index';\nimport { generateSSRHTML, type SSRHTMLResult } from '../ssrRenderer';\nimport { getStaticFilePath } from '../../shared/pathUtils';\nimport { parseJSON, loadI18nConfig } from '../jsonLoader';\nimport { packagePaths, projectPaths } from '../projectContext';\nimport { parseLocaleFromPath } from '../../shared/i18n';\nimport { buildSlugIndex, resolveSlugToPageId } from '../../shared/slugTranslator';\nimport type { CMSItem } from '../../shared/types';\nimport { generateErrorPage } from '../ssr/errorOverlay';\nimport { cacheScript, hashContent } from '../scriptCache';\nimport { readTextFile, fileExists, serveFile } from '../runtime';\n\n/** HTTP header sent by the studio's /__static__/ proxy to flag editor-preview requests. */\nconst EDITOR_HEADER = 'x-meno-editor';\n\n/**\n * Response header carrying the per-request CSP nonce. The Electron main\n * process (electron-app/main/window.js) reads this in onHeadersReceived and\n * splices `'nonce-${nonce}'` into the script-src directive while dropping\n * `'unsafe-inline'`, so the inline scripts the SSR pipeline emits (config,\n * CMS context, live reload, scroll sync, component script) keep executing\n * without re-enabling unrestricted inline JavaScript.\n */\nconst CSP_NONCE_HEADER = 'x-meno-csp-nonce';\n\n/**\n * Generate a fresh per-request CSP nonce.\n * 16 bytes of randomness \u2192 24 base64 chars, well above CSP3's 128-bit floor.\n */\nfunction generateCspNonce(): string {\n return randomBytes(16).toString('base64');\n}\n\n/**\n * Handle page route requests\n */\nexport async function handlePageRoute(\n url: URL,\n context: RouteContext,\n req?: Request\n): Promise<Response | undefined> {\n const { pageService, componentService, cmsService, injectLiveReload, isEditor, serverPort } = context;\n const pagePath = url.pathname;\n // Editor selection attributes (data-element-path, data-cms-context, ...).\n // Emitted whenever live-reload is on (dev SSR preview) so the inline\n // smart-diff script can identify elements when external browser tabs\n // refetch on draft pushes \u2014 without these attrs the diff only syncs\n // text nodes and className changes get silently dropped. Also still\n // emitted when the studio's /__static__/ proxy sets `x-meno-editor: 1`\n // (back-compat). Static/production builds keep clean output because\n // injectLiveReload is false there.\n const injectEditorAttrs = injectLiveReload === true || req?.headers.get(EDITOR_HEADER) === '1';\n\n // Fresh CSP nonce per request: stamped onto every inline <script> emitted\n // by the SSR pipeline AND sent back to the Electron main process via the\n // x-meno-csp-nonce header so it can splice `'nonce-XXX'` into the BrowserWindow\n // CSP in place of `'unsafe-inline'`. See electron-app/main/window.js.\n const cspNonce = generateCspNonce();\n\n // Load i18n config for locale extraction\n const i18nConfig = await loadI18nConfig();\n\n // Parse locale from URL path (e.g., /pl/o-nas -> locale: 'pl', path: '/o-nas')\n const { locale, pathWithoutLocale } = parseLocaleFromPath(pagePath, i18nConfig);\n\n // Build slug index for translation lookup\n const slugMappings = pageService.getSlugMappings();\n const slugIndex = buildSlugIndex(slugMappings);\n\n // 1. Try CMS route match first (pass locale for i18n slug matching)\n if (cmsService) {\n const cmsMatch = await cmsService.matchRoute(pathWithoutLocale, locale);\n\n if (cmsMatch) {\n // Editor-only draft preview: when the studio editor requests a CMS page\n // with `?previewDraft=1` and a draft exists for that item, swap the\n // matched item for the draft. SSR continues to render normally; the\n // live site (no editor header, no query param) is unaffected.\n if (injectEditorAttrs && url.searchParams.get('previewDraft') === '1' && cmsMatch.item._filename) {\n const draft = await cmsService.getDraft(cmsMatch.collection, cmsMatch.item._filename);\n if (draft) {\n cmsMatch.item = draft;\n }\n }\n // Load template page content by file path\n const templatePageContent = await loadPageByFilePath(cmsMatch.pagePath);\n\n if (templatePageContent) {\n // Convert absolute template path to URL path for client-side hydration\n // e.g., /Users/.../templates/posts.json -> /templates/posts\n const templatesDir = projectPaths.templates();\n const cmsTemplatePath = '/templates' + cmsMatch.pagePath\n .replace(templatesDir, '') // Remove templates directory prefix\n .replace(/\\\\/g, '/') // Normalize Windows backslashes\n .replace(/\\.json$/, ''); // Remove .json extension\n\n try {\n // Parse page JSON\n const pageData = parseJSON(templatePageContent);\n\n // Convert global components Map to Record for SSR\n const globalComponentsRecord = componentService.getAllComponents();\n\n // Generate SSR HTML with CMS context\n const baseUrl = `${url.protocol}//${url.host}`;\n const typedPageData = pageData as import('../../shared/types').JSONPage;\n\n // SSR preview mode: use external JS file (same pattern as static build)\n if (injectLiveReload) {\n const result = await generateSSRHTML({\n pageData: typedPageData,\n globalComponents: globalComponentsRecord,\n pagePath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsContext: { cms: cmsMatch.item },\n cmsService,\n cmsTemplatePath,\n pageLibraries: typedPageData.meta?.libraries,\n pageCustomCode: typedPageData.meta?.customCode,\n injectLiveReload,\n injectEditorAttrs,\n isEditor,\n serverPort,\n returnSeparateJS: true,\n cspNonce,\n }) as SSRHTMLResult;\n\n let finalHtml = result.html;\n if (result.javascript) {\n const hash = hashContent(result.javascript);\n cacheScript(hash, result.javascript);\n finalHtml = finalHtml.replace('</body>', ` <script src=\"/_scripts/${hash}.js\" defer></script>\\n</body>`);\n }\n\n return new Response(finalHtml, {\n headers: {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store, max-age=0',\n 'Pragma': 'no-cache',\n 'Expires': '0',\n [CSP_NONCE_HEADER]: cspNonce,\n },\n });\n }\n\n // Dev mode: inline JS\n const ssrHTML = await generateSSRHTML({\n pageData: typedPageData,\n globalComponents: globalComponentsRecord,\n pagePath,\n baseUrl,\n useBuiltBundle: false,\n locale,\n slugMappings,\n cmsContext: { cms: cmsMatch.item },\n cmsService,\n cmsTemplatePath,\n pageLibraries: typedPageData.meta?.libraries,\n pageCustomCode: typedPageData.meta?.customCode,\n injectEditorAttrs,\n isEditor,\n cspNonce,\n });\n\n return new Response(ssrHTML, {\n headers: {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store, max-age=0',\n 'Pragma': 'no-cache',\n 'Expires': '0',\n [CSP_NONCE_HEADER]: cspNonce,\n },\n });\n } catch (error) {\n console.error('Error rendering CMS page:', error);\n // Show error overlay in preview instead of silent fallback\n return new Response(generateErrorPage(error, `Error rendering template: ${cmsTemplatePath}`, cspNonce), {\n headers: {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store',\n [CSP_NONCE_HEADER]: cspNonce,\n },\n });\n }\n }\n }\n }\n\n // 2. Fall back to static page routing\n\n // Extract slug from path (remove leading slash)\n const slug = pathWithoutLocale === '/' ? '' : pathWithoutLocale.substring(1);\n\n // Try to resolve translated slug to pageId (e.g., \"o-nas\" + \"pl\" -> \"about\")\n const pageId = resolveSlugToPageId(slug, locale, slugIndex);\n\n // Determine lookup path: use resolved pageId or fall back to original path\n let lookupPath: string;\n if (pageId) {\n lookupPath = pageId === 'index' ? '/' : `/${pageId}`;\n } else {\n // No translation found, use original path without locale\n lookupPath = pathWithoutLocale;\n }\n\n // Skip static files in development mode - always use fresh SSR from JSON files\n const isDevelopment = true; // Always true when running dev server\n\n if (!isDevelopment) {\n // Production mode: Check for pre-built static file first\n const staticFilePath = getStaticFilePath(pagePath);\n\n if (await fileExists(staticFilePath)) {\n return serveFile(staticFilePath, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'public, max-age=31536000', // 1 year cache for static files\n });\n }\n }\n\n // Development mode: Always use fresh SSR from JSON files (no caching).\n // Studio-pushed draft (if any) wins over the on-disk version so external\n // browser tabs reflect unsaved edits.\n const pageContent = context.draftPageStore?.get(lookupPath) ?? pageService.getPage(lookupPath);\n\n if (pageContent) {\n try {\n // Parse page JSON\n const pageData = parseJSON(pageContent) as import('../../shared/types').JSONPage;\n\n // Convert global components Map to Record for SSR\n const globalComponentsRecord = componentService.getAllComponents();\n\n // Generate SSR HTML with pre-rendered content and locale\n const baseUrl = `${url.protocol}//${url.host}`;\n\n // SSR preview mode: use external JS file (same pattern as static build)\n if (injectLiveReload) {\n const result = await generateSSRHTML({\n pageData,\n globalComponents: globalComponentsRecord,\n pagePath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsService,\n pageLibraries: pageData.meta?.libraries,\n pageCustomCode: pageData.meta?.customCode,\n injectLiveReload,\n injectEditorAttrs,\n isEditor,\n serverPort,\n returnSeparateJS: true,\n cspNonce,\n }) as SSRHTMLResult;\n\n let finalHtml = result.html;\n if (result.javascript) {\n const hash = hashContent(result.javascript);\n cacheScript(hash, result.javascript);\n finalHtml = finalHtml.replace('</body>', ` <script src=\"/_scripts/${hash}.js\" defer></script>\\n</body>`);\n }\n\n return new Response(finalHtml, {\n headers: {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store, max-age=0',\n 'Pragma': 'no-cache',\n 'Expires': '0',\n [CSP_NONCE_HEADER]: cspNonce,\n },\n });\n }\n\n // Dev mode: inline JS\n const ssrHTML = await generateSSRHTML({\n pageData,\n globalComponents: globalComponentsRecord,\n pagePath,\n baseUrl,\n useBuiltBundle: false,\n locale,\n slugMappings,\n cmsService,\n pageLibraries: pageData.meta?.libraries,\n pageCustomCode: pageData.meta?.customCode,\n injectEditorAttrs,\n isEditor,\n cspNonce,\n });\n\n return new Response(ssrHTML, {\n headers: {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store, max-age=0',\n 'Pragma': 'no-cache',\n 'Expires': '0',\n [CSP_NONCE_HEADER]: cspNonce,\n },\n });\n } catch (error) {\n console.error('Error rendering page:', error);\n // Show error overlay in preview instead of silent fallback\n return new Response(generateErrorPage(error, `Error rendering page: ${lookupPath}`, cspNonce), {\n headers: {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store',\n [CSP_NONCE_HEADER]: cspNonce,\n },\n });\n }\n } else {\n // Page not found - still return HTML shell for client-side 404 handling\n return serveFile(packagePaths.indexHtml());\n }\n}\n\n/**\n * Load page content by file path (for CMS template pages)\n */\nasync function loadPageByFilePath(filePath: string): Promise<string | null> {\n try {\n if (await fileExists(filePath)) {\n return await readTextFile(filePath);\n }\n return null;\n } catch {\n return null;\n }\n}\n", "/**\n * Shared path utility functions\n * Used by both build system and server router\n */\n\nimport type { Path } from './paths';\nimport { \n stringToPath, \n pathToLegacyString, \n getParentPath as getParentPathArray,\n buildParentPaths as buildParentPathsArray,\n pathsEqual,\n isRootPath as isRootPathArray,\n ROOT_STRING,\n domPathStringToTreePath,\n treePathToDomPathString,\n isAncestorPath\n} from './paths';\n\n/**\n * Convert a page path to static HTML file path\n * \n * @example\n * getStaticFilePath(\"/\") -> \"./dist/index.html\"\n * getStaticFilePath(\"/about\") -> \"./dist/about.html\"\n * getStaticFilePath(\"/blog/post-1\") -> \"./dist/blog-post-1.html\"\n */\nexport function getStaticFilePath(pagePath: string, distDir: string = \"./dist\"): string {\n if (pagePath === \"/\") {\n return `${distDir}/index.html`;\n }\n \n // Convert /about -> about.html\n // Convert /blog/post-1 -> blog-post-1.html (flat structure)\n const pathParts = pagePath.substring(1).split(\"/\");\n const fileName = pathParts.join(\"-\") + \".html\";\n \n return `${distDir}/${fileName}`;\n}\n\n/**\n * Convert a page path to a page name (for file system)\n * \n * @example\n * pathToPageName(\"/\") -> \"index\"\n * pathToPageName(\"/about\") -> \"about\"\n */\nexport function pathToPageName(pagePath: string): string {\n return pagePath === \"/\" ? \"index\" : pagePath.substring(1);\n}\n\n/**\n * Convert a page name to a page path\n * \n * @example\n * pageNameToPath(\"index\") -> \"/\"\n * pageNameToPath(\"about\") -> \"/about\"\n */\nexport function pageNameToPath(pageName: string): string {\n return pageName === \"index\" ? \"/\" : `/${pageName}`;\n}\n\n/**\n * Convert tree path to DOM path\n * The tree adds a synthetic \"root\" container, so \"root_0\" in the tree corresponds to \"root\" in the DOM\n * Also accepts array paths: [0] -> \"root\", [0,0] -> \"root_children_0\"\n * \n * Uses array operations internally for conversion.\n * \n * @example\n * treePathToDomPath(\"root_0\") -> \"root\"\n * treePathToDomPath(\"root_0_children_0\") -> \"root_children_0\"\n * treePathToDomPath([0]) -> \"root\"\n * treePathToDomPath([0,0]) -> \"root_children_0\"\n */\nexport function treePathToDomPath(treePath: Path | string): string {\n // Convert to array if needed, then use array-based conversion\n const pathArray = typeof treePath === 'string' ? stringToPath(treePath) : treePath;\n return treePathToDomPathString(pathArray);\n}\n\n/**\n * Convert DOM path back to tree path\n * The tree adds a synthetic \"root\" container, so \"root\" in the DOM corresponds to \"root_0\" in the tree\n * Returns legacy string format for backward compatibility\n * \n * Uses array operations internally for conversion.\n * \n * @example\n * domPathToTreePath(\"root\") -> \"root_0\"\n * domPathToTreePath(\"root_children_0\") -> \"root_0_children_0\"\n */\nexport function domPathToTreePath(domPath: string): string {\n // Convert DOM path to array, then to legacy tree path string\n const pathArray = domPathStringToTreePath(domPath);\n return pathToLegacyString(pathArray);\n}\n\n/**\n * Build parent paths for expanding tree nodes\n * Returns all parent path segments for a given tree path\n * Also accepts array paths\n * \n * @example\n * buildParentPaths(\"root_0_children_0_children_1\") -> [\"root_0\", \"root_0_children_0\"]\n * buildParentPaths([0,0,1]) -> [\"root_0\", \"root_0_children_0\"]\n */\nexport function buildParentPaths(treePath: Path | string): string[] {\n const pathArray = typeof treePath === 'string' ? stringToPath(treePath) : treePath;\n \n if (isRootPathArray(pathArray)) {\n return [];\n }\n \n const parentArrays = buildParentPathsArray(pathArray);\n return parentArrays.map(pathToLegacyString);\n}\n\n/**\n * Calculate parent path from a child path\n * Also accepts array paths\n * Example: root_0_children_0 -> root_0\n * Example: root_0_children_0_children_1 -> root_0_children_0\n * Example: [0,0] -> \"root_0\"\n * Example: [0,0,1] -> \"root_0_children_0\"\n */\nexport function getParentPathFromChildPath(childPath: Path | string): string {\n const pathArray = typeof childPath === 'string' ? stringToPath(childPath) : childPath;\n const parentArray = getParentPathArray(pathArray);\n return pathToLegacyString(parentArray);\n}\n\n/**\n * Convert component instance path to component structure path\n * When editing a component, elements clicked inside the component instance on the page\n * need to be converted to their paths within the component structure.\n * \n * Uses array operations internally for path manipulation.\n * \n * @example\n * componentInstancePath: \"root_children_0\" (component instance on page)\n * instancePath: \"root_children_0_children_1\" (element inside instance)\n * Returns: \"root_children_1\" (component structure path)\n * \n * @param instancePath - Path of element within component instance on page (DOM path string)\n * @param componentInstancePath - Path of the component instance root on the page (DOM path string)\n * @returns Component structure path (always starts with \"root\")\n */\nexport function componentInstancePathToStructurePath(\n instancePath: string,\n componentInstancePath: string\n): string {\n // Convert DOM paths to arrays for manipulation\n const instancePathArray = domPathStringToTreePath(instancePath);\n const componentInstancePathArray = domPathStringToTreePath(componentInstancePath);\n \n // Check if instancePath is inside componentInstancePath using array operations\n if (!isAncestorPath(componentInstancePathArray, instancePathArray)) {\n // Not inside component instance - return as-is (shouldn't happen, but handle gracefully)\n return instancePath;\n }\n \n // Extract relative path using array operations\n // componentInstancePathArray: [0, 0] -> instancePathArray: [0, 0, 1]\n // relative: [1] -> convert to DOM path: \"root_children_1\"\n const relativePathArray = instancePathArray.slice(componentInstancePathArray.length);\n \n // Convert relative path array back to DOM path string\n // If relative is empty, return root\n if (relativePathArray.length === 0) {\n return ROOT_STRING;\n }\n \n // Build component structure path: root + relative path\n return treePathToDomPathString(relativePathArray);\n}\n\n/**\n * Convert component structure path to component instance path\n * When selecting an element in the component structure tree, convert it to\n * the path within the component instance on the page.\n * \n * Uses array operations internally for path manipulation.\n * \n * @example\n * componentInstancePath: \"root_children_0\" (component instance on page)\n * structurePath: \"root_children_1\" (element in component structure)\n * Returns: \"root_children_0_children_1\" (path within instance on page)\n * \n * @param structurePath - Path within component structure (starts with \"root\", DOM path string)\n * @param componentInstancePath - Path of the component instance root on the page (DOM path string)\n * @returns Path within component instance on page (DOM path string)\n */\nexport function componentStructurePathToInstancePath(\n structurePath: string,\n componentInstancePath: string\n): string {\n // Convert DOM paths to arrays for manipulation\n const structurePathArray = domPathStringToTreePath(structurePath);\n const componentInstancePathArray = domPathStringToTreePath(componentInstancePath);\n \n // Extract relative path from structure path (skip root [0])\n // structurePathArray: [0, 1] -> relative: [1]\n const relativePathArray = structurePathArray.slice(1);\n \n // Combine component instance path with relative path using array operations\n // componentInstancePathArray: [0, 0] + relativePathArray: [1] -> [0, 0, 1]\n const instancePathArray: Path = [...componentInstancePathArray, ...relativePathArray];\n \n // Convert back to DOM path string\n return treePathToDomPathString(instancePathArray);\n}\n\n/**\n * Convert path for component editing context\n * When editing a component, converts component instance paths to component structure paths\n * \n * Uses array operations internally for path manipulation.\n * \n * @param path - Path array from canvas\n * @param isEditingComponent - Whether we're editing a component\n * @param componentInstancePath - Path of component instance on page (if editing component, Path array)\n * @returns Path array for selection/hover (converted for component context if needed)\n */\nexport function convertPathForComponentContext(\n path: Path,\n isEditingComponent: boolean,\n componentInstancePath: Path | null\n): Path {\n if (isEditingComponent && componentInstancePath) {\n // Check if path is inside componentInstancePath using array operations\n if (isAncestorPath(componentInstancePath, path)) {\n // Extract relative path: componentInstancePath: [0, 0] -> path: [0, 0, 1]\n // relative: [1] -> component structure path: [0, 1]\n const relativePath = path.slice(componentInstancePath.length);\n \n // Build component structure path: [0] + relative path\n return [0, ...relativePath];\n }\n }\n \n // Regular page editing - return path as-is\n return path;\n}\n", "/**\n * Error Overlay Generator for Preview\n * Generates an HTML page with a styled error overlay when SSR fails\n * Also sends error details to parent editor via postMessage\n */\n\nimport { toFriendlyError } from '../../shared/friendlyError';\n\ninterface ErrorInfo {\n message: string;\n stack?: string;\n}\n\n/**\n * Extract useful error information from various error types\n */\nfunction extractErrorInfo(error: unknown): ErrorInfo {\n if (error instanceof Error) {\n return {\n message: error.message,\n stack: error.stack,\n };\n }\n if (typeof error === 'string') {\n return { message: error };\n }\n return { message: String(error) };\n}\n\n/**\n * Escape HTML to prevent XSS in error messages\n */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/**\n * Safely encode data for embedding in a script tag\n * Escapes </script> sequences and other problematic characters\n */\nfunction safeJsonForScript(data: unknown): string {\n return JSON.stringify(data)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026');\n}\n\n/**\n * Generate HTML page with error overlay.\n *\n * @param error Error to display\n * @param context Optional context label shown above the error message\n * @param cspNonce Per-request CSP nonce \u2014 when set, stamped on the inline\n * `<script>` so it executes under a strict (nonce-based)\n * script-src policy without `'unsafe-inline'`. Pass through\n * from the route handler that produces this response.\n */\nexport function generateErrorPage(error: unknown, context?: string, cspNonce?: string): string {\n const errorInfo = extractErrorInfo(error);\n const friendly = toFriendlyError(errorInfo.message);\n const errorMessage = escapeHtml(errorInfo.message);\n const errorStack = errorInfo.stack ? escapeHtml(errorInfo.stack) : '';\n // Escape first (XSS-safe), then turn `backtick` spans into <code> for display.\n const renderInline = (s: string) =>\n escapeHtml(s).replace(/`([^`]+)`/g, '<code>$1</code>');\n const friendlyTitle = escapeHtml(friendly.title);\n const friendlyMessage = renderInline(friendly.friendlyMessage);\n const friendlyHint = friendly.hint ? renderInline(friendly.hint) : '';\n const nonceAttr = cspNonce ? ` nonce=\"${cspNonce}\"` : '';\n\n // Safely encode error data for script. Includes friendly fields so the parent\n // editor can show plain-language text without re-mapping, plus the raw message\n // and stack so \"Copy\" still yields the exact original for debugging.\n const errorDataJson = safeJsonForScript({\n type: 'PREVIEW_ERROR',\n error: {\n message: friendly.friendlyMessage,\n title: friendly.title,\n hint: friendly.hint,\n raw: errorInfo.message,\n stack: errorInfo.stack,\n context,\n },\n });\n\n // Full error text for copying\n const fullErrorText = safeJsonForScript(\n errorInfo.message + (errorInfo.stack ? '\\n\\n' + errorInfo.stack : '')\n );\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Preview Error</title>\n <style${nonceAttr}>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #1a1a1a;\n color: #fff;\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n }\n .error-container {\n max-width: 800px;\n width: 100%;\n background: #2d2d2d;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n }\n .error-header {\n background: linear-gradient(135deg, #ff4444 0%, #cc0000 100%);\n padding: 20px 24px;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .error-icon { font-size: 24px; }\n .error-title { font-size: 18px; font-weight: 600; }\n .error-body { padding: 24px; }\n .error-context {\n font-size: 12px;\n color: #888;\n margin-bottom: 16px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n .error-friendly {\n font-size: 15px;\n line-height: 1.6;\n color: #e8e8e8;\n margin-bottom: 16px;\n }\n .error-friendly code {\n font-family: 'SF Mono', Menlo, Monaco, 'Courier New', monospace;\n font-size: 13px;\n background: #1a1a1a;\n border: 1px solid #444;\n border-radius: 4px;\n padding: 1px 5px;\n color: #ffb86b;\n }\n .error-message {\n background: #1a1a1a;\n border: 1px solid #444;\n border-radius: 8px;\n padding: 16px;\n font-family: 'SF Mono', Menlo, Monaco, 'Courier New', monospace;\n font-size: 14px;\n line-height: 1.6;\n color: #ff6b6b;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n }\n .error-stack { margin-top: 16px; }\n .stack-toggle {\n background: none;\n border: 1px solid #444;\n color: #888;\n padding: 8px 16px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 8px;\n transition: all 0.15s;\n }\n .stack-toggle:hover { background: #333; color: #fff; border-color: #555; }\n .stack-toggle svg { width: 14px; height: 14px; transition: transform 0.2s; }\n .stack-toggle.expanded svg { transform: rotate(90deg); }\n .stack-content {\n display: none;\n margin-top: 12px;\n background: #1a1a1a;\n border: 1px solid #444;\n border-radius: 8px;\n padding: 16px;\n font-family: 'SF Mono', Menlo, Monaco, 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.8;\n color: #999;\n overflow-x: auto;\n white-space: pre;\n }\n .stack-content.visible { display: block; }\n .error-footer {\n padding: 16px 24px;\n background: #252525;\n border-top: 1px solid #333;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 12px;\n }\n .error-hint { font-size: 13px; color: #888; }\n .copy-btn {\n background: #333;\n border: 1px solid #444;\n color: #fff;\n padding: 8px 16px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 13px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.15s;\n }\n .copy-btn:hover { background: #444; border-color: #555; }\n .copy-btn svg { width: 14px; height: 14px; }\n </style>\n</head>\n<body>\n <div class=\"error-container\">\n <div class=\"error-header\">\n <span class=\"error-icon\">\u26A0\uFE0F</span>\n <span class=\"error-title\">${friendlyTitle}</span>\n </div>\n <div class=\"error-body\">\n ${context ? `<div class=\"error-context\">${escapeHtml(context)}</div>` : ''}\n <p class=\"error-friendly\">${friendlyMessage}</p>\n <div class=\"error-stack\">\n <button class=\"stack-toggle\" id=\"stackToggle\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"9 18 15 12 9 6\"></polyline>\n </svg>\n <span>Show technical details</span>\n </button>\n <div class=\"stack-content\" id=\"stackContent\"><div class=\"error-message\">${errorMessage}</div>${errorStack ? `\\n${errorStack}` : ''}</div>\n </div>\n </div>\n <div class=\"error-footer\">\n <span class=\"error-hint\">${friendlyHint}</span>\n <button class=\"copy-btn\" id=\"copyBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect>\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path>\n </svg>\n <span>Copy Error</span>\n </button>\n </div>\n </div>\n <script${nonceAttr}>\n (function() {\n // Send error to parent editor\n if (window.parent && window.parent !== window) {\n try {\n window.parent.postMessage(${errorDataJson}, '*');\n } catch (e) {\n console.error('Failed to send error to parent:', e);\n }\n }\n\n // Stack trace toggle\n var stackToggle = document.getElementById('stackToggle');\n var stackContent = document.getElementById('stackContent');\n if (stackToggle && stackContent) {\n stackToggle.addEventListener('click', function() {\n var isVisible = stackContent.classList.toggle('visible');\n stackToggle.classList.toggle('expanded', isVisible);\n stackToggle.querySelector('span').textContent = isVisible ? 'Hide technical details' : 'Show technical details';\n });\n }\n\n // Copy button\n var copyBtn = document.getElementById('copyBtn');\n if (copyBtn) {\n copyBtn.addEventListener('click', function() {\n var errorText = ${fullErrorText};\n navigator.clipboard.writeText(errorText).then(function() {\n var span = copyBtn.querySelector('span');\n var original = span.textContent;\n span.textContent = 'Copied!';\n setTimeout(function() { span.textContent = original; }, 2000);\n }).catch(function(err) {\n console.error('Failed to copy:', err);\n });\n });\n }\n })();\n </script>\n</body>\n</html>`;\n}\n", "/**\n * Script Cache\n * In-memory cache for SSR preview scripts (same pattern as static build)\n */\n\nimport { hashContent as runtimeHashContent } from './runtime';\n\nconst scriptCache = new Map<string, string>();\n\n/**\n * Cache script content with given hash key\n */\nexport function cacheScript(hash: string, content: string): void {\n scriptCache.set(hash, content);\n}\n\n/**\n * Get cached script by hash\n */\nexport function getScript(hash: string): string | undefined {\n return scriptCache.get(hash);\n}\n\n/**\n * Hash content to generate cache key (matches static build pattern)\n */\nexport function hashContent(content: string): string {\n return runtimeHashContent(content);\n}\n\n/**\n * Clear script cache (useful for testing or memory management)\n */\nexport function clearScriptCache(): void {\n scriptCache.clear();\n}\n", "/**\n * Static File Route Handler\n * Serves static files and handles TypeScript/TSX file requests\n */\n\nimport { join } from 'path';\nimport { resolveProjectPath, resolvePackagePath, packagePaths, getProjectRoot, getPackageRoot } from '../projectContext';\nimport { isPathWithinRoot } from '../../shared/pathSecurity';\nimport { fileExists, serveFile, bundleFile } from '../runtime';\n\nexport async function handleStaticRoute(url: URL, req?: Request): Promise<Response | undefined> {\n // Handle client-router requests (both .js and .tsx)\n if (url.pathname === '/client-router.js' || url.pathname === '/client-router.tsx') {\n // Check for pre-bundled version first (Electron packaged mode)\n const preBundledPath = packagePaths.clientRouter().replace(/\\.tsx$/, '.js');\n if (preBundledPath !== packagePaths.clientRouter() && await fileExists(preBundledPath)) {\n return serveFile(preBundledPath, {\n 'Content-Type': 'application/javascript',\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n });\n }\n\n // Fall back to runtime bundling (dev mode)\n const result = await bundleFile(packagePaths.clientRouter(), {\n target: 'browser',\n format: 'esm',\n minify: false,\n sourcemap: 'inline',\n });\n\n if (result.success) {\n return new Response(result.code, {\n headers: {\n 'Content-Type': 'application/javascript',\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n },\n });\n }\n }\n\n // Serve client bundle with HMR enabled (editor TypeScript files)\n if (url.pathname.endsWith('.tsx') || url.pathname.endsWith('.ts')) {\n const entrypoint = resolvePackagePath(url.pathname.slice(1));\n\n // Security: Prevent path traversal attacks\n if (!isPathWithinRoot(entrypoint, getPackageRoot())) {\n return new Response('Forbidden', { status: 403 });\n }\n\n const result = await bundleFile(entrypoint, {\n target: 'browser',\n format: 'esm',\n minify: false,\n sourcemap: 'inline',\n });\n\n if (result.success) {\n return new Response(result.code, {\n headers: {\n 'Content-Type': 'application/javascript',\n 'Cache-Control': 'no-cache, no-store, must-revalidate',\n },\n });\n }\n }\n\n // Serve static files (including fonts and images)\n const decodedPathname = decodeURIComponent(url.pathname);\n\n // For fonts, images, and icons, resolve relative to project root\n // Other static files (editor assets) resolve relative to package root\n let filePath: string;\n let rootPath: string;\n if (decodedPathname.startsWith('/fonts/') || decodedPathname.startsWith('/images/') || decodedPathname.startsWith('/icons/') || decodedPathname.startsWith('/assets/') || decodedPathname.startsWith('/libraries/') || decodedPathname.startsWith('/videos/')) {\n rootPath = getProjectRoot();\n filePath = resolveProjectPath(decodedPathname.slice(1)); // Remove leading /\n } else {\n rootPath = getPackageRoot();\n filePath = resolvePackagePath(decodedPathname.slice(1)); // Remove leading /\n }\n\n // Security: Prevent path traversal attacks\n if (!isPathWithinRoot(filePath, rootPath)) {\n return new Response('Forbidden', { status: 403 });\n }\n\n if (await fileExists(filePath)) {\n const cacheControl = decodedPathname.startsWith('/libraries/')\n ? 'no-cache, no-store, must-revalidate'\n : 'public, max-age=31536000, immutable';\n return serveFile(filePath, { 'Cache-Control': cacheControl });\n }\n\n return undefined;\n}\n\n", "/**\n * Server Factory\n * Creates a runtime-agnostic server for meno-core\n * Can be extended by @meno/studio for editor functionality\n */\n\nimport type { PageService } from './services/pageService';\nimport type { ComponentService } from './services/componentService';\nimport type { CMSService } from './services/cmsService';\nimport type { CMSProvider } from '../shared/interfaces/contentProvider';\nimport type { DraftPageStore } from './draftPageStore';\nimport { WebSocketManager } from './websocketManager';\nimport { handleRoutes, type RouteContext } from './routes';\nimport { SERVER_PORT, MAX_PORT_ATTEMPTS, HMR_ROUTE } from '../shared/constants';\nimport { createRuntimeServer, type RuntimeServer, type RuntimeWSClient } from './runtime';\n\nconst COLLAB_ROUTE = '/__collab';\n\n// Custom message handler type\nexport type WSMessageHandler = (ws: RuntimeWSClient, data: unknown) => void;\n\n/**\n * Server configuration\n */\nexport interface ServerConfig {\n port?: number;\n pageService: PageService;\n componentService: ComponentService;\n wsManager: WebSocketManager;\n cmsService?: CMSService;\n cmsProvider?: CMSProvider;\n /**\n * Optional in-memory draft page store. When provided, the page route\n * reads a draft (if one exists for the requested path) before falling\n * back to disk. Enables live preview in external browser tabs without\n * persisting unsaved edits.\n */\n draftPageStore?: DraftPageStore;\n additionalRoutes?: AdditionalRouteHandler[];\n onWSMessage?: WSMessageHandler;\n /**\n * Inject live reload script for on-demand SSR preview mode.\n * When true, pages include a WebSocket client that reloads on HMR messages.\n */\n injectLiveReload?: boolean;\n /** Whether this is the visual editor (studio). Affects library filtering. */\n isEditor?: boolean;\n /**\n * Optional handler for collab WebSocket messages on the /__collab path.\n * When provided, enables the /__collab WebSocket endpoint for real-time\n * collaborative editing via Automerge.\n */\n onCollabWSMessage?: WSMessageHandler;\n /** Callback when a collab WebSocket client connects */\n onCollabWSOpen?: (ws: RuntimeWSClient) => void;\n /** Callback when a collab WebSocket client disconnects */\n onCollabWSClose?: (ws: RuntimeWSClient) => void;\n}\n\n/**\n * Additional route handler type\n */\nexport type AdditionalRouteHandler = (\n req: Request,\n url: URL,\n context: RouteContext\n) => Promise<Response | undefined>;\n\n/**\n * Server factory result\n */\nexport interface ServerResult {\n server: RuntimeServer;\n port: number;\n}\n\n/**\n * Create a server with the given configuration\n */\nexport async function createServer(config: ServerConfig): Promise<ServerResult> {\n const {\n port: requestedPort = SERVER_PORT,\n pageService,\n componentService,\n wsManager,\n cmsService,\n cmsProvider,\n draftPageStore,\n additionalRoutes = [],\n onWSMessage,\n injectLiveReload,\n isEditor,\n onCollabWSMessage,\n onCollabWSOpen,\n onCollabWSClose,\n } = config;\n\n // Track which WS path each client connected from\n const collabClients = new WeakSet<RuntimeWSClient>();\n\n const routeContext: RouteContext = {\n pageService,\n componentService,\n cmsService,\n cmsProvider,\n injectLiveReload,\n isEditor,\n wsManager,\n draftPageStore,\n };\n\n // Will be set after server starts to inject actual bound port into live reload script\n let boundPort: number | undefined;\n\n // Try to start server, incrementing port if busy\n let lastError: unknown;\n\n for (let portAttempt = 0; portAttempt < MAX_PORT_ATTEMPTS; portAttempt++) {\n const currentPort = requestedPort + portAttempt;\n\n try {\n const server = await createRuntimeServer({\n port: currentPort,\n hostname: 'localhost',\n wsPath: HMR_ROUTE,\n\n async fetch(req: Request, upgradeWebSocket: (req: Request) => boolean) {\n const url = new URL(req.url);\n\n // Check additional routes first (allows studio to inject routes)\n for (const handler of additionalRoutes) {\n const response = await handler(req, url, routeContext);\n if (response) {\n return response;\n }\n }\n\n // WebSocket upgrade for HMR\n if (url.pathname === HMR_ROUTE) {\n const success = upgradeWebSocket(req);\n return success\n ? undefined\n : new Response('WebSocket upgrade failed', { status: 500 });\n }\n\n // WebSocket upgrade for collab sync\n if (url.pathname === COLLAB_ROUTE && onCollabWSMessage) {\n const success = upgradeWebSocket(req);\n return success\n ? undefined\n : new Response('WebSocket upgrade failed', { status: 500 });\n }\n\n // Handle all routes through centralized router\n const response = await handleRoutes(req, url, null, routeContext);\n return response || new Response('Not Found', { status: 404 });\n },\n\n websocket: {\n open(ws: RuntimeWSClient) {\n // Note: In Bun, we can't distinguish WS paths in open() directly.\n // We use a WeakSet populated during the upgrade request to track collab clients.\n // For now, all WS clients are added to HMR manager; collab routing\n // happens in the message handler based on message type prefix.\n wsManager.addClient(ws);\n onCollabWSOpen?.(ws);\n },\n message(ws: RuntimeWSClient, message: string) {\n try {\n const data = JSON.parse(message);\n\n // Respond to ping with pong (for heartbeat)\n if (data.type === 'ping') {\n ws.send('pong');\n return;\n }\n\n // Route collab messages to collab handler\n if (\n onCollabWSMessage &&\n typeof data.type === 'string' &&\n data.type.startsWith('collab:')\n ) {\n collabClients.add(ws);\n onCollabWSMessage(ws, data);\n return;\n }\n\n // Allow custom message handlers\n if (onWSMessage) {\n onWSMessage(ws, data);\n }\n } catch (error) {\n // Ignore non-JSON messages\n }\n },\n close(ws: RuntimeWSClient) {\n wsManager.removeClient(ws);\n if (collabClients.has(ws)) {\n onCollabWSClose?.(ws);\n collabClients.delete(ws);\n }\n },\n },\n });\n\n if (portAttempt > 0) {\n console.log(`Warning: Port ${requestedPort} was busy, using port ${server.port} instead`);\n }\n\n // Set the actual bound port so live reload WS connects directly to this server\n routeContext.serverPort = server.port;\n\n return { server, port: server.port };\n } catch (error: unknown) {\n lastError = error;\n const err = error as { code?: string };\n if (err?.code === 'EADDRINUSE') {\n if (portAttempt >= MAX_PORT_ATTEMPTS - 1) {\n console.error(\n `Failed to start server: All ports from ${requestedPort} to ${requestedPort + MAX_PORT_ATTEMPTS - 1} are busy`\n );\n throw error;\n }\n continue;\n }\n throw error;\n }\n }\n\n throw lastError || new Error('Failed to start server');\n}\n\n/**\n * Re-export types for convenience\n */\nexport { WebSocketManager };\nexport type { RouteContext };\n", "/**\n * File System Page Provider\n * Implements PageProvider for loading pages from the file system\n */\n\nimport { existsSync, readdirSync, mkdirSync, rmdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport type { PageProvider } from '../../shared/interfaces/contentProvider';\nimport { isJSONFile, stripExtension, mapPageNameToPath, mapPathToPageName } from '../../shared/utils/fileUtils';\nimport { readTextFile, fileExists } from '../runtime';\n\n/**\n * Load JSON file content from disk\n */\nasync function loadJSONFile(filePath: string): Promise<string | null> {\n try {\n if (await fileExists(filePath)) {\n return await readTextFile(filePath);\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * FileSystemPageProvider\n * Loads and saves page JSON files from/to the file system\n * Supports both static pages in pages/ and CMS templates in root templates/\n */\nexport class FileSystemPageProvider implements PageProvider {\n constructor(\n private pagesDir: string,\n private templatesDir?: string\n ) {}\n\n async loadAll(): Promise<Map<string, string>> {\n const pages = new Map<string, string>();\n\n if (existsSync(this.pagesDir)) {\n await this.scanDirectory(this.pagesDir, '', pages);\n }\n\n // Also scan templates directory if provided\n if (this.templatesDir && existsSync(this.templatesDir)) {\n await this.scanDirectory(this.templatesDir, 'templates', pages);\n }\n\n return pages;\n }\n\n /**\n * Recursively scan a directory for JSON page files\n * @param dir - Absolute directory path to scan\n * @param prefix - Relative prefix for page names (e.g., '' for root, 'blog' for blog/)\n */\n private async scanDirectory(dir: string, prefix: string, pages: Map<string, string>): Promise<void> {\n const entries = readdirSync(dir, { withFileTypes: true });\n\n const fileEntries = entries.filter(e => e.isFile() && isJSONFile(e.name));\n const dirEntries = entries.filter(e => e.isDirectory());\n\n await Promise.all([\n ...fileEntries.map(async entry => {\n const pageName = prefix\n ? `${prefix}/${stripExtension(entry.name)}`\n : stripExtension(entry.name);\n const content = await loadJSONFile(join(dir, entry.name));\n if (content) {\n const pagePath = mapPageNameToPath(pageName);\n pages.set(pagePath, content);\n }\n }),\n ...dirEntries.map(entry => {\n const subPrefix = prefix ? `${prefix}/${entry.name}` : entry.name;\n return this.scanDirectory(join(dir, entry.name), subPrefix, pages);\n }),\n ]);\n }\n\n /**\n * Resolve a page path to its filesystem file path\n * Routes /templates/* paths to the templates directory\n */\n private resolveFilePath(path: string): string {\n const pageName = mapPathToPageName(path);\n if (this.templatesDir && pageName.startsWith('templates/')) {\n const templateName = pageName.substring('templates/'.length);\n return join(this.templatesDir, `${templateName}.json`);\n }\n return join(this.pagesDir, `${pageName}.json`);\n }\n\n /**\n * Resolve the root directory for cleanup operations\n * Returns the appropriate root dir (templates or pages) for a given path\n */\n private resolveRootDir(path: string): string {\n const pageName = mapPathToPageName(path);\n if (this.templatesDir && pageName.startsWith('templates/')) {\n return this.templatesDir;\n }\n return this.pagesDir;\n }\n\n async get(path: string): Promise<string | null> {\n const filePath = this.resolveFilePath(path);\n return loadJSONFile(filePath);\n }\n\n async save(path: string, content: string): Promise<void> {\n const { writeFile } = await import('fs/promises');\n const filePath = this.resolveFilePath(path);\n // Auto-create parent directories for nested pages (e.g., blog/post.json)\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n await writeFile(filePath, content, 'utf-8');\n }\n\n async delete(path: string): Promise<void> {\n const { unlink } = await import('fs/promises');\n const filePath = this.resolveFilePath(path);\n const rootDir = this.resolveRootDir(path);\n\n if (existsSync(filePath)) {\n await unlink(filePath);\n\n // Clean up empty parent directories (but not the root dir)\n let dir = dirname(filePath);\n while (dir !== rootDir) {\n try {\n const remaining = readdirSync(dir);\n if (remaining.length === 0) {\n rmdirSync(dir);\n } else {\n break;\n }\n } catch {\n break;\n }\n dir = dirname(dir);\n }\n }\n }\n\n async exists(path: string): Promise<boolean> {\n const filePath = this.resolveFilePath(path);\n return existsSync(filePath);\n }\n\n baseDir(): string {\n return this.pagesDir;\n }\n\n extension(): string {\n return '.json';\n }\n}\n", "/**\n * File Utilities\n * Common file path and extension handling functions\n */\n\n/**\n * Check if a filename has a .json extension\n */\nexport const isJSONFile = (name: string): boolean => name.endsWith('.json');\n\n/**\n * Check if a filename has a .js extension\n */\nexport const isJSFile = (name: string): boolean => name.endsWith('.js');\n\n/**\n * Check if a filename has a .css extension\n */\nexport const isCSSFile = (name: string): boolean => name.endsWith('.css');\n\n/**\n * Remove the file extension from a filename\n * @example stripExtension('page.json') => 'page'\n * @example stripExtension('component.test.ts') => 'component.test'\n */\nexport const stripExtension = (name: string): string => {\n const lastDotIndex = name.lastIndexOf('.');\n return lastDotIndex > 0 ? name.substring(0, lastDotIndex) : name;\n};\n\n/**\n * Get the base filename from a path\n * @example getBaseName('/path/to/file.json') => 'file.json'\n */\nexport const getBaseName = (filePath: string): string => {\n const parts = filePath.split('/');\n return parts[parts.length - 1] || '';\n};\n\n/**\n * Map page filename to route path\n * @example mapPageNameToPath('index') => '/'\n * @example mapPageNameToPath('about') => '/about'\n */\nexport const mapPageNameToPath = (pageName: string): string => {\n return pageName === 'index' ? '/' : `/${pageName}`;\n};\n\n/**\n * Map route path to page filename\n * @example mapPathToPageName('/') => 'index'\n * @example mapPathToPageName('/about') => 'about'\n */\nexport const mapPathToPageName = (path: string): string => {\n return path === '/' ? 'index' : path.substring(1);\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["path", "path", "path", "path", "join", "existsSync", "mkdirSync", "readdirSync", "rmdirSync", "join", "existsSync", "readdirSync", "writeFile", "mkdirSync", "rmdirSync", "path", "existsSync", "join", "existsSync", "join", "DEFAULT_OPTIONS", "schema", "path", "hashContent", "hashContent", "response", "response", "existsSync", "readdirSync", "mkdirSync", "rmdirSync", "join", "dirname", "mapPageNameToPath", "path", "loadJSONFile", "existsSync", "readdirSync", "join", "mapPageNameToPath", "path", "writeFile", "dirname", "mkdirSync", "rmdirSync"]
|
|
7
|
+
}
|