UNPKG

@friggframework/frigg-cli

Version:
118 lines (96 loc) • 5.1 kB
const fs = require('fs-extra'); const path = require('path'); const { findNearestBackendPackageJson } = require('@friggframework/core'); const { generateIAMCloudFormation, getFeatureSummary } = require('../infrastructure/domains/security/iam-generator'); /** * Generate IAM CloudFormation stack based on current app definition * @param {Object} options - Command options */ async function generateIamCommand(options = {}) { try { console.log('šŸ” Finding Frigg application...'); // Find the backend package.json const backendPath = findNearestBackendPackageJson(); if (!backendPath) { console.error('āŒ Could not find backend package.json'); console.error(' Make sure you are in a Frigg application directory'); process.exit(1); } const backendDir = path.dirname(backendPath); const backendFilePath = path.join(backendDir, 'index.js'); if (!fs.existsSync(backendFilePath)) { console.error('āŒ Could not find backend/index.js'); console.error(' Make sure your Frigg application has a backend/index.js file'); process.exit(1); } console.log(`šŸ“± Found Frigg application at: ${backendDir}`); // Load the app definition const backend = require(backendFilePath); const appDefinition = backend.Definition; if (!appDefinition) { console.error('āŒ No Definition found in backend/index.js'); console.error(' Make sure your backend exports a Definition object'); process.exit(1); } // Get feature summary const summary = getFeatureSummary(appDefinition); console.log('\\nšŸ“‹ Application Analysis:'); console.log(` App Name: ${summary.appName}`); console.log(` Integrations: ${summary.integrationCount}`); console.log('\\nšŸ”§ Features Detected:'); console.log(` āœ… Core deployment (always included)`); console.log(` ${summary.features.vpc ? 'āœ…' : 'āŒ'} VPC support`); console.log(` ${summary.features.kms ? 'āœ…' : 'āŒ'} KMS encryption`); console.log(` ${summary.features.ssm ? 'āœ…' : 'āŒ'} SSM Parameter Store`); console.log(` ${summary.features.websockets ? 'āœ…' : 'āŒ'} WebSocket support`); // Generate the CloudFormation template console.log('\\nšŸ—ļø Generating IAM CloudFormation template...'); const deploymentUserName = options.user || 'frigg-deployment-user'; const stackName = options.stackName || 'frigg-deployment-iam'; // Use the summary already extracted above (line 44) const cloudFormationYaml = generateIAMCloudFormation({ appName: summary.appName, features: summary.features, userPrefix: deploymentUserName, stackName }); // Determine output file path const outputDir = options.output || path.join(backendDir, 'infrastructure'); await fs.ensureDir(outputDir); const outputFile = path.join(outputDir, `${stackName}.yaml`); // Write the file await fs.writeFile(outputFile, cloudFormationYaml); console.log(`\\nāœ… IAM CloudFormation template generated successfully!`); console.log(`šŸ“„ File: ${outputFile}`); // Show deployment instructions console.log('\\nšŸ“š Next Steps:'); console.log('\\n1. Deploy the CloudFormation stack:'); console.log(` aws cloudformation deploy \\\\`); console.log(` --template-file ${path.relative(process.cwd(), outputFile)} \\\\`); console.log(` --stack-name ${stackName} \\\\`); console.log(` --capabilities CAPABILITY_NAMED_IAM \\\\`); console.log(` --parameter-overrides DeploymentUserName=${deploymentUserName}`); console.log('\\n2. Retrieve credentials:'); console.log(` aws cloudformation describe-stacks \\\\`); console.log(` --stack-name ${stackName} \\\\`); console.log(` --query 'Stacks[0].Outputs[?OutputKey==\`AccessKeyId\`].OutputValue' \\\\`); console.log(` --output text`); console.log('\\n3. Get secret access key:'); console.log(` aws secretsmanager get-secret-value \\\\`); console.log(` --secret-id frigg-deployment-credentials \\\\`); console.log(` --query SecretString \\\\`); console.log(` --output text | jq -r .SecretAccessKey`); if (options.verbose) { console.log('\\nšŸ” Generated Template Summary:'); console.log(` File size: ${Math.round(cloudFormationYaml.length / 1024)}KB`); console.log(` Features enabled: ${Object.values(summary.features).filter(Boolean).length}`); } } catch (error) { console.error('āŒ Error generating IAM template:', error.message); if (options.verbose) { console.error('Stack trace:', error.stack); } process.exit(1); } } module.exports = { generateIamCommand };