heliumts 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +10 -9
- package/dist/client/Router.js.map +1 -1
- package/dist/client/cache.d.ts.map +1 -1
- package/dist/client/cache.js +2 -1
- package/dist/client/cache.js.map +1 -1
- package/dist/client/env.d.ts +5 -0
- package/dist/client/env.d.ts.map +1 -0
- package/dist/client/env.js +14 -0
- package/dist/client/env.js.map +1 -0
- 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 +96 -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/ipExtractor.d.ts +48 -0
- package/dist/server/ipExtractor.d.ts.map +1 -0
- package/dist/server/ipExtractor.js +96 -0
- package/dist/server/ipExtractor.js.map +1 -0
- 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 +23 -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 +132 -0
- package/dist/server/seoMetadataRouter.js.map +1 -0
- package/dist/utils/deepEqual.d.ts +1 -0
- package/dist/utils/deepEqual.d.ts.map +1 -0
- package/dist/utils/deepEqual.js +2 -0
- package/dist/utils/deepEqual.js.map +1 -0
- package/dist/utils/formatError.d.ts +2 -0
- package/dist/utils/formatError.d.ts.map +1 -0
- package/dist/utils/formatError.js +18 -0
- package/dist/utils/formatError.js.map +1 -0
- package/dist/vite/heliumPlugin.d.ts.map +1 -1
- package/dist/vite/heliumPlugin.js +15 -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 +2 -1
|
@@ -5,7 +5,7 @@ import { attachToDevServer } from "../server/devServer.js";
|
|
|
5
5
|
import { createEnvDefines, injectEnvToProcess, loadEnvFiles } from "../utils/envLoader.js";
|
|
6
6
|
import { log } from "../utils/logger.js";
|
|
7
7
|
import { RESOLVED_VIRTUAL_CLIENT_MODULE_ID, RESOLVED_VIRTUAL_ENTRY_MODULE_ID, RESOLVED_VIRTUAL_SERVER_MANIFEST_ID, SERVER_DIR, VIRTUAL_CLIENT_MODULE_ID, VIRTUAL_ENTRY_MODULE_ID, VIRTUAL_SERVER_MANIFEST_ID, } from "./paths.js";
|
|
8
|
-
import { checkRouteCollisions, scanServerExports } from "./scanner.js";
|
|
8
|
+
import { checkRouteCollisions, scanPageRoutePatterns, scanServerExports } from "./scanner.js";
|
|
9
9
|
import { generateClientModule, generateEntryModule, generateServerManifest, generateTypeDefinitions } from "./virtualServerModule.js";
|
|
10
10
|
export default function helium() {
|
|
11
11
|
let root = process.cwd();
|
|
@@ -103,6 +103,7 @@ export default function helium() {
|
|
|
103
103
|
},
|
|
104
104
|
define: {
|
|
105
105
|
...envDefines,
|
|
106
|
+
__HELIUM_DEV__: JSON.stringify(mode !== "production"),
|
|
106
107
|
__HELIUM_RPC_TRANSPORT__: JSON.stringify(rpcClientConfig.transport),
|
|
107
108
|
__HELIUM_RPC_AUTO_HTTP_ON_MOBILE__: JSON.stringify(rpcClientConfig.autoHttpOnMobile),
|
|
108
109
|
__HELIUM_RPC_TOKEN_VALIDITY_MS__: JSON.stringify(rpcClientConfig.tokenValidityMs),
|
|
@@ -140,8 +141,9 @@ export default function helium() {
|
|
|
140
141
|
return generateClientModule(methods);
|
|
141
142
|
}
|
|
142
143
|
if (id === RESOLVED_VIRTUAL_SERVER_MANIFEST_ID) {
|
|
143
|
-
const { methods, httpHandlers, middleware, workers } = scanServerExports(root);
|
|
144
|
-
|
|
144
|
+
const { methods, httpHandlers, seoMetadata, middleware, workers } = scanServerExports(root);
|
|
145
|
+
const pageRoutePatterns = scanPageRoutePatterns(root);
|
|
146
|
+
return generateServerManifest(methods, httpHandlers, seoMetadata, pageRoutePatterns, middleware, workers);
|
|
145
147
|
}
|
|
146
148
|
if (id === RESOLVED_VIRTUAL_ENTRY_MODULE_ID + ".tsx") {
|
|
147
149
|
return generateEntryModule();
|
|
@@ -264,13 +266,17 @@ export default function helium() {
|
|
|
264
266
|
const mod = await server.ssrLoadModule(VIRTUAL_SERVER_MANIFEST_ID);
|
|
265
267
|
const registerAll = mod.registerAll;
|
|
266
268
|
const httpHandlers = mod.httpHandlers || [];
|
|
269
|
+
const seoMetadataHandlers = mod.seoMetadataHandlers || [];
|
|
270
|
+
const pageRoutePatterns = mod.pageRoutePatterns || [];
|
|
267
271
|
const middlewareHandler = mod.middlewareHandler || null;
|
|
268
272
|
const workers = mod.workers || [];
|
|
269
273
|
// Update the dev server registry with new methods and HTTP handlers
|
|
270
274
|
if (server.httpServer) {
|
|
271
|
-
attachToDevServer(server.httpServer, (registry, httpRouter) => {
|
|
275
|
+
attachToDevServer(server.httpServer, (registry, httpRouter, seoRouter) => {
|
|
272
276
|
registerAll(registry);
|
|
273
277
|
httpRouter.registerRoutes(httpHandlers);
|
|
278
|
+
seoRouter.registerRoutes(seoMetadataHandlers);
|
|
279
|
+
seoRouter.setPageRoutePatterns(pageRoutePatterns);
|
|
274
280
|
if (middlewareHandler) {
|
|
275
281
|
registry.setMiddleware(middlewareHandler);
|
|
276
282
|
httpRouter.setMiddleware(middlewareHandler);
|
|
@@ -359,12 +365,16 @@ export default function helium() {
|
|
|
359
365
|
const mod = await server.ssrLoadModule(VIRTUAL_SERVER_MANIFEST_ID);
|
|
360
366
|
const registerAll = mod.registerAll;
|
|
361
367
|
const httpHandlers = mod.httpHandlers || [];
|
|
368
|
+
const seoMetadataHandlers = mod.seoMetadataHandlers || [];
|
|
369
|
+
const pageRoutePatterns = mod.pageRoutePatterns || [];
|
|
362
370
|
const middlewareHandler = mod.middlewareHandler || null;
|
|
363
371
|
const workers = mod.workers || [];
|
|
364
372
|
if (server.httpServer) {
|
|
365
|
-
attachToDevServer(server.httpServer, (registry, httpRouter) => {
|
|
373
|
+
attachToDevServer(server.httpServer, (registry, httpRouter, seoRouter) => {
|
|
366
374
|
registerAll(registry);
|
|
367
375
|
httpRouter.registerRoutes(httpHandlers);
|
|
376
|
+
seoRouter.registerRoutes(seoMetadataHandlers);
|
|
377
|
+
seoRouter.setPageRoutePatterns(pageRoutePatterns);
|
|
368
378
|
if (middlewareHandler) {
|
|
369
379
|
registry.setMiddleware(middlewareHandler);
|
|
370
380
|
httpRouter.setMiddleware(middlewareHandler);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heliumPlugin.js","sourceRoot":"","sources":["../../src/vite/heliumPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport type { Plugin } from \"vite\";\n\nimport { clearConfigCache, getRpcClientConfig, loadConfig } from \"../server/config.js\";\nimport { attachToDevServer } from \"../server/devServer.js\";\nimport { createEnvDefines, injectEnvToProcess, loadEnvFiles } from \"../utils/envLoader.js\";\nimport { log } from \"../utils/logger.js\";\nimport {\n RESOLVED_VIRTUAL_CLIENT_MODULE_ID,\n RESOLVED_VIRTUAL_ENTRY_MODULE_ID,\n RESOLVED_VIRTUAL_SERVER_MANIFEST_ID,\n SERVER_DIR,\n VIRTUAL_CLIENT_MODULE_ID,\n VIRTUAL_ENTRY_MODULE_ID,\n VIRTUAL_SERVER_MANIFEST_ID,\n} from \"./paths.js\";\nimport { checkRouteCollisions, scanServerExports } from \"./scanner.js\";\nimport { generateClientModule, generateEntryModule, generateServerManifest, generateTypeDefinitions } from \"./virtualServerModule.js\";\n\nexport default function helium(): Plugin {\n let root = process.cwd();\n const serverDir = normalizeToPosix(SERVER_DIR);\n\n return {\n name: \"vite-plugin-helium\",\n enforce: \"pre\",\n configResolved(config) {\n root = config.root;\n\n // Load and inject environment variables\n const mode = config.mode || \"development\";\n const envVars = loadEnvFiles({ root, mode });\n injectEnvToProcess(envVars);\n },\n transformIndexHtml: {\n order: \"pre\",\n handler(html, _ctx) {\n // Check if HTML already has a script tag for entry\n if (html.includes(\"src/main.tsx\") || html.includes(\"src/main.ts\")) {\n return html; // User has their own entry, don't modify\n }\n\n // Ensure root div exists\n let modifiedHtml = html;\n if (!modifiedHtml.includes('id=\"root\"')) {\n modifiedHtml = modifiedHtml.replace(\"<body>\", '<body>\\n <div id=\"root\"></div>');\n }\n\n // Generate physical entry file\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, \"entry.tsx\");\n fs.writeFileSync(entryPath, generateEntryModule());\n\n // Return with tags to inject the entry (runtime config is fetched by the client)\n return [\n {\n tag: \"script\",\n attrs: {\n type: \"module\",\n src: \"/node_modules/.heliumts/entry.tsx\",\n },\n injectTo: \"body\",\n },\n ];\n },\n },\n async config(config) {\n // Load environment variables before config is finalized\n const mode = config.mode || \"development\";\n const envVars = loadEnvFiles({ root, mode });\n\n // Create defines for client-side env variables\n const envDefines = createEnvDefines(envVars);\n\n // Load helium config to get client-side RPC transport settings\n const heliumConfig = await loadConfig(root);\n const rpcClientConfig = getRpcClientConfig(heliumConfig);\n\n // Provide default index.html if none exists\n return {\n appType: \"spa\",\n optimizeDeps: {\n include: [\"react-dom/client\"],\n // Exclude helium from pre-bundling since it's the framework itself\n // This ensures changes to helium are picked up immediately\n exclude: [\"heliumts\", \"heliumts/client\", \"heliumts/server\", \"heliumts/vite\"],\n },\n // SSR configuration to properly isolate server-only code\n ssr: {\n // Externalize Node.js built-in modules - these should never be bundled\n external: [\"util\", \"zlib\", \"http\", \"https\", \"http2\", \"fs\", \"path\", \"crypto\", \"stream\", \"os\", \"url\", \"net\", \"tls\", \"child_process\", \"worker_threads\"],\n // Don't externalize heliumts - let the plugin handle the client/server split\n noExternal: [\"heliumts\"],\n },\n // Ensure Node.js built-ins are not bundled for client\n build: {\n rollupOptions: {\n external: [\n // Node.js built-in modules should never be in client bundle\n /^node:/,\n \"util\",\n \"zlib\",\n \"http\",\n \"https\",\n \"http2\",\n \"fs\",\n \"path\",\n \"crypto\",\n \"stream\",\n \"os\",\n \"url\",\n \"net\",\n \"tls\",\n \"child_process\",\n \"worker_threads\",\n ],\n },\n },\n define: {\n ...envDefines,\n __HELIUM_RPC_TRANSPORT__: JSON.stringify(rpcClientConfig.transport),\n __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__: JSON.stringify(rpcClientConfig.autoHttpOnMobile),\n __HELIUM_RPC_TOKEN_VALIDITY_MS__: JSON.stringify(rpcClientConfig.tokenValidityMs),\n },\n };\n },\n resolveId(id, importer) {\n if (id === VIRTUAL_CLIENT_MODULE_ID) {\n if (isServerModule(importer, root, serverDir)) {\n return null;\n }\n return RESOLVED_VIRTUAL_CLIENT_MODULE_ID;\n }\n if (id === VIRTUAL_SERVER_MANIFEST_ID) {\n return RESOLVED_VIRTUAL_SERVER_MANIFEST_ID;\n }\n if (id === VIRTUAL_ENTRY_MODULE_ID) {\n // Add .tsx extension so Vite knows it contains JSX\n return RESOLVED_VIRTUAL_ENTRY_MODULE_ID + \".tsx\";\n }\n // Intercept heliumts/server imports from client code\n if (id === \"heliumts/server\") {\n // If imported from server code, let it resolve normally\n if (isServerModule(importer, root, serverDir)) {\n return null;\n }\n // For client code, redirect to virtual client module\n return RESOLVED_VIRTUAL_CLIENT_MODULE_ID;\n }\n return null;\n },\n load(id) {\n if (id === RESOLVED_VIRTUAL_CLIENT_MODULE_ID) {\n const { methods } = scanServerExports(root);\n return generateClientModule(methods);\n }\n if (id === RESOLVED_VIRTUAL_SERVER_MANIFEST_ID) {\n const { methods, httpHandlers, middleware, workers } = scanServerExports(root);\n return generateServerManifest(methods, httpHandlers, middleware, workers);\n }\n if (id === RESOLVED_VIRTUAL_ENTRY_MODULE_ID + \".tsx\") {\n return generateEntryModule();\n }\n },\n buildStart() {\n const { methods } = scanServerExports(root);\n const dts = generateTypeDefinitions(methods, root);\n const typesDir = path.join(root, \"src\", \"types\");\n const dtsPath = path.join(typesDir, \"heliumts-server.d.ts\");\n\n // Ensure src/types exists\n if (!fs.existsSync(typesDir)) {\n fs.mkdirSync(typesDir, { recursive: true });\n }\n\n // At build start we always allow writing the canonical set.\n // Only skip if content is identical to avoid needless TS invalidation.\n if (!fs.existsSync(dtsPath) || fs.readFileSync(dtsPath, \"utf-8\") !== dts) {\n fs.writeFileSync(dtsPath, dts);\n touchTsConfig(root);\n }\n\n // Check for route collisions in pages directory\n checkRouteCollisions(root);\n },\n configureServer(server) {\n // Add middleware to handle HTML fallback for nested routes\n // This ensures that routes like /docs/guides/auth properly serve index.html\n // so the client-side router can handle them\n server.middlewares.use((req, res, next) => {\n const url = req.url || \"\";\n const cleanUrl = url.split(\"?\")[0];\n\n // Skip if:\n // - Has file extension (asset request)\n // - Is an API/special endpoint\n // - Is a dev server endpoint\n if (\n path.extname(cleanUrl) !== \"\" ||\n cleanUrl.startsWith(\"/api\") ||\n cleanUrl.startsWith(\"/webhooks\") ||\n cleanUrl.startsWith(\"/auth\") ||\n cleanUrl.startsWith(\"/@\") ||\n cleanUrl.startsWith(\"/__helium__\")\n ) {\n return next();\n }\n\n // For all other routes (including nested paths like /docs/guides/auth),\n // rewrite to index.html so Vite serves it and the client-side router handles routing\n req.url = \"/index.html\";\n next();\n });\n\n /**\n * Write type definitions only if content has changed.\n * This prevents unnecessary TypeScript recompilation.\n *\n * When `allowFewer` is false (default) the file will NOT be\n * overwritten if the new content has fewer method declarations\n * than the existing file — this guards against writing a\n * degraded .d.ts while the user's file is only partially saved.\n */\n const writeTypesIfChanged = (dts: string, allowFewer = false): boolean => {\n const typesDir = path.join(root, \"src\", \"types\");\n const dtsPath = path.join(typesDir, \"heliumts-server.d.ts\");\n\n if (!fs.existsSync(typesDir)) {\n fs.mkdirSync(typesDir, { recursive: true });\n }\n\n // Check if file exists and content is the same\n if (fs.existsSync(dtsPath)) {\n const existing = fs.readFileSync(dtsPath, \"utf-8\");\n if (existing === dts) {\n return false; // No change needed\n }\n\n // Guard: don't overwrite with fewer methods unless explicitly allowed\n // (e.g. on unlink). This prevents losing types during partial saves.\n if (!allowFewer) {\n const countExports = (s: string) => (s.match(/export const \\w+:/g) || []).length;\n const existingCount = countExports(existing);\n const newCount = countExports(dts);\n if (newCount < existingCount) {\n log(\"info\", `Skipping type generation: found ${newCount} methods, existing has ${existingCount} (likely partial save)`);\n return false;\n }\n }\n }\n\n fs.writeFileSync(dtsPath, dts);\n\n // Touch tsconfig.json to force the TypeScript language server\n // to reload the project. Without this, TS may cache stale\n // module augmentations and autocomplete won't reflect the\n // new methods until a manual restart.\n touchTsConfig(root);\n\n return true; // File was written\n };\n\n const regenerateTypes = (allowFewer = false): boolean => {\n try {\n const { methods } = scanServerExports(root);\n const dts = generateTypeDefinitions(methods, root);\n return writeTypesIfChanged(dts, allowFewer);\n } catch (e) {\n log(\"error\", \"Failed to regenerate types\", e);\n return false;\n }\n };\n\n // Debounce timer for file changes\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n const DEBOUNCE_DELAY = 300; // ms — long enough for format-on-save to finish\n\n const handleServerFileChange = async (allowFewer = false) => {\n // Regenerate type definitions\n regenerateTypes(allowFewer);\n\n // Invalidate the virtual modules so they get regenerated\n const clientModule = server.environments.client?.moduleGraph.getModuleById(RESOLVED_VIRTUAL_CLIENT_MODULE_ID);\n const serverModule = server.environments.ssr?.moduleGraph.getModuleById(RESOLVED_VIRTUAL_SERVER_MANIFEST_ID);\n\n if (clientModule) {\n server.environments.client?.moduleGraph.invalidateModule(clientModule);\n }\n if (serverModule) {\n server.environments.ssr?.moduleGraph.invalidateModule(serverModule);\n }\n\n // Reload the server manifest and re-register methods\n try {\n // Clear config cache to ensure fresh config is loaded\n clearConfigCache();\n const config = await loadConfig(root);\n const mod = await server.ssrLoadModule(VIRTUAL_SERVER_MANIFEST_ID);\n const registerAll = mod.registerAll;\n const httpHandlers = mod.httpHandlers || [];\n const middlewareHandler = mod.middlewareHandler || null;\n const workers = mod.workers || [];\n\n // Update the dev server registry with new methods and HTTP handlers\n if (server.httpServer) {\n attachToDevServer(\n server.httpServer,\n (registry, httpRouter) => {\n registerAll(registry);\n httpRouter.registerRoutes(httpHandlers);\n if (middlewareHandler) {\n registry.setMiddleware(middlewareHandler);\n httpRouter.setMiddleware(middlewareHandler);\n }\n },\n config,\n workers\n );\n }\n } catch (e) {\n log(\"error\", \"Failed to reload Helium server manifest\", e);\n }\n\n // Trigger HMR for any client code that imports heliumts/server\n server.ws.send({\n type: \"full-reload\",\n path: \"*\",\n });\n };\n\n // Watch server directory for changes\n const serverPath = path.join(root, serverDir);\n server.watcher.add(serverPath);\n\n // Watch config files for changes\n const configFiles = [\"helium.config.ts\", \"helium.config.js\", \"helium.config.mjs\"];\n for (const configFile of configFiles) {\n const configPath = path.join(root, configFile);\n if (fs.existsSync(configPath)) {\n server.watcher.add(configPath);\n }\n }\n\n /**\n * Debounced handler for server file changes.\n * This prevents multiple rapid regenerations during file saves.\n * @param allowFewer - pass true when files are deleted, so the\n * method count is allowed to decrease.\n */\n let pendingAllowFewer = false;\n const debouncedHandleServerFileChange = (allowFewer = false) => {\n // If any event in the batch is an unlink, honour it\n if (allowFewer) {\n pendingAllowFewer = true;\n }\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n const shouldAllowFewer = pendingAllowFewer;\n pendingAllowFewer = false;\n handleServerFileChange(shouldAllowFewer);\n }, DEBOUNCE_DELAY);\n };\n\n server.watcher.on(\"change\", (file) => {\n const relative = path.relative(root, file);\n const normalized = normalizeToPosix(relative);\n\n // If a server file changed, regenerate everything\n if (normalized.startsWith(`${serverDir}/`)) {\n debouncedHandleServerFileChange();\n }\n\n // If config file changed, reload config and regenerate\n if (configFiles.some((cf) => normalized === cf)) {\n log(\"info\", `Config file changed: ${normalized}`);\n debouncedHandleServerFileChange();\n }\n });\n\n server.watcher.on(\"add\", (file) => {\n const relative = path.relative(root, file);\n const normalized = normalizeToPosix(relative);\n\n // If a server file was added, regenerate everything\n if (normalized.startsWith(`${serverDir}/`)) {\n debouncedHandleServerFileChange();\n }\n });\n\n server.watcher.on(\"unlink\", (file) => {\n const relative = path.relative(root, file);\n const normalized = normalizeToPosix(relative);\n\n // If a server file was removed, regenerate (allow fewer methods)\n if (normalized.startsWith(`${serverDir}/`)) {\n debouncedHandleServerFileChange(true);\n }\n });\n\n // We hook into the server start to attach our RPC server\n server.httpServer?.on(\"listening\", async () => {\n try {\n // Load config\n const config = await loadConfig(root);\n\n // Load the manifest using Vite's SSR loader\n // This allows us to load TS files directly and handle dependencies\n const mod = await server.ssrLoadModule(VIRTUAL_SERVER_MANIFEST_ID);\n const registerAll = mod.registerAll;\n const httpHandlers = mod.httpHandlers || [];\n const middlewareHandler = mod.middlewareHandler || null;\n const workers = mod.workers || [];\n\n if (server.httpServer) {\n attachToDevServer(\n server.httpServer,\n (registry, httpRouter) => {\n registerAll(registry);\n httpRouter.registerRoutes(httpHandlers);\n if (middlewareHandler) {\n registry.setMiddleware(middlewareHandler);\n httpRouter.setMiddleware(middlewareHandler);\n }\n },\n config,\n workers\n );\n }\n } catch (e) {\n log(\"error\", \"Failed to attach Helium RPC server\", e);\n }\n });\n },\n };\n}\n\n/**\n * Convert file path to POSIX format\n * @internal Exported for testing\n */\nexport function normalizeToPosix(filePath: string): string {\n return filePath.split(path.sep).join(\"/\");\n}\n\n/**\n * Check if an importer is a server module\n * @internal Exported for testing\n */\nexport function isServerModule(importer: string | undefined, root: string, serverDir: string): boolean {\n if (!importer || importer.startsWith(\"\\0\")) {\n return false;\n }\n\n const [importerPath] = importer.split(\"?\");\n if (!importerPath) {\n return false;\n }\n\n const relative = path.relative(root, importerPath);\n if (!relative || relative.startsWith(\"..\")) {\n return false;\n }\n\n const normalized = normalizeToPosix(relative);\n return normalized === serverDir || normalized.startsWith(`${serverDir}/`);\n}\n\n/**\n * Touch the project's tsconfig.json to force the TypeScript language server\n * to reload the project and pick up changed module augmentations.\n *\n * TS language server watches tsconfig.json for changes. When a `.d.ts` file\n * with `declare module` augmentations is regenerated, TS doesn't always\n * detect the new content — leading to stale autocomplete. By updating\n * tsconfig.json's mtime we trigger a full project reload.\n *\n * The file content is NOT modified; only the filesystem timestamp changes.\n *\n * @internal Exported for testing\n */\nexport function touchTsConfig(root: string): void {\n const tsconfigPath = path.join(root, \"tsconfig.json\");\n try {\n if (fs.existsSync(tsconfigPath)) {\n const now = new Date();\n fs.utimesSync(tsconfigPath, now, now);\n }\n } catch {\n // Non-critical: if we can't touch the file, TS may just need a manual reload\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"heliumPlugin.js","sourceRoot":"","sources":["../../src/vite/heliumPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport type { Plugin } from \"vite\";\n\nimport { clearConfigCache, getRpcClientConfig, loadConfig } from \"../server/config.js\";\nimport { attachToDevServer } from \"../server/devServer.js\";\nimport { createEnvDefines, injectEnvToProcess, loadEnvFiles } from \"../utils/envLoader.js\";\nimport { log } from \"../utils/logger.js\";\nimport {\n RESOLVED_VIRTUAL_CLIENT_MODULE_ID,\n RESOLVED_VIRTUAL_ENTRY_MODULE_ID,\n RESOLVED_VIRTUAL_SERVER_MANIFEST_ID,\n SERVER_DIR,\n VIRTUAL_CLIENT_MODULE_ID,\n VIRTUAL_ENTRY_MODULE_ID,\n VIRTUAL_SERVER_MANIFEST_ID,\n} from \"./paths.js\";\nimport { checkRouteCollisions, scanPageRoutePatterns, scanServerExports } from \"./scanner.js\";\nimport { generateClientModule, generateEntryModule, generateServerManifest, generateTypeDefinitions } from \"./virtualServerModule.js\";\n\nexport default function helium(): Plugin {\n let root = process.cwd();\n const serverDir = normalizeToPosix(SERVER_DIR);\n\n return {\n name: \"vite-plugin-helium\",\n enforce: \"pre\",\n configResolved(config) {\n root = config.root;\n\n // Load and inject environment variables\n const mode = config.mode || \"development\";\n const envVars = loadEnvFiles({ root, mode });\n injectEnvToProcess(envVars);\n },\n transformIndexHtml: {\n order: \"pre\",\n handler(html, _ctx) {\n // Check if HTML already has a script tag for entry\n if (html.includes(\"src/main.tsx\") || html.includes(\"src/main.ts\")) {\n return html; // User has their own entry, don't modify\n }\n\n // Ensure root div exists\n let modifiedHtml = html;\n if (!modifiedHtml.includes('id=\"root\"')) {\n modifiedHtml = modifiedHtml.replace(\"<body>\", '<body>\\n <div id=\"root\"></div>');\n }\n\n // Generate physical entry file\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, \"entry.tsx\");\n fs.writeFileSync(entryPath, generateEntryModule());\n\n // Return with tags to inject the entry (runtime config is fetched by the client)\n return [\n {\n tag: \"script\",\n attrs: {\n type: \"module\",\n src: \"/node_modules/.heliumts/entry.tsx\",\n },\n injectTo: \"body\",\n },\n ];\n },\n },\n async config(config) {\n // Load environment variables before config is finalized\n const mode = config.mode || \"development\";\n const envVars = loadEnvFiles({ root, mode });\n\n // Create defines for client-side env variables\n const envDefines = createEnvDefines(envVars);\n\n // Load helium config to get client-side RPC transport settings\n const heliumConfig = await loadConfig(root);\n const rpcClientConfig = getRpcClientConfig(heliumConfig);\n\n // Provide default index.html if none exists\n return {\n appType: \"spa\",\n optimizeDeps: {\n include: [\"react-dom/client\"],\n // Exclude helium from pre-bundling since it's the framework itself\n // This ensures changes to helium are picked up immediately\n exclude: [\"heliumts\", \"heliumts/client\", \"heliumts/server\", \"heliumts/vite\"],\n },\n // SSR configuration to properly isolate server-only code\n ssr: {\n // Externalize Node.js built-in modules - these should never be bundled\n external: [\"util\", \"zlib\", \"http\", \"https\", \"http2\", \"fs\", \"path\", \"crypto\", \"stream\", \"os\", \"url\", \"net\", \"tls\", \"child_process\", \"worker_threads\"],\n // Don't externalize heliumts - let the plugin handle the client/server split\n noExternal: [\"heliumts\"],\n },\n // Ensure Node.js built-ins are not bundled for client\n build: {\n rollupOptions: {\n external: [\n // Node.js built-in modules should never be in client bundle\n /^node:/,\n \"util\",\n \"zlib\",\n \"http\",\n \"https\",\n \"http2\",\n \"fs\",\n \"path\",\n \"crypto\",\n \"stream\",\n \"os\",\n \"url\",\n \"net\",\n \"tls\",\n \"child_process\",\n \"worker_threads\",\n ],\n },\n },\n define: {\n ...envDefines,\n __HELIUM_DEV__: JSON.stringify(mode !== \"production\"),\n __HELIUM_RPC_TRANSPORT__: JSON.stringify(rpcClientConfig.transport),\n __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__: JSON.stringify(rpcClientConfig.autoHttpOnMobile),\n __HELIUM_RPC_TOKEN_VALIDITY_MS__: JSON.stringify(rpcClientConfig.tokenValidityMs),\n },\n };\n },\n resolveId(id, importer) {\n if (id === VIRTUAL_CLIENT_MODULE_ID) {\n if (isServerModule(importer, root, serverDir)) {\n return null;\n }\n return RESOLVED_VIRTUAL_CLIENT_MODULE_ID;\n }\n if (id === VIRTUAL_SERVER_MANIFEST_ID) {\n return RESOLVED_VIRTUAL_SERVER_MANIFEST_ID;\n }\n if (id === VIRTUAL_ENTRY_MODULE_ID) {\n // Add .tsx extension so Vite knows it contains JSX\n return RESOLVED_VIRTUAL_ENTRY_MODULE_ID + \".tsx\";\n }\n // Intercept heliumts/server imports from client code\n if (id === \"heliumts/server\") {\n // If imported from server code, let it resolve normally\n if (isServerModule(importer, root, serverDir)) {\n return null;\n }\n // For client code, redirect to virtual client module\n return RESOLVED_VIRTUAL_CLIENT_MODULE_ID;\n }\n return null;\n },\n load(id) {\n if (id === RESOLVED_VIRTUAL_CLIENT_MODULE_ID) {\n const { methods } = scanServerExports(root);\n return generateClientModule(methods);\n }\n if (id === RESOLVED_VIRTUAL_SERVER_MANIFEST_ID) {\n const { methods, httpHandlers, seoMetadata, middleware, workers } = scanServerExports(root);\n const pageRoutePatterns = scanPageRoutePatterns(root);\n return generateServerManifest(methods, httpHandlers, seoMetadata, pageRoutePatterns, middleware, workers);\n }\n if (id === RESOLVED_VIRTUAL_ENTRY_MODULE_ID + \".tsx\") {\n return generateEntryModule();\n }\n },\n buildStart() {\n const { methods } = scanServerExports(root);\n const dts = generateTypeDefinitions(methods, root);\n const typesDir = path.join(root, \"src\", \"types\");\n const dtsPath = path.join(typesDir, \"heliumts-server.d.ts\");\n\n // Ensure src/types exists\n if (!fs.existsSync(typesDir)) {\n fs.mkdirSync(typesDir, { recursive: true });\n }\n\n // At build start we always allow writing the canonical set.\n // Only skip if content is identical to avoid needless TS invalidation.\n if (!fs.existsSync(dtsPath) || fs.readFileSync(dtsPath, \"utf-8\") !== dts) {\n fs.writeFileSync(dtsPath, dts);\n touchTsConfig(root);\n }\n\n // Check for route collisions in pages directory\n checkRouteCollisions(root);\n },\n configureServer(server) {\n // Add middleware to handle HTML fallback for nested routes\n // This ensures that routes like /docs/guides/auth properly serve index.html\n // so the client-side router can handle them\n server.middlewares.use((req, res, next) => {\n const url = req.url || \"\";\n const cleanUrl = url.split(\"?\")[0];\n\n // Skip if:\n // - Has file extension (asset request)\n // - Is an API/special endpoint\n // - Is a dev server endpoint\n if (\n path.extname(cleanUrl) !== \"\" ||\n cleanUrl.startsWith(\"/api\") ||\n cleanUrl.startsWith(\"/webhooks\") ||\n cleanUrl.startsWith(\"/auth\") ||\n cleanUrl.startsWith(\"/@\") ||\n cleanUrl.startsWith(\"/__helium__\")\n ) {\n return next();\n }\n\n // For all other routes (including nested paths like /docs/guides/auth),\n // rewrite to index.html so Vite serves it and the client-side router handles routing\n req.url = \"/index.html\";\n next();\n });\n\n /**\n * Write type definitions only if content has changed.\n * This prevents unnecessary TypeScript recompilation.\n *\n * When `allowFewer` is false (default) the file will NOT be\n * overwritten if the new content has fewer method declarations\n * than the existing file — this guards against writing a\n * degraded .d.ts while the user's file is only partially saved.\n */\n const writeTypesIfChanged = (dts: string, allowFewer = false): boolean => {\n const typesDir = path.join(root, \"src\", \"types\");\n const dtsPath = path.join(typesDir, \"heliumts-server.d.ts\");\n\n if (!fs.existsSync(typesDir)) {\n fs.mkdirSync(typesDir, { recursive: true });\n }\n\n // Check if file exists and content is the same\n if (fs.existsSync(dtsPath)) {\n const existing = fs.readFileSync(dtsPath, \"utf-8\");\n if (existing === dts) {\n return false; // No change needed\n }\n\n // Guard: don't overwrite with fewer methods unless explicitly allowed\n // (e.g. on unlink). This prevents losing types during partial saves.\n if (!allowFewer) {\n const countExports = (s: string) => (s.match(/export const \\w+:/g) || []).length;\n const existingCount = countExports(existing);\n const newCount = countExports(dts);\n if (newCount < existingCount) {\n log(\"info\", `Skipping type generation: found ${newCount} methods, existing has ${existingCount} (likely partial save)`);\n return false;\n }\n }\n }\n\n fs.writeFileSync(dtsPath, dts);\n\n // Touch tsconfig.json to force the TypeScript language server\n // to reload the project. Without this, TS may cache stale\n // module augmentations and autocomplete won't reflect the\n // new methods until a manual restart.\n touchTsConfig(root);\n\n return true; // File was written\n };\n\n const regenerateTypes = (allowFewer = false): boolean => {\n try {\n const { methods } = scanServerExports(root);\n const dts = generateTypeDefinitions(methods, root);\n return writeTypesIfChanged(dts, allowFewer);\n } catch (e) {\n log(\"error\", \"Failed to regenerate types\", e);\n return false;\n }\n };\n\n // Debounce timer for file changes\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n const DEBOUNCE_DELAY = 300; // ms — long enough for format-on-save to finish\n\n const handleServerFileChange = async (allowFewer = false) => {\n // Regenerate type definitions\n regenerateTypes(allowFewer);\n\n // Invalidate the virtual modules so they get regenerated\n const clientModule = server.environments.client?.moduleGraph.getModuleById(RESOLVED_VIRTUAL_CLIENT_MODULE_ID);\n const serverModule = server.environments.ssr?.moduleGraph.getModuleById(RESOLVED_VIRTUAL_SERVER_MANIFEST_ID);\n\n if (clientModule) {\n server.environments.client?.moduleGraph.invalidateModule(clientModule);\n }\n if (serverModule) {\n server.environments.ssr?.moduleGraph.invalidateModule(serverModule);\n }\n\n // Reload the server manifest and re-register methods\n try {\n // Clear config cache to ensure fresh config is loaded\n clearConfigCache();\n const config = await loadConfig(root);\n const mod = await server.ssrLoadModule(VIRTUAL_SERVER_MANIFEST_ID);\n const registerAll = mod.registerAll;\n const httpHandlers = mod.httpHandlers || [];\n const seoMetadataHandlers = mod.seoMetadataHandlers || [];\n const pageRoutePatterns = mod.pageRoutePatterns || [];\n const middlewareHandler = mod.middlewareHandler || null;\n const workers = mod.workers || [];\n\n // Update the dev server registry with new methods and HTTP handlers\n if (server.httpServer) {\n attachToDevServer(\n server.httpServer,\n (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 config,\n workers\n );\n }\n } catch (e) {\n log(\"error\", \"Failed to reload Helium server manifest\", e);\n }\n\n // Trigger HMR for any client code that imports heliumts/server\n server.ws.send({\n type: \"full-reload\",\n path: \"*\",\n });\n };\n\n // Watch server directory for changes\n const serverPath = path.join(root, serverDir);\n server.watcher.add(serverPath);\n\n // Watch config files for changes\n const configFiles = [\"helium.config.ts\", \"helium.config.js\", \"helium.config.mjs\"];\n for (const configFile of configFiles) {\n const configPath = path.join(root, configFile);\n if (fs.existsSync(configPath)) {\n server.watcher.add(configPath);\n }\n }\n\n /**\n * Debounced handler for server file changes.\n * This prevents multiple rapid regenerations during file saves.\n * @param allowFewer - pass true when files are deleted, so the\n * method count is allowed to decrease.\n */\n let pendingAllowFewer = false;\n const debouncedHandleServerFileChange = (allowFewer = false) => {\n // If any event in the batch is an unlink, honour it\n if (allowFewer) {\n pendingAllowFewer = true;\n }\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n const shouldAllowFewer = pendingAllowFewer;\n pendingAllowFewer = false;\n handleServerFileChange(shouldAllowFewer);\n }, DEBOUNCE_DELAY);\n };\n\n server.watcher.on(\"change\", (file) => {\n const relative = path.relative(root, file);\n const normalized = normalizeToPosix(relative);\n\n // If a server file changed, regenerate everything\n if (normalized.startsWith(`${serverDir}/`)) {\n debouncedHandleServerFileChange();\n }\n\n // If config file changed, reload config and regenerate\n if (configFiles.some((cf) => normalized === cf)) {\n log(\"info\", `Config file changed: ${normalized}`);\n debouncedHandleServerFileChange();\n }\n });\n\n server.watcher.on(\"add\", (file) => {\n const relative = path.relative(root, file);\n const normalized = normalizeToPosix(relative);\n\n // If a server file was added, regenerate everything\n if (normalized.startsWith(`${serverDir}/`)) {\n debouncedHandleServerFileChange();\n }\n });\n\n server.watcher.on(\"unlink\", (file) => {\n const relative = path.relative(root, file);\n const normalized = normalizeToPosix(relative);\n\n // If a server file was removed, regenerate (allow fewer methods)\n if (normalized.startsWith(`${serverDir}/`)) {\n debouncedHandleServerFileChange(true);\n }\n });\n\n // We hook into the server start to attach our RPC server\n server.httpServer?.on(\"listening\", async () => {\n try {\n // Load config\n const config = await loadConfig(root);\n\n // Load the manifest using Vite's SSR loader\n // This allows us to load TS files directly and handle dependencies\n const mod = await server.ssrLoadModule(VIRTUAL_SERVER_MANIFEST_ID);\n const registerAll = mod.registerAll;\n const httpHandlers = mod.httpHandlers || [];\n const seoMetadataHandlers = mod.seoMetadataHandlers || [];\n const pageRoutePatterns = mod.pageRoutePatterns || [];\n const middlewareHandler = mod.middlewareHandler || null;\n const workers = mod.workers || [];\n\n if (server.httpServer) {\n attachToDevServer(\n server.httpServer,\n (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 config,\n workers\n );\n }\n } catch (e) {\n log(\"error\", \"Failed to attach Helium RPC server\", e);\n }\n });\n },\n };\n}\n\n/**\n * Convert file path to POSIX format\n * @internal Exported for testing\n */\nexport function normalizeToPosix(filePath: string): string {\n return filePath.split(path.sep).join(\"/\");\n}\n\n/**\n * Check if an importer is a server module\n * @internal Exported for testing\n */\nexport function isServerModule(importer: string | undefined, root: string, serverDir: string): boolean {\n if (!importer || importer.startsWith(\"\\0\")) {\n return false;\n }\n\n const [importerPath] = importer.split(\"?\");\n if (!importerPath) {\n return false;\n }\n\n const relative = path.relative(root, importerPath);\n if (!relative || relative.startsWith(\"..\")) {\n return false;\n }\n\n const normalized = normalizeToPosix(relative);\n return normalized === serverDir || normalized.startsWith(`${serverDir}/`);\n}\n\n/**\n * Touch the project's tsconfig.json to force the TypeScript language server\n * to reload the project and pick up changed module augmentations.\n *\n * TS language server watches tsconfig.json for changes. When a `.d.ts` file\n * with `declare module` augmentations is regenerated, TS doesn't always\n * detect the new content — leading to stale autocomplete. By updating\n * tsconfig.json's mtime we trigger a full project reload.\n *\n * The file content is NOT modified; only the filesystem timestamp changes.\n *\n * @internal Exported for testing\n */\nexport function touchTsConfig(root: string): void {\n const tsconfigPath = path.join(root, \"tsconfig.json\");\n try {\n if (fs.existsSync(tsconfigPath)) {\n const now = new Date();\n fs.utimesSync(tsconfigPath, now, now);\n }\n } catch {\n // Non-critical: if we can't touch the file, TS may just need a manual reload\n }\n}\n"]}
|
package/dist/vite/scanner.d.ts
CHANGED
|
@@ -14,9 +14,14 @@ export interface WorkerExport {
|
|
|
14
14
|
name: string;
|
|
15
15
|
filePath: string;
|
|
16
16
|
}
|
|
17
|
+
export interface SEOMetadataExport {
|
|
18
|
+
name: string;
|
|
19
|
+
filePath: string;
|
|
20
|
+
}
|
|
17
21
|
export interface ServerExports {
|
|
18
22
|
methods: MethodExport[];
|
|
19
23
|
httpHandlers: HTTPHandlerExport[];
|
|
24
|
+
seoMetadata: SEOMetadataExport[];
|
|
20
25
|
middleware?: MiddlewareExport;
|
|
21
26
|
workers: WorkerExport[];
|
|
22
27
|
}
|
|
@@ -26,6 +31,7 @@ export interface RouteCollision {
|
|
|
26
31
|
pattern: string;
|
|
27
32
|
files: string[];
|
|
28
33
|
}
|
|
34
|
+
export declare function scanPageRoutePatterns(root: string): string[];
|
|
29
35
|
/**
|
|
30
36
|
* Scan pages directory and detect route collisions
|
|
31
37
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/vite/scanner.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAG9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/vite/scanner.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAG9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CA6G7D;AA4BD,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAwC5D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,cAAc,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAsDlG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAyB1D"}
|
package/dist/vite/scanner.js
CHANGED
|
@@ -9,10 +9,11 @@ export function scanServerMethods(root) {
|
|
|
9
9
|
export function scanServerExports(root) {
|
|
10
10
|
const serverDir = path.resolve(root, SERVER_DIR);
|
|
11
11
|
if (!fs.existsSync(serverDir)) {
|
|
12
|
-
return { methods: [], httpHandlers: [], workers: [] };
|
|
12
|
+
return { methods: [], httpHandlers: [], seoMetadata: [], workers: [] };
|
|
13
13
|
}
|
|
14
14
|
const methods = [];
|
|
15
15
|
const httpHandlers = [];
|
|
16
|
+
const seoMetadata = [];
|
|
16
17
|
const workers = [];
|
|
17
18
|
let middleware;
|
|
18
19
|
function walk(dir) {
|
|
@@ -87,6 +88,14 @@ export function scanServerExports(root) {
|
|
|
87
88
|
filePath: fullPath,
|
|
88
89
|
});
|
|
89
90
|
}
|
|
91
|
+
// Find: export const seoName = defineSEOMetadata(...)
|
|
92
|
+
const seoRegex = /export\s+const\s+(\w+)\s*=\s*defineSEOMetadata/g;
|
|
93
|
+
while ((match = seoRegex.exec(content)) !== null) {
|
|
94
|
+
seoMetadata.push({
|
|
95
|
+
name: match[1],
|
|
96
|
+
filePath: fullPath,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
90
99
|
// Find: export const workerName = defineWorker(...)
|
|
91
100
|
const workerRegex = /export\s+const\s+(\w+)\s*=\s*defineWorker/g;
|
|
92
101
|
while ((match = workerRegex.exec(content)) !== null) {
|
|
@@ -99,7 +108,7 @@ export function scanServerExports(root) {
|
|
|
99
108
|
}
|
|
100
109
|
}
|
|
101
110
|
walk(serverDir);
|
|
102
|
-
return { methods, httpHandlers, middleware, workers };
|
|
111
|
+
return { methods, httpHandlers, seoMetadata, middleware, workers };
|
|
103
112
|
}
|
|
104
113
|
/**
|
|
105
114
|
* Convert a file path to a route pattern (same logic as client-side router)
|
|
@@ -122,6 +131,37 @@ function pathFromFile(file, root) {
|
|
|
122
131
|
pattern = pattern.replace(/\[(.+?)\]/g, ":$1");
|
|
123
132
|
return pattern;
|
|
124
133
|
}
|
|
134
|
+
export function scanPageRoutePatterns(root) {
|
|
135
|
+
const pagesDir = path.join(root, "src", "pages");
|
|
136
|
+
if (!fs.existsSync(pagesDir)) {
|
|
137
|
+
return [];
|
|
138
|
+
}
|
|
139
|
+
const patterns = new Set();
|
|
140
|
+
function walkPages(dir) {
|
|
141
|
+
const items = fs.readdirSync(dir);
|
|
142
|
+
for (const item of items) {
|
|
143
|
+
const fullPath = path.join(dir, item);
|
|
144
|
+
const stat = fs.statSync(fullPath);
|
|
145
|
+
if (stat.isDirectory()) {
|
|
146
|
+
walkPages(fullPath);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (!/\.(tsx|jsx|ts|js)$/.test(item)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (item.includes("_layout.")) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const pattern = pathFromFile(fullPath, root);
|
|
156
|
+
if (pattern === "__404__") {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
patterns.add(pattern);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
walkPages(pagesDir);
|
|
163
|
+
return [...patterns];
|
|
164
|
+
}
|
|
125
165
|
/**
|
|
126
166
|
* Scan pages directory and detect route collisions
|
|
127
167
|
*/
|
package/dist/vite/scanner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/vite/scanner.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\nimport { log } from \"../utils/logger.js\";\nimport { SERVER_DIR } from \"./paths.js\";\n\nexport interface MethodExport {\n name: string;\n filePath: string;\n}\n\nexport interface HTTPHandlerExport {\n name: string;\n filePath: string;\n}\n\nexport interface MiddlewareExport {\n name: string;\n filePath: string;\n}\n\nexport interface WorkerExport {\n name: string;\n filePath: string;\n}\n\nexport interface ServerExports {\n methods: MethodExport[];\n httpHandlers: HTTPHandlerExport[];\n middleware?: MiddlewareExport;\n workers: WorkerExport[];\n}\n\nexport function scanServerMethods(root: string): MethodExport[] {\n const exports = scanServerExports(root);\n return exports.methods;\n}\n\nexport function scanServerExports(root: string): ServerExports {\n const serverDir = path.resolve(root, SERVER_DIR);\n if (!fs.existsSync(serverDir)) {\n return { methods: [], httpHandlers: [], workers: [] };\n }\n\n const methods: MethodExport[] = [];\n const httpHandlers: HTTPHandlerExport[] = [];\n const workers: WorkerExport[] = [];\n let middleware: MiddlewareExport | undefined;\n\n function walk(dir: string) {\n let files: string[];\n try {\n files = fs.readdirSync(dir);\n } catch {\n // Directory might have been deleted during scan\n return;\n }\n for (const file of files) {\n const fullPath = path.join(dir, file);\n let stat: fs.Stats;\n try {\n stat = fs.statSync(fullPath);\n } catch {\n // File might have been deleted during scan\n continue;\n }\n\n if (stat.isDirectory()) {\n walk(fullPath);\n } else if (file.endsWith(\".ts\") && !file.endsWith(\".d.ts\")) {\n let content: string;\n try {\n content = fs.readFileSync(fullPath, \"utf-8\");\n } catch {\n // File might be being written to or deleted\n continue;\n }\n\n // Skip empty or near-empty files (likely partial writes)\n if (content.length < 10) {\n continue;\n }\n\n // Check for _middleware.ts file\n if (file === \"_middleware.ts\") {\n // Support both 'middleware' and 'defineMiddleware' (backwards compatibility)\n const middlewareRegex = /export\\s+(const|default)\\s+(\\w+)\\s*=\\s*(middleware|defineMiddleware)/;\n const match = middlewareRegex.exec(content);\n if (match) {\n middleware = {\n name: match[2],\n filePath: fullPath,\n };\n }\n // Also support default export\n const defaultRegex = /export\\s+default\\s+(middleware|defineMiddleware)/;\n if (defaultRegex.test(content)) {\n middleware = {\n name: \"default\",\n filePath: fullPath,\n };\n }\n }\n\n // Find: export const methodName = defineMethod(...)\n const methodRegex = /export\\s+const\\s+(\\w+)\\s*=\\s*defineMethod/g;\n let match;\n while ((match = methodRegex.exec(content)) !== null) {\n methods.push({\n name: match[1],\n filePath: fullPath,\n });\n }\n\n // Find: export const handlerName = defineHTTPRequest(...)\n const httpRegex = /export\\s+const\\s+(\\w+)\\s*=\\s*defineHTTPRequest/g;\n while ((match = httpRegex.exec(content)) !== null) {\n httpHandlers.push({\n name: match[1],\n filePath: fullPath,\n });\n }\n\n // Find: export const workerName = defineWorker(...)\n const workerRegex = /export\\s+const\\s+(\\w+)\\s*=\\s*defineWorker/g;\n while ((match = workerRegex.exec(content)) !== null) {\n workers.push({\n name: match[1],\n filePath: fullPath,\n });\n }\n }\n }\n }\n\n walk(serverDir);\n return { methods, httpHandlers, middleware, workers };\n}\n\n/**\n * Convert a file path to a route pattern (same logic as client-side router)\n */\nfunction pathFromFile(file: string, root: string): string {\n // Remove root/src/pages prefix and file extension\n const pagesDir = path.join(root, \"src\", \"pages\");\n const withoutPrefix = file.replace(pagesDir, \"\").replace(/\\.(tsx|jsx|ts|js)$/, \"\");\n\n // Handle special files\n if (withoutPrefix === \"/404\") {\n return \"__404__\";\n }\n\n // Remove route groups (folders in parentheses)\n let pattern = withoutPrefix.replace(/\\/\\([^)]+\\)/g, \"\");\n\n // Convert /index to /\n pattern = pattern.replace(/\\/index$/, \"\") || \"/\";\n // Convert [...param] to *param (catch-all)\n pattern = pattern.replace(/\\[\\.\\.\\.(.+?)\\]/g, \"*$1\");\n // Convert [param] to :param (single dynamic segment)\n pattern = pattern.replace(/\\[(.+?)\\]/g, \":$1\");\n\n return pattern;\n}\n\nexport interface RouteCollision {\n pattern: string;\n files: string[];\n}\n\n/**\n * Scan pages directory and detect route collisions\n */\nexport function scanPageRoutes(root: string): { collisions: RouteCollision[]; totalRoutes: number } {\n const pagesDir = path.join(root, \"src\", \"pages\");\n\n if (!fs.existsSync(pagesDir)) {\n return { collisions: [], totalRoutes: 0 };\n }\n\n const routePatternMap = new Map<string, string>();\n const collisions: RouteCollision[] = [];\n\n function walkPages(dir: string) {\n const items = fs.readdirSync(dir);\n\n for (const item of items) {\n const fullPath = path.join(dir, item);\n const stat = fs.statSync(fullPath);\n\n if (stat.isDirectory()) {\n walkPages(fullPath);\n } else if (/\\.(tsx|jsx|ts|js)$/.test(item)) {\n // Skip layout files\n if (item.includes(\"_layout.\")) {\n continue;\n }\n\n const pathPattern = pathFromFile(fullPath, root);\n\n // Skip special pages\n if (pathPattern === \"__404__\") {\n continue;\n }\n\n // Check for collision\n const existingFile = routePatternMap.get(pathPattern);\n if (existingFile) {\n // Check if this collision was already recorded\n const existingCollision = collisions.find((c) => c.pattern === pathPattern);\n if (existingCollision) {\n existingCollision.files.push(fullPath);\n } else {\n collisions.push({\n pattern: pathPattern,\n files: [existingFile, fullPath],\n });\n }\n } else {\n routePatternMap.set(pathPattern, fullPath);\n }\n }\n }\n }\n\n walkPages(pagesDir);\n return { collisions, totalRoutes: routePatternMap.size };\n}\n\n/**\n * Check for route collisions and log warnings\n */\nexport function checkRouteCollisions(root: string): boolean {\n const { collisions, totalRoutes } = scanPageRoutes(root);\n\n if (collisions.length === 0) {\n return false;\n }\n\n log(\"warn\", \"⚠️ Route collisions detected! Multiple files resolve to the same URL path:\");\n log(\"warn\", \"\");\n\n for (const collision of collisions) {\n log(\"error\", ` Route pattern: \"${collision.pattern}\"`);\n for (const file of collision.files) {\n const relative = path.relative(root, file);\n log(\"error\", ` - ${relative}`);\n }\n log(\"error\", ` ⚠️ Only the first file will be accessible.`);\n log(\"warn\", \"\");\n }\n\n log(\"warn\", `Found ${collisions.length} collision(s) across ${totalRoutes} unique routes.`);\n log(\"warn\", \"Consider using different file names or organizing files in subdirectories.\");\n log(\"warn\", \"\");\n\n return true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/vite/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAmCxC,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC1C,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,OAAO,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,YAAY,GAAwB,EAAE,CAAC;IAC7C,MAAM,WAAW,GAAwB,EAAE,CAAC;IAC5C,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,UAAwC,CAAC;IAE7C,SAAS,IAAI,CAAC,GAAW;QACrB,IAAI,KAAe,CAAC;QACpB,IAAI,CAAC;YACD,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACL,gDAAgD;YAChD,OAAO;QACX,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtC,IAAI,IAAc,CAAC;YACnB,IAAI,CAAC;gBACD,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACjC,CAAC;YAAC,MAAM,CAAC;gBACL,2CAA2C;gBAC3C,SAAS;YACb,CAAC;YAED,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrB,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnB,CAAC;iBAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzD,IAAI,OAAe,CAAC;gBACpB,IAAI,CAAC;oBACD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACjD,CAAC;gBAAC,MAAM,CAAC;oBACL,4CAA4C;oBAC5C,SAAS;gBACb,CAAC;gBAED,yDAAyD;gBACzD,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;oBACtB,SAAS;gBACb,CAAC;gBAED,gCAAgC;gBAChC,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;oBAC5B,6EAA6E;oBAC7E,MAAM,eAAe,GAAG,sEAAsE,CAAC;oBAC/F,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBAC5C,IAAI,KAAK,EAAE,CAAC;wBACR,UAAU,GAAG;4BACT,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;4BACd,QAAQ,EAAE,QAAQ;yBACrB,CAAC;oBACN,CAAC;oBACD,8BAA8B;oBAC9B,MAAM,YAAY,GAAG,kDAAkD,CAAC;oBACxE,IAAI,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC7B,UAAU,GAAG;4BACT,IAAI,EAAE,SAAS;4BACf,QAAQ,EAAE,QAAQ;yBACrB,CAAC;oBACN,CAAC;gBACL,CAAC;gBAED,oDAAoD;gBACpD,MAAM,WAAW,GAAG,4CAA4C,CAAC;gBACjE,IAAI,KAAK,CAAC;gBACV,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBAClD,OAAO,CAAC,IAAI,CAAC;wBACT,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;wBACd,QAAQ,EAAE,QAAQ;qBACrB,CAAC,CAAC;gBACP,CAAC;gBAED,0DAA0D;gBAC1D,MAAM,SAAS,GAAG,iDAAiD,CAAC;gBACpE,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBAChD,YAAY,CAAC,IAAI,CAAC;wBACd,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;wBACd,QAAQ,EAAE,QAAQ;qBACrB,CAAC,CAAC;gBACP,CAAC;gBAED,sDAAsD;gBACtD,MAAM,QAAQ,GAAG,iDAAiD,CAAC;gBACnE,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBAC/C,WAAW,CAAC,IAAI,CAAC;wBACb,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;wBACd,QAAQ,EAAE,QAAQ;qBACrB,CAAC,CAAC;gBACP,CAAC;gBAED,oDAAoD;gBACpD,MAAM,WAAW,GAAG,4CAA4C,CAAC;gBACjE,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;oBAClD,OAAO,CAAC,IAAI,CAAC;wBACT,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;wBACd,QAAQ,EAAE,QAAQ;qBACrB,CAAC,CAAC;gBACP,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED,IAAI,CAAC,SAAS,CAAC,CAAC;IAChB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACvE,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAY,EAAE,IAAY;IAC5C,kDAAkD;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAEnF,uBAAuB;IACvB,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,+CAA+C;IAC/C,IAAI,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAExD,sBAAsB;IACtB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;IACjD,2CAA2C;IAC3C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IACrD,qDAAqD;IACrD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAE/C,OAAO,OAAO,CAAC;AACnB,CAAC;AAOD,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,SAAS,SAAS,CAAC,GAAW;QAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEnC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrB,SAAS,CAAC,QAAQ,CAAC,CAAC;gBACpB,SAAS;YACb,CAAC;YAED,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,SAAS;YACb,CAAC;YAED,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC5B,SAAS;YACb,CAAC;YAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC7C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBACxB,SAAS;YACb,CAAC;YAED,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEpB,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAEjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IAC9C,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,MAAM,UAAU,GAAqB,EAAE,CAAC;IAExC,SAAS,SAAS,CAAC,GAAW;QAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEnC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrB,SAAS,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;iBAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,oBAAoB;gBACpB,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5B,SAAS;gBACb,CAAC;gBAED,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBAEjD,qBAAqB;gBACrB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBAC5B,SAAS;gBACb,CAAC;gBAED,sBAAsB;gBACtB,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACtD,IAAI,YAAY,EAAE,CAAC;oBACf,+CAA+C;oBAC/C,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,WAAW,CAAC,CAAC;oBAC5E,IAAI,iBAAiB,EAAE,CAAC;wBACpB,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAC3C,CAAC;yBAAM,CAAC;wBACJ,UAAU,CAAC,IAAI,CAAC;4BACZ,OAAO,EAAE,WAAW;4BACpB,KAAK,EAAE,CAAC,YAAY,EAAE,QAAQ,CAAC;yBAClC,CAAC,CAAC;oBACP,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACJ,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;gBAC/C,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED,SAAS,CAAC,QAAQ,CAAC,CAAC;IACpB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,CAAC,IAAI,EAAE,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC7C,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAEzD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,GAAG,CAAC,MAAM,EAAE,6EAA6E,CAAC,CAAC;IAC3F,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEhB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACjC,GAAG,CAAC,OAAO,EAAE,qBAAqB,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC;QACxD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC3C,GAAG,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,GAAG,CAAC,OAAO,EAAE,+CAA+C,CAAC,CAAC;QAC9D,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpB,CAAC;IAED,GAAG,CAAC,MAAM,EAAE,SAAS,UAAU,CAAC,MAAM,wBAAwB,WAAW,iBAAiB,CAAC,CAAC;IAC5F,GAAG,CAAC,MAAM,EAAE,4EAA4E,CAAC,CAAC;IAC1F,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEhB,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\nimport { log } from \"../utils/logger.js\";\nimport { SERVER_DIR } from \"./paths.js\";\n\nexport interface MethodExport {\n name: string;\n filePath: string;\n}\n\nexport interface HTTPHandlerExport {\n name: string;\n filePath: string;\n}\n\nexport interface MiddlewareExport {\n name: string;\n filePath: string;\n}\n\nexport interface WorkerExport {\n name: string;\n filePath: string;\n}\n\nexport interface SEOMetadataExport {\n name: string;\n filePath: string;\n}\n\nexport interface ServerExports {\n methods: MethodExport[];\n httpHandlers: HTTPHandlerExport[];\n seoMetadata: SEOMetadataExport[];\n middleware?: MiddlewareExport;\n workers: WorkerExport[];\n}\n\nexport function scanServerMethods(root: string): MethodExport[] {\n const exports = scanServerExports(root);\n return exports.methods;\n}\n\nexport function scanServerExports(root: string): ServerExports {\n const serverDir = path.resolve(root, SERVER_DIR);\n if (!fs.existsSync(serverDir)) {\n return { methods: [], httpHandlers: [], seoMetadata: [], workers: [] };\n }\n\n const methods: MethodExport[] = [];\n const httpHandlers: HTTPHandlerExport[] = [];\n const seoMetadata: SEOMetadataExport[] = [];\n const workers: WorkerExport[] = [];\n let middleware: MiddlewareExport | undefined;\n\n function walk(dir: string) {\n let files: string[];\n try {\n files = fs.readdirSync(dir);\n } catch {\n // Directory might have been deleted during scan\n return;\n }\n for (const file of files) {\n const fullPath = path.join(dir, file);\n let stat: fs.Stats;\n try {\n stat = fs.statSync(fullPath);\n } catch {\n // File might have been deleted during scan\n continue;\n }\n\n if (stat.isDirectory()) {\n walk(fullPath);\n } else if (file.endsWith(\".ts\") && !file.endsWith(\".d.ts\")) {\n let content: string;\n try {\n content = fs.readFileSync(fullPath, \"utf-8\");\n } catch {\n // File might be being written to or deleted\n continue;\n }\n\n // Skip empty or near-empty files (likely partial writes)\n if (content.length < 10) {\n continue;\n }\n\n // Check for _middleware.ts file\n if (file === \"_middleware.ts\") {\n // Support both 'middleware' and 'defineMiddleware' (backwards compatibility)\n const middlewareRegex = /export\\s+(const|default)\\s+(\\w+)\\s*=\\s*(middleware|defineMiddleware)/;\n const match = middlewareRegex.exec(content);\n if (match) {\n middleware = {\n name: match[2],\n filePath: fullPath,\n };\n }\n // Also support default export\n const defaultRegex = /export\\s+default\\s+(middleware|defineMiddleware)/;\n if (defaultRegex.test(content)) {\n middleware = {\n name: \"default\",\n filePath: fullPath,\n };\n }\n }\n\n // Find: export const methodName = defineMethod(...)\n const methodRegex = /export\\s+const\\s+(\\w+)\\s*=\\s*defineMethod/g;\n let match;\n while ((match = methodRegex.exec(content)) !== null) {\n methods.push({\n name: match[1],\n filePath: fullPath,\n });\n }\n\n // Find: export const handlerName = defineHTTPRequest(...)\n const httpRegex = /export\\s+const\\s+(\\w+)\\s*=\\s*defineHTTPRequest/g;\n while ((match = httpRegex.exec(content)) !== null) {\n httpHandlers.push({\n name: match[1],\n filePath: fullPath,\n });\n }\n\n // Find: export const seoName = defineSEOMetadata(...)\n const seoRegex = /export\\s+const\\s+(\\w+)\\s*=\\s*defineSEOMetadata/g;\n while ((match = seoRegex.exec(content)) !== null) {\n seoMetadata.push({\n name: match[1],\n filePath: fullPath,\n });\n }\n\n // Find: export const workerName = defineWorker(...)\n const workerRegex = /export\\s+const\\s+(\\w+)\\s*=\\s*defineWorker/g;\n while ((match = workerRegex.exec(content)) !== null) {\n workers.push({\n name: match[1],\n filePath: fullPath,\n });\n }\n }\n }\n }\n\n walk(serverDir);\n return { methods, httpHandlers, seoMetadata, middleware, workers };\n}\n\n/**\n * Convert a file path to a route pattern (same logic as client-side router)\n */\nfunction pathFromFile(file: string, root: string): string {\n // Remove root/src/pages prefix and file extension\n const pagesDir = path.join(root, \"src\", \"pages\");\n const withoutPrefix = file.replace(pagesDir, \"\").replace(/\\.(tsx|jsx|ts|js)$/, \"\");\n\n // Handle special files\n if (withoutPrefix === \"/404\") {\n return \"__404__\";\n }\n\n // Remove route groups (folders in parentheses)\n let pattern = withoutPrefix.replace(/\\/\\([^)]+\\)/g, \"\");\n\n // Convert /index to /\n pattern = pattern.replace(/\\/index$/, \"\") || \"/\";\n // Convert [...param] to *param (catch-all)\n pattern = pattern.replace(/\\[\\.\\.\\.(.+?)\\]/g, \"*$1\");\n // Convert [param] to :param (single dynamic segment)\n pattern = pattern.replace(/\\[(.+?)\\]/g, \":$1\");\n\n return pattern;\n}\n\nexport interface RouteCollision {\n pattern: string;\n files: string[];\n}\n\nexport function scanPageRoutePatterns(root: string): string[] {\n const pagesDir = path.join(root, \"src\", \"pages\");\n if (!fs.existsSync(pagesDir)) {\n return [];\n }\n\n const patterns = new Set<string>();\n\n function walkPages(dir: string) {\n const items = fs.readdirSync(dir);\n\n for (const item of items) {\n const fullPath = path.join(dir, item);\n const stat = fs.statSync(fullPath);\n\n if (stat.isDirectory()) {\n walkPages(fullPath);\n continue;\n }\n\n if (!/\\.(tsx|jsx|ts|js)$/.test(item)) {\n continue;\n }\n\n if (item.includes(\"_layout.\")) {\n continue;\n }\n\n const pattern = pathFromFile(fullPath, root);\n if (pattern === \"__404__\") {\n continue;\n }\n\n patterns.add(pattern);\n }\n }\n\n walkPages(pagesDir);\n\n return [...patterns];\n}\n\n/**\n * Scan pages directory and detect route collisions\n */\nexport function scanPageRoutes(root: string): { collisions: RouteCollision[]; totalRoutes: number } {\n const pagesDir = path.join(root, \"src\", \"pages\");\n\n if (!fs.existsSync(pagesDir)) {\n return { collisions: [], totalRoutes: 0 };\n }\n\n const routePatternMap = new Map<string, string>();\n const collisions: RouteCollision[] = [];\n\n function walkPages(dir: string) {\n const items = fs.readdirSync(dir);\n\n for (const item of items) {\n const fullPath = path.join(dir, item);\n const stat = fs.statSync(fullPath);\n\n if (stat.isDirectory()) {\n walkPages(fullPath);\n } else if (/\\.(tsx|jsx|ts|js)$/.test(item)) {\n // Skip layout files\n if (item.includes(\"_layout.\")) {\n continue;\n }\n\n const pathPattern = pathFromFile(fullPath, root);\n\n // Skip special pages\n if (pathPattern === \"__404__\") {\n continue;\n }\n\n // Check for collision\n const existingFile = routePatternMap.get(pathPattern);\n if (existingFile) {\n // Check if this collision was already recorded\n const existingCollision = collisions.find((c) => c.pattern === pathPattern);\n if (existingCollision) {\n existingCollision.files.push(fullPath);\n } else {\n collisions.push({\n pattern: pathPattern,\n files: [existingFile, fullPath],\n });\n }\n } else {\n routePatternMap.set(pathPattern, fullPath);\n }\n }\n }\n }\n\n walkPages(pagesDir);\n return { collisions, totalRoutes: routePatternMap.size };\n}\n\n/**\n * Check for route collisions and log warnings\n */\nexport function checkRouteCollisions(root: string): boolean {\n const { collisions, totalRoutes } = scanPageRoutes(root);\n\n if (collisions.length === 0) {\n return false;\n }\n\n log(\"warn\", \"⚠️ Route collisions detected! Multiple files resolve to the same URL path:\");\n log(\"warn\", \"\");\n\n for (const collision of collisions) {\n log(\"error\", ` Route pattern: \"${collision.pattern}\"`);\n for (const file of collision.files) {\n const relative = path.relative(root, file);\n log(\"error\", ` - ${relative}`);\n }\n log(\"error\", ` ⚠️ Only the first file will be accessible.`);\n log(\"warn\", \"\");\n }\n\n log(\"warn\", `Found ${collisions.length} collision(s) across ${totalRoutes} unique routes.`);\n log(\"warn\", \"Consider using different file names or organizing files in subdirectories.\");\n log(\"warn\", \"\");\n\n return true;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { HTTPHandlerExport, MethodExport, MiddlewareExport, WorkerExport } from "./scanner.js";
|
|
2
|
-
export declare function generateServerManifest(methods: MethodExport[], httpHandlers: HTTPHandlerExport[], middleware?: MiddlewareExport, workers?: WorkerExport[]): string;
|
|
1
|
+
import { HTTPHandlerExport, MethodExport, MiddlewareExport, SEOMetadataExport, WorkerExport } from "./scanner.js";
|
|
2
|
+
export declare function generateServerManifest(methods: MethodExport[], httpHandlers: HTTPHandlerExport[], seoMetadata?: SEOMetadataExport[], pageRoutePatterns?: string[], middleware?: MiddlewareExport, workers?: WorkerExport[]): string;
|
|
3
3
|
export declare function generateClientModule(methods: MethodExport[]): string;
|
|
4
4
|
export declare function generateTypeDefinitions(methods: MethodExport[], root: string): string;
|
|
5
5
|
export declare function generateEntryModule(): string;
|
|
@@ -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,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
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,YAAY,EAAE,MAAM,cAAc,CAAC;AAElH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,iBAAiB,EAAE,EACjC,WAAW,GAAE,iBAAiB,EAAO,EACrC,iBAAiB,GAAE,MAAM,EAAO,EAChC,UAAU,CAAC,EAAE,gBAAgB,EAC7B,OAAO,GAAE,YAAY,EAAO,GAC7B,MAAM,CAyCR;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAIpE;AAkBD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA+DrF;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAkB5C"}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
export function generateServerManifest(methods, httpHandlers, middleware, workers = []) {
|
|
2
|
+
export function generateServerManifest(methods, httpHandlers, seoMetadata = [], pageRoutePatterns = [], middleware, workers = []) {
|
|
3
3
|
const methodImports = methods.map((m, i) => `import { ${m.name} as method_${i} } from '${m.filePath}';`).join("\n");
|
|
4
4
|
const httpImports = httpHandlers.map((h, i) => `import { ${h.name} as http_${i} } from '${h.filePath}';`).join("\n");
|
|
5
|
+
const seoImports = seoMetadata.map((s, i) => `import { ${s.name} as seo_${i} } from '${s.filePath}';`).join("\n");
|
|
5
6
|
const workerImports = workers.map((w, i) => `import { ${w.name} as worker_${i} } from '${w.filePath}';`).join("\n");
|
|
6
7
|
const middlewareImport = middleware ? `import ${middleware.name === "default" ? "middleware" : `{ ${middleware.name} as middleware }`} from '${middleware.filePath}';` : "";
|
|
7
8
|
const methodRegistrations = methods.map((m, i) => ` registry.register('${m.name}', method_${i});`).join("\n");
|
|
8
9
|
const httpExports = httpHandlers.map((h, i) => ` { name: '${h.name}', handler: http_${i} },`).join("\n");
|
|
10
|
+
const seoExports = seoMetadata.map((s, i) => ` { name: '${s.name}', handler: seo_${i} },`).join("\n");
|
|
9
11
|
const workerExports = workers.map((w, i) => ` { name: '${w.name}', worker: worker_${i} },`).join("\n");
|
|
10
12
|
return `
|
|
11
13
|
${methodImports}
|
|
12
14
|
${httpImports}
|
|
15
|
+
${seoImports}
|
|
13
16
|
${workerImports}
|
|
14
17
|
${middlewareImport}
|
|
15
18
|
|
|
@@ -21,6 +24,12 @@ export const httpHandlers = [
|
|
|
21
24
|
${httpExports}
|
|
22
25
|
];
|
|
23
26
|
|
|
27
|
+
export const seoMetadataHandlers = [
|
|
28
|
+
${seoExports}
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
export const pageRoutePatterns = ${JSON.stringify(pageRoutePatterns)};
|
|
32
|
+
|
|
24
33
|
export const workers = [
|
|
25
34
|
${workerExports}
|
|
26
35
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualServerModule.js","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,MAAM,UAAU,sBAAsB,
|
|
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, WorkerExport } from \"./scanner.js\";\n\nexport function generateServerManifest(\n methods: MethodExport[],\n httpHandlers: HTTPHandlerExport[],\n seoMetadata: SEOMetadataExport[] = [],\n pageRoutePatterns: string[] = [],\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 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 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\n/**\n * Generate a deterministic suffix from a string.\n * Uses only file path and method name (NOT index) so that adding/removing\n * other methods does not change existing aliases.\n */\nfunction stableAlias(filePath: string, name: string): string {\n const input = `${filePath}:${name}`;\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return `${name}_${Math.abs(hash).toString(36)}`;\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 methodsWithAlias = sorted.map((m) => ({\n ...m,\n alias: stableAlias(m.filePath, m.name),\n }));\n\n const imports = methodsWithAlias\n .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 `import type { ${m.name} as ${m.alias} } from '${relPath}';`;\n })\n .join(\"\\n\");\n\n const methodExports = methodsWithAlias\n .map((m) => {\n return ` export const ${m.name}: import('heliumts/client').MethodStub<\n Parameters<typeof ${m.alias}['handler']>[0],\n Awaited<ReturnType<typeof ${m.alias}['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 = methodsWithAlias.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 } 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\ncreateRoot(rootEl).render(\n <React.StrictMode>\n <AppRouter AppShell={App} />\n </React.StrictMode>\n);\n`;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "heliumts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A lightweight full-stack React framework with file-based routing, RPC, and SSG support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"build": "tsc -p tsconfig.json",
|
|
64
64
|
"prepare": "npm run build",
|
|
65
65
|
"prepublishOnly": "npm run build",
|
|
66
|
+
"pentest": "node scripts/helium-pentest.mjs",
|
|
66
67
|
"format": "prettier --write \"src/**/*.{ts,tsx,js}\"",
|
|
67
68
|
"format:check": "prettier --check \"src/**/*.{ts,tsx,js}\"",
|
|
68
69
|
"lint": "eslint --ext .ts,.tsx src",
|