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 +152 -7
- package/build/index.cjs +19 -16
- package/build/index.cjs.map +1 -1
- package/build/index.js +13 -10
- package/build/index.js.map +1 -1
- package/eslint.config.js +41 -0
- package/package.json +11 -12
- package/src/index.ts +10 -4
- package/eslint.config.mjs +0 -79
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
|
-
|
|
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: '
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
-
Context
|
|
12
|
+
get Context () {
|
|
13
13
|
return Context;
|
|
14
14
|
},
|
|
15
|
-
createFilter
|
|
15
|
+
get createFilter () {
|
|
16
16
|
return createFilter;
|
|
17
17
|
},
|
|
18
|
-
createSort
|
|
18
|
+
get createSort () {
|
|
19
19
|
return createSort;
|
|
20
20
|
},
|
|
21
|
-
isPrimitive
|
|
21
|
+
get isPrimitive () {
|
|
22
22
|
return isPrimitive;
|
|
23
23
|
},
|
|
24
|
-
stringify
|
|
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
|
|
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
|
|
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)
|
|
73
|
-
|
|
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++}`;
|
package/build/index.cjs.map
CHANGED
|
@@ -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
|
|
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
|
|
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)
|
|
46
|
-
|
|
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++}`;
|
package/build/index.js.map
CHANGED
|
@@ -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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"}
|
package/eslint.config.js
ADDED
|
@@ -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.
|
|
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": "^
|
|
32
|
-
"@types/node": "^
|
|
33
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
34
|
-
"@typescript-eslint/parser": "^8.
|
|
35
|
-
"@typescript-eslint/typescript-estree": "^8.
|
|
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-
|
|
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": "^
|
|
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
|
|
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
|
|
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) =>
|
|
113
|
-
|
|
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
|
-
}];
|