ysugimoto/aws-lambda-image

View on GitHub
bin/configtest

Summary

Maintainability
Test Coverage
#!/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");
    }

})();