1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 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> = T extends "integer" | "number" ? number : T extends "boolean" ? boolean : T extends "array" ? unknown[] : T extends "object" ? Record<string, unknown> : 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, K extends string> = L extends readonly (infer X)[] ? (X extends { readonly [P in K]: infer V } ? V : never) : never;
export type HookOf<M> = M extends { readonly hooks: infer H } ? Of<H, "nsid"> : never;
export type ImplOf<M> = M extends { readonly implements: infer I } ? Of<I, "nsid"> : never;
export type EntryOf<M> = 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<T extends Type = Type> {
readonly $param: string;
readonly __type?: T;
}
export interface Host {
readonly $host: string;
}
type FieldsOf<M> = M extends { readonly config: readonly (infer F)[] } ? F : never;
type Arg<F> = F extends { readonly type: infer T } ? ValueOf<T> | Param<T & Type> | Host : string | Param<"string"> | Host;
/** The input an instance of M may have: its config fields, a required one required. */
type KeyOf<F> = F extends { readonly key: infer K extends string } ? K : never;
export type InputOf<M> = { [F in FieldsOf<M> as F extends { readonly required: true } ? KeyOf<F> : never]: Arg<F> } & {
[F in FieldsOf<M> as F extends { readonly required: true } ? never : KeyOf<F>]?: Arg<F>;
};
export interface Instance<M extends Binding> {
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 string, T extends Binding> = [N] extends [ImplOf<T>] ? unknown : { readonly [K in `${T["key"]} does not implement ${N}`]: true };
export interface Composition {
param<const T extends Type = "string">(
key: string,
opts?: { label?: string; type?: T; required?: boolean; description?: string; secret?: boolean; minimum?: number; maximum?: number; values?: { default?: ValueOf<T>; enum?: ValueOf<T>[] } },
): Param<T>;
instance<M extends Binding>(name: string, mod: M, opts?: { pin?: string | false; session?: string; input?: InputOf<M>; calls?: string[]; policies?: Policy[]; budget?: Record<string, number> }): Instance<M>;
handler(name: string, description?: string): Handler;
route<F extends Binding, const N extends HookOf<F>, T extends Binding>(from: Instance<F>, nsid: N, to: Instance<T> & Serves<NoInfer<N>, NoInfer<T>>, reason?: string, opts?: { policies?: Policy[] }): void;
route<F extends Binding, const N extends HookOf<F>>(from: Instance<F>, nsid: N, to: Handler, reason?: string, opts?: { policies?: Policy[] }): void;
export<T extends Binding, const N extends ImplOf<T>>(nsid: N, inst: Instance<T>): void;
export<T extends Binding>(nsid: string, inst: Instance<T>, entry: EntryOf<T>): void;
build(): Promise<Record<string, unknown>>;
json(): Promise<string>;
}
export function composition(head: { name: string; description?: string; limits?: { depth?: number; calls?: number } }): Composition;
export function host(name: string): Host;
export function policy<M extends Binding>(inst: Instance<M>, entry?: EntryOf<M>, args?: unknown): Policy;