UNPKG

@puls-atlas/cli

Version:

The Puls Atlas CLI tool for managing Atlas projects

151 lines 4.22 kB
import chalk from 'chalk'; import inquirer from 'inquirer'; import { warnIfNotReleaseBranch } from '../../utils/git.js'; import { requireFirebaseJson, resolveFirestoreIndexesSourceLabel, selectProject } from '../../utils/firebase.js'; import { logger } from '../../utils/logger.js'; import { execSync } from '../../utils/index.js'; const FIRESTORE_INDEXES_DEPLOY_TARGET = 'firestore:indexes'; const outputDeploymentSummary = ({ indexesSourceLabel, loggerImpl = logger, projectId }) => { loggerImpl.summary('Deployment plan', [{ label: 'Consumer project', value: projectId, tone: 'warning' }, { label: 'Deploy target', value: 'Firestore indexes', tone: 'accent' }, { label: 'Source', value: indexesSourceLabel, tone: 'warning' }], { spacing: 'after' }); }; const outputDeploymentOutcomeSummary = ({ indexesSourceLabel, loggerImpl = logger, projectId }) => { loggerImpl.summary('Deployment outcome', [{ label: 'Consumer project', value: projectId, tone: 'warning' }, { label: 'Deploy target', value: 'Firestore indexes', tone: 'accent' }, { label: 'Source', value: indexesSourceLabel, tone: 'warning' }, { label: 'Status', value: 'deployed', tone: 'success' }], { spacing: 'after' }); }; const confirmIndexesDeployment = async ({ indexesSourceLabel, projectId, promptImpl = inquirer.prompt }) => { const { isConfirmed } = await promptImpl([{ type: 'confirm', name: 'isConfirmed', default: false, message: `Deploy Firestore indexes from ${chalk.cyan(indexesSourceLabel)} ` + `to consumer project ${chalk.bold(projectId)}?` }]); return isConfirmed; }; export const createDeployIndexesHandler = (dependencies = {}) => { const { execSyncImpl = execSync, loggerImpl = logger, promptImpl = inquirer.prompt, requireFirebaseJsonImpl = requireFirebaseJson, resolveFirestoreIndexesSourceLabelImpl = resolveFirestoreIndexesSourceLabel, selectProjectImpl = selectProject, warnIfNotReleaseBranchImpl = warnIfNotReleaseBranch } = dependencies; return async () => { try { warnIfNotReleaseBranchImpl({ loggerImpl }); const { projectId } = await selectProjectImpl('.firebaserc', { promptMessage: 'Select a Google Cloud consumer project to deploy indexes to:' }); const firebaseJson = requireFirebaseJsonImpl(); const indexesSourceLabel = resolveFirestoreIndexesSourceLabelImpl(firebaseJson); if (!indexesSourceLabel) { loggerImpl.error('No Firestore indexes configuration found in firebase.json.', { exit: true, exitCode: 1 }); return false; } outputDeploymentSummary({ indexesSourceLabel, loggerImpl, projectId }); const isConfirmed = await confirmIndexesDeployment({ indexesSourceLabel, projectId, promptImpl }); if (!isConfirmed) { loggerImpl.warning('Deployment cancelled by the user.'); return false; } const spinner = loggerImpl.spinner('Deploying Firestore indexes...'); try { execSyncImpl('firebase deploy', { only: FIRESTORE_INDEXES_DEPLOY_TARGET, project: projectId, stdio: 'inherit' }); spinner.succeed('Firestore indexes deployed successfully.'); } catch (error) { spinner.fail('Deployment failed. See the error above for details.'); loggerImpl.error(error, { exit: true, exitCode: 1 }); return false; } outputDeploymentOutcomeSummary({ indexesSourceLabel, loggerImpl, projectId }); loggerImpl.success('Done!'); return true; } catch (error) { if (error instanceof Error && error.name === 'ExitPromptError') { loggerImpl.error('Deployment cancelled by the user.', { exit: true, exitCode: 130 }); return false; } loggerImpl.error(error, { exit: true, exitCode: 1 }); return false; } }; }; export default createDeployIndexesHandler();