/** * Operation-name validation and the typed `defineOperation` builder. * * The full list of runtime operations (workflow start/signal/update/query, * schedules, reviews, attributes, etc.) is populated incrementally by the * transport-adapter phases (Phases 9-13). This module supplies: * * - `validateOperationName` / `isValidOperationName` — the regex that * `OpenRPC` discovery and the JSON-RPC dispatcher both enforce. * Operation names must follow `weft.(.)+` with * lowercase ASCII segments. The form is single-source-of-truth here. * * - `defineOperation` — a fully-typed builder that returns a concrete * `OperationDefinition`. Use this when authoring * individual operations so the `Input`/`Output` types flow through * `authorize` and `invoke` without the `as unknown as ErasedOperation` * cast required at the registry boundary. */ import type { z } from 'zod'; import type { OperationDefinition, OperationDefinitionBase } from './operation-catalog/types.ts'; export { isValidOperationName, validateOperationName } from './operation-catalog.ts'; /** * Input shape for `defineOperation`. Mirrors `OperationDefinition` but * makes `tags` optional (default `[]`) so individual operation modules * stay terse. * * `authorize` is optional. When absent, the operation's `access` policy * is the sole authorization gate — `invoke` runs as soon as the policy * passes. When present, BOTH `access` AND `authorize` must permit the * call: the policy runs first, then the parameter-aware hook. */ type OperationDefinitionInputBase = Omit, 'tags'> & { readonly tags?: ReadonlyArray; }; /** * Discriminated input for `defineOperation`, mirroring the discriminated * union on `OperationDefinition`. Streaming and subscription kinds REQUIRE * `eventSchema`; unary kinds forbid it. The compiler rejects shapes that * don't satisfy this constraint, eliminating the runtime EngineFailure * that would otherwise fire when a streaming operation tries to validate * elements without a schema. */ export type OperationDefinitionInput = (OperationDefinitionInputBase & { readonly kind?: 'unary'; readonly eventSchema?: never; }) | (OperationDefinitionInputBase & { readonly kind: 'stream'; readonly eventSchema: z.ZodType; }) | (OperationDefinitionInputBase & { readonly kind: 'subscription'; readonly eventSchema: z.ZodType; }); /** * Typed builder for a single operation. Validates the name at construction * — registration-time errors then point at the offending source line, not * at the eventual registry assembly. Defensively shallow-copies every * mutable container in the input (`tags`, `access`, `transports`, * `unknownKeyPolicy`) so that a caller mutating their original references * after this call cannot change the returned definition. The registry * deep-freezes these again at insertion as defense in depth. * * Returns a fully-typed `OperationDefinition` so caller- * side `Input`/`Output` types flow through to `authorize` / `invoke` * without an `as` cast. * * Note: the registry re-validates `name` at assembly time. The * duplication is deliberate — the registry accepts any * `RegistrableOperation` (including hand-rolled object literals), and * the assembly check is the trust boundary that OpenRPC discovery and * JSON-RPC dispatch rely on. */ export declare function defineOperation(input: OperationDefinitionInput): OperationDefinition;