@voltro/database 0.13.0 → 0.15.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/CHANGELOG.md +412 -0
- package/dist/{fileBased-DEW2BvnP.js → fileBased-Dfuv6JWP.js} +67 -67
- package/dist/index.d.ts +52 -7
- package/dist/index.js +516 -516
- package/dist/sql.d.ts +90 -32
- package/dist/sql.js +748 -679
- package/package.json +2 -2
package/dist/sql.d.ts
CHANGED
|
@@ -702,6 +702,37 @@ export declare const defaultJsonClause: (value: object, dialect: DialectId) => s
|
|
|
702
702
|
|
|
703
703
|
export declare const describeOutcome: (outcome: BootMigrationOutcome, dialectId: string) => string;
|
|
704
704
|
|
|
705
|
+
/**
|
|
706
|
+
* Parse `VOLTRO_DESTRUCTIVE_OK`.
|
|
707
|
+
*
|
|
708
|
+
* `1` / `true` acknowledges every lossy op in the run. A comma-separated list
|
|
709
|
+
* acknowledges only those TABLES — which is the form somebody wants far more
|
|
710
|
+
* often, and its absence was a real complaint: a plan carrying one intended drop
|
|
711
|
+
* plus three other lossy ops had no way to say yes to the one. `1` said yes to
|
|
712
|
+
* all four, and the alternative was a hand-written DROP migration, which the
|
|
713
|
+
* framework's own upgrade note warns against.
|
|
714
|
+
*
|
|
715
|
+
* `undefined` = not set at all.
|
|
716
|
+
*/
|
|
717
|
+
export declare const destructiveScope: (raw: string | undefined) => {
|
|
718
|
+
readonly kind: "all";
|
|
719
|
+
} | {
|
|
720
|
+
readonly kind: "tables";
|
|
721
|
+
readonly tables: ReadonlySet<string>;
|
|
722
|
+
} | undefined;
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Compare declared reactivity against the triggers actually installed.
|
|
726
|
+
*
|
|
727
|
+
* Postgres only — it is the one dialect where reactivity is carried by DDL. The
|
|
728
|
+
* binlog and Change Tracking readers are configured at runtime from the same
|
|
729
|
+
* in-memory table list the schema produced, so they cannot drift from it.
|
|
730
|
+
*/
|
|
731
|
+
export declare const detectReactiveTriggerDrift: (sql: SqlClient.SqlClient, tables: ReadonlyArray<{
|
|
732
|
+
readonly tableName: string;
|
|
733
|
+
readonly isReactive?: boolean;
|
|
734
|
+
}>) => Effect.Effect<ReactiveTriggerDrift, SqlError_2>;
|
|
735
|
+
|
|
705
736
|
/** Dialect IDs the framework supports. */
|
|
706
737
|
declare type DialectId = 'postgres' | 'mysql' | 'mariadb' | 'mssql' | 'sqlite' | 'turso';
|
|
707
738
|
|
|
@@ -879,6 +910,9 @@ export declare interface FileMigrationRunResult {
|
|
|
879
910
|
*/
|
|
880
911
|
export declare const fingerprintSchema: (snapshot: SchemaSnapshot) => string;
|
|
881
912
|
|
|
913
|
+
/** Human report, or `undefined` when the database and the schema agree. */
|
|
914
|
+
export declare const formatReactiveTriggerDrift: (drift: ReactiveTriggerDrift) => string | undefined;
|
|
915
|
+
|
|
882
916
|
/**
|
|
883
917
|
* Fully-resolved scheme stored on the `id` column definition AFTER
|
|
884
918
|
* `table()` walks the fields. For `typeid`, the prefix is always
|
|
@@ -1369,6 +1403,17 @@ export declare const parseEnumCheck: (clause: string) => {
|
|
|
1369
1403
|
readonly values: ReadonlyArray<string>;
|
|
1370
1404
|
} | null;
|
|
1371
1405
|
|
|
1406
|
+
/**
|
|
1407
|
+
* The ids of migration files present on disk but NOT yet recorded against THIS
|
|
1408
|
+
* database — i.e. exactly what `runFileBasedMigrations` would execute next.
|
|
1409
|
+
*
|
|
1410
|
+
* Exists so a caller can decide WHETHER to apply before applying. `voltro dev`
|
|
1411
|
+
* uses it to refuse unattended file migrations against a remote database: that
|
|
1412
|
+
* decision needs the list (to name it in the refusal) and must not have run
|
|
1413
|
+
* anything to get it.
|
|
1414
|
+
*/
|
|
1415
|
+
export declare const pendingFileMigrationIds: (sql: SqlClient.SqlClient, projectRoot: string) => Effect.Effect<ReadonlyArray<string>, unknown>;
|
|
1416
|
+
|
|
1372
1417
|
export declare interface PlanInput {
|
|
1373
1418
|
readonly declared: ReadonlyArray<TableLike>;
|
|
1374
1419
|
readonly live: SchemaSnapshot;
|
|
@@ -1483,6 +1528,17 @@ export declare interface RawSqlFragment {
|
|
|
1483
1528
|
readonly dependsOn?: ReadonlyArray<string>;
|
|
1484
1529
|
}
|
|
1485
1530
|
|
|
1531
|
+
/** Prefix `reactiveTableTriggerSql` names its triggers with. */
|
|
1532
|
+
export declare const REACTIVE_TRIGGER_PREFIX = "framework_changes_";
|
|
1533
|
+
|
|
1534
|
+
export declare interface ReactiveTriggerDrift {
|
|
1535
|
+
/** Tables the schema says are reactive that carry no trigger in the DB. */
|
|
1536
|
+
readonly missing: ReadonlyArray<string>;
|
|
1537
|
+
/** Tables that carry a trigger but are declared `.nonReactive()` — their
|
|
1538
|
+
* writes still hit the NOTIFY channel and cost WAL for nothing. */
|
|
1539
|
+
readonly stale: ReadonlyArray<string>;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1486
1542
|
export declare const releaseMigrationLock: (sql: SqlClient.SqlClient) => Effect.Effect<void, SqlError_2>;
|
|
1487
1543
|
|
|
1488
1544
|
export declare const renderColumnMysql: (col: ColumnSnapshot) => string;
|
|
@@ -1507,16 +1563,6 @@ export declare const rollbackFileBasedMigration: (sql: SqlClient.SqlClient, ctx:
|
|
|
1507
1563
|
durationMs: number;
|
|
1508
1564
|
}, unknown>;
|
|
1509
1565
|
|
|
1510
|
-
/**
|
|
1511
|
-
* Discover + apply every pending file-based migration under
|
|
1512
|
-
* `projectRoot/migrations/`. Runs under the same advisory lock as
|
|
1513
|
-
* the planner-based applier, so concurrent invocations serialise.
|
|
1514
|
-
*
|
|
1515
|
-
* - Returns `applied` (newly-run ids + durations) + `skipped`
|
|
1516
|
-
* (ids that were already applied) for the caller's log line.
|
|
1517
|
-
* - Failures abort the run + propagate as the Effect's error
|
|
1518
|
-
* channel; the caller (dev.ts boot) is expected to refuse-to-boot.
|
|
1519
|
-
*/
|
|
1520
1566
|
export declare const runFileBasedMigrations: (sql: SqlClient.SqlClient, ctx: RunFileBasedMigrationsCtx) => Effect.Effect<FileMigrationRunResult, unknown>;
|
|
1521
1567
|
|
|
1522
1568
|
export declare interface RunFileBasedMigrationsCtx {
|
|
@@ -1655,7 +1701,7 @@ export declare interface SquashResult {
|
|
|
1655
1701
|
readonly snapshotId: string;
|
|
1656
1702
|
}
|
|
1657
1703
|
|
|
1658
|
-
declare interface Table<Name extends string, Fields extends Record<string, ColumnDefinition<unknown>>, Reactive extends boolean =
|
|
1704
|
+
declare interface Table<Name extends string, Fields extends Record<string, ColumnDefinition<unknown>>, Reactive extends boolean = true, IxNames extends string = never> extends TableLike {
|
|
1659
1705
|
readonly tableName: Name;
|
|
1660
1706
|
readonly fields: Fields;
|
|
1661
1707
|
readonly isReactive: Reactive;
|
|
@@ -1967,11 +2013,39 @@ declare interface Table<Name extends string, Fields extends Record<string, Colum
|
|
|
1967
2013
|
*/
|
|
1968
2014
|
primaryKey: <const F extends readonly [keyof Fields & string, keyof Fields & string, ...Array<keyof Fields & string>]>(fields: F) => Table<Name, Fields, Reactive, IxNames>;
|
|
1969
2015
|
/**
|
|
1970
|
-
*
|
|
1971
|
-
*
|
|
1972
|
-
*
|
|
2016
|
+
* Turn reactivity OFF for this table.
|
|
2017
|
+
*
|
|
2018
|
+
* Not "off across instances" — off. The table emits no change events at all:
|
|
2019
|
+
* no local subscriber fires, no cross-instance transport carries it. That is
|
|
2020
|
+
* what the name says, and a version of this that only silenced the
|
|
2021
|
+
* cross-instance half would leave every in-process subscription live on a
|
|
2022
|
+
* table declared non-reactive.
|
|
2023
|
+
*
|
|
2024
|
+
* Reactivity is the default because that is what this framework is for. The
|
|
2025
|
+
* inverse (`.reactive()`) was the API for a long time and failed in both
|
|
2026
|
+
* directions silently: written on mariadb it did nothing at all, omitted on
|
|
2027
|
+
* postgres+cdc it meant a write on one instance never reached another
|
|
2028
|
+
* instance's subscribers.
|
|
2029
|
+
*
|
|
2030
|
+
* Implemented in EVERY dialect, at the store's emit:
|
|
2031
|
+
*
|
|
2032
|
+
* memory the store's single emit point drops the event
|
|
2033
|
+
* sqlite / same, and turso reuses that store
|
|
2034
|
+
* turso
|
|
2035
|
+
* postgres also: no `REPLICA IDENTITY FULL`, no `pg_notify` trigger
|
|
2036
|
+
* mysql / also: excluded from the binlog reader's table filter
|
|
2037
|
+
* mariadb
|
|
2038
|
+
* mssql also: excluded from the Change Tracking table set
|
|
2039
|
+
*
|
|
2040
|
+
* The WRITE is unaffected — this is about notification, never persistence.
|
|
2041
|
+
*
|
|
2042
|
+
* Worth using for a genuinely hot table nobody subscribes to: an append-only
|
|
2043
|
+
* event log, a metrics sink. On postgres it also drops `REPLICA IDENTITY
|
|
2044
|
+
* FULL`, which widens every UPDATE/DELETE in the WAL. Do NOT use it on a
|
|
2045
|
+
* table a query reads — that subscription simply never fires. `voltro dev`
|
|
2046
|
+
* says so at boot.
|
|
1973
2047
|
*/
|
|
1974
|
-
|
|
2048
|
+
nonReactive: () => Table<Name, Fields, false, IxNames>;
|
|
1975
2049
|
}
|
|
1976
2050
|
|
|
1977
2051
|
/**
|
|
@@ -2105,23 +2179,7 @@ declare interface TableUnique {
|
|
|
2105
2179
|
};
|
|
2106
2180
|
}
|
|
2107
2181
|
|
|
2108
|
-
|
|
2109
|
-
* Clear the `blocked` flag on every LOSSY operation in a plan.
|
|
2110
|
-
*
|
|
2111
|
-
* Called only after the destructive opt-in has been established, and it is not
|
|
2112
|
-
* cosmetic. `applyPlan` carries its OWN unconditional refusal on any blocked
|
|
2113
|
-
* operation, with no override parameter. So a plan that the boot gate has
|
|
2114
|
-
* decided may proceed, but which still arrives marked blocked, is refused a
|
|
2115
|
-
* second time by the applier — which meant `VOLTRO_DESTRUCTIVE_OK=1` could
|
|
2116
|
-
* never actually drop a table. The planner's fix hint names that exact
|
|
2117
|
-
* variable, so the documented escape hatch pointed at a wall.
|
|
2118
|
-
*
|
|
2119
|
-
* Only `lossy` ops are unblocked, and callers must have already established
|
|
2120
|
-
* that no other class is blocked. A rename-without-marker or a NOT NULL
|
|
2121
|
-
* without backfill stays blocked even in destructive-OK mode: those lose data
|
|
2122
|
-
* regardless of intent, so intent is not the question being asked.
|
|
2123
|
-
*/
|
|
2124
|
-
export declare const unblockLossy: (plan: MigrationPlan) => MigrationPlan;
|
|
2182
|
+
export declare const unblockLossy: (plan: MigrationPlan, scope?: ReturnType<typeof destructiveScope>) => MigrationPlan;
|
|
2125
2183
|
|
|
2126
2184
|
/**
|
|
2127
2185
|
* Unique-constraint metadata. Set by `.unique()` (or `.unique({ dedup })`).
|