added lossy view
This commit is contained in:
parent
42df273052
commit
a283649c77
|
@ -0,0 +1,80 @@
|
||||||
|
import Debug from "debug";
|
||||||
|
import {Lossless, LosslessViewMany} from "../src/lossless";
|
||||||
|
import {Lossy, firstValueFromLosslessViewOne, firstValueFromCollapsedDelta} from "../src/lossy";
|
||||||
|
const debug = Debug('test:lossy');
|
||||||
|
|
||||||
|
describe('Lossy', () => {
|
||||||
|
describe('se a provided function to resolve entity views', () => {
|
||||||
|
const lossless = new Lossless();
|
||||||
|
const lossy = new Lossy(lossless);
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
lossless.ingestDelta({
|
||||||
|
creator: 'a',
|
||||||
|
host: 'h',
|
||||||
|
pointers: [{
|
||||||
|
localContext: "actor",
|
||||||
|
target: "keanu",
|
||||||
|
targetContext: "roles"
|
||||||
|
}, {
|
||||||
|
localContext: "role",
|
||||||
|
target: "neo",
|
||||||
|
targetContext: "actor"
|
||||||
|
}, {
|
||||||
|
localContext: "film",
|
||||||
|
target: "the_matrix",
|
||||||
|
targetContext: "cast"
|
||||||
|
}, {
|
||||||
|
localContext: "base_salary",
|
||||||
|
target: 1000000
|
||||||
|
}, {
|
||||||
|
localContext: "salary_currency",
|
||||||
|
target: "usd"
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('example summary', () => {
|
||||||
|
type Role = {
|
||||||
|
actor: string,
|
||||||
|
film: string,
|
||||||
|
role: string
|
||||||
|
};
|
||||||
|
|
||||||
|
type Summary = {
|
||||||
|
roles: Role[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const resolver = (losslessView: LosslessViewMany): Summary => {
|
||||||
|
const roles: Role[] = [];
|
||||||
|
debug('resolving roles');
|
||||||
|
for (const [id, ent] of Object.entries(losslessView)) {
|
||||||
|
if (ent.referencedAs.includes("role")) {
|
||||||
|
const {delta, value: actor} = firstValueFromLosslessViewOne(ent, "actor") ?? {};
|
||||||
|
if (!delta) continue; // TODO: panic
|
||||||
|
if (!actor) continue; // TODO: panic
|
||||||
|
const film = firstValueFromCollapsedDelta(delta, "film");
|
||||||
|
debug(`role ${id}`, {actor, film});
|
||||||
|
if (!film) continue; // TODO: panic
|
||||||
|
roles.push({
|
||||||
|
role: id,
|
||||||
|
actor,
|
||||||
|
film
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {roles};
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = lossy.resolve(resolver);
|
||||||
|
expect(result).toEqual({
|
||||||
|
roles: [{
|
||||||
|
film: "the_matrix",
|
||||||
|
role: "neo",
|
||||||
|
actor: "keanu"
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,41 @@
|
||||||
|
// We have the lossless transformation of the delta stream.
|
||||||
|
// We want to enable transformations from the lossless view,
|
||||||
|
// into various possible "lossy" views that combine or exclude some information.
|
||||||
|
//
|
||||||
|
// We can achieve this via functional expression, encoded as JSON-Logic.
|
||||||
|
// Fields in the output can be described as transformations
|
||||||
|
|
||||||
|
import {CollapsedDelta, Lossless, LosslessViewMany, LosslessViewOne} from "./lossless";
|
||||||
|
import {DeltaFilter} from "./types";
|
||||||
|
|
||||||
|
type Resolver = (losslessView: LosslessViewMany) => unknown;
|
||||||
|
|
||||||
|
export function firstValueFromCollapsedDelta(delta: CollapsedDelta, key: string): string | undefined {
|
||||||
|
const pointers = delta.pointers;
|
||||||
|
for (const pointer of pointers || []) {
|
||||||
|
const [[k, value]] = Object.entries(pointer);
|
||||||
|
if (k === key && typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function firstValueFromLosslessViewOne(ent: LosslessViewOne, key: string): {delta: CollapsedDelta, value: string} | undefined {
|
||||||
|
for (const delta of ent.properties[key] || []) {
|
||||||
|
const value = firstValueFromCollapsedDelta(delta, key);
|
||||||
|
if (value) return {delta, value};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Lossy {
|
||||||
|
lossless: Lossless;
|
||||||
|
|
||||||
|
constructor(lossless: Lossless) {
|
||||||
|
this.lossless = lossless;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(fn: Resolver, deltaFilter?: DeltaFilter) {
|
||||||
|
return fn(this.lossless.view(deltaFilter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue