395 lines
10 KiB
TypeScript
395 lines
10 KiB
TypeScript
declare const opaqueIdBrand: unique symbol;
|
|
|
|
type OpaqueId<Kind extends string> = string & {
|
|
readonly [opaqueIdBrand]: Kind;
|
|
};
|
|
|
|
export type WorkspaceId = OpaqueId<"WorkspaceId">;
|
|
export type WorkspaceRevisionId = OpaqueId<"WorkspaceRevisionId">;
|
|
export type AtomId = OpaqueId<"AtomId">;
|
|
export type InterfaceId = OpaqueId<"InterfaceId">;
|
|
export type InterfaceRevisionId = OpaqueId<"InterfaceRevisionId">;
|
|
export type MemberId = OpaqueId<"MemberId">;
|
|
export type OperationId = OpaqueId<"OperationId">;
|
|
export type SlotId = OpaqueId<"SlotId">;
|
|
export type EdgeTypeId = OpaqueId<"EdgeTypeId">;
|
|
export type EdgeProjectionId = OpaqueId<"EdgeProjectionId">;
|
|
export type PackageId = OpaqueId<"PackageId">;
|
|
export type PackageRevisionId = OpaqueId<"PackageRevisionId">;
|
|
export type PackageExportId = OpaqueId<"PackageExportId">;
|
|
export type DependencyPortId = OpaqueId<"DependencyPortId">;
|
|
export type ObjectId = OpaqueId<"ObjectId">;
|
|
|
|
const opaque = <Kind extends string>(value: string) => value as OpaqueId<Kind>;
|
|
|
|
/**
|
|
* Textual IDs remain opaque to the semantic model. Authoring tools may mint
|
|
* UUID-backed values later without changing the checked IR.
|
|
*/
|
|
export const capabilityId = {
|
|
workspace: (value: string) => opaque<"WorkspaceId">(value),
|
|
workspaceRevision: (value: string) =>
|
|
opaque<"WorkspaceRevisionId">(value),
|
|
atom: (value: string) => opaque<"AtomId">(value),
|
|
interface: (value: string) => opaque<"InterfaceId">(value),
|
|
interfaceRevision: (value: string) =>
|
|
opaque<"InterfaceRevisionId">(value),
|
|
member: (value: string) => opaque<"MemberId">(value),
|
|
operation: (value: string) => opaque<"OperationId">(value),
|
|
slot: (value: string) => opaque<"SlotId">(value),
|
|
edgeType: (value: string) => opaque<"EdgeTypeId">(value),
|
|
edgeProjection: (value: string) => opaque<"EdgeProjectionId">(value),
|
|
package: (value: string) => opaque<"PackageId">(value),
|
|
packageRevision: (value: string) => opaque<"PackageRevisionId">(value),
|
|
packageExport: (value: string) => opaque<"PackageExportId">(value),
|
|
dependencyPort: (value: string) => opaque<"DependencyPortId">(value),
|
|
object: (value: string) => opaque<"ObjectId">(value),
|
|
} as const;
|
|
|
|
export interface SourceRevision {
|
|
repository: string;
|
|
commit: string;
|
|
}
|
|
|
|
export type ScalarValueTypeName =
|
|
| "bool"
|
|
| "bytes"
|
|
| "double"
|
|
| "int32"
|
|
| "int64"
|
|
| "string"
|
|
| "uint32"
|
|
| "uint64";
|
|
|
|
export type ObjectExpectation =
|
|
| { kind: "atom"; atomId: AtomId }
|
|
| {
|
|
kind: "interface";
|
|
interfaceRevisionId: InterfaceRevisionId;
|
|
};
|
|
|
|
export type ValueType =
|
|
| { kind: "builtin"; name: "unit" | "watch-handle" }
|
|
| { kind: "scalar"; name: ScalarValueTypeName }
|
|
| { kind: "message"; descriptorId: string }
|
|
| { kind: "object-ref"; expectation: ObjectExpectation }
|
|
| { kind: "optional"; value: ValueType }
|
|
| { kind: "list"; value: ValueType };
|
|
|
|
export const valueType = {
|
|
unit: { kind: "builtin", name: "unit" } as const,
|
|
watchHandle: { kind: "builtin", name: "watch-handle" } as const,
|
|
bool: { kind: "scalar", name: "bool" } as const,
|
|
bytes: { kind: "scalar", name: "bytes" } as const,
|
|
double: { kind: "scalar", name: "double" } as const,
|
|
int32: { kind: "scalar", name: "int32" } as const,
|
|
int64: { kind: "scalar", name: "int64" } as const,
|
|
string: { kind: "scalar", name: "string" } as const,
|
|
uint32: { kind: "scalar", name: "uint32" } as const,
|
|
uint64: { kind: "scalar", name: "uint64" } as const,
|
|
message: (descriptorId: string): ValueType => ({
|
|
kind: "message",
|
|
descriptorId,
|
|
}),
|
|
atomRef: (atomId: AtomId): ValueType => ({
|
|
kind: "object-ref",
|
|
expectation: { kind: "atom", atomId },
|
|
}),
|
|
interfaceRef: (interfaceRevisionId: InterfaceRevisionId): ValueType => ({
|
|
kind: "object-ref",
|
|
expectation: { kind: "interface", interfaceRevisionId },
|
|
}),
|
|
optional: (value: ValueType): ValueType => ({ kind: "optional", value }),
|
|
list: (value: ValueType): ValueType => ({ kind: "list", value }),
|
|
} as const;
|
|
|
|
export interface AtomDefinition {
|
|
id: AtomId;
|
|
displayName: string;
|
|
documentation?: string;
|
|
}
|
|
|
|
export type InterfaceOperationMode =
|
|
| "call"
|
|
| "watch-start"
|
|
| "watch-stop"
|
|
| "subscribe"
|
|
| "unsubscribe";
|
|
|
|
export interface InterfaceOperation {
|
|
id: OperationId;
|
|
displayName: string;
|
|
inputType: ValueType;
|
|
outputType: ValueType;
|
|
mode: InterfaceOperationMode;
|
|
/** Required for watch-start/subscribe and absent for other modes. */
|
|
eventType?: ValueType;
|
|
}
|
|
|
|
interface InterfaceMemberBase {
|
|
id: MemberId;
|
|
displayName: string;
|
|
operations: InterfaceOperation[];
|
|
}
|
|
|
|
export interface ValueInterfaceMember extends InterfaceMemberBase {
|
|
kind: "value";
|
|
valueType: ValueType;
|
|
}
|
|
|
|
export type EdgeCardinality =
|
|
| "optional-one"
|
|
| "exactly-one"
|
|
| "many"
|
|
| "many-unique";
|
|
|
|
export type EdgeEndpointConstraint =
|
|
| { kind: "atom"; atomId: AtomId }
|
|
| {
|
|
kind: "interface";
|
|
interfaceRevisionId: InterfaceRevisionId;
|
|
};
|
|
|
|
export interface RelationshipInterfaceMember extends InterfaceMemberBase {
|
|
kind: "relationship";
|
|
target: EdgeEndpointConstraint;
|
|
cardinality: EdgeCardinality;
|
|
ordered: boolean;
|
|
}
|
|
|
|
/** A named callable capability that is not value or relationship sugar. */
|
|
export interface OperationInterfaceMember extends InterfaceMemberBase {
|
|
kind: "operation";
|
|
inputType: ValueType;
|
|
outputType: ValueType;
|
|
}
|
|
|
|
export type InterfaceMember =
|
|
| ValueInterfaceMember
|
|
| RelationshipInterfaceMember
|
|
| OperationInterfaceMember;
|
|
|
|
export interface InterfaceRevision {
|
|
interfaceId: InterfaceId;
|
|
revisionId: InterfaceRevisionId;
|
|
displayName: string;
|
|
source: SourceRevision;
|
|
members: InterfaceMember[];
|
|
}
|
|
|
|
export type StoragePolicy =
|
|
| { kind: "optimistic-register" }
|
|
| { kind: "crdt-document"; updateType: ValueType };
|
|
|
|
export interface StateSlotDefinition {
|
|
kind: "state";
|
|
id: SlotId;
|
|
attachedTo: AtomId;
|
|
displayName: string;
|
|
valueType: ValueType;
|
|
storagePolicy: StoragePolicy;
|
|
defaultValue?: unknown;
|
|
}
|
|
|
|
export interface EdgeEndpoint {
|
|
projectionId: EdgeProjectionId;
|
|
displayName: string;
|
|
constraint: EdgeEndpointConstraint;
|
|
cardinality: EdgeCardinality;
|
|
ordered: boolean;
|
|
}
|
|
|
|
export interface EdgeDefinition {
|
|
kind: "edge";
|
|
id: EdgeTypeId;
|
|
displayName: string;
|
|
endpoints: [EdgeEndpoint, EdgeEndpoint];
|
|
}
|
|
|
|
export type PersistentAttachment = StateSlotDefinition | EdgeDefinition;
|
|
|
|
export type StatePrimitive =
|
|
| "read"
|
|
| "write"
|
|
| "watch-start"
|
|
| "watch-stop";
|
|
|
|
export type EdgePrimitive =
|
|
| "resolve"
|
|
| "connect"
|
|
| "disconnect"
|
|
| "watch-start"
|
|
| "watch-stop";
|
|
|
|
export type PackageReceiverRequirement =
|
|
| { kind: "any-object" }
|
|
| { kind: "exact-atom"; atomId: AtomId }
|
|
| {
|
|
kind: "all-interfaces";
|
|
interfaceRevisionIds: InterfaceRevisionId[];
|
|
};
|
|
|
|
export type DependencyPortRequirement =
|
|
| {
|
|
kind: "state";
|
|
valueType: ValueType;
|
|
primitives: StatePrimitive[];
|
|
}
|
|
| {
|
|
kind: "edge";
|
|
target: EdgeEndpointConstraint;
|
|
cardinality: EdgeCardinality;
|
|
primitives: EdgePrimitive[];
|
|
}
|
|
| {
|
|
kind: "interface";
|
|
interfaceRevisionId: InterfaceRevisionId;
|
|
}
|
|
| { kind: "constructor"; atomId: AtomId; inputType?: ValueType };
|
|
|
|
export interface DependencyPort {
|
|
id: DependencyPortId;
|
|
displayName: string;
|
|
requirement: DependencyPortRequirement;
|
|
}
|
|
|
|
interface PackageExportBase {
|
|
id: PackageExportId;
|
|
displayName: string;
|
|
inputType: ValueType;
|
|
outputType: ValueType;
|
|
dependencyPorts: DependencyPort[];
|
|
}
|
|
|
|
export interface PackageOperationExport extends PackageExportBase {
|
|
kind: "operation";
|
|
mode: InterfaceOperationMode;
|
|
eventType?: ValueType;
|
|
receiverRequirement: PackageReceiverRequirement;
|
|
}
|
|
|
|
export interface PackageFunctionExport extends PackageExportBase {
|
|
kind: "function";
|
|
}
|
|
|
|
export interface PackageConstructorExport extends PackageExportBase {
|
|
kind: "constructor";
|
|
constructsAtom: AtomId;
|
|
}
|
|
|
|
export type PackageExport =
|
|
| PackageOperationExport
|
|
| PackageFunctionExport
|
|
| PackageConstructorExport;
|
|
|
|
export interface PackageRevision {
|
|
packageId: PackageId;
|
|
revisionId: PackageRevisionId;
|
|
displayName: string;
|
|
source: SourceRevision;
|
|
exports: PackageExport[];
|
|
}
|
|
|
|
export type DependencyBinding =
|
|
| { kind: "state"; slotId: SlotId; via?: EdgeTraversal }
|
|
| {
|
|
kind: "edge";
|
|
edgeTypeId: EdgeTypeId;
|
|
projectionId: EdgeProjectionId;
|
|
via?: EdgeTraversal;
|
|
}
|
|
| {
|
|
kind: "interface";
|
|
interfaceRevisionId: InterfaceRevisionId;
|
|
via?: EdgeTraversal;
|
|
}
|
|
| { kind: "constructor"; atomId: AtomId };
|
|
|
|
export interface BoundDependency {
|
|
portId: DependencyPortId;
|
|
binding: DependencyBinding;
|
|
}
|
|
|
|
/** Selects the object at the other end of an exactly-one relationship. */
|
|
export interface EdgeTraversal {
|
|
edgeTypeId: EdgeTypeId;
|
|
projectionId: EdgeProjectionId;
|
|
}
|
|
|
|
/**
|
|
* Provisional get-or-create recipe for a relationship implementation. The
|
|
* host projection is supplied by the relationship's resolve binding; this
|
|
* projection originates at the object constructed for the relationship.
|
|
*/
|
|
export interface RelationshipMaterialization {
|
|
memberId: MemberId;
|
|
constructorAtomId: AtomId;
|
|
edgeTypeId: EdgeTypeId;
|
|
constructedProjectionId: EdgeProjectionId;
|
|
}
|
|
|
|
export type Binding =
|
|
| {
|
|
kind: "state";
|
|
slotId: SlotId;
|
|
primitive: StatePrimitive;
|
|
}
|
|
| {
|
|
kind: "edge";
|
|
edgeTypeId: EdgeTypeId;
|
|
projectionId: EdgeProjectionId;
|
|
primitive: EdgePrimitive;
|
|
}
|
|
| {
|
|
kind: "package";
|
|
packageRevisionId: PackageRevisionId;
|
|
exportId: PackageExportId;
|
|
dependencies: BoundDependency[];
|
|
};
|
|
|
|
export interface OperationBinding {
|
|
operationId: OperationId;
|
|
binding: Binding;
|
|
}
|
|
|
|
export interface Conformance {
|
|
atomId: AtomId;
|
|
interfaceRevisionId: InterfaceRevisionId;
|
|
privateAttachments: PersistentAttachment[];
|
|
operationBindings: OperationBinding[];
|
|
relationshipMaterializations: RelationshipMaterialization[];
|
|
}
|
|
|
|
export interface AtomConstructorBinding {
|
|
atomId: AtomId;
|
|
packageRevisionId: PackageRevisionId;
|
|
exportId: PackageExportId;
|
|
dependencies: BoundDependency[];
|
|
}
|
|
|
|
export interface WorkspaceRevision {
|
|
id: WorkspaceRevisionId;
|
|
workspaceId: WorkspaceId;
|
|
parentRevisionIds: WorkspaceRevisionId[];
|
|
sourceRootCommit: string;
|
|
atoms: AtomDefinition[];
|
|
sharedAttachments: PersistentAttachment[];
|
|
interfaceImports: InterfaceRevision[];
|
|
packageImports: PackageRevision[];
|
|
conformances: Conformance[];
|
|
constructors: AtomConstructorBinding[];
|
|
}
|
|
|
|
export type AttachmentOwner =
|
|
| { kind: "workspace" }
|
|
| {
|
|
kind: "conformance";
|
|
atomId: AtomId;
|
|
interfaceRevisionId: InterfaceRevisionId;
|
|
};
|
|
|
|
export interface OwnedAttachment {
|
|
attachment: PersistentAttachment;
|
|
owner: AttachmentOwner;
|
|
}
|