@voltro/database 0.73.0 → 0.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4791,6 +4791,8 @@ export declare const isStagingTableName: (name: string) => boolean;
4791
4791
  */
4792
4792
  export declare const isTableReactive: (tableName: string) => boolean;
4793
4793
 
4794
+ export declare const isTransactionAbortedError: (e: unknown) => e is TransactionAbortedError;
4795
+
4794
4796
  /**
4795
4797
  * Dialect-agnostic: does this error, anywhere down its `cause` chain, carry a
4796
4798
  * contention signal any supported engine emits? The mutation runner replays
@@ -5011,6 +5013,8 @@ export declare interface MakeStoreOptions {
5011
5013
  readonly cdcConfig?: CdcConfig;
5012
5014
  }
5013
5015
 
5016
+ export declare const makeTransactionAbortTracker: (isFatal: (error: unknown) => boolean, label?: string) => TransactionAbortTracker;
5017
+
5014
5018
  export declare const many: (target: TableRef, options?: {
5015
5019
  readonly foreignKey?: string;
5016
5020
  readonly sourceKey?: string;
@@ -5210,8 +5214,17 @@ export declare interface MigrationSchemaOps {
5210
5214
  readonly onDelete?: 'cascade' | 'restrict' | 'setNull' | 'noAction';
5211
5215
  readonly onUpdate?: 'cascade' | 'restrict' | 'setNull' | 'noAction';
5212
5216
  }) => Effect.Effect<SchemaOpOutcome, unknown>;
5213
- /** Remove every row. `DELETE FROM` where the dialect has no TRUNCATE inside a unit. */
5214
- readonly truncate: (table: string) => Effect.Effect<void, unknown>;
5217
+ /**
5218
+ * Remove every row. `DELETE FROM` rather than TRUNCATE: it is a data
5219
+ * statement on every dialect, so it stays inside a transactional migration
5220
+ * where TRUNCATE (DDL on the MySQL family and SQL Server) would commit it.
5221
+ *
5222
+ * Answers `already-absent` for a table that is not there, like every
5223
+ * operation above — and deliberately does NOT go through the store, whose
5224
+ * set-based delete returns the deleted rows in order to fan out one change
5225
+ * event per row.
5226
+ */
5227
+ readonly truncate: (table: string) => Effect.Effect<SchemaOpOutcome, unknown>;
5215
5228
  /**
5216
5229
  * The Voltro way to change a table's shape in a migration: DECLARE the
5217
5230
  * table as it should be from here on, and the same planner that drives
@@ -7265,6 +7278,28 @@ export declare const runRetryingTransaction: <A>(spec: DialectTransactionSpec &
7265
7278
  readonly body: (conn: TransactionConnectionContext, attempt: number) => Promise<A>;
7266
7279
  }) => Promise<A>;
7267
7280
 
7281
+ /**
7282
+ * `DataStore.savepoint` for a transactional view — ONE algorithm for every
7283
+ * dialect; the view supplies only how to send one statement on its transaction
7284
+ * and which spelling its engine uses.
7285
+ *
7286
+ * It used to exist on the postgres view alone, while the message a caught
7287
+ * failure raises (`TransactionAbortedError`) names it as THE way to tolerate a
7288
+ * failing statement — so on three dialects, and through the store a handler
7289
+ * holds on all four, the advice pointed at a method that was `undefined`.
7290
+ *
7291
+ * `RELEASE` on success is not optional housekeeping: an unreleased savepoint
7292
+ * keeps a subtransaction alive for the rest of the transaction. SQL Server has
7293
+ * no release — a saved point simply ends with the transaction.
7294
+ */
7295
+ export declare const runSavepoint: <A>(input: {
7296
+ readonly tracker: TransactionAbortTracker;
7297
+ readonly name: string;
7298
+ /** Send one framework-authored statement on the view's transaction. */
7299
+ readonly exec: (statement: string) => Promise<unknown>;
7300
+ readonly spelling: "standard" | "mssql";
7301
+ }, fn: () => Promise<A>) => Promise<A>;
7302
+
7268
7303
  /**
7269
7304
  * THE entry point every dialect store's `transactional()` — and postgres'
7270
7305
  * `runInNamespace()` — routes through.
@@ -8778,6 +8813,50 @@ export declare const timestampMs: Schema.Schema<Date, number>;
8778
8813
  */
8779
8814
  export declare const timestampMsOrNull: Schema.Schema<Date | null, number | null>;
8780
8815
 
8816
+ /**
8817
+ * `transactional()`'s work caught a statement failure the engine had already
8818
+ * made fatal to the transaction, and returned normally. Nothing was committed —
8819
+ * not even the statements that succeeded before it.
8820
+ *
8821
+ * Raised instead of resolving, because a resolved `transactional()` is read as
8822
+ * "these writes are in the table", and here none are. The swallowed failure is
8823
+ * the `cause`.
8824
+ */
8825
+ export declare class TransactionAbortedError extends Error {
8826
+ readonly swallowed: unknown;
8827
+ readonly _tag: "TransactionAborted";
8828
+ constructor(label: string, swallowed: unknown);
8829
+ }
8830
+
8831
+ /**
8832
+ * Records, for one transactional view, the first statement failure the engine
8833
+ * made fatal to the transaction — the value `abortedBy()` reports.
8834
+ *
8835
+ * ONE implementation for every dialect view; the dialect supplies only
8836
+ * `isFatal`, because which failures end a transaction IS the dialect's (postgres:
8837
+ * any statement the server rejected; InnoDB: a deadlock, which rolls the whole
8838
+ * transaction back, while most other errors roll back only the statement).
8839
+ *
8840
+ * A failure inside `savepoint()` is not recorded: the savepoint's own rollback
8841
+ * leaves the transaction usable, which is the entire point of taking one. A
8842
+ * failure of that rollback IS recorded — the transaction is then unusable.
8843
+ */
8844
+ export declare interface TransactionAbortTracker {
8845
+ /**
8846
+ * Send one statement — given as a THUNK, so that after a fatal failure it is
8847
+ * not sent at all (a promise would already be on the wire). Records a fatal
8848
+ * rejection outside a savepoint.
8849
+ */
8850
+ track<T>(send: () => Promise<T>): Promise<T>;
8851
+ /** Run `fn` as a savepoint body: failures inside it are the savepoint's. */
8852
+ inSavepoint<A>(fn: () => Promise<A>): Promise<A>;
8853
+ /** Record a failure directly (a savepoint rollback that did not succeed). */
8854
+ record(error: unknown): void;
8855
+ abortedBy(): {
8856
+ readonly error: unknown;
8857
+ } | undefined;
8858
+ }
8859
+
8781
8860
  /**
8782
8861
  * A store's per-transaction `DataStore` view: buffers the ChangeEvents its
8783
8862
  * writes produce and drains them to the parent emitter only once the
@@ -8785,6 +8864,21 @@ export declare const timestampMsOrNull: Schema.Schema<Date | null, number | null
8785
8864
  */
8786
8865
  export declare interface TransactionalViewHandle {
8787
8866
  commitEvents(): void;
8867
+ /**
8868
+ * The first statement failure the ENGINE took as fatal to this transaction,
8869
+ * when the caller caught it and carried on. Absent on a dialect where a failed
8870
+ * statement leaves the transaction usable (mysql, sqlite): there a caught
8871
+ * failure is an ordinary, committable outcome.
8872
+ *
8873
+ * Postgres is the dialect that needs it. A failed statement aborts the whole
8874
+ * transaction; every later statement fails with 25P02, and COMMIT is then
8875
+ * executed AS A ROLLBACK — without raising. Before this existed, a work
8876
+ * callback that caught one failure and returned normally made
8877
+ * `transactional()` resolve, and nothing it wrote was in the table.
8878
+ */
8879
+ abortedBy?(): {
8880
+ readonly error: unknown;
8881
+ } | undefined;
8788
8882
  }
8789
8883
 
8790
8884
  /**