import * as Predicate from "effect/Predicate"; import * as Record from "effect/Record"; import * as GroupSpec from "./GroupSpec"; export const TypeId = "@confect/core/Spec"; export type TypeId = typeof TypeId; export const isSpec = (u: unknown): u is AnyWithProps => Predicate.hasProperty(u, TypeId); /** * A Confect spec: a flat container of function groups. Groups may be of any * runtime — a group built with `GroupSpec.makeNode()` (a Node action group) sits * alongside `GroupSpec.make()` groups in the same namespace. The runtime of a * group lives on the group itself (`GroupSpec.runtime`) and on each function's * `RuntimeAndFunctionType`; the spec does not carry a runtime of its own. */ export interface Spec { readonly [TypeId]: TypeId; readonly groups: { [GroupName in GroupSpec.Name]: GroupSpec.WithName< Groups_, GroupName >; }; add( group: Group, ): Spec; addAt( name: Name, group: Group, ): Spec>; } export interface Any { readonly [TypeId]: TypeId; } export interface AnyWithProps extends Spec {} export type Groups = Spec_["groups"][keyof Spec_["groups"]]; const Proto = { [TypeId]: TypeId, add(this: AnyWithProps, group: Group) { return makeProto({ groups: Record.set(this.groups, group.name, group), }); }, addAt( this: AnyWithProps, name: string, group: Group, ) { return makeProto({ groups: Record.set(this.groups, name, GroupSpec.withName(name, group)), }); }, }; const makeProto = ({ groups, }: { groups: Record.ReadonlyRecord; }): Spec => Object.assign(Object.create(Proto), { groups, }); export const make = (): Spec => makeProto({ groups: {} });