// Types for build.js: a route's NSID is one of the caller's hooks and its target's module implements it; an // instance's input is its module's config. type Type = "string" | "integer" | "number" | "boolean" | "object" | "array"; type ValueOf = T extends "integer" | "number" ? number : T extends "boolean" ? boolean : T extends "array" ? unknown[] : T extends "object" ? Record : string; export interface Field { readonly key: string; readonly type?: Type; readonly required?: boolean; } export interface Binding { readonly key: string; readonly pin?: string; readonly hooks?: readonly { readonly nsid: string; readonly reason: string }[]; readonly implements?: readonly { readonly nsid: string; readonly entry: string }[]; readonly config?: readonly Field[]; readonly entries: readonly string[]; } type Of = L extends readonly (infer X)[] ? (X extends { readonly [P in K]: infer V } ? V : never) : never; export type HookOf = M extends { readonly hooks: infer H } ? Of : never; export type ImplOf = M extends { readonly implements: infer I } ? Of : never; export type EntryOf = M extends { readonly entries: readonly (infer E)[] } ? E : never; /** A parameter's placeholder, typed by the parameter's type; a host value fits any field. */ export interface Param { readonly $param: string; readonly __type?: T; } export interface Host { readonly $host: string; } type FieldsOf = M extends { readonly config: readonly (infer F)[] } ? F : never; type Arg = F extends { readonly type: infer T } ? ValueOf | Param | Host : string | Param<"string"> | Host; /** The input an instance of M may have: its config fields, a required one required. */ type KeyOf = F extends { readonly key: infer K extends string } ? K : never; export type InputOf = { [F in FieldsOf as F extends { readonly required: true } ? KeyOf : never]: Arg } & { [F in FieldsOf as F extends { readonly required: true } ? never : KeyOf]?: Arg; }; export interface Instance { readonly name: string; readonly module: M; } export interface Handler { readonly handler: string; } export interface Policy { readonly instance: string; readonly entry?: string; readonly args?: unknown; } /** A target `T` for contract `N`: a type error names what is missing. */ type Serves = [N] extends [ImplOf] ? unknown : { readonly [K in `${T["key"]} does not implement ${N}`]: true }; export interface Composition { param( key: string, opts?: { label?: string; type?: T; required?: boolean; description?: string; secret?: boolean; minimum?: number; maximum?: number; values?: { default?: ValueOf; enum?: ValueOf[] } }, ): Param; instance(name: string, mod: M, opts?: { pin?: string | false; session?: string; input?: InputOf; calls?: string[]; policies?: Policy[]; budget?: Record }): Instance; handler(name: string, description?: string): Handler; route, T extends Binding>(from: Instance, nsid: N, to: Instance & Serves, NoInfer>, reason?: string, opts?: { policies?: Policy[] }): void; route>(from: Instance, nsid: N, to: Handler, reason?: string, opts?: { policies?: Policy[] }): void; export>(nsid: N, inst: Instance): void; export(nsid: string, inst: Instance, entry: EntryOf): void; build(): Promise>; json(): Promise; } export function composition(head: { name: string; description?: string; limits?: { depth?: number; calls?: number } }): Composition; export function host(name: string): Host; export function policy(inst: Instance, entry?: EntryOf, args?: unknown): Policy;