Publish camino-datatypes from ce2c8b6ed1926da7b3b3fe4aa3f1bbd8f327470a

This commit is contained in:
Quixos Subtree Publisher
2026-09-03 16:39:22 +00:00
6 changed files with 57 additions and 16 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"version": 1,
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos.git",
"sourceCommit": "3f984faf58a1e412467255f478e0736fdf1c1496",
"sourceCommit": "ce2c8b6ed1926da7b3b3fe4aa3f1bbd8f327470a",
"sourcePath": "quixos-instance/packages/camino-datatypes",
"exportName": "camino-datatypes",
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/camino-datatypes.git"
+2 -1
View File
@@ -18,7 +18,8 @@ export declare const loadAutomergeFieldDoc: (value: CaminoCrdtEnvelope, type: st
export declare const saveAutomergeFieldDoc: (doc: Automerge.Doc<AutomergeFieldDoc>, type: string) => CaminoCrdtEnvelope;
export declare const createAutomergeFieldValue: (value: unknown, type: string) => CaminoCrdtEnvelope;
export declare const isAutomergeFieldDoc: (value: unknown) => value is Automerge.Doc<AutomergeFieldDoc>;
export declare const createAutomergeFieldChanges: (base: Automerge.Doc<AutomergeFieldDoc>, next: Automerge.Doc<AutomergeFieldDoc>, type: string) => CaminoCrdtEnvelope;
export declare const reconcileAutomergeFieldDocs: <T>(base: CaminoAutomergeDoc<T>, desired: CaminoAutomergeDoc<T>) => CaminoAutomergeDoc<T>;
export declare const createAutomergeFieldChanges: (base: Automerge.Doc<AutomergeFieldDoc>, desired: Automerge.Doc<AutomergeFieldDoc>, type: string) => CaminoCrdtEnvelope;
export declare const encodeAutomergeFieldWrite: (value: unknown, type: string) => CaminoCrdtEnvelope;
export declare const normalizeAutomergeFieldValue: (value: unknown, type: string) => CaminoCrdtEnvelope;
export declare const materializeAutomergeFieldValue: (value: CaminoCrdtEnvelope, type: string) => unknown;
+9 -5
View File
@@ -107,11 +107,15 @@ const decodeChanges = (payload) => {
}
return changes;
};
export const createAutomergeFieldChanges = (base, next, type) => ({
$caminoCrdtType: type,
$caminoCrdtEncoding: AUTOMERGE_CHANGES_ENCODING,
$caminoCrdtPayload: bytesToBase64(encodeChanges(Automerge.getChanges(base, next))),
});
export const reconcileAutomergeFieldDocs = (base, desired) => Automerge.merge(Automerge.clone(base), Automerge.clone(desired));
export const createAutomergeFieldChanges = (base, desired, type) => {
const next = reconcileAutomergeFieldDocs(base, desired);
return {
$caminoCrdtType: type,
$caminoCrdtEncoding: AUTOMERGE_CHANGES_ENCODING,
$caminoCrdtPayload: bytesToBase64(encodeChanges(Automerge.getChanges(base, next))),
};
};
// Full snapshots remain an explicit escape hatch for initialization, import,
// and recovery when a client cannot establish a shared Automerge history.
export const encodeAutomergeFieldWrite = (value, type) => {
+1 -1
View File
File diff suppressed because one or more lines are too long
+17 -8
View File
@@ -162,17 +162,26 @@ const decodeChanges = (payload: Uint8Array): Automerge.Change[] => {
return changes;
};
export const reconcileAutomergeFieldDocs = <T>(
base: CaminoAutomergeDoc<T>,
desired: CaminoAutomergeDoc<T>,
): CaminoAutomergeDoc<T> =>
Automerge.merge(Automerge.clone(base), Automerge.clone(desired));
export const createAutomergeFieldChanges = (
base: Automerge.Doc<AutomergeFieldDoc>,
next: Automerge.Doc<AutomergeFieldDoc>,
desired: Automerge.Doc<AutomergeFieldDoc>,
type: string,
): CaminoCrdtEnvelope => ({
$caminoCrdtType: type,
$caminoCrdtEncoding: AUTOMERGE_CHANGES_ENCODING,
$caminoCrdtPayload: bytesToBase64(
encodeChanges(Automerge.getChanges(base, next)),
),
});
): CaminoCrdtEnvelope => {
const next = reconcileAutomergeFieldDocs(base, desired);
return {
$caminoCrdtType: type,
$caminoCrdtEncoding: AUTOMERGE_CHANGES_ENCODING,
$caminoCrdtPayload: bytesToBase64(
encodeChanges(Automerge.getChanges(base, next)),
),
};
};
// Full snapshots remain an explicit escape hatch for initialization, import,
// and recovery when a client cannot establish a shared Automerge history.
+27
View File
@@ -11,6 +11,7 @@ import {
loadAutomergeFieldDoc,
materializeAutomergeFieldValue,
mergeAutomergeFieldValues,
reconcileAutomergeFieldDocs,
saveAutomergeFieldDoc,
} from "../src/crdt-automerge.js";
@@ -105,6 +106,32 @@ test("Automerge change application is idempotent", () => {
assert.deepEqual(twice.materialized, { count: 1 });
});
test("Automerge changes retain remote history while local writes are pending", () => {
const stored = createAutomergeFieldValue({ local: false, remote: false }, type);
const base = loadAutomergeFieldDoc(stored, type);
const local = Automerge.change(
Automerge.clone(base, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
(doc) => {
(doc.value as { local: boolean }).local = true;
},
);
const remote = Automerge.change(
Automerge.clone(base, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
(doc) => {
(doc.value as { remote: boolean }).remote = true;
},
);
const rebased = reconcileAutomergeFieldDocs(remote, local);
const update = createAutomergeFieldChanges(remote, rebased, type);
const result = mergeAutomergeFieldValues({
existing: saveAutomergeFieldDoc(remote, type),
incoming: update,
type,
});
assert.deepEqual(result.materialized, { local: true, remote: true });
});
test("Automerge change batches reject malformed framing", () => {
const stored = createAutomergeFieldValue({ count: 0 }, type);
assert.throws(