Implement query execution, scoped RPC enrichment, live collections, and scaffold integration

This commit is contained in:
Timothy J. Aveni
2026-09-17 16:49:44 -07:00
parent 61a410f98f
commit cd13120937
37 changed files with 4406 additions and 2647 deletions
+15
View File
@@ -132,6 +132,21 @@ export const runtimeContracts = (workspace: WorkspaceRevision): RuntimeContract[
})),
});
const dependency = (parent: GraphNode, binding: DependencyBinding, atomId: string, reviews?: Set<string>) => {
if (binding.kind === "query") {
const pkg = workspace.packageImports.find((pkg) => pkg.revisionId === binding.packageRevisionId);
const query = pkg?.checkedQueries?.find((query) => query.declaration.id === binding.queryId);
if (!query) throw new Error(`Missing checked query contract ${binding.packageRevisionId}:${binding.queryId}`);
const key = `query:${binding.packageRevisionId}:${binding.queryId}`;
const queryNode = nodes.get(key) ?? node(key, query);
parent.dependencies.add(key);
for (const effect of query.effects) {
queryNode.dependencies.add(`interface:${effect.interfaceRevisionId}`);
for (const conformance of workspace.conformances.filter(
(entry) => entry.interfaceRevisionId === effect.interfaceRevisionId,
))
queryNode.dependencies.add(conformanceKey(conformance.atomId, conformance.interfaceRevisionId));
}
}
if (binding.kind === "state") parent.dependencies.add(`attachment:${binding.slotId}`);
if (binding.kind === "edge") parent.dependencies.add(`attachment:${binding.edgeTypeId}`);
if (binding.kind === "constructor") {
+3
View File
@@ -22,6 +22,7 @@ import {
export type GenericDependencyPort = Omit<DependencyPort, "requirement"> & {
requirement:
| Extract<DependencyPort["requirement"], { kind: "query" }>
| {
kind: "state";
valueType: ValueTypeExpression;
@@ -79,6 +80,8 @@ export const specializePackageExport = (
const ports: DependencyPort[] = definition.dependencyPorts.map((port) => {
const requirement = port.requirement;
switch (requirement.kind) {
case "query":
return { ...port, requirement };
case "state":
return { ...port, requirement: { ...requirement, valueType: substitution.value(requirement.valueType) } };
case "edge":
+1
View File
@@ -101,6 +101,7 @@ export const instantiateInterface = (
target: substitution.object(member.target, member.displayName),
cardinality: member.cardinality,
ordered: member.ordered,
...(member.keyType ? { keyType: member.keyType } : {}),
};
case "operation":
return {
+4
View File
@@ -148,6 +148,7 @@ export interface RelationshipInterfaceMember<
target: Target;
cardinality: EdgeCardinality;
ordered: boolean;
keyType?: "string" | "boolean" | "int64";
}
/** A named callable capability that is not value or relationship sugar. */
@@ -222,6 +223,7 @@ export type PackageReceiverRequirement =
};
export type DependencyPortRequirement =
| { kind: "query"; packageRevisionId: PackageRevisionId; queryId: string }
| {
kind: "state";
valueType: ValueType;
@@ -276,6 +278,7 @@ export type PackageExport = PackageOperationExport | PackageFunctionExport | Pac
export interface PackageRevision {
queries?: import("../query/types.js").QueryDeclaration[];
checkedQueries?: import("../query/types.js").CheckedQuery[];
queryTemplates?: import("../query/types.js").QueryTemplate[];
genericExports?: import("./generic-packages.js").GenericPackageExport[];
argumentRequirements?: { target: ObjectExpectation; required: InterfaceRevisionId }[];
migrationCatalog?: import("./migrations.js").MigrationCatalog;
@@ -289,6 +292,7 @@ export interface PackageRevision {
}
export type DependencyBinding =
| { kind: "query"; packageRevisionId: PackageRevisionId; queryId: string; via?: EdgeTraversal }
| { kind: "state"; slotId: SlotId; via?: EdgeTraversal }
| {
kind: "edge";
+79 -1
View File
@@ -504,6 +504,18 @@ const collectIdentityIndexes = (
const operations = new Map<OperationId, InterfaceOperationEntry>();
for (const [memberIndex, member] of revision.members.entries()) {
const memberPath = `${path}.members[${memberIndex}]`;
if (
member.kind === "relationship" &&
member.keyType !== undefined &&
(!["string", "boolean", "int64"].includes(member.keyType) ||
!["many", "many-unique"].includes(member.cardinality))
)
issue(
issues,
"invalid-query-contract",
memberPath,
"Keyed relationships require many cardinality and string, boolean or int64 keys",
);
if (member.kind !== "operation" && member.queryRead) {
const contract = member.queryRead.execution;
const getter = member.kind === "value" ? "get" : "resolve";
@@ -984,6 +996,21 @@ const validatePackages = (
for (const [portIndex, port] of entry.dependencyPorts.entries()) {
const portPath = `${exportPath}.dependencyPorts[${portIndex}]`;
switch (port.requirement.kind) {
case "query":
if (
!indexes.packages
.get(port.requirement.packageRevisionId)
?.revision.queries?.some(
(query) => port.requirement.kind === "query" && query.id === port.requirement.queryId,
)
)
issue(
issues,
"unresolved-reference",
portPath,
`Unknown query ${port.requirement.packageRevisionId}:${port.requirement.queryId}`,
);
break;
case "state":
validateValueType(issues, port.requirement.valueType, `${portPath}.requirement.valueType`, indexes);
uniquePrimitiveList(issues, port.requirement.primitives, `${portPath}.requirement.primitives`);
@@ -1133,6 +1160,41 @@ const validateBoundDependencies = (
continue;
}
switch (requirement.kind) {
case "query": {
const selected = binding as Extract<DependencyBinding, { kind: "query" }>;
const query = params.indexes.packages
.get(requirement.packageRevisionId)
?.revision.queries?.find((query) => query.id === requirement.queryId);
if (
!query ||
selected.queryId !== requirement.queryId ||
selected.packageRevisionId !== requirement.packageRevisionId
) {
issue(issues, "invalid-dependency-binding", path, "Query port must bind its exact checked query export");
break;
}
const traversal = selected.via
? validateTraversal(
issues,
params.indexes,
params.atomId,
selected.via,
`${path}.binding.via`,
params.conformance,
)
: undefined;
const targets = selected.via
? traversal
? [...params.indexes.atoms.keys()].filter((atom) =>
atomSatisfiesConstraint(atom as AtomId, traversal.target.constraint, params.indexes.conformances),
)
: []
: [params.atomId];
for (const atom of targets)
if (!params.indexes.conformances.has(conformanceKey(atom as AtomId, query.root)))
issue(issues, "unsatisfied-interface", path, `Query root ${atom} does not conform to ${query.root}`);
break;
}
case "state": {
const stateBinding = binding as Extract<DependencyBinding, { kind: "state" }>;
const attachment = findAttachment(params.indexes, "state", stateBinding.slotId);
@@ -1583,7 +1645,8 @@ const validateConformances = (
operationEntry.member.target,
indexes.conformances,
) ||
operationEntry.member.cardinality !== projection.endpoint.cardinality
operationEntry.member.cardinality !== projection.endpoint.cardinality ||
(operationEntry.member.keyType !== undefined && operationEntry.member.keyType !== projection.endpoint.keyType)
) {
issue(
issues,
@@ -2091,6 +2154,21 @@ export const computeCapabilityClosure = (
const includeDependencies = (atomId: AtomId, dependencies: readonly BoundDependency[]) => {
for (const dependency of dependencies) {
switch (dependency.binding.kind) {
case "query": {
packages.add(dependency.binding.packageRevisionId);
const query = plan.packages
.get(dependency.binding.packageRevisionId)
?.checkedQueries?.find(
(query) => dependency.binding.kind === "query" && query.declaration.id === dependency.binding.queryId,
);
if (dependency.binding.via) attachments.add(dependency.binding.via.edgeTypeId);
for (const effect of query?.effects ?? []) {
for (const conformance of sourceConformances.values())
if (conformance.interfaceRevisionId === effect.interfaceRevisionId)
queued.push({ atomId: conformance.atomId, interfaceRevisionId: conformance.interfaceRevisionId });
}
break;
}
case "state":
attachments.add(dependency.binding.slotId);
if (dependency.binding.via) {