import { ZodTypeAny, z } from 'zod'; /** * Public types for the Autonoma SDK. * * The SDK is now factory-driven: every model the dashboard can create * comes from a registered factory, and each factory carries a Zod input * schema (and optional ref schema). There is no SQL introspection, no * SQL fallback, and no executor on `HandlerConfig`. Factories that need * DB access use whatever client the host already has. */ interface SchemaInfo { models: ModelInfo[]; /** Always emitted as `[]` in factory-driven mode; kept for wire-shape symmetry. */ edges: FKEdge[]; /** Always emitted as `[]` in factory-driven mode; kept for wire-shape symmetry. */ relations: SchemaRelation[]; scopeField: string; } /** Wire-shape relic — emitted as an empty array in factory-driven mode. */ interface SchemaRelation { parentModel: string; childModel: string; parentField: string; childField: string; } interface ModelInfo { name: string; /** Cosmetic — snake_case of `name`; the dashboard renders it for display only. */ tableName: string; fields: FieldInfo[]; } interface FieldInfo { name: string; type: string; isRequired: boolean; isId: boolean; hasDefault: boolean; } /** Wire-shape relic — emitted as an empty array in factory-driven mode. */ interface FKEdge { from: string; to: string; localField: string; foreignField: string; nullable: boolean; } interface SdkInfo { language: string; orm: string; server: string; } interface FactoryContext { /** All refs created so far, keyed by model name */ refs: Record[]>; /** Logical scope value or testRunId fallback (kept for backwards-compat). */ scenarioName: string; /** Unique ID for this test run */ testRunId: string; } /** * Factory definition. * * The two type parameters are bound to the Zod schemas you pass in: * - `TInput extends ZodTypeAny` — the create input. `data` arrives * already validated and typed as `z.infer`, so your factory * body doesn't need a manual `z.infer<...>` annotation. * - `TRef extends ZodTypeAny` — the shape your `create` returns and * `teardown` later receives. When `refSchema` is omitted, `TRef` * widens to a generic `{ id; ... }` record so old factories keep * compiling without a refSchema. * * Bind both at the call site by writing `defineFactory({...})` — TS * infers the generics from the schema instances. */ interface FactoryDefinition { /** * Create a single entity. Receives the validated input (parsed by * `inputSchema`) and must return at least `{ id }`. When `refSchema` * is set, the return type is constrained to `z.input` so the * teardown signature lines up exactly. */ create: (data: z.infer, ctx: FactoryContext) => Promise> | RefRecord; /** * Optional teardown per record. Receives whatever `create` returned — * validated through `refSchema` first when one is registered. If * omitted the model is left alone on `down`. There is no SQL fallback. */ teardown?: (record: TRef extends ZodTypeAny ? z.infer : Record & { id: string | number; }, ctx: FactoryContext) => Promise | void; /** Required Zod schema for the create input — drives both validation and discover. */ inputSchema: TInput; /** Optional Zod schema for the record returned by `create` (validated on teardown). */ refSchema?: TRef; } type RefRecord = TRef extends ZodTypeAny ? z.input : Record & { id: string | number; }; type FactoryRegistry = Record>; interface HandlerConfig { /** Scope field name (camelCase), e.g., 'organizationId' */ scopeField: string; /** Shared secret — known by both you and Autonoma. Used to verify HMAC signatures on incoming requests. */ sharedSecret: string; /** Internal secret — only you know this. Used to sign the refs JWT token. Autonoma never sees it. */ signingSecret: string; /** Factory definitions per model. Required: every model the dashboard sends in `create` must have one. */ factories?: FactoryRegistry; /** * @deprecated Ignored - the endpoint is always enabled; HMAC signing is the * gate. On Autonoma preview environments (`AUTONOMA_PREVIEWKIT` is set) no * extra guard is needed. If you deploy the factory in your own environments * and want it dark in production, gate it in your handler, e.g. return 404 * when `process.env.NODE_ENV === 'production'`. */ allowProduction?: boolean; /** * Auth callback — called after entity creation during `up`. * Receives the first User record from refs (or null if no User model exists) * and a context object with scopeValue and refs. * Must return auth credentials for the test runner. */ auth: (user: Record | null, context: AuthContext) => Promise | AuthResult; /** * Optional hook called before teardown in `down`. * Use this to clean up data created outside the SDK (e.g., external service records). */ beforeDown?: (context: HookContext) => Promise | void; /** * Optional hook called after entity creation and auth in `up`. * Can modify the auth result before it is returned to the caller. */ afterUp?: (context: HookContext, authResult: AuthResult) => Promise | AuthResult; /** SDK identity metadata. Server adapters populate this. */ sdk?: Partial; } interface AuthContext { /** The detected scope value (e.g. organization ID) or testRunId fallback. */ scopeValue: string; /** All created entity refs, keyed by model name. */ refs: Record[]>; } interface HookContext { scenarioName: string; refs: Record[]>; } interface AuthCookie { name: string; value: string; httpOnly?: boolean; sameSite?: 'strict' | 'lax' | 'none'; path?: string; domain?: string; secure?: boolean; maxAge?: number; } interface AuthResult { cookies?: AuthCookie[]; headers?: Record; credentials?: Record; } interface HandlerRequest { body: string; headers: Record; } interface HandlerResponse { status: number; body: Record; } interface DiscoverResponse { schema: SchemaInfo; } interface UpResponse { auth: AuthResult; refs: Record[]>; refsToken: string; } interface DownResponse { ok: boolean; } interface TopoSortResult { sorted: string[]; cycles: string[][]; } /** * Topological sort via Kahn's algorithm. * Returns sorted nodes and any strongly connected components (cycles). * * After detecting cycles, runs a second pass to sort nodes that depend on * cycle members (these aren't in cycles themselves but couldn't be sorted * while their cycle-member dependencies had non-zero in-degree). */ declare function topoSort(nodes: string[], edges: FKEdge[]): TopoSortResult; /** * Find a nullable FK edge in a cycle that can be deferred. * Skips self-referential edges. */ declare function findDeferrableEdge(cycle: string[], edges: FKEdge[]): FKEdge | null; export { type AuthContext as A, type DiscoverResponse as D, type FactoryRegistry as F, type HandlerConfig as H, type ModelInfo as M, type SchemaInfo as S, type TopoSortResult as T, type UpResponse as U, type HandlerRequest as a, type HandlerResponse as b, type FactoryDefinition as c, type AuthCookie as d, type AuthResult as e, type DownResponse as f, type FKEdge as g, type FactoryContext as h, type FieldInfo as i, type HookContext as j, type SchemaRelation as k, type SdkInfo as l, findDeferrableEdge as m, topoSort as t };