heliumts 0.6.3 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/helium.js +6 -3
- package/dist/bin/helium.js.map +1 -1
- package/dist/client/Router.d.ts.map +1 -1
- package/dist/client/Router.js +75 -0
- package/dist/client/Router.js.map +1 -1
- package/dist/server/defineSEOMetadata.d.ts +23 -0
- package/dist/server/defineSEOMetadata.d.ts.map +1 -0
- package/dist/server/defineSEOMetadata.js +20 -0
- package/dist/server/defineSEOMetadata.js.map +1 -0
- package/dist/server/devServer.d.ts +2 -1
- package/dist/server/devServer.d.ts.map +1 -1
- package/dist/server/devServer.js +135 -1
- package/dist/server/devServer.js.map +1 -1
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/meta.d.ts +16 -0
- package/dist/server/meta.d.ts.map +1 -0
- package/dist/server/meta.js +69 -0
- package/dist/server/meta.js.map +1 -0
- package/dist/server/prodServer.d.ts +2 -1
- package/dist/server/prodServer.d.ts.map +1 -1
- package/dist/server/prodServer.js +56 -2
- package/dist/server/prodServer.js.map +1 -1
- package/dist/server/requestRouting.d.ts +4 -0
- package/dist/server/requestRouting.d.ts.map +1 -0
- package/dist/server/requestRouting.js +67 -0
- package/dist/server/requestRouting.js.map +1 -0
- package/dist/server/seoMetadataRouter.d.ts +22 -0
- package/dist/server/seoMetadataRouter.d.ts.map +1 -0
- package/dist/server/seoMetadataRouter.js +134 -0
- package/dist/server/seoMetadataRouter.js.map +1 -0
- package/dist/vite/heliumPlugin.d.ts.map +1 -1
- package/dist/vite/heliumPlugin.js +14 -5
- package/dist/vite/heliumPlugin.js.map +1 -1
- package/dist/vite/scanner.d.ts +6 -0
- package/dist/vite/scanner.d.ts.map +1 -1
- package/dist/vite/scanner.js +42 -2
- package/dist/vite/scanner.js.map +1 -1
- package/dist/vite/virtualServerModule.d.ts +2 -2
- package/dist/vite/virtualServerModule.d.ts.map +1 -1
- package/dist/vite/virtualServerModule.js +10 -1
- package/dist/vite/virtualServerModule.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/helium.js
CHANGED
|
@@ -6,7 +6,7 @@ import fs from "fs";
|
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { build as viteBuild } from "vite";
|
|
8
8
|
import { log } from "../utils/logger.js";
|
|
9
|
-
import { scanServerExports } from "../vite/scanner.js";
|
|
9
|
+
import { scanPageRoutePatterns, scanServerExports } from "../vite/scanner.js";
|
|
10
10
|
import { generateStaticPages } from "../vite/ssg.js";
|
|
11
11
|
import { generateServerManifest } from "../vite/virtualServerModule.js";
|
|
12
12
|
const cli = cac("helium");
|
|
@@ -78,7 +78,8 @@ cli.command("build", "Build for production").action(async () => {
|
|
|
78
78
|
log("info", "Building server...");
|
|
79
79
|
// Generate server entry
|
|
80
80
|
const serverExports = scanServerExports(root);
|
|
81
|
-
const
|
|
81
|
+
const pageRoutePatterns = scanPageRoutePatterns(root);
|
|
82
|
+
const manifestCode = generateServerManifest(serverExports.methods, serverExports.httpHandlers, serverExports.seoMetadata, pageRoutePatterns, serverExports.middleware, serverExports.workers);
|
|
82
83
|
// Create the main server module that will be imported after env is loaded
|
|
83
84
|
const serverModuleCode = `
|
|
84
85
|
import { startProdServer, loadConfig } from 'heliumts/server';
|
|
@@ -89,9 +90,11 @@ export async function start() {
|
|
|
89
90
|
|
|
90
91
|
startProdServer({
|
|
91
92
|
config,
|
|
92
|
-
registerHandlers: (registry, httpRouter) => {
|
|
93
|
+
registerHandlers: (registry, httpRouter, seoRouter) => {
|
|
93
94
|
registerAll(registry);
|
|
94
95
|
httpRouter.registerRoutes(httpHandlers);
|
|
96
|
+
seoRouter.registerRoutes(seoMetadataHandlers);
|
|
97
|
+
seoRouter.setPageRoutePatterns(pageRoutePatterns);
|
|
95
98
|
if (middlewareHandler) {
|
|
96
99
|
registry.setMiddleware(middlewareHandler);
|
|
97
100
|
httpRouter.setMiddleware(middlewareHandler);
|
package/dist/bin/helium.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helium.js","sourceRoot":"","sources":["../../src/bin/helium.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { cac } from \"cac\";\nimport { spawn } from \"child_process\";\nimport { build as esbuild } from \"esbuild\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { build as viteBuild } from \"vite\";\n\nimport { log } from \"../utils/logger.js\";\nimport { scanServerExports } from \"../vite/scanner.js\";\nimport { generateStaticPages } from \"../vite/ssg.js\";\nimport { generateServerManifest } from \"../vite/virtualServerModule.js\";\n\nconst cli = cac(\"helium\");\nconst root = process.cwd();\n\ncli.command(\"dev\", \"Start development server\").action(async () => {\n const vite = spawn(\"vite\", [], { stdio: \"inherit\", shell: true });\n vite.on(\"close\", (code) => {\n process.exit(code || 0);\n });\n});\n\ncli.command(\"build\", \"Build for production\").action(async () => {\n log(\"info\", \"--------------------------------\");\n log(\"info\", \"Building client...\");\n\n try {\n const result = await viteBuild({\n root,\n logLevel: \"silent\",\n build: {\n outDir: \"dist\",\n },\n });\n\n // Display build output\n if (result && \"output\" in result) {\n const outputs = result.output;\n const zlib = await import(\"zlib\");\n\n for (const chunk of outputs) {\n if (chunk.type === \"asset\" || chunk.type === \"chunk\") {\n const fileName = chunk.fileName;\n const content = \"code\" in chunk ? chunk.code : chunk.source;\n const size = Buffer.byteLength(content, \"utf-8\");\n const sizeKB = (size / 1024).toFixed(2);\n\n // Calculate gzipped size\n const gzipped = zlib.gzipSync(content);\n const gzipSizeKB = (gzipped.length / 1024).toFixed(2);\n\n log(\"info\", ` ${fileName.padEnd(35)} ${sizeKB.padStart(8)} kB │ gzip: ${gzipSizeKB.padStart(7)} kB`);\n }\n }\n }\n\n log(\"info\", \"Client build complete.\");\n\n // Generate static pages for SSG\n log(\"info\", \"--------------------------------\");\n try {\n // Read the generated index.html as a template for SSG\n const distDir = path.join(root, \"dist\");\n const htmlPath = path.join(distDir, \"index.html\");\n\n if (fs.existsSync(htmlPath)) {\n let htmlTemplate = fs.readFileSync(htmlPath, \"utf-8\");\n\n // Clean up the template for SSG:\n // 1. Remove the build-time HELIUM_CONNECTION_TOKEN (SSG pages don't need it)\n htmlTemplate = htmlTemplate.replace(/<script>window\\.HELIUM_CONNECTION_TOKEN = \"build-time-placeholder\";<\\/script>/g, \"\");\n\n // 2. Clear any existing content in root div from SPA build\n htmlTemplate = htmlTemplate.replace(/<div\\s+id=\"root\"[^>]*>.*?<\\/div>/s, '<div id=\"root\"></div>');\n\n await generateStaticPages(null, root, htmlTemplate, distDir);\n } else {\n log(\"warn\", \"index.html not found in dist, skipping SSG\");\n }\n } catch (e) {\n log(\"warn\", \"SSG generation failed:\", e);\n // Don't fail the build if SSG fails\n }\n log(\"info\", \"--------------------------------\");\n } catch (e) {\n log(\"error\", \"Client build failed:\", e);\n process.exit(1);\n }\n\n log(\"info\", \"Building server...\");\n // Generate server entry\n const serverExports = scanServerExports(root);\n const manifestCode = generateServerManifest(serverExports.methods, serverExports.httpHandlers, serverExports.middleware, serverExports.workers);\n\n // Create the main server module that will be imported after env is loaded\n const serverModuleCode = `\nimport { startProdServer, loadConfig } from 'heliumts/server';\n${manifestCode}\n\nexport async function start() {\n const config = await loadConfig();\n\n startProdServer({\n config,\n registerHandlers: (registry, httpRouter) => {\n registerAll(registry);\n httpRouter.registerRoutes(httpHandlers);\n if (middlewareHandler) {\n registry.setMiddleware(middlewareHandler);\n httpRouter.setMiddleware(middlewareHandler);\n }\n },\n workers\n });\n}\n`;\n\n // Create the entry loader that loads env first, then imports the server module\n const entryCode = `\n// Load environment variables FIRST, before any other imports\nimport './env-loader.js';\n// Now import and start the server (this ensures handlers load after env)\nimport { start } from './server-module.js';\nawait start();\n`;\n\n const envLoaderCode = `\nimport { loadEnvFiles, injectEnvToProcess, log } from 'heliumts/server';\nconst envRoot = process.cwd();\nlog('info', \\`Loading .env files from: \\${envRoot}\\`);\nconst envVars = loadEnvFiles({ mode: 'production' });\ninjectEnvToProcess(envVars);\nif (Object.keys(envVars).length > 0) {\n log('info', \\`Loaded \\${Object.keys(envVars).length} environment variable(s) from .env files\\`);\n} else {\n log('info', 'No .env files found (using platform environment variables if available)');\n}\n`;\n\n const heliumDir = path.join(root, \"node_modules\", \".heliumts\");\n if (!fs.existsSync(heliumDir)) {\n fs.mkdirSync(heliumDir, { recursive: true });\n }\n const entryPath = path.join(heliumDir, \"server-entry.ts\");\n const envLoaderPath = path.join(heliumDir, \"env-loader.ts\");\n const serverModuleSrcPath = path.join(heliumDir, \"server-module.ts\");\n\n fs.writeFileSync(entryPath, entryCode);\n fs.writeFileSync(envLoaderPath, envLoaderCode);\n fs.writeFileSync(serverModuleSrcPath, serverModuleCode);\n\n // Bundle with esbuild\n try {\n await esbuild({\n entryPoints: [entryPath],\n outfile: path.join(root, \"dist\", \"server.js\"),\n bundle: true,\n platform: \"node\",\n format: \"esm\",\n external: [\n // External common database and heavy dependencies\n \"mongodb\",\n \"mongoose\",\n \"pg\",\n \"mysql\",\n \"mysql2\",\n \"sqlite3\",\n \"better-sqlite3\",\n \"redis\",\n // Node.js built-ins are automatically external, but let's be explicit\n \"crypto\",\n \"fs\",\n \"path\",\n \"http\",\n \"https\",\n \"stream\",\n \"zlib\",\n \"util\",\n ],\n target: \"node18\",\n metafile: true,\n banner: {\n js: \"import { createRequire } from 'module'; const require = createRequire(import.meta.url);\",\n },\n });\n\n // Display server build output\n const serverOutputPath = path.relative(root, path.join(root, \"dist\", \"server.js\"));\n const serverStats = fs.statSync(path.join(root, \"dist\", \"server.js\"));\n const serverSizeKB = (serverStats.size / 1024).toFixed(2);\n log(\"info\", ` ${serverOutputPath.padEnd(35)} ${serverSizeKB.padStart(8)} kB`);\n\n log(\"info\", \"Server build complete.\");\n\n // Transpile helium.config.ts to helium.config.js if it exists\n const configTsPath = path.join(root, \"helium.config.ts\");\n if (fs.existsSync(configTsPath)) {\n log(\"info\", \"Transpiling helium.config.ts...\");\n try {\n await esbuild({\n entryPoints: [configTsPath],\n outfile: path.join(root, \"dist\", \"helium.config.js\"),\n bundle: false,\n platform: \"node\",\n format: \"esm\",\n target: \"node18\",\n });\n log(\"info\", \"Config file transpiled to dist/helium.config.js\");\n } catch (e) {\n log(\"warn\", \"Failed to transpile config file:\", e);\n log(\"warn\", \"You may need to manually rename helium.config.ts to helium.config.js\");\n }\n } else {\n // Check if .js or .mjs config exists and copy it to dist\n const configJsPath = path.join(root, \"helium.config.js\");\n const configMjsPath = path.join(root, \"helium.config.mjs\");\n\n if (fs.existsSync(configJsPath)) {\n fs.copyFileSync(configJsPath, path.join(root, \"dist\", \"helium.config.js\"));\n log(\"info\", \"Copied helium.config.js to dist/\");\n } else if (fs.existsSync(configMjsPath)) {\n fs.copyFileSync(configMjsPath, path.join(root, \"dist\", \"helium.config.mjs\"));\n log(\"info\", \"Copied helium.config.mjs to dist/\");\n }\n }\n\n log(\"info\", \"--------------------------------\");\n log(\"info\", \"✓ Build finished successfully.\");\n log(\"info\", \"▶ Run 'helium start' to start the production server.\");\n\n // Exit cleanly after build completes\n process.exit(0);\n } catch (e) {\n log(\"error\", \"Server build failed:\", e);\n process.exit(1);\n }\n});\n\ncli.command(\"start\", \"Start production server\").action(async () => {\n const serverPath = path.join(root, \"dist\", \"server.js\");\n if (!fs.existsSync(serverPath)) {\n log(\"error\", 'Server build not found. Run \"helium build\" first.');\n process.exit(1);\n }\n\n // When running in production, look for config in dist directory first\n // This allows the transpiled config to be found\n const server = spawn(\"node\", [serverPath], {\n stdio: \"inherit\",\n shell: true,\n env: { ...process.env, HELIUM_CONFIG_DIR: path.join(root, \"dist\") },\n });\n server.on(\"close\", (code) => {\n process.exit(code || 0);\n });\n});\n\ncli.help();\ncli.parse();\n"]}
|
|
1
|
+
{"version":3,"file":"helium.js","sourceRoot":"","sources":["../../src/bin/helium.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { cac } from \"cac\";\nimport { spawn } from \"child_process\";\nimport { build as esbuild } from \"esbuild\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { build as viteBuild } from \"vite\";\n\nimport { log } from \"../utils/logger.js\";\nimport { scanPageRoutePatterns, scanServerExports } from \"../vite/scanner.js\";\nimport { generateStaticPages } from \"../vite/ssg.js\";\nimport { generateServerManifest } from \"../vite/virtualServerModule.js\";\n\nconst cli = cac(\"helium\");\nconst root = process.cwd();\n\ncli.command(\"dev\", \"Start development server\").action(async () => {\n const vite = spawn(\"vite\", [], { stdio: \"inherit\", shell: true });\n vite.on(\"close\", (code) => {\n process.exit(code || 0);\n });\n});\n\ncli.command(\"build\", \"Build for production\").action(async () => {\n log(\"info\", \"--------------------------------\");\n log(\"info\", \"Building client...\");\n\n try {\n const result = await viteBuild({\n root,\n logLevel: \"silent\",\n build: {\n outDir: \"dist\",\n },\n });\n\n // Display build output\n if (result && \"output\" in result) {\n const outputs = result.output;\n const zlib = await import(\"zlib\");\n\n for (const chunk of outputs) {\n if (chunk.type === \"asset\" || chunk.type === \"chunk\") {\n const fileName = chunk.fileName;\n const content = \"code\" in chunk ? chunk.code : chunk.source;\n const size = Buffer.byteLength(content, \"utf-8\");\n const sizeKB = (size / 1024).toFixed(2);\n\n // Calculate gzipped size\n const gzipped = zlib.gzipSync(content);\n const gzipSizeKB = (gzipped.length / 1024).toFixed(2);\n\n log(\"info\", ` ${fileName.padEnd(35)} ${sizeKB.padStart(8)} kB │ gzip: ${gzipSizeKB.padStart(7)} kB`);\n }\n }\n }\n\n log(\"info\", \"Client build complete.\");\n\n // Generate static pages for SSG\n log(\"info\", \"--------------------------------\");\n try {\n // Read the generated index.html as a template for SSG\n const distDir = path.join(root, \"dist\");\n const htmlPath = path.join(distDir, \"index.html\");\n\n if (fs.existsSync(htmlPath)) {\n let htmlTemplate = fs.readFileSync(htmlPath, \"utf-8\");\n\n // Clean up the template for SSG:\n // 1. Remove the build-time HELIUM_CONNECTION_TOKEN (SSG pages don't need it)\n htmlTemplate = htmlTemplate.replace(/<script>window\\.HELIUM_CONNECTION_TOKEN = \"build-time-placeholder\";<\\/script>/g, \"\");\n\n // 2. Clear any existing content in root div from SPA build\n htmlTemplate = htmlTemplate.replace(/<div\\s+id=\"root\"[^>]*>.*?<\\/div>/s, '<div id=\"root\"></div>');\n\n await generateStaticPages(null, root, htmlTemplate, distDir);\n } else {\n log(\"warn\", \"index.html not found in dist, skipping SSG\");\n }\n } catch (e) {\n log(\"warn\", \"SSG generation failed:\", e);\n // Don't fail the build if SSG fails\n }\n log(\"info\", \"--------------------------------\");\n } catch (e) {\n log(\"error\", \"Client build failed:\", e);\n process.exit(1);\n }\n\n log(\"info\", \"Building server...\");\n // Generate server entry\n const serverExports = scanServerExports(root);\n const pageRoutePatterns = scanPageRoutePatterns(root);\n const manifestCode = generateServerManifest(\n serverExports.methods,\n serverExports.httpHandlers,\n serverExports.seoMetadata,\n pageRoutePatterns,\n serverExports.middleware,\n serverExports.workers\n );\n\n // Create the main server module that will be imported after env is loaded\n const serverModuleCode = `\nimport { startProdServer, loadConfig } from 'heliumts/server';\n${manifestCode}\n\nexport async function start() {\n const config = await loadConfig();\n\n startProdServer({\n config,\n registerHandlers: (registry, httpRouter, seoRouter) => {\n registerAll(registry);\n httpRouter.registerRoutes(httpHandlers);\n seoRouter.registerRoutes(seoMetadataHandlers);\n seoRouter.setPageRoutePatterns(pageRoutePatterns);\n if (middlewareHandler) {\n registry.setMiddleware(middlewareHandler);\n httpRouter.setMiddleware(middlewareHandler);\n }\n },\n workers\n });\n}\n`;\n\n // Create the entry loader that loads env first, then imports the server module\n const entryCode = `\n// Load environment variables FIRST, before any other imports\nimport './env-loader.js';\n// Now import and start the server (this ensures handlers load after env)\nimport { start } from './server-module.js';\nawait start();\n`;\n\n const envLoaderCode = `\nimport { loadEnvFiles, injectEnvToProcess, log } from 'heliumts/server';\nconst envRoot = process.cwd();\nlog('info', \\`Loading .env files from: \\${envRoot}\\`);\nconst envVars = loadEnvFiles({ mode: 'production' });\ninjectEnvToProcess(envVars);\nif (Object.keys(envVars).length > 0) {\n log('info', \\`Loaded \\${Object.keys(envVars).length} environment variable(s) from .env files\\`);\n} else {\n log('info', 'No .env files found (using platform environment variables if available)');\n}\n`;\n\n const heliumDir = path.join(root, \"node_modules\", \".heliumts\");\n if (!fs.existsSync(heliumDir)) {\n fs.mkdirSync(heliumDir, { recursive: true });\n }\n const entryPath = path.join(heliumDir, \"server-entry.ts\");\n const envLoaderPath = path.join(heliumDir, \"env-loader.ts\");\n const serverModuleSrcPath = path.join(heliumDir, \"server-module.ts\");\n\n fs.writeFileSync(entryPath, entryCode);\n fs.writeFileSync(envLoaderPath, envLoaderCode);\n fs.writeFileSync(serverModuleSrcPath, serverModuleCode);\n\n // Bundle with esbuild\n try {\n await esbuild({\n entryPoints: [entryPath],\n outfile: path.join(root, \"dist\", \"server.js\"),\n bundle: true,\n platform: \"node\",\n format: \"esm\",\n external: [\n // External common database and heavy dependencies\n \"mongodb\",\n \"mongoose\",\n \"pg\",\n \"mysql\",\n \"mysql2\",\n \"sqlite3\",\n \"better-sqlite3\",\n \"redis\",\n // Node.js built-ins are automatically external, but let's be explicit\n \"crypto\",\n \"fs\",\n \"path\",\n \"http\",\n \"https\",\n \"stream\",\n \"zlib\",\n \"util\",\n ],\n target: \"node18\",\n metafile: true,\n banner: {\n js: \"import { createRequire } from 'module'; const require = createRequire(import.meta.url);\",\n },\n });\n\n // Display server build output\n const serverOutputPath = path.relative(root, path.join(root, \"dist\", \"server.js\"));\n const serverStats = fs.statSync(path.join(root, \"dist\", \"server.js\"));\n const serverSizeKB = (serverStats.size / 1024).toFixed(2);\n log(\"info\", ` ${serverOutputPath.padEnd(35)} ${serverSizeKB.padStart(8)} kB`);\n\n log(\"info\", \"Server build complete.\");\n\n // Transpile helium.config.ts to helium.config.js if it exists\n const configTsPath = path.join(root, \"helium.config.ts\");\n if (fs.existsSync(configTsPath)) {\n log(\"info\", \"Transpiling helium.config.ts...\");\n try {\n await esbuild({\n entryPoints: [configTsPath],\n outfile: path.join(root, \"dist\", \"helium.config.js\"),\n bundle: false,\n platform: \"node\",\n format: \"esm\",\n target: \"node18\",\n });\n log(\"info\", \"Config file transpiled to dist/helium.config.js\");\n } catch (e) {\n log(\"warn\", \"Failed to transpile config file:\", e);\n log(\"warn\", \"You may need to manually rename helium.config.ts to helium.config.js\");\n }\n } else {\n // Check if .js or .mjs config exists and copy it to dist\n const configJsPath = path.join(root, \"helium.config.js\");\n const configMjsPath = path.join(root, \"helium.config.mjs\");\n\n if (fs.existsSync(configJsPath)) {\n fs.copyFileSync(configJsPath, path.join(root, \"dist\", \"helium.config.js\"));\n log(\"info\", \"Copied helium.config.js to dist/\");\n } else if (fs.existsSync(configMjsPath)) {\n fs.copyFileSync(configMjsPath, path.join(root, \"dist\", \"helium.config.mjs\"));\n log(\"info\", \"Copied helium.config.mjs to dist/\");\n }\n }\n\n log(\"info\", \"--------------------------------\");\n log(\"info\", \"✓ Build finished successfully.\");\n log(\"info\", \"▶ Run 'helium start' to start the production server.\");\n\n // Exit cleanly after build completes\n process.exit(0);\n } catch (e) {\n log(\"error\", \"Server build failed:\", e);\n process.exit(1);\n }\n});\n\ncli.command(\"start\", \"Start production server\").action(async () => {\n const serverPath = path.join(root, \"dist\", \"server.js\");\n if (!fs.existsSync(serverPath)) {\n log(\"error\", 'Server build not found. Run \"helium build\" first.');\n process.exit(1);\n }\n\n // When running in production, look for config in dist directory first\n // This allows the transpiled config to be found\n const server = spawn(\"node\", [serverPath], {\n stdio: \"inherit\",\n shell: true,\n env: { ...process.env, HELIUM_CONFIG_DIR: path.join(root, \"dist\") },\n });\n server.on(\"close\", (code) => {\n process.exit(code || 0);\n });\n});\n\ncli.help();\ncli.parse();\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAuD,MAAM,OAAO,CAAC;AAO5E,KAAK,WAAW,GAAG,YAAY,GAAG,mBAAmB,CAAC;AACtD,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,KAAK,IAAI,CAAC;AAgKhG,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACpC,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,YAAY,EAAE,eAAe,CAAC;IAC9B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACnE,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,KAAK,MAAM,IAAI,CAAC;IAChE,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,8GAA8G;IAC9G,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,aAAa,qCAAkD,CAAC;AAE7E;;;;;;;;GAQG;AACH,wBAAgB,SAAS,kBAmCxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAe,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,QAyBlF;AA6CD,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,CAC3C,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CACJ,CAAC;AA+BF;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,2CA4DpC;AAGD;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC9F,SAAS,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,SAAS,EAAE,UAAU,CAAC;CACzB,CAAC;AAGF,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAuD,MAAM,OAAO,CAAC;AAO5E,KAAK,WAAW,GAAG,YAAY,GAAG,mBAAmB,CAAC;AACtD,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,KAAK,IAAI,CAAC;AAgKhG,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACpC,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD,KAAK,aAAa,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,YAAY,EAAE,eAAe,CAAC;IAC9B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACnE,EAAE,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,KAAK,MAAM,IAAI,CAAC;IAChE,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,8GAA8G;IAC9G,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,aAAa,qCAAkD,CAAC;AAE7E;;;;;;;;GAQG;AACH,wBAAgB,SAAS,kBAmCxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAe,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,QAyBlF;AA6CD,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,iBAAiB,CAC3C,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CACJ,CAAC;AA+BF;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,2CA4DpC;AAGD;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC9F,SAAS,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACrC,SAAS,EAAE,UAAU,CAAC;CACzB,CAAC;AAGF,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;CAAE,2CAmHlF"}
|
package/dist/client/Router.js
CHANGED
|
@@ -372,6 +372,32 @@ export function AppRouter({ AppShell }) {
|
|
|
372
372
|
isNavigating: state.isNavigating,
|
|
373
373
|
isPending,
|
|
374
374
|
};
|
|
375
|
+
React.useEffect(() => {
|
|
376
|
+
const controller = new AbortController();
|
|
377
|
+
const targetPath = `${state.path}${window.location.search || ""}`;
|
|
378
|
+
const syncMetadata = async () => {
|
|
379
|
+
try {
|
|
380
|
+
const response = await fetch(`/__helium__/seo-metadata?path=${encodeURIComponent(targetPath)}`, {
|
|
381
|
+
method: "GET",
|
|
382
|
+
credentials: "same-origin",
|
|
383
|
+
cache: "no-store",
|
|
384
|
+
signal: controller.signal,
|
|
385
|
+
});
|
|
386
|
+
if (!response.ok) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const payload = (await response.json());
|
|
390
|
+
applyRouteMetadata(payload.meta ?? null);
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
if (error?.name === "AbortError") {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
syncMetadata();
|
|
399
|
+
return () => controller.abort();
|
|
400
|
+
}, [state.path, currentSearchParams.toString()]);
|
|
375
401
|
if (!match) {
|
|
376
402
|
const NotFoundComp = NotFound ?? (() => _jsx("div", { children: "Not found" }));
|
|
377
403
|
const content = _jsx(NotFoundComp, {});
|
|
@@ -395,4 +421,53 @@ export function AppRouter({ AppShell }) {
|
|
|
395
421
|
const finalContent = AppShell ? _jsx(AppShell, { Component: WrappedPage, pageProps: {} }) : _jsx(WrappedPage, {});
|
|
396
422
|
return _jsx(RouterContext.Provider, { value: routerValue, children: finalContent });
|
|
397
423
|
}
|
|
424
|
+
function applyRouteMetadata(meta) {
|
|
425
|
+
if (typeof document === "undefined") {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
const managedNodes = document.head.querySelectorAll('[data-helium-seo="true"]');
|
|
429
|
+
managedNodes.forEach((node) => node.remove());
|
|
430
|
+
if (!meta) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
document.title = meta.title;
|
|
434
|
+
const entries = [];
|
|
435
|
+
entries.push({ tag: "meta", attrs: { property: "og:title", content: meta.title } });
|
|
436
|
+
entries.push({ tag: "meta", attrs: { property: "og:type", content: meta.type ?? "website" } });
|
|
437
|
+
entries.push({ tag: "meta", attrs: { name: "twitter:card", content: meta.twitterCard ?? "summary_large_image" } });
|
|
438
|
+
entries.push({ tag: "meta", attrs: { name: "twitter:title", content: meta.title } });
|
|
439
|
+
if (meta.description) {
|
|
440
|
+
entries.push({ tag: "meta", attrs: { name: "description", content: meta.description } });
|
|
441
|
+
entries.push({ tag: "meta", attrs: { property: "og:description", content: meta.description } });
|
|
442
|
+
entries.push({ tag: "meta", attrs: { name: "twitter:description", content: meta.description } });
|
|
443
|
+
}
|
|
444
|
+
if (meta.image) {
|
|
445
|
+
entries.push({ tag: "meta", attrs: { property: "og:image", content: meta.image } });
|
|
446
|
+
entries.push({ tag: "meta", attrs: { name: "twitter:image", content: meta.image } });
|
|
447
|
+
}
|
|
448
|
+
if (meta.canonicalUrl) {
|
|
449
|
+
entries.push({ tag: "meta", attrs: { property: "og:url", content: meta.canonicalUrl } });
|
|
450
|
+
entries.push({ tag: "link", attrs: { rel: "canonical", href: meta.canonicalUrl } });
|
|
451
|
+
}
|
|
452
|
+
if (meta.siteName) {
|
|
453
|
+
entries.push({ tag: "meta", attrs: { property: "og:site_name", content: meta.siteName } });
|
|
454
|
+
}
|
|
455
|
+
if (meta.robots) {
|
|
456
|
+
entries.push({ tag: "meta", attrs: { name: "robots", content: meta.robots } });
|
|
457
|
+
}
|
|
458
|
+
if (meta.twitterSite) {
|
|
459
|
+
entries.push({ tag: "meta", attrs: { name: "twitter:site", content: meta.twitterSite } });
|
|
460
|
+
}
|
|
461
|
+
if (meta.twitterCreator) {
|
|
462
|
+
entries.push({ tag: "meta", attrs: { name: "twitter:creator", content: meta.twitterCreator } });
|
|
463
|
+
}
|
|
464
|
+
for (const entry of entries) {
|
|
465
|
+
const node = document.createElement(entry.tag);
|
|
466
|
+
for (const [key, value] of Object.entries(entry.attrs)) {
|
|
467
|
+
node.setAttribute(key, value);
|
|
468
|
+
}
|
|
469
|
+
node.setAttribute("data-helium-seo", "true");
|
|
470
|
+
document.head.appendChild(node);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
398
473
|
//# sourceMappingURL=Router.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Router.js","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentType } from \"react\";\nimport React, { useMemo, useSyncExternalStore, useTransition } from \"react\";\n\nimport { isDevEnvironment } from \"./env.js\";\nimport type { RouteEntry } from \"./routerManifest.js\";\nimport { buildRoutes } from \"./routerManifest.js\";\n\n// Event emitter for router events\ntype RouterEvent = \"navigation\" | \"before-navigation\";\ntype EventListener = (event: { from: string; to: string; preventDefault?: () => void }) => void;\n\nclass RouterEventEmitter {\n private listeners: Map<RouterEvent, Set<EventListener>> = new Map();\n\n on(event: RouterEvent, listener: EventListener): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n\n // Return unsubscribe function\n return () => {\n this.listeners.get(event)?.delete(listener);\n };\n }\n\n emit(event: RouterEvent, data: { from: string; to: string }): boolean {\n const eventListeners = this.listeners.get(event);\n if (!eventListeners || eventListeners.size === 0) {\n return true;\n }\n\n let prevented = false;\n const preventDefault = () => {\n prevented = true;\n };\n\n const eventData = event === \"before-navigation\" ? { ...data, preventDefault } : data;\n\n eventListeners.forEach((listener) => {\n listener(eventData);\n });\n\n return !prevented;\n }\n\n // Clear all listeners - useful for HMR\n clear() {\n this.listeners.clear();\n }\n}\n\n// Use a singleton that survives HMR by attaching to window in dev mode\nlet routerEventEmitter: RouterEventEmitter;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n // In dev mode, reuse the same emitter instance across HMR\n const globalWindow = window as typeof window & { __heliumRouterEmitter?: RouterEventEmitter };\n if (!globalWindow.__heliumRouterEmitter) {\n globalWindow.__heliumRouterEmitter = new RouterEventEmitter();\n }\n routerEventEmitter = globalWindow.__heliumRouterEmitter;\n} else {\n routerEventEmitter = new RouterEventEmitter();\n}\n\ntype RouterState = {\n path: string;\n searchParams: URLSearchParams;\n isNavigating: boolean;\n};\n\nfunction getLocation(): RouterState {\n const { pathname, search } = window.location;\n return {\n path: pathname,\n searchParams: new URLSearchParams(search),\n isNavigating: false,\n };\n}\n\nfunction matchRoute(path: string, routes: RouteEntry[]) {\n for (const r of routes) {\n const m = r.matcher(path);\n if (m) {\n return { params: m.params, route: r };\n }\n }\n return null;\n}\n\n// Location store for useSyncExternalStore\n// Preserve across HMR by attaching to window in dev mode\nlet currentLocation: RouterState;\nlet locationListeners: Set<() => void>;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & {\n __heliumCurrentLocation?: RouterState;\n __heliumLocationListeners?: Set<() => void>;\n };\n if (!globalWindow.__heliumCurrentLocation) {\n globalWindow.__heliumCurrentLocation = getLocation();\n }\n if (!globalWindow.__heliumLocationListeners) {\n globalWindow.__heliumLocationListeners = new Set();\n }\n currentLocation = globalWindow.__heliumCurrentLocation;\n locationListeners = globalWindow.__heliumLocationListeners;\n} else if (typeof window !== \"undefined\") {\n currentLocation = getLocation();\n locationListeners = new Set();\n} else {\n currentLocation = { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\n locationListeners = new Set();\n}\n\n// Helper to re-extract params from path using stored routes during HMR\nfunction extractParamsFromPath(path: string): Record<string, string | string[]> {\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n const routes = globalWindow.__heliumGlobalRoutes;\n if (routes && routes.length > 0) {\n const match = matchRoute(path, routes);\n if (match) {\n return match.params;\n }\n }\n }\n return {};\n}\n\nfunction subscribeToLocation(callback: () => void) {\n locationListeners.add(callback);\n return () => locationListeners.delete(callback);\n}\n\nfunction getLocationSnapshot() {\n return currentLocation;\n}\n\nfunction getServerSnapshot() {\n return { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\n}\n\nfunction updateLocation(isNavigating = false) {\n const newLocation = { ...getLocation(), isNavigating };\n currentLocation = newLocation;\n // Update the global reference in dev mode\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n (window as typeof window & { __heliumCurrentLocation?: RouterState }).__heliumCurrentLocation = newLocation;\n }\n locationListeners.forEach((listener) => listener());\n}\n\n// Set up global listeners once\nif (typeof window !== \"undefined\") {\n // Only set up once, survives HMR\n const globalWindow = window as typeof window & { __heliumLocationListenerSetup?: boolean };\n if (!globalWindow.__heliumLocationListenerSetup) {\n globalWindow.__heliumLocationListenerSetup = true;\n\n window.addEventListener(\"popstate\", () => updateLocation(false));\n\n // Also listen to navigation events from the emitter\n routerEventEmitter.on(\"navigation\", () => updateLocation(false));\n }\n}\n\n/** Options for push/replace navigation methods */\nexport interface RouterNavigationOptions {\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n}\n\n// Context for useRouter hook\ntype RouterContext = {\n path: string;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n push: (href: string, options?: RouterNavigationOptions) => void;\n replace: (href: string, options?: RouterNavigationOptions) => void;\n on: (event: RouterEvent, listener: EventListener) => () => void;\n status: 200 | 404;\n isNavigating: boolean;\n /** Indicates content is stale (old content shown while new content renders) - React 18+ concurrent feature */\n isPending: boolean;\n};\n\nexport const RouterContext = React.createContext<RouterContext | null>(null);\n\n/**\n * Access router context inside a component tree managed by <AppRouter />.\n *\n * Provides current path, route params, URL search params and navigation helpers\n * (\\`push\\`, \\`replace\\`) as well as an \\`on\\` method to subscribe to navigation events.\n * The \\`isNavigating\\` property indicates when a navigation is in progress.\n * The \\`isPending\\` property indicates when content is stale (React concurrent features).\n * Throws when used outside of an <AppRouter /> provider.\n */\nexport function useRouter() {\n const ctx = React.useContext(RouterContext);\n if (!ctx) {\n // During HMR in development, context might be temporarily unavailable\n // Provide a temporary fallback to prevent white screen of death\n // Re-extract params from current path using stored routes\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const currentPath = window.location.pathname;\n return {\n path: currentPath,\n params: extractParamsFromPath(currentPath),\n searchParams: new URLSearchParams(window.location.search),\n push: (href: string, options?: RouterNavigationOptions) => {\n window.history.pushState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n replace: (href: string, options?: RouterNavigationOptions) => {\n window.history.replaceState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n on: () => () => {},\n status: 200 as const,\n isNavigating: false,\n isPending: false,\n };\n }\n throw new Error(\"useRouter must be used inside <AppRouter>\");\n }\n return ctx;\n}\n\n/**\n * Redirect component for declarative navigation.\n * Use this instead of calling router.push() during render.\n *\n * @example\n * \\`\\`\\`tsx\n * export default function Docs() {\n * return <Redirect to=\"/docs/getting-started\" />;\n * }\n * \\`\\`\\`\n */\nexport function Redirect({ to, replace = false }: { to: string; replace?: boolean }) {\n const hasRedirected = React.useRef(false);\n\n // Use useLayoutEffect to redirect before paint\n React.useLayoutEffect(() => {\n const targetPath = to.split(\"?\")[0];\n if (!hasRedirected.current && window.location.pathname !== targetPath) {\n hasRedirected.current = true;\n\n // Perform navigation\n if (replace) {\n window.history.replaceState(null, \"\", to);\n } else {\n window.history.pushState(null, \"\", to);\n }\n\n // Emit navigation event to update router state\n routerEventEmitter.emit(\"navigation\", {\n from: window.location.pathname,\n to: targetPath,\n });\n }\n }, [to, replace]);\n\n return null;\n}\n\n/** Options for navigation */\ninterface NavigateOptions {\n replace?: boolean;\n scrollToTop?: boolean;\n}\n\n// Navigation helper\nfunction navigate(href: string, options: NavigateOptions = {}) {\n const { replace = false, scrollToTop = true } = options;\n const from = window.location.pathname;\n const to = href.split(\"?\")[0]; // Extract pathname from href\n\n // Emit before-navigation event (can be prevented)\n const canNavigate = routerEventEmitter.emit(\"before-navigation\", { from, to });\n if (!canNavigate) {\n return; // Navigation was prevented\n }\n\n // Set navigating state to true before navigation\n currentLocation = { ...currentLocation, isNavigating: true };\n locationListeners.forEach((listener) => listener());\n\n if (replace) {\n window.history.replaceState(null, \"\", href);\n } else {\n window.history.pushState(null, \"\", href);\n }\n\n // Scroll to top immediately after pushState, before React re-renders.\n // Using instant scroll avoids race conditions where smooth scrolling\n // gets interrupted by React DOM updates, especially on Safari mobile.\n if (scrollToTop) {\n window.scrollTo({ top: 0, left: 0, behavior: \"instant\" });\n }\n\n // Update location state synchronously so there is no stale-state window\n // between pushState and the next render.\n updateLocation(false);\n\n // Emit navigation event after state is consistent\n routerEventEmitter.emit(\"navigation\", { from, to });\n}\n\nexport type LinkProps = React.PropsWithChildren<\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> & {\n href: string;\n replace?: boolean;\n /** Disable prefetching on hover (default: false - prefetch is enabled) */\n prefetch?: boolean;\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n }\n>;\n\n/**\n * Check if a URL is external (different origin).\n */\nfunction isExternalUrl(href: string): boolean {\n if (typeof window === \"undefined\") {\n return false;\n }\n try {\n const url = new URL(href, window.location.origin);\n return url.origin !== window.location.origin;\n } catch {\n return false;\n }\n}\n\n// Store routes globally for prefetching (set by AppRouter)\n// Preserve across HMR in dev mode\nlet globalRoutes: RouteEntry[];\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n if (!globalWindow.__heliumGlobalRoutes) {\n globalWindow.__heliumGlobalRoutes = [];\n }\n globalRoutes = globalWindow.__heliumGlobalRoutes;\n} else {\n globalRoutes = [];\n}\n\n/**\n * Client-side navigation link.\n *\n * Intercepts left-clicks and uses the router's navigation helpers for SPA\n * navigation. Keeps normal anchor behaviour when modifier keys are used,\n * when the link is external, or when `target` / `download` attributes\n * are present.\n *\n * Automatically prefetches page chunks on hover for faster navigation.\n */\nexport function Link(props: LinkProps) {\n const {\n children,\n href,\n className,\n prefetch: prefetchProp = true,\n scrollToTop = true,\n replace: replaceProp,\n target,\n download,\n onClick: userOnClick,\n onMouseEnter: userOnMouseEnter,\n onFocus: userOnFocus,\n ...restProps\n } = props;\n\n const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Let user's onClick run first so they can call e.preventDefault()\n userOnClick?.(e);\n\n if (\n e.defaultPrevented ||\n e.button !== 0 || // only left click\n e.metaKey ||\n e.ctrlKey ||\n e.shiftKey ||\n e.altKey ||\n target || // let browser handle target=\"_blank\" etc.\n download != null || // let browser handle downloads\n isExternalUrl(href) // let browser handle external links\n ) {\n return;\n }\n e.preventDefault();\n navigate(href, { replace: replaceProp, scrollToTop });\n };\n\n const onMouseEnter = async (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Prefetch the route on hover if enabled and not external (lazy-load prefetch logic)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnMouseEnter?.(e);\n };\n\n const onFocus = async (e: React.FocusEvent<HTMLAnchorElement>) => {\n // Also prefetch on focus (keyboard navigation)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnFocus?.(e);\n };\n\n return (\n <a {...restProps} href={href} target={target} download={download} onClick={onClick} onMouseEnter={onMouseEnter} onFocus={onFocus} className={className}>\n {children}\n </a>\n );\n}\n\n// AppShell props type\n/**\n * Props passed to an optional \\`AppShell\\` wrapper component used by <AppRouter />.\n *\n * \\`Component\\` — the page component to render. \\`pageProps\\` — props provided to the page.\n */\nexport type AppShellProps<TPageProps extends Record<string, unknown> = Record<string, unknown>> = {\n Component: ComponentType<TPageProps>;\n pageProps: TPageProps;\n};\n\n// Main router component\nexport function AppRouter({ AppShell }: { AppShell?: ComponentType<AppShellProps> }) {\n // useTransition for concurrent rendering - allows React to keep UI responsive during navigation\n const [isPending, startTransition] = useTransition();\n\n // Build routes once on mount (client-side only)\n const { routes, NotFound } = useMemo(() => {\n if (typeof window === \"undefined\") {\n return { routes: [], NotFound: undefined };\n }\n const result = buildRoutes();\n // Store routes globally for Link prefetching\n // In dev mode, also update the global reference to survive HMR\n if (isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n globalWindow.__heliumGlobalRoutes = result.routes;\n // Update the module-level reference as well\n globalRoutes.length = 0;\n globalRoutes.push(...result.routes);\n } else {\n globalRoutes = result.routes;\n }\n return result;\n }, []);\n\n // Use useSyncExternalStore to subscribe to location changes\n // This ensures synchronous updates when location changes\n const state = useSyncExternalStore(subscribeToLocation, getLocationSnapshot, getServerSnapshot);\n\n const match = useMemo(() => matchRoute(state.path, routes), [state.path, routes]);\n\n // Use matched params, or fall back to re-extracting from path using global routes during HMR\n const currentParams = match?.params ?? (isDevEnvironment() ? extractParamsFromPath(state.path) : {});\n\n // In dev mode, always read fresh searchParams from URL to handle HMR edge cases\n const currentSearchParams = isDevEnvironment() ? new URLSearchParams(window.location.search) : state.searchParams;\n\n const routerValue: RouterContext = {\n path: state.path,\n params: currentParams,\n searchParams: currentSearchParams,\n push: (href, options) => {\n // Wrap navigation in startTransition for smoother updates\n startTransition(() => {\n navigate(href, { scrollToTop: options?.scrollToTop });\n });\n },\n replace: (href, options) => {\n startTransition(() => {\n navigate(href, { replace: true, scrollToTop: options?.scrollToTop });\n });\n },\n on: (event, listener) => routerEventEmitter.on(event, listener),\n status: match ? 200 : 404,\n isNavigating: state.isNavigating,\n isPending,\n };\n\n if (!match) {\n const NotFoundComp = NotFound ?? (() => <div>Not found</div>);\n const content = <NotFoundComp />;\n\n return <RouterContext.Provider value={routerValue}>{AppShell ? <AppShell Component={NotFoundComp} pageProps={{}} /> : content}</RouterContext.Provider>;\n }\n\n const Page = match.route.Component as ComponentType<{ params: Record<string, string | string[]>; searchParams: URLSearchParams }>;\n const pageProps = {\n params: match.params,\n searchParams: currentSearchParams,\n };\n\n // Create a wrapped component that includes all layouts\n const WrappedPage = () => {\n let content = <Page {...pageProps} />;\n // Wrap page with layouts (from outer to inner)\n for (let i = match.route.layouts.length - 1; i >= 0; i--) {\n const Layout = match.route.layouts[i];\n content = <Layout>{content}</Layout>;\n }\n return content;\n };\n\n const finalContent = AppShell ? <AppShell Component={WrappedPage} pageProps={{}} /> : <WrappedPage />;\n\n return <RouterContext.Provider value={routerValue}>{finalContent}</RouterContext.Provider>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Router.js","sourceRoot":"","sources":["../../src/client/Router.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ComponentType } from \"react\";\nimport React, { useMemo, useSyncExternalStore, useTransition } from \"react\";\n\nimport { isDevEnvironment } from \"./env.js\";\nimport type { RouteEntry } from \"./routerManifest.js\";\nimport { buildRoutes } from \"./routerManifest.js\";\n\n// Event emitter for router events\ntype RouterEvent = \"navigation\" | \"before-navigation\";\ntype EventListener = (event: { from: string; to: string; preventDefault?: () => void }) => void;\n\nclass RouterEventEmitter {\n private listeners: Map<RouterEvent, Set<EventListener>> = new Map();\n\n on(event: RouterEvent, listener: EventListener): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n\n // Return unsubscribe function\n return () => {\n this.listeners.get(event)?.delete(listener);\n };\n }\n\n emit(event: RouterEvent, data: { from: string; to: string }): boolean {\n const eventListeners = this.listeners.get(event);\n if (!eventListeners || eventListeners.size === 0) {\n return true;\n }\n\n let prevented = false;\n const preventDefault = () => {\n prevented = true;\n };\n\n const eventData = event === \"before-navigation\" ? { ...data, preventDefault } : data;\n\n eventListeners.forEach((listener) => {\n listener(eventData);\n });\n\n return !prevented;\n }\n\n // Clear all listeners - useful for HMR\n clear() {\n this.listeners.clear();\n }\n}\n\n// Use a singleton that survives HMR by attaching to window in dev mode\nlet routerEventEmitter: RouterEventEmitter;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n // In dev mode, reuse the same emitter instance across HMR\n const globalWindow = window as typeof window & { __heliumRouterEmitter?: RouterEventEmitter };\n if (!globalWindow.__heliumRouterEmitter) {\n globalWindow.__heliumRouterEmitter = new RouterEventEmitter();\n }\n routerEventEmitter = globalWindow.__heliumRouterEmitter;\n} else {\n routerEventEmitter = new RouterEventEmitter();\n}\n\ntype RouterState = {\n path: string;\n searchParams: URLSearchParams;\n isNavigating: boolean;\n};\n\nfunction getLocation(): RouterState {\n const { pathname, search } = window.location;\n return {\n path: pathname,\n searchParams: new URLSearchParams(search),\n isNavigating: false,\n };\n}\n\nfunction matchRoute(path: string, routes: RouteEntry[]) {\n for (const r of routes) {\n const m = r.matcher(path);\n if (m) {\n return { params: m.params, route: r };\n }\n }\n return null;\n}\n\n// Location store for useSyncExternalStore\n// Preserve across HMR by attaching to window in dev mode\nlet currentLocation: RouterState;\nlet locationListeners: Set<() => void>;\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & {\n __heliumCurrentLocation?: RouterState;\n __heliumLocationListeners?: Set<() => void>;\n };\n if (!globalWindow.__heliumCurrentLocation) {\n globalWindow.__heliumCurrentLocation = getLocation();\n }\n if (!globalWindow.__heliumLocationListeners) {\n globalWindow.__heliumLocationListeners = new Set();\n }\n currentLocation = globalWindow.__heliumCurrentLocation;\n locationListeners = globalWindow.__heliumLocationListeners;\n} else if (typeof window !== \"undefined\") {\n currentLocation = getLocation();\n locationListeners = new Set();\n} else {\n currentLocation = { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\n locationListeners = new Set();\n}\n\n// Helper to re-extract params from path using stored routes during HMR\nfunction extractParamsFromPath(path: string): Record<string, string | string[]> {\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n const routes = globalWindow.__heliumGlobalRoutes;\n if (routes && routes.length > 0) {\n const match = matchRoute(path, routes);\n if (match) {\n return match.params;\n }\n }\n }\n return {};\n}\n\nfunction subscribeToLocation(callback: () => void) {\n locationListeners.add(callback);\n return () => locationListeners.delete(callback);\n}\n\nfunction getLocationSnapshot() {\n return currentLocation;\n}\n\nfunction getServerSnapshot() {\n return { path: \"/\", searchParams: new URLSearchParams(), isNavigating: false };\n}\n\nfunction updateLocation(isNavigating = false) {\n const newLocation = { ...getLocation(), isNavigating };\n currentLocation = newLocation;\n // Update the global reference in dev mode\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n (window as typeof window & { __heliumCurrentLocation?: RouterState }).__heliumCurrentLocation = newLocation;\n }\n locationListeners.forEach((listener) => listener());\n}\n\n// Set up global listeners once\nif (typeof window !== \"undefined\") {\n // Only set up once, survives HMR\n const globalWindow = window as typeof window & { __heliumLocationListenerSetup?: boolean };\n if (!globalWindow.__heliumLocationListenerSetup) {\n globalWindow.__heliumLocationListenerSetup = true;\n\n window.addEventListener(\"popstate\", () => updateLocation(false));\n\n // Also listen to navigation events from the emitter\n routerEventEmitter.on(\"navigation\", () => updateLocation(false));\n }\n}\n\n/** Options for push/replace navigation methods */\nexport interface RouterNavigationOptions {\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n}\n\n// Context for useRouter hook\ntype RouterContext = {\n path: string;\n params: Record<string, string | string[]>;\n searchParams: URLSearchParams;\n push: (href: string, options?: RouterNavigationOptions) => void;\n replace: (href: string, options?: RouterNavigationOptions) => void;\n on: (event: RouterEvent, listener: EventListener) => () => void;\n status: 200 | 404;\n isNavigating: boolean;\n /** Indicates content is stale (old content shown while new content renders) - React 18+ concurrent feature */\n isPending: boolean;\n};\n\nexport const RouterContext = React.createContext<RouterContext | null>(null);\n\n/**\n * Access router context inside a component tree managed by <AppRouter />.\n *\n * Provides current path, route params, URL search params and navigation helpers\n * (\\`push\\`, \\`replace\\`) as well as an \\`on\\` method to subscribe to navigation events.\n * The \\`isNavigating\\` property indicates when a navigation is in progress.\n * The \\`isPending\\` property indicates when content is stale (React concurrent features).\n * Throws when used outside of an <AppRouter /> provider.\n */\nexport function useRouter() {\n const ctx = React.useContext(RouterContext);\n if (!ctx) {\n // During HMR in development, context might be temporarily unavailable\n // Provide a temporary fallback to prevent white screen of death\n // Re-extract params from current path using stored routes\n if (typeof window !== \"undefined\" && isDevEnvironment()) {\n const currentPath = window.location.pathname;\n return {\n path: currentPath,\n params: extractParamsFromPath(currentPath),\n searchParams: new URLSearchParams(window.location.search),\n push: (href: string, options?: RouterNavigationOptions) => {\n window.history.pushState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n replace: (href: string, options?: RouterNavigationOptions) => {\n window.history.replaceState({}, \"\", href);\n if (options?.scrollToTop !== false) {\n window.scrollTo({ top: 0, left: 0, behavior: \"smooth\" });\n }\n window.dispatchEvent(new PopStateEvent(\"popstate\"));\n },\n on: () => () => {},\n status: 200 as const,\n isNavigating: false,\n isPending: false,\n };\n }\n throw new Error(\"useRouter must be used inside <AppRouter>\");\n }\n return ctx;\n}\n\n/**\n * Redirect component for declarative navigation.\n * Use this instead of calling router.push() during render.\n *\n * @example\n * \\`\\`\\`tsx\n * export default function Docs() {\n * return <Redirect to=\"/docs/getting-started\" />;\n * }\n * \\`\\`\\`\n */\nexport function Redirect({ to, replace = false }: { to: string; replace?: boolean }) {\n const hasRedirected = React.useRef(false);\n\n // Use useLayoutEffect to redirect before paint\n React.useLayoutEffect(() => {\n const targetPath = to.split(\"?\")[0];\n if (!hasRedirected.current && window.location.pathname !== targetPath) {\n hasRedirected.current = true;\n\n // Perform navigation\n if (replace) {\n window.history.replaceState(null, \"\", to);\n } else {\n window.history.pushState(null, \"\", to);\n }\n\n // Emit navigation event to update router state\n routerEventEmitter.emit(\"navigation\", {\n from: window.location.pathname,\n to: targetPath,\n });\n }\n }, [to, replace]);\n\n return null;\n}\n\n/** Options for navigation */\ninterface NavigateOptions {\n replace?: boolean;\n scrollToTop?: boolean;\n}\n\n// Navigation helper\nfunction navigate(href: string, options: NavigateOptions = {}) {\n const { replace = false, scrollToTop = true } = options;\n const from = window.location.pathname;\n const to = href.split(\"?\")[0]; // Extract pathname from href\n\n // Emit before-navigation event (can be prevented)\n const canNavigate = routerEventEmitter.emit(\"before-navigation\", { from, to });\n if (!canNavigate) {\n return; // Navigation was prevented\n }\n\n // Set navigating state to true before navigation\n currentLocation = { ...currentLocation, isNavigating: true };\n locationListeners.forEach((listener) => listener());\n\n if (replace) {\n window.history.replaceState(null, \"\", href);\n } else {\n window.history.pushState(null, \"\", href);\n }\n\n // Scroll to top immediately after pushState, before React re-renders.\n // Using instant scroll avoids race conditions where smooth scrolling\n // gets interrupted by React DOM updates, especially on Safari mobile.\n if (scrollToTop) {\n window.scrollTo({ top: 0, left: 0, behavior: \"instant\" });\n }\n\n // Update location state synchronously so there is no stale-state window\n // between pushState and the next render.\n updateLocation(false);\n\n // Emit navigation event after state is consistent\n routerEventEmitter.emit(\"navigation\", { from, to });\n}\n\nexport type LinkProps = React.PropsWithChildren<\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> & {\n href: string;\n replace?: boolean;\n /** Disable prefetching on hover (default: false - prefetch is enabled) */\n prefetch?: boolean;\n /** Scroll to top after navigation (default: true) */\n scrollToTop?: boolean;\n }\n>;\n\n/**\n * Check if a URL is external (different origin).\n */\nfunction isExternalUrl(href: string): boolean {\n if (typeof window === \"undefined\") {\n return false;\n }\n try {\n const url = new URL(href, window.location.origin);\n return url.origin !== window.location.origin;\n } catch {\n return false;\n }\n}\n\n// Store routes globally for prefetching (set by AppRouter)\n// Preserve across HMR in dev mode\nlet globalRoutes: RouteEntry[];\n\nif (typeof window !== \"undefined\" && isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n if (!globalWindow.__heliumGlobalRoutes) {\n globalWindow.__heliumGlobalRoutes = [];\n }\n globalRoutes = globalWindow.__heliumGlobalRoutes;\n} else {\n globalRoutes = [];\n}\n\n/**\n * Client-side navigation link.\n *\n * Intercepts left-clicks and uses the router's navigation helpers for SPA\n * navigation. Keeps normal anchor behaviour when modifier keys are used,\n * when the link is external, or when `target` / `download` attributes\n * are present.\n *\n * Automatically prefetches page chunks on hover for faster navigation.\n */\nexport function Link(props: LinkProps) {\n const {\n children,\n href,\n className,\n prefetch: prefetchProp = true,\n scrollToTop = true,\n replace: replaceProp,\n target,\n download,\n onClick: userOnClick,\n onMouseEnter: userOnMouseEnter,\n onFocus: userOnFocus,\n ...restProps\n } = props;\n\n const onClick = (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Let user's onClick run first so they can call e.preventDefault()\n userOnClick?.(e);\n\n if (\n e.defaultPrevented ||\n e.button !== 0 || // only left click\n e.metaKey ||\n e.ctrlKey ||\n e.shiftKey ||\n e.altKey ||\n target || // let browser handle target=\"_blank\" etc.\n download != null || // let browser handle downloads\n isExternalUrl(href) // let browser handle external links\n ) {\n return;\n }\n e.preventDefault();\n navigate(href, { replace: replaceProp, scrollToTop });\n };\n\n const onMouseEnter = async (e: React.MouseEvent<HTMLAnchorElement>) => {\n // Prefetch the route on hover if enabled and not external (lazy-load prefetch logic)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnMouseEnter?.(e);\n };\n\n const onFocus = async (e: React.FocusEvent<HTMLAnchorElement>) => {\n // Also prefetch on focus (keyboard navigation)\n if (prefetchProp && !isExternalUrl(href) && globalRoutes.length > 0) {\n const { prefetchRoute } = await import(\"./prefetch.js\");\n prefetchRoute(href, globalRoutes);\n }\n userOnFocus?.(e);\n };\n\n return (\n <a {...restProps} href={href} target={target} download={download} onClick={onClick} onMouseEnter={onMouseEnter} onFocus={onFocus} className={className}>\n {children}\n </a>\n );\n}\n\n// AppShell props type\n/**\n * Props passed to an optional \\`AppShell\\` wrapper component used by <AppRouter />.\n *\n * \\`Component\\` — the page component to render. \\`pageProps\\` — props provided to the page.\n */\nexport type AppShellProps<TPageProps extends Record<string, unknown> = Record<string, unknown>> = {\n Component: ComponentType<TPageProps>;\n pageProps: TPageProps;\n};\n\n// Main router component\nexport function AppRouter({ AppShell }: { AppShell?: ComponentType<AppShellProps> }) {\n // useTransition for concurrent rendering - allows React to keep UI responsive during navigation\n const [isPending, startTransition] = useTransition();\n\n // Build routes once on mount (client-side only)\n const { routes, NotFound } = useMemo(() => {\n if (typeof window === \"undefined\") {\n return { routes: [], NotFound: undefined };\n }\n const result = buildRoutes();\n // Store routes globally for Link prefetching\n // In dev mode, also update the global reference to survive HMR\n if (isDevEnvironment()) {\n const globalWindow = window as typeof window & { __heliumGlobalRoutes?: RouteEntry[] };\n globalWindow.__heliumGlobalRoutes = result.routes;\n // Update the module-level reference as well\n globalRoutes.length = 0;\n globalRoutes.push(...result.routes);\n } else {\n globalRoutes = result.routes;\n }\n return result;\n }, []);\n\n // Use useSyncExternalStore to subscribe to location changes\n // This ensures synchronous updates when location changes\n const state = useSyncExternalStore(subscribeToLocation, getLocationSnapshot, getServerSnapshot);\n\n const match = useMemo(() => matchRoute(state.path, routes), [state.path, routes]);\n\n // Use matched params, or fall back to re-extracting from path using global routes during HMR\n const currentParams = match?.params ?? (isDevEnvironment() ? extractParamsFromPath(state.path) : {});\n\n // In dev mode, always read fresh searchParams from URL to handle HMR edge cases\n const currentSearchParams = isDevEnvironment() ? new URLSearchParams(window.location.search) : state.searchParams;\n\n const routerValue: RouterContext = {\n path: state.path,\n params: currentParams,\n searchParams: currentSearchParams,\n push: (href, options) => {\n // Wrap navigation in startTransition for smoother updates\n startTransition(() => {\n navigate(href, { scrollToTop: options?.scrollToTop });\n });\n },\n replace: (href, options) => {\n startTransition(() => {\n navigate(href, { replace: true, scrollToTop: options?.scrollToTop });\n });\n },\n on: (event, listener) => routerEventEmitter.on(event, listener),\n status: match ? 200 : 404,\n isNavigating: state.isNavigating,\n isPending,\n };\n\n React.useEffect(() => {\n const controller = new AbortController();\n const targetPath = `${state.path}${window.location.search || \"\"}`;\n\n const syncMetadata = async () => {\n try {\n const response = await fetch(`/__helium__/seo-metadata?path=${encodeURIComponent(targetPath)}`, {\n method: \"GET\",\n credentials: \"same-origin\",\n cache: \"no-store\",\n signal: controller.signal,\n });\n\n if (!response.ok) {\n return;\n }\n\n const payload = (await response.json()) as { meta?: ClientSocialMeta | null };\n applyRouteMetadata(payload.meta ?? null);\n } catch (error) {\n if ((error as { name?: string })?.name === \"AbortError\") {\n return;\n }\n }\n };\n\n syncMetadata();\n\n return () => controller.abort();\n }, [state.path, currentSearchParams.toString()]);\n\n if (!match) {\n const NotFoundComp = NotFound ?? (() => <div>Not found</div>);\n const content = <NotFoundComp />;\n\n return <RouterContext.Provider value={routerValue}>{AppShell ? <AppShell Component={NotFoundComp} pageProps={{}} /> : content}</RouterContext.Provider>;\n }\n\n const Page = match.route.Component as ComponentType<{ params: Record<string, string | string[]>; searchParams: URLSearchParams }>;\n const pageProps = {\n params: match.params,\n searchParams: currentSearchParams,\n };\n\n // Create a wrapped component that includes all layouts\n const WrappedPage = () => {\n let content = <Page {...pageProps} />;\n // Wrap page with layouts (from outer to inner)\n for (let i = match.route.layouts.length - 1; i >= 0; i--) {\n const Layout = match.route.layouts[i];\n content = <Layout>{content}</Layout>;\n }\n return content;\n };\n\n const finalContent = AppShell ? <AppShell Component={WrappedPage} pageProps={{}} /> : <WrappedPage />;\n\n return <RouterContext.Provider value={routerValue}>{finalContent}</RouterContext.Provider>;\n}\n\ntype ClientSocialMeta = {\n title: string;\n description?: string;\n image?: string;\n canonicalUrl?: string;\n siteName?: string;\n type?: string;\n robots?: string;\n twitterCard?: \"summary\" | \"summary_large_image\" | \"app\" | \"player\";\n twitterSite?: string;\n twitterCreator?: string;\n};\n\nfunction applyRouteMetadata(meta: ClientSocialMeta | null) {\n if (typeof document === \"undefined\") {\n return;\n }\n\n const managedNodes = document.head.querySelectorAll('[data-helium-seo=\"true\"]');\n managedNodes.forEach((node) => node.remove());\n\n if (!meta) {\n return;\n }\n\n document.title = meta.title;\n\n const entries: Array<{ tag: \"meta\" | \"link\"; attrs: Record<string, string> }> = [];\n\n entries.push({ tag: \"meta\", attrs: { property: \"og:title\", content: meta.title } });\n entries.push({ tag: \"meta\", attrs: { property: \"og:type\", content: meta.type ?? \"website\" } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:card\", content: meta.twitterCard ?? \"summary_large_image\" } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:title\", content: meta.title } });\n\n if (meta.description) {\n entries.push({ tag: \"meta\", attrs: { name: \"description\", content: meta.description } });\n entries.push({ tag: \"meta\", attrs: { property: \"og:description\", content: meta.description } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:description\", content: meta.description } });\n }\n\n if (meta.image) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:image\", content: meta.image } });\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:image\", content: meta.image } });\n }\n\n if (meta.canonicalUrl) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:url\", content: meta.canonicalUrl } });\n entries.push({ tag: \"link\", attrs: { rel: \"canonical\", href: meta.canonicalUrl } });\n }\n\n if (meta.siteName) {\n entries.push({ tag: \"meta\", attrs: { property: \"og:site_name\", content: meta.siteName } });\n }\n\n if (meta.robots) {\n entries.push({ tag: \"meta\", attrs: { name: \"robots\", content: meta.robots } });\n }\n\n if (meta.twitterSite) {\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:site\", content: meta.twitterSite } });\n }\n\n if (meta.twitterCreator) {\n entries.push({ tag: \"meta\", attrs: { name: \"twitter:creator\", content: meta.twitterCreator } });\n }\n\n for (const entry of entries) {\n const node = document.createElement(entry.tag);\n for (const [key, value] of Object.entries(entry.attrs)) {\n node.setAttribute(key, value);\n }\n node.setAttribute(\"data-helium-seo\", \"true\");\n document.head.appendChild(node);\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { HeliumContext } from "./context.js";
|
|
2
|
+
import type { SocialMeta } from "./meta.js";
|
|
3
|
+
export interface SEOMetadataRequest {
|
|
4
|
+
method: string;
|
|
5
|
+
path: string;
|
|
6
|
+
headers: Record<string, string | string[] | undefined>;
|
|
7
|
+
query: Record<string, string>;
|
|
8
|
+
params: Record<string, string | string[]>;
|
|
9
|
+
}
|
|
10
|
+
export type SEOMetadataHandler = (req: SEOMetadataRequest, ctx: HeliumContext) => Promise<SocialMeta | null | undefined> | SocialMeta | null | undefined;
|
|
11
|
+
export type HeliumSEOMetadataDef<TPath extends string = string> = {
|
|
12
|
+
__kind: "seo";
|
|
13
|
+
path: TPath;
|
|
14
|
+
handler: SEOMetadataHandler;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Define dynamic SEO metadata for page routes.
|
|
18
|
+
*
|
|
19
|
+
* This does not create a standalone HTTP endpoint. It is evaluated only when
|
|
20
|
+
* a normal page route is matched and HTML is being served.
|
|
21
|
+
*/
|
|
22
|
+
export declare function defineSEOMetadata<TPath extends string>(path: TPath, handler: SEOMetadataHandler): HeliumSEOMetadataDef<TPath>;
|
|
23
|
+
//# sourceMappingURL=defineSEOMetadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineSEOMetadata.d.ts","sourceRoot":"","sources":["../../src/server/defineSEOMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;AAEzJ,MAAM,MAAM,oBAAoB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI;IAC9D,MAAM,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,kBAAkB,CAAC;CAC/B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,SAAS,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAa7H"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Define dynamic SEO metadata for page routes.
|
|
3
|
+
*
|
|
4
|
+
* This does not create a standalone HTTP endpoint. It is evaluated only when
|
|
5
|
+
* a normal page route is matched and HTML is being served.
|
|
6
|
+
*/
|
|
7
|
+
export function defineSEOMetadata(path, handler) {
|
|
8
|
+
if (!path) {
|
|
9
|
+
throw new Error("defineSEOMetadata requires a path");
|
|
10
|
+
}
|
|
11
|
+
if (!handler) {
|
|
12
|
+
throw new Error("defineSEOMetadata requires a handler");
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
__kind: "seo",
|
|
16
|
+
path,
|
|
17
|
+
handler,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=defineSEOMetadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineSEOMetadata.js","sourceRoot":"","sources":["../../src/server/defineSEOMetadata.ts"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAuB,IAAW,EAAE,OAA2B;IAC5F,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACH,MAAM,EAAE,KAAK;QACb,IAAI;QACJ,OAAO;KACV,CAAC;AACN,CAAC","sourcesContent":["import type { HeliumContext } from \"./context.js\";\nimport type { SocialMeta } from \"./meta.js\";\n\nexport interface SEOMetadataRequest {\n method: string;\n path: string;\n headers: Record<string, string | string[] | undefined>;\n query: Record<string, string>;\n params: Record<string, string | string[]>;\n}\n\nexport type SEOMetadataHandler = (req: SEOMetadataRequest, ctx: HeliumContext) => Promise<SocialMeta | null | undefined> | SocialMeta | null | undefined;\n\nexport type HeliumSEOMetadataDef<TPath extends string = string> = {\n __kind: \"seo\";\n path: TPath;\n handler: SEOMetadataHandler;\n};\n\n/**\n * Define dynamic SEO metadata for page routes.\n *\n * This does not create a standalone HTTP endpoint. It is evaluated only when\n * a normal page route is matched and HTML is being served.\n */\nexport function defineSEOMetadata<TPath extends string>(path: TPath, handler: SEOMetadataHandler): HeliumSEOMetadataDef<TPath> {\n if (!path) {\n throw new Error(\"defineSEOMetadata requires a path\");\n }\n if (!handler) {\n throw new Error(\"defineSEOMetadata requires a handler\");\n }\n\n return {\n __kind: \"seo\",\n path,\n handler,\n };\n}\n"]}
|
|
@@ -5,7 +5,8 @@ import type { HeliumConfig } from "./config.js";
|
|
|
5
5
|
import type { HeliumWorkerDef } from "./defineWorker.js";
|
|
6
6
|
import { HTTPRouter } from "./httpRouter.js";
|
|
7
7
|
import { RpcRegistry } from "./rpcRegistry.js";
|
|
8
|
-
|
|
8
|
+
import { SEOMetadataRouter } from "./seoMetadataRouter.js";
|
|
9
|
+
type LoadHandlersFn = (registry: RpcRegistry, httpRouter: HTTPRouter, seoRouter: SEOMetadataRouter) => void;
|
|
9
10
|
type HttpServer = http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer;
|
|
10
11
|
interface WorkerEntry {
|
|
11
12
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devServer.d.ts","sourceRoot":"","sources":["../../src/server/devServer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"devServer.d.ts","sourceRoot":"","sources":["../../src/server/devServer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQ3D,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAC5G,KAAK,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,iBAAiB,CAAC;AAE3F,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;CAC3B;AASD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,GAAE,YAAiB,EAAE,OAAO,GAAE,WAAW,EAAO,QAud7I"}
|