import { CollectionConfig, ResolvedRelation } from "@rebasepro/types"; import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry"; /** * Turning a drizzle result into a row we serve. * * There are two shapes, and they are the same walk. Both take a row whose * relation fields hold nested objects, both unwrap junction rows to reach the * target behind them, and both leave every other column alone. They differ only * in what they put where the relation was: * * - `"ref"` — a `{ id, path, __type: "relation" }` reference carrying the * target's values. This is what the admin renders. * - `"inline"` — the target's own columns, flat. This is what REST serves, and * — since the in-process SDK reads through the same pipeline — what * `rebase.data` / `context.data` serve too. A developer never sees a ref. * * They used to be two functions that happened to agree, and the agreement was * not enforced by anything: the row-identity bug had to be fixed five times * across differently-shaped copies of this walk, and one of the copies was * dead code nobody had noticed. Whatever the next cross-cutting change is, it * is one edit here. */ export type RelationStyle = "ref" | "inline"; /** * Whether a many-relation reaches its target through a junction table. * * Also used to build the drizzle `with` config, which is why it is exported: * the query has to nest one level deeper for a junction, and the row walk has * to unwrap that same level back out. */ export declare function isJunctionRelation(relation: ResolvedRelation): boolean; /** * The address a relation ref points at. * * The whole key, not its first column: a composite-keyed target addressed by * `tenant_id` alone points at every row that shares it. A target whose key * cannot be resolved at all used to throw here — reading `[0]` of an empty * array — taking down the parent's fetch over a relation it may not even have * asked for. The first column is a guess, but a ref that resolves to nothing * beats no rows at all. */ export declare function relationTargetAddress(targetRow: Record, targetCollection: CollectionConfig, registry: PostgresCollectionRegistry): string; /** * The row the admin renders: every column, with relations as references. * * Values are normalized (dates, numbers, NaN) because the admin's view-model * expects real types. The row's own address is *not* among the columns — it is * derived by the consumer from the collection's primary keys. */ export declare function toFlatRow(row: Record, collection: CollectionConfig, registry: PostgresCollectionRegistry): Record; /** * The row REST serves: every column under its own name, with the value Postgres * returned, and relations inlined as the target's columns. * * Values are the ones the database returned, except where that contradicts the * declared type: a `number` property is served as a number (see * {@link coerceDeclaredNumber}). Dates stay as the database returned them — * JSON has its own opinions about dates that the admin's view-model does not * share. * * Keyed by the row rather than by the relation list — a REST fetch only loads * the relations `include` asked for, so the row is the authority on which are * actually there. */ export declare function toRestRow(row: Record, collection: CollectionConfig, registry: PostgresCollectionRegistry): Record;