ajoq 0.1.43 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,14 +1,49 @@
1
1
  # AJOQ
2
2
 
3
- Another Javascript Object Query.
4
-
5
3
  [![Github Build Status][github-image]][github-url]
6
4
  [![NPM version][npm-image]][npm-url]
7
5
  [![Downloads][downloads-image]][npm-url]
8
6
  [![Snyk][snyk-image]][snyk-url]
9
7
 
8
+ **The fastest MongoDB-style query library for JavaScript - 3x faster than Sift, 14x faster than Mingo.**
9
+
10
+ AJOQ compiles your queries into optimized JavaScript functions, giving you the expressive power of MongoDB queries with superior performance.
11
+
12
+ ## Why AJOQ?
13
+
14
+ - 🚀 **Blazing Fast** - 3-14x faster than alternatives (see [benchmarks](#performance-benchmarks))
15
+ - 🎯 **MongoDB Compatible** - Use familiar MongoDB query syntax
16
+ - 📦 **Zero Dependencies** - Tiny, self-contained library
17
+ - 🔧 **TypeScript Ready** - Full type safety and IntelliSense support
18
+ - ⚡ **Compiled Queries** - Queries compile to optimized JavaScript, not interpreted
19
+
20
+ ### Perfect for:
21
+ - **High-performance filtering** - When speed matters
22
+ - **Client-side operations** - Filter API responses without server roundtrips
23
+ - **Static site generators** - Fast search in build processes
24
+ - **Real-time applications** - Low-latency data filtering
25
+ - **Large datasets** - Efficiently process thousands of records
10
26
 
11
- Uses mongodb like query structure to execute in function
27
+ ## Quick Example
28
+
29
+ ```ts
30
+ // Complex user search with MongoDB-style queries
31
+ const users = [
32
+ { name: 'Alice', age: 28, skills: ['js', 'react'], active: true },
33
+ { name: 'Bob', age: 32, skills: ['python'], active: false },
34
+ { name: 'Charlie', age: 25, skills: ['js', 'vue'], active: true }
35
+ ];
36
+
37
+ // Find active users who know JavaScript and are under 30
38
+ const filter = createFilter({
39
+ active: true,
40
+ age: { $lt: 30 },
41
+ skills: { $con: 'js' }
42
+ });
43
+
44
+ const results = users.filter(filter);
45
+ // → [{ name: 'Alice', ... }, { name: 'Charlie', ... }]
46
+ ```
12
47
 
13
48
  ## Installation
14
49
 
@@ -16,7 +51,7 @@ Uses mongodb like query structure to execute in function
16
51
  npm install ajoq
17
52
  ```
18
53
 
19
- ## Usage
54
+ ## Basic Usage
20
55
 
21
56
  ### Filter function
22
57
  ```ts
@@ -45,14 +80,53 @@ interface Data {
45
80
  const values: Data[] = [{ name: 'John', age: 42 }, { name: 'Jane', age: 18 }];
46
81
 
47
82
  const sortFn = createSort<Data>({ name: 'asc', age: -1 });
48
- const sorted = values.toSorted(sortFn); // [{ name: 'John', age: 42 }, { name: 'Jane', age: 18 }]
83
+ const sorted = values.toSorted(sortFn); // [{ name: 'Jane', age: 18 }, { name: 'John', age: 42 }]
84
+ ```
85
+
86
+ ## Performance Benchmarks
87
+
88
+ ### AJOQ vs Popular Alternatives
89
+
90
+ Benchmarked on 10,000 objects using [Overtake](https://github.com/3axap4eHko/overtake) benchmark suite:
91
+
92
+ | Library | Operations/sec | Relative Speed | Weekly Downloads |
93
+ |---------|---------------|----------------|------------------|
94
+ | **AJOQ** | **7,673 ops/s** | **Baseline** | - |
95
+ | [Sift](https://github.com/crcn/sift.js) | 2,442 ops/s | 3.1x slower | 3.3M |
96
+ | [Mingo](https://github.com/kofrasa/mingo) | 551 ops/s | 13.9x slower | 178k |
97
+
98
+ ### Why is AJOQ Faster?
99
+
100
+ 1. **Query Compilation** - Queries compile once into native JavaScript functions
101
+ 2. **Zero Overhead** - No interpretation layer or external dependencies
102
+ 3. **Optimized Operations** - Automatic caching (e.g., Set creation for array operations)
103
+ 4. **Direct Property Access** - Generated code uses direct property access without abstraction
104
+
105
+ ### Run Benchmarks Yourself
106
+
107
+ ```bash
108
+ # Install dependencies
109
+ npm install --save-dev sift mingo overtake
110
+
111
+ # Run benchmark
112
+ npx overtake benchmark.ts
49
113
  ```
50
114
 
115
+ See [benchmark.ts](./benchmark.ts) for the full benchmark suite.
116
+
51
117
  ## Documentation
52
118
 
53
- ### Filter
119
+ ### How It Works
120
+
121
+ Unlike other query libraries that interpret queries at runtime, AJOQ **compiles** your MongoDB-style queries into optimized JavaScript functions. This means:
122
+
123
+ 1. **Parse once, run many times** - Query compilation happens once
124
+ 2. **Native JavaScript speed** - No interpretation overhead
125
+ 3. **Optimized operations** - Automatic caching of repeated operations (like Set creation)
126
+
127
+ ### Filter API
54
128
 
55
- The `Filter` type represents a flexible and expressive way to filter and search data. It supports combining conditions with logical operators, making it suitable for complex query requirements.
129
+ Filters support all MongoDB query operators for maximum compatibility.
56
130
 
57
131
  #### Logical Operators
58
132
 
@@ -72,6 +146,8 @@ The `Filter` type represents a flexible and expressive way to filter and search
72
146
  - `$exists`: Matches if the field exists or does not exist (true or false).
73
147
  - `$match`: Matches if the field value matches a regex or string.
74
148
  - `$nmatch`: Matches if the field value does not match a regex or string.
149
+ - `$incl`: Matches if the string field includes the specified substring.
150
+ - `$nincl`: Matches if the string field does not include the specified substring.
75
151
  - `$bits`: Matches if any bits from the field value match the specified bitmask.
76
152
  - `$nbits`: Matches if no bits from the field value match the specified bitmask.
77
153
  - `$type`: Matches if the field's type matches the specified type.
@@ -85,6 +161,75 @@ The `Filter` type represents a flexible and expressive way to filter and search
85
161
  - `$con`: Matches if the field array contains the specified value.
86
162
  - `$ncon`: Matches if the field array does not contain the specified value.
87
163
 
164
+ ### Real-World Examples
165
+
166
+ #### Complex Product Search
167
+ ```ts
168
+ // E-commerce product filtering
169
+ const productFilter = createFilter({
170
+ $and: [
171
+ { price: { $gte: 50, $lte: 200 } },
172
+ { category: { $in: ['electronics', 'computers'] } },
173
+ {
174
+ $or: [
175
+ { brand: 'Apple' },
176
+ { rating: { $gte: 4.5 } }
177
+ ]
178
+ },
179
+ { tags: { $con: 'wireless' } }
180
+ ]
181
+ });
182
+
183
+ const products = await fetch('/api/products').then(r => r.json());
184
+ const filtered = products.filter(productFilter);
185
+ ```
186
+
187
+ #### User Permission Check
188
+ ```ts
189
+ // Check complex permission rules
190
+ const canEdit = createFilter({
191
+ $or: [
192
+ { role: 'admin' },
193
+ {
194
+ $and: [
195
+ { role: 'editor' },
196
+ { permissions: { $sup: ['read', 'write'] } },
197
+ { suspended: { $ne: true } }
198
+ ]
199
+ }
200
+ ]
201
+ });
202
+
203
+ if (canEdit(currentUser)) {
204
+ // Allow editing
205
+ }
206
+ ```
207
+
208
+ ### Array Operator Examples
209
+
210
+ ```ts
211
+ import { createFilter } from "ajoq";
212
+
213
+ // $in - check if value is in array
214
+ const roleFilter = createFilter({ role: { $in: ['admin', 'moderator'] } });
215
+ roleFilter({ role: 'admin' }); // true
216
+ roleFilter({ role: 'user' }); // false
217
+
218
+ // $con - check if array contains value
219
+ const tagFilter = createFilter({ tags: { $con: 'javascript' } });
220
+ tagFilter({ tags: ['javascript', 'node'] }); // true
221
+ tagFilter({ tags: ['python', 'django'] }); // false
222
+
223
+ // $sub - check if array is subset
224
+ const subsetFilter = createFilter({ skills: { $sub: ['js', 'html', 'css'] } });
225
+ subsetFilter({ skills: ['js', 'html'] }); // true (subset of allowed)
226
+ subsetFilter({ skills: ['js', 'php'] }); // false (php not in allowed)
227
+
228
+ // $sup - check if array is superset
229
+ const supersetFilter = createFilter({ permissions: { $sup: ['read', 'write'] } });
230
+ supersetFilter({ permissions: ['read', 'write', 'delete'] }); // true
231
+ supersetFilter({ permissions: ['read'] }); // false
232
+ ```
88
233
 
89
234
  ## License
90
235
  License [The MIT License](./LICENSE)
package/build/index.cjs CHANGED
@@ -5,23 +5,23 @@ Object.defineProperty(exports, "__esModule", {
5
5
  function _export(target, all) {
6
6
  for(var name in all)Object.defineProperty(target, name, {
7
7
  enumerable: true,
8
- get: all[name]
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
- Context: function() {
12
+ get Context () {
13
13
  return Context;
14
14
  },
15
- createFilter: function() {
15
+ get createFilter () {
16
16
  return createFilter;
17
17
  },
18
- createSort: function() {
18
+ get createSort () {
19
19
  return createSort;
20
20
  },
21
- isPrimitive: function() {
21
+ get isPrimitive () {
22
22
  return isPrimitive;
23
23
  },
24
- stringify: function() {
24
+ get stringify () {
25
25
  return stringify;
26
26
  }
27
27
  });
@@ -60,17 +60,23 @@ const effectFilters = {
60
60
  $nin: (valuePath, value, context)=>`!${effectFilters.$in(valuePath, value, context)}`,
61
61
  $sub: (valuePath, value, context)=>{
62
62
  const scope = context.scope(new Set(value));
63
- return `${valuePath}.every((value) => ${scope}?.has(value))`;
63
+ return `!!${valuePath}?.every((value) => ${scope}?.has(value))`;
64
64
  },
65
65
  $nsub: (valuePath, value, context)=>`!${effectFilters.$sub(valuePath, value, context)}`,
66
66
  $sup: (valuePath, value, context)=>{
67
67
  const scope = context.scope(value);
68
68
  const name = context.register(`new Set(${valuePath})`);
69
- return `${scope}?.every((value) => ${name}.has(value))`;
69
+ return `!!${scope}?.every((value) => ${name}.has(value))`;
70
70
  },
71
71
  $nsup: (valuePath, value, context)=>`!${effectFilters.$sup(valuePath, value, context)}`,
72
- $con: (valuePath, value, context)=>`new Set(${valuePath}).has(${stringify(value, context)})`,
73
- $ncon: (valuePath, value, context)=>`!new Set(${valuePath}).has(${stringify(value, context)})`
72
+ $con: (valuePath, value, context)=>{
73
+ const setVar = context.register(`new Set(${valuePath})`);
74
+ return `${setVar}.has(${stringify(value, context)})`;
75
+ },
76
+ $ncon: (valuePath, value, context)=>{
77
+ const setVar = context.register(`new Set(${valuePath})`);
78
+ return `!${setVar}.has(${stringify(value, context)})`;
79
+ }
74
80
  };
75
81
  const operations = {
76
82
  $and: (value)=>`(${value.join(' && ')})`,
@@ -80,14 +86,11 @@ const operations = {
80
86
  };
81
87
  class Context {
82
88
  scopeMap;
83
- counter;
84
- values;
85
- cacheMap;
89
+ counter = 0;
90
+ values = [];
91
+ cacheMap = new Map();
86
92
  constructor(scopeMap){
87
93
  this.scopeMap = scopeMap;
88
- this.counter = 0;
89
- this.values = [];
90
- this.cacheMap = new Map();
91
94
  }
92
95
  scope(value) {
93
96
  const name = `s$$${this.counter++}`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type RegExpOrString<T> = T extends string ? RegExp | T : T;\nexport type ItemType<T> = T extends ReadonlyArray<infer U> ? T | RegExpOrString<U> : RegExpOrString<T>;\nexport type FilterCondition<T> = T | ItemType<T> | PureFilterOperators<T> | PureFilterOperators<ItemType<T>> | LogicOperators<FilterCondition<T>>;\nexport type QueryStatefulCondition<T> =\n | T\n | ItemType<T>\n | StatefulFilterOperators<T>\n | StatefulFilterOperators<ItemType<T>>\n | LogicOperators<FilterCondition<T>>;\n\nexport type Filter<T> = {\n [P in keyof T]?: FilterCondition<T[P]>;\n} & LogicOperators<T>;\n\nexport interface LogicOperators<T> {\n $and?: Filter<T>[];\n $or?: Filter<T>[];\n $nor?: Filter<T>[];\n $not?: Filter<T>;\n}\n\nexport interface ConditionFn {\n (valuePath: string, value: any, context: Context): string;\n}\n\nexport type OperationKeys = keyof LogicOperators<unknown>;\n\nexport interface PureFilterOperators<ValueType> {\n $eq?: ValueType;\n $ne?: ValueType;\n $gt?: ValueType;\n $gte?: ValueType;\n $lt?: ValueType;\n $lte?: ValueType;\n\n $exists?: boolean;\n $match?: RegExp | string;\n $nmatch?: RegExp | string;\n $incl?: string;\n $nincl?: string;\n $bits?: number;\n $nbits?: number;\n $type?: string;\n $ntype?: string;\n}\n\nexport type PureFilterOperatorsNames = keyof PureFilterOperators<unknown>;\n\nconst pureFilters: Record<PureFilterOperatorsNames, ConditionFn> = {\n $eq: (valuePath: string, value: unknown) => `(${valuePath} === ${value})`,\n $ne: (valuePath: string, value: unknown) => `(${valuePath} !== ${value})`,\n $gt: (valuePath: string, value: unknown) => `(${valuePath} > ${value})`,\n $gte: (valuePath: string, value: unknown) => `(${valuePath} >= ${value})`,\n $lt: (valuePath: string, value: unknown) => `(${valuePath} < ${value})`,\n $lte: (valuePath: string, value: unknown) => `(${valuePath} <= ${value})`,\n $exists: (valuePath: string, value: boolean) => `((${valuePath} !== undefined && ${valuePath} !== null) === ${value})`,\n $match: (valuePath: string, value: RegExp) => `${value}?.test('' + ${valuePath})`,\n $nmatch: (valuePath: string, value: RegExp) => `!${value}?.test('' + ${valuePath})`,\n $incl: (valuePath: string, value: string) => `${valuePath}?.includes(${value})`,\n $nincl: (valuePath: string, value: string) => `!${valuePath}?.includes(${value})`,\n $bits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) === ${value})`,\n $nbits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) !== ${value})`,\n $type: (valuePath: string, value: unknown) => `(typeof ${valuePath} === ${value})`,\n $ntype: (valuePath: string, value: unknown) => `(typeof ${valuePath} !== ${value})`,\n};\n\nexport interface EffectFilterOperators<ValueType> {\n $in?: ReadonlyArray<ValueType>;\n $nin?: ReadonlyArray<ValueType>;\n $sub?: ReadonlyArray<ValueType>;\n $nsub?: ReadonlyArray<ValueType>;\n $sup?: ReadonlyArray<ValueType>;\n $nsup?: ReadonlyArray<ValueType>;\n $con?: ValueType;\n $ncon?: ValueType;\n}\n\nexport type EffectFilterOperatorsNames = keyof EffectFilterOperators<unknown>;\n\nexport interface StatefulFilterOperators<ValueType> extends PureFilterOperators<ValueType> {\n $unique?: boolean;\n}\n\nexport const stringify = (value: unknown, context: Context) => {\n if (value === undefined) {\n return 'undefined';\n }\n if (!isPrimitive(value) || typeof value === 'bigint') {\n const scope = context.scope(value);\n return scope;\n }\n return JSON.stringify(value);\n};\n\nconst effectFilters: Record<EffectFilterOperatorsNames, ConditionFn> = {\n $in: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `${scope}?.has(${valuePath})`;\n },\n $nin: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$in(valuePath, value, context)}`,\n $sub: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `${valuePath}.every((value) => ${scope}?.has(value))`;\n },\n $nsub: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$sub(valuePath, value, context)}`,\n $sup: (valuePath: string, value: unknown, context: Context) => {\n const scope = context.scope(value);\n const name = context.register(`new Set(${valuePath})`);\n return `${scope}?.every((value) => ${name}.has(value))`;\n },\n $nsup: (valuePath: string, value: unknown, context: Context) => `!${effectFilters.$sup(valuePath, value, context)}`,\n $con: (valuePath: string, value: unknown, context: Context) => `new Set(${valuePath}).has(${stringify(value, context)})`,\n $ncon: (valuePath: string, value: unknown, context: Context) => `!new Set(${valuePath}).has(${stringify(value, context)})`,\n};\n\nconst operations: Record<keyof LogicOperators<unknown>, any> = {\n $and: (value: unknown[]) => `(${value.join(' && ')})`,\n $or: (value: unknown[]) => `(${value.join(' || ')})`,\n $nor: (value: unknown[]) => `!(${value.join(' || ')})`,\n $not: (value: unknown[]) => `!(${value})`,\n};\n\nexport class Context {\n private counter = 0;\n private values: string[] = [];\n private cacheMap = new Map<string, string>();\n\n constructor(private scopeMap: Map<string, unknown>) {}\n\n scope<T>(value: T): string {\n const name = `s$$${this.counter++}`;\n this.scopeMap.set(name, value);\n return `scope.get('${name}')`;\n }\n\n register(code: string) {\n if (!this.cacheMap.has(code)) {\n const name = `v$$${this.counter++}`;\n this.values.push(`const ${name} = ${code};`);\n this.cacheMap.set(code, name);\n }\n return this.cacheMap.get(code)!;\n }\n\n toString() {\n return this.values.join('\\n');\n }\n}\n\nconst filterCodeGen = <T extends object>(query: Filter<T> | undefined, valuePath: string, context: Context): string => {\n if (typeof query === 'object' && query !== null) {\n const condition = Object.entries(query).map(([key, value]) => {\n if (key in pureFilters) {\n return pureFilters[key as PureFilterOperatorsNames](valuePath, stringify(value, context), context);\n }\n if (key in effectFilters) {\n return effectFilters[key as EffectFilterOperatorsNames](valuePath, value, context);\n }\n if (key in operations) {\n const values = Array.isArray(value) ? value : [value];\n return operations[key as OperationKeys](values.map((v) => filterCodeGen(v, valuePath, context)));\n }\n const valueSubPath = `${valuePath}?.[${stringify(key, context)}]`;\n if (value instanceof RegExp) {\n return pureFilters.$match(valueSubPath, stringify(value, context), context);\n }\n if (typeof value === 'object' && value !== null) {\n return filterCodeGen(value, valueSubPath, context);\n }\n return pureFilters.$eq(valueSubPath, stringify(value, context), context);\n });\n if (condition.length > 0) {\n return `${condition.join(' && ')}`;\n }\n }\n return `${!!query}`;\n};\n\nconst PRIMITIVES = new Set(['string', 'number', 'boolean', 'bigint', 'symbol']);\n\nexport type Primitive = string | number | boolean | bigint | symbol;\nexport const isPrimitive = (value: unknown): value is Primitive => PRIMITIVES.has(typeof value);\n\nexport const createFilter = <T extends object | number | string | boolean | bigint | symbol>(\n filter: Filter<T> | number | string | boolean | bigint | symbol,\n): ((data: T) => boolean) => {\n if (isPrimitive(filter)) {\n return (data: T) => data === filter;\n }\n const scope = new Map<string, unknown>();\n const context = new Context(scope);\n const code = filterCodeGen(filter as object, 'data', context);\n const filterFn = new Function('data', 'scope', `${context}\\nreturn ${code};`);\n return (data: T) => filterFn(data, scope);\n};\n\nexport type SortType<T> = T extends number\n ? 1 | -1\n : T extends string\n ? 'asc' | 'desc'\n : T extends unknown[]\n ? { length?: 1 | -1 } & { [Index: number]: SortType<T[number]> }\n : boolean;\n\nexport type Sort<T> = T extends object\n ? {\n [K in keyof T]?: SortType<T[K]> | boolean;\n }\n : SortType<T> | boolean;\n\ntype SortDirection = 'asc' | 'desc' | 1 | -1 | true | false;\nconst SORT_MAP: Record<`${SortDirection}`, 1 | -1> = {\n asc: 1,\n desc: -1,\n 1: 1,\n '-1': -1,\n true: 1,\n false: -1,\n};\n\nconst sortCodeGen = <T>(sort: Sort<T>, valuePathA: string, valuePathB: string): string => {\n if (typeof sort === 'object' && sort !== null) {\n const condition = Object.entries(sort).map(([key, value]) => {\n const valueSubPathA = `${valuePathA}?.[${JSON.stringify(key)}]`;\n const valueSubPathB = `${valuePathB}?.[${JSON.stringify(key)}]`;\n return sortCodeGen(value, valueSubPathA, valueSubPathB);\n });\n if (condition.length > 0) {\n return condition.join(' || ');\n }\n }\n if (typeof sort === 'string' && (sort === 'asc' || sort === 'desc')) {\n return `(${valuePathA}?.localeCompare(${valuePathB}) * ${SORT_MAP[sort as `${SortDirection}`]})`;\n }\n if (typeof sort === 'number' && (sort === 1 || sort === -1)) {\n return `((${valuePathA} - ${valuePathB}) * ${SORT_MAP[`${sort}` as `${SortDirection}`]})`;\n }\n if (typeof sort === 'boolean') {\n return `(${valuePathA} > ${valuePathB} === ${sort} ? 1 : (${valuePathA} < ${valuePathB} === ${sort} ? -1 : 0)) `;\n }\n return `0`;\n};\n\nexport const createSort = <T>(sort?: Sort<T>): ((a: T, b: T) => number) => {\n if (!sort) {\n return () => 0;\n }\n const code = sortCodeGen(sort, 'a', 'b');\n const sortFn = new Function('a', 'b', `return ${code};`);\n return sortFn as (a: T, b: T) => number;\n};\n"],"names":["Context","createFilter","createSort","isPrimitive","stringify","pureFilters","$eq","valuePath","value","$ne","$gt","$gte","$lt","$lte","$exists","$match","$nmatch","$incl","$nincl","$bits","$nbits","$type","$ntype","context","undefined","scope","JSON","effectFilters","$in","Set","$nin","$sub","$nsub","$sup","name","register","$nsup","$con","$ncon","operations","$and","join","$or","$nor","$not","counter","values","cacheMap","constructor","scopeMap","Map","set","code","has","push","get","toString","filterCodeGen","query","condition","Object","entries","map","key","Array","isArray","v","valueSubPath","RegExp","length","PRIMITIVES","filter","data","filterFn","Function","SORT_MAP","asc","desc","true","false","sortCodeGen","sort","valuePathA","valuePathB","valueSubPathA","valueSubPathB","sortFn"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type RegExpOrString<T> = T extends string ? RegExp | T : T;\nexport type ItemType<T> = T extends ReadonlyArray<infer U> ? T | RegExpOrString<U> : RegExpOrString<T>;\nexport type FilterCondition<T> = T | ItemType<T> | PureFilterOperators<T> | PureFilterOperators<ItemType<T>> | LogicOperators<FilterCondition<T>>;\nexport type QueryStatefulCondition<T> =\n | T\n | ItemType<T>\n | StatefulFilterOperators<T>\n | StatefulFilterOperators<ItemType<T>>\n | LogicOperators<FilterCondition<T>>;\n\nexport type Filter<T> = {\n [P in keyof T]?: FilterCondition<T[P]>;\n} & LogicOperators<T>;\n\nexport interface LogicOperators<T> {\n $and?: Filter<T>[];\n $or?: Filter<T>[];\n $nor?: Filter<T>[];\n $not?: Filter<T>;\n}\n\nexport interface ConditionFn {\n (valuePath: string, value: any, context: Context): string;\n}\n\nexport type OperationKeys = keyof LogicOperators<unknown>;\n\nexport interface PureFilterOperators<ValueType> {\n $eq?: ValueType;\n $ne?: ValueType;\n $gt?: ValueType;\n $gte?: ValueType;\n $lt?: ValueType;\n $lte?: ValueType;\n\n $exists?: boolean;\n $match?: RegExp | string;\n $nmatch?: RegExp | string;\n $incl?: string;\n $nincl?: string;\n $bits?: number;\n $nbits?: number;\n $type?: string;\n $ntype?: string;\n}\n\nexport type PureFilterOperatorsNames = keyof PureFilterOperators<unknown>;\n\nconst pureFilters: Record<PureFilterOperatorsNames, ConditionFn> = {\n $eq: (valuePath: string, value: unknown) => `(${valuePath} === ${value})`,\n $ne: (valuePath: string, value: unknown) => `(${valuePath} !== ${value})`,\n $gt: (valuePath: string, value: unknown) => `(${valuePath} > ${value})`,\n $gte: (valuePath: string, value: unknown) => `(${valuePath} >= ${value})`,\n $lt: (valuePath: string, value: unknown) => `(${valuePath} < ${value})`,\n $lte: (valuePath: string, value: unknown) => `(${valuePath} <= ${value})`,\n $exists: (valuePath: string, value: boolean) => `((${valuePath} !== undefined && ${valuePath} !== null) === ${value})`,\n $match: (valuePath: string, value: RegExp) => `${value}?.test('' + ${valuePath})`,\n $nmatch: (valuePath: string, value: RegExp) => `!${value}?.test('' + ${valuePath})`,\n $incl: (valuePath: string, value: string) => `${valuePath}?.includes(${value})`,\n $nincl: (valuePath: string, value: string) => `!${valuePath}?.includes(${value})`,\n $bits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) === ${value})`,\n $nbits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) !== ${value})`,\n $type: (valuePath: string, value: unknown) => `(typeof ${valuePath} === ${value})`,\n $ntype: (valuePath: string, value: unknown) => `(typeof ${valuePath} !== ${value})`,\n};\n\nexport interface EffectFilterOperators<ValueType> {\n $in?: ReadonlyArray<ValueType>;\n $nin?: ReadonlyArray<ValueType>;\n $sub?: ReadonlyArray<ValueType>;\n $nsub?: ReadonlyArray<ValueType>;\n $sup?: ReadonlyArray<ValueType>;\n $nsup?: ReadonlyArray<ValueType>;\n $con?: ValueType;\n $ncon?: ValueType;\n}\n\nexport type EffectFilterOperatorsNames = keyof EffectFilterOperators<unknown>;\n\nexport interface StatefulFilterOperators<ValueType> extends PureFilterOperators<ValueType> {\n $unique?: boolean;\n}\n\nexport const stringify = (value: unknown, context: Context) => {\n if (value === undefined) {\n return 'undefined';\n }\n if (!isPrimitive(value) || typeof value === 'bigint') {\n const scope = context.scope(value);\n return scope;\n }\n return JSON.stringify(value);\n};\n\nconst effectFilters: Record<EffectFilterOperatorsNames, ConditionFn> = {\n $in: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `${scope}?.has(${valuePath})`;\n },\n $nin: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$in(valuePath, value, context)}`,\n $sub: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `!!${valuePath}?.every((value) => ${scope}?.has(value))`;\n },\n $nsub: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$sub(valuePath, value, context)}`,\n $sup: (valuePath: string, value: unknown, context: Context) => {\n const scope = context.scope(value);\n const name = context.register(`new Set(${valuePath})`);\n return `!!${scope}?.every((value) => ${name}.has(value))`;\n },\n $nsup: (valuePath: string, value: unknown, context: Context) => `!${effectFilters.$sup(valuePath, value, context)}`,\n $con: (valuePath: string, value: unknown, context: Context) => {\n const setVar = context.register(`new Set(${valuePath})`);\n return `${setVar}.has(${stringify(value, context)})`;\n },\n $ncon: (valuePath: string, value: unknown, context: Context) => {\n const setVar = context.register(`new Set(${valuePath})`);\n return `!${setVar}.has(${stringify(value, context)})`;\n },\n};\n\nconst operations: Record<keyof LogicOperators<unknown>, any> = {\n $and: (value: unknown[]) => `(${value.join(' && ')})`,\n $or: (value: unknown[]) => `(${value.join(' || ')})`,\n $nor: (value: unknown[]) => `!(${value.join(' || ')})`,\n $not: (value: unknown[]) => `!(${value})`,\n};\n\nexport class Context {\n private counter = 0;\n private values: string[] = [];\n private cacheMap = new Map<string, string>();\n\n constructor(private scopeMap: Map<string, unknown>) {}\n\n scope<T>(value: T): string {\n const name = `s$$${this.counter++}`;\n this.scopeMap.set(name, value);\n return `scope.get('${name}')`;\n }\n\n register(code: string) {\n if (!this.cacheMap.has(code)) {\n const name = `v$$${this.counter++}`;\n this.values.push(`const ${name} = ${code};`);\n this.cacheMap.set(code, name);\n }\n return this.cacheMap.get(code)!;\n }\n\n toString() {\n return this.values.join('\\n');\n }\n}\n\nconst filterCodeGen = <T extends object>(query: Filter<T> | undefined, valuePath: string, context: Context): string => {\n if (typeof query === 'object' && query !== null) {\n const condition = Object.entries(query).map(([key, value]) => {\n if (key in pureFilters) {\n return pureFilters[key as PureFilterOperatorsNames](valuePath, stringify(value, context), context);\n }\n if (key in effectFilters) {\n return effectFilters[key as EffectFilterOperatorsNames](valuePath, value, context);\n }\n if (key in operations) {\n const values = Array.isArray(value) ? value : [value];\n return operations[key as OperationKeys](values.map((v) => filterCodeGen(v, valuePath, context)));\n }\n const valueSubPath = `${valuePath}?.[${stringify(key, context)}]`;\n if (value instanceof RegExp) {\n return pureFilters.$match(valueSubPath, stringify(value, context), context);\n }\n if (typeof value === 'object' && value !== null) {\n return filterCodeGen(value, valueSubPath, context);\n }\n return pureFilters.$eq(valueSubPath, stringify(value, context), context);\n });\n if (condition.length > 0) {\n return `${condition.join(' && ')}`;\n }\n }\n return `${!!query}`;\n};\n\nconst PRIMITIVES = new Set(['string', 'number', 'boolean', 'bigint', 'symbol']);\n\nexport type Primitive = string | number | boolean | bigint | symbol;\nexport const isPrimitive = (value: unknown): value is Primitive => PRIMITIVES.has(typeof value);\n\nexport const createFilter = <T extends object | number | string | boolean | bigint | symbol>(\n filter: Filter<T> | number | string | boolean | bigint | symbol,\n): ((data: T) => boolean) => {\n if (isPrimitive(filter)) {\n return (data: T) => data === filter;\n }\n const scope = new Map<string, unknown>();\n const context = new Context(scope);\n const code = filterCodeGen(filter as object, 'data', context);\n const filterFn = new Function('data', 'scope', `${context}\\nreturn ${code};`);\n return (data: T) => filterFn(data, scope);\n};\n\nexport type SortType<T> = T extends number\n ? 1 | -1\n : T extends string\n ? 'asc' | 'desc'\n : T extends unknown[]\n ? { length?: 1 | -1 } & { [Index: number]: SortType<T[number]> }\n : boolean;\n\nexport type Sort<T> = T extends object\n ? {\n [K in keyof T]?: SortType<T[K]> | boolean;\n }\n : SortType<T> | boolean;\n\ntype SortDirection = 'asc' | 'desc' | 1 | -1 | true | false;\nconst SORT_MAP: Record<`${SortDirection}`, 1 | -1> = {\n asc: 1,\n desc: -1,\n 1: 1,\n '-1': -1,\n true: 1,\n false: -1,\n};\n\nconst sortCodeGen = <T>(sort: Sort<T>, valuePathA: string, valuePathB: string): string => {\n if (typeof sort === 'object' && sort !== null) {\n const condition = Object.entries(sort).map(([key, value]) => {\n const valueSubPathA = `${valuePathA}?.[${JSON.stringify(key)}]`;\n const valueSubPathB = `${valuePathB}?.[${JSON.stringify(key)}]`;\n return sortCodeGen(value, valueSubPathA, valueSubPathB);\n });\n if (condition.length > 0) {\n return condition.join(' || ');\n }\n }\n if (typeof sort === 'string' && (sort === 'asc' || sort === 'desc')) {\n return `(${valuePathA}?.localeCompare(${valuePathB}) * ${SORT_MAP[sort as `${SortDirection}`]})`;\n }\n if (typeof sort === 'number' && (sort === 1 || sort === -1)) {\n return `((${valuePathA} - ${valuePathB}) * ${SORT_MAP[`${sort}` as `${SortDirection}`]})`;\n }\n if (typeof sort === 'boolean') {\n return `(${valuePathA} > ${valuePathB} === ${sort} ? 1 : (${valuePathA} < ${valuePathB} === ${sort} ? -1 : 0)) `;\n }\n return `0`;\n};\n\nexport const createSort = <T>(sort?: Sort<T>): ((a: T, b: T) => number) => {\n if (!sort) {\n return () => 0;\n }\n const code = sortCodeGen(sort, 'a', 'b');\n const sortFn = new Function('a', 'b', `return ${code};`);\n return sortFn as (a: T, b: T) => number;\n};\n"],"names":["Context","createFilter","createSort","isPrimitive","stringify","pureFilters","$eq","valuePath","value","$ne","$gt","$gte","$lt","$lte","$exists","$match","$nmatch","$incl","$nincl","$bits","$nbits","$type","$ntype","context","undefined","scope","JSON","effectFilters","$in","Set","$nin","$sub","$nsub","$sup","name","register","$nsup","$con","setVar","$ncon","operations","$and","join","$or","$nor","$not","counter","values","cacheMap","Map","scopeMap","set","code","has","push","get","toString","filterCodeGen","query","condition","Object","entries","map","key","Array","isArray","v","valueSubPath","RegExp","length","PRIMITIVES","filter","data","filterFn","Function","SORT_MAP","asc","desc","true","false","sortCodeGen","sort","valuePathA","valuePathB","valueSubPathA","valueSubPathB","sortFn"],"mappings":"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"}
package/build/index.js CHANGED
@@ -33,17 +33,23 @@ const effectFilters = {
33
33
  $nin: (valuePath, value, context)=>`!${effectFilters.$in(valuePath, value, context)}`,
34
34
  $sub: (valuePath, value, context)=>{
35
35
  const scope = context.scope(new Set(value));
36
- return `${valuePath}.every((value) => ${scope}?.has(value))`;
36
+ return `!!${valuePath}?.every((value) => ${scope}?.has(value))`;
37
37
  },
38
38
  $nsub: (valuePath, value, context)=>`!${effectFilters.$sub(valuePath, value, context)}`,
39
39
  $sup: (valuePath, value, context)=>{
40
40
  const scope = context.scope(value);
41
41
  const name = context.register(`new Set(${valuePath})`);
42
- return `${scope}?.every((value) => ${name}.has(value))`;
42
+ return `!!${scope}?.every((value) => ${name}.has(value))`;
43
43
  },
44
44
  $nsup: (valuePath, value, context)=>`!${effectFilters.$sup(valuePath, value, context)}`,
45
- $con: (valuePath, value, context)=>`new Set(${valuePath}).has(${stringify(value, context)})`,
46
- $ncon: (valuePath, value, context)=>`!new Set(${valuePath}).has(${stringify(value, context)})`
45
+ $con: (valuePath, value, context)=>{
46
+ const setVar = context.register(`new Set(${valuePath})`);
47
+ return `${setVar}.has(${stringify(value, context)})`;
48
+ },
49
+ $ncon: (valuePath, value, context)=>{
50
+ const setVar = context.register(`new Set(${valuePath})`);
51
+ return `!${setVar}.has(${stringify(value, context)})`;
52
+ }
47
53
  };
48
54
  const operations = {
49
55
  $and: (value)=>`(${value.join(' && ')})`,
@@ -53,14 +59,11 @@ const operations = {
53
59
  };
54
60
  export class Context {
55
61
  scopeMap;
56
- counter;
57
- values;
58
- cacheMap;
62
+ counter = 0;
63
+ values = [];
64
+ cacheMap = new Map();
59
65
  constructor(scopeMap){
60
66
  this.scopeMap = scopeMap;
61
- this.counter = 0;
62
- this.values = [];
63
- this.cacheMap = new Map();
64
67
  }
65
68
  scope(value) {
66
69
  const name = `s$$${this.counter++}`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type RegExpOrString<T> = T extends string ? RegExp | T : T;\nexport type ItemType<T> = T extends ReadonlyArray<infer U> ? T | RegExpOrString<U> : RegExpOrString<T>;\nexport type FilterCondition<T> = T | ItemType<T> | PureFilterOperators<T> | PureFilterOperators<ItemType<T>> | LogicOperators<FilterCondition<T>>;\nexport type QueryStatefulCondition<T> =\n | T\n | ItemType<T>\n | StatefulFilterOperators<T>\n | StatefulFilterOperators<ItemType<T>>\n | LogicOperators<FilterCondition<T>>;\n\nexport type Filter<T> = {\n [P in keyof T]?: FilterCondition<T[P]>;\n} & LogicOperators<T>;\n\nexport interface LogicOperators<T> {\n $and?: Filter<T>[];\n $or?: Filter<T>[];\n $nor?: Filter<T>[];\n $not?: Filter<T>;\n}\n\nexport interface ConditionFn {\n (valuePath: string, value: any, context: Context): string;\n}\n\nexport type OperationKeys = keyof LogicOperators<unknown>;\n\nexport interface PureFilterOperators<ValueType> {\n $eq?: ValueType;\n $ne?: ValueType;\n $gt?: ValueType;\n $gte?: ValueType;\n $lt?: ValueType;\n $lte?: ValueType;\n\n $exists?: boolean;\n $match?: RegExp | string;\n $nmatch?: RegExp | string;\n $incl?: string;\n $nincl?: string;\n $bits?: number;\n $nbits?: number;\n $type?: string;\n $ntype?: string;\n}\n\nexport type PureFilterOperatorsNames = keyof PureFilterOperators<unknown>;\n\nconst pureFilters: Record<PureFilterOperatorsNames, ConditionFn> = {\n $eq: (valuePath: string, value: unknown) => `(${valuePath} === ${value})`,\n $ne: (valuePath: string, value: unknown) => `(${valuePath} !== ${value})`,\n $gt: (valuePath: string, value: unknown) => `(${valuePath} > ${value})`,\n $gte: (valuePath: string, value: unknown) => `(${valuePath} >= ${value})`,\n $lt: (valuePath: string, value: unknown) => `(${valuePath} < ${value})`,\n $lte: (valuePath: string, value: unknown) => `(${valuePath} <= ${value})`,\n $exists: (valuePath: string, value: boolean) => `((${valuePath} !== undefined && ${valuePath} !== null) === ${value})`,\n $match: (valuePath: string, value: RegExp) => `${value}?.test('' + ${valuePath})`,\n $nmatch: (valuePath: string, value: RegExp) => `!${value}?.test('' + ${valuePath})`,\n $incl: (valuePath: string, value: string) => `${valuePath}?.includes(${value})`,\n $nincl: (valuePath: string, value: string) => `!${valuePath}?.includes(${value})`,\n $bits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) === ${value})`,\n $nbits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) !== ${value})`,\n $type: (valuePath: string, value: unknown) => `(typeof ${valuePath} === ${value})`,\n $ntype: (valuePath: string, value: unknown) => `(typeof ${valuePath} !== ${value})`,\n};\n\nexport interface EffectFilterOperators<ValueType> {\n $in?: ReadonlyArray<ValueType>;\n $nin?: ReadonlyArray<ValueType>;\n $sub?: ReadonlyArray<ValueType>;\n $nsub?: ReadonlyArray<ValueType>;\n $sup?: ReadonlyArray<ValueType>;\n $nsup?: ReadonlyArray<ValueType>;\n $con?: ValueType;\n $ncon?: ValueType;\n}\n\nexport type EffectFilterOperatorsNames = keyof EffectFilterOperators<unknown>;\n\nexport interface StatefulFilterOperators<ValueType> extends PureFilterOperators<ValueType> {\n $unique?: boolean;\n}\n\nexport const stringify = (value: unknown, context: Context) => {\n if (value === undefined) {\n return 'undefined';\n }\n if (!isPrimitive(value) || typeof value === 'bigint') {\n const scope = context.scope(value);\n return scope;\n }\n return JSON.stringify(value);\n};\n\nconst effectFilters: Record<EffectFilterOperatorsNames, ConditionFn> = {\n $in: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `${scope}?.has(${valuePath})`;\n },\n $nin: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$in(valuePath, value, context)}`,\n $sub: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `${valuePath}.every((value) => ${scope}?.has(value))`;\n },\n $nsub: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$sub(valuePath, value, context)}`,\n $sup: (valuePath: string, value: unknown, context: Context) => {\n const scope = context.scope(value);\n const name = context.register(`new Set(${valuePath})`);\n return `${scope}?.every((value) => ${name}.has(value))`;\n },\n $nsup: (valuePath: string, value: unknown, context: Context) => `!${effectFilters.$sup(valuePath, value, context)}`,\n $con: (valuePath: string, value: unknown, context: Context) => `new Set(${valuePath}).has(${stringify(value, context)})`,\n $ncon: (valuePath: string, value: unknown, context: Context) => `!new Set(${valuePath}).has(${stringify(value, context)})`,\n};\n\nconst operations: Record<keyof LogicOperators<unknown>, any> = {\n $and: (value: unknown[]) => `(${value.join(' && ')})`,\n $or: (value: unknown[]) => `(${value.join(' || ')})`,\n $nor: (value: unknown[]) => `!(${value.join(' || ')})`,\n $not: (value: unknown[]) => `!(${value})`,\n};\n\nexport class Context {\n private counter = 0;\n private values: string[] = [];\n private cacheMap = new Map<string, string>();\n\n constructor(private scopeMap: Map<string, unknown>) {}\n\n scope<T>(value: T): string {\n const name = `s$$${this.counter++}`;\n this.scopeMap.set(name, value);\n return `scope.get('${name}')`;\n }\n\n register(code: string) {\n if (!this.cacheMap.has(code)) {\n const name = `v$$${this.counter++}`;\n this.values.push(`const ${name} = ${code};`);\n this.cacheMap.set(code, name);\n }\n return this.cacheMap.get(code)!;\n }\n\n toString() {\n return this.values.join('\\n');\n }\n}\n\nconst filterCodeGen = <T extends object>(query: Filter<T> | undefined, valuePath: string, context: Context): string => {\n if (typeof query === 'object' && query !== null) {\n const condition = Object.entries(query).map(([key, value]) => {\n if (key in pureFilters) {\n return pureFilters[key as PureFilterOperatorsNames](valuePath, stringify(value, context), context);\n }\n if (key in effectFilters) {\n return effectFilters[key as EffectFilterOperatorsNames](valuePath, value, context);\n }\n if (key in operations) {\n const values = Array.isArray(value) ? value : [value];\n return operations[key as OperationKeys](values.map((v) => filterCodeGen(v, valuePath, context)));\n }\n const valueSubPath = `${valuePath}?.[${stringify(key, context)}]`;\n if (value instanceof RegExp) {\n return pureFilters.$match(valueSubPath, stringify(value, context), context);\n }\n if (typeof value === 'object' && value !== null) {\n return filterCodeGen(value, valueSubPath, context);\n }\n return pureFilters.$eq(valueSubPath, stringify(value, context), context);\n });\n if (condition.length > 0) {\n return `${condition.join(' && ')}`;\n }\n }\n return `${!!query}`;\n};\n\nconst PRIMITIVES = new Set(['string', 'number', 'boolean', 'bigint', 'symbol']);\n\nexport type Primitive = string | number | boolean | bigint | symbol;\nexport const isPrimitive = (value: unknown): value is Primitive => PRIMITIVES.has(typeof value);\n\nexport const createFilter = <T extends object | number | string | boolean | bigint | symbol>(\n filter: Filter<T> | number | string | boolean | bigint | symbol,\n): ((data: T) => boolean) => {\n if (isPrimitive(filter)) {\n return (data: T) => data === filter;\n }\n const scope = new Map<string, unknown>();\n const context = new Context(scope);\n const code = filterCodeGen(filter as object, 'data', context);\n const filterFn = new Function('data', 'scope', `${context}\\nreturn ${code};`);\n return (data: T) => filterFn(data, scope);\n};\n\nexport type SortType<T> = T extends number\n ? 1 | -1\n : T extends string\n ? 'asc' | 'desc'\n : T extends unknown[]\n ? { length?: 1 | -1 } & { [Index: number]: SortType<T[number]> }\n : boolean;\n\nexport type Sort<T> = T extends object\n ? {\n [K in keyof T]?: SortType<T[K]> | boolean;\n }\n : SortType<T> | boolean;\n\ntype SortDirection = 'asc' | 'desc' | 1 | -1 | true | false;\nconst SORT_MAP: Record<`${SortDirection}`, 1 | -1> = {\n asc: 1,\n desc: -1,\n 1: 1,\n '-1': -1,\n true: 1,\n false: -1,\n};\n\nconst sortCodeGen = <T>(sort: Sort<T>, valuePathA: string, valuePathB: string): string => {\n if (typeof sort === 'object' && sort !== null) {\n const condition = Object.entries(sort).map(([key, value]) => {\n const valueSubPathA = `${valuePathA}?.[${JSON.stringify(key)}]`;\n const valueSubPathB = `${valuePathB}?.[${JSON.stringify(key)}]`;\n return sortCodeGen(value, valueSubPathA, valueSubPathB);\n });\n if (condition.length > 0) {\n return condition.join(' || ');\n }\n }\n if (typeof sort === 'string' && (sort === 'asc' || sort === 'desc')) {\n return `(${valuePathA}?.localeCompare(${valuePathB}) * ${SORT_MAP[sort as `${SortDirection}`]})`;\n }\n if (typeof sort === 'number' && (sort === 1 || sort === -1)) {\n return `((${valuePathA} - ${valuePathB}) * ${SORT_MAP[`${sort}` as `${SortDirection}`]})`;\n }\n if (typeof sort === 'boolean') {\n return `(${valuePathA} > ${valuePathB} === ${sort} ? 1 : (${valuePathA} < ${valuePathB} === ${sort} ? -1 : 0)) `;\n }\n return `0`;\n};\n\nexport const createSort = <T>(sort?: Sort<T>): ((a: T, b: T) => number) => {\n if (!sort) {\n return () => 0;\n }\n const code = sortCodeGen(sort, 'a', 'b');\n const sortFn = new Function('a', 'b', `return ${code};`);\n return sortFn as (a: T, b: T) => number;\n};\n"],"names":["pureFilters","$eq","valuePath","value","$ne","$gt","$gte","$lt","$lte","$exists","$match","$nmatch","$incl","$nincl","$bits","$nbits","$type","$ntype","stringify","context","undefined","isPrimitive","scope","JSON","effectFilters","$in","Set","$nin","$sub","$nsub","$sup","name","register","$nsup","$con","$ncon","operations","$and","join","$or","$nor","$not","Context","counter","values","cacheMap","constructor","scopeMap","Map","set","code","has","push","get","toString","filterCodeGen","query","condition","Object","entries","map","key","Array","isArray","v","valueSubPath","RegExp","length","PRIMITIVES","createFilter","filter","data","filterFn","Function","SORT_MAP","asc","desc","true","false","sortCodeGen","sort","valuePathA","valuePathB","valueSubPathA","valueSubPathB","createSort","sortFn"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type RegExpOrString<T> = T extends string ? RegExp | T : T;\nexport type ItemType<T> = T extends ReadonlyArray<infer U> ? T | RegExpOrString<U> : RegExpOrString<T>;\nexport type FilterCondition<T> = T | ItemType<T> | PureFilterOperators<T> | PureFilterOperators<ItemType<T>> | LogicOperators<FilterCondition<T>>;\nexport type QueryStatefulCondition<T> =\n | T\n | ItemType<T>\n | StatefulFilterOperators<T>\n | StatefulFilterOperators<ItemType<T>>\n | LogicOperators<FilterCondition<T>>;\n\nexport type Filter<T> = {\n [P in keyof T]?: FilterCondition<T[P]>;\n} & LogicOperators<T>;\n\nexport interface LogicOperators<T> {\n $and?: Filter<T>[];\n $or?: Filter<T>[];\n $nor?: Filter<T>[];\n $not?: Filter<T>;\n}\n\nexport interface ConditionFn {\n (valuePath: string, value: any, context: Context): string;\n}\n\nexport type OperationKeys = keyof LogicOperators<unknown>;\n\nexport interface PureFilterOperators<ValueType> {\n $eq?: ValueType;\n $ne?: ValueType;\n $gt?: ValueType;\n $gte?: ValueType;\n $lt?: ValueType;\n $lte?: ValueType;\n\n $exists?: boolean;\n $match?: RegExp | string;\n $nmatch?: RegExp | string;\n $incl?: string;\n $nincl?: string;\n $bits?: number;\n $nbits?: number;\n $type?: string;\n $ntype?: string;\n}\n\nexport type PureFilterOperatorsNames = keyof PureFilterOperators<unknown>;\n\nconst pureFilters: Record<PureFilterOperatorsNames, ConditionFn> = {\n $eq: (valuePath: string, value: unknown) => `(${valuePath} === ${value})`,\n $ne: (valuePath: string, value: unknown) => `(${valuePath} !== ${value})`,\n $gt: (valuePath: string, value: unknown) => `(${valuePath} > ${value})`,\n $gte: (valuePath: string, value: unknown) => `(${valuePath} >= ${value})`,\n $lt: (valuePath: string, value: unknown) => `(${valuePath} < ${value})`,\n $lte: (valuePath: string, value: unknown) => `(${valuePath} <= ${value})`,\n $exists: (valuePath: string, value: boolean) => `((${valuePath} !== undefined && ${valuePath} !== null) === ${value})`,\n $match: (valuePath: string, value: RegExp) => `${value}?.test('' + ${valuePath})`,\n $nmatch: (valuePath: string, value: RegExp) => `!${value}?.test('' + ${valuePath})`,\n $incl: (valuePath: string, value: string) => `${valuePath}?.includes(${value})`,\n $nincl: (valuePath: string, value: string) => `!${valuePath}?.includes(${value})`,\n $bits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) === ${value})`,\n $nbits: (valuePath: string, value: unknown) => `((${valuePath} & ${value}) !== ${value})`,\n $type: (valuePath: string, value: unknown) => `(typeof ${valuePath} === ${value})`,\n $ntype: (valuePath: string, value: unknown) => `(typeof ${valuePath} !== ${value})`,\n};\n\nexport interface EffectFilterOperators<ValueType> {\n $in?: ReadonlyArray<ValueType>;\n $nin?: ReadonlyArray<ValueType>;\n $sub?: ReadonlyArray<ValueType>;\n $nsub?: ReadonlyArray<ValueType>;\n $sup?: ReadonlyArray<ValueType>;\n $nsup?: ReadonlyArray<ValueType>;\n $con?: ValueType;\n $ncon?: ValueType;\n}\n\nexport type EffectFilterOperatorsNames = keyof EffectFilterOperators<unknown>;\n\nexport interface StatefulFilterOperators<ValueType> extends PureFilterOperators<ValueType> {\n $unique?: boolean;\n}\n\nexport const stringify = (value: unknown, context: Context) => {\n if (value === undefined) {\n return 'undefined';\n }\n if (!isPrimitive(value) || typeof value === 'bigint') {\n const scope = context.scope(value);\n return scope;\n }\n return JSON.stringify(value);\n};\n\nconst effectFilters: Record<EffectFilterOperatorsNames, ConditionFn> = {\n $in: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `${scope}?.has(${valuePath})`;\n },\n $nin: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$in(valuePath, value, context)}`,\n $sub: (valuePath: string, value: unknown[], context: Context) => {\n const scope = context.scope(new Set(value));\n return `!!${valuePath}?.every((value) => ${scope}?.has(value))`;\n },\n $nsub: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$sub(valuePath, value, context)}`,\n $sup: (valuePath: string, value: unknown, context: Context) => {\n const scope = context.scope(value);\n const name = context.register(`new Set(${valuePath})`);\n return `!!${scope}?.every((value) => ${name}.has(value))`;\n },\n $nsup: (valuePath: string, value: unknown, context: Context) => `!${effectFilters.$sup(valuePath, value, context)}`,\n $con: (valuePath: string, value: unknown, context: Context) => {\n const setVar = context.register(`new Set(${valuePath})`);\n return `${setVar}.has(${stringify(value, context)})`;\n },\n $ncon: (valuePath: string, value: unknown, context: Context) => {\n const setVar = context.register(`new Set(${valuePath})`);\n return `!${setVar}.has(${stringify(value, context)})`;\n },\n};\n\nconst operations: Record<keyof LogicOperators<unknown>, any> = {\n $and: (value: unknown[]) => `(${value.join(' && ')})`,\n $or: (value: unknown[]) => `(${value.join(' || ')})`,\n $nor: (value: unknown[]) => `!(${value.join(' || ')})`,\n $not: (value: unknown[]) => `!(${value})`,\n};\n\nexport class Context {\n private counter = 0;\n private values: string[] = [];\n private cacheMap = new Map<string, string>();\n\n constructor(private scopeMap: Map<string, unknown>) {}\n\n scope<T>(value: T): string {\n const name = `s$$${this.counter++}`;\n this.scopeMap.set(name, value);\n return `scope.get('${name}')`;\n }\n\n register(code: string) {\n if (!this.cacheMap.has(code)) {\n const name = `v$$${this.counter++}`;\n this.values.push(`const ${name} = ${code};`);\n this.cacheMap.set(code, name);\n }\n return this.cacheMap.get(code)!;\n }\n\n toString() {\n return this.values.join('\\n');\n }\n}\n\nconst filterCodeGen = <T extends object>(query: Filter<T> | undefined, valuePath: string, context: Context): string => {\n if (typeof query === 'object' && query !== null) {\n const condition = Object.entries(query).map(([key, value]) => {\n if (key in pureFilters) {\n return pureFilters[key as PureFilterOperatorsNames](valuePath, stringify(value, context), context);\n }\n if (key in effectFilters) {\n return effectFilters[key as EffectFilterOperatorsNames](valuePath, value, context);\n }\n if (key in operations) {\n const values = Array.isArray(value) ? value : [value];\n return operations[key as OperationKeys](values.map((v) => filterCodeGen(v, valuePath, context)));\n }\n const valueSubPath = `${valuePath}?.[${stringify(key, context)}]`;\n if (value instanceof RegExp) {\n return pureFilters.$match(valueSubPath, stringify(value, context), context);\n }\n if (typeof value === 'object' && value !== null) {\n return filterCodeGen(value, valueSubPath, context);\n }\n return pureFilters.$eq(valueSubPath, stringify(value, context), context);\n });\n if (condition.length > 0) {\n return `${condition.join(' && ')}`;\n }\n }\n return `${!!query}`;\n};\n\nconst PRIMITIVES = new Set(['string', 'number', 'boolean', 'bigint', 'symbol']);\n\nexport type Primitive = string | number | boolean | bigint | symbol;\nexport const isPrimitive = (value: unknown): value is Primitive => PRIMITIVES.has(typeof value);\n\nexport const createFilter = <T extends object | number | string | boolean | bigint | symbol>(\n filter: Filter<T> | number | string | boolean | bigint | symbol,\n): ((data: T) => boolean) => {\n if (isPrimitive(filter)) {\n return (data: T) => data === filter;\n }\n const scope = new Map<string, unknown>();\n const context = new Context(scope);\n const code = filterCodeGen(filter as object, 'data', context);\n const filterFn = new Function('data', 'scope', `${context}\\nreturn ${code};`);\n return (data: T) => filterFn(data, scope);\n};\n\nexport type SortType<T> = T extends number\n ? 1 | -1\n : T extends string\n ? 'asc' | 'desc'\n : T extends unknown[]\n ? { length?: 1 | -1 } & { [Index: number]: SortType<T[number]> }\n : boolean;\n\nexport type Sort<T> = T extends object\n ? {\n [K in keyof T]?: SortType<T[K]> | boolean;\n }\n : SortType<T> | boolean;\n\ntype SortDirection = 'asc' | 'desc' | 1 | -1 | true | false;\nconst SORT_MAP: Record<`${SortDirection}`, 1 | -1> = {\n asc: 1,\n desc: -1,\n 1: 1,\n '-1': -1,\n true: 1,\n false: -1,\n};\n\nconst sortCodeGen = <T>(sort: Sort<T>, valuePathA: string, valuePathB: string): string => {\n if (typeof sort === 'object' && sort !== null) {\n const condition = Object.entries(sort).map(([key, value]) => {\n const valueSubPathA = `${valuePathA}?.[${JSON.stringify(key)}]`;\n const valueSubPathB = `${valuePathB}?.[${JSON.stringify(key)}]`;\n return sortCodeGen(value, valueSubPathA, valueSubPathB);\n });\n if (condition.length > 0) {\n return condition.join(' || ');\n }\n }\n if (typeof sort === 'string' && (sort === 'asc' || sort === 'desc')) {\n return `(${valuePathA}?.localeCompare(${valuePathB}) * ${SORT_MAP[sort as `${SortDirection}`]})`;\n }\n if (typeof sort === 'number' && (sort === 1 || sort === -1)) {\n return `((${valuePathA} - ${valuePathB}) * ${SORT_MAP[`${sort}` as `${SortDirection}`]})`;\n }\n if (typeof sort === 'boolean') {\n return `(${valuePathA} > ${valuePathB} === ${sort} ? 1 : (${valuePathA} < ${valuePathB} === ${sort} ? -1 : 0)) `;\n }\n return `0`;\n};\n\nexport const createSort = <T>(sort?: Sort<T>): ((a: T, b: T) => number) => {\n if (!sort) {\n return () => 0;\n }\n const code = sortCodeGen(sort, 'a', 'b');\n const sortFn = new Function('a', 'b', `return ${code};`);\n return sortFn as (a: T, b: T) => number;\n};\n"],"names":["pureFilters","$eq","valuePath","value","$ne","$gt","$gte","$lt","$lte","$exists","$match","$nmatch","$incl","$nincl","$bits","$nbits","$type","$ntype","stringify","context","undefined","isPrimitive","scope","JSON","effectFilters","$in","Set","$nin","$sub","$nsub","$sup","name","register","$nsup","$con","setVar","$ncon","operations","$and","join","$or","$nor","$not","Context","counter","values","cacheMap","Map","scopeMap","set","code","has","push","get","toString","filterCodeGen","query","condition","Object","entries","map","key","Array","isArray","v","valueSubPath","RegExp","length","PRIMITIVES","createFilter","filter","data","filterFn","Function","SORT_MAP","asc","desc","true","false","sortCodeGen","sort","valuePathA","valuePathB","valueSubPathA","valueSubPathB","createSort","sortFn"],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import eslint from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+ import { globalIgnores } from 'eslint/config';
4
+ import prettier from 'eslint-plugin-prettier';
5
+
6
+ export default tseslint.config(
7
+ globalIgnores(['**/docs', '**/build', '**/coverage', '**/node_modules', '**/scripts', '**/*.tmp.ts', '**/__tests__/*', '**/*.js', '**/*.cjs', '**/*.mjs']),
8
+ eslint.configs.recommended,
9
+ tseslint.configs.recommendedTypeChecked,
10
+ {
11
+ files: ['**/*.ts'],
12
+ plugins: {
13
+ prettier,
14
+ },
15
+ languageOptions: {
16
+ parserOptions: {
17
+ projectService: true,
18
+ tsconfigRootDir: import.meta.dirname,
19
+ },
20
+ },
21
+ rules: {
22
+ 'prettier/prettier': 2,
23
+ '@typescript-eslint/no-explicit-any': 0,
24
+ '@typescript-eslint/no-floating-promises': 1,
25
+ '@typescript-eslint/no-unused-vars': 2,
26
+ '@typescript-eslint/no-unsafe-declaration-merging': 0,
27
+ '@typescript-eslint/ban-ts-comment': 1,
28
+ '@typescript-eslint/ban-types': 0,
29
+ '@typescript-eslint/prefer-promise-reject-errors': 0,
30
+ '@typescript-eslint/no-empty-object-type': 0,
31
+ '@typescript-eslint/await-thenable': 0,
32
+ '@typescript-eslint/require-await': 0,
33
+ '@typescript-eslint/no-misused-promises': 0,
34
+ '@typescript-eslint/restrict-template-expressions': 0,
35
+ '@typescript-eslint/no-unsafe-return': 0,
36
+ '@typescript-eslint/no-unsafe-call': 0,
37
+ '@typescript-eslint/no-implied-eval': 0,
38
+ '@typescript-eslint/no-unsafe-argument': 0
39
+ },
40
+ },
41
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ajoq",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "types": "build/index.d.ts",
@@ -27,24 +27,23 @@
27
27
  "author": "Ivan Zakharchanka",
28
28
  "license": "MIT",
29
29
  "devDependencies": {
30
+ "@eslint/js": "^9.33.0",
30
31
  "@swc/jest": "^0.2.39",
31
- "@types/jest": "^29.5.14",
32
- "@types/node": "^22.17.2",
33
- "@typescript-eslint/eslint-plugin": "^8.39.1",
34
- "@typescript-eslint/parser": "^8.39.1",
35
- "@typescript-eslint/typescript-estree": "^8.39.1",
32
+ "@types/jest": "^30.0.0",
33
+ "@types/node": "^24.3.0",
34
+ "@typescript-eslint/eslint-plugin": "^8.40.0",
35
+ "@typescript-eslint/parser": "^8.40.0",
36
+ "@typescript-eslint/typescript-estree": "^8.40.0",
36
37
  "eslint": "^9.33.0",
37
- "eslint-config-airbnb-base": "^15.0.0",
38
- "eslint-config-prettier": "^9.1.2",
39
- "eslint-plugin-import": "^2.32.0",
38
+ "eslint-config-prettier": "^10.1.8",
40
39
  "eslint-plugin-prettier": "^5.5.4",
41
40
  "husky": "^9.1.7",
42
41
  "inop": "^0.7.8",
43
- "jest": "^29.7.0",
44
- "mongodb": "^6.18.0",
42
+ "jest": "^30.0.5",
45
43
  "prettier": "^3.6.2",
46
44
  "ts-node": "^10.9.2",
47
- "typescript": "^5.9.2"
45
+ "typescript": "^5.9.2",
46
+ "typescript-eslint": "^8.35.1"
48
47
  },
49
48
  "scripts": {
50
49
  "build": "rm -rf build && NODE_ENV=production inop src/ build -i __tests__ && tsc --declaration --emitDeclarationOnly",
package/src/index.ts CHANGED
@@ -100,17 +100,23 @@ const effectFilters: Record<EffectFilterOperatorsNames, ConditionFn> = {
100
100
  $nin: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$in(valuePath, value, context)}`,
101
101
  $sub: (valuePath: string, value: unknown[], context: Context) => {
102
102
  const scope = context.scope(new Set(value));
103
- return `${valuePath}.every((value) => ${scope}?.has(value))`;
103
+ return `!!${valuePath}?.every((value) => ${scope}?.has(value))`;
104
104
  },
105
105
  $nsub: (valuePath: string, value: unknown[], context: Context) => `!${effectFilters.$sub(valuePath, value, context)}`,
106
106
  $sup: (valuePath: string, value: unknown, context: Context) => {
107
107
  const scope = context.scope(value);
108
108
  const name = context.register(`new Set(${valuePath})`);
109
- return `${scope}?.every((value) => ${name}.has(value))`;
109
+ return `!!${scope}?.every((value) => ${name}.has(value))`;
110
110
  },
111
111
  $nsup: (valuePath: string, value: unknown, context: Context) => `!${effectFilters.$sup(valuePath, value, context)}`,
112
- $con: (valuePath: string, value: unknown, context: Context) => `new Set(${valuePath}).has(${stringify(value, context)})`,
113
- $ncon: (valuePath: string, value: unknown, context: Context) => `!new Set(${valuePath}).has(${stringify(value, context)})`,
112
+ $con: (valuePath: string, value: unknown, context: Context) => {
113
+ const setVar = context.register(`new Set(${valuePath})`);
114
+ return `${setVar}.has(${stringify(value, context)})`;
115
+ },
116
+ $ncon: (valuePath: string, value: unknown, context: Context) => {
117
+ const setVar = context.register(`new Set(${valuePath})`);
118
+ return `!${setVar}.has(${stringify(value, context)})`;
119
+ },
114
120
  };
115
121
 
116
122
  const operations: Record<keyof LogicOperators<unknown>, any> = {
package/eslint.config.mjs DELETED
@@ -1,79 +0,0 @@
1
- import prettier from "eslint-plugin-prettier";
2
- import typescriptEslint from "@typescript-eslint/eslint-plugin";
3
- import tsParser from "@typescript-eslint/parser";
4
- import path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import js from "@eslint/js";
7
- import { FlatCompat } from "@eslint/eslintrc";
8
-
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = path.dirname(__filename);
11
- const compat = new FlatCompat({
12
- baseDirectory: __dirname,
13
- recommendedConfig: js.configs.recommended,
14
- allConfig: js.configs.all
15
- });
16
-
17
- export default [{
18
- ignores: [
19
- "**/docs",
20
- "**/build",
21
- "**/coverage",
22
- "**/node_modules",
23
- "**/scripts",
24
- "src/*.tmp.ts",
25
- "src/__tests__/*",
26
- ],
27
- }, ...compat.extends("eslint-config-airbnb-base").map(config => ({
28
- ...config,
29
- files: ["**/*.js"],
30
- })), {
31
- files: ["**/*.js"],
32
-
33
- plugins: {
34
- prettier,
35
- },
36
-
37
- languageOptions: {
38
- globals: {},
39
- },
40
-
41
- rules: {
42
- "prettier/prettier": "error",
43
- },
44
- }, ...compat.extends(
45
- "plugin:@typescript-eslint/eslint-recommended",
46
- "plugin:@typescript-eslint/recommended",
47
- ).map(config => ({
48
- ...config,
49
- files: ["**/*.ts"],
50
- })), {
51
- files: ["**/*.ts"],
52
-
53
- plugins: {
54
- "@typescript-eslint": typescriptEslint,
55
- prettier,
56
- },
57
-
58
- languageOptions: {
59
- globals: {},
60
- parser: tsParser,
61
- ecmaVersion: 5,
62
- sourceType: "script",
63
-
64
- parserOptions: {
65
- project: "./tsconfig.json",
66
- },
67
- },
68
-
69
- rules: {
70
- "prettier/prettier": "error",
71
- "@typescript-eslint/no-explicit-any": 0,
72
- "@typescript-eslint/no-floating-promises": 1,
73
- "@typescript-eslint/no-unused-vars": 2,
74
- "@typescript-eslint/no-unsafe-declaration-merging": 0,
75
- "@typescript-eslint/ban-ts-comment": 1,
76
- "@typescript-eslint/ban-types": 0,
77
- "@typescript-eslint/no-empty-object-type": 0
78
- },
79
- }];