@atscript/db 0.1.127 → 0.1.129

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 (41) hide show
  1. package/dist/{db-error-DXwEzmYJ.cjs → db-error-C4JuLcvb.cjs} +27 -0
  2. package/dist/{db-error-BHPXOKzc.mjs → db-error-COrO58t5.mjs} +22 -1
  3. package/dist/{db-readable-BkAGccv9.d.mts → db-readable-B7eYWS5q.d.cts} +299 -17
  4. package/dist/{db-readable-C0nDKX8A.d.cts → db-readable-Bn1bV_eC.d.mts} +299 -17
  5. package/dist/{db-space-B_ASuDaR.d.mts → db-space-C2UCnGHd.d.cts} +108 -30
  6. package/dist/{db-space-CSntT6yS.d.cts → db-space-DdIPYD0Q.d.mts} +108 -30
  7. package/dist/{db-view-BP0Qbeux.cjs → db-view-CRBgkEp0.cjs} +786 -100
  8. package/dist/{db-view-C8rZM5_N.mjs → db-view-Dl0aDTiT.mjs} +733 -101
  9. package/dist/index.cjs +48 -3
  10. package/dist/index.d.cts +162 -37
  11. package/dist/index.d.mts +162 -37
  12. package/dist/index.mjs +37 -5
  13. package/dist/{nested-writer-DI-HeTky.mjs → nested-writer-CkDo-ZfH.mjs} +1 -1
  14. package/dist/{nested-writer-DoDhl3X3.cjs → nested-writer-DxPhmWFz.cjs} +1 -1
  15. package/dist/{ops-DJRnNTVo.d.cts → ops-AqhV7s9o.d.cts} +24 -1
  16. package/dist/{ops-DJRnNTVo.d.mts → ops-AqhV7s9o.d.mts} +24 -1
  17. package/dist/ops.cjs +44 -1
  18. package/dist/ops.d.cts +2 -2
  19. package/dist/ops.d.mts +2 -2
  20. package/dist/ops.mjs +44 -2
  21. package/dist/plugin.cjs +12 -5
  22. package/dist/plugin.mjs +12 -5
  23. package/dist/rel.cjs +2 -2
  24. package/dist/rel.d.cts +1 -1
  25. package/dist/rel.d.mts +1 -1
  26. package/dist/rel.mjs +2 -2
  27. package/dist/{relation-loader-BnUgJsUG.cjs → relation-loader-C8GOpNYJ.cjs} +1 -1
  28. package/dist/{relation-loader-BmeOMj0b.mjs → relation-loader-CUGcxJ18.mjs} +1 -1
  29. package/dist/sync.cjs +1270 -398
  30. package/dist/sync.d.cts +255 -18
  31. package/dist/sync.d.mts +255 -18
  32. package/dist/sync.mjs +1269 -399
  33. package/dist/{validator-0vRXN51D.mjs → validator-CeD_fqyW.mjs} +21 -4
  34. package/dist/{validator-CSGug4vg.cjs → validator-lkCJKuoo.cjs} +32 -3
  35. package/dist/{validator-BcBtg8yW.d.cts → validator-wBARmD68.d.cts} +57 -1
  36. package/dist/{validator-BcBtg8yW.d.mts → validator-wBARmD68.d.mts} +57 -1
  37. package/dist/validator.cjs +7 -1
  38. package/dist/validator.d.cts +3 -3
  39. package/dist/validator.d.mts +3 -3
  40. package/dist/validator.mjs +4 -3
  41. package/package.json +8 -8
@@ -1,6 +1,6 @@
1
- import { C as TCascadeResolver, F as TDbDeleteResult, H as TDbInsertResult, K as TDbUpdateResult, V as TDbInsertManyResult, X as TFkLookupResolver, _t as TGenericLogger, a as TDbEncryptionOptions, c as BaseDbAdapter, ct as TWriteTableResolver, i as DbEncryption, ot as TTableResolver, pt as TableMetadata, t as AtscriptDbReadable } from "./db-readable-BkAGccv9.mjs";
2
- import { AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, NavPropsOf, OwnPropsOf, PrimaryKeyOf, TAtscriptAnnotatedType, TAtscriptDataType, Validator } from "@atscript/typescript/utils";
1
+ import { C as NullableOptional, Ct as TWriteOptions, E as TCascadeResolver, G as TDbInsertResult, Pt as TGenericLogger, Q as TDbUpdateResult, R as TDbDeleteResult, W as TDbInsertManyResult, a as TDbEncryptionOptions, bt as TTableResolver, c as BaseDbAdapter, ct as TFkLookupResolver, g as DbPatch, ht as TReferencingForeignKey, i as DbEncryption, kt as TableMetadata, nt as TDeleteOptions, t as AtscriptDbReadable, v as DbRow, wt as TWriteTableResolver, xt as TTouchManyOptions } from "./db-readable-B7eYWS5q.cjs";
3
2
  import { FilterExpr } from "@uniqu/core";
3
+ import { AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, NavPropsOf, OwnPropsOf, PrimaryKeyOf, TAtscriptAnnotatedType, TAtscriptDataType, Validator } from "@atscript/typescript/utils";
4
4
 
5
5
  //#region src/strategies/integrity.d.ts
6
6
  /**
@@ -24,7 +24,7 @@ declare class NativeIntegrity extends IntegrityStrategy {
24
24
  }
25
25
  //#endregion
26
26
  //#region src/table/db-table.d.ts
27
- declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = FlatOf<T>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = OwnPropsOf<T>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
27
+ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = NullableOptional<FlatOf<T>>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = NullableOptional<OwnPropsOf<T>>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
28
28
  protected _cascadeResolver?: TCascadeResolver;
29
29
  protected _fkLookupResolver?: TFkLookupResolver;
30
30
  protected readonly _integrity: IntegrityStrategy;
@@ -53,9 +53,7 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
53
53
  * Inserts a single record. Delegates to {@link insertMany} for unified
54
54
  * nested creation support.
55
55
  */
56
- insertOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
57
- maxDepth?: number;
58
- }): Promise<TDbInsertResult>;
56
+ insertOne(payload: DbPatch<DataType>, opts?: TWriteOptions<DataType>): Promise<TDbInsertResult>;
59
57
  /**
60
58
  * Inserts multiple records with batch-optimized nested creation.
61
59
  *
@@ -66,17 +64,16 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
66
64
  * (they receive our PKs as their FKs). Fully recursive — nested records
67
65
  * with their own nav data trigger further batch inserts at each level.
68
66
  * Recursive up to `maxDepth` (default 3).
67
+ *
68
+ * `opts.guard` (since 0.1.128) runs once inside the transaction, after
69
+ * defaults + validation, with the prepared rows — see {@link TWriteOptions}.
69
70
  */
70
- insertMany(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
71
- maxDepth?: number;
72
- }): Promise<TDbInsertManyResult>;
71
+ insertMany(payloads: Array<DbPatch<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbInsertManyResult>;
73
72
  /**
74
73
  * Replaces a single record identified by primary key(s).
75
74
  * Delegates to {@link bulkReplace} for unified nested relation support.
76
75
  */
77
- replaceOne(payload: DataType & Record<string, unknown>, opts?: {
78
- maxDepth?: number;
79
- }): Promise<TDbUpdateResult>;
76
+ replaceOne(payload: DbRow<DataType>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
80
77
  /**
81
78
  * Replaces multiple records with deep nested relation support.
82
79
  *
@@ -84,37 +81,69 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
84
81
  * replaced first (their PKs become our FKs), FROM dependents are replaced
85
82
  * after (they receive our PKs as their FKs), VIA relations clear and
86
83
  * re-create junction rows. Fully recursive up to `maxDepth` (default 3).
84
+ *
85
+ * `opts.guard` (since 0.1.128) runs once inside the transaction, after
86
+ * `$cas` extraction, defaults + validation — see {@link TWriteOptions}.
87
87
  */
88
- bulkReplace(payloads: Array<DataType & Record<string, unknown>>, opts?: {
89
- maxDepth?: number;
90
- }): Promise<TDbUpdateResult>;
88
+ bulkReplace(payloads: Array<DbRow<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
91
89
  /**
92
90
  * Partially updates a single record identified by primary key(s).
93
91
  * Delegates to {@link bulkUpdate} for unified nested relation support.
94
92
  */
95
- updateOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
96
- maxDepth?: number;
97
- }): Promise<TDbUpdateResult>;
93
+ updateOne(payload: DbPatch<DataType>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
98
94
  /**
99
95
  * Partially updates multiple records with deep nested relation support.
100
96
  *
101
97
  * Only TO relations (1:1, N:1) are supported for patching. FROM/VIA
102
98
  * relations will error — use {@link bulkReplace} for those.
103
99
  * Recursive up to `maxDepth` (default 3).
100
+ *
101
+ * `opts.guard` (since 0.1.128) runs once inside the transaction, after
102
+ * `$cas` extraction and validation, with the patches (identifying fields
103
+ * present, `$cas` removed) — see {@link TWriteOptions}.
104
+ */
105
+ bulkUpdate(payloads: Array<DbPatch<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
106
+ /**
107
+ * Batch versioned touch (since 0.1.129): bumps the version of every listed
108
+ * row by exactly one, each row guarded by its own expected version. This is
109
+ * the batch fence `updateMany(orFilter, {})` used to be before 0.1.128 (an
110
+ * empty patch is a no-op since then and takes no lock).
111
+ *
112
+ * Each key carries the primary key field(s) (composite supported) plus the
113
+ * version column and NOTHING else — a touch has no payload. Unique indexes
114
+ * do not identify a touch key. `undefined`-valued properties are ignored,
115
+ * like in every write payload. Empty `keys` → `{ 0, 0 }` without a statement.
116
+ *
117
+ * `require: 'all'` (default): one count over the whole key set runs FIRST;
118
+ * a stale or missing row throws {@link CasMismatchError} before any write.
119
+ * The bumps then run as `updateMany(orFilter, {})` chunks of at most
120
+ * {@link TOUCH_MANY_CHUNK} keys inside one adapter transaction; a summed
121
+ * `matchedCount` short of `keys.length` (a row moved between the count and
122
+ * the bump) throws the same error — SQL engines roll every bump back. The
123
+ * pre-count is therefore a deliberate double check on SQL: it is what makes
124
+ * the guarantee hold on adapters whose `withTransaction` is a passthrough
125
+ * (the memory adapter, a Mongo standalone topology) — there it covers the
126
+ * common stale case and the residual race window is accepted.
127
+ * `require: 'any'`: no pre-count, the honest summed result is returned.
128
+ *
129
+ * No `guard`, no `onWrite`; not exposed over HTTP.
104
130
  */
105
- bulkUpdate(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
106
- maxDepth?: number;
107
- }): Promise<TDbUpdateResult>;
131
+ touchMany(keys: Array<DbPatch<DataType>>, opts?: TTouchManyOptions): Promise<TDbUpdateResult>;
108
132
  /**
109
133
  * Deletes a single record by any type-compatible identifier — primary key
110
134
  * or single-field unique index. Uses the same resolution logic as `findById`.
111
135
  *
112
136
  * When the adapter does not support native foreign keys (e.g. MongoDB),
113
137
  * cascade and setNull actions are applied before the delete.
114
- */
115
- deleteOne(id: IdType): Promise<TDbDeleteResult>;
116
- updateMany(filter: FilterExpr<FlatType>, data: Partial<DataType> & Record<string, unknown>): Promise<TDbUpdateResult>;
117
- replaceMany(filter: FilterExpr<FlatType>, data: Record<string, unknown>): Promise<TDbUpdateResult>;
138
+ *
139
+ * `opts.guard` (since 0.1.128) runs inside the transaction once the id has
140
+ * resolved to a filter, before cascade / delete — see {@link TDeleteOptions}.
141
+ * An id that resolves to no filter answers `{ deletedCount: 0 }` without
142
+ * calling the guard.
143
+ */
144
+ deleteOne(id: IdType, opts?: TDeleteOptions<DataType>): Promise<TDbDeleteResult>;
145
+ updateMany(filter: FilterExpr<FlatType>, data: DbPatch<DataType>): Promise<TDbUpdateResult>;
146
+ replaceMany(filter: FilterExpr<FlatType>, data: DbRow<DataType>): Promise<TDbUpdateResult>;
118
147
  deleteMany(filter: FilterExpr<FlatType>): Promise<TDbDeleteResult>;
119
148
  /**
120
149
  * Synchronizes indexes between Atscript definitions and the database.
@@ -140,11 +169,31 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
140
169
  */
141
170
  protected _encryptItems(items: Array<Record<string, unknown>>, mode: "write" | "patch"): Promise<void>;
142
171
  /**
143
- * Applies default values for fields that are missing from the payload.
144
- * Defaults handled natively by the DB engine are skipped — the field stays
145
- * absent so the DB's own DEFAULT clause applies.
172
+ * Lazy pre-image read for a guard's `current(i)`: `null` when the row has
173
+ * no identifying key (e.g. an auto-increment insert) or the key cannot be
174
+ * resolved — never throws for a missing key.
175
+ * @internal
176
+ */
177
+ _readPreImage(row: unknown): Promise<DataType | null>;
178
+ /**
179
+ * Applies `@db.default` values in place to a row's absent fields — the
180
+ * defaults pass every insert / replace path runs before validation.
181
+ * Static value defaults (`@db.default 'x'`) are filled on EVERY adapter
182
+ * (since 0.1.128 — writing the column's own default explicitly is
183
+ * equivalent to leaving it to the DDL `DEFAULT`, and write guards see the
184
+ * full row). Function defaults (`now` / `uuid` / `increment` / custom) the
185
+ * adapter handles natively are NOT filled — the field stays absent so the
186
+ * engine's own default applies. The version column is never touched.
146
187
  */
147
188
  protected _applyDefaults(data: Record<string, unknown>): Record<string, unknown>;
189
+ /**
190
+ * The JS value for a `@db.default 'literal'`: strings (including unions of
191
+ * string literals) are used as-is, every other design type is parsed as
192
+ * JSON — the same value the SQL adapters put into the DDL `DEFAULT` clause.
193
+ * A literal that is not valid JSON falls back to the raw string so the
194
+ * validator reports it against the field instead of a bare `SyntaxError`.
195
+ */
196
+ private _parseValueDefault;
148
197
  /**
149
198
  * Extracts a record-identifying filter from a payload.
150
199
  *
@@ -235,7 +284,7 @@ interface TViewColumnMapping {
235
284
  * const users = await activeUsers.findMany({ filter: {}, controls: {} })
236
285
  * ```
237
286
  */
238
- declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = FlatOf<T>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = OwnPropsOf<T>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
287
+ declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = NullableOptional<FlatOf<T>>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = NullableOptional<OwnPropsOf<T>>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
239
288
  private _viewPlan?;
240
289
  get isView(): boolean;
241
290
  /**
@@ -267,6 +316,16 @@ declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
267
316
  */
268
317
  getViewColumnMappings(): TViewColumnMapping[];
269
318
  }
319
+ /**
320
+ * Structural type guard for views: `true` when the readable reports
321
+ * `isView`, whether or not it is an `AtscriptDbView` instance of THIS copy
322
+ * of `@atscript/db`. Adapters must use this (or `readable.isView`) instead of
323
+ * `instanceof AtscriptDbView` — in a bundle that carries two copies of the
324
+ * core (app bundle + external adapter), `instanceof` is false and the adapter
325
+ * would create an empty physical table under the view's name.
326
+ * @since 0.1.128
327
+ */
328
+ declare function isAtscriptDbView(readable: AtscriptDbReadable<any, any, any, any, any, any, any>): readable is AtscriptDbView<any, any, any, any, any, any, any>;
270
329
  //#endregion
271
330
  //#region src/table/db-space.d.ts
272
331
  /**
@@ -343,6 +402,25 @@ declare class DbSpace {
343
402
  * Drops a view by name. Used by schema sync to remove views no longer in the schema.
344
403
  */
345
404
  dropViewByName(viewName: string): Promise<void>;
405
+ /**
406
+ * Drops a group of mutually referencing tables as one operation.
407
+ * Used by schema sync to remove a foreign-key cycle no longer in the schema.
408
+ * @since 0.1.128
409
+ */
410
+ dropTablesByName(tableNames: string[]): Promise<void>;
411
+ /**
412
+ * Live foreign keys referencing `tableName`, or `undefined` when the
413
+ * adapter cannot introspect them. Used by schema sync for drop ordering
414
+ * and surviving-reference checks of tables without a registered readable.
415
+ * @since 0.1.128
416
+ */
417
+ getReferencingForeignKeys(tableName: string): Promise<TReferencingForeignKey[] | undefined>;
418
+ /**
419
+ * A factory-fresh adapter with NO registered readable. Only the name-taking
420
+ * primitives may run on it (`dropTableByName`, `dropViewByName`,
421
+ * `dropTablesByName`, `getReferencingForeignKeys`) — adapters derive the
422
+ * schema for those from the driver/connection, not from a bound table.
423
+ */
346
424
  private _getAdminAdapter;
347
425
  /**
348
426
  * Finds all child tables with FKs pointing to the given parent table name.
@@ -356,4 +434,4 @@ declare class DbSpace {
356
434
  private _getFkLookupTarget;
357
435
  }
358
436
  //#endregion
359
- export { TViewColumnMapping as a, AtscriptQueryNode$1 as c, TViewPlan as d, translateQueryTree as f, NativeIntegrity as h, AtscriptDbView as i, AtscriptRef as l, IntegrityStrategy as m, TAdapterFactory as n, AtscriptQueryComparison as o, AtscriptDbTable as p, TDbSpaceOptions as r, AtscriptQueryFieldRef$1 as s, DbSpace as t, TViewJoin as u };
437
+ export { TViewColumnMapping as a, AtscriptQueryFieldRef$1 as c, TViewJoin as d, TViewPlan as f, NativeIntegrity as g, IntegrityStrategy as h, AtscriptDbView as i, AtscriptQueryNode$1 as l, AtscriptDbTable as m, TAdapterFactory as n, isAtscriptDbView as o, translateQueryTree as p, TDbSpaceOptions as r, AtscriptQueryComparison as s, DbSpace as t, AtscriptRef as u };
@@ -1,6 +1,6 @@
1
- import { C as TCascadeResolver, F as TDbDeleteResult, H as TDbInsertResult, K as TDbUpdateResult, V as TDbInsertManyResult, X as TFkLookupResolver, _t as TGenericLogger, a as TDbEncryptionOptions, c as BaseDbAdapter, ct as TWriteTableResolver, i as DbEncryption, ot as TTableResolver, pt as TableMetadata, t as AtscriptDbReadable } from "./db-readable-C0nDKX8A.cjs";
2
- import { FilterExpr } from "@uniqu/core";
1
+ import { C as NullableOptional, Ct as TWriteOptions, E as TCascadeResolver, G as TDbInsertResult, Pt as TGenericLogger, Q as TDbUpdateResult, R as TDbDeleteResult, W as TDbInsertManyResult, a as TDbEncryptionOptions, bt as TTableResolver, c as BaseDbAdapter, ct as TFkLookupResolver, g as DbPatch, ht as TReferencingForeignKey, i as DbEncryption, kt as TableMetadata, nt as TDeleteOptions, t as AtscriptDbReadable, v as DbRow, wt as TWriteTableResolver, xt as TTouchManyOptions } from "./db-readable-Bn1bV_eC.mjs";
3
2
  import { AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, NavPropsOf, OwnPropsOf, PrimaryKeyOf, TAtscriptAnnotatedType, TAtscriptDataType, Validator } from "@atscript/typescript/utils";
3
+ import { FilterExpr } from "@uniqu/core";
4
4
 
5
5
  //#region src/strategies/integrity.d.ts
6
6
  /**
@@ -24,7 +24,7 @@ declare class NativeIntegrity extends IntegrityStrategy {
24
24
  }
25
25
  //#endregion
26
26
  //#region src/table/db-table.d.ts
27
- declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = FlatOf<T>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = OwnPropsOf<T>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
27
+ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = NullableOptional<FlatOf<T>>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = NullableOptional<OwnPropsOf<T>>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
28
28
  protected _cascadeResolver?: TCascadeResolver;
29
29
  protected _fkLookupResolver?: TFkLookupResolver;
30
30
  protected readonly _integrity: IntegrityStrategy;
@@ -53,9 +53,7 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
53
53
  * Inserts a single record. Delegates to {@link insertMany} for unified
54
54
  * nested creation support.
55
55
  */
56
- insertOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
57
- maxDepth?: number;
58
- }): Promise<TDbInsertResult>;
56
+ insertOne(payload: DbPatch<DataType>, opts?: TWriteOptions<DataType>): Promise<TDbInsertResult>;
59
57
  /**
60
58
  * Inserts multiple records with batch-optimized nested creation.
61
59
  *
@@ -66,17 +64,16 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
66
64
  * (they receive our PKs as their FKs). Fully recursive — nested records
67
65
  * with their own nav data trigger further batch inserts at each level.
68
66
  * Recursive up to `maxDepth` (default 3).
67
+ *
68
+ * `opts.guard` (since 0.1.128) runs once inside the transaction, after
69
+ * defaults + validation, with the prepared rows — see {@link TWriteOptions}.
69
70
  */
70
- insertMany(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
71
- maxDepth?: number;
72
- }): Promise<TDbInsertManyResult>;
71
+ insertMany(payloads: Array<DbPatch<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbInsertManyResult>;
73
72
  /**
74
73
  * Replaces a single record identified by primary key(s).
75
74
  * Delegates to {@link bulkReplace} for unified nested relation support.
76
75
  */
77
- replaceOne(payload: DataType & Record<string, unknown>, opts?: {
78
- maxDepth?: number;
79
- }): Promise<TDbUpdateResult>;
76
+ replaceOne(payload: DbRow<DataType>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
80
77
  /**
81
78
  * Replaces multiple records with deep nested relation support.
82
79
  *
@@ -84,37 +81,69 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
84
81
  * replaced first (their PKs become our FKs), FROM dependents are replaced
85
82
  * after (they receive our PKs as their FKs), VIA relations clear and
86
83
  * re-create junction rows. Fully recursive up to `maxDepth` (default 3).
84
+ *
85
+ * `opts.guard` (since 0.1.128) runs once inside the transaction, after
86
+ * `$cas` extraction, defaults + validation — see {@link TWriteOptions}.
87
87
  */
88
- bulkReplace(payloads: Array<DataType & Record<string, unknown>>, opts?: {
89
- maxDepth?: number;
90
- }): Promise<TDbUpdateResult>;
88
+ bulkReplace(payloads: Array<DbRow<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
91
89
  /**
92
90
  * Partially updates a single record identified by primary key(s).
93
91
  * Delegates to {@link bulkUpdate} for unified nested relation support.
94
92
  */
95
- updateOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
96
- maxDepth?: number;
97
- }): Promise<TDbUpdateResult>;
93
+ updateOne(payload: DbPatch<DataType>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
98
94
  /**
99
95
  * Partially updates multiple records with deep nested relation support.
100
96
  *
101
97
  * Only TO relations (1:1, N:1) are supported for patching. FROM/VIA
102
98
  * relations will error — use {@link bulkReplace} for those.
103
99
  * Recursive up to `maxDepth` (default 3).
100
+ *
101
+ * `opts.guard` (since 0.1.128) runs once inside the transaction, after
102
+ * `$cas` extraction and validation, with the patches (identifying fields
103
+ * present, `$cas` removed) — see {@link TWriteOptions}.
104
+ */
105
+ bulkUpdate(payloads: Array<DbPatch<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
106
+ /**
107
+ * Batch versioned touch (since 0.1.129): bumps the version of every listed
108
+ * row by exactly one, each row guarded by its own expected version. This is
109
+ * the batch fence `updateMany(orFilter, {})` used to be before 0.1.128 (an
110
+ * empty patch is a no-op since then and takes no lock).
111
+ *
112
+ * Each key carries the primary key field(s) (composite supported) plus the
113
+ * version column and NOTHING else — a touch has no payload. Unique indexes
114
+ * do not identify a touch key. `undefined`-valued properties are ignored,
115
+ * like in every write payload. Empty `keys` → `{ 0, 0 }` without a statement.
116
+ *
117
+ * `require: 'all'` (default): one count over the whole key set runs FIRST;
118
+ * a stale or missing row throws {@link CasMismatchError} before any write.
119
+ * The bumps then run as `updateMany(orFilter, {})` chunks of at most
120
+ * {@link TOUCH_MANY_CHUNK} keys inside one adapter transaction; a summed
121
+ * `matchedCount` short of `keys.length` (a row moved between the count and
122
+ * the bump) throws the same error — SQL engines roll every bump back. The
123
+ * pre-count is therefore a deliberate double check on SQL: it is what makes
124
+ * the guarantee hold on adapters whose `withTransaction` is a passthrough
125
+ * (the memory adapter, a Mongo standalone topology) — there it covers the
126
+ * common stale case and the residual race window is accepted.
127
+ * `require: 'any'`: no pre-count, the honest summed result is returned.
128
+ *
129
+ * No `guard`, no `onWrite`; not exposed over HTTP.
104
130
  */
105
- bulkUpdate(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
106
- maxDepth?: number;
107
- }): Promise<TDbUpdateResult>;
131
+ touchMany(keys: Array<DbPatch<DataType>>, opts?: TTouchManyOptions): Promise<TDbUpdateResult>;
108
132
  /**
109
133
  * Deletes a single record by any type-compatible identifier — primary key
110
134
  * or single-field unique index. Uses the same resolution logic as `findById`.
111
135
  *
112
136
  * When the adapter does not support native foreign keys (e.g. MongoDB),
113
137
  * cascade and setNull actions are applied before the delete.
114
- */
115
- deleteOne(id: IdType): Promise<TDbDeleteResult>;
116
- updateMany(filter: FilterExpr<FlatType>, data: Partial<DataType> & Record<string, unknown>): Promise<TDbUpdateResult>;
117
- replaceMany(filter: FilterExpr<FlatType>, data: Record<string, unknown>): Promise<TDbUpdateResult>;
138
+ *
139
+ * `opts.guard` (since 0.1.128) runs inside the transaction once the id has
140
+ * resolved to a filter, before cascade / delete — see {@link TDeleteOptions}.
141
+ * An id that resolves to no filter answers `{ deletedCount: 0 }` without
142
+ * calling the guard.
143
+ */
144
+ deleteOne(id: IdType, opts?: TDeleteOptions<DataType>): Promise<TDbDeleteResult>;
145
+ updateMany(filter: FilterExpr<FlatType>, data: DbPatch<DataType>): Promise<TDbUpdateResult>;
146
+ replaceMany(filter: FilterExpr<FlatType>, data: DbRow<DataType>): Promise<TDbUpdateResult>;
118
147
  deleteMany(filter: FilterExpr<FlatType>): Promise<TDbDeleteResult>;
119
148
  /**
120
149
  * Synchronizes indexes between Atscript definitions and the database.
@@ -140,11 +169,31 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
140
169
  */
141
170
  protected _encryptItems(items: Array<Record<string, unknown>>, mode: "write" | "patch"): Promise<void>;
142
171
  /**
143
- * Applies default values for fields that are missing from the payload.
144
- * Defaults handled natively by the DB engine are skipped — the field stays
145
- * absent so the DB's own DEFAULT clause applies.
172
+ * Lazy pre-image read for a guard's `current(i)`: `null` when the row has
173
+ * no identifying key (e.g. an auto-increment insert) or the key cannot be
174
+ * resolved — never throws for a missing key.
175
+ * @internal
176
+ */
177
+ _readPreImage(row: unknown): Promise<DataType | null>;
178
+ /**
179
+ * Applies `@db.default` values in place to a row's absent fields — the
180
+ * defaults pass every insert / replace path runs before validation.
181
+ * Static value defaults (`@db.default 'x'`) are filled on EVERY adapter
182
+ * (since 0.1.128 — writing the column's own default explicitly is
183
+ * equivalent to leaving it to the DDL `DEFAULT`, and write guards see the
184
+ * full row). Function defaults (`now` / `uuid` / `increment` / custom) the
185
+ * adapter handles natively are NOT filled — the field stays absent so the
186
+ * engine's own default applies. The version column is never touched.
146
187
  */
147
188
  protected _applyDefaults(data: Record<string, unknown>): Record<string, unknown>;
189
+ /**
190
+ * The JS value for a `@db.default 'literal'`: strings (including unions of
191
+ * string literals) are used as-is, every other design type is parsed as
192
+ * JSON — the same value the SQL adapters put into the DDL `DEFAULT` clause.
193
+ * A literal that is not valid JSON falls back to the raw string so the
194
+ * validator reports it against the field instead of a bare `SyntaxError`.
195
+ */
196
+ private _parseValueDefault;
148
197
  /**
149
198
  * Extracts a record-identifying filter from a payload.
150
199
  *
@@ -235,7 +284,7 @@ interface TViewColumnMapping {
235
284
  * const users = await activeUsers.findMany({ filter: {}, controls: {} })
236
285
  * ```
237
286
  */
238
- declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = FlatOf<T>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = OwnPropsOf<T>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
287
+ declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType, DataType = TAtscriptDataType<T>, FlatType = NullableOptional<FlatOf<T>>, A extends BaseDbAdapter = BaseDbAdapter, IdType = PrimaryKeyOf<T>, OwnProps = NullableOptional<OwnPropsOf<T>>, NavType extends Record<string, unknown> = NavPropsOf<T>> extends AtscriptDbReadable<T, DataType, FlatType, A, IdType, OwnProps, NavType> {
239
288
  private _viewPlan?;
240
289
  get isView(): boolean;
241
290
  /**
@@ -267,6 +316,16 @@ declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
267
316
  */
268
317
  getViewColumnMappings(): TViewColumnMapping[];
269
318
  }
319
+ /**
320
+ * Structural type guard for views: `true` when the readable reports
321
+ * `isView`, whether or not it is an `AtscriptDbView` instance of THIS copy
322
+ * of `@atscript/db`. Adapters must use this (or `readable.isView`) instead of
323
+ * `instanceof AtscriptDbView` — in a bundle that carries two copies of the
324
+ * core (app bundle + external adapter), `instanceof` is false and the adapter
325
+ * would create an empty physical table under the view's name.
326
+ * @since 0.1.128
327
+ */
328
+ declare function isAtscriptDbView(readable: AtscriptDbReadable<any, any, any, any, any, any, any>): readable is AtscriptDbView<any, any, any, any, any, any, any>;
270
329
  //#endregion
271
330
  //#region src/table/db-space.d.ts
272
331
  /**
@@ -343,6 +402,25 @@ declare class DbSpace {
343
402
  * Drops a view by name. Used by schema sync to remove views no longer in the schema.
344
403
  */
345
404
  dropViewByName(viewName: string): Promise<void>;
405
+ /**
406
+ * Drops a group of mutually referencing tables as one operation.
407
+ * Used by schema sync to remove a foreign-key cycle no longer in the schema.
408
+ * @since 0.1.128
409
+ */
410
+ dropTablesByName(tableNames: string[]): Promise<void>;
411
+ /**
412
+ * Live foreign keys referencing `tableName`, or `undefined` when the
413
+ * adapter cannot introspect them. Used by schema sync for drop ordering
414
+ * and surviving-reference checks of tables without a registered readable.
415
+ * @since 0.1.128
416
+ */
417
+ getReferencingForeignKeys(tableName: string): Promise<TReferencingForeignKey[] | undefined>;
418
+ /**
419
+ * A factory-fresh adapter with NO registered readable. Only the name-taking
420
+ * primitives may run on it (`dropTableByName`, `dropViewByName`,
421
+ * `dropTablesByName`, `getReferencingForeignKeys`) — adapters derive the
422
+ * schema for those from the driver/connection, not from a bound table.
423
+ */
346
424
  private _getAdminAdapter;
347
425
  /**
348
426
  * Finds all child tables with FKs pointing to the given parent table name.
@@ -356,4 +434,4 @@ declare class DbSpace {
356
434
  private _getFkLookupTarget;
357
435
  }
358
436
  //#endregion
359
- export { TViewColumnMapping as a, AtscriptQueryNode$1 as c, TViewPlan as d, translateQueryTree as f, NativeIntegrity as h, AtscriptDbView as i, AtscriptRef as l, IntegrityStrategy as m, TAdapterFactory as n, AtscriptQueryComparison as o, AtscriptDbTable as p, TDbSpaceOptions as r, AtscriptQueryFieldRef$1 as s, DbSpace as t, TViewJoin as u };
437
+ export { TViewColumnMapping as a, AtscriptQueryFieldRef$1 as c, TViewJoin as d, TViewPlan as f, NativeIntegrity as g, IntegrityStrategy as h, AtscriptDbView as i, AtscriptQueryNode$1 as l, AtscriptDbTable as m, TAdapterFactory as n, isAtscriptDbView as o, translateQueryTree as p, TDbSpaceOptions as r, AtscriptQueryComparison as s, DbSpace as t, AtscriptRef as u };