import { type AggregateFunction, type MetaData } from "@metaobjectsdev/metadata"; import type { ColumnNamingStrategy } from "../metaobjects-config.js"; /** Structurally matches migrate-ts's `ViewDescriptor` (name + body sql + optional schema). */ /** * One output column of the view, in SELECT order, described PHYSICALLY (table + * column, not entity + field). * * migrate-ts resolves each of these to a `SqlType` against its own expected table * descriptors. Deliberately no SqlType here: codegen-ts stays ignorant of migrate * concerns, and migrate-ts stays ignorant of metadata traversal — the existing * layering (migrate-ts never imports codegen-ts; the CLI threads views in). * * Postgres allows a non-destructive `CREATE OR REPLACE VIEW` only when the existing * output columns are a PREFIX of the new ones (same names, same types, same order). * That decision cannot be made without knowing the column list, which is why it is * carried here. */ export type ExpectedViewColumn = { kind: "passthrough"; name: string; sourceTable: string; sourceColumn: string; } | { kind: "aggregate"; name: string; sourceTable: string; sourceColumn: string; agg: AggregateFunction; }; export interface ExpectedView { name: string; schema?: string; sql: string; /** * `resolutionKey()` of the object that declared this view — the projection, or the * write-through entity hosting its own read view. migrate-ts records it as * PROVENANCE (never onto the view descriptor, never into the committed snapshot) so * a per-command `migrate.scope` can decide ownership on the declaring FQN rather * than on the physical view name, which no naming strategy can reverse. */ fqn: string; /** * Physical tables this view reads (base + every joined table). The migrate-ts * diff uses this to recreate the view when one of its source tables undergoes a * column-altering change — postgres blocks ALTER on a column a view depends on, * so the view must be dropped before and recreated after. */ dependsOn: string[]; /** * The view's output columns, in SELECT order — i.e. DECLARATION order, since * extractViewSpec walks the projection's children in order. That is exactly the * order Postgres's OR-REPLACE prefix rule wants: a field appended to the * projection lands last, so the change stays non-destructive. (Re-canonicalizing * to, say, alphabetical order would be strictly WORSE — it would scatter an * appended field into the middle and force a destructive drop+create.) * * OMITTED for an `@sql` (#208) view: the body is opaque — the tool never parses it, * so its output columns are unknown. migrate-ts reads absent columns as "unknown" * and fails safe to a gated drop+create instead of an illegal CREATE OR REPLACE. */ columns?: ExpectedViewColumn[]; } export interface BuildProjectionViewsOptions { dialect: "postgres" | "sqlite" | "d1"; columnNamingStrategy?: ColumnNamingStrategy; } export declare function buildProjectionViews(root: MetaData, opts: BuildProjectionViewsOptions): ExpectedView[]; //# sourceMappingURL=build-projection-views.d.ts.map