@warlock.js/cascade 5.19.1 → 5.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -1
- package/cjs/index.cjs +2356 -1039
- package/cjs/index.cjs.map +1 -1
- package/esm/context/database-transaction-context.d.mts +10 -0
- package/esm/context/database-transaction-context.d.mts.map +1 -1
- package/esm/context/database-transaction-context.mjs +17 -0
- package/esm/context/database-transaction-context.mjs.map +1 -1
- package/esm/contracts/query-builder.contract.d.mts +30 -3
- package/esm/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/data-source/data-source-registry.d.mts +33 -1
- package/esm/data-source/data-source-registry.d.mts.map +1 -1
- package/esm/data-source/data-source-registry.mjs +75 -5
- package/esm/data-source/data-source-registry.mjs.map +1 -1
- package/esm/database-dirty-tracker.d.mts +5 -0
- package/esm/database-dirty-tracker.d.mts.map +1 -1
- package/esm/database-dirty-tracker.mjs +16 -0
- package/esm/database-dirty-tracker.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.d.mts +12 -0
- package/esm/drivers/mongodb/mongodb-driver.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.mjs +58 -19
- package/esm/drivers/mongodb/mongodb-driver.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.d.mts +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.mjs +15 -18
- package/esm/drivers/mongodb/mongodb-migration-driver.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.d.mts +13 -3
- package/esm/drivers/mongodb/mongodb-query-builder.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs +72 -19
- package/esm/drivers/mongodb/mongodb-query-builder.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.d.mts +6 -0
- package/esm/drivers/mongodb/mongodb-query-parser.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-parser.mjs +128 -30
- package/esm/drivers/mongodb/mongodb-query-parser.mjs.map +1 -1
- package/esm/drivers/postgres/index.d.mts +2 -3
- package/esm/drivers/postgres/index.mjs +1 -2
- package/esm/drivers/postgres/postgres-blueprint.mjs +4 -4
- package/esm/drivers/postgres/postgres-blueprint.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-dialect.d.mts +5 -1
- package/esm/drivers/postgres/postgres-dialect.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-dialect.mjs +38 -8
- package/esm/drivers/postgres/postgres-dialect.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-driver.d.mts +52 -29
- package/esm/drivers/postgres/postgres-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-driver.mjs +196 -58
- package/esm/drivers/postgres/postgres-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.d.mts +2 -1
- package/esm/drivers/postgres/postgres-migration-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-migration-driver.mjs +8 -6
- package/esm/drivers/postgres/postgres-migration-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-builder.d.mts +18 -7
- package/esm/drivers/postgres/postgres-query-builder.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-builder.mjs +146 -31
- package/esm/drivers/postgres/postgres-query-builder.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.d.mts +23 -1
- package/esm/drivers/postgres/postgres-query-parser.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.mjs +160 -43
- package/esm/drivers/postgres/postgres-query-parser.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-sql-serializer.mjs +3 -2
- package/esm/drivers/postgres/postgres-sql-serializer.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-type-converters.mjs +57 -0
- package/esm/drivers/postgres/postgres-type-converters.mjs.map +1 -0
- package/esm/events/model-events.d.mts +1 -1
- package/esm/events/model-events.d.mts.map +1 -1
- package/esm/events/model-events.mjs.map +1 -1
- package/esm/index.d.mts +6 -6
- package/esm/index.mjs +5 -5
- package/esm/migration/column-builder.d.mts.map +1 -1
- package/esm/migration/column-builder.mjs +2 -2
- package/esm/migration/column-builder.mjs.map +1 -1
- package/esm/migration/index.d.mts +2 -2
- package/esm/migration/index.mjs +1 -1
- package/esm/migration/migration-order.mjs +5 -2
- package/esm/migration/migration-order.mjs.map +1 -1
- package/esm/migration/migration-runner.d.mts +50 -5
- package/esm/migration/migration-runner.d.mts.map +1 -1
- package/esm/migration/migration-runner.mjs +370 -147
- package/esm/migration/migration-runner.mjs.map +1 -1
- package/esm/migration/migration.d.mts +36 -3
- package/esm/migration/migration.d.mts.map +1 -1
- package/esm/migration/migration.mjs +62 -5
- package/esm/migration/migration.mjs.map +1 -1
- package/esm/model/methods/accessor-methods.mjs +1 -3
- package/esm/model/methods/accessor-methods.mjs.map +1 -1
- package/esm/model/methods/delete-methods.mjs +6 -2
- package/esm/model/methods/delete-methods.mjs.map +1 -1
- package/esm/model/methods/hydration-methods.mjs +16 -2
- package/esm/model/methods/hydration-methods.mjs.map +1 -1
- package/esm/model/methods/instance-event-methods.mjs +2 -1
- package/esm/model/methods/instance-event-methods.mjs.map +1 -1
- package/esm/model/methods/meta-methods.mjs +53 -16
- package/esm/model/methods/meta-methods.mjs.map +1 -1
- package/esm/model/methods/query-methods.mjs +86 -15
- package/esm/model/methods/query-methods.mjs.map +1 -1
- package/esm/model/methods/static-event-methods.mjs +16 -1
- package/esm/model/methods/static-event-methods.mjs.map +1 -1
- package/esm/model/methods/write-methods.d.mts.map +1 -1
- package/esm/model/methods/write-methods.mjs +50 -50
- package/esm/model/methods/write-methods.mjs.map +1 -1
- package/esm/model/model.d.mts +16 -1
- package/esm/model/model.d.mts.map +1 -1
- package/esm/model/model.mjs +39 -5
- package/esm/model/model.mjs.map +1 -1
- package/esm/model/register-model.d.mts +6 -1
- package/esm/model/register-model.d.mts.map +1 -1
- package/esm/model/register-model.mjs +16 -1
- package/esm/model/register-model.mjs.map +1 -1
- package/esm/query-builder/query-builder.d.mts +21 -2
- package/esm/query-builder/query-builder.d.mts.map +1 -1
- package/esm/query-builder/query-builder.mjs +97 -20
- package/esm/query-builder/query-builder.mjs.map +1 -1
- package/esm/relations/key-conventions.mjs +13 -3
- package/esm/relations/key-conventions.mjs.map +1 -1
- package/esm/relations/pivot-operations.mjs +1 -1
- package/esm/relations/relation-loader.d.mts +15 -5
- package/esm/relations/relation-loader.d.mts.map +1 -1
- package/esm/relations/relation-loader.mjs +51 -16
- package/esm/relations/relation-loader.mjs.map +1 -1
- package/esm/remover/database-remover.d.mts.map +1 -1
- package/esm/remover/database-remover.mjs +21 -7
- package/esm/remover/database-remover.mjs.map +1 -1
- package/esm/restorer/database-restorer.d.mts +12 -2
- package/esm/restorer/database-restorer.d.mts.map +1 -1
- package/esm/restorer/database-restorer.mjs +43 -13
- package/esm/restorer/database-restorer.mjs.map +1 -1
- package/esm/sync/model-events.mjs +63 -3
- package/esm/sync/model-events.mjs.map +1 -1
- package/esm/sync/model-sync-operation.d.mts.map +1 -1
- package/esm/sync/model-sync-operation.mjs +3 -2
- package/esm/sync/model-sync-operation.mjs.map +1 -1
- package/esm/sync/sync-manager.d.mts +3 -42
- package/esm/sync/sync-manager.d.mts.map +1 -1
- package/esm/sync/sync-manager.mjs +37 -126
- package/esm/sync/sync-manager.mjs.map +1 -1
- package/esm/transactions/after-commit.d.mts +24 -0
- package/esm/transactions/after-commit.d.mts.map +1 -0
- package/esm/transactions/after-commit.mjs +47 -0
- package/esm/transactions/after-commit.mjs.map +1 -0
- package/esm/utils/connect-to-database.d.mts.map +1 -1
- package/esm/utils/connect-to-database.mjs +4 -4
- package/esm/utils/connect-to-database.mjs.map +1 -1
- package/esm/utils/database-writer.utils.d.mts +1 -1
- package/esm/utils/database-writer.utils.d.mts.map +1 -1
- package/esm/utils/database-writer.utils.mjs +1 -0
- package/esm/utils/database-writer.utils.mjs.map +1 -1
- package/esm/utils/define-model.d.mts.map +1 -1
- package/esm/utils/define-model.mjs +2 -10
- package/esm/utils/define-model.mjs.map +1 -1
- package/esm/utils/is-valid-date-value.mjs +3 -2
- package/esm/utils/is-valid-date-value.mjs.map +1 -1
- package/esm/utils/once-connected.d.mts.map +1 -1
- package/esm/utils/once-connected.mjs +12 -2
- package/esm/utils/once-connected.mjs.map +1 -1
- package/esm/validation/mutators/embed-mutator.mjs +19 -11
- package/esm/validation/mutators/embed-mutator.mjs.map +1 -1
- package/esm/validation/plugins/embed-validator-plugin.d.mts +2 -2
- package/esm/validation/plugins/embed-validator-plugin.d.mts.map +1 -1
- package/esm/validation/plugins/embed-validator-plugin.mjs +8 -2
- package/esm/validation/plugins/embed-validator-plugin.mjs.map +1 -1
- package/esm/validation/rules/database-model-rule.mjs +6 -5
- package/esm/validation/rules/database-model-rule.mjs.map +1 -1
- package/esm/validation/rules/exists-rule.mjs +6 -4
- package/esm/validation/rules/exists-rule.mjs.map +1 -1
- package/esm/validation/rules/unique-rule.mjs +5 -2
- package/esm/validation/rules/unique-rule.mjs.map +1 -1
- package/esm/validation/validators/embed-validator.d.mts.map +1 -1
- package/esm/validation/validators/embed-validator.mjs +1 -1
- package/esm/validation/validators/embed-validator.mjs.map +1 -1
- package/esm/writer/database-writer.d.mts +27 -0
- package/esm/writer/database-writer.d.mts.map +1 -1
- package/esm/writer/database-writer.mjs +84 -17
- package/esm/writer/database-writer.mjs.map +1 -1
- package/llms-full.txt +2783 -2766
- package/llms.txt +15 -15
- package/package.json +6 -6
- package/skills/aggregate-data/SKILL.md +165 -165
- package/skills/alter-migration/SKILL.md +531 -531
- package/skills/configure-delete-strategy/SKILL.md +130 -130
- package/skills/define-model/SKILL.md +205 -205
- package/skills/define-relations/SKILL.md +171 -171
- package/skills/index.md +23 -0
- package/skills/manage-data-sources/SKILL.md +140 -140
- package/skills/manage-transactions/SKILL.md +208 -191
- package/skills/paginate-results/SKILL.md +122 -122
- package/skills/perform-atomic-ops/SKILL.md +156 -156
- package/skills/query-data/SKILL.md +213 -213
- package/skills/run-cascade-cli/SKILL.md +125 -125
- package/skills/search-by-vector/SKILL.md +127 -127
- package/skills/subscribe-to-model-events/SKILL.md +148 -148
- package/skills/track-changes/SKILL.md +127 -127
- package/skills/write-migration/SKILL.md +206 -206
- package/esm/drivers/postgres/postgres-sync-adapter.d.mts +0 -79
- package/esm/drivers/postgres/postgres-sync-adapter.d.mts.map +0 -1
- package/esm/drivers/postgres/postgres-sync-adapter.mjs +0 -162
- package/esm/drivers/postgres/postgres-sync-adapter.mjs.map +0 -1
|
@@ -71,6 +71,11 @@ declare class MongoQueryParser {
|
|
|
71
71
|
* ```
|
|
72
72
|
*/
|
|
73
73
|
parse(): any[];
|
|
74
|
+
/**
|
|
75
|
+
* Atlas requires `$vectorSearch` as the first stage. Any `$match` emitted
|
|
76
|
+
* before it (where clauses, scopes) moves into its `filter` instead.
|
|
77
|
+
*/
|
|
78
|
+
private hoistVectorSearch;
|
|
74
79
|
/**
|
|
75
80
|
* Apply a raw escape-hatch operation to the pipeline built so far.
|
|
76
81
|
*
|
|
@@ -224,6 +229,7 @@ declare class MongoQueryParser {
|
|
|
224
229
|
* @returns The MongoDB filter condition
|
|
225
230
|
*/
|
|
226
231
|
private buildOperatorCondition;
|
|
232
|
+
private assertArrayOperand;
|
|
227
233
|
/**
|
|
228
234
|
* Get MongoDB operator from comparison operator.
|
|
229
235
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongodb-query-parser.d.mts","names":[],"sources":["../../../../../../../../cascade/src/drivers/mongodb/mongodb-query-parser.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"mongodb-query-parser.d.mts","names":[],"sources":["../../../../../../../../cascade/src/drivers/mongodb/mongodb-query-parser.ts"],"mappings":";;;;;;;AAyDA;KAAY,uBAAA;6CAEV,UAAA,EAAY,UAAA,EAEA;EAAZ,UAAA,EAAY,SAAA,IAE6B;EAAzC,gBAAA,QAAwB,iBAAA;AAAA;AAuB1B;;;;;;;;AAAA,cAAa,gBAAA;;;;mBAIM,UAAA;EAkJT;;;EAAA,iBA7IS,UAAA;EAwTT;;;EAAA,iBAnTS,gBAAA;EA6cT;;;;EAAA,iBAvcS,eAAA;EA20BT;;;;;;EAAA,iBAn0BS,oBAAA;EAyqCT;;;;;cAlqCW,OAAA,EAAS,uBAAuB;EAktC3C;;;;;;;;;;;;;;;;;;;;EAxrCD,KAAA;EA07CC;;;;EAAA,QAj2CA,iBAAA;EAi6CA;;;;;;;;;;EAAA,QAl3CA,iBAAA;EAo2DA;;AAAgB;;;;;;;;;;;EAAhB,QAj0DA,yBAAA;;;;;;;;;;;;;;;;;;UAuDA,WAAA;;;;UAkCA,oBAAA;;;;;;UAkCA,yBAAA;;;;;;;;;;UAyBA,qBAAA;;;;;;;;;;;;;;;;;;;;;;;;EA4DD,cAAA;;;;;;;;UAmCC,eAAA;;;;;;;;UAoDA,UAAA;;;;;;;;;;;UAyEA,eAAA;EAAA,QAqKA,iBAAA;;;;;;;;;UAkBA,sBAAA;;;;;;;UAgFA,mBAAA;;;;;;;;;;;;;UAyNA,oBAAA;;;;;;;;;UAgBA,sBAAA;EAAA,QAkDA,kBAAA;;;;;;;UAcA,gBAAA;EAAA,QAYA,oBAAA;;;;;;;;UA2BA,4BAAA;EAAA,QAsBA,aAAA;EAAA,QAYA,qBAAA;EAAA,QASA,4BAAA;EAAA,QAWA,UAAA;EAAA,QAIA,0BAAA;EAAA,QAOA,wBAAA;EAAA,QAKA,uBAAA;EAAA,QAKA,kBAAA;EAAA,QAgBA,sBAAA;EAAA,QAiBA,0BAAA;EAAA,QAQA,+BAAA;EAAA,QAMA,6BAAA;EAAA,QAMA,wBAAA;EAAA,QASA,sBAAA;EAAA,QAQA,yBAAA;EAAA,QASA,kBAAA;EAAA,QAWA,UAAA;EAAA,QAMA,QAAA;EAAA,QAMA,aAAA;EAAA,QAIA,qBAAA;;;;;;UAeA,qBAAA;EAAA,QAmCA,kBAAA;EAAA,QAeA,2BAAA;EAAA,QA0BA,uBAAA;EAAA,QAoBA,wBAAA;EAAA,QAwBA,qBAAA;EAAA,QAMA,wBAAA;EAAA,QAMA,mBAAA;EAAA,QAeA,mBAAA;;;;;UAkBA,0BAAA;EAAA,QAaA,cAAA;EAAA,QAYA,qBAAA;EAAA,QAMA,uBAAA;;;;;;;UAsBA,iBAAA;;;;;;;UAgHA,cAAA;;;;;;;UA0BA,eAAA;EAAA,QA6DA,iBAAA;;;;;;;;UAgBA,+BAAA;;;;;;;;;;UAoCA,qBAAA;;;;;;;UA0BA,sBAAA;;;;;;;UA4BA,4BAAA;;;;;;;;;;;;;UAuFA,uBAAA;EAAA,QAoCA,YAAA;;;;;;;UAgDA,gBAAA;AAAA"}
|
|
@@ -1,11 +1,48 @@
|
|
|
1
1
|
import { UnsafeRawExpressionError } from "../../errors/unsafe-raw-expression.error.mjs";
|
|
2
2
|
import { UnsupportedQueryOperationError } from "../../errors/unsupported-query-operation.error.mjs";
|
|
3
3
|
import { isAggregateExpression } from "../../expressions/aggregate-expressions.mjs";
|
|
4
|
-
import { escapeRegex
|
|
4
|
+
import { escapeRegex } from "../../utils/escape-regex.mjs";
|
|
5
5
|
import { isPipelineStageObject } from "./pipeline-stage-object.mjs";
|
|
6
6
|
import { colors } from "@mongez/copper";
|
|
7
7
|
|
|
8
8
|
//#region ../cascade/src/drivers/mongodb/mongodb-query-parser.ts
|
|
9
|
+
const isPlainObject = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
10
|
+
/**
|
|
11
|
+
* AND one `key: value` condition into `target`. Operators on the same field
|
|
12
|
+
* with distinct keys are merged (`{ age: { $gt, $lt } }`); any other collision
|
|
13
|
+
* (same operator, `$expr`, `$nor`, ...) is pushed into `$and` so neither
|
|
14
|
+
* side is overwritten.
|
|
15
|
+
*/
|
|
16
|
+
const mergeConditionEntry = (target, key, value) => {
|
|
17
|
+
if (!(key in target)) {
|
|
18
|
+
target[key] = value;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (key === "$and" && Array.isArray(target.$and) && Array.isArray(value)) {
|
|
22
|
+
target.$and.push(...value);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const existing = target[key];
|
|
26
|
+
if (!key.startsWith("$") && isPlainObject(existing) && isPlainObject(value) && !Object.keys(value).some((operator) => operator in existing)) {
|
|
27
|
+
target[key] = {
|
|
28
|
+
...existing,
|
|
29
|
+
...value
|
|
30
|
+
};
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!Array.isArray(target.$and)) target.$and = [];
|
|
34
|
+
target.$and.push({ [key]: value });
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Compile a LIKE argument to regex source with the same wildcards as SQL/pg:
|
|
38
|
+
* `%` matches any run of characters and `_` exactly one. Every other regex
|
|
39
|
+
* metacharacter in a string is escaped, so `a.b*` matches literally. An explicit
|
|
40
|
+
* `RegExp` is developer-authored and used verbatim.
|
|
41
|
+
*/
|
|
42
|
+
function resolveMongoLikePattern(pattern) {
|
|
43
|
+
if (pattern instanceof RegExp) return pattern.source;
|
|
44
|
+
return escapeRegex(pattern).replace(/%+/g, ".*").replace(/_/g, ".");
|
|
45
|
+
}
|
|
9
46
|
/**
|
|
10
47
|
* Parses query builder operations into MongoDB aggregation pipeline.
|
|
11
48
|
*
|
|
@@ -96,6 +133,7 @@ var MongoQueryParser = class {
|
|
|
96
133
|
this.trackGroupFieldNames(stage, operations, stageIndex);
|
|
97
134
|
const renameStage = this.buildGroupRenameStage(builtStage, stageIndex);
|
|
98
135
|
if (renameStage) pipeline.push(renameStage);
|
|
136
|
+
if (stage === "$lookup" && builtStage.$lookup && operations[0]?.data?.type === "inner") pipeline.push({ $match: { [builtStage.$lookup.as]: { $ne: [] } } });
|
|
99
137
|
};
|
|
100
138
|
for (const op of this.orderStages(this.operations)) {
|
|
101
139
|
if (op.mergeable && op.stage === currentStage) {
|
|
@@ -115,7 +153,23 @@ var MongoQueryParser = class {
|
|
|
115
153
|
}
|
|
116
154
|
}
|
|
117
155
|
if (currentBuffer.length > 0) emit(currentStage, currentBuffer);
|
|
118
|
-
return pipeline;
|
|
156
|
+
return this.hoistVectorSearch(pipeline);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Atlas requires `$vectorSearch` as the first stage. Any `$match` emitted
|
|
160
|
+
* before it (where clauses, scopes) moves into its `filter` instead.
|
|
161
|
+
*/
|
|
162
|
+
hoistVectorSearch(pipeline) {
|
|
163
|
+
const index = pipeline.findIndex((stage) => stage.$vectorSearch);
|
|
164
|
+
if (index <= 0) return pipeline;
|
|
165
|
+
const before = pipeline.slice(0, index).filter((stage) => !stage.$limit);
|
|
166
|
+
if (!before.every((stage) => stage.$match)) throw new UnsupportedQueryOperationError("similarTo", "mongodb", "$vectorSearch must be the first pipeline stage; only where() filters can precede similarTo().");
|
|
167
|
+
const vectorStage = pipeline[index].$vectorSearch;
|
|
168
|
+
const filters = [...before.map((stage) => stage.$match), ...vectorStage.filter ? [vectorStage.filter] : []];
|
|
169
|
+
return [{ $vectorSearch: {
|
|
170
|
+
...vectorStage,
|
|
171
|
+
...filters.length === 0 ? {} : { filter: filters.length === 1 ? filters[0] : { $and: filters } }
|
|
172
|
+
} }, ...pipeline.slice(index + 1)];
|
|
119
173
|
}
|
|
120
174
|
/**
|
|
121
175
|
* Apply a raw escape-hatch operation to the pipeline built so far.
|
|
@@ -411,11 +465,7 @@ var MongoQueryParser = class {
|
|
|
411
465
|
pushOr(value);
|
|
412
466
|
return;
|
|
413
467
|
}
|
|
414
|
-
|
|
415
|
-
...andFilter[key],
|
|
416
|
-
...value
|
|
417
|
-
};
|
|
418
|
-
else andFilter[key] = value;
|
|
468
|
+
mergeConditionEntry(andFilter, key, value);
|
|
419
469
|
});
|
|
420
470
|
};
|
|
421
471
|
const queueSimpleWhere = (condition) => {
|
|
@@ -426,10 +476,9 @@ var MongoQueryParser = class {
|
|
|
426
476
|
const enterTopLevelOrMode = () => {
|
|
427
477
|
if (topLevelOrMode) return;
|
|
428
478
|
topLevelOrMode = true;
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
479
|
+
const pending = pendingSimpleWhere.splice(0).filter(Boolean);
|
|
480
|
+
if (pending.length === 1) pushOr(pending[0]);
|
|
481
|
+
else if (pending.length > 1) pushOr({ $and: pending });
|
|
433
482
|
};
|
|
434
483
|
const flushPendingSimpleWhere = () => {
|
|
435
484
|
if (pendingSimpleWhere.length === 0) return;
|
|
@@ -528,14 +577,13 @@ var MongoQueryParser = class {
|
|
|
528
577
|
}
|
|
529
578
|
return orClauses.length > 0 ? { $or: orClauses } : null;
|
|
530
579
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
580
|
+
const mergeInto = (condition) => {
|
|
581
|
+
if (!condition) return;
|
|
582
|
+
Object.entries(condition).forEach(([key, value]) => mergeConditionEntry(andFilter, key, value));
|
|
583
|
+
};
|
|
584
|
+
for (const op of matchOps) if (op.type === "where:callback") mergeInto(this.buildCallbackCondition(op.data));
|
|
585
|
+
else if (op.type === "where:object") mergeInto(op.data);
|
|
586
|
+
else mergeInto(this.buildWhereCondition(op));
|
|
539
587
|
return Object.keys(andFilter).length > 0 ? andFilter : null;
|
|
540
588
|
}
|
|
541
589
|
/**
|
|
@@ -549,11 +597,16 @@ var MongoQueryParser = class {
|
|
|
549
597
|
switch (op.type) {
|
|
550
598
|
case "where":
|
|
551
599
|
case "orWhere": return this.buildOperatorCondition(field, operator, value);
|
|
552
|
-
case "whereIn":
|
|
553
|
-
case "
|
|
554
|
-
case "
|
|
555
|
-
case "
|
|
556
|
-
case "
|
|
600
|
+
case "whereIn":
|
|
601
|
+
case "orWhereIn": return { [field]: { $in: value || op.data.values } };
|
|
602
|
+
case "whereNotIn":
|
|
603
|
+
case "orWhereNotIn": return { [field]: { $nin: value || op.data.values } };
|
|
604
|
+
case "whereNull":
|
|
605
|
+
case "orWhereNull": return { [field]: null };
|
|
606
|
+
case "whereNotNull":
|
|
607
|
+
case "orWhereNotNull": return { [field]: { $ne: null } };
|
|
608
|
+
case "whereBetween":
|
|
609
|
+
case "orWhereBetween": return { [field]: {
|
|
557
610
|
$gte: op.data.range[0],
|
|
558
611
|
$lte: op.data.range[1]
|
|
559
612
|
} };
|
|
@@ -648,7 +701,7 @@ var MongoQueryParser = class {
|
|
|
648
701
|
*/
|
|
649
702
|
buildLikeRegexSource(data) {
|
|
650
703
|
if (data.isRegExp === true && typeof data.pattern === "string") return data.pattern;
|
|
651
|
-
return
|
|
704
|
+
return resolveMongoLikePattern(data.pattern);
|
|
652
705
|
}
|
|
653
706
|
/**
|
|
654
707
|
* Build a condition based on the operator.
|
|
@@ -661,14 +714,59 @@ var MongoQueryParser = class {
|
|
|
661
714
|
buildOperatorCondition(field, operator, value) {
|
|
662
715
|
switch (operator) {
|
|
663
716
|
case "=": return { [field]: value };
|
|
664
|
-
case "!=":
|
|
717
|
+
case "!=":
|
|
718
|
+
case "<>": return { [field]: { $ne: value } };
|
|
719
|
+
case "in": return { [field]: { $in: this.assertArrayOperand(operator, value) } };
|
|
720
|
+
case "notIn":
|
|
721
|
+
case "not in": return { [field]: { $nin: this.assertArrayOperand(operator, value) } };
|
|
722
|
+
case "between":
|
|
723
|
+
case "notBetween":
|
|
724
|
+
case "not between": {
|
|
725
|
+
const range = this.assertArrayOperand(operator, value);
|
|
726
|
+
if (range.length !== 2) throw new Error(`Operator "${operator}" requires a [min, max] pair.`);
|
|
727
|
+
const bounds = {
|
|
728
|
+
$gte: range[0],
|
|
729
|
+
$lte: range[1]
|
|
730
|
+
};
|
|
731
|
+
return { [field]: operator === "between" ? bounds : { $not: bounds } };
|
|
732
|
+
}
|
|
733
|
+
case "like": return { [field]: {
|
|
734
|
+
$regex: resolveMongoLikePattern(value),
|
|
735
|
+
$options: "i"
|
|
736
|
+
} };
|
|
737
|
+
case "notLike":
|
|
738
|
+
case "not like": return { [field]: { $not: {
|
|
739
|
+
$regex: resolveMongoLikePattern(value),
|
|
740
|
+
$options: "i"
|
|
741
|
+
} } };
|
|
742
|
+
case "startsWith": return { [field]: {
|
|
743
|
+
$regex: `^${escapeRegex(String(value))}`,
|
|
744
|
+
$options: "i"
|
|
745
|
+
} };
|
|
746
|
+
case "notStartsWith": return { [field]: { $not: {
|
|
747
|
+
$regex: `^${escapeRegex(String(value))}`,
|
|
748
|
+
$options: "i"
|
|
749
|
+
} } };
|
|
750
|
+
case "endsWith": return { [field]: {
|
|
751
|
+
$regex: `${escapeRegex(String(value))}$`,
|
|
752
|
+
$options: "i"
|
|
753
|
+
} };
|
|
754
|
+
case "notEndsWith": return { [field]: { $not: {
|
|
755
|
+
$regex: `${escapeRegex(String(value))}$`,
|
|
756
|
+
$options: "i"
|
|
757
|
+
} } };
|
|
758
|
+
case "exists": return { [field]: { $exists: value !== false } };
|
|
665
759
|
case ">": return { [field]: { $gt: value } };
|
|
666
760
|
case ">=": return { [field]: { $gte: value } };
|
|
667
761
|
case "<": return { [field]: { $lt: value } };
|
|
668
762
|
case "<=": return { [field]: { $lte: value } };
|
|
669
|
-
default:
|
|
763
|
+
default: throw new Error(`Unsupported where operator "${operator}" on the MongoDB driver.`);
|
|
670
764
|
}
|
|
671
765
|
}
|
|
766
|
+
assertArrayOperand(operator, value) {
|
|
767
|
+
if (!Array.isArray(value)) throw new Error(`Operator "${operator}" requires an array operand.`);
|
|
768
|
+
return value;
|
|
769
|
+
}
|
|
672
770
|
/**
|
|
673
771
|
* Get MongoDB operator from comparison operator.
|
|
674
772
|
*
|
|
@@ -784,12 +882,12 @@ var MongoQueryParser = class {
|
|
|
784
882
|
}
|
|
785
883
|
startOfDay(date) {
|
|
786
884
|
const copy = new Date(date);
|
|
787
|
-
copy.
|
|
885
|
+
copy.setUTCHours(0, 0, 0, 0);
|
|
788
886
|
return copy;
|
|
789
887
|
}
|
|
790
888
|
endOfDay(date) {
|
|
791
889
|
const copy = new Date(date);
|
|
792
|
-
copy.
|
|
890
|
+
copy.setUTCHours(23, 59, 59, 999);
|
|
793
891
|
return copy;
|
|
794
892
|
}
|
|
795
893
|
normalizePath(path) {
|
|
@@ -989,7 +1087,7 @@ var MongoQueryParser = class {
|
|
|
989
1087
|
sort[op.data.field] = op.data.direction === "asc" ? 1 : -1;
|
|
990
1088
|
break;
|
|
991
1089
|
case "orderByRandom": return { $sample: { size: op.data.limit } };
|
|
992
|
-
case "orderByRaw":
|
|
1090
|
+
case "orderByRaw": throw new Error("orderByRaw() is not supported by the MongoDB driver; use orderBy() instead.");
|
|
993
1091
|
}
|
|
994
1092
|
return Object.keys(sort).length > 0 ? { $sort: sort } : null;
|
|
995
1093
|
}
|