url-builder-mcp
Version:
URL Builder MCP Server - Professional URL construction with intelligent parameter handling for Claude Desktop
170 lines (142 loc) ⢠4.55 kB
JavaScript
/**
* Pre-publish verification script
* Ensures zero errors, warnings, and test failures before NPM publication
*/
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
// ANSI color codes
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m'
};
function log(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
function runCommand(command, description) {
log(`\nš ${description}...`, 'cyan');
try {
const output = execSync(command, {
encoding: 'utf8',
stdio: 'pipe',
cwd: process.cwd()
});
log(`ā
${description} passed`, 'green');
return { success: true, output };
} catch (error) {
log(`ā ${description} failed`, 'red');
log(`Error: ${error.message}`, 'red');
if (error.stdout) {
log(`Output: ${error.stdout}`, 'yellow');
}
if (error.stderr) {
log(`Error output: ${error.stderr}`, 'red');
}
return { success: false, error };
}
}
function checkPackageJson() {
log('\nš¦ Checking package.json...', 'cyan');
const packagePath = path.join(process.cwd(), 'package.json');
if (!fs.existsSync(packagePath)) {
log('ā package.json not found', 'red');
return false;
}
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
// Check required fields
const requiredFields = ['name', 'version', 'description', 'main', 'bin'];
for (const field of requiredFields) {
if (!pkg[field]) {
log(`ā Missing required field: ${field}`, 'red');
return false;
}
}
// Check bin file exists
if (pkg.bin && typeof pkg.bin === 'object') {
for (const [name, binPath] of Object.entries(pkg.bin)) {
const fullPath = path.join(process.cwd(), binPath);
if (!fs.existsSync(fullPath)) {
log(`ā Bin file not found: ${binPath}`, 'red');
return false;
}
}
}
log('ā
package.json validation passed', 'green');
return true;
}
function checkFiles() {
log('\nš Checking required files...', 'cyan');
const requiredFiles = [
'README.md',
'LICENSE',
'dist/index.js',
'bin/url-builder-mcp.js'
];
for (const file of requiredFiles) {
const filePath = path.join(process.cwd(), file);
if (!fs.existsSync(filePath)) {
log(`ā Required file not found: ${file}`, 'red');
return false;
}
}
log('ā
All required files present', 'green');
return true;
}
async function main() {
log('š Pre-Publish Quality Gate - Zero Defects Policy', 'bright');
log('ā'.repeat(60), 'blue');
const checks = [
// Package validation
() => checkPackageJson(),
() => checkFiles(),
// Code quality checks
() => runCommand('npm run type-check', 'TypeScript type checking').success,
() => runCommand('npm run lint', 'ESLint validation (zero warnings)').success,
() => runCommand('npm run format:check', 'Prettier format checking').success,
// Testing
() => runCommand('npm run test', 'Unit tests').success,
() => runCommand('npm run test:coverage', 'Test coverage').success,
// Build verification
() => runCommand('npm run build', 'TypeScript compilation').success,
// Package verification
() => runCommand('npm pack --dry-run', 'NPM package validation').success,
// Launcher verification
() => runCommand('node bin/url-builder-mcp.js --help', 'Launcher functionality').success
];
let allPassed = true;
for (let i = 0; i < checks.length; i++) {
const checkPassed = checks[i]();
if (!checkPassed) {
allPassed = false;
break;
}
}
log('\n' + 'ā'.repeat(60), 'blue');
if (allPassed) {
log('š ALL QUALITY GATES PASSED!', 'green');
log('ā
Zero errors, zero warnings, zero test failures', 'green');
log('š Package is ready for NPM publication', 'green');
log('\nTo publish:', 'cyan');
log(' npm publish', 'bright');
process.exit(0);
} else {
log('ā QUALITY GATE FAILED!', 'red');
log('š« Cannot publish with errors or warnings', 'red');
log('š§ Please fix all issues before publishing', 'yellow');
process.exit(1);
}
}
// Run if called directly
if (require.main === module) {
main().catch(error => {
log(`š„ Unexpected error: ${error.message}`, 'red');
process.exit(1);
});
}
module.exports = { main };