zordius/api-validator.js

View on GitHub
lib/schema.js

Summary

Maintainability
A
0 mins
Test Coverage
/*jslint node: true */
'use strict';

var lodash = require('lodash'),
    traverse = require('traverse'),
    fs = require('fs'),
    path = require('path'),
    jsonlint = require('jsonlint'),

ASchema = {
    coreURL: 'http://uschema.github.io/json/apivalidator.',
    coreBase: path.resolve(__dirname, '../schemas'),
    coreSchemaMatch: /(schema)?\.json$/,
    find: function (base, match) {
        var F = [],
            D = base || process.cwd(),
            M = match || ASchema.coreSchemaMatch;

        try {
            fs.readdirSync(D).forEach(function (N) {
                var FN = D + '/' + N,
                    S = fs.statSync(FN);

                if (S.isDirectory()) {
                    lodash.map(ASchema.find(FN, M), function (O) {
                        F.push(O);
                    });
                    return;
                }

                if (N.match(M)) {
                    F.push(FN);
                }
            });
        } catch (E) {
        }

        return F;
    },
    load: function (FS) {
        var H = {};

        lodash.map(FS, function (F) {
            try {
                H[F] = jsonlint.parse(fs.readFileSync(F, 'utf8'));
            } catch (E) {
                throw new Error('JSON file "' + F + '" error: ' + E.message);
            }
        });

        return H;
    },
    resolveFileRef: function (U, base) {
        var M;
        try {
            M = U.match(/^file:\/\/(.+)(#.*)?/);
            if (M) {
                return 'file://' + path.resolve(base, M[1]) + (M[2] || '');
            }
        } catch (E) {
            // Do nothing ...
        }
        return U;
    },
    deepResolveFileRef: function (O, base, resolver) {
        var usedResolver = lodash.isFunction(resolver) ? resolver : ASchema.resolveFileRef;
        traverse(O).forEach(function (V) {
            if (this.key === '$ref') {
                this.update(usedResolver(V, base));
            }
        });
        return O;
    },
    loadResolveRef: function (base, match, fixer, opts) {
        var R = {};
        lodash.map(ASchema.load(ASchema.find(base, match)), function (S, F) {
            var O = fixer({
                name: F,
                schema: S,
                base: base,
                options: opts
            });
            R[O.name] = O.schema;
        });
        return R;
    },
    loadRemoteCached: function (base, match, opts) {
        return ASchema.loadResolveRef(base, match, ASchema.remoteFixer, opts);
    },
    loadRelativeFile: function (base, match, opts) {
        return ASchema.loadResolveRef(base, match, ASchema.relativeFileFixer, opts);
    },
    loadCoreSchemas: function () {
        return ASchema.loadRemoteCached(ASchema.coreBase);
    },
    remoteFixer: function (O) {
        O.name = O.schema.id;

        return O;
    },
    relativeFileFixer: function (O) {
        var FN = path.resolve(O.name),
            URI = 'file://' + FN,
            ID = (O.schema.id && O.schema.id.match(/:\/\//)) ? O.schema.id : URI;

        O.name = ID;
        O.schema.id = ID;
        O.schema = ASchema.deepResolveFileRef(O.schema, path.dirname(ID.replace(/file:\/\//, '')));

        return O;
    }
};

module.exports = ASchema;