/** * Step-matching types — shared between the convention walker * (libs/instance-factories/services/templates/_shared/step-matching.ts) * and consumers in `engines/src/realize/` (the per-action emitter, * the realize-time generators, ai-behaviors-generator). * * Why these types live here * ------------------------- * * The shared matcher implementation lives at * `engines/libs/instance-factories/services/templates/_shared/step-matching.ts`, * which is OUTSIDE `engines/tsconfig.json`'s `rootDir: 'src'`. tsc * rejects even type-only static imports across that boundary * (TS6059). The codebase pattern is runtime dynamic-import (see * `realize/index.ts` for `matchStep` / `matchMongoStep` / `matchPgStep`). * * Pre-#54: the four types were duplicated as local mirrors in * `engines/src/realize/per-action-emitter.ts`. Structural typing kept * them compatible at runtime, but every drift required updating both * sides — and the comments warning future readers were a footgun. * * Post-#54 (this file): both the runtime location AND the consumer * import these types from `@specverse/types`. Single source of truth; * no mirrors. Cross-package, but `@specverse/types` is the canonical * place for surfaces that span the rootDir boundary anyway. */ /** * Per-step context handed to convention walkers. * * The walker uses these fields to render a deterministic call * expression (e.g. `await prisma.poll.create({ data: { ... } })`) * that references the right model + service + parameter shape for * the action being emitted. */ export interface SharedStepContext { /** The owning model, e.g. `Poll`. */ modelName: string; /** The service / controller class name, e.g. `PollService`. */ serviceName: string; /** The action / operation being emitted. */ operationName: string; /** 1-indexed step ordinal within the action's `steps:` block. */ stepNum: number; /** Parameter names from the action signature, e.g. `['pollId', 'voter']`. */ parameterNames?: string[]; /** Variables already declared earlier in the emitted body * (so a later step can reference them without re-declaring). */ declaredVars?: Set; /** Variable name to bind the step's result to, when applicable. */ resultName?: string; } /** * One convention pattern + its emission rules. The walker iterates a * ReadonlyArray in priority order; the first * convention whose `pattern` matches the step text and whose * `generateCall` returns non-empty wins. * * Generic over the context type so per-ORM extensions (e.g. * prisma's `PrismaStepContext` adding model-graph metadata) can * carry richer data without breaking the base shape. */ export interface SharedConvention { /** Convention identifier (for audit logs + diagnostics). */ name: string; /** Regex matched against the step text. */ pattern: RegExp; /** * Emit inline code for this step. * * Returning the empty string signals "regex matched but I can't * safely emit" — the walker treats this as no-match and tries the * next convention, eventually falling through to the AI-delegate * shape. This pattern lets a convention guard against ambiguous * step bodies without complex regex back-references. */ generateCall: (match: RegExpMatchArray, ctx: C) => string; /** * Optional helper-method body emitted alongside the call site. * Used by conventions like prisma's `check {condition}` which * synthesise both an inline check and a `private async check()` * helper on the owning class. */ generateMethod?: (match: RegExpMatchArray, ctx: C) => string; } /** * The walker's result for one step. * * `matched: false` paths still populate `call`, `functionName`, * `inputs`, `resultVar` — these encode the AI-delegate fallback * call site so the controller and the AI-behaviors-generator agree * on the shape of the function the LLM is asked to fill. */ export interface MatchResult { /** Whether a convention matched (and emitted a non-empty call). */ matched: boolean; /** The emitted code line(s) for this step. */ call: string; /** A helper method body emitted alongside the call, if any. */ helperMethod?: string; /** AI-fallback only: the function name the LLM should fill. */ functionName?: string; /** AI-fallback only: parameter names passed to the LLM function. */ inputs?: string[]; /** AI-fallback only: variable name to bind the LLM result to. */ resultVar?: string; } /** * The walker's signature — exported as a distinct type so callers * can declare it as an injected dependency (e.g. on the per-action * emitter's `RealizeContext.matcher`). * * Generic over the context type for the same reason as * SharedConvention: per-ORM extensions stay structurally compatible. */ export type MatcherFn = (step: string, ctx: C, conventions: ReadonlyArray>, aiArgsExpr: (inputs: string[], paramNames: string[]) => string) => MatchResult; //# sourceMappingURL=step-matching.d.ts.map