@hf-chimera/query-builder 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +407 -0
- package/dist/index.cjs +49 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +34 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +34 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +49 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
# ChimeraQueryBuilder
|
|
2
|
+
|
|
3
|
+
A type-safe query builder for constructing filters and ordering rules for Chimera Store collections. `ChimeraQueryBuilder` provides a fluent API for building complex queries with support for filtering, ordering, and nested grouping.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Type-Safe**: Full TypeScript support with automatic type inference
|
|
8
|
+
- **Fluent API**: Chainable methods for building queries
|
|
9
|
+
- **Complex Filtering**: Support for operators, negations, and grouped conditions
|
|
10
|
+
- **Ordering**: Flexible sorting with null handling options
|
|
11
|
+
- **Nested Groups**: Create complex logical groupings with AND/OR/NOT
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Install both the core store and query builder
|
|
17
|
+
npm install @hf-chimera/store @hf-chimera/query-builder
|
|
18
|
+
|
|
19
|
+
# Or with yarn
|
|
20
|
+
yarn add @hf-chimera/store @hf-chimera/query-builder
|
|
21
|
+
|
|
22
|
+
# Or with pnpm
|
|
23
|
+
pnpm add @hf-chimera/store @hf-chimera/query-builder
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Setting Up Your Store
|
|
27
|
+
|
|
28
|
+
Before using `ChimeraQueryBuilder`, you need to create entity stores. Here's a complete example:
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { createChimeraEntityStore } from "@hf-chimera/store";
|
|
32
|
+
|
|
33
|
+
// Define your entity types
|
|
34
|
+
type Customer = {
|
|
35
|
+
id: number;
|
|
36
|
+
name: string;
|
|
37
|
+
email: string;
|
|
38
|
+
phone: string;
|
|
39
|
+
createdAt: Date;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type Order = {
|
|
43
|
+
id: number;
|
|
44
|
+
customerId: number;
|
|
45
|
+
productName: string;
|
|
46
|
+
quantity: number;
|
|
47
|
+
totalAmount: number;
|
|
48
|
+
status: "pending" | "completed" | "cancelled";
|
|
49
|
+
createdAt: Date;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Create entity stores
|
|
53
|
+
export const customerStore = createChimeraEntityStore<"customer", Customer>({
|
|
54
|
+
name: "customer",
|
|
55
|
+
idGetter: "id",
|
|
56
|
+
async collectionFetcher(params, requestParams) {
|
|
57
|
+
const response = await fetch(`/api/customers`, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: { "Content-Type": "application/json" },
|
|
60
|
+
body: JSON.stringify({ filter: params.filter, order: params.order }),
|
|
61
|
+
signal: requestParams.signal,
|
|
62
|
+
});
|
|
63
|
+
return { data: await response.json() };
|
|
64
|
+
},
|
|
65
|
+
async itemCreator(item, requestParams) {
|
|
66
|
+
const response = await fetch(`/api/customers`, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: { "Content-Type": "application/json" },
|
|
69
|
+
body: JSON.stringify(item),
|
|
70
|
+
signal: requestParams.signal,
|
|
71
|
+
});
|
|
72
|
+
return { data: await response.json() };
|
|
73
|
+
},
|
|
74
|
+
async itemUpdater(item, requestParams) {
|
|
75
|
+
const response = await fetch(`/api/customers/${item.id}`, {
|
|
76
|
+
method: "PUT",
|
|
77
|
+
headers: { "Content-Type": "application/json" },
|
|
78
|
+
body: JSON.stringify(item),
|
|
79
|
+
signal: requestParams.signal,
|
|
80
|
+
});
|
|
81
|
+
return { data: await response.json() };
|
|
82
|
+
},
|
|
83
|
+
async itemDeleter(id, requestParams) {
|
|
84
|
+
await fetch(`/api/customers/${id}`, {
|
|
85
|
+
method: "DELETE",
|
|
86
|
+
signal: requestParams.signal,
|
|
87
|
+
});
|
|
88
|
+
return { result: { id, success: true } };
|
|
89
|
+
},
|
|
90
|
+
async itemFetcher(params, requestParams) {
|
|
91
|
+
const response = await fetch(`/api/customers/${params.id}`, {
|
|
92
|
+
signal: requestParams.signal,
|
|
93
|
+
});
|
|
94
|
+
return { data: await response.json() };
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export const orderStore = createChimeraEntityStore<"order", Order>({
|
|
99
|
+
name: "order",
|
|
100
|
+
idGetter: "id",
|
|
101
|
+
// ... similar CRUD operations
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Basic Usage
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { ChimeraQueryBuilder } from "@hf-chimera/query-builder";
|
|
109
|
+
import { customerStore } from "./store";
|
|
110
|
+
|
|
111
|
+
// Create a query builder instance
|
|
112
|
+
const query = new ChimeraQueryBuilder<typeof customerStore, Customer, any>();
|
|
113
|
+
|
|
114
|
+
// Build a simple query
|
|
115
|
+
query
|
|
116
|
+
.where("name", "eq", "John")
|
|
117
|
+
.where("age", "gte", 18)
|
|
118
|
+
.orderBy("createdAt", true); // true = descending
|
|
119
|
+
|
|
120
|
+
// Build the query descriptor
|
|
121
|
+
const descriptor = query.build();
|
|
122
|
+
// Returns: { filter: {...}, order: [...] }
|
|
123
|
+
|
|
124
|
+
// Use with entity store
|
|
125
|
+
const customers = customerStore.getCollection(descriptor);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## API Reference
|
|
129
|
+
|
|
130
|
+
### `orderBy(key, desc?, nulls?)`
|
|
131
|
+
|
|
132
|
+
Adds an ordering rule to the query.
|
|
133
|
+
|
|
134
|
+
**Parameters:**
|
|
135
|
+
|
|
136
|
+
- `key`: `ChimeraPropertyGetter<Entity> | (keyof Entity & string)` - The property to order by (can be a property name string or a property getter function)
|
|
137
|
+
- `desc`: `boolean` (default: `false`) - Whether to sort in descending order
|
|
138
|
+
- `nulls`: `ChimeraOrderNulls` (default: `ChimeraOrderNulls.Last`) - How to handle null values (`Last` or `First`)
|
|
139
|
+
|
|
140
|
+
**Returns:** `this` - Returns the builder instance for chaining
|
|
141
|
+
|
|
142
|
+
**Example:**
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
query
|
|
146
|
+
.orderBy("name") // Ascending
|
|
147
|
+
.orderBy("age", true) // Descending
|
|
148
|
+
.orderBy("createdAt", false, ChimeraOrderNulls.First); // Nulls first
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### `where(value, op, test)`
|
|
152
|
+
|
|
153
|
+
Adds a filter condition to the query. Multiple `where` calls are combined with AND logic by default.
|
|
154
|
+
|
|
155
|
+
**Parameters:**
|
|
156
|
+
|
|
157
|
+
- `value`: `ChimeraPropertyGetter<Entity> | (KeysOfType<Entity, T> & string)` - The property to filter on (property name or getter function)
|
|
158
|
+
- `op`: `Op extends keyof OperatorsMap & string` - The operator to use (e.g., `'eq'`, `'gte'`, `'in'`, etc.)
|
|
159
|
+
- `test`: `Parameters<OperatorsMap[Op]>[1]` - The value to compare against (type depends on the operator)
|
|
160
|
+
|
|
161
|
+
**Returns:** `this` - Returns the builder instance for chaining
|
|
162
|
+
|
|
163
|
+
**Example:**
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
query
|
|
167
|
+
.where("status", "eq", "active")
|
|
168
|
+
.where("age", "gte", 18)
|
|
169
|
+
.where("tags", "in", ["javascript", "typescript"]);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### `whereNot(value, op, test)`
|
|
173
|
+
|
|
174
|
+
Adds a negated filter condition (NOT condition) to the query.
|
|
175
|
+
|
|
176
|
+
**Parameters:**
|
|
177
|
+
|
|
178
|
+
- `value`: Same as `where()`
|
|
179
|
+
- `op`: Same as `where()`
|
|
180
|
+
- `test`: Same as `where()`
|
|
181
|
+
|
|
182
|
+
**Returns:** `this` - Returns the builder instance for chaining
|
|
183
|
+
|
|
184
|
+
**Example:**
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
query.where("status", "eq", "active").whereNot("deleted", "eq", true); // NOT deleted = true
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `group(conjunction, builder)`
|
|
191
|
+
|
|
192
|
+
Creates a grouped condition with a specified logical conjunction. Useful for creating complex logical expressions with AND, OR, or NOT groups.
|
|
193
|
+
|
|
194
|
+
**Parameters:**
|
|
195
|
+
|
|
196
|
+
- `conjunction`: `ChimeraConjunctionType` - The logical operator: `'and'`, `'or'`, or `'not'`
|
|
197
|
+
- `builder`: `QueryBuilderCreator<Store, Entity, OperatorsMap>` - A callback function that receives a new builder instance for building the nested query
|
|
198
|
+
|
|
199
|
+
**Returns:** `this` - Returns the builder instance for chaining
|
|
200
|
+
|
|
201
|
+
**Example:**
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
// Create an OR group: (status = 'active' OR status = 'pending')
|
|
205
|
+
query.group("or", (q) => {
|
|
206
|
+
q.where("status", "eq", "active").where("status", "eq", "pending");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Create a NOT group: NOT (age < 18 OR deleted = true)
|
|
210
|
+
query.group("not", (q) => {
|
|
211
|
+
q.group("or", (nested) => {
|
|
212
|
+
nested.where("age", "lt", 18).where("deleted", "eq", true);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### `build()`
|
|
218
|
+
|
|
219
|
+
Builds and returns the final query descriptor object.
|
|
220
|
+
|
|
221
|
+
**Returns:**
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
{
|
|
225
|
+
filter: ChimeraFilterDescriptor<OperatorsMap, Entity> | null;
|
|
226
|
+
order: (ChimeraOrderDescriptor < Entity > []) | null;
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
- `filter`: The filter descriptor, or `null` if no filters were added
|
|
231
|
+
- `order`: An array of order descriptors, or `null` if no ordering was specified
|
|
232
|
+
|
|
233
|
+
**Example:**
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const { filter, order } = query.build();
|
|
237
|
+
|
|
238
|
+
// Use with store
|
|
239
|
+
const collection = store.from("customer").getCollection({ filter, order });
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Examples
|
|
243
|
+
|
|
244
|
+
_Note: The following examples use generic type parameters like `Store`, `User`, and `OperatorsMap`. See [Setting Up Your Store](#setting-up-your-store) section above for a complete store setup example._
|
|
245
|
+
|
|
246
|
+
### Simple Filtering
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
const query = new ChimeraQueryBuilder<Store, User, OperatorsMap>();
|
|
250
|
+
|
|
251
|
+
query
|
|
252
|
+
.where("email", "eq", "user@example.com")
|
|
253
|
+
.where("active", "eq", true)
|
|
254
|
+
.orderBy("createdAt", true);
|
|
255
|
+
|
|
256
|
+
const { filter, order } = query.build();
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Complex Logical Groups
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
const query = new ChimeraQueryBuilder<Store, Post, OperatorsMap>();
|
|
263
|
+
|
|
264
|
+
query
|
|
265
|
+
// Main AND condition
|
|
266
|
+
.where("published", "eq", true)
|
|
267
|
+
.where("createdAt", "gte", new Date("2024-01-01"))
|
|
268
|
+
|
|
269
|
+
// OR group: (authorId = '123' OR authorId = '456')
|
|
270
|
+
.group("or", (q) => {
|
|
271
|
+
q.where("authorId", "eq", "123").where("authorId", "eq", "456");
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
// NOT group: NOT (tags contains 'draft')
|
|
275
|
+
.group("not", (q) => {
|
|
276
|
+
q.where("tags", "contains", "draft");
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
.orderBy("createdAt", true)
|
|
280
|
+
.orderBy("title"); // Secondary sort
|
|
281
|
+
|
|
282
|
+
const { filter, order } = query.build();
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Multiple Order Rules
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const query = new ChimeraQueryBuilder<Store, Product, OperatorsMap>();
|
|
289
|
+
|
|
290
|
+
query
|
|
291
|
+
.where("inStock", "eq", true)
|
|
292
|
+
.orderBy("category") // Primary sort: category ascending
|
|
293
|
+
.orderBy("price", false) // Secondary sort: price ascending
|
|
294
|
+
.orderBy("rating", true) // Tertiary sort: rating descending
|
|
295
|
+
.orderBy("name"); // Final sort: name ascending
|
|
296
|
+
|
|
297
|
+
const { filter, order } = query.build();
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Combining whereNot and Groups
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
const query = new ChimeraQueryBuilder<Store, Article, OperatorsMap>();
|
|
304
|
+
|
|
305
|
+
query
|
|
306
|
+
.where("published", "eq", true)
|
|
307
|
+
.whereNot("archived", "eq", true)
|
|
308
|
+
|
|
309
|
+
// Either in featured category OR has high views
|
|
310
|
+
.group("or", (q) => {
|
|
311
|
+
q.where("category", "eq", "featured").where("views", "gte", 1000);
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
// But NOT in any of these tags
|
|
315
|
+
.group("not", (q) => {
|
|
316
|
+
q.where("tags", "in", ["spam", "deprecated"]);
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
.orderBy("publishedAt", true);
|
|
320
|
+
|
|
321
|
+
const { filter, order } = query.build();
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Empty Query
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
const query = new ChimeraQueryBuilder<Store, Entity, OperatorsMap>();
|
|
328
|
+
|
|
329
|
+
// Build without any filters or ordering
|
|
330
|
+
const { filter, order } = query.build();
|
|
331
|
+
// filter: null
|
|
332
|
+
// order: null
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Chaining Pattern
|
|
336
|
+
|
|
337
|
+
All methods return `this`, allowing you to chain operations:
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
const query = new ChimeraQueryBuilder<Store, User, OperatorsMap>()
|
|
341
|
+
.where("active", "eq", true)
|
|
342
|
+
.where("role", "in", ["admin", "moderator"])
|
|
343
|
+
.group("or", (q) => {
|
|
344
|
+
q.where("age", "gte", 18).where("verified", "eq", true);
|
|
345
|
+
})
|
|
346
|
+
.orderBy("lastActive", true)
|
|
347
|
+
.orderBy("name");
|
|
348
|
+
|
|
349
|
+
const descriptor = query.build();
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Type Safety
|
|
353
|
+
|
|
354
|
+
The `ChimeraQueryBuilder` is fully type-safe. It ensures:
|
|
355
|
+
|
|
356
|
+
- Property names must exist on the entity type
|
|
357
|
+
- Operator names must exist in the `OperatorsMap`
|
|
358
|
+
- Test values match the expected types for each operator
|
|
359
|
+
- Property getters are correctly typed
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
type User = {
|
|
363
|
+
id: string;
|
|
364
|
+
name: string;
|
|
365
|
+
age: number;
|
|
366
|
+
email: string;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
type OperatorsMap = {
|
|
370
|
+
eq: (value: any) => boolean;
|
|
371
|
+
gte: (value: number) => boolean;
|
|
372
|
+
in: (value: any[]) => boolean;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const query = new ChimeraQueryBuilder<Store, User, OperatorsMap>();
|
|
376
|
+
|
|
377
|
+
// ✅ Valid
|
|
378
|
+
query.where("name", "eq", "John");
|
|
379
|
+
query.where("age", "gte", 18);
|
|
380
|
+
query.where("id", "in", ["1", "2", "3"]);
|
|
381
|
+
|
|
382
|
+
// ❌ TypeScript errors
|
|
383
|
+
query.where("invalidProperty", "eq", "value"); // Property doesn't exist
|
|
384
|
+
query.where("age", "invalidOp", 18); // Operator doesn't exist
|
|
385
|
+
query.where("age", "eq", "not a number"); // Wrong type for operator
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Integration
|
|
389
|
+
|
|
390
|
+
### With Repository
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
const query = new ChimeraQueryBuilder<typeof store, User, OperatorsMap>()
|
|
394
|
+
.where("active", "eq", true)
|
|
395
|
+
.orderBy("createdAt", true);
|
|
396
|
+
|
|
397
|
+
// Use with entity store
|
|
398
|
+
const users = userStore.getCollection(query.build());
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Notes
|
|
402
|
+
|
|
403
|
+
- Multiple `where()` calls are combined with **AND** logic by default
|
|
404
|
+
- Use `group('or', ...)` to create OR conditions
|
|
405
|
+
- Use `group('not', ...)` or `whereNot()` for negations
|
|
406
|
+
- Order rules are applied in the sequence they're added (first = primary sort)
|
|
407
|
+
- An empty query builder will return `{ filter: null, order: null }`
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
let _hf_chimera_store = require("@hf-chimera/store");
|
|
2
|
+
|
|
3
|
+
//#region DefaultChimeraQueryBuilder.ts
|
|
4
|
+
var DefaultChimeraQueryBuilder = class {
|
|
5
|
+
orderRules = [];
|
|
6
|
+
isChimeraQueryBuilder = true;
|
|
7
|
+
create() {
|
|
8
|
+
return new this.constructor();
|
|
9
|
+
}
|
|
10
|
+
orderBy(key, desc = false, nulls = _hf_chimera_store.ChimeraOrderNulls.Last) {
|
|
11
|
+
this.orderRules.push((0, _hf_chimera_store.chimeraCreateOrderBy)(key, desc, nulls));
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
filters = [];
|
|
15
|
+
rootConjunction = "and";
|
|
16
|
+
conjunction(type) {
|
|
17
|
+
this.rootConjunction = type;
|
|
18
|
+
}
|
|
19
|
+
buildFilter() {
|
|
20
|
+
return this.filters.length ? (0, _hf_chimera_store.chimeraCreateConjunction)(this.rootConjunction, this.filters) : null;
|
|
21
|
+
}
|
|
22
|
+
where(value, op, test) {
|
|
23
|
+
this.filters.push((0, _hf_chimera_store.chimeraCreateOperator)(op, value, test));
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
group(conjunction, builder) {
|
|
27
|
+
const isNot = conjunction === "not";
|
|
28
|
+
const nestedBuilder = this.create();
|
|
29
|
+
!isNot && nestedBuilder.conjunction(conjunction);
|
|
30
|
+
builder(nestedBuilder);
|
|
31
|
+
const nestedQuery = nestedBuilder.buildFilter();
|
|
32
|
+
nestedQuery && this.filters.push(isNot ? (0, _hf_chimera_store.chimeraCreateNot)(nestedQuery) : nestedQuery);
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
whereNot(value, op, test) {
|
|
36
|
+
this.filters.push((0, _hf_chimera_store.chimeraCreateNot)((0, _hf_chimera_store.chimeraCreateOperator)(op, value, test)));
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
build() {
|
|
40
|
+
return {
|
|
41
|
+
filter: this.buildFilter(),
|
|
42
|
+
order: this.orderRules.length ? this.orderRules : null
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
exports.DefaultChimeraQueryBuilder = DefaultChimeraQueryBuilder;
|
|
49
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["ChimeraOrderNulls"],"sources":["../DefaultChimeraQueryBuilder.ts"],"sourcesContent":["import {\n\ttype AnyChimeraEntityStore,\n\ttype ChimeraConjunctionDescriptor,\n\ttype ChimeraConjunctionOperationDescriptor,\n\ttype ChimeraConjunctionType,\n\ttype ChimeraEntityStoreEntity,\n\ttype ChimeraEntityStoreOperatorsMap,\n\ttype ChimeraFilterDescriptor,\n\ttype ChimeraOrderDescriptor,\n\tChimeraOrderNulls,\n\ttype ChimeraPropertyGetter,\n\ttype Constructable,\n\tchimeraCreateConjunction,\n\tchimeraCreateNot,\n\tchimeraCreateOperator,\n\tchimeraCreateOrderBy,\n\ttype KeysOfType,\n} from \"@hf-chimera/store\";\nimport type { ChimeraQueryBuilder, QueryBuilderCreator } from \"./types\";\n\nexport class DefaultChimeraQueryBuilder<\n\tTStore extends AnyChimeraEntityStore,\n\tTEntity extends ChimeraEntityStoreEntity<TStore> = ChimeraEntityStoreEntity<TStore>,\n\tTOperatorsMap extends ChimeraEntityStoreOperatorsMap<TStore> = ChimeraEntityStoreOperatorsMap<TStore>,\n> implements ChimeraQueryBuilder<TStore>\n{\n\tprivate orderRules: ChimeraOrderDescriptor<TEntity>[] = [];\n\n\tisChimeraQueryBuilder: true = true;\n\n\tcreate(): this {\n\t\treturn new (this.constructor as Constructable)();\n\t}\n\n\torderBy(\n\t\tkey: ChimeraPropertyGetter<TEntity> | (keyof TEntity & string),\n\t\tdesc = false,\n\t\tnulls: ChimeraOrderNulls = ChimeraOrderNulls.Last,\n\t): this {\n\t\tthis.orderRules.push(chimeraCreateOrderBy<TEntity>(key, desc, nulls));\n\t\treturn this;\n\t}\n\n\tprivate filters: ChimeraConjunctionOperationDescriptor<TOperatorsMap, TEntity>[] = [];\n\tprivate rootConjunction: Exclude<ChimeraConjunctionType, \"not\"> = \"and\";\n\n\tprivate conjunction(type: Exclude<ChimeraConjunctionType, \"not\">) {\n\t\tthis.rootConjunction = type;\n\t}\n\n\tprivate buildFilter(): ChimeraConjunctionDescriptor<TOperatorsMap, TEntity> | null {\n\t\treturn this.filters.length\n\t\t\t? chimeraCreateConjunction<TEntity, TOperatorsMap>(this.rootConjunction, this.filters)\n\t\t\t: null;\n\t}\n\n\twhere<Op extends keyof TOperatorsMap & string>(\n\t\tvalue:\n\t\t\t| ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]>\n\t\t\t| (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string),\n\t\top: Op,\n\t\ttest: Parameters<TOperatorsMap[Op]>[1],\n\t): this {\n\t\tthis.filters.push(chimeraCreateOperator<TEntity, TOperatorsMap, Op>(op, value, test));\n\t\treturn this;\n\t}\n\n\tgroup(conjunction: ChimeraConjunctionType, builder: QueryBuilderCreator<TStore, this>): this {\n\t\tconst isNot = conjunction === \"not\";\n\t\tconst nestedBuilder = this.create();\n\n\t\t!isNot && nestedBuilder.conjunction(conjunction);\n\n\t\tbuilder(nestedBuilder);\n\n\t\tconst nestedQuery = nestedBuilder.buildFilter();\n\t\tnestedQuery && this.filters.push(isNot ? chimeraCreateNot<TEntity, TOperatorsMap>(nestedQuery) : nestedQuery);\n\n\t\treturn this;\n\t}\n\n\twhereNot<Op extends keyof TOperatorsMap & string>(\n\t\tvalue:\n\t\t\t| ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]>\n\t\t\t| (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string),\n\t\top: Op,\n\t\ttest: Parameters<TOperatorsMap[Op]>[1],\n\t): this {\n\t\tthis.filters.push(\n\t\t\tchimeraCreateNot<TEntity, TOperatorsMap>(chimeraCreateOperator<TEntity, TOperatorsMap, Op>(op, value, test)),\n\t\t);\n\t\treturn this;\n\t}\n\n\tbuild(): {\n\t\tfilter: ChimeraFilterDescriptor<TOperatorsMap, TEntity> | null;\n\t\torder: ChimeraOrderDescriptor<TEntity>[] | null;\n\t} {\n\t\treturn {\n\t\t\tfilter: this.buildFilter(),\n\t\t\torder: this.orderRules.length ? this.orderRules : null,\n\t\t};\n\t}\n}\n"],"mappings":";;;AAoBA,IAAa,6BAAb,MAKA;CACC,AAAQ,aAAgD,EAAE;CAE1D,wBAA8B;CAE9B,SAAe;AACd,SAAO,IAAK,KAAK,aAA+B;;CAGjD,QACC,KACA,OAAO,OACP,QAA2BA,oCAAkB,MACtC;AACP,OAAK,WAAW,iDAAmC,KAAK,MAAM,MAAM,CAAC;AACrE,SAAO;;CAGR,AAAQ,UAA2E,EAAE;CACrF,AAAQ,kBAA0D;CAElE,AAAQ,YAAY,MAA8C;AACjE,OAAK,kBAAkB;;CAGxB,AAAQ,cAA2E;AAClF,SAAO,KAAK,QAAQ,yDACgC,KAAK,iBAAiB,KAAK,QAAQ,GACpF;;CAGJ,MACC,OAGA,IACA,MACO;AACP,OAAK,QAAQ,kDAAuD,IAAI,OAAO,KAAK,CAAC;AACrF,SAAO;;CAGR,MAAM,aAAqC,SAAkD;EAC5F,MAAM,QAAQ,gBAAgB;EAC9B,MAAM,gBAAgB,KAAK,QAAQ;AAEnC,GAAC,SAAS,cAAc,YAAY,YAAY;AAEhD,UAAQ,cAAc;EAEtB,MAAM,cAAc,cAAc,aAAa;AAC/C,iBAAe,KAAK,QAAQ,KAAK,gDAAiD,YAAY,GAAG,YAAY;AAE7G,SAAO;;CAGR,SACC,OAGA,IACA,MACO;AACP,OAAK,QAAQ,0FAC+E,IAAI,OAAO,KAAK,CAAC,CAC5G;AACD,SAAO;;CAGR,QAGE;AACD,SAAO;GACN,QAAQ,KAAK,aAAa;GAC1B,OAAO,KAAK,WAAW,SAAS,KAAK,aAAa;GAClD"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AnyChimeraEntityStore, ChimeraConjunctionType, ChimeraEntityStoreEntity, ChimeraEntityStoreOperatorsMap, ChimeraFilterDescriptor, ChimeraOrderDescriptor, ChimeraOrderNulls, ChimeraPropertyGetter, KeysOfType, Nullish } from "@hf-chimera/store";
|
|
2
|
+
|
|
3
|
+
//#region types.d.ts
|
|
4
|
+
interface ChimeraQueryBuilder<TStore extends AnyChimeraEntityStore> {
|
|
5
|
+
isChimeraQueryBuilder: true;
|
|
6
|
+
create(): this;
|
|
7
|
+
build(): {
|
|
8
|
+
filter: ChimeraFilterDescriptor<ChimeraEntityStoreOperatorsMap<TStore>, ChimeraEntityStoreEntity<TStore>> | null;
|
|
9
|
+
order: ChimeraOrderDescriptor<ChimeraEntityStoreEntity<TStore>>[] | null;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
type QueryBuilderCreator<TStore extends AnyChimeraEntityStore, TQueryBuilder extends ChimeraQueryBuilder<TStore> = ChimeraQueryBuilder<TStore>> = (q: TQueryBuilder) => Nullish<ChimeraQueryBuilder<TStore>>;
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region DefaultChimeraQueryBuilder.d.ts
|
|
15
|
+
declare class DefaultChimeraQueryBuilder<TStore extends AnyChimeraEntityStore, TEntity extends ChimeraEntityStoreEntity<TStore> = ChimeraEntityStoreEntity<TStore>, TOperatorsMap extends ChimeraEntityStoreOperatorsMap<TStore> = ChimeraEntityStoreOperatorsMap<TStore>> implements ChimeraQueryBuilder<TStore> {
|
|
16
|
+
private orderRules;
|
|
17
|
+
isChimeraQueryBuilder: true;
|
|
18
|
+
create(): this;
|
|
19
|
+
orderBy(key: ChimeraPropertyGetter<TEntity> | (keyof TEntity & string), desc?: boolean, nulls?: ChimeraOrderNulls): this;
|
|
20
|
+
private filters;
|
|
21
|
+
private rootConjunction;
|
|
22
|
+
private conjunction;
|
|
23
|
+
private buildFilter;
|
|
24
|
+
where<Op extends keyof TOperatorsMap & string>(value: ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]> | (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string), op: Op, test: Parameters<TOperatorsMap[Op]>[1]): this;
|
|
25
|
+
group(conjunction: ChimeraConjunctionType, builder: QueryBuilderCreator<TStore, this>): this;
|
|
26
|
+
whereNot<Op extends keyof TOperatorsMap & string>(value: ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]> | (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string), op: Op, test: Parameters<TOperatorsMap[Op]>[1]): this;
|
|
27
|
+
build(): {
|
|
28
|
+
filter: ChimeraFilterDescriptor<TOperatorsMap, TEntity> | null;
|
|
29
|
+
order: ChimeraOrderDescriptor<TEntity>[] | null;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { type ChimeraQueryBuilder, DefaultChimeraQueryBuilder, type QueryBuilderCreator };
|
|
34
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../types.ts","../DefaultChimeraQueryBuilder.ts"],"sourcesContent":[],"mappings":";;;UASiB,mCAAmC;;EAAnC,MAAA,EAAA,EAAA,IAAA;EAAmC,KAAA,EAAA,EAAA;IAMa,MAAA,EAAvD,uBAAuD,CAA/B,8BAA+B,CAAA,MAAA,CAAA,EAAS,wBAAT,CAAkC,MAAlC,CAAA,CAAA,GAAA,IAAA;IAA/B,KAAA,EACzB,sBADyB,CACF,wBADE,CACuB,MADvB,CAAA,CAAA,EAAA,GAAA,IAAA;EAAiE,CAAA;;AAAzF,KAKE,mBALF,CAAA,eAMM,qBANN,EAAA,sBAOa,mBAPb,CAOiC,MAPjC,CAAA,GAO2C,mBAP3C,CAO+D,MAP/D,CAAA,CAAA,GAAA,CAAA,CAAA,EAQF,aARE,EAAA,GAQgB,OARhB,CAQwB,mBARxB,CAQ4C,MAR5C,CAAA,CAAA;;;cCKG,0CACG,uCACC,yBAAyB,UAAU,yBAAyB,+BACtD,+BAA+B,UAAU,+BAA+B,oBAClF,oBAAoB;EDfhB,QAAA,UAAA;EAAmC,qBAAA,EAAA,IAAA;EAMa,MAAA,CAAA,CAAA,EAAA,IAAA;EAA/B,OAAA,CAAA,GAAA,ECoB3B,qBDpB2B,CCoBL,ODpBK,CAAA,GAAA,CAAA,MCoBa,ODpBb,GAAA,MAAA,CAAA,EAAA,IAAA,CAAA,EAAA,OAAA,EAAA,KAAA,CAAA,ECsBzB,iBDtByB,CAAA,EAAA,IAAA;EAAiE,QAAA,OAAA;EAAzB,QAAA,eAAA;EAAhE,QAAA,WAAA;EAC+C,QAAA,WAAA;EAAzB,KAAA,CAAA,WAAA,MCwCR,aDxCQ,GAAA,MAAA,CAAA,CAAA,KAAA,EC0C3B,qBD1C2B,CC0CL,OD1CK,EC0CI,UD1CJ,CC0Ce,aD1Cf,CC0C6B,ED1C7B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CC2C1B,UD3C0B,CC2Cf,OD3Ce,EC2CN,UD3CM,CC2CK,aD3CL,CC2CmB,ED3CnB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,MAAA,CAAA,EAAA,EAAA,EC4C1B,ED5C0B,EAAA,IAAA,EC6CxB,UD7CwB,CC6Cb,aD7Ca,CC6CC,ED7CD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,IAAA;EAAvB,KAAA,CAAA,WAAA,ECmDW,sBDnDX,EAAA,OAAA,ECmD4C,mBDnD5C,CCmDgE,MDnDhE,EAAA,IAAA,CAAA,CAAA,EAAA,IAAA;EAAsB,QAAA,CAAA,WAAA,MCiEJ,aDjEI,GAAA,MAAA,CAAA,CAAA,KAAA,ECmE1B,qBDnE0B,CCmEJ,ODnEI,ECmEK,UDnEL,CCmEgB,aDnEhB,CCmE8B,EDnE9B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CCoEzB,UDpEyB,CCoEd,ODpEc,ECoEL,UDpEK,CCoEM,aDpEN,CCoEoB,EDpEpB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,MAAA,CAAA,EAAA,EAAA,ECqEzB,EDrEyB,EAAA,IAAA,ECsEvB,UDtEuB,CCsEZ,aDtEY,CCsEE,EDtEF,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,IAAA;EAInB,KAAA,CAAA,CAAA,EAAA;IACI,MAAA,EC0EN,uBD1EM,CC0EkB,aD1ElB,EC0EiC,OD1EjC,CAAA,GAAA,IAAA;IAC2B,KAAA,EC0ElC,sBD1EkC,CC0EX,OD1EW,CAAA,EAAA,GAAA,IAAA;EAApB,CAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AnyChimeraEntityStore, ChimeraConjunctionType, ChimeraEntityStoreEntity, ChimeraEntityStoreOperatorsMap, ChimeraFilterDescriptor, ChimeraOrderDescriptor, ChimeraOrderNulls, ChimeraPropertyGetter, KeysOfType, Nullish } from "@hf-chimera/store";
|
|
2
|
+
|
|
3
|
+
//#region types.d.ts
|
|
4
|
+
interface ChimeraQueryBuilder<TStore extends AnyChimeraEntityStore> {
|
|
5
|
+
isChimeraQueryBuilder: true;
|
|
6
|
+
create(): this;
|
|
7
|
+
build(): {
|
|
8
|
+
filter: ChimeraFilterDescriptor<ChimeraEntityStoreOperatorsMap<TStore>, ChimeraEntityStoreEntity<TStore>> | null;
|
|
9
|
+
order: ChimeraOrderDescriptor<ChimeraEntityStoreEntity<TStore>>[] | null;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
type QueryBuilderCreator<TStore extends AnyChimeraEntityStore, TQueryBuilder extends ChimeraQueryBuilder<TStore> = ChimeraQueryBuilder<TStore>> = (q: TQueryBuilder) => Nullish<ChimeraQueryBuilder<TStore>>;
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region DefaultChimeraQueryBuilder.d.ts
|
|
15
|
+
declare class DefaultChimeraQueryBuilder<TStore extends AnyChimeraEntityStore, TEntity extends ChimeraEntityStoreEntity<TStore> = ChimeraEntityStoreEntity<TStore>, TOperatorsMap extends ChimeraEntityStoreOperatorsMap<TStore> = ChimeraEntityStoreOperatorsMap<TStore>> implements ChimeraQueryBuilder<TStore> {
|
|
16
|
+
private orderRules;
|
|
17
|
+
isChimeraQueryBuilder: true;
|
|
18
|
+
create(): this;
|
|
19
|
+
orderBy(key: ChimeraPropertyGetter<TEntity> | (keyof TEntity & string), desc?: boolean, nulls?: ChimeraOrderNulls): this;
|
|
20
|
+
private filters;
|
|
21
|
+
private rootConjunction;
|
|
22
|
+
private conjunction;
|
|
23
|
+
private buildFilter;
|
|
24
|
+
where<Op extends keyof TOperatorsMap & string>(value: ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]> | (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string), op: Op, test: Parameters<TOperatorsMap[Op]>[1]): this;
|
|
25
|
+
group(conjunction: ChimeraConjunctionType, builder: QueryBuilderCreator<TStore, this>): this;
|
|
26
|
+
whereNot<Op extends keyof TOperatorsMap & string>(value: ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]> | (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string), op: Op, test: Parameters<TOperatorsMap[Op]>[1]): this;
|
|
27
|
+
build(): {
|
|
28
|
+
filter: ChimeraFilterDescriptor<TOperatorsMap, TEntity> | null;
|
|
29
|
+
order: ChimeraOrderDescriptor<TEntity>[] | null;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { type ChimeraQueryBuilder, DefaultChimeraQueryBuilder, type QueryBuilderCreator };
|
|
34
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../types.ts","../DefaultChimeraQueryBuilder.ts"],"sourcesContent":[],"mappings":";;;UASiB,mCAAmC;;EAAnC,MAAA,EAAA,EAAA,IAAA;EAAmC,KAAA,EAAA,EAAA;IAMa,MAAA,EAAvD,uBAAuD,CAA/B,8BAA+B,CAAA,MAAA,CAAA,EAAS,wBAAT,CAAkC,MAAlC,CAAA,CAAA,GAAA,IAAA;IAA/B,KAAA,EACzB,sBADyB,CACF,wBADE,CACuB,MADvB,CAAA,CAAA,EAAA,GAAA,IAAA;EAAiE,CAAA;;AAAzF,KAKE,mBALF,CAAA,eAMM,qBANN,EAAA,sBAOa,mBAPb,CAOiC,MAPjC,CAAA,GAO2C,mBAP3C,CAO+D,MAP/D,CAAA,CAAA,GAAA,CAAA,CAAA,EAQF,aARE,EAAA,GAQgB,OARhB,CAQwB,mBARxB,CAQ4C,MAR5C,CAAA,CAAA;;;cCKG,0CACG,uCACC,yBAAyB,UAAU,yBAAyB,+BACtD,+BAA+B,UAAU,+BAA+B,oBAClF,oBAAoB;EDfhB,QAAA,UAAA;EAAmC,qBAAA,EAAA,IAAA;EAMa,MAAA,CAAA,CAAA,EAAA,IAAA;EAA/B,OAAA,CAAA,GAAA,ECoB3B,qBDpB2B,CCoBL,ODpBK,CAAA,GAAA,CAAA,MCoBa,ODpBb,GAAA,MAAA,CAAA,EAAA,IAAA,CAAA,EAAA,OAAA,EAAA,KAAA,CAAA,ECsBzB,iBDtByB,CAAA,EAAA,IAAA;EAAiE,QAAA,OAAA;EAAzB,QAAA,eAAA;EAAhE,QAAA,WAAA;EAC+C,QAAA,WAAA;EAAzB,KAAA,CAAA,WAAA,MCwCR,aDxCQ,GAAA,MAAA,CAAA,CAAA,KAAA,EC0C3B,qBD1C2B,CC0CL,OD1CK,EC0CI,UD1CJ,CC0Ce,aD1Cf,CC0C6B,ED1C7B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CC2C1B,UD3C0B,CC2Cf,OD3Ce,EC2CN,UD3CM,CC2CK,aD3CL,CC2CmB,ED3CnB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,MAAA,CAAA,EAAA,EAAA,EC4C1B,ED5C0B,EAAA,IAAA,EC6CxB,UD7CwB,CC6Cb,aD7Ca,CC6CC,ED7CD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,IAAA;EAAvB,KAAA,CAAA,WAAA,ECmDW,sBDnDX,EAAA,OAAA,ECmD4C,mBDnD5C,CCmDgE,MDnDhE,EAAA,IAAA,CAAA,CAAA,EAAA,IAAA;EAAsB,QAAA,CAAA,WAAA,MCiEJ,aDjEI,GAAA,MAAA,CAAA,CAAA,KAAA,ECmE1B,qBDnE0B,CCmEJ,ODnEI,ECmEK,UDnEL,CCmEgB,aDnEhB,CCmE8B,EDnE9B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CCoEzB,UDpEyB,CCoEd,ODpEc,ECoEL,UDpEK,CCoEM,aDpEN,CCoEoB,EDpEpB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,MAAA,CAAA,EAAA,EAAA,ECqEzB,EDrEyB,EAAA,IAAA,ECsEvB,UDtEuB,CCsEZ,aDtEY,CCsEE,EDtEF,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,IAAA;EAInB,KAAA,CAAA,CAAA,EAAA;IACI,MAAA,EC0EN,uBD1EM,CC0EkB,aD1ElB,EC0EiC,OD1EjC,CAAA,GAAA,IAAA;IAC2B,KAAA,EC0ElC,sBD1EkC,CC0EX,OD1EW,CAAA,EAAA,GAAA,IAAA;EAApB,CAAA"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ChimeraOrderNulls, chimeraCreateConjunction, chimeraCreateNot, chimeraCreateOperator, chimeraCreateOrderBy } from "@hf-chimera/store";
|
|
2
|
+
|
|
3
|
+
//#region DefaultChimeraQueryBuilder.ts
|
|
4
|
+
var DefaultChimeraQueryBuilder = class {
|
|
5
|
+
orderRules = [];
|
|
6
|
+
isChimeraQueryBuilder = true;
|
|
7
|
+
create() {
|
|
8
|
+
return new this.constructor();
|
|
9
|
+
}
|
|
10
|
+
orderBy(key, desc = false, nulls = ChimeraOrderNulls.Last) {
|
|
11
|
+
this.orderRules.push(chimeraCreateOrderBy(key, desc, nulls));
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
filters = [];
|
|
15
|
+
rootConjunction = "and";
|
|
16
|
+
conjunction(type) {
|
|
17
|
+
this.rootConjunction = type;
|
|
18
|
+
}
|
|
19
|
+
buildFilter() {
|
|
20
|
+
return this.filters.length ? chimeraCreateConjunction(this.rootConjunction, this.filters) : null;
|
|
21
|
+
}
|
|
22
|
+
where(value, op, test) {
|
|
23
|
+
this.filters.push(chimeraCreateOperator(op, value, test));
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
group(conjunction, builder) {
|
|
27
|
+
const isNot = conjunction === "not";
|
|
28
|
+
const nestedBuilder = this.create();
|
|
29
|
+
!isNot && nestedBuilder.conjunction(conjunction);
|
|
30
|
+
builder(nestedBuilder);
|
|
31
|
+
const nestedQuery = nestedBuilder.buildFilter();
|
|
32
|
+
nestedQuery && this.filters.push(isNot ? chimeraCreateNot(nestedQuery) : nestedQuery);
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
whereNot(value, op, test) {
|
|
36
|
+
this.filters.push(chimeraCreateNot(chimeraCreateOperator(op, value, test)));
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
build() {
|
|
40
|
+
return {
|
|
41
|
+
filter: this.buildFilter(),
|
|
42
|
+
order: this.orderRules.length ? this.orderRules : null
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { DefaultChimeraQueryBuilder };
|
|
49
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../DefaultChimeraQueryBuilder.ts"],"sourcesContent":["import {\n\ttype AnyChimeraEntityStore,\n\ttype ChimeraConjunctionDescriptor,\n\ttype ChimeraConjunctionOperationDescriptor,\n\ttype ChimeraConjunctionType,\n\ttype ChimeraEntityStoreEntity,\n\ttype ChimeraEntityStoreOperatorsMap,\n\ttype ChimeraFilterDescriptor,\n\ttype ChimeraOrderDescriptor,\n\tChimeraOrderNulls,\n\ttype ChimeraPropertyGetter,\n\ttype Constructable,\n\tchimeraCreateConjunction,\n\tchimeraCreateNot,\n\tchimeraCreateOperator,\n\tchimeraCreateOrderBy,\n\ttype KeysOfType,\n} from \"@hf-chimera/store\";\nimport type { ChimeraQueryBuilder, QueryBuilderCreator } from \"./types\";\n\nexport class DefaultChimeraQueryBuilder<\n\tTStore extends AnyChimeraEntityStore,\n\tTEntity extends ChimeraEntityStoreEntity<TStore> = ChimeraEntityStoreEntity<TStore>,\n\tTOperatorsMap extends ChimeraEntityStoreOperatorsMap<TStore> = ChimeraEntityStoreOperatorsMap<TStore>,\n> implements ChimeraQueryBuilder<TStore>\n{\n\tprivate orderRules: ChimeraOrderDescriptor<TEntity>[] = [];\n\n\tisChimeraQueryBuilder: true = true;\n\n\tcreate(): this {\n\t\treturn new (this.constructor as Constructable)();\n\t}\n\n\torderBy(\n\t\tkey: ChimeraPropertyGetter<TEntity> | (keyof TEntity & string),\n\t\tdesc = false,\n\t\tnulls: ChimeraOrderNulls = ChimeraOrderNulls.Last,\n\t): this {\n\t\tthis.orderRules.push(chimeraCreateOrderBy<TEntity>(key, desc, nulls));\n\t\treturn this;\n\t}\n\n\tprivate filters: ChimeraConjunctionOperationDescriptor<TOperatorsMap, TEntity>[] = [];\n\tprivate rootConjunction: Exclude<ChimeraConjunctionType, \"not\"> = \"and\";\n\n\tprivate conjunction(type: Exclude<ChimeraConjunctionType, \"not\">) {\n\t\tthis.rootConjunction = type;\n\t}\n\n\tprivate buildFilter(): ChimeraConjunctionDescriptor<TOperatorsMap, TEntity> | null {\n\t\treturn this.filters.length\n\t\t\t? chimeraCreateConjunction<TEntity, TOperatorsMap>(this.rootConjunction, this.filters)\n\t\t\t: null;\n\t}\n\n\twhere<Op extends keyof TOperatorsMap & string>(\n\t\tvalue:\n\t\t\t| ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]>\n\t\t\t| (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string),\n\t\top: Op,\n\t\ttest: Parameters<TOperatorsMap[Op]>[1],\n\t): this {\n\t\tthis.filters.push(chimeraCreateOperator<TEntity, TOperatorsMap, Op>(op, value, test));\n\t\treturn this;\n\t}\n\n\tgroup(conjunction: ChimeraConjunctionType, builder: QueryBuilderCreator<TStore, this>): this {\n\t\tconst isNot = conjunction === \"not\";\n\t\tconst nestedBuilder = this.create();\n\n\t\t!isNot && nestedBuilder.conjunction(conjunction);\n\n\t\tbuilder(nestedBuilder);\n\n\t\tconst nestedQuery = nestedBuilder.buildFilter();\n\t\tnestedQuery && this.filters.push(isNot ? chimeraCreateNot<TEntity, TOperatorsMap>(nestedQuery) : nestedQuery);\n\n\t\treturn this;\n\t}\n\n\twhereNot<Op extends keyof TOperatorsMap & string>(\n\t\tvalue:\n\t\t\t| ChimeraPropertyGetter<TEntity, Parameters<TOperatorsMap[Op]>[0]>\n\t\t\t| (KeysOfType<TEntity, Parameters<TOperatorsMap[Op]>[0]> & string),\n\t\top: Op,\n\t\ttest: Parameters<TOperatorsMap[Op]>[1],\n\t): this {\n\t\tthis.filters.push(\n\t\t\tchimeraCreateNot<TEntity, TOperatorsMap>(chimeraCreateOperator<TEntity, TOperatorsMap, Op>(op, value, test)),\n\t\t);\n\t\treturn this;\n\t}\n\n\tbuild(): {\n\t\tfilter: ChimeraFilterDescriptor<TOperatorsMap, TEntity> | null;\n\t\torder: ChimeraOrderDescriptor<TEntity>[] | null;\n\t} {\n\t\treturn {\n\t\t\tfilter: this.buildFilter(),\n\t\t\torder: this.orderRules.length ? this.orderRules : null,\n\t\t};\n\t}\n}\n"],"mappings":";;;AAoBA,IAAa,6BAAb,MAKA;CACC,AAAQ,aAAgD,EAAE;CAE1D,wBAA8B;CAE9B,SAAe;AACd,SAAO,IAAK,KAAK,aAA+B;;CAGjD,QACC,KACA,OAAO,OACP,QAA2B,kBAAkB,MACtC;AACP,OAAK,WAAW,KAAK,qBAA8B,KAAK,MAAM,MAAM,CAAC;AACrE,SAAO;;CAGR,AAAQ,UAA2E,EAAE;CACrF,AAAQ,kBAA0D;CAElE,AAAQ,YAAY,MAA8C;AACjE,OAAK,kBAAkB;;CAGxB,AAAQ,cAA2E;AAClF,SAAO,KAAK,QAAQ,SACjB,yBAAiD,KAAK,iBAAiB,KAAK,QAAQ,GACpF;;CAGJ,MACC,OAGA,IACA,MACO;AACP,OAAK,QAAQ,KAAK,sBAAkD,IAAI,OAAO,KAAK,CAAC;AACrF,SAAO;;CAGR,MAAM,aAAqC,SAAkD;EAC5F,MAAM,QAAQ,gBAAgB;EAC9B,MAAM,gBAAgB,KAAK,QAAQ;AAEnC,GAAC,SAAS,cAAc,YAAY,YAAY;AAEhD,UAAQ,cAAc;EAEtB,MAAM,cAAc,cAAc,aAAa;AAC/C,iBAAe,KAAK,QAAQ,KAAK,QAAQ,iBAAyC,YAAY,GAAG,YAAY;AAE7G,SAAO;;CAGR,SACC,OAGA,IACA,MACO;AACP,OAAK,QAAQ,KACZ,iBAAyC,sBAAkD,IAAI,OAAO,KAAK,CAAC,CAC5G;AACD,SAAO;;CAGR,QAGE;AACD,SAAO;GACN,QAAQ,KAAK,aAAa;GAC1B,OAAO,KAAK,WAAW,SAAS,KAAK,aAAa;GAClD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hf-chimera/query-builder",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Cross-end reactivity API - Query builder",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "hewston",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"query-builder",
|
|
9
|
+
"reactivity",
|
|
10
|
+
"reactive",
|
|
11
|
+
"typescript",
|
|
12
|
+
"fullstack"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"main": "./dist/index.cjs",
|
|
17
|
+
"module": "./dist/index.js",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"require": "./dist/index.cjs",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/hf-chimera/store/issues"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"url": "https://github.com/hf-chimera/store"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@hf-chimera/store": "workspace:^"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsdown",
|
|
39
|
+
"changeset:patch": "node ../../scripts/changeset-patch.mjs @hf-chimera/query-builder"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public",
|
|
43
|
+
"provenance": true
|
|
44
|
+
}
|
|
45
|
+
}
|