146 lines
4.1 KiB
JavaScript
146 lines
4.1 KiB
JavaScript
/**
|
||
* Build Verification Script
|
||
*
|
||
* Extracts and validates environment variables embedded in the built bundle.
|
||
* Ensures redirect URIs match the expected deployment target.
|
||
*
|
||
* Usage:
|
||
* BUILD_TARGET=docker-local npm run build:verify
|
||
* BUILD_TARGET=production npm run build:verify
|
||
*/
|
||
import fs from 'fs';
|
||
import path from 'path';
|
||
import { fileURLToPath } from 'url';
|
||
|
||
const __filename = fileURLToPath(import.meta.url);
|
||
const __dirname = path.dirname(__filename);
|
||
|
||
// Expected redirect URIs for each deployment target
|
||
const EXPECTED_URIS = {
|
||
'docker-local': 'http://localhost:8099/oauth/callback',
|
||
production: 'https://app.pokedex.online/oauth/callback'
|
||
};
|
||
|
||
// ANSI colors
|
||
const colors = {
|
||
red: '\x1b[31m',
|
||
green: '\x1b[32m',
|
||
yellow: '\x1b[33m',
|
||
blue: '\x1b[34m',
|
||
reset: '\x1b[0m'
|
||
};
|
||
|
||
function log(color, symbol, message) {
|
||
console.log(`${colors[color]}${symbol}${colors.reset} ${message}`);
|
||
}
|
||
|
||
function findBuiltAssets() {
|
||
const distPath = path.resolve(__dirname, '../dist/assets');
|
||
|
||
if (!fs.existsSync(distPath)) {
|
||
throw new Error('dist/assets directory not found. Run build first.');
|
||
}
|
||
|
||
const files = fs.readdirSync(distPath);
|
||
const jsFiles = files.filter(
|
||
f => f.endsWith('.js') && f.startsWith('index-')
|
||
);
|
||
|
||
if (jsFiles.length === 0) {
|
||
throw new Error('No built JavaScript files found in dist/assets/');
|
||
}
|
||
|
||
return jsFiles.map(f => path.join(distPath, f));
|
||
}
|
||
|
||
function extractRedirectUri(content) {
|
||
// Look for the Discord redirect URI in the built bundle
|
||
const patterns = [
|
||
/VITE_DISCORD_REDIRECT_URI[\"']?\s*[:=]\s*[\"']([^\"']+)[\"']/,
|
||
/discord_redirect_uri[\"']?\s*[:=]\s*[\"']([^\"']+)[\"']/i,
|
||
/redirectUri[\"']?\s*[:=]\s*[\"']([^\"']+oauth\/callback)[\"']/,
|
||
/(https?:\/\/[^\"'\s]+\/oauth\/callback)/
|
||
];
|
||
|
||
for (const pattern of patterns) {
|
||
const match = content.match(pattern);
|
||
if (match && match[1]) {
|
||
return match[1];
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function verifyBuild() {
|
||
console.log('\n🔍 Build Verification\n');
|
||
|
||
// Get target from environment variable
|
||
const target = process.env.BUILD_TARGET || 'local';
|
||
|
||
if (!EXPECTED_URIS[target]) {
|
||
log('red', '❌', `Invalid BUILD_TARGET: ${target}`);
|
||
log('blue', 'ℹ', 'Valid targets: docker-local, production');
|
||
process.exit(1);
|
||
}
|
||
|
||
const expectedUri = EXPECTED_URIS[target];
|
||
log('blue', 'ℹ', `Deployment target: ${target}`);
|
||
log('blue', 'ℹ', `Expected redirect URI: ${expectedUri}`);
|
||
|
||
try {
|
||
// Find built assets
|
||
const assetFiles = findBuiltAssets();
|
||
log('green', '✅', `Found ${assetFiles.length} built asset(s)`);
|
||
|
||
// Search for redirect URI in all assets
|
||
let foundUri = null;
|
||
for (const assetFile of assetFiles) {
|
||
const content = fs.readFileSync(assetFile, 'utf8');
|
||
const uri = extractRedirectUri(content);
|
||
|
||
if (uri) {
|
||
foundUri = uri;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!foundUri) {
|
||
log('yellow', '⚠', 'Could not find Discord redirect URI in bundle');
|
||
log('blue', 'ℹ', 'This may be OK if OAuth is not used');
|
||
process.exit(0);
|
||
}
|
||
|
||
log('blue', 'ℹ', `Found redirect URI: ${foundUri}`);
|
||
|
||
// Validate URI matches expected
|
||
if (foundUri === expectedUri) {
|
||
log('green', '✅', 'Redirect URI matches expected value!');
|
||
console.log('\n✅ Build verification passed\n');
|
||
process.exit(0);
|
||
} else {
|
||
log('red', '❌', 'Redirect URI MISMATCH!');
|
||
log('blue', 'ℹ', `Expected: ${expectedUri}`);
|
||
log('blue', 'ℹ', `Found: ${foundUri}`);
|
||
console.log('\n❌ Build verification failed\n');
|
||
console.log(
|
||
'This usually means the wrong .env.{mode} file was used during build.'
|
||
);
|
||
console.log("Check that you're using the correct Vite mode flag:\n");
|
||
console.log(
|
||
' vite build --mode docker-local (for local Docker deployment)'
|
||
);
|
||
console.log(
|
||
' vite build --mode production (for Synology deployment)\n'
|
||
);
|
||
process.exit(1);
|
||
}
|
||
} catch (error) {
|
||
log('red', '❌', `Verification error: ${error.message}`);
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
// Run verification
|
||
verifyBuild();
|