bertui 0.2.1 → 0.2.3
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/package.json +7 -6
- package/src/client/compiler.js +34 -36
- package/src/router/Router.js +4 -1
- package/src/server/dev-server.js +3 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bertui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Lightning-fast React dev server powered by Bun and Elysia",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
"bertui": "./bin/bertui.js"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
".": "./index.js",
|
|
12
|
+
"./styles": "./src/styles/bertui.css",
|
|
13
|
+
"./logger": "./src/logger/logger.js",
|
|
14
|
+
"./router": "./src/router/Router.jsx"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"bin",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"build-tool",
|
|
35
35
|
"bundler",
|
|
36
36
|
"fast",
|
|
37
|
-
"hmr"
|
|
37
|
+
"hmr",
|
|
38
|
+
"file-based-routing"
|
|
38
39
|
],
|
|
39
40
|
"author": "Pease Ernest",
|
|
40
41
|
"license": "MIT",
|
package/src/client/compiler.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// src/client/compiler.js
|
|
2
1
|
import { existsSync, mkdirSync, readdirSync, statSync } from 'fs';
|
|
3
2
|
import { join, extname, relative } from 'path';
|
|
4
3
|
import logger from '../logger/logger.js';
|
|
@@ -112,9 +111,7 @@ async function generateRouter(routes, outDir, root) {
|
|
|
112
111
|
return ` { path: '${route.route}', component: ${componentName}, type: '${route.type}' }`;
|
|
113
112
|
}).join(',\n');
|
|
114
113
|
|
|
115
|
-
|
|
116
|
-
const routerComponentCode = `
|
|
117
|
-
import { useState, useEffect, createContext, useContext } from 'react';
|
|
114
|
+
const routerComponentCode = `import { useState, useEffect, createContext, useContext, createElement } from 'react';
|
|
118
115
|
|
|
119
116
|
const RouterContext = createContext(null);
|
|
120
117
|
|
|
@@ -139,7 +136,7 @@ export function Router({ routes }) {
|
|
|
139
136
|
|
|
140
137
|
window.addEventListener('popstate', handlePopState);
|
|
141
138
|
return () => window.removeEventListener('popstate', handlePopState);
|
|
142
|
-
}, []);
|
|
139
|
+
}, [routes]);
|
|
143
140
|
|
|
144
141
|
function matchAndSetRoute(pathname) {
|
|
145
142
|
for (const route of routes) {
|
|
@@ -188,10 +185,10 @@ export function Router({ routes }) {
|
|
|
188
185
|
|
|
189
186
|
const Component = currentRoute?.component;
|
|
190
187
|
|
|
191
|
-
return (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
188
|
+
return createElement(
|
|
189
|
+
RouterContext.Provider,
|
|
190
|
+
{ value: routerValue },
|
|
191
|
+
Component ? createElement(Component, { params }) : createElement(NotFound, null)
|
|
195
192
|
);
|
|
196
193
|
}
|
|
197
194
|
|
|
@@ -203,29 +200,28 @@ export function Link({ to, children, ...props }) {
|
|
|
203
200
|
navigate(to);
|
|
204
201
|
}
|
|
205
202
|
|
|
206
|
-
return (
|
|
207
|
-
<a href={to} onClick={handleClick} {...props}>
|
|
208
|
-
{children}
|
|
209
|
-
</a>
|
|
210
|
-
);
|
|
203
|
+
return createElement('a', { href: to, onClick: handleClick, ...props }, children);
|
|
211
204
|
}
|
|
212
205
|
|
|
213
206
|
function NotFound() {
|
|
214
|
-
return (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
207
|
+
return createElement(
|
|
208
|
+
'div',
|
|
209
|
+
{
|
|
210
|
+
style: {
|
|
211
|
+
display: 'flex',
|
|
212
|
+
flexDirection: 'column',
|
|
213
|
+
alignItems: 'center',
|
|
214
|
+
justifyContent: 'center',
|
|
215
|
+
minHeight: '100vh',
|
|
216
|
+
fontFamily: 'system-ui'
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
createElement('h1', { style: { fontSize: '6rem', margin: 0 } }, '404'),
|
|
220
|
+
createElement('p', { style: { fontSize: '1.5rem', color: '#666' } }, 'Page not found'),
|
|
221
|
+
createElement('a', {
|
|
222
|
+
href: '/',
|
|
223
|
+
style: { color: '#10b981', textDecoration: 'none', fontSize: '1.2rem' }
|
|
224
|
+
}, 'Go home')
|
|
229
225
|
);
|
|
230
226
|
}
|
|
231
227
|
|
|
@@ -266,7 +262,6 @@ async function compileDirectory(srcDir, outDir, root) {
|
|
|
266
262
|
const outPath = join(outDir, file);
|
|
267
263
|
let code = await Bun.file(srcPath).text();
|
|
268
264
|
|
|
269
|
-
// Fix imports in .js files too
|
|
270
265
|
code = fixImports(code);
|
|
271
266
|
|
|
272
267
|
await Bun.write(outPath, code);
|
|
@@ -289,13 +284,19 @@ async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
|
289
284
|
try {
|
|
290
285
|
let code = await Bun.file(srcPath).text();
|
|
291
286
|
|
|
292
|
-
// Fix imports BEFORE transpiling
|
|
293
287
|
code = fixImports(code);
|
|
294
288
|
|
|
295
|
-
const transpiler = new Bun.Transpiler({
|
|
289
|
+
const transpiler = new Bun.Transpiler({
|
|
290
|
+
loader,
|
|
291
|
+
tsconfig: {
|
|
292
|
+
compilerOptions: {
|
|
293
|
+
jsx: 'react-jsx',
|
|
294
|
+
jsxImportSource: 'react'
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
});
|
|
296
298
|
let compiled = await transpiler.transform(code);
|
|
297
299
|
|
|
298
|
-
// Add .js extensions to relative imports
|
|
299
300
|
compiled = fixRelativeImports(compiled);
|
|
300
301
|
|
|
301
302
|
const outFilename = filename.replace(/\.(jsx|tsx|ts)$/, '.js');
|
|
@@ -310,16 +311,13 @@ async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
|
310
311
|
}
|
|
311
312
|
|
|
312
313
|
function fixImports(code) {
|
|
313
|
-
// Remove bertui/styles imports
|
|
314
314
|
code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
|
|
315
315
|
|
|
316
|
-
// Replace bertui/router with /compiled/router.js
|
|
317
316
|
code = code.replace(
|
|
318
317
|
/from\s+['"]bertui\/router['"]/g,
|
|
319
318
|
"from '/compiled/router.js'"
|
|
320
319
|
);
|
|
321
320
|
|
|
322
|
-
// Fix ../.bertui/compiled paths to /compiled
|
|
323
321
|
code = code.replace(
|
|
324
322
|
/from\s+['"]\.\.\/\.bertui\/compiled\/([^'"]+)['"]/g,
|
|
325
323
|
"from '/compiled/$1'"
|
package/src/router/Router.js
CHANGED
|
@@ -23,9 +23,10 @@ export function Router({ routes }) {
|
|
|
23
23
|
|
|
24
24
|
window.addEventListener('popstate', handlePopState);
|
|
25
25
|
return () => window.removeEventListener('popstate', handlePopState);
|
|
26
|
-
}, []);
|
|
26
|
+
}, [routes]);
|
|
27
27
|
|
|
28
28
|
function matchAndSetRoute(pathname) {
|
|
29
|
+
// Try static routes first
|
|
29
30
|
for (const route of routes) {
|
|
30
31
|
if (route.type === 'static' && route.path === pathname) {
|
|
31
32
|
setCurrentRoute(route);
|
|
@@ -34,6 +35,7 @@ export function Router({ routes }) {
|
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
// Try dynamic routes
|
|
37
39
|
for (const route of routes) {
|
|
38
40
|
if (route.type === 'dynamic') {
|
|
39
41
|
const pattern = route.path.replace(/\[([^\]]+)\]/g, '([^/]+)');
|
|
@@ -54,6 +56,7 @@ export function Router({ routes }) {
|
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
// No match found
|
|
57
60
|
setCurrentRoute(null);
|
|
58
61
|
setParams({});
|
|
59
62
|
}
|
package/src/server/dev-server.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// src/server/dev-server.js
|
|
2
1
|
import { Elysia } from 'elysia';
|
|
3
2
|
import { watch } from 'fs';
|
|
4
3
|
import { join, extname } from 'path';
|
|
@@ -17,7 +16,7 @@ export async function startDevServer(options = {}) {
|
|
|
17
16
|
const routerPath = join(compiledDir, 'router.js');
|
|
18
17
|
if (existsSync(routerPath)) {
|
|
19
18
|
hasRouter = true;
|
|
20
|
-
logger.info('
|
|
19
|
+
logger.info('File-based routing enabled');
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
const app = new Elysia()
|
|
@@ -158,7 +157,6 @@ function serveHTML(root, hasRouter) {
|
|
|
158
157
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
159
158
|
<title>BertUI App - Dev</title>
|
|
160
159
|
|
|
161
|
-
<!-- Import Map for React and dependencies -->
|
|
162
160
|
<script type="importmap">
|
|
163
161
|
{
|
|
164
162
|
"imports": {
|
|
@@ -171,7 +169,6 @@ function serveHTML(root, hasRouter) {
|
|
|
171
169
|
</script>
|
|
172
170
|
|
|
173
171
|
<style>
|
|
174
|
-
/* Inline basic styles since we're skipping CSS for now */
|
|
175
172
|
* {
|
|
176
173
|
margin: 0;
|
|
177
174
|
padding: 0;
|
|
@@ -186,10 +183,9 @@ function serveHTML(root, hasRouter) {
|
|
|
186
183
|
<div id="root"></div>
|
|
187
184
|
<script type="module" src="/hmr-client.js"></script>
|
|
188
185
|
${hasRouter
|
|
189
|
-
? '<script type="module" src="/compiled/
|
|
190
|
-
: ''
|
|
186
|
+
? '<script type="module" src="/compiled/main.js"></script>'
|
|
187
|
+
: '<script type="module" src="/compiled/main.js"></script>'
|
|
191
188
|
}
|
|
192
|
-
<script type="module" src="/compiled/main.js"></script>
|
|
193
189
|
</body>
|
|
194
190
|
</html>`;
|
|
195
191
|
|