@rimbu/deep 0.11.2 → 0.12.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.
Files changed (53) hide show
  1. package/dist/main/deep.js +211 -0
  2. package/dist/main/deep.js.map +1 -0
  3. package/dist/main/index.js +7 -9
  4. package/dist/main/index.js.map +1 -1
  5. package/dist/main/internal.js +6 -4
  6. package/dist/main/internal.js.map +1 -1
  7. package/dist/main/match.js +160 -199
  8. package/dist/main/match.js.map +1 -1
  9. package/dist/main/patch.js +101 -125
  10. package/dist/main/patch.js.map +1 -1
  11. package/dist/main/path.js +109 -62
  12. package/dist/main/path.js.map +1 -1
  13. package/dist/main/protected.js +0 -19
  14. package/dist/main/protected.js.map +1 -1
  15. package/dist/main/selector.js +40 -0
  16. package/dist/main/selector.js.map +1 -0
  17. package/dist/main/tuple.js.map +1 -1
  18. package/dist/module/deep.js +192 -0
  19. package/dist/module/deep.js.map +1 -0
  20. package/dist/module/index.js +9 -1
  21. package/dist/module/index.js.map +1 -1
  22. package/dist/module/internal.js +4 -4
  23. package/dist/module/internal.js.map +1 -1
  24. package/dist/module/match.js +159 -179
  25. package/dist/module/match.js.map +1 -1
  26. package/dist/module/patch.js +91 -112
  27. package/dist/module/patch.js.map +1 -1
  28. package/dist/module/path.js +99 -44
  29. package/dist/module/path.js.map +1 -1
  30. package/dist/module/protected.js +1 -17
  31. package/dist/module/protected.js.map +1 -1
  32. package/dist/module/selector.js +36 -0
  33. package/dist/module/selector.js.map +1 -0
  34. package/dist/module/tuple.js.map +1 -1
  35. package/dist/types/deep.d.ts +284 -0
  36. package/dist/types/index.d.ts +10 -1
  37. package/dist/types/internal.d.ts +7 -4
  38. package/dist/types/match.d.ts +74 -80
  39. package/dist/types/patch.d.ts +57 -50
  40. package/dist/types/path.d.ts +177 -34
  41. package/dist/types/protected.d.ts +1 -16
  42. package/dist/types/selector.d.ts +47 -0
  43. package/dist/types/tuple.d.ts +10 -0
  44. package/package.json +4 -4
  45. package/src/deep.ts +362 -0
  46. package/src/index.ts +14 -10
  47. package/src/internal.ts +7 -4
  48. package/src/match.ts +396 -212
  49. package/src/patch.ts +173 -176
  50. package/src/path.ts +400 -74
  51. package/src/protected.ts +14 -25
  52. package/src/selector.ts +90 -0
  53. package/src/tuple.ts +12 -0
package/src/deep.ts ADDED
@@ -0,0 +1,362 @@
1
+ import type { Match, Patch, Path, Protected, Selector } from './internal';
2
+ import { Deep } from './internal';
3
+
4
+ export { match, type Match } from './match';
5
+ export { patch, type Patch } from './patch';
6
+ export { getAt, patchAt, type Path } from './path';
7
+ export { select, type Selector } from './selector';
8
+ export type { Protected } from './protected';
9
+
10
+ /**
11
+ * Returns the same value wrapped in the `Protected` type.
12
+ * @typeparam T - the source value type
13
+ * @param source - the value to wrap
14
+ * @note does not perform any runtime protection, it is only a utility to easily add the `Protected`
15
+ * type to a value
16
+ * @example
17
+ * ```ts
18
+ * const obj = Deep.protect({ a: 1, b: { c: true, d: [1] } })
19
+ * obj.a = 2 // compiler error: a is readonly
20
+ * obj.b.c = false // compiler error: c is readonly
21
+ * obj.b.d.push(2) // compiler error: d is a readonly array
22
+ * (obj as any).b.d.push(2) // will actually mutate the object
23
+ * ```
24
+ */
25
+ export function protect<T>(source: T): Protected<T> {
26
+ return source as Protected<T>;
27
+ }
28
+
29
+ /**
30
+ * Returns a function that gets the value at the given string `path` inside an object.
31
+ * @typeparam T - the input value type
32
+ * @typeparam P - the string literal path type in the object
33
+ * @param path - the string path in the object
34
+ * @param source - the value from which to extract the path value
35
+ * @example
36
+ * ```ts
37
+ * const items = [{ a: { b: 1, c: 'a' } }, { a: { b: 2, c: 'b' } }];
38
+ * items.map(Deep.getAtWith('a.c'));
39
+ * // => ['a', 'b']
40
+ * ```
41
+ */
42
+ export function getAtWith<T, P extends Path.Get<T>>(
43
+ path: P
44
+ ): (source: T) => Path.Result<T, P> {
45
+ return (source) => Deep.getAt(source, path);
46
+ }
47
+
48
+ /**
49
+ * Returns a function that patches a given `source` with the given `patchItems`.
50
+ * @typeparam T - the patch value type
51
+ * @typeparam TE - utility type
52
+ * @typeparam TT - utility type
53
+ * @param patchItem - the `Patch` definition to update the given value of type `T` with.
54
+ * @param source - the value to use the given `patchItem` on.
55
+ * @example
56
+ * ```ts
57
+ * const items = [{ a: 1, b: 'a' }, { a: 2, b: 'b' }];
58
+ * items.map(Deep.patchWith([{ a: v => v + 1 }]));
59
+ * // => [{ a: 2, b: 'a' }, { a: 3, b: 'b' }]
60
+ * ```
61
+ */
62
+ export function patchWith<T, TE extends T = T, TT = T>(
63
+ patchItem: Patch<TE, TT>
64
+ ): (source: T) => T {
65
+ return (source) => Deep.patch(source, patchItem);
66
+ }
67
+
68
+ /**
69
+ * Returns a function that patches a given `value` with the given `patchItems` at the given `path`.
70
+ * @typeparam T - the patch value type
71
+ * @typeparam P - the string literal path type in the object
72
+ * @typeparam TE - utility type
73
+ * @typeparam TT - utility type
74
+ * @param path - the string path in the object
75
+ * @param patchItem - the `Patch` definition to update the value at the given `path` in `T` with.
76
+ * @param source - the value to use the given `patchItem` on at the given `path`.
77
+ * @example
78
+ * ```ts
79
+ * const items = [{ a: { b: 1, c: 'a' } }, { a: { b: 2, c: 'b' } }];
80
+ * items.map(Deep.patchAtWith('a', [{ b: (v) => v + 1 }]));
81
+ * // => [{ a: { b: 2, c: 'a' } }, { a: { b: 3, c: 'b' } }]
82
+ * ```
83
+ */
84
+ export function patchAtWith<T, P extends Path.Set<T>, TE extends T = T, TT = T>(
85
+ path: P,
86
+ patchItem: Patch<Path.Result<TE, P>, Path.Result<TT, P>>
87
+ ): (source: T) => T {
88
+ return (source) => Deep.patchAt(source, path, patchItem as any);
89
+ }
90
+
91
+ /**
92
+ * Returns a function that matches a given `value` with the given `matcher`.
93
+ * @typeparam T - the patch value type
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`.
96
+ * @example
97
+ * ```ts
98
+ * const items = [{ a: 1, b: 'a' }, { a: 2, b: 'b' }];
99
+ * items.filter(Deep.matchWith({ a: 2 }));
100
+ * // => [{ a: 2, b: 'b' }]
101
+ * ```
102
+ */
103
+ export function matchWith<T>(matcher: Match<T>): (source: T) => boolean {
104
+ return (source) => Deep.match(source, matcher);
105
+ }
106
+
107
+ /**
108
+ * Returns true if the given `value` object matches the given `matcher` at the given `path`, false otherwise.
109
+ * @typeparam T - the input value type
110
+ * @typeparam P - the string literal path type in the object
111
+ * @param source - the input value
112
+ * @param path - the string path in the object
113
+ * @param matcher - a matcher object or a function taking the matcher API and returning a match object
114
+ * @example
115
+ * ```ts
116
+ * const input = { a: 1, b: { c: true, d: 'a' } }
117
+ * Deep.matchAt(input, 'b', { c: true })
118
+ * // => true
119
+ * ```
120
+ */
121
+ export function matchAt<T, P extends Path.Get<T>>(
122
+ source: T,
123
+ path: P,
124
+ matcher: Match<Path.Result<T, P>>
125
+ ): boolean {
126
+ return Deep.match(Deep.getAt(source, path), matcher);
127
+ }
128
+
129
+ /**
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
132
+ * @typeparam P - the string literal path type in the object
133
+ * @typeparam TE - utility type
134
+ * @param path - the string path in the object
135
+ * @param matcher - a matcher object that matches input values.
136
+ * @param source - the value to use the given `matcher` on at the given `path`.
137
+ * @example
138
+ * ```ts
139
+ * const items = [{ a: { b: 1, c: 'a' } }, { a: { b: 2, c: 'b' } }];
140
+ * items.filter(Deep.matchAtWith('a.b', 2));
141
+ * // => [{ a: 2, b: 'b' }]
142
+ * ```
143
+ */
144
+ export function matchAtWith<T, P extends Path.Get<T>, TE extends T = T>(
145
+ path: P,
146
+ matcher: Match<Path.Result<T & TE, P>>
147
+ ): (source: T) => boolean {
148
+ return (source) => Deep.matchAt(source, path, matcher as any);
149
+ }
150
+
151
+ /**
152
+ * Returns a function that selects a certain shape from a given `value` with the given `selector`.
153
+ * @typeparam T - the patch value type
154
+ * @typeparam SL - the selector shape type
155
+ * @param selector - a shape indicating the selection from the source values
156
+ * @param source - the value to use the given `selector` on.
157
+ * @example
158
+ * ```ts
159
+ * const items = [{ a: { b: 1, c: 'a' } }, { a: { b: 2, c: 'b' } }];
160
+ * items.map(Deep.selectWith({ q: 'a.c', z: ['a.b', v => v.a.b + 1] as const }));
161
+ * // => [{ q: 'a', z: [1, 2] }, { q: 'b', z: [2, 3] }]
162
+ * ```
163
+ */
164
+ export function selectWith<T, SL extends Selector<T>>(
165
+ selector: Selector.Shape<SL>
166
+ ): (source: T) => Selector.Result<T, SL> {
167
+ return (source) => Deep.select(source, selector);
168
+ }
169
+
170
+ /**
171
+ * Returns the result of applying the given `selector` shape to the given `source` value.
172
+ * @typeparam T - the patch value type
173
+ * @typeparam P - the string literal path type in the object
174
+ * @typeparam SL - the selector shape type
175
+ * @param source - the source value to select from
176
+ * @param path - the string path in the object
177
+ * @param selector - a shape indicating the selection from the source value at the given path
178
+ * @example
179
+ * ```ts
180
+ * const item = { a: { b: 1, c: 'a' } };
181
+ * Deep.selectAt(item, 'a', { q: 'c', z: ['b', v => v.b + 1] as const });
182
+ * // => { q: 'a', z: [1, 2] }
183
+ * ```
184
+ */
185
+ export function selectAt<
186
+ T,
187
+ P extends Path.Get<T>,
188
+ SL extends Selector<Path.Result<T, P>>
189
+ >(
190
+ source: T,
191
+ path: P,
192
+ selector: Selector.Shape<SL>
193
+ ): Selector.Result<Path.Result<T, P>, SL> {
194
+ return Deep.select(Deep.getAt(source, path), selector);
195
+ }
196
+
197
+ /**
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
200
+ * @typeparam P - the string literal path type in the object
201
+ * @typeparam SL - the selector shape type
202
+ * @param path - the string path in the object
203
+ * @param selector - a shape indicating the selection from the source values
204
+ * @example
205
+ * ```ts
206
+ * const items = [{ a: { b: 1, c: 'a' } }, { a: { b: 2, c: 'b' } }];
207
+ * items.map(Deep.selectAtWith('a', { q: 'c', z: ['b', v => v.b + 1] as const }));
208
+ * // => [{ q: 'a', z: [1, 2] }, { q: 'b', z: [2, 3] }]
209
+ * ```
210
+ */
211
+ export function selectAtWith<
212
+ T,
213
+ P extends Path.Get<T>,
214
+ SL extends Selector<Path.Result<T, P>>
215
+ >(
216
+ path: P,
217
+ selector: Selector.Shape<SL>
218
+ ): (source: T) => Selector.Result<Path.Result<T, P>, SL> {
219
+ return (source) => Deep.selectAt(source, path, selector);
220
+ }
221
+
222
+ /**
223
+ * Typed and curried Deep API, used in situations where the target type
224
+ * is known but the value will be applied later.
225
+ * @typeparam T - the target type
226
+ * @example
227
+ * ```ts
228
+ * const s = { a: 1, b: { c: 'a', d: true }};
229
+ * const upd = Deep.withType<typeof s>().patchWith([{ a: (v) => v + 1 }]);
230
+ * upd(s);
231
+ * // => { a: 2, b: { c: 'a', d: true }}
232
+ * ```
233
+ */
234
+ export interface WithType<T> {
235
+ /**
236
+ * Returns a function that given an object returns the value at the given `path`.
237
+ * @typeparam P - a Path in object type T
238
+ * @param path - the path into the object
239
+ * @example
240
+ * ```ts
241
+ * const value = { a: { b: { c: 5 } } }
242
+ * const getValue = Deep.withType<typeof value>().getAtWith('a.b.c');
243
+ * getValue(value);
244
+ * // => 5
245
+ * ```
246
+ */
247
+ getAtWith<P extends Path.Get<T>>(path: P): (source: T) => Path.Result<T, P>;
248
+ /**
249
+ * Returns a function that patches a given `value` with the given `patchItems`.
250
+ * @typeparam TT - utility type
251
+ * @param patchItem - the `Patch` definition to update the given value with
252
+ * @param source - the value to use the given `patchItem` on.
253
+ * @example
254
+ * ```ts
255
+ * const value = { a: 1, b: 'a' };
256
+ * const upd = Deep.withType<typeof value>().patch([{ a: v => v + 1 }]);
257
+ * upd(value);
258
+ * // => { a: 2, b: 'a' }
259
+ * ```
260
+ */
261
+ patchWith<TT = T>(patchItem: Patch<T, TT>): (source: T) => T;
262
+ /**
263
+ * Returns a function that patches a given `value` with the given `patchItems` at the given `path`.
264
+ * @typeparam P - the string literal path type in the object
265
+ * @typeparam TT - utility type
266
+ * @param path - the string path in the object
267
+ * @param patchItem - the `Patch` definition to update the given value with
268
+ * @param source - the value to use the given `patchItem` on at the given `path`.
269
+ * @example
270
+ * ```ts
271
+ * const value = { a: { b: 1, c: 'a' } };
272
+ * const upd = Deep.withType<typeof value>().patchAtWith('a', [{ b: (v) => v + 1 }])
273
+ * upd(value);
274
+ * // => { a: { b: 2, c: 'a' } }
275
+ * ```
276
+ */
277
+ patchAtWith<P extends Path.Set<T>, TT = T>(
278
+ path: P,
279
+ patchItem: Patch<Path.Result<T, P>, Path.Result<TT, P>>
280
+ ): (source: T) => T;
281
+ /**
282
+ * Returns a function that matches a given `value` with the given `matcher`.
283
+ * @param matcher - a matcher object that matches input values.
284
+ * @param source - the value to use the given `matcher` on.
285
+ * @example
286
+ * ```ts
287
+ * const value = { a: 1, b: 'a' };
288
+ * const m = Deep.withType<typeof value>().matchWith({ a: 1 });
289
+ * m(value);
290
+ * // => true
291
+ * ```
292
+ */
293
+ matchWith(matcher: Match<T>): (source: T) => boolean;
294
+ /**
295
+ * Returns a function that matches a given `value` with the given `matcher` at the given string `path`.
296
+ * @typeparam P - the string literal path type in the object
297
+ * @param path - the string path in the object
298
+ * @param matcher - a matcher object that matches input values.
299
+ * @param source - the value to use the given `matcher` on at the given `path`.
300
+ * @example
301
+ * ```ts
302
+ * const items = [{ a: { b: 1, c: 'a' } }, { a: { b: 2, c: 'b' } }];
303
+ * items.filter(Deep.matchAtWith('a.b', 2));
304
+ * // => [{ a: 2, b: 'b' }]
305
+ * ```
306
+ */
307
+ matchAtWith<P extends Path.Get<T>>(
308
+ path: P,
309
+ matcher: Match<Path.Result<T, P>>
310
+ ): (source: T) => boolean;
311
+ /**
312
+ * Returns a function that selects a certain shape from a given `value` with the given `selector`.
313
+ * @typeparam SL - the selector shape type
314
+ * @param selector - a shape indicating the selection from the source values
315
+ * @param source - the value to use the given `selector` on.
316
+ * @example
317
+ * ```ts
318
+ * const value = { a: { b: 1, c: 'a' } };
319
+ * const sel = Deep.withType<typeof value>().selectWith({ q: 'a.b' });
320
+ * sel(value);
321
+ * // => { q: 1 }
322
+ * ```
323
+ */
324
+ selectWith<SL extends Selector<T>>(
325
+ selector: Selector.Shape<SL>
326
+ ): (source: T) => Selector.Result<T, SL>;
327
+ /**
328
+ * Returns a function that selects a certain shape from a given `value` with the given `selector` at the given string `path`.
329
+ * @typeparam P - the string literal path type in the object
330
+ * @typeparam SL - the selector shape type
331
+ * @param path - the string path in the object
332
+ * @param selector - a shape indicating the selection from the source values
333
+ * @param source - the value to use the given `selector` on at the given `path`.
334
+ * @example
335
+ * ```ts
336
+ * const value = { a: { b: 1, c: 'a' } };
337
+ * const sel = Deep.withType<typeof value>().selectAtWith('a', { q: 'b' });
338
+ * sel(value);
339
+ * // => { q: 1 }
340
+ * ```
341
+ */
342
+ selectAtWith<P extends Path.Get<T>, SL extends Selector<Path.Result<T, P>>>(
343
+ path: P,
344
+ selector: Selector.Shape<SL>
345
+ ): (source: T) => Selector.Result<Path.Result<T, P>, SL>;
346
+ }
347
+
348
+ /**
349
+ * Returns a curried API with a known target type. This can be useful for using the methods in
350
+ * contexts where the target type can be inferred from the usage.
351
+ * @typeparam T - the target type
352
+ * @example
353
+ * ```ts
354
+ * const s = { a: 1, b: { c: 'a', d: true }}
355
+ * const upd = Deep.withType<typeof s>().patchWith([{ d: (v) => !v }])
356
+ * upd(s)
357
+ * // => { a: 1, b: { c: 'a', d: false }}
358
+ * ```
359
+ */
360
+ export function withType<T>(): WithType<T> {
361
+ return Deep;
362
+ }
package/src/index.ts CHANGED
@@ -6,14 +6,18 @@
6
6
  * See the [Rimbu docs Deep overview page](/docs/deep/overview) for more information.
7
7
  */
8
8
 
9
- export {
10
- patch,
11
- patchNested,
12
- Patch,
13
- match,
14
- Match,
15
- Path,
16
- Protected,
17
- } from './internal';
18
-
19
9
  export { Tuple } from './tuple';
10
+
11
+ export type { Protected, Patch } from './internal';
12
+ export { Path, type Selector, type Match } from './internal';
13
+
14
+ export * from './deep';
15
+
16
+ import * as Deep from './deep';
17
+ export {
18
+ /**
19
+ * Convenience namespace offering access to most common functions used in the `@rimbu/deep` package.
20
+ * These are mainly utilities to patch and match plain JavaScript objects.
21
+ */
22
+ Deep,
23
+ };
package/src/internal.ts CHANGED
@@ -1,5 +1,8 @@
1
- export * from './protected';
1
+ export type { Protected } from './protected';
2
+ export { Path } from './path';
3
+ export { type Match } from './match';
4
+ export type { Patch } from './patch';
5
+ export type { Selector } from './selector';
2
6
 
3
- export * from './match';
4
- export * from './patch';
5
- export * from './path';
7
+ import * as Deep from './deep';
8
+ export { Deep };