@voltro/database 0.83.1 → 0.84.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
@@ -1637,6 +1637,14 @@ export declare interface ColumnDefinition<TsType, Type extends ColumnType = Colu
1637
1637
  * column is just `bytes` with server-merge semantics.
1638
1638
  */
1639
1639
  readonly crdtManaged?: boolean;
1640
+ /**
1641
+ * End-to-end-sealed CRDT marker, set by `crdtSealed()`. The column holds an
1642
+ * append-only LOG of encrypted CRDT updates the server cannot read: the
1643
+ * write path appends an incoming frame (or applies a client's snapshot
1644
+ * frame) and never decodes or merges — clients holding the key do. Same
1645
+ * `bytes` storage and zero DDL churn as `crdtManaged`.
1646
+ */
1647
+ readonly crdtSealed?: boolean;
1640
1648
  /**
1641
1649
  * Optimistic-concurrency marker, set by `.version()`.
1642
1650
  *
@@ -1694,6 +1702,7 @@ export declare interface ColumnDefinition<TsType, Type extends ColumnType = Colu
1694
1702
  * MUST be `<= precision`. See {@link ColumnDefinition.precision}.
1695
1703
  */
1696
1704
  readonly scale?: number;
1705
+ /* Excluded from this release type: sqliteDecimalEncoding */
1697
1706
  /**
1698
1707
  * Vector dimensionality. Populated only when `type === 'vector'`.
1699
1708
  * The migration emitter uses it to size the column DDL —
@@ -1965,6 +1974,10 @@ declare interface ColumnSnapshot {
1965
1974
  */
1966
1975
  readonly precision?: number;
1967
1976
  readonly scale?: number;
1977
+ /** Physical SQLite-family exact-decimal representation. Absent on ordinary
1978
+ * NUMERIC columns. The marker is observable schema state, not a DSL hint:
1979
+ * changing it requires data conversion, never a plain SQL type cast. */
1980
+ readonly sqliteDecimalEncoding?: 'sortable-v1';
1968
1981
  /**
1969
1982
  * Id-generation scheme for `type: 'id'` columns. Mirrors
1970
1983
  * `ColumnDefinition.idScheme.kind` so the applier can tell a numeric
@@ -2157,24 +2170,8 @@ export declare const compileEagerJson: (descriptor: QueryDescriptor, sql: SqlCon
2157
2170
  */
2158
2171
  export declare const compileJsonPatch: (sql: SqlConstructor, dialect: DialectId, path: string, value: unknown, source?: Statement.Fragment) => Statement.Fragment;
2159
2172
 
2160
- /**
2161
- * Lower a `Predicate` AST to a SQL `Fragment` suitable for use inside a
2162
- * WHERE clause. Identifiers are quoted via `sql(col)`; values flow through
2163
- * `sql\`${v}\`` as parameters — no string concatenation, no injection.
2164
- */
2165
- export declare const compilePredicate: (predicate: Predicate, sql: SqlConstructor, namespace?: QueryNamespace,
2166
- /**
2167
- * The table this predicate filters, when the caller knows it. Supplied so a
2168
- * leaf's VALUE can be coerced to the column's shape — `eq('capturedAt',
2169
- * epochMs)` against a `timestamp()` column otherwise compiles to
2170
- * `WHERE capturedAt = 1767916800000` and matches nothing, silently. The write
2171
- * path has always encoded; this closes the asymmetry.
2172
- *
2173
- * Optional because `compilePredicate` is also called for JOIN conditions and
2174
- * by callers that hold only the AST. Absent → no coercion, i.e. exactly the
2175
- * previous behaviour.
2176
- */
2177
- table?: string) => Statement.Fragment;
2173
+ /** Compile a standalone predicate; SELECT supplies its own lexical CTE scope. */
2174
+ export declare const compilePredicate: (predicate: Predicate, sql: SqlConstructor, namespace?: QueryNamespace, table?: string) => Statement.Fragment;
2178
2175
 
2179
2176
  /**
2180
2177
  * Rebind a captured {@link RawSqlFragment} onto a live `sql`
@@ -2193,6 +2190,7 @@ export declare const compileRawFragment: <Row extends object = Record<string, un
2193
2190
  * Shared by SELECT and DML RETURNING; other dialects retain native projection. */
2194
2191
  export declare const compileRowProjection: (table: string, sql: SqlConstructor, projection?: ReadonlyArray<string>) => Statement.Fragment;
2195
2192
 
2193
+ /** Compile a public query descriptor; recursive CTE terms use their SQL scope. */
2196
2194
  export declare const compileSelect: <Row extends object>(descriptor: QueryDescriptor, sql: SqlConstructor, namespace?: QueryNamespace) => Statement.Statement<Row>;
2197
2195
 
2198
2196
  /** Compose the durable identity written to `_voltro_cdcout_claims.changeKey`. */
@@ -2413,6 +2411,22 @@ export declare const count: (alias?: string) => AggregateColumn<number>;
2413
2411
 
2414
2412
  export declare const countDistinct: (column: string, alias?: string) => AggregateColumn<number>;
2415
2413
 
2414
+ /**
2415
+ * A CONVERGING COUNTER column — likes, stock reservations, votes, a running
2416
+ * total — that any number of clients increment and decrement concurrently,
2417
+ * offline too, without losing a single step. A plain `integer()` column read,
2418
+ * incremented and written back by two clients at once keeps one of the two
2419
+ * increments; this keeps both.
2420
+ *
2421
+ * Each writer (one client session) accumulates its own increments and
2422
+ * decrements under its own key, and the value is the sum over all writers, so
2423
+ * concurrent steps commute. Storage, nullability and the authoritative server
2424
+ * merge are those of `crdtText()` — the column stores the encoded CRDT state
2425
+ * as `bytes`. Read the number with `@voltro/local-first`'s
2426
+ * `crdtCounterValue(state)`; bind it in React with `useCrdtCounter`.
2427
+ */
2428
+ export declare const crdtCounter: () => ColumnBuilder<Uint8Array | null, "bytes">;
2429
+
2416
2430
  /**
2417
2431
  * A whole collaborative DOCUMENT as a column — rich text, nested maps/arrays,
2418
2432
  * whatever the CRDT backend's document model holds. `crdtText()` is the
@@ -2450,6 +2464,22 @@ export declare const crdtManagedColumns: (table: TableLike) => ReadonlyArray<str
2450
2464
  * folds and the capture paths (undo, row history) exclude. */
2451
2465
  export declare const crdtManagedColumnsOf: (table: TableLike) => ReadonlyArray<string>;
2452
2466
 
2467
+ /**
2468
+ * An END-TO-END ENCRYPTED collaborative column: clients encrypt every CRDT
2469
+ * update with a key the server never sees (AES-GCM, `@voltro/local-first`'s
2470
+ * `seal` option on `useCrdtText` / `useCrdtDoc` / `useCrdtCounter`), and the
2471
+ * server stores an append-only log of the sealed frames. It cannot read,
2472
+ * validate or merge the content — clients decrypt and merge locally, which is
2473
+ * why the convergence still holds — and a client's snapshot frame compacts the
2474
+ * log without losing a frame appended concurrently.
2475
+ *
2476
+ * Trade-offs, by construction: `crdt.validate` and server-side restore cannot
2477
+ * see the content, and the downstream lane ships the log, not an increment.
2478
+ * The size limits still apply. Choose it for content the operator must not be
2479
+ * able to read.
2480
+ */
2481
+ export declare const crdtSealed: () => ColumnBuilder<Uint8Array | null, "bytes">;
2482
+
2453
2483
  /**
2454
2484
  * CRDT-managed text column — a field whose value is a CONFLICT-FREE replicated
2455
2485
  * text document rather than a plain string. Two clients editing it at the same
@@ -3122,19 +3152,20 @@ export declare interface DbOpSample {
3122
3152
  }
3123
3153
 
3124
3154
  /**
3125
- * Fixed-point exact-decimal column — money, tax rates, anything where
3126
- * floating-point rounding is unacceptable. Emits `NUMERIC(precision, scale)`
3127
- * on postgres and `DECIMAL(precision, scale)` on mysql / mariadb / mssql;
3128
- * sqlite / turso have no fixed-point type, so it's `NUMERIC` affinity storing
3129
- * the value as text.
3155
+ * Fixed-point exact-decimal column for money, tax rates and other values
3156
+ * that must not pass through floating-point arithmetic. Emits
3157
+ * `NUMERIC(precision, scale)` on postgres and `DECIMAL(precision, scale)`
3158
+ * on mysql / mariadb / mssql. SQLite, native Turso and libSQL use exact,
3159
+ * order-preserving encoded TEXT storage, including declared defaults.
3160
+ * Existing NUMERIC columns require a reviewed offline conversion.
3130
3161
  *
3131
- * The row type is **`string`**, NOT `number`, on purpose: a JS `number` is an
3132
- * IEEE-754 double and silently loses precision past ~15-17 significant digits
3133
- * (`0.1 + 0.2 !== 0.3`), so a `DECIMAL(38,9)` value round-tripped through a JS
3134
- * number would corrupt. The drivers already hand these back as strings
3135
- * (node-postgres, mysql2), and the row decoder coerces the mssql numeric back
3136
- * to a string, so the value is lossless end-to-end. Do arithmetic with a
3137
- * decimal library (or in SQL), not JS `+`.
3162
+ * The row type is **`string`**, NOT `number`: JavaScript numbers lose
3163
+ * precision beyond roughly 15–17 significant digits. SQLite-family stores
3164
+ * encode writes and decode reads at the declared scale. MSSQL's driver
3165
+ * can already have rounded large values before string decoding; use a
3166
+ * text projection for values beyond the driver's numeric precision.
3167
+ * Use a decimal library or supported typed query-builder operations for
3168
+ * arithmetic. Raw SQL must not treat encoded TEXT as a decimal number.
3138
3169
  *
3139
3170
  * ```ts
3140
3171
  * price: decimal(12, 2), // up to 9_999_999_999.99
@@ -3226,8 +3257,11 @@ export declare const decodeRowsForTable: <T extends Record<string, unknown>>(row
3226
3257
  * Unknown tables (not registered) pass through unchanged — this is
3227
3258
  * the case for the framework's internal cluster-runtime tables and
3228
3259
  * for ad-hoc raw-SQL paths that bypass the typed-table mechanism.
3260
+ * Pass the SELECT descriptor when decoding a compileSelect result: explicitly
3261
+ * encoded SQLite queries return logical projections, not physical table rows.
3262
+ * Omit it for DML RETURNING, whose cells retain their storage representation.
3229
3263
  */
3230
- export declare const decodeRowsFromSchema: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, tableName: string, dialect: DecoderDialectId) => ReadonlyArray<T>;
3264
+ export declare const decodeRowsFromSchema: <T extends Record<string, unknown>>(rows: ReadonlyArray<T>, tableName: string, dialect: DecoderDialectId, query?: QueryDescriptor) => ReadonlyArray<T>;
3231
3265
 
3232
3266
  /**
3233
3267
  * Decrypt every `.encrypted()` column's value on read. A value that
@@ -3752,8 +3786,8 @@ declare type EmptyMerge = unknown;
3752
3786
  export declare const encodeFieldValue: (cipher: FieldCipher, value: unknown, binding?: FieldBinding) => string;
3753
3787
 
3754
3788
  /**
3755
- * Serialize selected json()/array()/vector() cells to JSON strings so they can be
3756
- * bound as scalar SQL parameters. Symmetric to `decodeRowsFromSchema`.
3789
+ * Serialize selected JSON-like cells and explicitly marked decimal storage
3790
+ * values so they can be bound as scalar SQL parameters. Symmetric to `decodeRowsFromSchema`.
3757
3791
  * No-op for tables with no json/array columns (cost: one map build +
3758
3792
  * a per-cell type lookup). Unknown tables pass through unchanged.
3759
3793
  */