Lower checked shared edges into the portable graph model
This commit is contained in:
@@ -213,17 +213,28 @@ export function generateComponentClientBindings(plan: ExecutionPlan, packageRevi
|
||||
`ExtraModuleProps<${JSON.stringify(JSON.stringify([iface, member]))}>`;
|
||||
// Preserve closed type arguments for the artifact consumer. Interpretation of
|
||||
// a particular module contract belongs to that consumer, not this compiler.
|
||||
const moduleArguments = (iface: InterfaceRevision) => `[${(iface.application?.arguments ?? []).map(argument => {
|
||||
if (argument.kind === "value") return tsType(argument.type);
|
||||
const target = argument.target;
|
||||
const reference = target.kind === "atom" ? `ManagedReference<"atom", ${JSON.stringify(target.atomId)}>` : `ManagedReference<"interface", ${JSON.stringify(target.interfaceRevisionId)}>`;
|
||||
const fields = target.kind === "interface" ? find(target.interfaceRevisionId).members.flatMap(member => {
|
||||
if ((member.kind !== "value" && member.kind !== "relationship") || !member.queryRead) return [];
|
||||
const getter = member.operations.find(operation => operation.displayName === (member.kind === "value" ? "get" : "resolve"));
|
||||
return getter ? [`readonly ${JSON.stringify(member.displayName)}: ${tsType(getter.outputType)}`] : [];
|
||||
}) : [];
|
||||
return `{readonly reference: ${reference}; readonly values: {${fields.join(";")}}}`;
|
||||
}).join(",")}]`;
|
||||
const moduleArguments = (iface: InterfaceRevision) =>
|
||||
`[${(iface.application?.arguments ?? [])
|
||||
.map((argument) => {
|
||||
if (argument.kind === "value") return tsType(argument.type);
|
||||
const target = argument.target;
|
||||
const reference =
|
||||
target.kind === "atom"
|
||||
? `ManagedReference<"atom", ${JSON.stringify(target.atomId)}>`
|
||||
: `ManagedReference<"interface", ${JSON.stringify(target.interfaceRevisionId)}>`;
|
||||
const fields =
|
||||
target.kind === "interface"
|
||||
? find(target.interfaceRevisionId).members.flatMap((member) => {
|
||||
if ((member.kind !== "value" && member.kind !== "relationship") || !member.queryRead) return [];
|
||||
const getter = member.operations.find(
|
||||
(operation) => operation.displayName === (member.kind === "value" ? "get" : "resolve"),
|
||||
);
|
||||
return getter ? [`readonly ${JSON.stringify(member.displayName)}: ${tsType(getter.outputType)}`] : [];
|
||||
})
|
||||
: [];
|
||||
return `{readonly reference: ${reference}; readonly values: {${fields.join(";")}}}`;
|
||||
})
|
||||
.join(",")}]`;
|
||||
const interfaces = generateInterfaceClientBindings(imports, "@quixos/camino-react", props);
|
||||
const subjectBindings = generateInterfaceClientBindings(subjects, "@quixos/camino-react", props)
|
||||
.split("\n")
|
||||
|
||||
@@ -18,7 +18,15 @@ const meta = () => selection("_camino", { selection: [selection("ref")] });
|
||||
export const inspectionPackage = "org.quixos.inspection/1";
|
||||
export interface InspectionTemplate {
|
||||
interface: string;
|
||||
members: { id: string; name: string; key: string; flag: string; lane: "local" | "server"; many: boolean; relationship: boolean }[];
|
||||
members: {
|
||||
id: string;
|
||||
name: string;
|
||||
key: string;
|
||||
flag: string;
|
||||
lane: "local" | "server";
|
||||
many: boolean;
|
||||
relationship: boolean;
|
||||
}[];
|
||||
inputs?: PublicQueryContract;
|
||||
view?: PublicQueryContract;
|
||||
server?: PublicQueryContract;
|
||||
@@ -81,7 +89,15 @@ export function compileInspectionTemplates(plan: ExecutionPlan) {
|
||||
// Only native edges promise the relationship traversal used by the interpreter.
|
||||
if (member.kind === "relationship" && providers.some((op) => op!.binding.kind !== "edge")) continue;
|
||||
if (!complete && (lane === "local" || !portable))
|
||||
template.members.push({ id: member.id, name: member.displayName, key, flag, lane, many, relationship: member.kind === "relationship" });
|
||||
template.members.push({
|
||||
id: member.id,
|
||||
name: member.displayName,
|
||||
key,
|
||||
flag,
|
||||
lane,
|
||||
many,
|
||||
relationship: member.kind === "relationship",
|
||||
});
|
||||
inputFields[flag] = scalar("bool");
|
||||
const field = selection(member.displayName, {
|
||||
key,
|
||||
|
||||
@@ -22,11 +22,11 @@ export function compileKernelProgram(plan: ExecutionPlan): unknown {
|
||||
if (hexDigest(plan.definition) !== plan.digest)
|
||||
throw new ExecutionPlanError("INVALID_PLAN", "kernel", "Plan digest mismatch");
|
||||
const workspace = plan.definition.workspace;
|
||||
if (workspace.sharedAttachments.length)
|
||||
if (workspace.sharedAttachments.some((attachment) => attachment.kind !== "edge"))
|
||||
throw new ExecutionPlanError(
|
||||
"UNSUPPORTED_SHARED_STORAGE",
|
||||
"kernel",
|
||||
"Stage 0 requires explicit conformance-owned storage",
|
||||
"Shared scalar storage is not implemented; use conformance-owned state",
|
||||
);
|
||||
const schema = (type: ValueType): unknown | null => {
|
||||
try {
|
||||
@@ -36,7 +36,30 @@ export function compileKernelProgram(plan: ExecutionPlan): unknown {
|
||||
}
|
||||
};
|
||||
const ownerBySlot = new Map<string, string>();
|
||||
const edges: { id: string; owner: string; a: unknown; b: unknown }[] = [];
|
||||
const edges: { id: string; owner: string | null; a: unknown; b: unknown }[] = [];
|
||||
const lowerEdge = (storage: Extract<PersistentAttachment, { kind: "edge" }>, owner: string | null) => {
|
||||
const endpoints = storage.endpoints.map((endpoint) => {
|
||||
if (endpoint.ordered || (endpoint.keyType && endpoint.keyType !== "string") || endpoint.retainOther)
|
||||
throw new ExecutionPlanError(
|
||||
"UNSUPPORTED_GRAPH_FEATURE",
|
||||
storage.id,
|
||||
"Ordered relations, non-string keys and automatic retention are not implemented",
|
||||
);
|
||||
return {
|
||||
projection: endpoint.projectionId,
|
||||
constraint: {
|
||||
kind: endpoint.constraint.kind,
|
||||
id:
|
||||
endpoint.constraint.kind === "atom" ? endpoint.constraint.atomId : endpoint.constraint.interfaceRevisionId,
|
||||
},
|
||||
cardinality: endpoint.cardinality,
|
||||
...(endpoint.keyType ? { keyType: endpoint.keyType } : {}),
|
||||
...(endpoint.onDelete ? { onDelete: endpoint.onDelete } : {}),
|
||||
};
|
||||
});
|
||||
edges.push({ id: storage.id, owner, a: endpoints[0], b: endpoints[1] });
|
||||
};
|
||||
for (const storage of workspace.sharedAttachments) if (storage.kind === "edge") lowerEdge(storage, null);
|
||||
const owners = plan.definition.owners.map((owner) => {
|
||||
const slots: unknown[] = [];
|
||||
for (const storage of owner.storage as PersistentAttachment[]) {
|
||||
@@ -51,30 +74,7 @@ export function compileKernelProgram(plan: ExecutionPlan): unknown {
|
||||
policy: storage.storagePolicy.kind === "register" ? "register" : "crdt",
|
||||
...(Object.hasOwn(storage, "defaultValue") ? { defaultLiteral: storage.defaultValue } : {}),
|
||||
});
|
||||
} else {
|
||||
const endpoints = storage.endpoints.map((endpoint) => {
|
||||
if (endpoint.ordered || (endpoint.keyType && endpoint.keyType !== "string") || endpoint.retainOther)
|
||||
throw new ExecutionPlanError(
|
||||
"UNSUPPORTED_GRAPH_FEATURE",
|
||||
storage.id,
|
||||
"Ordered relations, non-string keys and automatic retention are not implemented",
|
||||
);
|
||||
return {
|
||||
projection: endpoint.projectionId,
|
||||
constraint: {
|
||||
kind: endpoint.constraint.kind,
|
||||
id:
|
||||
endpoint.constraint.kind === "atom"
|
||||
? endpoint.constraint.atomId
|
||||
: endpoint.constraint.interfaceRevisionId,
|
||||
},
|
||||
cardinality: endpoint.cardinality,
|
||||
...(endpoint.keyType ? { keyType: endpoint.keyType } : {}),
|
||||
...(endpoint.onDelete ? { onDelete: endpoint.onDelete } : {}),
|
||||
};
|
||||
});
|
||||
edges.push({ id: storage.id, owner: owner.id, a: endpoints[0], b: endpoints[1] });
|
||||
}
|
||||
} else lowerEdge(storage, owner.id);
|
||||
}
|
||||
return {
|
||||
id: owner.id,
|
||||
|
||||
@@ -82,7 +82,9 @@ function componentDeclarations(workspace: WorkspaceRevision, pkg: WorkspaceRevis
|
||||
...(pkg.modules ?? []).flatMap((module) => {
|
||||
const contract = moduleContract(workspace.interfaceImports, module)!;
|
||||
if (
|
||||
!["org.quixos.react.component/1", "org.quixos.react.component/2", "org.quixos.react.subject-only/1"].includes(contract.contract) ||
|
||||
!["org.quixos.react.component/1", "org.quixos.react.component/2", "org.quixos.react.subject-only/1"].includes(
|
||||
contract.contract,
|
||||
) ||
|
||||
contract.subject?.kind !== "interface"
|
||||
)
|
||||
return [];
|
||||
|
||||
Reference in New Issue
Block a user