bertui 1.2.9 → 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 (183) hide show
  1. package/README.md +44 -242
  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 -263
  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 -67
  25. package/src/build/ssr-renderer.js +0 -64
  26. package/src/build.js +0 -273
  27. package/src/cli.js +0 -131
  28. package/src/client/compiler.js +0 -522
  29. package/src/client/fast-refresh.js +0 -72
  30. package/src/client/hmr-runtime.js +0 -59
  31. package/src/compiler/index.js +0 -25
  32. package/src/compiler/router-generator-pure.js +0 -104
  33. package/src/compiler/transform.js +0 -149
  34. package/src/config/defaultConfig.js +0 -37
  35. package/src/config/index.js +0 -2
  36. package/src/config/loadConfig.js +0 -64
  37. package/src/config/og-image.png +0 -0
  38. package/src/css/index.js +0 -46
  39. package/src/css/processor.js +0 -172
  40. package/src/dev.js +0 -68
  41. package/src/hydration/index.js +0 -151
  42. package/src/image-optimizer/index.js +0 -103
  43. package/src/images/index.js +0 -102
  44. package/src/images/processor.js +0 -169
  45. package/src/layouts/index.js +0 -165
  46. package/src/loading/index.js +0 -210
  47. package/src/logger/logger.js +0 -320
  48. package/src/logger/notes.md +0 -20
  49. package/src/middleware/index.js +0 -182
  50. package/src/router/Router.js +0 -150
  51. package/src/router/SSRRouter.js +0 -156
  52. package/src/router/index.js +0 -3
  53. package/src/scaffolder/index.js +0 -310
  54. package/src/serve.js +0 -193
  55. package/src/server/dev-handler.js +0 -195
  56. package/src/server/dev-server-utils.js +0 -406
  57. package/src/server/dev-server.js +0 -15
  58. package/src/server/hmr-handler.js +0 -148
  59. package/src/server/index.js +0 -3
  60. package/src/server/notes.md +0 -1
  61. package/src/server/request-handler.js +0 -36
  62. package/src/server-islands/extractor.js +0 -198
  63. package/src/server-islands/index.js +0 -59
  64. package/src/styles/bertui.css +0 -210
  65. package/src/utils/cache.js +0 -297
  66. package/src/utils/env.js +0 -87
  67. package/src/utils/importhow.js +0 -52
  68. package/src/utils/index.js +0 -11
  69. package/src/utils/meta-extractor.js +0 -127
  70. package/types/bin/bertui.d.ts +0 -3
  71. package/types/bin/bertui.d.ts.map +0 -1
  72. package/types/error-overlay.d.ts +0 -2
  73. package/types/error-overlay.d.ts.map +0 -1
  74. package/types/index.d.ts +0 -26
  75. package/types/index.d.ts.map +0 -1
  76. package/types/scripts/fix-wasm-exports.d.ts +0 -2
  77. package/types/scripts/fix-wasm-exports.d.ts.map +0 -1
  78. package/types/src/analyzer/index.d.ts +0 -8
  79. package/types/src/analyzer/index.d.ts.map +0 -1
  80. package/types/src/build/compiler/file-transpiler.d.ts +0 -5
  81. package/types/src/build/compiler/file-transpiler.d.ts.map +0 -1
  82. package/types/src/build/compiler/index.d.ts +0 -12
  83. package/types/src/build/compiler/index.d.ts.map +0 -1
  84. package/types/src/build/compiler/route-discoverer.d.ts +0 -2
  85. package/types/src/build/compiler/route-discoverer.d.ts.map +0 -1
  86. package/types/src/build/compiler/router-generator.d.ts +0 -2
  87. package/types/src/build/compiler/router-generator.d.ts.map +0 -1
  88. package/types/src/build/css-builder.d.ts +0 -18
  89. package/types/src/build/css-builder.d.ts.map +0 -1
  90. package/types/src/build/generators/html-generator.d.ts +0 -2
  91. package/types/src/build/generators/html-generator.d.ts.map +0 -1
  92. package/types/src/build/generators/robots-generator.d.ts +0 -11
  93. package/types/src/build/generators/robots-generator.d.ts.map +0 -1
  94. package/types/src/build/generators/sitemap-generator.d.ts +0 -5
  95. package/types/src/build/generators/sitemap-generator.d.ts.map +0 -1
  96. package/types/src/build/image-optimizer.d.ts +0 -11
  97. package/types/src/build/image-optimizer.d.ts.map +0 -1
  98. package/types/src/build/processors/asset-processor.d.ts +0 -2
  99. package/types/src/build/processors/asset-processor.d.ts.map +0 -1
  100. package/types/src/build/processors/css-builder.d.ts +0 -2
  101. package/types/src/build/processors/css-builder.d.ts.map +0 -1
  102. package/types/src/build/server-island-validator.d.ts +0 -27
  103. package/types/src/build/server-island-validator.d.ts.map +0 -1
  104. package/types/src/build.d.ts +0 -5
  105. package/types/src/build.d.ts.map +0 -1
  106. package/types/src/cli.d.ts +0 -2
  107. package/types/src/cli.d.ts.map +0 -1
  108. package/types/src/client/compiler.d.ts +0 -16
  109. package/types/src/client/compiler.d.ts.map +0 -1
  110. package/types/src/client/fast-refresh.d.ts +0 -3
  111. package/types/src/client/fast-refresh.d.ts.map +0 -1
  112. package/types/src/client/hmr-runtime.d.ts +0 -4
  113. package/types/src/client/hmr-runtime.d.ts.map +0 -1
  114. package/types/src/compiler/index.d.ts +0 -8
  115. package/types/src/compiler/index.d.ts.map +0 -1
  116. package/types/src/compiler/router-generator-pure.d.ts +0 -2
  117. package/types/src/compiler/router-generator-pure.d.ts.map +0 -1
  118. package/types/src/compiler/transform.d.ts +0 -36
  119. package/types/src/compiler/transform.d.ts.map +0 -1
  120. package/types/src/config/defaultConfig.d.ts +0 -26
  121. package/types/src/config/defaultConfig.d.ts.map +0 -1
  122. package/types/src/config/index.d.ts +0 -3
  123. package/types/src/config/index.d.ts.map +0 -1
  124. package/types/src/config/loadConfig.d.ts +0 -2
  125. package/types/src/config/loadConfig.d.ts.map +0 -1
  126. package/types/src/css/index.d.ts +0 -6
  127. package/types/src/css/index.d.ts.map +0 -1
  128. package/types/src/css/processor.d.ts +0 -23
  129. package/types/src/css/processor.d.ts.map +0 -1
  130. package/types/src/dev.d.ts +0 -2
  131. package/types/src/dev.d.ts.map +0 -1
  132. package/types/src/hydration/index.d.ts +0 -33
  133. package/types/src/hydration/index.d.ts.map +0 -1
  134. package/types/src/image-optimizer/index.d.ts +0 -24
  135. package/types/src/image-optimizer/index.d.ts.map +0 -1
  136. package/types/src/images/index.d.ts +0 -12
  137. package/types/src/images/index.d.ts.map +0 -1
  138. package/types/src/images/processor.d.ts +0 -30
  139. package/types/src/images/processor.d.ts.map +0 -1
  140. package/types/src/layouts/index.d.ts +0 -28
  141. package/types/src/layouts/index.d.ts.map +0 -1
  142. package/types/src/loading/index.d.ts +0 -28
  143. package/types/src/loading/index.d.ts.map +0 -1
  144. package/types/src/logger/logger.d.ts +0 -30
  145. package/types/src/logger/logger.d.ts.map +0 -1
  146. package/types/src/middleware/index.d.ts +0 -61
  147. package/types/src/middleware/index.d.ts.map +0 -1
  148. package/types/src/router/Router.d.ts +0 -16
  149. package/types/src/router/Router.d.ts.map +0 -1
  150. package/types/src/router/SSRRouter.d.ts +0 -20
  151. package/types/src/router/SSRRouter.d.ts.map +0 -1
  152. package/types/src/router/index.d.ts +0 -3
  153. package/types/src/router/index.d.ts.map +0 -1
  154. package/types/src/scaffolder/index.d.ts +0 -14
  155. package/types/src/scaffolder/index.d.ts.map +0 -1
  156. package/types/src/serve.d.ts +0 -3
  157. package/types/src/serve.d.ts.map +0 -1
  158. package/types/src/server/dev-handler.d.ts +0 -13
  159. package/types/src/server/dev-handler.d.ts.map +0 -1
  160. package/types/src/server/dev-server-utils.d.ts +0 -6
  161. package/types/src/server/dev-server-utils.d.ts.map +0 -1
  162. package/types/src/server/dev-server.d.ts +0 -18
  163. package/types/src/server/dev-server.d.ts.map +0 -1
  164. package/types/src/server/hmr-handler.d.ts +0 -19
  165. package/types/src/server/hmr-handler.d.ts.map +0 -1
  166. package/types/src/server/index.d.ts +0 -4
  167. package/types/src/server/index.d.ts.map +0 -1
  168. package/types/src/server/request-handler.d.ts +0 -19
  169. package/types/src/server/request-handler.d.ts.map +0 -1
  170. package/types/src/server-islands/extractor.d.ts +0 -16
  171. package/types/src/server-islands/extractor.d.ts.map +0 -1
  172. package/types/src/server-islands/index.d.ts +0 -3
  173. package/types/src/server-islands/index.d.ts.map +0 -1
  174. package/types/src/utils/cache.d.ts +0 -52
  175. package/types/src/utils/cache.d.ts.map +0 -1
  176. package/types/src/utils/env.d.ts +0 -20
  177. package/types/src/utils/env.d.ts.map +0 -1
  178. package/types/src/utils/importhow.d.ts +0 -15
  179. package/types/src/utils/importhow.d.ts.map +0 -1
  180. package/types/src/utils/index.d.ts +0 -3
  181. package/types/src/utils/index.d.ts.map +0 -1
  182. package/types/src/utils/meta-extractor.d.ts +0 -13
  183. package/types/src/utils/meta-extractor.d.ts.map +0 -1
package/src/build.js DELETED
@@ -1,273 +0,0 @@
1
- // bertui/src/build.js
2
- import { join } from 'path';
3
- import { existsSync, mkdirSync, rmSync, readdirSync } from 'fs';
4
- import logger from './logger/logger.js';
5
- import { loadEnvVariables } from './utils/env.js';
6
- import { globalCache } from './utils/cache.js';
7
-
8
- import { compileForBuild } from './build/compiler/index.js';
9
- import { buildAllCSS } from './build/processors/css-builder.js';
10
- import { copyAllStaticAssets } from './build/processors/asset-processor.js';
11
- import { generateProductionHTML } from './build/generators/html-generator.js';
12
- import { generateSitemap } from './build/generators/sitemap-generator.js';
13
- import { generateRobots } from './build/generators/robots-generator.js';
14
- import { compileLayouts } from './layouts/index.js';
15
- import { compileLoadingComponents } from './loading/index.js';
16
- import { analyzeRoutes } from './hydration/index.js';
17
- import { analyzeBuild } from './analyzer/index.js';
18
-
19
- const TOTAL_STEPS = 10;
20
-
21
- export async function buildProduction(options = {}) {
22
- const root = options.root || process.cwd();
23
- const buildDir = join(root, '.bertuibuild');
24
- const outDir = join(root, 'dist');
25
-
26
- process.env.NODE_ENV = 'production';
27
-
28
- logger.printHeader('BUILD');
29
-
30
- if (existsSync(buildDir)) rmSync(buildDir, { recursive: true, force: true });
31
- if (existsSync(outDir)) rmSync(outDir, { recursive: true, force: true });
32
- mkdirSync(buildDir, { recursive: true });
33
- mkdirSync(outDir, { recursive: true });
34
-
35
- let totalKB = '0';
36
-
37
- try {
38
- // ── Step 1: Env ──────────────────────────────────────────────────────────
39
- logger.step(1, TOTAL_STEPS, 'Loading env');
40
- const envVars = loadEnvVariables(root);
41
- const { loadConfig } = await import('./config/loadConfig.js');
42
- const config = await loadConfig(root);
43
- const importhow = config.importhow || {};
44
- logger.stepDone('Loading env', `${Object.keys(envVars).length} vars`);
45
-
46
- // ── Step 2: Compile ──────────────────────────────────────────────────────
47
- // ── Step 2: Compile ──────────────────────────────────────────────────────
48
- logger.step(2, TOTAL_STEPS, 'Compiling');
49
- const { routes } = await compileForBuild(root, buildDir, envVars, config);
50
- logger.stepDone('Compiling', `${routes.length} routes`);
51
-
52
- // TEMP DEBUG - remove after
53
- const aboutPath = join(buildDir, 'pages', 'about.js')
54
- if (existsSync(aboutPath)) {
55
- const src = await Bun.file(aboutPath).text()
56
- console.log('\n--- about.js compiled output ---\n', src.slice(0, 500), '\n---\n')
57
- }
58
- // ── Step 3: Layouts ──────────────────────────────────────────────────────
59
- logger.step(3, TOTAL_STEPS, 'Layouts');
60
- const layouts = await compileLayouts(root, buildDir);
61
- logger.stepDone('Layouts', `${Object.keys(layouts).length} found`);
62
-
63
- // ── Step 4: Loading states ───────────────────────────────────────────────
64
- logger.step(4, TOTAL_STEPS, 'Loading states');
65
- await compileLoadingComponents(root, buildDir);
66
- logger.stepDone('Loading states');
67
-
68
- // ── Step 5: Hydration analysis ───────────────────────────────────────────
69
- logger.step(5, TOTAL_STEPS, 'Hydration analysis');
70
- const analyzedRoutes = await analyzeRoutes(routes);
71
- logger.stepDone('Hydration analysis',
72
- `${analyzedRoutes.interactive.length} interactive · ${analyzedRoutes.static.length} static`);
73
-
74
- // ── Step 6: CSS ──────────────────────────────────────────────────────────
75
- logger.step(6, TOTAL_STEPS, 'Processing CSS');
76
- await buildAllCSS(root, outDir);
77
- logger.stepDone('Processing CSS');
78
-
79
- // ── Step 7: Static assets ────────────────────────────────────────────────
80
- logger.step(7, TOTAL_STEPS, 'Static assets');
81
- await copyAllStaticAssets(root, outDir);
82
- logger.stepDone('Static assets');
83
-
84
- // ── Step 8: Bundle JS ────────────────────────────────────────────────────
85
- logger.step(8, TOTAL_STEPS, 'Bundling JS');
86
- const buildEntry = join(buildDir, 'main.js');
87
- if (!existsSync(buildEntry)) {
88
- throw new Error('main.js not found in build dir — make sure src/main.jsx exists');
89
- }
90
- const result = await bundleJavaScript(buildEntry, outDir, envVars, buildDir, root, config);
91
- totalKB = (result.outputs.reduce((a, o) => a + (o.size || 0), 0) / 1024).toFixed(1);
92
- logger.stepDone('Bundling JS', `${totalKB} KB · tree-shaken`);
93
-
94
- // ── Step 9: HTML ─────────────────────────────────────────────────────────
95
- logger.step(9, TOTAL_STEPS, 'Generating HTML');
96
- await generateProductionHTML(root, outDir, result, routes, config, buildDir)
97
- logger.stepDone('Generating HTML', `${routes.length} pages`);
98
-
99
- // ── Step 10: Sitemap + robots ────────────────────────────────────────────
100
- logger.step(10, TOTAL_STEPS, 'Sitemap & robots');
101
- await generateSitemap(routes, config, outDir);
102
- await generateRobots(config, outDir, routes);
103
- logger.stepDone('Sitemap & robots');
104
-
105
- if (existsSync(buildDir)) rmSync(buildDir, { recursive: true, force: true });
106
-
107
- try {
108
- await analyzeBuild(outDir, { outputFile: join(outDir, 'bundle-report.html') });
109
- } catch (reportErr) {
110
- logger.debug(`Bundle report generation skipped: ${reportErr.message}`);
111
- }
112
-
113
- logger.printSummary({
114
- routes: routes.length,
115
- interactive: analyzedRoutes.interactive.length,
116
- staticRoutes: analyzedRoutes.static.length,
117
- jsSize: `${totalKB} KB`,
118
- outDir: 'dist/',
119
- });
120
-
121
- logger.cleanup();
122
- return { success: true };
123
-
124
- } catch (error) {
125
- logger.stepFail('Build', error?.message || String(error));
126
- if (existsSync(buildDir)) rmSync(buildDir, { recursive: true, force: true });
127
- throw error;
128
- }
129
- }
130
-
131
- // ─────────────────────────────────────────────────────────────────────────────
132
-
133
- async function generateProductionImportMap(root, config) {
134
- const importMap = {
135
- 'react': 'https://esm.sh/react@18.2.0',
136
- 'react-dom': 'https://esm.sh/react-dom@18.2.0',
137
- 'react-dom/client': 'https://esm.sh/react-dom@18.2.0/client',
138
- 'react/jsx-runtime': 'https://esm.sh/react@18.2.0/jsx-runtime',
139
- '@bunnyx/api': '/bunnyx-api/api-client.js',
140
- };
141
-
142
- const nodeModulesDir = join(root, 'node_modules');
143
- if (!existsSync(nodeModulesDir)) return importMap;
144
-
145
- try {
146
- for (const pkg of readdirSync(nodeModulesDir)) {
147
- if (!pkg.startsWith('bertui-') || pkg.startsWith('.')) continue;
148
- const pkgDir = join(nodeModulesDir, pkg);
149
- const pkgJson = join(pkgDir, 'package.json');
150
- if (!existsSync(pkgJson)) continue;
151
- try {
152
- const p = JSON.parse(await Bun.file(pkgJson).text());
153
- for (const entry of [p.browser, p.module, p.main, 'dist/index.js', 'index.js'].filter(Boolean)) {
154
- if (existsSync(join(pkgDir, entry))) {
155
- importMap[pkg] = `/assets/node_modules/${pkg}/${entry}`;
156
- break;
157
- }
158
- }
159
- } catch { continue; }
160
- }
161
- } catch { /* ignore */ }
162
-
163
- return importMap;
164
- }
165
-
166
- async function copyNodeModulesToDist(root, outDir, importMap) {
167
- const { mkdirSync } = await import('fs');
168
- const dest = join(outDir, 'assets', 'node_modules');
169
- mkdirSync(dest, { recursive: true });
170
- const src = join(root, 'node_modules');
171
-
172
- for (const [, assetPath] of Object.entries(importMap)) {
173
- if (assetPath.startsWith('https://')) continue;
174
- const match = assetPath.match(/\/assets\/node_modules\/(.+)$/);
175
- if (!match) continue;
176
- const parts = match[1].split('/');
177
- const pkgName = parts[0];
178
- const subPath = parts.slice(1);
179
- const srcFile = join(src, pkgName, ...subPath);
180
- const destFile = join(dest, pkgName, ...subPath);
181
- mkdirSync(join(dest, pkgName, ...subPath.slice(0, -1)), { recursive: true });
182
- if (existsSync(srcFile)) await Bun.write(destFile, Bun.file(srcFile));
183
- }
184
- }
185
-
186
- async function bundleJavaScript(buildEntry, outDir, envVars, buildDir, root, config) {
187
- const originalCwd = process.cwd();
188
- process.chdir(buildDir);
189
-
190
- try {
191
- const importMap = await generateProductionImportMap(root, config);
192
- await Bun.write(join(outDir, 'import-map.json'), JSON.stringify({ imports: importMap }, null, 2));
193
- await copyNodeModulesToDist(root, outDir, importMap);
194
-
195
- const bunnyxSrc = join(root, 'bunnyx-api', 'api-client.js');
196
- if (existsSync(bunnyxSrc)) {
197
- const { mkdirSync } = await import('fs');
198
- mkdirSync(join(outDir, 'bunnyx-api'), { recursive: true });
199
- await Bun.write(join(outDir, 'bunnyx-api', 'api-client.js'), Bun.file(bunnyxSrc));
200
- }
201
-
202
- const cssModulePlugin = {
203
- name: 'css-modules',
204
- setup(build) {
205
- build.onLoad({ filter: /\.module\.css$/ }, () => ({
206
- contents: 'export default new Proxy({}, { get: (_, k) => k });',
207
- loader: 'js',
208
- }));
209
- build.onLoad({ filter: /\.css$/ }, () => ({
210
- contents: '',
211
- loader: 'js',
212
- }));
213
- },
214
- };
215
-
216
- let result;
217
- try {
218
- result = await Bun.build({
219
- entrypoints: [buildEntry],
220
- outdir: join(outDir, 'assets'),
221
- target: 'browser',
222
- format: 'esm',
223
- plugins: [cssModulePlugin],
224
- minify: {
225
- whitespace: true,
226
- syntax: true,
227
- identifiers: true,
228
- },
229
- splitting: true,
230
- sourcemap: 'external',
231
- metafile: true,
232
- naming: {
233
- entry: 'js/[name]-[hash].js',
234
- chunk: 'js/chunks/[name]-[hash].js',
235
- asset: 'assets/[name]-[hash].[ext]',
236
- },
237
- external: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime', '@bunnyx/api'],
238
- define: {
239
- 'process.env.NODE_ENV': '"production"',
240
- ...Object.fromEntries(
241
- Object.entries(envVars).map(([k, v]) => [`process.env.${k}`, JSON.stringify(v)])
242
- ),
243
- },
244
- });
245
- } catch (err) {
246
- throw new Error(`Bun.build failed: ${err?.message || String(err)}`);
247
- }
248
-
249
- if (!result.success) {
250
- const msgs = (result.logs || []).map(l => l?.message || l?.text || JSON.stringify(l)).join('\n');
251
- throw new Error(`Bundle failed\n${msgs || 'Check your imports for .jsx extensions or unresolvable paths'}`);
252
- }
253
-
254
- if (result.metafile) {
255
- await Bun.write(join(outDir, 'metafile.json'), JSON.stringify(result.metafile, null, 2));
256
- }
257
-
258
- return result;
259
-
260
- } finally {
261
- process.chdir(originalCwd);
262
- }
263
- }
264
-
265
- export async function build(options = {}) {
266
- try {
267
- await buildProduction(options);
268
- process.exit(0);
269
- } catch (error) {
270
- console.error('Build error:', error?.message || String(error));
271
- process.exit(1);
272
- }
273
- }
package/src/cli.js DELETED
@@ -1,131 +0,0 @@
1
- // bertui/src/cli.js - WITH ALL COMMANDS
2
- import { startDev } from './dev.js';
3
- import { buildProduction } from './build.js';
4
- import { startPreviewServer } from './serve.js';
5
- import { scaffold, parseCreateArgs } from './scaffolder/index.js';
6
- import { analyzeBuild } from './analyzer/index.js';
7
- import logger from './logger/logger.js';
8
- import { join } from 'path';
9
-
10
- export function program() {
11
- const args = process.argv.slice(2);
12
- const command = args[0] || 'dev';
13
-
14
- switch (command) {
15
- case 'dev': {
16
- const devPort = getArg('--port', '-p') || 3000;
17
- startDev({
18
- port: parseInt(devPort),
19
- root: process.cwd(),
20
- });
21
- break;
22
- }
23
-
24
- case 'build': {
25
- buildProduction({ root: process.cwd() });
26
- break;
27
- }
28
-
29
- case 'serve':
30
- case 'preview': {
31
- const previewPort = getArg('--port', '-p') || 5000;
32
- startPreviewServer({
33
- port: parseInt(previewPort),
34
- root: process.cwd(),
35
- dir: 'dist',
36
- });
37
- break;
38
- }
39
-
40
- // ✅ NEW: Component/page/layout scaffolder
41
- case 'create': {
42
- const createArgs = args.slice(1);
43
- const parsed = parseCreateArgs(createArgs);
44
- if (parsed) {
45
- scaffold(parsed.type, parsed.name, { root: process.cwd() })
46
- .then(result => {
47
- if (!result) process.exit(1);
48
- })
49
- .catch(err => {
50
- logger.error(`Create failed: ${err.message}`);
51
- process.exit(1);
52
- });
53
- }
54
- break;
55
- }
56
-
57
- // ✅ NEW: Bundle analyzer
58
- case 'analyze': {
59
- const outDir = join(process.cwd(), 'dist');
60
- const open = args.includes('--open');
61
- analyzeBuild(outDir, { open })
62
- .then(result => {
63
- if (!result) {
64
- logger.error('No build found. Run: bertui build');
65
- process.exit(1);
66
- }
67
- })
68
- .catch(err => {
69
- logger.error(`Analyze failed: ${err.message}`);
70
- process.exit(1);
71
- });
72
- break;
73
- }
74
-
75
- case '--version':
76
- case '-v':
77
- console.log('bertui v1.2.0');
78
- break;
79
-
80
- case '--help':
81
- case '-h':
82
- showHelp();
83
- break;
84
-
85
- default:
86
- logger.error(`Unknown command: ${command}`);
87
- showHelp();
88
- }
89
- }
90
-
91
- function getArg(longForm, shortForm) {
92
- const args = process.argv.slice(2);
93
- const longIndex = args.indexOf(longForm);
94
- const shortIndex = args.indexOf(shortForm);
95
- const index = longIndex !== -1 ? longIndex : shortIndex;
96
- return index !== -1 && args[index + 1] ? args[index + 1] : null;
97
- }
98
-
99
- function showHelp() {
100
- logger.bigLog('BERTUI CLI', { color: 'blue' });
101
- console.log(`
102
- Commands:
103
- bertui dev [--port] Start development server (default: 3000)
104
- bertui build Build for production
105
- bertui serve [--port] Preview production build (default: 5000)
106
- bertui analyze [--open] Analyze bundle size (opens report in browser)
107
-
108
- bertui create component <Name> Scaffold a React component
109
- bertui create page <name> Scaffold a page (adds to file-based routing)
110
- bertui create layout <name> Scaffold a layout (default wraps all pages)
111
- bertui create loading <route> Scaffold a per-route loading state
112
- bertui create middleware Scaffold src/middleware.ts
113
-
114
- Options:
115
- --port, -p <number> Port for server
116
- --open Open browser after command
117
-
118
- Examples:
119
- bertui dev
120
- bertui dev --port 8080
121
- bertui build
122
- bertui analyze --open
123
- bertui create component Button
124
- bertui create page About
125
- bertui create page blog/[slug]
126
- bertui create layout default
127
- bertui create layout blog
128
- bertui create loading blog
129
- bertui create middleware
130
- `);
131
- }