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
@@ -1,210 +0,0 @@
1
- // bertui/src/loading/index.js
2
- // Built-in loading states - per route loading UI
3
-
4
- import { join, extname, basename } from 'path';
5
- import { existsSync, readdirSync } from 'fs';
6
- import logger from '../logger/logger.js';
7
-
8
- /**
9
- * Default loading spinner HTML injected into pages
10
- * Beautiful, zero-dependency, CSS-only spinner
11
- */
12
- export const DEFAULT_LOADING_HTML = `
13
- <div id="bertui-loading" style="
14
- position: fixed;
15
- top: 0;
16
- left: 0;
17
- width: 100%;
18
- height: 100%;
19
- background: rgba(255,255,255,0.95);
20
- display: flex;
21
- flex-direction: column;
22
- align-items: center;
23
- justify-content: center;
24
- z-index: 99999;
25
- font-family: system-ui, sans-serif;
26
- transition: opacity 0.2s ease;
27
- ">
28
- <div style="
29
- width: 40px;
30
- height: 40px;
31
- border: 3px solid #e5e7eb;
32
- border-top-color: #10b981;
33
- border-radius: 50%;
34
- animation: bertui-spin 0.7s linear infinite;
35
- "></div>
36
- <p style="margin-top: 16px; color: #6b7280; font-size: 14px; font-weight: 500;">Loading...</p>
37
- </div>
38
- <style>
39
- @keyframes bertui-spin {
40
- to { transform: rotate(360deg); }
41
- }
42
- </style>
43
- <script>
44
- // Remove loading screen once React mounts
45
- window.__BERTUI_HIDE_LOADING__ = function() {
46
- const el = document.getElementById('bertui-loading');
47
- if (el) {
48
- el.style.opacity = '0';
49
- setTimeout(() => el.remove(), 200);
50
- }
51
- };
52
-
53
- // Fallback: remove after 5s no matter what
54
- setTimeout(() => window.__BERTUI_HIDE_LOADING__?.(), 5000);
55
-
56
- // React root observer - hide when #root gets children
57
- const observer = new MutationObserver(() => {
58
- const root = document.getElementById('root');
59
- if (root && root.children.length > 0) {
60
- window.__BERTUI_HIDE_LOADING__?.();
61
- observer.disconnect();
62
- }
63
- });
64
- const root = document.getElementById('root');
65
- if (root) observer.observe(root, { childList: true, subtree: true });
66
- </script>
67
- `;
68
-
69
- /**
70
- * Discover per-route loading components from src/pages/
71
- * Convention: create a loading.tsx next to your page file
72
- * e.g., src/pages/blog/loading.tsx → shown while /blog loads
73
- */
74
- export async function discoverLoadingComponents(root) {
75
- const pagesDir = join(root, 'src', 'pages');
76
- if (!existsSync(pagesDir)) return {};
77
-
78
- const loadingComponents = {};
79
-
80
- function scan(dir, routeBase = '') {
81
- const entries = readdirSync(dir, { withFileTypes: true });
82
-
83
- for (const entry of entries) {
84
- const fullPath = join(dir, entry.name);
85
-
86
- if (entry.isDirectory()) {
87
- scan(fullPath, `${routeBase}/${entry.name}`);
88
- } else if (entry.isFile()) {
89
- const ext = extname(entry.name);
90
- const name = basename(entry.name, ext);
91
-
92
- if (name === 'loading' && ['.jsx', '.tsx', '.js', '.ts'].includes(ext)) {
93
- const route = routeBase || '/';
94
- loadingComponents[route] = {
95
- path: fullPath,
96
- route,
97
- };
98
- logger.debug(`⏳ Loading component: ${route} → ${entry.name}`);
99
- }
100
- }
101
- }
102
- }
103
-
104
- scan(pagesDir);
105
-
106
- if (Object.keys(loadingComponents).length > 0) {
107
- logger.success(`✅ ${Object.keys(loadingComponents).length} loading component(s) found`);
108
- }
109
-
110
- return loadingComponents;
111
- }
112
-
113
- /**
114
- * Compile loading components to .bertui/compiled/loading/
115
- */
116
- export async function compileLoadingComponents(root, compiledDir) {
117
- const components = await discoverLoadingComponents(root);
118
- if (Object.keys(components).length === 0) return components;
119
-
120
- const outDir = join(compiledDir, 'loading');
121
- const { mkdirSync } = await import('fs');
122
- mkdirSync(outDir, { recursive: true });
123
-
124
- for (const [route, comp] of Object.entries(components)) {
125
- const ext = extname(comp.path);
126
- const loader = ext === '.tsx' ? 'tsx' : ext === '.ts' ? 'ts' : 'jsx';
127
- const safeName = route.replace(/\//g, '_').replace(/^_/, '') || 'root';
128
-
129
- try {
130
- let code = await Bun.file(comp.path).text();
131
-
132
- if (!code.includes('import React')) {
133
- code = `import React from 'react';\n${code}`;
134
- }
135
-
136
- const transpiler = new Bun.Transpiler({
137
- loader,
138
- target: 'browser',
139
- tsconfig: {
140
- compilerOptions: {
141
- jsx: 'react',
142
- jsxFactory: 'React.createElement',
143
- jsxFragmentFactory: 'React.Fragment',
144
- },
145
- },
146
- });
147
-
148
- const compiled = await transpiler.transform(code);
149
- await Bun.write(join(outDir, `${safeName}.js`), compiled);
150
- components[route].compiledPath = join(outDir, `${safeName}.js`);
151
- components[route].compiledName = safeName;
152
-
153
- } catch (err) {
154
- logger.error(`Failed to compile loading component for ${route}: ${err.message}`);
155
- }
156
- }
157
-
158
- return components;
159
- }
160
-
161
- /**
162
- * Generate loading-aware router code
163
- * Wraps each route component with Suspense + loading fallback
164
- */
165
- export function generateLoadingAwareRouter(routes, loadingComponents) {
166
- const hasLoading = Object.keys(loadingComponents).length > 0;
167
-
168
- const loadingImports = hasLoading
169
- ? Object.entries(loadingComponents)
170
- .map(([route, comp]) => {
171
- const safeName = comp.compiledName || (route.replace(/\//g, '_').replace(/^_/, '') || 'root');
172
- return `import Loading_${safeName} from './loading/${safeName}.js';`;
173
- })
174
- .join('\n')
175
- : '';
176
-
177
- const getLoadingComponent = (route) => {
178
- // Exact match
179
- if (loadingComponents[route]) {
180
- const safeName = loadingComponents[route].compiledName ||
181
- (route.replace(/\//g, '_').replace(/^_/, '') || 'root');
182
- return `Loading_${safeName}`;
183
- }
184
-
185
- // Parent route match
186
- const segments = route.split('/').filter(Boolean);
187
- while (segments.length > 0) {
188
- segments.pop();
189
- const parent = '/' + segments.join('/') || '/';
190
- if (loadingComponents[parent]) {
191
- const safeName = loadingComponents[parent].compiledName ||
192
- (parent.replace(/\//g, '_').replace(/^_/, '') || 'root');
193
- return `Loading_${safeName}`;
194
- }
195
- }
196
-
197
- return null;
198
- };
199
-
200
- return { loadingImports, getLoadingComponent };
201
- }
202
-
203
- /**
204
- * Generate the default loading screen script to inject into HTML
205
- */
206
- export function getLoadingScript(customText = 'Loading...', color = '#10b981') {
207
- return DEFAULT_LOADING_HTML
208
- .replace('Loading...', customText)
209
- .replace('#10b981', color);
210
- }
@@ -1,320 +0,0 @@
1
- // bertui/src/logger/logger.js
2
- // Compact, progress-style CLI — replaces verbose line-by-line logs
3
-
4
- import { createWriteStream } from 'fs';
5
- import { join } from 'path';
6
- import { mkdirSync, existsSync } from 'fs';
7
-
8
- // ── ANSI helpers ─────────────────────────────────────────────────────────────
9
- const C = {
10
- reset: '\x1b[0m',
11
- bold: '\x1b[1m',
12
- dim: '\x1b[2m',
13
- red: '\x1b[31m',
14
- green: '\x1b[32m',
15
- yellow: '\x1b[33m',
16
- blue: '\x1b[34m',
17
- magenta: '\x1b[35m',
18
- cyan: '\x1b[36m',
19
- white: '\x1b[37m',
20
- bgBlack: '\x1b[40m',
21
- bgRed: '\x1b[41m',
22
- bgGreen: '\x1b[42m',
23
- bgBlue: '\x1b[44m',
24
- bgCyan: '\x1b[46m',
25
- bgWhite: '\x1b[47m',
26
- gray: '\x1b[90m',
27
- };
28
-
29
- const isTTY = process.stdout.isTTY;
30
-
31
- // ── Spinner frames ────────────────────────────────────────────────────────────
32
- const SPINNER = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
33
- let _spinnerFrame = 0;
34
- let _spinnerTimer = null;
35
- let _currentSpinnerLine = '';
36
-
37
- // ── Internal state ────────────────────────────────────────────────────────────
38
- let _mode = 'idle'; // 'idle' | 'build' | 'dev'
39
- let _totalSteps = 10;
40
- let _stepIndex = 0;
41
- let _stepLabel = '';
42
- let _stepDetail = '';
43
- let _errors = [];
44
- let _warnings = [];
45
- let _startTime = null;
46
-
47
- // ── Header ────────────────────────────────────────────────────────────────────
48
- export function printHeader(mode = 'BUILD') {
49
- _mode = mode.toLowerCase();
50
- _startTime = Date.now();
51
- _errors = [];
52
- _warnings = [];
53
-
54
- const W = 46;
55
- const bar = '█'.repeat(W);
56
-
57
- // Big block-letter BERTUI (6 rows)
58
- const BIG = [
59
- ' ██████╗ ███████╗██████╗ ████████╗██╗ ██╗██╗',
60
- ' ██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██║ ██║██║',
61
- ' ██████╔╝█████╗ ██████╔╝ ██║ ██║ ██║██║',
62
- ' ██╔══██╗██╔══╝ ██╔══██╗ ██║ ██║ ██║██║',
63
- ' ██████╔╝███████╗██║ ██║ ██║ ╚██████╔╝██║',
64
- ' ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝',
65
- ];
66
-
67
- process.stdout.write('\n');
68
- process.stdout.write(`${C.cyan}${C.bold} ${bar}${C.reset}\n`);
69
- for (const row of BIG) {
70
- process.stdout.write(`${C.cyan}${C.bold}${row}${C.reset}\n`);
71
- }
72
- process.stdout.write(`${C.gray} by Pease Ernest${C.reset}${C.gray} · ${C.reset}${C.white}${C.bold}${mode.toUpperCase()}${C.reset}\n`);
73
- process.stdout.write(`${C.cyan}${C.bold} ${bar}${C.reset}\n`);
74
- process.stdout.write('\n');
75
- }
76
-
77
- // ── Step progress ─────────────────────────────────────────────────────────────
78
- export function step(index, total, label, detail = '') {
79
- _stepIndex = index;
80
- _totalSteps = total;
81
- _stepLabel = label;
82
- _stepDetail = detail;
83
- _stopSpinner();
84
- _renderStep('running', detail);
85
- _startSpinner();
86
- }
87
-
88
- export function stepDone(label, detail = '') {
89
- _stopSpinner();
90
- _clearLine();
91
- const idx = String(_stepIndex).padStart(2, ' ');
92
- const lbl = (label || _stepLabel).padEnd(24, ' ');
93
- const det = detail ? `${C.gray}${_truncate(detail, 38)}${C.reset}` : '';
94
- process.stdout.write(
95
- ` ${C.gray}[${idx}/${_totalSteps}]${C.reset} ${C.green}✓${C.reset} ${C.white}${lbl}${C.reset} ${det}\n`
96
- );
97
- }
98
-
99
- export function stepFail(label, detail = '') {
100
- _stopSpinner();
101
- _clearLine();
102
- const idx = String(_stepIndex).padStart(2, ' ');
103
- const lbl = (label || _stepLabel).padEnd(24, ' ');
104
- process.stdout.write(
105
- ` ${C.gray}[${idx}/${_totalSteps}]${C.reset} ${C.red}✗${C.reset} ${C.white}${lbl}${C.reset} ${C.red}${detail}${C.reset}\n`
106
- );
107
- }
108
-
109
- // ── Inline file progress (replaces "Progress: 2/2 (100%)") ───────────────────
110
- export function fileProgress(current, total, filename) {
111
- if (!isTTY) return;
112
- _clearLine();
113
- const pct = Math.round((current / total) * 100);
114
- const bar = _bar(pct, 16);
115
- const name = _truncate(filename, 30);
116
- _currentSpinnerLine =
117
- ` ${C.gray}[${String(_stepIndex).padStart(2,' ')}/${_totalSteps}]${C.reset}` +
118
- ` ${C.cyan}⠸${C.reset} ${C.white}${_stepLabel.padEnd(24,' ')}${C.reset}` +
119
- ` ${bar} ${C.gray}${current}/${total}${C.reset} ${C.dim}${name}${C.reset}`;
120
- process.stdout.write('\r' + _currentSpinnerLine);
121
- }
122
-
123
- // ── Simple log levels (used internally, suppressed in compact mode) ───────────
124
- export function info(msg) {
125
- _debugLog('INFO', msg);
126
- }
127
-
128
- export function success(msg) {
129
- _debugLog('SUCCESS', msg);
130
- }
131
-
132
- export function warn(msg) {
133
- _warnings.push(msg);
134
- _stopSpinner();
135
- _clearLine();
136
- process.stdout.write(` ${C.yellow}⚠${C.reset} ${C.yellow}${msg}${C.reset}\n`);
137
- if (_stepLabel) _startSpinner();
138
- }
139
-
140
- export function error(msg) {
141
- _errors.push(msg);
142
- _stopSpinner();
143
- _clearLine();
144
- process.stdout.write(` ${C.red}✗${C.reset} ${C.red}${msg}${C.reset}\n`);
145
- }
146
-
147
- export function debug(msg) {
148
- _debugLog('DEBUG', msg);
149
- }
150
-
151
- // ── Table (kept for route/island tables but made compact) ─────────────────────
152
- export function table(rows) {
153
- if (!rows || rows.length === 0) return;
154
- _stopSpinner();
155
- const keys = Object.keys(rows[0]).filter(k => k !== '');
156
- const widths = keys.map(k =>
157
- Math.max(k.length, ...rows.map(r => String(r[k] ?? '').length))
158
- );
159
-
160
- const hr = ' ' + widths.map(w => '─'.repeat(w + 2)).join('┼') ;
161
- const header = ' ' + keys.map((k, i) => ` ${C.bold}${k.padEnd(widths[i])}${C.reset} `).join('│');
162
-
163
- process.stdout.write(`${C.gray}${hr}${C.reset}\n`);
164
- process.stdout.write(`${header}\n`);
165
- process.stdout.write(`${C.gray}${hr}${C.reset}\n`);
166
-
167
- for (const row of rows) {
168
- const line = ' ' + keys.map((k, i) => ` ${String(row[k] ?? '').padEnd(widths[i])} `).join(`${C.gray}│${C.reset}`);
169
- process.stdout.write(`${line}\n`);
170
- }
171
- process.stdout.write(`${C.gray}${hr}${C.reset}\n`);
172
-
173
- if (_stepLabel) _startSpinner();
174
- }
175
-
176
- // ── bigLog — replaced by section headers ─────────────────────────────────────
177
- export function bigLog(title, opts = {}) {
178
- _stopSpinner();
179
- _clearLine();
180
- process.stdout.write(`\n ${C.bold}${C.cyan}── ${title} ──${C.reset}\n\n`);
181
- if (_stepLabel) _startSpinner();
182
- }
183
-
184
- // ── Build/Dev summary ─────────────────────────────────────────────────────────
185
- export function printSummary(stats = {}) {
186
- _stopSpinner();
187
- // Close the log stream before printing summary
188
- _closeLogStream();
189
-
190
- process.stdout.write('\n');
191
-
192
- const dur = _startTime ? `${((Date.now() - _startTime) / 1000).toFixed(2)}s` : '';
193
-
194
- process.stdout.write(`${C.cyan}${C.bold} ────────────────────────────────────────────${C.reset}\n`);
195
- process.stdout.write(`${C.green}${C.bold} ✓ Done${C.reset}${dur ? ` ${C.gray}${dur}${C.reset}` : ''}\n`);
196
-
197
- if (stats.routes) _summaryLine('Routes', stats.routes);
198
- if (stats.serverIslands)_summaryLine('Server Islands', stats.serverIslands);
199
- if (stats.interactive) _summaryLine('Interactive', stats.interactive);
200
- if (stats.staticRoutes) _summaryLine('Static', stats.staticRoutes);
201
- if (stats.jsSize) _summaryLine('JS bundle', stats.jsSize);
202
- if (stats.cssSize) _summaryLine('CSS bundle', stats.cssSize);
203
- if (stats.outDir) _summaryLine('Output', stats.outDir);
204
-
205
- if (_warnings.length > 0) {
206
- process.stdout.write(`\n ${C.yellow}${_warnings.length} warning(s)${C.reset}\n`);
207
- }
208
- if (_errors.length > 0) {
209
- process.stdout.write(`\n ${C.red}${_errors.length} error(s)${C.reset}\n`);
210
- _errors.forEach(e => process.stdout.write(` ${C.red} · ${e}${C.reset}\n`));
211
- }
212
-
213
- process.stdout.write(`${C.cyan}${C.bold} ────────────────────────────────────────────${C.reset}\n\n`);
214
- }
215
-
216
- function _summaryLine(label, value) {
217
- process.stdout.write(
218
- ` ${C.gray}${label.padEnd(18)}${C.reset}${C.white}${value}${C.reset}\n`
219
- );
220
- }
221
-
222
- // ── Spinner internals ─────────────────────────────────────────────────────────
223
- function _startSpinner() {
224
- if (!isTTY || _spinnerTimer) return;
225
- _spinnerTimer = setInterval(() => {
226
- _spinnerFrame = (_spinnerFrame + 1) % SPINNER.length;
227
- _renderStep('running', _stepDetail);
228
- }, 80);
229
- }
230
-
231
- function _stopSpinner() {
232
- if (_spinnerTimer) {
233
- clearInterval(_spinnerTimer);
234
- _spinnerTimer = null;
235
- }
236
- }
237
-
238
- function _renderStep(state, detail = '') {
239
- if (!isTTY) return;
240
- _clearLine();
241
- const spin = SPINNER[_spinnerFrame];
242
- const idx = String(_stepIndex).padStart(2, ' ');
243
- const lbl = _stepLabel.padEnd(24, ' ');
244
- const det = detail ? `${C.gray}${_truncate(detail, 38)}${C.reset}` : '';
245
- _currentSpinnerLine =
246
- ` ${C.gray}[${idx}/${_totalSteps}]${C.reset} ${C.cyan}${spin}${C.reset} ${C.white}${lbl}${C.reset} ${det}`;
247
- process.stdout.write('\r' + _currentSpinnerLine);
248
- }
249
-
250
- function _clearLine() {
251
- if (!isTTY) return;
252
- process.stdout.write('\r\x1b[2K');
253
- }
254
-
255
- // ── Helpers ───────────────────────────────────────────────────────────────────
256
- function _bar(pct, width) {
257
- const filled = Math.round((pct / 100) * width);
258
- const empty = width - filled;
259
- return `${C.cyan}${'█'.repeat(filled)}${C.gray}${'░'.repeat(empty)}${C.reset}`;
260
- }
261
-
262
- function _truncate(str, max) {
263
- if (!str) return '';
264
- str = String(str);
265
- return str.length > max ? '…' + str.slice(-(max - 1)) : str;
266
- }
267
-
268
- // ── Debug file log (always written, never shown in terminal) ──────────────────
269
- let _logStream = null;
270
- function _debugLog(level, msg) {
271
- if (!_logStream) {
272
- try {
273
- const logDir = join(process.cwd(), '.bertui');
274
- if (!existsSync(logDir)) {
275
- mkdirSync(logDir, { recursive: true });
276
- }
277
-
278
- _logStream = createWriteStream(
279
- join(logDir, 'dev.log'),
280
- { flags: 'a' }
281
- );
282
- } catch (err) {
283
- return;
284
- }
285
- }
286
- const ts = new Date().toISOString().substring(11, 23);
287
- _logStream.write(`[${ts}] [${level}] ${msg}\n`);
288
- }
289
-
290
- // NEW: Function to close the log stream
291
- function _closeLogStream() {
292
- if (_logStream) {
293
- _logStream.end();
294
- _logStream = null;
295
- }
296
- }
297
-
298
- // NEW: Cleanup function to be called when done
299
- export function cleanup() {
300
- _stopSpinner();
301
- _closeLogStream();
302
- }
303
-
304
- // ── Default export ────────────────────────────────────────────────────────────
305
- export default {
306
- printHeader,
307
- step,
308
- stepDone,
309
- stepFail,
310
- fileProgress,
311
- info,
312
- success,
313
- warn,
314
- error,
315
- debug,
316
- table,
317
- bigLog,
318
- printSummary,
319
- cleanup, // Export cleanup function
320
- };
@@ -1,20 +0,0 @@
1
- here we will use the ernest logger libraray instead of chalk because i want colourfull logs and not just normal b/w logs the whole module is exported for use in the libraray
2
- it is a file that is complete and needs no updated later on
3
- // src/utils/logger.js
4
- import { createLogger } from 'ernest-logger';
5
-
6
- // Create logger instance for BertUI
7
- const logger = createLogger({
8
- time: true,
9
- emoji: true,
10
- level: 'info',
11
- prefix: '[BertUI]',
12
- customLevels: {
13
- server: { color: 'brightCyan', emoji: '🌐', priority: 2 },
14
- build: { color: 'brightGreen', emoji: '📦', priority: 2 },
15
- hmr: { color: 'brightYellow', emoji: '🔥', priority: 2 }
16
- }
17
- });
18
-
19
- // Export the logger
20
- export default logger;