bin/configtest
#!/usr/bin/env node
var path = require("path");
var fs = require("fs");
var configPath = path.resolve(__dirname, "../config.json");
var projectDir = path.resolve(__dirname, "..");
var warning = [];
var fatals = [];
var stdout = process.stdout;
var config;
var buffer;
var red = '\u001b[31m';
var green = '\u001b[32m';
var magenta = '\u001b[35m';
var yellow = '\u001b[33m';
var reset = '\u001b[0m';
(function() {
console.log(green + "==========================================" + reset);
console.log(green + " AWS-Lambda-Image Configuration Checker" + reset);
console.log(green + "==========================================" + reset);
stdout.write("\r\n");
if ( ! fs.existsSync(configPath) ) {
stdout.write(red + "[Error] Config file not exists.\r\n" + reset);
stdout.write(red + "Did you put a config file at " + projectDir + "/config.json?\r\n" + reset);
return;
}
buffer = fs.readFileSync(configPath, {encoding: "utf8"});
stdout.write(magenta + "Configuration status: " + reset);
try {
config = JSON.parse(buffer);
stdout.write(" OK\r\n");
} catch ( e ) {
stdout.write("\r\n");
stdout.write(red + "Error!\r\n" + reset);
console.log(e.message);
process.exit(1);
}
var jpegOptimizer = config.jpegOptimizer;
stdout.write(magenta + "Global Optimizer: " + reset + (jpegOptimizer || "Not set") + "\r\n");
var bucket = config.bucket;
stdout.write(magenta + "Destination bucket: " + reset + (bucket || "[Same bucket]") + "\r\n");
var acl = config.acl;
stdout.write(magenta + "Global S3 ACL: " + reset + (acl || "Not set") + "\r\n");
var cacheControl = config.cacheControl;
stdout.write(magenta + "Global S3 CacheControl: " + reset + (cacheControl || "Not set") + "\r\n");
var keepExtension = config.keepExtension;
stdout.write(magenta + "Keep original extension: " + reset + (keepExtension ? "yes": "no") + "\r\n");
var optimizer = config.optimizers || {};
stdout.write("\r\n");
stdout.write("Override Optimizer configuration\r\n");
stdout.write("--------------------------------\r\n");
stdout.write(magenta + " pngquant : " + reset + (optimizer.pngquant ? formatArray(optimizer.pngquant) : "Not set") + "\r\n");
stdout.write(magenta + " jpegoptim : " + reset + (optimizer.jpegoptim ? formatArray(optimizer.jpegoptim) : "Not set") + "\r\n");
stdout.write(magenta + " mozjpeg : " + reset + (optimizer.mozjpeg ? formatArray(optimizer.mozjpeg) : "Not set") + "\r\n");
stdout.write(magenta + " gifsicle : " + reset + (optimizer.gifsicle ? formatArray(optimizer.gifsicle) : "Not set") + "\r\n");
stdout.write("\r\n");
stdout.write("Backup image configuration\r\n");
stdout.write("--------------------------------\r\n");
if ( "backup" in config ) {
var backup = config.backup || {};
validateDestination(stdout, bucket, backup.bucket, backup.directory, backup.template);
validatePrefixAndSuffix(stdout, backup.prefix, backup.suffix);
validateAcl(stdout, acl, backup.acl);
validateCacheControl(stdout, cacheControl, backup.cacheControl);
validateKeepExtension(stdout, keepExtension, backup.keepExtension);
} else {
stdout.write("Backup option is not supplied, skip it.\r\n");
}
stdout.write("\r\n");
stdout.write("Reduce image configuration\r\n");
stdout.write("--------------------------------\r\n");
if ( "reduce" in config ) {
var reduce = config.reduce || {};
validateQuality(stdout, reduce.quality);
validateOptimizer(stdout, reduce.jpegOptimizer || jpegOptimizer);
validateDestination(stdout, bucket, reduce.bucket, reduce.directory, reduce.template);
validatePrefixAndSuffix(stdout, reduce.prefix, reduce.suffix);
validateAcl(stdout, acl, reduce.acl);
validateCacheControl(stdout, cacheControl, reduce.cacheControl);
validateKeepExtension(stdout, keepExtension, reduce.keepExtension);
} else {
stdout.write("Reduce option is not supplied, skip it.\r\n");
}
stdout.write("\r\n");
stdout.write("Resize image configuration\r\n");
stdout.write("--------------------------------\r\n");
var resizes = config.resizes || [];
stdout.write(magenta + " Number of resize images: " + reset + resizes.length + "\r\n");
stdout.write("\r\n");
resizes.forEach(function(resize, index) {
stdout.write(" Resize image " + (index + 1) + " ( of " + resizes.length + " )\r\n");
stdout.write(" --------------------------------\r\n");
validateSize(stdout, resize.size);
validateFormat(stdout, resize.format);
validateQuality(stdout, resize.quality);
validateCrop(stdout, resize.crop);
validateOptimizer(stdout, resize.jpegOptimizer || jpegOptimizer);
validateDestination(stdout, bucket, resize.bucket, resize.directory, resize.template);
validatePrefixAndSuffix(stdout, resize.prefix, resize.suffix);
validateAcl(stdout, acl, resize.acl);
validateCacheControl(stdout, cacheControl, resize.cacheControl);
validateKeepExtension(stdout, keepExtension, resize.keepExtension);
stdout.write("\r\n");
});
stdout.write("\r\n");
stdout.write(green + "Configuration check finished.\r\n" + reset + "\r\n");
if ( fatals.length === 0 && warning.length === 0 ) {
stdout.write(green + "Your configuration is green!\r\n" + reset);
} else {
new Set(fatals).forEach(function(f) {
stdout.write(red + "[Fatal] " + f + "\r\n" + reset);
});
new Set(warning).forEach(function(n) {
stdout.write(red + "[Warning] " + n + "\r\n" + reset);
});
}
if (fatals.length !== 0) {
process.exit(1);
}
function formatArray(ary) {
return `[${ary.map(v => `"${v}"`).join(", ")}]`;
}
function validateSize(stdout, size) {
var color = reset;
if ( ! size ) {
fatals.push("Resize destination size must be supplied");
color = red;
} else if ( isNaN(parseInt(size, 10)) ) {
fatals.push("Resize destination size must be a number");
color = red;
}
stdout.write(magenta + " Size: " + color + size + reset + "\r\n");
}
function validateQuality(stdout, quality) {
if ( quality ) {
var color = reset;
if ( isNaN(parseInt(quality, 10)) || quality < 0 || quality > 100 ) {
fatals.push("Invalid value of 'quality' option. It should be a number in range 0-100.");
color = red;
}
stdout.write(magenta + " Image Quality: " + color + quality + " (JPG Only)" + reset + "\r\n");
}
}
function validateOptimizer(stdout, optimizer) {
var color = reset;
if ( ["mozjpeg", "jpegoptim", undefined].indexOf(optimizer) === -1 ) {
warning.push("Optimizer is invalid. It accepts 'jpegoptim', 'mozjpeg' or undefined only.");
color = red;
}
var optimizers;
if ( ["mozjpeg", "jpegoptim"].indexOf(optimizer) !== -1 ) {
optimizers = optimizer + " (JPG Only)";
} else {
optimizers = "default (JPG Only)";
}
stdout.write(magenta + " Optimizer: " + color + optimizers + reset + "\r\n");
}
function validateFormat(stdout, format) {
if ( format ) {
stdout.write(magenta + " Convert: " + reset + format + "\r\n");
}
}
function validateDestination(stdout, globalBucket, bucket, directory, template) {
var color = reset;
if ( ! bucket && ! globalBucket && (! directory || /^\.\//.test(directory)) && (! template || ! template.pattern)) {
warning.push(" Saving image to the same or relative directory may cause infinite Lambda process loop.");
color = red;
}
stdout.write( magenta + " Save bucket: " + color );
stdout.write( bucket ? bucket : globalBucket ? globalBucket : "[Same bucket]");
stdout.write("\r\n");
stdout.write (magenta + " Save directory: " + color );
if ( directory ) {
stdout.write(directory);
stdout.write( /^\.\.?/.test(directory) ? " [Relative]" : "");
} else if ( template && template.pattern ) {
stdout.write(template.output || "/");
stdout.write(" [Pattern]");
} else {
stdout.write("[Same directory]");
}
stdout.write(reset + "\r\n");
}
function validatePrefixAndSuffix(stdout, prefix, suffix) {
if ( prefix ) {
stdout.write(magenta + " Filename Prefix: " + reset + prefix + "\r\n");
}
if ( suffix ) {
stdout.write(magenta + " Filename Suffix: " + reset + suffix + "\r\n");
}
}
function validateAcl(stdout, globalAcl, acl) {
stdout.write(magenta + " S3 ACL: " + reset);
stdout.write(acl ? acl : globalAcl ? "[Global ACL]" : "[Source ACL]");
stdout.write("\r\n");
}
function validateCacheControl(stdout, globalCacheControl, cacheControl) {
stdout.write(magenta + " S3 CacheControl: " + reset);
stdout.write((cacheControl !== undefined) ? (cacheControl || "null") : globalCacheControl ? "[Global CacheControl]" : "[Source CacheControl]");
stdout.write("\r\n");
}
function validateKeepExtension(stdout, globalKeepExtension, keepExtension) {
var enable = keepExtension || globalKeepExtension || false;
stdout.write(magenta + " Keep Extension: " + reset);
stdout.write(enable ? "yes" : "no");
stdout.write("\r\n");
}
function validateCrop(stdout, cropOption) {
if ( ! cropOption ) {
return;
}
const cropSpec = /(\d+)x(\d+)([+-]\d+)?([+-]\d+)?(%)?/;
if ( ! cropSpec.test(cropOption) ) {
fatals.push("Resize crop option is invalid for expected spec: " + cropOption);
}
stdout.write(magenta + " Crop: " + reset);
stdout.write(cropOption);
stdout.write("\r\n");
}
})();