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 CHANGED
@@ -18,7 +18,7 @@ bun add bertui react react-dom
18
18
  ## Usage
19
19
  ```javascript
20
20
  // src/main.jsx
21
- import 'bertui/styles';
21
+ ;
22
22
  import React from 'react';
23
23
  import ReactDOM from 'react-dom/client';
24
24
 
package/index.js CHANGED
@@ -32,5 +32,5 @@ export default {
32
32
  buildCSS,
33
33
  copyCSS,
34
34
  program,
35
- version: "0.1.7"
35
+ version: "0.1.8"
36
36
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bertui",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Lightning-fast React dev server powered by Bun and Elysia",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -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
- const importPath = `./pages/${route.file.replace(/\\/g, '/')}`;
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
- // CRITICAL FIX: Resolve bare module specifiers
199
- code = resolveBareImports(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
  }
@@ -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
- // CRITICAL FIX: Serve .js files with correct MIME type
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
- // CRITICAL FIX: Always serve .js files with JavaScript MIME type
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
- <link rel="stylesheet" href="/styles/bertui.css">
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 }));