heliumts 0.8.7 → 0.8.8
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/server/prodServer.d.ts.map +1 -1
- package/dist/server/prodServer.js +3 -0
- package/dist/server/prodServer.js.map +1 -1
- package/dist/utils/envLoader.d.ts +27 -0
- package/dist/utils/envLoader.d.ts.map +1 -1
- package/dist/utils/envLoader.js +56 -1
- package/dist/utils/envLoader.js.map +1 -1
- package/dist/vite/virtualServerModule.d.ts.map +1 -1
- package/dist/vite/virtualServerModule.js +8 -1
- package/dist/vite/virtualServerModule.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prodServer.d.ts","sourceRoot":"","sources":["../../src/server/prodServer.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"prodServer.d.ts","sourceRoot":"","sources":["../../src/server/prodServer.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUtD,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;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAuD,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3F,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;CAC3B;AAED,UAAU,iBAAiB;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACxG,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,aAAa,CAAC;QAAE,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;CACrK;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,wEAmjBzD;AAqBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CA4BtF"}
|
|
@@ -8,6 +8,7 @@ import { brotliCompress, deflate, gzip } from "zlib";
|
|
|
8
8
|
import { SEO_METADATA_RPC_METHOD } from "../runtime/internalMethods.js";
|
|
9
9
|
import { extractClientIP } from "../utils/ipExtractor.js";
|
|
10
10
|
import { log } from "../utils/logger.js";
|
|
11
|
+
import { injectPublicEnvIntoHtml } from "../utils/envLoader.js";
|
|
11
12
|
import { getRpcConfig, getRpcSecurityConfig, getTrustProxyDepth } from "./config.js";
|
|
12
13
|
import { startWorker, stopAllWorkers } from "./defineWorker.js";
|
|
13
14
|
import { HTTPRouter } from "./httpRouter.js";
|
|
@@ -364,6 +365,8 @@ export function startProdServer(options) {
|
|
|
364
365
|
if (metadata) {
|
|
365
366
|
html = injectSocialMetaIntoHtml(html, metadata);
|
|
366
367
|
}
|
|
368
|
+
// Inject runtime public env vars (for platform deployments like Render, DO Apps)
|
|
369
|
+
html = injectPublicEnvIntoHtml(html);
|
|
367
370
|
responseBody = Buffer.from(html, "utf-8");
|
|
368
371
|
}
|
|
369
372
|
// Set status code to 404 if serving the 404 page
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prodServer.js","sourceRoot":"","sources":["../../src/server/prodServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode as msgpackEncode } from \"@msgpack/msgpack\";\nimport fs from \"fs\";\nimport http from \"http\";\nimport path from \"path\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { promisify } from \"util\";\nimport type WebSocket from \"ws\";\nimport { WebSocketServer } from \"ws\";\nimport { brotliCompress, deflate, gzip } from \"zlib\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport type { HeliumConfig } from \"./config.js\";\nimport { getRpcConfig, getRpcSecurityConfig, getTrustProxyDepth } from \"./config.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumWorkerDef } from \"./defineWorker.js\";\nimport { startWorker, stopAllWorkers } from \"./defineWorker.js\";\nimport { HTTPRouter } from \"./httpRouter.js\";\nimport { injectSocialMetaIntoHtml, loadDefaultSocialMetaFromHtmlFile } from \"./meta.js\";\nimport { RateLimiter } from \"./rateLimiter.js\";\nimport { RpcRegistry } from \"./rpcRegistry.js\";\nimport { generateConnectionToken, initializeSecurity, verifyConnectionToken } from \"./security.js\";\nimport { SEOMetadataRouter } from \"./seoMetadataRouter.js\";\nimport { prepareForMsgpack } from \"./serializer.js\";\nimport { matchSSRPage, renderSSRHTML, resolveServerSideProps, SSRPageDef } from \"./ssr.js\";\n\nconst gzipAsync = promisify(gzip);\nconst deflateAsync = promisify(deflate);\nconst brotliCompressAsync = promisify(brotliCompress);\n\ninterface WorkerEntry {\n name: string;\n worker: HeliumWorkerDef;\n}\n\ninterface ProdServerOptions {\n port?: number;\n distDir?: string;\n staticDir?: string;\n registerHandlers: (registry: RpcRegistry, httpRouter: HTTPRouter, seoRouter: SEOMetadataRouter) => void;\n config?: HeliumConfig;\n workers?: WorkerEntry[];\n ssrPages?: SSRPageDef[];\n appShell?: (() => Promise<ComponentType<{ Component: ComponentType<Record<string, unknown>>; pageProps: Record<string, unknown>; children?: ReactNode }>>) | null;\n}\n\n/**\n * Starts a production HTTP server that:\n * - Serves static files from the dist directory\n * - Supports SSG (Static Site Generation) by serving .html files for routes (e.g., /about -> about.html)\n * - Falls back to index.html for client-side routing (SPA)\n * - Handles custom HTTP endpoints (webhooks, auth, etc.)\n * - Hosts WebSocket RPC server\n * - Starts background workers\n *\n * SSG Behavior:\n * - Production correctly serves SSG pages (e.g., /about serves about.html with pre-rendered content)\n * - This ensures search engines and social media crawlers see the correct content\n * - Client-side navigation between pages still works via React Router\n */\nexport function startProdServer(options: ProdServerOptions) {\n const {\n port = Number(process.env.PORT || 3000),\n distDir = \"dist\",\n staticDir = path.resolve(process.cwd(), distDir),\n registerHandlers,\n config = {},\n workers = [],\n ssrPages = [],\n appShell = null,\n } = options;\n\n // Load configuration\n const trustProxyDepth = getTrustProxyDepth(config);\n const rpcSecurity = getRpcSecurityConfig(config);\n const rpcConfig = getRpcConfig(config);\n const compressionConfig = rpcConfig.compression;\n initializeSecurity(rpcSecurity);\n\n // Initialize rate limiter\n const rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);\n\n const registry = new RpcRegistry();\n const httpRouter = new HTTPRouter({ maxBodySize: rpcConfig.maxBodySize });\n const seoRouter = new SEOMetadataRouter();\n httpRouter.setTrustProxyDepth(trustProxyDepth);\n registerHandlers(registry, httpRouter, seoRouter);\n registry.setRateLimiter(rateLimiter);\n registry.setMaxBatchSize(rpcConfig.maxBatchSize);\n\n // Security: max body size for HTTP requests (1 MB default)\n const maxBodySize = rpcConfig.maxBodySize ?? 1_048_576;\n let cachedDefaultMeta: Awaited<ReturnType<typeof loadDefaultSocialMetaFromHtmlFile>> | undefined;\n\n const getDefaultMeta = async () => {\n if (cachedDefaultMeta !== undefined) {\n return cachedDefaultMeta;\n }\n\n cachedDefaultMeta = await loadDefaultSocialMetaFromHtmlFile(path.join(staticDir, \"index.html\"));\n return cachedDefaultMeta;\n };\n\n registry.register(SEO_METADATA_RPC_METHOD, {\n __kind: \"method\",\n __id: SEO_METADATA_RPC_METHOD,\n handler: async (args: { path?: string } | undefined, ctx: HeliumContext) => {\n const requestedPath = typeof args?.path === \"string\" ? args.path : \"/\";\n const targetPath = requestedPath.startsWith(\"/\") ? requestedPath : `/${requestedPath}`;\n const metadata = await seoRouter.resolve(ctx.req.raw, ctx, targetPath);\n return metadata ?? (await getDefaultMeta());\n },\n });\n\n // Create HTTP server\n const server = http.createServer(async (req, res) => {\n // Apply security headers to all responses\n setSecurityHeaders(res, config);\n\n // Handle CORS preflight\n if (req.method === \"OPTIONS\") {\n handleCorsHeaders(req, res, config);\n res.writeHead(204);\n res.end();\n return;\n }\n handleCorsHeaders(req, res, config);\n\n // Handle token refresh endpoint\n const requestUrl = new URL(req.url || \"/\", \"http://localhost\");\n const requestPathname = requestUrl.pathname;\n\n if (requestPathname === \"/__helium__/page-props\" && req.method === \"GET\") {\n const pathQuery = requestUrl.searchParams.get(\"path\") || \"/\";\n const targetUrl = new URL(pathQuery, \"http://localhost\");\n const targetPathname = targetUrl.pathname;\n const ssrMatch = matchSSRPage(targetPathname, ssrPages);\n\n if (!ssrMatch) {\n res.writeHead(200, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: false, props: null }));\n return;\n }\n\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n try {\n const ssrResult = await resolveServerSideProps({\n req,\n pathname: targetPathname,\n params: ssrMatch.params,\n page: ssrMatch.page,\n ctx: httpCtx,\n });\n\n if (ssrResult.kind === \"redirect\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: true, redirect: ssrResult.redirect }));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: true, props: ssrResult.props }));\n } catch (error) {\n log(\"error\", \"Failed to resolve SSR page props:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: true, props: null, error: \"Internal server error\" }));\n }\n\n return;\n }\n\n if (req.url === \"/__helium__/refresh-token\") {\n // Security: only allow POST to prevent CSRF via <img>/<script> tags\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n // Security: require custom header to prevent cross-origin requests\n if (!req.headers[\"x-requested-with\"]) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Forbidden\" }));\n return;\n }\n const token = generateConnectionToken();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ token }));\n return;\n }\n\n // Handle HTTP-based RPC endpoint (alternative to WebSocket for mobile networks)\n if (req.url === \"/__helium__/rpc\" && req.method === \"POST\") {\n // Security: verify connection token for HTTP RPC\n const authToken = req.headers[\"x-helium-token\"] as string | undefined;\n if (!authToken || !verifyConnectionToken(authToken)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Unauthorized\" }));\n return;\n }\n\n // Security: check Content-Length before reading body\n const contentLength = parseInt(req.headers[\"content-length\"] || \"0\", 10);\n if (contentLength > maxBodySize) {\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n let aborted = false;\n req.on(\"data\", (chunk: Buffer) => {\n totalSize += chunk.length;\n if (totalSize > maxBodySize) {\n aborted = true;\n req.destroy();\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", async () => {\n if (aborted) {\n return;\n }\n try {\n const body = Buffer.concat(chunks);\n const ip = extractClientIP(req, trustProxyDepth);\n const result = await registry.handleHttpRequest(body, ip, req);\n\n const encoded = msgpackEncode(prepareForMsgpack(result.response));\n let responseBody = Buffer.from(encoded as Uint8Array);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/msgpack\",\n \"Cache-Control\": \"no-store\",\n };\n\n // Handle compression\n const acceptEncoding = req.headers[\"accept-encoding\"] as string;\n if (acceptEncoding && responseBody.length > 1024) {\n if (acceptEncoding.includes(\"br\")) {\n responseBody = await brotliCompressAsync(responseBody);\n headers[\"Content-Encoding\"] = \"br\";\n } else if (acceptEncoding.includes(\"gzip\")) {\n responseBody = await gzipAsync(responseBody);\n headers[\"Content-Encoding\"] = \"gzip\";\n } else if (acceptEncoding.includes(\"deflate\")) {\n responseBody = await deflateAsync(responseBody);\n headers[\"Content-Encoding\"] = \"deflate\";\n }\n }\n\n res.writeHead(200, headers);\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"HTTP RPC error:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Internal server error\" }));\n }\n });\n return;\n }\n\n // Try HTTP handlers first (webhooks, auth, etc.)\n const handled = await httpRouter.handleRequest(req, res);\n if (handled) {\n return;\n }\n\n // Serve static files\n const url = req.url || \"/\";\n\n // Block access to sensitive configuration and server files\n const blockedFiles = [\"helium.config.js\", \"helium.config.mjs\", \"helium.config.ts\", \"server.js\", \".env\", \".env.local\", \".env.production\"];\n\n const requestedFile = path.basename(url.split(\"?\")[0]);\n let filePath: string = path.join(staticDir, \"index.html\");\n let is404 = false;\n\n if (blockedFiles.some((blocked) => requestedFile === blocked || requestedFile.startsWith(\".env\"))) {\n // Serve index.html so the SPA router can render the 404 page\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n } else {\n // Clean URL (remove query params and trailing slash)\n const cleanUrl = url.split(\"?\")[0].replace(/\\/$/, \"\") || \"/\";\n\n // Security: path traversal prevention — resolve and verify\n const resolvedStaticDir = path.resolve(staticDir);\n const candidatePath = path.resolve(staticDir, \".\" + cleanUrl);\n if (!candidatePath.startsWith(resolvedStaticDir + path.sep) && candidatePath !== resolvedStaticDir) {\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n }\n\n // Try different file paths for SSG support\n if (!is404 && cleanUrl === \"/\") {\n // Try index.ssg.html first (if root page has SSG)\n const ssgIndexPath = path.join(staticDir, \"index.ssg.html\");\n if (fs.existsSync(ssgIndexPath)) {\n filePath = ssgIndexPath;\n } else {\n filePath = path.join(staticDir, \"index.html\");\n }\n } else if (!is404) {\n // If cleanUrl has no extension, prioritize .html files for SSG pages\n if (!path.extname(cleanUrl)) {\n const htmlPath = path.join(staticDir, cleanUrl + \".html\");\n if (fs.existsSync(htmlPath)) {\n filePath = htmlPath;\n } else {\n // Fall back to exact path (for assets or directories)\n filePath = path.join(staticDir, cleanUrl);\n }\n } else {\n // Has an extension, try exact path (for assets like /assets/main.js)\n filePath = path.join(staticDir, cleanUrl);\n }\n }\n\n // If file doesn't exist or is a directory, fall back to index.html for SPA routing\n const isFileOrExists = !is404 && filePath && fs.existsSync(filePath) && fs.statSync(filePath).isFile();\n if (!isFileOrExists && !url.startsWith(\"/api\") && !url.startsWith(\"/webhooks\") && !url.startsWith(\"/auth\")) {\n // Fall back to index.html for SPA routing\n // Note: We don't set is404 here because the client-side router will determine\n // if the route exists. If it doesn't, the router will render the 404 page.\n filePath = path.join(staticDir, \"index.html\");\n // Don't set is404 = true here - let the client-side router handle it\n }\n }\n\n // Check if file exists (should always exist now since we fallback to index.html)\n if (!fs.existsSync(filePath)) {\n // This should rarely happen - only if index.html itself is missing\n res.writeHead(404, { \"Content-Type\": \"text/html\" });\n res.end(\"Not found\");\n return;\n }\n\n // Determine content type\n const ext = path.extname(filePath);\n const contentTypes: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".eot\": \"application/vnd.ms-fontobject\",\n };\n const contentType = contentTypes[ext] || \"application/octet-stream\";\n\n try {\n const content = fs.readFileSync(filePath);\n let responseBody = content;\n const cleanedPathname = (req.url || \"/\").split(\"?\")[0].replace(/\\/$/, \"\") || \"/\";\n const htmlSsrMatch = req.method === \"GET\" && contentType === \"text/html\" ? matchSSRPage(cleanedPathname, ssrPages) : null;\n\n if (!is404 && contentType === \"text/html\") {\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n const metadata = await seoRouter.resolve(req, httpCtx);\n let html = content.toString(\"utf-8\");\n\n if (htmlSsrMatch) {\n try {\n const rendered = await renderSSRHTML({\n htmlTemplate: html,\n pathname: cleanedPathname,\n search: requestUrl.search,\n params: htmlSsrMatch.params,\n page: htmlSsrMatch.page,\n req,\n ctx: httpCtx,\n loadAppShell: appShell,\n });\n\n if (\"redirect\" in rendered) {\n res.writeHead(rendered.redirect.statusCode, {\n Location: rendered.redirect.destination,\n \"Cache-Control\": \"no-store\",\n });\n res.end();\n return;\n }\n\n html = rendered.html;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const isBrowserGlobalError = /\\bwindow is not defined\\b|\\bdocument is not defined\\b|\\bnavigator is not defined\\b/i.test(message);\n\n if (isBrowserGlobalError) {\n log(\n \"warn\",\n `SSR disabled for ${cleanedPathname} due to browser-only import. Render map/browser-only modules on client only (e.g. dynamic import inside useEffect).`\n );\n } else {\n log(\"error\", `Failed to render SSR page for ${cleanedPathname}:`, error);\n }\n }\n }\n\n if (metadata) {\n html = injectSocialMetaIntoHtml(html, metadata);\n }\n\n responseBody = Buffer.from(html, \"utf-8\");\n }\n\n // Set status code to 404 if serving the 404 page\n const statusCode = is404 ? 404 : 200;\n res.writeHead(statusCode, { \"Content-Type\": contentType });\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"Error serving file:\", error);\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal server error\");\n }\n });\n\n // Setup WebSocket server for RPC\n const wss = new WebSocketServer({\n noServer: true,\n maxPayload: rpcConfig.maxWsPayload,\n perMessageDeflate: compressionConfig.enabled\n ? {\n zlibDeflateOptions: {\n chunkSize: 1024,\n memLevel: 7,\n level: 9, // 6 is default compression level (balanced)\n },\n zlibInflateOptions: {\n chunkSize: 10 * 1024,\n },\n threshold: compressionConfig.threshold,\n }\n : false,\n });\n\n wss.on(\"connection\", (socket: WebSocket, req: http.IncomingMessage) => {\n // Extract client IP with proxy configuration\n const ip = extractClientIP(req, trustProxyDepth);\n\n // Store connection metadata for RPC context\n registry.setSocketMetadata(socket, ip, req);\n\n // Track connection and check IP limit\n if (!rateLimiter.trackConnection(socket, ip)) {\n socket.close(1008, \"Too many connections from your IP\");\n return;\n }\n\n // Prevent unhandled errors from crashing the process (e.g. maxPayload exceeded)\n socket.on(\"error\", (err) => {\n log(\"warn\", \"WebSocket error:\", err);\n if (socket.readyState === socket.OPEN || socket.readyState === socket.CLOSING) {\n socket.close(1009, \"Message too large\");\n }\n });\n\n socket.on(\"message\", (msg: WebSocket.RawData, _isBinary: boolean) => {\n // Check rate limit\n if (!rateLimiter.checkRateLimit(socket)) {\n // Parse request to get the ID for proper error response\n try {\n let req: any;\n // Always expect MessagePack\n const buffer = Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any);\n const { decode: msgpackDecode } = require(\"@msgpack/msgpack\");\n req = msgpackDecode(buffer);\n\n const stats = rateLimiter.getConnectionStats(socket);\n const now = Date.now();\n const resetInSeconds = stats ? Math.ceil((stats.resetTimeMs - now) / 1000) : 0;\n\n const createError = (id: string) => ({\n id,\n ok: false,\n stats: {\n remainingRequests: stats ? stats.remainingMessages : 0,\n resetInSeconds,\n },\n error: \"Rate limit exceeded\",\n });\n\n let errorResponse: any;\n if (Array.isArray(req)) {\n errorResponse = req.map((r: any) => createError(r.id));\n } else {\n errorResponse = createError(req.id);\n }\n\n log(\"warn\", `Rate limit exceeded for IP ${ip}, resets in ${resetInSeconds} seconds`);\n socket.send(msgpackEncode(errorResponse) as Buffer);\n } catch {\n // If we can't parse the request, just close the connection\n socket.close();\n }\n return;\n }\n\n registry.handleMessage(socket, Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any));\n });\n });\n\n // Handle WebSocket upgrade requests\n server.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/rpc\")) {\n // Security: read token from Sec-WebSocket-Protocol header instead of query string\n const protocols = req.headers[\"sec-websocket-protocol\"];\n const token =\n typeof protocols === \"string\"\n ? protocols\n .split(\",\")\n .map((p) => p.trim())\n .find((p) => p.includes(\".\"))\n : undefined;\n\n if (!token || !verifyConnectionToken(token)) {\n log(\"warn\", \"WebSocket connection rejected - invalid token\");\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n // Check IP connection limit before upgrading\n const ip = extractClientIP(req, trustProxyDepth);\n if (rpcSecurity.maxConnectionsPerIP > 0) {\n const currentConnections = rateLimiter.getIPConnectionCount(ip);\n if (currentConnections >= rpcSecurity.maxConnectionsPerIP) {\n log(\"warn\", `WebSocket connection rejected - IP ${ip} has ${currentConnections} connections`);\n socket.write(\"HTTP/1.1 429 Too Many Requests\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n } else {\n socket.destroy();\n }\n });\n\n // Start server\n server.listen(port, () => {\n log(\"info\", `Production server listening on http://localhost:${port}`);\n log(\"info\", `Serving static files from ${staticDir}`);\n log(\"info\", `WebSocket RPC available at ws://localhost:${port}/rpc`);\n\n // Start workers\n if (workers.length > 0) {\n log(\"info\", `Starting ${workers.length} worker(s)...`);\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n }\n });\n\n // Handle graceful shutdown\n const shutdown = async () => {\n log(\"info\", \"Shutting down...\");\n await stopAllWorkers();\n server.close(() => {\n log(\"info\", \"Server closed\");\n process.exit(0);\n });\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n return server;\n}\n\n// ============================================================================\n// Security helper functions\n// ============================================================================\n\n/**\n * Set default security headers on every HTTP response.\n */\nfunction setSecurityHeaders(res: http.ServerResponse, config: HeliumConfig): void {\n const headers = getSecurityHeaders(config);\n\n for (const [name, value] of Object.entries(headers)) {\n if (value === null) {\n res.removeHeader(name);\n continue;\n }\n res.setHeader(name, value);\n }\n}\n\n/**\n * Resolve security headers for the current request from config.\n * Returns a final header map where `null` indicates the header should be removed.\n *\n * @internal\n */\nexport function getSecurityHeaders(config: HeliumConfig): Record<string, string | null> {\n const headers: Record<string, string | null> = {};\n const securityConfig = config.security;\n\n if (securityConfig?.defaultHeaders !== false) {\n headers[\"X-Content-Type-Options\"] = \"nosniff\";\n headers[\"X-Frame-Options\"] = \"DENY\";\n headers[\"X-XSS-Protection\"] = \"0\";\n headers[\"Referrer-Policy\"] = \"strict-origin-when-cross-origin\";\n headers[\"Permissions-Policy\"] = \"camera=(), microphone=(), geolocation=()\";\n\n const csp = securityConfig?.contentSecurityPolicy;\n if (csp) {\n headers[\"Content-Security-Policy\"] = csp;\n }\n\n if (securityConfig?.hsts !== false) {\n headers[\"Strict-Transport-Security\"] = \"max-age=31536000; includeSubDomains\";\n }\n }\n\n if (securityConfig?.headerOverrides) {\n for (const [name, value] of Object.entries(securityConfig.headerOverrides)) {\n headers[name] = value;\n }\n }\n\n return headers;\n}\n\n/**\n * Handle CORS headers based on configuration.\n * Default: restrict to same-origin (no CORS header = browser blocks cross-origin).\n */\nfunction handleCorsHeaders(req: http.IncomingMessage, res: http.ServerResponse, config: HeliumConfig): void {\n const allowedOrigins = config.security?.corsOrigins;\n if (!allowedOrigins || allowedOrigins.length === 0) {\n // No CORS configured — same-origin only by default\n return;\n }\n\n const origin = req.headers.origin;\n if (!origin) {\n return;\n }\n\n const isAllowed = allowedOrigins.includes(\"*\") || allowedOrigins.includes(origin);\n if (isAllowed) {\n res.setHeader(\"Access-Control-Allow-Origin\", allowedOrigins.includes(\"*\") ? \"*\" : origin);\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, X-Requested-With, X-Helium-Token\");\n res.setHeader(\"Access-Control-Max-Age\", \"86400\");\n\n if (!allowedOrigins.includes(\"*\")) {\n res.setHeader(\"Vary\", \"Origin\");\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"prodServer.js","sourceRoot":"","sources":["../../src/server/prodServer.ts"],"names":[],"mappings":"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","sourcesContent":["import { encode as msgpackEncode } from \"@msgpack/msgpack\";\nimport fs from \"fs\";\nimport http from \"http\";\nimport path from \"path\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { promisify } from \"util\";\nimport type WebSocket from \"ws\";\nimport { WebSocketServer } from \"ws\";\nimport { brotliCompress, deflate, gzip } from \"zlib\";\n\nimport { SEO_METADATA_RPC_METHOD } from \"../runtime/internalMethods.js\";\nimport { extractClientIP } from \"../utils/ipExtractor.js\";\nimport { log } from \"../utils/logger.js\";\nimport { injectPublicEnvIntoHtml } from \"../utils/envLoader.js\";\nimport type { HeliumConfig } from \"./config.js\";\nimport { getRpcConfig, getRpcSecurityConfig, getTrustProxyDepth } from \"./config.js\";\nimport type { HeliumContext } from \"./context.js\";\nimport type { HeliumWorkerDef } from \"./defineWorker.js\";\nimport { startWorker, stopAllWorkers } from \"./defineWorker.js\";\nimport { HTTPRouter } from \"./httpRouter.js\";\nimport { injectSocialMetaIntoHtml, loadDefaultSocialMetaFromHtmlFile } from \"./meta.js\";\nimport { RateLimiter } from \"./rateLimiter.js\";\nimport { RpcRegistry } from \"./rpcRegistry.js\";\nimport { generateConnectionToken, initializeSecurity, verifyConnectionToken } from \"./security.js\";\nimport { SEOMetadataRouter } from \"./seoMetadataRouter.js\";\nimport { prepareForMsgpack } from \"./serializer.js\";\nimport { matchSSRPage, renderSSRHTML, resolveServerSideProps, SSRPageDef } from \"./ssr.js\";\n\nconst gzipAsync = promisify(gzip);\nconst deflateAsync = promisify(deflate);\nconst brotliCompressAsync = promisify(brotliCompress);\n\ninterface WorkerEntry {\n name: string;\n worker: HeliumWorkerDef;\n}\n\ninterface ProdServerOptions {\n port?: number;\n distDir?: string;\n staticDir?: string;\n registerHandlers: (registry: RpcRegistry, httpRouter: HTTPRouter, seoRouter: SEOMetadataRouter) => void;\n config?: HeliumConfig;\n workers?: WorkerEntry[];\n ssrPages?: SSRPageDef[];\n appShell?: (() => Promise<ComponentType<{ Component: ComponentType<Record<string, unknown>>; pageProps: Record<string, unknown>; children?: ReactNode }>>) | null;\n}\n\n/**\n * Starts a production HTTP server that:\n * - Serves static files from the dist directory\n * - Supports SSG (Static Site Generation) by serving .html files for routes (e.g., /about -> about.html)\n * - Falls back to index.html for client-side routing (SPA)\n * - Handles custom HTTP endpoints (webhooks, auth, etc.)\n * - Hosts WebSocket RPC server\n * - Starts background workers\n *\n * SSG Behavior:\n * - Production correctly serves SSG pages (e.g., /about serves about.html with pre-rendered content)\n * - This ensures search engines and social media crawlers see the correct content\n * - Client-side navigation between pages still works via React Router\n */\nexport function startProdServer(options: ProdServerOptions) {\n const {\n port = Number(process.env.PORT || 3000),\n distDir = \"dist\",\n staticDir = path.resolve(process.cwd(), distDir),\n registerHandlers,\n config = {},\n workers = [],\n ssrPages = [],\n appShell = null,\n } = options;\n\n // Load configuration\n const trustProxyDepth = getTrustProxyDepth(config);\n const rpcSecurity = getRpcSecurityConfig(config);\n const rpcConfig = getRpcConfig(config);\n const compressionConfig = rpcConfig.compression;\n initializeSecurity(rpcSecurity);\n\n // Initialize rate limiter\n const rateLimiter = new RateLimiter(rpcSecurity.maxMessagesPerWindow, rpcSecurity.rateLimitWindowMs, rpcSecurity.maxConnectionsPerIP);\n\n const registry = new RpcRegistry();\n const httpRouter = new HTTPRouter({ maxBodySize: rpcConfig.maxBodySize });\n const seoRouter = new SEOMetadataRouter();\n httpRouter.setTrustProxyDepth(trustProxyDepth);\n registerHandlers(registry, httpRouter, seoRouter);\n registry.setRateLimiter(rateLimiter);\n registry.setMaxBatchSize(rpcConfig.maxBatchSize);\n\n // Security: max body size for HTTP requests (1 MB default)\n const maxBodySize = rpcConfig.maxBodySize ?? 1_048_576;\n let cachedDefaultMeta: Awaited<ReturnType<typeof loadDefaultSocialMetaFromHtmlFile>> | undefined;\n\n const getDefaultMeta = async () => {\n if (cachedDefaultMeta !== undefined) {\n return cachedDefaultMeta;\n }\n\n cachedDefaultMeta = await loadDefaultSocialMetaFromHtmlFile(path.join(staticDir, \"index.html\"));\n return cachedDefaultMeta;\n };\n\n registry.register(SEO_METADATA_RPC_METHOD, {\n __kind: \"method\",\n __id: SEO_METADATA_RPC_METHOD,\n handler: async (args: { path?: string } | undefined, ctx: HeliumContext) => {\n const requestedPath = typeof args?.path === \"string\" ? args.path : \"/\";\n const targetPath = requestedPath.startsWith(\"/\") ? requestedPath : `/${requestedPath}`;\n const metadata = await seoRouter.resolve(ctx.req.raw, ctx, targetPath);\n return metadata ?? (await getDefaultMeta());\n },\n });\n\n // Create HTTP server\n const server = http.createServer(async (req, res) => {\n // Apply security headers to all responses\n setSecurityHeaders(res, config);\n\n // Handle CORS preflight\n if (req.method === \"OPTIONS\") {\n handleCorsHeaders(req, res, config);\n res.writeHead(204);\n res.end();\n return;\n }\n handleCorsHeaders(req, res, config);\n\n // Handle token refresh endpoint\n const requestUrl = new URL(req.url || \"/\", \"http://localhost\");\n const requestPathname = requestUrl.pathname;\n\n if (requestPathname === \"/__helium__/page-props\" && req.method === \"GET\") {\n const pathQuery = requestUrl.searchParams.get(\"path\") || \"/\";\n const targetUrl = new URL(pathQuery, \"http://localhost\");\n const targetPathname = targetUrl.pathname;\n const ssrMatch = matchSSRPage(targetPathname, ssrPages);\n\n if (!ssrMatch) {\n res.writeHead(200, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: false, props: null }));\n return;\n }\n\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n try {\n const ssrResult = await resolveServerSideProps({\n req,\n pathname: targetPathname,\n params: ssrMatch.params,\n page: ssrMatch.page,\n ctx: httpCtx,\n });\n\n if (ssrResult.kind === \"redirect\") {\n res.writeHead(200, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: true, redirect: ssrResult.redirect }));\n return;\n }\n\n res.writeHead(200, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: true, props: ssrResult.props }));\n } catch (error) {\n log(\"error\", \"Failed to resolve SSR page props:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify({ ssr: true, props: null, error: \"Internal server error\" }));\n }\n\n return;\n }\n\n if (req.url === \"/__helium__/refresh-token\") {\n // Security: only allow POST to prevent CSRF via <img>/<script> tags\n if (req.method !== \"POST\") {\n res.writeHead(405, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Method not allowed\" }));\n return;\n }\n // Security: require custom header to prevent cross-origin requests\n if (!req.headers[\"x-requested-with\"]) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Forbidden\" }));\n return;\n }\n const token = generateConnectionToken();\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ token }));\n return;\n }\n\n // Handle HTTP-based RPC endpoint (alternative to WebSocket for mobile networks)\n if (req.url === \"/__helium__/rpc\" && req.method === \"POST\") {\n // Security: verify connection token for HTTP RPC\n const authToken = req.headers[\"x-helium-token\"] as string | undefined;\n if (!authToken || !verifyConnectionToken(authToken)) {\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Unauthorized\" }));\n return;\n }\n\n // Security: check Content-Length before reading body\n const contentLength = parseInt(req.headers[\"content-length\"] || \"0\", 10);\n if (contentLength > maxBodySize) {\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n let aborted = false;\n req.on(\"data\", (chunk: Buffer) => {\n totalSize += chunk.length;\n if (totalSize > maxBodySize) {\n aborted = true;\n req.destroy();\n res.writeHead(413, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Request entity too large\" }));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", async () => {\n if (aborted) {\n return;\n }\n try {\n const body = Buffer.concat(chunks);\n const ip = extractClientIP(req, trustProxyDepth);\n const result = await registry.handleHttpRequest(body, ip, req);\n\n const encoded = msgpackEncode(prepareForMsgpack(result.response));\n let responseBody = Buffer.from(encoded as Uint8Array);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/msgpack\",\n \"Cache-Control\": \"no-store\",\n };\n\n // Handle compression\n const acceptEncoding = req.headers[\"accept-encoding\"] as string;\n if (acceptEncoding && responseBody.length > 1024) {\n if (acceptEncoding.includes(\"br\")) {\n responseBody = await brotliCompressAsync(responseBody);\n headers[\"Content-Encoding\"] = \"br\";\n } else if (acceptEncoding.includes(\"gzip\")) {\n responseBody = await gzipAsync(responseBody);\n headers[\"Content-Encoding\"] = \"gzip\";\n } else if (acceptEncoding.includes(\"deflate\")) {\n responseBody = await deflateAsync(responseBody);\n headers[\"Content-Encoding\"] = \"deflate\";\n }\n }\n\n res.writeHead(200, headers);\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"HTTP RPC error:\", error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: false, error: \"Internal server error\" }));\n }\n });\n return;\n }\n\n // Try HTTP handlers first (webhooks, auth, etc.)\n const handled = await httpRouter.handleRequest(req, res);\n if (handled) {\n return;\n }\n\n // Serve static files\n const url = req.url || \"/\";\n\n // Block access to sensitive configuration and server files\n const blockedFiles = [\"helium.config.js\", \"helium.config.mjs\", \"helium.config.ts\", \"server.js\", \".env\", \".env.local\", \".env.production\"];\n\n const requestedFile = path.basename(url.split(\"?\")[0]);\n let filePath: string = path.join(staticDir, \"index.html\");\n let is404 = false;\n\n if (blockedFiles.some((blocked) => requestedFile === blocked || requestedFile.startsWith(\".env\"))) {\n // Serve index.html so the SPA router can render the 404 page\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n } else {\n // Clean URL (remove query params and trailing slash)\n const cleanUrl = url.split(\"?\")[0].replace(/\\/$/, \"\") || \"/\";\n\n // Security: path traversal prevention — resolve and verify\n const resolvedStaticDir = path.resolve(staticDir);\n const candidatePath = path.resolve(staticDir, \".\" + cleanUrl);\n if (!candidatePath.startsWith(resolvedStaticDir + path.sep) && candidatePath !== resolvedStaticDir) {\n filePath = path.join(staticDir, \"index.html\");\n is404 = true;\n }\n\n // Try different file paths for SSG support\n if (!is404 && cleanUrl === \"/\") {\n // Try index.ssg.html first (if root page has SSG)\n const ssgIndexPath = path.join(staticDir, \"index.ssg.html\");\n if (fs.existsSync(ssgIndexPath)) {\n filePath = ssgIndexPath;\n } else {\n filePath = path.join(staticDir, \"index.html\");\n }\n } else if (!is404) {\n // If cleanUrl has no extension, prioritize .html files for SSG pages\n if (!path.extname(cleanUrl)) {\n const htmlPath = path.join(staticDir, cleanUrl + \".html\");\n if (fs.existsSync(htmlPath)) {\n filePath = htmlPath;\n } else {\n // Fall back to exact path (for assets or directories)\n filePath = path.join(staticDir, cleanUrl);\n }\n } else {\n // Has an extension, try exact path (for assets like /assets/main.js)\n filePath = path.join(staticDir, cleanUrl);\n }\n }\n\n // If file doesn't exist or is a directory, fall back to index.html for SPA routing\n const isFileOrExists = !is404 && filePath && fs.existsSync(filePath) && fs.statSync(filePath).isFile();\n if (!isFileOrExists && !url.startsWith(\"/api\") && !url.startsWith(\"/webhooks\") && !url.startsWith(\"/auth\")) {\n // Fall back to index.html for SPA routing\n // Note: We don't set is404 here because the client-side router will determine\n // if the route exists. If it doesn't, the router will render the 404 page.\n filePath = path.join(staticDir, \"index.html\");\n // Don't set is404 = true here - let the client-side router handle it\n }\n }\n\n // Check if file exists (should always exist now since we fallback to index.html)\n if (!fs.existsSync(filePath)) {\n // This should rarely happen - only if index.html itself is missing\n res.writeHead(404, { \"Content-Type\": \"text/html\" });\n res.end(\"Not found\");\n return;\n }\n\n // Determine content type\n const ext = path.extname(filePath);\n const contentTypes: Record<string, string> = {\n \".html\": \"text/html\",\n \".js\": \"application/javascript\",\n \".css\": \"text/css\",\n \".json\": \"application/json\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".eot\": \"application/vnd.ms-fontobject\",\n };\n const contentType = contentTypes[ext] || \"application/octet-stream\";\n\n try {\n const content = fs.readFileSync(filePath);\n let responseBody = content;\n const cleanedPathname = (req.url || \"/\").split(\"?\")[0].replace(/\\/$/, \"\") || \"/\";\n const htmlSsrMatch = req.method === \"GET\" && contentType === \"text/html\" ? matchSSRPage(cleanedPathname, ssrPages) : null;\n\n if (!is404 && contentType === \"text/html\") {\n const ip = extractClientIP(req, trustProxyDepth);\n const httpCtx: HeliumContext = {\n req: {\n ip,\n headers: req.headers,\n url: req.url,\n method: req.method,\n raw: req,\n },\n };\n\n const metadata = await seoRouter.resolve(req, httpCtx);\n let html = content.toString(\"utf-8\");\n\n if (htmlSsrMatch) {\n try {\n const rendered = await renderSSRHTML({\n htmlTemplate: html,\n pathname: cleanedPathname,\n search: requestUrl.search,\n params: htmlSsrMatch.params,\n page: htmlSsrMatch.page,\n req,\n ctx: httpCtx,\n loadAppShell: appShell,\n });\n\n if (\"redirect\" in rendered) {\n res.writeHead(rendered.redirect.statusCode, {\n Location: rendered.redirect.destination,\n \"Cache-Control\": \"no-store\",\n });\n res.end();\n return;\n }\n\n html = rendered.html;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const isBrowserGlobalError = /\\bwindow is not defined\\b|\\bdocument is not defined\\b|\\bnavigator is not defined\\b/i.test(message);\n\n if (isBrowserGlobalError) {\n log(\n \"warn\",\n `SSR disabled for ${cleanedPathname} due to browser-only import. Render map/browser-only modules on client only (e.g. dynamic import inside useEffect).`\n );\n } else {\n log(\"error\", `Failed to render SSR page for ${cleanedPathname}:`, error);\n }\n }\n }\n\n if (metadata) {\n html = injectSocialMetaIntoHtml(html, metadata);\n }\n\n // Inject runtime public env vars (for platform deployments like Render, DO Apps)\n html = injectPublicEnvIntoHtml(html);\n\n responseBody = Buffer.from(html, \"utf-8\");\n }\n\n // Set status code to 404 if serving the 404 page\n const statusCode = is404 ? 404 : 200;\n res.writeHead(statusCode, { \"Content-Type\": contentType });\n res.end(responseBody);\n } catch (error) {\n log(\"error\", \"Error serving file:\", error);\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n res.end(\"Internal server error\");\n }\n });\n\n // Setup WebSocket server for RPC\n const wss = new WebSocketServer({\n noServer: true,\n maxPayload: rpcConfig.maxWsPayload,\n perMessageDeflate: compressionConfig.enabled\n ? {\n zlibDeflateOptions: {\n chunkSize: 1024,\n memLevel: 7,\n level: 9, // 6 is default compression level (balanced)\n },\n zlibInflateOptions: {\n chunkSize: 10 * 1024,\n },\n threshold: compressionConfig.threshold,\n }\n : false,\n });\n\n wss.on(\"connection\", (socket: WebSocket, req: http.IncomingMessage) => {\n // Extract client IP with proxy configuration\n const ip = extractClientIP(req, trustProxyDepth);\n\n // Store connection metadata for RPC context\n registry.setSocketMetadata(socket, ip, req);\n\n // Track connection and check IP limit\n if (!rateLimiter.trackConnection(socket, ip)) {\n socket.close(1008, \"Too many connections from your IP\");\n return;\n }\n\n // Prevent unhandled errors from crashing the process (e.g. maxPayload exceeded)\n socket.on(\"error\", (err) => {\n log(\"warn\", \"WebSocket error:\", err);\n if (socket.readyState === socket.OPEN || socket.readyState === socket.CLOSING) {\n socket.close(1009, \"Message too large\");\n }\n });\n\n socket.on(\"message\", (msg: WebSocket.RawData, _isBinary: boolean) => {\n // Check rate limit\n if (!rateLimiter.checkRateLimit(socket)) {\n // Parse request to get the ID for proper error response\n try {\n let req: any;\n // Always expect MessagePack\n const buffer = Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any);\n const { decode: msgpackDecode } = require(\"@msgpack/msgpack\");\n req = msgpackDecode(buffer);\n\n const stats = rateLimiter.getConnectionStats(socket);\n const now = Date.now();\n const resetInSeconds = stats ? Math.ceil((stats.resetTimeMs - now) / 1000) : 0;\n\n const createError = (id: string) => ({\n id,\n ok: false,\n stats: {\n remainingRequests: stats ? stats.remainingMessages : 0,\n resetInSeconds,\n },\n error: \"Rate limit exceeded\",\n });\n\n let errorResponse: any;\n if (Array.isArray(req)) {\n errorResponse = req.map((r: any) => createError(r.id));\n } else {\n errorResponse = createError(req.id);\n }\n\n log(\"warn\", `Rate limit exceeded for IP ${ip}, resets in ${resetInSeconds} seconds`);\n socket.send(msgpackEncode(errorResponse) as Buffer);\n } catch {\n // If we can't parse the request, just close the connection\n socket.close();\n }\n return;\n }\n\n registry.handleMessage(socket, Buffer.isBuffer(msg) ? msg : Buffer.from(msg as any));\n });\n });\n\n // Handle WebSocket upgrade requests\n server.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/rpc\")) {\n // Security: read token from Sec-WebSocket-Protocol header instead of query string\n const protocols = req.headers[\"sec-websocket-protocol\"];\n const token =\n typeof protocols === \"string\"\n ? protocols\n .split(\",\")\n .map((p) => p.trim())\n .find((p) => p.includes(\".\"))\n : undefined;\n\n if (!token || !verifyConnectionToken(token)) {\n log(\"warn\", \"WebSocket connection rejected - invalid token\");\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n // Check IP connection limit before upgrading\n const ip = extractClientIP(req, trustProxyDepth);\n if (rpcSecurity.maxConnectionsPerIP > 0) {\n const currentConnections = rateLimiter.getIPConnectionCount(ip);\n if (currentConnections >= rpcSecurity.maxConnectionsPerIP) {\n log(\"warn\", `WebSocket connection rejected - IP ${ip} has ${currentConnections} connections`);\n socket.write(\"HTTP/1.1 429 Too Many Requests\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit(\"connection\", ws, req);\n });\n } else {\n socket.destroy();\n }\n });\n\n // Start server\n server.listen(port, () => {\n log(\"info\", `Production server listening on http://localhost:${port}`);\n log(\"info\", `Serving static files from ${staticDir}`);\n log(\"info\", `WebSocket RPC available at ws://localhost:${port}/rpc`);\n\n // Start workers\n if (workers.length > 0) {\n log(\"info\", `Starting ${workers.length} worker(s)...`);\n for (const { name, worker } of workers) {\n // Use export name if worker name is anonymous\n if (worker.name === \"anonymous\") {\n worker.name = name;\n worker.__id = name;\n worker.options.name = name;\n }\n if (worker.options.autoStart) {\n const createContext = (): HeliumContext => ({\n req: {\n ip: \"127.0.0.1\",\n headers: {},\n url: undefined,\n method: undefined,\n raw: {} as http.IncomingMessage,\n },\n });\n startWorker(worker, createContext).catch((err) => {\n log(\"error\", `Failed to start worker '${worker.name}':`, err);\n });\n }\n }\n }\n });\n\n // Handle graceful shutdown\n const shutdown = async () => {\n log(\"info\", \"Shutting down...\");\n await stopAllWorkers();\n server.close(() => {\n log(\"info\", \"Server closed\");\n process.exit(0);\n });\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n return server;\n}\n\n// ============================================================================\n// Security helper functions\n// ============================================================================\n\n/**\n * Set default security headers on every HTTP response.\n */\nfunction setSecurityHeaders(res: http.ServerResponse, config: HeliumConfig): void {\n const headers = getSecurityHeaders(config);\n\n for (const [name, value] of Object.entries(headers)) {\n if (value === null) {\n res.removeHeader(name);\n continue;\n }\n res.setHeader(name, value);\n }\n}\n\n/**\n * Resolve security headers for the current request from config.\n * Returns a final header map where `null` indicates the header should be removed.\n *\n * @internal\n */\nexport function getSecurityHeaders(config: HeliumConfig): Record<string, string | null> {\n const headers: Record<string, string | null> = {};\n const securityConfig = config.security;\n\n if (securityConfig?.defaultHeaders !== false) {\n headers[\"X-Content-Type-Options\"] = \"nosniff\";\n headers[\"X-Frame-Options\"] = \"DENY\";\n headers[\"X-XSS-Protection\"] = \"0\";\n headers[\"Referrer-Policy\"] = \"strict-origin-when-cross-origin\";\n headers[\"Permissions-Policy\"] = \"camera=(), microphone=(), geolocation=()\";\n\n const csp = securityConfig?.contentSecurityPolicy;\n if (csp) {\n headers[\"Content-Security-Policy\"] = csp;\n }\n\n if (securityConfig?.hsts !== false) {\n headers[\"Strict-Transport-Security\"] = \"max-age=31536000; includeSubDomains\";\n }\n }\n\n if (securityConfig?.headerOverrides) {\n for (const [name, value] of Object.entries(securityConfig.headerOverrides)) {\n headers[name] = value;\n }\n }\n\n return headers;\n}\n\n/**\n * Handle CORS headers based on configuration.\n * Default: restrict to same-origin (no CORS header = browser blocks cross-origin).\n */\nfunction handleCorsHeaders(req: http.IncomingMessage, res: http.ServerResponse, config: HeliumConfig): void {\n const allowedOrigins = config.security?.corsOrigins;\n if (!allowedOrigins || allowedOrigins.length === 0) {\n // No CORS configured — same-origin only by default\n return;\n }\n\n const origin = req.headers.origin;\n if (!origin) {\n return;\n }\n\n const isAllowed = allowedOrigins.includes(\"*\") || allowedOrigins.includes(origin);\n if (isAllowed) {\n res.setHeader(\"Access-Control-Allow-Origin\", allowedOrigins.includes(\"*\") ? \"*\" : origin);\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, X-Requested-With, X-Helium-Token\");\n res.setHeader(\"Access-Control-Max-Age\", \"86400\");\n\n if (!allowedOrigins.includes(\"*\")) {\n res.setHeader(\"Vary\", \"Origin\");\n }\n }\n}\n"]}
|
|
@@ -2,6 +2,12 @@ export interface EnvLoadOptions {
|
|
|
2
2
|
root?: string;
|
|
3
3
|
mode?: string;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Collects HELIUM_PUBLIC_ prefixed variables from process.env.
|
|
7
|
+
* Used as a fallback for platform environments (Render, DigitalOcean Apps, etc.)
|
|
8
|
+
* where env vars are set as platform variables rather than .env files.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getPublicEnvFromProcess(prefix?: string): Record<string, string>;
|
|
5
11
|
/**
|
|
6
12
|
* Loads environment variables from .env files with priority.
|
|
7
13
|
* Similar to Next.js, supports:
|
|
@@ -9,6 +15,12 @@ export interface EnvLoadOptions {
|
|
|
9
15
|
* - .env.local (not loaded in test mode)
|
|
10
16
|
* - .env.{mode}
|
|
11
17
|
* - .env
|
|
18
|
+
* - process.env HELIUM_PUBLIC_* variables (lowest priority fallback)
|
|
19
|
+
*
|
|
20
|
+
* Platform environment variables (process.env) are used as the base layer,
|
|
21
|
+
* so .env file values always take precedence. This ensures compatibility
|
|
22
|
+
* with platforms like Render, DigitalOcean Apps, and Railway where env vars
|
|
23
|
+
* are set as platform variables rather than .env files.
|
|
12
24
|
*/
|
|
13
25
|
export declare function loadEnvFiles(options?: EnvLoadOptions): Record<string, string>;
|
|
14
26
|
/**
|
|
@@ -24,4 +36,19 @@ export declare function filterClientEnv(env: Record<string, string>, prefix?: st
|
|
|
24
36
|
* Creates Vite define config for injecting env variables into the client bundle.
|
|
25
37
|
*/
|
|
26
38
|
export declare function createEnvDefines(env: Record<string, string>, prefix?: string): Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Generates an inline <script> tag that injects HELIUM_PUBLIC_ env vars
|
|
41
|
+
* into import.meta.env at runtime. This is used by the production server
|
|
42
|
+
* to ensure platform environment variables are available even if they
|
|
43
|
+
* weren't present at build time.
|
|
44
|
+
*
|
|
45
|
+
* The script is injected before module scripts in <head>, so the values
|
|
46
|
+
* are available when application code runs.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildPublicEnvScript(prefix?: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Injects the public env script into an HTML string, placing it
|
|
51
|
+
* at the beginning of <head> so it runs before any module scripts.
|
|
52
|
+
*/
|
|
53
|
+
export declare function injectPublicEnvIntoHtml(html: string, prefix?: string): string;
|
|
27
54
|
//# sourceMappingURL=envLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envLoader.d.ts","sourceRoot":"","sources":["../../src/utils/envLoader.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"envLoader.d.ts","sourceRoot":"","sources":["../../src/utils/envLoader.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,GAAE,MAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUjG;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,cAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA0BjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAOpE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAE,MAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUtH;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAE,MAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASvH;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,GAAE,MAAyB,GAAG,MAAM,CAS9E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAyB,GAAG,MAAM,CAe/F"}
|
package/dist/utils/envLoader.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import dotenv from "dotenv";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
|
+
/**
|
|
5
|
+
* Collects HELIUM_PUBLIC_ prefixed variables from process.env.
|
|
6
|
+
* Used as a fallback for platform environments (Render, DigitalOcean Apps, etc.)
|
|
7
|
+
* where env vars are set as platform variables rather than .env files.
|
|
8
|
+
*/
|
|
9
|
+
export function getPublicEnvFromProcess(prefix = "HELIUM_PUBLIC_") {
|
|
10
|
+
const publicEnv = {};
|
|
11
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
12
|
+
if (key.startsWith(prefix) && value !== undefined) {
|
|
13
|
+
publicEnv[key] = value;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return publicEnv;
|
|
17
|
+
}
|
|
4
18
|
/**
|
|
5
19
|
* Loads environment variables from .env files with priority.
|
|
6
20
|
* Similar to Next.js, supports:
|
|
@@ -8,6 +22,12 @@ import path from "path";
|
|
|
8
22
|
* - .env.local (not loaded in test mode)
|
|
9
23
|
* - .env.{mode}
|
|
10
24
|
* - .env
|
|
25
|
+
* - process.env HELIUM_PUBLIC_* variables (lowest priority fallback)
|
|
26
|
+
*
|
|
27
|
+
* Platform environment variables (process.env) are used as the base layer,
|
|
28
|
+
* so .env file values always take precedence. This ensures compatibility
|
|
29
|
+
* with platforms like Render, DigitalOcean Apps, and Railway where env vars
|
|
30
|
+
* are set as platform variables rather than .env files.
|
|
11
31
|
*/
|
|
12
32
|
export function loadEnvFiles(options = {}) {
|
|
13
33
|
const { root = process.cwd(), mode = process.env.NODE_ENV || "development" } = options;
|
|
@@ -18,7 +38,8 @@ export function loadEnvFiles(options = {}) {
|
|
|
18
38
|
`.env.${mode}`,
|
|
19
39
|
`.env`,
|
|
20
40
|
].filter(Boolean);
|
|
21
|
-
|
|
41
|
+
// Start with platform env vars as the lowest-priority base layer
|
|
42
|
+
const loadedEnv = getPublicEnvFromProcess();
|
|
22
43
|
// Load in reverse order so earlier files override later ones
|
|
23
44
|
for (let i = envFiles.length - 1; i >= 0; i--) {
|
|
24
45
|
const envFile = envFiles[i];
|
|
@@ -65,4 +86,38 @@ export function createEnvDefines(env, prefix = "HELIUM_PUBLIC_") {
|
|
|
65
86
|
}
|
|
66
87
|
return defines;
|
|
67
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Generates an inline <script> tag that injects HELIUM_PUBLIC_ env vars
|
|
91
|
+
* into import.meta.env at runtime. This is used by the production server
|
|
92
|
+
* to ensure platform environment variables are available even if they
|
|
93
|
+
* weren't present at build time.
|
|
94
|
+
*
|
|
95
|
+
* The script is injected before module scripts in <head>, so the values
|
|
96
|
+
* are available when application code runs.
|
|
97
|
+
*/
|
|
98
|
+
export function buildPublicEnvScript(prefix = "HELIUM_PUBLIC_") {
|
|
99
|
+
const publicEnv = getPublicEnvFromProcess(prefix);
|
|
100
|
+
if (Object.keys(publicEnv).length === 0) {
|
|
101
|
+
return "";
|
|
102
|
+
}
|
|
103
|
+
const envJson = JSON.stringify(publicEnv);
|
|
104
|
+
return `<script>window.__HELIUM_PUBLIC_ENV__=${envJson}</script>`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Injects the public env script into an HTML string, placing it
|
|
108
|
+
* at the beginning of <head> so it runs before any module scripts.
|
|
109
|
+
*/
|
|
110
|
+
export function injectPublicEnvIntoHtml(html, prefix = "HELIUM_PUBLIC_") {
|
|
111
|
+
const script = buildPublicEnvScript(prefix);
|
|
112
|
+
if (!script) {
|
|
113
|
+
return html;
|
|
114
|
+
}
|
|
115
|
+
// Inject at the start of <head> so it runs before module scripts
|
|
116
|
+
const headMatch = html.match(/<head[^>]*>/i);
|
|
117
|
+
if (headMatch) {
|
|
118
|
+
return html.replace(headMatch[0], `${headMatch[0]}\n${script}`);
|
|
119
|
+
}
|
|
120
|
+
// Fallback: prepend to HTML
|
|
121
|
+
return `${script}\n${html}`;
|
|
122
|
+
}
|
|
68
123
|
//# sourceMappingURL=envLoader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envLoader.js","sourceRoot":"","sources":["../../src/utils/envLoader.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB
|
|
1
|
+
{"version":3,"file":"envLoader.js","sourceRoot":"","sources":["../../src/utils/envLoader.ts"],"names":[],"mappings":"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","sourcesContent":["import dotenv from \"dotenv\";\nimport fs from \"fs\";\nimport path from \"path\";\n\nexport interface EnvLoadOptions {\n root?: string;\n mode?: string;\n}\n\n/**\n * Collects HELIUM_PUBLIC_ prefixed variables from process.env.\n * Used as a fallback for platform environments (Render, DigitalOcean Apps, etc.)\n * where env vars are set as platform variables rather than .env files.\n */\nexport function getPublicEnvFromProcess(prefix: string = \"HELIUM_PUBLIC_\"): Record<string, string> {\n const publicEnv: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(process.env)) {\n if (key.startsWith(prefix) && value !== undefined) {\n publicEnv[key] = value;\n }\n }\n\n return publicEnv;\n}\n\n/**\n * Loads environment variables from .env files with priority.\n * Similar to Next.js, supports:\n * - .env.{mode}.local (highest priority)\n * - .env.local (not loaded in test mode)\n * - .env.{mode}\n * - .env\n * - process.env HELIUM_PUBLIC_* variables (lowest priority fallback)\n *\n * Platform environment variables (process.env) are used as the base layer,\n * so .env file values always take precedence. This ensures compatibility\n * with platforms like Render, DigitalOcean Apps, and Railway where env vars\n * are set as platform variables rather than .env files.\n */\nexport function loadEnvFiles(options: EnvLoadOptions = {}): Record<string, string> {\n const { root = process.cwd(), mode = process.env.NODE_ENV || \"development\" } = options;\n\n const envFiles = [\n `.env.${mode}.local`,\n // Don't load .env.local in test mode\n mode !== \"test\" ? `.env.local` : null,\n `.env.${mode}`,\n `.env`,\n ].filter(Boolean) as string[];\n\n // Start with platform env vars as the lowest-priority base layer\n const loadedEnv: Record<string, string> = getPublicEnvFromProcess();\n\n // Load in reverse order so earlier files override later ones\n for (let i = envFiles.length - 1; i >= 0; i--) {\n const envFile = envFiles[i];\n const envPath = path.resolve(root, envFile);\n\n if (fs.existsSync(envPath)) {\n const parsed = dotenv.parse(fs.readFileSync(envPath, \"utf-8\"));\n Object.assign(loadedEnv, parsed);\n }\n }\n\n return loadedEnv;\n}\n\n/**\n * Injects env variables into process.env\n */\nexport function injectEnvToProcess(env: Record<string, string>): void {\n for (const [key, value] of Object.entries(env)) {\n // Don't override existing process.env values\n if (process.env[key] === undefined) {\n process.env[key] = value;\n }\n }\n}\n\n/**\n * Filters env variables that should be exposed to the client.\n * By default, only HELIUM_PUBLIC_ prefixed variables are exposed.\n */\nexport function filterClientEnv(env: Record<string, string>, prefix: string = \"HELIUM_PUBLIC_\"): Record<string, string> {\n const clientEnv: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(env)) {\n if (key.startsWith(prefix)) {\n clientEnv[key] = value;\n }\n }\n\n return clientEnv;\n}\n\n/**\n * Creates Vite define config for injecting env variables into the client bundle.\n */\nexport function createEnvDefines(env: Record<string, string>, prefix: string = \"HELIUM_PUBLIC_\"): Record<string, string> {\n const defines: Record<string, string> = {};\n const clientEnv = filterClientEnv(env, prefix);\n\n for (const [key, value] of Object.entries(clientEnv)) {\n defines[`import.meta.env.${key}`] = JSON.stringify(value);\n }\n\n return defines;\n}\n\n/**\n * Generates an inline <script> tag that injects HELIUM_PUBLIC_ env vars\n * into import.meta.env at runtime. This is used by the production server\n * to ensure platform environment variables are available even if they\n * weren't present at build time.\n *\n * The script is injected before module scripts in <head>, so the values\n * are available when application code runs.\n */\nexport function buildPublicEnvScript(prefix: string = \"HELIUM_PUBLIC_\"): string {\n const publicEnv = getPublicEnvFromProcess(prefix);\n\n if (Object.keys(publicEnv).length === 0) {\n return \"\";\n }\n\n const envJson = JSON.stringify(publicEnv);\n return `<script>window.__HELIUM_PUBLIC_ENV__=${envJson}</script>`;\n}\n\n/**\n * Injects the public env script into an HTML string, placing it\n * at the beginning of <head> so it runs before any module scripts.\n */\nexport function injectPublicEnvIntoHtml(html: string, prefix: string = \"HELIUM_PUBLIC_\"): string {\n const script = buildPublicEnvScript(prefix);\n\n if (!script) {\n return html;\n }\n\n // Inject at the start of <head> so it runs before module scripts\n const headMatch = html.match(/<head[^>]*>/i);\n if (headMatch) {\n return html.replace(headMatch[0], `${headMatch[0]}\\n${script}`);\n }\n\n // Fallback: prepend to HTML\n return `${script}\\n${html}`;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualServerModule.d.ts","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjI,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,iBAAiB,EAAE,EACjC,WAAW,GAAE,iBAAiB,EAAO,EACrC,iBAAiB,GAAE,MAAM,EAAO,EAChC,QAAQ,GAAE,aAAa,EAAO,EAC9B,gBAAgB,GAAE,MAAM,GAAG,IAAW,EACtC,UAAU,CAAC,EAAE,gBAAgB,EAC7B,OAAO,GAAE,YAAY,EAAO,GAC7B,MAAM,CAmGR;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAIpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiErF;AAED,wBAAgB,mBAAmB,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"virtualServerModule.d.ts","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjI,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,iBAAiB,EAAE,EACjC,WAAW,GAAE,iBAAiB,EAAO,EACrC,iBAAiB,GAAE,MAAM,EAAO,EAChC,QAAQ,GAAE,aAAa,EAAO,EAC9B,gBAAgB,GAAE,MAAM,GAAG,IAAW,EACtC,UAAU,CAAC,EAAE,gBAAgB,EAC7B,OAAO,GAAE,YAAY,EAAO,GAC7B,MAAM,CAmGR;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAIpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiErF;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CA+B5C"}
|
|
@@ -159,9 +159,16 @@ import { createRoot, hydrateRoot } from 'react-dom/client';
|
|
|
159
159
|
import { AppRouter } from 'heliumts/client';
|
|
160
160
|
import App from '/src/App';
|
|
161
161
|
|
|
162
|
+
// Merge runtime public env vars injected by the production server.
|
|
163
|
+
// This ensures platform env vars (Render, DigitalOcean Apps, etc.) are
|
|
164
|
+
// available via import.meta.env even if they weren't present at build time.
|
|
165
|
+
if (typeof window !== 'undefined' && window.__HELIUM_PUBLIC_ENV__) {
|
|
166
|
+
Object.assign(import.meta.env, window.__HELIUM_PUBLIC_ENV__);
|
|
167
|
+
}
|
|
168
|
+
|
|
162
169
|
const rootEl = document.getElementById('root');
|
|
163
170
|
if (!rootEl) {
|
|
164
|
-
throw new Error('Root element not found. Helium requires a <div id
|
|
171
|
+
throw new Error('Root element not found. Helium requires a <div id="root"></div> in your HTML.');
|
|
165
172
|
}
|
|
166
173
|
|
|
167
174
|
const app = (
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualServerModule.js","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\n\nimport { HTTPHandlerExport, MethodExport, MiddlewareExport, SEOMetadataExport, SSRPageExport, WorkerExport } from \"./scanner.js\";\n\nexport function generateServerManifest(\n methods: MethodExport[],\n httpHandlers: HTTPHandlerExport[],\n seoMetadata: SEOMetadataExport[] = [],\n pageRoutePatterns: string[] = [],\n ssrPages: SSRPageExport[] = [],\n appShellFilePath: string | null = null,\n middleware?: MiddlewareExport,\n workers: WorkerExport[] = []\n): string {\n const methodImports = methods.map((m, i) => `import { ${m.name} as method_${i} } from '${m.filePath}';`).join(\"\\n\");\n const httpImports = httpHandlers.map((h, i) => `import { ${h.name} as http_${i} } from '${h.filePath}';`).join(\"\\n\");\n const seoImports = seoMetadata.map((s, i) => `import { ${s.name} as seo_${i} } from '${s.filePath}';`).join(\"\\n\");\n const workerImports = workers.map((w, i) => `import { ${w.name} as worker_${i} } from '${w.filePath}';`).join(\"\\n\");\n const middlewareImport = middleware ? `import ${middleware.name === \"default\" ? \"middleware\" : `{ ${middleware.name} as middleware }`} from '${middleware.filePath}';` : \"\";\n\n const methodRegistrations = methods.map((m, i) => ` registry.register('${m.name}', method_${i});`).join(\"\\n\");\n\n const httpExports = httpHandlers.map((h, i) => ` { name: '${h.name}', handler: http_${i} },`).join(\"\\n\");\n const seoExports = seoMetadata.map((s, i) => ` { name: '${s.name}', handler: seo_${i} },`).join(\"\\n\");\n\n const workerExports = workers.map((w, i) => ` { name: '${w.name}', worker: worker_${i} },`).join(\"\\n\");\n\n const ssrPageExports = ssrPages\n .map((s, i) => {\n const loadLayoutsBody = s.layoutFilePaths\n .map(\n (layoutPath, layoutIndex) => ` {\n const mod_${layoutIndex} = await import('${layoutPath}');\n if (mod_${layoutIndex}.default) {\n layouts.push(mod_${layoutIndex}.default);\n }\n }`\n )\n .join(\"\\n\");\n\n const sidecarCheck = s.serverFilePath\n ? ` {\n const sidecar = await import('${s.serverFilePath}');\n if (typeof sidecar.getServerSideProps === 'function') {\n return sidecar.getServerSideProps(req, ctx);\n }\n }\n`\n : \"\";\n\n return ` {\n pathPattern: '${s.pathPattern}',\n loadComponent: async () => {\n const page = await import('${s.pageFilePath}');\n return page.default;\n },\n loadLayouts: async () => {\n const layouts = [];\n${loadLayoutsBody}\n return layouts;\n },\n getServerSideProps: async (req, ctx) => {\n${sidecarCheck} const page = await import('${s.pageFilePath}');\n if (typeof page.getServerSideProps === 'function') {\n return page.getServerSideProps(req, ctx);\n }\n return null;\n }\n },`;\n })\n .join(\"\\n\");\n\n return `\n${methodImports}\n${httpImports}\n${seoImports}\n${workerImports}\n${middlewareImport}\n\nexport function registerAll(registry) {\n${methodRegistrations}\n}\n\nexport const httpHandlers = [\n${httpExports}\n];\n\nexport const seoMetadataHandlers = [\n${seoExports}\n];\n\nexport const pageRoutePatterns = ${JSON.stringify(pageRoutePatterns)};\n\nexport const ssrPages = [\n${ssrPageExports}\n];\n\nexport const appShell = ${\n appShellFilePath\n ? `async () => {\n const mod = await import('${appShellFilePath}');\n return mod.default ?? mod.App ?? mod.app ?? null;\n}`\n : \"null\"\n };\n\nexport const workers = [\n${workerExports}\n];\n\nexport const middlewareHandler = ${middleware ? \"middleware\" : \"null\"};\n`;\n}\n\nexport function generateClientModule(methods: MethodExport[]): string {\n const exports = methods.map((m) => `export const ${m.name} = { __id: '${m.name}' };`).join(\"\\n\");\n\n return exports;\n}\n\nexport function generateTypeDefinitions(methods: MethodExport[], root: string): string {\n // Sort methods by name for a stable output regardless of file-system walk order\n const sorted = [...methods].sort((a, b) => a.name.localeCompare(b.name));\n\n const methodsWithRelativePath = sorted.map((m) => {\n let relPath = path.relative(path.join(root, \"src\"), m.filePath);\n if (!relPath.startsWith(\".\")) {\n relPath = \"../\" + relPath;\n }\n // Normalize to posix separators for import paths\n relPath = relPath.replace(/\\\\/g, \"/\").replace(/\\.ts$/, \"\");\n return {\n ...m,\n relPath,\n };\n });\n\n const imports = methodsWithRelativePath\n .map((m, index) => {\n return `import type { ${m.name} as __helium_method_${index} } from '${m.relPath}';`;\n })\n .join(\"\\n\");\n\n const methodExports = methodsWithRelativePath\n .map((m, index) => {\n return ` export const ${m.name}: import('heliumts/client').MethodStub<\n Parameters<typeof __helium_method_${index}['handler']>[0],\n Awaited<ReturnType<typeof __helium_method_${index}['handler']>>\n >;`;\n })\n .join(\"\\n\");\n\n // If there are no methods, we don't need to generate any augmentation\n // This prevents shadowing the actual heliumts/server exports\n if (methods.length === 0) {\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n* \n* This file is empty because no methods have been defined yet.\n* Once you create a method using defineMethod(), type stubs will be generated here.\n*\n* @helium-methods (none)\n**/\nexport {};\n`;\n }\n\n const methodSignature = methodsWithRelativePath.map((m) => m.name).join(\", \");\n\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n*\n* @helium-methods ${methodSignature}\n**/\n${imports}\n\ndeclare module 'heliumts/server' {\n // Method stubs for client-side type inference\n${methodExports}\n}\n`;\n}\n\nexport function generateEntryModule(): string {\n return `\nimport React from 'react';\nimport { createRoot, hydrateRoot } from 'react-dom/client';\nimport { AppRouter } from 'heliumts/client';\nimport App from '/src/App';\n\nconst rootEl = document.getElementById('root');\nif (!rootEl) {\n throw new Error('Root element not found. Helium requires a <div id=\\\"root\\\"></div> in your HTML.');\n}\n\nconst app = (\n <React.StrictMode>\n <AppRouter AppShell={App} />\n </React.StrictMode>\n);\n\nif (rootEl.hasChildNodes()) {\n hydrateRoot(rootEl, app);\n} else {\n createRoot(rootEl).render(app);\n}\n`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"virtualServerModule.js","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\n\nimport { HTTPHandlerExport, MethodExport, MiddlewareExport, SEOMetadataExport, SSRPageExport, WorkerExport } from \"./scanner.js\";\n\nexport function generateServerManifest(\n methods: MethodExport[],\n httpHandlers: HTTPHandlerExport[],\n seoMetadata: SEOMetadataExport[] = [],\n pageRoutePatterns: string[] = [],\n ssrPages: SSRPageExport[] = [],\n appShellFilePath: string | null = null,\n middleware?: MiddlewareExport,\n workers: WorkerExport[] = []\n): string {\n const methodImports = methods.map((m, i) => `import { ${m.name} as method_${i} } from '${m.filePath}';`).join(\"\\n\");\n const httpImports = httpHandlers.map((h, i) => `import { ${h.name} as http_${i} } from '${h.filePath}';`).join(\"\\n\");\n const seoImports = seoMetadata.map((s, i) => `import { ${s.name} as seo_${i} } from '${s.filePath}';`).join(\"\\n\");\n const workerImports = workers.map((w, i) => `import { ${w.name} as worker_${i} } from '${w.filePath}';`).join(\"\\n\");\n const middlewareImport = middleware ? `import ${middleware.name === \"default\" ? \"middleware\" : `{ ${middleware.name} as middleware }`} from '${middleware.filePath}';` : \"\";\n\n const methodRegistrations = methods.map((m, i) => ` registry.register('${m.name}', method_${i});`).join(\"\\n\");\n\n const httpExports = httpHandlers.map((h, i) => ` { name: '${h.name}', handler: http_${i} },`).join(\"\\n\");\n const seoExports = seoMetadata.map((s, i) => ` { name: '${s.name}', handler: seo_${i} },`).join(\"\\n\");\n\n const workerExports = workers.map((w, i) => ` { name: '${w.name}', worker: worker_${i} },`).join(\"\\n\");\n\n const ssrPageExports = ssrPages\n .map((s, i) => {\n const loadLayoutsBody = s.layoutFilePaths\n .map(\n (layoutPath, layoutIndex) => ` {\n const mod_${layoutIndex} = await import('${layoutPath}');\n if (mod_${layoutIndex}.default) {\n layouts.push(mod_${layoutIndex}.default);\n }\n }`\n )\n .join(\"\\n\");\n\n const sidecarCheck = s.serverFilePath\n ? ` {\n const sidecar = await import('${s.serverFilePath}');\n if (typeof sidecar.getServerSideProps === 'function') {\n return sidecar.getServerSideProps(req, ctx);\n }\n }\n`\n : \"\";\n\n return ` {\n pathPattern: '${s.pathPattern}',\n loadComponent: async () => {\n const page = await import('${s.pageFilePath}');\n return page.default;\n },\n loadLayouts: async () => {\n const layouts = [];\n${loadLayoutsBody}\n return layouts;\n },\n getServerSideProps: async (req, ctx) => {\n${sidecarCheck} const page = await import('${s.pageFilePath}');\n if (typeof page.getServerSideProps === 'function') {\n return page.getServerSideProps(req, ctx);\n }\n return null;\n }\n },`;\n })\n .join(\"\\n\");\n\n return `\n${methodImports}\n${httpImports}\n${seoImports}\n${workerImports}\n${middlewareImport}\n\nexport function registerAll(registry) {\n${methodRegistrations}\n}\n\nexport const httpHandlers = [\n${httpExports}\n];\n\nexport const seoMetadataHandlers = [\n${seoExports}\n];\n\nexport const pageRoutePatterns = ${JSON.stringify(pageRoutePatterns)};\n\nexport const ssrPages = [\n${ssrPageExports}\n];\n\nexport const appShell = ${\n appShellFilePath\n ? `async () => {\n const mod = await import('${appShellFilePath}');\n return mod.default ?? mod.App ?? mod.app ?? null;\n}`\n : \"null\"\n };\n\nexport const workers = [\n${workerExports}\n];\n\nexport const middlewareHandler = ${middleware ? \"middleware\" : \"null\"};\n`;\n}\n\nexport function generateClientModule(methods: MethodExport[]): string {\n const exports = methods.map((m) => `export const ${m.name} = { __id: '${m.name}' };`).join(\"\\n\");\n\n return exports;\n}\n\nexport function generateTypeDefinitions(methods: MethodExport[], root: string): string {\n // Sort methods by name for a stable output regardless of file-system walk order\n const sorted = [...methods].sort((a, b) => a.name.localeCompare(b.name));\n\n const methodsWithRelativePath = sorted.map((m) => {\n let relPath = path.relative(path.join(root, \"src\"), m.filePath);\n if (!relPath.startsWith(\".\")) {\n relPath = \"../\" + relPath;\n }\n // Normalize to posix separators for import paths\n relPath = relPath.replace(/\\\\/g, \"/\").replace(/\\.ts$/, \"\");\n return {\n ...m,\n relPath,\n };\n });\n\n const imports = methodsWithRelativePath\n .map((m, index) => {\n return `import type { ${m.name} as __helium_method_${index} } from '${m.relPath}';`;\n })\n .join(\"\\n\");\n\n const methodExports = methodsWithRelativePath\n .map((m, index) => {\n return ` export const ${m.name}: import('heliumts/client').MethodStub<\n Parameters<typeof __helium_method_${index}['handler']>[0],\n Awaited<ReturnType<typeof __helium_method_${index}['handler']>>\n >;`;\n })\n .join(\"\\n\");\n\n // If there are no methods, we don't need to generate any augmentation\n // This prevents shadowing the actual heliumts/server exports\n if (methods.length === 0) {\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n* \n* This file is empty because no methods have been defined yet.\n* Once you create a method using defineMethod(), type stubs will be generated here.\n*\n* @helium-methods (none)\n**/\nexport {};\n`;\n }\n\n const methodSignature = methodsWithRelativePath.map((m) => m.name).join(\", \");\n\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n*\n* @helium-methods ${methodSignature}\n**/\n${imports}\n\ndeclare module 'heliumts/server' {\n // Method stubs for client-side type inference\n${methodExports}\n}\n`;\n}\n\nexport function generateEntryModule(): string {\n return `\nimport React from 'react';\nimport { createRoot, hydrateRoot } from 'react-dom/client';\nimport { AppRouter } from 'heliumts/client';\nimport App from '/src/App';\n\n// Merge runtime public env vars injected by the production server.\n// This ensures platform env vars (Render, DigitalOcean Apps, etc.) are\n// available via import.meta.env even if they weren't present at build time.\nif (typeof window !== 'undefined' && window.__HELIUM_PUBLIC_ENV__) {\n Object.assign(import.meta.env, window.__HELIUM_PUBLIC_ENV__);\n}\n\nconst rootEl = document.getElementById('root');\nif (!rootEl) {\n throw new Error('Root element not found. Helium requires a <div id=\"root\"></div> in your HTML.');\n}\n\nconst app = (\n <React.StrictMode>\n <AppRouter AppShell={App} />\n </React.StrictMode>\n);\n\nif (rootEl.hasChildNodes()) {\n hydrateRoot(rootEl, app);\n} else {\n createRoot(rootEl).render(app);\n}\n`;\n}\n"]}
|