Implement query execution, scoped RPC enrichment, live collections, and scaffold integration
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user