nav-new-publication-cli
Version:
Add new publication to the navigator web project
250 lines (215 loc) • 6.57 kB
text/typescript
#!/usr/bin/env node
import { Command } from 'commander';
import prompts from 'prompts';
import { cyan, green, red } from 'picocolors';
import { readJson, writeJson, existsSync } from 'fs-extra';
import { resolve } from 'path';
import { logError, logWarn, logSuccess } from './utils';
import { loadJson, writePublicationJson, PublicationData } from './readWritePublications';
import { PromptConfig, createPrompts } from './prompts';
import { updateFiles } from './fileUpdates';
import { checkArn, checkNotEmpty, stripSpace, checkName, checkDomain } from './checkers';
const program = new Command();
const handleSigTerm = () => process.exit(0)
process.on('SIGINT', handleSigTerm);
process.on('SIGTERM', handleSigTerm);
(async ()=> {
const packageObj = await loadJson(resolve('./package.json'), {
error: 'Error loading package.json',
success: null
});
program
.version(
packageObj.version,
'-v, --version',
'Output the current version of create new publication.'
)
.helpOption('-h, --help', 'Display this help message.')
.option('--db, --debug', 'output extra debugging')
.option('-p, --platform <type>', 'platform')
.option('-t, --title <type>', 'publication title')
.option('-c, --cue-name <type>', 'name in cue')
.option('--vr', '--vr-steps <type>', 'number of vr steps')
.option('-f, --func-steps <type>', 'number of functional steps')
.option('-d, --domain <type>', 'domain of site')
.allowUnknownOption();
program.parse(process.argv);
})();
const opts = program.opts()
const platforms: prompts.Choice[] = [
{
title: 'nationals',
value: 'nationals'
},
{
title: 'ronionals',
value: 'ronionals',
},
{
title: 'regionals',
value: 'regionals',
},
{
title: "visionals",
value: "visionals",
}
];
async function run () {
const currentDir = process.cwd();
const webRepoPath = currentDir.includes('web') ? currentDir : null;
if (!webRepoPath) {
throw new Error('This script must be run inside the web repository.');
}
const publicationJson = resolve(webRepoPath, 'drone', 'publication.json');
if (!existsSync(publicationJson)) {
throw new Error(`Required file not found: ${publicationJson}`);
}
const publicationList = await loadJson(publicationJson, {
error: 'Error loading publication list',
success: 'Publication list loaded successfully'
});
const platformObj = platforms.find(({title})=> title === opts.platform);
let config: PublicationData = {
domain: opts.domain,
platform: (platformObj) ? platformObj.value : null,
title: opts.title,
stackAlias: opts.cueName,
vr: opts.vrSteps,
func: opts.funcSteps,
arn: {
dev: '',
qa: '',
preprod: '',
prod: '',
},
autoScaling: {
min: 5,
max: 20,
}
};
config = await createPrompts(config, 'platform', {
type: 'select',
name: 'platform',
message: 'What Platform is it on?',
choices: platforms,
errorMsg: 'Platform is required'
});
console.log(config, publicationList, publicationList[config.platform])
config = await createPrompts(config, 'title', {
type: 'text',
name: 'title',
errorMsg: 'Publication Name is required',
message: 'What is the Name of the publication?',
validate: checkName(publicationList[config.platform]) as PromptConfig['validate']
});
config = await createPrompts(config, 'cueName', [
{
type: 'confirm',
name: 'hasCue',
message: 'Is the publication name different in cue?',
initial: false
},
{
type: prev => prev ? 'text' : null,
name: 'stackAlias',
message: 'What is the publication\'s name in cue?',
validate: checkNotEmpty as PromptConfig['validate']
}
]);
if(!config.domain) {
const { domain } = await prompts({
type: 'text',
name: 'domain',
message: 'What is the publication\'s domain?',
validate: checkDomain
});
config.domain = domain;
}
if(!config.vr) {
const { vr } = await prompts({
type: 'number',
name: 'vr',
message: 'How many vr steps for this publication?',
initial: 5
});
config.vr = vr;
}
if(!config.func) {
const { func } = await prompts({
type: 'number',
name: 'func',
message: 'How many Functional steps for this publication?',
initial: 14
},);
config.func = func;
}
const awsResponses = await prompts([
{
type: 'confirm',
name: 'arnTrue',
message: 'Do you know the certificateArn for each environment?',
initial: true
},
{
type: (prev: any, values: {arnTrue: boolean}) => values.arnTrue ? 'text' : null,
name: 'devCertificateArn',
message: 'What is certificateArn for dev environment?',
validate: checkArn
},
{
type: (prev: any, values: {arnTrue: boolean}) => values.arnTrue ? 'text' : null,
name: 'qaCertificateArn',
message: 'What is certificateArn for QA environment?',
validate: checkArn
},
{
type: (prev: any, values: {arnTrue: boolean}) => values.arnTrue ? 'text' : null,
name: 'preprodCertificateArn',
message: 'What is certificateArn for PreProd environment?',
validate: checkArn
},
{
type: (prev: any, values: {arnTrue: boolean}) => values.arnTrue ? 'text' : null,
name: 'prodCertificateArn',
message: 'What is certificateArn for Prod environment?',
validate: checkArn
},
{
type: 'number',
name: 'autoScalingMin',
message: 'AWS autoscaling, what is the minimum capacity?',
initial: 5,
},
{
type: 'number',
name: 'autoScalingMax',
message: 'AWS autoscaling, what is the maximum capacity?',
initial: 20,
},
]);
config.arn = {
dev: awsResponses.devCertificateArn,
qa: awsResponses.qaCertificateArn,
preprod: awsResponses.preprodCertificateArn,
prod: awsResponses.prodCertificateArn,
};
config.autoScaling = {
min: awsResponses.autoScalingMin,
max: awsResponses.autoScalingMax,
};
await updateFiles(config);
};
async function exit(reason: any) {
console.log()
console.log('Aborting installation.')
if (reason.command) {
console.log(` ${cyan(reason.command)} has failed.`)
} else {
console.log(
red('Unexpected error. Please report it as a bug:') + '\n',
reason
)
}
process.exit(1)
}
run().catch(exit);