quetch 0.20.0 → 0.22.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/dist/tools/queryItemList.js +2 -2
- package/dist/tools/queryItemList.js.map +1 -1
- package/dist/tools/sameField.d.ts +2 -0
- package/dist/tools/sameField.js +13 -0
- package/dist/tools/sameField.js.map +1 -0
- package/dist/tools/sortItemList.d.ts +3 -2
- package/dist/tools/sortItemList.js +25 -2
- package/dist/tools/sortItemList.js.map +1 -1
- package/dist/tools/splitPath.d.ts +21 -0
- package/dist/tools/splitPath.js +19 -0
- package/dist/tools/splitPath.js.map +1 -0
- package/dist/tools/testFilter.js +3 -2
- package/dist/tools/testFilter.js.map +1 -1
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +2 -0
- package/dist/tools.js.map +1 -1
- package/dist/types/Field.d.ts +2 -3
- package/dist/types/FieldKey.d.ts +3 -0
- package/dist/types/FieldKey.js +1 -0
- package/dist/types/FieldKey.js.map +1 -0
- package/dist/types/FieldMap.d.ts +5 -0
- package/dist/types/FieldMap.js +1 -0
- package/dist/types/FieldMap.js.map +1 -0
- package/dist/types/QuerySettings.d.ts +13 -5
- package/dist/types/ValueMap.d.ts +7 -0
- package/dist/types/ValueMap.js +1 -0
- package/dist/types/ValueMap.js.map +1 -0
- package/dist/types.d.ts +3 -0
- package/doc/README.md +5 -0
- package/doc/classes/RequestError.md +5 -5
- package/doc/functions/aggregate.md +1 -1
- package/doc/functions/branch.md +1 -1
- package/doc/functions/cache.md +1 -1
- package/doc/functions/combine.md +1 -1
- package/doc/functions/cork.md +1 -1
- package/doc/functions/defineCheckQuery.md +1 -1
- package/doc/functions/defineCustomFetch.md +1 -1
- package/doc/functions/defineGenericFetch.md +1 -1
- package/doc/functions/escapeRegex.md +1 -1
- package/doc/functions/fetchExternal.md +1 -1
- package/doc/functions/fetchLocal.md +1 -1
- package/doc/functions/fieldListFromFilter.md +1 -1
- package/doc/functions/filterChildren.md +1 -1
- package/doc/functions/filterFromContext.md +1 -1
- package/doc/functions/get.md +1 -1
- package/doc/functions/identity.md +1 -1
- package/doc/functions/isFilterGroup.md +1 -1
- package/doc/functions/log.md +1 -1
- package/doc/functions/normalizeOrder.md +1 -1
- package/doc/functions/queryItemList.md +1 -1
- package/doc/functions/retry.md +1 -1
- package/doc/functions/reverseOrder.md +1 -1
- package/doc/functions/sameField.md +27 -0
- package/doc/functions/sortItemList.md +8 -2
- package/doc/functions/splitPath.md +73 -0
- package/doc/functions/testFilter.md +1 -1
- package/doc/interfaces/CustomFetch.md +1 -1
- package/doc/type-aliases/AggregateFunction.md +1 -1
- package/doc/type-aliases/AggregateFunctionOperator.md +1 -1
- package/doc/type-aliases/CombineUnion.md +1 -1
- package/doc/type-aliases/Context.md +1 -1
- package/doc/type-aliases/CustomFieldAggregateMap.md +1 -1
- package/doc/type-aliases/CustomFieldMap.md +1 -1
- package/doc/type-aliases/Field.md +1 -1
- package/doc/type-aliases/FieldFiltered.md +1 -1
- package/doc/type-aliases/FieldFunction.md +1 -1
- package/doc/type-aliases/FieldFunctionCustom.md +1 -1
- package/doc/type-aliases/FieldFunctionFormatDate.md +1 -1
- package/doc/type-aliases/FieldFunctionReturn.md +1 -1
- package/doc/type-aliases/FieldKey.md +17 -0
- package/doc/type-aliases/FieldMap.md +21 -0
- package/doc/type-aliases/Filter.md +1 -1
- package/doc/type-aliases/FilterArray.md +2 -2
- package/doc/type-aliases/FilterBoolean.md +1 -1
- package/doc/type-aliases/FilterChildren.md +2 -2
- package/doc/type-aliases/FilterCustom.md +1 -1
- package/doc/type-aliases/FilterField.md +2 -2
- package/doc/type-aliases/FilterGroup.md +1 -1
- package/doc/type-aliases/FilterNumber.md +2 -2
- package/doc/type-aliases/FilterOperator.md +1 -1
- package/doc/type-aliases/FilterString.md +2 -2
- package/doc/type-aliases/FilterStringIntersect.md +2 -2
- package/doc/type-aliases/FilterStringMatch.md +2 -2
- package/doc/type-aliases/Get.md +1 -1
- package/doc/type-aliases/Group.md +1 -1
- package/doc/type-aliases/Handler.md +1 -1
- package/doc/type-aliases/Immutable.md +1 -1
- package/doc/type-aliases/Increment.md +1 -1
- package/doc/type-aliases/InjectCustomFields.md +1 -1
- package/doc/type-aliases/IntersectUnion.md +1 -1
- package/doc/type-aliases/Item.md +1 -1
- package/doc/type-aliases/Join.md +1 -1
- package/doc/type-aliases/Key.md +1 -1
- package/doc/type-aliases/KeyFiltered.md +1 -1
- package/doc/type-aliases/KeyFromUnion.md +1 -1
- package/doc/type-aliases/Locale.md +1 -1
- package/doc/type-aliases/NextHandler.md +1 -1
- package/doc/type-aliases/Order.md +1 -1
- package/doc/type-aliases/OrderNormalized.md +1 -1
- package/doc/type-aliases/Parameters.md +1 -1
- package/doc/type-aliases/Path.md +1 -1
- package/doc/type-aliases/PathFiltered.md +1 -1
- package/doc/type-aliases/Primitive.md +1 -1
- package/doc/type-aliases/PrimitiveObject.md +1 -1
- package/doc/type-aliases/Query.md +1 -1
- package/doc/type-aliases/QueryAggregate.md +1 -1
- package/doc/type-aliases/QueryCreate.md +1 -1
- package/doc/type-aliases/QueryCreateMultiple.md +1 -1
- package/doc/type-aliases/QueryDelete.md +1 -1
- package/doc/type-aliases/QueryDeleteMultiple.md +1 -1
- package/doc/type-aliases/QueryMethod.md +1 -1
- package/doc/type-aliases/QueryRead.md +1 -1
- package/doc/type-aliases/QueryReadMultiple.md +1 -1
- package/doc/type-aliases/QuerySettings.md +23 -5
- package/doc/type-aliases/QueryUpdate.md +1 -1
- package/doc/type-aliases/QueryUpdateMultiple.md +1 -1
- package/doc/type-aliases/Result.md +1 -1
- package/doc/type-aliases/Store.md +1 -1
- package/doc/type-aliases/Value.md +1 -1
- package/doc/type-aliases/ValueMap.md +21 -0
- package/doc/variables/CACHE.md +1 -1
- package/doc/variables/SELF.md +1 -1
- package/lib/tools/queryItemList.ts +2 -2
- package/lib/tools/sameField.ts +15 -0
- package/lib/tools/sortItemList.test.ts +59 -0
- package/lib/tools/sortItemList.ts +40 -2
- package/lib/tools/splitPath.test.ts +17 -0
- package/lib/tools/splitPath.ts +54 -0
- package/lib/tools/testFilter.test.ts +4 -4
- package/lib/tools/testFilter.ts +6 -4
- package/lib/tools.ts +2 -0
- package/lib/types/Field.ts +2 -4
- package/lib/types/FieldKey.ts +5 -0
- package/lib/types/FieldMap.ts +6 -0
- package/lib/types/QuerySettings.ts +13 -6
- package/lib/types/ValueMap.ts +14 -0
- package/lib/types.ts +3 -0
- package/package.json +1 -1
|
@@ -48,4 +48,4 @@ Query settings.
|
|
|
48
48
|
|
|
49
49
|
## Defined in
|
|
50
50
|
|
|
51
|
-
[lib/types/QueryDelete.ts:9](https://github.com/nevoland/quetch/blob/
|
|
51
|
+
[lib/types/QueryDelete.ts:9](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QueryDelete.ts#L9)
|
|
@@ -48,4 +48,4 @@ Query settings.
|
|
|
48
48
|
|
|
49
49
|
## Defined in
|
|
50
50
|
|
|
51
|
-
[lib/types/QueryDeleteMultiple.ts:9](https://github.com/nevoland/quetch/blob/
|
|
51
|
+
[lib/types/QueryDeleteMultiple.ts:9](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QueryDeleteMultiple.ts#L9)
|
|
@@ -12,4 +12,4 @@ Available query methods.
|
|
|
12
12
|
|
|
13
13
|
## Defined in
|
|
14
14
|
|
|
15
|
-
[lib/types/QueryMethod.ts:6](https://github.com/nevoland/quetch/blob/
|
|
15
|
+
[lib/types/QueryMethod.ts:6](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QueryMethod.ts#L6)
|
|
@@ -76,4 +76,4 @@ Query settings.
|
|
|
76
76
|
|
|
77
77
|
## Defined in
|
|
78
78
|
|
|
79
|
-
[lib/types/QueryRead.ts:10](https://github.com/nevoland/quetch/blob/
|
|
79
|
+
[lib/types/QueryRead.ts:10](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QueryRead.ts#L10)
|
|
@@ -80,4 +80,4 @@ Query settings.
|
|
|
80
80
|
|
|
81
81
|
## Defined in
|
|
82
82
|
|
|
83
|
-
[lib/types/QueryReadMultiple.ts:11](https://github.com/nevoland/quetch/blob/
|
|
83
|
+
[lib/types/QueryReadMultiple.ts:11](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QueryReadMultiple.ts#L11)
|
|
@@ -22,17 +22,35 @@ Settings to use when doing a query.
|
|
|
22
22
|
|
|
23
23
|
Abort controller to abort the query.
|
|
24
24
|
|
|
25
|
-
###
|
|
25
|
+
### pathField?
|
|
26
26
|
|
|
27
|
-
> `optional` **
|
|
27
|
+
> `optional` **pathField**: [`FieldFiltered`](FieldFiltered.md)\<`T`, `string`\>
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Path to the field that contains the path value of an item, used for displaying items in a tree.
|
|
30
30
|
|
|
31
31
|
### pathFieldSeparator?
|
|
32
32
|
|
|
33
33
|
> `optional` **pathFieldSeparator**: `string`
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Maps path fields to a string used to separate the path nodes of a field value.
|
|
36
|
+
|
|
37
|
+
#### Default
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
"/"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### pathFieldSeparatorEscape?
|
|
44
|
+
|
|
45
|
+
> `optional` **pathFieldSeparatorEscape**: `string`
|
|
46
|
+
|
|
47
|
+
String used to escape the separator.
|
|
48
|
+
|
|
49
|
+
#### Default
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
"\\"
|
|
53
|
+
```
|
|
36
54
|
|
|
37
55
|
### signal?
|
|
38
56
|
|
|
@@ -62,4 +80,4 @@ A filter that captures the items expressed by the provided `FilterChildren`.
|
|
|
62
80
|
|
|
63
81
|
## Defined in
|
|
64
82
|
|
|
65
|
-
[lib/types/QuerySettings.ts:8](https://github.com/nevoland/quetch/blob/
|
|
83
|
+
[lib/types/QuerySettings.ts:8](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QuerySettings.ts#L8)
|
|
@@ -68,4 +68,4 @@ Partial property values to update.
|
|
|
68
68
|
|
|
69
69
|
## Defined in
|
|
70
70
|
|
|
71
|
-
[lib/types/QueryUpdate.ts:9](https://github.com/nevoland/quetch/blob/
|
|
71
|
+
[lib/types/QueryUpdate.ts:9](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QueryUpdate.ts#L9)
|
|
@@ -72,4 +72,4 @@ Partial property values to update.
|
|
|
72
72
|
|
|
73
73
|
## Defined in
|
|
74
74
|
|
|
75
|
-
[lib/types/QueryUpdateMultiple.ts:10](https://github.com/nevoland/quetch/blob/
|
|
75
|
+
[lib/types/QueryUpdateMultiple.ts:10](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/QueryUpdateMultiple.ts#L10)
|
|
@@ -16,4 +16,4 @@
|
|
|
16
16
|
|
|
17
17
|
## Defined in
|
|
18
18
|
|
|
19
|
-
[lib/types/Result.ts:20](https://github.com/nevoland/quetch/blob/
|
|
19
|
+
[lib/types/Result.ts:20](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/Result.ts#L20)
|
|
@@ -68,4 +68,4 @@
|
|
|
68
68
|
|
|
69
69
|
## Defined in
|
|
70
70
|
|
|
71
|
-
[lib/types/Store.ts:2](https://github.com/nevoland/quetch/blob/
|
|
71
|
+
[lib/types/Store.ts:2](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/Store.ts#L2)
|
|
@@ -36,4 +36,4 @@ Path leading to the value.
|
|
|
36
36
|
|
|
37
37
|
## Defined in
|
|
38
38
|
|
|
39
|
-
[lib/types/Value.ts:6](https://github.com/nevoland/quetch/blob/
|
|
39
|
+
[lib/types/Value.ts:6](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/Value.ts#L6)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[**quetch**](../README.md)
|
|
2
|
+
|
|
3
|
+
***
|
|
4
|
+
|
|
5
|
+
[quetch](../README.md) / ValueMap
|
|
6
|
+
|
|
7
|
+
# Type Alias: ValueMap\<T, V\>
|
|
8
|
+
|
|
9
|
+
> **ValueMap**\<`T`, `V`\>: `T` *extends* [`Primitive`](Primitive.md) ? `V` : `T` *extends* infer P[] ? `Record`\<`number`, [`ValueMap`](ValueMap.md)\<`P`, `V`\>\> : `T` *extends* `object` ? `{ [K in keyof T]?: ValueMap<T[K], V> }` : `never`
|
|
10
|
+
|
|
11
|
+
Maps the properties of the provided value `T` to a specific value `V`.
|
|
12
|
+
|
|
13
|
+
## Type Parameters
|
|
14
|
+
|
|
15
|
+
• **T**
|
|
16
|
+
|
|
17
|
+
• **V**
|
|
18
|
+
|
|
19
|
+
## Defined in
|
|
20
|
+
|
|
21
|
+
[lib/types/ValueMap.ts:6](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/types/ValueMap.ts#L6)
|
package/doc/variables/CACHE.md
CHANGED
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
|
|
11
11
|
## Defined in
|
|
12
12
|
|
|
13
|
-
[lib/constants/CACHE.ts:1](https://github.com/nevoland/quetch/blob/
|
|
13
|
+
[lib/constants/CACHE.ts:1](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/constants/CACHE.ts#L1)
|
package/doc/variables/SELF.md
CHANGED
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
|
|
11
11
|
## Defined in
|
|
12
12
|
|
|
13
|
-
[lib/constants/SELF.ts:1](https://github.com/nevoland/quetch/blob/
|
|
13
|
+
[lib/constants/SELF.ts:1](https://github.com/nevoland/quetch/blob/5d54d23c7450a0f85309e15fdf3a25ea832b3452/lib/constants/SELF.ts#L1)
|
|
@@ -83,7 +83,7 @@ export function queryItemList<T, const Q extends Query<T>>(
|
|
|
83
83
|
);
|
|
84
84
|
}
|
|
85
85
|
// Sort
|
|
86
|
-
result = sortItemList(order, result);
|
|
86
|
+
result = sortItemList(order, result, query.settings);
|
|
87
87
|
// Slice
|
|
88
88
|
if (offset !== 0 || limit !== Infinity) {
|
|
89
89
|
result = result.slice(offset, offset + limit);
|
|
@@ -125,7 +125,7 @@ export function queryItemList<T, const Q extends Query<T>>(
|
|
|
125
125
|
);
|
|
126
126
|
}
|
|
127
127
|
// Sort
|
|
128
|
-
result = sortItemList(order, result);
|
|
128
|
+
result = sortItemList(order, result, query.settings);
|
|
129
129
|
// Slice
|
|
130
130
|
if (offset !== 0 || limit !== Infinity) {
|
|
131
131
|
result = result.slice(offset, offset + limit);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Field } from "../types";
|
|
2
|
+
|
|
3
|
+
const { isArray } = Array;
|
|
4
|
+
|
|
5
|
+
export function sameField(a: Field<any>, b: Field<any>): boolean {
|
|
6
|
+
if (a === b) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
const aNormalized = isArray(a) ? a : [a];
|
|
10
|
+
const bNormalized = isArray(b) ? b : [b];
|
|
11
|
+
if (aNormalized.length !== bNormalized.length) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return aNormalized.every((value, index) => value === bNormalized[index]);
|
|
15
|
+
}
|
|
@@ -61,3 +61,62 @@ test("sorts items", () => {
|
|
|
61
61
|
{ a: 3, c: "b" },
|
|
62
62
|
]);
|
|
63
63
|
});
|
|
64
|
+
|
|
65
|
+
test("sorts items with separator setting", () => {
|
|
66
|
+
expect(
|
|
67
|
+
sortItemList(
|
|
68
|
+
[{ descending: false, field: "path" }],
|
|
69
|
+
[
|
|
70
|
+
{ path: "a" },
|
|
71
|
+
{ path: "a/b" },
|
|
72
|
+
{ path: "a.b" },
|
|
73
|
+
{ path: "a/b/c" },
|
|
74
|
+
{ path: "a.b.c" },
|
|
75
|
+
{ path: "a/b.c" },
|
|
76
|
+
{ path: "a\\/b.c" },
|
|
77
|
+
{ path: "a.b/c" },
|
|
78
|
+
],
|
|
79
|
+
{
|
|
80
|
+
pathField: "path",
|
|
81
|
+
pathFieldSeparator: "/",
|
|
82
|
+
},
|
|
83
|
+
),
|
|
84
|
+
).toEqual([
|
|
85
|
+
{ path: "a" },
|
|
86
|
+
{ path: "a/b" },
|
|
87
|
+
{ path: "a/b/c" },
|
|
88
|
+
{ path: "a/b.c" },
|
|
89
|
+
{ path: "a.b" },
|
|
90
|
+
{ path: "a.b/c" },
|
|
91
|
+
{ path: "a.b.c" },
|
|
92
|
+
{ path: "a\\/b.c" },
|
|
93
|
+
]);
|
|
94
|
+
expect(
|
|
95
|
+
sortItemList(
|
|
96
|
+
[{ descending: false, field: "path" }],
|
|
97
|
+
[
|
|
98
|
+
{ path: "a" },
|
|
99
|
+
{ path: "a/b" },
|
|
100
|
+
{ path: "a.b" },
|
|
101
|
+
{ path: "a/b/c" },
|
|
102
|
+
{ path: "a.b.c" },
|
|
103
|
+
{ path: "a/b.c" },
|
|
104
|
+
{ path: "a\\/b.c" },
|
|
105
|
+
{ path: "a.b/c" },
|
|
106
|
+
],
|
|
107
|
+
{
|
|
108
|
+
pathField: "path",
|
|
109
|
+
pathFieldSeparator: "/",
|
|
110
|
+
},
|
|
111
|
+
),
|
|
112
|
+
).toEqual([
|
|
113
|
+
{ path: "a" },
|
|
114
|
+
{ path: "a/b" },
|
|
115
|
+
{ path: "a/b/c" },
|
|
116
|
+
{ path: "a/b.c" },
|
|
117
|
+
{ path: "a.b" },
|
|
118
|
+
{ path: "a.b/c" },
|
|
119
|
+
{ path: "a.b.c" },
|
|
120
|
+
{ path: "a\\/b.c" },
|
|
121
|
+
]);
|
|
122
|
+
});
|
|
@@ -1,24 +1,42 @@
|
|
|
1
|
-
import type { Order } from "../types";
|
|
1
|
+
import type { Order, QuerySettings } from "../types";
|
|
2
2
|
|
|
3
|
+
import { escapeRegex } from "./escapeRegex.js";
|
|
3
4
|
import { get } from "./get.js";
|
|
4
5
|
import { normalizeOrder } from "./normalizeOrder.js";
|
|
6
|
+
import { sameField } from "./sameField.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Sorts provided `value` array according to the `orderList`.
|
|
8
10
|
*
|
|
9
11
|
* @param orderList The order to use for sorting.
|
|
10
12
|
* @param value The array to sort.
|
|
13
|
+
* @param settings Optional query settings.
|
|
11
14
|
* @returns A new sorted array.
|
|
12
15
|
*/
|
|
13
16
|
export function sortItemList<T>(
|
|
14
17
|
orderList: readonly Order<T>[] | undefined,
|
|
15
18
|
value: readonly T[],
|
|
19
|
+
settings?: QuerySettings<T>,
|
|
16
20
|
) {
|
|
21
|
+
const {
|
|
22
|
+
pathField,
|
|
23
|
+
pathFieldSeparator = "/",
|
|
24
|
+
pathFieldSeparatorEscape,
|
|
25
|
+
} = settings ?? {};
|
|
17
26
|
if (orderList === undefined || orderList.length === 0) {
|
|
18
27
|
return value;
|
|
19
28
|
}
|
|
20
29
|
const normalizedOrder = orderList.map(normalizeOrder);
|
|
21
|
-
|
|
30
|
+
const fieldSeparatorRegexp =
|
|
31
|
+
pathField == null || pathFieldSeparator == null
|
|
32
|
+
? null
|
|
33
|
+
: new RegExp(
|
|
34
|
+
!pathFieldSeparatorEscape
|
|
35
|
+
? escapeRegex(pathFieldSeparator)
|
|
36
|
+
: `(?<!${escapeRegex(pathFieldSeparatorEscape)})${escapeRegex(pathFieldSeparator)}`,
|
|
37
|
+
"g",
|
|
38
|
+
);
|
|
39
|
+
return value.toSorted((a, b) => {
|
|
22
40
|
for (let index = 0; index < normalizedOrder.length; index++) {
|
|
23
41
|
const { field, descending } = normalizedOrder[index]!;
|
|
24
42
|
const valueA = get(a, field as any);
|
|
@@ -26,6 +44,26 @@ export function sortItemList<T>(
|
|
|
26
44
|
if (valueA === valueB) {
|
|
27
45
|
continue;
|
|
28
46
|
}
|
|
47
|
+
if (fieldSeparatorRegexp != null && sameField(field, pathField!)) {
|
|
48
|
+
if (valueA == null) {
|
|
49
|
+
return valueB == null ? 0 : descending ? 1 : -1;
|
|
50
|
+
}
|
|
51
|
+
if (valueB == null) {
|
|
52
|
+
return descending ? -1 : 1;
|
|
53
|
+
}
|
|
54
|
+
const normalizedA = (valueA as string).replaceAll(
|
|
55
|
+
fieldSeparatorRegexp,
|
|
56
|
+
"\x00",
|
|
57
|
+
);
|
|
58
|
+
const normalizedB = (valueB as string).replaceAll(
|
|
59
|
+
fieldSeparatorRegexp,
|
|
60
|
+
"\x00",
|
|
61
|
+
);
|
|
62
|
+
if (normalizedA > normalizedB) {
|
|
63
|
+
return descending ? -1 : 1;
|
|
64
|
+
}
|
|
65
|
+
return descending ? 1 : -1;
|
|
66
|
+
}
|
|
29
67
|
if (valueA > valueB) {
|
|
30
68
|
return descending ? -1 : 1;
|
|
31
69
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { splitPath } from "./splitPath.js";
|
|
4
|
+
|
|
5
|
+
test("splits paths", () => {
|
|
6
|
+
expect(splitPath("/", "\\", "/a/b")).toEqual(["", "a", "b"]);
|
|
7
|
+
expect(splitPath("/", "\\", "/a\\/b")).toEqual(["", "a\\/b"]);
|
|
8
|
+
expect(splitPath("/", "", "/a\\/b")).toEqual(["", "a\\", "b"]);
|
|
9
|
+
expect(splitPath("", "", "/a/b")).toEqual(["/a/b"]);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("returns path splitter", () => {
|
|
13
|
+
expect(splitPath("/", "\\")("/a/b")).toEqual(["", "a", "b"]);
|
|
14
|
+
expect(splitPath("/", "\\")("/a\\/b")).toEqual(["", "a\\/b"]);
|
|
15
|
+
expect(splitPath("/", "")("/a\\/b")).toEqual(["", "a\\", "b"]);
|
|
16
|
+
expect(splitPath("", "")("/a/b")).toEqual(["/a/b"]);
|
|
17
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { escapeRegex } from "./escapeRegex.js";
|
|
2
|
+
|
|
3
|
+
type PathSplitter =
|
|
4
|
+
/**
|
|
5
|
+
* Takes a `path` string and returns an array of path items.
|
|
6
|
+
*
|
|
7
|
+
* @param path The path string to split.
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
(path: string) => readonly string[];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Splits a `path` string using the `separator`, omitting those prefixed with a `separatorEscape`.
|
|
14
|
+
*
|
|
15
|
+
* If `path` is `undefined`, returns a function that takes `path` and splits it according to the provided `separator` and `separatorEscape` arguments.
|
|
16
|
+
*
|
|
17
|
+
* @param separator The separator string to use (defaults to `"/"`).
|
|
18
|
+
* @param separatorEscape The separator escape string to use (default to `"\\"`).
|
|
19
|
+
* @param path The path string to split.
|
|
20
|
+
* @returns An array containing the splitted path items if `path` is defined, or a function that takes a `path` string and returns an array.
|
|
21
|
+
*/
|
|
22
|
+
export function splitPath(
|
|
23
|
+
separator: string | undefined,
|
|
24
|
+
separatorEscape: string | undefined,
|
|
25
|
+
path: string,
|
|
26
|
+
): readonly string[];
|
|
27
|
+
export function splitPath(
|
|
28
|
+
separator?: string,
|
|
29
|
+
separatorEscape?: string,
|
|
30
|
+
): PathSplitter;
|
|
31
|
+
export function splitPath(
|
|
32
|
+
separator = "/",
|
|
33
|
+
separatorEscape = "\\",
|
|
34
|
+
path?: string,
|
|
35
|
+
): readonly string[] | PathSplitter {
|
|
36
|
+
const fieldSeparatorRegexp = !separator
|
|
37
|
+
? null
|
|
38
|
+
: new RegExp(
|
|
39
|
+
!separatorEscape
|
|
40
|
+
? escapeRegex(separator)
|
|
41
|
+
: `(?<!${escapeRegex(separatorEscape)})${escapeRegex(separator)}`,
|
|
42
|
+
"g",
|
|
43
|
+
);
|
|
44
|
+
if (path == null) {
|
|
45
|
+
if (fieldSeparatorRegexp == null) {
|
|
46
|
+
return (path: string) => [path];
|
|
47
|
+
}
|
|
48
|
+
return (path: string) => path.split(fieldSeparatorRegexp);
|
|
49
|
+
}
|
|
50
|
+
if (fieldSeparatorRegexp == null) {
|
|
51
|
+
return [path];
|
|
52
|
+
}
|
|
53
|
+
return path.split(fieldSeparatorRegexp);
|
|
54
|
+
}
|
|
@@ -322,7 +322,7 @@ test("tests filter with children predicates", () => {
|
|
|
322
322
|
{ operator: "children", value: ".a" },
|
|
323
323
|
{ path: ".a.b" },
|
|
324
324
|
{
|
|
325
|
-
|
|
325
|
+
pathField: "path",
|
|
326
326
|
pathFieldSeparator: ".",
|
|
327
327
|
},
|
|
328
328
|
),
|
|
@@ -332,7 +332,7 @@ test("tests filter with children predicates", () => {
|
|
|
332
332
|
{ operator: "notChildren", value: ".a" },
|
|
333
333
|
{ path: ".a.b" },
|
|
334
334
|
{
|
|
335
|
-
|
|
335
|
+
pathField: "path",
|
|
336
336
|
pathFieldSeparator: ".",
|
|
337
337
|
},
|
|
338
338
|
),
|
|
@@ -368,7 +368,7 @@ test("tests filter with children predicates", () => {
|
|
|
368
368
|
{ operator: "children", value: "ba" },
|
|
369
369
|
{ path: ".a.b" },
|
|
370
370
|
{
|
|
371
|
-
|
|
371
|
+
pathField: "path",
|
|
372
372
|
pathFieldSeparator: ".",
|
|
373
373
|
},
|
|
374
374
|
),
|
|
@@ -378,7 +378,7 @@ test("tests filter with children predicates", () => {
|
|
|
378
378
|
{ operator: "notChildren", value: "ba" },
|
|
379
379
|
{ path: ".a.b" },
|
|
380
380
|
{
|
|
381
|
-
|
|
381
|
+
pathField: "path",
|
|
382
382
|
pathFieldSeparator: ".",
|
|
383
383
|
},
|
|
384
384
|
),
|
package/lib/tools/testFilter.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { EMPTY_OBJECT } from "unchangeable";
|
|
2
|
+
|
|
1
3
|
import { CACHE } from "../constants/CACHE.js";
|
|
2
4
|
import type { QuerySettings } from "../types/QuerySettings.js";
|
|
3
5
|
import type { FieldFiltered, Filter, FilterString } from "../types.js";
|
|
@@ -113,12 +115,12 @@ export function testFilter<T>(
|
|
|
113
115
|
break;
|
|
114
116
|
default: {
|
|
115
117
|
const {
|
|
116
|
-
|
|
117
|
-
pathFieldSeparator
|
|
118
|
-
} = settings ||
|
|
118
|
+
pathField = "id" as FieldFiltered<T, string>,
|
|
119
|
+
pathFieldSeparator,
|
|
120
|
+
} = settings || (EMPTY_OBJECT as QuerySettings<T>);
|
|
119
121
|
filter[CACHE] = filterChildren(
|
|
120
122
|
filter.value as string,
|
|
121
|
-
|
|
123
|
+
pathField,
|
|
122
124
|
filter.deep,
|
|
123
125
|
pathFieldSeparator,
|
|
124
126
|
);
|
package/lib/tools.ts
CHANGED
|
@@ -12,5 +12,7 @@ export { isFilterGroup } from "./tools/isFilterGroup.js";
|
|
|
12
12
|
export { normalizeOrder } from "./tools/normalizeOrder.js";
|
|
13
13
|
export { queryItemList } from "./tools/queryItemList.js";
|
|
14
14
|
export { reverseOrder } from "./tools/reverseOrder.js";
|
|
15
|
+
export { sameField } from "./tools/sameField.js";
|
|
15
16
|
export { sortItemList } from "./tools/sortItemList.js";
|
|
17
|
+
export { splitPath } from "./tools/splitPath.js";
|
|
16
18
|
export { testFilter } from "./tools/testFilter.js";
|
package/lib/types/Field.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import type { SELF } from "../constants/SELF.js";
|
|
2
|
-
|
|
3
1
|
import type { CombineUnion } from "./CombineUnion";
|
|
2
|
+
import type { FieldKey } from "./FieldKey.js";
|
|
4
3
|
import type { Path } from "./Path";
|
|
5
|
-
import type { Primitive } from "./Primitive";
|
|
6
4
|
|
|
7
5
|
export type Field<T> = KeyOrPath<CombineUnion<T>>;
|
|
8
6
|
|
|
9
|
-
type KeyOrPath<T> =
|
|
7
|
+
type KeyOrPath<T> = FieldKey<T> | Path<T>;
|
|
@@ -6,15 +6,22 @@ import type { FilterChildren } from "./FilterChildren";
|
|
|
6
6
|
* Settings to use when doing a query.
|
|
7
7
|
*/
|
|
8
8
|
export type QuerySettings<T> = {
|
|
9
|
-
// TODO: Move `path*` and `transform*` to fetch middleware?
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
10
|
+
* Path to the field that contains the path value of an item, used for displaying items in a tree.
|
|
12
11
|
*/
|
|
13
|
-
|
|
12
|
+
pathField?: FieldFiltered<T, string>;
|
|
13
|
+
/**
|
|
14
|
+
* String used to escape the separator.
|
|
15
|
+
*
|
|
16
|
+
* @default "\\"
|
|
17
|
+
*/
|
|
18
|
+
pathFieldSeparatorEscape?: string;
|
|
14
19
|
/**
|
|
15
|
-
*
|
|
20
|
+
* Maps path fields to a string used to separate the path nodes of a field value.
|
|
21
|
+
*
|
|
22
|
+
* @default "/"
|
|
16
23
|
*/
|
|
17
|
-
|
|
24
|
+
pathFieldSeparator?: string;
|
|
18
25
|
/**
|
|
19
26
|
* Returns a filter that captures the items expressed by the provided `FilterChildren`. The return filter cannot use filters of type `FilterChildren`.
|
|
20
27
|
*
|
|
@@ -23,7 +30,7 @@ export type QuerySettings<T> = {
|
|
|
23
30
|
*/
|
|
24
31
|
transformFilterChildren?: (
|
|
25
32
|
filter: FilterChildren<T>,
|
|
26
|
-
) => Exclude<Filter<T>, { operator: "children" }>;
|
|
33
|
+
) => Exclude<Filter<T>, { operator: "children" | "notChildren" }>;
|
|
27
34
|
/**
|
|
28
35
|
* Abort signal to abort the query.
|
|
29
36
|
*/
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Primitive } from "./Primitive";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Maps the properties of the provided value `T` to a specific value `V`.
|
|
5
|
+
*/
|
|
6
|
+
export type ValueMap<T, V> = T extends Primitive
|
|
7
|
+
? V
|
|
8
|
+
: T extends Array<infer P>
|
|
9
|
+
? Record<number, ValueMap<P, V>>
|
|
10
|
+
: T extends object
|
|
11
|
+
? {
|
|
12
|
+
[K in keyof T]?: ValueMap<T[K], V>;
|
|
13
|
+
}
|
|
14
|
+
: never;
|
package/lib/types.ts
CHANGED
|
@@ -12,6 +12,8 @@ export type { FieldFunction } from "./types/FieldFunction";
|
|
|
12
12
|
export type { FieldFunctionCustom } from "./types/FieldFunctionCustom";
|
|
13
13
|
export type { FieldFunctionFormatDate } from "./types/FieldFunctionFormatDate";
|
|
14
14
|
export type { FieldFunctionReturn } from "./types/FieldFunctionReturn";
|
|
15
|
+
export type { FieldKey } from "./types/FieldKey";
|
|
16
|
+
export type { FieldMap } from "./types/FieldMap";
|
|
15
17
|
export type { Filter } from "./types/Filter";
|
|
16
18
|
export type { FilterArray } from "./types/FilterArray";
|
|
17
19
|
export type { FilterBoolean } from "./types/FilterBoolean";
|
|
@@ -60,3 +62,4 @@ export type { QueryUpdateMultiple } from "./types/QueryUpdateMultiple";
|
|
|
60
62
|
export type { Result } from "./types/Result";
|
|
61
63
|
export type { Store } from "./types/Store";
|
|
62
64
|
export type { Value } from "./types/Value";
|
|
65
|
+
export type { ValueMap } from "./types/ValueMap";
|