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
@@ -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;