diff --git a/modules/showcase/provisioner/index.ts b/modules/showcase/provisioner/index.ts index 5e4b9bf8..aea284cd 100644 --- a/modules/showcase/provisioner/index.ts +++ b/modules/showcase/provisioner/index.ts @@ -1,20 +1,19 @@ // showcase's provisioner — how a consumer is given an instance of what this module provides. // // **A provider ships the provisioner that creates instances of the resource it offers** (ADR -// 0040). The mesh asks; this adapts that request to whatever the software actually needs, and -// hands back what the consumer is given. -import { provisioner } from "@novox/mesh-sdk/provisioner"; +// 0040). The mesh asks; this adapts that request to whatever the software actually needs. The +// reconcile loop is the sdk's (`runProvisioner`); this writes only the per-service half. +import { runProvisioner, type Provision } from "@novox/mesh-sdk/provisioner"; -await provisioner({ - provision: "greeting", - async create({ consumer }: { consumer: string }) { +runProvisioner("greeting", { + async create(p: Provision): Promise { // A real provider would create something here — a database, a vhost, an account. This one has - // nothing to create, so it returns what a consumer is told, which is the half that matters: - // the mesh seals it and delivers it, and the consumer never sees this code. - return { serves: { greeting: `hello ${consumer}` } }; + // nothing to create: what a consumer is told is the manifest's `serves` block, which the mesh + // fills for this consumer, seals and delivers (ADR 0048), so the consumer never sees this code. + console.log(`[showcase] greeting ready for ${p.consumer ?? p.as}`); }, - async remove() { + async remove(): Promise { // Removal is not optional. A provider that cannot take an instance back leaves the mesh unable - // to unassign a consumer without leaking whatever it was given. + // to unassign a consumer without leaking whatever it was given. Nothing was made, so nothing goes. }, }); diff --git a/modules/showcase/tools/index.ts b/modules/showcase/tools/index.ts index 45243192..65e2dad8 100644 --- a/modules/showcase/tools/index.ts +++ b/modules/showcase/tools/index.ts @@ -1,25 +1,31 @@ // showcase's tools — its operator-facing surface, served over the broker. // // Two of them, because one tool proves a tool can exist and two prove a module can have a surface. -import { tool } from "@novox/mesh-sdk/tools"; +import { registerModuleTools, type ToolDefinition } from "@novox/mesh-sdk/tools"; -tool({ - name: "showcase_greet", - description: "Greet somebody, and say which machine did it.", - input: { type: "object", properties: { who: { type: "string" } } }, - async run({ who }: { who?: string }) { - return { greeting: `hello ${who ?? "world"}`, from: process.env.MESH_NODE ?? "somewhere" }; - }, -}); +export function getShowcaseTools(env: NodeJS.ProcessEnv = process.env): ToolDefinition[] { + return [ + { + name: "showcase_greet", + description: "Greet somebody, and say which machine did it.", + input: { type: "object", properties: { who: { type: "string" } } }, + async run(args: Readonly>) { + const who = typeof args.who === "string" && args.who !== "" ? args.who : "world"; + return { greeting: `hello ${who}`, from: env.MESH_NODE ?? "somewhere" }; + }, + }, + { + name: "showcase_state", + description: "What this module was configured with, so a test can read it back.", + input: { type: "object", properties: {} }, + async run() { + return { + greeting: env.SHOWCASE_GREETING ?? "", + database: env.SHOWCASE_DATABASE ?? "", + }; + }, + }, + ]; +} -tool({ - name: "showcase_state", - description: "What this module was configured with, so a test can read it back.", - input: { type: "object", properties: {} }, - async run() { - return { - greeting: process.env.SHOWCASE_GREETING ?? "", - database: process.env.SHOWCASE_DATABASE ?? "", - }; - }, -}); +registerModuleTools("showcase", (env) => getShowcaseTools(env));