@atscript/db 0.1.127 → 0.1.128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{db-readable-BkAGccv9.d.mts → db-readable-BTl4NzNN.d.mts} +289 -16
- package/dist/{db-readable-C0nDKX8A.d.cts → db-readable-CkbZn_z-.d.cts} +289 -16
- package/dist/{db-space-B_ASuDaR.d.mts → db-space-BEB5Jl8M.d.mts} +81 -29
- package/dist/{db-space-CSntT6yS.d.cts → db-space-BevOyVrC.d.cts} +81 -29
- package/dist/{db-view-BP0Qbeux.cjs → db-view-C8-MsjND.cjs} +696 -97
- package/dist/{db-view-C8rZM5_N.mjs → db-view-Ck0I-PMI.mjs} +643 -98
- package/dist/index.cjs +46 -2
- package/dist/index.d.cts +162 -37
- package/dist/index.d.mts +162 -37
- package/dist/index.mjs +36 -4
- package/dist/{ops-DJRnNTVo.d.cts → ops-AqhV7s9o.d.cts} +24 -1
- package/dist/{ops-DJRnNTVo.d.mts → ops-AqhV7s9o.d.mts} +24 -1
- package/dist/ops.cjs +43 -0
- package/dist/ops.d.cts +2 -2
- package/dist/ops.d.mts +2 -2
- package/dist/ops.mjs +43 -1
- package/dist/plugin.cjs +12 -5
- package/dist/plugin.mjs +12 -5
- package/dist/rel.d.cts +1 -1
- package/dist/rel.d.mts +1 -1
- package/dist/sync.cjs +1096 -361
- package/dist/sync.d.cts +234 -15
- package/dist/sync.d.mts +234 -15
- package/dist/sync.mjs +1095 -362
- package/dist/{validator-CSGug4vg.cjs → validator-BNUHCXIE.cjs} +31 -2
- package/dist/{validator-BcBtg8yW.d.cts → validator-DuAmWc8L.d.cts} +38 -1
- package/dist/{validator-BcBtg8yW.d.mts → validator-DuAmWc8L.d.mts} +38 -1
- package/dist/{validator-0vRXN51D.mjs → validator-eKYWf3xf.mjs} +20 -3
- package/dist/validator.cjs +7 -1
- package/dist/validator.d.cts +3 -3
- package/dist/validator.d.mts +3 -3
- package/dist/validator.mjs +4 -3
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_db_error = require("./db-error-DXwEzmYJ.cjs");
|
|
3
|
-
const require_db_view = require("./db-view-
|
|
3
|
+
const require_db_view = require("./db-view-C8-MsjND.cjs");
|
|
4
|
+
const require_validator = require("./validator-BNUHCXIE.cjs");
|
|
4
5
|
const require_consts = require("./consts-BzRfCcH2.cjs");
|
|
5
6
|
const require_ops = require("./ops.cjs");
|
|
6
|
-
const require_validator = require("./validator-CSGug4vg.cjs");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let _uniqu_core = require("@uniqu/core");
|
|
9
9
|
//#region src/encryption.ts
|
|
@@ -150,6 +150,11 @@ var DbEncryption = class {
|
|
|
150
150
|
* a version conflict (`matchedCount === 0`) it re-reads the row, calls the
|
|
151
151
|
* mutator with the fresh state, and retries — up to `maxAttempts` times.
|
|
152
152
|
*
|
|
153
|
+
* A mutator that returns `undefined` or an empty object `{}` aborts without
|
|
154
|
+
* writing: the helper resolves `{ matchedCount: 1, modifiedCount: 0 }` and the
|
|
155
|
+
* version does not move (since 0.1.128 — previously `{}` reported a fabricated
|
|
156
|
+
* match as well, but through the empty-patch short-circuit).
|
|
157
|
+
*
|
|
153
158
|
* The filter (typically the primary key) is threaded into the update payload
|
|
154
159
|
* so the table layer can extract the row identity. If `mutator` returns
|
|
155
160
|
* fields that overlap with the filter, the patch wins (last-write semantics
|
|
@@ -179,6 +184,10 @@ async function withOptimisticRetry(table, filter, mutator, opts) {
|
|
|
179
184
|
}]);
|
|
180
185
|
lastSeenVersion = row[versionColumn];
|
|
181
186
|
const patch = await mutator(row);
|
|
187
|
+
if (patch === void 0 || require_validator.isEmptyObject(patch)) return {
|
|
188
|
+
matchedCount: 1,
|
|
189
|
+
modifiedCount: 0
|
|
190
|
+
};
|
|
182
191
|
const result = await table.updateOne({
|
|
183
192
|
...filter,
|
|
184
193
|
...patch,
|
|
@@ -294,6 +303,29 @@ var DbSpace = class {
|
|
|
294
303
|
const adapter = this._getAdminAdapter();
|
|
295
304
|
if (adapter.dropViewByName) await adapter.dropViewByName(viewName);
|
|
296
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* Drops a group of mutually referencing tables as one operation.
|
|
308
|
+
* Used by schema sync to remove a foreign-key cycle no longer in the schema.
|
|
309
|
+
* @since 0.1.128
|
|
310
|
+
*/
|
|
311
|
+
async dropTablesByName(tableNames) {
|
|
312
|
+
await this._getAdminAdapter().dropTablesByName(tableNames);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Live foreign keys referencing `tableName`, or `undefined` when the
|
|
316
|
+
* adapter cannot introspect them. Used by schema sync for drop ordering
|
|
317
|
+
* and surviving-reference checks of tables without a registered readable.
|
|
318
|
+
* @since 0.1.128
|
|
319
|
+
*/
|
|
320
|
+
async getReferencingForeignKeys(tableName) {
|
|
321
|
+
return this._getAdminAdapter().getReferencingForeignKeys?.(tableName);
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* A factory-fresh adapter with NO registered readable. Only the name-taking
|
|
325
|
+
* primitives may run on it (`dropTableByName`, `dropViewByName`,
|
|
326
|
+
* `dropTablesByName`, `getReferencingForeignKeys`) — adapters derive the
|
|
327
|
+
* schema for those from the driver/connection, not from a bound table.
|
|
328
|
+
*/
|
|
297
329
|
_getAdminAdapter() {
|
|
298
330
|
return this._adminAdapter ??= this.adapterFactory();
|
|
299
331
|
}
|
|
@@ -372,6 +404,9 @@ exports.assertGeoPoint = require_db_view.assertGeoPoint;
|
|
|
372
404
|
exports.assertNoVersionWrites = require_db_view.assertNoVersionWrites;
|
|
373
405
|
exports.buildDbValidator = require_validator.buildDbValidator;
|
|
374
406
|
exports.buildValidationContext = require_validator.buildValidationContext;
|
|
407
|
+
exports.checkHavingKeys = require_db_view.checkHavingKeys;
|
|
408
|
+
exports.classifyQueryPath = require_db_view.classifyQueryPath;
|
|
409
|
+
exports.collectQueryPaths = require_db_view.collectQueryPaths;
|
|
375
410
|
Object.defineProperty(exports, "computeInsights", {
|
|
376
411
|
enumerable: true,
|
|
377
412
|
get: function() {
|
|
@@ -381,26 +416,35 @@ Object.defineProperty(exports, "computeInsights", {
|
|
|
381
416
|
exports.createDbValidatorPlugin = require_validator.createDbValidatorPlugin;
|
|
382
417
|
exports.createFailureCollector = require_db_view.createFailureCollector;
|
|
383
418
|
exports.decomposePatch = require_db_view.decomposePatch;
|
|
419
|
+
exports.findAncestorInSet = require_db_view.findAncestorInSet;
|
|
384
420
|
exports.forceNavNonOptional = require_validator.forceNavNonOptional;
|
|
385
421
|
exports.getDbFieldOp = require_ops.getDbFieldOp;
|
|
386
422
|
exports.getKeyProps = require_validator.getKeyProps;
|
|
387
423
|
exports.guardAggregate = require_db_view.guardAggregate;
|
|
388
424
|
exports.guardFilter = require_db_view.guardFilter;
|
|
425
|
+
exports.guardPath = require_db_view.guardPath;
|
|
426
|
+
exports.guardPaths = require_db_view.guardPaths;
|
|
389
427
|
exports.guardQuery = require_db_view.guardQuery;
|
|
428
|
+
exports.isAtscriptDbView = require_db_view.isAtscriptDbView;
|
|
390
429
|
exports.isDbFieldOp = require_ops.isDbFieldOp;
|
|
430
|
+
exports.isEmptyObject = require_validator.isEmptyObject;
|
|
391
431
|
exports.isGeoIndexableType = require_db_view.isGeoIndexableType;
|
|
392
432
|
exports.isGeoPointType = require_db_view.isGeoPointType;
|
|
393
433
|
exports.isNavRelation = require_validator.isNavRelation;
|
|
434
|
+
exports.isPlainObject = require_validator.isPlainObject;
|
|
394
435
|
Object.defineProperty(exports, "isPrimitive", {
|
|
395
436
|
enumerable: true,
|
|
396
437
|
get: function() {
|
|
397
438
|
return _uniqu_core.isPrimitive;
|
|
398
439
|
}
|
|
399
440
|
});
|
|
441
|
+
exports.reconcileCas = require_ops.reconcileCas;
|
|
400
442
|
exports.resolveDesignType = require_db_view.resolveDesignType;
|
|
401
443
|
exports.separateCas = require_ops.separateCas;
|
|
402
444
|
exports.separateFieldOps = require_ops.separateFieldOps;
|
|
445
|
+
exports.sortFieldNames = require_db_view.sortFieldNames;
|
|
403
446
|
exports.translateQueryTree = translateQueryTree;
|
|
447
|
+
exports.unsupportedOperatorMessage = require_db_view.unsupportedOperatorMessage;
|
|
404
448
|
Object.defineProperty(exports, "walkFilter", {
|
|
405
449
|
enumerable: true,
|
|
406
450
|
get: function() {
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { a as $mul, c as $update, d as TDbFieldOp, f as TFieldOps, g as
|
|
3
|
-
import { a as TViewColumnMapping, c as
|
|
1
|
+
import { $ as TDbWriteAction, A as TCrudPermissions, At as isGeoIndexableType, B as TDbForeignKey, C as NullableOptional, Ct as TWriteTableResolver, D as TCascadeTarget, Dt as WithRelation, E as TCascadeResolver, Et as UniqueryControls, F as TDbCollation, G as TDbInsertResult, H as TDbIndexField, I as TDbDefaultFn, J as TDbRelation, K as TDbObjectKind, L as TDbDefaultValue, M as TDbActionIntent, Mt as NoopLogger, N as TDbActionLevel, Nt as TGenericLogger, O as TColumnDiff, Ot as TableMetadata, P as TDbActionProcessor, Pt as UniquSelect, Q as TDbUpdateResult, R as TDbDeleteResult, S as NavPropsOf, St as TWriteOptions, T as PrimaryKeyOf, Tt as Uniquery, U as TDbIndexType, V as TDbIndex, W as TDbInsertManyResult, X as TDbRemoveGuardContext, Y as TDbRemoveGuard, Z as TDbStorageType, _ as DbQuery, _t as TSearchIndexInfo, a as TDbEncryptionOptions, at as TExistingForeignKey, b as FilterExpr, bt as TTableResolver, c as BaseDbAdapter, ct as TFkLookupResolver, d as AggregateFn, dt as TIdentification, et as TDbWriteGuard, f as AggregateQuery, ft as TMetaResponse, g as DbPatch, gt as TRelationInfo, h as DbControls, ht as TReferencingForeignKey, i as DbEncryption, it as TExistingColumn, j as TDbActionInfo, jt as isGeoPointType, k as TCrudOp, kt as findAncestorInSet, l as AggregateControls, lt as TFkLookupTarget, m as AtscriptDbWritable, mt as TPrimaryKeyChange, n as DbResponse, nt as TDeleteOptions, o as DocumentFieldMapper, ot as TExistingTableOption, p as AggregateResult, pt as TMetadataOverrides, q as TDbReferentialAction, r as resolveDesignType, rt as TEnsureTableOptions, s as FieldMappingStrategy, st as TFieldMeta, t as AtscriptDbReadable, tt as TDbWriteGuardContext, u as AggregateExpr, ut as TIdDescriptor, v as DbRow, vt as TSyncColumnResult, w as OwnPropsOf, wt as TypedWithRelation, x as FlatOf, xt as TValueFormatterPair, y as FieldOpsFor, yt as TTableOptionDiff, z as TDbFieldMeta } from "./db-readable-CkbZn_z-.cjs";
|
|
2
|
+
import { _ as separateFieldOps, a as $mul, c as $update, d as TDbFieldOp, f as TFieldOps, g as separateCas, h as reconcileCas, i as $insert, l as $upsert, m as isDbFieldOp, n as $dec, o as $remove, p as getDbFieldOp, r as $inc, s as $replace, t as $cas, u as TDbCas } from "./ops-AqhV7s9o.cjs";
|
|
3
|
+
import { a as TViewColumnMapping, c as AtscriptQueryFieldRef, d as TViewJoin, f as TViewPlan, g as NativeIntegrity, h as IntegrityStrategy, i as AtscriptDbView, l as AtscriptQueryNode, m as AtscriptDbTable, n as TAdapterFactory, o as isAtscriptDbView, p as translateQueryTree, r as TDbSpaceOptions, s as AtscriptQueryComparison, t as DbSpace, u as AtscriptRef } from "./db-space-BevOyVrC.cjs";
|
|
4
|
+
import { a as buildValidationContext, c as isNavRelation, d as TArrayPatch, f as TDbPatch, g as DbErrorCode, h as DbError, l as isEmptyObject, m as CasExhaustedError, n as ValidatorMode, p as getKeyProps, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as isPlainObject } from "./validator-DuAmWc8L.cjs";
|
|
4
5
|
import { n as createDbValidatorPlugin, t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.cjs";
|
|
5
|
-
import { a as buildValidationContext, c as isNavRelation, d as getKeyProps, l as TArrayPatch, n as ValidatorMode, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as TDbPatch } from "./validator-BcBtg8yW.cjs";
|
|
6
6
|
import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, Uniquery as Uniquery$1, computeInsights, isPrimitive, walkFilter } from "@uniqu/core";
|
|
7
7
|
|
|
8
8
|
//#region src/shared/consts.d.ts
|
|
@@ -88,33 +88,6 @@ declare class ApplicationIntegrity extends IntegrityStrategy {
|
|
|
88
88
|
private buildCascadeChildFilter;
|
|
89
89
|
}
|
|
90
90
|
//#endregion
|
|
91
|
-
//#region src/db-error.d.ts
|
|
92
|
-
type DbErrorCode = "CONFLICT" | "FK_VIOLATION" | "NOT_FOUND" | "CASCADE_CYCLE" | "INVALID_QUERY" | "DEPTH_EXCEEDED" | "VERSION_COLUMN_WRITE" | "CAS_EXHAUSTED" | "ENC_CONFIG_MISSING" | "ENC_KEY_INVALID" | "ENC_NOT_ENCRYPTED" | "ENC_DECRYPT_FAILED" | "ENC_FIELD_FILTER" | "ENC_FIELD_SORT" | "ENC_FIELD_AGG" | "ENC_FIELD_PATCH_OP" | "GEO_INDEX_MISSING" | "GEO_NOT_SUPPORTED" | "FILTER_TYPE_MISMATCH";
|
|
93
|
-
declare class DbError extends Error {
|
|
94
|
-
readonly code: DbErrorCode;
|
|
95
|
-
readonly errors: Array<{
|
|
96
|
-
path: string;
|
|
97
|
-
message: string;
|
|
98
|
-
}>;
|
|
99
|
-
name: string;
|
|
100
|
-
constructor(code: DbErrorCode, errors: Array<{
|
|
101
|
-
path: string;
|
|
102
|
-
message: string;
|
|
103
|
-
}>, message?: string);
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Thrown by {@link withOptimisticRetry} when `maxAttempts` is reached
|
|
107
|
-
* without a successful CAS commit — the target row kept changing under
|
|
108
|
-
* the read-modify-write loop. Surfaces the attempt count and the
|
|
109
|
-
* last-observed version so callers can log/report the contention.
|
|
110
|
-
*/
|
|
111
|
-
declare class CasExhaustedError extends DbError {
|
|
112
|
-
readonly attempts: number;
|
|
113
|
-
readonly lastSeenVersion: number | undefined;
|
|
114
|
-
name: string;
|
|
115
|
-
constructor(attempts: number, lastSeenVersion: number | undefined);
|
|
116
|
-
}
|
|
117
|
-
//#endregion
|
|
118
91
|
//#region src/query/query-guards.d.ts
|
|
119
92
|
/**
|
|
120
93
|
* Engine-agnostic query-time guards, applied in the core layer BEFORE filter
|
|
@@ -127,6 +100,11 @@ declare class CasExhaustedError extends DbError {
|
|
|
127
100
|
* - `$geoWithin` on a non-geoPoint field → `FILTER_TYPE_MISMATCH`
|
|
128
101
|
* - `$geoWithin` with a malformed circle → `INVALID_QUERY`
|
|
129
102
|
* - `$geoWithin` on an adapter without geo support → `GEO_NOT_SUPPORTED`
|
|
103
|
+
* - every filter / `$sort` / `$select` / `$groupBy` / `$having` / aggregate
|
|
104
|
+
* path must resolve to physical storage on THIS adapter and pass the
|
|
105
|
+
* adapter's `canFilterField` / `canSortField` → `INVALID_QUERY`
|
|
106
|
+
* (see {@link guardPaths}). Runs after the checks above so `ENC_*` codes
|
|
107
|
+
* keep firing first for encrypted subtrees.
|
|
130
108
|
*/
|
|
131
109
|
/** Validates a `[lng, lat]` tuple (GeoJSON coordinate order). */
|
|
132
110
|
declare function assertGeoPoint(point: unknown, path: string): asserts point is [number, number];
|
|
@@ -135,14 +113,156 @@ declare function assertGeoPoint(point: unknown, path: string): asserts point is
|
|
|
135
113
|
* validating `$geoWithin` operator nodes.
|
|
136
114
|
*/
|
|
137
115
|
declare function guardFilter(meta: TableMetadata, adapter: BaseDbAdapter, filter: FilterExpr$1 | undefined, encCode?: "ENC_FIELD_FILTER" | "ENC_FIELD_AGG"): void;
|
|
138
|
-
/**
|
|
139
|
-
|
|
116
|
+
/** The query positions a field path can appear in. */
|
|
117
|
+
type TQueryPathOp = "filter" | "sort" | "select" | "groupBy" | "having" | "aggregate";
|
|
118
|
+
/** Query shape accepted by {@link guardPaths} / {@link collectQueryPaths} — the raw (pre-translation) uniqu controls. */
|
|
119
|
+
interface TGuardedQuery {
|
|
140
120
|
filter?: FilterExpr$1;
|
|
141
121
|
controls?: {
|
|
142
122
|
$sort?: unknown;
|
|
123
|
+
$select?: unknown;
|
|
124
|
+
$groupBy?: unknown;
|
|
125
|
+
$having?: unknown;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The one wording for a filter-node `$`-key that is not `$and` / `$or` /
|
|
130
|
+
* `$not` (uniqu's walker would treat it as a field named `$…`). The core
|
|
131
|
+
* guard and the HTTP gate both answer with it; `path` is the operator itself.
|
|
132
|
+
*/
|
|
133
|
+
declare function unsupportedOperatorMessage(op: string): string;
|
|
134
|
+
/**
|
|
135
|
+
* Normalizes every accepted `$sort` form (`"a,-b"`, `["a", "-b"]`,
|
|
136
|
+
* `[{ a: 1 }]`, `{ a: 1 }`) into its field names. Mirrors the HTTP layer's
|
|
137
|
+
* walker so programmatic callers get the same acceptance set.
|
|
138
|
+
*/
|
|
139
|
+
declare function sortFieldNames(sort: unknown): string[];
|
|
140
|
+
/** Every logical path a parsed query references, grouped by position (since 0.1.128). */
|
|
141
|
+
interface TQueryPathRefs {
|
|
142
|
+
/** Filter keys (recursing through `$and` / `$or` / `$not`), minus the geo predicates below. */
|
|
143
|
+
filter: string[];
|
|
144
|
+
/**
|
|
145
|
+
* Filter keys whose predicate is `$geoWithin`. Their shape and index support
|
|
146
|
+
* are validated by `guardFilter`, so the core path guard skips the adapter's
|
|
147
|
+
* scalar filter veto for them; the HTTP gate checks them like any filter path.
|
|
148
|
+
*/
|
|
149
|
+
geoFilter: string[];
|
|
150
|
+
sort: string[];
|
|
151
|
+
select: string[];
|
|
152
|
+
groupBy: string[];
|
|
153
|
+
having: string[];
|
|
154
|
+
/** Aggregate `$field`s (`*` excluded). Only populated in aggregate mode. */
|
|
155
|
+
aggregate: string[];
|
|
156
|
+
/** `true` in aggregate mode: `$select` entries are aggregate expressions, aliases are exempt in `$sort` / `$having`. */
|
|
157
|
+
aggregateMode: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* First filter-node `$`-key that is not `$and` / `$or` / `$not`. uniqu's
|
|
160
|
+
* walker would treat it as a field named `$…` — reject instead of 500.
|
|
161
|
+
*/
|
|
162
|
+
unsupportedOperator?: string;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Walks the PARSED query structure (not the flattened insights map, which
|
|
166
|
+
* cannot tell `$select=assignee.name` from `$with=assignee($select=name)`)
|
|
167
|
+
* and returns the root paths per position. `$with` sub-trees are not
|
|
168
|
+
* visited — they are validated against their target relation separately.
|
|
169
|
+
*
|
|
170
|
+
* Aggregate mode is `aggregate` when given, else the presence of `$groupBy`.
|
|
171
|
+
* In aggregate mode `$select` entries are aggregate expressions whose
|
|
172
|
+
* `$field` is collected and whose alias (`$as`, else `fn_field` — the core's
|
|
173
|
+
* `resolveAlias`) is exempted from `$sort` / `$having`; outside it non-string
|
|
174
|
+
* `$select` entries are ignored (the projection seal handles them).
|
|
175
|
+
*/
|
|
176
|
+
declare function collectQueryPaths(query: TGuardedQuery, aggregate?: boolean): TQueryPathRefs;
|
|
177
|
+
/** What a logical path is on THIS readable / adapter (since 0.1.128). */
|
|
178
|
+
type TQueryPathKind = /** A navigation relation or anything under one — never a column of this table. */"nav" /** A stored leaf (a non-ignored, non-nav descriptor). */ | "leaf" /** A nested-object parent: flattened away on relational adapters, an unlisted descriptor on nested-object ones. */ | "objectParent" /** A descendant of a JSON-stored column that this adapter cannot address (relational adapters). */ | "jsonDescendant" /** A descendant of an `@db.encrypted` field (the ciphertext column covers the subtree). */ | "encryptedDescendant" /** Unknown to this table. */ | "unknown";
|
|
179
|
+
/** The lookups {@link classifyQueryPath} needs — `TableMetadata` and moost-db's `FieldCapabilityIndex` both provide them. */
|
|
180
|
+
interface TQueryPathSource {
|
|
181
|
+
navFields: ReadonlySet<string>;
|
|
182
|
+
/** Stored leaves by logical path. */
|
|
183
|
+
leaves: {
|
|
184
|
+
has(path: string): boolean;
|
|
185
|
+
};
|
|
186
|
+
/** Nested-object parents by logical path. */
|
|
187
|
+
objectParents: {
|
|
188
|
+
has(path: string): boolean;
|
|
143
189
|
};
|
|
144
|
-
|
|
145
|
-
|
|
190
|
+
jsonParents: ReadonlySet<string>;
|
|
191
|
+
encryptedFields: ReadonlySet<string>;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Classifies one logical path. The rules exist once, in this order, for the
|
|
195
|
+
* core backstop ({@link guardPath}) and the HTTP capability gate alike:
|
|
196
|
+
*
|
|
197
|
+
* 1. navigation relations (and anything under them) — `parent` is the nav
|
|
198
|
+
* head when the path is a descendant;
|
|
199
|
+
* 2. a stored leaf;
|
|
200
|
+
* 3. a nested-object parent;
|
|
201
|
+
* 4. a descendant of a JSON-stored column — `parent` names the column;
|
|
202
|
+
* 5. a descendant of an `@db.encrypted` field — `parent` names the field;
|
|
203
|
+
* 6. unknown.
|
|
204
|
+
*/
|
|
205
|
+
declare function classifyQueryPath(source: TQueryPathSource, path: string): {
|
|
206
|
+
kind: TQueryPathKind;
|
|
207
|
+
parent?: string;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Validates ONE logical path for ONE query position against this table's
|
|
211
|
+
* metadata and adapter capability — the classification of
|
|
212
|
+
* {@link classifyQueryPath} plus the position's physical requirement:
|
|
213
|
+
*
|
|
214
|
+
* - a leaf → physical capability (`canFilterField` / `canSortField`;
|
|
215
|
+
* `$select` always passes);
|
|
216
|
+
* - a nested-object parent → only `$select`, and only when it expands to
|
|
217
|
+
* leaf columns (`selectExpansion`);
|
|
218
|
+
* - everything else is rejected.
|
|
219
|
+
*
|
|
220
|
+
* `geoPredicate` marks a filter entry whose operator is `$geoWithin`: its
|
|
221
|
+
* shape and index support were already validated by {@link guardFilter}, so
|
|
222
|
+
* the adapter's scalar `canFilterField` veto does not apply.
|
|
223
|
+
*
|
|
224
|
+
* Messages are the short programmatic forms; the HTTP wording (moost-db's
|
|
225
|
+
* `FieldCapabilityIndex`, with `$with` hints and leaf lists) is what clients
|
|
226
|
+
* see and is authoritative — the HTTP gate always answers first.
|
|
227
|
+
*/
|
|
228
|
+
declare function guardPath(meta: TableMetadata, adapter: BaseDbAdapter, path: string, op: TQueryPathOp, geoPredicate?: boolean): void;
|
|
229
|
+
/**
|
|
230
|
+
* Core backstop for every read / aggregate / mutation-filter entry point:
|
|
231
|
+
* each referenced path (see {@link collectQueryPaths}) must exist on THIS
|
|
232
|
+
* adapter with the physical capability the position needs (see
|
|
233
|
+
* {@link guardPath}). Adapters may therefore assume every path they receive
|
|
234
|
+
* is physical.
|
|
235
|
+
*
|
|
236
|
+
* In aggregate mode (`aggregate = true`) `$select` entries are aggregate
|
|
237
|
+
* expressions whose `$field` is checked, `$groupBy` fields are checked, and
|
|
238
|
+
* aggregate aliases (`$as` or `fn_field`) are exempt in `$sort` / `$having`.
|
|
239
|
+
*
|
|
240
|
+
* Returns the collected refs so callers can run further structural rules
|
|
241
|
+
* (see {@link checkHavingKeys}) without walking the query again.
|
|
242
|
+
*/
|
|
243
|
+
declare function guardPaths(meta: TableMetadata, adapter: BaseDbAdapter, query: TGuardedQuery | undefined, aggregate?: boolean): TQueryPathRefs | undefined;
|
|
244
|
+
/** Shared read-path guard: filter + $sort encryption checks, then the path guard. */
|
|
245
|
+
declare function guardQuery(meta: TableMetadata, adapter: BaseDbAdapter, query: TGuardedQuery | undefined): void;
|
|
246
|
+
/**
|
|
247
|
+
* `$having` is a post-aggregation filter, so a key is either an aggregate
|
|
248
|
+
* alias (`$as`, else `fn_field` — already exempt in {@link collectQueryPaths})
|
|
249
|
+
* or a `$groupBy` field (exact logical-path match: `metadata.clicks` grouped
|
|
250
|
+
* stays valid). Any other key — a real but non-grouped column included — is
|
|
251
|
+
* rejected here, once, for SDK and HTTP callers alike, instead of by the
|
|
252
|
+
* engine (PostgreSQL / MySQL error, SQLite tolerance, Mongo `[]`). Returns
|
|
253
|
+
* the first offending key as an error entry (`path` = the bare key, as the
|
|
254
|
+
* `Unknown field` rejection uses); `undefined` when every key is valid.
|
|
255
|
+
*/
|
|
256
|
+
declare function checkHavingKeys(refs: TQueryPathRefs): {
|
|
257
|
+
path: string;
|
|
258
|
+
message: string;
|
|
259
|
+
} | undefined;
|
|
260
|
+
/**
|
|
261
|
+
* Aggregate-path guard: $groupBy / $select / $having encryption refs + filter
|
|
262
|
+
* + $sort, then the path guard, then the `$having` key rule
|
|
263
|
+
* ({@link checkHavingKeys} — after the path guard so an unknown key still
|
|
264
|
+
* reads `Unknown field`).
|
|
265
|
+
*/
|
|
146
266
|
declare function guardAggregate(meta: TableMetadata, adapter: BaseDbAdapter, query: AggregateQuery$1): void;
|
|
147
267
|
//#endregion
|
|
148
268
|
//#region src/with-optimistic-retry.d.ts
|
|
@@ -164,6 +284,11 @@ interface WithOptimisticRetryOptions {
|
|
|
164
284
|
* a version conflict (`matchedCount === 0`) it re-reads the row, calls the
|
|
165
285
|
* mutator with the fresh state, and retries — up to `maxAttempts` times.
|
|
166
286
|
*
|
|
287
|
+
* A mutator that returns `undefined` or an empty object `{}` aborts without
|
|
288
|
+
* writing: the helper resolves `{ matchedCount: 1, modifiedCount: 0 }` and the
|
|
289
|
+
* version does not move (since 0.1.128 — previously `{}` reported a fabricated
|
|
290
|
+
* match as well, but through the empty-patch short-circuit).
|
|
291
|
+
*
|
|
167
292
|
* The filter (typically the primary key) is threaded into the update payload
|
|
168
293
|
* so the table layer can extract the row identity. If `mutator` returns
|
|
169
294
|
* fields that overlap with the filter, the patch wins (last-write semantics
|
|
@@ -177,7 +302,7 @@ interface WithOptimisticRetryOptions {
|
|
|
177
302
|
* @throws {CasExhaustedError} if `maxAttempts` is reached without a
|
|
178
303
|
* successful commit.
|
|
179
304
|
*/
|
|
180
|
-
declare function withOptimisticRetry<TRow extends Record<string, unknown>>(table: AtscriptDbTable, filter: Record<string, unknown>, mutator: (row: TRow) => Promise<Record<string, unknown
|
|
305
|
+
declare function withOptimisticRetry<TRow extends Record<string, unknown>>(table: AtscriptDbTable, filter: Record<string, unknown>, mutator: (row: TRow) => Promise<Record<string, unknown> | undefined> | Record<string, unknown> | undefined, opts?: WithOptimisticRetryOptions): Promise<TDbUpdateResult>;
|
|
181
306
|
//#endregion
|
|
182
307
|
//#region src/patch/patch-decomposer.d.ts
|
|
183
308
|
/**
|
|
@@ -237,4 +362,4 @@ declare function createFailureCollector(what: string): {
|
|
|
237
362
|
throwIfAny: () => void;
|
|
238
363
|
};
|
|
239
364
|
//#endregion
|
|
240
|
-
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, CasExhaustedError, DEFAULT_DB_SPACE, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbQuery, type DbResponse, DbSpace, type DbValidationContext, DocumentFieldMapper, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type TAdapterFactory, type TArrayPatch, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertManyResult, type TDbInsertResult, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TExistingColumn, type TExistingTableOption, type TFieldMeta, type TFieldOps, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TIdDescriptor, type TIdentification, type TMetaResponse, type TMetadataOverrides, type TRelationInfo, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, type TViewPlan, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WithOptimisticRetryOptions, type WithRelation, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardQuery, isDbFieldOp, isGeoIndexableType, isGeoPointType, isNavRelation, isPrimitive, resolveDesignType, separateCas, separateFieldOps, translateQueryTree, walkFilter, withOptimisticRetry };
|
|
365
|
+
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, CasExhaustedError, DEFAULT_DB_SPACE, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbPatch, type DbQuery, type DbResponse, type DbRow, DbSpace, type DbValidationContext, DocumentFieldMapper, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type NullableOptional, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type TAdapterFactory, type TArrayPatch, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertManyResult, type TDbInsertResult, type TDbObjectKind, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbRemoveGuard, type TDbRemoveGuardContext, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TDbWriteAction, type TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, type TEnsureTableOptions, type TExistingColumn, type TExistingForeignKey, type TExistingTableOption, type TFieldMeta, type TFieldOps, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TGuardedQuery, type TIdDescriptor, type TIdentification, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReferencingForeignKey, type TRelationInfo, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, type TViewPlan, type TWriteOptions, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WithOptimisticRetryOptions, type WithRelation, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isNavRelation, isPlainObject, isPrimitive, reconcileCas, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { a as $mul, c as $update, d as TDbFieldOp, f as TFieldOps, g as
|
|
3
|
-
import { a as TViewColumnMapping, c as
|
|
1
|
+
import { $ as TDbWriteAction, A as TCrudPermissions, At as isGeoIndexableType, B as TDbForeignKey, C as NullableOptional, Ct as TWriteTableResolver, D as TCascadeTarget, Dt as WithRelation, E as TCascadeResolver, Et as UniqueryControls, F as TDbCollation, G as TDbInsertResult, H as TDbIndexField, I as TDbDefaultFn, J as TDbRelation, K as TDbObjectKind, L as TDbDefaultValue, M as TDbActionIntent, Mt as NoopLogger, N as TDbActionLevel, Nt as TGenericLogger, O as TColumnDiff, Ot as TableMetadata, P as TDbActionProcessor, Pt as UniquSelect, Q as TDbUpdateResult, R as TDbDeleteResult, S as NavPropsOf, St as TWriteOptions, T as PrimaryKeyOf, Tt as Uniquery, U as TDbIndexType, V as TDbIndex, W as TDbInsertManyResult, X as TDbRemoveGuardContext, Y as TDbRemoveGuard, Z as TDbStorageType, _ as DbQuery, _t as TSearchIndexInfo, a as TDbEncryptionOptions, at as TExistingForeignKey, b as FilterExpr, bt as TTableResolver, c as BaseDbAdapter, ct as TFkLookupResolver, d as AggregateFn, dt as TIdentification, et as TDbWriteGuard, f as AggregateQuery, ft as TMetaResponse, g as DbPatch, gt as TRelationInfo, h as DbControls, ht as TReferencingForeignKey, i as DbEncryption, it as TExistingColumn, j as TDbActionInfo, jt as isGeoPointType, k as TCrudOp, kt as findAncestorInSet, l as AggregateControls, lt as TFkLookupTarget, m as AtscriptDbWritable, mt as TPrimaryKeyChange, n as DbResponse, nt as TDeleteOptions, o as DocumentFieldMapper, ot as TExistingTableOption, p as AggregateResult, pt as TMetadataOverrides, q as TDbReferentialAction, r as resolveDesignType, rt as TEnsureTableOptions, s as FieldMappingStrategy, st as TFieldMeta, t as AtscriptDbReadable, tt as TDbWriteGuardContext, u as AggregateExpr, ut as TIdDescriptor, v as DbRow, vt as TSyncColumnResult, w as OwnPropsOf, wt as TypedWithRelation, x as FlatOf, xt as TValueFormatterPair, y as FieldOpsFor, yt as TTableOptionDiff, z as TDbFieldMeta } from "./db-readable-BTl4NzNN.mjs";
|
|
2
|
+
import { _ as separateFieldOps, a as $mul, c as $update, d as TDbFieldOp, f as TFieldOps, g as separateCas, h as reconcileCas, i as $insert, l as $upsert, m as isDbFieldOp, n as $dec, o as $remove, p as getDbFieldOp, r as $inc, s as $replace, t as $cas, u as TDbCas } from "./ops-AqhV7s9o.mjs";
|
|
3
|
+
import { a as TViewColumnMapping, c as AtscriptQueryFieldRef, d as TViewJoin, f as TViewPlan, g as NativeIntegrity, h as IntegrityStrategy, i as AtscriptDbView, l as AtscriptQueryNode, m as AtscriptDbTable, n as TAdapterFactory, o as isAtscriptDbView, p as translateQueryTree, r as TDbSpaceOptions, s as AtscriptQueryComparison, t as DbSpace, u as AtscriptRef } from "./db-space-BEB5Jl8M.mjs";
|
|
4
|
+
import { a as buildValidationContext, c as isNavRelation, d as TArrayPatch, f as TDbPatch, g as DbErrorCode, h as DbError, l as isEmptyObject, m as CasExhaustedError, n as ValidatorMode, p as getKeyProps, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as isPlainObject } from "./validator-DuAmWc8L.mjs";
|
|
4
5
|
import { n as createDbValidatorPlugin, t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.mjs";
|
|
5
|
-
import { a as buildValidationContext, c as isNavRelation, d as getKeyProps, l as TArrayPatch, n as ValidatorMode, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as TDbPatch } from "./validator-BcBtg8yW.mjs";
|
|
6
6
|
import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, Uniquery as Uniquery$1, computeInsights, isPrimitive, walkFilter } from "@uniqu/core";
|
|
7
7
|
|
|
8
8
|
//#region src/shared/consts.d.ts
|
|
@@ -88,33 +88,6 @@ declare class ApplicationIntegrity extends IntegrityStrategy {
|
|
|
88
88
|
private buildCascadeChildFilter;
|
|
89
89
|
}
|
|
90
90
|
//#endregion
|
|
91
|
-
//#region src/db-error.d.ts
|
|
92
|
-
type DbErrorCode = "CONFLICT" | "FK_VIOLATION" | "NOT_FOUND" | "CASCADE_CYCLE" | "INVALID_QUERY" | "DEPTH_EXCEEDED" | "VERSION_COLUMN_WRITE" | "CAS_EXHAUSTED" | "ENC_CONFIG_MISSING" | "ENC_KEY_INVALID" | "ENC_NOT_ENCRYPTED" | "ENC_DECRYPT_FAILED" | "ENC_FIELD_FILTER" | "ENC_FIELD_SORT" | "ENC_FIELD_AGG" | "ENC_FIELD_PATCH_OP" | "GEO_INDEX_MISSING" | "GEO_NOT_SUPPORTED" | "FILTER_TYPE_MISMATCH";
|
|
93
|
-
declare class DbError extends Error {
|
|
94
|
-
readonly code: DbErrorCode;
|
|
95
|
-
readonly errors: Array<{
|
|
96
|
-
path: string;
|
|
97
|
-
message: string;
|
|
98
|
-
}>;
|
|
99
|
-
name: string;
|
|
100
|
-
constructor(code: DbErrorCode, errors: Array<{
|
|
101
|
-
path: string;
|
|
102
|
-
message: string;
|
|
103
|
-
}>, message?: string);
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Thrown by {@link withOptimisticRetry} when `maxAttempts` is reached
|
|
107
|
-
* without a successful CAS commit — the target row kept changing under
|
|
108
|
-
* the read-modify-write loop. Surfaces the attempt count and the
|
|
109
|
-
* last-observed version so callers can log/report the contention.
|
|
110
|
-
*/
|
|
111
|
-
declare class CasExhaustedError extends DbError {
|
|
112
|
-
readonly attempts: number;
|
|
113
|
-
readonly lastSeenVersion: number | undefined;
|
|
114
|
-
name: string;
|
|
115
|
-
constructor(attempts: number, lastSeenVersion: number | undefined);
|
|
116
|
-
}
|
|
117
|
-
//#endregion
|
|
118
91
|
//#region src/query/query-guards.d.ts
|
|
119
92
|
/**
|
|
120
93
|
* Engine-agnostic query-time guards, applied in the core layer BEFORE filter
|
|
@@ -127,6 +100,11 @@ declare class CasExhaustedError extends DbError {
|
|
|
127
100
|
* - `$geoWithin` on a non-geoPoint field → `FILTER_TYPE_MISMATCH`
|
|
128
101
|
* - `$geoWithin` with a malformed circle → `INVALID_QUERY`
|
|
129
102
|
* - `$geoWithin` on an adapter without geo support → `GEO_NOT_SUPPORTED`
|
|
103
|
+
* - every filter / `$sort` / `$select` / `$groupBy` / `$having` / aggregate
|
|
104
|
+
* path must resolve to physical storage on THIS adapter and pass the
|
|
105
|
+
* adapter's `canFilterField` / `canSortField` → `INVALID_QUERY`
|
|
106
|
+
* (see {@link guardPaths}). Runs after the checks above so `ENC_*` codes
|
|
107
|
+
* keep firing first for encrypted subtrees.
|
|
130
108
|
*/
|
|
131
109
|
/** Validates a `[lng, lat]` tuple (GeoJSON coordinate order). */
|
|
132
110
|
declare function assertGeoPoint(point: unknown, path: string): asserts point is [number, number];
|
|
@@ -135,14 +113,156 @@ declare function assertGeoPoint(point: unknown, path: string): asserts point is
|
|
|
135
113
|
* validating `$geoWithin` operator nodes.
|
|
136
114
|
*/
|
|
137
115
|
declare function guardFilter(meta: TableMetadata, adapter: BaseDbAdapter, filter: FilterExpr$1 | undefined, encCode?: "ENC_FIELD_FILTER" | "ENC_FIELD_AGG"): void;
|
|
138
|
-
/**
|
|
139
|
-
|
|
116
|
+
/** The query positions a field path can appear in. */
|
|
117
|
+
type TQueryPathOp = "filter" | "sort" | "select" | "groupBy" | "having" | "aggregate";
|
|
118
|
+
/** Query shape accepted by {@link guardPaths} / {@link collectQueryPaths} — the raw (pre-translation) uniqu controls. */
|
|
119
|
+
interface TGuardedQuery {
|
|
140
120
|
filter?: FilterExpr$1;
|
|
141
121
|
controls?: {
|
|
142
122
|
$sort?: unknown;
|
|
123
|
+
$select?: unknown;
|
|
124
|
+
$groupBy?: unknown;
|
|
125
|
+
$having?: unknown;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* The one wording for a filter-node `$`-key that is not `$and` / `$or` /
|
|
130
|
+
* `$not` (uniqu's walker would treat it as a field named `$…`). The core
|
|
131
|
+
* guard and the HTTP gate both answer with it; `path` is the operator itself.
|
|
132
|
+
*/
|
|
133
|
+
declare function unsupportedOperatorMessage(op: string): string;
|
|
134
|
+
/**
|
|
135
|
+
* Normalizes every accepted `$sort` form (`"a,-b"`, `["a", "-b"]`,
|
|
136
|
+
* `[{ a: 1 }]`, `{ a: 1 }`) into its field names. Mirrors the HTTP layer's
|
|
137
|
+
* walker so programmatic callers get the same acceptance set.
|
|
138
|
+
*/
|
|
139
|
+
declare function sortFieldNames(sort: unknown): string[];
|
|
140
|
+
/** Every logical path a parsed query references, grouped by position (since 0.1.128). */
|
|
141
|
+
interface TQueryPathRefs {
|
|
142
|
+
/** Filter keys (recursing through `$and` / `$or` / `$not`), minus the geo predicates below. */
|
|
143
|
+
filter: string[];
|
|
144
|
+
/**
|
|
145
|
+
* Filter keys whose predicate is `$geoWithin`. Their shape and index support
|
|
146
|
+
* are validated by `guardFilter`, so the core path guard skips the adapter's
|
|
147
|
+
* scalar filter veto for them; the HTTP gate checks them like any filter path.
|
|
148
|
+
*/
|
|
149
|
+
geoFilter: string[];
|
|
150
|
+
sort: string[];
|
|
151
|
+
select: string[];
|
|
152
|
+
groupBy: string[];
|
|
153
|
+
having: string[];
|
|
154
|
+
/** Aggregate `$field`s (`*` excluded). Only populated in aggregate mode. */
|
|
155
|
+
aggregate: string[];
|
|
156
|
+
/** `true` in aggregate mode: `$select` entries are aggregate expressions, aliases are exempt in `$sort` / `$having`. */
|
|
157
|
+
aggregateMode: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* First filter-node `$`-key that is not `$and` / `$or` / `$not`. uniqu's
|
|
160
|
+
* walker would treat it as a field named `$…` — reject instead of 500.
|
|
161
|
+
*/
|
|
162
|
+
unsupportedOperator?: string;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Walks the PARSED query structure (not the flattened insights map, which
|
|
166
|
+
* cannot tell `$select=assignee.name` from `$with=assignee($select=name)`)
|
|
167
|
+
* and returns the root paths per position. `$with` sub-trees are not
|
|
168
|
+
* visited — they are validated against their target relation separately.
|
|
169
|
+
*
|
|
170
|
+
* Aggregate mode is `aggregate` when given, else the presence of `$groupBy`.
|
|
171
|
+
* In aggregate mode `$select` entries are aggregate expressions whose
|
|
172
|
+
* `$field` is collected and whose alias (`$as`, else `fn_field` — the core's
|
|
173
|
+
* `resolveAlias`) is exempted from `$sort` / `$having`; outside it non-string
|
|
174
|
+
* `$select` entries are ignored (the projection seal handles them).
|
|
175
|
+
*/
|
|
176
|
+
declare function collectQueryPaths(query: TGuardedQuery, aggregate?: boolean): TQueryPathRefs;
|
|
177
|
+
/** What a logical path is on THIS readable / adapter (since 0.1.128). */
|
|
178
|
+
type TQueryPathKind = /** A navigation relation or anything under one — never a column of this table. */"nav" /** A stored leaf (a non-ignored, non-nav descriptor). */ | "leaf" /** A nested-object parent: flattened away on relational adapters, an unlisted descriptor on nested-object ones. */ | "objectParent" /** A descendant of a JSON-stored column that this adapter cannot address (relational adapters). */ | "jsonDescendant" /** A descendant of an `@db.encrypted` field (the ciphertext column covers the subtree). */ | "encryptedDescendant" /** Unknown to this table. */ | "unknown";
|
|
179
|
+
/** The lookups {@link classifyQueryPath} needs — `TableMetadata` and moost-db's `FieldCapabilityIndex` both provide them. */
|
|
180
|
+
interface TQueryPathSource {
|
|
181
|
+
navFields: ReadonlySet<string>;
|
|
182
|
+
/** Stored leaves by logical path. */
|
|
183
|
+
leaves: {
|
|
184
|
+
has(path: string): boolean;
|
|
185
|
+
};
|
|
186
|
+
/** Nested-object parents by logical path. */
|
|
187
|
+
objectParents: {
|
|
188
|
+
has(path: string): boolean;
|
|
143
189
|
};
|
|
144
|
-
|
|
145
|
-
|
|
190
|
+
jsonParents: ReadonlySet<string>;
|
|
191
|
+
encryptedFields: ReadonlySet<string>;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Classifies one logical path. The rules exist once, in this order, for the
|
|
195
|
+
* core backstop ({@link guardPath}) and the HTTP capability gate alike:
|
|
196
|
+
*
|
|
197
|
+
* 1. navigation relations (and anything under them) — `parent` is the nav
|
|
198
|
+
* head when the path is a descendant;
|
|
199
|
+
* 2. a stored leaf;
|
|
200
|
+
* 3. a nested-object parent;
|
|
201
|
+
* 4. a descendant of a JSON-stored column — `parent` names the column;
|
|
202
|
+
* 5. a descendant of an `@db.encrypted` field — `parent` names the field;
|
|
203
|
+
* 6. unknown.
|
|
204
|
+
*/
|
|
205
|
+
declare function classifyQueryPath(source: TQueryPathSource, path: string): {
|
|
206
|
+
kind: TQueryPathKind;
|
|
207
|
+
parent?: string;
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Validates ONE logical path for ONE query position against this table's
|
|
211
|
+
* metadata and adapter capability — the classification of
|
|
212
|
+
* {@link classifyQueryPath} plus the position's physical requirement:
|
|
213
|
+
*
|
|
214
|
+
* - a leaf → physical capability (`canFilterField` / `canSortField`;
|
|
215
|
+
* `$select` always passes);
|
|
216
|
+
* - a nested-object parent → only `$select`, and only when it expands to
|
|
217
|
+
* leaf columns (`selectExpansion`);
|
|
218
|
+
* - everything else is rejected.
|
|
219
|
+
*
|
|
220
|
+
* `geoPredicate` marks a filter entry whose operator is `$geoWithin`: its
|
|
221
|
+
* shape and index support were already validated by {@link guardFilter}, so
|
|
222
|
+
* the adapter's scalar `canFilterField` veto does not apply.
|
|
223
|
+
*
|
|
224
|
+
* Messages are the short programmatic forms; the HTTP wording (moost-db's
|
|
225
|
+
* `FieldCapabilityIndex`, with `$with` hints and leaf lists) is what clients
|
|
226
|
+
* see and is authoritative — the HTTP gate always answers first.
|
|
227
|
+
*/
|
|
228
|
+
declare function guardPath(meta: TableMetadata, adapter: BaseDbAdapter, path: string, op: TQueryPathOp, geoPredicate?: boolean): void;
|
|
229
|
+
/**
|
|
230
|
+
* Core backstop for every read / aggregate / mutation-filter entry point:
|
|
231
|
+
* each referenced path (see {@link collectQueryPaths}) must exist on THIS
|
|
232
|
+
* adapter with the physical capability the position needs (see
|
|
233
|
+
* {@link guardPath}). Adapters may therefore assume every path they receive
|
|
234
|
+
* is physical.
|
|
235
|
+
*
|
|
236
|
+
* In aggregate mode (`aggregate = true`) `$select` entries are aggregate
|
|
237
|
+
* expressions whose `$field` is checked, `$groupBy` fields are checked, and
|
|
238
|
+
* aggregate aliases (`$as` or `fn_field`) are exempt in `$sort` / `$having`.
|
|
239
|
+
*
|
|
240
|
+
* Returns the collected refs so callers can run further structural rules
|
|
241
|
+
* (see {@link checkHavingKeys}) without walking the query again.
|
|
242
|
+
*/
|
|
243
|
+
declare function guardPaths(meta: TableMetadata, adapter: BaseDbAdapter, query: TGuardedQuery | undefined, aggregate?: boolean): TQueryPathRefs | undefined;
|
|
244
|
+
/** Shared read-path guard: filter + $sort encryption checks, then the path guard. */
|
|
245
|
+
declare function guardQuery(meta: TableMetadata, adapter: BaseDbAdapter, query: TGuardedQuery | undefined): void;
|
|
246
|
+
/**
|
|
247
|
+
* `$having` is a post-aggregation filter, so a key is either an aggregate
|
|
248
|
+
* alias (`$as`, else `fn_field` — already exempt in {@link collectQueryPaths})
|
|
249
|
+
* or a `$groupBy` field (exact logical-path match: `metadata.clicks` grouped
|
|
250
|
+
* stays valid). Any other key — a real but non-grouped column included — is
|
|
251
|
+
* rejected here, once, for SDK and HTTP callers alike, instead of by the
|
|
252
|
+
* engine (PostgreSQL / MySQL error, SQLite tolerance, Mongo `[]`). Returns
|
|
253
|
+
* the first offending key as an error entry (`path` = the bare key, as the
|
|
254
|
+
* `Unknown field` rejection uses); `undefined` when every key is valid.
|
|
255
|
+
*/
|
|
256
|
+
declare function checkHavingKeys(refs: TQueryPathRefs): {
|
|
257
|
+
path: string;
|
|
258
|
+
message: string;
|
|
259
|
+
} | undefined;
|
|
260
|
+
/**
|
|
261
|
+
* Aggregate-path guard: $groupBy / $select / $having encryption refs + filter
|
|
262
|
+
* + $sort, then the path guard, then the `$having` key rule
|
|
263
|
+
* ({@link checkHavingKeys} — after the path guard so an unknown key still
|
|
264
|
+
* reads `Unknown field`).
|
|
265
|
+
*/
|
|
146
266
|
declare function guardAggregate(meta: TableMetadata, adapter: BaseDbAdapter, query: AggregateQuery$1): void;
|
|
147
267
|
//#endregion
|
|
148
268
|
//#region src/with-optimistic-retry.d.ts
|
|
@@ -164,6 +284,11 @@ interface WithOptimisticRetryOptions {
|
|
|
164
284
|
* a version conflict (`matchedCount === 0`) it re-reads the row, calls the
|
|
165
285
|
* mutator with the fresh state, and retries — up to `maxAttempts` times.
|
|
166
286
|
*
|
|
287
|
+
* A mutator that returns `undefined` or an empty object `{}` aborts without
|
|
288
|
+
* writing: the helper resolves `{ matchedCount: 1, modifiedCount: 0 }` and the
|
|
289
|
+
* version does not move (since 0.1.128 — previously `{}` reported a fabricated
|
|
290
|
+
* match as well, but through the empty-patch short-circuit).
|
|
291
|
+
*
|
|
167
292
|
* The filter (typically the primary key) is threaded into the update payload
|
|
168
293
|
* so the table layer can extract the row identity. If `mutator` returns
|
|
169
294
|
* fields that overlap with the filter, the patch wins (last-write semantics
|
|
@@ -177,7 +302,7 @@ interface WithOptimisticRetryOptions {
|
|
|
177
302
|
* @throws {CasExhaustedError} if `maxAttempts` is reached without a
|
|
178
303
|
* successful commit.
|
|
179
304
|
*/
|
|
180
|
-
declare function withOptimisticRetry<TRow extends Record<string, unknown>>(table: AtscriptDbTable, filter: Record<string, unknown>, mutator: (row: TRow) => Promise<Record<string, unknown
|
|
305
|
+
declare function withOptimisticRetry<TRow extends Record<string, unknown>>(table: AtscriptDbTable, filter: Record<string, unknown>, mutator: (row: TRow) => Promise<Record<string, unknown> | undefined> | Record<string, unknown> | undefined, opts?: WithOptimisticRetryOptions): Promise<TDbUpdateResult>;
|
|
181
306
|
//#endregion
|
|
182
307
|
//#region src/patch/patch-decomposer.d.ts
|
|
183
308
|
/**
|
|
@@ -237,4 +362,4 @@ declare function createFailureCollector(what: string): {
|
|
|
237
362
|
throwIfAny: () => void;
|
|
238
363
|
};
|
|
239
364
|
//#endregion
|
|
240
|
-
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, CasExhaustedError, DEFAULT_DB_SPACE, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbQuery, type DbResponse, DbSpace, type DbValidationContext, DocumentFieldMapper, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type TAdapterFactory, type TArrayPatch, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertManyResult, type TDbInsertResult, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TExistingColumn, type TExistingTableOption, type TFieldMeta, type TFieldOps, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TIdDescriptor, type TIdentification, type TMetaResponse, type TMetadataOverrides, type TRelationInfo, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, type TViewPlan, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WithOptimisticRetryOptions, type WithRelation, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardQuery, isDbFieldOp, isGeoIndexableType, isGeoPointType, isNavRelation, isPrimitive, resolveDesignType, separateCas, separateFieldOps, translateQueryTree, walkFilter, withOptimisticRetry };
|
|
365
|
+
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, CasExhaustedError, DEFAULT_DB_SPACE, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbPatch, type DbQuery, type DbResponse, type DbRow, DbSpace, type DbValidationContext, DocumentFieldMapper, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type NullableOptional, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type TAdapterFactory, type TArrayPatch, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertManyResult, type TDbInsertResult, type TDbObjectKind, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbRemoveGuard, type TDbRemoveGuardContext, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TDbWriteAction, type TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, type TEnsureTableOptions, type TExistingColumn, type TExistingForeignKey, type TExistingTableOption, type TFieldMeta, type TFieldOps, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TGuardedQuery, type TIdDescriptor, type TIdentification, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReferencingForeignKey, type TRelationInfo, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, type TViewPlan, type TWriteOptions, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WithOptimisticRetryOptions, type WithRelation, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isNavRelation, isPlainObject, isPrimitive, reconcileCas, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
|