Author and apply bounded structured CRDT edits through the mutation log

This commit is contained in:
Timothy J. Aveni
2026-09-20 04:41:35 -07:00
parent c75888833b
commit 824caddbf2
2 changed files with 18 additions and 2 deletions
+1 -1
View File
@@ -73,5 +73,5 @@ export function generatePortableClientBindings(
}
const groups = (entries: Map<string, string[]>) =>
[...entries].map(([name, values]) => `${JSON.stringify(name)}: {${values.join(",\n")}}`).join(",\n");
return `// Generated application descriptors. Regenerate; do not edit.\nimport { defineOperationDescriptor, type ManagedReference, type ReplicaProjection, type LocalQueryDescriptor } from ${JSON.stringify(options.runtimeModule ?? "@quixos/camino-replica-core")};\nexport const planDigest = ${JSON.stringify(plan.digest)};\nexport const operations = {${groups(atoms)}} as const;\nexport const queries = {${groups(queries)}} as const;\nexport const views = {${groups(views)}} as const;\nexport const unavailable = ${JSON.stringify(unavailable)} as const;\n`;
return `// Generated application descriptors. Regenerate; do not edit.\nimport { defineOperationDescriptor, type PreparedChange, type ManagedReference, type ReplicaProjection, type LocalQueryDescriptor } from ${JSON.stringify(options.runtimeModule ?? "@quixos/camino-replica-core")};\nexport const planDigest = ${JSON.stringify(plan.digest)};\nexport const operations = {${groups(atoms)}} as const;\nexport const queries = {${groups(queries)}} as const;\nexport const views = {${groups(views)}} as const;\nexport const unavailable = ${JSON.stringify(unavailable)} as const;\n`;
}
+17 -1
View File
@@ -29,6 +29,16 @@ const expectation = (e: ObjectExpectation) => ({
/** The protocol IR and replica wire schema intentionally share structure, not reference identity. */
export function portableValueSchema(type: ValueType): unknown {
switch (type.kind) {
case "change":
return {
kind: "record",
fields: {
codec: { kind: "scalar", name: "string" },
profile: { kind: "scalar", name: "string" },
generation: { kind: "scalar", name: "string" },
changes: { kind: "list", value: { kind: "scalar", name: "bytes" } },
},
};
case "scalar":
return type;
case "builtin":
@@ -55,6 +65,8 @@ export function portableValueSchema(type: ValueType): unknown {
export function tsType(type: ValueType): string {
portableValueSchema(type);
switch (type.kind) {
case "change":
return `PreparedChange<${tsType(type.value)}>`;
case "scalar":
return type.name === "bool"
? "boolean"
@@ -125,6 +137,10 @@ function methods(schema: BindingSchema, entry: PackageExport, port: DependencyPo
writable();
return method("set", { kind: "state", primitive }, req.valueType, unit);
}
if (primitive === "edit") {
writable();
return method("edit", { kind: "state", primitive }, { kind: "change", value: req.valueType }, unit);
}
throw new PortableBindingError(path, `State ${primitive} is not supported by this portable adapter yet`);
});
case "edge": {
@@ -248,5 +264,5 @@ export function generatePortableTypeScriptBindings(
methods: all.map((m) => ({ ...m, input: portableValueSchema(m.input), output: portableValueSchema(m.output) })),
});
}
return `// Generated portable bindings. Regenerate from the checked capability schema; do not edit.\nimport { definePortableRegistry, type PortableExport, type ManagedReference, type ExactReference, type MutationKey } from ${q(options.runtimeModule ?? "@quixos/camino-replica-core")};\nexport const bindingDigest = ${q(hexDigest(schema))};\nexport const packageRevision = ${q(revision)};\nexport const target = ${q(options.target)};\nexport type Contexts = { ${contexts.join(";\n")} };\nexport type PortableImplementation = { ${implementations.join(";\n")} };\nexport const declarations = ${JSON.stringify(descriptors, null, 2)} as const satisfies readonly PortableExport[];\nexport function createRegistry(handlers: PortableImplementation) { const installed = { ...handlers }; return definePortableRegistry(declarations, { ${adapters.join(",\n")} }); }\n`;
return `// Generated portable bindings. Regenerate from the checked capability schema; do not edit.\nimport { definePortableRegistry, type PortableExport, type PreparedChange, type ManagedReference, type ExactReference, type MutationKey } from ${q(options.runtimeModule ?? "@quixos/camino-replica-core")};\nexport const bindingDigest = ${q(hexDigest(schema))};\nexport const packageRevision = ${q(revision)};\nexport const target = ${q(options.target)};\nexport type Contexts = { ${contexts.join(";\n")} };\nexport type PortableImplementation = { ${implementations.join(";\n")} };\nexport const declarations = ${JSON.stringify(descriptors, null, 2)} as const satisfies readonly PortableExport[];\nexport function createRegistry(handlers: PortableImplementation) { const installed = { ...handlers }; return definePortableRegistry(declarations, { ${adapters.join(",\n")} }); }\n`;
}