// --------------------------------------------------------------------------- // defineExecutorConfig — typed config declaration consumed by both the // schema-gen CLI and the host runtime. Single source of truth for the // plugin list. First-party and third-party plugins go through the same // `bun add @executor-js/plugin-foo` + import-and-call flow. // // `plugins` is always a factory `(deps?) => readonly AnyPlugin[]`. Some // plugins want runtime values from the host (e.g., the openapi plugin's // `configFile` sink, which is keyed to the active scope cwd and so can't // be constructed at module-eval time). Deps are optional — the // schema-gen CLI and Vite plugin call `plugins()` with no args (they // read `plugin.schema` / `plugin.packageName` only); runtime callers // pass concrete deps. // // Each app declares its own deps shape inline on the factory parameter // — TS infers `TDeps` from there, so apps don't reach into the SDK's // types via `declare module`. // --------------------------------------------------------------------------- import type { AnyPlugin } from "./plugin"; export type ExecutorDialect = "pg" | "sqlite" | "mysql"; export type ExecutorPluginsFactory< TDeps extends object = object, TPlugins extends readonly AnyPlugin[] = readonly AnyPlugin[], > = (deps?: TDeps) => TPlugins; export interface ExecutorCliConfig< TDeps extends object = object, TPlugins extends readonly AnyPlugin[] = readonly AnyPlugin[], > { readonly dialect: ExecutorDialect; readonly plugins: ExecutorPluginsFactory; } /** * Declare an executor config. The CLI imports this file via jiti and * reads `plugins` + `dialect` to generate the drizzle schema; the host * runtime imports the same file to instantiate plugins. Plugin runtime * credentials passed to the factory may be stubs from the CLI — only * `plugin.schema` is read there. * * The `const TPlugins` modifier preserves the tuple-literal inference * from the factory's return so per-plugin extension typing flows through * (`ReturnType` keeps `[OpenApi, Mcp, ...]`). * * `TDeps` is inferred from the factory's parameter — apps annotate * the destructure (e.g., `({ configFile }: { configFile?: ConfigFileSink })`) * directly. No global module augmentation needed. */ export const defineExecutorConfig = < TDeps extends object, const TPlugins extends readonly AnyPlugin[], >( config: ExecutorCliConfig, ): ExecutorCliConfig => config;