what-compiler 0.5.4 → 0.6.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/README.md +1 -1
- package/dist/babel-plugin.js +1238 -0
- package/dist/babel-plugin.js.map +7 -0
- package/dist/babel-plugin.min.js +2 -0
- package/dist/babel-plugin.min.js.map +7 -0
- package/dist/file-router.js +195 -0
- package/dist/file-router.js.map +7 -0
- package/dist/file-router.min.js +3 -0
- package/dist/file-router.min.js.map +7 -0
- package/dist/index.js +1996 -0
- package/dist/index.js.map +7 -0
- package/dist/index.min.js +397 -0
- package/dist/index.min.js.map +7 -0
- package/dist/runtime.js +9 -0
- package/dist/runtime.js.map +7 -0
- package/dist/runtime.min.js +2 -0
- package/dist/runtime.min.js.map +7 -0
- package/dist/vite-plugin.js +1985 -0
- package/dist/vite-plugin.js.map +7 -0
- package/dist/vite-plugin.min.js +397 -0
- package/dist/vite-plugin.min.js.map +7 -0
- package/package.json +27 -11
- package/src/babel-plugin.js +818 -520
- package/src/error-overlay.js +190 -119
- package/src/file-router.js +2 -1
- package/src/vite-plugin.js +86 -3
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// packages/compiler/src/file-router.js
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
var PAGE_EXTENSIONS = /* @__PURE__ */ new Set([".jsx", ".tsx", ".js", ".ts"]);
|
|
5
|
+
var IGNORED_FILES = /* @__PURE__ */ new Set(["_layout", "_error", "_loading", "_404"]);
|
|
6
|
+
function scanPages(pagesDir) {
|
|
7
|
+
const pages = [];
|
|
8
|
+
const layouts = [];
|
|
9
|
+
const apiRoutes = [];
|
|
10
|
+
function walk(dir, urlPrefix = "") {
|
|
11
|
+
if (!fs.existsSync(dir)) return;
|
|
12
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
const fullPath = path.join(dir, entry.name);
|
|
15
|
+
if (entry.isDirectory()) {
|
|
16
|
+
const groupMatch = entry.name.match(/^\((.+)\)$/);
|
|
17
|
+
if (groupMatch) {
|
|
18
|
+
walk(fullPath, urlPrefix);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (entry.name === "api" && urlPrefix === "") {
|
|
22
|
+
walkApi(fullPath, "/api");
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
walk(fullPath, urlPrefix + "/" + fileNameToSegment(entry.name));
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const ext = path.extname(entry.name);
|
|
29
|
+
if (!PAGE_EXTENSIONS.has(ext)) continue;
|
|
30
|
+
const baseName = path.basename(entry.name, ext);
|
|
31
|
+
if (baseName === "_layout") {
|
|
32
|
+
layouts.push({
|
|
33
|
+
filePath: fullPath,
|
|
34
|
+
urlPrefix: urlPrefix || "/"
|
|
35
|
+
});
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (IGNORED_FILES.has(baseName)) continue;
|
|
39
|
+
const urlSegment = fileNameToSegment(baseName);
|
|
40
|
+
const routePath = baseName === "index" ? urlPrefix || "/" : urlPrefix + "/" + urlSegment;
|
|
41
|
+
pages.push({
|
|
42
|
+
filePath: fullPath,
|
|
43
|
+
routePath: normalizePath(routePath),
|
|
44
|
+
isDynamic: routePath.includes(":") || routePath.includes("*")
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function walkApi(dir, urlPrefix) {
|
|
49
|
+
if (!fs.existsSync(dir)) return;
|
|
50
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const fullPath = path.join(dir, entry.name);
|
|
53
|
+
if (entry.isDirectory()) {
|
|
54
|
+
walkApi(fullPath, urlPrefix + "/" + fileNameToSegment(entry.name));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const ext = path.extname(entry.name);
|
|
58
|
+
if (!PAGE_EXTENSIONS.has(ext)) continue;
|
|
59
|
+
const baseName = path.basename(entry.name, ext);
|
|
60
|
+
const segment = fileNameToSegment(baseName);
|
|
61
|
+
const routePath = baseName === "index" ? urlPrefix : urlPrefix + "/" + segment;
|
|
62
|
+
apiRoutes.push({
|
|
63
|
+
filePath: fullPath,
|
|
64
|
+
routePath: normalizePath(routePath)
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
walk(pagesDir);
|
|
69
|
+
pages.sort((a, b) => {
|
|
70
|
+
const aWeight = routeWeight(a.routePath);
|
|
71
|
+
const bWeight = routeWeight(b.routePath);
|
|
72
|
+
return aWeight - bWeight;
|
|
73
|
+
});
|
|
74
|
+
return { pages, layouts, apiRoutes };
|
|
75
|
+
}
|
|
76
|
+
function fileNameToSegment(name) {
|
|
77
|
+
const catchAll = name.match(/^\[\.\.\.(\w+)\]$/);
|
|
78
|
+
if (catchAll) return "*" + catchAll[1];
|
|
79
|
+
const dynamic = name.match(/^\[(\w+)\]$/);
|
|
80
|
+
if (dynamic) return ":" + dynamic[1];
|
|
81
|
+
return name.toLowerCase();
|
|
82
|
+
}
|
|
83
|
+
function normalizePath(p) {
|
|
84
|
+
let result = p.replace(/\/+/g, "/");
|
|
85
|
+
if (result.length > 1 && result.endsWith("/")) {
|
|
86
|
+
result = result.slice(0, -1);
|
|
87
|
+
}
|
|
88
|
+
return result || "/";
|
|
89
|
+
}
|
|
90
|
+
function routeWeight(path2) {
|
|
91
|
+
if (path2.includes("*")) return 100;
|
|
92
|
+
if (path2.includes(":")) return 10;
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
function extractPageConfig(source) {
|
|
96
|
+
const match = source.match(
|
|
97
|
+
/export\s+const\s+page\s*=\s*(\{[^}]*\})/s
|
|
98
|
+
);
|
|
99
|
+
if (!match) {
|
|
100
|
+
return { mode: "client" };
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const obj = match[1].replace(/'/g, '"').replace(/(\w+)\s*:/g, '"$1":').replace(/,\s*}/g, "}").replace(/\/\/[^\n]*/g, "");
|
|
104
|
+
return { mode: "client", ...JSON.parse(obj) };
|
|
105
|
+
} catch {
|
|
106
|
+
return { mode: "client" };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function generateRoutesModule(pagesDir, rootDir) {
|
|
110
|
+
const { pages, layouts, apiRoutes } = scanPages(pagesDir);
|
|
111
|
+
const imports = [];
|
|
112
|
+
const routeEntries = [];
|
|
113
|
+
const layoutMap = /* @__PURE__ */ new Map();
|
|
114
|
+
layouts.forEach((layout, i) => {
|
|
115
|
+
const varName = `_layout${i}`;
|
|
116
|
+
const relPath = toImportPath(layout.filePath, rootDir);
|
|
117
|
+
imports.push(`import ${varName} from '${relPath}';`);
|
|
118
|
+
layoutMap.set(layout.urlPrefix, varName);
|
|
119
|
+
});
|
|
120
|
+
pages.forEach((page, i) => {
|
|
121
|
+
const varName = `_page${i}`;
|
|
122
|
+
const relPath = toImportPath(page.filePath, rootDir);
|
|
123
|
+
imports.push(`import ${varName} from '${relPath}';`);
|
|
124
|
+
let pageConfig = { mode: "client" };
|
|
125
|
+
try {
|
|
126
|
+
const source = fs.readFileSync(page.filePath, "utf-8");
|
|
127
|
+
pageConfig = extractPageConfig(source);
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
const layoutVar = findLayout(page.routePath, layoutMap);
|
|
131
|
+
const entry = {
|
|
132
|
+
path: page.routePath,
|
|
133
|
+
component: varName,
|
|
134
|
+
mode: pageConfig.mode || "client",
|
|
135
|
+
layout: layoutVar || null
|
|
136
|
+
};
|
|
137
|
+
routeEntries.push(entry);
|
|
138
|
+
});
|
|
139
|
+
const apiEntries = [];
|
|
140
|
+
apiRoutes.forEach((route, i) => {
|
|
141
|
+
const varName = `_api${i}`;
|
|
142
|
+
const relPath = toImportPath(route.filePath, rootDir);
|
|
143
|
+
imports.push(`import * as ${varName} from '${relPath}';`);
|
|
144
|
+
apiEntries.push({
|
|
145
|
+
path: route.routePath,
|
|
146
|
+
handlers: varName
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
const lines = [
|
|
150
|
+
"// Auto-generated by What Framework file router",
|
|
151
|
+
"// Do not edit \u2014 changes will be overwritten",
|
|
152
|
+
"",
|
|
153
|
+
...imports,
|
|
154
|
+
"",
|
|
155
|
+
"export const routes = [",
|
|
156
|
+
...routeEntries.map(
|
|
157
|
+
(r) => ` { path: '${r.path}', component: ${r.component}, mode: '${r.mode}'${r.layout ? `, layout: ${r.layout}` : ""} },`
|
|
158
|
+
),
|
|
159
|
+
"];",
|
|
160
|
+
"",
|
|
161
|
+
`export const apiRoutes = [`,
|
|
162
|
+
...apiEntries.map(
|
|
163
|
+
(r) => ` { path: '${r.path}', handlers: ${r.handlers} },`
|
|
164
|
+
),
|
|
165
|
+
"];",
|
|
166
|
+
"",
|
|
167
|
+
// Export page modes for the build system
|
|
168
|
+
"export const pageModes = {",
|
|
169
|
+
...routeEntries.map(
|
|
170
|
+
(r) => ` '${r.path}': '${r.mode}',`
|
|
171
|
+
),
|
|
172
|
+
"};"
|
|
173
|
+
];
|
|
174
|
+
return lines.join("\n");
|
|
175
|
+
}
|
|
176
|
+
function toImportPath(filePath, rootDir) {
|
|
177
|
+
const rel = path.relative(rootDir, filePath);
|
|
178
|
+
return "/" + rel.split(path.sep).join("/");
|
|
179
|
+
}
|
|
180
|
+
function findLayout(routePath, layoutMap) {
|
|
181
|
+
const segments = routePath.split("/").filter(Boolean);
|
|
182
|
+
while (segments.length > 0) {
|
|
183
|
+
const prefix = "/" + segments.join("/");
|
|
184
|
+
if (layoutMap.has(prefix)) return layoutMap.get(prefix);
|
|
185
|
+
segments.pop();
|
|
186
|
+
}
|
|
187
|
+
if (layoutMap.has("/")) return layoutMap.get("/");
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
export {
|
|
191
|
+
extractPageConfig,
|
|
192
|
+
generateRoutesModule,
|
|
193
|
+
scanPages
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=file-router.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/file-router.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * File-Based Router for What Framework\n *\n * Scans a pages directory and generates route configuration.\n *\n * File conventions:\n * src/pages/index.jsx \u2192 /\n * src/pages/about.jsx \u2192 /about\n * src/pages/blog/index.jsx \u2192 /blog\n * src/pages/blog/[slug].jsx \u2192 /blog/:slug\n * src/pages/[...path].jsx \u2192 catch-all\n * src/pages/_layout.jsx \u2192 layout for that directory\n * src/pages/(auth)/login.jsx \u2192 /login (group doesn't affect URL)\n * src/pages/api/users.js \u2192 API route: /api/users\n *\n * Page declarations (optional export in each page file):\n * export const page = {\n * mode: 'client', // default \u2014 SPA, JS required\n * mode: 'server', // SSR on every request\n * mode: 'static', // pre-rendered at build time\n * mode: 'hybrid', // static HTML shell + interactive islands\n * };\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nconst PAGE_EXTENSIONS = new Set(['.jsx', '.tsx', '.js', '.ts']);\nconst IGNORED_FILES = new Set(['_layout', '_error', '_loading', '_404']);\n\n/**\n * Scan a directory recursively and return all page files.\n */\nexport function scanPages(pagesDir) {\n const pages = [];\n const layouts = [];\n const apiRoutes = [];\n\n function walk(dir, urlPrefix = '') {\n if (!fs.existsSync(dir)) return;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Route groups: (name)/ \u2014 strip from URL\n const groupMatch = entry.name.match(/^\\((.+)\\)$/);\n if (groupMatch) {\n walk(fullPath, urlPrefix); // Same URL prefix\n continue;\n }\n\n // API directory\n if (entry.name === 'api' && urlPrefix === '') {\n walkApi(fullPath, '/api');\n continue;\n }\n\n walk(fullPath, urlPrefix + '/' + fileNameToSegment(entry.name));\n continue;\n }\n\n // Only process page extensions\n const ext = path.extname(entry.name);\n if (!PAGE_EXTENSIONS.has(ext)) continue;\n\n const baseName = path.basename(entry.name, ext);\n\n // Layout files\n if (baseName === '_layout') {\n layouts.push({\n filePath: fullPath,\n urlPrefix: urlPrefix || '/',\n });\n continue;\n }\n\n // Error/loading/404 boundaries (reserved names)\n if (IGNORED_FILES.has(baseName)) continue;\n\n // Convert file name to URL segment\n const urlSegment = fileNameToSegment(baseName);\n const routePath = baseName === 'index'\n ? (urlPrefix || '/')\n : urlPrefix + '/' + urlSegment;\n\n pages.push({\n filePath: fullPath,\n routePath: normalizePath(routePath),\n isDynamic: routePath.includes(':') || routePath.includes('*'),\n });\n }\n }\n\n function walkApi(dir, urlPrefix) {\n if (!fs.existsSync(dir)) return;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n walkApi(fullPath, urlPrefix + '/' + fileNameToSegment(entry.name));\n continue;\n }\n\n const ext = path.extname(entry.name);\n if (!PAGE_EXTENSIONS.has(ext)) continue;\n\n const baseName = path.basename(entry.name, ext);\n const segment = fileNameToSegment(baseName);\n const routePath = baseName === 'index'\n ? urlPrefix\n : urlPrefix + '/' + segment;\n\n apiRoutes.push({\n filePath: fullPath,\n routePath: normalizePath(routePath),\n });\n }\n }\n\n walk(pagesDir);\n\n // Sort: static routes first, then dynamic, then catch-all\n pages.sort((a, b) => {\n const aWeight = routeWeight(a.routePath);\n const bWeight = routeWeight(b.routePath);\n return aWeight - bWeight;\n });\n\n return { pages, layouts, apiRoutes };\n}\n\n/**\n * Convert a file name to a URL segment.\n * [slug] \u2192 :slug\n * [...path] \u2192 *path (catch-all)\n * about \u2192 about\n */\nfunction fileNameToSegment(name) {\n // Catch-all: [...param]\n const catchAll = name.match(/^\\[\\.\\.\\.(\\w+)\\]$/);\n if (catchAll) return '*' + catchAll[1];\n\n // Dynamic: [param]\n const dynamic = name.match(/^\\[(\\w+)\\]$/);\n if (dynamic) return ':' + dynamic[1];\n\n // Lowercase page names for URL consistency (About.jsx \u2192 /about)\n return name.toLowerCase();\n}\n\n/**\n * Normalize a route path.\n */\nfunction normalizePath(p) {\n // Remove double slashes\n let result = p.replace(/\\/+/g, '/');\n // Remove trailing slash (except root)\n if (result.length > 1 && result.endsWith('/')) {\n result = result.slice(0, -1);\n }\n return result || '/';\n}\n\n/**\n * Route weight for sorting \u2014 static routes first.\n */\nfunction routeWeight(path) {\n if (path.includes('*')) return 100; // Catch-all last\n if (path.includes(':')) return 10; // Dynamic middle\n return 0; // Static first\n}\n\n/**\n * Extract `export const page = { ... }` from a file's source code.\n * Uses simple regex \u2014 doesn't need a full parser for this.\n */\nexport function extractPageConfig(source) {\n // Match: export const page = { ... }\n // Handles single-line and simple multi-line objects\n const match = source.match(\n /export\\s+const\\s+page\\s*=\\s*(\\{[^}]*\\})/s\n );\n\n if (!match) {\n return { mode: 'client' }; // Default\n }\n\n try {\n // Simple evaluation of the object literal\n // Only supports string/boolean/number literals for safety\n const obj = match[1]\n .replace(/'/g, '\"')\n .replace(/(\\w+)\\s*:/g, '\"$1\":')\n .replace(/,\\s*}/g, '}')\n .replace(/\\/\\/[^\\n]*/g, ''); // Strip comments\n\n return { mode: 'client', ...JSON.parse(obj) };\n } catch {\n return { mode: 'client' };\n }\n}\n\n/**\n * Generate the virtual routes module source code.\n * This is what gets imported as 'virtual:what-routes'.\n */\nexport function generateRoutesModule(pagesDir, rootDir) {\n const { pages, layouts, apiRoutes } = scanPages(pagesDir);\n\n const imports = [];\n const routeEntries = [];\n\n // Generate layout imports\n const layoutMap = new Map();\n layouts.forEach((layout, i) => {\n const varName = `_layout${i}`;\n const relPath = toImportPath(layout.filePath, rootDir);\n imports.push(`import ${varName} from '${relPath}';`);\n layoutMap.set(layout.urlPrefix, varName);\n });\n\n // Generate page imports and route entries\n pages.forEach((page, i) => {\n const varName = `_page${i}`;\n const relPath = toImportPath(page.filePath, rootDir);\n imports.push(`import ${varName} from '${relPath}';`);\n\n // Read file to extract page config\n let pageConfig = { mode: 'client' };\n try {\n const source = fs.readFileSync(page.filePath, 'utf-8');\n pageConfig = extractPageConfig(source);\n } catch {}\n\n // Find matching layout (closest parent)\n const layoutVar = findLayout(page.routePath, layoutMap);\n\n const entry = {\n path: page.routePath,\n component: varName,\n mode: pageConfig.mode || 'client',\n layout: layoutVar || null,\n };\n\n routeEntries.push(entry);\n });\n\n // Generate API route entries\n const apiEntries = [];\n apiRoutes.forEach((route, i) => {\n const varName = `_api${i}`;\n const relPath = toImportPath(route.filePath, rootDir);\n imports.push(`import * as ${varName} from '${relPath}';`);\n apiEntries.push({\n path: route.routePath,\n handlers: varName,\n });\n });\n\n // Build the module\n const lines = [\n '// Auto-generated by What Framework file router',\n '// Do not edit \u2014 changes will be overwritten',\n '',\n ...imports,\n '',\n 'export const routes = [',\n ...routeEntries.map(r =>\n ` { path: '${r.path}', component: ${r.component}, mode: '${r.mode}'${r.layout ? `, layout: ${r.layout}` : ''} },`\n ),\n '];',\n '',\n `export const apiRoutes = [`,\n ...apiEntries.map(r =>\n ` { path: '${r.path}', handlers: ${r.handlers} },`\n ),\n '];',\n '',\n // Export page modes for the build system\n 'export const pageModes = {',\n ...routeEntries.map(r =>\n ` '${r.path}': '${r.mode}',`\n ),\n '};',\n ];\n\n return lines.join('\\n');\n}\n\n/**\n * Convert absolute file path to a root-relative import path.\n */\nfunction toImportPath(filePath, rootDir) {\n const rel = path.relative(rootDir, filePath);\n // Ensure forward slashes and starts with /\n return '/' + rel.split(path.sep).join('/');\n}\n\n/**\n * Find the closest layout for a given route path.\n */\nfunction findLayout(routePath, layoutMap) {\n // Walk up from the route path to find the nearest layout\n const segments = routePath.split('/').filter(Boolean);\n\n while (segments.length > 0) {\n const prefix = '/' + segments.join('/');\n if (layoutMap.has(prefix)) return layoutMap.get(prefix);\n segments.pop();\n }\n\n // Check root layout\n if (layoutMap.has('/')) return layoutMap.get('/');\n return null;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["path"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import d from"fs";import p from"path";var w=new Set([".jsx",".tsx",".js",".ts"]),_=new Set(["_layout","_error","_loading","_404"]);function b(n){let e=[],c=[],m=[];function g(r,a=""){if(!d.existsSync(r))return;let h=d.readdirSync(r,{withFileTypes:!0});for(let o of h){let t=p.join(r,o.name);if(o.isDirectory()){if(o.name.match(/^\((.+)\)$/)){g(t,a);continue}if(o.name==="api"&&a===""){f(t,"/api");continue}g(t,a+"/"+y(o.name));continue}let i=p.extname(o.name);if(!w.has(i))continue;let s=p.basename(o.name,i);if(s==="_layout"){c.push({filePath:t,urlPrefix:a||"/"});continue}if(_.has(s))continue;let u=y(s),l=s==="index"?a||"/":a+"/"+u;e.push({filePath:t,routePath:x(l),isDynamic:l.includes(":")||l.includes("*")})}}function f(r,a){if(!d.existsSync(r))return;let h=d.readdirSync(r,{withFileTypes:!0});for(let o of h){let t=p.join(r,o.name);if(o.isDirectory()){f(t,a+"/"+y(o.name));continue}let i=p.extname(o.name);if(!w.has(i))continue;let s=p.basename(o.name,i),u=y(s),l=s==="index"?a:a+"/"+u;m.push({filePath:t,routePath:x(l)})}}return g(n),e.sort((r,a)=>{let h=S(r.routePath),o=S(a.routePath);return h-o}),{pages:e,layouts:c,apiRoutes:m}}function y(n){let e=n.match(/^\[\.\.\.(\w+)\]$/);if(e)return"*"+e[1];let c=n.match(/^\[(\w+)\]$/);return c?":"+c[1]:n.toLowerCase()}function x(n){let e=n.replace(/\/+/g,"/");return e.length>1&&e.endsWith("/")&&(e=e.slice(0,-1)),e||"/"}function S(n){return n.includes("*")?100:n.includes(":")?10:0}function j(n){let e=n.match(/export\s+const\s+page\s*=\s*(\{[^}]*\})/s);if(!e)return{mode:"client"};try{let c=e[1].replace(/'/g,'"').replace(/(\w+)\s*:/g,'"$1":').replace(/,\s*}/g,"}").replace(/\/\/[^\n]*/g,"");return{mode:"client",...JSON.parse(c)}}catch{return{mode:"client"}}}function W(n,e){let{pages:c,layouts:m,apiRoutes:g}=b(n),f=[],r=[],a=new Map;m.forEach((t,i)=>{let s=`_layout${i}`,u=$(t.filePath,e);f.push(`import ${s} from '${u}';`),a.set(t.urlPrefix,s)}),c.forEach((t,i)=>{let s=`_page${i}`,u=$(t.filePath,e);f.push(`import ${s} from '${u}';`);let l={mode:"client"};try{let N=d.readFileSync(t.filePath,"utf-8");l=j(N)}catch{}let P=v(t.routePath,a),E={path:t.routePath,component:s,mode:l.mode||"client",layout:P||null};r.push(E)});let h=[];return g.forEach((t,i)=>{let s=`_api${i}`,u=$(t.filePath,e);f.push(`import * as ${s} from '${u}';`),h.push({path:t.routePath,handlers:s})}),["// Auto-generated by What Framework file router","// Do not edit \u2014 changes will be overwritten","",...f,"","export const routes = [",...r.map(t=>` { path: '${t.path}', component: ${t.component}, mode: '${t.mode}'${t.layout?`, layout: ${t.layout}`:""} },`),"];","","export const apiRoutes = [",...h.map(t=>` { path: '${t.path}', handlers: ${t.handlers} },`),"];","","export const pageModes = {",...r.map(t=>` '${t.path}': '${t.mode}',`),"};"].join(`
|
|
2
|
+
`)}function $(n,e){return"/"+p.relative(e,n).split(p.sep).join("/")}function v(n,e){let c=n.split("/").filter(Boolean);for(;c.length>0;){let m="/"+c.join("/");if(e.has(m))return e.get(m);c.pop()}return e.has("/")?e.get("/"):null}export{j as extractPageConfig,W as generateRoutesModule,b as scanPages};
|
|
3
|
+
//# sourceMappingURL=file-router.min.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/file-router.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * File-Based Router for What Framework\n *\n * Scans a pages directory and generates route configuration.\n *\n * File conventions:\n * src/pages/index.jsx \u2192 /\n * src/pages/about.jsx \u2192 /about\n * src/pages/blog/index.jsx \u2192 /blog\n * src/pages/blog/[slug].jsx \u2192 /blog/:slug\n * src/pages/[...path].jsx \u2192 catch-all\n * src/pages/_layout.jsx \u2192 layout for that directory\n * src/pages/(auth)/login.jsx \u2192 /login (group doesn't affect URL)\n * src/pages/api/users.js \u2192 API route: /api/users\n *\n * Page declarations (optional export in each page file):\n * export const page = {\n * mode: 'client', // default \u2014 SPA, JS required\n * mode: 'server', // SSR on every request\n * mode: 'static', // pre-rendered at build time\n * mode: 'hybrid', // static HTML shell + interactive islands\n * };\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nconst PAGE_EXTENSIONS = new Set(['.jsx', '.tsx', '.js', '.ts']);\nconst IGNORED_FILES = new Set(['_layout', '_error', '_loading', '_404']);\n\n/**\n * Scan a directory recursively and return all page files.\n */\nexport function scanPages(pagesDir) {\n const pages = [];\n const layouts = [];\n const apiRoutes = [];\n\n function walk(dir, urlPrefix = '') {\n if (!fs.existsSync(dir)) return;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n // Route groups: (name)/ \u2014 strip from URL\n const groupMatch = entry.name.match(/^\\((.+)\\)$/);\n if (groupMatch) {\n walk(fullPath, urlPrefix); // Same URL prefix\n continue;\n }\n\n // API directory\n if (entry.name === 'api' && urlPrefix === '') {\n walkApi(fullPath, '/api');\n continue;\n }\n\n walk(fullPath, urlPrefix + '/' + fileNameToSegment(entry.name));\n continue;\n }\n\n // Only process page extensions\n const ext = path.extname(entry.name);\n if (!PAGE_EXTENSIONS.has(ext)) continue;\n\n const baseName = path.basename(entry.name, ext);\n\n // Layout files\n if (baseName === '_layout') {\n layouts.push({\n filePath: fullPath,\n urlPrefix: urlPrefix || '/',\n });\n continue;\n }\n\n // Error/loading/404 boundaries (reserved names)\n if (IGNORED_FILES.has(baseName)) continue;\n\n // Convert file name to URL segment\n const urlSegment = fileNameToSegment(baseName);\n const routePath = baseName === 'index'\n ? (urlPrefix || '/')\n : urlPrefix + '/' + urlSegment;\n\n pages.push({\n filePath: fullPath,\n routePath: normalizePath(routePath),\n isDynamic: routePath.includes(':') || routePath.includes('*'),\n });\n }\n }\n\n function walkApi(dir, urlPrefix) {\n if (!fs.existsSync(dir)) return;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n walkApi(fullPath, urlPrefix + '/' + fileNameToSegment(entry.name));\n continue;\n }\n\n const ext = path.extname(entry.name);\n if (!PAGE_EXTENSIONS.has(ext)) continue;\n\n const baseName = path.basename(entry.name, ext);\n const segment = fileNameToSegment(baseName);\n const routePath = baseName === 'index'\n ? urlPrefix\n : urlPrefix + '/' + segment;\n\n apiRoutes.push({\n filePath: fullPath,\n routePath: normalizePath(routePath),\n });\n }\n }\n\n walk(pagesDir);\n\n // Sort: static routes first, then dynamic, then catch-all\n pages.sort((a, b) => {\n const aWeight = routeWeight(a.routePath);\n const bWeight = routeWeight(b.routePath);\n return aWeight - bWeight;\n });\n\n return { pages, layouts, apiRoutes };\n}\n\n/**\n * Convert a file name to a URL segment.\n * [slug] \u2192 :slug\n * [...path] \u2192 *path (catch-all)\n * about \u2192 about\n */\nfunction fileNameToSegment(name) {\n // Catch-all: [...param]\n const catchAll = name.match(/^\\[\\.\\.\\.(\\w+)\\]$/);\n if (catchAll) return '*' + catchAll[1];\n\n // Dynamic: [param]\n const dynamic = name.match(/^\\[(\\w+)\\]$/);\n if (dynamic) return ':' + dynamic[1];\n\n // Lowercase page names for URL consistency (About.jsx \u2192 /about)\n return name.toLowerCase();\n}\n\n/**\n * Normalize a route path.\n */\nfunction normalizePath(p) {\n // Remove double slashes\n let result = p.replace(/\\/+/g, '/');\n // Remove trailing slash (except root)\n if (result.length > 1 && result.endsWith('/')) {\n result = result.slice(0, -1);\n }\n return result || '/';\n}\n\n/**\n * Route weight for sorting \u2014 static routes first.\n */\nfunction routeWeight(path) {\n if (path.includes('*')) return 100; // Catch-all last\n if (path.includes(':')) return 10; // Dynamic middle\n return 0; // Static first\n}\n\n/**\n * Extract `export const page = { ... }` from a file's source code.\n * Uses simple regex \u2014 doesn't need a full parser for this.\n */\nexport function extractPageConfig(source) {\n // Match: export const page = { ... }\n // Handles single-line and simple multi-line objects\n const match = source.match(\n /export\\s+const\\s+page\\s*=\\s*(\\{[^}]*\\})/s\n );\n\n if (!match) {\n return { mode: 'client' }; // Default\n }\n\n try {\n // Simple evaluation of the object literal\n // Only supports string/boolean/number literals for safety\n const obj = match[1]\n .replace(/'/g, '\"')\n .replace(/(\\w+)\\s*:/g, '\"$1\":')\n .replace(/,\\s*}/g, '}')\n .replace(/\\/\\/[^\\n]*/g, ''); // Strip comments\n\n return { mode: 'client', ...JSON.parse(obj) };\n } catch {\n return { mode: 'client' };\n }\n}\n\n/**\n * Generate the virtual routes module source code.\n * This is what gets imported as 'virtual:what-routes'.\n */\nexport function generateRoutesModule(pagesDir, rootDir) {\n const { pages, layouts, apiRoutes } = scanPages(pagesDir);\n\n const imports = [];\n const routeEntries = [];\n\n // Generate layout imports\n const layoutMap = new Map();\n layouts.forEach((layout, i) => {\n const varName = `_layout${i}`;\n const relPath = toImportPath(layout.filePath, rootDir);\n imports.push(`import ${varName} from '${relPath}';`);\n layoutMap.set(layout.urlPrefix, varName);\n });\n\n // Generate page imports and route entries\n pages.forEach((page, i) => {\n const varName = `_page${i}`;\n const relPath = toImportPath(page.filePath, rootDir);\n imports.push(`import ${varName} from '${relPath}';`);\n\n // Read file to extract page config\n let pageConfig = { mode: 'client' };\n try {\n const source = fs.readFileSync(page.filePath, 'utf-8');\n pageConfig = extractPageConfig(source);\n } catch {}\n\n // Find matching layout (closest parent)\n const layoutVar = findLayout(page.routePath, layoutMap);\n\n const entry = {\n path: page.routePath,\n component: varName,\n mode: pageConfig.mode || 'client',\n layout: layoutVar || null,\n };\n\n routeEntries.push(entry);\n });\n\n // Generate API route entries\n const apiEntries = [];\n apiRoutes.forEach((route, i) => {\n const varName = `_api${i}`;\n const relPath = toImportPath(route.filePath, rootDir);\n imports.push(`import * as ${varName} from '${relPath}';`);\n apiEntries.push({\n path: route.routePath,\n handlers: varName,\n });\n });\n\n // Build the module\n const lines = [\n '// Auto-generated by What Framework file router',\n '// Do not edit \u2014 changes will be overwritten',\n '',\n ...imports,\n '',\n 'export const routes = [',\n ...routeEntries.map(r =>\n ` { path: '${r.path}', component: ${r.component}, mode: '${r.mode}'${r.layout ? `, layout: ${r.layout}` : ''} },`\n ),\n '];',\n '',\n `export const apiRoutes = [`,\n ...apiEntries.map(r =>\n ` { path: '${r.path}', handlers: ${r.handlers} },`\n ),\n '];',\n '',\n // Export page modes for the build system\n 'export const pageModes = {',\n ...routeEntries.map(r =>\n ` '${r.path}': '${r.mode}',`\n ),\n '};',\n ];\n\n return lines.join('\\n');\n}\n\n/**\n * Convert absolute file path to a root-relative import path.\n */\nfunction toImportPath(filePath, rootDir) {\n const rel = path.relative(rootDir, filePath);\n // Ensure forward slashes and starts with /\n return '/' + rel.split(path.sep).join('/');\n}\n\n/**\n * Find the closest layout for a given route path.\n */\nfunction findLayout(routePath, layoutMap) {\n // Walk up from the route path to find the nearest layout\n const segments = routePath.split('/').filter(Boolean);\n\n while (segments.length > 0) {\n const prefix = '/' + segments.join('/');\n if (layoutMap.has(prefix)) return layoutMap.get(prefix);\n segments.pop();\n }\n\n // Check root layout\n if (layoutMap.has('/')) return layoutMap.get('/');\n return null;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["fs", "path", "PAGE_EXTENSIONS", "IGNORED_FILES", "scanPages", "pagesDir", "pages", "layouts", "apiRoutes", "walk", "dir", "urlPrefix", "entries", "entry", "fullPath", "walkApi", "fileNameToSegment", "ext", "baseName", "urlSegment", "routePath", "normalizePath", "segment", "a", "b", "aWeight", "routeWeight", "bWeight", "name", "catchAll", "dynamic", "p", "result", "extractPageConfig", "source", "match", "obj", "generateRoutesModule", "rootDir", "imports", "routeEntries", "layoutMap", "layout", "varName", "relPath", "toImportPath", "page", "pageConfig", "layoutVar", "findLayout", "apiEntries", "route", "r", "filePath", "segments", "prefix"]
|
|
7
|
+
}
|