@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.
Files changed (48) hide show
  1. package/README.md +295 -60
  2. package/dist/bun/deep.mts +8 -8
  3. package/dist/bun/match.mts +29 -27
  4. package/dist/bun/patch.mts +11 -10
  5. package/dist/bun/path.mts +98 -100
  6. package/dist/bun/protected.mts +18 -17
  7. package/dist/bun/selector.mts +22 -20
  8. package/dist/bun/tuple.mts +6 -2
  9. package/dist/cjs/deep.cjs +18 -18
  10. package/dist/cjs/deep.cjs.map +1 -1
  11. package/dist/cjs/deep.d.cts +6 -6
  12. package/dist/cjs/match.cjs +2 -3
  13. package/dist/cjs/match.cjs.map +1 -1
  14. package/dist/cjs/match.d.cts +2 -2
  15. package/dist/cjs/patch.cjs +2 -3
  16. package/dist/cjs/patch.cjs.map +1 -1
  17. package/dist/cjs/patch.d.cts +1 -1
  18. package/dist/cjs/path.cjs +5 -5
  19. package/dist/cjs/path.cjs.map +1 -1
  20. package/dist/cjs/path.d.cts +8 -6
  21. package/dist/cjs/selector.cjs +1 -2
  22. package/dist/cjs/selector.cjs.map +1 -1
  23. package/dist/cjs/tuple.cjs +1 -1
  24. package/dist/cjs/tuple.cjs.map +1 -1
  25. package/dist/cjs/tuple.d.cts +5 -1
  26. package/dist/esm/deep.d.mts +6 -6
  27. package/dist/esm/deep.mjs +6 -6
  28. package/dist/esm/match.d.mts +2 -2
  29. package/dist/esm/match.mjs +1 -1
  30. package/dist/esm/match.mjs.map +1 -1
  31. package/dist/esm/patch.d.mts +1 -1
  32. package/dist/esm/patch.mjs +1 -1
  33. package/dist/esm/patch.mjs.map +1 -1
  34. package/dist/esm/path.d.mts +8 -6
  35. package/dist/esm/path.mjs +2 -2
  36. package/dist/esm/path.mjs.map +1 -1
  37. package/dist/esm/selector.mjs.map +1 -1
  38. package/dist/esm/tuple.d.mts +5 -1
  39. package/dist/esm/tuple.mjs +1 -1
  40. package/dist/esm/tuple.mjs.map +1 -1
  41. package/package.json +7 -7
  42. package/src/deep.mts +8 -8
  43. package/src/match.mts +29 -27
  44. package/src/patch.mts +11 -10
  45. package/src/path.mts +98 -100
  46. package/src/protected.mts +18 -17
  47. package/src/selector.mts +22 -20
  48. 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.1",
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": "ts-node ../../config/api-extractor.ts config/api-extractor.main.json",
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.1",
82
- "@rimbu/common": "^2.0.1",
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": "b7ed656d2c55d1a715d6a3f52e364e68cb98c759"
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 patch value type
93
+ * @typeparam T - the input value type
94
94
  * @param matcher - a matcher object that matches input values.
95
- * @param source - the value to use the given `patchItem` on at the given `path`.
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 patch value type
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 patch value type
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 patch value type
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 patch value type
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> = IsAnyFunc<T> extends true
32
- ? // function can only be directly matched
33
- T
34
- : IsPlainObj<T> extends true
35
- ? // determine allowed match values for object
36
- Match.WithResult<T, P, R, Match.Obj<T, C, P, R>>
37
- : IsArray<T> extends true
38
- ? // determine allowed match values for array or tuple
39
- | Match.Arr<T, C, P, R>
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
- | Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[]
47
- >
48
- : // only accept values with same interface
49
- Match.WithResult<T, P, R, { [K in keyof C]: C[K & keyof T] }>;
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
- * Compount matcher for objects, can only be an array staring with a compound type keyword.
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, (['every', { a: (v) => v > 0 }, { b: { c: true } }]) // => true
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> = IsAnyFunc<T> extends true
26
- ? T
27
- : IsPlainObj<T> extends true
28
- ? Patch.WithResult<T, P, R, Patch.Obj<T, C, R>>
29
- : Tuple.IsTuple<T> extends true
30
- ? Patch.WithResult<T, P, R, T | Patch.Tup<T, C, R>>
31
- : IsArray<T> extends true
32
- ? Patch.WithResult<T, P, R, T>
33
- : Patch.WithResult<T, P, R, T>;
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: [{ a: (v) => v + 1, b: [{ d: 'q' }] }] )
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
- > = Path.Internal.IsOptional<T> extends true
59
- ? // the value T may be null or undefined, check whether further chaining is allowed
60
- Write extends false
61
- ? // path is not used to write to, so optional chaining is allowed
62
- Path.Internal.Generic<Exclude<T, undefined | null>, Write, true>
63
- : // path can be written to, no optional chaining allowed
64
- never
65
- : // determine separator, and continue with non-optional value
66
- `${Path.Internal.Separator<
67
- First,
68
- Maybe,
69
- IsArray<T>
70
- >}${Path.Internal.NonOptional<T, Write, Maybe>}`;
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
- Write extends boolean,
82
- Maybe extends boolean
83
- > = Tuple.IsTuple<T> extends true
84
- ? // determine allowed paths for tuple
85
- Path.Internal.Tup<T, Write, Maybe>
86
- : T extends readonly any[]
87
- ? // determine allowed paths for array
88
- Write extends false
89
- ? // path is not writable so arrays are allowed
90
- Path.Internal.Arr<T>
91
- : // path is writable, no arrays allowed
92
- never
93
- : IsPlainObj<T> extends true
94
- ? // determine allowed paths for object
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 seperator based on the input types.
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
- ? // first non-optional value has empty separator
155
- ''
156
- : IsArray extends true
157
- ? // array selectors do not have separator
158
- ''
159
- : // normal separator
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
- ? // is optional
173
- True
174
- : // not optional
175
- False;
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
- * @typeparma A - the input string array
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
- ? // T can be null or undefined, so continue with Maybe set to true
233
- Path.Result.For<Exclude<T, undefined | null>, Tokens, Maybe>
234
- : Tokens extends ['?.', infer Key, ...infer Rest]
235
- ? // optional chaining, process first part and set Maybe to true
236
- Path.Result.For<Path.Result.Part<T, Key, Maybe>, Rest, true>
237
- : Tokens extends ['.', infer Key, ...infer Rest]
238
- ? // normal chaining, process first part and continue
239
- Path.Result.For<Path.Result.Part<T, Key, false>, Rest, Maybe>
240
- : Tokens extends [infer Key, ...infer Rest]
241
- ? // process first part, and continue
242
- Path.Result.For<Path.Result.Part<T, Key, false>, Rest, Maybe>
243
- : never;
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> = IsArray<T> extends true
253
- ? // for arrays, Maybe needs to be set to true to force optional chaining
254
- // for tuples, Maybe should be false
255
- Path.Internal.MaybeValue<
256
- T[K & keyof T],
257
- Tuple.IsTuple<T> extends true ? Maybe : true
258
- >
259
- : // Return the type at the given key, and take `Maybe` into account
260
- Path.Internal.MaybeValue<T[K & keyof T], Maybe>;
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
- ? // input is an array selector, append index to tokens. Continue with new token
277
- Tokenize<
278
- Rest,
279
- '',
280
- [...Path.Internal.AppendIfNotEmpty<Res, Token>, Index]
281
- >
282
- : P extends `?.${infer Rest}`
283
- ? // optional chaining, append to tokens. Continue with new token
284
- Tokenize<
285
- Rest,
286
- '',
287
- [...Path.Internal.AppendIfNotEmpty<Res, Token>, '?.']
288
- >
289
- : P extends `.${infer Rest}`
290
- ? // normal chaining, append to tokens. Continue with new token
291
- Tokenize<Rest, '', [...Path.Internal.AppendIfNotEmpty<Res, Token>, '.']>
292
- : P extends `${infer First}${infer Rest}`
293
- ? // process next character
294
- Tokenize<Rest, `${Token}${First}`, Res>
295
- : never;
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: 5 }]
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> = IsAny<T> extends true
15
- ? // to prevent infinite recursion, any will be any
16
- T
17
- : T extends readonly any[] & infer A
18
- ? // convert all keys to readonly and all values to `Protected`
19
- { readonly [K in keyof A]: Protected<A[K]> }
20
- : T extends Map<infer K, infer V>
21
- ? ReadonlyMap<Protected<K>, Protected<V>>
22
- : T extends Set<infer E>
23
- ? ReadonlySet<Protected<E>>
24
- : T extends Promise<infer E>
25
- ? Promise<Protected<E>>
26
- : IsPlainObj<T> extends true
27
- ? // convert all keys to readonly and all values to `Protected`
28
- { readonly [K in keyof T]: Protected<T[K]> }
29
- : // nothing to do, just return `T`
30
- T;
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> = IsAnyFunc<SL> extends true
26
- ? // functions are allowed, type provided by `Selector`
27
- SL
28
- : IsArray<SL> extends true
29
- ? // ensure tuple type is preserved
30
- readonly [...(SL extends readonly unknown[] ? SL : never)]
31
- : SL extends { readonly [key: string | number | symbol]: unknown }
32
- ? // ensure all object properties satisfy `Shape`
33
- { readonly [K in keyof SL]: Selector.Shape<SL[K]> }
34
- : // nothing to check
35
- SL;
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> = Selector<T> extends SL
43
- ? never
44
- : SL extends (...args: any[]) => infer R
45
- ? R
46
- : SL extends string
47
- ? Path.Result<T, SL>
48
- : {
49
- readonly [K in keyof SL]: Selector.Result<T, SL[K]>;
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
  /**