@bouygues-telecom/staticjs 0.1.11 → 0.1.14

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 (66) hide show
  1. package/_build/helpers/cachePages.d.ts +15 -0
  2. package/_build/helpers/cachePages.js +162 -0
  3. package/_build/helpers/createPage.d.ts +18 -0
  4. package/_build/helpers/createPage.js +41 -0
  5. package/_build/helpers/layoutDiscovery.d.ts +9 -0
  6. package/_build/helpers/layoutDiscovery.js +39 -0
  7. package/_build/helpers/readPages.d.ts +3 -0
  8. package/_build/helpers/readPages.js +24 -0
  9. package/_build/helpers/renderPageRuntime.d.ts +13 -0
  10. package/_build/helpers/renderPageRuntime.js +222 -0
  11. package/_build/scripts/build-html.d.ts +1 -0
  12. package/_build/scripts/build-html.js +138 -0
  13. package/_build/scripts/cli.d.ts +6 -0
  14. package/_build/scripts/cli.js +119 -0
  15. package/_build/scripts/create-static-app.d.ts +2 -0
  16. package/{dist → _build}/scripts/create-static-app.js +0 -0
  17. package/_build/scripts/generate-test-multiapps.d.ts +6 -0
  18. package/_build/scripts/generate-test-multiapps.js +79 -0
  19. package/_build/server/config/index.d.ts +20 -0
  20. package/_build/server/config/index.js +25 -0
  21. package/_build/server/config/vite.config.d.ts +2 -0
  22. package/_build/server/config/vite.config.js +31 -0
  23. package/_build/server/config/vite.plugin.d.ts +11 -0
  24. package/_build/server/config/vite.plugin.js +75 -0
  25. package/_build/server/index.d.ts +22 -0
  26. package/_build/server/index.js +124 -0
  27. package/_build/server/middleware/errorHandling.d.ts +22 -0
  28. package/_build/server/middleware/errorHandling.js +48 -0
  29. package/_build/server/middleware/hotReload.d.ts +31 -0
  30. package/_build/server/middleware/hotReload.js +152 -0
  31. package/_build/server/middleware/logging.d.ts +13 -0
  32. package/_build/server/middleware/logging.js +23 -0
  33. package/_build/server/middleware/parsing.d.ts +9 -0
  34. package/_build/server/middleware/parsing.js +21 -0
  35. package/_build/server/middleware/performance.d.ts +13 -0
  36. package/_build/server/middleware/performance.js +26 -0
  37. package/_build/server/middleware/rateLimiting.d.ts +17 -0
  38. package/_build/server/middleware/rateLimiting.js +38 -0
  39. package/_build/server/middleware/runtime.d.ts +23 -0
  40. package/_build/server/middleware/runtime.js +186 -0
  41. package/_build/server/middleware/security.d.ts +24 -0
  42. package/_build/server/middleware/security.js +39 -0
  43. package/_build/server/middleware/static.d.ts +9 -0
  44. package/_build/server/middleware/static.js +63 -0
  45. package/_build/server/routes/api.d.ts +23 -0
  46. package/_build/server/routes/api.js +124 -0
  47. package/_build/server/scripts/revalidate.d.ts +2 -0
  48. package/{dist → _build/server}/scripts/revalidate.js +3 -3
  49. package/_build/server/utils/fileWatcher.d.ts +27 -0
  50. package/_build/server/utils/fileWatcher.js +194 -0
  51. package/_build/server/utils/startup.d.ts +18 -0
  52. package/_build/server/utils/startup.js +93 -0
  53. package/_build/server/utils/vite.d.ts +18 -0
  54. package/_build/server/utils/vite.js +61 -0
  55. package/_build/server/utils/websocket.d.ts +26 -0
  56. package/_build/server/utils/websocket.js +140 -0
  57. package/package.json +28 -16
  58. package/LICENSE +0 -190
  59. package/README.md +0 -158
  60. package/dist/config/vite.plugin.js +0 -80
  61. package/dist/helpers/cachePages.js +0 -26
  62. package/dist/helpers/createPage.js +0 -23
  63. package/dist/helpers/readPages.js +0 -19
  64. package/dist/scripts/build-html.js +0 -82
  65. package/dist/scripts/cli.js +0 -36
  66. package/dist/scripts/generate-test-multiapps.js +0 -51
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Load cache entries with error handling and auto-generation
3
+ * @param projectDir - The template directory path (e.g., "templates/react")
4
+ * @param verbose
5
+ * @returns The loaded or generated cache entries object
6
+ */
7
+ export declare const loadCacheEntries: (projectDir: string, verbose?: boolean) => any;
8
+ /**
9
+ * CLI wrapper that uses the modern API functions
10
+ * @param templateDir - Template directory (defaults to current directory for backward compatibility)
11
+ * @param specificFiles - Optional array of specific .tsx files to process
12
+ */
13
+ export declare const runCli: (templateDir?: string, specificFiles?: string[]) => {
14
+ [key: string]: string;
15
+ };
@@ -0,0 +1,162 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { readPages } from "./readPages.js";
4
+ import { CONFIG } from "../server/config/index.js";
5
+ const generateExcludedFiles = (entries) => {
6
+ const excludedFiles = [];
7
+ Object.entries(entries).forEach(([name, path]) => {
8
+ const content = fs.readFileSync(path, "utf8");
9
+ const firstLine = content.split("\n")[0];
10
+ if (firstLine.includes("no scripts")) {
11
+ delete entries[name];
12
+ excludedFiles.push(name);
13
+ // File excluded from build due to "no scripts" directive
14
+ }
15
+ });
16
+ try {
17
+ const cacheDir = path.resolve(process.cwd(), CONFIG.BUILD_DIR, "cache");
18
+ const excludedFilePath = path.resolve(cacheDir, "excludedFiles.json");
19
+ if (!fs.existsSync(cacheDir)) {
20
+ fs.mkdirSync(cacheDir, { recursive: true });
21
+ }
22
+ fs.writeFileSync(excludedFilePath, JSON.stringify(excludedFiles, null, 2), "utf8");
23
+ }
24
+ catch (error) {
25
+ console.error("Error generating excluded files:", error);
26
+ throw error; // Re-throw to handle it in the caller
27
+ }
28
+ };
29
+ /**
30
+ * Generate cache entries for a given template directory
31
+ * @param projectDir - The template directory path (e.g., "templates/react")
32
+ * @param verbose
33
+ * @returns The generated cache entries object
34
+ */
35
+ const generateCacheEntries = (projectDir, verbose = false) => {
36
+ const pagesDir = path.resolve(projectDir, "src/pages");
37
+ const cacheDir = path.resolve(projectDir, CONFIG.BUILD_DIR, "cache");
38
+ const cacheFilePath = path.resolve(cacheDir, "pagesCache.json");
39
+ // Generating pages cache (silent unless error)
40
+ // Check if pages directory exists
41
+ if (!fs.existsSync(pagesDir)) {
42
+ if (verbose) {
43
+ console.warn(`Pages directory not found: ${pagesDir}`);
44
+ }
45
+ return {};
46
+ }
47
+ // Scan for page files using existing helper
48
+ const entries = readPages(pagesDir);
49
+ // Create cache directory if it doesn't exist
50
+ if (!fs.existsSync(cacheDir)) {
51
+ fs.mkdirSync(cacheDir, { recursive: true });
52
+ if (verbose) {
53
+ console.log(` Created cache directory: ${cacheDir}`);
54
+ }
55
+ }
56
+ // Write cache file
57
+ fs.writeFileSync(cacheFilePath, JSON.stringify(entries, null, 2), "utf8");
58
+ generateExcludedFiles(entries);
59
+ if (verbose) {
60
+ console.log(` Generated cache file: ${cacheFilePath}`);
61
+ console.log(` Found ${Object.keys(entries).length} page(s)\n`);
62
+ }
63
+ return entries;
64
+ };
65
+ /**
66
+ * Load cache entries with error handling and auto-generation
67
+ * @param projectDir - The template directory path (e.g., "templates/react")
68
+ * @param verbose
69
+ * @returns The loaded or generated cache entries object
70
+ */
71
+ export const loadCacheEntries = (projectDir, verbose = false) => {
72
+ const cacheFilePath = path.resolve(projectDir, CONFIG.BUILD_DIR, "cache/pagesCache.json");
73
+ try {
74
+ if (!fs.existsSync(cacheFilePath)) {
75
+ if (verbose) {
76
+ console.log('\n📝 Cache file not found, generating automatically...');
77
+ }
78
+ return generateCacheEntries(projectDir, verbose);
79
+ }
80
+ const entries = JSON.parse(fs.readFileSync(cacheFilePath, 'utf8'));
81
+ if (!entries || typeof entries !== 'object') {
82
+ if (verbose) {
83
+ console.log('\n📝 Invalid cache file format, regenerating...');
84
+ }
85
+ return generateCacheEntries(projectDir, verbose);
86
+ }
87
+ if (verbose) {
88
+ console.log(`\n✅ Loaded ${Object.keys(entries).length} cached page(s)`);
89
+ }
90
+ return entries;
91
+ }
92
+ catch (error) {
93
+ const errorMessage = error instanceof Error ? error.message : String(error);
94
+ console.error('\n❌ StaticJS Cache Error:');
95
+ console.error(` ${errorMessage}`);
96
+ console.log('\n📝 Attempting to generate cache automatically...');
97
+ try {
98
+ return generateCacheEntries(projectDir, verbose);
99
+ }
100
+ catch (generateError) {
101
+ const generateErrorMessage = generateError instanceof Error ? generateError.message : String(generateError);
102
+ console.error('\n❌ Failed to generate cache automatically:');
103
+ console.error(` ${generateErrorMessage}`);
104
+ console.error('\n💡 To fix this issue:');
105
+ console.error(' 1. Run: npm run build');
106
+ console.error(' 2. Or run: npm run dev (will auto-build if needed)');
107
+ console.error(' 3. Or run: npm run validate-setup\n');
108
+ // Return empty object to prevent Vite from crashing
109
+ return {};
110
+ }
111
+ }
112
+ };
113
+ /**
114
+ * Process CLI arguments to generate specific page entries
115
+ * @param args - Command line arguments
116
+ * @param pagesDir - Pages directory path
117
+ * @returns Processed entries object
118
+ */
119
+ const processCliArgs = (args, pagesDir) => {
120
+ return args
121
+ .filter((arg) => arg.endsWith(".tsx"))
122
+ .reduce((obj, tsxFile) => {
123
+ console.log(`Processing arg: ${tsxFile}`);
124
+ const relativePathWithoutExtension = tsxFile.replace(/\.tsx$/, "");
125
+ const fullPath = path.resolve(pagesDir, tsxFile);
126
+ obj[relativePathWithoutExtension] = fullPath;
127
+ return obj;
128
+ }, {});
129
+ };
130
+ /**
131
+ * CLI wrapper that uses the modern API functions
132
+ * @param templateDir - Template directory (defaults to current directory for backward compatibility)
133
+ * @param specificFiles - Optional array of specific .tsx files to process
134
+ */
135
+ export const runCli = (templateDir = ".", specificFiles) => {
136
+ const args = specificFiles || process.argv.slice(2);
137
+ if (args.length > 0) {
138
+ // Handle specific files by temporarily overriding readPages behavior
139
+ const pagesDir = path.resolve(process.cwd(), templateDir, "src/pages");
140
+ const entries = processCliArgs(args, pagesDir);
141
+ // Use generateCacheEntries but with custom entries
142
+ const cacheDir = path.resolve(process.cwd(), templateDir, CONFIG.BUILD_DIR, "cache");
143
+ const cacheFilePath = path.resolve(cacheDir, "pagesCache.json");
144
+ if (!fs.existsSync(cacheDir)) {
145
+ fs.mkdirSync(cacheDir, { recursive: true });
146
+ }
147
+ fs.writeFileSync(cacheFilePath, JSON.stringify(entries, null, 2), "utf8");
148
+ console.log("Pages cached successfully.");
149
+ return entries;
150
+ }
151
+ else {
152
+ // Use the modern API for full directory scanning
153
+ return generateCacheEntries(templateDir, true);
154
+ }
155
+ };
156
+ // Legacy CLI support - maintain backward compatibility
157
+ // Only run CLI logic if this file is executed directly (not imported)
158
+ // Check if this is the main module using import.meta.url
159
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
160
+ if (isMainModule) {
161
+ runCli();
162
+ }
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ interface IcreatePage {
3
+ data: any;
4
+ AppComponent: React.FC<{
5
+ Component: React.FC;
6
+ props: {};
7
+ pageData?: any;
8
+ }>;
9
+ PageComponent: () => React.JSX.Element;
10
+ initialDatasId: string;
11
+ rootId: string;
12
+ pageName: string;
13
+ JSfileName: string | false;
14
+ returnHtml?: boolean;
15
+ pageData?: any;
16
+ }
17
+ export declare const createPage: ({ data, AppComponent, PageComponent, initialDatasId, rootId, pageName, JSfileName, returnHtml, pageData, }: IcreatePage) => Promise<string | void>;
18
+ export {};
@@ -0,0 +1,41 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import React from "react";
4
+ import ReactDOMServer from "react-dom/server";
5
+ import { CONFIG } from "../server/config/index.js";
6
+ export const createPage = async ({ data, AppComponent, PageComponent, initialDatasId, rootId, pageName, JSfileName, returnHtml = false, // Default to false for backward compatibility
7
+ pageData = {}, // Default to empty object
8
+ }) => {
9
+ const template = `{{html}}
10
+ ${data ? `<script id=initial-data-{{initialDatasId}} type="application/json">${JSON.stringify(data)}</script>` : ""}
11
+ ${JSfileName ? `<script type="module" src="{{scriptPath}}"></script>` : ""}
12
+ `;
13
+ // Create a wrapper component that adds the app div around the page component
14
+ const PageWithAppDiv = (props) => {
15
+ return React.createElement('div', { id: `app-${rootId}` }, React.createElement(PageComponent, props));
16
+ };
17
+ const component = React.createElement(AppComponent, {
18
+ Component: PageWithAppDiv,
19
+ props: { data },
20
+ pageData, // Pass pageData to AppComponent
21
+ });
22
+ const htmlContent = template
23
+ .replace("{{initialDatasId}}", initialDatasId)
24
+ .replace("{{html}}", ReactDOMServer.renderToString(component))
25
+ .replace("{{scriptPath}}", `/${pageName}.js`);
26
+ // Return HTML string for runtime rendering or write to file for build time
27
+ if (returnHtml) {
28
+ return htmlContent;
29
+ }
30
+ else {
31
+ // If page name contains a slash, create directories
32
+ const pageNameParts = pageName.split("/");
33
+ if (pageNameParts.length > 1) {
34
+ const dirPath = path.join(CONFIG.PROJECT_ROOT, CONFIG.BUILD_DIR, ...pageNameParts.slice(0, -1));
35
+ if (!fs.existsSync(dirPath)) {
36
+ fs.mkdirSync(dirPath, { recursive: true });
37
+ }
38
+ }
39
+ fs.writeFileSync(path.join(CONFIG.PROJECT_ROOT, CONFIG.BUILD_DIR, `${pageName}.html`), htmlContent);
40
+ }
41
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Discovers the closest layout.tsx file by walking up the directory tree
3
+ * from the given page path
4
+ */
5
+ export declare function findClosestLayout(pagePath: string, rootDir: string): string | null;
6
+ /**
7
+ * Gets the relative path from rootDir for layout identification
8
+ */
9
+ export declare function getLayoutIdentifier(layoutPath: string, rootDir: string): string;
@@ -0,0 +1,39 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ /**
4
+ * Discovers the closest layout.tsx file by walking up the directory tree
5
+ * from the given page path
6
+ */
7
+ export function findClosestLayout(pagePath, rootDir) {
8
+ // Get the directory containing the page
9
+ const pageDir = path.dirname(pagePath);
10
+ // Start from the page's directory and walk up
11
+ let currentDir = pageDir;
12
+ while (true) {
13
+ // Check if layout.tsx exists in current directory
14
+ const layoutPath = path.join(currentDir, "layout.tsx");
15
+ if (fs.existsSync(layoutPath)) {
16
+ return layoutPath;
17
+ }
18
+ // Get parent directory
19
+ const parentDir = path.dirname(currentDir);
20
+ // If we've reached the root directory or can't go up further, stop
21
+ if (parentDir === currentDir || !currentDir.startsWith(rootDir)) {
22
+ break;
23
+ }
24
+ currentDir = parentDir;
25
+ }
26
+ // Fallback to global layout if no layout.tsx found in the hierarchy
27
+ const globalLayoutPath = path.join(rootDir, "layout.tsx");
28
+ if (fs.existsSync(globalLayoutPath)) {
29
+ return globalLayoutPath;
30
+ }
31
+ return null;
32
+ }
33
+ /**
34
+ * Gets the relative path from rootDir for layout identification
35
+ */
36
+ export function getLayoutIdentifier(layoutPath, rootDir) {
37
+ const relativePath = path.relative(rootDir, layoutPath);
38
+ return relativePath.replace(/\.tsx$/, "");
39
+ }
@@ -0,0 +1,3 @@
1
+ export declare function readPages(dir: string, baseDir?: string): {
2
+ [key: string]: string;
3
+ };
@@ -0,0 +1,24 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ export function readPages(dir, baseDir = dir) {
4
+ let result = {};
5
+ const files = fs.readdirSync(dir);
6
+ for (const file of files) {
7
+ const fullPath = path.join(dir, file);
8
+ const stat = fs.statSync(fullPath);
9
+ if (stat.isDirectory()) {
10
+ // Check if this directory contains an index.tsx file
11
+ const indexPath = path.join(fullPath, "index.tsx");
12
+ if (fs.existsSync(indexPath)) {
13
+ // Create route path from folder structure
14
+ const relPath = path.relative(baseDir, fullPath);
15
+ result[relPath] = indexPath;
16
+ }
17
+ // Continue recursively searching for more pages
18
+ const nested = readPages(fullPath, baseDir);
19
+ result = { ...result, ...nested };
20
+ }
21
+ // Note: Direct .tsx files are no longer supported - only folder-based routes with index.tsx
22
+ }
23
+ return result;
24
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Runtime page rendering function that uses the same logic as build-html.ts
3
+ * but returns HTML string instead of writing to file
4
+ */
5
+ export declare function renderPageRuntime(requestPath: string, params?: {
6
+ [key: string]: string;
7
+ }): Promise<string | null>;
8
+ /**
9
+ * Get all available pages for development mode
10
+ */
11
+ export declare function getAvailablePagesRuntime(): {
12
+ [key: string]: string;
13
+ };
@@ -0,0 +1,222 @@
1
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
2
+ import fs from "fs/promises";
3
+ import crypto from "node:crypto";
4
+ import path from "path";
5
+ import React from "react";
6
+ import { createPage } from "./createPage.js";
7
+ import { readPages } from "./readPages.js";
8
+ import { CONFIG } from "../server/config/index.js";
9
+ import { findClosestLayout } from "./layoutDiscovery.js";
10
+ const rootDir = path.resolve(process.cwd(), "./src");
11
+ async function loadJson(filePath) {
12
+ try {
13
+ const data = await fs.readFile(filePath, "utf-8");
14
+ return JSON.parse(data);
15
+ }
16
+ catch (error) {
17
+ // Return empty object if file doesn't exist (for development mode)
18
+ return {};
19
+ }
20
+ }
21
+ /**
22
+ * Runtime page rendering function that uses the same logic as build-html.ts
23
+ * but returns HTML string instead of writing to file
24
+ */
25
+ export async function renderPageRuntime(requestPath, params) {
26
+ try {
27
+ // Load excluded files for "no scripts" functionality
28
+ const excludedJSFiles = await loadJson(path.join(process.cwd(), `./${CONFIG.BUILD_DIR}/cache/excludedFiles.json`));
29
+ // Get available pages using readPages helper
30
+ const pagesDir = path.resolve(process.cwd(), "src/pages");
31
+ const pages = readPages(pagesDir);
32
+ // Find the matching page
33
+ let matchedPage = null;
34
+ let matchedParams = {};
35
+ // Handle root path
36
+ if (requestPath === "/" || requestPath === "") {
37
+ if (pages["index"]) {
38
+ matchedPage = { path: pages["index"], pageName: "index" };
39
+ }
40
+ }
41
+ else {
42
+ // Remove leading slash and try exact match first
43
+ const cleanPath = requestPath.replace(/^\//, "");
44
+ // Try exact match first
45
+ if (pages[cleanPath]) {
46
+ matchedPage = { path: pages[cleanPath], pageName: cleanPath };
47
+ }
48
+ else {
49
+ // Try to match with different prefixes (for flexibility)
50
+ const possiblePaths = [
51
+ cleanPath,
52
+ `partials/${cleanPath}`,
53
+ cleanPath.replace(/^partials\//, "")
54
+ ];
55
+ for (const testPath of possiblePaths) {
56
+ if (pages[testPath]) {
57
+ matchedPage = { path: pages[testPath], pageName: testPath };
58
+ break;
59
+ }
60
+ }
61
+ // If still no match, try dynamic routes
62
+ if (!matchedPage) {
63
+ for (const [pageName, pagePath] of Object.entries(pages)) {
64
+ if (pageName.includes("[") && pageName.includes("]")) {
65
+ // Extract the dynamic parameter name
66
+ const paramMatch = pageName.match(/\[([^\]]+)\]/);
67
+ if (paramMatch) {
68
+ const paramName = paramMatch[1];
69
+ // Try matching against multiple possible paths
70
+ for (const testPath of possiblePaths) {
71
+ // Create a regex pattern from the page name
72
+ const regexPattern = pageName.replace(/\[([^\]]+)\]/g, '([^/]+)');
73
+ const regex = new RegExp(`^${regexPattern}$`);
74
+ const match = testPath.match(regex);
75
+ if (match) {
76
+ // Extract the parameter value from the matched groups
77
+ const paramValue = match[1];
78
+ if (paramValue) {
79
+ matchedPage = { path: pagePath, pageName: testPath };
80
+ matchedParams[paramName] = paramValue;
81
+ break;
82
+ }
83
+ }
84
+ }
85
+ if (matchedPage)
86
+ break;
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
93
+ if (!matchedPage) {
94
+ return null; // Page not found
95
+ }
96
+ return await processPageRuntime(matchedPage, excludedJSFiles, matchedParams);
97
+ }
98
+ catch (error) {
99
+ console.error("Error in renderPageRuntime:", error);
100
+ return null;
101
+ }
102
+ }
103
+ /**
104
+ * Process a single page for runtime rendering (adapted from build-html.ts processPage)
105
+ */
106
+ async function processPageRuntime(page, excludedJSFiles, params = {}) {
107
+ let data;
108
+ const absolutePath = page.path;
109
+ // Add cache busting to avoid module caching issues in development
110
+ const cacheBuster = `?t=${Date.now()}`;
111
+ try {
112
+ const pageModule = await import(`${absolutePath}${cacheBuster}`);
113
+ // Load page data.json if it exists
114
+ const pageDir = path.dirname(absolutePath);
115
+ const dataJsonPath = path.join(pageDir, 'data.json');
116
+ let pageData = {};
117
+ try {
118
+ const dataContent = await fs.readFile(dataJsonPath, 'utf-8');
119
+ pageData = JSON.parse(dataContent);
120
+ }
121
+ catch (error) {
122
+ // data.json doesn't exist, use empty object
123
+ }
124
+ // Discover the closest layout for this page
125
+ const layoutPath = findClosestLayout(absolutePath, rootDir);
126
+ if (!layoutPath) {
127
+ throw new Error(`No layout found for page ${page.pageName}`);
128
+ }
129
+ const layoutModule = await import(`${layoutPath}${cacheBuster}`);
130
+ const appModule = await import(`${rootDir}/app.tsx${cacheBuster}`);
131
+ const fileName = path.basename(page.path, path.extname(page.path));
132
+ // Create a dynamic App component that uses the discovered layout
133
+ const LayoutComponent = layoutModule.Layout;
134
+ if (!LayoutComponent) {
135
+ throw new Error(`Layout component not found in ${layoutPath}. Make sure it exports 'Layout'.`);
136
+ }
137
+ // Create a wrapper App component that uses the actual App component
138
+ const AppComponent = ({ Component, props }) => {
139
+ // Create a layout wrapper that accepts pageData
140
+ const LayoutWrapper = ({ children }) => {
141
+ return React.createElement(LayoutComponent, { pageData, children });
142
+ };
143
+ // Use the actual App component and wrap it with our layout
144
+ return React.createElement(LayoutWrapper, {
145
+ children: React.createElement(appModule.App, { Component, props, pageData })
146
+ });
147
+ };
148
+ const PageComponent = pageModule.default;
149
+ const getStaticProps = pageModule?.getStaticProps;
150
+ const getStaticPaths = pageModule?.getStaticPaths;
151
+ const injectJS = !excludedJSFiles.includes(page.pageName);
152
+ const rootId = crypto
153
+ .createHash("sha256")
154
+ .update(`app-${absolutePath}`)
155
+ .digest("hex")
156
+ .slice(0, 10);
157
+ const initialDatasId = crypto
158
+ .createHash("sha256")
159
+ .update(`initial-data-${absolutePath}`)
160
+ .digest("hex")
161
+ .slice(0, 10);
162
+ if (!PageComponent) {
163
+ throw new Error(`Failed to import PageComponent from ${page.pageName}.tsx`);
164
+ }
165
+ // Handle getStaticProps with or without dynamic params
166
+ if (getStaticProps) {
167
+ if (Object.keys(params).length > 0) {
168
+ // Dynamic route with params
169
+ const { props } = await getStaticProps({ params });
170
+ data = props.data;
171
+ }
172
+ else {
173
+ // Static route
174
+ const { props } = await getStaticProps();
175
+ data = props.data;
176
+ }
177
+ }
178
+ // Generate HTML using createPage helper with returnHtml flag
179
+ // Use dynamic import to load createPage from the template directory
180
+ let htmlContent;
181
+ try {
182
+ // Try to import createPage from the template's helpers directory
183
+ const templateCreatePagePath = path.resolve(process.cwd(), "../../helpers/createPage.js");
184
+ const { createPage: templateCreatePage } = await import(templateCreatePagePath);
185
+ htmlContent = templateCreatePage({
186
+ data,
187
+ AppComponent,
188
+ PageComponent,
189
+ initialDatasId,
190
+ rootId,
191
+ pageName: page.pageName,
192
+ JSfileName: injectJS && fileName,
193
+ returnHtml: true,
194
+ });
195
+ }
196
+ catch (error) {
197
+ // Fallback to server's createPage
198
+ htmlContent = await createPage({
199
+ data,
200
+ AppComponent,
201
+ PageComponent,
202
+ initialDatasId,
203
+ rootId,
204
+ pageName: page.pageName,
205
+ JSfileName: injectJS && fileName,
206
+ returnHtml: true,
207
+ });
208
+ }
209
+ return htmlContent;
210
+ }
211
+ catch (error) {
212
+ console.error(`[DEBUG] Error in processPageRuntime:`, error);
213
+ throw error;
214
+ }
215
+ }
216
+ /**
217
+ * Get all available pages for development mode
218
+ */
219
+ export function getAvailablePagesRuntime() {
220
+ const pagesDir = path.resolve(process.cwd(), "src/pages");
221
+ return readPages(pagesDir);
222
+ }
@@ -0,0 +1 @@
1
+ export {};