bertui 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/src/client/compiler.js +15 -24
- package/src/server/dev-server.js +27 -44
package/README.md
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
package/src/client/compiler.js
CHANGED
|
@@ -33,9 +33,6 @@ export async function compileProject(root) {
|
|
|
33
33
|
file: r.file,
|
|
34
34
|
type: r.type
|
|
35
35
|
})));
|
|
36
|
-
|
|
37
|
-
await generateRouter(routes, outDir, root);
|
|
38
|
-
logger.info('Generated router.js');
|
|
39
36
|
}
|
|
40
37
|
}
|
|
41
38
|
|
|
@@ -43,6 +40,12 @@ export async function compileProject(root) {
|
|
|
43
40
|
const stats = await compileDirectory(srcDir, outDir, root);
|
|
44
41
|
const duration = Date.now() - startTime;
|
|
45
42
|
|
|
43
|
+
// Generate router AFTER compilation so we reference .js files
|
|
44
|
+
if (routes.length > 0) {
|
|
45
|
+
await generateRouter(routes, outDir, root);
|
|
46
|
+
logger.info('Generated router.js');
|
|
47
|
+
}
|
|
48
|
+
|
|
46
49
|
logger.success(`Compiled ${stats.files} files in ${duration}ms`);
|
|
47
50
|
logger.info(`Output: ${outDir}`);
|
|
48
51
|
|
|
@@ -77,7 +80,7 @@ async function discoverRoutes(pagesDir) {
|
|
|
77
80
|
|
|
78
81
|
routes.push({
|
|
79
82
|
route: route === '' ? '/' : route,
|
|
80
|
-
file: relativePath,
|
|
83
|
+
file: relativePath.replace(/\\/g, '/'),
|
|
81
84
|
path: fullPath,
|
|
82
85
|
type
|
|
83
86
|
});
|
|
@@ -101,7 +104,8 @@ async function discoverRoutes(pagesDir) {
|
|
|
101
104
|
async function generateRouter(routes, outDir, root) {
|
|
102
105
|
const imports = routes.map((route, i) => {
|
|
103
106
|
const componentName = `Page${i}`;
|
|
104
|
-
|
|
107
|
+
// CRITICAL FIX: Import .js files (compiled), not .jsx
|
|
108
|
+
const importPath = `./pages/${route.file.replace(/\.(jsx|tsx|ts)$/, '.js')}`;
|
|
105
109
|
return `import ${componentName} from '${importPath}';`;
|
|
106
110
|
}).join('\n');
|
|
107
111
|
|
|
@@ -192,12 +196,15 @@ async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
|
192
196
|
const loader = ext === '.tsx' ? 'tsx' : ext === '.ts' ? 'ts' : 'jsx';
|
|
193
197
|
|
|
194
198
|
try {
|
|
195
|
-
const transpiler = new Bun.Transpiler({ loader });
|
|
196
199
|
let code = await Bun.file(srcPath).text();
|
|
197
200
|
|
|
198
|
-
//
|
|
199
|
-
code =
|
|
201
|
+
// Remove bertui/styles imports completely
|
|
202
|
+
code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
|
|
200
203
|
|
|
204
|
+
// Replace bertui/router imports with CDN React Router (we'll use a simpler approach)
|
|
205
|
+
// For now, keep the import as-is and handle it differently
|
|
206
|
+
|
|
207
|
+
const transpiler = new Bun.Transpiler({ loader });
|
|
201
208
|
const compiled = await transpiler.transform(code);
|
|
202
209
|
|
|
203
210
|
const outFilename = filename.replace(/\.(jsx|tsx|ts)$/, '.js');
|
|
@@ -209,20 +216,4 @@ async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
|
209
216
|
logger.error(`Failed to compile ${relativePath}: ${error.message}`);
|
|
210
217
|
throw error;
|
|
211
218
|
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function resolveBareImports(code) {
|
|
215
|
-
// Replace bertui/styles with actual CSS path
|
|
216
|
-
code = code.replace(
|
|
217
|
-
/import\s+['"]bertui\/styles['"]/g,
|
|
218
|
-
"import '/styles/bertui.css'"
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
// Replace bertui/router with actual router path
|
|
222
|
-
code = code.replace(
|
|
223
|
-
/from\s+['"]bertui\/router['"]/g,
|
|
224
|
-
"from '/compiled/router.js'"
|
|
225
|
-
);
|
|
226
|
-
|
|
227
|
-
return code;
|
|
228
219
|
}
|
package/src/server/dev-server.js
CHANGED
|
@@ -14,7 +14,6 @@ export async function startDevServer(options = {}) {
|
|
|
14
14
|
const clients = new Set();
|
|
15
15
|
let hasRouter = false;
|
|
16
16
|
|
|
17
|
-
// Check if router exists
|
|
18
17
|
const routerPath = join(compiledDir, 'router.js');
|
|
19
18
|
if (existsSync(routerPath)) {
|
|
20
19
|
hasRouter = true;
|
|
@@ -22,28 +21,21 @@ export async function startDevServer(options = {}) {
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
const app = new Elysia()
|
|
25
|
-
// Main HTML route - serves all pages
|
|
26
24
|
.get('/', async () => {
|
|
27
25
|
return serveHTML(root, hasRouter);
|
|
28
26
|
})
|
|
29
27
|
|
|
30
|
-
// Catch-all route for SPA routing
|
|
31
28
|
.get('/*', async ({ params, set }) => {
|
|
32
29
|
const path = params['*'];
|
|
33
30
|
|
|
34
|
-
// Check if it's a file request
|
|
35
31
|
if (path.includes('.')) {
|
|
36
|
-
// Try to serve compiled files
|
|
37
32
|
if (path.startsWith('compiled/')) {
|
|
38
33
|
const filePath = join(compiledDir, path.replace('compiled/', ''));
|
|
39
34
|
const file = Bun.file(filePath);
|
|
40
35
|
|
|
41
36
|
if (await file.exists()) {
|
|
42
37
|
const ext = extname(path);
|
|
43
|
-
|
|
44
|
-
const contentType = ext === '.js' || ext === '.jsx'
|
|
45
|
-
? 'application/javascript'
|
|
46
|
-
: getContentType(ext);
|
|
38
|
+
const contentType = ext === '.js' ? 'application/javascript' : getContentType(ext);
|
|
47
39
|
|
|
48
40
|
return new Response(await file.text(), {
|
|
49
41
|
headers: {
|
|
@@ -58,7 +50,6 @@ export async function startDevServer(options = {}) {
|
|
|
58
50
|
return 'File not found';
|
|
59
51
|
}
|
|
60
52
|
|
|
61
|
-
// For non-file routes, serve the main HTML (SPA mode)
|
|
62
53
|
return serveHTML(root, hasRouter);
|
|
63
54
|
})
|
|
64
55
|
|
|
@@ -108,25 +99,6 @@ ws.onclose = () => {
|
|
|
108
99
|
}
|
|
109
100
|
})
|
|
110
101
|
|
|
111
|
-
// Serve BertUI CSS
|
|
112
|
-
.get('/styles/bertui.css', async ({ set }) => {
|
|
113
|
-
const cssPath = join(import.meta.dir, '../styles/bertui.css');
|
|
114
|
-
const file = Bun.file(cssPath);
|
|
115
|
-
|
|
116
|
-
if (!await file.exists()) {
|
|
117
|
-
set.status = 404;
|
|
118
|
-
return 'CSS file not found';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return new Response(await file.text(), {
|
|
122
|
-
headers: {
|
|
123
|
-
'Content-Type': 'text/css',
|
|
124
|
-
'Cache-Control': 'no-store'
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
// Serve compiled files with correct MIME types
|
|
130
102
|
.get('/compiled/*', async ({ params, set }) => {
|
|
131
103
|
const filepath = join(compiledDir, params['*']);
|
|
132
104
|
const file = Bun.file(filepath);
|
|
@@ -137,10 +109,7 @@ ws.onclose = () => {
|
|
|
137
109
|
}
|
|
138
110
|
|
|
139
111
|
const ext = extname(filepath);
|
|
140
|
-
|
|
141
|
-
const contentType = ext === '.js'
|
|
142
|
-
? 'application/javascript'
|
|
143
|
-
: getContentType(ext);
|
|
112
|
+
const contentType = ext === '.js' ? 'application/javascript' : getContentType(ext);
|
|
144
113
|
|
|
145
114
|
return new Response(await file.text(), {
|
|
146
115
|
headers: {
|
|
@@ -150,7 +119,6 @@ ws.onclose = () => {
|
|
|
150
119
|
});
|
|
151
120
|
})
|
|
152
121
|
|
|
153
|
-
// Serve public assets
|
|
154
122
|
.get('/public/*', async ({ params, set }) => {
|
|
155
123
|
const publicDir = join(root, 'public');
|
|
156
124
|
const filepath = join(publicDir, params['*']);
|
|
@@ -174,7 +142,6 @@ ws.onclose = () => {
|
|
|
174
142
|
logger.success(`🚀 Server running at http://localhost:${port}`);
|
|
175
143
|
logger.info(`📁 Serving: ${root}`);
|
|
176
144
|
|
|
177
|
-
// Watch for file changes
|
|
178
145
|
setupWatcher(root, compiledDir, clients, () => {
|
|
179
146
|
hasRouter = existsSync(join(compiledDir, 'router.js'));
|
|
180
147
|
});
|
|
@@ -190,7 +157,30 @@ function serveHTML(root, hasRouter) {
|
|
|
190
157
|
<meta charset="UTF-8">
|
|
191
158
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
192
159
|
<title>BertUI App - Dev</title>
|
|
193
|
-
|
|
160
|
+
|
|
161
|
+
<!-- Import Map for React and dependencies -->
|
|
162
|
+
<script type="importmap">
|
|
163
|
+
{
|
|
164
|
+
"imports": {
|
|
165
|
+
"react": "https://esm.sh/react@18.2.0",
|
|
166
|
+
"react-dom": "https://esm.sh/react-dom@18.2.0",
|
|
167
|
+
"react-dom/client": "https://esm.sh/react-dom@18.2.0/client",
|
|
168
|
+
"bertui/router": "/compiled/router.js"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
</script>
|
|
172
|
+
|
|
173
|
+
<style>
|
|
174
|
+
/* Inline basic styles since we're skipping CSS for now */
|
|
175
|
+
* {
|
|
176
|
+
margin: 0;
|
|
177
|
+
padding: 0;
|
|
178
|
+
box-sizing: border-box;
|
|
179
|
+
}
|
|
180
|
+
body {
|
|
181
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
182
|
+
}
|
|
183
|
+
</style>
|
|
194
184
|
</head>
|
|
195
185
|
<body>
|
|
196
186
|
<div id="root"></div>
|
|
@@ -220,11 +210,7 @@ function getContentType(ext) {
|
|
|
220
210
|
'.jpeg': 'image/jpeg',
|
|
221
211
|
'.gif': 'image/gif',
|
|
222
212
|
'.svg': 'image/svg+xml',
|
|
223
|
-
'.ico': 'image/x-icon'
|
|
224
|
-
'.woff': 'font/woff',
|
|
225
|
-
'.woff2': 'font/woff2',
|
|
226
|
-
'.ttf': 'font/ttf',
|
|
227
|
-
'.eot': 'application/vnd.ms-fontobject'
|
|
213
|
+
'.ico': 'image/x-icon'
|
|
228
214
|
};
|
|
229
215
|
|
|
230
216
|
return types[ext] || 'text/plain';
|
|
@@ -247,7 +233,6 @@ function setupWatcher(root, compiledDir, clients, onRecompile) {
|
|
|
247
233
|
if (['.js', '.jsx', '.ts', '.tsx', '.css'].includes(ext)) {
|
|
248
234
|
logger.info(`📝 File changed: ${filename}`);
|
|
249
235
|
|
|
250
|
-
// Notify clients
|
|
251
236
|
for (const client of clients) {
|
|
252
237
|
try {
|
|
253
238
|
client.send(JSON.stringify({ type: 'recompiling' }));
|
|
@@ -256,7 +241,6 @@ function setupWatcher(root, compiledDir, clients, onRecompile) {
|
|
|
256
241
|
}
|
|
257
242
|
}
|
|
258
243
|
|
|
259
|
-
// Recompile
|
|
260
244
|
try {
|
|
261
245
|
await compileProject(root);
|
|
262
246
|
|
|
@@ -264,7 +248,6 @@ function setupWatcher(root, compiledDir, clients, onRecompile) {
|
|
|
264
248
|
onRecompile();
|
|
265
249
|
}
|
|
266
250
|
|
|
267
|
-
// Notify reload
|
|
268
251
|
for (const client of clients) {
|
|
269
252
|
try {
|
|
270
253
|
client.send(JSON.stringify({ type: 'reload', file: filename }));
|