@voltro/database 0.70.0 → 0.71.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.
@@ -800,11 +800,11 @@ var me = () => new s({
800
800
  }, qe = (e) => e === "sqlite" || e === "turso", Je = (e) => e === "mysql" || e === "mariadb", R = (e, t) => {
801
801
  switch (t) {
802
802
  case "mysql":
803
- case "mariadb": return `\`${e}\``;
804
- case "mssql": return `[${e}]`;
803
+ case "mariadb": return `\`${e.replace(/`/g, "``")}\``;
804
+ case "mssql": return `[${e.replace(/\]/g, "]]")}]`;
805
805
  case "postgres":
806
806
  case "sqlite":
807
- case "turso": return `"${e}"`;
807
+ case "turso": return `"${e.replace(/"/g, "\"\"")}"`;
808
808
  }
809
809
  }, Ye = 1e4, z = Symbol.for("@voltro/database/tableRegistry"), B = globalThis, V = B[z] ?? (B[z] = /* @__PURE__ */ new Map()), H = (e) => {
810
810
  let t = V.get(e.tableName);
package/dist/index.d.ts CHANGED
@@ -1825,6 +1825,9 @@ export declare const columnsPerRow: (rows: ReadonlyArray<Record<string, unknown>
1825
1825
 
1826
1826
  export declare type ColumnType = 'id' | 'text' | 'integer' | 'real' | 'decimal' | 'bigint' | 'boolean' | 'timestamp' | 'date' | 'json' | 'bytes' | 'reference' | 'vector' | 'enum' | 'array' | 'interval' | 'raw';
1827
1827
 
1828
+ /** Exact comparison of fixed-point decimal strings, without a floating-point conversion. */
1829
+ export declare const compareDecimal: (left: unknown, right: unknown) => number | null;
1830
+
1828
1831
  /**
1829
1832
  * Try to compile a `QueryDescriptor` with `eager` populated into a
1830
1833
  * single-roundtrip JSON-agg query for the given dialect.
@@ -2396,20 +2399,15 @@ export declare interface DataStore {
2396
2399
  * `insertIgnore`, plus the one thing it cannot report: whether the row was
2397
2400
  * INSERTED or already there.
2398
2401
  *
2399
- * On the ignore path `insertIgnore` returns the existing row, which looks
2400
- * exactly like a freshly inserted one — so a loop that plants missing rows
2401
- * counts every row it visited as planted, unless it reads the destination
2402
- * first. Same shape and same answer as `upsertWithOutcome`: the wrapper
2403
- * mints the id before the statement, the ignore path hands back the EXISTING
2404
- * row's id, and two ids that differ are the answer. Where that comparison
2405
- * cannot decide (the caller supplied the id, or the id is database-assigned)
2406
- * the destination is read first, so `'inserted'` is exact, never a guess.
2407
- *
2408
- * Optional and wrapper-provided for the same reason as `upsertWithOutcome`:
2409
- * present on `ctx.store`, not required of a hand-written `DataStore`. The
2410
- * typed helper is `insertIgnoreRowOutcome`.
2402
+ * The store's actual insert decision supplies the outcome, including for
2403
+ * caller-supplied and database-generated IDs. A pre-read or comparison of
2404
+ * IDs cannot establish which concurrent caller inserted. Every raw store,
2405
+ * namespace view and transaction view implements this method; wrappers
2406
+ * preserve its outcome while encoding/decoding the row. Inside a transaction
2407
+ * the result is provisional until commit. The typed helper is
2408
+ * `insertIgnoreRowOutcome`.
2411
2409
  */
2412
- insertIgnoreWithOutcome?(table: string, row: Row, options: {
2410
+ insertIgnoreWithOutcome(table: string, row: Row, options: {
2413
2411
  conflictColumns: ReadonlyArray<string>;
2414
2412
  }): Promise<InsertIgnoreResult>;
2415
2413
  /**
@@ -2417,7 +2415,8 @@ export declare interface DataStore {
2417
2415
  * made via `work`'s store reference (passed as argument) are:
2418
2416
  *
2419
2417
  * - atomic — the dialect's native BEGIN/COMMIT/ROLLBACK wraps the
2420
- * writes; the memory store serialises trivially.
2418
+ * writes; memory validates snapshot read/write-table revisions before
2419
+ * committing and retries conflicting attempts with a fresh snapshot.
2421
2420
  * - delta-deferred — ChangeEvents queue inside the transaction and
2422
2421
  * are emitted ONLY after a successful commit. A throw triggers
2423
2422
  * rollback AND drops every queued event so no subscriber ever
@@ -2425,6 +2424,10 @@ export declare interface DataStore {
2425
2424
  *
2426
2425
  * Reads (`query()`) inside the transaction see the in-flight write
2427
2426
  * set (read-your-own-writes within the transaction).
2427
+ * Transient contention can replay the whole callback (at most four attempts,
2428
+ * exponential delay starting at 10 ms). Do not perform external side effects
2429
+ * in the callback. Memory validation is table-granular and process-local;
2430
+ * `forUpdate` does not acquire a blocking row lock there.
2428
2431
  *
2429
2432
  * `transactional()` MUST NOT be nested — nested invocations throw to
2430
2433
  * surface design mistakes (transactions are atomic units, not
@@ -3388,7 +3391,7 @@ declare type EmptyMerge = unknown;
3388
3391
  export declare const encodeFieldValue: (cipher: FieldCipher, value: unknown, binding?: FieldBinding) => string;
3389
3392
 
3390
3393
  /**
3391
- * Serialize a row's json()/array() cells to JSON strings so they can be
3394
+ * Serialize selected json()/array()/vector() cells to JSON strings so they can be
3392
3395
  * bound as scalar SQL parameters. Symmetric to `decodeRowsFromSchema`.
3393
3396
  * No-op for tables with no json/array columns (cost: one map build +
3394
3397
  * a per-cell type lookup). Unknown tables pass through unchanged.
@@ -3458,7 +3461,9 @@ export declare const eq: <RowOf = Record<string, unknown>, K extends keyof RowOf
3458
3461
  * explicit `ESCAPE '\'` clause at the call site. */
3459
3462
  export declare const escapeLike: (value: string) => string;
3460
3463
 
3461
- export declare const evaluatePredicate: (predicate: Predicate, row: Row | null, subqueries?: SubqueryResults | null) => boolean;
3464
+ export declare const evaluatePredicate: (predicate: Predicate, row: Row | null, subqueries?: SubqueryResults | null, columns?: Readonly<Record<string, {
3465
+ readonly type: string;
3466
+ }>>) => boolean;
3462
3467
 
3463
3468
  /** `EXCEPT` — rows in the FIRST input not present in any subsequent input. */
3464
3469
  export declare const except: (...queries: ReadonlyArray<QueryWithDescriptorAny>) => Query<Row, string>;
@@ -4023,14 +4028,14 @@ export declare interface IndexKindOptions {
4023
4028
  * - `'inner'` → `vector_ip_ops` (negative inner product)
4024
4029
  * The opclass MUST match the metric the query orders by, or the
4025
4030
  * index can't accelerate the search. Set `opclass` directly only to
4026
- * override the mapping (e.g. `halfvec_cosine_ops`).
4031
+ * override the mapping. Half-precision columns select `halfvec_*` automatically.
4027
4032
  */
4028
4033
  readonly distance?: VectorDistance;
4029
4034
  /**
4030
4035
  * pgvector opclass token spliced into `USING hnsw (col <opclass>)`.
4031
- * When unset, derived from `distance` (default `vector_cosine_ops`).
4032
- * Set explicitly to override (e.g. `'halfvec_cosine_ops'` for a
4033
- * `vector(n, { precision: 'half' })` column).
4036
+ * When unset, derived from `distance` and the column's precision
4037
+ * (default `vector_cosine_ops`, or `halfvec_cosine_ops` for half precision).
4038
+ * An explicit override is an unquoted, optionally schema-qualified identifier.
4034
4039
  */
4035
4040
  readonly opclass?: string;
4036
4041
  };
@@ -4103,19 +4108,16 @@ export declare interface InsertIgnoreResult {
4103
4108
  * `insertIgnore`, plus whether the row was INSERTED or was already there.
4104
4109
  *
4105
4110
  * `insertIgnore` returns the existing row on the ignore path, and that row is
4106
- * indistinguishable from one it just wrote — so a loop that plants missing
4107
- * rows reports every row it visited as planted unless it reads first. The
4108
- * store knows the answer the same way `upsertRowOutcome` does: the id it
4109
- * minted before the statement is not the id the ignore path hands back.
4111
+ * indistinguishable from one it just wrote. The native store's insert
4112
+ * decision supplies the outcome; wrappers preserve it without a pre-read.
4110
4113
  *
4111
4114
  * const { row, outcome } = await insertIgnoreRowOutcome(ctx.store, actors, actor, {
4112
4115
  * conflictColumns: ['id'],
4113
4116
  * })
4114
4117
  * if (outcome === 'inserted') planted++
4115
4118
  *
4116
- * `'inserted'` is never a stand-in for "could not tell". Where the id cannot
4117
- * decide it — the caller supplied one, or the table's id is database-assigned
4118
- * — the store reads the destination first and answers exactly.
4119
+ * Caller-supplied and database-assigned IDs obey the same contract. Inside
4120
+ * a transaction the decision becomes durable only when that transaction commits.
4119
4121
  */
4120
4122
  export declare const insertIgnoreRowOutcome: <T extends AnyTable>(store: TypedInsertIgnoreOutcomeStore, table: T, row: InferInsertRow<T>, options: {
4121
4123
  readonly conflictColumns: ReadonlyArray<keyof InferRow<T> & string>;
@@ -6064,9 +6066,8 @@ declare interface QueryWithDescriptorAny {
6064
6066
  * in ANSI_QUOTES mode)
6065
6067
  * - mssql: `[name]` (T-SQL bracketed identifier)
6066
6068
  *
6067
- * Identifier names in the schema DSL are restricted to
6068
- * `[a-zA-Z][a-zA-Z0-9_]*`, so the inner quote character never needs
6069
- * escaping — but the dialect MUST match the engine to avoid syntax errors.
6069
+ * Catalog-derived identifiers can contain quote characters even when the
6070
+ * schema DSL restricts its own names. Escape them at this shared boundary.
6070
6071
  */
6071
6072
  export declare const quoteIdent: (name: string, dialect: DialectId) => string;
6072
6073
 
@@ -8197,6 +8198,9 @@ export declare interface TransactionalViewHandle {
8197
8198
  */
8198
8199
  export declare type TransactionConnectionContext = Context.Tag.Service<typeof TransactionConnection>;
8199
8200
 
8201
+ /** Shared bounded contention policy, including stores without a SQL connection. */
8202
+ export declare const transactionRetrySchedule: (isRetryable: (error: unknown) => boolean) => Schedule.Schedule<number, unknown, never>;
8203
+
8200
8204
  /** Turso's MVCC conflicts arrive as messages, not codes. */
8201
8205
  export declare const TURSO_TRANSIENT_MESSAGE: RegExp;
8202
8206
 
@@ -8222,7 +8226,7 @@ export declare interface TxnRecorderPort {
8222
8226
 
8223
8227
  /** The minimal store surface `insertIgnoreRowOutcome` needs. */
8224
8228
  export declare interface TypedInsertIgnoreOutcomeStore {
8225
- readonly insertIgnoreWithOutcome?: (table: string, row: Row, options: {
8229
+ readonly insertIgnoreWithOutcome: (table: string, row: Row, options: {
8226
8230
  readonly conflictColumns: ReadonlyArray<string>;
8227
8231
  }) => Promise<{
8228
8232
  readonly row: Row;