@voltro/database 0.11.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sql.d.ts CHANGED
@@ -29,6 +29,14 @@ export declare interface AppliedMigration {
29
29
  readonly environment: 'dev' | 'staging' | 'prod';
30
30
  readonly rollbackPlan?: ReadonlyArray<MigrationOperation>;
31
31
  readonly durationMs: number;
32
+ /**
33
+ * How many operations the applier actually EXECUTED, counted from the per-op
34
+ * results — not `operations.length`, which is what the plan asked for. The
35
+ * two can only differ if an op reports `skipped`, but the log lines quote
36
+ * this one on principle: "applied N op(s)" derived from the plan length is a
37
+ * claim about intent dressed up as a claim about the database.
38
+ */
39
+ readonly appliedOps: number;
32
40
  readonly onlineStrategy?: 'inline' | 'concurrent' | 'batched' | 'shadow-column';
33
41
  readonly source: 'auto-diff' | 'file';
34
42
  readonly notes?: string;
@@ -90,6 +98,31 @@ export declare interface ApplyPlanCtx {
90
98
  readonly source: 'auto-diff' | 'file';
91
99
  /** Optional human note via `voltro db apply --note "..."`. */
92
100
  readonly notes?: string;
101
+ /**
102
+ * Re-plan against the LIVE schema — the convergence proof.
103
+ *
104
+ * `applyPlan` calls this once, after the DDL and BEFORE it records the
105
+ * fingerprint. A plan that converged re-plans to zero operations; anything
106
+ * left is DDL that ran without error and did not take effect, and the apply
107
+ * fails rather than recording a fingerprint that describes a database state
108
+ * that does not exist.
109
+ *
110
+ * This exists because "reports success, applies nothing" is not hypothetical.
111
+ * A schema shipped 31 operations that logged `applied 31 op(s)` on every boot
112
+ * for two releases: the statements were real, postgres accepted all of them,
113
+ * and none of them changed anything (`ALTER COLUMN … TYPE text` on a text
114
+ * column; `SET DEFAULT NULL` for a default the renderer couldn't express).
115
+ * The recorded fingerprint then made the next boot short-circuit on
116
+ * "schema up to date". Both underlying defects are fixed — this is the guard
117
+ * that makes the NEXT one loud instead of permanent.
118
+ *
119
+ * It is REQUIRED, not optional, because the caller is the only place that
120
+ * knows the exact planner inputs (which tables were filtered, which were
121
+ * ignored); an applier-side re-plan would compare against a different set and
122
+ * report drift that isn't there. A caller that cannot re-plan cannot prove it
123
+ * applied anything.
124
+ */
125
+ readonly replan: (sql: SqlClient.SqlClient) => Effect.Effect<MigrationPlan, SqlError_2, SqlClient.SqlClient>;
93
126
  }
94
127
 
95
128
  /**
@@ -598,6 +631,43 @@ export declare interface ColumnSnapshot {
598
631
  * blocks a masking export until classified.
599
632
  */
600
633
  readonly safe?: boolean;
634
+ /**
635
+ * Type PARAMETERS for the three `ColumnType`s whose DDL is not determined by
636
+ * the type tag alone — `vector(n)`, `array(of)`, `enum(name, values)`.
637
+ * DECLARED-side only (introspection reports a concrete SQL type, not the
638
+ * declaration that produced it).
639
+ *
640
+ * These exist because the applier renders its DDL from a ColumnSnapshot, not
641
+ * from the `ColumnDefinition` that `migrate.ts`'s canonical `sqlType` reads.
642
+ * Without them the snapshot renderers had nothing to render and collapsed all
643
+ * three to `text` — which is not a smaller mistake than it looks. A declared
644
+ * `vector(1536)` against a live `text` column planned an `alter-column-type`
645
+ * that emitted `ALTER COLUMN … TYPE text`: valid SQL, applied successfully,
646
+ * changed nothing. The plan re-emitted it on every boot, the applier reported
647
+ * success every time, and the schema never converged. (Reported from a live
648
+ * pod: "applied 31 op(s)" with none of the 31 present in the database.)
649
+ *
650
+ * The rule for anything added later: if the applier has to RENDER it, the
651
+ * snapshot has to CARRY it — a snapshot renderer must never invent a type it
652
+ * wasn't given.
653
+ */
654
+ readonly vectorDim?: number;
655
+ readonly vectorPrecision?: 'float32' | 'half';
656
+ readonly arrayElement?: ColumnType;
657
+ readonly enumName?: string;
658
+ readonly enumValues?: ReadonlyArray<string>;
659
+ /**
660
+ * PostGIS `geography(kind, srid)` / `geometry(kind, srid)` parameters. Same
661
+ * reason as the three above: a spatial column declares `type: 'text'`, so
662
+ * WITHOUT this the applier's `add-column` created a plain `text` column and
663
+ * introspection (`USER-DEFINED` → `text`) agreed with it — no churn, no
664
+ * error, and no spatial column. DECLARED-side only.
665
+ */
666
+ readonly spatial?: {
667
+ readonly kind: 'geography' | 'geometry';
668
+ readonly geomKind: string;
669
+ readonly srid: number;
670
+ };
601
671
  }
602
672
 
603
673
  declare type ColumnType = 'id' | 'text' | 'integer' | 'real' | 'decimal' | 'bigint' | 'boolean' | 'timestamp' | 'date' | 'json' | 'bytes' | 'reference' | 'vector' | 'enum' | 'array' | 'interval' | 'raw';
@@ -610,6 +680,16 @@ declare type ColumnType = 'id' | 'text' | 'integer' | 'real' | 'decimal' | 'bigi
610
680
  */
611
681
  export declare const declaredSnapshot: (tables: ReadonlyArray<TableLike>, dialect?: DialectId) => SchemaSnapshot;
612
682
 
683
+ /**
684
+ * `DEFAULT <expr>` for an array-valued default.
685
+ *
686
+ * Postgres is the only dialect with native arrays, so a `array()` column there
687
+ * takes an array literal (`'{a,b}'::text[]`); every other dialect stores the
688
+ * value as JSON/TEXT and takes the json form. A default on a `json()` column
689
+ * always takes the json form — the array is the VALUE, not the storage.
690
+ */
691
+ export declare const defaultArrayClause: (value: ReadonlyArray<unknown>, column: ColumnDefinition<unknown>, dialect: DialectId) => string;
692
+
613
693
  export declare const defaultClause: (column: ColumnDefinition<unknown>, dialect: DialectId) => string | null;
614
694
 
615
695
  /**
@@ -1498,6 +1578,14 @@ export declare interface SchemaSnapshot {
1498
1578
  */
1499
1579
  export declare const shortFingerprint: (fp: string) => string;
1500
1580
 
1581
+ /**
1582
+ * Snapshot a single `TableLike` declaration. Drops the runtime-only
1583
+ * fields (`computed`, `defaultFactory`, `__tsType`) that don't round-
1584
+ * trip to/from `information_schema`. `idScheme.kind` IS carried — the
1585
+ * applier needs it to emit auto-increment DDL for numeric ids.
1586
+ */
1587
+ export declare const snapshotColumn: (name: string, def: ColumnDefinition<unknown>) => ColumnSnapshot;
1588
+
1501
1589
  /**
1502
1590
  * The `sql` template tag — captures a tagged-template literal into a
1503
1591
  * {@link RawSqlFragment} descriptor without binding it to any client.