@nuxfly/cli
Version:
CLI tool for deploying Nuxt applications to Fly.io
128 lines (104 loc) • 4.87 kB
JavaScript
import { join } from 'path';
import consola from 'consola';
import { ensureNuxflyDir, writeFile, copyDistDir, copyDrizzleMigrations } from '../utils/filesystem.mjs';
import { withErrorHandling } from '../utils/errors.mjs';
import { hasDistDir, getEnvironmentSpecificFlyTomlPath } from '../utils/config.mjs';
import { buildApplication, installNuxflyDependencies } from '../utils/build.mjs';
import { generateDockerfile, generateDockerignore } from '../templates/dockerfile.mjs';
import { generateFlyToml } from '../templates/fly-toml.mjs';
import { generateDrizzleConfig, generateLitestreamConfig, generateStartScript, generateDrizzlePackageJson } from '../templates/database.mjs';
/**
* Generate command - creates all fly-related files in .nuxfly directory
*/
export const generate = withErrorHandling(async (args, config) => {
consola.info('⚡ Generating deployment files...');
// Note: Generate command creates fly.toml, so we don't validate its existence first
// Validate Nuxt project structure
if (!hasDistDir(config) && !args.build) {
consola.error('❌ No .output directory found! Please build your Nuxt application first.');
process.exit(1);
}
let step = 1;
// Build the application first (unless --no-build is specified)
if (args.build) {
consola.info(`Step ${step++}: Building application...`);
await buildApplication({ skipBuild: !args.build });
}
// Ensure .nuxfly directory exists
const nuxflyDir = await ensureNuxflyDir(config);
try {
// Generate environment-specific fly.toml
consola.info(`Step ${step++}: Generating fly.toml...`);
const flyTomlContent = generateFlyToml(config);
const flyTomlPath = getEnvironmentSpecificFlyTomlPath() || join(process.cwd(), 'fly.toml');
await writeFile(flyTomlPath, flyTomlContent);
consola.success(`Generated fly.toml at: ${flyTomlPath}`);
// Generate Dockerfile
consola.info(`Step ${step++}: Generating Dockerfile...`);
const dockerfileContent = generateDockerfile({
nodeVersion: config.nodeVersion,
});
await writeFile(join(nuxflyDir, 'Dockerfile'), dockerfileContent);
// Generate .dockerignore
consola.info(`Step ${step++}: Generating .dockerignore...`);
const dockerignoreContent = generateDockerignore();
await writeFile(join(process.cwd(), '.dockerignore'), dockerignoreContent);
// Generate database-related files
consola.info(`Step ${step++}: Generating database configuration files...`);
// Generate drizzle.config.ts
const drizzleConfigContent = generateDrizzleConfig();
await writeFile(join(nuxflyDir, 'drizzle.config.ts'), drizzleConfigContent);
// Generate litestream.yml
const litestreamConfigContent = generateLitestreamConfig({});
await writeFile(join(nuxflyDir, 'litestream.yml'), litestreamConfigContent);
// Generate start.sh
const startScriptContent = generateStartScript();
await writeFile(join(nuxflyDir, 'start.sh'), startScriptContent);
// Generate package.json for drizzle-kit
const drizzlePackageJsonContent = await generateDrizzlePackageJson();
await writeFile(join(nuxflyDir, 'package.json'), drizzlePackageJsonContent);
// Install dependencies to populate package-lock.json
await installNuxflyDependencies(nuxflyDir);
// Copy drizzle migrations from parent project
await copyDrizzleMigrations(config);
// Copy dist directory if it exists
if (hasDistDir(config)) {
consola.info(`Step ${step++}: Copying .output directory...`);
await copyDistDir(config);
} else {
consola.debug('No dist directory found, skipping copy');
}
consola.success('✅ All deployment files generated successfully!');
// Display generated files
displayGeneratedFiles(hasDistDir(config), args.build);
} catch (error) {
throw new Error(`Failed to generate deployment files: ${error.message}`);
}
});
/**
* Display list of generated files
*/
function displayGeneratedFiles(hasDistCopy, build) {
const flyTomlPath = getEnvironmentSpecificFlyTomlPath() || 'fly.toml';
const files = [
`📄 ${flyTomlPath} (Fly.io configuration)`,
'🚫 .dockerignore (build exclusions)',
'🐳 .nuxfly/Dockerfile (container image)',
'⚙️ .nuxfly/drizzle.config.ts (database configuration)',
'💾 .nuxfly/litestream.yml (database backup configuration)',
'🚀 .nuxfly/start.sh (startup script)',
'📦 .nuxfly/package.json (drizzle-kit dependencies)',
'🔒 .nuxfly/package-lock.json (dependency lock file)',
];
if (hasDistCopy) {
files.push('📁 .output/ (application '+(build ? 'built' : 'not built')+')');
}
consola.box({
title: '📁 Generated files',
message: files.join('\n'),
style: {
borderColor: 'cyan',
padding: 1,
},
});
}