bertui 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/build.js +37 -25
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync, mkdirSync, rmSync, cpSync, readdirSync, statSync } from 'fs
|
|
|
3
3
|
import { extname, dirname } from 'path';
|
|
4
4
|
import logger from './logger/logger.js';
|
|
5
5
|
import { buildCSS } from './build/css-builder.js';
|
|
6
|
+
import { loadEnvVariables, replaceEnvInCode } from './utils/env.js'; // ✅ IMPORT THIS!
|
|
6
7
|
|
|
7
8
|
export async function buildProduction(options = {}) {
|
|
8
9
|
const root = options.root || process.cwd();
|
|
@@ -25,8 +26,15 @@ export async function buildProduction(options = {}) {
|
|
|
25
26
|
const startTime = Date.now();
|
|
26
27
|
|
|
27
28
|
try {
|
|
29
|
+
// ✅ LOAD ENV VARS BEFORE COMPILATION!
|
|
30
|
+
logger.info('Step 0: Loading environment variables...');
|
|
31
|
+
const envVars = loadEnvVariables(root);
|
|
32
|
+
if (Object.keys(envVars).length > 0) {
|
|
33
|
+
logger.info(`Loaded ${Object.keys(envVars).length} environment variables`);
|
|
34
|
+
}
|
|
35
|
+
|
|
28
36
|
logger.info('Step 1: Compiling for production...');
|
|
29
|
-
const { routes } = await compileForBuild(root, buildDir);
|
|
37
|
+
const { routes } = await compileForBuild(root, buildDir, envVars); // ✅ PASS ENV VARS!
|
|
30
38
|
logger.success('Production compilation complete');
|
|
31
39
|
|
|
32
40
|
logger.info('Step 2: Building CSS with Lightning CSS...');
|
|
@@ -68,7 +76,21 @@ export async function buildProduction(options = {}) {
|
|
|
68
76
|
chunk: 'chunks/[name]-[hash].js',
|
|
69
77
|
asset: '[name]-[hash].[ext]'
|
|
70
78
|
},
|
|
71
|
-
external: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime']
|
|
79
|
+
external: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime'],
|
|
80
|
+
// ✅ CRITICAL: Add define to replace process.env at bundle time!
|
|
81
|
+
define: {
|
|
82
|
+
'process.env.NODE_ENV': '"production"',
|
|
83
|
+
'process.env.PUBLIC_APP_NAME': JSON.stringify(envVars.PUBLIC_APP_NAME || 'BertUI App'),
|
|
84
|
+
'process.env.PUBLIC_API_URL': JSON.stringify(envVars.PUBLIC_API_URL || ''),
|
|
85
|
+
'process.env.PUBLIC_USERNAME': JSON.stringify(envVars.PUBLIC_USERNAME || ''),
|
|
86
|
+
// Add all other env vars dynamically
|
|
87
|
+
...Object.fromEntries(
|
|
88
|
+
Object.entries(envVars).map(([key, value]) => [
|
|
89
|
+
`process.env.${key}`,
|
|
90
|
+
JSON.stringify(value)
|
|
91
|
+
])
|
|
92
|
+
)
|
|
93
|
+
}
|
|
72
94
|
});
|
|
73
95
|
|
|
74
96
|
if (!result.success) {
|
|
@@ -131,7 +153,8 @@ async function buildAllCSS(root, outDir) {
|
|
|
131
153
|
}
|
|
132
154
|
}
|
|
133
155
|
|
|
134
|
-
|
|
156
|
+
// ✅ ACCEPT ENV VARS PARAMETER
|
|
157
|
+
async function compileForBuild(root, buildDir, envVars) {
|
|
135
158
|
const srcDir = join(root, 'src');
|
|
136
159
|
const pagesDir = join(srcDir, 'pages');
|
|
137
160
|
|
|
@@ -145,7 +168,8 @@ async function compileForBuild(root, buildDir) {
|
|
|
145
168
|
logger.info(`Found ${routes.length} routes`);
|
|
146
169
|
}
|
|
147
170
|
|
|
148
|
-
|
|
171
|
+
// ✅ PASS ENV VARS TO COMPILATION
|
|
172
|
+
await compileBuildDirectory(srcDir, buildDir, root, envVars);
|
|
149
173
|
|
|
150
174
|
if (routes.length > 0) {
|
|
151
175
|
await generateBuildRouter(routes, buildDir);
|
|
@@ -343,7 +367,8 @@ ${routeConfigs}
|
|
|
343
367
|
await Bun.write(join(buildDir, 'router.js'), routerCode);
|
|
344
368
|
}
|
|
345
369
|
|
|
346
|
-
|
|
370
|
+
// ✅ ACCEPT ENV VARS PARAMETER
|
|
371
|
+
async function compileBuildDirectory(srcDir, buildDir, root, envVars) {
|
|
347
372
|
const files = readdirSync(srcDir);
|
|
348
373
|
|
|
349
374
|
for (const file of files) {
|
|
@@ -353,19 +378,20 @@ async function compileBuildDirectory(srcDir, buildDir, root) {
|
|
|
353
378
|
if (stat.isDirectory()) {
|
|
354
379
|
const subBuildDir = join(buildDir, file);
|
|
355
380
|
mkdirSync(subBuildDir, { recursive: true });
|
|
356
|
-
await compileBuildDirectory(srcPath, subBuildDir, root);
|
|
381
|
+
await compileBuildDirectory(srcPath, subBuildDir, root, envVars); // ✅ PASS IT DOWN
|
|
357
382
|
} else {
|
|
358
383
|
const ext = extname(file);
|
|
359
384
|
|
|
360
385
|
if (ext === '.css') continue;
|
|
361
386
|
|
|
362
387
|
if (['.jsx', '.tsx', '.ts'].includes(ext)) {
|
|
363
|
-
await compileBuildFile(srcPath, buildDir, file, root);
|
|
388
|
+
await compileBuildFile(srcPath, buildDir, file, root, envVars); // ✅ PASS IT HERE
|
|
364
389
|
} else if (ext === '.js') {
|
|
365
390
|
const outPath = join(buildDir, file);
|
|
366
391
|
let code = await Bun.file(srcPath).text();
|
|
367
392
|
|
|
368
393
|
code = removeCSSImports(code);
|
|
394
|
+
code = replaceEnvInCode(code, envVars); // ✅ REPLACE ENV VARS!
|
|
369
395
|
code = fixBuildImports(code, srcPath, outPath, root);
|
|
370
396
|
|
|
371
397
|
await Bun.write(outPath, code);
|
|
@@ -374,7 +400,8 @@ async function compileBuildDirectory(srcDir, buildDir, root) {
|
|
|
374
400
|
}
|
|
375
401
|
}
|
|
376
402
|
|
|
377
|
-
|
|
403
|
+
// ✅ ACCEPT ENV VARS PARAMETER
|
|
404
|
+
async function compileBuildFile(srcPath, buildDir, filename, root, envVars) {
|
|
378
405
|
const ext = extname(filename);
|
|
379
406
|
const loader = ext === '.tsx' ? 'tsx' : ext === '.ts' ? 'ts' : 'jsx';
|
|
380
407
|
|
|
@@ -382,6 +409,7 @@ async function compileBuildFile(srcPath, buildDir, filename, root) {
|
|
|
382
409
|
let code = await Bun.file(srcPath).text();
|
|
383
410
|
|
|
384
411
|
code = removeCSSImports(code);
|
|
412
|
+
code = replaceEnvInCode(code, envVars); // ✅ REPLACE ENV VARS BEFORE TRANSPILATION!
|
|
385
413
|
|
|
386
414
|
const outFilename = filename.replace(/\.(jsx|tsx|ts)$/, '.js');
|
|
387
415
|
const outPath = join(buildDir, outFilename);
|
|
@@ -448,18 +476,15 @@ function fixRelativeImports(code) {
|
|
|
448
476
|
return code;
|
|
449
477
|
}
|
|
450
478
|
|
|
451
|
-
// ✅ FIXED: Better meta extraction that handles multi-line objects
|
|
452
479
|
function extractMetaFromSource(code) {
|
|
453
480
|
try {
|
|
454
|
-
// Match export const meta = { ... } with proper brace counting
|
|
455
481
|
const metaMatch = code.match(/export\s+const\s+meta\s*=\s*\{/);
|
|
456
482
|
if (!metaMatch) return null;
|
|
457
483
|
|
|
458
|
-
const startIndex = metaMatch.index + metaMatch[0].length - 1;
|
|
484
|
+
const startIndex = metaMatch.index + metaMatch[0].length - 1;
|
|
459
485
|
let braceCount = 0;
|
|
460
486
|
let endIndex = startIndex;
|
|
461
487
|
|
|
462
|
-
// Count braces to find the closing brace
|
|
463
488
|
for (let i = startIndex; i < code.length; i++) {
|
|
464
489
|
if (code[i] === '{') braceCount++;
|
|
465
490
|
if (code[i] === '}') {
|
|
@@ -474,11 +499,7 @@ function extractMetaFromSource(code) {
|
|
|
474
499
|
if (endIndex === startIndex) return null;
|
|
475
500
|
|
|
476
501
|
const metaString = code.substring(startIndex, endIndex + 1);
|
|
477
|
-
|
|
478
|
-
// Parse the meta object safely
|
|
479
502
|
const meta = {};
|
|
480
|
-
|
|
481
|
-
// Extract key-value pairs (handles strings with quotes)
|
|
482
503
|
const pairRegex = /(\w+)\s*:\s*(['"`])((?:(?!\2).)*)\2/g;
|
|
483
504
|
let match;
|
|
484
505
|
|
|
@@ -495,7 +516,6 @@ function extractMetaFromSource(code) {
|
|
|
495
516
|
}
|
|
496
517
|
}
|
|
497
518
|
|
|
498
|
-
// ✅ FIXED: Correct bundle path and proper hydration
|
|
499
519
|
async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
500
520
|
const mainBundle = buildResult.outputs.find(o =>
|
|
501
521
|
o.path.includes('main') && o.kind === 'entry-point'
|
|
@@ -505,9 +525,7 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
|
505
525
|
throw new Error('Could not find main bundle in build output');
|
|
506
526
|
}
|
|
507
527
|
|
|
508
|
-
// ✅ FIX 1: Get ONLY the relative path from dist/
|
|
509
528
|
const bundlePath = relative(outDir, mainBundle.path).replace(/\\/g, '/');
|
|
510
|
-
|
|
511
529
|
logger.info(`Main bundle path: ${bundlePath}`);
|
|
512
530
|
|
|
513
531
|
const srcStylesDir = join(root, 'src', 'styles');
|
|
@@ -520,7 +538,6 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
|
520
538
|
).join('\n');
|
|
521
539
|
}
|
|
522
540
|
|
|
523
|
-
// Load config for default meta
|
|
524
541
|
const { loadConfig } = await import('./config/loadConfig.js');
|
|
525
542
|
const config = await loadConfig(root);
|
|
526
543
|
const defaultMeta = config.meta || {};
|
|
@@ -533,18 +550,14 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
|
533
550
|
continue;
|
|
534
551
|
}
|
|
535
552
|
|
|
536
|
-
// Read source file and extract meta
|
|
537
553
|
const sourceCode = await Bun.file(route.path).text();
|
|
538
554
|
const pageMeta = extractMetaFromSource(sourceCode);
|
|
539
|
-
|
|
540
|
-
// Merge page meta with default meta
|
|
541
555
|
const meta = { ...defaultMeta, ...pageMeta };
|
|
542
556
|
|
|
543
557
|
if (pageMeta) {
|
|
544
558
|
logger.info(`Extracted meta for ${route.route}: ${JSON.stringify(pageMeta)}`);
|
|
545
559
|
}
|
|
546
560
|
|
|
547
|
-
// ✅ FIX 2: Generate proper HTML with correct script path
|
|
548
561
|
const html = `<!DOCTYPE html>
|
|
549
562
|
<html lang="${meta.lang || 'en'}">
|
|
550
563
|
<head>
|
|
@@ -590,7 +603,6 @@ ${userStylesheets}
|
|
|
590
603
|
</body>
|
|
591
604
|
</html>`;
|
|
592
605
|
|
|
593
|
-
// Determine output path
|
|
594
606
|
let htmlPath;
|
|
595
607
|
if (route.route === '/') {
|
|
596
608
|
htmlPath = join(outDir, 'index.html');
|