bertui 1.2.8 → 2.0.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.
Files changed (182) hide show
  1. package/README.md +45 -196
  2. package/TYPES_PATCH.md +17 -0
  3. package/bin/bertui.js +2 -7
  4. package/package.json +32 -98
  5. package/src/config.ts +4 -0
  6. package/src/index.ts +32 -0
  7. package/src/optional.ts +49 -0
  8. package/src/router.ts +3 -0
  9. package/tsconfig.json +29 -0
  10. package/LICENSE +0 -21
  11. package/index.js +0 -103
  12. package/src/analyzer/index.js +0 -370
  13. package/src/build/compiler/file-transpiler.js +0 -216
  14. package/src/build/compiler/index.js +0 -31
  15. package/src/build/compiler/route-discoverer.js +0 -49
  16. package/src/build/compiler/router-generator.js +0 -105
  17. package/src/build/css-builder.js +0 -81
  18. package/src/build/generators/html-generator.js +0 -151
  19. package/src/build/generators/robots-generator.js +0 -58
  20. package/src/build/generators/sitemap-generator.js +0 -63
  21. package/src/build/image-optimizer.js +0 -137
  22. package/src/build/processors/asset-processor.js +0 -19
  23. package/src/build/processors/css-builder.js +0 -142
  24. package/src/build/server-island-validator.js +0 -12
  25. package/src/build.js +0 -266
  26. package/src/cli.js +0 -131
  27. package/src/client/compiler.js +0 -522
  28. package/src/client/fast-refresh.js +0 -72
  29. package/src/client/hmr-runtime.js +0 -59
  30. package/src/compiler/index.js +0 -25
  31. package/src/compiler/router-generator-pure.js +0 -104
  32. package/src/compiler/transform.js +0 -149
  33. package/src/config/defaultConfig.js +0 -37
  34. package/src/config/index.js +0 -2
  35. package/src/config/loadConfig.js +0 -64
  36. package/src/config/og-image.png +0 -0
  37. package/src/css/index.js +0 -46
  38. package/src/css/processor.js +0 -172
  39. package/src/dev.js +0 -68
  40. package/src/hydration/index.js +0 -151
  41. package/src/image-optimizer/index.js +0 -103
  42. package/src/images/index.js +0 -102
  43. package/src/images/processor.js +0 -169
  44. package/src/layouts/index.js +0 -165
  45. package/src/loading/index.js +0 -210
  46. package/src/logger/logger.js +0 -320
  47. package/src/logger/notes.md +0 -20
  48. package/src/middleware/index.js +0 -182
  49. package/src/router/Router.js +0 -150
  50. package/src/router/SSRRouter.js +0 -156
  51. package/src/router/index.js +0 -3
  52. package/src/scaffolder/index.js +0 -310
  53. package/src/serve.js +0 -193
  54. package/src/server/dev-handler.js +0 -195
  55. package/src/server/dev-server-utils.js +0 -406
  56. package/src/server/dev-server.js +0 -15
  57. package/src/server/hmr-handler.js +0 -148
  58. package/src/server/index.js +0 -3
  59. package/src/server/notes.md +0 -1
  60. package/src/server/request-handler.js +0 -36
  61. package/src/server-islands/extractor.js +0 -198
  62. package/src/server-islands/index.js +0 -59
  63. package/src/styles/bertui.css +0 -210
  64. package/src/utils/cache.js +0 -297
  65. package/src/utils/env.js +0 -87
  66. package/src/utils/importhow.js +0 -52
  67. package/src/utils/index.js +0 -11
  68. package/src/utils/meta-extractor.js +0 -127
  69. package/types/bin/bertui.d.ts +0 -3
  70. package/types/bin/bertui.d.ts.map +0 -1
  71. package/types/error-overlay.d.ts +0 -2
  72. package/types/error-overlay.d.ts.map +0 -1
  73. package/types/index.d.ts +0 -26
  74. package/types/index.d.ts.map +0 -1
  75. package/types/scripts/fix-wasm-exports.d.ts +0 -2
  76. package/types/scripts/fix-wasm-exports.d.ts.map +0 -1
  77. package/types/src/analyzer/index.d.ts +0 -8
  78. package/types/src/analyzer/index.d.ts.map +0 -1
  79. package/types/src/build/compiler/file-transpiler.d.ts +0 -5
  80. package/types/src/build/compiler/file-transpiler.d.ts.map +0 -1
  81. package/types/src/build/compiler/index.d.ts +0 -12
  82. package/types/src/build/compiler/index.d.ts.map +0 -1
  83. package/types/src/build/compiler/route-discoverer.d.ts +0 -2
  84. package/types/src/build/compiler/route-discoverer.d.ts.map +0 -1
  85. package/types/src/build/compiler/router-generator.d.ts +0 -2
  86. package/types/src/build/compiler/router-generator.d.ts.map +0 -1
  87. package/types/src/build/css-builder.d.ts +0 -18
  88. package/types/src/build/css-builder.d.ts.map +0 -1
  89. package/types/src/build/generators/html-generator.d.ts +0 -2
  90. package/types/src/build/generators/html-generator.d.ts.map +0 -1
  91. package/types/src/build/generators/robots-generator.d.ts +0 -11
  92. package/types/src/build/generators/robots-generator.d.ts.map +0 -1
  93. package/types/src/build/generators/sitemap-generator.d.ts +0 -5
  94. package/types/src/build/generators/sitemap-generator.d.ts.map +0 -1
  95. package/types/src/build/image-optimizer.d.ts +0 -11
  96. package/types/src/build/image-optimizer.d.ts.map +0 -1
  97. package/types/src/build/processors/asset-processor.d.ts +0 -2
  98. package/types/src/build/processors/asset-processor.d.ts.map +0 -1
  99. package/types/src/build/processors/css-builder.d.ts +0 -2
  100. package/types/src/build/processors/css-builder.d.ts.map +0 -1
  101. package/types/src/build/server-island-validator.d.ts +0 -27
  102. package/types/src/build/server-island-validator.d.ts.map +0 -1
  103. package/types/src/build.d.ts +0 -5
  104. package/types/src/build.d.ts.map +0 -1
  105. package/types/src/cli.d.ts +0 -2
  106. package/types/src/cli.d.ts.map +0 -1
  107. package/types/src/client/compiler.d.ts +0 -16
  108. package/types/src/client/compiler.d.ts.map +0 -1
  109. package/types/src/client/fast-refresh.d.ts +0 -3
  110. package/types/src/client/fast-refresh.d.ts.map +0 -1
  111. package/types/src/client/hmr-runtime.d.ts +0 -4
  112. package/types/src/client/hmr-runtime.d.ts.map +0 -1
  113. package/types/src/compiler/index.d.ts +0 -8
  114. package/types/src/compiler/index.d.ts.map +0 -1
  115. package/types/src/compiler/router-generator-pure.d.ts +0 -2
  116. package/types/src/compiler/router-generator-pure.d.ts.map +0 -1
  117. package/types/src/compiler/transform.d.ts +0 -36
  118. package/types/src/compiler/transform.d.ts.map +0 -1
  119. package/types/src/config/defaultConfig.d.ts +0 -26
  120. package/types/src/config/defaultConfig.d.ts.map +0 -1
  121. package/types/src/config/index.d.ts +0 -3
  122. package/types/src/config/index.d.ts.map +0 -1
  123. package/types/src/config/loadConfig.d.ts +0 -2
  124. package/types/src/config/loadConfig.d.ts.map +0 -1
  125. package/types/src/css/index.d.ts +0 -6
  126. package/types/src/css/index.d.ts.map +0 -1
  127. package/types/src/css/processor.d.ts +0 -23
  128. package/types/src/css/processor.d.ts.map +0 -1
  129. package/types/src/dev.d.ts +0 -2
  130. package/types/src/dev.d.ts.map +0 -1
  131. package/types/src/hydration/index.d.ts +0 -33
  132. package/types/src/hydration/index.d.ts.map +0 -1
  133. package/types/src/image-optimizer/index.d.ts +0 -24
  134. package/types/src/image-optimizer/index.d.ts.map +0 -1
  135. package/types/src/images/index.d.ts +0 -12
  136. package/types/src/images/index.d.ts.map +0 -1
  137. package/types/src/images/processor.d.ts +0 -30
  138. package/types/src/images/processor.d.ts.map +0 -1
  139. package/types/src/layouts/index.d.ts +0 -28
  140. package/types/src/layouts/index.d.ts.map +0 -1
  141. package/types/src/loading/index.d.ts +0 -28
  142. package/types/src/loading/index.d.ts.map +0 -1
  143. package/types/src/logger/logger.d.ts +0 -30
  144. package/types/src/logger/logger.d.ts.map +0 -1
  145. package/types/src/middleware/index.d.ts +0 -61
  146. package/types/src/middleware/index.d.ts.map +0 -1
  147. package/types/src/router/Router.d.ts +0 -16
  148. package/types/src/router/Router.d.ts.map +0 -1
  149. package/types/src/router/SSRRouter.d.ts +0 -20
  150. package/types/src/router/SSRRouter.d.ts.map +0 -1
  151. package/types/src/router/index.d.ts +0 -3
  152. package/types/src/router/index.d.ts.map +0 -1
  153. package/types/src/scaffolder/index.d.ts +0 -14
  154. package/types/src/scaffolder/index.d.ts.map +0 -1
  155. package/types/src/serve.d.ts +0 -3
  156. package/types/src/serve.d.ts.map +0 -1
  157. package/types/src/server/dev-handler.d.ts +0 -13
  158. package/types/src/server/dev-handler.d.ts.map +0 -1
  159. package/types/src/server/dev-server-utils.d.ts +0 -6
  160. package/types/src/server/dev-server-utils.d.ts.map +0 -1
  161. package/types/src/server/dev-server.d.ts +0 -18
  162. package/types/src/server/dev-server.d.ts.map +0 -1
  163. package/types/src/server/hmr-handler.d.ts +0 -19
  164. package/types/src/server/hmr-handler.d.ts.map +0 -1
  165. package/types/src/server/index.d.ts +0 -4
  166. package/types/src/server/index.d.ts.map +0 -1
  167. package/types/src/server/request-handler.d.ts +0 -19
  168. package/types/src/server/request-handler.d.ts.map +0 -1
  169. package/types/src/server-islands/extractor.d.ts +0 -16
  170. package/types/src/server-islands/extractor.d.ts.map +0 -1
  171. package/types/src/server-islands/index.d.ts +0 -3
  172. package/types/src/server-islands/index.d.ts.map +0 -1
  173. package/types/src/utils/cache.d.ts +0 -52
  174. package/types/src/utils/cache.d.ts.map +0 -1
  175. package/types/src/utils/env.d.ts +0 -20
  176. package/types/src/utils/env.d.ts.map +0 -1
  177. package/types/src/utils/importhow.d.ts +0 -15
  178. package/types/src/utils/importhow.d.ts.map +0 -1
  179. package/types/src/utils/index.d.ts +0 -3
  180. package/types/src/utils/index.d.ts.map +0 -1
  181. package/types/src/utils/meta-extractor.d.ts +0 -13
  182. package/types/src/utils/meta-extractor.d.ts.map +0 -1
package/index.js DELETED
@@ -1,103 +0,0 @@
1
- // bertui/index.js - v1.2.2
2
-
3
- // Compiler
4
- export { compileProject, compileFile } from './src/client/compiler.js';
5
- export { compileForBuild } from './src/build/compiler/index.js';
6
- export { discoverRoutes } from './src/build/compiler/route-discoverer.js';
7
-
8
- // HMR
9
- export { hmr } from './src/client/hmr-runtime.js';
10
-
11
- // Image Optimizer
12
- export {
13
- optimizeImage,
14
- optimizeImagesBatch,
15
- hasWasm,
16
- version as optimizerVersion,
17
- } from './src/image-optimizer/index.js';
18
-
19
- // Build
20
- export { buildProduction } from './src/build.js';
21
- export { optimizeImages } from './src/build/image-optimizer.js';
22
-
23
- // Router
24
- export { Router, Link, useRouter } from './src/router/index.js';
25
- export { SSRRouter } from './src/router/SSRRouter.js';
26
-
27
- // Config
28
- export { loadConfig, defaultConfig } from './src/config/index.js';
29
-
30
- // Logger
31
- export { default as logger } from './src/logger/logger.js';
32
-
33
- // CLI
34
- export { program } from './src/cli.js';
35
-
36
- // ✅ Middleware system
37
- export {
38
- MiddlewareManager,
39
- loadMiddleware,
40
- runMiddleware,
41
- MiddlewareContext,
42
- } from './src/middleware/index.js';
43
-
44
- // ✅ Layout system
45
- export {
46
- discoverLayouts,
47
- compileLayouts,
48
- matchLayout,
49
- generateLayoutWrapper,
50
- injectLayoutsIntoRouter,
51
- } from './src/layouts/index.js';
52
-
53
- // ✅ Loading states
54
- export {
55
- discoverLoadingComponents,
56
- compileLoadingComponents,
57
- generateLoadingAwareRouter,
58
- getLoadingScript,
59
- DEFAULT_LOADING_HTML,
60
- } from './src/loading/index.js';
61
-
62
- // ✅ Partial hydration
63
- export {
64
- needsHydration,
65
- getInteractiveFeatures,
66
- analyzeRoutes,
67
- generatePartialHydrationCode,
68
- logHydrationReport,
69
- } from './src/hydration/index.js';
70
-
71
- // ✅ Bundle analyzer
72
- export { analyzeBuild } from './src/analyzer/index.js';
73
-
74
- // ✅ CLI scaffolder
75
- export { scaffold, parseCreateArgs } from './src/scaffolder/index.js';
76
-
77
- // Server
78
- export { createDevHandler } from './src/server/dev-handler.js';
79
- export { startDevServer } from './src/server/dev-server.js';
80
-
81
- // CSS
82
- export { minifyCSS, combineCSS } from './src/css/processor.js';
83
-
84
- // Images
85
- export { copyImagesSync, isImageFile } from './src/images/index.js';
86
-
87
- // Server Islands
88
- export {
89
- extractStaticHTML,
90
- isServerIsland,
91
- validateServerIsland,
92
- } from './src/server-islands/index.js';
93
-
94
- // ✅ NEW: importhow — alias/import resolution system
95
- // Bunny and external tools can use these to apply the same alias logic
96
- export {
97
- buildAliasMap,
98
- rewriteAliasImports,
99
- getAliasDirs,
100
- } from './src/utils/importhow.js';
101
-
102
- // Version
103
- export const version = '1.2.2';
@@ -1,370 +0,0 @@
1
- // bertui/src/analyzer/index.js
2
- // Bundle analyzer - reads Bun metafile, generates HTML report
3
-
4
- import { join, relative } from 'path';
5
- import { existsSync } from 'fs';
6
- import logger from '../logger/logger.js';
7
-
8
- /**
9
- * Analyze build output and generate HTML report
10
- */
11
- export async function analyzeBuild(outDir, options = {}) {
12
- const {
13
- open = false,
14
- outputFile = join(outDir, 'bundle-report.html'),
15
- title = 'BertUI Bundle Report',
16
- } = options;
17
-
18
- // Collect all JS files from dist/assets
19
- const assetsDir = join(outDir, 'assets');
20
- if (!existsSync(assetsDir)) {
21
- logger.warn('No assets directory found. Run bun run build first.');
22
- return null;
23
- }
24
-
25
- const files = await collectFiles(assetsDir, outDir);
26
- const report = generateReport(files, title, outDir);
27
-
28
- await Bun.write(outputFile, report);
29
- logger.success(`📊 Bundle report: ${outputFile}`);
30
-
31
- if (open) {
32
- try {
33
- const { exec } = await import('child_process');
34
- const cmd = process.platform === 'darwin' ? 'open' :
35
- process.platform === 'win32' ? 'start' : 'xdg-open';
36
- exec(`${cmd} ${outputFile}`);
37
- } catch (e) {}
38
- }
39
-
40
- return { outputFile, files };
41
- }
42
-
43
- async function collectFiles(assetsDir, outDir) {
44
- const { readdirSync, statSync } = await import('fs');
45
- const files = [];
46
-
47
- function scan(dir) {
48
- const entries = readdirSync(dir, { withFileTypes: true });
49
- for (const entry of entries) {
50
- const fullPath = join(dir, entry.name);
51
- if (entry.isDirectory()) {
52
- scan(fullPath);
53
- } else if (entry.isFile()) {
54
- const stat = statSync(fullPath);
55
- const relPath = relative(outDir, fullPath);
56
- const ext = entry.name.split('.').pop();
57
-
58
- files.push({
59
- name: entry.name,
60
- path: relPath,
61
- size: stat.size,
62
- sizeKB: (stat.size / 1024).toFixed(2),
63
- type: getFileType(ext),
64
- ext,
65
- });
66
- }
67
- }
68
- }
69
-
70
- scan(assetsDir);
71
- files.sort((a, b) => b.size - a.size);
72
- return files;
73
- }
74
-
75
- function getFileType(ext) {
76
- if (['js', 'mjs'].includes(ext)) return 'javascript';
77
- if (ext === 'css') return 'css';
78
- if (['map'].includes(ext)) return 'sourcemap';
79
- if (['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'avif'].includes(ext)) return 'image';
80
- return 'other';
81
- }
82
-
83
- function formatBytes(bytes) {
84
- if (bytes === 0) return '0 B';
85
- const k = 1024;
86
- const sizes = ['B', 'KB', 'MB', 'GB'];
87
- const i = Math.floor(Math.log(bytes) / Math.log(k));
88
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
89
- }
90
-
91
- function getColor(type) {
92
- return {
93
- javascript: '#3b82f6',
94
- css: '#8b5cf6',
95
- sourcemap: '#6b7280',
96
- image: '#f59e0b',
97
- other: '#10b981',
98
- }[type] || '#6b7280';
99
- }
100
-
101
- function generateReport(files, title, outDir) {
102
- const totalSize = files.reduce((s, f) => s + f.size, 0);
103
- const jsFiles = files.filter(f => f.type === 'javascript');
104
- const cssFiles = files.filter(f => f.type === 'css');
105
- const imageFiles = files.filter(f => f.type === 'image');
106
- const otherFiles = files.filter(f => !['javascript','css','image'].includes(f.type));
107
-
108
- const jsTotal = jsFiles.reduce((s, f) => s + f.size, 0);
109
- const cssTotal = cssFiles.reduce((s, f) => s + f.size, 0);
110
- const imageTotal = imageFiles.reduce((s, f) => s + f.size, 0);
111
-
112
- const fileRows = files.map(f => {
113
- const pct = totalSize > 0 ? ((f.size / totalSize) * 100).toFixed(1) : 0;
114
- const barWidth = Math.max(2, Math.round((f.size / (files[0]?.size || 1)) * 200));
115
- const color = getColor(f.type);
116
- return `
117
- <tr>
118
- <td class="file-name">
119
- <span class="dot" style="background:${color}"></span>
120
- ${f.name}
121
- </td>
122
- <td class="file-path">${f.path}</td>
123
- <td class="file-type">${f.type}</td>
124
- <td class="file-size">${formatBytes(f.size)}</td>
125
- <td class="file-pct">
126
- <div class="bar-wrap">
127
- <div class="bar" style="width:${barWidth}px;background:${color}"></div>
128
- <span>${pct}%</span>
129
- </div>
130
- </td>
131
- </tr>`;
132
- }).join('');
133
-
134
- const now = new Date().toLocaleString();
135
-
136
- return `<!DOCTYPE html>
137
- <html lang="en">
138
- <head>
139
- <meta charset="UTF-8">
140
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
141
- <title>${title}</title>
142
- <style>
143
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
144
- body {
145
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
146
- background: #0f172a;
147
- color: #e2e8f0;
148
- min-height: 100vh;
149
- padding: 32px;
150
- }
151
- .header {
152
- display: flex;
153
- align-items: center;
154
- gap: 16px;
155
- margin-bottom: 32px;
156
- }
157
- .header h1 { font-size: 28px; font-weight: 700; color: #f8fafc; }
158
- .header .badge {
159
- background: #10b981;
160
- color: white;
161
- padding: 4px 12px;
162
- border-radius: 20px;
163
- font-size: 12px;
164
- font-weight: 600;
165
- }
166
- .meta { color: #64748b; font-size: 13px; margin-top: 4px; }
167
- .cards {
168
- display: grid;
169
- grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
170
- gap: 16px;
171
- margin-bottom: 32px;
172
- }
173
- .card {
174
- background: #1e293b;
175
- border: 1px solid #334155;
176
- border-radius: 12px;
177
- padding: 20px;
178
- }
179
- .card .label { font-size: 12px; color: #64748b; text-transform: uppercase; letter-spacing: 0.05em; }
180
- .card .value { font-size: 28px; font-weight: 700; margin-top: 4px; }
181
- .card .sub { font-size: 12px; color: #64748b; margin-top: 2px; }
182
- .section {
183
- background: #1e293b;
184
- border: 1px solid #334155;
185
- border-radius: 12px;
186
- overflow: hidden;
187
- margin-bottom: 24px;
188
- }
189
- .section-header {
190
- padding: 16px 24px;
191
- border-bottom: 1px solid #334155;
192
- display: flex;
193
- align-items: center;
194
- gap: 8px;
195
- }
196
- .section-header h2 { font-size: 15px; font-weight: 600; color: #f1f5f9; }
197
- .section-header .count {
198
- background: #334155;
199
- color: #94a3b8;
200
- padding: 2px 8px;
201
- border-radius: 10px;
202
- font-size: 12px;
203
- }
204
- table { width: 100%; border-collapse: collapse; }
205
- th {
206
- text-align: left;
207
- padding: 12px 24px;
208
- font-size: 11px;
209
- text-transform: uppercase;
210
- letter-spacing: 0.05em;
211
- color: #64748b;
212
- border-bottom: 1px solid #334155;
213
- }
214
- td {
215
- padding: 12px 24px;
216
- font-size: 13px;
217
- border-bottom: 1px solid #1e293b;
218
- vertical-align: middle;
219
- }
220
- tr:last-child td { border-bottom: none; }
221
- tr:hover td { background: #263348; }
222
- .file-name { font-weight: 600; color: #f1f5f9; white-space: nowrap; }
223
- .file-path { color: #64748b; font-size: 12px; font-family: monospace; }
224
- .file-type { color: #94a3b8; font-size: 12px; text-transform: uppercase; }
225
- .file-size { font-weight: 600; color: #10b981; white-space: nowrap; }
226
- .dot {
227
- display: inline-block;
228
- width: 8px;
229
- height: 8px;
230
- border-radius: 50%;
231
- margin-right: 8px;
232
- vertical-align: middle;
233
- }
234
- .bar-wrap {
235
- display: flex;
236
- align-items: center;
237
- gap: 8px;
238
- }
239
- .bar {
240
- height: 6px;
241
- border-radius: 3px;
242
- min-width: 2px;
243
- }
244
- .bar-wrap span { color: #64748b; font-size: 12px; white-space: nowrap; }
245
- .filter-bar {
246
- display: flex;
247
- gap: 8px;
248
- padding: 16px 24px;
249
- border-bottom: 1px solid #334155;
250
- flex-wrap: wrap;
251
- }
252
- .filter-btn {
253
- background: #334155;
254
- color: #94a3b8;
255
- border: none;
256
- padding: 6px 14px;
257
- border-radius: 8px;
258
- font-size: 12px;
259
- cursor: pointer;
260
- transition: all 0.15s;
261
- }
262
- .filter-btn:hover, .filter-btn.active {
263
- background: #10b981;
264
- color: white;
265
- }
266
- input[type="search"] {
267
- background: #334155;
268
- border: 1px solid #475569;
269
- color: #f1f5f9;
270
- padding: 6px 14px;
271
- border-radius: 8px;
272
- font-size: 13px;
273
- outline: none;
274
- width: 240px;
275
- }
276
- input[type="search"]::placeholder { color: #64748b; }
277
- input[type="search"]:focus { border-color: #10b981; }
278
- .footer { color: #64748b; font-size: 12px; text-align: center; margin-top: 24px; }
279
- </style>
280
- </head>
281
- <body>
282
- <div class="header">
283
- <div>
284
- <div style="display:flex;align-items:center;gap:12px">
285
- <h1>📊 ${title}</h1>
286
- <span class="badge">⚡ BertUI</span>
287
- </div>
288
- <p class="meta">Generated ${now} · ${outDir}</p>
289
- </div>
290
- </div>
291
-
292
- <div class="cards">
293
- <div class="card">
294
- <div class="label">Total Size</div>
295
- <div class="value" style="color:#10b981">${formatBytes(totalSize)}</div>
296
- <div class="sub">${files.length} files</div>
297
- </div>
298
- <div class="card">
299
- <div class="label">JavaScript</div>
300
- <div class="value" style="color:#3b82f6">${formatBytes(jsTotal)}</div>
301
- <div class="sub">${jsFiles.length} files</div>
302
- </div>
303
- <div class="card">
304
- <div class="label">CSS</div>
305
- <div class="value" style="color:#8b5cf6">${formatBytes(cssTotal)}</div>
306
- <div class="sub">${cssFiles.length} files</div>
307
- </div>
308
- <div class="card">
309
- <div class="label">Images</div>
310
- <div class="value" style="color:#f59e0b">${formatBytes(imageTotal)}</div>
311
- <div class="sub">${imageFiles.length} files</div>
312
- </div>
313
- </div>
314
-
315
- <div class="section">
316
- <div class="section-header">
317
- <h2>All Files</h2>
318
- <span class="count">${files.length}</span>
319
- </div>
320
- <div class="filter-bar">
321
- <button class="filter-btn active" onclick="filterFiles('all', this)">All</button>
322
- <button class="filter-btn" onclick="filterFiles('javascript', this)">JS</button>
323
- <button class="filter-btn" onclick="filterFiles('css', this)">CSS</button>
324
- <button class="filter-btn" onclick="filterFiles('image', this)">Images</button>
325
- <input type="search" id="search" placeholder="Search files..." oninput="searchFiles(this.value)">
326
- </div>
327
- <table id="files-table">
328
- <thead>
329
- <tr>
330
- <th>File</th>
331
- <th>Path</th>
332
- <th>Type</th>
333
- <th>Size</th>
334
- <th>% of Total</th>
335
- </tr>
336
- </thead>
337
- <tbody>${fileRows}</tbody>
338
- </table>
339
- </div>
340
-
341
- <p class="footer">Built with BertUI · bundle-report.html</p>
342
-
343
- <script>
344
- let currentFilter = 'all';
345
- const rows = Array.from(document.querySelectorAll('#files-table tbody tr'));
346
-
347
- function filterFiles(type, btn) {
348
- currentFilter = type;
349
- document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
350
- btn.classList.add('active');
351
- applyFilters();
352
- }
353
-
354
- function searchFiles(query) {
355
- applyFilters(query);
356
- }
357
-
358
- function applyFilters(query = document.getElementById('search').value) {
359
- rows.forEach(row => {
360
- const typeCell = row.cells[2].textContent.trim();
361
- const nameCell = row.cells[0].textContent.trim();
362
- const matchesType = currentFilter === 'all' || typeCell === currentFilter;
363
- const matchesSearch = !query || nameCell.toLowerCase().includes(query.toLowerCase());
364
- row.style.display = matchesType && matchesSearch ? '' : 'none';
365
- });
366
- }
367
- </script>
368
- </body>
369
- </html>`;
370
- }
@@ -1,216 +0,0 @@
1
- // bertui/src/build/compiler/file-transpiler.js
2
- import { join, relative, dirname, extname } from 'path';
3
- import { readdirSync, statSync, mkdirSync, writeFileSync, existsSync } from 'fs';
4
- import logger from '../../logger/logger.js';
5
- import { replaceEnvInCode } from '../../utils/env.js';
6
- import { buildAliasMap, rewriteAliasImports } from '../../utils/importhow.js';
7
-
8
- /**
9
- * Compile src/ + alias dirs into buildDir.
10
- */
11
- export async function compileBuildDirectory(srcDir, buildDir, root, envVars, importhow = {}) {
12
- writeFileSync(
13
- join(buildDir, 'bunfig.toml'),
14
- `[build]\njsx = "react"\njsxFactory = "React.createElement"\njsxFragment = "React.Fragment"`.trim()
15
- );
16
- logger.info('Created bunfig.toml for classic JSX');
17
-
18
- // Build mode: aliases resolve to buildDir/<alias> so relative paths inside dist/ are correct
19
- const aliasMap = buildAliasMap(importhow, root, buildDir);
20
-
21
- // Compile src/
22
- await _compileDir(srcDir, buildDir, root, envVars, aliasMap);
23
-
24
- // Compile each alias source dir → buildDir/<alias>
25
- for (const [alias, relPath] of Object.entries(importhow)) {
26
- const absAliasDir = join(root, relPath);
27
-
28
- if (!existsSync(absAliasDir)) {
29
- logger.warn(`⚠️ importhow alias "${alias}" points to missing dir: ${absAliasDir}`);
30
- continue;
31
- }
32
-
33
- const aliasOutDir = join(buildDir, alias);
34
- mkdirSync(aliasOutDir, { recursive: true });
35
-
36
- logger.info(`📦 Compiling alias dir [${alias}] → ${aliasOutDir}`);
37
- await _compileDir(absAliasDir, aliasOutDir, root, envVars, aliasMap);
38
- }
39
- }
40
-
41
- // ─────────────────────────────────────────────────────────────────────────────
42
-
43
- async function _compileDir(srcDir, buildDir, root, envVars, aliasMap) {
44
- const files = readdirSync(srcDir);
45
- const filesToCompile = [];
46
-
47
- for (const file of files) {
48
- const srcPath = join(srcDir, file);
49
- const stat = statSync(srcPath);
50
-
51
- if (stat.isDirectory()) {
52
- if (file === 'api') { logger.debug('⏭️ Skipping api/'); continue; }
53
- const subBuildDir = join(buildDir, file);
54
- mkdirSync(subBuildDir, { recursive: true });
55
- await _compileDir(srcPath, subBuildDir, root, envVars, aliasMap);
56
- } else {
57
- const ext = extname(file);
58
- if (ext === '.css') continue;
59
- if (['.jsx', '.tsx', '.ts'].includes(ext)) {
60
- filesToCompile.push({ path: srcPath, dir: buildDir, name: file, type: 'tsx' });
61
- } else if (ext === '.js') {
62
- filesToCompile.push({ path: srcPath, dir: buildDir, name: file, type: 'js' });
63
- }
64
- }
65
- }
66
-
67
- if (filesToCompile.length === 0) return;
68
-
69
- logger.info(`📦 Compiling ${filesToCompile.length} files in ${srcDir.split('/').slice(-2).join('/')}...`);
70
-
71
- for (let i = 0; i < filesToCompile.length; i++) {
72
- const file = filesToCompile[i];
73
- try {
74
- if (file.type === 'tsx') {
75
- await _compileTSXFile(file.path, file.dir, file.name, root, envVars, buildDir, aliasMap);
76
- } else {
77
- await _compileJSFile(file.path, file.dir, file.name, root, envVars, aliasMap);
78
- }
79
-
80
- if ((i + 1) % 10 === 0 || i === filesToCompile.length - 1) {
81
- const pct = (((i + 1) / filesToCompile.length) * 100).toFixed(0);
82
- logger.info(` Progress: ${i + 1}/${filesToCompile.length} (${pct}%)`);
83
- }
84
- } catch (error) {
85
- logger.error(`Failed to compile ${file.name}: ${error.message}`);
86
- }
87
- }
88
-
89
- logger.success(`✅ Compiled ${filesToCompile.length} files`);
90
- }
91
-
92
- // ─────────────────────────────────────────────────────────────────────────────
93
- // _rewriteNodeModuleImports — intentionally a no-op.
94
- //
95
- // Previously this rewrote bare specifiers like 'react' → '/node_modules/react/index.js'
96
- // which caused "Could not resolve" errors during Bun.build because:
97
- // 1. 'react' is marked `external` in Bun.build and expected as a bare specifier.
98
- // 2. Other npm packages are better handled by Bun.build natively (tree-shaken + minified).
99
- //
100
- // Leaving bare specifiers untouched lets Bun.build do the right thing for both cases.
101
- // ─────────────────────────────────────────────────────────────────────────────
102
- function _rewriteNodeModuleImports(code) {
103
- return code;
104
- }
105
-
106
- async function _compileTSXFile(srcPath, buildDir, filename, root, envVars, configDir, aliasMap) {
107
- const ext = extname(filename);
108
-
109
- try {
110
- let code = await Bun.file(srcPath).text();
111
- code = _removeCSSImports(code);
112
- code = replaceEnvInCode(code, envVars);
113
-
114
- const outFilename = filename.replace(/\.(jsx|tsx|ts)$/, '.js');
115
- const outPath = join(buildDir, outFilename);
116
-
117
- code = _fixBuildImports(code, srcPath, outPath, root);
118
-
119
- if (!code.includes('import React')) {
120
- code = `import React from 'react';\n${code}`;
121
- }
122
-
123
- const transpiler = new Bun.Transpiler({
124
- loader: ext === '.tsx' ? 'tsx' : ext === '.ts' ? 'ts' : 'jsx',
125
- target: 'browser',
126
- define: { 'process.env.NODE_ENV': '"production"' },
127
- tsconfig: {
128
- compilerOptions: {
129
- jsx: 'react',
130
- jsxFactory: 'React.createElement',
131
- jsxFragmentFactory: 'React.Fragment',
132
- target: 'ES2020'
133
- }
134
- }
135
- });
136
-
137
- let compiled = await transpiler.transform(code);
138
-
139
- if (compiled.includes('jsxDEV')) {
140
- logger.warn(`⚠️ Dev JSX in ${filename}, fixing...`);
141
- compiled = compiled.replace(/jsxDEV/g, 'jsx');
142
- }
143
-
144
- compiled = _fixRelativeImports(compiled);
145
-
146
- // ✅ Alias rewrite AFTER transpile — Bun won't undo it
147
- compiled = rewriteAliasImports(compiled, outPath, aliasMap);
148
-
149
- // NOTE: _rewriteNodeModuleImports is intentionally a no-op — bare specifiers
150
- // are left for Bun.build to handle natively (tree-shaking + bundling).
151
- compiled = _rewriteNodeModuleImports(compiled);
152
-
153
- await Bun.write(outPath, compiled);
154
-
155
- } catch (error) {
156
- logger.error(`Failed to compile ${filename}: ${error.message}`);
157
- throw error;
158
- }
159
- }
160
-
161
- async function _compileJSFile(srcPath, buildDir, filename, root, envVars, aliasMap) {
162
- const outPath = join(buildDir, filename);
163
- let code = await Bun.file(srcPath).text();
164
- code = _removeCSSImports(code);
165
- code = replaceEnvInCode(code, envVars);
166
- code = _fixBuildImports(code, srcPath, outPath, root);
167
-
168
- // JS files don't go through Bun.Transpiler so rewrite is safe here
169
- code = rewriteAliasImports(code, outPath, aliasMap);
170
-
171
- // NOTE: _rewriteNodeModuleImports is intentionally a no-op — see above.
172
- code = _rewriteNodeModuleImports(code);
173
-
174
- if (_usesJSX(code) && !code.includes('import React')) {
175
- code = `import React from 'react';\n${code}`;
176
- }
177
-
178
- await Bun.write(outPath, code);
179
- }
180
-
181
- // ─────────────────────────────────────────────────────────────────────────────
182
-
183
- function _usesJSX(code) {
184
- return code.includes('React.createElement') ||
185
- code.includes('React.Fragment') ||
186
- /<[A-Z]/.test(code);
187
- }
188
-
189
- function _removeCSSImports(code) {
190
- // Replace CSS module imports with a Proxy so styles.foo = 'foo' at runtime
191
- code = code.replace(
192
- /import\s+(\w+)\s+from\s+['"][^'"]*\.module\.css['"];?\s*/g,
193
- (_, varName) => `const ${varName} = new Proxy({}, { get: (_, k) => k });\n`
194
- );
195
- // Strip plain CSS imports entirely
196
- code = code.replace(/import\s+['"][^'"]*\.css['"];?\s*/g, '');
197
- code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
198
- return code;
199
- }
200
- function _fixBuildImports(code, srcPath, outPath, root) {
201
- const buildDir = join(root, '.bertuibuild');
202
- const routerPath = join(buildDir, 'router.js');
203
- const rel = relative(dirname(outPath), routerPath).replace(/\\/g, '/');
204
- const routerImport = rel.startsWith('.') ? rel : './' + rel;
205
- code = code.replace(/from\s+['"]bertui\/router['"]/g, `from '${routerImport}'`);
206
- return code;
207
- }
208
-
209
- function _fixRelativeImports(code) {
210
- const importRegex = /from\s+['"](\.\.[\\/]|\.\/)(?:[^'"]+?)(?<!\.js|\.jsx|\.ts|\.tsx|\.json)['"]/g;
211
- code = code.replace(importRegex, (match) => {
212
- if (/\.\w+['"]/.test(match)) return match;
213
- return match.replace(/['"]$/, '.js"');
214
- });
215
- return code;
216
- }