UNPKG

@finnair/diff

Version:
116 lines (115 loc) 4.13 kB
import { parsePath, parsePathMatcher } from '@finnair/path-parser'; import { Diff } from './Diff.js'; const NO_PREVIOUS_VALUES = Object.freeze({}); export class VersionInfo { current; previous; _changes; _paths; _previousValues; config; constructor(current, previous, config) { this.current = current; this.previous = previous; this.config = config ?? { diff: new Diff({}) }; } map(fn, config) { return new VersionInfo(fn(this.current), this.previous ? fn(this.previous) : undefined, config ?? this.config); } async mapAsync(fn, config) { return new VersionInfo(await fn(this.current), this.previous ? await fn(this.previous) : undefined, config ?? this.config); } get changes() { if (this.previous) { if (this._changes === undefined) { this._changes = this.config.diff.changeset(this.previous, this.current); } return this._changes; } return undefined; } get changedPaths() { if (this.previous) { if (this._paths === undefined) { this._paths = new Set(this.changes.keys()); } return this._paths; } return undefined; } get paths() { if (this._paths === undefined) { if (this.previous) { this._paths = this.changedPaths; } else { this._paths = new Set(this.config.diff.allPaths(this.current)); } } return this._paths; } get previousValues() { if (this.previous && this.config.previousValues?.length) { if (this._previousValues === undefined) { this._previousValues = NO_PREVIOUS_VALUES; for (const [key, value] of this.changes) { const path = parsePath(key); if (this.config.previousValues.some((matcher) => matcher.match(path))) { if (this._previousValues === NO_PREVIOUS_VALUES) { this._previousValues = Array.isArray(this.previous) ? [] : {}; } path.set(this._previousValues, value.oldValue); } } } return this._previousValues === NO_PREVIOUS_VALUES ? undefined : this._previousValues; } return undefined; } matches(pathExpression) { const matcher = VersionInfo.toMatcher(pathExpression); if (this.previous) { const changedPaths = VersionInfo.parsePaths(this.changedPaths); return VersionInfo.matchesAnyPath(matcher, changedPaths); } else { return matcher.findFirst(this.current) !== undefined; } } matchesAny(pathExpressions) { if (this.previous) { const changedPaths = VersionInfo.parsePaths(this.changedPaths); return pathExpressions.some((pathExpression) => { const matcher = VersionInfo.toMatcher(pathExpression); return VersionInfo.matchesAnyPath(matcher, changedPaths); }); } else { return pathExpressions.some((pathExpression) => { const matcher = VersionInfo.toMatcher(pathExpression); return matcher.findFirst(this.current) !== undefined; }); } } toJSON() { const changedPaths = this.changedPaths; return { current: this.current, changedPaths: changedPaths && Array.from(changedPaths), previous: this.previousValues, }; } static parsePaths(paths) { const result = []; for (const path of paths) { result.push(parsePath(path)); } return result; } static matchesAnyPath(matcher, paths) { return paths.some((path) => matcher.prefixMatch(path)); } static toMatcher(pathExpression) { return typeof pathExpression === 'string' ? parsePathMatcher(pathExpression) : pathExpression; } }