@voltro/database 0.52.0 → 0.54.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
@@ -1987,6 +1987,30 @@ export declare const count: (alias?: string) => AggregateColumn;
1987
1987
 
1988
1988
  export declare const countDistinct: (column: string, alias?: string) => AggregateColumn;
1989
1989
 
1990
+ /**
1991
+ * A whole collaborative DOCUMENT as a column — rich text, nested maps/arrays,
1992
+ * whatever the CRDT backend's document model holds. `crdtText()` is the
1993
+ * single-plain-text specialisation; this is the general form an editor
1994
+ * binding (Tiptap over Yjs) edits.
1995
+ *
1996
+ * Storage, nullability and the authoritative server merge are IDENTICAL to
1997
+ * `crdtText()` — the merge primitive (`Y.mergeUpdates`) is doc-agnostic, so
1998
+ * the same write-path fold converges whole documents. What differs is intent
1999
+ * and the exposure rules:
2000
+ *
2001
+ * - `.serverOnly()` THROWS at declaration (a doc clients write but never read
2002
+ * cannot be collaborated on);
2003
+ * - `.encrypted()` is allowed but makes the column ONLINE-ONLY for
2004
+ * local-first purposes: the client mirror refuses to persist decrypted
2005
+ * content on the device (see `@voltro/local-first`), so offline editing of
2006
+ * an encrypted doc requires local encryption the framework does not ship.
2007
+ * Declare it deliberately.
2008
+ *
2009
+ * Anchors (stable positions for inline comments) come from
2010
+ * `@voltro/local-first`'s `CrdtDocHandle.encodeAnchor`/`resolveAnchor`.
2011
+ */
2012
+ export declare const crdtDoc: () => ColumnBuilder<Uint8Array | null, "bytes">;
2013
+
1990
2014
  /**
1991
2015
  * The names of a table's CRDT-managed columns (`crdtText()`). These store an
1992
2016
  * encoded CRDT state as `bytes` and get an authoritative SERVER-SIDE merge on
@@ -1996,6 +2020,10 @@ export declare const countDistinct: (column: string, alias?: string) => Aggregat
1996
2020
  */
1997
2021
  export declare const crdtManagedColumns: (table: TableLike) => ReadonlyArray<string>;
1998
2022
 
2023
+ /** The `crdtText()`/`crdtDoc()` columns of a table — the set the server merge
2024
+ * folds and the capture paths (undo, row history) exclude. */
2025
+ export declare const crdtManagedColumnsOf: (table: TableLike) => ReadonlyArray<string>;
2026
+
1999
2027
  /**
2000
2028
  * CRDT-managed text column — a field whose value is a CONFLICT-FREE replicated
2001
2029
  * text document rather than a plain string. Two clients editing it at the same
@@ -4325,12 +4353,26 @@ export declare interface MigrationStepContext {
4325
4353
  export declare const min: (column: string, alias?: string) => AggregateColumn;
4326
4354
 
4327
4355
  /**
4328
- * The `conflictColumns` an upsert names that are absent from its payload. An
4329
- * upsert keyed on a column the row doesn't set can't match a conflict target —
4330
- * the dialect fails obscurely (or worse, inserts a duplicate). Naming it at the
4331
- * call is the difference between a one-line fix and reading a driver error.
4356
+ * The `conflictColumns` an upsert names that cannot match its conflict target.
4357
+ * An upsert keyed on a column the row doesn't set can't match the dialect
4358
+ * fails obscurely (or worse, silently inserts a duplicate on every re-run).
4359
+ * Naming it at the call is the difference between a one-line fix and reading a
4360
+ * driver error.
4361
+ *
4362
+ * Takes the TABLE, exactly like `missingRequiredColumns` above, and for the
4363
+ * same reason six lines up: a generated column (`generatedAs`) is DB-computed
4364
+ * and takes no caller value — MariaDB/Postgres REJECT an explicit one, and the
4365
+ * framework's own stamping STRIPS one — so for a generated conflict column,
4366
+ * absence from the payload is the only correct state. The first version took
4367
+ * only `(conflictColumns, row)` and therefore COULD NOT know: it refused every
4368
+ * upsert keyed on a stored generated column, a condition nobody can satisfy.
4369
+ * The very shape that makes such a unique work (folding NULLs to a constant so
4370
+ * a composite unique can hold, e.g. `CASE WHEN ref IS NULL THEN 1 END`) is the
4371
+ * shape it rejected. `undefined` table = the definition is not available; no
4372
+ * column can be recognised as generated, so none is skipped — pass the table
4373
+ * whenever you have one.
4332
4374
  */
4333
- export declare const missingConflictColumns: (conflictColumns: ReadonlyArray<string>, row: Row) => ReadonlyArray<string>;
4375
+ export declare const missingConflictColumns: (table: TableLike | undefined, conflictColumns: ReadonlyArray<string>, row: Row) => ReadonlyArray<UnmatchableConflictColumn>;
4334
4376
 
4335
4377
  /**
4336
4378
  * Columns the row must carry but doesn't. Empty when the row is complete.
@@ -7522,6 +7564,17 @@ export declare interface UniqueSpec {
7522
7564
  readonly dedup?: 'fail' | 'suffix-counter' | Statement.Fragment;
7523
7565
  }
7524
7566
 
7567
+ /** Why a conflict column cannot match its target — the two are different bugs
7568
+ * with different fixes, and one shared word ("missing") sent a reader hunting
7569
+ * for an absent field that was present-but-NULL. */
7570
+ export declare interface UnmatchableConflictColumn {
7571
+ readonly column: string;
7572
+ /** `absent` — not in the payload at all. `null` — present, but NULL, and
7573
+ * NULL never matches a unique conflict target: the write would always
7574
+ * INSERT. */
7575
+ readonly reason: 'absent' | 'null';
7576
+ }
7577
+
7525
7578
  /**
7526
7579
  * Remove ONE name this process added for a bounded operation.
7527
7580
  *