/** * Read an application's own refusal, and let it dictate the next request. * * `src/seed/values.ts` builds a row the *database* will accept by reading what * Postgres says when it refuses one: the constraint names the column, so the * next attempt corrects that column rather than a guessed one. This is the same * move against an HTTP application, and it works for the same reason — a * validation library does not answer "no", it answers "no, `title`, expected a * string, received undefined". * * The three shapes below cover the overwhelming majority of what an agent * writes today, and all three are machine-readable by design: * * Zod `{ issues: [{ path, code, expected, message }] }`, however it * is wrapped — bare, under `error`, or under `errors`. Both v3 * (`invalid_enum_value` / `options`) and v4 (`invalid_value` / * `values`, `invalid_format` / `format`) are read. * FastAPI `{ detail: [{ loc: ["body", "title"], msg, type }] }`, with * the `body` prefix stripped off the location. * Rails, Laravel, express-validator * `{ errors: { title: ["can't be blank"] } }` and the array * forms with a `field` / `param` / `name` beside the message. * * What is deliberately *not* here is any attempt to parse English. A body that * says `{"error":"bad request"}` names no field, and the honest outcome is to * stop and report which endpoint refused with what — not to start permuting * plausible field names until something sticks. Guessing a value into a field * the application never asked about is how a seeder ends up creating rows that * mean nothing, and a resource we cannot account for is worse than a resource * we never made. */ export interface FieldComplaint { /** Where in the body it belongs, e.g. `["profile", "name"]` or `["tags", 0]`. */ path: (string | number)[]; /** The same, as the application would print it: `profile.name`. */ field: string; message: string; /** A type the application said it expected, when it said one. */ expected?: string; /** The exact values it said it would accept, when it listed them. */ options?: string[]; /** A named string format — `email`, `uuid`, `url`, `datetime`. */ format?: string; /** A lower bound it stated, for a number, a string length or an array. */ minimum?: number; } /** Everything a validation error said, or `null` if it named no field at all. */ export declare function readComplaints(body: string): FieldComplaint[] | null; /** * A value for a field the application asked about. * * The marker goes into anything that will hold a string, because a resource * with no marker in it is a resource we cannot recognise later and therefore * cannot use as an oracle. Everything else follows what the application itself * said: the type it named, the values it listed, the bound it stated. Where it * said nothing, the field's own name is the last thing consulted — `email` and * `password` are the two fields on earth whose name really does determine the * shape of the value, and both appear on every signup form there is. */ export declare function valueFor(complaint: FieldComplaint, marker: string): unknown; /** Write a value at a dotted/indexed path, creating the containers on the way. */ export declare function setPath(body: Record, path: (string | number)[], value: unknown): void; /** Read a value back out of a body by the same path. */ export declare function getPath(body: unknown, path: (string | number)[]): unknown;