@puls-atlas/cli
Version:
The Puls Atlas CLI tool for managing Atlas projects
97 lines • 2.93 kB
JavaScript
import { randomBytes } from 'node:crypto';
import chalk from 'chalk';
import inquirer from 'inquirer';
import { getRequiredFirebasercProjects } from '../../utils/firebase.js';
import { logger } from '../../utils/logger.js';
import { createSecret } from '../../utils/secrets.js';
const SECRET_DEFINITIONS = [{
key: 'puls-atlas-api-key',
value: randomBytesImpl => createSecretValue(16, {
randomBytesImpl
})
}, {
key: 'puls-atlas-jwt',
value: randomBytesImpl => createSecretValue(32, {
randomBytesImpl
})
}, {
key: 'puls-gcr-auth-token',
value: randomBytesImpl => createSecretValue(32, {
randomBytesImpl
})
}];
const isSecretAlreadyExistsError = (error, secretName) => error instanceof Error && error.message === `Secret ${secretName} already exists`;
export const createSecretValue = (length = 32, dependencies = {}) => {
const {
randomBytesImpl = randomBytes
} = dependencies;
return randomBytesImpl(Math.ceil(length / 2)).toString('hex').slice(0, length);
};
export const confirmCreateSecret = async ({
createSecretImpl = createSecret,
loggerImpl = logger,
projectId,
promptImpl = inquirer.prompt,
secretName,
secretValue
}) => {
const {
shouldCreate
} = await promptImpl([{
type: 'confirm',
name: 'shouldCreate',
default: false,
message: `Do you want to create the secret ${chalk.yellow(secretName)} ` + `for project ${chalk.yellow(projectId)}?`
}]);
if (!shouldCreate) {
return 'skipped';
}
const spinner = loggerImpl.spinner(`Creating secret ${secretName}...`);
try {
await createSecretImpl(secretName, secretValue, projectId);
spinner.succeed(`Secret ${secretName} created successfully.`);
return 'created';
} catch (error) {
if (isSecretAlreadyExistsError(error, secretName)) {
spinner.succeed(`Secret ${secretName} already exists.`);
return 'existing';
}
spinner.fail(`Failed to create secret ${secretName}: ${error.message}`);
throw error;
}
};
export default async (dependencies = {}) => {
const {
createSecret: createSecretImpl = createSecret,
getRequiredFirebasercProjects: getRequiredFirebasercProjectsImpl = getRequiredFirebasercProjects,
logger: loggerImpl = logger,
prompt: promptImpl = inquirer.prompt,
randomBytes: randomBytesImpl = randomBytes
} = dependencies;
const {
developmentProjectId,
productionProjectId
} = getRequiredFirebasercProjectsImpl();
for (const {
key,
value
} of SECRET_DEFINITIONS) {
await confirmCreateSecret({
createSecretImpl,
loggerImpl,
projectId: productionProjectId,
promptImpl,
secretName: key,
secretValue: value(randomBytesImpl)
});
await confirmCreateSecret({
createSecretImpl,
loggerImpl,
projectId: developmentProjectId,
promptImpl,
secretName: key,
secretValue: value(randomBytesImpl)
});
}
return true;
};