@voltro/database 0.62.3 → 0.64.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 +104 -0
- package/dist/{frameworkLiveTables-CewCJ809.js → frameworkLiveTables-BURogL9N.js} +223 -188
- package/dist/index.d.ts +225 -35
- package/dist/index.js +840 -817
- package/dist/sql.d.ts +37 -11
- package/dist/sql.js +973 -953
- package/dist/wire-B28cPjEp.js +32 -0
- package/dist/wire.d.ts +21 -0
- package/dist/wire.js +2 -5
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,32 @@ export declare const actorsTable: Table<'actors', Record<string, ColumnDefinitio
|
|
|
30
30
|
*/
|
|
31
31
|
export declare const admitBranch: (branches: ReadonlyArray<BranchRecord>, policy: BranchPolicy, nowMs: number) => BranchLimitDecision;
|
|
32
32
|
|
|
33
|
+
export declare interface AgedSoftDropSnapshot {
|
|
34
|
+
/** `table` or `table.column`. */
|
|
35
|
+
readonly name: string;
|
|
36
|
+
readonly droppedAt: Date;
|
|
37
|
+
readonly ageDays: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The soft-drop snapshots older than the review window — the ones nobody
|
|
42
|
+
* restored and nobody reclaimed. A snapshot is a full copy of the dropped data,
|
|
43
|
+
* PII included, and `gc-snapshots` is a manual step an operator has to
|
|
44
|
+
* remember; this is the reminder, computed from the stamp in the name so it
|
|
45
|
+
* costs no query beyond the introspection that already ran.
|
|
46
|
+
*/
|
|
47
|
+
export declare const agedSoftDropSnapshots: (live: {
|
|
48
|
+
readonly tables: ReadonlyArray<{
|
|
49
|
+
readonly name: string;
|
|
50
|
+
readonly columns?: ReadonlyArray<{
|
|
51
|
+
readonly name: string;
|
|
52
|
+
}>;
|
|
53
|
+
}>;
|
|
54
|
+
}, options?: {
|
|
55
|
+
readonly now?: Date;
|
|
56
|
+
readonly retentionDays?: number;
|
|
57
|
+
}) => ReadonlyArray<AgedSoftDropSnapshot>;
|
|
58
|
+
|
|
33
59
|
export declare interface AggregateColumn<TResult = number | Date | null> {
|
|
34
60
|
readonly op: 'count' | 'sum' | 'avg' | 'min' | 'max' | 'count-distinct' | 'window-row-number' | 'window-rank' | 'window-dense-rank' | 'window-lag' | 'window-lead' | 'window-sum-over' | 'window-avg-over' | 'column';
|
|
35
61
|
readonly column?: string;
|
|
@@ -303,6 +329,9 @@ export declare const bindResidentStore: <S>(subject: ResidencySubject, config: R
|
|
|
303
329
|
|
|
304
330
|
export declare const boolean: () => ColumnBuilder<boolean, "boolean", boolean>;
|
|
305
331
|
|
|
332
|
+
/** The BOUND envelope: `enc:v2:<r|c>:<iv>:<tag>:<ct>` — see {@link FieldBinding}. */
|
|
333
|
+
export declare const BOUND_ENCRYPTED_PREFIX = "enc:v2:";
|
|
334
|
+
|
|
306
335
|
export declare type BranchEvent = 'provision' | 'provisioned' | 'fail' | 'destroy' | 'destroyed';
|
|
307
336
|
|
|
308
337
|
/**
|
|
@@ -1380,6 +1409,14 @@ export declare interface ColumnDefinition<TsType, Type extends ColumnType = Colu
|
|
|
1380
1409
|
* has nothing to do with FK semantics.
|
|
1381
1410
|
*/
|
|
1382
1411
|
readonly refOnUpdate?: 'cascade' | 'restrict' | 'setNull' | 'noAction';
|
|
1412
|
+
/**
|
|
1413
|
+
* What the RUNTIME does to this column's rows when the referenced row is
|
|
1414
|
+
* SOFT-deleted (`deletedAt` set) — set by `reference(…, { onSoftDelete })`.
|
|
1415
|
+
* A foreign key never sees a soft delete (it is an UPDATE), so `onDelete`
|
|
1416
|
+
* cannot express it; the store's post-commit change channel enforces this
|
|
1417
|
+
* one instead, the way `pluginRef` orphan rules are enforced.
|
|
1418
|
+
*/
|
|
1419
|
+
readonly refOnSoftDelete?: 'cascade' | 'setNull';
|
|
1383
1420
|
/**
|
|
1384
1421
|
* Auto-create a B-tree index on this FK column. Default `true` — FK
|
|
1385
1422
|
* columns are nearly always read-by, and the lookup cost of a missing
|
|
@@ -1483,12 +1520,16 @@ export declare interface ColumnDefinition<TsType, Type extends ColumnType = Colu
|
|
|
1483
1520
|
/**
|
|
1484
1521
|
* Field-level encryption flag, set by `.encrypted()`. When `true`
|
|
1485
1522
|
* the runtime's store middleware encrypts the value on write and
|
|
1486
|
-
* decrypts on read via the registered field cipher (AES-256-GCM,
|
|
1487
|
-
*
|
|
1488
|
-
*
|
|
1489
|
-
*
|
|
1523
|
+
* decrypts on read via the registered field cipher (AES-256-GCM, keyed
|
|
1524
|
+
* from `VOLTRO_FIELD_ENCRYPTION_KEY` through the Secrets-Resolver — the
|
|
1525
|
+
* framework registers it on both boot paths; `voltro dev` mints the key).
|
|
1526
|
+
* The stored column is an opaque `enc:v2:…` string — bound by GCM's
|
|
1527
|
+
* additional authenticated data to its table, column and row
|
|
1528
|
+
* (`FieldBinding`), so a ciphertext copied into another row or column
|
|
1529
|
+
* does not decrypt there — and the DB type stays `text`. A row written
|
|
1530
|
+
* while encryption is active can't be
|
|
1490
1531
|
* read back without the key — losing the key loses the data, by
|
|
1491
|
-
* design. Boot
|
|
1532
|
+
* design. Boot refuses if an `.encrypted()` column is declared but
|
|
1492
1533
|
* no cipher is registered.
|
|
1493
1534
|
*/
|
|
1494
1535
|
readonly encrypted?: boolean;
|
|
@@ -2757,7 +2798,7 @@ export declare const declareEnumRename: (enumName: string, rename: EnumValueRena
|
|
|
2757
2798
|
* it is written here so the next reader does not go looking for the branch that
|
|
2758
2799
|
* handles it.
|
|
2759
2800
|
*/
|
|
2760
|
-
export declare const decodeFieldValue: (cipher: FieldCipher, ciphertext: string, expected?: string) => unknown;
|
|
2801
|
+
export declare const decodeFieldValue: (cipher: FieldCipher, ciphertext: string, expected?: string, binding?: FieldBinding) => unknown;
|
|
2761
2802
|
|
|
2762
2803
|
export declare type DecoderDialectId = 'postgres' | 'mysql' | 'mariadb' | 'sqlite' | 'mssql' | 'turso';
|
|
2763
2804
|
|
|
@@ -2789,6 +2830,9 @@ export declare const decryptFieldsOnRead: (rows: ReadonlyArray<Row>, table: Tabl
|
|
|
2789
2830
|
readonly column: string;
|
|
2790
2831
|
readonly reason: string;
|
|
2791
2832
|
}) => void;
|
|
2833
|
+
/** The row's id when the rows themselves do not carry it — the row a KEYED
|
|
2834
|
+
* write returns is addressed by the `pk` the caller passed. */
|
|
2835
|
+
readonly rowId?: unknown;
|
|
2792
2836
|
}) => ReadonlyArray<Row>;
|
|
2793
2837
|
|
|
2794
2838
|
/**
|
|
@@ -2821,6 +2865,10 @@ export declare const DEFAULT_CHANGE_CLAIM_TTL_HOURS = 1;
|
|
|
2821
2865
|
*/
|
|
2822
2866
|
export declare const DEFAULT_EAGER_FALLBACK_WARN_INTERVAL_MS = 300000;
|
|
2823
2867
|
|
|
2868
|
+
/** Default review window for a soft-drop snapshot, in days — the "~7d" the
|
|
2869
|
+
* soft-drop advice promises. Past it, a boot and a `db plan` say so. */
|
|
2870
|
+
export declare const DEFAULT_SOFT_DROP_RETENTION_DAYS = 7;
|
|
2871
|
+
|
|
2824
2872
|
export declare const DEFAULT_SUBJECT_GRAPH_DEPTH = 4;
|
|
2825
2873
|
|
|
2826
2874
|
export declare const defineMigration: (input: MigrationDefinitionInput) => MigrationDefinition;
|
|
@@ -2921,6 +2969,9 @@ export declare interface DeriveSubjectGraphInput {
|
|
|
2921
2969
|
*/
|
|
2922
2970
|
export declare const deriveTypeIdPrefix: (tableName: string) => string;
|
|
2923
2971
|
|
|
2972
|
+
/** The one line both the boot and `db plan` print for an aged snapshot set. */
|
|
2973
|
+
export declare const describeAgedSoftDropSnapshots: (aged: ReadonlyArray<AgedSoftDropSnapshot>, retentionDays: number) => string;
|
|
2974
|
+
|
|
2924
2975
|
/**
|
|
2925
2976
|
* A one-line driver summary for an error, or `undefined` when the chain carries
|
|
2926
2977
|
* nothing driver-shaped.
|
|
@@ -3268,7 +3319,7 @@ declare type EmptyMerge = unknown;
|
|
|
3268
3319
|
* remedies, and collapsing them is what cost the consumer a day. `decodeFieldValue`
|
|
3269
3320
|
* therefore decrypts and decodes as two separate steps and says which one failed.
|
|
3270
3321
|
*/
|
|
3271
|
-
export declare const encodeFieldValue: (cipher: FieldCipher, value: unknown) => string;
|
|
3322
|
+
export declare const encodeFieldValue: (cipher: FieldCipher, value: unknown, binding?: FieldBinding) => string;
|
|
3272
3323
|
|
|
3273
3324
|
/**
|
|
3274
3325
|
* Serialize a row's json()/array() cells to JSON strings so they can be
|
|
@@ -3278,7 +3329,7 @@ export declare const encodeFieldValue: (cipher: FieldCipher, value: unknown) =>
|
|
|
3278
3329
|
*/
|
|
3279
3330
|
export declare const encodeRowForSchema: <T extends Record<string, unknown>>(row: T, tableName: string, types?: ReadonlyArray<ColumnType>) => T;
|
|
3280
3331
|
|
|
3281
|
-
/**
|
|
3332
|
+
/** The UNBOUND envelope: `enc:v1:<iv>:<tag>:<ct>`. */
|
|
3282
3333
|
export declare const ENCRYPTED_PREFIX = "enc:v1:";
|
|
3283
3334
|
|
|
3284
3335
|
/** Column names on a table flagged `.encrypted()`. */
|
|
@@ -3290,10 +3341,14 @@ export declare const encryptedColumnsOf: (table: TableLike) => ReadonlyArray<str
|
|
|
3290
3341
|
* `null` / `undefined` pass through. An already-encrypted value is left
|
|
3291
3342
|
* as-is (idempotent — a re-passed ciphertext isn't double-wrapped).
|
|
3292
3343
|
*
|
|
3344
|
+
* Each value is BOUND to its address (`FieldBinding`): to the row when its id
|
|
3345
|
+
* is known — the row's own `id`, or `rowId` for a keyed write whose patch does
|
|
3346
|
+
* not carry it — and to the column otherwise.
|
|
3347
|
+
*
|
|
3293
3348
|
* Throws if an encrypted column carries a value but no cipher is
|
|
3294
3349
|
* registered — losing the key silently would be worse than a loud boot.
|
|
3295
3350
|
*/
|
|
3296
|
-
export declare const encryptFieldsForWrite: (row: Row, table: TableLike | undefined, cipher: FieldCipher | undefined) => Row;
|
|
3351
|
+
export declare const encryptFieldsForWrite: (row: Row, table: TableLike | undefined, cipher: FieldCipher | undefined, rowId?: unknown) => Row;
|
|
3297
3352
|
|
|
3298
3353
|
/** Mark it finished — AFTER its `routeEvent` has registered, not after the
|
|
3299
3354
|
* statement. That is the whole point: the window being closed is exactly the
|
|
@@ -3374,9 +3429,10 @@ export declare interface ExistsPredicate {
|
|
|
3374
3429
|
* expiry on every existing row".
|
|
3375
3430
|
*
|
|
3376
3431
|
* Reads filter it out on EVERY dialect from the moment it passes; the physical
|
|
3377
|
-
* delete is
|
|
3378
|
-
*
|
|
3379
|
-
*
|
|
3432
|
+
* delete is the retention sweep, on every dialect, after a grace of
|
|
3433
|
+
* `VOLTRO_EXPIRED_ROWS_TTL_HOURS` (default 24). Read the header before relying
|
|
3434
|
+
* on the second half — an expired row is INVISIBLE everywhere and still
|
|
3435
|
+
* PRESENT for up to that grace, which is the right trade and a surprising one.
|
|
3380
3436
|
*
|
|
3381
3437
|
* Opt out for a deliberate read of expired rows the same way soft-delete does:
|
|
3382
3438
|
* `ctx.store.select('inviteLinks').includeExpired()`.
|
|
@@ -3427,10 +3483,54 @@ export declare interface FallbackLogger {
|
|
|
3427
3483
|
readonly debug: (message: string, fields?: Record<string, unknown>) => void;
|
|
3428
3484
|
}
|
|
3429
3485
|
|
|
3486
|
+
/**
|
|
3487
|
+
* Where a ciphertext BELONGS — the table, the column and, when the row's
|
|
3488
|
+
* identity is known at write time, the row. Fed to AES-GCM as additional
|
|
3489
|
+
* authenticated data, so the tag covers the address as well as the bytes.
|
|
3490
|
+
*
|
|
3491
|
+
* ── The attack this closes ─────────────────────────────────────────────────
|
|
3492
|
+
*
|
|
3493
|
+
* Without it, a ciphertext is a bearer value: anyone who can WRITE the database
|
|
3494
|
+
* — a leaked migration credential, a compromised replica, an operator with too
|
|
3495
|
+
* much access — copies user A's encrypted token into user B's row, and the app,
|
|
3496
|
+
* acting for B, decrypts and USES A's credential. No key is needed; the app is
|
|
3497
|
+
* the confused deputy that holds it. The same copy across columns turns a
|
|
3498
|
+
* refresh token into an access token. Bound to `table:column:rowId`, the copied
|
|
3499
|
+
* value fails GCM authentication in its new home: the attacker needs the key to
|
|
3500
|
+
* re-bind it, which is the thing they did not have.
|
|
3501
|
+
*
|
|
3502
|
+
* `row` is the strong binding and `column` the fallback: a set-based write has
|
|
3503
|
+
* no row identity, and a table whose id the DATABASE assigns has none at insert.
|
|
3504
|
+
* The envelope records which one was used (`enc:v2:r:` / `enc:v2:c:`), so the
|
|
3505
|
+
* reader never guesses.
|
|
3506
|
+
*/
|
|
3507
|
+
export declare interface FieldBinding {
|
|
3508
|
+
/** `table:column`. */
|
|
3509
|
+
readonly column: string;
|
|
3510
|
+
/** `table:column:rowId` — present iff the row's id is known. */
|
|
3511
|
+
readonly row?: string;
|
|
3512
|
+
}
|
|
3513
|
+
|
|
3514
|
+
/** The binding for one column of one row. `rowId` is the id as the row carries
|
|
3515
|
+
* it; a number is spelled the way `String()` spells it so a keyed update by
|
|
3516
|
+
* its string form and a read of the numeric column agree. */
|
|
3517
|
+
export declare const fieldBinding: (table: string, column: string, rowId?: unknown) => FieldBinding;
|
|
3518
|
+
|
|
3430
3519
|
/** The cipher the store middleware injects. Operates on opaque strings. */
|
|
3431
3520
|
export declare interface FieldCipher {
|
|
3432
|
-
|
|
3433
|
-
|
|
3521
|
+
/**
|
|
3522
|
+
* With a binding: an `enc:v2:r:` (row-bound, when `binding.row` is set) or
|
|
3523
|
+
* `enc:v2:c:` (column-bound) envelope whose GCM tag covers the binding.
|
|
3524
|
+
* Without one: the unbound `enc:v1:` envelope — the raw-SQL escape hatch's
|
|
3525
|
+
* form, and what every row written before 0.64 carries.
|
|
3526
|
+
*/
|
|
3527
|
+
readonly encrypt: (plaintext: string, binding?: FieldBinding) => string;
|
|
3528
|
+
/**
|
|
3529
|
+
* Reads every envelope. A bound one is verified against the matching member
|
|
3530
|
+
* of `binding` and fails when it is absent or differs — that failure IS the
|
|
3531
|
+
* feature, and the reader must not fall back to an unbound read.
|
|
3532
|
+
*/
|
|
3533
|
+
readonly decrypt: (ciphertext: string, binding?: FieldBinding) => string;
|
|
3434
3534
|
}
|
|
3435
3535
|
|
|
3436
3536
|
/**
|
|
@@ -3977,6 +4077,10 @@ export declare const intersect: (...queries: ReadonlyArray<QueryWithDescriptorAn
|
|
|
3977
4077
|
*/
|
|
3978
4078
|
export declare const interval: () => ColumnBuilder<string, "interval", boolean>;
|
|
3979
4079
|
|
|
4080
|
+
/** Is this value a BOUND ciphertext (`enc:v2:`)? An unbound `enc:v1:` value
|
|
4081
|
+
* reads fine and is what `voltro db encrypt-column` re-binds. */
|
|
4082
|
+
export declare const isBoundCiphertext: (value: unknown) => value is string;
|
|
4083
|
+
|
|
3980
4084
|
/** Is this namespace one of ours? (so a teardown sweep never touches a real
|
|
3981
4085
|
* tenant namespace). */
|
|
3982
4086
|
export declare const isBranchNamespace: (namespace: string) => boolean;
|
|
@@ -4069,7 +4173,7 @@ export declare const isQueryTimeout: (dbCause: Record<string, unknown>) => boole
|
|
|
4069
4173
|
* to normalise a column without touching rows that are already current. Answers
|
|
4070
4174
|
* `undefined` when the two forms coincide (a numeric column, or a value that
|
|
4071
4175
|
* parses to itself) — nothing to do either way. */
|
|
4072
|
-
export declare const isRawEncoding: (cipher: FieldCipher, ciphertext: string, expected?: string) => boolean | undefined;
|
|
4176
|
+
export declare const isRawEncoding: (cipher: FieldCipher, ciphertext: string, expected?: string, binding?: FieldBinding) => boolean | undefined;
|
|
4073
4177
|
|
|
4074
4178
|
/** Can THIS deployment serve the region? */
|
|
4075
4179
|
export declare const isRegionServable: (region: string, config: ResidencyConfig) => boolean;
|
|
@@ -4078,6 +4182,11 @@ export declare const isRelationsSpec: (value: unknown) => value is RelationsSpec
|
|
|
4078
4182
|
|
|
4079
4183
|
export declare const isSeedDefinition: (value: unknown) => value is SeedDefinition;
|
|
4080
4184
|
|
|
4185
|
+
/** True when `name` is a soft-drop snapshot (`<original>__dropped_<ts>`) left
|
|
4186
|
+
* behind by `VOLTRO_SOFT_DROP=1`. Applies to tables AND columns — the applier
|
|
4187
|
+
* uses one suffix for both. */
|
|
4188
|
+
export declare const isSoftDropSnapshotName: (name: string) => boolean;
|
|
4189
|
+
|
|
4081
4190
|
/**
|
|
4082
4191
|
* `turso` (the Rust rewrite of SQLite, `@voltro/sql-turso`) is
|
|
4083
4192
|
* SQL-semantically identical to `sqlite` — it differs only in the connection
|
|
@@ -4144,6 +4253,13 @@ export declare const isStagingTableName: (name: string) => boolean;
|
|
|
4144
4253
|
*/
|
|
4145
4254
|
export declare const isTableReactive: (tableName: string) => boolean;
|
|
4146
4255
|
|
|
4256
|
+
/**
|
|
4257
|
+
* Dialect-agnostic: does this error, anywhere down its `cause` chain, carry a
|
|
4258
|
+
* contention signal any supported engine emits? The mutation runner replays
|
|
4259
|
+
* the whole transaction on a `true`.
|
|
4260
|
+
*/
|
|
4261
|
+
export declare const isTransientContention: (err: unknown) => boolean;
|
|
4262
|
+
|
|
4147
4263
|
/** Type guard: is this descriptor a read-only view (vs a base table)? */
|
|
4148
4264
|
export declare const isView: (t: TableLike) => t is View<string, Record<string, ColumnDefinition<unknown>>>;
|
|
4149
4265
|
|
|
@@ -4608,6 +4724,12 @@ export declare interface MixinOptions<Input extends FieldsInput> {
|
|
|
4608
4724
|
readonly policies?: MixinDefinition<FieldDefinitions<Input>>['policies'];
|
|
4609
4725
|
}
|
|
4610
4726
|
|
|
4727
|
+
/** SQL Server error numbers, as decimal strings. */
|
|
4728
|
+
export declare const MSSQL_TRANSIENT_NUMBERS: ReadonlySet<string>;
|
|
4729
|
+
|
|
4730
|
+
/** MySQL / MariaDB — `errno` as a decimal string, or the symbolic `code`. */
|
|
4731
|
+
export declare const MYSQL_TRANSIENT_CODES: ReadonlySet<string>;
|
|
4732
|
+
|
|
4611
4733
|
/**
|
|
4612
4734
|
* Type-narrowing migration marker. Tells the planner that this column
|
|
4613
4735
|
* previously had type `from` and is now being narrowed/converted to its
|
|
@@ -4997,6 +5119,9 @@ export declare interface PluginRefSpec {
|
|
|
4997
5119
|
/** The declared spec for a column builder, when it is a `pluginRef`. */
|
|
4998
5120
|
export declare const pluginRefSpecOf: (column: unknown) => PluginRefSpec | undefined;
|
|
4999
5121
|
|
|
5122
|
+
/** Postgres SQLSTATEs. */
|
|
5123
|
+
export declare const POSTGRES_TRANSIENT_STATES: ReadonlySet<string>;
|
|
5124
|
+
|
|
5000
5125
|
export declare type Predicate = PredicateLeaf | AndPredicate | OrPredicate | NotPredicate | SubqueryInPredicate | ExistsPredicate;
|
|
5001
5126
|
|
|
5002
5127
|
export declare interface PredicateLeaf {
|
|
@@ -5112,6 +5237,16 @@ Joins extends JoinsMap = {}> {
|
|
|
5112
5237
|
* SEE tombstoned rows. No-op on tables without `softDelete()`.
|
|
5113
5238
|
*/
|
|
5114
5239
|
withDeleted: () => Query<RowOf, IxNames, Joins>;
|
|
5240
|
+
/**
|
|
5241
|
+
* Lock the matched rows until the enclosing transaction commits — the
|
|
5242
|
+
* read half of a read-modify-write that must not lose an update to a
|
|
5243
|
+
* concurrent writer. A json array appended by two requests at once keeps
|
|
5244
|
+
* one append without it; with it the second reader waits for the first
|
|
5245
|
+
* transaction and reads the row it wrote. Per dialect: `FOR UPDATE`
|
|
5246
|
+
* (postgres / mysql / mariadb), `WITH (UPDLOCK, ROWLOCK)` (mssql), nothing
|
|
5247
|
+
* on sqlite (its writers are serialised already).
|
|
5248
|
+
*/
|
|
5249
|
+
forUpdate: () => Query<RowOf, IxNames, Joins>;
|
|
5115
5250
|
/**
|
|
5116
5251
|
* Cross-tenant: opt OUT of the runtime's automatic
|
|
5117
5252
|
* `tenantId = <subject.tenantId>` scope on `tenant()` tables. Use for
|
|
@@ -5477,6 +5612,15 @@ export declare interface QueryDescriptor<R = Row> {
|
|
|
5477
5612
|
* rows (an admin view, a grace-period check). Same shape and same posture as
|
|
5478
5613
|
* `includeDeleted`. */
|
|
5479
5614
|
readonly includeExpired?: boolean;
|
|
5615
|
+
/**
|
|
5616
|
+
* Lock the matched rows for the rest of the enclosing transaction — set by
|
|
5617
|
+
* `.forUpdate()`. `SELECT … FOR UPDATE` on postgres / mysql / mariadb,
|
|
5618
|
+
* `WITH (UPDLOCK, ROWLOCK)` on mssql; sqlite serialises writers already and
|
|
5619
|
+
* emits nothing. Outside a transaction the lock is released as the statement
|
|
5620
|
+
* ends, which is harmless and useless — the point is a read-modify-write
|
|
5621
|
+
* whose read and write share one transaction.
|
|
5622
|
+
*/
|
|
5623
|
+
readonly lock?: 'update';
|
|
5480
5624
|
/**
|
|
5481
5625
|
* Opt OUT of the runtime's automatic tenant scope on `tenant()` tables.
|
|
5482
5626
|
* Set by `.unscoped()`. Honored by the runtime, same as `includeDeleted`.
|
|
@@ -5907,25 +6051,26 @@ export declare interface RecordedWrite {
|
|
|
5907
6051
|
|
|
5908
6052
|
export declare const recordsTable: (table: string) => boolean;
|
|
5909
6053
|
|
|
5910
|
-
/**
|
|
5911
|
-
* Foreign-key reference to another table's id column.
|
|
5912
|
-
*
|
|
5913
|
-
* Default cascade semantics: `onDelete: 'restrict'`,
|
|
5914
|
-
* `onUpdate: 'noAction'`, `index: true`. Override per call when the
|
|
5915
|
-
* relationship genuinely is owned-lifecycle (junction tables typically
|
|
5916
|
-
* want `onDelete: 'cascade'`).
|
|
5917
|
-
*
|
|
5918
|
-
* ```ts
|
|
5919
|
-
* userId: reference(() => users, { onDelete: 'cascade' })
|
|
5920
|
-
* tenantId: reference(() => tenants) // restrict default
|
|
5921
|
-
* cacheBucketId: reference(() => cacheBuckets, { index: false }) // rare opt-out
|
|
5922
|
-
* ```
|
|
5923
|
-
*/
|
|
5924
6054
|
export declare const reference: (target: () => TableLike, options?: ReferenceOptions) => ColumnBuilder<string, "reference">;
|
|
5925
6055
|
|
|
5926
6056
|
export declare interface ReferenceOptions {
|
|
5927
6057
|
readonly onDelete?: 'cascade' | 'restrict' | 'setNull' | 'noAction';
|
|
5928
6058
|
readonly onUpdate?: 'cascade' | 'restrict' | 'setNull' | 'noAction';
|
|
6059
|
+
/**
|
|
6060
|
+
* The soft-delete counterpart of `onDelete`. A soft delete is an UPDATE that
|
|
6061
|
+
* sets `deletedAt`, so `ON DELETE CASCADE` never fires for it and the
|
|
6062
|
+
* children of a soft-deleted parent stay visible — a team's members outlive
|
|
6063
|
+
* the team. This is enforced by the runtime on the store's change channel:
|
|
6064
|
+
*
|
|
6065
|
+
* 'cascade' → soft-delete the referencing rows (their table must carry
|
|
6066
|
+
* `softDelete()` too — a hard delete of a child cannot be
|
|
6067
|
+
* undone when the parent is restored, so it is refused at boot)
|
|
6068
|
+
* 'setNull' → null the reference (the column must be `.nullable()`)
|
|
6069
|
+
*
|
|
6070
|
+
* Restoring the parent does NOT restore the children; a restore is a
|
|
6071
|
+
* deliberate act on one row, and the children carry their own `deletedAt`.
|
|
6072
|
+
*/
|
|
6073
|
+
readonly onSoftDelete?: 'cascade' | 'setNull';
|
|
5929
6074
|
/**
|
|
5930
6075
|
* Auto-build a B-tree index on this column. Default `true` because
|
|
5931
6076
|
* FK columns are almost always read-by. Set `false` only for tiny
|
|
@@ -6529,6 +6674,19 @@ export declare interface SchemaTable extends TableLike {
|
|
|
6529
6674
|
readonly appliedFullText: ReadonlyArray<TableFullTextIndex>;
|
|
6530
6675
|
}
|
|
6531
6676
|
|
|
6677
|
+
/** The longest scope key stored. A scope is an address, not a document; a
|
|
6678
|
+
* value longer than this is truncated, deterministically, so equal scopes
|
|
6679
|
+
* keep equal keys. */
|
|
6680
|
+
export declare const SCOPE_KEY_MAX_LENGTH = 255;
|
|
6681
|
+
|
|
6682
|
+
/**
|
|
6683
|
+
* The scope's key. A string scope is its own key (`'team:frontend'`); anything
|
|
6684
|
+
* else is canonical JSON — object keys sorted, `undefined` fields dropped — so
|
|
6685
|
+
* `{ team: 'a', org: 'b' }` and `{ org: 'b', team: 'a' }` address the same rows.
|
|
6686
|
+
* `null` / `undefined` have no key.
|
|
6687
|
+
*/
|
|
6688
|
+
export declare const scopeKeyOf: (scope: unknown) => string | null;
|
|
6689
|
+
|
|
6532
6690
|
export declare interface SeedDefinition {
|
|
6533
6691
|
readonly __seed: true;
|
|
6534
6692
|
readonly id: string;
|
|
@@ -6655,6 +6813,26 @@ export declare interface SeedStore {
|
|
|
6655
6813
|
delete(table: string, primaryKey: string): Promise<boolean>;
|
|
6656
6814
|
}
|
|
6657
6815
|
|
|
6816
|
+
/**
|
|
6817
|
+
* The target thunk `selfReference()` plants — `table()` swaps it for the table
|
|
6818
|
+
* being built. Calling it before then is a declaration error, said out loud
|
|
6819
|
+
* rather than returned as `undefined`.
|
|
6820
|
+
*/
|
|
6821
|
+
export declare const SELF_REFERENCE_TARGET: () => TableLike;
|
|
6822
|
+
|
|
6823
|
+
/**
|
|
6824
|
+
* A reference to the table this column is declared IN — `parentId` on
|
|
6825
|
+
* `teams`, `replyToId` on `comments`.
|
|
6826
|
+
*
|
|
6827
|
+
* `reference(() => teams)` inside `teams`' own declaration is a TypeScript
|
|
6828
|
+
* cycle (TS7022 — the table's type depends on the column, whose type mentions
|
|
6829
|
+
* the table), so the honest workaround was `text()` and a foreign key the
|
|
6830
|
+
* schema no longer knew about. This column carries no target type, only the
|
|
6831
|
+
* thunk `table()` resolves to itself, so the FK, the eager loader and the
|
|
6832
|
+
* subject graph see it as the reference it is.
|
|
6833
|
+
*/
|
|
6834
|
+
export declare const selfReference: (options?: ReferenceOptions) => ColumnBuilder<string, "reference">;
|
|
6835
|
+
|
|
6658
6836
|
/**
|
|
6659
6837
|
* Data-sensitivity classes for `.sensitive(class)`. The class picks the
|
|
6660
6838
|
* format-preserving fake the export masker applies (an `'email'` becomes a
|
|
@@ -6720,6 +6898,10 @@ export declare const settleVersionedUpdate: (input: {
|
|
|
6720
6898
|
readonly current: number | null;
|
|
6721
6899
|
}) => VersionConflict | undefined;
|
|
6722
6900
|
|
|
6901
|
+
/** When a `<name>__dropped_<YYYYMMDDHHMMSS>` snapshot was taken (UTC), or
|
|
6902
|
+
* `undefined` for a name that is not one. */
|
|
6903
|
+
export declare const softDropSnapshotStamp: (name: string) => Date | undefined;
|
|
6904
|
+
|
|
6723
6905
|
/**
|
|
6724
6906
|
* PostGIS spatial-distance clause carried on a {@link QueryDescriptor}.
|
|
6725
6907
|
* Drives a `ST_Distance` projected column (distance-as-a-value) and/or a
|
|
@@ -6824,6 +7006,9 @@ export declare interface SqlDialect {
|
|
|
6824
7006
|
readonly retryFilter: (error: unknown) => RetryDecision;
|
|
6825
7007
|
}
|
|
6826
7008
|
|
|
7009
|
+
/** SQLite / turso result codes — symbolic and numeric spellings. */
|
|
7010
|
+
export declare const SQLITE_TRANSIENT_CODES: ReadonlySet<string>;
|
|
7011
|
+
|
|
6827
7012
|
/**
|
|
6828
7013
|
* How long a staged run's silence has to last before its scratch tables are
|
|
6829
7014
|
* treated as abandoned.
|
|
@@ -7387,10 +7572,11 @@ export declare interface Table<Name extends string, Fields extends Record<string
|
|
|
7387
7572
|
* row with the same key is allowed — no hand-written
|
|
7388
7573
|
* `generatedAs("CASE WHEN …")` column, no resurrection footgun.
|
|
7389
7574
|
*
|
|
7390
|
-
* **mysql / mariadb:** these engines have no partial-index support, so
|
|
7391
|
-
* `.uniqueActive()`
|
|
7392
|
-
*
|
|
7393
|
-
*
|
|
7575
|
+
* **mysql / mariadb:** these engines have no partial-index support, so the
|
|
7576
|
+
* migrator LOWERS `.uniqueActive()` to a generated STORED column holding the
|
|
7577
|
+
* key while the predicate holds (NULL otherwise, and NULLs never collide) plus
|
|
7578
|
+
* a UNIQUE index on it — the same guarantee, on the dialects that cannot
|
|
7579
|
+
* spell it directly. See `lowerUniqueActive` in `migrate.ts`.
|
|
7394
7580
|
*/
|
|
7395
7581
|
uniqueActive: {
|
|
7396
7582
|
<const F extends readonly [keyof Fields & string, ...Array<keyof Fields & string>]>(fields: F, options?: {
|
|
@@ -7655,8 +7841,9 @@ export declare interface TableIndex {
|
|
|
7655
7841
|
* declarative planner is predicate-blind, these are emitted by the
|
|
7656
7842
|
* fresh-schema DDL path (like every partial predicate) and kept OUT of the
|
|
7657
7843
|
* declarative index snapshot. mysql/mariadb have no partial-index support —
|
|
7658
|
-
* `.uniqueActive()`
|
|
7659
|
-
* silently dropping the predicate into a full
|
|
7844
|
+
* `.uniqueActive()` is lowered there to a generated STORED column + UNIQUE
|
|
7845
|
+
* (`migrate.ts`) rather than silently dropping the predicate into a full
|
|
7846
|
+
* unique index.
|
|
7660
7847
|
*/
|
|
7661
7848
|
readonly unique?: boolean;
|
|
7662
7849
|
}
|
|
@@ -7835,6 +8022,9 @@ export declare interface TransactionalViewHandle {
|
|
|
7835
8022
|
*/
|
|
7836
8023
|
export declare type TransactionConnectionContext = Context.Tag.Service<typeof TransactionConnection>;
|
|
7837
8024
|
|
|
8025
|
+
/** Turso's MVCC conflicts arrive as messages, not codes. */
|
|
8026
|
+
export declare const TURSO_TRANSIENT_MESSAGE: RegExp;
|
|
8027
|
+
|
|
7838
8028
|
/** Append one row inside the caller's transaction. Insert-only by design. */
|
|
7839
8029
|
export declare type TxnAppend = (table: string, row: Row) => Promise<void>;
|
|
7840
8030
|
|