@atscript/db 0.1.161 → 0.1.163

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.
Files changed (65) hide show
  1. package/dist/agg.cjs +1 -1
  2. package/dist/agg.d.cts +1 -1
  3. package/dist/agg.d.mts +1 -1
  4. package/dist/agg.mjs +1 -1
  5. package/dist/{aggregate-fns-B_sgl4mB.mjs → aggregate-fns-DsS9UQVB.mjs} +1 -1
  6. package/dist/{aggregate-fns-DFtKAv7Q.cjs → aggregate-fns-DupYzFD7.cjs} +1 -1
  7. package/dist/{buckets-B4T_alUe.d.cts → buckets-B8UOod-v.d.cts} +488 -57
  8. package/dist/{buckets-8mG67Mtw.d.mts → buckets-CHyspjYP.d.mts} +488 -57
  9. package/dist/{column-diff-DpeUbhEI.cjs → column-diff-BIGX3sRH.cjs} +853 -232
  10. package/dist/{column-diff-DR1glykD.mjs → column-diff-BfNIlMwX.mjs} +836 -233
  11. package/dist/{validator-B3xlbrWf.d.cts → db-error-B_DRL1E9.d.cts} +18 -89
  12. package/dist/{validator-B3xlbrWf.d.mts → db-error-B_DRL1E9.d.mts} +18 -89
  13. package/dist/{db-error-JcfJqqpk.cjs → db-error-DmF1_xrz.cjs} +13 -0
  14. package/dist/{db-error-eSsQX7rt.mjs → db-error-hraC12B9.mjs} +8 -1
  15. package/dist/{db-validator-plugin-BWy60OvG.d.cts → db-validator-plugin-wRqMYNBI.d.cts} +6 -0
  16. package/dist/{db-validator-plugin-BWy60OvG.d.mts → db-validator-plugin-wRqMYNBI.d.mts} +6 -0
  17. package/dist/{fk-diff-5gX42hBt.d.mts → fk-diff-BNGawZi9.d.cts} +34 -10
  18. package/dist/{fk-diff-BWdQ7kRZ.d.cts → fk-diff-rj9N2QLw.d.mts} +34 -10
  19. package/dist/index.cjs +15 -11
  20. package/dist/index.d.cts +24 -21
  21. package/dist/index.d.mts +24 -21
  22. package/dist/index.mjs +10 -12
  23. package/dist/{nested-writer-BOj_c_lI.mjs → nested-writer-ClUX0DB0.mjs} +16 -22
  24. package/dist/{nested-writer-Bl1SZS7x.cjs → nested-writer-yCy6wGuN.cjs} +16 -22
  25. package/dist/{object-CtPYTIvy.d.cts → object-Czia_qD4.d.cts} +7 -1
  26. package/dist/{object-CtPYTIvy.d.mts → object-Czia_qD4.d.mts} +7 -1
  27. package/dist/{object-Djg28csK.cjs → object-GjsuPNqo.cjs} +19 -0
  28. package/dist/{object-TkiJQ-Dp.mjs → object-PQ1J8jri.mjs} +14 -1
  29. package/dist/ops.cjs +6 -21
  30. package/dist/ops.mjs +6 -21
  31. package/dist/plugin.cjs +263 -323
  32. package/dist/plugin.mjs +163 -223
  33. package/dist/rel.cjs +2 -2
  34. package/dist/rel.d.cts +3 -3
  35. package/dist/rel.d.mts +3 -3
  36. package/dist/rel.mjs +2 -2
  37. package/dist/{relation-helpers-17_2f5hX.d.mts → relation-helpers-DloMywNs.d.cts} +1 -1
  38. package/dist/{relation-helpers-BLBrLQYi.d.cts → relation-helpers-zwt19E7r.d.mts} +1 -1
  39. package/dist/{relation-loader-DeulLrAw.cjs → relation-loader-DujL_Mh9.cjs} +1 -1
  40. package/dist/{relation-loader-CNBMPfRr.mjs → relation-loader-Qv3LrQ42.mjs} +1 -1
  41. package/dist/{search-fields-CT_UZ9fg.cjs → search-fields-B49-RCWd.cjs} +65 -1
  42. package/dist/{search-fields-CE8cmj9X.mjs → search-fields-BPNsxrCk.mjs} +48 -2
  43. package/dist/search-fields-CHqqcC3W.d.cts +30 -0
  44. package/dist/search-fields-CHqqcC3W.d.mts +30 -0
  45. package/dist/server-stamped-B6XbUQ4p.cjs +33 -0
  46. package/dist/server-stamped-BoP56K9M.mjs +22 -0
  47. package/dist/shared.cjs +42 -26
  48. package/dist/shared.d.cts +98 -4
  49. package/dist/shared.d.mts +98 -4
  50. package/dist/shared.mjs +4 -2
  51. package/dist/sync.cjs +228 -65
  52. package/dist/sync.d.cts +41 -5
  53. package/dist/sync.d.mts +41 -5
  54. package/dist/sync.mjs +228 -66
  55. package/dist/{validator-B4YDLUkj.cjs → validator-DK9Ijpo7.cjs} +3 -2
  56. package/dist/validator-DX97RzC2.d.cts +108 -0
  57. package/dist/validator-DX97RzC2.d.mts +108 -0
  58. package/dist/{validator-B3fPJjS1.mjs → validator-DuDWsIdQ.mjs} +3 -2
  59. package/dist/validator.cjs +6 -3
  60. package/dist/validator.d.cts +5 -4
  61. package/dist/validator.d.mts +5 -4
  62. package/dist/validator.mjs +5 -4
  63. package/dist/{validation-utils-BGjqc2jU.mjs → view-validation-BcgDq7M9.mjs} +364 -20
  64. package/dist/{validation-utils-CtLNlBtB.cjs → view-validation-BiDLCYMw.cjs} +452 -18
  65. package/package.json +6 -6
@@ -1,3 +1,4 @@
1
+ import { r as DbError } from "./db-error-B_DRL1E9.cjs";
1
2
  import { f as TFieldOps } from "./ops-AqhV7s9o.cjs";
2
3
  import { AggregateControls, AggregateExpr, AggregateExpr as AggregateExpr$1, AggregateFn, AggregateFn as AggregateFn$1, AggregateQuery, AggregateQuery as AggregateQuery$1, AggregateResult, BucketUnit, FieldOpsFor, FilterExpr, FilterExpr as FilterExpr$1, NullsPlacement, NullsPlacement as NullsPlacement$1, RelationOp, ResolvedBucket, ResolvedRowOrderKey, ResolvedSelectExpr, TypedWithRelation, Uniquery, Uniquery as Uniquery$1, UniqueryControls, UniqueryControls as UniqueryControls$1, UniqueryInsights, WithRelation, WithRelation as WithRelation$1 } from "@uniqu/core";
3
4
  import { AtscriptExprNode, AtscriptExprNode as AtscriptExprNode$1, AtscriptOrderItem, AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, FlatOf as FlatOf$1, NavPropsOf, NavPropsOf as NavPropsOf$1, OwnPropsOf, OwnPropsOf as OwnPropsOf$1, PrimaryKeyOf, PrimaryKeyOf as PrimaryKeyOf$1, TAtscriptAnnotatedType, TAtscriptDataType, TAtscriptTypeObject, TMetadataMap, TSerializedAnnotatedType, TValidatorOptions, TValidatorPlugin, Validator } from "@atscript/typescript/utils";
@@ -761,6 +762,14 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
761
762
  * @internal Adapter-facing surface; not part of the consumer API.
762
763
  */
763
764
  get versionColumnPhysical(): string | undefined;
765
+ /**
766
+ * Physical column names of the `@db.onUpdate.inc` fields (since 0.1.162):
767
+ * adapters add `col = col + 1` to every replace. Empty when there are none.
768
+ *
769
+ * @internal Adapter-facing surface; not part of the consumer API.
770
+ */
771
+ get onUpdateIncPhysical(): readonly string[];
772
+ private _onUpdateIncPhysical?;
764
773
  /**
765
774
  * Logical paths of the `@db.column.version.exempt` fields, including objects
766
775
  * whose direct children are all exempt. A patch that writes only these (and
@@ -860,7 +869,7 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
860
869
  * `query` with {@link _withPkTieBreak} applied and its `$nulls` resolved
861
870
  * ({@link NullsSource.resolveSort}) — a copy when either changes.
862
871
  */
863
- private _withStableSort;
872
+ protected _withStableSort(query: Uniquery): Uniquery;
864
873
  private _nullsCache?;
865
874
  /** NULL-placement resolution for this table (`$nulls`, `@db.sort.nulls`; since 0.1.153). */
866
875
  private get _nulls();
@@ -949,18 +958,43 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
949
958
  * Creates a new validator with custom options.
950
959
  */
951
960
  createValidator(opts?: Partial<TValidatorOptions>): Validator<T, DataType>;
961
+ /**
962
+ * The row lock a `findOne` / `findMany` asked for (`opts.lock`, since
963
+ * 0.1.162), validated — `undefined` when none was asked for.
964
+ *
965
+ * @throws DbError `INVALID_QUERY` — bad `lock` / `wait` value, a view, a
966
+ * grouped / aggregate / `$count` read, or no `withTransaction` scope of
967
+ * this table's adapter; `LOCK_NOT_SUPPORTED` — the adapter cannot lock.
968
+ */
969
+ private _readLock;
952
970
  /**
953
971
  * Finds a single record matching the query.
954
972
  * The return type automatically excludes nav props unless they are
955
973
  * explicitly requested via `$with`.
974
+ *
975
+ * `opts.lock` (since 0.1.162) makes it a locking read — see
976
+ * {@link TReadLockOptions}:
977
+ *
978
+ * ```typescript
979
+ * await adapter.withTransaction(async () => {
980
+ * const order = await orders.findOne({ filter: { id }, controls: {} }, { lock: 'update' })
981
+ * // … the row stays locked until the transaction ends
982
+ * })
983
+ * ```
956
984
  */
957
- findOne<Q extends Uniquery<OwnProps, NavType>>(query: Q): Promise<DbResponse<DataType, NavType, Q> | null>;
985
+ findOne<Q extends Uniquery<OwnProps, NavType>>(query: Q, opts?: TReadLockOptions): Promise<DbResponse<DataType, NavType, Q> | null>;
986
+ /** {@link findOne} of a guarded query with an already validated lock. */
987
+ private _findOne;
958
988
  /**
959
989
  * Finds all records matching the query.
960
990
  * The return type automatically excludes nav props unless they are
961
991
  * explicitly requested via `$with`.
992
+ *
993
+ * `opts.lock` (since 0.1.162) makes it a locking read — see
994
+ * {@link TReadLockOptions}. Sort by the primary key when locking several
995
+ * rows, so concurrent transactions take the locks in the same order.
962
996
  */
963
- findMany<Q extends Uniquery<OwnProps, NavType>>(query: Q): Promise<Array<DbResponse<DataType, NavType, Q>>>;
997
+ findMany<Q extends Uniquery<OwnProps, NavType>>(query: Q, opts?: TReadLockOptions): Promise<Array<DbResponse<DataType, NavType, Q>>>;
964
998
  /**
965
999
  * `findMany` for the generic `$with` loader. With `partitionBy` (logical
966
1000
  * fields), `$skip` / `$limit` apply per group of rows sharing those fields'
@@ -1118,11 +1152,14 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
1118
1152
  *
1119
1153
  * // With relations — only requested nav props appear
1120
1154
  * const user = await table.findById('123', { controls: { $with: [{ name: 'posts' }] } })
1155
+ *
1156
+ * // Locking read inside a transaction (since 0.1.162) — see TReadLockOptions
1157
+ * const user = await table.findById('123', { lock: 'update' })
1121
1158
  * ```
1122
1159
  */
1123
1160
  findById<Q extends {
1124
1161
  controls?: UniqueryControls<OwnProps, NavType>;
1125
- } = Record<string, never>>(id: IdType, query?: Q): Promise<DbResponse<DataType, NavType, Q> | null>;
1162
+ } = Record<string, never>>(id: IdType, query?: Q & TReadLockOptions): Promise<DbResponse<DataType, NavType, Q> | null>;
1126
1163
  /**
1127
1164
  * Reads the ONE row an id addresses — resolved exactly like
1128
1165
  * {@link resolveRowFilter} (primary key first, `opts.scope` /
@@ -1132,11 +1169,18 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
1132
1169
  * must also match `opts.scope` (an out-of-scope row answers `null` like a
1133
1170
  * missing one).
1134
1171
  *
1172
+ * `opts.lock` / `opts.wait` (since 0.1.162) lock the row found — see
1173
+ * {@link TReadLockOptions}. The id is then resolved to its one row first
1174
+ * (an unlocked read, exactly like {@link resolveRowFilter}) and that row is
1175
+ * read with the lock: with `wait: 'skipLocked'` a row another transaction
1176
+ * holds answers `null` — never a lower-precedence identification naming a
1177
+ * different row.
1178
+ *
1135
1179
  * @since 0.1.143
1136
1180
  */
1137
1181
  findOneByRow<Q extends {
1138
1182
  controls?: UniqueryControls<OwnProps, NavType>;
1139
- } = Record<string, never>>(id: unknown, opts?: TRowResolveOptions & Q): Promise<DbResponse<DataType, NavType, Q> | null>;
1183
+ } = Record<string, never>>(id: unknown, opts?: TRowResolveOptions & TReadLockOptions & Q): Promise<DbResponse<DataType, NavType, Q> | null>;
1140
1184
  /**
1141
1185
  * Resolve an id value (scalar or object) into a {@link FilterExpr} using the
1142
1186
  * same identifications as {@link findById}. Public so callers can
@@ -1424,9 +1468,77 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
1424
1468
  * calling the guard.
1425
1469
  */
1426
1470
  deleteOne(id: IdType, opts?: TDeleteOptions<DataType>): Promise<TDbDeleteResult>;
1427
- updateMany(filter: FilterExpr<FlatType>, data: DbPatch<DataType>): Promise<TDbUpdateResult>;
1471
+ /**
1472
+ * Patches every row matching `filter` with `data` (own fields only — no
1473
+ * relations, no `$cas`). Since 0.1.162 the payload is validated in `patch`
1474
+ * mode, exactly like {@link updateOne}: a type mismatch, `null` on a
1475
+ * non-nullable field, `@meta.required` or `@expect.*` failures throw a
1476
+ * `ValidatorError` before any statement runs.
1477
+ *
1478
+ * `opts.limit` (since 0.1.162) bounds the write to the first `limit` matching
1479
+ * rows in `opts.sort` order (default: primary key ascending; the primary key
1480
+ * always breaks ties). Loop until `matchedCount === 0` to process every
1481
+ * match in batches. Not exposed over HTTP.
1482
+ */
1483
+ updateMany(filter: FilterExpr<FlatType>, data: DbPatch<DataType>, opts?: TBulkWriteOptions<FlatType>): Promise<TDbUpdateResult>;
1484
+ /**
1485
+ * Replaces the own fields of every row matching `filter` with `data`. The
1486
+ * payload is validated in `replace` mode (since 0.1.162) — every required
1487
+ * field must be present — except the primary key, which the filter
1488
+ * replaces as a row picker.
1489
+ */
1428
1490
  replaceMany(filter: FilterExpr<FlatType>, data: DbRow<DataType>): Promise<TDbUpdateResult>;
1429
- deleteMany(filter: FilterExpr<FlatType>): Promise<TDbDeleteResult>;
1491
+ /**
1492
+ * Deletes every row matching `filter` (application-level cascades run first
1493
+ * where the adapter has no native foreign keys).
1494
+ *
1495
+ * `opts.limit` (since 0.1.162) bounds the delete to the first `limit`
1496
+ * matching rows in `opts.sort` order (default: primary key ascending; the
1497
+ * primary key always breaks ties) — for retention sweeps that keep each
1498
+ * statement small. Loop until `deletedCount === 0`, not until it is below
1499
+ * `limit`: a concurrent writer can make one round delete fewer rows while
1500
+ * matches remain. Not exposed over HTTP.
1501
+ */
1502
+ deleteMany(filter: FilterExpr<FlatType>, opts?: TBulkWriteOptions<FlatType>): Promise<TDbDeleteResult>;
1503
+ /**
1504
+ * Runs a bounded write. `native` (default: `supportsWriteLimit()`) hands
1505
+ * `write` the physical filter and the bound; otherwise the primary keys of
1506
+ * the picked rows are read first and `write` gets `filter AND keys` per
1507
+ * key batch (no bound) — a pick that finds nothing writes nothing.
1508
+ *
1509
+ * When the write affected no rows although a row still matches — a
1510
+ * concurrent transaction deleted or changed the picked rows between the
1511
+ * pick and the write — it runs again, at most
1512
+ * {@link BOUNDED_WRITE_RETRIES} more times; an emulated write's next pick
1513
+ * is that check. Rows still matching after the last attempt throw a
1514
+ * retryable `SERIALIZATION_FAILURE`. So `0` means nothing matched (a loop
1515
+ * until `0` cannot stop early); fewer than `limit` stays possible.
1516
+ * A native write whose adapter reports `writeLimitIsAtomic()` is never
1517
+ * re-checked.
1518
+ */
1519
+ private _runBounded;
1520
+ /** Whether any row still matches a bounded write's filter (a one-row key read). */
1521
+ private _boundStillMatches;
1522
+ /**
1523
+ * Application-level cascade, then the delete. `translate` maps `filter` to
1524
+ * the adapter's physical filter (identity for an already-physical one).
1525
+ */
1526
+ private _cascadeDelete;
1527
+ /**
1528
+ * Validates `opts` of a bounded `updateMany` / `deleteMany` and returns the
1529
+ * translated read of the rows it picks (filter, order with the primary-key
1530
+ * tie-breaker, `limit`, primary-key projection), or `undefined` when the
1531
+ * write is unbounded.
1532
+ */
1533
+ private _writeBound;
1534
+ /** `updateMany` / `replaceMany` write the table's own fields only. */
1535
+ private _rejectNavWrite;
1536
+ /**
1537
+ * A logical patch → the adapter's physical `{ update, ops }`: nested
1538
+ * merge-strategy objects decomposed into dot-paths (so nested field ops are
1539
+ * caught), field ops separated, keys translated.
1540
+ */
1541
+ private _translatePatch;
1430
1542
  /**
1431
1543
  * Synchronizes indexes between Atscript definitions and the database.
1432
1544
  */
@@ -1566,7 +1678,11 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
1566
1678
  * them once the patch is known to write something.
1567
1679
  */
1568
1680
  private _stampOnUpdate;
1569
- /** Sets the top-level `@db.onUpdate.now` columns of a non-empty patch to `now`. */
1681
+ /**
1682
+ * Sets the top-level `@db.onUpdate.now` columns of a non-empty patch to
1683
+ * `now` and increments its `@db.onUpdate.inc` counters (`$inc: 1`).
1684
+ * `force`: stamp an empty patch too (a touch writes the row).
1685
+ */
1570
1686
  private _stampTopLevel;
1571
1687
  /** {@link _nestedDefaultFillable} per nested default path. */
1572
1688
  private _fillableDefaults?;
@@ -1738,6 +1854,13 @@ interface TViewSource {
1738
1854
  designType: string;
1739
1855
  /** Set for a relational object stored as one column per leaf. */
1740
1856
  flattened?: true;
1857
+ /**
1858
+ * Set when the path is itself a JSON-stored column (relational) — a
1859
+ * `@db.json` field, an array or a structured mixed union — so
1860
+ * {@link column} holds its JSON text, not the typed value.
1861
+ * @since 0.1.162
1862
+ */
1863
+ jsonColumn?: true;
1741
1864
  /**
1742
1865
  * `true` when the value may be absent: the path or an ancestor segment is
1743
1866
  * optional, or it reads inside a JSON-stored value.
@@ -1797,6 +1920,9 @@ interface TViewColumnMapping {
1797
1920
  /**
1798
1921
  * Set when the source is a primitive leaf inside a JSON column
1799
1922
  * ({@link sourceColumn}): the path within it and the leaf's declared type.
1923
+ * Since 0.1.162 also set, with an empty `path` (the JSON root), when the
1924
+ * source is itself a primitive `@db.json` column — the view reads its typed
1925
+ * value, not the JSON text.
1800
1926
  * @since 0.1.136
1801
1927
  */
1802
1928
  json?: {
@@ -2140,8 +2266,87 @@ declare const ALL_BUCKET_UNITS: ReadonlySet<BucketUnit>;
2140
2266
  * @since 0.1.147
2141
2267
  */
2142
2268
  type TViewCapability = "compute" | "firstJoin";
2269
+ /**
2270
+ * Every isolation level, weakest first — what an adapter that provides them
2271
+ * all returns from `isolationLevels()`. @since 0.1.162
2272
+ */
2273
+ declare const ALL_ISOLATION_LEVELS: ReadonlySet<TDbIsolationLevel>;
2143
2274
  /** Every view capability — what the bundled adapters return from `viewCapabilities()`. @since 0.1.147 */
2144
2275
  declare const ALL_VIEW_CAPABILITIES: ReadonlySet<TViewCapability>;
2276
+ /**
2277
+ * What an adapter hands `BaseDbAdapter.syncIndexesWithDiff`: the three
2278
+ * DB-specific primitives plus how to compare and skip.
2279
+ * @since 0.1.162 (inline before)
2280
+ */
2281
+ interface TIndexDiffOptions {
2282
+ /**
2283
+ * Existing indexes. When `columns` is provided (ordered column names),
2284
+ * plain/unique indexes whose definition no longer matches the model are
2285
+ * dropped and recreated — a name match alone is not enough (e.g. a
2286
+ * composite index that gained or lost a member keeps its name).
2287
+ */
2288
+ listExisting(): Promise<Array<{
2289
+ name: string;
2290
+ columns?: string[];
2291
+ }>>;
2292
+ createIndex(index: TDbIndex): Promise<void>;
2293
+ dropIndex(name: string): Promise<void>;
2294
+ prefix?: string;
2295
+ /**
2296
+ * Renders one desired key part for the drift comparison, so adapters whose
2297
+ * `listExisting` reports more than a bare column name (e.g. MySQL's
2298
+ * `col(255)` key-length prefix) can render the model side identically.
2299
+ * Default: the column name.
2300
+ * @since 0.1.128
2301
+ */
2302
+ renderDesiredColumn?(index: TDbIndex, field: TDbIndex["fields"][number]): string;
2303
+ /**
2304
+ * An index this diff does not build: a string — the warning to log (e.g. a
2305
+ * geo index without PostGIS); `null` — skipped silently (e.g. an index type
2306
+ * the adapter maintains itself); `undefined` — built. A skipped index is not
2307
+ * desired — never reported as work to do, and a stale one is dropped.
2308
+ * @since 0.1.162
2309
+ */
2310
+ skipIndex?(index: TDbIndex): string | null | undefined;
2311
+ /**
2312
+ * Skips (silently) every index of a type this returns `true` for.
2313
+ * @deprecated since 0.1.162 — use {@link TIndexDiffOptions.skipIndex} (return `null`).
2314
+ */
2315
+ shouldSkipType?(type: TDbIndex["type"]): boolean;
2316
+ /**
2317
+ * Index types the adapter does not support — warned about and skipped.
2318
+ * @deprecated since 0.1.162 — use {@link TIndexDiffOptions.skipIndex} (return the warning).
2319
+ */
2320
+ warnUnsupportedTypes?: {
2321
+ adapter: string;
2322
+ types: ReadonlyArray<TDbIndex["type"]>;
2323
+ };
2324
+ /**
2325
+ * Prefixed indexes the adapter manages itself, outside the model's
2326
+ * `indexes` (e.g. PostgreSQL's pgvector HNSW indexes) — never dropped as
2327
+ * stale here.
2328
+ * @since 0.1.162
2329
+ */
2330
+ isUnmanaged?(name: string): boolean;
2331
+ /**
2332
+ * Compute the changes only — no DDL (`planIndexes`).
2333
+ * @since 0.1.162
2334
+ */
2335
+ dryRun?: boolean;
2336
+ }
2337
+ /**
2338
+ * What an adapter hands `BaseDbAdapter.syncForeignKeysWithDiff`: its
2339
+ * foreign-key constraint primitives.
2340
+ * @since 0.1.162
2341
+ */
2342
+ interface TForeignKeyDiffOptions {
2343
+ /** The live table's foreign-key constraints: constraint name → local column names. */
2344
+ listExisting(): Promise<ReadonlyMap<string, string[]>>;
2345
+ dropConstraint(name: string): Promise<void>;
2346
+ addConstraint(fk: TDbForeignKey): Promise<void>;
2347
+ /** Compute the changes only — no DDL (`planForeignKeys`). */
2348
+ dryRun?: boolean;
2349
+ }
2145
2350
  /**
2146
2351
  * Abstract base class for database adapters.
2147
2352
  *
@@ -2228,6 +2433,31 @@ declare abstract class BaseDbAdapter {
2228
2433
  * `expectedVersion`; a violation throws).
2229
2434
  */
2230
2435
  protected _versionColumnFor(opts?: TDbUpdateOptions, expectedVersion?: number): string | undefined;
2436
+ /**
2437
+ * `@db.onUpdate.inc` columns (physical names, since 0.1.162) as a field-op
2438
+ * increment by one, or `undefined` when the table declares none. A replace
2439
+ * path renders it next to the replacement data (the core leaves these
2440
+ * columns out of the payload); the patch paths get the `$inc` from the core.
2441
+ */
2442
+ protected _onUpdateIncOps(): TFieldOps | undefined;
2443
+ /**
2444
+ * Whether `updateMany` / `deleteMany` render a row bound
2445
+ * ({@link TDbWriteLimit}) natively in one statement (since 0.1.162). When
2446
+ * `false` (the default) the core emulates a bounded write: it reads the
2447
+ * primary keys of the first `limit` matching rows in order, then writes the
2448
+ * rows matching the filter AND those keys.
2449
+ */
2450
+ supportsWriteLimit(): boolean;
2451
+ /**
2452
+ * Whether a native bounded write ({@link supportsWriteLimit}) picks and
2453
+ * writes its rows atomically — a row a concurrent transaction deletes or
2454
+ * moves out of the filter is passed over and the next match taken, so `0`
2455
+ * affected rows always means nothing matched (MySQL's
2456
+ * `UPDATE/DELETE … ORDER BY … LIMIT`). When `false` (the default) the core
2457
+ * probes for a remaining match after a bounded write that affected no rows
2458
+ * and retries it a few times (since 0.1.162).
2459
+ */
2460
+ writeLimitIsAtomic(): boolean;
2231
2461
  /**
2232
2462
  * Logs a debug message if verbose mode is enabled.
2233
2463
  * Adapters call this to log DB operations with zero overhead when disabled.
@@ -2242,8 +2472,58 @@ declare abstract class BaseDbAdapter {
2242
2472
  * The generic layer handles nesting detection via `AsyncLocalStorage`.
2243
2473
  * Adapters override `_beginTransaction`, `_commitTransaction`, and
2244
2474
  * `_rollbackTransaction` to provide raw DB-specific transaction primitives.
2475
+ *
2476
+ * `opts.isolation` (since 0.1.162) sets the isolation level of the
2477
+ * transaction this call opens — "at least this level". An adapter whose
2478
+ * {@link isolationLevels} lacks it throws `ISOLATION_NOT_SUPPORTED`. A
2479
+ * nested call joins the open transaction; it may request a level only when
2480
+ * that transaction was opened with the same or a stricter one, else it
2481
+ * throws `INVALID_QUERY` (the level of a running transaction cannot change).
2482
+ */
2483
+ withTransaction<T>(fn: () => Promise<T>, opts?: TTransactionOptions): Promise<T>;
2484
+ /**
2485
+ * The isolation levels {@link withTransaction} can open a transaction at
2486
+ * (since 0.1.162). Default: none — a requested level throws
2487
+ * `ISOLATION_NOT_SUPPORTED`. Override and apply the level in
2488
+ * {@link _beginTransaction} (`opts.isolation`).
2245
2489
  */
2246
- withTransaction<T>(fn: () => Promise<T>): Promise<T>;
2490
+ isolationLevels(): ReadonlySet<TDbIsolationLevel>;
2491
+ /**
2492
+ * The level every transaction of this adapter runs at regardless of the
2493
+ * request (since 0.1.162) — SQLite's `BEGIN IMMEDIATE` is always
2494
+ * serializable. A nested `withTransaction` asking for any level then joins
2495
+ * without error. Default `undefined` (the engine default / what was asked).
2496
+ */
2497
+ protected _inherentIsolation(): TDbIsolationLevel | undefined;
2498
+ /**
2499
+ * Validates a `withTransaction` isolation request against
2500
+ * {@link isolationLevels} — the requested level, or `undefined`.
2501
+ * @throws DbError `INVALID_QUERY` (unknown level) / `ISOLATION_NOT_SUPPORTED`.
2502
+ */
2503
+ protected _checkIsolation(opts: TTransactionOptions | undefined): TDbIsolationLevel | undefined;
2504
+ /** The `ISOLATION_NOT_SUPPORTED` error of a `withTransaction` isolation request. */
2505
+ protected _isolationNotSupported(message: string): DbError;
2506
+ /**
2507
+ * A nested `withTransaction` asked for `requested` while a transaction
2508
+ * opened at `open` runs: fine when `open` is at least as strict.
2509
+ * @throws DbError `INVALID_QUERY` otherwise.
2510
+ */
2511
+ protected _assertJoinIsolation(open: TDbIsolationLevel | undefined, requested: TDbIsolationLevel): void;
2512
+ /**
2513
+ * Whether the readable layer may pass a row lock on `DbQuery.lock` to
2514
+ * `findOne` / `findMany` (since 0.1.162). Default `false` — a locking read
2515
+ * throws `LOCK_NOT_SUPPORTED`. An adapter whose transaction already
2516
+ * serialises writers may return `true` and ignore the lock.
2517
+ */
2518
+ supportsReadLocks(): boolean;
2519
+ /**
2520
+ * `true` inside a `withTransaction` scope of this adapter's owner — a real
2521
+ * transaction or a pass-through one (adapters without transaction
2522
+ * primitives, such as the in-memory one). Unlike {@link isInTransaction} a
2523
+ * pass-through scope counts. Used to require a scope for locking reads.
2524
+ * @since 0.1.162
2525
+ */
2526
+ inTransactionScope(): boolean;
2247
2527
  /**
2248
2528
  * The object a transaction state is branded with (since 0.1.128). Every
2249
2529
  * adapter instance that returns the same owner shares one transaction —
@@ -2277,9 +2557,10 @@ declare abstract class BaseDbAdapter {
2277
2557
  protected _runInTransactionContext<T>(state: unknown, fn: () => Promise<T>): Promise<T>;
2278
2558
  /**
2279
2559
  * Starts a raw transaction. Returns opaque state stored in the async context.
2280
- * Override in adapters that support transactions.
2560
+ * Override in adapters that support transactions. `opts.isolation` (since
2561
+ * 0.1.162) is set only to a level of {@link isolationLevels}.
2281
2562
  */
2282
- protected _beginTransaction(): Promise<unknown>;
2563
+ protected _beginTransaction(_opts?: TTransactionOptions): Promise<unknown>;
2283
2564
  /** Commits the raw transaction. Override in adapters that support transactions. */
2284
2565
  protected _commitTransaction(_state: unknown): Promise<void>;
2285
2566
  /** Rolls back the raw transaction. Override in adapters that support transactions. */
@@ -2334,6 +2615,16 @@ declare abstract class BaseDbAdapter {
2334
2615
  * to generate the value client-side or leave it for the DB.
2335
2616
  */
2336
2617
  nativeDefaultFns(): ReadonlySet<TDbDefaultFn>;
2618
+ /**
2619
+ * How this engine's introspection (`getExistingColumns`) reports the
2620
+ * model default `desired` (`serializeDefaultValue` form) of `field` when
2621
+ * it cannot report it exactly — e.g. MySQL reports a 4-byte character of a
2622
+ * literal default as `?` while the column stores it intact. Schema sync
2623
+ * treats a live default equal to this as unchanged. Optional — omit when
2624
+ * introspection reports defaults faithfully.
2625
+ * @since 0.1.162
2626
+ */
2627
+ reportedDefault?(desired: string, field: TDbFieldMeta): string;
2337
2628
  /**
2338
2629
  * Calendar-bucket units (`{ $bucket, $field }` in an aggregate `$select`)
2339
2630
  * this adapter can group by, over IANA time zones. Empty (the default) =
@@ -2584,48 +2875,27 @@ declare abstract class BaseDbAdapter {
2584
2875
  *
2585
2876
  * @example
2586
2877
  * ```typescript
2587
- * async syncIndexes() {
2588
- * await this.syncIndexesWithDiff({
2878
+ * protected override _syncIndexes(dryRun: boolean) {
2879
+ * return this.syncIndexesWithDiff({
2880
+ * dryRun,
2589
2881
  * listExisting: async () => this.driver.all('PRAGMA index_list(...)'),
2590
2882
  * createIndex: async (index) => this.driver.exec('CREATE INDEX ...'),
2591
2883
  * dropIndex: async (name) => this.driver.exec('DROP INDEX ...'),
2592
- * shouldSkipType: (type) => type === 'fulltext',
2884
+ * skipIndex: (index) => (index.type === 'fulltext' ? null : undefined),
2593
2885
  * })
2594
2886
  * }
2595
2887
  * ```
2596
2888
  */
2597
- protected syncIndexesWithDiff(opts: {
2598
- /**
2599
- * Existing indexes. When `columns` is provided (ordered column names),
2600
- * plain/unique indexes whose definition no longer matches the model are
2601
- * dropped and recreated — a name match alone is not enough (e.g. a
2602
- * composite index that gained or lost a member keeps its name).
2603
- */
2604
- listExisting(): Promise<Array<{
2605
- name: string;
2606
- columns?: string[];
2607
- }>>;
2608
- createIndex(index: TDbIndex): Promise<void>;
2609
- dropIndex(name: string): Promise<void>;
2610
- prefix?: string;
2611
- shouldSkipType?(type: TDbIndex["type"]): boolean;
2612
- /**
2613
- * Renders one desired key part for the drift comparison, so adapters whose
2614
- * `listExisting` reports more than a bare column name (e.g. MySQL's
2615
- * `col(255)` key-length prefix) can render the model side identically.
2616
- * Default: the column name.
2617
- * @since 0.1.128
2618
- */
2619
- renderDesiredColumn?(index: TDbIndex, field: TDbIndex["fields"][number]): string;
2620
- /**
2621
- * Index types declared on the model but not supported by this adapter —
2622
- * warns and skips (models stay portable; sync never errors on these).
2623
- */
2624
- warnUnsupportedTypes?: {
2625
- adapter: string;
2626
- types: ReadonlyArray<TDbIndex["type"]>;
2627
- };
2628
- }): Promise<void>;
2889
+ protected syncIndexesWithDiff(opts: TIndexDiffOptions): Promise<TIndexChange[]>;
2890
+ /**
2891
+ * Template method for foreign-key constraint synchronization: drops the
2892
+ * live constraints the model does not declare and adds the declared ones
2893
+ * the live table lacks — matched by their sorted local columns
2894
+ * ({@link fkKey}). A failing statement throws. Returns the changes (made,
2895
+ * or with `dryRun` only computed).
2896
+ * @since 0.1.162
2897
+ */
2898
+ protected syncForeignKeysWithDiff(opts: TForeignKeyDiffOptions): Promise<TForeignKeyChange[]>;
2629
2899
  /**
2630
2900
  * Returns available search indexes for this adapter.
2631
2901
  * UI uses this to show index picker. Override in adapters that support search.
@@ -2800,15 +3070,33 @@ declare abstract class BaseDbAdapter {
2800
3070
  /** `opts.keepVersion` — skip the version bump; see {@link TDbUpdateOptions}. */
2801
3071
  abstract updateMany(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, opts?: TDbUpdateOptions): Promise<TDbUpdateResult>;
2802
3072
  abstract replaceMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
2803
- abstract deleteMany(filter: FilterExpr): Promise<TDbDeleteResult>;
3073
+ /** `opts.limit` — bounded delete, sent only when {@link supportsWriteLimit} (since 0.1.162). */
3074
+ abstract deleteMany(filter: FilterExpr, opts?: TDbDeleteManyOptions): Promise<TDbDeleteResult>;
2804
3075
  /**
2805
3076
  * Synchronizes indexes between the Atscript definitions and the database.
2806
- * Uses `this._table.indexes` for the full index definitions. Schema sync
3077
+ * Uses `this._table.indexes` for the full index definitions. Returns the
3078
+ * changes it made (since 0.1.162) — schema sync reports them on the run
3079
+ * entry; `void` reports none. Schema sync
2807
3080
  * passes `opts` when safe mode skipped work the indexes depend on (see
2808
3081
  * {@link TSyncIndexesOptions}); an adapter whose indexes do not depend on it
2809
- * ignores them.
3082
+ * ignores them. Default: {@link _syncIndexes} without `dryRun`.
3083
+ */
3084
+ syncIndexes(opts?: TSyncIndexesOptions): Promise<void | TIndexChange[]>;
3085
+ /**
3086
+ * The index changes {@link syncIndexes} would make now — no DDL. Schema
3087
+ * sync's plan reports them (`entry.indexChanges`) and marks the entry
3088
+ * `alter`; a run reports what `syncIndexes` returns.
3089
+ * @since 0.1.162
2810
3090
  */
2811
- abstract syncIndexes(opts?: TSyncIndexesOptions): Promise<void>;
3091
+ planIndexes(opts?: TSyncIndexesOptions): Promise<TIndexChange[]>;
3092
+ /**
3093
+ * The one index pass behind {@link syncIndexes} (`dryRun: false`) and
3094
+ * {@link planIndexes} (`dryRun: true` — compute the changes, no DDL).
3095
+ * Adapters implement this (usually over {@link syncIndexesWithDiff}). An
3096
+ * adapter that overrides `syncIndexes` instead plans no index work.
3097
+ * @since 0.1.162
3098
+ */
3099
+ protected _syncIndexes(dryRun: boolean, _opts?: TSyncIndexesOptions): Promise<TIndexChange[]>;
2812
3100
  /**
2813
3101
  * Ensures the table exists in the database, creating it if needed.
2814
3102
  * Uses `this._table.tableName`, `this._table.schema`, etc.
@@ -2820,11 +3108,6 @@ declare abstract class BaseDbAdapter {
2820
3108
  * order. Adapters without inline constraints ignore the parameter.
2821
3109
  */
2822
3110
  abstract ensureTable(opts?: TEnsureTableOptions): Promise<void>;
2823
- /**
2824
- * Synchronizes foreign key constraints between Atscript definitions and the database.
2825
- * Uses `this._table.foreignKeys` for the full FK definitions.
2826
- * Optional — only relational adapters need to implement this.
2827
- */
2828
3111
  /**
2829
3112
  * Post-sync hook called after all table operations (columns, indexes, FKs)
2830
3113
  * are complete. Adapters can use this for finalization work such as
@@ -2832,7 +3115,22 @@ declare abstract class BaseDbAdapter {
2832
3115
  * Optional — most adapters don't need this.
2833
3116
  */
2834
3117
  afterSyncTable?(): Promise<void>;
2835
- syncForeignKeys?(): Promise<void>;
3118
+ /**
3119
+ * Synchronizes foreign key constraints between Atscript definitions and
3120
+ * the live table — adds the missing ones, drops the ones the model does
3121
+ * not declare (matched by their local columns). Returns what it changed
3122
+ * (since 0.1.162); schema sync reports it on the run entry. Optional —
3123
+ * only relational adapters implement it (usually over
3124
+ * {@link syncForeignKeysWithDiff}); without it, schema sync recreates the
3125
+ * table to change its foreign keys (when the adapter can).
3126
+ */
3127
+ syncForeignKeys?(): Promise<void | TForeignKeyChange[]>;
3128
+ /**
3129
+ * The changes {@link syncForeignKeys} would make now — no DDL. Schema
3130
+ * sync's plan reports them with the snapshot-based FK diff.
3131
+ * @since 0.1.162
3132
+ */
3133
+ planForeignKeys?(): Promise<TForeignKeyChange[]>;
2836
3134
  /**
2837
3135
  * Drops FK constraints identified by their canonical local column key.
2838
3136
  * Called by the sync executor before column operations to remove stale FKs
@@ -3140,6 +3438,12 @@ declare class TableMetadata {
3140
3438
  * @since 0.1.156
3141
3439
  */
3142
3440
  onUpdateNow: Set<string>;
3441
+ /**
3442
+ * Top-level fields annotated with `@db.onUpdate.inc`: `0` on insert, `+1` in
3443
+ * the same statement on every update and replace.
3444
+ * @since 0.1.162
3445
+ */
3446
+ onUpdateInc: Set<string>;
3143
3447
  /** Logical path → `@db.column` override (top-level keys only on document storage). */
3144
3448
  columnMap: Map<string, string>;
3145
3449
  dimensions: string[];
@@ -3429,6 +3733,67 @@ interface DbQuery {
3429
3733
  controls: DbControls;
3430
3734
  /** Pre-computed query insights (field → operators). Adapters may use this to apply query-time behaviour (e.g. collation). */
3431
3735
  insights?: UniqueryInsights;
3736
+ /**
3737
+ * Row lock the read takes (`findOne` / `findMany` with `{ lock }`; since
3738
+ * 0.1.162). Only ever set on a table read inside a transaction of the
3739
+ * adapter's owner, and only when `supportsReadLocks()` is true. SQL
3740
+ * adapters render `FOR UPDATE` / `FOR SHARE` [`NOWAIT` / `SKIP LOCKED`];
3741
+ * an adapter whose transaction already serialises writers may ignore it.
3742
+ */
3743
+ lock?: TDbReadLock;
3744
+ }
3745
+ /** Lock strength of a locking read: exclusive (`update`) or shared (`share`). */
3746
+ type TDbLockMode = "update" | "share";
3747
+ /**
3748
+ * What a locking read does when a row is locked by another transaction:
3749
+ * `block` (default) waits for it; `nowait` fails at once with a retryable
3750
+ * `DbError("LOCK_TIMEOUT")`; `skipLocked` leaves the locked rows out of the
3751
+ * result.
3752
+ */
3753
+ type TDbLockWait = "block" | "nowait" | "skipLocked";
3754
+ /** The resolved row lock handed to the adapter on {@link DbQuery.lock}. */
3755
+ interface TDbReadLock {
3756
+ mode: TDbLockMode;
3757
+ wait: TDbLockWait;
3758
+ }
3759
+ /**
3760
+ * Second argument of `findOne` / `findMany` (and part of the `findById` /
3761
+ * `findOneByRow` options): a locking read. Server-side only — it is never a
3762
+ * query control, so it cannot arrive over HTTP.
3763
+ *
3764
+ * A lock requires a `withTransaction` scope of the table's adapter and a
3765
+ * table (not a view); `$groupBy` / aggregate `$select` / `$count` reads are
3766
+ * rejected. Only the root rows are locked — `$with` relations load with
3767
+ * plain reads. The locks are held until the outermost transaction commits
3768
+ * or rolls back.
3769
+ *
3770
+ * @since 0.1.162
3771
+ */
3772
+ interface TReadLockOptions {
3773
+ /** `'update'` — exclusive row lock (`FOR UPDATE`); `'share'` — shared lock (`FOR SHARE`). */
3774
+ lock?: TDbLockMode;
3775
+ /** Behaviour on a row locked by another transaction (default `'block'`); requires `lock`. */
3776
+ wait?: TDbLockWait;
3777
+ }
3778
+ /**
3779
+ * Transaction isolation level. Semantics are "at least this level": an
3780
+ * engine that always runs stricter (SQLite) satisfies every level.
3781
+ * @since 0.1.162
3782
+ */
3783
+ type TDbIsolationLevel = "read committed" | "repeatable read" | "serializable";
3784
+ /**
3785
+ * Options of `withTransaction(fn, opts)` (since 0.1.162). Apply to the
3786
+ * outermost call only — a nested call joins the open transaction and may
3787
+ * request an isolation level only when the open transaction was started with
3788
+ * the same or a stricter one (otherwise `INVALID_QUERY`).
3789
+ */
3790
+ interface TTransactionOptions {
3791
+ /**
3792
+ * Isolation level of the transaction. An adapter that cannot provide it
3793
+ * throws `DbError("ISOLATION_NOT_SUPPORTED")`. Omitted: the engine default
3794
+ * (PostgreSQL READ COMMITTED, MySQL REPEATABLE READ).
3795
+ */
3796
+ isolation?: TDbIsolationLevel;
3432
3797
  }
3433
3798
  /** Describes an available search index exposed by a database adapter. */
3434
3799
  interface TSearchIndexInfo {
@@ -3846,6 +4211,48 @@ interface TDbUpdateOptions {
3846
4211
  * the option keeps bumping (the pre-0.1.150 behaviour).
3847
4212
  */
3848
4213
  keepVersion?: boolean;
4214
+ /**
4215
+ * Bounded update (`updateMany(filter, data, { limit })`, since 0.1.162):
4216
+ * write at most `limit.limit` rows, the first ones in `limit.sort` order.
4217
+ * Sent only to an adapter whose {@link BaseDbAdapter.supportsWriteLimit}
4218
+ * is `true`; the core emulates it for the others.
4219
+ */
4220
+ limit?: TDbWriteLimit;
4221
+ }
4222
+ /**
4223
+ * The row bound of a bounded `updateMany` / `deleteMany` as the adapter
4224
+ * receives it (since 0.1.162): physical column names, the primary key always
4225
+ * included in `sort` as the final tie-breaker so the order is total.
4226
+ */
4227
+ interface TDbWriteLimit {
4228
+ /** Positive integer — the most rows the statement may touch. */
4229
+ limit: number;
4230
+ /** Physical column → direction. Never empty. */
4231
+ sort: Record<string, 1 | -1>;
4232
+ /** Resolved NULL placement per `sort` key (see `DbControls.$nulls`). */
4233
+ nulls?: DbControls["$nulls"];
4234
+ }
4235
+ /** Per-call options of an adapter `deleteMany` (since 0.1.162). */
4236
+ interface TDbDeleteManyOptions {
4237
+ /** Bounded delete — see {@link TDbWriteLimit}. Sent only when `supportsWriteLimit()`. */
4238
+ limit?: TDbWriteLimit;
4239
+ }
4240
+ /**
4241
+ * Options of `AtscriptDbTable.updateMany` / `deleteMany` (since 0.1.162).
4242
+ * Not exposed over HTTP.
4243
+ */
4244
+ interface TBulkWriteOptions<FlatType = Record<string, unknown>> {
4245
+ /**
4246
+ * Touch at most this many matching rows (a positive integer). Loop until a
4247
+ * call reports `0` to process every match in batches.
4248
+ */
4249
+ limit?: number;
4250
+ /**
4251
+ * The order in which a bounded write picks rows (`$sort` shape). Defaults
4252
+ * to the primary key ascending; the primary key is always appended as the
4253
+ * final tie-breaker. Needs `limit`.
4254
+ */
4255
+ sort?: Partial<Record<keyof FlatType & string, 1 | -1>>;
3849
4256
  }
3850
4257
  interface TDbDeleteResult {
3851
4258
  deletedCount: number;
@@ -4225,6 +4632,30 @@ interface TSyncIndexesOptions {
4225
4632
  */
4226
4633
  keepColumns?: readonly string[];
4227
4634
  }
4635
+ /**
4636
+ * One managed index `syncIndexes` creates (`add`), drops (`drop`) or drops
4637
+ * and recreates because its definition drifted (`rebuild`) — returned by
4638
+ * `BaseDbAdapter.syncIndexes` / `planIndexes` and reported on schema-sync
4639
+ * entries (`entry.indexChanges`). `name` is the physical index name (or the
4640
+ * adapter's artifact for it, e.g. SQLite's FTS5 table).
4641
+ * @since 0.1.162
4642
+ */
4643
+ interface TIndexChange {
4644
+ name: string;
4645
+ action: "add" | "drop" | "rebuild";
4646
+ }
4647
+ /**
4648
+ * One foreign key `syncForeignKeys` adds to the live table (missing there,
4649
+ * e.g. dropped by hand) or drops from it (not in the model) — matched by
4650
+ * the sorted local columns. `targetTable` is set for an added constraint;
4651
+ * a dropped one may leave it out.
4652
+ * @since 0.1.162
4653
+ */
4654
+ interface TForeignKeyChange {
4655
+ fields: string[];
4656
+ targetTable?: string;
4657
+ action: "add" | "drop";
4658
+ }
4228
4659
  /** Result of applying column diff to the database. */
4229
4660
  interface TSyncColumnResult {
4230
4661
  added: string[];
@@ -4725,4 +5156,4 @@ declare function isJsonValueField(fd: TDbFieldMeta): boolean;
4725
5156
  */
4726
5157
  declare function jsonValueAncestor(path: string, jsonValueParents: ReadonlySet<string>): string | undefined;
4727
5158
  //#endregion
4728
- export { TDbInsertResult as $, ALL_VIEW_CAPABILITIES as $t, TColumnDiff as A, REL_FILTER_MAX_NODES as An, TPrimaryKeyChange as At, TDbDefaultFn as B, isResolvedRelationFilter as Bn, TValueFormatterPair as Bt, NavPropsOf$1 as C, IntegrityStrategy as Cn, TIdDescriptor as Ct, PrimaryKeyOf$1 as D, DbResponse as Dn, TJsonCopyTarget as Dt, OwnPropsOf$1 as E, AtscriptDbReadable as En, TInsertOptions as Et, TDbActionLevel as F, TRelationStaticFilter as Fn, TSyncColumnResult as Ft, TDbIndex as G, FieldMappingStrategy as Gn, Uniquery$1 as Gt, TDbDeleteResult as H, DbEncryption as Hn, TWriteOptions as Ht, TDbActionProcessor as I, andFilters as In, TSyncIndexesOptions as It, TDbInsertIgnoreOptions as J, TGenericLogger as Jn, TableMetadata as Jt, TDbIndexField as K, TReadControls as Kn, UniqueryControls$1 as Kt, TDbActionTargetSummary as L, containsRelationFilter as Ln, TTableOptionDiff as Lt, TCrudPermissions as M, TRelGuardState as Mn, TRelationInfo as Mt, TDbActionInfo as N, TRelationFilterJunction as Nn, TRowResolveOptions as Nt, TCascadeResolver as O, resolveDesignType as On, TMetaResponse as Ot, TDbActionIntent as P, TRelationFilterTable as Pn, TSearchIndexInfo as Pt, TDbInsertManyResult as Q, UniquSelect as Qn, ALL_BUCKET_UNITS as Qt, TDbAvailableActions as R, forEachResolvedRelation as Rn, TTableResolver as Rt, FlatOf$1 as S, AtscriptDbTable as Sn, TFkLookupTarget as St, NullsPlacement$1 as T, TCascadePin as Tn, TIdentification as Tt, TDbFieldMeta as U, TDbEncryptionOptions as Un, TWriteTableResolver as Ut, TDbDefaultValue as V, relationStaticFilter as Vn, TViewJsonType as Vt, TDbForeignKey as W, DocumentFieldMapper as Wn, TypedWithRelation as Wt, TDbInsertIgnoreSlot as X, TFirstLast as Xn, isGeoPointType as Xt, TDbInsertIgnoreResult as Y, TExprAggregate as Yn, isGeoIndexableType as Yt, TDbInsertManyIgnoreResult as Z, TRowOrderKey as Zn, TPathPresence as Zt, DbPatch as _, TViewJoin as _n, TExistingColumn as _t, isJsonValueField as a, AtscriptDbView as an, TDbStorageType as at, FieldOpsFor as b, isFieldRef as bn, TFieldMeta as bt, resolveCalendarBuckets as c, isViewType as cn, TDbWriteAction as ct, AggregateFn$1 as d, AtscriptExprNode$1 as dn, TDbWriteGuard as dt, BaseDbAdapter as en, TDbObjectKind as et, AggregateQuery$1 as f, AtscriptOrderItem as fn, TDbWriteGuardContext as ft, DbControls as g, AtscriptRef as gn, TEnsureTableOptions as gt, AtscriptDbWritable as h, AtscriptQueryNode$1 as hn, TDerivedColumn as ht, isBucketableField as i, TDbSpaceOptions as in, TDbRemoveGuardContext as it, TCrudOp as j, ResolvedRelationFilter as jn, TReferencingForeignKey as jt, TCascadeTarget as k, REL_FILTER_MAX_DEPTH as kn, TMetadataOverrides as kt, AggregateControls as l, TViewReadPlan as ln, TDbWriteCheck as lt, AtscriptDbTableLike as m, AtscriptQueryFieldRef$1 as mn, TDerivedChangeReason as mt, TComputedSelect as n, DbSpace as nn, TDbRelation as nt, jsonValueAncestor as o, TViewColumnMapping as on, TDbUpdateOptions as ot, AggregateResult as p, AtscriptQueryComparison as pn, TDeleteOptions as pt, TDbIndexType as q, NoopLogger as qn, WithRelation$1 as qt, TResolvedBucket as r, TAdapterFactory as rn, TDbRemoveGuard as rt, normalizeComputedSelect as s, isAtscriptDbView as sn, TDbUpdateResult as st, TBucketFieldSource as t, TViewCapability as tn, TDbReferentialAction as tt, AggregateExpr$1 as u, aliasTargetOf as un, TDbWriteCheckContext as ut, DbQuery as v, TViewPlan as vn, TExistingForeignKey as vt, NullableOptional as w, NativeIntegrity as wn, TIdResolveOptions as wt, FilterExpr$1 as x, translateQueryTree as xn, TFkLookupResolver as xt, DbRow as y, evaluateExpr as yn, TExistingTableOption as yt, TDbCollation as z, hasRelationOp as zn, TTouchManyOptions as zt };
5159
+ export { TDbInsertManyIgnoreResult as $, hasRelationOp as $n, TWriteOptions as $t, TCascadeTarget as A, AtscriptRef as An, TForeignKeyChange as At, TDbCollation as B, AtscriptDbReadable as Bn, TReadLockOptions as Bt, NavPropsOf$1 as C, TViewReadPlan as Cn, TEnsureTableOptions as Ct, PrimaryKeyOf$1 as D, AtscriptQueryComparison as Dn, TFieldMeta as Dt, OwnPropsOf$1 as E, AtscriptOrderItem as En, TExistingTableOption as Et, TDbActionIntent as F, translateQueryTree as Fn, TInsertOptions as Ft, TDbFieldMeta as G, ResolvedRelationFilter as Gn, TSyncColumnResult as Gt, TDbDefaultValue as H, resolveDesignType as Hn, TRelationInfo as Ht, TDbActionLevel as I, AtscriptDbTable as In, TJsonCopyTarget as It, TDbIndexField as J, TRelationFilterTable as Jn, TTableResolver as Jt, TDbForeignKey as K, TRelGuardState as Kn, TSyncIndexesOptions as Kt, TDbActionProcessor as L, IntegrityStrategy as Ln, TMetaResponse as Lt, TCrudOp as M, TViewPlan as Mn, TIdResolveOptions as Mt, TCrudPermissions as N, evaluateExpr as Nn, TIdentification as Nt, TBulkWriteOptions as O, AtscriptQueryFieldRef$1 as On, TFkLookupResolver as Ot, TDbActionInfo as P, isFieldRef as Pn, TIndexChange as Pt, TDbInsertIgnoreSlot as Q, forEachResolvedRelation as Qn, TViewJsonType as Qt, TDbActionTargetSummary as R, NativeIntegrity as Rn, TMetadataOverrides as Rt, FlatOf$1 as S, isViewType as Sn, TDerivedColumn as St, NullsPlacement$1 as T, AtscriptExprNode$1 as Tn, TExistingForeignKey as Tt, TDbDeleteManyOptions as U, REL_FILTER_MAX_DEPTH as Un, TRowResolveOptions as Ut, TDbDefaultFn as V, DbResponse as Vn, TReferencingForeignKey as Vt, TDbDeleteResult as W, REL_FILTER_MAX_NODES as Wn, TSearchIndexInfo as Wt, TDbInsertIgnoreOptions as X, andFilters as Xn, TTransactionOptions as Xt, TDbIndexType as Y, TRelationStaticFilter as Yn, TTouchManyOptions as Yt, TDbInsertIgnoreResult as Z, containsRelationFilter as Zn, TValueFormatterPair as Zt, DbPatch as _, TAdapterFactory as _n, TDbWriteGuard as _t, isJsonValueField as a, TableMetadata as an, FieldMappingStrategy as ar, TDbObjectKind as at, FieldOpsFor as b, TViewColumnMapping as bn, TDeleteOptions as bt, resolveCalendarBuckets as c, TPathPresence as cn, TGenericLogger as cr, TDbRelation as ct, AggregateFn$1 as d, ALL_VIEW_CAPABILITIES as dn, TRowOrderKey as dr, TDbStorageType as dt, TWriteTableResolver as en, isResolvedRelationFilter as er, TDbInsertManyResult as et, AggregateQuery$1 as f, BaseDbAdapter as fn, UniquSelect as fr, TDbUpdateOptions as ft, DbControls as g, DbSpace as gn, TDbWriteCheckContext as gt, AtscriptDbWritable as h, TViewCapability as hn, TDbWriteCheck as ht, isBucketableField as i, WithRelation$1 as in, DocumentFieldMapper as ir, TDbLockWait as it, TColumnDiff as j, TViewJoin as jn, TIdDescriptor as jt, TCascadeResolver as k, AtscriptQueryNode$1 as kn, TFkLookupTarget as kt, AggregateControls as l, ALL_BUCKET_UNITS as ln, TExprAggregate as lr, TDbRemoveGuard as lt, AtscriptDbTableLike as m, TIndexDiffOptions as mn, TDbWriteAction as mt, TComputedSelect as n, Uniquery$1 as nn, DbEncryption as nr, TDbIsolationLevel as nt, jsonValueAncestor as o, isGeoIndexableType as on, TReadControls as or, TDbReadLock as ot, AggregateResult as p, TForeignKeyDiffOptions as pn, TDbUpdateResult as pt, TDbIndex as q, TRelationFilterJunction as qn, TTableOptionDiff as qt, TResolvedBucket as r, UniqueryControls$1 as rn, TDbEncryptionOptions as rr, TDbLockMode as rt, normalizeComputedSelect as s, isGeoPointType as sn, NoopLogger as sr, TDbReferentialAction as st, TBucketFieldSource as t, TypedWithRelation as tn, relationStaticFilter as tr, TDbInsertResult as tt, AggregateExpr$1 as u, ALL_ISOLATION_LEVELS as un, TFirstLast as ur, TDbRemoveGuardContext as ut, DbQuery as v, TDbSpaceOptions as vn, TDbWriteGuardContext as vt, NullableOptional as w, aliasTargetOf as wn, TExistingColumn as wt, FilterExpr$1 as x, isAtscriptDbView as xn, TDerivedChangeReason as xt, DbRow as y, AtscriptDbView as yn, TDbWriteLimit as yt, TDbAvailableActions as z, TCascadePin as zn, TPrimaryKeyChange as zt };