pame-core-cli
Version:
PAME.AI Core Operating System CLI - Open Source AI Platform for Agentic Commerce
592 lines โข 26.6 kB
JavaScript
import { Command } from 'commander';
import { execSync } from 'child_process';
import * as path from 'path';
import * as fs from 'fs';
import { VercelDeploymentSDK } from '../services/vercel-deployment-sdk.js';
import { handleCalendarIntegration } from './deploy-calendar.js';
import chalk from 'chalk';
export const deployCommand = new Command('deploy')
.description('Deployment operations for PAME.AI services')
.addCommand(new Command('all')
.description('Deploy all platforms (www, app, core, store, mcp)')
.option('--production', 'Deploy to production environment')
.option('--use-sdk', 'Use Vercel SDK for enhanced deployment (recommended)', false)
.option('--schedule', 'Schedule deployment using calendar integration')
.option('--check-team', 'Check team availability before deployment')
.action(async (options) => {
if (options.schedule || options.checkTeam) {
await handleCalendarIntegration(options, 'all');
return;
}
console.log(chalk.blue('๐ Deploying all PAME.AI platforms...\n'));
// Deploy in order
await deployWWW(options.production);
await deployApp(options.production);
await deployCore(options.production);
await deployStore(options.production);
await deployMCP(options.production);
console.log(chalk.green('\nโ
All platforms deployed successfully!'));
console.log(chalk.cyan('๐ www.pame.ai - Marketing website'));
console.log(chalk.cyan('๐ app.pame.ai - Developer platform'));
console.log(chalk.cyan('๐ก๏ธ core.pame.ai - Core team platform'));
console.log(chalk.cyan('๐ช store.pame.ai - App marketplace'));
console.log(chalk.cyan('๐ mcp.pame.ai - MCP connector for ChatGPT'));
}))
.addCommand(new Command('www')
.description('Deploy www.pame.ai marketing website')
.option('--production', 'Deploy to production environment')
.option('--use-sdk', 'Use Vercel SDK for enhanced deployment', false)
.action(async (options) => {
if (options.useSdk) {
await deployPlatformWithSDK('www', 'pame-www', options.production);
}
else {
await deployWWW(options.production);
}
}))
.addCommand(new Command('app')
.description('Deploy app.pame.ai developer platform')
.option('--production', 'Deploy to production environment')
.option('--use-sdk', 'Use Vercel SDK for enhanced deployment', false)
.action(async (options) => {
if (options.useSdk) {
await deployPlatformWithSDK('app', 'pame-app', options.production);
}
else {
await deployApp(options.production);
}
}))
.addCommand(new Command('core')
.description('Deploy core.pame.ai internal platform')
.option('--production', 'Deploy to production environment')
.option('--use-sdk', 'Use Vercel SDK for enhanced deployment', false)
.action(async (options) => {
if (options.useSdk) {
await deployPlatformWithSDK('core', 'pame-core', options.production, { RESTRICTED_ACCESS: 'true' });
}
else {
await deployCore(options.production);
}
}))
.addCommand(new Command('store')
.description('Deploy store.pame.ai marketplace platform')
.option('--production', 'Deploy to production environment')
.option('--use-sdk', 'Use Vercel SDK for enhanced deployment', false)
.action(async (options) => {
if (options.useSdk) {
await deployPlatformWithSDK('store', 'pame-store', options.production);
}
else {
await deployStore(options.production);
}
}))
.addCommand(new Command('mcp')
.description('Deploy mcp.pame.ai MCP server for ChatGPT integration')
.option('--production', 'Deploy to production environment')
.option('--use-sdk', 'Use Vercel SDK for enhanced deployment', false)
.action(async (options) => {
if (options.useSdk) {
await deployPlatformWithSDK('mcp', 'pame-mcp', options.production);
}
else {
await deployMCP(options.production);
}
}));
async function deployWWW(production = false) {
console.log('๐ Deploying www.pame.ai marketing website...');
const projectPath = process.cwd();
// Check if we're in the correct directory
if (!fs.existsSync(path.join(projectPath, 'app')) || !fs.existsSync(path.join(projectPath, 'package.json'))) {
console.error('โ Project directory not found. Please run from the root pame.ai directory');
process.exit(1);
}
try {
console.log(`๐ Working in: ${projectPath}`);
// Link to the pame-www project
console.log('๐ Linking to pame-www project...');
execSync('vercel link --yes --project pame-www', { stdio: 'inherit' });
// Create www-specific vercel config
const wwwVercelConfig = {
version: 2,
alias: production ? ['www.pame.ai', 'pame.ai'] : [],
regions: ['iad1'],
buildCommand: 'npm run build',
outputDirectory: '.next',
framework: 'nextjs',
env: {
NEXT_PUBLIC_PLATFORM: 'www',
NEXT_PUBLIC_API_URL: 'https://api.pame.ai'
},
rewrites: [
// Block access to app routes
{ source: '/saas/(.*)', destination: '/404' },
{ source: '/core/(.*)', destination: '/404' },
{ source: '/api/saas/(.*)', destination: '/404' },
{ source: '/api/core/(.*)', destination: '/404' }
]
};
// Write config file
fs.writeFileSync('vercel-www.json', JSON.stringify(wwwVercelConfig, null, 2));
console.log('๐ฆ Installing dependencies...');
execSync('npm install', { stdio: 'inherit' });
console.log('๐๏ธ Building marketing website...');
execSync('npm run build', { stdio: 'inherit' });
console.log('โ๏ธ Deploying marketing website to www.pame.ai...');
// Deploy to the linked project
const deployCmd = production
? 'vercel --prod --yes -A vercel-www.json'
: 'vercel --yes -A vercel-www.json';
console.log(`๐ Using config: vercel-www.json`);
console.log(`๐ Running: ${deployCmd}`);
execSync(deployCmd, { stdio: 'inherit' });
if (production) {
console.log('๐ Adding custom domains...');
try {
execSync('vercel domains add www.pame.ai --scope=getaifactory', { stdio: 'inherit' });
execSync('vercel domains add pame.ai --scope=getaifactory', { stdio: 'inherit' });
}
catch (error) {
console.log('โน๏ธ Domains may already exist or need manual configuration in Vercel dashboard');
}
}
console.log('โ
www.pame.ai marketing website deployed successfully!');
console.log('๐ Visit: https://www.pame.ai');
// Clean up
fs.unlinkSync('vercel-www.json');
console.log('๐งน Cleaned up temporary config file');
}
catch (error) {
console.error('โ WWW deployment failed:', error);
process.exit(1);
}
}
async function deployApp(production = false) {
console.log('๐ Deploying app.pame.ai developer platform...');
const projectPath = process.cwd();
// Check if we're in the correct directory
if (!fs.existsSync(path.join(projectPath, 'app')) || !fs.existsSync(path.join(projectPath, 'package.json'))) {
console.error('โ Project directory not found. Please run from the root pame.ai directory');
process.exit(1);
}
try {
console.log(`๐ Working in: ${projectPath}`);
// Link to the pame-app project
console.log('๐ Linking to pame-app project...');
execSync('vercel link --yes --project pame-app', { stdio: 'inherit' });
// Create app-specific vercel config
const appVercelConfig = {
version: 2,
alias: production ? ['app.pame.ai'] : [],
regions: ['iad1'],
buildCommand: 'npm run build',
outputDirectory: '.next',
framework: 'nextjs',
env: {
NEXT_PUBLIC_PLATFORM: 'app',
NEXT_PUBLIC_API_URL: 'https://api.pame.ai',
ENABLE_AUTH: 'true'
},
rewrites: [
// Block access to other platforms
{ source: '/core/(.*)', destination: '/404' }
],
functions: {
'app/api/**': {
maxDuration: 60
}
}
};
// Write config file
fs.writeFileSync('vercel-app.json', JSON.stringify(appVercelConfig, null, 2));
console.log('๐ฆ Installing dependencies...');
execSync('npm install', { stdio: 'inherit' });
console.log('๐๏ธ Building developer platform...');
execSync('npm run build', { stdio: 'inherit' });
console.log('โ๏ธ Deploying developer platform to app.pame.ai...');
// Deploy to the linked project
const deployCmd = production
? 'vercel --prod --yes -A vercel-app.json'
: 'vercel --yes -A vercel-app.json';
console.log(`๐ Using config: vercel-app.json`);
console.log(`๐ Running: ${deployCmd}`);
execSync(deployCmd, { stdio: 'inherit' });
if (production) {
console.log('๐ Adding custom domain app.pame.ai...');
try {
execSync('vercel domains add app.pame.ai --scope=getaifactory', { stdio: 'inherit' });
}
catch (error) {
console.log('โน๏ธ Domain may already exist or need manual configuration in Vercel dashboard');
}
}
console.log('โ
app.pame.ai developer platform deployed successfully!');
console.log('๐ Visit: https://app.pame.ai');
console.log('๐ Login with Google OAuth or use pame login from CLI');
// Clean up
fs.unlinkSync('vercel-app.json');
console.log('๐งน Cleaned up temporary config file');
}
catch (error) {
console.error('โ App deployment failed:', error);
process.exit(1);
}
}
async function deployCore(production = false) {
console.log('๐ก๏ธ Deploying core.pame.ai internal platform...');
const projectPath = process.cwd();
// Check if we're in the correct directory
if (!fs.existsSync(path.join(projectPath, 'app')) || !fs.existsSync(path.join(projectPath, 'package.json'))) {
console.error('โ Project directory not found. Please run from the root pame.ai directory');
process.exit(1);
}
try {
console.log(`๐ Working in: ${projectPath}`);
// Link to the pame-core project
console.log('๐ Linking to pame-core project...');
execSync('vercel link --yes --project pame-core', { stdio: 'inherit' });
// Create core-specific vercel config
const coreVercelConfig = {
version: 2,
alias: production ? ['core.pame.ai'] : [],
regions: ['iad1'],
buildCommand: 'npm run build',
outputDirectory: '.next',
framework: 'nextjs',
env: {
NEXT_PUBLIC_PLATFORM: 'core',
NEXT_PUBLIC_API_URL: 'https://api.pame.ai',
ENABLE_AUTH: 'true',
RESTRICTED_ACCESS: 'true'
},
rewrites: [
// Core platform routes
{ source: '/', destination: '/core' },
{ source: '/login', destination: '/core/login' },
{ source: '/cli-auth', destination: '/core/cli-auth' },
{ source: '/dashboard', destination: '/core/dashboard' },
// API routes
{ source: '/api/(.*)', destination: '/api/core/$1' },
// Block access to other platforms
{ source: '/saas/(.*)', destination: '/404' },
{ source: '/app/(.*)', destination: '/404' }
],
functions: {
'app/api/**': {
maxDuration: 60
}
},
headers: [
{
source: '/(.*)',
headers: [
{
key: 'X-Content-Type-Options',
value: 'nosniff'
},
{
key: 'X-Frame-Options',
value: 'DENY'
},
{
key: 'X-XSS-Protection',
value: '1; mode=block'
}
]
}
]
};
// Write config file
fs.writeFileSync('vercel-core.json', JSON.stringify(coreVercelConfig, null, 2));
console.log('๐ฆ Installing dependencies...');
execSync('npm install', { stdio: 'inherit' });
console.log('๐๏ธ Building core platform...');
execSync('npm run build', { stdio: 'inherit' });
console.log('โ๏ธ Deploying core platform to core.pame.ai...');
// Deploy to the linked project
const deployCmd = production
? 'vercel --prod --yes -A vercel-core.json'
: 'vercel --yes -A vercel-core.json';
console.log(`๐ Using config: vercel-core.json`);
console.log(`๐ Running: ${deployCmd}`);
execSync(deployCmd, { stdio: 'inherit' });
if (production) {
console.log('๐ Adding custom domain core.pame.ai...');
try {
execSync('vercel domains add core.pame.ai --scope=getaifactory', { stdio: 'inherit' });
}
catch (error) {
console.log('โน๏ธ Domain may already exist or need manual configuration in Vercel dashboard');
}
}
console.log('โ
core.pame.ai platform deployed successfully!');
console.log('๐ Visit: https://core.pame.ai');
console.log('๐ Core team access only - Login with: alec@getaifactory.com / 1234');
console.log('๐ก๏ธ Secured with role-based access control');
// Clean up
fs.unlinkSync('vercel-core.json');
console.log('๐งน Cleaned up temporary config file');
}
catch (error) {
console.error('โ Core deployment failed:', error);
process.exit(1);
}
}
async function deployStore(production = false) {
console.log('๐ช Deploying store.pame.ai marketplace platform...');
const projectPath = process.cwd();
// Check if we're in the correct directory
if (!fs.existsSync(path.join(projectPath, 'app')) || !fs.existsSync(path.join(projectPath, 'package.json'))) {
console.error('โ Project directory not found. Please run from the root pame.ai directory');
process.exit(1);
}
try {
console.log(`๐ Working in: ${projectPath}`);
// Link to the pame-store project
console.log('๐ Linking to pame-store project...');
execSync('vercel link --yes --project pame-store', { stdio: 'inherit' });
// Create store-specific vercel config
const storeVercelConfig = {
version: 2,
alias: production ? ['store.pame.ai'] : [],
regions: ['iad1'],
buildCommand: 'npm run build',
outputDirectory: '.next',
framework: 'nextjs',
env: {
NEXT_PUBLIC_PLATFORM: 'store',
NEXT_PUBLIC_API_URL: 'https://api.pame.ai',
ENABLE_AUTH: 'true'
},
rewrites: [
// Store-specific rewrites
{ source: '/business/:path*', destination: '/store/:path*' },
{ source: '/marketplace/:path*', destination: '/store/:path*' },
// Block other platform routes
{ source: '/saas/(.*)', destination: '/404' },
{ source: '/core/(.*)', destination: '/404' },
{ source: '/api/core/(.*)', destination: '/404' }
]
};
// Write config file
fs.writeFileSync('vercel-store.json', JSON.stringify(storeVercelConfig, null, 2));
console.log('๐ฆ Installing dependencies...');
execSync('npm install', { stdio: 'inherit' });
console.log('๐๏ธ Building marketplace platform...');
execSync('npm run build', { stdio: 'inherit' });
console.log('โ๏ธ Deploying marketplace to store.pame.ai...');
// Deploy to the linked project
const deployCmd = production
? 'vercel --prod --yes -A vercel-store.json'
: 'vercel --yes -A vercel-store.json';
console.log(`๐ Using config: vercel-store.json`);
console.log(`๐ Running: ${deployCmd}`);
execSync(deployCmd, { stdio: 'inherit' });
if (production) {
console.log('๐ Adding custom domain store.pame.ai...');
try {
execSync('vercel domains add store.pame.ai --scope=getaifactory', { stdio: 'inherit' });
}
catch (error) {
console.log('โน๏ธ Domain may already exist or need manual configuration in Vercel dashboard');
}
}
console.log('โ
store.pame.ai marketplace deployed successfully!');
console.log('๐ช Visit: https://store.pame.ai');
console.log('๐ฆ Features: AI app marketplace, discovery, vetting, and distribution');
console.log('๐ Compliance: SOC2, ISO 27001, GDPR ready');
// Clean up
fs.unlinkSync('vercel-store.json');
console.log('๐งน Cleaned up temporary config file');
}
catch (error) {
console.error('โ Store deployment failed:', error);
process.exit(1);
}
}
async function deployMCP(production = false) {
const environment = production ? 'production' : 'staging';
console.log(chalk.blue(`๐ Deploying MCP server to ${environment}...`));
try {
// Change to MCP project directory
const mcpDir = path.join(process.cwd(), 'mcp-pame-ai');
if (!fs.existsSync(mcpDir)) {
throw new Error('MCP project directory not found. Run this from the project root.');
}
process.chdir(mcpDir);
// Install dependencies
console.log(chalk.gray('๐ฆ Installing dependencies...'));
execSync('npm install', { stdio: 'inherit' });
// Build the project
console.log(chalk.gray('๐๏ธ Building MCP server...'));
execSync('npm run build', { stdio: 'inherit' });
// Deploy to Vercel
const deployCommand = production ? 'vercel --prod' : 'vercel';
console.log(chalk.gray(`๐ Deploying to Vercel (${environment})...`));
execSync(deployCommand, { stdio: 'inherit' });
console.log(chalk.green(`โ
MCP server deployed successfully to ${environment}!`));
console.log(chalk.cyan(`๐ URL: https://mcp.pame.ai${production ? '' : '-staging'}`));
console.log(chalk.gray('๐ MCP Connector URL: https://mcp.pame.ai/sse/'));
}
catch (error) {
console.error(chalk.red(`โ MCP deployment failed: ${error.message}`));
process.exit(1);
}
finally {
// Return to original directory
process.chdir('..');
}
}
async function deploySubdomain(subdomain, production = false, skipDns = false) {
console.log(`๐ Deploying ${subdomain}.pame.ai...`);
const projectPath = process.cwd();
const projectName = `pame-${subdomain}`;
// Check if we're in the correct directory
if (!fs.existsSync(path.join(projectPath, 'app')) || !fs.existsSync(path.join(projectPath, 'package.json'))) {
console.error('โ Project directory not found. Please run from the root pame.ai directory');
process.exit(1);
}
try {
console.log(`๐ Working in: ${projectPath}`);
// Link to the subdomain project
console.log(`๐ Linking to ${projectName} project...`);
try {
execSync(`vercel link --yes --project ${projectName}`, { stdio: 'inherit' });
}
catch (error) {
console.error(`โ Failed to link to project ${projectName}. Make sure it exists.`);
console.log(`๐ก Create the project first with: pame-core subdomain create ${subdomain}`);
process.exit(1);
}
// Create subdomain-specific vercel config
const subdomainVercelConfig = {
version: 2,
alias: production ? [`${subdomain}.pame.ai`] : [],
regions: ['iad1'],
buildCommand: 'npm run build',
outputDirectory: '.next',
framework: 'nextjs',
env: {
NEXT_PUBLIC_PLATFORM: subdomain,
NEXT_PUBLIC_API_URL: 'https://api.pame.ai',
ENABLE_AUTH: 'true'
},
rewrites: [
// Block access to other platform routes
{ source: '/core/(.*)', destination: '/404' },
{ source: '/saas/(.*)', destination: '/404' }
],
functions: {
'app/api/**': {
maxDuration: 60
}
}
};
// Write config file
const configFile = `vercel-${subdomain}.json`;
fs.writeFileSync(configFile, JSON.stringify(subdomainVercelConfig, null, 2));
console.log('๐ฆ Installing dependencies...');
execSync('npm install', { stdio: 'inherit' });
console.log(`๐๏ธ Building ${subdomain} platform...`);
execSync('npm run build', { stdio: 'inherit' });
console.log(`โ๏ธ Deploying to ${subdomain}.pame.ai...`);
// Deploy to the linked project
const deployCmd = production
? `vercel --prod --yes -A ${configFile}`
: `vercel --yes -A ${configFile}`;
console.log(`๐ Using config: ${configFile}`);
console.log(`๐ Running: ${deployCmd}`);
execSync(deployCmd, { stdio: 'inherit' });
if (production) {
console.log(`๐ Adding custom domain ${subdomain}.pame.ai...`);
try {
execSync(`vercel domains add ${subdomain}.pame.ai --scope=getaifactory`, { stdio: 'inherit' });
}
catch (error) {
console.log('โน๏ธ Domain may already exist or need manual configuration in Vercel dashboard');
}
// Verify DNS if not skipped
if (!skipDns) {
console.log('๐ Verifying DNS configuration...');
try {
const { GoDaddyManager } = await import('../services/godaddy-manager.js');
const godaddyManager = new GoDaddyManager();
// Get current DNS records
const cnameRecords = await godaddyManager.getRecords('CNAME', subdomain);
const txtRecords = await godaddyManager.getRecords('TXT', '_vercel');
if (cnameRecords.length === 0) {
console.log(`โ ๏ธ No CNAME record found for ${subdomain}.pame.ai`);
console.log(`๐ก Set up DNS with: pame-core subdomain create ${subdomain}`);
}
const relevantTxtRecords = txtRecords.filter(record => record.data.includes(`${subdomain}.pame.ai`));
if (relevantTxtRecords.length === 0) {
console.log(`โ ๏ธ No TXT verification record found for ${subdomain}.pame.ai`);
console.log(`๐ก Set up DNS with: pame-core subdomain create ${subdomain}`);
}
if (cnameRecords.length > 0 && relevantTxtRecords.length > 0) {
console.log('โ
DNS configuration looks good');
}
}
catch (error) {
console.log('โ ๏ธ Could not verify DNS configuration:', error instanceof Error ? error.message : String(error));
}
}
}
console.log(`โ
${subdomain}.pame.ai deployed successfully!`);
console.log(`๐ Visit: https://${subdomain}.pame.ai`);
console.log(`๐ง Project: ${projectName}`);
// Clean up
fs.unlinkSync(configFile);
console.log('๐งน Cleaned up temporary config file');
}
catch (error) {
console.error(`โ ${subdomain} deployment failed:`, error instanceof Error ? error.message : String(error));
process.exit(1);
}
}
// New SDK-based deployment functions
async function deployAllWithSDK(production = false) {
try {
const deploymentSDK = new VercelDeploymentSDK();
const results = await deploymentSDK.deployAllPlatforms(production);
// Enhanced testing after deployment
console.log(chalk.blue('\n๐ Testing deployed endpoints...\n'));
for (const result of results) {
if (result.success && result.deployment.url) {
await deploymentSDK.testEndpoint(result.deployment.url);
}
}
const successCount = results.filter(r => r.success).length;
console.log(chalk.green(`\n๐ SDK deployment completed: ${successCount}/${results.length} successful`));
}
catch (error) {
console.error(chalk.red('โ SDK deployment failed:'), error instanceof Error ? error.message : String(error));
process.exit(1);
}
}
async function deployPlatformWithSDK(platform, projectName, production = false, envVars = {}) {
const sdk = new VercelDeploymentSDK();
const config = {
platform,
projectName,
production,
envVars: {
NEXT_PUBLIC_PLATFORM: platform,
NEXT_PUBLIC_API_URL: 'https://api.pame.ai',
...envVars
}
};
console.log(chalk.blue(`๐ Deploying ${platform}.pame.ai using Vercel SDK...`));
try {
const result = await sdk.deploy(config);
console.log(chalk.green(`โ
${platform}.pame.ai deployed successfully!`));
console.log(chalk.cyan(`๐ URL: ${result.url}`));
if (platform === 'mcp') {
console.log(chalk.gray('๐ MCP Connector URL: https://mcp.pame.ai/sse/'));
}
}
catch (error) {
console.error(chalk.red(`โ ${platform} deployment failed: ${error.message}`));
throw error;
}
} // Calendar integration function
//# sourceMappingURL=deploy.js.map