Encode Automerge docs for Camino CRDT writes

This commit is contained in:
Timothy J. Aveni
2026-07-12 20:15:51 -07:00
parent 864f8f5de6
commit e72b3c5577
5 changed files with 112 additions and 8 deletions
+48 -4
View File
@@ -12,10 +12,32 @@ type AutomergeFieldDoc = {
value: unknown;
};
const bytesToBase64 = (value: Uint8Array) =>
Buffer.from(value).toString("base64");
export type CaminoAutomergeDoc<T = unknown> = Automerge.Doc<{
value: T;
}>;
const base64ToBytes = (value: string) => Buffer.from(value, "base64");
const bytesToBase64 = (value: Uint8Array) => {
if (typeof Buffer !== "undefined") {
return Buffer.from(value).toString("base64");
}
let binary = "";
for (const byte of value) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
};
const base64ToBytes = (value: string) => {
if (typeof Buffer !== "undefined") {
return Buffer.from(value, "base64");
}
const binary = atob(value);
const bytes = new Uint8Array(binary.length);
for (let index = 0; index < binary.length; index += 1) {
bytes[index] = binary.charCodeAt(index);
}
return bytes;
};
export const isCaminoCrdtEnvelope = (
value: unknown,
@@ -65,16 +87,38 @@ export const createAutomergeFieldValue = (
): CaminoCrdtEnvelope =>
saveAutomergeFieldDoc(Automerge.from<AutomergeFieldDoc>({ value }), type);
export const normalizeAutomergeFieldValue = (
export const isAutomergeFieldDoc = (
value: unknown,
): value is Automerge.Doc<AutomergeFieldDoc> => {
if (!value || typeof value !== "object") {
return false;
}
try {
Automerge.getHeads(value as Automerge.Doc<AutomergeFieldDoc>);
return true;
} catch {
return false;
}
};
export const encodeAutomergeFieldWrite = (
value: unknown,
type: string,
): CaminoCrdtEnvelope => {
if (isCaminoCrdtEnvelope(value)) {
return saveAutomergeFieldDoc(loadAutomergeFieldDoc(value, type), type);
}
if (isAutomergeFieldDoc(value)) {
return saveAutomergeFieldDoc(value, type);
}
return createAutomergeFieldValue(value, type);
};
export const normalizeAutomergeFieldValue = (
value: unknown,
type: string,
): CaminoCrdtEnvelope => encodeAutomergeFieldWrite(value, type);
export const materializeAutomergeFieldValue = (
value: CaminoCrdtEnvelope,
type: string,