ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
1import * as esbuild from 'esbuild';
2import * as fs from 'fs';
3import * as path from 'path';
4import { fileURLToPath } from 'url';
5
6const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
8const watch = process.argv.includes('--watch');
9const isProd = process.argv.includes('--prod') || process.env.NODE_ENV === 'production';
10const mode = isProd ? 'production' : 'development';
11
12// Environment-specific configuration
13const ATLAST_API_URL = mode === 'production'
14 ? 'https://atlast.byarielm.fyi'
15 : 'http://127.0.0.1:8888';
16
17console.log(`🌍 Building for ${mode} mode`);
18console.log(`🔗 API URL: ${ATLAST_API_URL}`);
19
20// Clean dist directory
21const distDir = path.join(__dirname, 'dist', 'chrome');
22if (fs.existsSync(distDir)) {
23 fs.rmSync(distDir, { recursive: true });
24}
25fs.mkdirSync(distDir, { recursive: true });
26
27// Build configuration base
28const buildConfigBase = {
29 bundle: true,
30 minify: !watch,
31 sourcemap: watch ? 'inline' : false,
32 target: 'es2020',
33 format: 'esm',
34 define: {
35 '__ATLAST_API_URL__': JSON.stringify(ATLAST_API_URL),
36 '__BUILD_MODE__': JSON.stringify(mode),
37 },
38};
39
40// Build scripts
41const scripts = [
42 {
43 ...buildConfigBase,
44 entryPoints: ['src/content/index.ts'],
45 outfile: path.join(distDir, 'content', 'index.js'),
46 },
47 {
48 ...buildConfigBase,
49 entryPoints: ['src/background/service-worker.ts'],
50 outfile: path.join(distDir, 'background', 'service-worker.js'),
51 },
52 {
53 ...buildConfigBase,
54 entryPoints: ['src/popup/popup.ts'],
55 outfile: path.join(distDir, 'popup', 'popup.js'),
56 },
57];
58
59// Build function
60async function build() {
61 try {
62 console.log('🔨 Building extension...');
63
64 // Build all scripts
65 for (const config of scripts) {
66 if (watch) {
67 const ctx = await esbuild.context(config);
68 await ctx.watch();
69 console.log(`👀 Watching ${path.basename(config.entryPoints[0])}...`);
70 } else {
71 await esbuild.build(config);
72 console.log(`✅ Built ${path.basename(config.entryPoints[0])}`);
73 }
74 }
75
76 // Copy static files
77 copyStaticFiles();
78
79 if (!watch) {
80 console.log('✨ Build complete!');
81 }
82 } catch (error) {
83 console.error('❌ Build failed:', error);
84 process.exit(1);
85 }
86}
87
88// Copy static files
89function copyStaticFiles() {
90 const filesToCopy = [
91 { from: 'manifest.json', to: 'manifest.json' },
92 { from: 'src/popup/popup.html', to: 'popup/popup.html' },
93 { from: 'src/popup/popup.css', to: 'popup/popup.css' },
94 ];
95
96 for (const file of filesToCopy) {
97 const srcPath = path.join(__dirname, file.from);
98 const destPath = path.join(distDir, file.to);
99
100 // Create directory if it doesn't exist
101 const destDir = path.dirname(destPath);
102 if (!fs.existsSync(destDir)) {
103 fs.mkdirSync(destDir, { recursive: true });
104 }
105
106 fs.copyFileSync(srcPath, destPath);
107 }
108
109 // Create placeholder icons (TODO: replace with actual icons)
110 const assetsDir = path.join(distDir, 'assets');
111 if (!fs.existsSync(assetsDir)) {
112 fs.mkdirSync(assetsDir, { recursive: true });
113 }
114
115 // Create simple text files as placeholder icons
116 const sizes = [16, 48, 128];
117 for (const size of sizes) {
118 const iconPath = path.join(assetsDir, `icon-${size}.png`);
119 if (!fs.existsSync(iconPath)) {
120 // TODO: Generate actual PNG icons
121 fs.writeFileSync(iconPath, `Placeholder ${size}x${size} icon`);
122 }
123 }
124
125 console.log('📋 Copied static files');
126}
127
128// Run build
129build();