@simtlix/simfinity-js 2.6.3 → 2.6.4
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 +23 -3
- package/package.json +1 -1
- package/src/index.js +21 -1
package/README.md
CHANGED
|
@@ -352,6 +352,25 @@ query {
|
|
|
352
352
|
}
|
|
353
353
|
```
|
|
354
354
|
|
|
355
|
+
As an equivalent shorthand, you can pass the full dotted path in `field` and omit `path`:
|
|
356
|
+
|
|
357
|
+
```graphql
|
|
358
|
+
query {
|
|
359
|
+
books(
|
|
360
|
+
OR: [
|
|
361
|
+
{ conditions: [{ field: "author.name", operator: LIKE, value: "Adams" }] }
|
|
362
|
+
{ conditions: [{ field: "author.name", operator: LIKE, value: "Pratchett" }] }
|
|
363
|
+
]
|
|
364
|
+
) {
|
|
365
|
+
id
|
|
366
|
+
title
|
|
367
|
+
author { name }
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Both forms produce the same query. Multi-segment paths work too — e.g. `field: "author.country.code"` is equivalent to `field: "author", path: "country.code"`. Supplying both a dotted `field` and a separate `path` is rejected as ambiguous.
|
|
373
|
+
|
|
355
374
|
#### Mixing Flat Filters with AND/OR
|
|
356
375
|
|
|
357
376
|
You can freely combine the existing flat filter syntax with AND/OR groups. Flat filters and AND groups are all ANDed together at the top level:
|
|
@@ -439,7 +458,8 @@ query {
|
|
|
439
458
|
AND: [
|
|
440
459
|
{ conditions: [{ field: "year", operator: GTE, value: 2022 }] }
|
|
441
460
|
{ conditions: [
|
|
442
|
-
{ field: "episodes", path: "name",
|
|
461
|
+
# Equivalent to: { field: "episodes", path: "name", ... }
|
|
462
|
+
{ field: "episodes.name", operator: LIKE, value: "Final" }
|
|
443
463
|
] }
|
|
444
464
|
]
|
|
445
465
|
}
|
|
@@ -462,8 +482,8 @@ This translates to: `number > 1 AND (year = 2020 OR (year >= 2022 AND episodes.n
|
|
|
462
482
|
| `QLFilterGroup` | `AND: [QLFilterGroup]`, `OR: [QLFilterGroup]`, `conditions: [QLFilterCondition]` | Recursive logical group |
|
|
463
483
|
| `QLFilterCondition` | `field: String!`, `operator: QLOperator`, `value: QLValue`, `path: String` | Individual filter condition |
|
|
464
484
|
|
|
465
|
-
- `field` identifies the entity field by name (e.g., `"title"`, `"author"`)
|
|
466
|
-
- `path` is required for object/relationship fields (e.g., `"name"`, `"country.name"`)
|
|
485
|
+
- `field` identifies the entity field by name (e.g., `"title"`, `"author"`). For object/relationship fields you can also pass the full dotted path here as a shorthand (e.g., `"author.name"`, `"author.country.name"`)
|
|
486
|
+
- `path` is required for object/relationship fields when `field` is just the top-level name (e.g., `"name"`, `"country.name"`). Omit `path` if you used the dotted-`field` shorthand. Supplying both is an error.
|
|
467
487
|
- Multiple `conditions` in the same group are combined with AND
|
|
468
488
|
- Maximum nesting depth: 5 levels
|
|
469
489
|
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -316,6 +316,25 @@ const assertValidFilterPath = (path) => {
|
|
|
316
316
|
}
|
|
317
317
|
};
|
|
318
318
|
|
|
319
|
+
const normalizeFilterCondition = (condition) => {
|
|
320
|
+
const { field } = condition;
|
|
321
|
+
if (typeof field !== 'string') return condition;
|
|
322
|
+
const dotIdx = field.indexOf('.');
|
|
323
|
+
if (dotIdx < 0) return condition;
|
|
324
|
+
if (condition.path != null && condition.path !== '') {
|
|
325
|
+
throw new SimfinityError(
|
|
326
|
+
'Filter condition cannot use both dotted field syntax and a separate path',
|
|
327
|
+
'AMBIGUOUS_FILTER_FIELD',
|
|
328
|
+
400,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
...condition,
|
|
333
|
+
field: field.slice(0, dotIdx),
|
|
334
|
+
path: field.slice(dotIdx + 1),
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
|
|
319
338
|
const OP_TO_MONGO = {
|
|
320
339
|
LT: (v) => ({ $lt: v }),
|
|
321
340
|
GT: (v) => ({ $gt: v }),
|
|
@@ -1397,7 +1416,8 @@ const buildFilterGroupMatch = async (filterGroup, gqltype, aggregateClauses, agg
|
|
|
1397
1416
|
const fields = gqltype.getFields();
|
|
1398
1417
|
|
|
1399
1418
|
if (filterGroup.conditions?.length > 0) {
|
|
1400
|
-
for (const
|
|
1419
|
+
for (const rawCondition of filterGroup.conditions) {
|
|
1420
|
+
const condition = normalizeFilterCondition(rawCondition);
|
|
1401
1421
|
const qlField = fields[condition.field];
|
|
1402
1422
|
if (!qlField) {
|
|
1403
1423
|
throw new SimfinityError(`Unknown filter field: ${condition.field}`, 'INVALID_FILTER_FIELD', 400);
|