Skip to main content
Glama
publish.js8.19 kB
#!/usr/bin/env node /** * NPM Publish Script for LicenseSpring MCP Server * * Usage: * node scripts/publish.js # Publish stable release * node scripts/publish.js --beta # Publish beta release * node scripts/publish.js --dry-run # Preview publish */ import { execSync } from 'child_process'; import { readFileSync, writeFileSync, statSync } from 'fs'; import { join } from 'path'; class PublishManager { constructor() { this.packagePath = join(process.cwd(), 'package.json'); } log(message, type = 'info') { const colors = { info: '\x1b[36m', // cyan success: '\x1b[32m', // green warning: '\x1b[33m', // yellow error: '\x1b[31m', // red reset: '\x1b[0m' }; const prefix = type === 'error' ? '❌' : type === 'success' ? '✅' : type === 'warning' ? '⚠️' : 'ℹ️'; console.log(`${colors[type]}${prefix} ${message}${colors.reset}`); } getPackageInfo() { const packageJson = JSON.parse(readFileSync(this.packagePath, 'utf8')); return { name: packageJson.name, version: packageJson.version, description: packageJson.description }; } checkNpmAuth() { try { const result = execSync('npm whoami', { encoding: 'utf8' }).trim(); this.log(`Authenticated as: ${result}`, 'success'); return true; } catch (error) { this.log('Not authenticated with NPM. Run: npm login', 'error'); return false; } } runPrePublishChecks(dryRun = false) { this.log('Running pre-publish checks...', 'info'); // Check if we're on main branch try { const branch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim(); if (branch !== 'main' && !dryRun) { this.log(`Warning: Publishing from branch '${branch}' instead of 'main'`, 'warning'); } } catch (error) { this.log('Could not determine git branch', 'warning'); } // Check for uncommitted changes try { const status = execSync('git status --porcelain', { encoding: 'utf8' }).trim(); if (status && !dryRun) { this.log('Warning: You have uncommitted changes', 'warning'); console.log(status); } } catch (error) { this.log('Could not check git status', 'warning'); } // Run tests if (!dryRun) { this.log('Running tests...', 'info'); try { execSync('npm test', { stdio: 'inherit' }); this.log('All tests passed!', 'success'); } catch (error) { this.log('Tests failed! Aborting publish.', 'error'); process.exit(1); } } // Build project if (!dryRun) { this.log('Building project...', 'info'); try { execSync('npm run build', { stdio: 'inherit' }); this.log('Build completed successfully!', 'success'); } catch (error) { this.log('Build failed! Aborting publish.', 'error'); process.exit(1); } } } checkPackageContents(dryRun = false) { this.log('Checking package contents...', 'info'); try { // Check if essential files exist in the file system const essentialFiles = [ { path: 'dist', type: 'directory' }, { path: 'package.json', type: 'file' }, { path: 'README.md', type: 'file' } ]; const missingFiles = essentialFiles.filter(item => { try { const stats = statSync(item.path); if (item.type === 'directory') { return !stats.isDirectory(); } else { return !stats.isFile(); } } catch (error) { return true; // File doesn't exist } }); if (missingFiles.length > 0) { this.log(`Missing essential files: ${missingFiles.map(f => f.path).join(', ')}`, 'error'); process.exit(1); } // Show npm pack output for verification if (dryRun) { this.log('NPM pack preview:', 'info'); const result = execSync('npm pack --dry-run', { encoding: 'utf8' }); console.log(result); } this.log('Package contents verified!', 'success'); } catch (error) { this.log(`Failed to check package contents: ${error.message}`, 'error'); process.exit(1); } } publishToNpm(tag = 'latest', dryRun = false) { const { name, version } = this.getPackageInfo(); this.log(`Publishing ${name}@${version} with tag '${tag}'...`, 'info'); if (dryRun) { this.log('🔍 DRY RUN - Would publish to NPM', 'warning'); return; } try { const publishCommand = tag === 'latest' ? 'npm publish' : `npm publish --tag ${tag}`; execSync(publishCommand, { stdio: 'inherit' }); this.log(`Successfully published ${name}@${version}!`, 'success'); this.log(`📦 NPM: https://www.npmjs.com/package/${name}`, 'info'); this.log(`📋 Install: npm install ${name}@${version}`, 'info'); if (tag !== 'latest') { this.log(`🏷️ Tagged as: ${tag}`, 'info'); this.log(`📋 Install tagged: npm install ${name}@${tag}`, 'info'); } } catch (error) { this.log(`Failed to publish: ${error.message}`, 'error'); process.exit(1); } } updateDistributionDocs() { const { name, version } = this.getPackageInfo(); this.log('Updating distribution documentation...', 'info'); const distributionInfo = ` # Distribution Information ## Latest Release - **Package**: ${name} - **Version**: ${version} - **Published**: ${new Date().toISOString()} ## Installation \`\`\`bash npm install ${name} \`\`\` ## Usage \`\`\`bash # Run License API server npx licensespring-mcp-license # Run Management API server npx licensespring-mcp-management # Run both servers npx licensespring-mcp-server \`\`\` ## Links - [NPM Package](https://www.npmjs.com/package/${name}) - [GitHub Repository](https://github.com/stier1ba/licensespring-mcp) - [Documentation](https://github.com/stier1ba/licensespring-mcp#readme) `; try { writeFileSync('DISTRIBUTION.md', distributionInfo); this.log('Updated DISTRIBUTION.md', 'success'); } catch (error) { this.log(`Failed to update distribution docs: ${error.message}`, 'warning'); } } showUsage() { console.log(` 📦 LicenseSpring MCP Server Publish Manager Usage: node scripts/publish.js [options] Options: --beta Publish as beta release (npm install package@beta) --dry-run Preview publish without actually publishing --skip-checks Skip pre-publish checks (not recommended) Examples: node scripts/publish.js # Publish stable release node scripts/publish.js --beta # Publish beta release node scripts/publish.js --dry-run # Preview publish `); } run() { const args = process.argv.slice(2); if (args.includes('--help') || args.includes('-h')) { this.showUsage(); return; } const dryRun = args.includes('--dry-run'); const beta = args.includes('--beta'); const skipChecks = args.includes('--skip-checks'); const tag = beta ? 'beta' : 'latest'; const { name, version } = this.getPackageInfo(); this.log(`🚀 Starting publish process for ${name}@${version}`, 'info'); if (dryRun) { this.log('🔍 DRY RUN MODE - No actual publishing will occur', 'warning'); } // Check NPM authentication if (!dryRun && !this.checkNpmAuth()) { process.exit(1); } // Run pre-publish checks if (!skipChecks) { this.runPrePublishChecks(dryRun); } // Check package contents this.checkPackageContents(dryRun); // Publish to NPM this.publishToNpm(tag, dryRun); // Update distribution documentation if (!dryRun) { this.updateDistributionDocs(); } if (dryRun) { this.log('🔍 Dry run completed - no changes made', 'info'); } else { this.log('🎉 Publish completed successfully!', 'success'); this.log('📦 Package is now available on NPM', 'info'); } } } // Run the publish manager const publishManager = new PublishManager(); publishManager.run();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stier1ba/licensespring-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server