meno-core 1.0.37 → 1.0.38
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-static.ts
CHANGED
|
@@ -259,12 +259,13 @@ function cleanDist(): void {
|
|
|
259
259
|
let cleaned = 0;
|
|
260
260
|
|
|
261
261
|
for (const file of files) {
|
|
262
|
-
// Keep fonts, images, icons, and
|
|
262
|
+
// Keep fonts, images, icons, assets, and videos
|
|
263
263
|
if (
|
|
264
264
|
file === "fonts" ||
|
|
265
265
|
file === "images" ||
|
|
266
266
|
file === "icons" ||
|
|
267
|
-
file === "assets"
|
|
267
|
+
file === "assets" ||
|
|
268
|
+
file === "videos"
|
|
268
269
|
) {
|
|
269
270
|
continue;
|
|
270
271
|
}
|
|
@@ -653,6 +654,7 @@ export async function buildStaticPages(): Promise<void> {
|
|
|
653
654
|
copyDirectory(projectPaths.images(), join(distDir, "images"));
|
|
654
655
|
copyDirectory(projectPaths.icons(), join(distDir, "icons"));
|
|
655
656
|
copyDirectory(projectPaths.assets(), join(distDir, "assets"));
|
|
657
|
+
copyDirectory(projectPaths.videos(), join(distDir, "videos"));
|
|
656
658
|
|
|
657
659
|
// Copy libraries folder (downloaded external JS/CSS files)
|
|
658
660
|
const librariesDir = join(projectPaths.project, "libraries");
|
package/dist/build-static.js
CHANGED
|
@@ -527,7 +527,7 @@ function cleanDist() {
|
|
|
527
527
|
const files = readdirSync(distDir);
|
|
528
528
|
let cleaned = 0;
|
|
529
529
|
for (const file of files) {
|
|
530
|
-
if (file === "fonts" || file === "images" || file === "icons" || file === "assets") {
|
|
530
|
+
if (file === "fonts" || file === "images" || file === "icons" || file === "assets" || file === "videos") {
|
|
531
531
|
continue;
|
|
532
532
|
}
|
|
533
533
|
try {
|
|
@@ -782,6 +782,7 @@ async function buildStaticPages() {
|
|
|
782
782
|
copyDirectory(projectPaths.images(), join(distDir, "images"));
|
|
783
783
|
copyDirectory(projectPaths.icons(), join(distDir, "icons"));
|
|
784
784
|
copyDirectory(projectPaths.assets(), join(distDir, "assets"));
|
|
785
|
+
copyDirectory(projectPaths.videos(), join(distDir, "videos"));
|
|
785
786
|
const librariesDir = join(projectPaths.project, "libraries");
|
|
786
787
|
if (existsSync(librariesDir)) {
|
|
787
788
|
copyDirectory(librariesDir, join(distDir, "libraries"));
|
|
@@ -1129,4 +1130,4 @@ export {
|
|
|
1129
1130
|
injectTrackingScript,
|
|
1130
1131
|
buildStaticPages
|
|
1131
1132
|
};
|
|
1132
|
-
//# sourceMappingURL=chunk-
|
|
1133
|
+
//# sourceMappingURL=chunk-JACS3C25.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../build-static.ts", "../../lib/server/ab/generateFunctions.ts", "../../lib/server/ab/trackingScript.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Static Site Generation Build Script\n * Pre-generates HTML files for all pages at build time\n * CSP-compliant: Extracts JavaScript to external files\n */\n\nimport { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { writeFile, readFile } from \"fs/promises\";\nimport { join } from \"path\";\nimport type { BuildError, BuildErrorsData } from \"./lib/server/ssr/buildErrorOverlay\";\nimport { createHash } from \"crypto\";\nimport { inspect, minifyJS as runtimeMinifyJS } from './lib/server/runtime';\nimport {\n loadJSONFile,\n loadComponentDirectory,\n mapPageNameToPath,\n parseJSON,\n loadI18nConfig\n} from \"./lib/server/jsonLoader\";\nimport { generateSSRHTML } from \"./lib/server/ssrRenderer\";\nimport type { SSRHTMLResult } from \"./lib/server/ssr/htmlGenerator\";\nimport { prepareClientData, type ClientDataCollection } from \"./lib/server/ssr/clientDataInjector\";\nimport { clearJSValidationCache, getJSValidationErrors } from \"./lib/server/ssr/jsCollector\";\nimport { projectPaths } from \"./lib/server/projectContext\";\nimport { loadProjectConfig } from \"./lib/shared/fontLoader\";\nimport { FileSystemCMSProvider } from \"./lib/server/providers/fileSystemCMSProvider\";\nimport { CMSService } from \"./lib/server/services/cmsService\";\nimport { isI18nValue, resolveI18nValue } from \"./lib/shared/i18n\";\nimport type { ComponentDefinition, JSONPage, CMSSchema, CMSItem, I18nConfig, Experiment } from \"./lib/shared/types\";\nimport { isItemDraftForLocale, isItemFullyPublished } from \"./lib/shared/types\";\nimport type { SlugMap } from \"./lib/shared/slugTranslator\";\nimport { buildItemUrl } from \"./lib/shared/itemTemplateUtils\";\nimport { generateMiddleware, generateTrackFunction, generateResultsFunction } from \"./lib/server/ab/generateFunctions\";\nimport { generateTrackingScript } from \"./lib/server/ab/trackingScript\";\nimport { migrateTemplatesDirectory } from \"./lib/server/migrateTemplates\";\nimport { extractLibraryOrigins, collectComponentLibraries, filterLibrariesByContext } from \"./lib/shared/libraryLoader\";\nimport type { LibrariesConfig } from \"./lib/shared/types/libraries\";\n\n/**\n * Collect build errors for error overlay\n */\nconst buildErrors: BuildError[] = [];\n\n/**\n * Generate short hash from content for file naming\n */\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex').slice(0, 8);\n}\n\n/**\n * Format a Bun build log entry to a readable string\n */\nexport function formatBunLog(log: any): string {\n const parts: string[] = [];\n\n // Try to get position info\n if (log.position) {\n const pos = log.position;\n if (pos.file) parts.push(`File: ${pos.file}`);\n if (pos.line !== undefined) parts.push(`Line ${pos.line}:${pos.column || 0}`);\n if (pos.lineText) parts.push(` ${pos.lineText}`);\n }\n\n // Get the message\n if (log.message) {\n parts.push(log.message);\n } else if (log.text) {\n parts.push(log.text);\n }\n\n // If we couldn't extract anything useful, stringify the whole thing\n if (parts.length === 0) {\n try {\n return JSON.stringify(log, null, 2);\n } catch {\n return String(log);\n }\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Minify JavaScript code using runtime bundler\n * Throws on error instead of silently failing\n */\nasync function minifyJS(code: string): Promise<string> {\n const result = await runtimeMinifyJS(code);\n if (result.success) {\n return result.code;\n }\n throw new Error(`JavaScript minification failed:\\n${result.errors.join('\\n\\n')}`);\n}\n\n/**\n * Track JavaScript files to avoid duplicates\n * Maps content hash -> script path\n */\nconst jsFileCache = new Map<string, string>();\n\n/**\n * Get or create script file path for given JS content\n * Returns the path to reference in HTML\n */\nasync function getScriptPath(jsContent: string, distDir: string): Promise<string> {\n // Minify JavaScript for production\n const minified = await minifyJS(jsContent);\n const hash = hashContent(minified);\n\n // Check if we already wrote this content\n if (jsFileCache.has(hash)) {\n return jsFileCache.get(hash)!;\n }\n\n // Create scripts directory if needed\n const scriptsDir = join(distDir, '_scripts');\n if (!existsSync(scriptsDir)) {\n mkdirSync(scriptsDir, { recursive: true });\n }\n\n // Write minified script file\n const scriptPath = `/_scripts/${hash}.js`;\n const fullPath = join(distDir, '_scripts', `${hash}.js`);\n await writeFile(fullPath, minified, 'utf-8');\n\n // Cache for reuse\n jsFileCache.set(hash, scriptPath);\n\n return scriptPath;\n}\n\n/**\n * Recursively copy directory contents\n */\nfunction copyDirectory(src: string, dest: string): void {\n if (!existsSync(src)) {\n return;\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const files = readdirSync(src);\n\n for (const file of files) {\n const srcPath = join(src, file);\n const destPath = join(dest, file);\n const stat = statSync(srcPath);\n\n if (stat.isDirectory()) {\n copyDirectory(srcPath, destPath);\n } else {\n copyFileSync(srcPath, destPath);\n }\n }\n}\n\n\n/**\n * Get locale-specific output path for a page with translated slug support\n * Default locale files go to root, other locales to subdirectories\n * Uses translated slugs from meta.slugs if available\n */\nexport function getLocalizedOutputPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n distDir: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale, or fall back to default path\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n // Build filename from slug\n const fileName = slug === \"\" ? \"index.html\" : `${slug}.html`;\n\n if (locale === defaultLocale) {\n return `${distDir}/${fileName}`;\n }\n return `${distDir}/${locale}/${fileName}`;\n}\n\n/**\n * Get display path for logging (the actual URL the user will visit)\n */\nexport function getDisplayPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n if (locale === defaultLocale) {\n return slug === \"\" ? \"/\" : `/${slug}`;\n }\n return slug === \"\" ? `/${locale}` : `/${locale}/${slug}`;\n}\n\n/**\n * Generate robots.txt with sensible defaults\n */\nexport async function generateRobotsTxt(siteUrl: string, distDir: string): Promise<void> {\n const content = `User-agent: *\nAllow: /\n\nSitemap: ${siteUrl}/sitemap.xml\n`;\n await writeFile(join(distDir, 'robots.txt'), content, 'utf-8');\n}\n\n/**\n * Generate sitemap.xml from collected URLs\n */\nexport async function generateSitemap(urls: string[], siteUrl: string, distDir: string): Promise<void> {\n // Sort URLs for deterministic output\n const sortedUrls = [...urls].sort();\n\n const urlEntries = sortedUrls\n .map(url => ` <url><loc>${siteUrl}${url}</loc></url>`)\n .join('\\n');\n\n const content = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${urlEntries}\n</urlset>\n`;\n await writeFile(join(distDir, 'sitemap.xml'), content, 'utf-8');\n}\n\n/**\n * Clean dist directory, keeping only production files\n */\nfunction cleanDist(): void {\n const distDir = projectPaths.dist();\n if (!existsSync(distDir)) {\n mkdirSync(distDir, { recursive: true });\n return;\n }\n\n const files = readdirSync(distDir);\n let cleaned = 0;\n\n for (const file of files) {\n // Keep fonts, images, icons, assets, and videos\n if (\n file === \"fonts\" ||\n file === \"images\" ||\n file === \"icons\" ||\n file === \"assets\" ||\n file === \"videos\"\n ) {\n continue;\n }\n\n // Remove everything else (editor files, old HTML, etc.)\n try {\n const filePath = join(distDir, file);\n const stat = statSync(filePath);\n\n if (stat.isDirectory()) {\n rmSync(filePath, { recursive: true, force: true });\n } else {\n rmSync(filePath, { force: true });\n }\n cleaned++;\n } catch (error) {\n console.warn(`\u26A0\uFE0F Could not remove ${file}:`, error);\n }\n }\n\n if (cleaned > 0) {\n console.log(`\uD83E\uDDF9 Cleaned ${cleaned} file(s) from dist\\n`);\n }\n}\n\n/**\n * Check if a page is a CMS template\n */\nexport function isCMSPage(pageData: JSONPage): boolean {\n return pageData.meta?.source === 'cms' && !!pageData.meta?.cms;\n}\n\n/**\n * Build URL path for a CMS item based on the URL pattern\n * Uses schema.slugField to get the slug value, supporting i18n slugs\n */\nexport function buildCMSItemPath(\n urlPattern: string,\n item: CMSItem,\n slugField: string,\n locale: string,\n i18nConfig: I18nConfig\n): string {\n // Get slug from the schema-defined slugField, fall back to _slug or _id\n let slug = item[slugField] ?? item._slug ?? item._id;\n\n // Resolve i18n slug to locale-specific value\n if (isI18nValue(slug)) {\n slug = resolveI18nValue(slug, locale, i18nConfig) as string;\n }\n\n return urlPattern.replace('{{slug}}', String(slug));\n}\n\n/**\n * Generate static JSON data files for collections with 'static' strategy\n * Output: /data/{collection}/index.json\n */\nasync function generateStaticDataFiles(\n staticCollections: Map<string, ClientDataCollection>,\n distDir: string\n): Promise<void> {\n if (staticCollections.size === 0) return;\n\n console.log(`\\n\uD83D\uDCE6 Generating static data files...`);\n\n for (const [collectionId, data] of staticCollections) {\n const dataDir = join(distDir, 'data', collectionId);\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n const jsonPath = join(dataDir, 'index.json');\n await writeFile(jsonPath, JSON.stringify(data.items), 'utf-8');\n console.log(` \u2705 /data/${collectionId}/index.json (${data.items.length} items)`);\n }\n}\n\n/**\n * Build CMS templates from root templates/ directory\n */\nasync function buildCMSTemplates(\n templatesDir: string,\n globalComponents: Record<string, ComponentDefinition>,\n i18nConfig: I18nConfig,\n slugMappings: SlugMap[],\n distDir: string,\n cmsService: CMSService,\n generatedUrls: Set<string>,\n staticCollections: Map<string, ClientDataCollection>,\n siteUrl?: string,\n abTrackingScript?: string | null\n): Promise<{ success: number; errors: number }> {\n let successCount = 0;\n let errorCount = 0;\n\n if (!existsSync(templatesDir)) {\n return { success: 0, errors: 0 };\n }\n\n const templateFiles = readdirSync(templatesDir).filter(f => f.endsWith('.json'));\n\n if (templateFiles.length === 0) {\n return { success: 0, errors: 0 };\n }\n\n console.log(`\\n\uD83D\uDCDD Processing ${templateFiles.length} CMS template(s)...\\n`);\n\n for (const file of templateFiles) {\n const templateContent = await loadJSONFile(join(templatesDir, file));\n if (!templateContent) continue;\n\n try {\n const pageData = parseJSON<JSONPage>(templateContent);\n\n // Skip draft templates in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft template: ${file}`);\n continue;\n }\n\n if (!isCMSPage(pageData)) {\n console.warn(`\u26A0\uFE0F ${file} is in templates/ but missing meta.source: \"cms\"`);\n continue;\n }\n\n const cmsSchema = pageData.meta!.cms as CMSSchema;\n console.log(`\uD83D\uDCDD CMS Collection: ${cmsSchema.id}`);\n\n // Use shared cmsService to get items\n const items = await cmsService.queryItems({ collection: cmsSchema.id });\n\n if (items.length === 0) {\n console.log(` \u26A0\uFE0F No items found in cms/${cmsSchema.id}/`);\n continue;\n }\n\n console.log(` Found ${items.length} item(s)`);\n\n // Prepare client data if clientData is enabled\n // Filter out fully-draft items from client data (client data is locale-agnostic)\n let clientDataCollections: Map<string, ClientDataCollection> | undefined;\n if (cmsSchema.clientData?.enabled) {\n const publishedItems = items.filter(item => isItemFullyPublished(item));\n const clientData = prepareClientData(cmsSchema.id, publishedItems, cmsSchema.clientData);\n if (clientData) {\n if (clientData.strategy === 'inline') {\n // Inline data embedded in HTML\n clientDataCollections = new Map([[cmsSchema.id, clientData]]);\n console.log(` \uD83D\uDCE6 Client data (inline): ${clientData.items.length} items (${clientData.config.fields?.length || 'all'} fields)`);\n } else if (clientData.strategy === 'static') {\n // Static data written to separate file\n staticCollections.set(cmsSchema.id, clientData);\n console.log(` \uD83D\uDCE6 Client data (static): ${clientData.items.length} items \u2192 /data/${cmsSchema.id}/index.json`);\n }\n }\n }\n\n for (const item of items) {\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n\n // Skip draft items per locale in production builds\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (!isDevBuild && isItemDraftForLocale(item, locale)) {\n console.log(` \u23ED\uFE0F Skipping draft: ${item._filename || item._id} [${locale}]`);\n continue;\n }\n\n const baseUrl = siteUrl || \"\";\n const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);\n\n // Create CMS item with computed _url for {{cms._url}} template access\n const itemWithUrl: CMSItem = { ...item, _url: itemPath };\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: itemPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsContext: { cms: itemWithUrl },\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n clientDataCollections,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (abTrackingScript) {\n finalHtml = injectTrackingScript(finalHtml, abTrackingScript);\n }\n\n const outputPath = locale === i18nConfig.defaultLocale\n ? `${distDir}${itemPath}.html`\n : `${distDir}/${locale}${itemPath}.html`;\n\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/'));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n await writeFile(outputPath, finalHtml, 'utf-8');\n\n const displayPath = locale === i18nConfig.defaultLocale ? itemPath : `/${locale}${itemPath}`;\n generatedUrls.add(displayPath);\n console.log(` \u2705 ${displayPath}`);\n successCount++;\n }\n }\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error processing ${file}:`, error);\n buildErrors.push({\n file: `templates/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'cms',\n });\n errorCount++;\n }\n }\n\n return { success: successCount, errors: errorCount };\n}\n\n/**\n * Load running experiments from experiments.json\n */\nasync function loadRunningExperiments(): Promise<Experiment[]> {\n const experimentsPath = join(projectPaths.project, 'experiments.json');\n if (!existsSync(experimentsPath)) return [];\n\n try {\n const content = await readFile(experimentsPath, 'utf-8');\n const data = JSON.parse(content);\n const experiments: Experiment[] = data.experiments || [];\n return experiments.filter(e => e.status === 'running');\n } catch {\n return [];\n }\n}\n\n/**\n * Inject A/B tracking script into HTML before </head>\n */\nexport function injectTrackingScript(html: string, trackingJs: string): string {\n const scriptTag = `<script>${trackingJs}</script>`;\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n}\n\n/**\n * Generate A/B testing Cloudflare Functions into dist/functions/\n */\nasync function generateABFunctions(experiments: Experiment[], distDir: string): Promise<void> {\n // Generate middleware\n const middlewareContent = generateMiddleware(experiments);\n if (middlewareContent) {\n const middlewarePath = join(distDir, 'functions', '_middleware.ts');\n const middlewareDir = join(distDir, 'functions');\n if (!existsSync(middlewareDir)) {\n mkdirSync(middlewareDir, { recursive: true });\n }\n await writeFile(middlewarePath, middlewareContent, 'utf-8');\n }\n\n // Generate tracking endpoint\n const trackContent = generateTrackFunction();\n const trackDir = join(distDir, 'functions', 'api');\n if (!existsSync(trackDir)) {\n mkdirSync(trackDir, { recursive: true });\n }\n await writeFile(join(trackDir, 'ab-track.ts'), trackContent, 'utf-8');\n\n // Generate results endpoint\n const resultsContent = generateResultsFunction();\n await writeFile(join(trackDir, 'ab-results.ts'), resultsContent, 'utf-8');\n}\n\n/**\n * Main build function\n */\nexport async function buildStaticPages(): Promise<void> {\n console.log(\"\uD83C\uDFD7\uFE0F Building static HTML files...\\n\");\n\n // Clear previous build errors and JS validation cache\n buildErrors.length = 0;\n clearJSValidationCache();\n\n // Reset configService to ensure it loads from the correct project directory\n const { configService } = await import(\"./lib/server/services/configService\");\n configService.reset();\n\n // Load project config first\n const projectConfig = await loadProjectConfig();\n const siteUrl = (projectConfig as { siteUrl?: string }).siteUrl?.replace(/\\/$/, ''); // Remove trailing slash\n\n // Track all generated URLs for sitemap\n const generatedUrls = new Set<string>();\n\n // Load running A/B experiments (if any)\n const runningExperiments = await loadRunningExperiments();\n let trackingScript: string | null = null;\n if (runningExperiments.length > 0) {\n const exp = runningExperiments[0]; // Use first running experiment\n trackingScript = generateTrackingScript(exp.id, exp.conversionGoals);\n console.log(`\uD83E\uDDEA A/B experiment active: \"${exp.name}\" (${exp.variants.length} variant(s))\\n`);\n }\n\n // Load i18n config for multi-locale build\n const i18nConfig = await loadI18nConfig();\n console.log(`\uD83C\uDF10 Locales: ${i18nConfig.locales.map(l => l.code).join(\", \")} (default: ${i18nConfig.defaultLocale})\\n`);\n\n // Auto-migrate pages/templates/ \u2192 templates/ if needed\n await migrateTemplatesDirectory();\n\n // Clean dist directory (removes editor files, old HTML)\n cleanDist();\n\n // Clear the JS file cache since cleanDist() removed _scripts/\n // Without this, cached entries would skip file creation on subsequent builds\n jsFileCache.clear();\n\n // Copy fonts, images, icons, and functions directories to dist\n console.log(\"\uD83D\uDCE6 Copying assets...\");\n const distDir = projectPaths.dist();\n\n // Delete old _errors.json if it exists (start fresh)\n const errorsPath = join(distDir, '_errors.json');\n if (existsSync(errorsPath)) {\n unlinkSync(errorsPath);\n }\n copyDirectory(projectPaths.fonts(), join(distDir, \"fonts\"));\n copyDirectory(projectPaths.images(), join(distDir, \"images\"));\n copyDirectory(projectPaths.icons(), join(distDir, \"icons\"));\n copyDirectory(projectPaths.assets(), join(distDir, \"assets\"));\n copyDirectory(projectPaths.videos(), join(distDir, \"videos\"));\n\n // Copy libraries folder (downloaded external JS/CSS files)\n const librariesDir = join(projectPaths.project, \"libraries\");\n if (existsSync(librariesDir)) {\n copyDirectory(librariesDir, join(distDir, \"libraries\"));\n }\n\n // Copy functions folder for Cloudflare Pages\n const functionsDir = projectPaths.functions();\n if (existsSync(functionsDir)) {\n copyDirectory(functionsDir, join(distDir, \"functions\"));\n }\n\n // Copy user-created root files for static hosting\n const hostingFiles: string[] = [];\n const rootFilesToCopy = [\n '_headers', // Netlify/Cloudflare headers\n '_redirects', // Netlify/Cloudflare redirects\n 'llms.txt', // LLM context\n 'humans.txt', // Team credits\n 'ads.txt', // Ad verification\n 'security.txt', // Security contact\n 'CNAME', // GitHub Pages domain\n 'manifest.json', // PWA manifest\n 'site.webmanifest', // PWA manifest (alt)\n ];\n\n for (const file of rootFilesToCopy) {\n const filePath = join(projectPaths.project, file);\n if (existsSync(filePath)) {\n copyFileSync(filePath, join(distDir, file));\n hostingFiles.push(file);\n }\n }\n\n // Copy .well-known directory if exists\n const wellKnownDir = join(projectPaths.project, '.well-known');\n if (existsSync(wellKnownDir)) {\n copyDirectory(wellKnownDir, join(distDir, '.well-known'));\n hostingFiles.push('.well-known/');\n }\n\n const parts = ['Assets'];\n if (existsSync(functionsDir)) parts.push('functions');\n if (hostingFiles.length > 0) parts.push(hostingFiles.join(', '));\n console.log(`\u2705 ${parts.join(', ')} copied\\n`);\n\n // Load all global components\n const { components, warnings, errors } = await loadComponentDirectory(projectPaths.components());\n const globalComponents: Record<string, ComponentDefinition> = {};\n components.forEach((value, key) => {\n globalComponents[key] = value;\n });\n\n for (const warning of warnings) console.warn(`\u26A0\uFE0F ${warning}`);\n for (const error of errors) console.error(`\u274C ${error}`);\n console.log(`\u2705 Loaded ${components.size} global component(s)\\n`);\n\n // Initialize CMS service for CMSList rendering\n const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());\n const cmsService = new CMSService(cmsProvider);\n await cmsService.initialize();\n console.log(`\u2705 CMS service initialized\\n`);\n\n // Load all pages\n const pagesDir = projectPaths.pages();\n if (!existsSync(pagesDir)) {\n console.error(\"\u274C Pages directory not found!\");\n process.exit(1);\n }\n\n // Recursively collect all .json page files (supports nested folders like pages/a/b.json)\n const pageFiles: string[] = [];\n function scanPagesDir(dir: string, prefix: string): void {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.json')) {\n pageFiles.push(prefix ? `${prefix}/${entry.name}` : entry.name);\n } else if (entry.isDirectory()) {\n scanPagesDir(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);\n }\n }\n }\n scanPagesDir(pagesDir, '');\n \n if (pageFiles.length === 0) {\n console.warn(\"\u26A0\uFE0F No pages found in ./pages directory\");\n return;\n }\n\n console.log(`\uD83D\uDCC4 Found ${pageFiles.length} page(s) to build\\n`);\n\n // First pass: collect all slug mappings and page-level libraries\n const slugMappings: SlugMap[] = [];\n const allPageLibraries: LibrariesConfig[] = [];\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n if (pageContent) {\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n if (pageData.meta?.slugs) {\n const pageId = basePath === '/' ? 'index' : basePath.substring(1);\n slugMappings.push({ pageId, slugs: pageData.meta.slugs });\n }\n if (pageData.meta?.libraries) {\n allPageLibraries.push(pageData.meta.libraries as LibrariesConfig);\n }\n } catch { /* ignore parse errors in first pass */ }\n }\n }\n\n // Generate _headers from CSP config, auto-including library CDN domains\n // Always regenerate when CSP config exists \u2014 overwrites any stale _headers file\n // that may have been copied from the project root\n {\n await configService.load();\n const cspConfig = configService.getCSP();\n if (cspConfig && Object.keys(cspConfig).length > 0) {\n // Collect all library sources: global + component + page-level\n // Note: we concatenate (not mergeLibraries) because _headers applies globally \u2014\n // we need the union of ALL origins, regardless of per-page merge modes\n const globalLibraries = configService.getLibraries();\n const componentLibraries = collectComponentLibraries(globalComponents);\n const allJs = [\n ...(globalLibraries.js || []),\n ...(componentLibraries.js || []),\n ...allPageLibraries.flatMap(p => p.js || []),\n ];\n const allCss = [\n ...(globalLibraries.css || []),\n ...(componentLibraries.css || []),\n ...allPageLibraries.flatMap(p => p.css || []),\n ];\n const allLibs: LibrariesConfig = { js: allJs, css: allCss };\n\n // Filter out CSS libs disabled for build before extracting CSP origins\n const buildLibs = filterLibrariesByContext(allLibs, 'build');\n\n // Extract CDN origins from all library URLs\n const { scriptOrigins, styleOrigins } = extractLibraryOrigins(buildLibs);\n\n const extraScripts = [\n ...(cspConfig.scriptSrc || []),\n ...Array.from(scriptOrigins),\n ].join(' ');\n const extraStyles = [\n ...(cspConfig.styleSrc || []),\n ...Array.from(styleOrigins),\n ].join(' ');\n const extraConnect = cspConfig.connectSrc?.join(' ') || '';\n const extraFrames = cspConfig.frameSrc?.join(' ') || '';\n const extraFonts = cspConfig.fontSrc?.join(' ') || '';\n const extraImgs = cspConfig.imgSrc?.join(' ') || '';\n\n const cspDirectives = [\n \"default-src 'self'\",\n `script-src 'self' 'unsafe-inline' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),\n `style-src 'self' 'unsafe-inline' https://f.vimeocdn.com ${extraStyles}`.trim(),\n `img-src 'self' data: https: ${extraImgs}`.trim(),\n `connect-src 'self' https://vimeo.com https://*.vimeocdn.com ${extraConnect}`.trim(),\n `frame-src https://player.vimeo.com https://vimeo.com https://www.youtube.com https://www.youtube-nocookie.com ${extraFrames}`.trim(),\n `font-src 'self' data: ${extraFonts}`.trim(),\n \"media-src 'self' https: blob:\"\n ].join('; ');\n\n const headersContent = `/*\\n Content-Security-Policy: ${cspDirectives}\\n`;\n writeFileSync(join(distDir, '_headers'), headersContent);\n console.log(`\u2705 Generated _headers with CSP (auto-included ${scriptOrigins.size + styleOrigins.size} library origin(s))\\n`);\n }\n }\n\n let successCount = 0;\n let errorCount = 0;\n\n // Build each page for each locale\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n\n if (!pageContent) {\n console.warn(`\u26A0\uFE0F Skipping ${basePath} (empty file)`);\n errorCount++;\n continue;\n }\n\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n\n // Skip draft pages in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft: ${basePath}`);\n continue;\n }\n\n // Get translated slugs from page meta (if available)\n const slugs = pageData.meta?.slugs;\n\n // Generate HTML for each locale\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n const baseUrl = siteUrl || \"\";\n\n // Build the URL path that will be used for this locale\n const urlPath = getDisplayPath(basePath, locale, i18nConfig.defaultLocale, slugs);\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: urlPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n // Insert script reference before </body>\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (trackingScript) {\n finalHtml = injectTrackingScript(finalHtml, trackingScript);\n }\n\n // Determine locale-specific output path with translated slug\n const outputPath = getLocalizedOutputPath(basePath, locale, i18nConfig.defaultLocale, distDir, slugs);\n\n // Ensure directory exists\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf(\"/\"));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Debug: show end of HTML\n if (urlPath === '/') {\n console.log('[DEBUG] Last 500 chars of HTML:', finalHtml.slice(-500));\n }\n\n await writeFile(outputPath, finalHtml, \"utf-8\");\n\n generatedUrls.add(urlPath);\n console.log(`\u2705 Built: ${urlPath} \u2192 ${outputPath}`);\n successCount++;\n }\n\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error building ${basePath}:`, error);\n buildErrors.push({\n file: `pages/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'render',\n });\n errorCount++;\n }\n }\n\n // Build CMS templates from root templates/ directory\n const templatesDir = projectPaths.templates();\n const staticCollections = new Map<string, ClientDataCollection>();\n const cmsResult = await buildCMSTemplates(\n templatesDir,\n globalComponents,\n i18nConfig,\n slugMappings,\n distDir,\n cmsService,\n generatedUrls,\n staticCollections,\n siteUrl,\n trackingScript\n );\n successCount += cmsResult.success;\n errorCount += cmsResult.errors;\n\n // Generate static data files for collections with 'static' strategy\n await generateStaticDataFiles(staticCollections, distDir);\n\n // Generate A/B testing functions if experiments are running\n if (runningExperiments.length > 0) {\n await generateABFunctions(runningExperiments, distDir);\n console.log(`\\n\uD83E\uDDEA A/B testing functions generated (middleware, tracker, results API)`);\n }\n\n // Generate SEO files (robots.txt and sitemap.xml)\n if (siteUrl) {\n await generateRobotsTxt(siteUrl, distDir);\n await generateSitemap([...generatedUrls], siteUrl, distDir);\n console.log(`\\n\uD83D\uDD0D SEO files generated (robots.txt, sitemap.xml)`);\n } else {\n console.warn(`\\n\u26A0\uFE0F Skipping SEO files: siteUrl not configured in project.config.json`);\n }\n\n console.log(\"\\n\" + \"=\".repeat(50));\n console.log(`\u2728 Build complete!`);\n console.log(` \u2705 Success: ${successCount}`);\n if (errorCount > 0) {\n console.log(` \u274C Errors: ${errorCount}`);\n }\n console.log(`\\n\uD83D\uDCE6 Production files in /dist:`);\n console.log(` - *.html (Static pages with vanilla JS)`);\n console.log(` - fonts/ (Custom fonts)`);\n console.log(` - images/ (Image assets)`);\n console.log(` - icons/ (Favicon and icons)`);\n if (staticCollections.size > 0) {\n console.log(` - data/ (CMS collection data for client filtering)`);\n }\n if (existsSync(functionsDir)) {\n console.log(` - functions/ (Cloudflare Pages Functions)`);\n }\n if (runningExperiments.length > 0) {\n console.log(` - A/B testing (middleware + tracking injected)`);\n }\n if (siteUrl) {\n console.log(` - robots.txt, sitemap.xml (SEO)`);\n }\n console.log(` - No React, no client-router \u2713`);\n\n // Collect component JS validation errors\n const jsErrors = getJSValidationErrors();\n for (const { component, error } of jsErrors) {\n buildErrors.push({\n file: `components/${component}`,\n message: error,\n type: 'minify',\n });\n }\n\n // Write build errors to _errors.json for static server overlay\n if (buildErrors.length > 0) {\n // Deduplicate errors by message (same error may occur on multiple pages)\n const seenMessages = new Set<string>();\n const uniqueErrors = buildErrors.filter(err => {\n if (seenMessages.has(err.message)) return false;\n seenMessages.add(err.message);\n return true;\n });\n\n const errorsData: BuildErrorsData = {\n errors: uniqueErrors,\n timestamp: Date.now(),\n };\n await writeFile(errorsPath, JSON.stringify(errorsData, null, 2), 'utf-8');\n const countMsg = uniqueErrors.length === buildErrors.length\n ? `${uniqueErrors.length} error${uniqueErrors.length === 1 ? '' : 's'}`\n : `${uniqueErrors.length} unique error${uniqueErrors.length === 1 ? '' : 's'} (affected ${buildErrors.length} files)`;\n console.log(`\\n\u26A0\uFE0F Build errors written to dist/_errors.json (${countMsg})`);\n }\n}\n\n\n", "/**\n * A/B Testing Functions Generator\n * Generates Cloudflare Pages Functions for traffic splitting and event tracking\n * Only called at build time when experiments are running\n */\n\nimport type { Experiment } from '../../shared/types/experiments';\n\n/**\n * Generate the _middleware.ts content for traffic splitting\n */\nexport function generateMiddleware(experiments: Experiment[]): string {\n const running = experiments.filter(e => e.status === 'running');\n if (running.length === 0) return '';\n\n // Embed experiment config as JSON\n const configJSON = JSON.stringify(running.map(e => ({\n id: e.id,\n controlBranch: e.controlBranch,\n controlWeight: e.controlWeight,\n variants: e.variants.map(v => ({\n branch: v.branch,\n weight: v.weight,\n deployUrl: v.deployUrl,\n })),\n })));\n\n return `/**\n * A/B Testing Traffic Splitting Middleware\n * Auto-generated by Meno build - do not edit manually\n */\n\ninterface Env {\n AB_DB?: D1Database;\n}\n\ninterface ExperimentConfig {\n id: string;\n controlBranch: string;\n controlWeight: number;\n variants: Array<{ branch: string; weight: number; deployUrl: string }>;\n}\n\nconst EXPERIMENTS: ExperimentConfig[] = ${configJSON};\n\nfunction getCookie(request: Request, name: string): string | null {\n const cookieHeader = request.headers.get('Cookie');\n if (!cookieHeader) return null;\n const match = cookieHeader.match(new RegExp('(?:^|;\\\\\\\\s*)' + name + '=([^;]*)'));\n return match ? decodeURIComponent(match[1]) : null;\n}\n\nfunction assignVariant(experiment: ExperimentConfig): string {\n const rand = Math.random() * 100;\n let cumulative = experiment.controlWeight;\n if (rand < cumulative) return 'control';\n for (const variant of experiment.variants) {\n cumulative += variant.weight;\n if (rand < cumulative) return variant.branch;\n }\n return 'control';\n}\n\nexport async function onRequest(context: { request: Request; next: () => Promise<Response>; env: Env }) {\n const url = new URL(context.request.url);\n\n // Skip API routes and static assets\n if (url.pathname.startsWith('/api/') || url.pathname.match(/\\\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/)) {\n return context.next();\n }\n\n // Use first running experiment (single experiment at a time for simplicity)\n const experiment = EXPERIMENTS[0];\n if (!experiment) return context.next();\n\n // Check for existing variant assignment (sticky sessions)\n let variant = getCookie(context.request, 'meno_variant');\n\n // If no cookie, assign a variant\n if (!variant) {\n variant = assignVariant(experiment);\n }\n\n let response: Response;\n\n if (variant === 'control') {\n // Control: serve local assets (pass through)\n response = await context.next();\n } else {\n // Variant: proxy to branch preview deploy\n const variantConfig = experiment.variants.find(v => v.branch === variant);\n if (!variantConfig) {\n response = await context.next();\n } else {\n // Fetch from the variant's deploy URL\n const variantUrl = new URL(url.pathname + url.search, variantConfig.deployUrl);\n try {\n const proxyResponse = await fetch(variantUrl.toString(), {\n method: context.request.method,\n headers: context.request.headers,\n });\n response = new Response(proxyResponse.body, {\n status: proxyResponse.status,\n statusText: proxyResponse.statusText,\n headers: new Headers(proxyResponse.headers),\n });\n } catch {\n // Fallback to control if variant fetch fails\n response = await context.next();\n variant = 'control';\n }\n }\n }\n\n // Set variant cookie (30-day expiry)\n const headers = new Headers(response.headers);\n headers.append(\n 'Set-Cookie',\n \\`meno_variant=\\${encodeURIComponent(variant!)}; Path=/; Max-Age=2592000; SameSite=Lax\\`\n );\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n`;\n}\n\n/**\n * Generate the api/ab-track.ts content for event collection\n */\nexport function generateTrackFunction(): string {\n return `/**\n * A/B Testing Event Tracker\n * Auto-generated by Meno build - do not edit manually\n * POST /api/ab-track - stores pageview/conversion events in D1\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface TrackEvent {\n experimentId: string;\n visitorId: string;\n variant: string;\n eventType: 'pageview' | 'conversion';\n goalId?: string;\n url?: string;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n waitUntil: (promise: Promise<unknown>) => void;\n}\n\nexport async function onRequestPost(context: PagesContext<Env>): Promise<Response> {\n try {\n const body: TrackEvent = await context.request.json();\n\n // Validate required fields\n if (!body.experimentId || !body.visitorId || !body.variant || !body.eventType) {\n return new Response(null, { status: 400 });\n }\n\n // Validate event type\n if (body.eventType !== 'pageview' && body.eventType !== 'conversion') {\n return new Response(null, { status: 400 });\n }\n\n // Insert event into D1\n await context.env.AB_DB.prepare(\n 'INSERT INTO ab_events (experiment_id, visitor_id, variant, event_type, goal_id, url, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)'\n ).bind(\n body.experimentId,\n body.visitorId,\n body.variant,\n body.eventType,\n body.goalId || null,\n body.url || null,\n Date.now()\n ).run();\n\n return new Response(null, { status: 204 });\n } catch {\n return new Response(null, { status: 500 });\n }\n}\n`;\n}\n\n/**\n * Generate the api/ab-results.ts content for results aggregation\n */\nexport function generateResultsFunction(): string {\n return `/**\n * A/B Testing Results API\n * Auto-generated by Meno build - do not edit manually\n * GET /api/ab-results?experiment=<id> - returns aggregated results with significance\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n}\n\ninterface VariantResult {\n variant: string;\n visitors: number;\n conversions: number;\n conversionRate: number;\n lift?: number;\n pValue?: number;\n isSignificant: boolean;\n}\n\n/**\n * Two-proportion z-test for statistical significance\n */\nfunction zTest(\n conversionsA: number, visitorsA: number,\n conversionsB: number, visitorsB: number\n): number {\n if (visitorsA === 0 || visitorsB === 0) return 1;\n\n const pA = conversionsA / visitorsA;\n const pB = conversionsB / visitorsB;\n const pPool = (conversionsA + conversionsB) / (visitorsA + visitorsB);\n\n if (pPool === 0 || pPool === 1) return 1;\n\n const se = Math.sqrt(pPool * (1 - pPool) * (1 / visitorsA + 1 / visitorsB));\n if (se === 0) return 1;\n\n const z = Math.abs(pA - pB) / se;\n\n // Approximate two-tailed p-value using rational approximation\n const t = 1 / (1 + 0.2316419 * z);\n const d = 0.3989422804014327;\n const p = d * Math.exp(-z * z / 2) * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));\n return 2 * p;\n}\n\nexport async function onRequestGet(context: PagesContext<Env>): Promise<Response> {\n const url = new URL(context.request.url);\n const experimentId = url.searchParams.get('experiment');\n\n if (!experimentId) {\n return Response.json({ error: 'Missing experiment parameter' }, { status: 400 });\n }\n\n try {\n // Get unique visitors per variant\n const visitorsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as visitors FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'pageview\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Get conversions per variant\n const conversionsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as conversions FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'conversion\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Build results map\n const visitorMap = new Map<string, number>();\n const conversionMap = new Map<string, number>();\n\n for (const row of (visitorsResult.results || [])) {\n visitorMap.set(row.variant as string, row.visitors as number);\n }\n for (const row of (conversionsResult.results || [])) {\n conversionMap.set(row.variant as string, row.conversions as number);\n }\n\n // Get all variant names\n const allVariants = new Set([...visitorMap.keys(), ...conversionMap.keys()]);\n\n // Calculate results\n const variants: VariantResult[] = [];\n let controlVisitors = 0;\n let controlConversions = 0;\n\n for (const variant of allVariants) {\n const visitors = visitorMap.get(variant) || 0;\n const conversions = conversionMap.get(variant) || 0;\n const conversionRate = visitors > 0 ? conversions / visitors : 0;\n\n if (variant === 'control') {\n controlVisitors = visitors;\n controlConversions = conversions;\n }\n\n variants.push({\n variant,\n visitors,\n conversions,\n conversionRate,\n isSignificant: false,\n });\n }\n\n // Calculate lift and significance for non-control variants\n const controlRate = controlVisitors > 0 ? controlConversions / controlVisitors : 0;\n for (const result of variants) {\n if (result.variant !== 'control' && controlVisitors > 0) {\n result.lift = controlRate > 0\n ? ((result.conversionRate - controlRate) / controlRate) * 100\n : 0;\n result.pValue = zTest(\n controlConversions, controlVisitors,\n result.conversions, result.visitors\n );\n result.isSignificant = result.pValue < 0.05;\n }\n }\n\n // Sort: control first, then by variant name\n variants.sort((a, b) => {\n if (a.variant === 'control') return -1;\n if (b.variant === 'control') return 1;\n return a.variant.localeCompare(b.variant);\n });\n\n return Response.json({\n experimentId,\n variants,\n }, {\n headers: {\n 'Access-Control-Allow-Origin': '*',\n 'Cache-Control': 'no-cache',\n }\n });\n } catch (error) {\n return Response.json({ error: 'Failed to query results' }, { status: 500 });\n }\n}\n`;\n}\n", "/**\n * A/B Testing Tracking Script Generator\n * Generates a lightweight client-side tracking script to be injected into HTML\n */\n\nimport type { ConversionGoal } from '../../shared/types/experiments';\n\n/**\n * Generate the tracking script content with embedded experiment config\n */\nexport function generateTrackingScript(experimentId: string, goals: ConversionGoal[]): string {\n const goalsJSON = JSON.stringify(goals);\n\n return `(function(){\nvar EXP_ID=${JSON.stringify(experimentId)};\nvar GOALS=${goalsJSON};\n\nfunction getCookie(n){var m=document.cookie.match(new RegExp('(?:^|;\\\\\\\\s*)'+n+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}\nfunction setCookie(n,v,d){var e=new Date();e.setTime(e.getTime()+d*864e5);document.cookie=n+'='+encodeURIComponent(v)+';path=/;expires='+e.toUTCString()+';SameSite=Lax'}\n\nvar variant=getCookie('meno_variant')||'control';\nvar visitor=getCookie('meno_visitor');\nif(!visitor){visitor=Math.random().toString(36).slice(2)+Date.now().toString(36);setCookie('meno_visitor',visitor,365)}\n\nfunction track(type,goalId){\ntry{navigator.sendBeacon('/api/ab-track',JSON.stringify({experimentId:EXP_ID,visitorId:visitor,variant:variant,eventType:type,goalId:goalId||null,url:location.pathname}))}catch(e){}\n}\n\ntrack('pageview');\n\nGOALS.forEach(function(g){\nif(g.type==='click'&&g.selector){\ndocument.addEventListener('click',function(e){\nif(e.target&&e.target.closest&&e.target.closest(g.selector)){track('conversion',g.id)}\n})\n}\nif(g.type==='navigation'&&g.url){\nif(location.pathname===g.url||location.href.indexOf(g.url)>-1){track('conversion',g.id)}\n}\nif(g.type==='custom'&&g.event){\nwindow.addEventListener(g.event,function(){track('conversion',g.id)})\n}\n});\n})();`;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["minifyJS", "isDevBuild"]
|
|
7
|
+
}
|
package/dist/lib/server/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../build-static.ts", "../../lib/server/ab/generateFunctions.ts", "../../lib/server/ab/trackingScript.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Static Site Generation Build Script\n * Pre-generates HTML files for all pages at build time\n * CSP-compliant: Extracts JavaScript to external files\n */\n\nimport { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { writeFile, readFile } from \"fs/promises\";\nimport { join } from \"path\";\nimport type { BuildError, BuildErrorsData } from \"./lib/server/ssr/buildErrorOverlay\";\nimport { createHash } from \"crypto\";\nimport { inspect, minifyJS as runtimeMinifyJS } from './lib/server/runtime';\nimport {\n loadJSONFile,\n loadComponentDirectory,\n mapPageNameToPath,\n parseJSON,\n loadI18nConfig\n} from \"./lib/server/jsonLoader\";\nimport { generateSSRHTML } from \"./lib/server/ssrRenderer\";\nimport type { SSRHTMLResult } from \"./lib/server/ssr/htmlGenerator\";\nimport { prepareClientData, type ClientDataCollection } from \"./lib/server/ssr/clientDataInjector\";\nimport { clearJSValidationCache, getJSValidationErrors } from \"./lib/server/ssr/jsCollector\";\nimport { projectPaths } from \"./lib/server/projectContext\";\nimport { loadProjectConfig } from \"./lib/shared/fontLoader\";\nimport { FileSystemCMSProvider } from \"./lib/server/providers/fileSystemCMSProvider\";\nimport { CMSService } from \"./lib/server/services/cmsService\";\nimport { isI18nValue, resolveI18nValue } from \"./lib/shared/i18n\";\nimport type { ComponentDefinition, JSONPage, CMSSchema, CMSItem, I18nConfig, Experiment } from \"./lib/shared/types\";\nimport { isItemDraftForLocale, isItemFullyPublished } from \"./lib/shared/types\";\nimport type { SlugMap } from \"./lib/shared/slugTranslator\";\nimport { buildItemUrl } from \"./lib/shared/itemTemplateUtils\";\nimport { generateMiddleware, generateTrackFunction, generateResultsFunction } from \"./lib/server/ab/generateFunctions\";\nimport { generateTrackingScript } from \"./lib/server/ab/trackingScript\";\nimport { migrateTemplatesDirectory } from \"./lib/server/migrateTemplates\";\nimport { extractLibraryOrigins, collectComponentLibraries, filterLibrariesByContext } from \"./lib/shared/libraryLoader\";\nimport type { LibrariesConfig } from \"./lib/shared/types/libraries\";\n\n/**\n * Collect build errors for error overlay\n */\nconst buildErrors: BuildError[] = [];\n\n/**\n * Generate short hash from content for file naming\n */\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex').slice(0, 8);\n}\n\n/**\n * Format a Bun build log entry to a readable string\n */\nexport function formatBunLog(log: any): string {\n const parts: string[] = [];\n\n // Try to get position info\n if (log.position) {\n const pos = log.position;\n if (pos.file) parts.push(`File: ${pos.file}`);\n if (pos.line !== undefined) parts.push(`Line ${pos.line}:${pos.column || 0}`);\n if (pos.lineText) parts.push(` ${pos.lineText}`);\n }\n\n // Get the message\n if (log.message) {\n parts.push(log.message);\n } else if (log.text) {\n parts.push(log.text);\n }\n\n // If we couldn't extract anything useful, stringify the whole thing\n if (parts.length === 0) {\n try {\n return JSON.stringify(log, null, 2);\n } catch {\n return String(log);\n }\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Minify JavaScript code using runtime bundler\n * Throws on error instead of silently failing\n */\nasync function minifyJS(code: string): Promise<string> {\n const result = await runtimeMinifyJS(code);\n if (result.success) {\n return result.code;\n }\n throw new Error(`JavaScript minification failed:\\n${result.errors.join('\\n\\n')}`);\n}\n\n/**\n * Track JavaScript files to avoid duplicates\n * Maps content hash -> script path\n */\nconst jsFileCache = new Map<string, string>();\n\n/**\n * Get or create script file path for given JS content\n * Returns the path to reference in HTML\n */\nasync function getScriptPath(jsContent: string, distDir: string): Promise<string> {\n // Minify JavaScript for production\n const minified = await minifyJS(jsContent);\n const hash = hashContent(minified);\n\n // Check if we already wrote this content\n if (jsFileCache.has(hash)) {\n return jsFileCache.get(hash)!;\n }\n\n // Create scripts directory if needed\n const scriptsDir = join(distDir, '_scripts');\n if (!existsSync(scriptsDir)) {\n mkdirSync(scriptsDir, { recursive: true });\n }\n\n // Write minified script file\n const scriptPath = `/_scripts/${hash}.js`;\n const fullPath = join(distDir, '_scripts', `${hash}.js`);\n await writeFile(fullPath, minified, 'utf-8');\n\n // Cache for reuse\n jsFileCache.set(hash, scriptPath);\n\n return scriptPath;\n}\n\n/**\n * Recursively copy directory contents\n */\nfunction copyDirectory(src: string, dest: string): void {\n if (!existsSync(src)) {\n return;\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const files = readdirSync(src);\n\n for (const file of files) {\n const srcPath = join(src, file);\n const destPath = join(dest, file);\n const stat = statSync(srcPath);\n\n if (stat.isDirectory()) {\n copyDirectory(srcPath, destPath);\n } else {\n copyFileSync(srcPath, destPath);\n }\n }\n}\n\n\n/**\n * Get locale-specific output path for a page with translated slug support\n * Default locale files go to root, other locales to subdirectories\n * Uses translated slugs from meta.slugs if available\n */\nexport function getLocalizedOutputPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n distDir: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale, or fall back to default path\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n // Build filename from slug\n const fileName = slug === \"\" ? \"index.html\" : `${slug}.html`;\n\n if (locale === defaultLocale) {\n return `${distDir}/${fileName}`;\n }\n return `${distDir}/${locale}/${fileName}`;\n}\n\n/**\n * Get display path for logging (the actual URL the user will visit)\n */\nexport function getDisplayPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n if (locale === defaultLocale) {\n return slug === \"\" ? \"/\" : `/${slug}`;\n }\n return slug === \"\" ? `/${locale}` : `/${locale}/${slug}`;\n}\n\n/**\n * Generate robots.txt with sensible defaults\n */\nexport async function generateRobotsTxt(siteUrl: string, distDir: string): Promise<void> {\n const content = `User-agent: *\nAllow: /\n\nSitemap: ${siteUrl}/sitemap.xml\n`;\n await writeFile(join(distDir, 'robots.txt'), content, 'utf-8');\n}\n\n/**\n * Generate sitemap.xml from collected URLs\n */\nexport async function generateSitemap(urls: string[], siteUrl: string, distDir: string): Promise<void> {\n // Sort URLs for deterministic output\n const sortedUrls = [...urls].sort();\n\n const urlEntries = sortedUrls\n .map(url => ` <url><loc>${siteUrl}${url}</loc></url>`)\n .join('\\n');\n\n const content = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${urlEntries}\n</urlset>\n`;\n await writeFile(join(distDir, 'sitemap.xml'), content, 'utf-8');\n}\n\n/**\n * Clean dist directory, keeping only production files\n */\nfunction cleanDist(): void {\n const distDir = projectPaths.dist();\n if (!existsSync(distDir)) {\n mkdirSync(distDir, { recursive: true });\n return;\n }\n\n const files = readdirSync(distDir);\n let cleaned = 0;\n\n for (const file of files) {\n // Keep fonts, images, icons, and assets\n if (\n file === \"fonts\" ||\n file === \"images\" ||\n file === \"icons\" ||\n file === \"assets\"\n ) {\n continue;\n }\n\n // Remove everything else (editor files, old HTML, etc.)\n try {\n const filePath = join(distDir, file);\n const stat = statSync(filePath);\n\n if (stat.isDirectory()) {\n rmSync(filePath, { recursive: true, force: true });\n } else {\n rmSync(filePath, { force: true });\n }\n cleaned++;\n } catch (error) {\n console.warn(`\u26A0\uFE0F Could not remove ${file}:`, error);\n }\n }\n\n if (cleaned > 0) {\n console.log(`\uD83E\uDDF9 Cleaned ${cleaned} file(s) from dist\\n`);\n }\n}\n\n/**\n * Check if a page is a CMS template\n */\nexport function isCMSPage(pageData: JSONPage): boolean {\n return pageData.meta?.source === 'cms' && !!pageData.meta?.cms;\n}\n\n/**\n * Build URL path for a CMS item based on the URL pattern\n * Uses schema.slugField to get the slug value, supporting i18n slugs\n */\nexport function buildCMSItemPath(\n urlPattern: string,\n item: CMSItem,\n slugField: string,\n locale: string,\n i18nConfig: I18nConfig\n): string {\n // Get slug from the schema-defined slugField, fall back to _slug or _id\n let slug = item[slugField] ?? item._slug ?? item._id;\n\n // Resolve i18n slug to locale-specific value\n if (isI18nValue(slug)) {\n slug = resolveI18nValue(slug, locale, i18nConfig) as string;\n }\n\n return urlPattern.replace('{{slug}}', String(slug));\n}\n\n/**\n * Generate static JSON data files for collections with 'static' strategy\n * Output: /data/{collection}/index.json\n */\nasync function generateStaticDataFiles(\n staticCollections: Map<string, ClientDataCollection>,\n distDir: string\n): Promise<void> {\n if (staticCollections.size === 0) return;\n\n console.log(`\\n\uD83D\uDCE6 Generating static data files...`);\n\n for (const [collectionId, data] of staticCollections) {\n const dataDir = join(distDir, 'data', collectionId);\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n const jsonPath = join(dataDir, 'index.json');\n await writeFile(jsonPath, JSON.stringify(data.items), 'utf-8');\n console.log(` \u2705 /data/${collectionId}/index.json (${data.items.length} items)`);\n }\n}\n\n/**\n * Build CMS templates from root templates/ directory\n */\nasync function buildCMSTemplates(\n templatesDir: string,\n globalComponents: Record<string, ComponentDefinition>,\n i18nConfig: I18nConfig,\n slugMappings: SlugMap[],\n distDir: string,\n cmsService: CMSService,\n generatedUrls: Set<string>,\n staticCollections: Map<string, ClientDataCollection>,\n siteUrl?: string,\n abTrackingScript?: string | null\n): Promise<{ success: number; errors: number }> {\n let successCount = 0;\n let errorCount = 0;\n\n if (!existsSync(templatesDir)) {\n return { success: 0, errors: 0 };\n }\n\n const templateFiles = readdirSync(templatesDir).filter(f => f.endsWith('.json'));\n\n if (templateFiles.length === 0) {\n return { success: 0, errors: 0 };\n }\n\n console.log(`\\n\uD83D\uDCDD Processing ${templateFiles.length} CMS template(s)...\\n`);\n\n for (const file of templateFiles) {\n const templateContent = await loadJSONFile(join(templatesDir, file));\n if (!templateContent) continue;\n\n try {\n const pageData = parseJSON<JSONPage>(templateContent);\n\n // Skip draft templates in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft template: ${file}`);\n continue;\n }\n\n if (!isCMSPage(pageData)) {\n console.warn(`\u26A0\uFE0F ${file} is in templates/ but missing meta.source: \"cms\"`);\n continue;\n }\n\n const cmsSchema = pageData.meta!.cms as CMSSchema;\n console.log(`\uD83D\uDCDD CMS Collection: ${cmsSchema.id}`);\n\n // Use shared cmsService to get items\n const items = await cmsService.queryItems({ collection: cmsSchema.id });\n\n if (items.length === 0) {\n console.log(` \u26A0\uFE0F No items found in cms/${cmsSchema.id}/`);\n continue;\n }\n\n console.log(` Found ${items.length} item(s)`);\n\n // Prepare client data if clientData is enabled\n // Filter out fully-draft items from client data (client data is locale-agnostic)\n let clientDataCollections: Map<string, ClientDataCollection> | undefined;\n if (cmsSchema.clientData?.enabled) {\n const publishedItems = items.filter(item => isItemFullyPublished(item));\n const clientData = prepareClientData(cmsSchema.id, publishedItems, cmsSchema.clientData);\n if (clientData) {\n if (clientData.strategy === 'inline') {\n // Inline data embedded in HTML\n clientDataCollections = new Map([[cmsSchema.id, clientData]]);\n console.log(` \uD83D\uDCE6 Client data (inline): ${clientData.items.length} items (${clientData.config.fields?.length || 'all'} fields)`);\n } else if (clientData.strategy === 'static') {\n // Static data written to separate file\n staticCollections.set(cmsSchema.id, clientData);\n console.log(` \uD83D\uDCE6 Client data (static): ${clientData.items.length} items \u2192 /data/${cmsSchema.id}/index.json`);\n }\n }\n }\n\n for (const item of items) {\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n\n // Skip draft items per locale in production builds\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (!isDevBuild && isItemDraftForLocale(item, locale)) {\n console.log(` \u23ED\uFE0F Skipping draft: ${item._filename || item._id} [${locale}]`);\n continue;\n }\n\n const baseUrl = siteUrl || \"\";\n const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);\n\n // Create CMS item with computed _url for {{cms._url}} template access\n const itemWithUrl: CMSItem = { ...item, _url: itemPath };\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: itemPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsContext: { cms: itemWithUrl },\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n clientDataCollections,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (abTrackingScript) {\n finalHtml = injectTrackingScript(finalHtml, abTrackingScript);\n }\n\n const outputPath = locale === i18nConfig.defaultLocale\n ? `${distDir}${itemPath}.html`\n : `${distDir}/${locale}${itemPath}.html`;\n\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/'));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n await writeFile(outputPath, finalHtml, 'utf-8');\n\n const displayPath = locale === i18nConfig.defaultLocale ? itemPath : `/${locale}${itemPath}`;\n generatedUrls.add(displayPath);\n console.log(` \u2705 ${displayPath}`);\n successCount++;\n }\n }\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error processing ${file}:`, error);\n buildErrors.push({\n file: `templates/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'cms',\n });\n errorCount++;\n }\n }\n\n return { success: successCount, errors: errorCount };\n}\n\n/**\n * Load running experiments from experiments.json\n */\nasync function loadRunningExperiments(): Promise<Experiment[]> {\n const experimentsPath = join(projectPaths.project, 'experiments.json');\n if (!existsSync(experimentsPath)) return [];\n\n try {\n const content = await readFile(experimentsPath, 'utf-8');\n const data = JSON.parse(content);\n const experiments: Experiment[] = data.experiments || [];\n return experiments.filter(e => e.status === 'running');\n } catch {\n return [];\n }\n}\n\n/**\n * Inject A/B tracking script into HTML before </head>\n */\nexport function injectTrackingScript(html: string, trackingJs: string): string {\n const scriptTag = `<script>${trackingJs}</script>`;\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n}\n\n/**\n * Generate A/B testing Cloudflare Functions into dist/functions/\n */\nasync function generateABFunctions(experiments: Experiment[], distDir: string): Promise<void> {\n // Generate middleware\n const middlewareContent = generateMiddleware(experiments);\n if (middlewareContent) {\n const middlewarePath = join(distDir, 'functions', '_middleware.ts');\n const middlewareDir = join(distDir, 'functions');\n if (!existsSync(middlewareDir)) {\n mkdirSync(middlewareDir, { recursive: true });\n }\n await writeFile(middlewarePath, middlewareContent, 'utf-8');\n }\n\n // Generate tracking endpoint\n const trackContent = generateTrackFunction();\n const trackDir = join(distDir, 'functions', 'api');\n if (!existsSync(trackDir)) {\n mkdirSync(trackDir, { recursive: true });\n }\n await writeFile(join(trackDir, 'ab-track.ts'), trackContent, 'utf-8');\n\n // Generate results endpoint\n const resultsContent = generateResultsFunction();\n await writeFile(join(trackDir, 'ab-results.ts'), resultsContent, 'utf-8');\n}\n\n/**\n * Main build function\n */\nexport async function buildStaticPages(): Promise<void> {\n console.log(\"\uD83C\uDFD7\uFE0F Building static HTML files...\\n\");\n\n // Clear previous build errors and JS validation cache\n buildErrors.length = 0;\n clearJSValidationCache();\n\n // Reset configService to ensure it loads from the correct project directory\n const { configService } = await import(\"./lib/server/services/configService\");\n configService.reset();\n\n // Load project config first\n const projectConfig = await loadProjectConfig();\n const siteUrl = (projectConfig as { siteUrl?: string }).siteUrl?.replace(/\\/$/, ''); // Remove trailing slash\n\n // Track all generated URLs for sitemap\n const generatedUrls = new Set<string>();\n\n // Load running A/B experiments (if any)\n const runningExperiments = await loadRunningExperiments();\n let trackingScript: string | null = null;\n if (runningExperiments.length > 0) {\n const exp = runningExperiments[0]; // Use first running experiment\n trackingScript = generateTrackingScript(exp.id, exp.conversionGoals);\n console.log(`\uD83E\uDDEA A/B experiment active: \"${exp.name}\" (${exp.variants.length} variant(s))\\n`);\n }\n\n // Load i18n config for multi-locale build\n const i18nConfig = await loadI18nConfig();\n console.log(`\uD83C\uDF10 Locales: ${i18nConfig.locales.map(l => l.code).join(\", \")} (default: ${i18nConfig.defaultLocale})\\n`);\n\n // Auto-migrate pages/templates/ \u2192 templates/ if needed\n await migrateTemplatesDirectory();\n\n // Clean dist directory (removes editor files, old HTML)\n cleanDist();\n\n // Clear the JS file cache since cleanDist() removed _scripts/\n // Without this, cached entries would skip file creation on subsequent builds\n jsFileCache.clear();\n\n // Copy fonts, images, icons, and functions directories to dist\n console.log(\"\uD83D\uDCE6 Copying assets...\");\n const distDir = projectPaths.dist();\n\n // Delete old _errors.json if it exists (start fresh)\n const errorsPath = join(distDir, '_errors.json');\n if (existsSync(errorsPath)) {\n unlinkSync(errorsPath);\n }\n copyDirectory(projectPaths.fonts(), join(distDir, \"fonts\"));\n copyDirectory(projectPaths.images(), join(distDir, \"images\"));\n copyDirectory(projectPaths.icons(), join(distDir, \"icons\"));\n copyDirectory(projectPaths.assets(), join(distDir, \"assets\"));\n\n // Copy libraries folder (downloaded external JS/CSS files)\n const librariesDir = join(projectPaths.project, \"libraries\");\n if (existsSync(librariesDir)) {\n copyDirectory(librariesDir, join(distDir, \"libraries\"));\n }\n\n // Copy functions folder for Cloudflare Pages\n const functionsDir = projectPaths.functions();\n if (existsSync(functionsDir)) {\n copyDirectory(functionsDir, join(distDir, \"functions\"));\n }\n\n // Copy user-created root files for static hosting\n const hostingFiles: string[] = [];\n const rootFilesToCopy = [\n '_headers', // Netlify/Cloudflare headers\n '_redirects', // Netlify/Cloudflare redirects\n 'llms.txt', // LLM context\n 'humans.txt', // Team credits\n 'ads.txt', // Ad verification\n 'security.txt', // Security contact\n 'CNAME', // GitHub Pages domain\n 'manifest.json', // PWA manifest\n 'site.webmanifest', // PWA manifest (alt)\n ];\n\n for (const file of rootFilesToCopy) {\n const filePath = join(projectPaths.project, file);\n if (existsSync(filePath)) {\n copyFileSync(filePath, join(distDir, file));\n hostingFiles.push(file);\n }\n }\n\n // Copy .well-known directory if exists\n const wellKnownDir = join(projectPaths.project, '.well-known');\n if (existsSync(wellKnownDir)) {\n copyDirectory(wellKnownDir, join(distDir, '.well-known'));\n hostingFiles.push('.well-known/');\n }\n\n const parts = ['Assets'];\n if (existsSync(functionsDir)) parts.push('functions');\n if (hostingFiles.length > 0) parts.push(hostingFiles.join(', '));\n console.log(`\u2705 ${parts.join(', ')} copied\\n`);\n\n // Load all global components\n const { components, warnings, errors } = await loadComponentDirectory(projectPaths.components());\n const globalComponents: Record<string, ComponentDefinition> = {};\n components.forEach((value, key) => {\n globalComponents[key] = value;\n });\n\n for (const warning of warnings) console.warn(`\u26A0\uFE0F ${warning}`);\n for (const error of errors) console.error(`\u274C ${error}`);\n console.log(`\u2705 Loaded ${components.size} global component(s)\\n`);\n\n // Initialize CMS service for CMSList rendering\n const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());\n const cmsService = new CMSService(cmsProvider);\n await cmsService.initialize();\n console.log(`\u2705 CMS service initialized\\n`);\n\n // Load all pages\n const pagesDir = projectPaths.pages();\n if (!existsSync(pagesDir)) {\n console.error(\"\u274C Pages directory not found!\");\n process.exit(1);\n }\n\n // Recursively collect all .json page files (supports nested folders like pages/a/b.json)\n const pageFiles: string[] = [];\n function scanPagesDir(dir: string, prefix: string): void {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.json')) {\n pageFiles.push(prefix ? `${prefix}/${entry.name}` : entry.name);\n } else if (entry.isDirectory()) {\n scanPagesDir(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);\n }\n }\n }\n scanPagesDir(pagesDir, '');\n \n if (pageFiles.length === 0) {\n console.warn(\"\u26A0\uFE0F No pages found in ./pages directory\");\n return;\n }\n\n console.log(`\uD83D\uDCC4 Found ${pageFiles.length} page(s) to build\\n`);\n\n // First pass: collect all slug mappings and page-level libraries\n const slugMappings: SlugMap[] = [];\n const allPageLibraries: LibrariesConfig[] = [];\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n if (pageContent) {\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n if (pageData.meta?.slugs) {\n const pageId = basePath === '/' ? 'index' : basePath.substring(1);\n slugMappings.push({ pageId, slugs: pageData.meta.slugs });\n }\n if (pageData.meta?.libraries) {\n allPageLibraries.push(pageData.meta.libraries as LibrariesConfig);\n }\n } catch { /* ignore parse errors in first pass */ }\n }\n }\n\n // Generate _headers from CSP config, auto-including library CDN domains\n // Always regenerate when CSP config exists \u2014 overwrites any stale _headers file\n // that may have been copied from the project root\n {\n await configService.load();\n const cspConfig = configService.getCSP();\n if (cspConfig && Object.keys(cspConfig).length > 0) {\n // Collect all library sources: global + component + page-level\n // Note: we concatenate (not mergeLibraries) because _headers applies globally \u2014\n // we need the union of ALL origins, regardless of per-page merge modes\n const globalLibraries = configService.getLibraries();\n const componentLibraries = collectComponentLibraries(globalComponents);\n const allJs = [\n ...(globalLibraries.js || []),\n ...(componentLibraries.js || []),\n ...allPageLibraries.flatMap(p => p.js || []),\n ];\n const allCss = [\n ...(globalLibraries.css || []),\n ...(componentLibraries.css || []),\n ...allPageLibraries.flatMap(p => p.css || []),\n ];\n const allLibs: LibrariesConfig = { js: allJs, css: allCss };\n\n // Filter out CSS libs disabled for build before extracting CSP origins\n const buildLibs = filterLibrariesByContext(allLibs, 'build');\n\n // Extract CDN origins from all library URLs\n const { scriptOrigins, styleOrigins } = extractLibraryOrigins(buildLibs);\n\n const extraScripts = [\n ...(cspConfig.scriptSrc || []),\n ...Array.from(scriptOrigins),\n ].join(' ');\n const extraStyles = [\n ...(cspConfig.styleSrc || []),\n ...Array.from(styleOrigins),\n ].join(' ');\n const extraConnect = cspConfig.connectSrc?.join(' ') || '';\n const extraFrames = cspConfig.frameSrc?.join(' ') || '';\n const extraFonts = cspConfig.fontSrc?.join(' ') || '';\n const extraImgs = cspConfig.imgSrc?.join(' ') || '';\n\n const cspDirectives = [\n \"default-src 'self'\",\n `script-src 'self' 'unsafe-inline' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),\n `style-src 'self' 'unsafe-inline' https://f.vimeocdn.com ${extraStyles}`.trim(),\n `img-src 'self' data: https: ${extraImgs}`.trim(),\n `connect-src 'self' https://vimeo.com https://*.vimeocdn.com ${extraConnect}`.trim(),\n `frame-src https://player.vimeo.com https://vimeo.com https://www.youtube.com https://www.youtube-nocookie.com ${extraFrames}`.trim(),\n `font-src 'self' data: ${extraFonts}`.trim(),\n \"media-src 'self' https: blob:\"\n ].join('; ');\n\n const headersContent = `/*\\n Content-Security-Policy: ${cspDirectives}\\n`;\n writeFileSync(join(distDir, '_headers'), headersContent);\n console.log(`\u2705 Generated _headers with CSP (auto-included ${scriptOrigins.size + styleOrigins.size} library origin(s))\\n`);\n }\n }\n\n let successCount = 0;\n let errorCount = 0;\n\n // Build each page for each locale\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n\n if (!pageContent) {\n console.warn(`\u26A0\uFE0F Skipping ${basePath} (empty file)`);\n errorCount++;\n continue;\n }\n\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n\n // Skip draft pages in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft: ${basePath}`);\n continue;\n }\n\n // Get translated slugs from page meta (if available)\n const slugs = pageData.meta?.slugs;\n\n // Generate HTML for each locale\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n const baseUrl = siteUrl || \"\";\n\n // Build the URL path that will be used for this locale\n const urlPath = getDisplayPath(basePath, locale, i18nConfig.defaultLocale, slugs);\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: urlPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n // Insert script reference before </body>\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (trackingScript) {\n finalHtml = injectTrackingScript(finalHtml, trackingScript);\n }\n\n // Determine locale-specific output path with translated slug\n const outputPath = getLocalizedOutputPath(basePath, locale, i18nConfig.defaultLocale, distDir, slugs);\n\n // Ensure directory exists\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf(\"/\"));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Debug: show end of HTML\n if (urlPath === '/') {\n console.log('[DEBUG] Last 500 chars of HTML:', finalHtml.slice(-500));\n }\n\n await writeFile(outputPath, finalHtml, \"utf-8\");\n\n generatedUrls.add(urlPath);\n console.log(`\u2705 Built: ${urlPath} \u2192 ${outputPath}`);\n successCount++;\n }\n\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error building ${basePath}:`, error);\n buildErrors.push({\n file: `pages/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'render',\n });\n errorCount++;\n }\n }\n\n // Build CMS templates from root templates/ directory\n const templatesDir = projectPaths.templates();\n const staticCollections = new Map<string, ClientDataCollection>();\n const cmsResult = await buildCMSTemplates(\n templatesDir,\n globalComponents,\n i18nConfig,\n slugMappings,\n distDir,\n cmsService,\n generatedUrls,\n staticCollections,\n siteUrl,\n trackingScript\n );\n successCount += cmsResult.success;\n errorCount += cmsResult.errors;\n\n // Generate static data files for collections with 'static' strategy\n await generateStaticDataFiles(staticCollections, distDir);\n\n // Generate A/B testing functions if experiments are running\n if (runningExperiments.length > 0) {\n await generateABFunctions(runningExperiments, distDir);\n console.log(`\\n\uD83E\uDDEA A/B testing functions generated (middleware, tracker, results API)`);\n }\n\n // Generate SEO files (robots.txt and sitemap.xml)\n if (siteUrl) {\n await generateRobotsTxt(siteUrl, distDir);\n await generateSitemap([...generatedUrls], siteUrl, distDir);\n console.log(`\\n\uD83D\uDD0D SEO files generated (robots.txt, sitemap.xml)`);\n } else {\n console.warn(`\\n\u26A0\uFE0F Skipping SEO files: siteUrl not configured in project.config.json`);\n }\n\n console.log(\"\\n\" + \"=\".repeat(50));\n console.log(`\u2728 Build complete!`);\n console.log(` \u2705 Success: ${successCount}`);\n if (errorCount > 0) {\n console.log(` \u274C Errors: ${errorCount}`);\n }\n console.log(`\\n\uD83D\uDCE6 Production files in /dist:`);\n console.log(` - *.html (Static pages with vanilla JS)`);\n console.log(` - fonts/ (Custom fonts)`);\n console.log(` - images/ (Image assets)`);\n console.log(` - icons/ (Favicon and icons)`);\n if (staticCollections.size > 0) {\n console.log(` - data/ (CMS collection data for client filtering)`);\n }\n if (existsSync(functionsDir)) {\n console.log(` - functions/ (Cloudflare Pages Functions)`);\n }\n if (runningExperiments.length > 0) {\n console.log(` - A/B testing (middleware + tracking injected)`);\n }\n if (siteUrl) {\n console.log(` - robots.txt, sitemap.xml (SEO)`);\n }\n console.log(` - No React, no client-router \u2713`);\n\n // Collect component JS validation errors\n const jsErrors = getJSValidationErrors();\n for (const { component, error } of jsErrors) {\n buildErrors.push({\n file: `components/${component}`,\n message: error,\n type: 'minify',\n });\n }\n\n // Write build errors to _errors.json for static server overlay\n if (buildErrors.length > 0) {\n // Deduplicate errors by message (same error may occur on multiple pages)\n const seenMessages = new Set<string>();\n const uniqueErrors = buildErrors.filter(err => {\n if (seenMessages.has(err.message)) return false;\n seenMessages.add(err.message);\n return true;\n });\n\n const errorsData: BuildErrorsData = {\n errors: uniqueErrors,\n timestamp: Date.now(),\n };\n await writeFile(errorsPath, JSON.stringify(errorsData, null, 2), 'utf-8');\n const countMsg = uniqueErrors.length === buildErrors.length\n ? `${uniqueErrors.length} error${uniqueErrors.length === 1 ? '' : 's'}`\n : `${uniqueErrors.length} unique error${uniqueErrors.length === 1 ? '' : 's'} (affected ${buildErrors.length} files)`;\n console.log(`\\n\u26A0\uFE0F Build errors written to dist/_errors.json (${countMsg})`);\n }\n}\n\n\n", "/**\n * A/B Testing Functions Generator\n * Generates Cloudflare Pages Functions for traffic splitting and event tracking\n * Only called at build time when experiments are running\n */\n\nimport type { Experiment } from '../../shared/types/experiments';\n\n/**\n * Generate the _middleware.ts content for traffic splitting\n */\nexport function generateMiddleware(experiments: Experiment[]): string {\n const running = experiments.filter(e => e.status === 'running');\n if (running.length === 0) return '';\n\n // Embed experiment config as JSON\n const configJSON = JSON.stringify(running.map(e => ({\n id: e.id,\n controlBranch: e.controlBranch,\n controlWeight: e.controlWeight,\n variants: e.variants.map(v => ({\n branch: v.branch,\n weight: v.weight,\n deployUrl: v.deployUrl,\n })),\n })));\n\n return `/**\n * A/B Testing Traffic Splitting Middleware\n * Auto-generated by Meno build - do not edit manually\n */\n\ninterface Env {\n AB_DB?: D1Database;\n}\n\ninterface ExperimentConfig {\n id: string;\n controlBranch: string;\n controlWeight: number;\n variants: Array<{ branch: string; weight: number; deployUrl: string }>;\n}\n\nconst EXPERIMENTS: ExperimentConfig[] = ${configJSON};\n\nfunction getCookie(request: Request, name: string): string | null {\n const cookieHeader = request.headers.get('Cookie');\n if (!cookieHeader) return null;\n const match = cookieHeader.match(new RegExp('(?:^|;\\\\\\\\s*)' + name + '=([^;]*)'));\n return match ? decodeURIComponent(match[1]) : null;\n}\n\nfunction assignVariant(experiment: ExperimentConfig): string {\n const rand = Math.random() * 100;\n let cumulative = experiment.controlWeight;\n if (rand < cumulative) return 'control';\n for (const variant of experiment.variants) {\n cumulative += variant.weight;\n if (rand < cumulative) return variant.branch;\n }\n return 'control';\n}\n\nexport async function onRequest(context: { request: Request; next: () => Promise<Response>; env: Env }) {\n const url = new URL(context.request.url);\n\n // Skip API routes and static assets\n if (url.pathname.startsWith('/api/') || url.pathname.match(/\\\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/)) {\n return context.next();\n }\n\n // Use first running experiment (single experiment at a time for simplicity)\n const experiment = EXPERIMENTS[0];\n if (!experiment) return context.next();\n\n // Check for existing variant assignment (sticky sessions)\n let variant = getCookie(context.request, 'meno_variant');\n\n // If no cookie, assign a variant\n if (!variant) {\n variant = assignVariant(experiment);\n }\n\n let response: Response;\n\n if (variant === 'control') {\n // Control: serve local assets (pass through)\n response = await context.next();\n } else {\n // Variant: proxy to branch preview deploy\n const variantConfig = experiment.variants.find(v => v.branch === variant);\n if (!variantConfig) {\n response = await context.next();\n } else {\n // Fetch from the variant's deploy URL\n const variantUrl = new URL(url.pathname + url.search, variantConfig.deployUrl);\n try {\n const proxyResponse = await fetch(variantUrl.toString(), {\n method: context.request.method,\n headers: context.request.headers,\n });\n response = new Response(proxyResponse.body, {\n status: proxyResponse.status,\n statusText: proxyResponse.statusText,\n headers: new Headers(proxyResponse.headers),\n });\n } catch {\n // Fallback to control if variant fetch fails\n response = await context.next();\n variant = 'control';\n }\n }\n }\n\n // Set variant cookie (30-day expiry)\n const headers = new Headers(response.headers);\n headers.append(\n 'Set-Cookie',\n \\`meno_variant=\\${encodeURIComponent(variant!)}; Path=/; Max-Age=2592000; SameSite=Lax\\`\n );\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n`;\n}\n\n/**\n * Generate the api/ab-track.ts content for event collection\n */\nexport function generateTrackFunction(): string {\n return `/**\n * A/B Testing Event Tracker\n * Auto-generated by Meno build - do not edit manually\n * POST /api/ab-track - stores pageview/conversion events in D1\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface TrackEvent {\n experimentId: string;\n visitorId: string;\n variant: string;\n eventType: 'pageview' | 'conversion';\n goalId?: string;\n url?: string;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n waitUntil: (promise: Promise<unknown>) => void;\n}\n\nexport async function onRequestPost(context: PagesContext<Env>): Promise<Response> {\n try {\n const body: TrackEvent = await context.request.json();\n\n // Validate required fields\n if (!body.experimentId || !body.visitorId || !body.variant || !body.eventType) {\n return new Response(null, { status: 400 });\n }\n\n // Validate event type\n if (body.eventType !== 'pageview' && body.eventType !== 'conversion') {\n return new Response(null, { status: 400 });\n }\n\n // Insert event into D1\n await context.env.AB_DB.prepare(\n 'INSERT INTO ab_events (experiment_id, visitor_id, variant, event_type, goal_id, url, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)'\n ).bind(\n body.experimentId,\n body.visitorId,\n body.variant,\n body.eventType,\n body.goalId || null,\n body.url || null,\n Date.now()\n ).run();\n\n return new Response(null, { status: 204 });\n } catch {\n return new Response(null, { status: 500 });\n }\n}\n`;\n}\n\n/**\n * Generate the api/ab-results.ts content for results aggregation\n */\nexport function generateResultsFunction(): string {\n return `/**\n * A/B Testing Results API\n * Auto-generated by Meno build - do not edit manually\n * GET /api/ab-results?experiment=<id> - returns aggregated results with significance\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n}\n\ninterface VariantResult {\n variant: string;\n visitors: number;\n conversions: number;\n conversionRate: number;\n lift?: number;\n pValue?: number;\n isSignificant: boolean;\n}\n\n/**\n * Two-proportion z-test for statistical significance\n */\nfunction zTest(\n conversionsA: number, visitorsA: number,\n conversionsB: number, visitorsB: number\n): number {\n if (visitorsA === 0 || visitorsB === 0) return 1;\n\n const pA = conversionsA / visitorsA;\n const pB = conversionsB / visitorsB;\n const pPool = (conversionsA + conversionsB) / (visitorsA + visitorsB);\n\n if (pPool === 0 || pPool === 1) return 1;\n\n const se = Math.sqrt(pPool * (1 - pPool) * (1 / visitorsA + 1 / visitorsB));\n if (se === 0) return 1;\n\n const z = Math.abs(pA - pB) / se;\n\n // Approximate two-tailed p-value using rational approximation\n const t = 1 / (1 + 0.2316419 * z);\n const d = 0.3989422804014327;\n const p = d * Math.exp(-z * z / 2) * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));\n return 2 * p;\n}\n\nexport async function onRequestGet(context: PagesContext<Env>): Promise<Response> {\n const url = new URL(context.request.url);\n const experimentId = url.searchParams.get('experiment');\n\n if (!experimentId) {\n return Response.json({ error: 'Missing experiment parameter' }, { status: 400 });\n }\n\n try {\n // Get unique visitors per variant\n const visitorsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as visitors FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'pageview\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Get conversions per variant\n const conversionsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as conversions FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'conversion\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Build results map\n const visitorMap = new Map<string, number>();\n const conversionMap = new Map<string, number>();\n\n for (const row of (visitorsResult.results || [])) {\n visitorMap.set(row.variant as string, row.visitors as number);\n }\n for (const row of (conversionsResult.results || [])) {\n conversionMap.set(row.variant as string, row.conversions as number);\n }\n\n // Get all variant names\n const allVariants = new Set([...visitorMap.keys(), ...conversionMap.keys()]);\n\n // Calculate results\n const variants: VariantResult[] = [];\n let controlVisitors = 0;\n let controlConversions = 0;\n\n for (const variant of allVariants) {\n const visitors = visitorMap.get(variant) || 0;\n const conversions = conversionMap.get(variant) || 0;\n const conversionRate = visitors > 0 ? conversions / visitors : 0;\n\n if (variant === 'control') {\n controlVisitors = visitors;\n controlConversions = conversions;\n }\n\n variants.push({\n variant,\n visitors,\n conversions,\n conversionRate,\n isSignificant: false,\n });\n }\n\n // Calculate lift and significance for non-control variants\n const controlRate = controlVisitors > 0 ? controlConversions / controlVisitors : 0;\n for (const result of variants) {\n if (result.variant !== 'control' && controlVisitors > 0) {\n result.lift = controlRate > 0\n ? ((result.conversionRate - controlRate) / controlRate) * 100\n : 0;\n result.pValue = zTest(\n controlConversions, controlVisitors,\n result.conversions, result.visitors\n );\n result.isSignificant = result.pValue < 0.05;\n }\n }\n\n // Sort: control first, then by variant name\n variants.sort((a, b) => {\n if (a.variant === 'control') return -1;\n if (b.variant === 'control') return 1;\n return a.variant.localeCompare(b.variant);\n });\n\n return Response.json({\n experimentId,\n variants,\n }, {\n headers: {\n 'Access-Control-Allow-Origin': '*',\n 'Cache-Control': 'no-cache',\n }\n });\n } catch (error) {\n return Response.json({ error: 'Failed to query results' }, { status: 500 });\n }\n}\n`;\n}\n", "/**\n * A/B Testing Tracking Script Generator\n * Generates a lightweight client-side tracking script to be injected into HTML\n */\n\nimport type { ConversionGoal } from '../../shared/types/experiments';\n\n/**\n * Generate the tracking script content with embedded experiment config\n */\nexport function generateTrackingScript(experimentId: string, goals: ConversionGoal[]): string {\n const goalsJSON = JSON.stringify(goals);\n\n return `(function(){\nvar EXP_ID=${JSON.stringify(experimentId)};\nvar GOALS=${goalsJSON};\n\nfunction getCookie(n){var m=document.cookie.match(new RegExp('(?:^|;\\\\\\\\s*)'+n+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}\nfunction setCookie(n,v,d){var e=new Date();e.setTime(e.getTime()+d*864e5);document.cookie=n+'='+encodeURIComponent(v)+';path=/;expires='+e.toUTCString()+';SameSite=Lax'}\n\nvar variant=getCookie('meno_variant')||'control';\nvar visitor=getCookie('meno_visitor');\nif(!visitor){visitor=Math.random().toString(36).slice(2)+Date.now().toString(36);setCookie('meno_visitor',visitor,365)}\n\nfunction track(type,goalId){\ntry{navigator.sendBeacon('/api/ab-track',JSON.stringify({experimentId:EXP_ID,visitorId:visitor,variant:variant,eventType:type,goalId:goalId||null,url:location.pathname}))}catch(e){}\n}\n\ntrack('pageview');\n\nGOALS.forEach(function(g){\nif(g.type==='click'&&g.selector){\ndocument.addEventListener('click',function(e){\nif(e.target&&e.target.closest&&e.target.closest(g.selector)){track('conversion',g.id)}\n})\n}\nif(g.type==='navigation'&&g.url){\nif(location.pathname===g.url||location.href.indexOf(g.url)>-1){track('conversion',g.id)}\n}\nif(g.type==='custom'&&g.event){\nwindow.addEventListener(g.event,function(){track('conversion',g.id)})\n}\n});\n})();`;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["minifyJS", "isDevBuild"]
|
|
7
|
-
}
|