heliumts 0.2.2

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.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +356 -0
  3. package/dist/bin/helium.d.ts +3 -0
  4. package/dist/bin/helium.d.ts.map +1 -0
  5. package/dist/bin/helium.js +236 -0
  6. package/dist/bin/helium.js.map +1 -0
  7. package/dist/client/Router.d.ts +83 -0
  8. package/dist/client/Router.d.ts.map +1 -0
  9. package/dist/client/Router.js +329 -0
  10. package/dist/client/Router.js.map +1 -0
  11. package/dist/client/cache.d.ts +8 -0
  12. package/dist/client/cache.d.ts.map +1 -0
  13. package/dist/client/cache.js +82 -0
  14. package/dist/client/cache.js.map +1 -0
  15. package/dist/client/index.d.ts +10 -0
  16. package/dist/client/index.d.ts.map +1 -0
  17. package/dist/client/index.js +9 -0
  18. package/dist/client/index.js.map +1 -0
  19. package/dist/client/prefetch.d.ts +12 -0
  20. package/dist/client/prefetch.d.ts.map +1 -0
  21. package/dist/client/prefetch.js +33 -0
  22. package/dist/client/prefetch.js.map +1 -0
  23. package/dist/client/routerManifest.d.ts +28 -0
  24. package/dist/client/routerManifest.d.ts.map +1 -0
  25. package/dist/client/routerManifest.js +242 -0
  26. package/dist/client/routerManifest.js.map +1 -0
  27. package/dist/client/rpcClient.d.ts +33 -0
  28. package/dist/client/rpcClient.d.ts.map +1 -0
  29. package/dist/client/rpcClient.js +383 -0
  30. package/dist/client/rpcClient.js.map +1 -0
  31. package/dist/client/transitions.d.ts +85 -0
  32. package/dist/client/transitions.d.ts.map +1 -0
  33. package/dist/client/transitions.js +92 -0
  34. package/dist/client/transitions.js.map +1 -0
  35. package/dist/client/types.d.ts +6 -0
  36. package/dist/client/types.d.ts.map +1 -0
  37. package/dist/client/types.js +2 -0
  38. package/dist/client/types.js.map +1 -0
  39. package/dist/client/useCall.d.ts +31 -0
  40. package/dist/client/useCall.d.ts.map +1 -0
  41. package/dist/client/useCall.js +40 -0
  42. package/dist/client/useCall.js.map +1 -0
  43. package/dist/client/useFetch.d.ts +34 -0
  44. package/dist/client/useFetch.d.ts.map +1 -0
  45. package/dist/client/useFetch.js +152 -0
  46. package/dist/client/useFetch.js.map +1 -0
  47. package/dist/index.d.ts +4 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +4 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/runtime/protocol.d.ts +25 -0
  52. package/dist/runtime/protocol.d.ts.map +1 -0
  53. package/dist/runtime/protocol.js +2 -0
  54. package/dist/runtime/protocol.js.map +1 -0
  55. package/dist/server/config.d.ts +216 -0
  56. package/dist/server/config.d.ts.map +1 -0
  57. package/dist/server/config.js +130 -0
  58. package/dist/server/config.js.map +1 -0
  59. package/dist/server/context.d.ts +38 -0
  60. package/dist/server/context.d.ts.map +1 -0
  61. package/dist/server/context.js +2 -0
  62. package/dist/server/context.js.map +1 -0
  63. package/dist/server/defineHTTPRequest.d.ts +49 -0
  64. package/dist/server/defineHTTPRequest.d.ts.map +1 -0
  65. package/dist/server/defineHTTPRequest.js +34 -0
  66. package/dist/server/defineHTTPRequest.js.map +1 -0
  67. package/dist/server/defineMethod.d.ts +20 -0
  68. package/dist/server/defineMethod.d.ts.map +1 -0
  69. package/dist/server/defineMethod.js +23 -0
  70. package/dist/server/defineMethod.js.map +1 -0
  71. package/dist/server/devServer.d.ts +15 -0
  72. package/dist/server/devServer.d.ts.map +1 -0
  73. package/dist/server/devServer.js +219 -0
  74. package/dist/server/devServer.js.map +1 -0
  75. package/dist/server/handlerLoader.d.ts +1 -0
  76. package/dist/server/handlerLoader.d.ts.map +1 -0
  77. package/dist/server/handlerLoader.js +2 -0
  78. package/dist/server/handlerLoader.js.map +1 -0
  79. package/dist/server/httpRouter.d.ts +17 -0
  80. package/dist/server/httpRouter.d.ts.map +1 -0
  81. package/dist/server/httpRouter.js +227 -0
  82. package/dist/server/httpRouter.js.map +1 -0
  83. package/dist/server/index.d.ts +11 -0
  84. package/dist/server/index.d.ts.map +1 -0
  85. package/dist/server/index.js +13 -0
  86. package/dist/server/index.js.map +1 -0
  87. package/dist/server/middleware.d.ts +30 -0
  88. package/dist/server/middleware.d.ts.map +1 -0
  89. package/dist/server/middleware.js +23 -0
  90. package/dist/server/middleware.js.map +1 -0
  91. package/dist/server/prodServer.d.ts +27 -0
  92. package/dist/server/prodServer.d.ts.map +1 -0
  93. package/dist/server/prodServer.js +301 -0
  94. package/dist/server/prodServer.js.map +1 -0
  95. package/dist/server/rateLimiter.d.ts +36 -0
  96. package/dist/server/rateLimiter.d.ts.map +1 -0
  97. package/dist/server/rateLimiter.js +113 -0
  98. package/dist/server/rateLimiter.js.map +1 -0
  99. package/dist/server/rpcRegistry.d.ts +34 -0
  100. package/dist/server/rpcRegistry.d.ts.map +1 -0
  101. package/dist/server/rpcRegistry.js +231 -0
  102. package/dist/server/rpcRegistry.js.map +1 -0
  103. package/dist/server/security.d.ts +5 -0
  104. package/dist/server/security.d.ts.map +1 -0
  105. package/dist/server/security.js +59 -0
  106. package/dist/server/security.js.map +1 -0
  107. package/dist/server/serializer.d.ts +9 -0
  108. package/dist/server/serializer.d.ts.map +1 -0
  109. package/dist/server/serializer.js +40 -0
  110. package/dist/server/serializer.js.map +1 -0
  111. package/dist/utils/envLoader.d.ts +27 -0
  112. package/dist/utils/envLoader.d.ts.map +1 -0
  113. package/dist/utils/envLoader.js +68 -0
  114. package/dist/utils/envLoader.js.map +1 -0
  115. package/dist/utils/ipExtractor.d.ts +59 -0
  116. package/dist/utils/ipExtractor.d.ts.map +1 -0
  117. package/dist/utils/ipExtractor.js +126 -0
  118. package/dist/utils/ipExtractor.js.map +1 -0
  119. package/dist/utils/logger.d.ts +2 -0
  120. package/dist/utils/logger.d.ts.map +1 -0
  121. package/dist/utils/logger.js +24 -0
  122. package/dist/utils/logger.js.map +1 -0
  123. package/dist/vite/heliumPlugin.d.ts +3 -0
  124. package/dist/vite/heliumPlugin.d.ts.map +1 -0
  125. package/dist/vite/heliumPlugin.js +294 -0
  126. package/dist/vite/heliumPlugin.js.map +1 -0
  127. package/dist/vite/index.d.ts +3 -0
  128. package/dist/vite/index.d.ts.map +1 -0
  129. package/dist/vite/index.js +3 -0
  130. package/dist/vite/index.js.map +1 -0
  131. package/dist/vite/paths.d.ts +8 -0
  132. package/dist/vite/paths.d.ts.map +1 -0
  133. package/dist/vite/paths.js +8 -0
  134. package/dist/vite/paths.js.map +1 -0
  135. package/dist/vite/scanner.d.ts +35 -0
  136. package/dist/vite/scanner.d.ts.map +1 -0
  137. package/dist/vite/scanner.js +167 -0
  138. package/dist/vite/scanner.js.map +1 -0
  139. package/dist/vite/ssg.d.ts +22 -0
  140. package/dist/vite/ssg.d.ts.map +1 -0
  141. package/dist/vite/ssg.js +547 -0
  142. package/dist/vite/ssg.js.map +1 -0
  143. package/dist/vite/virtualServerModule.d.ts +6 -0
  144. package/dist/vite/virtualServerModule.d.ts.map +1 -0
  145. package/dist/vite/virtualServerModule.js +82 -0
  146. package/dist/vite/virtualServerModule.js.map +1 -0
  147. package/package.json +103 -0
@@ -0,0 +1,547 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { log } from "../utils/logger.js";
4
+ import { scanServerExports } from "./scanner.js";
5
+ import { generateClientModule } from "./virtualServerModule.js";
6
+ /**
7
+ * Remove string literals from content to avoid false positives when checking for patterns
8
+ * This removes template literals, single-quoted strings, and double-quoted strings
9
+ */
10
+ function stripStringLiterals(content) {
11
+ // Remove template literals (backtick strings) - handle nested expressions
12
+ let result = content;
13
+ // Remove template literals with their content (simplified - doesn't handle all edge cases but good enough)
14
+ result = result.replace(/`(?:[^`\\]|\\.)*`/g, '""');
15
+ // Remove double-quoted strings
16
+ result = result.replace(/"(?:[^"\\]|\\.)*"/g, '""');
17
+ // Remove single-quoted strings
18
+ result = result.replace(/'(?:[^'\\]|\\.)*'/g, "''");
19
+ // Also remove JSX text content between tags (but not the tags themselves)
20
+ // This helps with cases like <code>useState</code>
21
+ result = result.replace(/>([^<]+)</g, "><");
22
+ return result;
23
+ }
24
+ /**
25
+ * Validate if a page file can be truly statically generated
26
+ * Checks for React hooks and helium imports that would prevent static generation
27
+ */
28
+ function validateSSGPage(filePath) {
29
+ const rawContent = fs.readFileSync(filePath, "utf-8");
30
+ const warnings = [];
31
+ // Strip string literals and JSX text to avoid false positives
32
+ const content = stripStringLiterals(rawContent);
33
+ // Check for React hooks (common ones)
34
+ const hookPatterns = [
35
+ /\buse(State|Effect|Context|Reducer|Callback|Memo|Ref|ImperativeHandle|LayoutEffect|DebugValue)\s*\(/,
36
+ /\buse[A-Z]\w+\s*\(/, // Custom hooks (useXxx) - must be followed by ( to be a call
37
+ ];
38
+ const hasHooks = hookPatterns.some((pattern) => pattern.test(content));
39
+ if (hasHooks) {
40
+ warnings.push("Page uses React hooks which may cause hydration issues");
41
+ }
42
+ // Check for heliumts/client imports - use raw content since imports should be at top level
43
+ const hasClientImports = /^import\s+.*from\s+['"]heliumts\/client['"]/m.test(rawContent);
44
+ if (hasClientImports) {
45
+ warnings.push("Page imports from 'heliumts/client' which requires client-side execution");
46
+ }
47
+ // Check for heliumts/server imports - use raw content since imports should be at top level
48
+ const hasServerImports = /^import\s+.*from\s+['"]heliumts\/server['"]/m.test(rawContent);
49
+ if (hasServerImports) {
50
+ warnings.push("Page imports from 'heliumts/server' which may cause runtime issues");
51
+ }
52
+ return {
53
+ hasHooks,
54
+ hasClientImports,
55
+ hasServerImports,
56
+ warnings,
57
+ };
58
+ }
59
+ /**
60
+ * Scan pages directory and find all pages with "use ssg" directive
61
+ */
62
+ export function scanSSGPages(root) {
63
+ const pagesDir = path.join(root, "src", "pages");
64
+ if (!fs.existsSync(pagesDir)) {
65
+ return [];
66
+ }
67
+ const ssgPages = [];
68
+ function walkDirectory(dir) {
69
+ const items = fs.readdirSync(dir);
70
+ for (const item of items) {
71
+ const fullPath = path.join(dir, item);
72
+ const stat = fs.statSync(fullPath);
73
+ if (stat.isDirectory()) {
74
+ walkDirectory(fullPath);
75
+ }
76
+ else if (/\.(tsx|jsx|ts|js)$/.test(item)) {
77
+ const content = fs.readFileSync(fullPath, "utf-8");
78
+ // Check for "use ssg"; directive at the top of the file
79
+ if (/^\s*["']use ssg["']\s*;/m.test(content)) {
80
+ const relativePath = path.relative(path.join(root, "src"), fullPath);
81
+ const urlPath = filePathToUrlPath(relativePath);
82
+ // Validate the page for SSG compatibility
83
+ const validation = validateSSGPage(fullPath);
84
+ const warnings = [...validation.warnings];
85
+ // Also check all layouts for this page
86
+ const layoutPaths = findLayoutPathsForPage(fullPath, root);
87
+ for (const layoutPath of layoutPaths) {
88
+ const layoutValidation = validateSSGPage(layoutPath);
89
+ if (layoutValidation.warnings.length > 0) {
90
+ const layoutRelative = path.relative(path.join(root, "src"), layoutPath);
91
+ warnings.push(`Layout ${layoutRelative} has issues:`);
92
+ for (const warning of layoutValidation.warnings) {
93
+ warnings.push(` └─ ${warning}`);
94
+ }
95
+ }
96
+ }
97
+ ssgPages.push({
98
+ filePath: fullPath,
99
+ urlPath,
100
+ relativePath,
101
+ warnings,
102
+ });
103
+ }
104
+ }
105
+ }
106
+ }
107
+ walkDirectory(pagesDir);
108
+ return ssgPages;
109
+ }
110
+ /**
111
+ * Convert file path to URL path
112
+ * pages/index.tsx -> /
113
+ * pages/about.tsx -> /about
114
+ * pages/blog/post.tsx -> /blog/post
115
+ * pages/(website)/contact.tsx -> /contact
116
+ * pages/(portal)/dashboard.tsx -> /dashboard
117
+ */
118
+ function filePathToUrlPath(relativePath) {
119
+ // Remove 'pages/' prefix and file extension
120
+ let urlPath = relativePath.replace(/^pages\//, "").replace(/\.(tsx|jsx|ts|js)$/, "");
121
+ // Remove route groups (folders in parentheses)
122
+ // E.g., (website)/contact -> /contact
123
+ urlPath = urlPath.replace(/\([^)]+\)\//g, "");
124
+ // Handle index files
125
+ if (urlPath.endsWith("/index") || urlPath === "index") {
126
+ urlPath = urlPath.replace(/\/index$/, "").replace(/^index$/, "");
127
+ }
128
+ // Ensure leading slash
129
+ if (!urlPath.startsWith("/")) {
130
+ urlPath = "/" + urlPath;
131
+ }
132
+ // Root path
133
+ if (urlPath === "/") {
134
+ return "/";
135
+ }
136
+ return urlPath;
137
+ }
138
+ /**
139
+ * Convert URL path to output file path
140
+ * / -> __index.html (special case - renamed later to prevent conflicts)
141
+ * /about -> about.html
142
+ * /blog/post -> blog/post.html
143
+ */
144
+ function urlPathToOutputPath(urlPath) {
145
+ if (urlPath === "/") {
146
+ return "__index.html";
147
+ }
148
+ // Remove leading slash and add .html extension
149
+ const cleanPath = urlPath.replace(/^\//, "");
150
+ return `${cleanPath}.html`;
151
+ }
152
+ /**
153
+ * Find all layout file paths for a given page path (from root to leaf)
154
+ */
155
+ function findLayoutPathsForPage(pagePath, root) {
156
+ const pagesDir = path.join(root, "src", "pages");
157
+ const relativePath = path.relative(pagesDir, pagePath);
158
+ const pathParts = path
159
+ .dirname(relativePath)
160
+ .split(path.sep)
161
+ .filter((p) => p !== ".");
162
+ const layoutPaths = [];
163
+ // Check for _layout.tsx from root to leaf (maintains nesting order)
164
+ // Start with root layout
165
+ const rootLayoutPath = path.join(pagesDir, "_layout.tsx");
166
+ if (fs.existsSync(rootLayoutPath)) {
167
+ layoutPaths.push(rootLayoutPath);
168
+ }
169
+ // Then check nested layouts
170
+ for (let i = 1; i <= pathParts.length; i++) {
171
+ const dirPath = path.join(pagesDir, ...pathParts.slice(0, i));
172
+ const layoutPath = path.join(dirPath, "_layout.tsx");
173
+ if (fs.existsSync(layoutPath)) {
174
+ layoutPaths.push(layoutPath);
175
+ }
176
+ }
177
+ return layoutPaths;
178
+ }
179
+ /**
180
+ * Find all layout components for a given page path (from root to leaf)
181
+ * Note: Layouts cannot use routing features during SSG since they're pre-rendered
182
+ */
183
+ async function findLayoutsForPage(pagePath, root, viteServer) {
184
+ const layoutPaths = findLayoutPathsForPage(pagePath, root);
185
+ const layouts = [];
186
+ for (const layoutPath of layoutPaths) {
187
+ try {
188
+ const layoutModule = await viteServer.ssrLoadModule(layoutPath);
189
+ if (layoutModule.default) {
190
+ layouts.push(layoutModule.default);
191
+ }
192
+ }
193
+ catch (error) {
194
+ log("warn", `Could not load layout at ${layoutPath}: ${error instanceof Error ? error.message : String(error)}`);
195
+ }
196
+ }
197
+ return layouts;
198
+ }
199
+ /**
200
+ * Render a page component to static HTML using Vite SSR with timeout
201
+ */
202
+ async function renderPageToHTML(page, root, htmlTemplate, viteServer, timeout = 10000) {
203
+ // Create timeout promise
204
+ const timeoutPromise = new Promise((_, reject) => {
205
+ setTimeout(() => {
206
+ reject(new Error(`Rendering timeout after ${timeout}ms - page may contain hooks or async operations`));
207
+ }, timeout);
208
+ });
209
+ // Create render promise
210
+ const renderPromise = (async () => {
211
+ try {
212
+ // Dynamically import React and ReactDOMServer
213
+ const React = (await import("react")).default;
214
+ const ReactDOMServer = await import("react-dom/server");
215
+ // Use Vite's SSR loader to load the page component
216
+ const pageModule = await viteServer.ssrLoadModule(page.filePath);
217
+ const PageComponent = pageModule.default;
218
+ if (!PageComponent) {
219
+ throw new Error(`No default export found in ${page.relativePath}`);
220
+ }
221
+ // Find all layouts (from root to leaf)
222
+ const layouts = await findLayoutsForPage(page.filePath, root, viteServer);
223
+ // Build the component tree: layouts wrap the page, innermost to outermost
224
+ let element = React.createElement(PageComponent);
225
+ // Wrap with layouts from innermost to outermost (reverse order)
226
+ for (let i = layouts.length - 1; i >= 0; i--) {
227
+ element = React.createElement(layouts[i], { children: element });
228
+ }
229
+ // Load RouterContext from our stub
230
+ const heliumClient = await viteServer.ssrLoadModule("heliumts/client");
231
+ const RouterContext = heliumClient.RouterContext;
232
+ // Mock Router Context with the page's URL
233
+ const routerValue = {
234
+ path: page.urlPath,
235
+ params: {},
236
+ searchParams: new URLSearchParams(),
237
+ push: () => { },
238
+ replace: () => { },
239
+ on: () => () => { },
240
+ status: 200,
241
+ };
242
+ // Wrap with RouterContext
243
+ if (RouterContext) {
244
+ element = React.createElement(RouterContext.Provider, { value: routerValue }, element);
245
+ }
246
+ // Render to static HTML
247
+ const markup = ReactDOMServer.renderToString(element);
248
+ // Inject the markup into the HTML template with the SSG marker
249
+ const finalHtml = htmlTemplate.replace(/<div\s+id="root"[^>]*>(.*?)<\/div>/s, `<div id="root" data-ssg-page="${page.urlPath}">${markup}</div>`);
250
+ return finalHtml;
251
+ }
252
+ catch (error) {
253
+ log("error", `Failed to render ${page.relativePath}:`, error);
254
+ throw error; // Don't fallback, let the caller handle the error
255
+ }
256
+ })();
257
+ // Race between timeout and render
258
+ return Promise.race([renderPromise, timeoutPromise]);
259
+ }
260
+ /**
261
+ * Generate static HTML files for all SSG pages
262
+ */
263
+ export async function generateStaticPages(context, root, htmlTemplate, distDir) {
264
+ // Scan for SSG pages
265
+ const ssgPages = scanSSGPages(root);
266
+ if (ssgPages.length === 0) {
267
+ return;
268
+ }
269
+ log("info", `Generating ${ssgPages.length} static page(s) for SSG...`);
270
+ // Check for dynamic routes (not supported yet)
271
+ const dynamicPages = ssgPages.filter((p) => p.relativePath.includes("["));
272
+ if (dynamicPages.length > 0) {
273
+ log("warn", `Skipping ${dynamicPages.length} dynamic route(s) - not yet supported:\n` + dynamicPages.map((p) => ` - ${p.relativePath}`).join("\n"));
274
+ }
275
+ // Filter out dynamic routes
276
+ const staticPages = ssgPages.filter((p) => !p.relativePath.includes("["));
277
+ // Display warnings for pages that may not be truly static
278
+ const pagesWithWarnings = staticPages.filter((p) => p.warnings.length > 0);
279
+ if (pagesWithWarnings.length > 0) {
280
+ log("warn", "");
281
+ log("warn", "⚠️ SSG Warning: The following pages may not be fully static:");
282
+ for (const page of pagesWithWarnings) {
283
+ log("warn", ` ${page.relativePath}:`);
284
+ for (const warning of page.warnings) {
285
+ log("warn", ` - ${warning}`);
286
+ }
287
+ }
288
+ log("warn", " These pages will be pre-rendered but may require client-side hydration.");
289
+ log("warn", "");
290
+ }
291
+ // Precompute RPC client stubs for SSG (mirrors helium Vite plugin)
292
+ const { methods } = scanServerExports(root);
293
+ const serverStubCode = `// Auto-generated SSG RPC stub\n${generateClientModule(methods)}\n`;
294
+ // Create a stub for heliumts/client that provides mock Router and hooks
295
+ const clientStubCode = `
296
+ // Auto-generated SSG client stub
297
+ import React from 'react';
298
+
299
+ // Mock RouterContext
300
+ export const RouterContext = React.createContext({
301
+ path: '/',
302
+ params: {},
303
+ searchParams: new URLSearchParams(),
304
+ push: () => {},
305
+ replace: () => {},
306
+ on: () => () => {},
307
+ status: 200,
308
+ isNavigating: false,
309
+ isPending: false,
310
+ });
311
+
312
+ // Mock useRouter hook
313
+ export function useRouter() {
314
+ const ctx = React.useContext(RouterContext);
315
+ if (!ctx) {
316
+ console.warn('useRouter called outside RouterContext during SSG');
317
+ return {
318
+ path: '/',
319
+ params: {},
320
+ searchParams: new URLSearchParams(),
321
+ push: () => {},
322
+ replace: () => {},
323
+ on: () => () => {},
324
+ status: 200,
325
+ isNavigating: false,
326
+ isPending: false,
327
+ };
328
+ }
329
+ return ctx;
330
+ }
331
+
332
+ // Mock AppRouter component (alias for Router)
333
+ export function AppRouter({ children }) {
334
+ return React.createElement(React.Fragment, null, children);
335
+ }
336
+
337
+ // Mock Router component
338
+ export function Router({ children }) {
339
+ return React.createElement(React.Fragment, null, children);
340
+ }
341
+
342
+ // Mock Link component
343
+ export function Link({ href, children, prefetch, ...props }) {
344
+ return React.createElement('a', { href, ...props }, children);
345
+ }
346
+
347
+ // Mock Redirect component
348
+ export function Redirect({ to, replace }) {
349
+ return null;
350
+ }
351
+
352
+ // Mock useCall hook
353
+ export function useCall(serverFn) {
354
+ return async (...args) => {
355
+ console.warn('useCall called during SSG - this will not execute');
356
+ return null;
357
+ };
358
+ }
359
+
360
+ // Mock useFetch hook
361
+ export function useFetch(serverFn, ...args) {
362
+ console.warn('useFetch called during SSG - returning null');
363
+ return { data: null, loading: false, error: null, refetch: async () => {} };
364
+ }
365
+
366
+ // Re-export cache (mock)
367
+ export const cache = {
368
+ get: () => null,
369
+ set: () => {},
370
+ delete: () => {},
371
+ clear: () => {},
372
+ };
373
+
374
+ // Mock PageTransition and useDeferredNavigation (also available from heliumts/client/transitions)
375
+ export function useDeferredNavigation() {
376
+ return {
377
+ path: '/',
378
+ deferredPath: '/',
379
+ isStale: false,
380
+ isPending: false,
381
+ isTransitioning: false,
382
+ };
383
+ }
384
+
385
+ export function PageTransition({ children, loadingClassName, loadingStyle, fallback }) {
386
+ return React.createElement('div', null, children);
387
+ }
388
+ `;
389
+ // Create a stub for heliumts/client/transitions
390
+ const transitionsStubCode = `
391
+ // Auto-generated SSG transitions stub
392
+ import React from 'react';
393
+
394
+ // Mock useDeferredNavigation hook - returns static values for SSG
395
+ export function useDeferredNavigation() {
396
+ return {
397
+ path: '/',
398
+ deferredPath: '/',
399
+ isStale: false,
400
+ isPending: false,
401
+ isTransitioning: false,
402
+ };
403
+ }
404
+
405
+ // Mock PageTransition component - renders children without transition logic
406
+ export function PageTransition({ children, loadingClassName, loadingStyle, fallback }) {
407
+ // During SSG, just render the children without any transition logic
408
+ return React.createElement('div', null, children);
409
+ }
410
+
411
+ export default {
412
+ useDeferredNavigation,
413
+ PageTransition,
414
+ };
415
+ `;
416
+ // Create a stub for heliumts/client/prefetch
417
+ const prefetchStubCode = `
418
+ // Auto-generated SSG prefetch stub
419
+ export function prefetchRoute() {
420
+ // No-op during SSG
421
+ }
422
+
423
+ export function clearPrefetchCache() {
424
+ // No-op during SSG
425
+ }
426
+ `;
427
+ // Write stub files to node_modules/.helium
428
+ const heliumInternalDir = path.join(root, "node_modules", ".helium");
429
+ if (!fs.existsSync(heliumInternalDir)) {
430
+ fs.mkdirSync(heliumInternalDir, { recursive: true });
431
+ }
432
+ const ssgServerStubPath = path.join(heliumInternalDir, "ssg-server-stub.mjs");
433
+ const ssgClientStubPath = path.join(heliumInternalDir, "ssg-client-stub.mjs");
434
+ const ssgTransitionsStubPath = path.join(heliumInternalDir, "ssg-transitions-stub.mjs");
435
+ const ssgPrefetchStubPath = path.join(heliumInternalDir, "ssg-prefetch-stub.mjs");
436
+ fs.writeFileSync(ssgServerStubPath, serverStubCode, "utf-8");
437
+ fs.writeFileSync(ssgClientStubPath, clientStubCode, "utf-8");
438
+ fs.writeFileSync(ssgTransitionsStubPath, transitionsStubCode, "utf-8");
439
+ fs.writeFileSync(ssgPrefetchStubPath, prefetchStubCode, "utf-8");
440
+ // Create a temporary Vite server for SSR rendering
441
+ const { createServer } = await import("vite");
442
+ const heliumPlugin = (await import("./heliumPlugin.js")).default;
443
+ const viteServer = await createServer({
444
+ root,
445
+ server: { middlewareMode: true },
446
+ appType: "custom",
447
+ logLevel: "error",
448
+ plugins: [heliumPlugin()],
449
+ resolve: {
450
+ alias: [
451
+ // Most specific aliases first - heliumts/client/transitions and heliumts/client/prefetch
452
+ { find: /^heliumts\/client\/transitions$/, replacement: ssgTransitionsStubPath },
453
+ { find: /^heliumts\/client\/prefetch$/, replacement: ssgPrefetchStubPath },
454
+ // Then heliumts/client and heliumts/server
455
+ { find: /^heliumts\/client$/, replacement: ssgClientStubPath },
456
+ { find: /^heliumts\/server$/, replacement: ssgServerStubPath },
457
+ ],
458
+ },
459
+ ssr: {
460
+ external: ["react", "react-dom"],
461
+ // Don't externalize heliumts packages - we want to use our stubs
462
+ noExternal: ["heliumts"],
463
+ },
464
+ });
465
+ try {
466
+ // Generate HTML for each static page
467
+ const zlib = await import("zlib");
468
+ let successCount = 0;
469
+ let failureCount = 0;
470
+ let hasIndexSSG = false;
471
+ // Calculate max path length for proper alignment (min 35, max 80)
472
+ const maxPathLength = Math.min(80, Math.max(35, ...staticPages.map((p) => urlPathToOutputPath(p.urlPath).length)));
473
+ for (const page of staticPages) {
474
+ try {
475
+ // Render the page component to static HTML using Vite SSR with 10s timeout
476
+ const html = await renderPageToHTML(page, root, htmlTemplate, viteServer, 10000);
477
+ const outputPath = urlPathToOutputPath(page.urlPath);
478
+ const fullOutputPath = path.join(distDir, outputPath);
479
+ // Track if the root page (/) has SSG
480
+ if (page.urlPath === "/") {
481
+ hasIndexSSG = true;
482
+ }
483
+ // Ensure directory exists
484
+ const outputDir = path.dirname(fullOutputPath);
485
+ if (!fs.existsSync(outputDir)) {
486
+ fs.mkdirSync(outputDir, { recursive: true });
487
+ }
488
+ // Write the HTML file
489
+ fs.writeFileSync(fullOutputPath, html, "utf-8");
490
+ // Calculate file size and gzipped size
491
+ const size = Buffer.byteLength(html, "utf-8");
492
+ const sizeKB = (size / 1024).toFixed(2);
493
+ // Calculate gzipped size
494
+ const gzipped = zlib.gzipSync(html);
495
+ const gzipSizeKB = (gzipped.length / 1024).toFixed(2);
496
+ log("info", ` ${outputPath.padEnd(maxPathLength)} ${sizeKB.padStart(8)} kB │ gzip: ${gzipSizeKB.padStart(7)} kB`);
497
+ successCount++;
498
+ }
499
+ catch (error) {
500
+ const errorMsg = error instanceof Error ? error.message : String(error);
501
+ if (errorMsg.includes("timeout")) {
502
+ log("error", ` ✗ ${page.relativePath} - ${errorMsg}`);
503
+ }
504
+ else {
505
+ log("error", ` ✗ ${page.relativePath} - Failed to generate:`, error);
506
+ }
507
+ // Write a fallback HTML file with empty root div (client will hydrate)
508
+ const outputPath = urlPathToOutputPath(page.urlPath);
509
+ const fullOutputPath = path.join(distDir, outputPath);
510
+ const outputDir = path.dirname(fullOutputPath);
511
+ if (!fs.existsSync(outputDir)) {
512
+ fs.mkdirSync(outputDir, { recursive: true });
513
+ }
514
+ const fallbackHtml = htmlTemplate.replace(/<div\s+id="root"[^>]*>.*?<\/div>/s, `<div id="root" data-ssg-failed="${page.urlPath}"></div>`);
515
+ fs.writeFileSync(fullOutputPath, fallbackHtml, "utf-8");
516
+ failureCount++;
517
+ }
518
+ }
519
+ // If index page has SSG, we need to handle it specially:
520
+ // 1. Rename __index.html to index.ssg.html (the SSG version)
521
+ // 2. Create a clean blank index.html as fallback for non-root routes
522
+ if (hasIndexSSG) {
523
+ const tempIndexPath = path.join(distDir, "__index.html");
524
+ const ssgIndexPath = path.join(distDir, "index.ssg.html");
525
+ const indexPath = path.join(distDir, "index.html");
526
+ // Move __index.html to index.ssg.html
527
+ if (fs.existsSync(tempIndexPath)) {
528
+ fs.renameSync(tempIndexPath, ssgIndexPath);
529
+ }
530
+ // Create a blank index.html as the SPA fallback
531
+ const blankIndexHtml = htmlTemplate.replace(/<div\s+id="root"[^>]*>.*?<\/div>/s, '<div id="root"></div>');
532
+ fs.writeFileSync(indexPath, blankIndexHtml, "utf-8");
533
+ log("info", ` ${"index.ssg.html".padEnd(maxPathLength)} (SSG root page)`);
534
+ log("info", ` ${"index.html".padEnd(maxPathLength)} (blank SPA fallback)`);
535
+ }
536
+ // Summary
537
+ if (failureCount > 0) {
538
+ log("warn", "");
539
+ log("warn", `SSG completed with ${successCount} success(es) and ${failureCount} failure(s).`);
540
+ }
541
+ }
542
+ finally {
543
+ // Always close the Vite server, even if generation fails
544
+ await viteServer.close();
545
+ }
546
+ }
547
+ //# sourceMappingURL=ssg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssg.js","sourceRoot":"","sources":["../../src/vite/ssg.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { HTTPHandlerExport, MethodExport, MiddlewareExport } from "./scanner.js";
2
+ export declare function generateServerManifest(methods: MethodExport[], httpHandlers: HTTPHandlerExport[], middleware?: MiddlewareExport): string;
3
+ export declare function generateClientModule(methods: MethodExport[]): string;
4
+ export declare function generateTypeDefinitions(methods: MethodExport[], root: string): string;
5
+ export declare function generateEntryModule(): string;
6
+ //# sourceMappingURL=virtualServerModule.d.ts.map
@@ -0,0 +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,MAAM,cAAc,CAAC;AAEjF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,YAAY,EAAE,iBAAiB,EAAE,EAAE,UAAU,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAwBxI;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,CAqCrF;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAkB5C"}
@@ -0,0 +1,82 @@
1
+ import path from "path";
2
+ export function generateServerManifest(methods, httpHandlers, middleware) {
3
+ const methodImports = methods.map((m, i) => `import { ${m.name} as method_${i} } from '${m.filePath}';`).join("\n");
4
+ const httpImports = httpHandlers.map((h, i) => `import { ${h.name} as http_${i} } from '${h.filePath}';`).join("\n");
5
+ const middlewareImport = middleware ? `import ${middleware.name === "default" ? "middleware" : `{ ${middleware.name} as middleware }`} from '${middleware.filePath}';` : "";
6
+ const methodRegistrations = methods.map((m, i) => ` registry.register('${m.name}', method_${i});`).join("\n");
7
+ const httpExports = httpHandlers.map((h, i) => ` { name: '${h.name}', handler: http_${i} },`).join("\n");
8
+ return `
9
+ ${methodImports}
10
+ ${httpImports}
11
+ ${middlewareImport}
12
+
13
+ export function registerAll(registry) {
14
+ ${methodRegistrations}
15
+ }
16
+
17
+ export const httpHandlers = [
18
+ ${httpExports}
19
+ ];
20
+
21
+ export const middlewareHandler = ${middleware ? "middleware" : "null"};
22
+ `;
23
+ }
24
+ export function generateClientModule(methods) {
25
+ const exports = methods.map((m) => `export const ${m.name} = { __id: '${m.name}' };`).join("\n");
26
+ return exports;
27
+ }
28
+ export function generateTypeDefinitions(methods, root) {
29
+ const methodsWithSuffix = methods.map((m, i) => ({
30
+ ...m,
31
+ alias: `${m.name}_${i}${Math.random().toString(36).substring(2, 8)}`,
32
+ }));
33
+ const imports = methodsWithSuffix
34
+ .map((m) => {
35
+ let relPath = path.relative(path.join(root, "src"), m.filePath);
36
+ if (!relPath.startsWith(".")) {
37
+ relPath = "../" + relPath;
38
+ }
39
+ relPath = relPath.replace(/\.ts$/, "");
40
+ return `import type { ${m.name} as ${m.alias} } from '${relPath}';`;
41
+ })
42
+ .join("\n");
43
+ const exports = methodsWithSuffix
44
+ .map((m) => {
45
+ return `export const ${m.name}: import('heliumts/client').MethodStub<
46
+ Parameters<typeof ${m.alias}['handler']>[0],
47
+ Awaited<ReturnType<typeof ${m.alias}['handler']>>
48
+ >;`;
49
+ })
50
+ .join("\n");
51
+ return `/* eslint-disable */
52
+ /**
53
+ * Auto generated file - DO NOT EDIT!
54
+ * # Helium Server Type Definitions
55
+ **/
56
+ ${imports}
57
+
58
+ declare module 'heliumts/server' {
59
+ ${exports}
60
+ }
61
+ `;
62
+ }
63
+ export function generateEntryModule() {
64
+ return `
65
+ import React from 'react';
66
+ import { createRoot } from 'react-dom/client';
67
+ import { AppRouter } from 'heliumts/client';
68
+ import App from '/src/App';
69
+
70
+ const rootEl = document.getElementById('root');
71
+ if (!rootEl) {
72
+ throw new Error('Root element not found. Helium requires a <div id=\"root\"></div> in your HTML.');
73
+ }
74
+
75
+ createRoot(rootEl).render(
76
+ <React.StrictMode>
77
+ <AppRouter AppShell={App} />
78
+ </React.StrictMode>
79
+ );
80
+ `;
81
+ }
82
+ //# sourceMappingURL=virtualServerModule.js.map