Monorepo for Aesthetic.Computer
aesthetic.computer
1// Build script for Keeps Wallet extension
2// Bundles dependencies and prepares for Chrome loading
3// Run: node scripts/build.mjs
4
5import * as esbuild from 'esbuild';
6import { existsSync, mkdirSync, copyFileSync, readdirSync, writeFileSync, readFileSync } from 'fs';
7import { dirname, join } from 'path';
8import { fileURLToPath } from 'url';
9
10const __dirname = dirname(fileURLToPath(import.meta.url));
11const extDir = join(__dirname, '..');
12const distDir = join(extDir, 'dist');
13
14// Ensure dist directory exists
15if (!existsSync(distDir)) {
16 mkdirSync(distDir, { recursive: true });
17}
18
19// Ensure dist/popup directory exists
20const distPopupDir = join(distDir, 'popup');
21if (!existsSync(distPopupDir)) {
22 mkdirSync(distPopupDir, { recursive: true });
23}
24
25// Ensure dist/icons directory exists
26const distIconsDir = join(distDir, 'icons');
27if (!existsSync(distIconsDir)) {
28 mkdirSync(distIconsDir, { recursive: true });
29}
30
31const isWatch = process.argv.includes('--watch');
32
33async function build() {
34 console.log('🔨 Building Keeps Wallet extension...\n');
35
36 // 1. Bundle background.js with dependencies
37 console.log(' 📦 Bundling background.js...');
38 await esbuild.build({
39 entryPoints: [join(extDir, 'background.js')],
40 bundle: true,
41 outfile: join(distDir, 'background.js'),
42 format: 'esm',
43 platform: 'browser',
44 target: 'chrome120',
45 minify: !isWatch,
46 sourcemap: isWatch,
47 external: [], // Bundle everything
48 });
49
50 // 2. Bundle inpage.js (injected into pages)
51 console.log(' 📦 Bundling inpage.js...');
52 await esbuild.build({
53 entryPoints: [join(extDir, 'inpage.js')],
54 bundle: true,
55 outfile: join(distDir, 'inpage.js'),
56 format: 'iife',
57 platform: 'browser',
58 target: 'chrome120',
59 minify: !isWatch,
60 sourcemap: isWatch,
61 });
62
63 // 3. Copy content.js (no bundling needed, it's just a relay)
64 console.log(' 📄 Copying content.js...');
65 copyFileSync(join(extDir, 'content.js'), join(distDir, 'content.js'));
66
67 // 4. Copy popup files
68 console.log(' 📄 Copying popup files...');
69 copyFileSync(join(extDir, 'popup', 'popup.html'), join(distPopupDir, 'popup.html'));
70 copyFileSync(join(extDir, 'popup', 'popup.js'), join(distPopupDir, 'popup.js'));
71
72 // 4b. Copy Beacon confirmation popup files
73 console.log(' 📄 Copying confirm.html and confirm.js...');
74 copyFileSync(join(extDir, 'confirm.html'), join(distDir, 'confirm.html'));
75 copyFileSync(join(extDir, 'confirm.js'), join(distDir, 'confirm.js'));
76
77 // 5. Copy manifest.json
78 console.log(' 📄 Copying manifest.json...');
79 copyFileSync(join(extDir, 'manifest.json'), join(distDir, 'manifest.json'));
80
81 // 6. Copy icons
82 console.log(' 🎨 Copying icons...');
83 const iconsDir = join(extDir, 'icons');
84 if (existsSync(iconsDir)) {
85 for (const file of readdirSync(iconsDir)) {
86 if (file.endsWith('.png')) {
87 copyFileSync(join(iconsDir, file), join(distIconsDir, file));
88 }
89 }
90 } else {
91 console.log(' ⚠️ No icons found. Run: npm run build:icons');
92 }
93
94 console.log('\n✅ Build complete! Extension ready in dist/\n');
95 console.log('📋 To install in Chrome:');
96 console.log(' 1. Open chrome://extensions');
97 console.log(' 2. Enable "Developer mode" (top right)');
98 console.log(' 3. Click "Load unpacked"');
99 console.log(` 4. Select: ${distDir}`);
100 console.log('');
101}
102
103if (isWatch) {
104 console.log('👀 Watching for changes...\n');
105 // Simple watch - rebuild on any change
106 // For production, use esbuild's watch API
107 build();
108} else {
109 build().catch((err) => {
110 console.error('Build failed:', err);
111 process.exit(1);
112 });
113}