Compare commits

..

No commits in common. "5c1c8a23b8baaa04dd1d4c33bd6af1e847931736" and "8043b6725850cad33a859df445b26ad12566c062" have entirely different histories.

6 changed files with 108 additions and 102 deletions

View File

@ -1,6 +0,0 @@
---
description: Update the current file to use delta builder
---
Replace each deltav2 instantiation with a fluent call to createDelta from delta builder, using the following process:
- pass creator and host as arguments to createDelta

View File

@ -0,0 +1,7 @@
---
description: Update deltas to use the object style for pointers
---
- in the current file, for each v1 delta, rewrite it as a v2 delta
- make sure the new delta is isomorphic to the original
- do not include a timestamp

View File

@ -158,7 +158,7 @@ describe('DeltaBuilder', () => {
.buildV2(); .buildV2();
// Check for transaction ID in V2 pointers // Check for transaction ID in V2 pointers
expect(delta.pointers['_transaction']).toEqual({ [txId]: 'deltas' }); expect(delta.pointers['_transaction']).toBe(txId);
}); });
it('should support negation', () => { it('should support negation', () => {

View File

@ -1,19 +1,22 @@
import {Delta, DeltaFilter, DeltaV2} from '../src/core'; import {Delta, DeltaFilter, DeltaV2} from '../src/core';
import {Lossless} from '../src/views'; import {Lossless} from '../src/views';
import {RhizomeNode} from '../src/node'; import {RhizomeNode} from '../src/node';
import {createDelta} from '../src/core/delta-builder';
describe('Lossless', () => { describe('Lossless', () => {
const node = new RhizomeNode(); const node = new RhizomeNode();
it('creates a lossless view of keanu as neo in the matrix', () => { it('creates a lossless view of keanu as neo in the matrix', () => {
const delta = createDelta('a', 'h') const delta = new DeltaV2({
.addPointer('actor', 'keanu', 'roles') creator: 'a',
.addPointer('role', 'neo', 'actor') host: 'h',
.addPointer('film', 'the_matrix', 'cast') pointers: {
.addPointer('base_salary', 1000000) actor: {"keanu": "roles"},
.addPointer('salary_currency', 'usd') role: {"neo": "actor"},
.buildV1(); film: {"the_matrix": "cast"},
base_salary: 1000000,
salary_currency: "usd"
}
}).toV1();
expect(delta.pointers).toMatchObject([{ expect(delta.pointers).toMatchObject([{
localContext: "actor", localContext: "actor",
@ -92,13 +95,17 @@ describe('Lossless', () => {
}); });
it('accepts DeltaV2 instances', () => { it('accepts DeltaV2 instances', () => {
const delta = createDelta('a', 'h') const delta = new DeltaV2({
.addPointer('actor', 'keanu', 'roles') creator: 'a',
.addPointer('role', 'neo', 'actor') host: 'h',
.addPointer('film', 'the_matrix', 'cast') pointers: {
.addPointer('base_salary', 1000000) actor: {"keanu": "roles"},
.addPointer('salary_currency', 'usd') role: {"neo": "actor"},
.buildV2(); film: {"the_matrix": "cast"},
base_salary: 1000000,
salary_currency: "usd"
}
});
const lossless = new Lossless(node); const lossless = new Lossless(node);
@ -160,20 +167,26 @@ describe('Lossless', () => {
const lossless = new Lossless(node); const lossless = new Lossless(node);
beforeAll(() => { beforeAll(() => {
// First delta lossless.ingestDelta(new Delta({
lossless.ingestDelta( creator: 'A',
createDelta('A', 'H') host: 'H',
.addPointer('1', 'ace', 'value') pointers: [{
.buildV1() localContext: "1",
); target: "ace",
targetContext: "value"
}]
}));
// Second delta lossless.ingestDelta(new Delta({
lossless.ingestDelta( creator: 'B',
createDelta('B', 'H') host: 'H',
pointers: [{
// 10 11j 12q 13k 14a // 10 11j 12q 13k 14a
.addPointer('14', 'ace', 'value') localContext: "14",
.buildV1() target: "ace",
); targetContext: "value"
}]
}));
expect(lossless.view()).toMatchObject({ expect(lossless.view()).toMatchObject({
ace: { ace: {
@ -238,42 +251,51 @@ describe('Lossless', () => {
const transactionId = 'tx-filter-test'; const transactionId = 'tx-filter-test';
// Declare transaction with 3 deltas // Declare transaction with 3 deltas
losslessT.ingestDelta( losslessT.ingestDelta(new Delta({
createDelta('system', 'H') creator: 'system',
.declareTransaction(transactionId, 3) host: 'H',
.buildV1() pointers: [
); { localContext: '_transaction', target: transactionId, targetContext: 'size' },
{ localContext: 'size', target: 3 }
]
}));
// A1: First delta from creator A // A1: First delta from creator A
losslessT.ingestDelta( losslessT.ingestDelta(new Delta({
createDelta('A', 'H') creator: 'A',
.inTransaction(transactionId) host: 'H',
.addPointer('step', 'process1', 'status') pointers: [
.addPointer('value', 'started') { localContext: '_transaction', target: transactionId, targetContext: 'deltas' },
.buildV1() { localContext: 'step', target: 'process1', targetContext: 'status' },
); { localContext: 'value', target: 'started' }
]
}));
// B: Delta from creator B // B: Delta from creator B
losslessT.ingestDelta( losslessT.ingestDelta(new Delta({
createDelta('B', 'H') creator: 'B',
.inTransaction(transactionId) host: 'H',
.addPointer('step', 'process1', 'status') pointers: [
.addPointer('value', 'processing') { localContext: '_transaction', target: transactionId, targetContext: 'deltas' },
.buildV1() { localContext: 'step', target: 'process1', targetContext: 'status' },
); { localContext: 'value', target: 'processing' }
]
}));
// Transaction incomplete - nothing should show // Transaction incomplete - nothing should show
const incompleteView = losslessT.view(['process1']); const incompleteView = losslessT.view(['process1']);
expect(incompleteView.process1).toBeUndefined(); expect(incompleteView.process1).toBeUndefined();
// A2: Second delta from creator A completes transaction // A2: Second delta from creator A completes transaction
losslessT.ingestDelta( losslessT.ingestDelta(new Delta({
createDelta('A', 'H') creator: 'A',
.inTransaction(transactionId) host: 'H',
.addPointer('step', 'process1', 'status') pointers: [
.addPointer('value', 'completed') { localContext: '_transaction', target: transactionId, targetContext: 'deltas' },
.buildV1() { localContext: 'step', target: 'process1', targetContext: 'status' },
); { localContext: 'value', target: 'completed' }
]
}));
// All deltas visible now // All deltas visible now
const completeView = losslessT.view(['process1']); const completeView = losslessT.view(['process1']);

View File

@ -51,18 +51,6 @@ export class DeltaBuilder {
this.transactionId = transactionId; this.transactionId = transactionId;
return this; return this;
} }
/**
* Declare a transaction with a size
* @param transactionId The ID of the transaction
* @param size The size of the transaction
* @returns
*/
declareTransaction(transactionId: string, size: number): this {
this.addPointer('_transaction', transactionId, 'size');
this.addPointer('size', size)
return this;
}
/** /**
* Mark this delta as a negation of another delta * Mark this delta as a negation of another delta
@ -111,7 +99,7 @@ export class DeltaBuilder {
const pointers = { ...this.pointers }; const pointers = { ...this.pointers };
if (this.transactionId) { if (this.transactionId) {
pointers['_transaction'] = { [this.transactionId]: 'deltas' }; pointers['_transaction'] = this.transactionId;
} }
if (this.isNegation && this.negatedDeltaId) { if (this.isNegation && this.negatedDeltaId) {

View File

@ -9,7 +9,6 @@ import {Transactions} from '../features/transactions';
import {DomainEntityID, PropertyID, PropertyTypes, TransactionID, ViewMany} from "../core/types"; import {DomainEntityID, PropertyID, PropertyTypes, TransactionID, ViewMany} from "../core/types";
import {Negation} from '../features/negation'; import {Negation} from '../features/negation';
import {NegationHelper} from '../features/negation'; import {NegationHelper} from '../features/negation';
import { createDelta } from '../core/delta-builder';
const debug = Debug('rz:lossless'); const debug = Debug('rz:lossless');
export type CollapsedPointer = {[key: PropertyID]: PropertyTypes}; export type CollapsedPointer = {[key: PropertyID]: PropertyTypes};
@ -200,35 +199,31 @@ export class Lossless {
for (const delta of deltas) { for (const delta of deltas) {
if (!seenDeltaIds.has(delta.id)) { if (!seenDeltaIds.has(delta.id)) {
seenDeltaIds.add(delta.id); seenDeltaIds.add(delta.id);
// Convert CollapsedDelta back to Delta
// Create a new delta using DeltaBuilder const fullDelta = new Delta({
const builder = createDelta(delta.creator, delta.host) id: delta.id,
.withId(delta.id) creator: delta.creator,
.withTimestamp(delta.timeCreated); host: delta.host,
timeCreated: delta.timeCreated,
// Add all pointers from the collapsed delta pointers: delta.pointers.map(pointer => {
for (const pointer of delta.pointers) { // Convert back to V1 pointer format for Delta constructor
const pointerEntries = Object.entries(pointer); const pointerEntries = Object.entries(pointer);
if (pointerEntries.length === 1) { if (pointerEntries.length === 1) {
const [localContext, target] = pointerEntries[0]; const [localContext, target] = pointerEntries[0];
if (target === null || target === undefined) { if (typeof target === 'string' && this.domainEntities.has(target)) {
continue; // Skip null/undefined targets // This is a reference pointer to an entity
// The targetContext is the property ID this delta appears under
return { localContext, target, targetContext: propertyId };
} else {
// Scalar pointer
return { localContext, target: target as PropertyTypes };
}
} }
if (typeof target === 'string' && this.domainEntities.has(target)) { // Fallback for unexpected pointer structure
// This is a reference pointer to an entity return { localContext: 'unknown', target: 'unknown' };
builder.addPointer(localContext, target, propertyId); })
} else if (typeof target === 'string' || typeof target === 'number' || typeof target === 'boolean') { });
// Scalar pointer with valid type allDeltas.push(fullDelta);
builder.addPointer(localContext, target);
} else {
// For other types (objects, arrays), convert to string
builder.addPointer(localContext, JSON.stringify(target));
}
}
}
// Build the delta and add to results
allDeltas.push(builder.buildV1());
} }
} }
} }