UNPKG

@finnair/path

Version:
105 lines (104 loc) 3.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Projection = void 0; exports.projection = projection; const PathMatcher_js_1 = require("./PathMatcher.js"); const jsonClone_js_1 = require("./jsonClone.js"); class Projection { includes; excludes; always; replacer; allowGaps; constructor(includes, excludes, always, replacer) { this.includes = includes; this.excludes = excludes; this.always = always; this.replacer = replacer; this.allowGaps = this.includes.some(expression => expression.allowGaps) || this.excludes.some(expression => expression.allowGaps) || this.always.some(expression => expression.allowGaps); Object.freeze(this.includes); Object.freeze(this.excludes); Object.freeze(this.always); Object.freeze(this); } map(input) { // Clone input for safety: nothing invisible to JSON should be accessible! let safeInput = (0, jsonClone_js_1.jsonClone)(input, this.replacer); if (typeof safeInput !== 'object' || safeInput === null) { throw new Error(`Expected JSON of the input to be non-null object, got ${safeInput}`); } let output; if (this.includes.length) { output = Array.isArray(safeInput) ? [] : {}; this.includes.forEach(expression => include(safeInput, expression, output)); } else if (this.excludes.length) { output = safeInput; } else { return safeInput; } this.excludes.forEach(expression => exclude(output, expression)); if (this.includes.length || this.excludes.length) { this.always.forEach(expression => include(input, expression, output)); } if (this.allowGaps) { return removeGaps(output); } return output; } match(path) { if (this.always.some(expression => expression.prefixMatch(path))) { return true; } if (this.includes.length && !this.includes.some(expression => expression.partialMatch(path))) { return false; } if (this.excludes.some(expression => expression.prefixMatch(path))) { return false; } return true; } static of(includes, excludes, always, replacer) { includes = includes ? includes.map(validatePathMatcher) : []; excludes = excludes ? excludes.map(validatePathMatcher) : []; always = always ? always.map(validatePathMatcher) : []; return new Projection(includes, excludes, always, replacer); } } exports.Projection = Projection; function projection(includes, excludes, always, replacer) { const projection = Projection.of(includes, excludes, always, replacer); return (input) => projection.map(input); } function validatePathMatcher(value) { if (value instanceof PathMatcher_js_1.PathMatcher) { return value; } else { throw new Error(`Expected an instance of PathMatcher, got ${value}`); } } function include(input, matcher, output) { matcher.find(input, (path, value) => path.set(output, value)); } function exclude(output, matcher) { matcher.find(output, (path) => path.unset(output)); } function removeGaps(value) { if (typeof value === 'object') { if (Array.isArray(value)) { value = value .filter(item => item !== undefined) .map(removeGaps); } else { for (const key in value) { value[key] = removeGaps(value[key]); } } } return value; }