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';
5import postcss from 'postcss';
6import tailwindcss from 'tailwindcss';
7import autoprefixer from 'autoprefixer';
8
9const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
11const watch = process.argv.includes('--watch');
12const isProd = process.argv.includes('--prod') || process.env.NODE_ENV === 'production';
13const mode = isProd ? 'production' : 'development';
14
15// Environment-specific configuration
16const ATLAST_API_URL = mode === 'production'
17 ? 'https://atlast.byarielm.fyi'
18 : 'http://127.0.0.1:8888';
19
20console.log(`🌍 Building for ${mode} mode`);
21console.log(`🔗 API URL: ${ATLAST_API_URL}`);
22
23// Clean dist directory
24const distDir = path.join(__dirname, 'dist', 'chrome');
25if (fs.existsSync(distDir)) {
26 fs.rmSync(distDir, { recursive: true });
27}
28fs.mkdirSync(distDir, { recursive: true });
29
30// Build configuration base
31const buildConfigBase = {
32 bundle: true,
33 minify: !watch,
34 sourcemap: watch ? 'inline' : false,
35 target: 'es2020',
36 format: 'esm',
37 define: {
38 '__ATLAST_API_URL__': JSON.stringify(ATLAST_API_URL),
39 '__BUILD_MODE__': JSON.stringify(mode),
40 },
41};
42
43// Build scripts
44const scripts = [
45 {
46 ...buildConfigBase,
47 entryPoints: ['src/content/index.ts'],
48 outfile: path.join(distDir, 'content', 'index.js'),
49 },
50 {
51 ...buildConfigBase,
52 entryPoints: ['src/background/service-worker.ts'],
53 outfile: path.join(distDir, 'background', 'service-worker.js'),
54 },
55 {
56 ...buildConfigBase,
57 entryPoints: ['src/popup/popup.ts'],
58 outfile: path.join(distDir, 'popup', 'popup.js'),
59 },
60];
61
62// Build function
63async function build() {
64 try {
65 console.log('🔨 Building extension...');
66
67 // Build all scripts
68 for (const config of scripts) {
69 if (watch) {
70 const ctx = await esbuild.context(config);
71 await ctx.watch();
72 console.log(`👀 Watching ${path.basename(config.entryPoints[0])}...`);
73 } else {
74 await esbuild.build(config);
75 console.log(`✅ Built ${path.basename(config.entryPoints[0])}`);
76 }
77 }
78
79 // Copy static files
80 copyStaticFiles();
81
82 // Process CSS with Tailwind
83 await processCSS();
84
85 if (!watch) {
86 console.log('✨ Build complete!');
87 }
88 } catch (error) {
89 console.error('❌ Build failed:', error);
90 process.exit(1);
91 }
92}
93
94// Process CSS with PostCSS (Tailwind + Autoprefixer)
95async function processCSS() {
96 const cssPath = path.join(__dirname, 'src/popup/popup.css');
97 const outputPath = path.join(distDir, 'popup/popup.css');
98
99 const css = fs.readFileSync(cssPath, 'utf8');
100
101 // Import cssnano dynamically for production minification
102 const plugins = [tailwindcss, autoprefixer];
103 if (isProd) {
104 const cssnano = (await import('cssnano')).default;
105 plugins.push(cssnano);
106 }
107
108 const result = await postcss(plugins).process(css, {
109 from: cssPath,
110 to: outputPath,
111 });
112
113 // Create directory if it doesn't exist
114 const destDir = path.dirname(outputPath);
115 if (!fs.existsSync(destDir)) {
116 fs.mkdirSync(destDir, { recursive: true });
117 }
118
119 fs.writeFileSync(outputPath, result.css);
120 console.log('🎨 Processed CSS with Tailwind');
121}
122
123// Copy static files
124function copyStaticFiles() {
125 const filesToCopy = [
126 { from: 'manifest.json', to: 'manifest.json' },
127 { from: 'src/popup/popup.html', to: 'popup/popup.html' },
128 ];
129
130 for (const file of filesToCopy) {
131 const srcPath = path.join(__dirname, file.from);
132 const destPath = path.join(distDir, file.to);
133
134 // Create directory if it doesn't exist
135 const destDir = path.dirname(destPath);
136 if (!fs.existsSync(destDir)) {
137 fs.mkdirSync(destDir, { recursive: true });
138 }
139
140 fs.copyFileSync(srcPath, destPath);
141 }
142
143 // Create placeholder icons (TODO: replace with actual icons)
144 const assetsDir = path.join(distDir, 'assets');
145 if (!fs.existsSync(assetsDir)) {
146 fs.mkdirSync(assetsDir, { recursive: true });
147 }
148
149 // Create simple text files as placeholder icons
150 const sizes = [16, 48, 128];
151 for (const size of sizes) {
152 const iconPath = path.join(assetsDir, `icon-${size}.png`);
153 if (!fs.existsSync(iconPath)) {
154 // TODO: Generate actual PNG icons
155 fs.writeFileSync(iconPath, `Placeholder ${size}x${size} icon`);
156 }
157 }
158
159 console.log('📋 Copied static files');
160}
161
162// Run build
163build();