@furystack/core 15.1.0 → 15.2.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 CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [15.2.0] - 2026-02-22
4
+
5
+ ### ✨ Features
6
+
7
+ ### Public `filterItems()` function
8
+
9
+ Extracted the filter logic from `InMemoryStore` into a standalone `filterItems()` function, now exported from `@furystack/core`. This allows consumers to filter arrays using `FilterType` expressions without needing a store instance.
10
+
11
+ **Usage:**
12
+
13
+ ```typescript
14
+ import { filterItems } from '@furystack/core'
15
+
16
+ const results = filterItems(myArray, {
17
+ name: { $startsWith: 'foo' },
18
+ age: { $gte: 18 },
19
+ })
20
+ ```
21
+
22
+ ### ♻️ Refactoring
23
+
24
+ - `InMemoryStore` now delegates to the public `filterItems()` function internally instead of using a private method
25
+
3
26
  ## [15.1.0] - 2026-02-19
4
27
 
5
28
  ### ✨ Features
@@ -0,0 +1,11 @@
1
+ import type { FilterType } from './models/physical-store.js';
2
+ /**
3
+ * Filters an array of items using a {@link FilterType} expression.
4
+ * Supports field-level operators ($eq, $ne, $in, $nin, $gt, $gte, $lt, $lte, $startsWith, $endsWith, $like, $regex)
5
+ * and logical operators ($and, $or).
6
+ * @param values The array of items to filter
7
+ * @param filter The filter expression to apply
8
+ * @returns The filtered array of items
9
+ */
10
+ export declare function filterItems<T>(values: T[], filter?: FilterType<T>): T[];
11
+ //# sourceMappingURL=filter-items.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-items.d.ts","sourceRoot":"","sources":["../src/filter-items.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAyB5D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAkHvE"}
@@ -0,0 +1,130 @@
1
+ import { isLogicalOperator, isOperator } from './models/physical-store.js';
2
+ const escapeRegexMeta = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
3
+ const evaluateLike = (value, likeString) => {
4
+ const likeRegex = `^${likeString.split('%').map(escapeRegexMeta).join('.*')}$`;
5
+ return value.match(new RegExp(likeRegex, 'i'));
6
+ };
7
+ /**
8
+ * Filters an array of items using a {@link FilterType} expression.
9
+ * Supports field-level operators ($eq, $ne, $in, $nin, $gt, $gte, $lt, $lte, $startsWith, $endsWith, $like, $regex)
10
+ * and logical operators ($and, $or).
11
+ * @param values The array of items to filter
12
+ * @param filter The filter expression to apply
13
+ * @returns The filtered array of items
14
+ */
15
+ export function filterItems(values, filter) {
16
+ if (!filter) {
17
+ return values;
18
+ }
19
+ return values.filter((item) => {
20
+ const filterRecord = filter;
21
+ const itemRecord = item;
22
+ for (const key in filterRecord) {
23
+ if (isLogicalOperator(key)) {
24
+ const filterValue = filterRecord[key];
25
+ switch (key) {
26
+ case '$and':
27
+ if (filterValue.some((v) => !filterItems([item], v).length)) {
28
+ return false;
29
+ }
30
+ break;
31
+ case '$or':
32
+ if (filterValue.some((v) => filterItems([item], v).length)) {
33
+ break;
34
+ }
35
+ return false;
36
+ default:
37
+ throw new Error(`The logical operation '${key}' is not a valid operation`);
38
+ }
39
+ }
40
+ else {
41
+ const fieldFilter = filterRecord[key];
42
+ if (typeof fieldFilter === 'object' && fieldFilter !== null) {
43
+ for (const filterKey in fieldFilter) {
44
+ if (isOperator(filterKey)) {
45
+ const itemValue = itemRecord[key];
46
+ const filterValue = fieldFilter[filterKey];
47
+ switch (filterKey) {
48
+ case '$eq':
49
+ if (filterValue !== itemValue) {
50
+ return false;
51
+ }
52
+ break;
53
+ case '$ne':
54
+ if (filterValue === itemValue) {
55
+ return false;
56
+ }
57
+ break;
58
+ case '$in':
59
+ if (!filterValue.includes(itemValue)) {
60
+ return false;
61
+ }
62
+ break;
63
+ case '$nin':
64
+ if (filterValue.includes(itemValue)) {
65
+ return false;
66
+ }
67
+ break;
68
+ case '$lt':
69
+ if (itemValue < filterValue) {
70
+ break;
71
+ }
72
+ return false;
73
+ case '$lte':
74
+ if (itemValue <= filterValue) {
75
+ break;
76
+ }
77
+ return false;
78
+ case '$gt':
79
+ if (itemValue > filterValue) {
80
+ break;
81
+ }
82
+ return false;
83
+ case '$gte':
84
+ if (itemValue >= filterValue) {
85
+ break;
86
+ }
87
+ return false;
88
+ case '$regex':
89
+ try {
90
+ if (!new RegExp(filterValue).test(String(itemValue))) {
91
+ return false;
92
+ }
93
+ }
94
+ catch (e) {
95
+ throw new Error(`Invalid regular expression for $regex filter on field '${key}': ${e.message}`, { cause: e });
96
+ }
97
+ break;
98
+ case '$startsWith':
99
+ if (!itemValue.startsWith(filterValue)) {
100
+ return false;
101
+ }
102
+ break;
103
+ case '$endsWith':
104
+ if (!itemValue.endsWith(filterValue)) {
105
+ return false;
106
+ }
107
+ break;
108
+ case '$like':
109
+ if (!evaluateLike(itemValue, filterValue)) {
110
+ return false;
111
+ }
112
+ break;
113
+ default:
114
+ throw new Error(`The expression (${filterKey}) is not a supported filter operation`);
115
+ }
116
+ }
117
+ else {
118
+ throw new Error(`The filter key '${filterKey}' is not a valid operation`);
119
+ }
120
+ }
121
+ }
122
+ else {
123
+ throw new Error(`The filter has to be an object, got ${typeof fieldFilter} for field '${key}'`);
124
+ }
125
+ }
126
+ }
127
+ return true;
128
+ });
129
+ }
130
+ //# sourceMappingURL=filter-items.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-items.js","sourceRoot":"","sources":["../src/filter-items.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=filter-items.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-items.spec.d.ts","sourceRoot":"","sources":["../src/filter-items.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,174 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { filterItems } from './filter-items.js';
3
+ const items = [
4
+ { id: 1, name: 'Alice', age: 30, active: true },
5
+ { id: 2, name: 'Bob', age: 25, active: false },
6
+ { id: 3, name: 'Charlie', age: 35, active: true },
7
+ { id: 4, name: 'Diana', age: 28, active: false },
8
+ { id: 5, name: 'Eve', age: 22, active: true },
9
+ ];
10
+ describe('filterItems', () => {
11
+ describe('no filter', () => {
12
+ it('should return all items when filter is undefined', () => {
13
+ expect(filterItems(items, undefined)).toEqual(items);
14
+ });
15
+ it('should return all items when filter is not provided', () => {
16
+ expect(filterItems(items)).toEqual(items);
17
+ });
18
+ it('should return an empty array when input is empty', () => {
19
+ expect(filterItems([], { name: { $eq: 'Alice' } })).toEqual([]);
20
+ });
21
+ it('should return all items when filter is an empty object', () => {
22
+ expect(filterItems(items, {})).toEqual(items);
23
+ });
24
+ });
25
+ describe('$eq', () => {
26
+ it('should return items matching the exact value', () => {
27
+ const result = filterItems(items, { name: { $eq: 'Alice' } });
28
+ expect(result).toEqual([items[0]]);
29
+ });
30
+ it('should return empty array when no items match', () => {
31
+ const result = filterItems(items, { name: { $eq: 'Nobody' } });
32
+ expect(result).toEqual([]);
33
+ });
34
+ });
35
+ describe('$ne', () => {
36
+ it('should return items not matching the value', () => {
37
+ const result = filterItems(items, { name: { $ne: 'Alice' } });
38
+ expect(result).toEqual([items[1], items[2], items[3], items[4]]);
39
+ });
40
+ });
41
+ describe('$in', () => {
42
+ it('should return items whose value is in the array', () => {
43
+ const result = filterItems(items, { name: { $in: ['Alice', 'Bob'] } });
44
+ expect(result).toEqual([items[0], items[1]]);
45
+ });
46
+ it('should return empty array when no values match', () => {
47
+ const result = filterItems(items, { name: { $in: ['Nobody'] } });
48
+ expect(result).toEqual([]);
49
+ });
50
+ });
51
+ describe('$nin', () => {
52
+ it('should return items whose value is not in the array', () => {
53
+ const result = filterItems(items, { name: { $nin: ['Alice', 'Bob'] } });
54
+ expect(result).toEqual([items[2], items[3], items[4]]);
55
+ });
56
+ });
57
+ describe('$gt', () => {
58
+ it('should return items with value greater than the threshold', () => {
59
+ const result = filterItems(items, { age: { $gt: 30 } });
60
+ expect(result).toEqual([items[2]]);
61
+ });
62
+ it('should exclude items equal to the threshold', () => {
63
+ const result = filterItems(items, { age: { $gt: 35 } });
64
+ expect(result).toEqual([]);
65
+ });
66
+ });
67
+ describe('$gte', () => {
68
+ it('should return items with value greater than or equal to the threshold', () => {
69
+ const result = filterItems(items, { age: { $gte: 30 } });
70
+ expect(result).toEqual([items[0], items[2]]);
71
+ });
72
+ });
73
+ describe('$lt', () => {
74
+ it('should return items with value less than the threshold', () => {
75
+ const result = filterItems(items, { age: { $lt: 25 } });
76
+ expect(result).toEqual([items[4]]);
77
+ });
78
+ it('should exclude items equal to the threshold', () => {
79
+ const result = filterItems(items, { age: { $lt: 22 } });
80
+ expect(result).toEqual([]);
81
+ });
82
+ });
83
+ describe('$lte', () => {
84
+ it('should return items with value less than or equal to the threshold', () => {
85
+ const result = filterItems(items, { age: { $lte: 25 } });
86
+ expect(result).toEqual([items[1], items[4]]);
87
+ });
88
+ });
89
+ describe('$startsWith', () => {
90
+ it('should return items whose string field starts with the value', () => {
91
+ const result = filterItems(items, { name: { $startsWith: 'Al' } });
92
+ expect(result).toEqual([items[0]]);
93
+ });
94
+ it('should return empty array when no items match', () => {
95
+ const result = filterItems(items, { name: { $startsWith: 'Zz' } });
96
+ expect(result).toEqual([]);
97
+ });
98
+ });
99
+ describe('$endsWith', () => {
100
+ it('should return items whose string field ends with the value', () => {
101
+ const result = filterItems(items, { name: { $endsWith: 'ce' } });
102
+ expect(result).toEqual([items[0]]);
103
+ });
104
+ });
105
+ describe('$like', () => {
106
+ it('should match with % wildcards', () => {
107
+ const result = filterItems(items, { name: { $like: 'A%' } });
108
+ expect(result).toEqual([items[0]]);
109
+ });
110
+ it('should match with % in the middle', () => {
111
+ const result = filterItems(items, { name: { $like: 'A%e' } });
112
+ expect(result).toEqual([items[0]]);
113
+ });
114
+ it('should be case-insensitive', () => {
115
+ const result = filterItems(items, { name: { $like: 'alice' } });
116
+ expect(result).toEqual([items[0]]);
117
+ });
118
+ it('should escape regex metacharacters in the pattern', () => {
119
+ const testItems = [{ value: 'foo.bar' }, { value: 'fooXbar' }];
120
+ const result = filterItems(testItems, { value: { $like: 'foo.bar' } });
121
+ expect(result).toEqual([{ value: 'foo.bar' }]);
122
+ });
123
+ });
124
+ describe('$regex', () => {
125
+ it('should return items matching the regex', () => {
126
+ const result = filterItems(items, { name: { $regex: '^[A-C]' } });
127
+ expect(result).toEqual([items[0], items[1], items[2]]);
128
+ });
129
+ it('should return empty array when no items match', () => {
130
+ const result = filterItems(items, { name: { $regex: '^Z' } });
131
+ expect(result).toEqual([]);
132
+ });
133
+ it('should throw on invalid regex syntax', () => {
134
+ expect(() => filterItems(items, { name: { $regex: '[invalid' } })).toThrow();
135
+ });
136
+ });
137
+ describe('$and', () => {
138
+ it('should return items matching all conditions', () => {
139
+ const result = filterItems(items, { $and: [{ age: { $gte: 25 } }, { active: { $eq: true } }] });
140
+ expect(result).toEqual([items[0], items[2]]);
141
+ });
142
+ it('should return empty array when conditions are mutually exclusive', () => {
143
+ const result = filterItems(items, { $and: [{ name: { $eq: 'Alice' } }, { name: { $eq: 'Bob' } }] });
144
+ expect(result).toEqual([]);
145
+ });
146
+ });
147
+ describe('$or', () => {
148
+ it('should return items matching any condition', () => {
149
+ const result = filterItems(items, { $or: [{ name: { $eq: 'Alice' } }, { name: { $eq: 'Bob' } }] });
150
+ expect(result).toEqual([items[0], items[1]]);
151
+ });
152
+ it('should return empty array when no conditions match', () => {
153
+ const result = filterItems(items, { $or: [{ name: { $eq: 'Nobody' } }, { name: { $eq: 'Nope' } }] });
154
+ expect(result).toEqual([]);
155
+ });
156
+ });
157
+ describe('combined field-level filters', () => {
158
+ it('should AND multiple field filters together', () => {
159
+ const result = filterItems(items, { age: { $gte: 25 }, active: { $eq: true } });
160
+ expect(result).toEqual([items[0], items[2]]);
161
+ });
162
+ });
163
+ describe('error cases', () => {
164
+ it('should throw when a field filter is not an object', () => {
165
+ const badFilter = { name: 'Alice' };
166
+ expect(() => filterItems(items, badFilter)).toThrow("The filter has to be an object, got string for field 'name'");
167
+ });
168
+ it('should throw for an unsupported filter operation', () => {
169
+ const badFilter = { name: { $unknown: 'x' } };
170
+ expect(() => filterItems(items, badFilter)).toThrow("The filter key '$unknown' is not a valid operation");
171
+ });
172
+ });
173
+ });
174
+ //# sourceMappingURL=filter-items.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-items.spec.js","sourceRoot":"","sources":["../src/filter-items.spec.ts"],"names":[],"mappings":"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"}
@@ -21,8 +21,6 @@ export declare class InMemoryStore<T, TPrimaryKey extends keyof T> extends Event
21
21
  add(...entries: T[]): Promise<CreateResult<T>>;
22
22
  cache: Map<T[TPrimaryKey], T>;
23
23
  get: (key: T[TPrimaryKey], select?: Array<keyof T>) => Promise<Awaited<T> | undefined>;
24
- private evaluateLike;
25
- private filterInternal;
26
24
  find<TFields extends Array<keyof T>>(searchOptions: FindOptions<T, TFields>): Promise<PartialResult<T, TFields>[]>;
27
25
  count(filter?: FilterType<T>): Promise<number>;
28
26
  update(id: T[TPrimaryKey], data: T): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-store.d.ts","sourceRoot":"","sources":["../src/in-memory-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAqBrH,qBAAa,aAAa,CAAC,CAAC,EAAE,WAAW,SAAS,MAAM,CAAC,CACvD,SAAQ,QAAQ,CAAC;IACf,aAAa,EAAE;QAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAA;IAC5B,eAAe,EAAE;QAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,CAAA;IAC3D,eAAe,EAAE;QAAE,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;KAAE,CAAA;CACzC,CACD,YAAW,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAE3C;;;OAGG;IACU,MAAM,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrD,GAAG,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAapD,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAY;IACzC,GAAG,GAAI,KAAK,CAAC,CAAC,WAAW,CAAC,EAAE,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,qCAGzD;IAED,OAAO,CAAC,YAAY,CAGnB;IAED,OAAO,CAAC,cAAc;IA8GT,IAAI,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC;IA4B3E,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IAI5B,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC;IAWxC,CAAC,MAAM,CAAC,OAAO,CAAC;IAKvB,SAAgB,UAAU,EAAE,WAAW,CAAA;IACvC,SAAgB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAEvC;;;;;OAKG;gBACS,OAAO,EAAE;QACnB;;WAEG;QACH,UAAU,EAAE,WAAW,CAAA;QACvB;;WAEG;QACH,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;KACxB;CAKF"}
1
+ {"version":3,"file":"in-memory-store.d.ts","sourceRoot":"","sources":["../src/in-memory-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAIrH,qBAAa,aAAa,CAAC,CAAC,EAAE,WAAW,SAAS,MAAM,CAAC,CACvD,SAAQ,QAAQ,CAAC;IACf,aAAa,EAAE;QAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAA;IAC5B,eAAe,EAAE;QAAE,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;KAAE,CAAA;IAC3D,eAAe,EAAE;QAAE,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;KAAE,CAAA;CACzC,CACD,YAAW,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAE3C;;;OAGG;IACU,MAAM,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrD,GAAG,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAapD,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAY;IACzC,GAAG,GAAI,KAAK,CAAC,CAAC,WAAW,CAAC,EAAE,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,qCAGzD;IAEY,IAAI,CAAC,OAAO,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC;IA4B3E,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IAI5B,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC;IAWxC,CAAC,MAAM,CAAC,OAAO,CAAC;IAKvB,SAAgB,UAAU,EAAE,WAAW,CAAA;IACvC,SAAgB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAEvC;;;;;OAKG;gBACS,OAAO,EAAE;QACnB;;WAEG;QACH,UAAU,EAAE,WAAW,CAAA;QACvB;;WAEG;QACH,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;KACxB;CAKF"}
@@ -1,5 +1,6 @@
1
1
  import { EventHub } from '@furystack/utils';
2
- import { isLogicalOperator, isOperator, selectFields } from './models/physical-store.js';
2
+ import { selectFields } from './models/physical-store.js';
3
+ import { filterItems } from './filter-items.js';
3
4
  export class InMemoryStore extends EventHub {
4
5
  /**
5
6
  *
@@ -28,122 +29,8 @@ export class InMemoryStore extends EventHub {
28
29
  const item = this.cache.get(key);
29
30
  return Promise.resolve(item && select ? selectFields(item, ...select) : item);
30
31
  };
31
- evaluateLike = (value, likeString) => {
32
- const likeRegex = `^${likeString.replace(/%/g, '.*')}$`;
33
- return value.match(new RegExp(likeRegex, 'i'));
34
- };
35
- filterInternal(values, filter) {
36
- if (!filter) {
37
- return values;
38
- }
39
- return values.filter((item) => {
40
- const filterRecord = filter;
41
- const itemRecord = item;
42
- for (const key in filterRecord) {
43
- if (isLogicalOperator(key)) {
44
- const filterValue = filterRecord[key];
45
- switch (key) {
46
- case '$and':
47
- if (filterValue.some((v) => !this.filterInternal([item], v).length)) {
48
- return false;
49
- }
50
- break;
51
- case '$or':
52
- if (filterValue.some((v) => this.filterInternal([item], v).length)) {
53
- break;
54
- }
55
- return false;
56
- default:
57
- throw new Error(`The logical operation '${key}' is not a valid operation`);
58
- }
59
- }
60
- else {
61
- const fieldFilter = filterRecord[key];
62
- if (typeof fieldFilter === 'object' && fieldFilter !== null) {
63
- for (const filterKey in fieldFilter) {
64
- if (isOperator(filterKey)) {
65
- const itemValue = itemRecord[key];
66
- const filterValue = fieldFilter[filterKey];
67
- switch (filterKey) {
68
- case '$eq':
69
- if (filterValue !== itemValue) {
70
- return false;
71
- }
72
- break;
73
- case '$ne':
74
- if (filterValue === itemValue) {
75
- return false;
76
- }
77
- break;
78
- case '$in':
79
- if (!filterValue.includes(itemValue)) {
80
- return false;
81
- }
82
- break;
83
- case '$nin':
84
- if (filterValue.includes(itemValue)) {
85
- return false;
86
- }
87
- break;
88
- case '$lt':
89
- if (itemValue < filterValue) {
90
- break;
91
- }
92
- return false;
93
- case '$lte':
94
- if (itemValue <= filterValue) {
95
- break;
96
- }
97
- return false;
98
- case '$gt':
99
- if (itemValue > filterValue) {
100
- break;
101
- }
102
- return false;
103
- case '$gte':
104
- if (itemValue >= filterValue) {
105
- break;
106
- }
107
- return false;
108
- case '$regex':
109
- if (!new RegExp(filterValue).test(String(itemValue))) {
110
- return false;
111
- }
112
- break;
113
- case '$startsWith':
114
- if (!itemValue.startsWith(filterValue)) {
115
- return false;
116
- }
117
- break;
118
- case '$endsWith':
119
- if (!itemValue.endsWith(filterValue)) {
120
- return false;
121
- }
122
- break;
123
- case '$like':
124
- if (!this.evaluateLike(itemValue, filterValue)) {
125
- return false;
126
- }
127
- break;
128
- default:
129
- throw new Error(`The expression (${filterKey}) is not supported by '${this.constructor.name}'!`);
130
- }
131
- }
132
- else {
133
- throw new Error(`The filter key '${filterKey}' is not a valid operation`);
134
- }
135
- }
136
- }
137
- else {
138
- throw new Error(`The filter has to be an object, got ${typeof fieldFilter} for field '${key}'`);
139
- }
140
- }
141
- }
142
- return true;
143
- });
144
- }
145
32
  async find(searchOptions) {
146
- let value = this.filterInternal([...this.cache.values()], searchOptions.filter);
33
+ let value = filterItems([...this.cache.values()], searchOptions.filter);
147
34
  if (searchOptions.order) {
148
35
  const orderRecord = searchOptions.order;
149
36
  for (const fieldName of Object.keys(searchOptions.order)) {
@@ -168,7 +55,7 @@ export class InMemoryStore extends EventHub {
168
55
  return value;
169
56
  }
170
57
  async count(filter) {
171
- return this.filterInternal([...this.cache.values()], filter).length;
58
+ return filterItems([...this.cache.values()], filter).length;
172
59
  }
173
60
  async update(id, data) {
174
61
  if (!this.cache.has(id)) {
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-store.js","sourceRoot":"","sources":["../src/in-memory-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"in-memory-store.js","sourceRoot":"","sources":["../src/in-memory-store.ts"],"names":[],"mappings":"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"}
package/esm/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './errors/index.js';
2
2
  export * from './models/physical-store.js';
3
3
  export * from './models/user.js';
4
+ export * from './filter-items.js';
4
5
  export * from './in-memory-store.js';
5
6
  export * from './store-manager.js';
6
7
  export * from './global-disposables.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,cAAc,CAAA"}
package/esm/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './errors/index.js';
2
2
  export * from './models/physical-store.js';
3
3
  export * from './models/user.js';
4
+ export * from './filter-items.js';
4
5
  export * from './in-memory-store.js';
5
6
  export * from './store-manager.js';
6
7
  export * from './global-disposables.js';
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,cAAc,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furystack/core",
3
- "version": "15.1.0",
3
+ "version": "15.2.0",
4
4
  "description": "Core FuryStack package",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -0,0 +1,216 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { filterItems } from './filter-items.js'
3
+ import type { FilterType } from './models/physical-store.js'
4
+
5
+ type TestItem = {
6
+ id: number
7
+ name: string
8
+ age: number
9
+ active: boolean
10
+ }
11
+
12
+ const items: TestItem[] = [
13
+ { id: 1, name: 'Alice', age: 30, active: true },
14
+ { id: 2, name: 'Bob', age: 25, active: false },
15
+ { id: 3, name: 'Charlie', age: 35, active: true },
16
+ { id: 4, name: 'Diana', age: 28, active: false },
17
+ { id: 5, name: 'Eve', age: 22, active: true },
18
+ ]
19
+
20
+ describe('filterItems', () => {
21
+ describe('no filter', () => {
22
+ it('should return all items when filter is undefined', () => {
23
+ expect(filterItems(items, undefined)).toEqual(items)
24
+ })
25
+
26
+ it('should return all items when filter is not provided', () => {
27
+ expect(filterItems(items)).toEqual(items)
28
+ })
29
+
30
+ it('should return an empty array when input is empty', () => {
31
+ expect(filterItems<TestItem>([], { name: { $eq: 'Alice' } })).toEqual([])
32
+ })
33
+
34
+ it('should return all items when filter is an empty object', () => {
35
+ expect(filterItems(items, {} as FilterType<TestItem>)).toEqual(items)
36
+ })
37
+ })
38
+
39
+ describe('$eq', () => {
40
+ it('should return items matching the exact value', () => {
41
+ const result = filterItems(items, { name: { $eq: 'Alice' } })
42
+ expect(result).toEqual([items[0]])
43
+ })
44
+
45
+ it('should return empty array when no items match', () => {
46
+ const result = filterItems(items, { name: { $eq: 'Nobody' } })
47
+ expect(result).toEqual([])
48
+ })
49
+ })
50
+
51
+ describe('$ne', () => {
52
+ it('should return items not matching the value', () => {
53
+ const result = filterItems(items, { name: { $ne: 'Alice' } })
54
+ expect(result).toEqual([items[1], items[2], items[3], items[4]])
55
+ })
56
+ })
57
+
58
+ describe('$in', () => {
59
+ it('should return items whose value is in the array', () => {
60
+ const result = filterItems(items, { name: { $in: ['Alice', 'Bob'] } })
61
+ expect(result).toEqual([items[0], items[1]])
62
+ })
63
+
64
+ it('should return empty array when no values match', () => {
65
+ const result = filterItems(items, { name: { $in: ['Nobody'] } })
66
+ expect(result).toEqual([])
67
+ })
68
+ })
69
+
70
+ describe('$nin', () => {
71
+ it('should return items whose value is not in the array', () => {
72
+ const result = filterItems(items, { name: { $nin: ['Alice', 'Bob'] } })
73
+ expect(result).toEqual([items[2], items[3], items[4]])
74
+ })
75
+ })
76
+
77
+ describe('$gt', () => {
78
+ it('should return items with value greater than the threshold', () => {
79
+ const result = filterItems(items, { age: { $gt: 30 } })
80
+ expect(result).toEqual([items[2]])
81
+ })
82
+
83
+ it('should exclude items equal to the threshold', () => {
84
+ const result = filterItems(items, { age: { $gt: 35 } })
85
+ expect(result).toEqual([])
86
+ })
87
+ })
88
+
89
+ describe('$gte', () => {
90
+ it('should return items with value greater than or equal to the threshold', () => {
91
+ const result = filterItems(items, { age: { $gte: 30 } })
92
+ expect(result).toEqual([items[0], items[2]])
93
+ })
94
+ })
95
+
96
+ describe('$lt', () => {
97
+ it('should return items with value less than the threshold', () => {
98
+ const result = filterItems(items, { age: { $lt: 25 } })
99
+ expect(result).toEqual([items[4]])
100
+ })
101
+
102
+ it('should exclude items equal to the threshold', () => {
103
+ const result = filterItems(items, { age: { $lt: 22 } })
104
+ expect(result).toEqual([])
105
+ })
106
+ })
107
+
108
+ describe('$lte', () => {
109
+ it('should return items with value less than or equal to the threshold', () => {
110
+ const result = filterItems(items, { age: { $lte: 25 } })
111
+ expect(result).toEqual([items[1], items[4]])
112
+ })
113
+ })
114
+
115
+ describe('$startsWith', () => {
116
+ it('should return items whose string field starts with the value', () => {
117
+ const result = filterItems(items, { name: { $startsWith: 'Al' } })
118
+ expect(result).toEqual([items[0]])
119
+ })
120
+
121
+ it('should return empty array when no items match', () => {
122
+ const result = filterItems(items, { name: { $startsWith: 'Zz' } })
123
+ expect(result).toEqual([])
124
+ })
125
+ })
126
+
127
+ describe('$endsWith', () => {
128
+ it('should return items whose string field ends with the value', () => {
129
+ const result = filterItems(items, { name: { $endsWith: 'ce' } })
130
+ expect(result).toEqual([items[0]])
131
+ })
132
+ })
133
+
134
+ describe('$like', () => {
135
+ it('should match with % wildcards', () => {
136
+ const result = filterItems(items, { name: { $like: 'A%' } })
137
+ expect(result).toEqual([items[0]])
138
+ })
139
+
140
+ it('should match with % in the middle', () => {
141
+ const result = filterItems(items, { name: { $like: 'A%e' } })
142
+ expect(result).toEqual([items[0]])
143
+ })
144
+
145
+ it('should be case-insensitive', () => {
146
+ const result = filterItems(items, { name: { $like: 'alice' } })
147
+ expect(result).toEqual([items[0]])
148
+ })
149
+
150
+ it('should escape regex metacharacters in the pattern', () => {
151
+ type Item = { value: string }
152
+ const testItems: Item[] = [{ value: 'foo.bar' }, { value: 'fooXbar' }]
153
+ const result = filterItems(testItems, { value: { $like: 'foo.bar' } } as FilterType<Item>)
154
+ expect(result).toEqual([{ value: 'foo.bar' }])
155
+ })
156
+ })
157
+
158
+ describe('$regex', () => {
159
+ it('should return items matching the regex', () => {
160
+ const result = filterItems(items, { name: { $regex: '^[A-C]' } })
161
+ expect(result).toEqual([items[0], items[1], items[2]])
162
+ })
163
+
164
+ it('should return empty array when no items match', () => {
165
+ const result = filterItems(items, { name: { $regex: '^Z' } })
166
+ expect(result).toEqual([])
167
+ })
168
+
169
+ it('should throw on invalid regex syntax', () => {
170
+ expect(() => filterItems(items, { name: { $regex: '[invalid' } })).toThrow()
171
+ })
172
+ })
173
+
174
+ describe('$and', () => {
175
+ it('should return items matching all conditions', () => {
176
+ const result = filterItems(items, { $and: [{ age: { $gte: 25 } }, { active: { $eq: true } }] })
177
+ expect(result).toEqual([items[0], items[2]])
178
+ })
179
+
180
+ it('should return empty array when conditions are mutually exclusive', () => {
181
+ const result = filterItems(items, { $and: [{ name: { $eq: 'Alice' } }, { name: { $eq: 'Bob' } }] })
182
+ expect(result).toEqual([])
183
+ })
184
+ })
185
+
186
+ describe('$or', () => {
187
+ it('should return items matching any condition', () => {
188
+ const result = filterItems(items, { $or: [{ name: { $eq: 'Alice' } }, { name: { $eq: 'Bob' } }] })
189
+ expect(result).toEqual([items[0], items[1]])
190
+ })
191
+
192
+ it('should return empty array when no conditions match', () => {
193
+ const result = filterItems(items, { $or: [{ name: { $eq: 'Nobody' } }, { name: { $eq: 'Nope' } }] })
194
+ expect(result).toEqual([])
195
+ })
196
+ })
197
+
198
+ describe('combined field-level filters', () => {
199
+ it('should AND multiple field filters together', () => {
200
+ const result = filterItems(items, { age: { $gte: 25 }, active: { $eq: true } })
201
+ expect(result).toEqual([items[0], items[2]])
202
+ })
203
+ })
204
+
205
+ describe('error cases', () => {
206
+ it('should throw when a field filter is not an object', () => {
207
+ const badFilter = { name: 'Alice' } as unknown as FilterType<TestItem>
208
+ expect(() => filterItems(items, badFilter)).toThrow("The filter has to be an object, got string for field 'name'")
209
+ })
210
+
211
+ it('should throw for an unsupported filter operation', () => {
212
+ const badFilter = { name: { $unknown: 'x' } } as unknown as FilterType<TestItem>
213
+ expect(() => filterItems(items, badFilter)).toThrow("The filter key '$unknown' is not a valid operation")
214
+ })
215
+ })
216
+ })
@@ -0,0 +1,148 @@
1
+ import type { FilterType } from './models/physical-store.js'
2
+ import { isLogicalOperator, isOperator } from './models/physical-store.js'
3
+
4
+ type FieldOperatorFilter = {
5
+ $eq?: unknown
6
+ $ne?: unknown
7
+ $in?: unknown[]
8
+ $nin?: unknown[]
9
+ $gt?: unknown
10
+ $gte?: unknown
11
+ $lt?: unknown
12
+ $lte?: unknown
13
+ $startsWith?: string
14
+ $endsWith?: string
15
+ $like?: string
16
+ $regex?: string
17
+ }
18
+
19
+ const escapeRegexMeta = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
20
+
21
+ const evaluateLike = (value: string, likeString: string) => {
22
+ const likeRegex = `^${likeString.split('%').map(escapeRegexMeta).join('.*')}$`
23
+ return value.match(new RegExp(likeRegex, 'i'))
24
+ }
25
+
26
+ /**
27
+ * Filters an array of items using a {@link FilterType} expression.
28
+ * Supports field-level operators ($eq, $ne, $in, $nin, $gt, $gte, $lt, $lte, $startsWith, $endsWith, $like, $regex)
29
+ * and logical operators ($and, $or).
30
+ * @param values The array of items to filter
31
+ * @param filter The filter expression to apply
32
+ * @returns The filtered array of items
33
+ */
34
+ export function filterItems<T>(values: T[], filter?: FilterType<T>): T[] {
35
+ if (!filter) {
36
+ return values
37
+ }
38
+ return values.filter((item) => {
39
+ const filterRecord = filter as Record<string, Array<FilterType<T>> | FieldOperatorFilter | undefined>
40
+ const itemRecord = item as Record<string, unknown>
41
+
42
+ for (const key in filterRecord) {
43
+ if (isLogicalOperator(key)) {
44
+ const filterValue = filterRecord[key] as Array<FilterType<T>>
45
+ switch (key) {
46
+ case '$and':
47
+ if (filterValue.some((v: FilterType<T>) => !filterItems([item], v).length)) {
48
+ return false
49
+ }
50
+ break
51
+ case '$or':
52
+ if (filterValue.some((v: FilterType<T>) => filterItems([item], v).length)) {
53
+ break
54
+ }
55
+ return false
56
+ default:
57
+ throw new Error(`The logical operation '${key}' is not a valid operation`)
58
+ }
59
+ } else {
60
+ const fieldFilter = filterRecord[key] as FieldOperatorFilter | undefined
61
+ if (typeof fieldFilter === 'object' && fieldFilter !== null) {
62
+ for (const filterKey in fieldFilter) {
63
+ if (isOperator(filterKey)) {
64
+ const itemValue = itemRecord[key]
65
+ const filterValue = fieldFilter[filterKey as keyof FieldOperatorFilter]
66
+ switch (filterKey) {
67
+ case '$eq':
68
+ if (filterValue !== itemValue) {
69
+ return false
70
+ }
71
+ break
72
+ case '$ne':
73
+ if (filterValue === itemValue) {
74
+ return false
75
+ }
76
+ break
77
+ case '$in':
78
+ if (!(filterValue as unknown[]).includes(itemValue)) {
79
+ return false
80
+ }
81
+ break
82
+ case '$nin':
83
+ if ((filterValue as unknown[]).includes(itemValue)) {
84
+ return false
85
+ }
86
+ break
87
+ case '$lt':
88
+ if ((itemValue as number) < (filterValue as number)) {
89
+ break
90
+ }
91
+ return false
92
+ case '$lte':
93
+ if ((itemValue as number) <= (filterValue as number)) {
94
+ break
95
+ }
96
+ return false
97
+ case '$gt':
98
+ if ((itemValue as number) > (filterValue as number)) {
99
+ break
100
+ }
101
+ return false
102
+ case '$gte':
103
+ if ((itemValue as number) >= (filterValue as number)) {
104
+ break
105
+ }
106
+ return false
107
+ case '$regex':
108
+ try {
109
+ if (!new RegExp(filterValue as string).test(String(itemValue))) {
110
+ return false
111
+ }
112
+ } catch (e) {
113
+ throw new Error(
114
+ `Invalid regular expression for $regex filter on field '${key}': ${(e as Error).message}`,
115
+ { cause: e },
116
+ )
117
+ }
118
+ break
119
+ case '$startsWith':
120
+ if (!(itemValue as string).startsWith(filterValue as string)) {
121
+ return false
122
+ }
123
+ break
124
+ case '$endsWith':
125
+ if (!(itemValue as string).endsWith(filterValue as string)) {
126
+ return false
127
+ }
128
+ break
129
+ case '$like':
130
+ if (!evaluateLike(itemValue as string, filterValue as string)) {
131
+ return false
132
+ }
133
+ break
134
+ default:
135
+ throw new Error(`The expression (${filterKey}) is not a supported filter operation`)
136
+ }
137
+ } else {
138
+ throw new Error(`The filter key '${filterKey}' is not a valid operation`)
139
+ }
140
+ }
141
+ } else {
142
+ throw new Error(`The filter has to be an object, got ${typeof fieldFilter} for field '${key}'`)
143
+ }
144
+ }
145
+ }
146
+ return true
147
+ })
148
+ }
@@ -1,25 +1,8 @@
1
1
  import type { Constructable } from '@furystack/inject'
2
2
  import { EventHub } from '@furystack/utils'
3
3
  import type { CreateResult, FilterType, FindOptions, PartialResult, PhysicalStore } from './models/physical-store.js'
4
- import { isLogicalOperator, isOperator, selectFields } from './models/physical-store.js'
5
-
6
- /**
7
- * Helper type representing all possible field filter operations
8
- */
9
- type FieldOperatorFilter = {
10
- $eq?: unknown
11
- $ne?: unknown
12
- $in?: unknown[]
13
- $nin?: unknown[]
14
- $gt?: unknown
15
- $gte?: unknown
16
- $lt?: unknown
17
- $lte?: unknown
18
- $startsWith?: string
19
- $endsWith?: string
20
- $like?: string
21
- $regex?: string
22
- }
4
+ import { selectFields } from './models/physical-store.js'
5
+ import { filterItems } from './filter-items.js'
23
6
 
24
7
  export class InMemoryStore<T, TPrimaryKey extends keyof T>
25
8
  extends EventHub<{
@@ -59,123 +42,8 @@ export class InMemoryStore<T, TPrimaryKey extends keyof T>
59
42
  return Promise.resolve(item && select ? selectFields(item, ...select) : item)
60
43
  }
61
44
 
62
- private evaluateLike = (value: string, likeString: string) => {
63
- const likeRegex = `^${likeString.replace(/%/g, '.*')}$`
64
- return value.match(new RegExp(likeRegex, 'i'))
65
- }
66
-
67
- private filterInternal(values: T[], filter?: FilterType<T>): T[] {
68
- if (!filter) {
69
- return values
70
- }
71
- return values.filter((item) => {
72
- const filterRecord = filter as Record<string, Array<FilterType<T>> | FieldOperatorFilter | undefined>
73
- const itemRecord = item as Record<string, unknown>
74
-
75
- for (const key in filterRecord) {
76
- if (isLogicalOperator(key)) {
77
- const filterValue = filterRecord[key] as Array<FilterType<T>>
78
- switch (key) {
79
- case '$and':
80
- if (filterValue.some((v: FilterType<T>) => !this.filterInternal([item], v).length)) {
81
- return false
82
- }
83
- break
84
- case '$or':
85
- if (filterValue.some((v: FilterType<T>) => this.filterInternal([item], v).length)) {
86
- break
87
- }
88
- return false
89
- default:
90
- throw new Error(`The logical operation '${key}' is not a valid operation`)
91
- }
92
- } else {
93
- const fieldFilter = filterRecord[key] as FieldOperatorFilter | undefined
94
- if (typeof fieldFilter === 'object' && fieldFilter !== null) {
95
- for (const filterKey in fieldFilter) {
96
- if (isOperator(filterKey)) {
97
- const itemValue = itemRecord[key]
98
- const filterValue = fieldFilter[filterKey as keyof FieldOperatorFilter]
99
- switch (filterKey) {
100
- case '$eq':
101
- if (filterValue !== itemValue) {
102
- return false
103
- }
104
- break
105
- case '$ne':
106
- if (filterValue === itemValue) {
107
- return false
108
- }
109
- break
110
- case '$in':
111
- if (!(filterValue as unknown[]).includes(itemValue)) {
112
- return false
113
- }
114
- break
115
-
116
- case '$nin':
117
- if ((filterValue as unknown[]).includes(itemValue)) {
118
- return false
119
- }
120
- break
121
- case '$lt':
122
- if ((itemValue as number) < (filterValue as number)) {
123
- break
124
- }
125
- return false
126
- case '$lte':
127
- if ((itemValue as number) <= (filterValue as number)) {
128
- break
129
- }
130
- return false
131
- case '$gt':
132
- if ((itemValue as number) > (filterValue as number)) {
133
- break
134
- }
135
- return false
136
- case '$gte':
137
- if ((itemValue as number) >= (filterValue as number)) {
138
- break
139
- }
140
- return false
141
- case '$regex':
142
- if (!new RegExp(filterValue as string).test(String(itemValue))) {
143
- return false
144
- }
145
- break
146
- case '$startsWith':
147
- if (!(itemValue as string).startsWith(filterValue as string)) {
148
- return false
149
- }
150
- break
151
- case '$endsWith':
152
- if (!(itemValue as string).endsWith(filterValue as string)) {
153
- return false
154
- }
155
- break
156
- case '$like':
157
- if (!this.evaluateLike(itemValue as string, filterValue as string)) {
158
- return false
159
- }
160
- break
161
- default:
162
- throw new Error(`The expression (${filterKey}) is not supported by '${this.constructor.name}'!`)
163
- }
164
- } else {
165
- throw new Error(`The filter key '${filterKey}' is not a valid operation`)
166
- }
167
- }
168
- } else {
169
- throw new Error(`The filter has to be an object, got ${typeof fieldFilter} for field '${key}'`)
170
- }
171
- }
172
- }
173
- return true
174
- })
175
- }
176
-
177
45
  public async find<TFields extends Array<keyof T>>(searchOptions: FindOptions<T, TFields>) {
178
- let value: Array<PartialResult<T, TFields>> = this.filterInternal([...this.cache.values()], searchOptions.filter)
46
+ let value: Array<PartialResult<T, TFields>> = filterItems([...this.cache.values()], searchOptions.filter)
179
47
 
180
48
  if (searchOptions.order) {
181
49
  const orderRecord = searchOptions.order as Record<string, 'ASC' | 'DESC'>
@@ -203,7 +71,7 @@ export class InMemoryStore<T, TPrimaryKey extends keyof T>
203
71
  }
204
72
 
205
73
  public async count(filter?: FilterType<T>) {
206
- return this.filterInternal([...this.cache.values()], filter).length
74
+ return filterItems([...this.cache.values()], filter).length
207
75
  }
208
76
 
209
77
  public async update(id: T[TPrimaryKey], data: T) {
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './errors/index.js'
2
2
  export * from './models/physical-store.js'
3
3
  export * from './models/user.js'
4
+ export * from './filter-items.js'
4
5
  export * from './in-memory-store.js'
5
6
  export * from './store-manager.js'
6
7
  export * from './global-disposables.js'