@voltro/database 0.80.0 → 0.82.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 +1610 -6
- package/dist/index.d.ts +83 -26
- package/dist/index.js +592 -583
- package/dist/{replaceInProgress-BmSjNTp0.js → replaceInProgress-BbN7p1Q-.js} +509 -461
- package/dist/sql.d.ts +421 -26
- package/dist/sql.js +1858 -1551
- package/package.json +2 -2
package/dist/sql.d.ts
CHANGED
|
@@ -3,11 +3,15 @@ import { Effect } from 'effect';
|
|
|
3
3
|
import { Layer } from 'effect';
|
|
4
4
|
import { Schema } from 'effect';
|
|
5
5
|
import { SqlClient } from '@effect/sql';
|
|
6
|
-
import { SqlError } from '@effect/sql';
|
|
7
|
-
import { SqlError as SqlError_2 } from '@effect/sql
|
|
6
|
+
import { SqlError } from '@effect/sql/SqlError';
|
|
7
|
+
import { SqlError as SqlError_2 } from '@effect/sql';
|
|
8
8
|
import { Statement } from '@effect/sql';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
/** Every hash this source may have been recorded under: its own, and the body
|
|
11
|
+
* before each framework edit in {@link FRAMEWORK_MIGRATION_EDITS}. */
|
|
12
|
+
export declare const acceptedBodyHashes: (source: string) => ReadonlySet<string>;
|
|
13
|
+
|
|
14
|
+
export declare const acquireMigrationLock: (sql: SqlClient.SqlClient, scope?: MigrationLockScope) => Effect.Effect<HeldMigrationLock, SqlError>;
|
|
11
15
|
|
|
12
16
|
export declare const addColumnDdl: (op: Extract<MigrationOperation, {
|
|
13
17
|
kind: "add-column";
|
|
@@ -161,7 +165,36 @@ declare type AnyView = View<string, Record<string, ColumnDefinition<unknown>>>;
|
|
|
161
165
|
*/
|
|
162
166
|
export declare const appliedAtValue: (sql: SqlClient.SqlClient, iso: string) => Effect.Effect<string>;
|
|
163
167
|
|
|
164
|
-
|
|
168
|
+
/**
|
|
169
|
+
* Does the plan ledger exist on THIS database? Asked of the CATALOG, which
|
|
170
|
+
* ANSWERS on a virgin database rather than failing.
|
|
171
|
+
*
|
|
172
|
+
* The read below used to be a plain `SELECT` with `Effect.catchAll(() => [])`
|
|
173
|
+
* beside it, and that is correct only OUTSIDE a transaction — the rule
|
|
174
|
+
* `objectReadable` states in `applier.ts`, in those words, about its own query.
|
|
175
|
+
* `voltro db apply` opens ONE transaction on the plan-transactional dialects,
|
|
176
|
+
* so against a database without the ledger the failed SELECT aborted that
|
|
177
|
+
* transaction and every later statement of the deploy died — starting with the
|
|
178
|
+
* first migration's own `SAVEPOINT`:
|
|
179
|
+
*
|
|
180
|
+
* ERROR: relation "_voltro_migration_plans" does not exist
|
|
181
|
+
* ERROR: current transaction is aborted, commands ignored until end of
|
|
182
|
+
* transaction block
|
|
183
|
+
*
|
|
184
|
+
* The catch turned an error postgres does not forget into one only Effect had
|
|
185
|
+
* forgotten. So a project with even ONE file under `migrations/` could not
|
|
186
|
+
* `db apply` against an empty database at all — every new environment, every
|
|
187
|
+
* reset local database, every hermetic e2e stack — and the schema was never
|
|
188
|
+
* created.
|
|
189
|
+
*
|
|
190
|
+
* The fix is NOT to create the ledger first. Both apply paths used to open with
|
|
191
|
+
* `applySchema(voltroFrameworkTables)`, and it was removed for a reason the
|
|
192
|
+
* header of `runApplyFromPlanFile` records: on a virgin database it created
|
|
193
|
+
* tables and thereby moved the very fingerprint the saved plan was measured
|
|
194
|
+
* against. The ledger is planned like any other declared table; what had to
|
|
195
|
+
* change is that ASKING for it stops being a statement that can fail.
|
|
196
|
+
*/
|
|
197
|
+
export declare const appliedFileMigrationIds: (sql: SqlClient.SqlClient) => Effect.Effect<ReadonlyArray<string>, SqlError>;
|
|
165
198
|
|
|
166
199
|
/**
|
|
167
200
|
* The applied file migrations WITH the body hash recorded at the time.
|
|
@@ -175,7 +208,7 @@ export declare const appliedFileMigrationIds: (sql: SqlClient.SqlClient) => Effe
|
|
|
175
208
|
export declare const appliedFileMigrations: (sql: SqlClient.SqlClient) => Effect.Effect<ReadonlyArray<{
|
|
176
209
|
readonly id: string;
|
|
177
210
|
readonly hash: string;
|
|
178
|
-
}>,
|
|
211
|
+
}>, SqlError>;
|
|
179
212
|
|
|
180
213
|
/**
|
|
181
214
|
* The operations the resume ledger says RAN — `started`, `added` or `applied` —
|
|
@@ -245,9 +278,14 @@ export declare const applyNamespacedSchema: (tables: ReadonlyArray<AnyTable>, na
|
|
|
245
278
|
* interruption, which is exactly the set a JS `finally` inside `Effect.gen`
|
|
246
279
|
* does not cover.
|
|
247
280
|
*/
|
|
248
|
-
export declare const applyPlan: (sql: SqlClient.SqlClient, plan: MigrationPlan, ctx: ApplyPlanCtx) => Effect.Effect<AppliedMigration,
|
|
281
|
+
export declare const applyPlan: (sql: SqlClient.SqlClient, plan: MigrationPlan, ctx: ApplyPlanCtx) => Effect.Effect<AppliedMigration, SqlError, SqlClient.SqlClient>;
|
|
249
282
|
|
|
250
283
|
export declare interface ApplyPlanCtx {
|
|
284
|
+
/** Prepare schema-owned resources under the migration lock after replan,
|
|
285
|
+
* refusal checks and interrupted-run reconciliation, before planned work.
|
|
286
|
+
* Not called when no operations remain. Ledger/extension bootstrap may
|
|
287
|
+
* already have run; this is not a dry-run boundary or its own transaction. */
|
|
288
|
+
readonly beforeExecute?: Effect.Effect<void, SqlError, SqlClient.SqlClient>;
|
|
251
289
|
/** Tables declared by user code — needed to look up
|
|
252
290
|
* `.backfill()` specs for add-column ops, since the snapshot
|
|
253
291
|
* doesn't carry them. */
|
|
@@ -319,7 +357,13 @@ export declare interface ApplyPlanCtx {
|
|
|
319
357
|
* migration was a framework bug. `voltro db apply` did exactly that for two
|
|
320
358
|
* releases while `voltro dev`'s boot diff, which uses this parameter, did not.
|
|
321
359
|
*/
|
|
322
|
-
readonly replan: (sql: SqlClient.SqlClient) => Effect.Effect<MigrationPlan,
|
|
360
|
+
readonly replan: (sql: SqlClient.SqlClient) => Effect.Effect<MigrationPlan, SqlError, SqlClient.SqlClient>;
|
|
361
|
+
/**
|
|
362
|
+
* The declared store charset — the one `replan` plans with. Here only for
|
|
363
|
+
* the resume ledger this creates before the first statement: nothing declares
|
|
364
|
+
* it, so without this it is created in the database default.
|
|
365
|
+
*/
|
|
366
|
+
readonly charset?: MysqlCharset | undefined;
|
|
323
367
|
}
|
|
324
368
|
|
|
325
369
|
export declare const applySchema: (tables: ReadonlyArray<AnyTable>, dialect?: DialectId,
|
|
@@ -330,6 +374,14 @@ export declare const applySchema: (tables: ReadonlyArray<AnyTable>, dialect?: Di
|
|
|
330
374
|
* raised nothing. */
|
|
331
375
|
cdcChannel?: string, options?: SchemaApplyOptions) => Effect.Effect<void, never, SqlClient.SqlClient>;
|
|
332
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Run the work. No lock of its own — the caller holds the one that fits:
|
|
379
|
+
* `convergeUndeclaredCharset` the migration lock, the cluster gate its own.
|
|
380
|
+
* `.unprepared`, the text protocol, like every DDL statement a prepared
|
|
381
|
+
* protocol may refuse on one of the two engines.
|
|
382
|
+
*/
|
|
383
|
+
export declare const applyUndeclaredCharsetWork: (sql: SqlClient.SqlClient, work: UndeclaredCharsetWork) => Effect.Effect<void, SqlError>;
|
|
384
|
+
|
|
333
385
|
/**
|
|
334
386
|
* The OPT-IN refuse gate over the advisory. By default (`VOLTRO_ROLLING_DEPLOY`
|
|
335
387
|
* unset) this never fires — the classifier stays a `db plan` advisory, because
|
|
@@ -530,6 +582,9 @@ declare type ChangeEvent = {
|
|
|
530
582
|
* re-read failed, or the row was already gone). Re-read or resync.
|
|
531
583
|
*/
|
|
532
584
|
readonly oversized?: 'rehydrated' | 'tombstone' | 'unrecovered';
|
|
585
|
+
/** A net-change feed may coalesce intermediate writes and supply current
|
|
586
|
+
* images or delete keys only. It cannot support exact historical replay. */
|
|
587
|
+
readonly netChange?: true;
|
|
533
588
|
/**
|
|
534
589
|
* How the event reached this process. Absent/'inline' = emitted by this
|
|
535
590
|
* process's own write path; 'injected' = delivered over a cross-instance
|
|
@@ -609,6 +664,25 @@ export declare const charsetColumnsOf: (table: TableSnapshot) => ReadonlyArray<{
|
|
|
609
664
|
readonly charset: string;
|
|
610
665
|
}>;
|
|
611
666
|
|
|
667
|
+
/**
|
|
668
|
+
* Check — and, when `mayWrite`, establish — which app owns this schema.
|
|
669
|
+
*
|
|
670
|
+
* With `mayWrite` the owner table is bootstrapped and an unclaimed schema is
|
|
671
|
+
* claimed for `claim.appName`. Two apps racing for an unclaimed database both
|
|
672
|
+
* try the INSERT; the loser's fails on the primary key and it re-reads, so
|
|
673
|
+
* exactly one of them owns it and the other is told so.
|
|
674
|
+
*
|
|
675
|
+
* Without `mayWrite` nothing is created or written: a missing table or row is
|
|
676
|
+
* `unclaimed`, and only an existing FOREIGN claim is reported.
|
|
677
|
+
*/
|
|
678
|
+
export declare const checkSchemaOwner: (sql: SqlClient.SqlClient, claim: SchemaOwnerClaim,
|
|
679
|
+
/** `charset`: the declared store charset (MySQL family) the owner table is
|
|
680
|
+
* created in — the same one every other framework table gets. */
|
|
681
|
+
options: {
|
|
682
|
+
readonly mayWrite: boolean;
|
|
683
|
+
readonly charset: MysqlCharset | undefined;
|
|
684
|
+
}) => Effect.Effect<SchemaOwnership, SqlError>;
|
|
685
|
+
|
|
612
686
|
/** Partition into ≤`n`-sized chunks (disjoint, complete). Exported for the
|
|
613
687
|
* batching regression test — the introspection's correctness reduces to this
|
|
614
688
|
* producing a complete, non-overlapping partition of the table list. */
|
|
@@ -1504,6 +1578,28 @@ export declare type ColumnInput = {
|
|
|
1504
1578
|
__definition(): ColumnDefinition<unknown>;
|
|
1505
1579
|
} | ColumnDefinition<unknown>;
|
|
1506
1580
|
|
|
1581
|
+
/**
|
|
1582
|
+
* A table's COLUMN-level CHECKs on MariaDB, by column — what a `MODIFY COLUMN`
|
|
1583
|
+
* has to restate so that it keeps them.
|
|
1584
|
+
*
|
|
1585
|
+
* MariaDB records a CHECK written inline on a column (the bring-up path writes
|
|
1586
|
+
* every enum CHECK that way) as part of the column definition
|
|
1587
|
+
* (`check_constraints.level = 'Column'`, named after the column), and `MODIFY
|
|
1588
|
+
* COLUMN` REDEFINES the column: a definition without the CHECK removes it.
|
|
1589
|
+
* Measured on 11.8 — plain MODIFY: gone; MODIFY with the CHECK inline: kept,
|
|
1590
|
+
* still column-level. A table-level CHECK (what `add-check` writes) survives
|
|
1591
|
+
* either way, and MySQL has no column-level constraints in its catalog, so this
|
|
1592
|
+
* is empty there.
|
|
1593
|
+
*
|
|
1594
|
+
* Without it every operation that renders MODIFY — a character-set conversion,
|
|
1595
|
+
* a nullability or type change — removed the CHECK as a side effect, the re-plan
|
|
1596
|
+
* proposed `add-check`, and the apply refused as "did not converge". A declared
|
|
1597
|
+
* charset over a real schema produced 67 of them at once. The planner's own
|
|
1598
|
+
* `drop-check` still removes a CHECK the declaration no longer has: it runs
|
|
1599
|
+
* after the column changes and reads the catalog again.
|
|
1600
|
+
*/
|
|
1601
|
+
export declare const columnLevelChecksMysql: (sql: SqlClient.SqlClient, table: string) => Effect.Effect<ReadonlyMap<string, string>, SqlError>;
|
|
1602
|
+
|
|
1507
1603
|
/**
|
|
1508
1604
|
* A column as seen by the planner: either declared in code (extracted
|
|
1509
1605
|
* from `ColumnDefinition`) or live in the DB (extracted via introspection).
|
|
@@ -1764,6 +1860,17 @@ declare type ColumnType = 'id' | 'text' | 'integer' | 'real' | 'decimal' | 'bigi
|
|
|
1764
1860
|
|
|
1765
1861
|
declare type ColumnType_2 = 'id' | 'text' | 'integer' | 'real' | 'decimal' | 'bigint' | 'boolean' | 'timestamp' | 'date' | 'json' | 'bytes' | 'reference' | 'vector' | 'enum' | 'array' | 'interval' | 'raw';
|
|
1766
1862
|
|
|
1863
|
+
/**
|
|
1864
|
+
* Carry a `utf8mb4` declaration to the undeclared framework tables that
|
|
1865
|
+
* already exist, under the migration lock. Idempotent: a second run reads a
|
|
1866
|
+
* converged catalog and does nothing.
|
|
1867
|
+
*/
|
|
1868
|
+
export declare const convergeUndeclaredCharset: (sql: SqlClient.SqlClient, options: {
|
|
1869
|
+
readonly declaredNames: ReadonlySet<string>;
|
|
1870
|
+
readonly charset: MysqlCharset | undefined;
|
|
1871
|
+
readonly lockSchema?: string | undefined;
|
|
1872
|
+
}) => Effect.Effect<UndeclaredCharsetWork, SqlError>;
|
|
1873
|
+
|
|
1767
1874
|
/** A live foreign key a charset conversion has to carry across the rewrite. */
|
|
1768
1875
|
export declare interface ConvertCharsetForeignKey {
|
|
1769
1876
|
/** Catalog name of the constraint. */
|
|
@@ -2369,8 +2476,8 @@ export declare const defaultJsonClause: (value: object, dialect: DialectId) => s
|
|
|
2369
2476
|
export declare interface DeferredData {
|
|
2370
2477
|
readonly table: string;
|
|
2371
2478
|
readonly op: MigrationOperation;
|
|
2372
|
-
readonly data: Effect.Effect<void,
|
|
2373
|
-
readonly after: Effect.Effect<void,
|
|
2479
|
+
readonly data: Effect.Effect<void, SqlError>;
|
|
2480
|
+
readonly after: Effect.Effect<void, SqlError>;
|
|
2374
2481
|
}
|
|
2375
2482
|
|
|
2376
2483
|
export declare const DEPLOY_LEDGER_TABLE = "_voltro_deploys";
|
|
@@ -2393,6 +2500,9 @@ export declare const describeProbe: (probe: SchemaProbe) => string;
|
|
|
2393
2500
|
/** One line per finding, for the CLI and the doctor. */
|
|
2394
2501
|
export declare const describeStoreCharsetFinding: (f: StoreCharsetFinding) => string;
|
|
2395
2502
|
|
|
2503
|
+
/** The lines `db plan` prints and `db apply` logs — one per table. */
|
|
2504
|
+
export declare const describeUndeclaredCharsetWork: (w: UndeclaredCharsetWork) => ReadonlyArray<string>;
|
|
2505
|
+
|
|
2396
2506
|
/**
|
|
2397
2507
|
* Parse `VOLTRO_DESTRUCTIVE_OK`.
|
|
2398
2508
|
*
|
|
@@ -2426,11 +2536,33 @@ export declare const detectReactiveTriggerDrift: (sql: SqlClient.SqlClient, tabl
|
|
|
2426
2536
|
/** The app's `cdcChannel`. Part of the trigger NAME on any non-default
|
|
2427
2537
|
* channel, so omitting it here reported every table as missing on a database
|
|
2428
2538
|
* where every trigger was present. */
|
|
2429
|
-
channel?: string) => Effect.Effect<ReactiveTriggerDrift,
|
|
2539
|
+
channel?: string) => Effect.Effect<ReactiveTriggerDrift, SqlError>;
|
|
2430
2540
|
|
|
2431
2541
|
/** Dialect IDs the framework supports. */
|
|
2432
2542
|
declare type DialectId = 'postgres' | 'mysql' | 'mariadb' | 'mssql' | 'sqlite' | 'turso';
|
|
2433
2543
|
|
|
2544
|
+
/**
|
|
2545
|
+
* Resolve the live dialect from the `SqlClient`.
|
|
2546
|
+
*
|
|
2547
|
+
* `sql.onDialectOrElse` collapses the six voltro dialects onto four driver
|
|
2548
|
+
* tokens: mysql+mariadb share `mysql` (one `@effect/sql-mysql2` client) and
|
|
2549
|
+
* sqlite+turso share `sqlite`. That collapse is fine for every consumer here —
|
|
2550
|
+
* the paired dialects behave identically for everything this module decides.
|
|
2551
|
+
*
|
|
2552
|
+
* Single copy on purpose: a second, subtly different dialect switch is how a
|
|
2553
|
+
* per-dialect divergence gets shipped in this codebase.
|
|
2554
|
+
*/
|
|
2555
|
+
export declare const dialectOf: (sql: {
|
|
2556
|
+
readonly onDialectOrElse: <A, B, C, D, E, F>(options: {
|
|
2557
|
+
readonly orElse: () => A;
|
|
2558
|
+
readonly sqlite?: () => B;
|
|
2559
|
+
readonly pg?: () => C;
|
|
2560
|
+
readonly mysql?: () => D;
|
|
2561
|
+
readonly mssql?: () => E;
|
|
2562
|
+
readonly clickhouse?: () => F;
|
|
2563
|
+
}) => A | B | C | D | E | F;
|
|
2564
|
+
}) => DialectId;
|
|
2565
|
+
|
|
2434
2566
|
/**
|
|
2435
2567
|
* Output of `voltro db drift`: compares the live DB's introspected
|
|
2436
2568
|
* schema against the last applied fingerprint in `_voltro_migrations`.
|
|
@@ -2746,7 +2878,19 @@ declare type EmptyMerge = unknown;
|
|
|
2746
2878
|
export declare const engineFromVersion: (version: string) => MysqlEngine;
|
|
2747
2879
|
|
|
2748
2880
|
/** The deploy ledger (`_voltro_deploys`) — same bootstrap, same reason: it has to exist before the first plan. */
|
|
2749
|
-
export declare const ensureDeployLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void,
|
|
2881
|
+
export declare const ensureDeployLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset: MysqlCharset | undefined) => Effect.Effect<void, SqlError>;
|
|
2882
|
+
|
|
2883
|
+
/**
|
|
2884
|
+
* Make every declared full-text index exist, on a database the PLANNER
|
|
2885
|
+
* migrates. The planner diffs what it introspects — columns, indexes — and
|
|
2886
|
+
* deliberately skips the FTS artifacts (a generated tsvector column and its GIN
|
|
2887
|
+
* index, a FULLTEXT index, an FTS5 shadow table): they are framework plumbing
|
|
2888
|
+
* for a declaration, carry no data of their own, and their DDL is idempotent.
|
|
2889
|
+
* So they CONVERGE after the plan instead of being planned — without this, a
|
|
2890
|
+
* table the planner created never got its index, and `.matching()` failed on
|
|
2891
|
+
* the missing column. Returns how many statements ran.
|
|
2892
|
+
*/
|
|
2893
|
+
export declare const ensureFullTextIndexes: (tables: ReadonlyArray<AnyTable>, dialect: DialectId) => Effect.Effect<number, SqlError_2.SqlError, SqlClient.SqlClient>;
|
|
2750
2894
|
|
|
2751
2895
|
/**
|
|
2752
2896
|
* Create `_voltro_migration_ops` if it isn't there yet.
|
|
@@ -2761,7 +2905,7 @@ export declare const ensureDeployLedgerTable: (sql: SqlClient.SqlClient, dialect
|
|
|
2761
2905
|
* framework-table set because it has to exist before the FIRST plan — and the
|
|
2762
2906
|
* first plan is the one that creates the framework tables.
|
|
2763
2907
|
*/
|
|
2764
|
-
export declare const ensureLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void,
|
|
2908
|
+
export declare const ensureLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset: MysqlCharset | undefined) => Effect.Effect<void, SqlError>;
|
|
2765
2909
|
|
|
2766
2910
|
/**
|
|
2767
2911
|
* The PLAN ledger (`_voltro_migration_plans`) — same bootstrap, one caller.
|
|
@@ -2776,7 +2920,11 @@ export declare const ensureLedgerTable: (sql: SqlClient.SqlClient, dialect: Dial
|
|
|
2776
2920
|
* Index-free like the others, so the planner still owns the table's shape and a
|
|
2777
2921
|
* re-plan converges by adding the indexes it declares.
|
|
2778
2922
|
*/
|
|
2779
|
-
export declare const ensurePlanLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void,
|
|
2923
|
+
export declare const ensurePlanLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset: MysqlCharset | undefined) => Effect.Effect<void, SqlError>;
|
|
2924
|
+
|
|
2925
|
+
/** The plugin-migration ledger (`_voltro_plugin_migrations`) — same bootstrap:
|
|
2926
|
+
* a plugin's steps run after the schema apply, outside any plan. */
|
|
2927
|
+
export declare const ensurePluginMigrationsLedgerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset: MysqlCharset | undefined) => Effect.Effect<void, SqlError>;
|
|
2780
2928
|
|
|
2781
2929
|
/**
|
|
2782
2930
|
* The in-progress marker (`_voltro_replace_in_progress`) — same bootstrap,
|
|
@@ -2792,7 +2940,11 @@ export declare const ensurePlanLedgerTable: (sql: SqlClient.SqlClient, dialect:
|
|
|
2792
2940
|
* exits 1 over a database that is otherwise fine. The planner emits no trigger
|
|
2793
2941
|
* for this table either, so the shape converges on the next apply.
|
|
2794
2942
|
*/
|
|
2795
|
-
export declare const ensureReplaceMarkerTable: (sql: SqlClient.SqlClient, dialect: DialectId) => Effect.Effect<void,
|
|
2943
|
+
export declare const ensureReplaceMarkerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset: MysqlCharset | undefined) => Effect.Effect<void, SqlError>;
|
|
2944
|
+
|
|
2945
|
+
/** The schema-owner row's table (`_voltro_schema_owner`) — bootstrapped so the
|
|
2946
|
+
* ownership check can run BEFORE the first plan, which is the plan it guards. */
|
|
2947
|
+
export declare const ensureSchemaOwnerTable: (sql: SqlClient.SqlClient, dialect: DialectId, charset: MysqlCharset | undefined) => Effect.Effect<void, SqlError>;
|
|
2796
2948
|
|
|
2797
2949
|
/** Exported for the same reason as {@link enumTypeBlocks}, and it MUST run
|
|
2798
2950
|
* before it — see that function's note on ordering. */
|
|
@@ -2849,6 +3001,21 @@ export declare const failedExpectations: (expectations: ReadonlyArray<{
|
|
|
2849
3001
|
readonly check: () => Promise<boolean> | Effect.Effect<boolean, unknown, never>;
|
|
2850
3002
|
}>) => Effect.Effect<ReadonlyArray<string>, unknown>;
|
|
2851
3003
|
|
|
3004
|
+
/**
|
|
3005
|
+
* Look up the most recently applied plan's fingerprint. Returns
|
|
3006
|
+
* `undefined` if the table doesn't exist yet or no rows are present —
|
|
3007
|
+
* both meaning "the framework hasn't applied a planner-style migration
|
|
3008
|
+
* in this DB yet" (typical for fresh installs).
|
|
3009
|
+
*
|
|
3010
|
+
* A failed read is NOT one of those two unless the table is really absent.
|
|
3011
|
+
* This read used to end in `catchAll(() => undefined)`, and on SQL Server its
|
|
3012
|
+
* `LIMIT 1` was a syntax error: every production boot there reported
|
|
3013
|
+
* `live=<no _voltro_migration_plans row>` over a table holding the row, and
|
|
3014
|
+
* refused. So a failure is followed by a probe that is valid on every dialect;
|
|
3015
|
+
* if the table answers it, the original failure is the answer, loudly.
|
|
3016
|
+
*/
|
|
3017
|
+
export declare const fetchLastFingerprint: (sql: SqlClient.SqlClient) => Effect.Effect<string | undefined, never>;
|
|
3018
|
+
|
|
2852
3019
|
/**
|
|
2853
3020
|
* Filename pattern the discovery walker matches: timestamp-prefixed
|
|
2854
3021
|
* `.ts` files in any depth under the project's `migrations/` dir.
|
|
@@ -3144,6 +3311,9 @@ export declare const fingerprintSchema: (snapshot: SchemaSnapshot) => string;
|
|
|
3144
3311
|
|
|
3145
3312
|
export declare const fnv1a64: (input: string) => bigint;
|
|
3146
3313
|
|
|
3314
|
+
/** The refusal a foreign claim produces — one sentence for both boot paths. */
|
|
3315
|
+
export declare const foreignOwnerMessage: (self: string, owner: string, claimedAt: string | undefined) => string;
|
|
3316
|
+
|
|
3147
3317
|
/** Human/PR-comment rendering. Markdown-free on purpose — the CI job that posts
|
|
3148
3318
|
* it to a PR wraps it, and a terminal reader gets the same text. */
|
|
3149
3319
|
export declare const formatBranchRehearsal: (report: BranchRehearsalReport) => string;
|
|
@@ -3151,6 +3321,49 @@ export declare const formatBranchRehearsal: (report: BranchRehearsalReport) => s
|
|
|
3151
3321
|
/** Human report, or `undefined` when the database and the schema agree. */
|
|
3152
3322
|
export declare const formatReactiveTriggerDrift: (drift: ReactiveTriggerDrift) => string | undefined;
|
|
3153
3323
|
|
|
3324
|
+
/**
|
|
3325
|
+
* Edits the FRAMEWORK made to migration files — through a codemod, after they
|
|
3326
|
+
* may already have run — each with the inverse that recovers the body as it was
|
|
3327
|
+
* when it ran.
|
|
3328
|
+
*
|
|
3329
|
+
* `0.78.0/01_file-migration-phase` inserted `phase: 'before-schema',` into every
|
|
3330
|
+
* migration without one, and 0.78.0 made the field required. Every migration
|
|
3331
|
+
* applied before that then warned on every boot that its body had changed,
|
|
3332
|
+
* forever: the file cannot be put back, and the recorded hash is the operator's
|
|
3333
|
+
* to keep, not to hand-edit. A warning that is always there is the one nobody
|
|
3334
|
+
* reads when a real edit lands, so an edit we made is not drift.
|
|
3335
|
+
*
|
|
3336
|
+
* A codemod that rewrites files under `migrations/` adds its inverse here in the
|
|
3337
|
+
* same change — `fileMigrationCodemodInverses.test.ts` fails otherwise, and runs
|
|
3338
|
+
* the real codemod over every file shape it has measured. An inverse returns
|
|
3339
|
+
* the CANDIDATE originals, because the rewrite is not always one line: ts-morph
|
|
3340
|
+
* replaces the whitespace around the property it inserts with its own (LF, two
|
|
3341
|
+
* spaces), so a one-line spec, a CRLF file and a tab-indented one each lose
|
|
3342
|
+
* bytes that only the file's own style can put back. It undoes exactly what the
|
|
3343
|
+
* codemod wrote: a hand-written `after-schema` on an applied migration is still
|
|
3344
|
+
* an edit, and still said.
|
|
3345
|
+
*/
|
|
3346
|
+
export declare const FRAMEWORK_MIGRATION_EDITS: ReadonlyArray<{
|
|
3347
|
+
readonly codemod: string;
|
|
3348
|
+
readonly inverse: (source: string) => ReadonlyArray<string>;
|
|
3349
|
+
}>;
|
|
3350
|
+
|
|
3351
|
+
/**
|
|
3352
|
+
* The DDL that makes a table's `.fullTextIndex(...)` declarations exist —
|
|
3353
|
+
* THE one builder, used by the full-schema emit and by
|
|
3354
|
+
* `ensureFullTextIndexes` (the planner path's convergence). Idempotent per
|
|
3355
|
+
* dialect:
|
|
3356
|
+
* postgres: STORED tsvector column + GIN index (`IF NOT EXISTS`)
|
|
3357
|
+
* mysql/mariadb: native FULLTEXT INDEX (a re-run's duplicate is swallowed)
|
|
3358
|
+
* sqlite: native FTS5 virtual table + sync triggers (`IF NOT EXISTS`)
|
|
3359
|
+
* mssql: nothing — a ranked LIKE fallback at query time
|
|
3360
|
+
* Turso has no FTS5 and throws.
|
|
3361
|
+
*/
|
|
3362
|
+
export declare const fullTextIndexSql: (table: AnyTable, dialect: DialectId) => ReadonlyArray<string>;
|
|
3363
|
+
|
|
3364
|
+
/** A converged schema can still have an unfinished history write. Boot must not skip it. */
|
|
3365
|
+
export declare const hasInterruptedMigration: (sql: SqlClient.SqlClient) => Effect.Effect<boolean, SqlError>;
|
|
3366
|
+
|
|
3154
3367
|
/**
|
|
3155
3368
|
* A lock that is being HELD, and the only way to let it go.
|
|
3156
3369
|
*
|
|
@@ -3164,7 +3377,7 @@ export declare const formatReactiveTriggerDrift: (drift: ReactiveTriggerDrift) =
|
|
|
3164
3377
|
export declare interface HeldMigrationLock {
|
|
3165
3378
|
/** Release the lock and return its connection to the pool. Idempotent only
|
|
3166
3379
|
* in the sense that the dialect statements are; call it once. */
|
|
3167
|
-
readonly release: Effect.Effect<void,
|
|
3380
|
+
readonly release: Effect.Effect<void, SqlError>;
|
|
3168
3381
|
}
|
|
3169
3382
|
|
|
3170
3383
|
/**
|
|
@@ -3388,7 +3601,7 @@ declare interface InsertIgnoreResult {
|
|
|
3388
3601
|
readonly outcome: 'inserted' | 'ignored';
|
|
3389
3602
|
}
|
|
3390
3603
|
|
|
3391
|
-
export declare const introspectSchema: (sql: SqlClient.SqlClient) => Effect.Effect<SchemaSnapshot,
|
|
3604
|
+
export declare const introspectSchema: (sql: SqlClient.SqlClient) => Effect.Effect<SchemaSnapshot, SqlError>;
|
|
3392
3605
|
|
|
3393
3606
|
/**
|
|
3394
3607
|
* A `down` that says there is no inverse — with the reason, which is what a
|
|
@@ -3433,6 +3646,16 @@ export declare const isRawSqlFragment: (value: unknown) => value is RawSqlFragme
|
|
|
3433
3646
|
*/
|
|
3434
3647
|
export declare const isReRunSafeDdl: (statement: string, dialect: DialectId) => boolean;
|
|
3435
3648
|
|
|
3649
|
+
/**
|
|
3650
|
+
* The tables this step owns: created by the framework or its engines, not
|
|
3651
|
+
* declared by the app. A soft-drop snapshot and a `--mode replace` staging copy
|
|
3652
|
+
* are data the operator is handling, and `_cloud_*` / `__turso_internal_*`
|
|
3653
|
+
* belong to another product and another engine.
|
|
3654
|
+
*/
|
|
3655
|
+
export declare const isUndeclaredCharsetTable: (name: string, declaredNames: ReadonlySet<string>) => boolean;
|
|
3656
|
+
|
|
3657
|
+
export declare const isUndeclaredCharsetWorkEmpty: (w: UndeclaredCharsetWork) => boolean;
|
|
3658
|
+
|
|
3436
3659
|
/**
|
|
3437
3660
|
* A json-path index entry, produced by {@link jsonIndex}. Unlike a plain
|
|
3438
3661
|
* `{ expr }` (verbatim, dialect-specific) this carries the column + path
|
|
@@ -3453,6 +3676,22 @@ declare type LeafOperator = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' |
|
|
|
3453
3676
|
|
|
3454
3677
|
declare type LeafOperator_2 = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'notIn' | 'contains' | 'startsWith' | 'arrayContains' | 'arrayOverlaps' | 'arrayHas' | 'isNull' | 'isNotNull' | 'spatial';
|
|
3455
3678
|
|
|
3679
|
+
/**
|
|
3680
|
+
* `LIMIT n`, spelled for the dialect — after an `ORDER BY`, which every caller
|
|
3681
|
+
* has. SQL Server has no LIMIT; `OFFSET 0 ROWS FETCH NEXT n ROWS ONLY` is its
|
|
3682
|
+
* spelling, valid in a derived table too.
|
|
3683
|
+
*
|
|
3684
|
+
* One helper because the same mistake was written six times: a batched
|
|
3685
|
+
* backfill failed on its first page, and `voltro serve`'s schema check read the
|
|
3686
|
+
* newest applied plan with `LIMIT 1`, got a syntax error back, and reported it
|
|
3687
|
+
* as "no plan row" — so a production serve on SQL Server refused every boot,
|
|
3688
|
+
* including the one right after `voltro db apply`.
|
|
3689
|
+
*
|
|
3690
|
+
* Splicing a number into SQL text needs a reason: this one is framework-chosen
|
|
3691
|
+
* and floored to a positive integer here, so it cannot carry anything but digits.
|
|
3692
|
+
*/
|
|
3693
|
+
export declare const limitClause: (sql: SqlClient.SqlClient, n: number) => Statement.Fragment;
|
|
3694
|
+
|
|
3456
3695
|
/**
|
|
3457
3696
|
* Build the context for one migration body. Returns the context and the
|
|
3458
3697
|
* post-conditions it collects, so the runner can evaluate them after `up`.
|
|
@@ -3957,6 +4196,20 @@ export declare class MigrationSkipped {
|
|
|
3957
4196
|
constructor(reason: string);
|
|
3958
4197
|
}
|
|
3959
4198
|
|
|
4199
|
+
export declare interface MigrationSnapshotCandidate {
|
|
4200
|
+
readonly planId: string;
|
|
4201
|
+
readonly objects: ReadonlyArray<SnapshotRestorationObject>;
|
|
4202
|
+
}
|
|
4203
|
+
|
|
4204
|
+
export declare interface MigrationSquashPreview {
|
|
4205
|
+
readonly before: string;
|
|
4206
|
+
readonly fingerprint: string;
|
|
4207
|
+
readonly planIds: ReadonlyArray<string>;
|
|
4208
|
+
readonly count: number;
|
|
4209
|
+
/** Opaque selection identity, not an authorization credential. */
|
|
4210
|
+
readonly token: string;
|
|
4211
|
+
}
|
|
4212
|
+
|
|
3960
4213
|
declare interface MixinDefinition<F extends Record<string, ColumnDefinition<unknown>>> {
|
|
3961
4214
|
/**
|
|
3962
4215
|
* Stable dedup key. Two mixins with the same `id` reaching a table via
|
|
@@ -4341,6 +4594,9 @@ export declare const plannedCreations: (plan: MigrationPlan) => ReadonlyArray<Sc
|
|
|
4341
4594
|
*/
|
|
4342
4595
|
export declare interface PlannedOperation {
|
|
4343
4596
|
readonly op: MigrationOperation;
|
|
4597
|
+
/** Exact retained object name assigned by the applier before soft-drop DDL.
|
|
4598
|
+
* Persisted in operation/resume history; absent when the history has no recorded identity or for hard drops. */
|
|
4599
|
+
readonly softDropSnapshot?: string;
|
|
4344
4600
|
readonly classification: OperationClass;
|
|
4345
4601
|
/** Why the op was classified this way (also surfaces in the CLI). */
|
|
4346
4602
|
readonly reason?: string;
|
|
@@ -4412,6 +4668,10 @@ declare interface PredicateLeaf_2 {
|
|
|
4412
4668
|
readonly path?: ReadonlyArray<string | number>;
|
|
4413
4669
|
}
|
|
4414
4670
|
|
|
4671
|
+
/** Read the complete eligible history, independent of the dashboard's recent
|
|
4672
|
+
* history limit. The token must be rechecked by squashMigrationPlans on write. */
|
|
4673
|
+
export declare const previewMigrationSquash: (options: Pick<SquashOptions, "before" | "fingerprint">) => Effect.Effect<MigrationSquashPreview, Error, SqlClient.SqlClient>;
|
|
4674
|
+
|
|
4415
4675
|
/**
|
|
4416
4676
|
* Imperative `applyNamespacedSchema` against a fresh SqlClient — the
|
|
4417
4677
|
* entry point the CLI / runtime use to provision a tenant's namespace
|
|
@@ -4435,7 +4695,7 @@ declare interface PredicateLeaf_2 {
|
|
|
4435
4695
|
* Eager provisioning is the APP's move (call this from a seed/startup over its
|
|
4436
4696
|
* own tenant table); the framework has no tenant registry to enumerate.
|
|
4437
4697
|
*/
|
|
4438
|
-
export declare const provisionTenantNamespace: (tables: ReadonlyArray<AnyTable>, namespace: string, sqlLayer: Layer.Layer<SqlClient.SqlClient, ConfigError.ConfigError |
|
|
4698
|
+
export declare const provisionTenantNamespace: (tables: ReadonlyArray<AnyTable>, namespace: string, sqlLayer: Layer.Layer<SqlClient.SqlClient, ConfigError.ConfigError | SqlError_2.SqlError, never>, dialect?: DialectId, options?: SchemaApplyOptions) => Promise<void>;
|
|
4439
4699
|
|
|
4440
4700
|
/**
|
|
4441
4701
|
* The runtime-facing materialized query — a plain bag of strings the store and
|
|
@@ -4577,6 +4837,16 @@ declare interface QueryDescriptor<R = Row> {
|
|
|
4577
4837
|
readonly alias: string;
|
|
4578
4838
|
readonly order: boolean;
|
|
4579
4839
|
};
|
|
4840
|
+
/** Each query word matches as a word BEGINNING (`tomato` finds
|
|
4841
|
+
* `tomatoes`), every word required — `.matching(…, { prefix: true })`. */
|
|
4842
|
+
readonly prefix?: boolean;
|
|
4843
|
+
/**
|
|
4844
|
+
* Set by a store whose engine keeps no full-text index (Turso's MVCC mode
|
|
4845
|
+
* has no FTS5): the match compiles to a case-insensitive LIKE over the
|
|
4846
|
+
* covered columns, ranked by how many of them hit — the same fallback as
|
|
4847
|
+
* mssql. Never set by the query builder.
|
|
4848
|
+
*/
|
|
4849
|
+
readonly fallback?: 'like';
|
|
4580
4850
|
};
|
|
4581
4851
|
/**
|
|
4582
4852
|
* Common-Table-Expression definitions (Q4) — `WITH <name> AS (...)`.
|
|
@@ -4855,6 +5125,16 @@ declare interface QueryDescriptor_2<R = Row_2> {
|
|
|
4855
5125
|
readonly alias: string;
|
|
4856
5126
|
readonly order: boolean;
|
|
4857
5127
|
};
|
|
5128
|
+
/** Each query word matches as a word BEGINNING (`tomato` finds
|
|
5129
|
+
* `tomatoes`), every word required — `.matching(…, { prefix: true })`. */
|
|
5130
|
+
readonly prefix?: boolean;
|
|
5131
|
+
/**
|
|
5132
|
+
* Set by a store whose engine keeps no full-text index (Turso's MVCC mode
|
|
5133
|
+
* has no FTS5): the match compiles to a case-insensitive LIKE over the
|
|
5134
|
+
* covered columns, ranked by how many of them hit — the same fallback as
|
|
5135
|
+
* mssql. Never set by the query builder.
|
|
5136
|
+
*/
|
|
5137
|
+
readonly fallback?: 'like';
|
|
4858
5138
|
};
|
|
4859
5139
|
/**
|
|
4860
5140
|
* Common-Table-Expression definitions (Q4) — `WITH <name> AS (...)`.
|
|
@@ -5114,6 +5394,11 @@ export declare const reactiveTriggerRepairSql: (input: {
|
|
|
5114
5394
|
readonly channel?: string;
|
|
5115
5395
|
}) => ReadonlyArray<string>;
|
|
5116
5396
|
|
|
5397
|
+
export declare const readMigrationSnapshotCandidates: (sql: SqlClient.SqlClient, live: SchemaSnapshot) => Effect.Effect<ReadonlyArray<MigrationSnapshotCandidate>, SqlError>;
|
|
5398
|
+
|
|
5399
|
+
/** Every string column of a base table in the connected database. */
|
|
5400
|
+
export declare const readUndeclaredCharsetColumns: (sql: SqlClient.SqlClient) => Effect.Effect<ReadonlyArray<UndeclaredCharsetColumn>, SqlError>;
|
|
5401
|
+
|
|
5117
5402
|
/**
|
|
5118
5403
|
* Record that a schema was applied even though there was nothing to DO.
|
|
5119
5404
|
*
|
|
@@ -5213,7 +5498,12 @@ export declare const renderColumnPg: (col: ColumnSnapshot, hasCompositePk?: bool
|
|
|
5213
5498
|
*/
|
|
5214
5499
|
export declare const resolveMigrationLockSchema: (scope?: MigrationLockScope) => string | undefined;
|
|
5215
5500
|
|
|
5216
|
-
export declare const resolveMysqlEngine: (sql: SqlClient.SqlClient) => Effect.Effect<MysqlEngine,
|
|
5501
|
+
export declare const resolveMysqlEngine: (sql: SqlClient.SqlClient) => Effect.Effect<MysqlEngine, SqlError>;
|
|
5502
|
+
|
|
5503
|
+
/** Restore only recorded objects, under the same lock as schema migrations. */
|
|
5504
|
+
export declare const restoreMigrationSnapshots: (sql: SqlClient.SqlClient, planId: string, options?: {
|
|
5505
|
+
readonly beforeExecute?: (sql: SqlClient.SqlClient) => Effect.Effect<void, SqlError, SqlClient.SqlClient>;
|
|
5506
|
+
}) => Effect.Effect<SnapshotRestorationResult, SqlError | Error, SqlClient.SqlClient>;
|
|
5217
5507
|
|
|
5218
5508
|
declare type RetryDecision = 'retry' | 'noRetry';
|
|
5219
5509
|
|
|
@@ -5267,6 +5557,9 @@ export declare const rollbackFileBasedMigration: (sql: SqlClient.SqlClient, ctx:
|
|
|
5267
5557
|
id: string;
|
|
5268
5558
|
lockSchema?: string;
|
|
5269
5559
|
store: DataStore;
|
|
5560
|
+
/** Runs under the migration lock after all refusal checks, immediately
|
|
5561
|
+
* before down. Failure leaves the body and ledger untouched. */
|
|
5562
|
+
beforeExecute?: Effect.Effect<void, unknown>;
|
|
5270
5563
|
}) => Effect.Effect<{
|
|
5271
5564
|
id: string;
|
|
5272
5565
|
durationMs: number;
|
|
@@ -5365,6 +5658,10 @@ declare interface RuleViolationDetail {
|
|
|
5365
5658
|
export declare const runFileBasedMigrations: (sql: SqlClient.SqlClient, ctx: RunFileBasedMigrationsCtx) => Effect.Effect<FileMigrationRunResult, unknown>;
|
|
5366
5659
|
|
|
5367
5660
|
export declare interface RunFileBasedMigrationsCtx {
|
|
5661
|
+
/** Runs once under the migration lock, after pending work is rechecked and
|
|
5662
|
+
* before its bodies start. Not called for an empty/already-applied pass.
|
|
5663
|
+
* Failure aborts the pass. Preparation is outside each body's transaction. */
|
|
5664
|
+
readonly beforeExecute?: Effect.Effect<void, unknown>;
|
|
5368
5665
|
readonly projectRoot: string;
|
|
5369
5666
|
readonly env: 'dev' | 'staging' | 'prod';
|
|
5370
5667
|
readonly appliedBy: string;
|
|
@@ -5391,6 +5688,12 @@ export declare interface RunFileBasedMigrationsCtx {
|
|
|
5391
5688
|
* called — which is the defect the phase exists to remove, moved up a layer.
|
|
5392
5689
|
*/
|
|
5393
5690
|
readonly phase: MigrationPhase;
|
|
5691
|
+
/**
|
|
5692
|
+
* The declared store charset (MySQL family), for the ledgers this run
|
|
5693
|
+
* creates before any plan has. Required, `undefined` spelled out — see
|
|
5694
|
+
* `ensureBootstrapTable`.
|
|
5695
|
+
*/
|
|
5696
|
+
readonly charset: MysqlCharset | undefined;
|
|
5394
5697
|
}
|
|
5395
5698
|
|
|
5396
5699
|
/**
|
|
@@ -5401,7 +5704,7 @@ export declare interface RunFileBasedMigrationsCtx {
|
|
|
5401
5704
|
* `voltro_isr_cache` so framework releases that grow new columns
|
|
5402
5705
|
* don't crash old DBs at boot.
|
|
5403
5706
|
*/
|
|
5404
|
-
export declare const runFrameworkBootstrap: (tables: ReadonlyArray<AnyTable>, sqlLayer: Layer.Layer<SqlClient.SqlClient, ConfigError.ConfigError |
|
|
5707
|
+
export declare const runFrameworkBootstrap: (tables: ReadonlyArray<AnyTable>, sqlLayer: Layer.Layer<SqlClient.SqlClient, ConfigError.ConfigError | SqlError_2.SqlError, never>, dialect?: DialectId, options?: SchemaApplyOptions) => Promise<void>;
|
|
5405
5708
|
|
|
5406
5709
|
/**
|
|
5407
5710
|
* Run `applySchema` against a fresh SqlClient from the provided sqlLayer.
|
|
@@ -5411,7 +5714,7 @@ export declare const runFrameworkBootstrap: (tables: ReadonlyArray<AnyTable>, sq
|
|
|
5411
5714
|
* `dialect` is passed through to the DDL emitter so SQL types + reactive
|
|
5412
5715
|
* trigger emission match the underlying engine.
|
|
5413
5716
|
*/
|
|
5414
|
-
export declare const runMigrate: (tables: ReadonlyArray<AnyTable>, sqlLayer: Layer.Layer<SqlClient.SqlClient, ConfigError.ConfigError |
|
|
5717
|
+
export declare const runMigrate: (tables: ReadonlyArray<AnyTable>, sqlLayer: Layer.Layer<SqlClient.SqlClient, ConfigError.ConfigError | SqlError_2.SqlError, never>, dialect?: DialectId, options?: SchemaApplyOptions) => Promise<void>;
|
|
5415
5718
|
|
|
5416
5719
|
/**
|
|
5417
5720
|
* Execute ONE planned operation with the applier's own per-dialect
|
|
@@ -5422,7 +5725,7 @@ export declare const runMigrate: (tables: ReadonlyArray<AnyTable>, sqlLayer: Lay
|
|
|
5422
5725
|
* shape from: the live table with the change applied, materialised as a
|
|
5423
5726
|
* declaration by the caller.
|
|
5424
5727
|
*/
|
|
5425
|
-
export declare const runMigrationOp: (sql: SqlClient.SqlClient, planned: PlannedOperation, declared: ReadonlyArray<TableLike>) => Effect.Effect<AppliedOp,
|
|
5728
|
+
export declare const runMigrationOp: (sql: SqlClient.SqlClient, planned: PlannedOperation, declared: ReadonlyArray<TableLike>) => Effect.Effect<AppliedOp, SqlError>;
|
|
5426
5729
|
|
|
5427
5730
|
/**
|
|
5428
5731
|
* Top-level entry point — called once per boot. Returns a
|
|
@@ -5431,9 +5734,11 @@ export declare const runMigrationOp: (sql: SqlClient.SqlClient, planned: Planned
|
|
|
5431
5734
|
*
|
|
5432
5735
|
* Wires the dev/prod dispatch + the VOLTRO_AUTO_MIGRATE escape hatch.
|
|
5433
5736
|
*/
|
|
5434
|
-
export declare const runPlannedMigrations: (sql: SqlClient.SqlClient, declared: ReadonlyArray<TableLike>, ctx: RunPlannedMigrationsCtx) => Effect.Effect<BootMigrationOutcome,
|
|
5737
|
+
export declare const runPlannedMigrations: (sql: SqlClient.SqlClient, declared: ReadonlyArray<TableLike>, ctx: RunPlannedMigrationsCtx) => Effect.Effect<BootMigrationOutcome, SqlError, SqlClient.SqlClient>;
|
|
5435
5738
|
|
|
5436
5739
|
export declare interface RunPlannedMigrationsCtx {
|
|
5740
|
+
/** Forwarded to the applier only when an approved schema plan executes. */
|
|
5741
|
+
readonly beforeExecute?: Effect.Effect<void, SqlError, SqlClient.SqlClient>;
|
|
5437
5742
|
/** What `voltro logs` should attribute this run to. */
|
|
5438
5743
|
readonly appliedBy: string;
|
|
5439
5744
|
readonly environment: BootEnvironment;
|
|
@@ -5458,10 +5763,12 @@ export declare interface RunPlannedMigrationsCtx {
|
|
|
5458
5763
|
* answers `already-absent` before reaching here). This function assumes the
|
|
5459
5764
|
* object is there.
|
|
5460
5765
|
*/
|
|
5461
|
-
export declare const runSchemaOp: (sql: SqlClient.SqlClient, op: MigrationSchemaOp, live: SchemaSnapshot) => Effect.Effect<void,
|
|
5766
|
+
export declare const runSchemaOp: (sql: SqlClient.SqlClient, op: MigrationSchemaOp, live: SchemaSnapshot) => Effect.Effect<void, SqlError>;
|
|
5462
5767
|
|
|
5463
5768
|
/** Runs one Effect over the connection — the shape `ManagedRuntime.runPromise` and a store's `run` share. */
|
|
5464
|
-
export declare type RunSql = <A>(effect: Effect.Effect<A,
|
|
5769
|
+
export declare type RunSql = <A>(effect: Effect.Effect<A, SqlError, SqlClient.SqlClient>) => Promise<A>;
|
|
5770
|
+
|
|
5771
|
+
export declare const SCHEMA_OWNER_TABLE = "_voltro_schema_owner";
|
|
5465
5772
|
|
|
5466
5773
|
/**
|
|
5467
5774
|
* Effect that applies the emitted DDL to the provided SqlClient. Splits
|
|
@@ -5507,6 +5814,34 @@ export declare interface SchemaEmitOptions {
|
|
|
5507
5814
|
/** What a schema operation on the migration context found to do. */
|
|
5508
5815
|
export declare type SchemaOpOutcome = 'applied' | 'already-absent' | 'already-present';
|
|
5509
5816
|
|
|
5817
|
+
/** Who is claiming the schema. */
|
|
5818
|
+
export declare interface SchemaOwnerClaim {
|
|
5819
|
+
/** The app's `name` — the identity compared on every boot. */
|
|
5820
|
+
readonly appName: string;
|
|
5821
|
+
readonly projectName?: string;
|
|
5822
|
+
readonly frameworkVersion?: string;
|
|
5823
|
+
}
|
|
5824
|
+
|
|
5825
|
+
export declare type SchemaOwnership =
|
|
5826
|
+
/** This app already owned the schema. */
|
|
5827
|
+
{
|
|
5828
|
+
readonly kind: 'owned';
|
|
5829
|
+
}
|
|
5830
|
+
/** Unclaimed until now; this app's claim was written. */
|
|
5831
|
+
| {
|
|
5832
|
+
readonly kind: 'claimed';
|
|
5833
|
+
}
|
|
5834
|
+
/** ANOTHER app owns it — the boot must refuse. */
|
|
5835
|
+
| {
|
|
5836
|
+
readonly kind: 'foreign';
|
|
5837
|
+
readonly owner: string;
|
|
5838
|
+
readonly claimedAt: string | undefined;
|
|
5839
|
+
}
|
|
5840
|
+
/** Read-only mode found no claim (or no table) to compare against. */
|
|
5841
|
+
| {
|
|
5842
|
+
readonly kind: 'unclaimed';
|
|
5843
|
+
};
|
|
5844
|
+
|
|
5510
5845
|
/** A schema object a body asked about, in the vocabulary a user writes. */
|
|
5511
5846
|
export declare type SchemaProbe = {
|
|
5512
5847
|
readonly kind: 'table';
|
|
@@ -5558,6 +5893,19 @@ export declare const snapshotColumn: (name: string, def: ColumnDefinition<unknow
|
|
|
5558
5893
|
/** Needed only for `storageType` — a caller that renders DDL does not want it. */
|
|
5559
5894
|
dialect?: DialectId) => ColumnSnapshot;
|
|
5560
5895
|
|
|
5896
|
+
export declare interface SnapshotRestorationObject {
|
|
5897
|
+
readonly kind: 'column' | 'table';
|
|
5898
|
+
readonly table: string;
|
|
5899
|
+
readonly originalName: string;
|
|
5900
|
+
readonly snapshotName: string;
|
|
5901
|
+
}
|
|
5902
|
+
|
|
5903
|
+
export declare interface SnapshotRestorationResult {
|
|
5904
|
+
readonly restoredColumns: number;
|
|
5905
|
+
readonly restoredTables: number;
|
|
5906
|
+
readonly objects: ReadonlyArray<SnapshotRestorationObject>;
|
|
5907
|
+
}
|
|
5908
|
+
|
|
5561
5909
|
/**
|
|
5562
5910
|
* PostGIS spatial-distance clause carried on a {@link QueryDescriptor}.
|
|
5563
5911
|
* Drives a `ST_Distance` projected column (distance-as-a-value) and/or a
|
|
@@ -5669,7 +6017,7 @@ export declare const sqlType: (column: ColumnDefinition<unknown>, dialect: Diale
|
|
|
5669
6017
|
* Effect that performs the squash + returns a summary. Fails if:
|
|
5670
6018
|
* - no eligible rows match (`before` cut everything off)
|
|
5671
6019
|
* - the latest pre-squash fingerprint differs from `fingerprint`
|
|
5672
|
-
* (
|
|
6020
|
+
* (the cut-off may select an older schema, or declarations may be unapplied)
|
|
5673
6021
|
*/
|
|
5674
6022
|
export declare const squashMigrationPlans: (options: SquashOptions) => Effect.Effect<SquashResult, Error, SqlClient.SqlClient>;
|
|
5675
6023
|
|
|
@@ -5688,6 +6036,9 @@ export declare interface SquashOptions {
|
|
|
5688
6036
|
readonly appliedBy: string;
|
|
5689
6037
|
/** Environment tag for the snapshot row. */
|
|
5690
6038
|
readonly environment: string;
|
|
6039
|
+
/** Confirmation token from previewMigrationSquash. Rechecked under the lock
|
|
6040
|
+
* before writing; changed eligibility refuses without changing history. */
|
|
6041
|
+
readonly expectedPreview?: string;
|
|
5691
6042
|
}
|
|
5692
6043
|
|
|
5693
6044
|
export declare interface SquashResult {
|
|
@@ -6420,8 +6771,52 @@ export declare class TransactionBrokenByBodyError extends Error {
|
|
|
6420
6771
|
constructor(migrationId: string, dialect: DialectId);
|
|
6421
6772
|
}
|
|
6422
6773
|
|
|
6774
|
+
/**
|
|
6775
|
+
* Hand the schema to a different app name — `voltro db claim`. The one
|
|
6776
|
+
* deliberate way to change the owner: an app was RENAMED, not replaced.
|
|
6777
|
+
*/
|
|
6778
|
+
export declare const transferSchemaOwner: (sql: SqlClient.SqlClient, claim: SchemaOwnerClaim, charset: MysqlCharset | undefined) => Effect.Effect<{
|
|
6779
|
+
readonly previous: string | undefined;
|
|
6780
|
+
}, SqlError>;
|
|
6781
|
+
|
|
6423
6782
|
export declare const unblockLossy: (plan: MigrationPlan, scope?: ReturnType<typeof destructiveScope>) => MigrationPlan;
|
|
6424
6783
|
|
|
6784
|
+
/** One string column of an undeclared framework table, as the catalog reports it. */
|
|
6785
|
+
export declare interface UndeclaredCharsetColumn {
|
|
6786
|
+
readonly table: string;
|
|
6787
|
+
readonly column: string;
|
|
6788
|
+
readonly charset: string;
|
|
6789
|
+
/** `information_schema.columns.column_type`, e.g. `varchar(255)`, `text`. */
|
|
6790
|
+
readonly columnType: string;
|
|
6791
|
+
readonly nullable: boolean;
|
|
6792
|
+
/** Raw `column_default`; `null` (or the text `NULL` on MariaDB) when there is none. */
|
|
6793
|
+
readonly columnDefault: string | null;
|
|
6794
|
+
readonly generated: boolean;
|
|
6795
|
+
}
|
|
6796
|
+
|
|
6797
|
+
/**
|
|
6798
|
+
* One `ALTER TABLE` per table of the work. `checks` is each table's
|
|
6799
|
+
* column-level CHECKs (`columnLevelChecksMysql`): MariaDB stores such a CHECK
|
|
6800
|
+
* in the column definition, and a MODIFY that does not restate it deletes it.
|
|
6801
|
+
*/
|
|
6802
|
+
export declare const undeclaredCharsetStatements: (w: UndeclaredCharsetWork, checks?: ReadonlyMap<string, ReadonlyMap<string, string>>) => ReadonlyArray<string>;
|
|
6803
|
+
|
|
6804
|
+
export declare interface UndeclaredCharsetWork {
|
|
6805
|
+
readonly tables: ReadonlyArray<{
|
|
6806
|
+
readonly table: string;
|
|
6807
|
+
readonly columns: ReadonlyArray<UndeclaredCharsetColumn>;
|
|
6808
|
+
}>;
|
|
6809
|
+
/** Columns that are off but carry a default or a generation expression — named, not rewritten. */
|
|
6810
|
+
readonly left: ReadonlyArray<UndeclaredCharsetColumn>;
|
|
6811
|
+
}
|
|
6812
|
+
|
|
6813
|
+
/**
|
|
6814
|
+
* What a declaration asks of the undeclared framework tables. Pure, so `db
|
|
6815
|
+
* plan` can print it and `db apply` can do it from the same reading. `only`
|
|
6816
|
+
* narrows it to named tables — the ones the cluster gate has just created.
|
|
6817
|
+
*/
|
|
6818
|
+
export declare const undeclaredCharsetWork: (columns: ReadonlyArray<UndeclaredCharsetColumn>, declaredNames: ReadonlySet<string>, charset: MysqlCharset | undefined, only?: ReadonlySet<string>) => UndeclaredCharsetWork;
|
|
6819
|
+
|
|
6425
6820
|
/** Every deploy that did not finish — `running` (the process died) or `failed` (its undo did not complete). An absent table is an empty ledger. */
|
|
6426
6821
|
export declare const unfinishedDeploys: (sql: SqlClient.SqlClient) => Effect.Effect<ReadonlyArray<DeployLedgerRow>, never>;
|
|
6427
6822
|
|
|
@@ -6597,7 +6992,7 @@ declare interface WindowSpec_2 {
|
|
|
6597
6992
|
}>;
|
|
6598
6993
|
}
|
|
6599
6994
|
|
|
6600
|
-
export declare const withMigrationLock: <A, E, R = never>(sql: SqlClient.SqlClient, work: Effect.Effect<A, E, R>, scope?: MigrationLockScope) => Effect.Effect<A, E |
|
|
6995
|
+
export declare const withMigrationLock: <A, E, R = never>(sql: SqlClient.SqlClient, work: Effect.Effect<A, E, R>, scope?: MigrationLockScope) => Effect.Effect<A, E | SqlError, R>;
|
|
6601
6996
|
|
|
6602
6997
|
/**
|
|
6603
6998
|
* Wrap a migration context so its four existence questions are recorded when —
|