Add activated workspace reflection and Studio definition watches
Expose bounded snapshot-bound definition reads and latest-only watches from the serving checked bundle. Add checked reflection dependency ports, generated SDK bindings and selector-scoped invocation authority. Move Studio factory, contract and query discovery to public reflection inventories. Share an active-definition watch across canvas and standalone routes and invalidate/reload on epoch changes instead of polling GetWorkspace. Document the API and deferred scope; cover compiler/codegen, SDK injection, transport authorization, activation publication, pagination and reconnect behavior. Keep all work local; no deployment or publication.
This commit is contained in:
@@ -22,7 +22,7 @@ import {
|
||||
|
||||
export type GenericDependencyPort = Omit<DependencyPort, "requirement"> & {
|
||||
requirement:
|
||||
| Extract<DependencyPort["requirement"], { kind: "query" }>
|
||||
| Extract<DependencyPort["requirement"], { kind: "query" | "reflection" }>
|
||||
| {
|
||||
kind: "state";
|
||||
valueType: ValueTypeExpression;
|
||||
@@ -80,6 +80,7 @@ export const specializePackageExport = (
|
||||
const ports: DependencyPort[] = definition.dependencyPorts.map((port) => {
|
||||
const requirement = port.requirement;
|
||||
switch (requirement.kind) {
|
||||
case "reflection":
|
||||
case "query":
|
||||
return { ...port, requirement };
|
||||
case "state":
|
||||
|
||||
@@ -223,6 +223,7 @@ export type PackageReceiverRequirement =
|
||||
};
|
||||
|
||||
export type DependencyPortRequirement =
|
||||
| { kind: "reflection"; selectors: string[] }
|
||||
| { kind: "query"; packageRevisionId: PackageRevisionId; queryId: string }
|
||||
| {
|
||||
kind: "state";
|
||||
@@ -292,6 +293,7 @@ export interface PackageRevision {
|
||||
}
|
||||
|
||||
export type DependencyBinding =
|
||||
| { kind: "reflection"; selectors: string[]; via?: never }
|
||||
| {
|
||||
kind: "query";
|
||||
packageRevisionId: PackageRevisionId;
|
||||
|
||||
@@ -998,6 +998,16 @@ const validatePackages = (
|
||||
for (const [portIndex, port] of entry.dependencyPorts.entries()) {
|
||||
const portPath = `${exportPath}.dependencyPorts[${portIndex}]`;
|
||||
switch (port.requirement.kind) {
|
||||
case "reflection":
|
||||
if (
|
||||
!port.requirement.selectors.length ||
|
||||
new Set(port.requirement.selectors).size !== port.requirement.selectors.length ||
|
||||
port.requirement.selectors.some(
|
||||
(kind) => !["active", "atoms", "interfaces", "conformances", "queries", "indexes"].includes(kind),
|
||||
)
|
||||
)
|
||||
issue(issues, "invalid-dependency-binding", portPath, "Reflection requires distinct supported selectors");
|
||||
break;
|
||||
case "query":
|
||||
if (
|
||||
!indexes.packages
|
||||
@@ -1162,6 +1172,20 @@ const validateBoundDependencies = (
|
||||
continue;
|
||||
}
|
||||
switch (requirement.kind) {
|
||||
case "reflection": {
|
||||
const selected = binding as Extract<DependencyBinding, { kind: "reflection" }>;
|
||||
if (
|
||||
selected.via ||
|
||||
JSON.stringify([...selected.selectors].sort()) !== JSON.stringify([...requirement.selectors].sort())
|
||||
)
|
||||
issue(
|
||||
issues,
|
||||
"invalid-dependency-binding",
|
||||
path,
|
||||
"Reflection requires an explicit workspace binding with exactly the declared selectors",
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "query": {
|
||||
const selected = binding as Extract<DependencyBinding, { kind: "query" }>;
|
||||
const query = params.indexes.packages
|
||||
|
||||
Reference in New Issue
Block a user