diff --git a/src/main.ts b/src/main.ts index 4c17be6..c3bcc4c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,13 +1,21 @@ -// The runnable entrypoint. Reads its configuration from the environment the host resolved for it, -// connects the mesh broker, and serves the assigned modules' tools until stopped. +// The runnable entrypoint. Two modes: // -// MESH_BROKER_URL amqp://… the mesh broker -// MESH_TOOL_MODULES /path/a,/path/b,… compiled tool entrypoints of the assigned modules +// mesh-tools serve — bind the broker and serve the assigned modules until +// stopped. A module entrypoint that subscribes to events (on("#")) +// starts consuming as it is imported, so this also runs consumers. +// mesh-tools emit TYPE [JSON] emit one event onto the mesh and exit — an operable primitive, +// and what an events test uses to put a message on the wire. +// +// MESH_BROKER_URL amqp://… the mesh broker (both modes) +// MESH_TOOL_MODULES /path/a,/path/b,… compiled module entrypoints (serve mode) +// MESH_MODULE / MESH_NODE the identity stamped onto emitted events (ADR 0047) import { connectAmqp } from "./broker-amqp.js"; import { runTools } from "./runtime.js"; +import { useBroker } from "@novox/mesh-sdk/messaging"; +import { emit } from "@novox/mesh-sdk/events"; -async function main(): Promise { +async function serve(): Promise { const url = requireEnv("MESH_BROKER_URL"); const moduleEntrypoints = (process.env.MESH_TOOL_MODULES ?? "") .split(",") @@ -26,6 +34,38 @@ async function main(): Promise { process.on("SIGINT", () => void shutdown()); } +async function emitOnce(type: string, bodyJson: string): Promise { + const url = requireEnv("MESH_BROKER_URL"); + let body: unknown = {}; + if (bodyJson) { + try { + body = JSON.parse(bodyJson); + } catch { + console.error(`mesh-tools emit: body is not JSON: ${bodyJson}`); + process.exit(1); + } + } + const broker = await connectAmqp(url); + useBroker(() => broker); + // emit awaits the broker's publish confirm (ADR 0047), so the event is accepted before we close. + await emit(type, body); + await broker.close(); +} + +async function main(): Promise { + const [command, ...rest] = process.argv.slice(2); + if (command === "emit") { + const type = rest[0]; + if (!type) { + console.error("mesh-tools emit [json-body] — a routing key is required"); + process.exit(1); + } + await emitOnce(type, rest[1] ?? ""); + return; + } + await serve(); +} + function requireEnv(name: string): string { const v = process.env[name]; if (!v) {