@hf-chimera/query-builder 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +407 -407
- package/dist/index.cjs +7 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +4 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +7 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +44 -44
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Hewston Fox
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,407 +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 }`
|
|
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
CHANGED
|
@@ -44,6 +44,13 @@ var DefaultChimeraQueryBuilder = class {
|
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region factory.ts
|
|
49
|
+
function createDefaultQueryBuilder() {
|
|
50
|
+
return new DefaultChimeraQueryBuilder();
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
//#endregion
|
|
48
54
|
exports.DefaultChimeraQueryBuilder = DefaultChimeraQueryBuilder;
|
|
55
|
+
exports.createDefaultQueryBuilder = createDefaultQueryBuilder;
|
|
49
56
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["ChimeraOrderNulls"],"sources":["../DefaultChimeraQueryBuilder.ts","../factory.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","import type { AnyChimeraEntityStore } from \"@hf-chimera/store\";\nimport { DefaultChimeraQueryBuilder } from \"./DefaultChimeraQueryBuilder\";\n\nexport function createDefaultQueryBuilder<TStore extends AnyChimeraEntityStore>(): DefaultChimeraQueryBuilder<TStore> {\n\treturn new DefaultChimeraQueryBuilder<TStore>();\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;;;;;;AClGH,SAAgB,4BAAsG;AACrH,QAAO,IAAI,4BAAoC"}
|
package/dist/index.d.cts
CHANGED
|
@@ -30,5 +30,8 @@ declare class DefaultChimeraQueryBuilder<TStore extends AnyChimeraEntityStore, T
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
//#endregion
|
|
33
|
-
|
|
33
|
+
//#region factory.d.ts
|
|
34
|
+
declare function createDefaultQueryBuilder<TStore extends AnyChimeraEntityStore>(): DefaultChimeraQueryBuilder<TStore>;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { type ChimeraQueryBuilder, DefaultChimeraQueryBuilder, type QueryBuilderCreator, createDefaultQueryBuilder };
|
|
34
37
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +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"}
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../types.ts","../DefaultChimeraQueryBuilder.ts","../factory.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;;;;iBEnBP,yCAAyC,0BAA0B,2BAA2B"}
|
package/dist/index.d.mts
CHANGED
|
@@ -30,5 +30,8 @@ declare class DefaultChimeraQueryBuilder<TStore extends AnyChimeraEntityStore, T
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
//#endregion
|
|
33
|
-
|
|
33
|
+
//#region factory.d.ts
|
|
34
|
+
declare function createDefaultQueryBuilder<TStore extends AnyChimeraEntityStore>(): DefaultChimeraQueryBuilder<TStore>;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { type ChimeraQueryBuilder, DefaultChimeraQueryBuilder, type QueryBuilderCreator, createDefaultQueryBuilder };
|
|
34
37
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +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"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../types.ts","../DefaultChimeraQueryBuilder.ts","../factory.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;;;;iBEnBP,yCAAyC,0BAA0B,2BAA2B"}
|
package/dist/index.mjs
CHANGED
|
@@ -45,5 +45,11 @@ var DefaultChimeraQueryBuilder = class {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
//#endregion
|
|
48
|
-
|
|
48
|
+
//#region factory.ts
|
|
49
|
+
function createDefaultQueryBuilder() {
|
|
50
|
+
return new DefaultChimeraQueryBuilder();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
export { DefaultChimeraQueryBuilder, createDefaultQueryBuilder };
|
|
49
55
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../DefaultChimeraQueryBuilder.ts","../factory.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","import type { AnyChimeraEntityStore } from \"@hf-chimera/store\";\nimport { DefaultChimeraQueryBuilder } from \"./DefaultChimeraQueryBuilder\";\n\nexport function createDefaultQueryBuilder<TStore extends AnyChimeraEntityStore>(): DefaultChimeraQueryBuilder<TStore> {\n\treturn new DefaultChimeraQueryBuilder<TStore>();\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;;;;;;AClGH,SAAgB,4BAAsG;AACrH,QAAO,IAAI,4BAAoC"}
|
package/package.json
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
2
|
+
"name": "@hf-chimera/query-builder",
|
|
3
|
+
"version": "0.2.2",
|
|
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": "~0.2.0"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public",
|
|
39
|
+
"provenance": true
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsdown",
|
|
43
|
+
"changeset:patch": "node ../../scripts/changeset-patch.mjs @hf-chimera/query-builder"
|
|
44
|
+
}
|
|
45
|
+
}
|