@voltro/database 0.20.2 → 0.22.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 +398 -0
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/dist/{fileBased-Dfuv6JWP.js → fileBased-CDnutVVk.js} +19 -0
- package/dist/index.d.ts +121 -1
- package/dist/index.js +488 -444
- package/dist/sql.d.ts +96 -30
- package/dist/sql.js +600 -450
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -173,9 +173,10 @@ export declare const attachEagerLoads: (rows: ReadonlyArray<Row_2>, spec: WithSp
|
|
|
173
173
|
* time the async-local scope is gone. Stamping at creation is what makes the
|
|
174
174
|
* transactional path carry identity at all.
|
|
175
175
|
*/
|
|
176
|
-
export declare const attributionFields: () => {
|
|
176
|
+
export declare const attributionFields: (explicit?: WriteAttribution | undefined) => {
|
|
177
177
|
traceId?: string;
|
|
178
178
|
subjectId?: string | null;
|
|
179
|
+
procedure?: string;
|
|
179
180
|
};
|
|
180
181
|
|
|
181
182
|
/** The write's identity, as both sides can compute it. NOT the row image: the
|
|
@@ -245,6 +246,12 @@ export declare interface BackfillSpec<TsType = unknown> {
|
|
|
245
246
|
readonly sleepMs?: number;
|
|
246
247
|
}
|
|
247
248
|
|
|
249
|
+
/** Mark a non-transactional write to `table` as started. Pairs with
|
|
250
|
+
* `endLocalWrite` in a `finally` — an unpaired begin holds that table's echoes
|
|
251
|
+
* until `DEFER_BOUND_MS`, which is why the pairing is the store's job and not
|
|
252
|
+
* the caller's. */
|
|
253
|
+
export declare const beginLocalWrite: (table: string) => void;
|
|
254
|
+
|
|
248
255
|
/**
|
|
249
256
|
* 64-bit integer column — `BIGINT` on postgres / mysql / mariadb / mssql,
|
|
250
257
|
* `INTEGER` (which is 64-bit) on sqlite / turso. Use for values that can
|
|
@@ -515,6 +522,17 @@ export declare type ChangeEvent = {
|
|
|
515
522
|
* `undefined` = no request context at all. The two are different facts.
|
|
516
523
|
*/
|
|
517
524
|
readonly subjectId?: string | null;
|
|
525
|
+
/**
|
|
526
|
+
* The rpc tag of the call that caused this write (`teams.removeSubTeamMember`).
|
|
527
|
+
*
|
|
528
|
+
* `traceId` says WHICH call; this says WHAT CALL IT WAS. The difference
|
|
529
|
+
* matters to anything rendering history for a human: a row diff carries no
|
|
530
|
+
* intent, and the same delete on a join table is a member removal, a cascade,
|
|
531
|
+
* or an expiry depending only on who asked. Absent for a write with no
|
|
532
|
+
* procedure behind it (seed, startup, migration, schedule) — same meaning as
|
|
533
|
+
* an absent `traceId`.
|
|
534
|
+
*/
|
|
535
|
+
readonly procedure?: string;
|
|
518
536
|
};
|
|
519
537
|
|
|
520
538
|
/**
|
|
@@ -2111,6 +2129,11 @@ export declare const encryptedColumnsOf: (table: TableLike) => ReadonlyArray<str
|
|
|
2111
2129
|
*/
|
|
2112
2130
|
export declare const encryptFieldsForWrite: (row: Row, table: TableLike | undefined, cipher: FieldCipher | undefined) => Row;
|
|
2113
2131
|
|
|
2132
|
+
/** Mark it finished — AFTER its `routeEvent` has registered, not after the
|
|
2133
|
+
* statement. That is the whole point: the window being closed is exactly the
|
|
2134
|
+
* gap between the committing statement and the registration. */
|
|
2135
|
+
export declare const endLocalWrite: (table: string) => void;
|
|
2136
|
+
|
|
2114
2137
|
/**
|
|
2115
2138
|
* Enforce the storage-cost caps: evict live branches past their TTL, and report
|
|
2116
2139
|
* whether a new branch would exceed `maxBranches` (counting only what survives
|
|
@@ -4169,6 +4192,10 @@ export declare interface RecordedWrite {
|
|
|
4169
4192
|
/** Request identity, when the write had a request behind it. */
|
|
4170
4193
|
readonly traceId?: string | undefined;
|
|
4171
4194
|
readonly subjectId?: string | null | undefined;
|
|
4195
|
+
/** The rpc tag of the call doing the writing. Same meaning and same absence
|
|
4196
|
+
* rules as `traceId`; carried so a transactional write records WHICH CALL
|
|
4197
|
+
* changed a row, not only which trace. */
|
|
4198
|
+
readonly procedure?: string | undefined;
|
|
4172
4199
|
}
|
|
4173
4200
|
|
|
4174
4201
|
/**
|
|
@@ -4401,6 +4428,18 @@ declare type Resolve<T> = {
|
|
|
4401
4428
|
*/
|
|
4402
4429
|
export declare const resolveBranchMechanism: (opts: BranchMechanismOptions) => BranchMechanism;
|
|
4403
4430
|
|
|
4431
|
+
/**
|
|
4432
|
+
* Answer a transport echo with the attribution of the local write that produced
|
|
4433
|
+
* it, or with `undefined` when the write came from another replica.
|
|
4434
|
+
*
|
|
4435
|
+
* `deliver` is called EXACTLY once — synchronously in the common case, and on a
|
|
4436
|
+
* later turn only when a local write to the same table is mid-registration.
|
|
4437
|
+
* Stores must emit through this rather than calling `claimPendingAttribution`
|
|
4438
|
+
* themselves: the claim is the easy half, and the two dialect stores had a
|
|
4439
|
+
* hand-written copy of it each, which is how a decision drifts.
|
|
4440
|
+
*/
|
|
4441
|
+
export declare const resolveEchoAttribution: (table: string, op: string, primaryKey: unknown, deliver: (attribution: WriteAttribution | undefined) => void) => void;
|
|
4442
|
+
|
|
4404
4443
|
/**
|
|
4405
4444
|
* Resolve a `.fullTextIndex(name, ...)` declaration off the source
|
|
4406
4445
|
* table so `.matching()` can stamp the covered columns + config onto
|
|
@@ -4977,6 +5016,23 @@ export declare interface Table<Name extends string, Fields extends Record<string
|
|
|
4977
5016
|
readonly appliedUniques: ReadonlyArray<TableUnique>;
|
|
4978
5017
|
readonly appliedFullText: ReadonlyArray<TableFullTextIndex>;
|
|
4979
5018
|
readonly appliedChecks: ReadonlyArray<TableCheck>;
|
|
5019
|
+
/**
|
|
5020
|
+
* The name this table used to have, set by `.renamedFrom('old_name')`.
|
|
5021
|
+
* Named apart from the METHOD that sets it — one interface cannot carry both.
|
|
5022
|
+
*
|
|
5023
|
+
* The table-level twin of a column's `.renamedFrom()`, and it exists for the
|
|
5024
|
+
* same reason: a rename and a drop+create are structurally identical to a
|
|
5025
|
+
* differ (old table gone, new table present) and mean completely different
|
|
5026
|
+
* things. Without the marker the planner has to assume drop + create, which
|
|
5027
|
+
* for a TABLE is data loss, so it refuses — and the rename can only be done
|
|
5028
|
+
* by hand.
|
|
5029
|
+
*
|
|
5030
|
+
* A chained method, matching a column's `.renamedFrom()` — the two mean the
|
|
5031
|
+
* same thing one level apart, so they read the same. It survives every
|
|
5032
|
+
* subsequent `.index(...)` / `.with(...)` because each rebuild spreads its
|
|
5033
|
+
* options through.
|
|
5034
|
+
*/
|
|
5035
|
+
readonly previousTableName?: string;
|
|
4980
5036
|
/**
|
|
4981
5037
|
* Composite PRIMARY KEY column set, declared via `.primaryKey(['a','b'])`.
|
|
4982
5038
|
* When set it REPLACES the single-column `id()` PK assumption: no column
|
|
@@ -5313,6 +5369,23 @@ export declare interface Table<Name extends string, Fields extends Record<string
|
|
|
5313
5369
|
* says so at boot.
|
|
5314
5370
|
*/
|
|
5315
5371
|
nonReactive: () => Table<Name, Fields, false, IxNames>;
|
|
5372
|
+
/**
|
|
5373
|
+
* Declare the name this table used to have, so the planner folds what would
|
|
5374
|
+
* otherwise be DROP + CREATE — the loss of every row — into an in-place
|
|
5375
|
+
* `rename-table`.
|
|
5376
|
+
*
|
|
5377
|
+
* Deliberately the SAME SHAPE as a column's `.renamedFrom()`, because the two
|
|
5378
|
+
* mean the same thing one level apart, and a reader who learned one will reach
|
|
5379
|
+
* for the other. It first shipped as a third argument to `table()`; that made
|
|
5380
|
+
* the one API in this family that had to be looked up.
|
|
5381
|
+
*
|
|
5382
|
+
* export const notes = table('archive_notes', { … }).renamedFrom('notes')
|
|
5383
|
+
*
|
|
5384
|
+
* Drop the marker once the rename has been applied in every environment. A
|
|
5385
|
+
* marker whose old table is absent is a silent no-op, so it can sit in source
|
|
5386
|
+
* across a staged rollout.
|
|
5387
|
+
*/
|
|
5388
|
+
renamedFrom: (oldName: string) => Table<Name, Fields, Reactive, IxNames>;
|
|
5316
5389
|
}
|
|
5317
5390
|
|
|
5318
5391
|
export declare const table: <const Name extends string, const Input extends FieldsInput>(name: Name, fields: Input) => Table<Name, FieldDefinitions<Input>, true, never>;
|
|
@@ -5962,6 +6035,34 @@ export declare interface WindowSpec {
|
|
|
5962
6035
|
}>;
|
|
5963
6036
|
}
|
|
5964
6037
|
|
|
6038
|
+
/**
|
|
6039
|
+
* Capture the attribution ONCE, at a point that is synchronously inside the
|
|
6040
|
+
* request, and hand it to `fn` — while ALSO re-entering the async-local scope for
|
|
6041
|
+
* everything `fn` reaches that has not been threaded.
|
|
6042
|
+
*
|
|
6043
|
+
* WHY BOTH. Re-entering the scope alone is not enough, and that is measured
|
|
6044
|
+
* rather than assumed. `AsyncLocalStorage` propagates through continuations the
|
|
6045
|
+
* current context CREATES; a continuation scheduled by ANOTHER context — which is
|
|
6046
|
+
* exactly what a connection-pool handoff does when an acquisition queues — resumes
|
|
6047
|
+
* with whatever store that other context had. So a `routeEvent` running after
|
|
6048
|
+
* `await runPromise(...)` can read an EMPTY scope under contention, and the write
|
|
6049
|
+
* lands with `traceId`/`subjectId` NULL. NULL is a legal value there meaning "no
|
|
6050
|
+
* request behind this write", so the result does not look like a defect; it looks
|
|
6051
|
+
* like a schedule. In a compliance trail that asymmetry is the whole problem.
|
|
6052
|
+
*
|
|
6053
|
+
* A consumer could not reproduce it across 2700 writes at 96-way concurrency with
|
|
6054
|
+
* every core saturated — which is good evidence the window is narrow at their load
|
|
6055
|
+
* and no evidence at all that it is closed. Their own framing is why this is being
|
|
6056
|
+
* closed structurally rather than left: *"impossible beats unlikely when the
|
|
6057
|
+
* failure is invisible."*
|
|
6058
|
+
*
|
|
6059
|
+
* The captured value is passed EXPLICITLY down the write path; the re-entered
|
|
6060
|
+
* scope is the fallback for any path not yet threaded. That ordering is deliberate
|
|
6061
|
+
* — a site that has not been threaded behaves exactly as it does today rather than
|
|
6062
|
+
* worse, so the threading can be verified site by site instead of all at once.
|
|
6063
|
+
*/
|
|
6064
|
+
export declare const withCapturedAttribution: <T>(fn: (attribution: WriteAttribution | undefined) => T) => T;
|
|
6065
|
+
|
|
5965
6066
|
/** Tree of relations to eager-load. */
|
|
5966
6067
|
export declare type WithSpec = Readonly<Record<string, true | EagerLoadSpec>>;
|
|
5967
6068
|
|
|
@@ -5976,6 +6077,25 @@ export declare type WithSpec = Readonly<Record<string, true | EagerLoadSpec>>;
|
|
|
5976
6077
|
*/
|
|
5977
6078
|
export declare interface WriteAttribution {
|
|
5978
6079
|
readonly traceId?: string;
|
|
6080
|
+
/**
|
|
6081
|
+
* The rpc tag of the call doing the writing (`teams.removeSubTeamMember`).
|
|
6082
|
+
*
|
|
6083
|
+
* WHY IT IS HERE AND NOT DERIVED. A row change carries no intent. The same
|
|
6084
|
+
* DELETE on `userTeams` is a member being removed, a team being deleted, a
|
|
6085
|
+
* user being deleted, or a membership expiring — and the before/after diff
|
|
6086
|
+
* cannot tell those apart, because the difference is not in the data. A
|
|
6087
|
+
* consumer building an audit UI hit exactly this: `_voltro_row_history` could
|
|
6088
|
+
* say "row X of userTeams changed" and show the JSON, and could not say "Anna
|
|
6089
|
+
* removed Bernd from the Frontend sub-team".
|
|
6090
|
+
*
|
|
6091
|
+
* The tag is the missing anchor, and it is already known at the boundary that
|
|
6092
|
+
* establishes this attribution, so it costs one field rather than an app-side
|
|
6093
|
+
* hook that would have to reconstruct intent from shape.
|
|
6094
|
+
*
|
|
6095
|
+
* Absent for a write with no procedure behind it — a seed, a `*.startup.tsx`,
|
|
6096
|
+
* a migration. Same meaning as an absent `traceId`.
|
|
6097
|
+
*/
|
|
6098
|
+
readonly procedure?: string;
|
|
5979
6099
|
/** `null` is meaningful: a resolved subject with no acting user (an
|
|
5980
6100
|
* anonymous or system call), as distinct from `undefined` = no request. */
|
|
5981
6101
|
readonly subjectId?: string | null;
|