@objectstack/driver-memory 3.2.1 → 3.2.2
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +16 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +102 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +102 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/memory-driver.test.ts +128 -0
- package/src/memory-driver.ts +127 -2
- package/src/memory-matcher.ts +9 -6
package/dist/index.mjs
CHANGED
|
@@ -161,9 +161,6 @@ import { Query, Aggregator } from "mingo";
|
|
|
161
161
|
|
|
162
162
|
// src/memory-matcher.ts
|
|
163
163
|
function getValueByPath(obj, path2) {
|
|
164
|
-
if (path2 === "_id" && obj._id === void 0 && obj.id !== void 0) {
|
|
165
|
-
return obj.id;
|
|
166
|
-
}
|
|
167
164
|
if (!path2.includes(".")) return obj[path2];
|
|
168
165
|
return path2.split(".").reduce((o, i) => o ? o[i] : void 0, obj);
|
|
169
166
|
}
|
|
@@ -633,7 +630,7 @@ var _InMemoryDriver = class _InMemoryDriver {
|
|
|
633
630
|
const op = filters.operator === "or" ? "$or" : "$and";
|
|
634
631
|
return { [op]: conditions };
|
|
635
632
|
}
|
|
636
|
-
return filters;
|
|
633
|
+
return this.normalizeFilterCondition(filters);
|
|
637
634
|
}
|
|
638
635
|
if (!Array.isArray(filters) || filters.length === 0) return {};
|
|
639
636
|
const logicGroups = [
|
|
@@ -694,6 +691,9 @@ var _InMemoryDriver = class _InMemoryDriver {
|
|
|
694
691
|
case "contains":
|
|
695
692
|
case "like":
|
|
696
693
|
return { [field]: { $regex: new RegExp(this.escapeRegex(value), "i") } };
|
|
694
|
+
case "notcontains":
|
|
695
|
+
case "not_contains":
|
|
696
|
+
return { [field]: { $not: { $regex: new RegExp(this.escapeRegex(value), "i") } } };
|
|
697
697
|
case "startswith":
|
|
698
698
|
case "starts_with":
|
|
699
699
|
return { [field]: { $regex: new RegExp(`^${this.escapeRegex(value)}`, "i") } };
|
|
@@ -709,6 +709,104 @@ var _InMemoryDriver = class _InMemoryDriver {
|
|
|
709
709
|
return null;
|
|
710
710
|
}
|
|
711
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* Normalize a FilterCondition object by converting non-standard $-prefixed
|
|
714
|
+
* operators ($contains, $notContains, $startsWith, $endsWith, $between, $null)
|
|
715
|
+
* to Mingo-compatible equivalents ($regex, $gte/$lte, null checks).
|
|
716
|
+
*/
|
|
717
|
+
normalizeFilterCondition(filter) {
|
|
718
|
+
const result = {};
|
|
719
|
+
const extraAndConditions = [];
|
|
720
|
+
for (const key of Object.keys(filter)) {
|
|
721
|
+
const value = filter[key];
|
|
722
|
+
if (key === "$and" || key === "$or") {
|
|
723
|
+
result[key] = Array.isArray(value) ? value.map((child) => this.normalizeFilterCondition(child)) : value;
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
if (key === "$not") {
|
|
727
|
+
result[key] = value && typeof value === "object" ? this.normalizeFilterCondition(value) : value;
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
if (key.startsWith("$")) {
|
|
731
|
+
result[key] = value;
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp)) {
|
|
735
|
+
const normalized = this.normalizeFieldOperators(value);
|
|
736
|
+
if (normalized._multiRegex) {
|
|
737
|
+
const regexConditions = normalized._multiRegex;
|
|
738
|
+
delete normalized._multiRegex;
|
|
739
|
+
for (const rc of regexConditions) {
|
|
740
|
+
extraAndConditions.push({ [key]: { ...normalized, ...rc } });
|
|
741
|
+
}
|
|
742
|
+
} else {
|
|
743
|
+
result[key] = normalized;
|
|
744
|
+
}
|
|
745
|
+
} else {
|
|
746
|
+
result[key] = value;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
if (extraAndConditions.length > 0) {
|
|
750
|
+
const existing = result.$and;
|
|
751
|
+
const andArray = Array.isArray(existing) ? existing : [];
|
|
752
|
+
if (Object.keys(result).filter((k) => k !== "$and").length > 0) {
|
|
753
|
+
const rest = { ...result };
|
|
754
|
+
delete rest.$and;
|
|
755
|
+
andArray.push(rest);
|
|
756
|
+
}
|
|
757
|
+
andArray.push(...extraAndConditions);
|
|
758
|
+
return { $and: andArray };
|
|
759
|
+
}
|
|
760
|
+
return result;
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Convert non-standard field operators to Mingo-compatible format.
|
|
764
|
+
* When multiple regex-producing operators appear on the same field
|
|
765
|
+
* (e.g. $startsWith + $endsWith), they are combined via $and.
|
|
766
|
+
*/
|
|
767
|
+
normalizeFieldOperators(ops) {
|
|
768
|
+
const result = {};
|
|
769
|
+
const regexConditions = [];
|
|
770
|
+
for (const op of Object.keys(ops)) {
|
|
771
|
+
const val = ops[op];
|
|
772
|
+
switch (op) {
|
|
773
|
+
case "$contains":
|
|
774
|
+
regexConditions.push({ $regex: new RegExp(this.escapeRegex(val), "i") });
|
|
775
|
+
break;
|
|
776
|
+
case "$notContains":
|
|
777
|
+
result.$not = { $regex: new RegExp(this.escapeRegex(val), "i") };
|
|
778
|
+
break;
|
|
779
|
+
case "$startsWith":
|
|
780
|
+
regexConditions.push({ $regex: new RegExp(`^${this.escapeRegex(val)}`, "i") });
|
|
781
|
+
break;
|
|
782
|
+
case "$endsWith":
|
|
783
|
+
regexConditions.push({ $regex: new RegExp(`${this.escapeRegex(val)}$`, "i") });
|
|
784
|
+
break;
|
|
785
|
+
case "$between":
|
|
786
|
+
if (Array.isArray(val) && val.length === 2) {
|
|
787
|
+
result.$gte = val[0];
|
|
788
|
+
result.$lte = val[1];
|
|
789
|
+
}
|
|
790
|
+
break;
|
|
791
|
+
case "$null":
|
|
792
|
+
if (val === true) {
|
|
793
|
+
result.$eq = null;
|
|
794
|
+
} else {
|
|
795
|
+
result.$ne = null;
|
|
796
|
+
}
|
|
797
|
+
break;
|
|
798
|
+
default:
|
|
799
|
+
result[op] = val;
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
if (regexConditions.length === 1) {
|
|
804
|
+
Object.assign(result, regexConditions[0]);
|
|
805
|
+
} else if (regexConditions.length > 1) {
|
|
806
|
+
result._multiRegex = regexConditions;
|
|
807
|
+
}
|
|
808
|
+
return result;
|
|
809
|
+
}
|
|
712
810
|
/**
|
|
713
811
|
* Escape special regex characters for safe literal matching.
|
|
714
812
|
*/
|