@rimbu/deep 2.0.1 → 2.0.3
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 +295 -60
- package/dist/bun/deep.mts +8 -8
- package/dist/bun/match.mts +29 -27
- package/dist/bun/patch.mts +11 -10
- package/dist/bun/path.mts +98 -100
- package/dist/bun/protected.mts +18 -17
- package/dist/bun/selector.mts +22 -20
- package/dist/bun/tuple.mts +6 -2
- package/dist/cjs/deep.cjs +18 -18
- package/dist/cjs/deep.cjs.map +1 -1
- package/dist/cjs/deep.d.cts +6 -6
- package/dist/cjs/match.cjs +2 -3
- package/dist/cjs/match.cjs.map +1 -1
- package/dist/cjs/match.d.cts +2 -2
- package/dist/cjs/patch.cjs +2 -3
- package/dist/cjs/patch.cjs.map +1 -1
- package/dist/cjs/patch.d.cts +1 -1
- package/dist/cjs/path.cjs +5 -5
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +8 -6
- package/dist/cjs/selector.cjs +1 -2
- package/dist/cjs/selector.cjs.map +1 -1
- package/dist/cjs/tuple.cjs +1 -1
- package/dist/cjs/tuple.cjs.map +1 -1
- package/dist/cjs/tuple.d.cts +5 -1
- package/dist/esm/deep.d.mts +6 -6
- package/dist/esm/deep.mjs +6 -6
- package/dist/esm/match.d.mts +2 -2
- package/dist/esm/match.mjs +1 -1
- package/dist/esm/match.mjs.map +1 -1
- package/dist/esm/patch.d.mts +1 -1
- package/dist/esm/patch.mjs +1 -1
- package/dist/esm/patch.mjs.map +1 -1
- package/dist/esm/path.d.mts +8 -6
- package/dist/esm/path.mjs +2 -2
- package/dist/esm/path.mjs.map +1 -1
- package/dist/esm/selector.mjs.map +1 -1
- package/dist/esm/tuple.d.mts +5 -1
- package/dist/esm/tuple.mjs +1 -1
- package/dist/esm/tuple.mjs.map +1 -1
- package/package.json +7 -7
- package/src/deep.mts +8 -8
- package/src/match.mts +29 -27
- package/src/patch.mts +11 -10
- package/src/path.mts +98 -100
- package/src/protected.mts +18 -17
- package/src/selector.mts +22 -20
- package/src/tuple.mts +6 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimbu/deep",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Tools to use handle plain JS objects as immutable objects",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"immutable",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"types": "./dist/cjs/index.d.cts",
|
|
37
37
|
"exports": {
|
|
38
38
|
".": {
|
|
39
|
+
"bun": "./dist/bun/index.mts",
|
|
39
40
|
"import": {
|
|
40
41
|
"types": "./dist/esm/index.d.mts",
|
|
41
42
|
"default": "./dist/esm/index.mjs"
|
|
@@ -43,8 +44,7 @@
|
|
|
43
44
|
"require": {
|
|
44
45
|
"types": "./dist/cjs/index.d.cts",
|
|
45
46
|
"default": "./dist/cjs/index.cjs"
|
|
46
|
-
}
|
|
47
|
-
"bun": "./dist/bun/index.mts"
|
|
47
|
+
}
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"files": [
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"bundle:deno-clean": "rimraf _deno_prepare",
|
|
67
67
|
"bundle:esm": "tsc --p tsconfig.esm.json",
|
|
68
68
|
"clean": "rimraf dist",
|
|
69
|
-
"extract-api": "
|
|
69
|
+
"extract-api": "tsx ../../config/api-extractor.ts config/api-extractor.main.json",
|
|
70
70
|
"format": "yarn format:base --write",
|
|
71
71
|
"format:base": "prettier \"{!CHANGELOG.md}|**/**/*.{ts,tsx,js,mts,mjs,json,md}\"",
|
|
72
72
|
"format:check": "yarn format:base --check",
|
|
@@ -78,12 +78,12 @@
|
|
|
78
78
|
"typecheck": "tsc"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@rimbu/base": "^2.0.
|
|
82
|
-
"@rimbu/common": "^2.0.
|
|
81
|
+
"@rimbu/base": "^2.0.3",
|
|
82
|
+
"@rimbu/common": "^2.0.3",
|
|
83
83
|
"tslib": "^2.6.2"
|
|
84
84
|
},
|
|
85
85
|
"publishConfig": {
|
|
86
86
|
"access": "public"
|
|
87
87
|
},
|
|
88
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "1c35dbdd9ce13aeba818b41eb20bab1e826b3e16"
|
|
89
89
|
}
|
package/src/deep.mts
CHANGED
|
@@ -90,9 +90,9 @@ export function patchAtWith<T, P extends Path.Set<T>, TE extends T = T, TT = T>(
|
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* Returns a function that matches a given `value` with the given `matcher`.
|
|
93
|
-
* @typeparam T - the
|
|
93
|
+
* @typeparam T - the input value type
|
|
94
94
|
* @param matcher - a matcher object that matches input values.
|
|
95
|
-
* @param source - the value to
|
|
95
|
+
* @param source - the value to match (parameter of the returned function).
|
|
96
96
|
* @example
|
|
97
97
|
* ```ts
|
|
98
98
|
* const items = [{ a: 1, b: 'a' }, { a: 2, b: 'b' }];
|
|
@@ -128,7 +128,7 @@ export function matchAt<T, P extends Path.Get<T>>(
|
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* Returns a function that matches a given `value` with the given `matcher` at the given string `path`.
|
|
131
|
-
* @typeparam T - the
|
|
131
|
+
* @typeparam T - the input value type
|
|
132
132
|
* @typeparam P - the string literal path type in the object
|
|
133
133
|
* @typeparam TE - utility type
|
|
134
134
|
* @param path - the string path in the object
|
|
@@ -150,7 +150,7 @@ export function matchAtWith<T, P extends Path.Get<T>, TE extends T = T>(
|
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* Returns a function that selects a certain shape from a given `value` with the given `selector`.
|
|
153
|
-
* @typeparam T - the
|
|
153
|
+
* @typeparam T - the input value type
|
|
154
154
|
* @typeparam SL - the selector shape type
|
|
155
155
|
* @param selector - a shape indicating the selection from the source values
|
|
156
156
|
* @param source - the value to use the given `selector` on.
|
|
@@ -169,7 +169,7 @@ export function selectWith<T, SL extends Selector<T>>(
|
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
171
|
* Returns the result of applying the given `selector` shape to the given `source` value.
|
|
172
|
-
* @typeparam T - the
|
|
172
|
+
* @typeparam T - the input value type
|
|
173
173
|
* @typeparam P - the string literal path type in the object
|
|
174
174
|
* @typeparam SL - the selector shape type
|
|
175
175
|
* @param source - the source value to select from
|
|
@@ -185,7 +185,7 @@ export function selectWith<T, SL extends Selector<T>>(
|
|
|
185
185
|
export function selectAt<
|
|
186
186
|
T,
|
|
187
187
|
P extends Path.Get<T>,
|
|
188
|
-
SL extends Selector<Path.Result<T, P
|
|
188
|
+
SL extends Selector<Path.Result<T, P>>,
|
|
189
189
|
>(
|
|
190
190
|
source: T,
|
|
191
191
|
path: P,
|
|
@@ -196,7 +196,7 @@ export function selectAt<
|
|
|
196
196
|
|
|
197
197
|
/**
|
|
198
198
|
* Returns a function that selects a certain shape from a given `value` with the given `selector` at the given string `path`.
|
|
199
|
-
* @typeparam T - the
|
|
199
|
+
* @typeparam T - the input value type
|
|
200
200
|
* @typeparam P - the string literal path type in the object
|
|
201
201
|
* @typeparam SL - the selector shape type
|
|
202
202
|
* @param path - the string path in the object
|
|
@@ -211,7 +211,7 @@ export function selectAt<
|
|
|
211
211
|
export function selectAtWith<
|
|
212
212
|
T,
|
|
213
213
|
P extends Path.Get<T>,
|
|
214
|
-
SL extends Selector<Path.Result<T, P
|
|
214
|
+
SL extends Selector<Path.Result<T, P>>,
|
|
215
215
|
>(
|
|
216
216
|
path: P,
|
|
217
217
|
selector: Selector.Shape<SL>
|
package/src/match.mts
CHANGED
|
@@ -28,25 +28,31 @@ export namespace Match {
|
|
|
28
28
|
* @typeparam P - the parent type
|
|
29
29
|
* @typeparam R - the root object type
|
|
30
30
|
*/
|
|
31
|
-
export type Entry<T, C, P, R> =
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
| Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[]
|
|
41
|
-
| Match.Func<
|
|
42
|
-
T,
|
|
43
|
-
P,
|
|
44
|
-
R,
|
|
31
|
+
export type Entry<T, C, P, R> =
|
|
32
|
+
IsAnyFunc<T> extends true
|
|
33
|
+
? // function can only be directly matched
|
|
34
|
+
T
|
|
35
|
+
: IsPlainObj<T> extends true
|
|
36
|
+
? // determine allowed match values for object
|
|
37
|
+
Match.WithResult<T, P, R, Match.Obj<T, C, P, R>>
|
|
38
|
+
: IsArray<T> extends true
|
|
39
|
+
? // determine allowed match values for array or tuple
|
|
45
40
|
| Match.Arr<T, C, P, R>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
| Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[]
|
|
42
|
+
| Match.Func<
|
|
43
|
+
T,
|
|
44
|
+
P,
|
|
45
|
+
R,
|
|
46
|
+
| Match.Arr<T, C, P, R>
|
|
47
|
+
| Match.Entry<
|
|
48
|
+
T[number & keyof T],
|
|
49
|
+
C[number & keyof C],
|
|
50
|
+
P,
|
|
51
|
+
R
|
|
52
|
+
>[]
|
|
53
|
+
>
|
|
54
|
+
: // only accept values with same interface
|
|
55
|
+
Match.WithResult<T, P, R, { [K in keyof C]: C[K & keyof T] }>;
|
|
50
56
|
|
|
51
57
|
/**
|
|
52
58
|
* The type that determines allowed matchers for objects.
|
|
@@ -128,7 +134,7 @@ export namespace Match {
|
|
|
128
134
|
export type ArrayTraversalType = `${CompoundType}Item`;
|
|
129
135
|
|
|
130
136
|
/**
|
|
131
|
-
*
|
|
137
|
+
* Compound matcher for objects, represented as an array starting with a compound type keyword.
|
|
132
138
|
* @typeparam T - the input value type
|
|
133
139
|
* @typeparam C - utility type
|
|
134
140
|
* @typeparam P - the parent type
|
|
@@ -136,7 +142,7 @@ export namespace Match {
|
|
|
136
142
|
*/
|
|
137
143
|
export type CompoundForObj<T, C, P, R> = [
|
|
138
144
|
Match.CompoundType,
|
|
139
|
-
...Match.Entry<T, C, P, R>[]
|
|
145
|
+
...Match.Entry<T, C, P, R>[],
|
|
140
146
|
];
|
|
141
147
|
|
|
142
148
|
/**
|
|
@@ -188,7 +194,7 @@ export namespace Match {
|
|
|
188
194
|
* match(input, { a: 2 }) // => false
|
|
189
195
|
* match(input, { a: (v) => v > 10 }) // => false
|
|
190
196
|
* match(input, { b: { c: true }}) // => true
|
|
191
|
-
* match(input,
|
|
197
|
+
* match(input, ['every', { a: (v) => v > 0 }, { b: { c: true } }]) // => true
|
|
192
198
|
* match(input, { b: { c: (v, parent, root) => v && parent.d.length > 0 && root.a > 0 } })
|
|
193
199
|
* // => true
|
|
194
200
|
* ```
|
|
@@ -272,9 +278,7 @@ function matchEntry<T, C, P, R>(
|
|
|
272
278
|
// already determined above that the source and matcher are not equal
|
|
273
279
|
|
|
274
280
|
failureLog?.push(
|
|
275
|
-
`value ${JSON.stringify(
|
|
276
|
-
source
|
|
277
|
-
)} does not match given matcher ${JSON.stringify(matcher)}`
|
|
281
|
+
`value ${JSON.stringify(source)} does not match given matcher ${JSON.stringify(matcher)}`
|
|
278
282
|
);
|
|
279
283
|
|
|
280
284
|
return false;
|
|
@@ -469,9 +473,7 @@ function matchPlainObj<T extends object, C, P, R>(
|
|
|
469
473
|
// the source does not have the given key
|
|
470
474
|
|
|
471
475
|
failureLog?.push(
|
|
472
|
-
`key ${key} is specified in matcher but not present in value ${JSON.stringify(
|
|
473
|
-
source
|
|
474
|
-
)}`
|
|
476
|
+
`key ${key} is specified in matcher but not present in value ${JSON.stringify(source)}`
|
|
475
477
|
);
|
|
476
478
|
|
|
477
479
|
return false;
|
package/src/patch.mts
CHANGED
|
@@ -22,15 +22,16 @@ export namespace Patch {
|
|
|
22
22
|
* @typeparam P - the parent type
|
|
23
23
|
* @typeparam R - the root object type
|
|
24
24
|
*/
|
|
25
|
-
export type Entry<T, C, P, R> =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
export type Entry<T, C, P, R> =
|
|
26
|
+
IsAnyFunc<T> extends true
|
|
27
|
+
? T
|
|
28
|
+
: IsPlainObj<T> extends true
|
|
29
|
+
? Patch.WithResult<T, P, R, Patch.Obj<T, C, R>>
|
|
30
|
+
: Tuple.IsTuple<T> extends true
|
|
31
|
+
? Patch.WithResult<T, P, R, T | Patch.Tup<T, C, R>>
|
|
32
|
+
: IsArray<T> extends true
|
|
33
|
+
? Patch.WithResult<T, P, R, T>
|
|
34
|
+
: Patch.WithResult<T, P, R, T>;
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Either result type S, or a patch function with the value type, the parent type, and the root type.
|
|
@@ -109,7 +110,7 @@ export namespace Patch {
|
|
|
109
110
|
* patch(input, [{ a: 2 }]) // => { a: 2, b: { c: true, d: 'a' } }
|
|
110
111
|
* patch(input, [{ b: [{ c: (v) => !v }] }] )
|
|
111
112
|
* // => { a: 1, b: { c: false, d: 'a' } }
|
|
112
|
-
* patch(input
|
|
113
|
+
* patch(input, [{ a: (v) => v + 1, b: [{ d: 'q' }] }] )
|
|
113
114
|
* // => { a: 2, b: { c: true, d: 'q' } }
|
|
114
115
|
* ```
|
|
115
116
|
*/
|
package/src/path.mts
CHANGED
|
@@ -36,7 +36,7 @@ export namespace Path {
|
|
|
36
36
|
T,
|
|
37
37
|
Write extends boolean,
|
|
38
38
|
Maybe extends boolean,
|
|
39
|
-
First extends boolean = false
|
|
39
|
+
First extends boolean = false,
|
|
40
40
|
> = `${IsAnyFunc<T> extends true
|
|
41
41
|
? // functions can not be further decomposed
|
|
42
42
|
''
|
|
@@ -54,47 +54,44 @@ export namespace Path {
|
|
|
54
54
|
T,
|
|
55
55
|
Write extends boolean,
|
|
56
56
|
Maybe extends boolean,
|
|
57
|
-
First extends boolean
|
|
58
|
-
> =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
57
|
+
First extends boolean,
|
|
58
|
+
> =
|
|
59
|
+
Path.Internal.IsOptional<T> extends true
|
|
60
|
+
? // the value T may be null or undefined, check whether further chaining is allowed
|
|
61
|
+
Write extends false
|
|
62
|
+
? // path is not used to write to, so optional chaining is allowed
|
|
63
|
+
Path.Internal.Generic<Exclude<T, undefined | null>, Write, true>
|
|
64
|
+
: // path can be written to, no optional chaining allowed
|
|
65
|
+
never
|
|
66
|
+
: // determine separator, and continue with non-optional value
|
|
67
|
+
`${Path.Internal.Separator<
|
|
68
|
+
First,
|
|
69
|
+
Maybe,
|
|
70
|
+
IsArray<T>
|
|
71
|
+
>}${Path.Internal.NonOptional<T, Write, Maybe>}`;
|
|
71
72
|
|
|
72
73
|
/**
|
|
73
74
|
* Determines the allowed paths into a non-optional value of type `T`.
|
|
74
75
|
* @typeparam T - the source type
|
|
75
76
|
* @typeparam Write - if true the path should be writable (no optional chaining)
|
|
76
77
|
* @typeparam Maybe - if true the value at the current path is optional
|
|
77
|
-
* @typeparam First - if true this is the root call
|
|
78
78
|
*/
|
|
79
|
-
export type NonOptional<
|
|
80
|
-
T
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
Path.Internal.Obj<T, Write, Maybe>
|
|
96
|
-
: // no match
|
|
97
|
-
never;
|
|
79
|
+
export type NonOptional<T, Write extends boolean, Maybe extends boolean> =
|
|
80
|
+
Tuple.IsTuple<T> extends true
|
|
81
|
+
? // determine allowed paths for tuple
|
|
82
|
+
Path.Internal.Tup<T, Write, Maybe>
|
|
83
|
+
: T extends readonly any[]
|
|
84
|
+
? // determine allowed paths for array
|
|
85
|
+
Write extends false
|
|
86
|
+
? // path is not writable so arrays are allowed
|
|
87
|
+
Path.Internal.Arr<T>
|
|
88
|
+
: // path is writable, no arrays allowed
|
|
89
|
+
never
|
|
90
|
+
: IsPlainObj<T> extends true
|
|
91
|
+
? // determine allowed paths for object
|
|
92
|
+
Path.Internal.Obj<T, Write, Maybe>
|
|
93
|
+
: // no match
|
|
94
|
+
never;
|
|
98
95
|
|
|
99
96
|
/**
|
|
100
97
|
* Determines the allowed paths for a tuple. Since tuples have fixed types, they do not
|
|
@@ -104,11 +101,7 @@ export namespace Path {
|
|
|
104
101
|
* @typeparam Maybe - if true the value at the current path is optional
|
|
105
102
|
*/
|
|
106
103
|
export type Tup<T, Write extends boolean, Maybe extends boolean> = {
|
|
107
|
-
[K in Tuple.KeysOf<T>]: `[${K}]${Path.Internal.Generic<
|
|
108
|
-
T[K],
|
|
109
|
-
Write,
|
|
110
|
-
Maybe
|
|
111
|
-
>}`;
|
|
104
|
+
[K in Tuple.KeysOf<T>]: `[${K}]${Path.Internal.Generic<T[K], Write, Maybe>}`;
|
|
112
105
|
}[Tuple.KeysOf<T>];
|
|
113
106
|
|
|
114
107
|
/**
|
|
@@ -135,7 +128,7 @@ export namespace Path {
|
|
|
135
128
|
}[keyof T];
|
|
136
129
|
|
|
137
130
|
/**
|
|
138
|
-
* Determines the allowed path part
|
|
131
|
+
* Determines the allowed path part separator based on the input types.
|
|
139
132
|
* @typeparam First - if true, this is the first call
|
|
140
133
|
* @typeparam Maybe - if true, the value is optional
|
|
141
134
|
* @typeparam IsArray - if true, the value is an array
|
|
@@ -143,7 +136,7 @@ export namespace Path {
|
|
|
143
136
|
export type Separator<
|
|
144
137
|
First extends boolean,
|
|
145
138
|
Maybe extends boolean,
|
|
146
|
-
IsArray extends boolean
|
|
139
|
+
IsArray extends boolean,
|
|
147
140
|
> = Maybe extends true
|
|
148
141
|
? First extends true
|
|
149
142
|
? // first optional value cannot have separator
|
|
@@ -151,13 +144,13 @@ export namespace Path {
|
|
|
151
144
|
: // non-first optional value must have separator
|
|
152
145
|
'?.'
|
|
153
146
|
: First extends true
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
147
|
+
? // first non-optional value has empty separator
|
|
148
|
+
''
|
|
149
|
+
: IsArray extends true
|
|
150
|
+
? // array selectors do not have separator
|
|
151
|
+
''
|
|
152
|
+
: // normal separator
|
|
153
|
+
'.';
|
|
161
154
|
|
|
162
155
|
/**
|
|
163
156
|
* Determines whether the given type `T` is optional, that is, whether it can be null or undefined.
|
|
@@ -169,10 +162,10 @@ export namespace Path {
|
|
|
169
162
|
? // is optional
|
|
170
163
|
True
|
|
171
164
|
: null extends T
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
165
|
+
? // is optional
|
|
166
|
+
True
|
|
167
|
+
: // not optional
|
|
168
|
+
False;
|
|
176
169
|
|
|
177
170
|
/**
|
|
178
171
|
* Returns type `T` if `Maybe` is false, `T | undefined` otherwise.
|
|
@@ -185,12 +178,12 @@ export namespace Path {
|
|
|
185
178
|
|
|
186
179
|
/**
|
|
187
180
|
* Utility type to only add non-empty string types to a string array.
|
|
188
|
-
* @
|
|
181
|
+
* @typeparam A - the input string array
|
|
189
182
|
* @typeparam T - the string value to optionally add
|
|
190
183
|
*/
|
|
191
184
|
export type AppendIfNotEmpty<
|
|
192
185
|
A extends string[],
|
|
193
|
-
T extends string
|
|
186
|
+
T extends string,
|
|
194
187
|
> = T extends ''
|
|
195
188
|
? // empty string, do not add
|
|
196
189
|
A
|
|
@@ -224,23 +217,23 @@ export namespace Path {
|
|
|
224
217
|
export type For<
|
|
225
218
|
T,
|
|
226
219
|
Tokens,
|
|
227
|
-
Maybe extends boolean = Path.Internal.IsOptional<T
|
|
220
|
+
Maybe extends boolean = Path.Internal.IsOptional<T>,
|
|
228
221
|
> = Tokens extends []
|
|
229
222
|
? // no more token
|
|
230
223
|
Path.Internal.MaybeValue<T, Maybe>
|
|
231
224
|
: Path.Internal.IsOptional<T> extends true
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
225
|
+
? // T can be null or undefined, so continue with Maybe set to true
|
|
226
|
+
Path.Result.For<Exclude<T, undefined | null>, Tokens, Maybe>
|
|
227
|
+
: Tokens extends ['?.', infer Key, ...infer Rest]
|
|
228
|
+
? // optional chaining, process first part and set Maybe to true
|
|
229
|
+
Path.Result.For<Path.Result.Part<T, Key, Maybe>, Rest, true>
|
|
230
|
+
: Tokens extends ['.', infer Key, ...infer Rest]
|
|
231
|
+
? // normal chaining, process first part and continue
|
|
232
|
+
Path.Result.For<Path.Result.Part<T, Key, false>, Rest, Maybe>
|
|
233
|
+
: Tokens extends [infer Key, ...infer Rest]
|
|
234
|
+
? // process first part, and continue
|
|
235
|
+
Path.Result.For<Path.Result.Part<T, Key, false>, Rest, Maybe>
|
|
236
|
+
: never;
|
|
244
237
|
|
|
245
238
|
/**
|
|
246
239
|
* Determines the result of getting the property/index `K` from type `T`, taking into
|
|
@@ -249,15 +242,16 @@ export namespace Path {
|
|
|
249
242
|
* @typeparam K - the key to get from the source type
|
|
250
243
|
* @typeparam Maybe - if true indicates that the path may be undefined
|
|
251
244
|
*/
|
|
252
|
-
export type Part<T, K, Maybe extends boolean> =
|
|
253
|
-
|
|
254
|
-
// for
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
245
|
+
export type Part<T, K, Maybe extends boolean> =
|
|
246
|
+
IsArray<T> extends true
|
|
247
|
+
? // for arrays, Maybe needs to be set to true to force optional chaining
|
|
248
|
+
// for tuples, Maybe should be false
|
|
249
|
+
Path.Internal.MaybeValue<
|
|
250
|
+
T[K & keyof T],
|
|
251
|
+
Tuple.IsTuple<T> extends true ? Maybe : true
|
|
252
|
+
>
|
|
253
|
+
: // Return the type at the given key, and take `Maybe` into account
|
|
254
|
+
Path.Internal.MaybeValue<T[K & keyof T], Maybe>;
|
|
261
255
|
|
|
262
256
|
/**
|
|
263
257
|
* Converts a path string into separate tokens in a string array.
|
|
@@ -268,31 +262,35 @@ export namespace Path {
|
|
|
268
262
|
export type Tokenize<
|
|
269
263
|
P extends string,
|
|
270
264
|
Token extends string = '',
|
|
271
|
-
Res extends string[] = []
|
|
265
|
+
Res extends string[] = [],
|
|
272
266
|
> = P extends ''
|
|
273
267
|
? // no more input to process, return result
|
|
274
268
|
Path.Internal.AppendIfNotEmpty<Res, Token>
|
|
275
269
|
: P extends `[${infer Index}]${infer Rest}`
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
270
|
+
? // input is an array selector, append index to tokens. Continue with new token
|
|
271
|
+
Tokenize<
|
|
272
|
+
Rest,
|
|
273
|
+
'',
|
|
274
|
+
[...Path.Internal.AppendIfNotEmpty<Res, Token>, Index]
|
|
275
|
+
>
|
|
276
|
+
: P extends `?.${infer Rest}`
|
|
277
|
+
? // optional chaining, append to tokens. Continue with new token
|
|
278
|
+
Tokenize<
|
|
279
|
+
Rest,
|
|
280
|
+
'',
|
|
281
|
+
[...Path.Internal.AppendIfNotEmpty<Res, Token>, '?.']
|
|
282
|
+
>
|
|
283
|
+
: P extends `.${infer Rest}`
|
|
284
|
+
? // normal chaining, append to tokens. Continue with new token
|
|
285
|
+
Tokenize<
|
|
286
|
+
Rest,
|
|
287
|
+
'',
|
|
288
|
+
[...Path.Internal.AppendIfNotEmpty<Res, Token>, '.']
|
|
289
|
+
>
|
|
290
|
+
: P extends `${infer First}${infer Rest}`
|
|
291
|
+
? // process next character
|
|
292
|
+
Tokenize<Rest, `${Token}${First}`, Res>
|
|
293
|
+
: never;
|
|
296
294
|
}
|
|
297
295
|
|
|
298
296
|
/**
|
|
@@ -327,9 +325,9 @@ export namespace Path {
|
|
|
327
325
|
* ```ts
|
|
328
326
|
* const value = { a: { b: { c: [{ d: 5 }, { d: 6 }] } } }
|
|
329
327
|
* Deep.getAt(value, 'a.b');
|
|
330
|
-
* // => { c: 5 }
|
|
328
|
+
* // => { c: [{ d: 5 }, { d: 6 }] }
|
|
331
329
|
* Deep.getAt(value, 'a.b.c');
|
|
332
|
-
* // => [{ d: 5 }, { d:
|
|
330
|
+
* // => [{ d: 5 }, { d: 6 }]
|
|
333
331
|
* Deep.getAt(value, 'a.b.c[1]');
|
|
334
332
|
* // => { d: 6 }
|
|
335
333
|
* Deep.getAt(value, 'a.b.c[1]?.d');
|
package/src/protected.mts
CHANGED
|
@@ -11,20 +11,21 @@ import type { IsAny, IsPlainObj } from '@rimbu/base';
|
|
|
11
11
|
* - Any other type will not be mapped
|
|
12
12
|
* @typeparam T - the input type
|
|
13
13
|
*/
|
|
14
|
-
export type Protected<T> =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
export type Protected<T> =
|
|
15
|
+
IsAny<T> extends true
|
|
16
|
+
? // to prevent infinite recursion, any will be any
|
|
17
|
+
T
|
|
18
|
+
: T extends readonly any[] & infer A
|
|
19
|
+
? // convert all keys to readonly and all values to `Protected`
|
|
20
|
+
{ readonly [K in keyof A]: Protected<A[K]> }
|
|
21
|
+
: T extends Map<infer K, infer V>
|
|
22
|
+
? ReadonlyMap<Protected<K>, Protected<V>>
|
|
23
|
+
: T extends Set<infer E>
|
|
24
|
+
? ReadonlySet<Protected<E>>
|
|
25
|
+
: T extends Promise<infer E>
|
|
26
|
+
? Promise<Protected<E>>
|
|
27
|
+
: IsPlainObj<T> extends true
|
|
28
|
+
? // convert all keys to readonly and all values to `Protected`
|
|
29
|
+
{ readonly [K in keyof T]: Protected<T[K]> }
|
|
30
|
+
: // nothing to do, just return `T`
|
|
31
|
+
T;
|
package/src/selector.mts
CHANGED
|
@@ -22,32 +22,34 @@ export namespace Selector {
|
|
|
22
22
|
* Type defining the shape of allowed selectors, used to improve compiler checking.
|
|
23
23
|
* @typeparam SL - the selector type
|
|
24
24
|
*/
|
|
25
|
-
export type Shape<SL> =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
export type Shape<SL> =
|
|
26
|
+
IsAnyFunc<SL> extends true
|
|
27
|
+
? // functions are allowed, type provided by `Selector`
|
|
28
|
+
SL
|
|
29
|
+
: IsArray<SL> extends true
|
|
30
|
+
? // ensure tuple type is preserved
|
|
31
|
+
readonly [...(SL extends readonly unknown[] ? SL : never)]
|
|
32
|
+
: SL extends { readonly [key: string | number | symbol]: unknown }
|
|
33
|
+
? // ensure all object properties satisfy `Shape`
|
|
34
|
+
{ readonly [K in keyof SL]: Selector.Shape<SL[K]> }
|
|
35
|
+
: // nothing to check
|
|
36
|
+
SL;
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* Type defining the result type of applying the SL selector type to the T value type.
|
|
39
40
|
* @typeparam T - the source value type
|
|
40
41
|
* @typeparam SL - the selector type
|
|
41
42
|
*/
|
|
42
|
-
export type Result<T, SL> =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
export type Result<T, SL> =
|
|
44
|
+
Selector<T> extends SL
|
|
45
|
+
? never
|
|
46
|
+
: SL extends (...args: any[]) => infer R
|
|
47
|
+
? R
|
|
48
|
+
: SL extends string
|
|
49
|
+
? Path.Result<T, SL>
|
|
50
|
+
: {
|
|
51
|
+
readonly [K in keyof SL]: Selector.Result<T, SL[K]>;
|
|
52
|
+
};
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
/**
|