@atscript/db 0.1.39 → 0.1.40
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/README.md +18 -18
- package/dist/agg.cjs +8 -3
- package/dist/agg.d.cts +7 -0
- package/dist/agg.d.mts +7 -0
- package/dist/agg.mjs +7 -3
- package/dist/control-DRgryKeg.cjs +14 -0
- package/dist/{control_as-bjmwe24C.mjs → control-IANbnfjG.mjs} +6 -18
- package/dist/db-readable-BQQzfguJ.d.cts +1249 -0
- package/dist/db-readable-Bbr4CjMb.d.mts +1249 -0
- package/dist/db-space-BUrQ5BFm.d.mts +309 -0
- package/dist/db-space-Vxpcnyt5.d.cts +309 -0
- package/dist/db-validator-plugin-07kDiis2.d.cts +22 -0
- package/dist/db-validator-plugin-CiqsHTI_.d.mts +22 -0
- package/dist/db-view-BntnAmXO.cjs +3071 -0
- package/dist/db-view-ZsoN91-q.mjs +2970 -0
- package/dist/index.cjs +95 -2801
- package/dist/index.d.cts +137 -0
- package/dist/index.d.mts +137 -0
- package/dist/index.mjs +55 -2761
- package/dist/{nested-writer-BkqL7cp3.cjs → nested-writer-BDXsDMPP.cjs} +196 -150
- package/dist/{nested-writer-NEN51mnR.mjs → nested-writer-Dmm1gbZV.mjs} +118 -70
- package/dist/ops-BdRAFLKY.d.mts +67 -0
- package/dist/ops-DXJ4Zw0P.d.cts +67 -0
- package/dist/ops.cjs +123 -0
- package/dist/ops.d.cts +2 -0
- package/dist/ops.d.mts +2 -0
- package/dist/ops.mjs +112 -0
- package/dist/plugin.cjs +90 -109
- package/dist/plugin.d.cts +6 -0
- package/dist/plugin.d.mts +6 -0
- package/dist/plugin.mjs +29 -49
- package/dist/rel.cjs +20 -20
- package/dist/rel.d.cts +119 -0
- package/dist/rel.d.mts +119 -0
- package/dist/rel.mjs +4 -5
- package/dist/{relation-helpers-guFL_oRf.cjs → relation-helpers-BYvsE1tR.cjs} +26 -22
- package/dist/{relation-helpers-DyBIlQnB.mjs → relation-helpers-CLasawQq.mjs} +11 -6
- package/dist/{relation-loader-Dv7qXYq7.mjs → relation-loader-BEOTXNcq.mjs} +63 -43
- package/dist/{relation-loader-CpnDRf9k.cjs → relation-loader-CRC5LcqM.cjs} +74 -49
- package/dist/shared.cjs +13 -13
- package/dist/{shared.d.ts → shared.d.cts} +14 -13
- package/dist/shared.d.mts +71 -0
- package/dist/shared.mjs +2 -3
- package/dist/sync.cjs +300 -252
- package/dist/sync.d.cts +369 -0
- package/dist/sync.d.mts +369 -0
- package/dist/sync.mjs +284 -233
- package/dist/{validation-utils-DEoCMmEb.cjs → validation-utils-DVJDijnB.cjs} +141 -109
- package/dist/{validation-utils-DhR_mtKa.mjs → validation-utils-DhjIjP1-.mjs} +71 -37
- package/package.json +30 -29
- package/LICENSE +0 -21
- package/dist/agg-BJFJ3dFQ.mjs +0 -8
- package/dist/agg-DnUWAOK8.cjs +0 -14
- package/dist/agg.d.ts +0 -13
- package/dist/chunk-CrpGerW8.cjs +0 -31
- package/dist/control_as-BFPERAF_.cjs +0 -28
- package/dist/index.d.ts +0 -1706
- package/dist/logger-B7oxCfLQ.mjs +0 -12
- package/dist/logger-Dt2v_-wb.cjs +0 -18
- package/dist/plugin.d.ts +0 -5
- package/dist/rel.d.ts +0 -1305
- package/dist/relation-loader-D4mTw6yH.cjs +0 -4
- package/dist/relation-loader-Ggy1ujwR.mjs +0 -4
- package/dist/sync.d.ts +0 -1878
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { F as TDbInsertResult, H as TFkLookupResolver, O as TDbDeleteResult, P as TDbInsertManyResult, S as TCascadeResolver, Y as TTableResolver, Z as TWriteTableResolver, l as TGenericLogger, o as BaseDbAdapter, s as TableMetadata, t as AtscriptDbReadable, z as TDbUpdateResult } from "./db-readable-Bbr4CjMb.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";
|
|
3
|
+
import { FilterExpr } from "@uniqu/core";
|
|
4
|
+
|
|
5
|
+
//#region src/strategies/integrity.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Strategy for referential integrity enforcement.
|
|
8
|
+
* Two implementations: {@link NativeIntegrity} (DB handles FK constraints)
|
|
9
|
+
* and `ApplicationIntegrity` (generic layer validates + cascades).
|
|
10
|
+
*/
|
|
11
|
+
declare abstract class IntegrityStrategy {
|
|
12
|
+
abstract validateForeignKeys(items: Array<Record<string, unknown>>, meta: TableMetadata, fkLookupResolver: TFkLookupResolver | undefined, writeTableResolver: TWriteTableResolver | undefined, partial?: boolean, excludeTargetTable?: string): Promise<void>;
|
|
13
|
+
abstract cascadeBeforeDelete(filter: FilterExpr, tableName: string, meta: TableMetadata, cascadeResolver: TCascadeResolver, translateFilter: (f: FilterExpr) => FilterExpr, adapter: BaseDbAdapter): Promise<void>;
|
|
14
|
+
abstract needsCascade(cascadeResolver: TCascadeResolver | undefined): boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Integrity strategy for adapters with native FK support (e.g. SQLite, MySQL).
|
|
18
|
+
* All operations are no-ops — the database engine enforces constraints.
|
|
19
|
+
*/
|
|
20
|
+
declare class NativeIntegrity extends IntegrityStrategy {
|
|
21
|
+
validateForeignKeys(): Promise<void>;
|
|
22
|
+
cascadeBeforeDelete(): Promise<void>;
|
|
23
|
+
needsCascade(): boolean;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
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> {
|
|
28
|
+
protected _cascadeResolver?: TCascadeResolver;
|
|
29
|
+
protected _fkLookupResolver?: TFkLookupResolver;
|
|
30
|
+
protected readonly _integrity: IntegrityStrategy;
|
|
31
|
+
protected readonly validators: Map<string, Validator<T, DataType>>;
|
|
32
|
+
constructor(_type: T, adapter: A, logger?: TGenericLogger, _tableResolver?: TTableResolver, _writeTableResolver?: TWriteTableResolver);
|
|
33
|
+
/**
|
|
34
|
+
* Sets the cascade resolver for application-level cascade deletes.
|
|
35
|
+
* Called by DbSpace after table creation.
|
|
36
|
+
*/
|
|
37
|
+
setCascadeResolver(resolver: TCascadeResolver): void;
|
|
38
|
+
/**
|
|
39
|
+
* Sets the FK lookup resolver for application-level FK validation.
|
|
40
|
+
* Called by DbSpace after table creation.
|
|
41
|
+
*/
|
|
42
|
+
setFkLookupResolver(resolver: TFkLookupResolver): void;
|
|
43
|
+
/**
|
|
44
|
+
* Returns a cached validator for the given purpose.
|
|
45
|
+
* Built with adapter plugins from {@link BaseDbAdapter.getValidatorPlugins}.
|
|
46
|
+
*
|
|
47
|
+
* Standard purposes: `'insert'`, `'update'`, `'patch'`.
|
|
48
|
+
* Adapters may define additional purposes.
|
|
49
|
+
*/
|
|
50
|
+
getValidator(purpose: string): Validator<T, DataType>;
|
|
51
|
+
/**
|
|
52
|
+
* Inserts a single record. Delegates to {@link insertMany} for unified
|
|
53
|
+
* nested creation support.
|
|
54
|
+
*/
|
|
55
|
+
insertOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
|
|
56
|
+
maxDepth?: number;
|
|
57
|
+
}): Promise<TDbInsertResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Inserts multiple records with batch-optimized nested creation.
|
|
60
|
+
*
|
|
61
|
+
* Supports **nested creation**: if payloads include data for navigation
|
|
62
|
+
* fields (`@db.rel.to` / `@db.rel.from`), related records are created
|
|
63
|
+
* automatically in batches. TO dependencies are batch-created first
|
|
64
|
+
* (their PKs become our FKs), FROM dependents are batch-created after
|
|
65
|
+
* (they receive our PKs as their FKs). Fully recursive — nested records
|
|
66
|
+
* with their own nav data trigger further batch inserts at each level.
|
|
67
|
+
* Recursive up to `maxDepth` (default 3).
|
|
68
|
+
*/
|
|
69
|
+
insertMany(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
|
|
70
|
+
maxDepth?: number;
|
|
71
|
+
}): Promise<TDbInsertManyResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Replaces a single record identified by primary key(s).
|
|
74
|
+
* Delegates to {@link bulkReplace} for unified nested relation support.
|
|
75
|
+
*/
|
|
76
|
+
replaceOne(payload: DataType & Record<string, unknown>, opts?: {
|
|
77
|
+
maxDepth?: number;
|
|
78
|
+
}): Promise<TDbUpdateResult>;
|
|
79
|
+
/**
|
|
80
|
+
* Replaces multiple records with deep nested relation support.
|
|
81
|
+
*
|
|
82
|
+
* Supports all relation types (TO, FROM, VIA). TO dependencies are
|
|
83
|
+
* replaced first (their PKs become our FKs), FROM dependents are replaced
|
|
84
|
+
* after (they receive our PKs as their FKs), VIA relations clear and
|
|
85
|
+
* re-create junction rows. Fully recursive up to `maxDepth` (default 3).
|
|
86
|
+
*/
|
|
87
|
+
bulkReplace(payloads: Array<DataType & Record<string, unknown>>, opts?: {
|
|
88
|
+
maxDepth?: number;
|
|
89
|
+
}): Promise<TDbUpdateResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Partially updates a single record identified by primary key(s).
|
|
92
|
+
* Delegates to {@link bulkUpdate} for unified nested relation support.
|
|
93
|
+
*/
|
|
94
|
+
updateOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
|
|
95
|
+
maxDepth?: number;
|
|
96
|
+
}): Promise<TDbUpdateResult>;
|
|
97
|
+
/**
|
|
98
|
+
* Partially updates multiple records with deep nested relation support.
|
|
99
|
+
*
|
|
100
|
+
* Only TO relations (1:1, N:1) are supported for patching. FROM/VIA
|
|
101
|
+
* relations will error — use {@link bulkReplace} for those.
|
|
102
|
+
* Recursive up to `maxDepth` (default 3).
|
|
103
|
+
*/
|
|
104
|
+
bulkUpdate(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
|
|
105
|
+
maxDepth?: number;
|
|
106
|
+
}): Promise<TDbUpdateResult>;
|
|
107
|
+
/**
|
|
108
|
+
* Deletes a single record by any type-compatible identifier — primary key
|
|
109
|
+
* or single-field unique index. Uses the same resolution logic as `findById`.
|
|
110
|
+
*
|
|
111
|
+
* When the adapter does not support native foreign keys (e.g. MongoDB),
|
|
112
|
+
* cascade and setNull actions are applied before the delete.
|
|
113
|
+
*/
|
|
114
|
+
deleteOne(id: IdType): Promise<TDbDeleteResult>;
|
|
115
|
+
updateMany(filter: FilterExpr<FlatType>, data: Partial<DataType> & Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
116
|
+
replaceMany(filter: FilterExpr<FlatType>, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
117
|
+
deleteMany(filter: FilterExpr<FlatType>): Promise<TDbDeleteResult>;
|
|
118
|
+
/**
|
|
119
|
+
* Synchronizes indexes between Atscript definitions and the database.
|
|
120
|
+
*/
|
|
121
|
+
syncIndexes(): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Ensures the table/collection exists in the database.
|
|
124
|
+
*/
|
|
125
|
+
ensureTable(): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Applies default values for fields that are missing from the payload.
|
|
128
|
+
* Defaults handled natively by the DB engine are skipped — the field stays
|
|
129
|
+
* absent so the DB's own DEFAULT clause applies.
|
|
130
|
+
*/
|
|
131
|
+
protected _applyDefaults(data: Record<string, unknown>): Record<string, unknown>;
|
|
132
|
+
/**
|
|
133
|
+
* Extracts primary key field(s) from a payload to build a filter.
|
|
134
|
+
*/
|
|
135
|
+
protected _extractPrimaryKeyFilter(payload: Record<string, unknown>): FilterExpr;
|
|
136
|
+
/**
|
|
137
|
+
* Pre-validate items (type validation + FK constraints) without inserting them.
|
|
138
|
+
* Used by parent tables to validate FROM children before the main insert,
|
|
139
|
+
* ensuring errors are caught before the parent is committed.
|
|
140
|
+
*
|
|
141
|
+
* @param opts.excludeFkTargetTable - Skip FK validation to this table (the parent).
|
|
142
|
+
*/
|
|
143
|
+
preValidateItems(items: Array<Record<string, unknown>>, opts?: {
|
|
144
|
+
excludeFkTargetTable?: string;
|
|
145
|
+
}): Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Builds a validator for a given purpose with adapter plugins.
|
|
148
|
+
*
|
|
149
|
+
* Uses annotation-based `replace` callback to make `@meta.id` and
|
|
150
|
+
* `@db.default` fields optional — works at all nesting levels
|
|
151
|
+
* (including inside nav field target types).
|
|
152
|
+
*/
|
|
153
|
+
protected _buildValidator(purpose: string): Validator<T, DataType>;
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/query/query-tree.d.ts
|
|
157
|
+
/** A single join in a view query plan. */
|
|
158
|
+
interface TViewJoin {
|
|
159
|
+
targetType: () => TAtscriptAnnotatedType;
|
|
160
|
+
targetTable: string;
|
|
161
|
+
condition: AtscriptQueryNode;
|
|
162
|
+
}
|
|
163
|
+
/** Resolved view query plan produced by AtscriptDbView. */
|
|
164
|
+
interface TViewPlan {
|
|
165
|
+
entryType: () => TAtscriptAnnotatedType;
|
|
166
|
+
entryTable: string;
|
|
167
|
+
joins: TViewJoin[];
|
|
168
|
+
filter?: AtscriptQueryNode;
|
|
169
|
+
having?: AtscriptQueryNode;
|
|
170
|
+
materialized: boolean;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Translates a JS-emitted query tree into a FilterExpr.
|
|
174
|
+
* Resolves field references (type + field path) to physical column names
|
|
175
|
+
* via the provided resolver function.
|
|
176
|
+
*/
|
|
177
|
+
declare function translateQueryTree(node: AtscriptQueryNode, resolveField: (ref: AtscriptQueryFieldRef) => string): FilterExpr;
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/table/db-view.d.ts
|
|
180
|
+
interface TViewColumnMapping {
|
|
181
|
+
viewColumn: string;
|
|
182
|
+
sourceTable: string;
|
|
183
|
+
sourceColumn: string;
|
|
184
|
+
/** Aggregate function name ('sum'|'avg'|'count'|'min'|'max') if this is an aggregate column. */
|
|
185
|
+
aggFn?: string;
|
|
186
|
+
/** Source field for the aggregate function ('*' for COUNT(*)). */
|
|
187
|
+
aggField?: string;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Database view abstraction driven by Atscript `@db.view.*` annotations.
|
|
191
|
+
*
|
|
192
|
+
* Extends {@link AtscriptDbReadable} with view plan resolution — entry table,
|
|
193
|
+
* joins, filter, and materialization flag. Read operations are inherited;
|
|
194
|
+
* write operations are not available on views.
|
|
195
|
+
*
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const adapter = new SqliteAdapter(db)
|
|
198
|
+
* const activeUsers = new AtscriptDbView(ActiveUsersType, adapter)
|
|
199
|
+
* const users = await activeUsers.findMany({ filter: {}, controls: {} })
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
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> {
|
|
203
|
+
private _viewPlan?;
|
|
204
|
+
get isView(): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Whether this is an external view — declared with `@db.view` only,
|
|
207
|
+
* without `@db.view.for`. External views reference pre-existing DB views
|
|
208
|
+
* and are not managed (created/dropped) by schema sync.
|
|
209
|
+
*/
|
|
210
|
+
get isExternal(): boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Lazily resolves the view plan from `@db.view.*` metadata.
|
|
213
|
+
*
|
|
214
|
+
* - `db.view.for` → entry type ref (required)
|
|
215
|
+
* - `db.view.joins` → array of `{ target, condition }` (optional, multiple)
|
|
216
|
+
* - `db.view.filter` → query tree (optional)
|
|
217
|
+
* - `db.view.materialized` → boolean (optional)
|
|
218
|
+
*/
|
|
219
|
+
get viewPlan(): TViewPlan;
|
|
220
|
+
/**
|
|
221
|
+
* Resolves a query field ref to a quoted `table.column` SQL fragment.
|
|
222
|
+
*
|
|
223
|
+
* @param ref - The field reference from the query tree.
|
|
224
|
+
* @param qi - Identifier quoting function (e.g. backtick for MySQL, double-quote for SQLite).
|
|
225
|
+
* Defaults to double-quote wrapping for backwards compatibility.
|
|
226
|
+
*/
|
|
227
|
+
resolveFieldRef(ref: AtscriptQueryFieldRef, qi?: (name: string) => string): string;
|
|
228
|
+
/**
|
|
229
|
+
* Maps each view field to its source table and column via ref chain.
|
|
230
|
+
* Fields without refs (inline definitions) map to the entry table with the same name.
|
|
231
|
+
*/
|
|
232
|
+
getViewColumnMappings(): TViewColumnMapping[];
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/table/db-space.d.ts
|
|
236
|
+
/**
|
|
237
|
+
* Adapter factory function. Called once per table/view to create a fresh adapter instance.
|
|
238
|
+
* Each readable gets its own adapter (1:1 relationship required by BaseDbAdapter).
|
|
239
|
+
*/
|
|
240
|
+
type TAdapterFactory = () => BaseDbAdapter;
|
|
241
|
+
/**
|
|
242
|
+
* A database space — a registry of tables and views sharing the same adapter type and driver.
|
|
243
|
+
*
|
|
244
|
+
* `DbSpace` solves the cross-table discovery problem: when table A has a relation
|
|
245
|
+
* to table B, it needs to find and query table B. The space acts as the registry
|
|
246
|
+
* that makes this possible via the table resolver callback.
|
|
247
|
+
*
|
|
248
|
+
* Each table/view gets its own adapter instance (created by the factory), but all
|
|
249
|
+
* share the same space and can discover each other for `$with` relation loading.
|
|
250
|
+
*
|
|
251
|
+
* ```typescript
|
|
252
|
+
* // SQLite
|
|
253
|
+
* const driver = new BetterSqlite3Driver(':memory:')
|
|
254
|
+
* const db = new DbSpace(() => new SqliteAdapter(driver))
|
|
255
|
+
* const users = db.getTable(UsersType)
|
|
256
|
+
* const activeUsers = db.getView(ActiveUsersType)
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
declare class DbSpace {
|
|
260
|
+
protected readonly adapterFactory: TAdapterFactory;
|
|
261
|
+
protected readonly logger: TGenericLogger;
|
|
262
|
+
private _readables;
|
|
263
|
+
/** All tables created in this space — used for reverse FK lookup during cascade. */
|
|
264
|
+
private _allTables;
|
|
265
|
+
/** Lazily created adapter for administrative ops (drop table/view) that don't need a registered readable. */
|
|
266
|
+
private _adminAdapter?;
|
|
267
|
+
constructor(adapterFactory: TAdapterFactory, logger?: TGenericLogger);
|
|
268
|
+
/**
|
|
269
|
+
* Auto-detects whether the type is a table or view and returns the
|
|
270
|
+
* appropriate instance. Uses `@db.view` or `@db.view.for` presence to distinguish.
|
|
271
|
+
*/
|
|
272
|
+
get<T extends TAtscriptAnnotatedType>(type: T, logger?: TGenericLogger): AtscriptDbReadable<T>;
|
|
273
|
+
/**
|
|
274
|
+
* Returns the table for the given annotated type.
|
|
275
|
+
* Creates the table + adapter on first access, caches for subsequent calls.
|
|
276
|
+
*/
|
|
277
|
+
getTable<T extends TAtscriptAnnotatedType>(type: T, logger?: TGenericLogger): AtscriptDbTable<T>;
|
|
278
|
+
/**
|
|
279
|
+
* Returns the view for the given annotated type.
|
|
280
|
+
* Creates the view + adapter on first access, caches for subsequent calls.
|
|
281
|
+
*/
|
|
282
|
+
getView<T extends TAtscriptAnnotatedType>(type: T, logger?: TGenericLogger): AtscriptDbView<T>;
|
|
283
|
+
/**
|
|
284
|
+
* Returns the adapter for the given annotated type.
|
|
285
|
+
* Creates the table/view + adapter on first access if needed.
|
|
286
|
+
*/
|
|
287
|
+
getAdapter(type: TAtscriptAnnotatedType): BaseDbAdapter;
|
|
288
|
+
/**
|
|
289
|
+
* Drops a table by name. Used by schema sync to remove tables no longer in the schema.
|
|
290
|
+
*/
|
|
291
|
+
dropTableByName(tableName: string): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Drops a view by name. Used by schema sync to remove views no longer in the schema.
|
|
294
|
+
*/
|
|
295
|
+
dropViewByName(viewName: string): Promise<void>;
|
|
296
|
+
private _getAdminAdapter;
|
|
297
|
+
/**
|
|
298
|
+
* Finds all child tables with FKs pointing to the given parent table name.
|
|
299
|
+
* Accesses `table.foreignKeys` which triggers `_flatten()` if needed.
|
|
300
|
+
*/
|
|
301
|
+
private _getCascadeTargets;
|
|
302
|
+
/**
|
|
303
|
+
* Resolves a table name to a queryable target for FK validation.
|
|
304
|
+
* Searches all registered tables for one with the matching table name.
|
|
305
|
+
*/
|
|
306
|
+
private _getFkLookupTarget;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
export { AtscriptQueryComparison as a, AtscriptRef as c, translateQueryTree as d, AtscriptDbTable as f, TViewColumnMapping as i, TViewJoin as l, NativeIntegrity as m, TAdapterFactory as n, AtscriptQueryFieldRef$1 as o, IntegrityStrategy as p, AtscriptDbView as r, AtscriptQueryNode$1 as s, DbSpace as t, TViewPlan as u };
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { F as TDbInsertResult, H as TFkLookupResolver, O as TDbDeleteResult, P as TDbInsertManyResult, S as TCascadeResolver, Y as TTableResolver, Z as TWriteTableResolver, l as TGenericLogger, o as BaseDbAdapter, s as TableMetadata, t as AtscriptDbReadable, z as TDbUpdateResult } from "./db-readable-BQQzfguJ.cjs";
|
|
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
|
+
|
|
5
|
+
//#region src/strategies/integrity.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Strategy for referential integrity enforcement.
|
|
8
|
+
* Two implementations: {@link NativeIntegrity} (DB handles FK constraints)
|
|
9
|
+
* and `ApplicationIntegrity` (generic layer validates + cascades).
|
|
10
|
+
*/
|
|
11
|
+
declare abstract class IntegrityStrategy {
|
|
12
|
+
abstract validateForeignKeys(items: Array<Record<string, unknown>>, meta: TableMetadata, fkLookupResolver: TFkLookupResolver | undefined, writeTableResolver: TWriteTableResolver | undefined, partial?: boolean, excludeTargetTable?: string): Promise<void>;
|
|
13
|
+
abstract cascadeBeforeDelete(filter: FilterExpr, tableName: string, meta: TableMetadata, cascadeResolver: TCascadeResolver, translateFilter: (f: FilterExpr) => FilterExpr, adapter: BaseDbAdapter): Promise<void>;
|
|
14
|
+
abstract needsCascade(cascadeResolver: TCascadeResolver | undefined): boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Integrity strategy for adapters with native FK support (e.g. SQLite, MySQL).
|
|
18
|
+
* All operations are no-ops — the database engine enforces constraints.
|
|
19
|
+
*/
|
|
20
|
+
declare class NativeIntegrity extends IntegrityStrategy {
|
|
21
|
+
validateForeignKeys(): Promise<void>;
|
|
22
|
+
cascadeBeforeDelete(): Promise<void>;
|
|
23
|
+
needsCascade(): boolean;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
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> {
|
|
28
|
+
protected _cascadeResolver?: TCascadeResolver;
|
|
29
|
+
protected _fkLookupResolver?: TFkLookupResolver;
|
|
30
|
+
protected readonly _integrity: IntegrityStrategy;
|
|
31
|
+
protected readonly validators: Map<string, Validator<T, DataType>>;
|
|
32
|
+
constructor(_type: T, adapter: A, logger?: TGenericLogger, _tableResolver?: TTableResolver, _writeTableResolver?: TWriteTableResolver);
|
|
33
|
+
/**
|
|
34
|
+
* Sets the cascade resolver for application-level cascade deletes.
|
|
35
|
+
* Called by DbSpace after table creation.
|
|
36
|
+
*/
|
|
37
|
+
setCascadeResolver(resolver: TCascadeResolver): void;
|
|
38
|
+
/**
|
|
39
|
+
* Sets the FK lookup resolver for application-level FK validation.
|
|
40
|
+
* Called by DbSpace after table creation.
|
|
41
|
+
*/
|
|
42
|
+
setFkLookupResolver(resolver: TFkLookupResolver): void;
|
|
43
|
+
/**
|
|
44
|
+
* Returns a cached validator for the given purpose.
|
|
45
|
+
* Built with adapter plugins from {@link BaseDbAdapter.getValidatorPlugins}.
|
|
46
|
+
*
|
|
47
|
+
* Standard purposes: `'insert'`, `'update'`, `'patch'`.
|
|
48
|
+
* Adapters may define additional purposes.
|
|
49
|
+
*/
|
|
50
|
+
getValidator(purpose: string): Validator<T, DataType>;
|
|
51
|
+
/**
|
|
52
|
+
* Inserts a single record. Delegates to {@link insertMany} for unified
|
|
53
|
+
* nested creation support.
|
|
54
|
+
*/
|
|
55
|
+
insertOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
|
|
56
|
+
maxDepth?: number;
|
|
57
|
+
}): Promise<TDbInsertResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Inserts multiple records with batch-optimized nested creation.
|
|
60
|
+
*
|
|
61
|
+
* Supports **nested creation**: if payloads include data for navigation
|
|
62
|
+
* fields (`@db.rel.to` / `@db.rel.from`), related records are created
|
|
63
|
+
* automatically in batches. TO dependencies are batch-created first
|
|
64
|
+
* (their PKs become our FKs), FROM dependents are batch-created after
|
|
65
|
+
* (they receive our PKs as their FKs). Fully recursive — nested records
|
|
66
|
+
* with their own nav data trigger further batch inserts at each level.
|
|
67
|
+
* Recursive up to `maxDepth` (default 3).
|
|
68
|
+
*/
|
|
69
|
+
insertMany(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
|
|
70
|
+
maxDepth?: number;
|
|
71
|
+
}): Promise<TDbInsertManyResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Replaces a single record identified by primary key(s).
|
|
74
|
+
* Delegates to {@link bulkReplace} for unified nested relation support.
|
|
75
|
+
*/
|
|
76
|
+
replaceOne(payload: DataType & Record<string, unknown>, opts?: {
|
|
77
|
+
maxDepth?: number;
|
|
78
|
+
}): Promise<TDbUpdateResult>;
|
|
79
|
+
/**
|
|
80
|
+
* Replaces multiple records with deep nested relation support.
|
|
81
|
+
*
|
|
82
|
+
* Supports all relation types (TO, FROM, VIA). TO dependencies are
|
|
83
|
+
* replaced first (their PKs become our FKs), FROM dependents are replaced
|
|
84
|
+
* after (they receive our PKs as their FKs), VIA relations clear and
|
|
85
|
+
* re-create junction rows. Fully recursive up to `maxDepth` (default 3).
|
|
86
|
+
*/
|
|
87
|
+
bulkReplace(payloads: Array<DataType & Record<string, unknown>>, opts?: {
|
|
88
|
+
maxDepth?: number;
|
|
89
|
+
}): Promise<TDbUpdateResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Partially updates a single record identified by primary key(s).
|
|
92
|
+
* Delegates to {@link bulkUpdate} for unified nested relation support.
|
|
93
|
+
*/
|
|
94
|
+
updateOne(payload: Partial<DataType> & Record<string, unknown>, opts?: {
|
|
95
|
+
maxDepth?: number;
|
|
96
|
+
}): Promise<TDbUpdateResult>;
|
|
97
|
+
/**
|
|
98
|
+
* Partially updates multiple records with deep nested relation support.
|
|
99
|
+
*
|
|
100
|
+
* Only TO relations (1:1, N:1) are supported for patching. FROM/VIA
|
|
101
|
+
* relations will error — use {@link bulkReplace} for those.
|
|
102
|
+
* Recursive up to `maxDepth` (default 3).
|
|
103
|
+
*/
|
|
104
|
+
bulkUpdate(payloads: Array<Partial<DataType> & Record<string, unknown>>, opts?: {
|
|
105
|
+
maxDepth?: number;
|
|
106
|
+
}): Promise<TDbUpdateResult>;
|
|
107
|
+
/**
|
|
108
|
+
* Deletes a single record by any type-compatible identifier — primary key
|
|
109
|
+
* or single-field unique index. Uses the same resolution logic as `findById`.
|
|
110
|
+
*
|
|
111
|
+
* When the adapter does not support native foreign keys (e.g. MongoDB),
|
|
112
|
+
* cascade and setNull actions are applied before the delete.
|
|
113
|
+
*/
|
|
114
|
+
deleteOne(id: IdType): Promise<TDbDeleteResult>;
|
|
115
|
+
updateMany(filter: FilterExpr<FlatType>, data: Partial<DataType> & Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
116
|
+
replaceMany(filter: FilterExpr<FlatType>, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
117
|
+
deleteMany(filter: FilterExpr<FlatType>): Promise<TDbDeleteResult>;
|
|
118
|
+
/**
|
|
119
|
+
* Synchronizes indexes between Atscript definitions and the database.
|
|
120
|
+
*/
|
|
121
|
+
syncIndexes(): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Ensures the table/collection exists in the database.
|
|
124
|
+
*/
|
|
125
|
+
ensureTable(): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Applies default values for fields that are missing from the payload.
|
|
128
|
+
* Defaults handled natively by the DB engine are skipped — the field stays
|
|
129
|
+
* absent so the DB's own DEFAULT clause applies.
|
|
130
|
+
*/
|
|
131
|
+
protected _applyDefaults(data: Record<string, unknown>): Record<string, unknown>;
|
|
132
|
+
/**
|
|
133
|
+
* Extracts primary key field(s) from a payload to build a filter.
|
|
134
|
+
*/
|
|
135
|
+
protected _extractPrimaryKeyFilter(payload: Record<string, unknown>): FilterExpr;
|
|
136
|
+
/**
|
|
137
|
+
* Pre-validate items (type validation + FK constraints) without inserting them.
|
|
138
|
+
* Used by parent tables to validate FROM children before the main insert,
|
|
139
|
+
* ensuring errors are caught before the parent is committed.
|
|
140
|
+
*
|
|
141
|
+
* @param opts.excludeFkTargetTable - Skip FK validation to this table (the parent).
|
|
142
|
+
*/
|
|
143
|
+
preValidateItems(items: Array<Record<string, unknown>>, opts?: {
|
|
144
|
+
excludeFkTargetTable?: string;
|
|
145
|
+
}): Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Builds a validator for a given purpose with adapter plugins.
|
|
148
|
+
*
|
|
149
|
+
* Uses annotation-based `replace` callback to make `@meta.id` and
|
|
150
|
+
* `@db.default` fields optional — works at all nesting levels
|
|
151
|
+
* (including inside nav field target types).
|
|
152
|
+
*/
|
|
153
|
+
protected _buildValidator(purpose: string): Validator<T, DataType>;
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/query/query-tree.d.ts
|
|
157
|
+
/** A single join in a view query plan. */
|
|
158
|
+
interface TViewJoin {
|
|
159
|
+
targetType: () => TAtscriptAnnotatedType;
|
|
160
|
+
targetTable: string;
|
|
161
|
+
condition: AtscriptQueryNode;
|
|
162
|
+
}
|
|
163
|
+
/** Resolved view query plan produced by AtscriptDbView. */
|
|
164
|
+
interface TViewPlan {
|
|
165
|
+
entryType: () => TAtscriptAnnotatedType;
|
|
166
|
+
entryTable: string;
|
|
167
|
+
joins: TViewJoin[];
|
|
168
|
+
filter?: AtscriptQueryNode;
|
|
169
|
+
having?: AtscriptQueryNode;
|
|
170
|
+
materialized: boolean;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Translates a JS-emitted query tree into a FilterExpr.
|
|
174
|
+
* Resolves field references (type + field path) to physical column names
|
|
175
|
+
* via the provided resolver function.
|
|
176
|
+
*/
|
|
177
|
+
declare function translateQueryTree(node: AtscriptQueryNode, resolveField: (ref: AtscriptQueryFieldRef) => string): FilterExpr;
|
|
178
|
+
//#endregion
|
|
179
|
+
//#region src/table/db-view.d.ts
|
|
180
|
+
interface TViewColumnMapping {
|
|
181
|
+
viewColumn: string;
|
|
182
|
+
sourceTable: string;
|
|
183
|
+
sourceColumn: string;
|
|
184
|
+
/** Aggregate function name ('sum'|'avg'|'count'|'min'|'max') if this is an aggregate column. */
|
|
185
|
+
aggFn?: string;
|
|
186
|
+
/** Source field for the aggregate function ('*' for COUNT(*)). */
|
|
187
|
+
aggField?: string;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Database view abstraction driven by Atscript `@db.view.*` annotations.
|
|
191
|
+
*
|
|
192
|
+
* Extends {@link AtscriptDbReadable} with view plan resolution — entry table,
|
|
193
|
+
* joins, filter, and materialization flag. Read operations are inherited;
|
|
194
|
+
* write operations are not available on views.
|
|
195
|
+
*
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const adapter = new SqliteAdapter(db)
|
|
198
|
+
* const activeUsers = new AtscriptDbView(ActiveUsersType, adapter)
|
|
199
|
+
* const users = await activeUsers.findMany({ filter: {}, controls: {} })
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
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> {
|
|
203
|
+
private _viewPlan?;
|
|
204
|
+
get isView(): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Whether this is an external view — declared with `@db.view` only,
|
|
207
|
+
* without `@db.view.for`. External views reference pre-existing DB views
|
|
208
|
+
* and are not managed (created/dropped) by schema sync.
|
|
209
|
+
*/
|
|
210
|
+
get isExternal(): boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Lazily resolves the view plan from `@db.view.*` metadata.
|
|
213
|
+
*
|
|
214
|
+
* - `db.view.for` → entry type ref (required)
|
|
215
|
+
* - `db.view.joins` → array of `{ target, condition }` (optional, multiple)
|
|
216
|
+
* - `db.view.filter` → query tree (optional)
|
|
217
|
+
* - `db.view.materialized` → boolean (optional)
|
|
218
|
+
*/
|
|
219
|
+
get viewPlan(): TViewPlan;
|
|
220
|
+
/**
|
|
221
|
+
* Resolves a query field ref to a quoted `table.column` SQL fragment.
|
|
222
|
+
*
|
|
223
|
+
* @param ref - The field reference from the query tree.
|
|
224
|
+
* @param qi - Identifier quoting function (e.g. backtick for MySQL, double-quote for SQLite).
|
|
225
|
+
* Defaults to double-quote wrapping for backwards compatibility.
|
|
226
|
+
*/
|
|
227
|
+
resolveFieldRef(ref: AtscriptQueryFieldRef, qi?: (name: string) => string): string;
|
|
228
|
+
/**
|
|
229
|
+
* Maps each view field to its source table and column via ref chain.
|
|
230
|
+
* Fields without refs (inline definitions) map to the entry table with the same name.
|
|
231
|
+
*/
|
|
232
|
+
getViewColumnMappings(): TViewColumnMapping[];
|
|
233
|
+
}
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/table/db-space.d.ts
|
|
236
|
+
/**
|
|
237
|
+
* Adapter factory function. Called once per table/view to create a fresh adapter instance.
|
|
238
|
+
* Each readable gets its own adapter (1:1 relationship required by BaseDbAdapter).
|
|
239
|
+
*/
|
|
240
|
+
type TAdapterFactory = () => BaseDbAdapter;
|
|
241
|
+
/**
|
|
242
|
+
* A database space — a registry of tables and views sharing the same adapter type and driver.
|
|
243
|
+
*
|
|
244
|
+
* `DbSpace` solves the cross-table discovery problem: when table A has a relation
|
|
245
|
+
* to table B, it needs to find and query table B. The space acts as the registry
|
|
246
|
+
* that makes this possible via the table resolver callback.
|
|
247
|
+
*
|
|
248
|
+
* Each table/view gets its own adapter instance (created by the factory), but all
|
|
249
|
+
* share the same space and can discover each other for `$with` relation loading.
|
|
250
|
+
*
|
|
251
|
+
* ```typescript
|
|
252
|
+
* // SQLite
|
|
253
|
+
* const driver = new BetterSqlite3Driver(':memory:')
|
|
254
|
+
* const db = new DbSpace(() => new SqliteAdapter(driver))
|
|
255
|
+
* const users = db.getTable(UsersType)
|
|
256
|
+
* const activeUsers = db.getView(ActiveUsersType)
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
declare class DbSpace {
|
|
260
|
+
protected readonly adapterFactory: TAdapterFactory;
|
|
261
|
+
protected readonly logger: TGenericLogger;
|
|
262
|
+
private _readables;
|
|
263
|
+
/** All tables created in this space — used for reverse FK lookup during cascade. */
|
|
264
|
+
private _allTables;
|
|
265
|
+
/** Lazily created adapter for administrative ops (drop table/view) that don't need a registered readable. */
|
|
266
|
+
private _adminAdapter?;
|
|
267
|
+
constructor(adapterFactory: TAdapterFactory, logger?: TGenericLogger);
|
|
268
|
+
/**
|
|
269
|
+
* Auto-detects whether the type is a table or view and returns the
|
|
270
|
+
* appropriate instance. Uses `@db.view` or `@db.view.for` presence to distinguish.
|
|
271
|
+
*/
|
|
272
|
+
get<T extends TAtscriptAnnotatedType>(type: T, logger?: TGenericLogger): AtscriptDbReadable<T>;
|
|
273
|
+
/**
|
|
274
|
+
* Returns the table for the given annotated type.
|
|
275
|
+
* Creates the table + adapter on first access, caches for subsequent calls.
|
|
276
|
+
*/
|
|
277
|
+
getTable<T extends TAtscriptAnnotatedType>(type: T, logger?: TGenericLogger): AtscriptDbTable<T>;
|
|
278
|
+
/**
|
|
279
|
+
* Returns the view for the given annotated type.
|
|
280
|
+
* Creates the view + adapter on first access, caches for subsequent calls.
|
|
281
|
+
*/
|
|
282
|
+
getView<T extends TAtscriptAnnotatedType>(type: T, logger?: TGenericLogger): AtscriptDbView<T>;
|
|
283
|
+
/**
|
|
284
|
+
* Returns the adapter for the given annotated type.
|
|
285
|
+
* Creates the table/view + adapter on first access if needed.
|
|
286
|
+
*/
|
|
287
|
+
getAdapter(type: TAtscriptAnnotatedType): BaseDbAdapter;
|
|
288
|
+
/**
|
|
289
|
+
* Drops a table by name. Used by schema sync to remove tables no longer in the schema.
|
|
290
|
+
*/
|
|
291
|
+
dropTableByName(tableName: string): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Drops a view by name. Used by schema sync to remove views no longer in the schema.
|
|
294
|
+
*/
|
|
295
|
+
dropViewByName(viewName: string): Promise<void>;
|
|
296
|
+
private _getAdminAdapter;
|
|
297
|
+
/**
|
|
298
|
+
* Finds all child tables with FKs pointing to the given parent table name.
|
|
299
|
+
* Accesses `table.foreignKeys` which triggers `_flatten()` if needed.
|
|
300
|
+
*/
|
|
301
|
+
private _getCascadeTargets;
|
|
302
|
+
/**
|
|
303
|
+
* Resolves a table name to a queryable target for FK validation.
|
|
304
|
+
* Searches all registered tables for one with the matching table name.
|
|
305
|
+
*/
|
|
306
|
+
private _getFkLookupTarget;
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
export { AtscriptQueryComparison as a, AtscriptRef as c, translateQueryTree as d, AtscriptDbTable as f, TViewColumnMapping as i, TViewJoin as l, NativeIntegrity as m, TAdapterFactory as n, AtscriptQueryFieldRef$1 as o, IntegrityStrategy as p, AtscriptDbView as r, AtscriptQueryNode$1 as s, DbSpace as t, TViewPlan as u };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TAtscriptAnnotatedType, TValidatorPlugin } from "@atscript/typescript/utils";
|
|
2
|
+
|
|
3
|
+
//#region src/db-validator-plugin.d.ts
|
|
4
|
+
interface DbValidationContext {
|
|
5
|
+
mode: "insert" | "replace" | "patch";
|
|
6
|
+
/** Flat map from the table — used to check if an array is a top-level array. */
|
|
7
|
+
flatMap?: Map<string, TAtscriptAnnotatedType>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Validator plugin for database operations.
|
|
11
|
+
*
|
|
12
|
+
* Handles navigation field constraints and delegates to the standard validator
|
|
13
|
+
* for type checking. The annotated type tree already includes nav fields with
|
|
14
|
+
* their full target types — this plugin controls WHEN recursion is allowed
|
|
15
|
+
* based on the operation mode (insert/replace/patch).
|
|
16
|
+
*
|
|
17
|
+
* Replaces the old `navFieldsValidatorPlugin` (which blindly skipped all nav
|
|
18
|
+
* fields) and `_checkNavProps()` (which validated constraints separately).
|
|
19
|
+
*/
|
|
20
|
+
declare function createDbValidatorPlugin(): TValidatorPlugin;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { createDbValidatorPlugin as n, DbValidationContext as t };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TAtscriptAnnotatedType, TValidatorPlugin } from "@atscript/typescript/utils";
|
|
2
|
+
|
|
3
|
+
//#region src/db-validator-plugin.d.ts
|
|
4
|
+
interface DbValidationContext {
|
|
5
|
+
mode: "insert" | "replace" | "patch";
|
|
6
|
+
/** Flat map from the table — used to check if an array is a top-level array. */
|
|
7
|
+
flatMap?: Map<string, TAtscriptAnnotatedType>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Validator plugin for database operations.
|
|
11
|
+
*
|
|
12
|
+
* Handles navigation field constraints and delegates to the standard validator
|
|
13
|
+
* for type checking. The annotated type tree already includes nav fields with
|
|
14
|
+
* their full target types — this plugin controls WHEN recursion is allowed
|
|
15
|
+
* based on the operation mode (insert/replace/patch).
|
|
16
|
+
*
|
|
17
|
+
* Replaces the old `navFieldsValidatorPlugin` (which blindly skipped all nav
|
|
18
|
+
* fields) and `_checkNavProps()` (which validated constraints separately).
|
|
19
|
+
*/
|
|
20
|
+
declare function createDbValidatorPlugin(): TValidatorPlugin;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { createDbValidatorPlugin as n, DbValidationContext as t };
|