/** * Granularity driver: restructure a pgpm module's deploy surface between the * atomic, object, and consolidated shapes. * * The upstream pass (`restructureSql` in `@pgsql/transform`) rewrites one SQL * script between equivalent shapes, guarded by the statement dependency * graph. This driver lifts that to the pgpm change model: it flattens a * module's deploy scripts in plan order into one program, restructures it to * the target granularity, then re-slices the result into changes — one change * per created object — with change dependencies recomputed from the statement * graph. Like the other drivers in this package it is structurally typed on * the bundle seams: no dependency on `@pgpmjs/bundle` or `@pgpmjs/core`. * * - `atomic` — the machine-emitted shape: bare CREATE TABLE plus one * ALTER per column/constraint. * - `object` — each table fully baked; cross-object statements * (FKs, indexes, triggers, policies) stay separate. * - `consolidated` — additionally inlines FKs proven safe by the graph. */ import type { ObjectIdentity as NamingIdentity } from '@pgpmjs/naming-spec'; import type { StatementFacts } from '@pgsql/semantics'; import type { Granularity } from '@pgsql/transform'; export type { Granularity } from '@pgsql/transform'; /** * How statements are distributed across pgpm changes — orthogonal to * `Granularity`, which shapes the SQL *within* a change. * * - `alteration` — one change per alteration: every `ADD COLUMN` / * `ADD CONSTRAINT` becomes its own plan entry with its own * deploy/revert/verify and graph-derived requires, so a * single column can deploy or revert independently. * - `object` — one change per created object (the default): a table's * CREATE and all its ALTERs share one plan entry. * - `single` — one change for the whole module: every statement lands in * a single plan entry with one deploy/revert/verify. */ export type ChangeGranularity = 'alteration' | 'object' | 'single'; export declare const CHANGE_GRANULARITIES: readonly ChangeGranularity[]; export declare const isChangeGranularity: (value: string) => value is ChangeGranularity; /** A change's deploy surface going into or out of the restructure. */ export interface GranularityChange { /** Change name (plan token, e.g. `schemas/app/tables/users/table`). */ name: string; /** Change names this change requires (within the same module). */ dependencies: string[]; /** Deploy SQL (headerless — the caller owns pgpm headers). */ deploy: string; } /** A restructured change: deploy plus generated revert/verify scripts. */ export interface RestructuredChange extends GranularityChange { /** * Generated revert SQL (headerless): mechanical inverses of the change's * statements in reverse topological order within the group, via * `revertFor`. Non-invertible statements leave a `-- revert not * derivable` comment and a warning. */ revert: string; /** * Generated verify SQL (headerless): one raise-on-failure existence check * per created object, via `verifyFor`. */ verify: string; } export interface RestructureModuleOptions { granularity: Granularity; /** * Change-level distribution (default `object`). With `alteration`, every * single-command `ALTER TABLE ADD COLUMN` / `ADD CONSTRAINT` in the * restructured script becomes its own change, named by the sub-object's * naming-spec path (`.../columns/{name}/column`, * `.../constraints/{name}/constraint`); unnamed constraints are first * given their Postgres default name so each change stays revertible. * With `single`, the whole restructured script becomes one change. */ changeGranularity?: ChangeGranularity; /** * Plan token for the single change (used only with `changeGranularity: * 'single'`). Defaults to `module/init`. */ singleChangeName?: string; /** * Derive a change name for an alteration group from its sub-object * identity (used only with `changeGranularity: 'alteration'`). Defaults to * `pathFor` in `directory` style. */ subObjectName?: (identity: NamingIdentity) => string; /** * Derive a change name for a statement group from the facts of its primary * (creating) statement. Defaults to {@link defaultChangeName}: naming spec * v1 paths (`identityOf` + `pathFor`). */ changeName?: (facts: StatementFacts) => string; } export interface RestructureModuleResult { /** Restructured changes in deploy order, dependencies recomputed. */ changes: RestructuredChange[]; /** Non-fatal notes (folds rejected to preserve ordering, etc.). */ warnings: string[]; } /** * Default change name for a statement group: the object's canonical naming * spec v1 path — `identityOf(facts)` (Postgres-native identity, from * `@pgsql/transform`) rendered through `pathFor` (`@pgpmjs/naming-spec`). * Paths are pure projections of identity, never authored. */ export declare function defaultChangeName(facts: StatementFacts): string; /** * Restructure a module's deploy changes to the target granularity. * * The flattened program is restructured as one script, then re-sliced: each * emitted statement joins the group of the object it creates (statements * creating nothing attach to the previous group), groups become changes named * by `changeName`, and change dependencies are the statement-graph edges * mapped onto owning groups. Requires `loadModule()` from `plpgsql-parser`. */ export declare function restructureChanges(changes: GranularityChange[], options: RestructureModuleOptions): RestructureModuleResult;