Introduce persisted Web Studio component capabilities
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
type EdgeEndpoint,
|
||||
type EdgeEndpointConstraint,
|
||||
type EdgePrimitive,
|
||||
type EdgeTraversal,
|
||||
type InterfaceMember,
|
||||
type InterfaceOperation,
|
||||
type InterfaceOperationMode,
|
||||
@@ -56,6 +57,7 @@ import { QuixosCapabilityParser,
|
||||
type ValueMemberContext,
|
||||
type ValueTypeContext,
|
||||
type RelationshipMemberContext,
|
||||
type RelationshipMaterializationDeclContext,
|
||||
type WorkspaceDeclContext,
|
||||
} from "./generated/QuixosCapabilityParser.js";
|
||||
|
||||
@@ -91,6 +93,7 @@ interface InterfaceSymbol {
|
||||
members: Map<
|
||||
string,
|
||||
{
|
||||
memberId: InterfaceMember["id"];
|
||||
operations: Map<string, InterfaceOperation["id"]>;
|
||||
}
|
||||
>;
|
||||
@@ -556,6 +559,7 @@ const lowerInterface = (
|
||||
symbol.members,
|
||||
member.displayName,
|
||||
{
|
||||
memberId: member.id,
|
||||
operations: new Map(
|
||||
member.operations.map((operation) => [operation.displayName, operation.id]),
|
||||
),
|
||||
@@ -1003,6 +1007,34 @@ const lowerBoundDependencies = (
|
||||
if (!portId) {
|
||||
return [];
|
||||
}
|
||||
const traversal = (
|
||||
edgeName: string,
|
||||
projectionName: string,
|
||||
): EdgeTraversal | undefined => {
|
||||
const attachment = requireSymbol(
|
||||
state,
|
||||
state.attachments,
|
||||
edgeName,
|
||||
entry,
|
||||
"attachment",
|
||||
);
|
||||
if (!attachment || attachment.attachment.kind !== "edge") {
|
||||
if (attachment) {
|
||||
loweringIssue(state, entry, "wrong-attachment-kind", `${edgeName} is state, not an edge`);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
const projectionId = requireSymbol(
|
||||
state,
|
||||
attachment.projections,
|
||||
projectionName,
|
||||
entry,
|
||||
`projection on ${edgeName}`,
|
||||
);
|
||||
return projectionId
|
||||
? { edgeTypeId: attachment.attachment.id, projectionId }
|
||||
: undefined;
|
||||
};
|
||||
if (entry.STATE()) {
|
||||
const attachmentName = identifier(entry.identifier(1));
|
||||
const attachment = requireSymbol(
|
||||
@@ -1023,9 +1055,16 @@ const lowerBoundDependencies = (
|
||||
}
|
||||
return [];
|
||||
}
|
||||
return [{ portId, binding: { kind: "state", slotId: attachment.attachment.id } }];
|
||||
const via = entry.VIA()
|
||||
? traversal(identifier(entry.identifier(2)), identifier(entry.identifier(3)))
|
||||
: undefined;
|
||||
if (entry.VIA() && !via) return [];
|
||||
return [{
|
||||
portId,
|
||||
binding: { kind: "state", slotId: attachment.attachment.id, ...(via ? { via } : {}) },
|
||||
}];
|
||||
}
|
||||
if (entry.EDGE()) {
|
||||
if (entry.EDGE(0)) {
|
||||
const attachmentName = identifier(entry.identifier(1));
|
||||
const projectionName = identifier(entry.identifier(2));
|
||||
const attachment = requireSymbol(
|
||||
@@ -1053,6 +1092,10 @@ const lowerBoundDependencies = (
|
||||
entry,
|
||||
`projection on ${attachmentName}`,
|
||||
);
|
||||
const via = entry.VIA()
|
||||
? traversal(identifier(entry.identifier(3)), identifier(entry.identifier(4)))
|
||||
: undefined;
|
||||
if (entry.VIA() && !via) return [];
|
||||
return projectionId
|
||||
? [
|
||||
{
|
||||
@@ -1061,6 +1104,7 @@ const lowerBoundDependencies = (
|
||||
kind: "edge",
|
||||
edgeTypeId: attachment.attachment.id,
|
||||
projectionId,
|
||||
...(via ? { via } : {}),
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -1095,6 +1139,50 @@ const lowerBoundDependencies = (
|
||||
});
|
||||
};
|
||||
|
||||
const lowerRelationshipMaterialization = (
|
||||
state: LoweringState,
|
||||
interfaceName: string,
|
||||
context: RelationshipMaterializationDeclContext,
|
||||
): WorkspaceRevision["conformances"][number]["relationshipMaterializations"][number] | undefined => {
|
||||
const memberName = identifier(context.identifier(0));
|
||||
const member = requireSymbol(
|
||||
state,
|
||||
state.interfaces.get(interfaceName)?.members ?? new Map(),
|
||||
memberName,
|
||||
context,
|
||||
`member on ${interfaceName}`,
|
||||
);
|
||||
const constructorAtom = requireSymbol(
|
||||
state,
|
||||
state.atoms,
|
||||
identifier(context.identifier(1)),
|
||||
context,
|
||||
"constructor atom",
|
||||
);
|
||||
const edgeName = identifier(context.identifier(2));
|
||||
const edge = requireSymbol(state, state.attachments, edgeName, context, "attachment");
|
||||
if (edge && edge.attachment.kind !== "edge") {
|
||||
loweringIssue(state, context, "wrong-attachment-kind", `${edgeName} is state, not an edge`);
|
||||
}
|
||||
const projectionId = edge?.attachment.kind === "edge"
|
||||
? requireSymbol(
|
||||
state,
|
||||
edge.projections,
|
||||
identifier(context.identifier(3)),
|
||||
context,
|
||||
`projection on ${edgeName}`,
|
||||
)
|
||||
: undefined;
|
||||
return member && constructorAtom && edge?.attachment.kind === "edge" && projectionId
|
||||
? {
|
||||
memberId: member.memberId,
|
||||
constructorAtomId: constructorAtom,
|
||||
edgeTypeId: edge.attachment.id,
|
||||
constructedProjectionId: projectionId,
|
||||
}
|
||||
: undefined;
|
||||
};
|
||||
|
||||
const lowerConformance = (
|
||||
state: LoweringState,
|
||||
context: ConformanceDeclContext,
|
||||
@@ -1246,11 +1334,18 @@ const lowerConformance = (
|
||||
]
|
||||
: [];
|
||||
});
|
||||
const relationshipMaterializations = context.conformanceItem().flatMap((item) => {
|
||||
const materialization = item.relationshipMaterializationDecl();
|
||||
if (!materialization) return [];
|
||||
const lowered = lowerRelationshipMaterialization(state, interfaceName, materialization);
|
||||
return lowered ? [lowered] : [];
|
||||
});
|
||||
return {
|
||||
atomId,
|
||||
interfaceRevisionId: interfaceSymbol.revisionId,
|
||||
privateAttachments,
|
||||
operationBindings,
|
||||
relationshipMaterializations,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user