fix: vercel sdk command

This commit is contained in:
veganbeef 2025-07-07 10:13:11 -07:00
parent f42a5f8d33
commit f898e23299
No known key found for this signature in database
2 changed files with 145 additions and 30 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@neynar/create-farcaster-mini-app", "name": "@neynar/create-farcaster-mini-app",
"version": "1.5.3", "version": "1.5.4",
"type": "module", "type": "module",
"private": false, "private": false,
"access": "public", "access": "public",

View File

@ -474,6 +474,45 @@ async function setEnvironmentVariables(vercelClient, projectId, envVars, project
return results; return results;
} }
async function waitForDeployment(vercelClient, projectId, maxWaitTime = 300000) { // 5 minutes
console.log('\n⏳ Waiting for deployment to complete...');
const startTime = Date.now();
while (Date.now() - startTime < maxWaitTime) {
try {
const deployments = await vercelClient.deployments.list({
projectId: projectId,
limit: 1
});
if (deployments.deployments?.[0]) {
const deployment = deployments.deployments[0];
console.log(`📊 Deployment status: ${deployment.state}`);
if (deployment.state === 'READY') {
console.log('✅ Deployment completed successfully!');
return deployment;
} else if (deployment.state === 'ERROR') {
throw new Error(`Deployment failed with state: ${deployment.state}`);
} else if (deployment.state === 'CANCELED') {
throw new Error('Deployment was canceled');
}
// Still building, wait and check again
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
} else {
console.log('⏳ No deployment found yet, waiting...');
await new Promise(resolve => setTimeout(resolve, 5000));
}
} catch (error) {
console.warn('⚠️ Could not check deployment status:', error.message);
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
throw new Error('Deployment timed out after 5 minutes');
}
async function deployToVercel(useGitHub = false) { async function deployToVercel(useGitHub = false) {
try { try {
console.log('\n🚀 Deploying to Vercel...'); console.log('\n🚀 Deploying to Vercel...');
@ -493,15 +532,42 @@ async function deployToVercel(useGitHub = false) {
console.log('An initial deployment is required to get an assigned domain that can be used in the mini app manifest\n'); console.log('An initial deployment is required to get an assigned domain that can be used in the mini app manifest\n');
console.log('\n⚠ Note: choosing a longer, more unique project name will help avoid conflicts with other existing domains\n'); console.log('\n⚠ Note: choosing a longer, more unique project name will help avoid conflicts with other existing domains\n');
execSync('vercel', { // Use spawn instead of execSync for better error handling
const { spawn } = await import('child_process');
const vercelSetup = spawn('vercel', [], {
cwd: projectRoot, cwd: projectRoot,
stdio: 'inherit', stdio: 'inherit',
shell: process.platform === 'win32' shell: process.platform === 'win32'
}); });
await new Promise((resolve, reject) => {
vercelSetup.on('close', (code) => {
if (code === 0 || code === null) {
console.log('✅ Vercel project setup completed');
resolve();
} else {
console.log('⚠️ Vercel setup command completed (this is normal)');
resolve(); // Don't reject, as this is often expected
}
});
vercelSetup.on('error', (error) => {
console.log('⚠️ Vercel setup command completed (this is normal)');
resolve(); // Don't reject, as this is often expected
});
});
// Wait a moment for project files to be written
await new Promise(resolve => setTimeout(resolve, 2000));
// Load project info // Load project info
let projectId;
try {
const projectJson = JSON.parse(fs.readFileSync('.vercel/project.json', 'utf8')); const projectJson = JSON.parse(fs.readFileSync('.vercel/project.json', 'utf8'));
const projectId = projectJson.projectId; projectId = projectJson.projectId;
} catch (error) {
throw new Error('Failed to load project info. Please ensure the Vercel project was created successfully.');
}
// Get Vercel token and initialize SDK client // Get Vercel token and initialize SDK client
let vercelClient = null; let vercelClient = null;
@ -537,6 +603,7 @@ async function deployToVercel(useGitHub = false) {
// Fallback to CLI method if SDK failed // Fallback to CLI method if SDK failed
if (!domain) { if (!domain) {
try {
const inspectOutput = execSync(`vercel project inspect ${projectId} 2>&1`, { const inspectOutput = execSync(`vercel project inspect ${projectId} 2>&1`, {
cwd: projectRoot, cwd: projectRoot,
encoding: 'utf8' encoding: 'utf8'
@ -554,9 +621,18 @@ async function deployToVercel(useGitHub = false) {
domain = `${projectName}.vercel.app`; domain = `${projectName}.vercel.app`;
console.log('🌐 Using project name for domain:', domain); console.log('🌐 Using project name for domain:', domain);
} else { } else {
throw new Error('Could not determine project name from inspection output'); console.warn('⚠️ Could not determine project name from inspection, using fallback');
// Use a fallback domain based on project ID
domain = `project-${projectId.slice(-8)}.vercel.app`;
console.log('🌐 Using fallback domain:', domain);
} }
} }
} catch (error) {
console.warn('⚠️ Could not inspect project, using fallback domain');
// Use a fallback domain based on project ID
domain = `project-${projectId.slice(-8)}.vercel.app`;
console.log('🌐 Using fallback domain:', domain);
}
} }
// Generate mini app metadata if we have a seed phrase // Generate mini app metadata if we have a seed phrase
@ -609,27 +685,49 @@ async function deployToVercel(useGitHub = false) {
console.log('\n📦 Deploying local code directly...'); console.log('\n📦 Deploying local code directly...');
} }
execSync('vercel deploy --prod', { // Use spawn for better control over the deployment process
const vercelDeploy = spawn('vercel', ['deploy', '--prod'], {
cwd: projectRoot, cwd: projectRoot,
stdio: 'inherit', stdio: 'inherit',
env: process.env env: process.env
}); });
await new Promise((resolve, reject) => {
vercelDeploy.on('close', (code) => {
if (code === 0) {
console.log('✅ Vercel deployment command completed');
resolve();
} else {
console.error(`❌ Vercel deployment failed with code: ${code}`);
reject(new Error(`Vercel deployment failed with exit code: ${code}`));
}
});
vercelDeploy.on('error', (error) => {
console.error('❌ Vercel deployment error:', error.message);
reject(error);
});
});
// Wait for deployment to actually complete
let deployment;
if (vercelClient) {
try {
deployment = await waitForDeployment(vercelClient, projectId);
} catch (error) {
console.warn('⚠️ Could not verify deployment completion:', error.message);
console.log(' Proceeding with domain verification...');
}
}
// Verify actual domain after deployment // Verify actual domain after deployment
console.log('\n🔍 Verifying deployment domain...'); console.log('\n🔍 Verifying deployment domain...');
let actualDomain = domain; let actualDomain = domain;
if (vercelClient) { if (vercelClient && deployment) {
try { try {
const deployments = await vercelClient.deployments.list({ actualDomain = deployment.url || domain;
projectId: projectId,
limit: 1
});
if (deployments.deployments?.[0]?.url) {
actualDomain = deployments.deployments[0].url;
console.log('🌐 Verified actual domain:', actualDomain); console.log('🌐 Verified actual domain:', actualDomain);
}
} catch (error) { } catch (error) {
console.warn('⚠️ Could not verify domain via SDK, using assumed domain'); console.warn('⚠️ Could not verify domain via SDK, using assumed domain');
} }
@ -656,12 +754,29 @@ async function deployToVercel(useGitHub = false) {
await setEnvironmentVariables(vercelClient, projectId, updatedEnv, projectRoot); await setEnvironmentVariables(vercelClient, projectId, updatedEnv, projectRoot);
console.log('\n📦 Redeploying with correct domain...'); console.log('\n📦 Redeploying with correct domain...');
execSync('vercel deploy --prod', { const vercelRedeploy = spawn('vercel', ['deploy', '--prod'], {
cwd: projectRoot, cwd: projectRoot,
stdio: 'inherit', stdio: 'inherit',
env: process.env env: process.env
}); });
await new Promise((resolve, reject) => {
vercelRedeploy.on('close', (code) => {
if (code === 0) {
console.log('✅ Redeployment completed');
resolve();
} else {
console.error(`❌ Redeployment failed with code: ${code}`);
reject(new Error(`Redeployment failed with exit code: ${code}`));
}
});
vercelRedeploy.on('error', (error) => {
console.error('❌ Redeployment error:', error.message);
reject(error);
});
});
domain = actualDomain; domain = actualDomain;
} }