@gauntface/cli
Version:
A CLI tool to help with repetitive tasks.
124 lines (97 loc) ⢠3.35 kB
JavaScript
const spawn = require('child_process').spawn;
const { program } = require('commander');
run().catch((err) => {
console.error(`ā ļø An unexpected error occured.`);
console.error(err);
return process.exit(1);
})
async function run() {
program
.version('0.0.1')
.option('--delete_exclude <type>', 'Directories to exclude in the sync')
.requiredOption('--directory <type>', 'Directory of the site to upload')
.requiredOption('--bucket_name <type>', 'The name of the bucket to upload to');
program.parse(process.argv);
const opts = program.opts();
const directory = opts.directory;
const bucketName = opts['bucket_name'];
const deleteExclude = opts['delete_exclude'];
logMetadata(directory, deleteExclude, bucketName);
await publishToS3Bucket(directory, deleteExclude, bucketName);
}
function logMetadata(directory, deleteExclude, bucketName) {
console.log(`
šæļø Shipit squirrel hard at work!
š Directory: ${directory}
š Delete Exclude: ${deleteExclude}
šļø Bucket: ${bucketName}
`);
}
async function publishToS3Bucket(dir, deleteExclude, bucketName) {
const s3Bucket = `s3://${bucketName}/`;
const shortTermCacheExt = ['html', 'xml', 'json', 'svg'];
const longTermCacheExt = ['css', 'js', 'ico', 'png', 'jpg', 'jpeg', 'gif', 'webp', 'avif', 'woff', 'woff2', 'mp3', 'pdf'];
const deleteExt = shortTermCacheExt.concat(longTermCacheExt);
const steps = [
// Add cache headers for assets that do not have a hash
makeSyncCmd(dir, s3Bucket, 86400, shortTermCacheExt),
// Add cache headers for assets that do have a hash
makeSyncCmd(dir, s3Bucket, 31104000, longTermCacheExt),
// Delete any files we no longer need
makeSyncDelete(dir, deleteExclude, s3Bucket, deleteExt),
];
for (const s of steps) {
await runCmd(s);
}
}
function makeSyncCmd(dir, s3Bucket, maxAge, extensions) {
const parts = [
`aws s3 sync ${dir} ${s3Bucket}`,
'--acl', 'public-read',
'--exclude', '*',
]
for (const e of extensions) {
parts.push(`--include`, `*.${e}`)
}
// --cache-control Set cache control headers
parts.push(`--cache-control max-age=${maxAge}`);
return parts.join(" ")
}
function makeSyncDelete(dir, deleteExclude, s3Bucket, extensions) {
const parts = [
`aws s3 sync ${dir} ${s3Bucket}`,
'--delete',
]
for (const e of extensions) {
parts.push(`--include`, `*.${e}`)
}
// Exclude at the end to ensure the generated files are excluded
if (deleteExclude) {
parts.push('--exclude', deleteExclude)
} else {
parts.push('--exclude', '*')
}
return parts.join(" ")
}
async function runCmd(cmd) {
console.log(`š¤ Running \`${cmd}\``);
const cmdPieces = cmd.split(' ');
return new Promise((resolve, reject) => {
// Note: We use spawn here since exec has a max buffer size for stdout and stderr that
// AWS blasts through
const cmdProcess = spawn(cmdPieces[0], cmdPieces.splice(1))
cmdProcess.stdout.on('data', function (data) {
console.log(`${data}`);
});
cmdProcess.stderr.on('data', function (data) {
console.error(`${data}`);
});
cmdProcess.on('close', function (code) {
if (code != 0) {
reject(`Unexpected error code: ${code}`);
return
}
resolve();
});
});
}